diff --git a/packages/linux/patches/linux-3.2.28-601-RPi_support-f23da7f.patch b/packages/linux/patches/linux-3.2.28-601-RPi_support-78f82bc.patch similarity index 76% rename from packages/linux/patches/linux-3.2.28-601-RPi_support-f23da7f.patch rename to packages/linux/patches/linux-3.2.28-601-RPi_support-78f82bc.patch index 5c3f10d942..b5c991e8ac 100644 --- a/packages/linux/patches/linux-3.2.28-601-RPi_support-f23da7f.patch +++ b/packages/linux/patches/linux-3.2.28-601-RPi_support-78f82bc.patch @@ -1,13 +1,83 @@ -diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_cutdown_defconfig linux-rpi-bootc-3.2.23/arch/arm/configs/bcmrpi_cutdown_defconfig ---- linux-3.2.23/arch/arm/configs/bcmrpi_cutdown_defconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/configs/bcmrpi_cutdown_defconfig 2012-07-15 20:28:26.407092434 +0200 -@@ -0,0 +1,494 @@ +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 987c72d..5285fbf 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -955,6 +955,22 @@ config PLAT_SPEAR + help + Support for ST's SPEAr platform (SPEAr3xx, SPEAr6xx and SPEAr13xx). + ++config ARCH_BCM2708 ++ bool "Broadcom BCM2708 family" ++ select CPU_V6 ++ select ARM_AMBA ++ select HAVE_CLK ++ select HAVE_SCHED_CLOCK ++ select NEED_MACH_MEMORY_H ++ select CLKDEV_LOOKUP ++ select GENERIC_CLOCKEVENTS ++ select ARM_ERRATA_411920 ++ select MACH_BCM2708 ++ select VC4 ++ select FIQ ++ help ++ This enables support for Broadcom BCM2708 boards. ++ + config ARCH_VT8500 + bool "VIA/WonderMedia 85xx" + select CPU_ARM926T +@@ -1098,6 +1114,7 @@ source "arch/arm/plat-versatile/Kconfig" + source "arch/arm/mach-vt8500/Kconfig" + + source "arch/arm/mach-w90x900/Kconfig" ++source "arch/arm/mach-bcm2708/Kconfig" + + # Definitions to make life easier + config ARCH_ACORN +diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug +index c5213e7..5e58b8f 100644 +--- a/arch/arm/Kconfig.debug ++++ b/arch/arm/Kconfig.debug +@@ -247,6 +247,14 @@ choice + their output to the standard serial port on the RealView + PB1176 platform. + ++ config DEBUG_BCM2708_UART0 ++ bool "Broadcom BCM2708 UART0 (PL011)" ++ depends on MACH_BCM2708 ++ help ++ Say Y here if you want the debug print routines to direct ++ their output to UART 0. The port must have been initialised ++ by the boot-loader before use. ++ + endchoice + + config EARLY_PRINTK +diff --git a/arch/arm/Makefile b/arch/arm/Makefile +index dfcf3b0..1b18ede 100644 +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -198,6 +198,7 @@ machine-$(CONFIG_MACH_SPEAR310) := spear3xx + machine-$(CONFIG_MACH_SPEAR320) := spear3xx + machine-$(CONFIG_MACH_SPEAR600) := spear6xx + machine-$(CONFIG_ARCH_ZYNQ) := zynq ++machine-$(CONFIG_ARCH_BCM2708) := bcm2708 + + # Platform directory name. This list is sorted alphanumerically + # by CONFIG_* macro name. +diff --git a/arch/arm/configs/bcmrpi_cutdown_defconfig b/arch/arm/configs/bcmrpi_cutdown_defconfig +new file mode 100644 +index 0000000..3b8bd74 +--- /dev/null ++++ b/arch/arm/configs/bcmrpi_cutdown_defconfig +@@ -0,0 +1,546 @@ +CONFIG_EXPERIMENTAL=y ++CONFIG_LOCALVERSION="-cutdown" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y ++CONFIG_SCHED_AUTOGROUP=y +# CONFIG_UID16 is not set +# CONFIG_KALLSYMS is not set +CONFIG_EMBEDDED=y @@ -22,6 +92,7 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_cutdown_defconfig linux-rpi-boot +CONFIG_ARCH_BCM2708=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y ++CONFIG_PREEMPT=y +CONFIG_AEABI=y +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZBOOT_ROM_BSS=0x0 @@ -45,7 +116,7 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_cutdown_defconfig linux-rpi-boot +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +# CONFIG_INET_DIAG is not set -+# CONFIG_IPV6 is not set ++CONFIG_IPV6_PRIVACY=y +CONFIG_NET_PKTGEN=m +CONFIG_IRDA=m +CONFIG_IRLAN=m @@ -86,6 +157,7 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_cutdown_defconfig linux-rpi-boot +CONFIG_NFC=m +CONFIG_NFC_PN533=m +CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m @@ -99,12 +171,43 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_cutdown_defconfig linux-rpi-boot +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_NETDEVICES=y ++CONFIG_NETCONSOLE=m +CONFIG_TUN=m +CONFIG_PHYLIB=m +CONFIG_MDIO_BITBANG=m -+CONFIG_NET_ETHERNET=y -+# CONFIG_NETDEV_1000 is not set -+# CONFIG_NETDEV_10000 is not set ++CONFIG_PPP=m ++CONFIG_PPP_BSDCOMP=m ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_ASYNC=m ++CONFIG_PPP_SYNC_TTY=m ++CONFIG_SLIP=m ++CONFIG_SLIP_COMPRESSED=y ++CONFIG_USB_CATC=m ++CONFIG_USB_KAWETH=m ++CONFIG_USB_PEGASUS=m ++CONFIG_USB_RTL8150=m ++CONFIG_USB_USBNET=y ++CONFIG_USB_NET_AX8817X=m ++CONFIG_USB_NET_CDCETHER=m ++CONFIG_USB_NET_CDC_EEM=m ++CONFIG_USB_NET_DM9601=m ++CONFIG_USB_NET_SMSC75XX=m ++CONFIG_USB_NET_SMSC95XX=y ++CONFIG_USB_NET_GL620A=m ++CONFIG_USB_NET_NET1080=m ++CONFIG_USB_NET_PLUSB=m ++CONFIG_USB_NET_MCS7830=m ++CONFIG_USB_NET_CDC_SUBSET=m ++CONFIG_USB_ALI_M5632=y ++CONFIG_USB_AN2720=y ++CONFIG_USB_KC2190=y ++# CONFIG_USB_NET_ZAURUS is not set ++CONFIG_USB_NET_CX82310_ETH=m ++CONFIG_USB_NET_KALMIA=m ++CONFIG_USB_NET_INT51X1=m ++CONFIG_USB_IPHETH=m ++CONFIG_USB_SIERRA_NET=m ++CONFIG_USB_VL600=m +CONFIG_LIBERTAS_THINFIRM=m +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_AT76C50X_USB=m @@ -137,40 +240,6 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_cutdown_defconfig linux-rpi-boot +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_WIMAX_I2400M_USB=m -+CONFIG_USB_CATC=m -+CONFIG_USB_KAWETH=m -+CONFIG_USB_PEGASUS=m -+CONFIG_USB_RTL8150=m -+CONFIG_USB_USBNET=y -+CONFIG_USB_NET_AX8817X=m -+CONFIG_USB_NET_CDCETHER=m -+CONFIG_USB_NET_CDC_EEM=m -+CONFIG_USB_NET_DM9601=m -+CONFIG_USB_NET_SMSC75XX=m -+CONFIG_USB_NET_SMSC95XX=y -+CONFIG_USB_NET_GL620A=m -+CONFIG_USB_NET_NET1080=m -+CONFIG_USB_NET_PLUSB=m -+CONFIG_USB_NET_MCS7830=m -+CONFIG_USB_NET_CDC_SUBSET=m -+CONFIG_USB_ALI_M5632=y -+CONFIG_USB_AN2720=y -+CONFIG_USB_KC2190=y -+# CONFIG_USB_NET_ZAURUS is not set -+CONFIG_USB_NET_CX82310_ETH=m -+CONFIG_USB_NET_KALMIA=m -+CONFIG_USB_NET_INT51X1=m -+CONFIG_USB_IPHETH=m -+CONFIG_USB_SIERRA_NET=m -+CONFIG_USB_VL600=m -+CONFIG_PPP=m -+CONFIG_PPP_ASYNC=m -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_PPP_BSDCOMP=m -+CONFIG_SLIP=m -+CONFIG_SLIP_COMPRESSED=y -+CONFIG_NETCONSOLE=m +CONFIG_INPUT_POLLDEV=m +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_JOYDEV=m @@ -179,7 +248,6 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_cutdown_defconfig linux-rpi-boot +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_AD714X=m -+CONFIG_INPUT_ATI_REMOTE=m +CONFIG_INPUT_ATI_REMOTE2=m +CONFIG_INPUT_KEYSPAN_REMOTE=m +CONFIG_INPUT_POWERMATE=m @@ -205,7 +273,58 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_cutdown_defconfig linux-rpi-boot +# CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_BCM2708_WDT=m -+# CONFIG_MFD_SUPPORT is not set ++CONFIG_MEDIA_SUPPORT=m ++CONFIG_VIDEO_DEV=m ++CONFIG_USB_VIDEO_CLASS=m ++CONFIG_USB_M5602=m ++CONFIG_USB_STV06XX=m ++CONFIG_USB_GL860=m ++CONFIG_USB_GSPCA_BENQ=m ++CONFIG_USB_GSPCA_CONEX=m ++CONFIG_USB_GSPCA_CPIA1=m ++CONFIG_USB_GSPCA_ETOMS=m ++CONFIG_USB_GSPCA_FINEPIX=m ++CONFIG_USB_GSPCA_JEILINJ=m ++CONFIG_USB_GSPCA_KINECT=m ++CONFIG_USB_GSPCA_KONICA=m ++CONFIG_USB_GSPCA_MARS=m ++CONFIG_USB_GSPCA_MR97310A=m ++CONFIG_USB_GSPCA_NW80X=m ++CONFIG_USB_GSPCA_OV519=m ++CONFIG_USB_GSPCA_OV534=m ++CONFIG_USB_GSPCA_OV534_9=m ++CONFIG_USB_GSPCA_PAC207=m ++CONFIG_USB_GSPCA_PAC7302=m ++CONFIG_USB_GSPCA_PAC7311=m ++CONFIG_USB_GSPCA_SE401=m ++CONFIG_USB_GSPCA_SN9C2028=m ++CONFIG_USB_GSPCA_SN9C20X=m ++CONFIG_USB_GSPCA_SONIXB=m ++CONFIG_USB_GSPCA_SONIXJ=m ++CONFIG_USB_GSPCA_SPCA500=m ++CONFIG_USB_GSPCA_SPCA501=m ++CONFIG_USB_GSPCA_SPCA505=m ++CONFIG_USB_GSPCA_SPCA506=m ++CONFIG_USB_GSPCA_SPCA508=m ++CONFIG_USB_GSPCA_SPCA561=m ++CONFIG_USB_GSPCA_SPCA1528=m ++CONFIG_USB_GSPCA_SQ905=m ++CONFIG_USB_GSPCA_SQ905C=m ++CONFIG_USB_GSPCA_SQ930X=m ++CONFIG_USB_GSPCA_STK014=m ++CONFIG_USB_GSPCA_STV0680=m ++CONFIG_USB_GSPCA_SUNPLUS=m ++CONFIG_USB_GSPCA_T613=m ++CONFIG_USB_GSPCA_TV8532=m ++CONFIG_USB_GSPCA_VC032X=m ++CONFIG_USB_GSPCA_VICAM=m ++CONFIG_USB_GSPCA_XIRLINK_CIT=m ++CONFIG_USB_GSPCA_ZC3XX=m ++CONFIG_VIDEO_HDPVR=m ++CONFIG_USB_PWC=m ++CONFIG_USB_ZR364XX=m ++CONFIG_USB_STKWEBCAM=m ++CONFIG_USB_S2255=m +CONFIG_FB=y +CONFIG_FB_BCM2708=y +CONFIG_FRAMEBUFFER_CONSOLE=y @@ -475,6 +594,7 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_cutdown_defconfig linux-rpi-boot +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m +# CONFIG_SCHED_DEBUG is not set ++# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_BUGVERBOSE is not set +# CONFIG_FTRACE is not set +# CONFIG_ARM_UNWIND is not set @@ -496,10 +616,13 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_cutdown_defconfig linux-rpi-boot +# CONFIG_CRYPTO_HW is not set +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y -diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_defconfig linux-rpi-bootc-3.2.23/arch/arm/configs/bcmrpi_defconfig ---- linux-3.2.23/arch/arm/configs/bcmrpi_defconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/configs/bcmrpi_defconfig 2012-07-15 20:28:26.377091869 +0200 -@@ -0,0 +1,530 @@ +diff --git a/arch/arm/configs/bcmrpi_defconfig b/arch/arm/configs/bcmrpi_defconfig +new file mode 100644 +index 0000000..5ed9c30 +--- /dev/null ++++ b/arch/arm/configs/bcmrpi_defconfig +@@ -0,0 +1,907 @@ ++# CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y @@ -507,6 +630,10 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_defconfig linux-rpi-bootc-3.2.23 +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_FHANDLE=y ++CONFIG_TASKSTATS=y ++CONFIG_TASK_DELAY_ACCT=y ++CONFIG_TASK_XACCT=y ++CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_AUDIT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y @@ -517,6 +644,7 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_defconfig linux-rpi-bootc-3.2.23 +CONFIG_BLK_CGROUP=y +CONFIG_NAMESPACES=y +CONFIG_SCHED_AUTOGROUP=y ++CONFIG_RELAY=y +CONFIG_EMBEDDED=y +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y @@ -533,7 +661,9 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_defconfig linux-rpi-bootc-3.2.23 +CONFIG_ARCH_BCM2708=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y ++CONFIG_PREEMPT=y +CONFIG_AEABI=y ++CONFIG_UACCESS_WITH_MEMCPY=y +CONFIG_SECCOMP=y +CONFIG_CC_STACKPROTECTOR=y +CONFIG_ZBOOT_ROM_TEXT=0x0 @@ -550,19 +680,235 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_defconfig linux-rpi-bootc-3.2.23 +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y ++CONFIG_IP_ADVANCED_ROUTER=y ++CONFIG_IP_MULTIPLE_TABLES=y ++CONFIG_IP_ROUTE_MULTIPATH=y ++CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_RARP=y ++CONFIG_NET_IPIP=m +CONFIG_SYN_COOKIES=y -+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -+# CONFIG_INET_XFRM_MODE_TUNNEL is not set -+# CONFIG_INET_XFRM_MODE_BEET is not set -+# CONFIG_INET_LRO is not set -+# CONFIG_INET_DIAG is not set -+# CONFIG_IPV6 is not set ++CONFIG_INET_AH=m ++CONFIG_INET_ESP=m ++CONFIG_INET_IPCOMP=m ++CONFIG_INET_XFRM_MODE_TRANSPORT=m ++CONFIG_INET_XFRM_MODE_TUNNEL=m ++CONFIG_INET_XFRM_MODE_BEET=m ++CONFIG_INET_LRO=m ++CONFIG_INET_DIAG=m ++CONFIG_IPV6_PRIVACY=y ++CONFIG_INET6_AH=m ++CONFIG_INET6_ESP=m ++CONFIG_INET6_IPCOMP=m ++CONFIG_IPV6_MULTIPLE_TABLES=y ++CONFIG_NETFILTER=y ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_ZONES=y ++CONFIG_NF_CONNTRACK_EVENTS=y ++CONFIG_NF_CONNTRACK_TIMESTAMP=y ++CONFIG_NF_CT_PROTO_DCCP=m ++CONFIG_NF_CT_PROTO_SCTP=m ++CONFIG_NF_CT_PROTO_UDPLITE=m ++CONFIG_NF_CONNTRACK_AMANDA=m ++CONFIG_NF_CONNTRACK_FTP=m ++CONFIG_NF_CONNTRACK_H323=m ++CONFIG_NF_CONNTRACK_IRC=m ++CONFIG_NF_CONNTRACK_NETBIOS_NS=m ++CONFIG_NF_CONNTRACK_SNMP=m ++CONFIG_NF_CONNTRACK_PPTP=m ++CONFIG_NF_CONNTRACK_SANE=m ++CONFIG_NF_CONNTRACK_SIP=m ++CONFIG_NF_CONNTRACK_TFTP=m ++CONFIG_NF_CT_NETLINK=m ++CONFIG_NETFILTER_TPROXY=m ++CONFIG_NETFILTER_XT_SET=m ++CONFIG_NETFILTER_XT_TARGET_AUDIT=m ++CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m ++CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m ++CONFIG_NETFILTER_XT_TARGET_CONNMARK=m ++CONFIG_NETFILTER_XT_TARGET_CT=m ++CONFIG_NETFILTER_XT_TARGET_DSCP=m ++CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m ++CONFIG_NETFILTER_XT_TARGET_LED=m ++CONFIG_NETFILTER_XT_TARGET_MARK=m ++CONFIG_NETFILTER_XT_TARGET_NFLOG=m ++CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m ++CONFIG_NETFILTER_XT_TARGET_NOTRACK=m ++CONFIG_NETFILTER_XT_TARGET_TEE=m ++CONFIG_NETFILTER_XT_TARGET_TPROXY=m ++CONFIG_NETFILTER_XT_TARGET_TRACE=m ++CONFIG_NETFILTER_XT_TARGET_TCPMSS=m ++CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m ++CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m ++CONFIG_NETFILTER_XT_MATCH_CLUSTER=m ++CONFIG_NETFILTER_XT_MATCH_COMMENT=m ++CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m ++CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_CONNMARK=m ++CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m ++CONFIG_NETFILTER_XT_MATCH_CPU=m ++CONFIG_NETFILTER_XT_MATCH_DCCP=m ++CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m ++CONFIG_NETFILTER_XT_MATCH_DSCP=m ++CONFIG_NETFILTER_XT_MATCH_ESP=m ++CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m ++CONFIG_NETFILTER_XT_MATCH_HELPER=m ++CONFIG_NETFILTER_XT_MATCH_IPRANGE=m ++CONFIG_NETFILTER_XT_MATCH_LENGTH=m ++CONFIG_NETFILTER_XT_MATCH_LIMIT=m ++CONFIG_NETFILTER_XT_MATCH_MAC=m ++CONFIG_NETFILTER_XT_MATCH_MARK=m ++CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m ++CONFIG_NETFILTER_XT_MATCH_OSF=m ++CONFIG_NETFILTER_XT_MATCH_OWNER=m ++CONFIG_NETFILTER_XT_MATCH_POLICY=m ++CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m ++CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m ++CONFIG_NETFILTER_XT_MATCH_QUOTA=m ++CONFIG_NETFILTER_XT_MATCH_RATEEST=m ++CONFIG_NETFILTER_XT_MATCH_REALM=m ++CONFIG_NETFILTER_XT_MATCH_RECENT=m ++CONFIG_NETFILTER_XT_MATCH_SCTP=m ++CONFIG_NETFILTER_XT_MATCH_SOCKET=m ++CONFIG_NETFILTER_XT_MATCH_STATE=m ++CONFIG_NETFILTER_XT_MATCH_STATISTIC=m ++CONFIG_NETFILTER_XT_MATCH_STRING=m ++CONFIG_NETFILTER_XT_MATCH_TCPMSS=m ++CONFIG_NETFILTER_XT_MATCH_TIME=m ++CONFIG_NETFILTER_XT_MATCH_U32=m ++CONFIG_IP_SET=m ++CONFIG_IP_SET_BITMAP_IP=m ++CONFIG_IP_SET_BITMAP_IPMAC=m ++CONFIG_IP_SET_BITMAP_PORT=m ++CONFIG_IP_SET_HASH_IP=m ++CONFIG_IP_SET_HASH_IPPORT=m ++CONFIG_IP_SET_HASH_IPPORTIP=m ++CONFIG_IP_SET_HASH_IPPORTNET=m ++CONFIG_IP_SET_HASH_NET=m ++CONFIG_IP_SET_HASH_NETPORT=m ++CONFIG_IP_SET_HASH_NETIFACE=m ++CONFIG_IP_SET_LIST_SET=m ++CONFIG_NF_CONNTRACK_IPV4=m ++CONFIG_IP_NF_IPTABLES=m ++CONFIG_IP_NF_MATCH_AH=m ++CONFIG_IP_NF_MATCH_ECN=m ++CONFIG_IP_NF_MATCH_TTL=m ++CONFIG_IP_NF_FILTER=m ++CONFIG_IP_NF_TARGET_REJECT=m ++CONFIG_IP_NF_TARGET_LOG=m ++CONFIG_IP_NF_TARGET_ULOG=m ++CONFIG_NF_NAT=m ++CONFIG_IP_NF_TARGET_MASQUERADE=m ++CONFIG_IP_NF_TARGET_NETMAP=m ++CONFIG_IP_NF_TARGET_REDIRECT=m ++CONFIG_IP_NF_MANGLE=m ++CONFIG_IP_NF_TARGET_ECN=m ++CONFIG_IP_NF_TARGET_TTL=m ++CONFIG_IP_NF_RAW=m ++CONFIG_IP_NF_ARPTABLES=m ++CONFIG_IP_NF_ARPFILTER=m ++CONFIG_IP_NF_ARP_MANGLE=m ++CONFIG_NF_CONNTRACK_IPV6=m ++CONFIG_IP6_NF_IPTABLES=m ++CONFIG_IP6_NF_MATCH_AH=m ++CONFIG_IP6_NF_MATCH_EUI64=m ++CONFIG_IP6_NF_MATCH_FRAG=m ++CONFIG_IP6_NF_MATCH_OPTS=m ++CONFIG_IP6_NF_MATCH_HL=m ++CONFIG_IP6_NF_MATCH_IPV6HEADER=m ++CONFIG_IP6_NF_MATCH_MH=m ++CONFIG_IP6_NF_MATCH_RT=m ++CONFIG_IP6_NF_TARGET_HL=m ++CONFIG_IP6_NF_TARGET_LOG=m ++CONFIG_IP6_NF_FILTER=m ++CONFIG_IP6_NF_TARGET_REJECT=m ++CONFIG_IP6_NF_MANGLE=m ++CONFIG_IP6_NF_RAW=m ++CONFIG_BRIDGE_NF_EBTABLES=m ++CONFIG_BRIDGE_EBT_BROUTE=m ++CONFIG_BRIDGE_EBT_T_FILTER=m ++CONFIG_BRIDGE_EBT_T_NAT=m ++CONFIG_BRIDGE_EBT_802_3=m ++CONFIG_BRIDGE_EBT_AMONG=m ++CONFIG_BRIDGE_EBT_ARP=m ++CONFIG_BRIDGE_EBT_IP=m ++CONFIG_BRIDGE_EBT_IP6=m ++CONFIG_BRIDGE_EBT_LIMIT=m ++CONFIG_BRIDGE_EBT_MARK=m ++CONFIG_BRIDGE_EBT_PKTTYPE=m ++CONFIG_BRIDGE_EBT_STP=m ++CONFIG_BRIDGE_EBT_VLAN=m ++CONFIG_BRIDGE_EBT_ARPREPLY=m ++CONFIG_BRIDGE_EBT_DNAT=m ++CONFIG_BRIDGE_EBT_MARK_T=m ++CONFIG_BRIDGE_EBT_REDIRECT=m ++CONFIG_BRIDGE_EBT_SNAT=m ++CONFIG_BRIDGE_EBT_LOG=m ++CONFIG_BRIDGE_EBT_ULOG=m ++CONFIG_BRIDGE_EBT_NFLOG=m ++CONFIG_BRIDGE=m ++CONFIG_VLAN_8021Q=m ++CONFIG_VLAN_8021Q_GVRP=y ++CONFIG_NET_SCHED=y ++CONFIG_NET_SCH_CBQ=m ++CONFIG_NET_SCH_HTB=m ++CONFIG_NET_SCH_HFSC=m ++CONFIG_NET_SCH_PRIO=m ++CONFIG_NET_SCH_MULTIQ=m ++CONFIG_NET_SCH_RED=m ++CONFIG_NET_SCH_SFB=m ++CONFIG_NET_SCH_SFQ=m ++CONFIG_NET_SCH_TEQL=m ++CONFIG_NET_SCH_TBF=m ++CONFIG_NET_SCH_GRED=m ++CONFIG_NET_SCH_DSMARK=m ++CONFIG_NET_SCH_NETEM=m ++CONFIG_NET_SCH_DRR=m ++CONFIG_NET_SCH_MQPRIO=m ++CONFIG_NET_SCH_CHOKE=m ++CONFIG_NET_SCH_QFQ=m ++CONFIG_NET_CLS_BASIC=m ++CONFIG_NET_CLS_TCINDEX=m ++CONFIG_NET_CLS_ROUTE4=m ++CONFIG_NET_CLS_FW=m ++CONFIG_NET_CLS_U32=m ++CONFIG_CLS_U32_MARK=y ++CONFIG_NET_CLS_RSVP=m ++CONFIG_NET_CLS_RSVP6=m ++CONFIG_NET_CLS_FLOW=m ++CONFIG_NET_CLS_CGROUP=m ++CONFIG_NET_EMATCH=y ++CONFIG_NET_EMATCH_CMP=m ++CONFIG_NET_EMATCH_NBYTE=m ++CONFIG_NET_EMATCH_U32=m ++CONFIG_NET_EMATCH_META=m ++CONFIG_NET_EMATCH_TEXT=m ++CONFIG_NET_CLS_ACT=y ++CONFIG_NET_ACT_POLICE=m ++CONFIG_NET_ACT_GACT=m ++CONFIG_GACT_PROB=y ++CONFIG_NET_ACT_MIRRED=m ++CONFIG_NET_ACT_IPT=m ++CONFIG_NET_ACT_NAT=m ++CONFIG_NET_ACT_PEDIT=m ++CONFIG_NET_ACT_SIMP=m ++CONFIG_NET_ACT_SKBEDIT=m ++CONFIG_NET_ACT_CSUM=m +CONFIG_NET_PKTGEN=m ++CONFIG_HAMRADIO=y ++CONFIG_AX25=m ++CONFIG_NETROM=m ++CONFIG_ROSE=m ++CONFIG_MKISS=m ++CONFIG_6PACK=m ++CONFIG_BPQETHER=m ++CONFIG_BAYCOM_SER_FDX=m ++CONFIG_BAYCOM_SER_HDX=m ++CONFIG_YAM=m +CONFIG_IRDA=m +CONFIG_IRLAN=m ++CONFIG_IRNET=m +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y +CONFIG_IRDA_CACHE_LAST_LSAP=y @@ -599,9 +945,11 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_defconfig linux-rpi-bootc-3.2.23 +CONFIG_NET_9P=m +CONFIG_NFC=m +CONFIG_NFC_PN533=m -+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" ++CONFIG_DEVTMPFS=y ++CONFIG_DEVTMPFS_MOUNT=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_CRYPTOLOOP=m ++CONFIG_BLK_DEV_DRBD=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_CDROM_PKTCDVD=m @@ -609,49 +957,39 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_defconfig linux-rpi-bootc-3.2.23 +CONFIG_SCSI=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y ++CONFIG_CHR_DEV_ST=m ++CONFIG_CHR_DEV_OSST=m +CONFIG_BLK_DEV_SR=m +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_LOWLEVEL is not set +CONFIG_MD=y ++CONFIG_BLK_DEV_DM=m ++CONFIG_DM_CRYPT=m ++CONFIG_DM_SNAPSHOT=m ++CONFIG_DM_MIRROR=m ++CONFIG_DM_RAID=m ++CONFIG_DM_LOG_USERSPACE=m ++CONFIG_DM_ZERO=m ++CONFIG_DM_DELAY=m +CONFIG_NETDEVICES=y ++CONFIG_BONDING=m ++CONFIG_MACVLAN=m ++CONFIG_NETCONSOLE=m +CONFIG_TUN=m +CONFIG_PHYLIB=m +CONFIG_MDIO_BITBANG=m -+CONFIG_NET_ETHERNET=y -+# CONFIG_NETDEV_1000 is not set -+# CONFIG_NETDEV_10000 is not set -+CONFIG_LIBERTAS_THINFIRM=m -+CONFIG_LIBERTAS_THINFIRM_USB=m -+CONFIG_AT76C50X_USB=m -+CONFIG_USB_ZD1201=m -+CONFIG_USB_NET_RNDIS_WLAN=m -+CONFIG_RTL8187=m -+CONFIG_MAC80211_HWSIM=m -+CONFIG_ATH_COMMON=m -+CONFIG_ATH9K=m -+CONFIG_ATH9K_HTC=m -+CONFIG_CARL9170=m -+CONFIG_B43=m -+CONFIG_B43LEGACY=m -+CONFIG_HOSTAP=m -+CONFIG_IWM=m -+CONFIG_LIBERTAS=m -+CONFIG_LIBERTAS_USB=m -+CONFIG_LIBERTAS_SDIO=m -+CONFIG_P54_COMMON=m -+CONFIG_P54_USB=m -+CONFIG_RT2X00=m -+CONFIG_RT2500USB=m -+CONFIG_RT73USB=m -+CONFIG_RT2800USB=m -+CONFIG_RT2800USB_RT53XX=y -+CONFIG_RTL8192CU=m -+CONFIG_WL1251=m -+CONFIG_WL12XX_MENU=m -+CONFIG_ZD1211RW=m -+CONFIG_MWIFIEX=m -+CONFIG_MWIFIEX_SDIO=m -+CONFIG_WIMAX_I2400M_USB=m ++CONFIG_PPP=m ++CONFIG_PPP_BSDCOMP=m ++CONFIG_PPP_DEFLATE=m ++CONFIG_PPP_FILTER=y ++CONFIG_PPP_MPPE=m ++CONFIG_PPP_MULTILINK=y ++CONFIG_PPPOE=m ++CONFIG_PPP_ASYNC=m ++CONFIG_PPP_SYNC_TTY=m ++CONFIG_SLIP=m ++CONFIG_SLIP_COMPRESSED=y ++CONFIG_SLIP_SMART=y +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m @@ -678,14 +1016,39 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_defconfig linux-rpi-bootc-3.2.23 +CONFIG_USB_IPHETH=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m -+CONFIG_PPP=m -+CONFIG_PPP_ASYNC=m -+CONFIG_PPP_SYNC_TTY=m -+CONFIG_PPP_DEFLATE=m -+CONFIG_PPP_BSDCOMP=m -+CONFIG_SLIP=m -+CONFIG_SLIP_COMPRESSED=y -+CONFIG_NETCONSOLE=m ++CONFIG_LIBERTAS_THINFIRM=m ++CONFIG_LIBERTAS_THINFIRM_USB=m ++CONFIG_AT76C50X_USB=m ++CONFIG_USB_ZD1201=m ++CONFIG_USB_NET_RNDIS_WLAN=m ++CONFIG_RTL8187=m ++CONFIG_MAC80211_HWSIM=m ++CONFIG_ATH_COMMON=m ++CONFIG_ATH9K=m ++CONFIG_ATH9K_HTC=m ++CONFIG_CARL9170=m ++CONFIG_B43=m ++CONFIG_B43_PHY_N=y ++CONFIG_B43LEGACY=m ++CONFIG_HOSTAP=m ++CONFIG_IWM=m ++CONFIG_LIBERTAS=m ++CONFIG_LIBERTAS_USB=m ++CONFIG_LIBERTAS_SDIO=m ++CONFIG_P54_COMMON=m ++CONFIG_P54_USB=m ++CONFIG_RT2X00=m ++CONFIG_RT2500USB=m ++CONFIG_RT73USB=m ++CONFIG_RT2800USB=m ++CONFIG_RT2800USB_RT53XX=y ++CONFIG_WL1251=m ++CONFIG_WL12XX_MENU=m ++CONFIG_ZD1211RW=m ++CONFIG_MWIFIEX=m ++CONFIG_MWIFIEX_SDIO=m ++CONFIG_RTL8192CU=m ++CONFIG_WIMAX_I2400M_USB=m +CONFIG_INPUT_POLLDEV=m +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_JOYDEV=m @@ -694,7 +1057,6 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_defconfig linux-rpi-bootc-3.2.23 +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_AD714X=m -+CONFIG_INPUT_ATI_REMOTE=m +CONFIG_INPUT_ATI_REMOTE2=m +CONFIG_INPUT_KEYSPAN_REMOTE=m +CONFIG_INPUT_POWERMATE=m @@ -714,13 +1076,143 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_defconfig linux-rpi-bootc-3.2.23 +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y ++CONFIG_TTY_PRINTK=y +# CONFIG_HW_RANDOM is not set +CONFIG_RAW_DRIVER=y ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=m ++CONFIG_I2C_BCM2708=m ++CONFIG_SPI=y ++CONFIG_SPI_BCM2708=m ++CONFIG_SPI_SPIDEV=m +CONFIG_GPIO_SYSFS=y ++CONFIG_W1=m ++CONFIG_W1_MASTER_DS2490=m ++CONFIG_W1_MASTER_DS2482=m ++CONFIG_W1_MASTER_DS1WM=m ++CONFIG_W1_MASTER_GPIO=m ++CONFIG_W1_SLAVE_THERM=m ++CONFIG_W1_SLAVE_SMEM=m ++CONFIG_W1_SLAVE_DS2408=m ++CONFIG_W1_SLAVE_DS2423=m ++CONFIG_W1_SLAVE_DS2431=m ++CONFIG_W1_SLAVE_DS2433=m ++CONFIG_W1_SLAVE_DS2760=m ++CONFIG_W1_SLAVE_DS2780=m ++CONFIG_W1_SLAVE_BQ27000=m +# CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_BCM2708_WDT=m -+# CONFIG_MFD_SUPPORT is not set ++CONFIG_MEDIA_SUPPORT=m ++CONFIG_VIDEO_DEV=m ++CONFIG_DVB_CORE=m ++CONFIG_RC_ATI_REMOTE=m ++CONFIG_IR_IMON=m ++CONFIG_IR_MCEUSB=m ++CONFIG_IR_REDRAT3=m ++CONFIG_IR_STREAMZAP=m ++CONFIG_RC_LOOPBACK=m ++CONFIG_MEDIA_ATTACH=y ++CONFIG_USB_VIDEO_CLASS=m ++CONFIG_USB_M5602=m ++CONFIG_USB_STV06XX=m ++CONFIG_USB_GL860=m ++CONFIG_USB_GSPCA_BENQ=m ++CONFIG_USB_GSPCA_CONEX=m ++CONFIG_USB_GSPCA_CPIA1=m ++CONFIG_USB_GSPCA_ETOMS=m ++CONFIG_USB_GSPCA_FINEPIX=m ++CONFIG_USB_GSPCA_JEILINJ=m ++CONFIG_USB_GSPCA_KINECT=m ++CONFIG_USB_GSPCA_KONICA=m ++CONFIG_USB_GSPCA_MARS=m ++CONFIG_USB_GSPCA_MR97310A=m ++CONFIG_USB_GSPCA_NW80X=m ++CONFIG_USB_GSPCA_OV519=m ++CONFIG_USB_GSPCA_OV534=m ++CONFIG_USB_GSPCA_OV534_9=m ++CONFIG_USB_GSPCA_PAC207=m ++CONFIG_USB_GSPCA_PAC7302=m ++CONFIG_USB_GSPCA_PAC7311=m ++CONFIG_USB_GSPCA_SE401=m ++CONFIG_USB_GSPCA_SN9C2028=m ++CONFIG_USB_GSPCA_SN9C20X=m ++CONFIG_USB_GSPCA_SONIXB=m ++CONFIG_USB_GSPCA_SONIXJ=m ++CONFIG_USB_GSPCA_SPCA500=m ++CONFIG_USB_GSPCA_SPCA501=m ++CONFIG_USB_GSPCA_SPCA505=m ++CONFIG_USB_GSPCA_SPCA506=m ++CONFIG_USB_GSPCA_SPCA508=m ++CONFIG_USB_GSPCA_SPCA561=m ++CONFIG_USB_GSPCA_SPCA1528=m ++CONFIG_USB_GSPCA_SQ905=m ++CONFIG_USB_GSPCA_SQ905C=m ++CONFIG_USB_GSPCA_SQ930X=m ++CONFIG_USB_GSPCA_STK014=m ++CONFIG_USB_GSPCA_STV0680=m ++CONFIG_USB_GSPCA_SUNPLUS=m ++CONFIG_USB_GSPCA_T613=m ++CONFIG_USB_GSPCA_TV8532=m ++CONFIG_USB_GSPCA_VC032X=m ++CONFIG_USB_GSPCA_VICAM=m ++CONFIG_USB_GSPCA_XIRLINK_CIT=m ++CONFIG_USB_GSPCA_ZC3XX=m ++CONFIG_VIDEO_PVRUSB2=m ++CONFIG_VIDEO_HDPVR=m ++CONFIG_VIDEO_EM28XX=m ++CONFIG_VIDEO_EM28XX_ALSA=m ++CONFIG_VIDEO_EM28XX_DVB=m ++CONFIG_VIDEO_TLG2300=m ++CONFIG_VIDEO_CX231XX=m ++CONFIG_VIDEO_CX231XX_ALSA=m ++CONFIG_VIDEO_CX231XX_DVB=m ++CONFIG_VIDEO_USBVISION=m ++CONFIG_USB_ET61X251=m ++CONFIG_USB_SN9C102=m ++CONFIG_USB_PWC=m ++CONFIG_USB_ZR364XX=m ++CONFIG_USB_STKWEBCAM=m ++CONFIG_USB_S2255=m ++CONFIG_USB_DSBR=m ++CONFIG_RADIO_SI470X=y ++CONFIG_USB_SI470X=m ++CONFIG_USB_MR800=m ++CONFIG_DVB_USB=m ++CONFIG_DVB_USB_A800=m ++CONFIG_DVB_USB_DIBUSB_MB=m ++CONFIG_DVB_USB_DIBUSB_MC=m ++CONFIG_DVB_USB_DIB0700=m ++CONFIG_DVB_USB_UMT_010=m ++CONFIG_DVB_USB_CXUSB=m ++CONFIG_DVB_USB_M920X=m ++CONFIG_DVB_USB_GL861=m ++CONFIG_DVB_USB_AU6610=m ++CONFIG_DVB_USB_DIGITV=m ++CONFIG_DVB_USB_VP7045=m ++CONFIG_DVB_USB_VP702X=m ++CONFIG_DVB_USB_GP8PSK=m ++CONFIG_DVB_USB_NOVA_T_USB2=m ++CONFIG_DVB_USB_TTUSB2=m ++CONFIG_DVB_USB_DTT200U=m ++CONFIG_DVB_USB_OPERA1=m ++CONFIG_DVB_USB_AF9005=m ++CONFIG_DVB_USB_AF9005_REMOTE=m ++CONFIG_DVB_USB_DW2102=m ++CONFIG_DVB_USB_CINERGY_T2=m ++CONFIG_DVB_USB_ANYSEE=m ++CONFIG_DVB_USB_DTV5100=m ++CONFIG_DVB_USB_AF9015=m ++CONFIG_DVB_USB_CE6230=m ++CONFIG_DVB_USB_FRIIO=m ++CONFIG_DVB_USB_EC168=m ++CONFIG_DVB_USB_AZ6027=m ++CONFIG_DVB_USB_LME2510=m ++CONFIG_DVB_USB_TECHNISAT_USB2=m ++CONFIG_SMS_SIANO_MDTV=m ++CONFIG_SMS_USB_DRV=m ++CONFIG_DVB_B2C2_FLEXCOP=m ++CONFIG_DVB_B2C2_FLEXCOP_USB=m +CONFIG_FB=y +CONFIG_FB_BCM2708=y +CONFIG_FRAMEBUFFER_CONSOLE=y @@ -893,9 +1385,16 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_defconfig linux-rpi-bootc-3.2.23 +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LEDS_TRIGGER_HEARTBEAT=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=m ++CONFIG_RTC_CLASS=y ++CONFIG_RTC_DRV_DS1307=m +CONFIG_UIO=m +CONFIG_UIO_PDRV=m +CONFIG_UIO_PDRV_GENIRQ=m ++CONFIG_STAGING=y ++CONFIG_W35UND=m ++CONFIG_PRISM2_USB=m ++CONFIG_R8712U=m ++CONFIG_ZRAM=m +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y @@ -936,6 +1435,9 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_defconfig linux-rpi-bootc-3.2.23 +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_CONFIGFS_FS=y ++CONFIG_ECRYPT_FS=m ++CONFIG_HFS_FS=m ++CONFIG_HFSPLUS_FS=m +CONFIG_SQUASHFS=m +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_LZO=y @@ -946,6 +1448,9 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_defconfig linux-rpi-bootc-3.2.23 +CONFIG_NFS_V4=y +CONFIG_ROOT_NFS=y +CONFIG_NFS_FSCACHE=y ++CONFIG_NFSD=m ++CONFIG_NFSD_V3_ACL=y ++CONFIG_NFSD_V4=y +CONFIG_CIFS=m +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y @@ -993,28 +1498,23 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_defconfig linux-rpi-bootc-3.2.23 +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m -+CONFIG_NLS_UTF8=m +CONFIG_PRINTK_TIME=y ++CONFIG_DEBUG_FS=y +CONFIG_DETECT_HUNG_TASK=y +CONFIG_TIMER_STATS=y -+CONFIG_DEBUG_STACK_USAGE=y -+CONFIG_DEBUG_INFO=y ++# CONFIG_DEBUG_PREEMPT is not set +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_BOOT_PRINTK_DELAY=y +CONFIG_LATENCYTOP=y +CONFIG_SYSCTL_SYSCALL_CHECK=y -+CONFIG_IRQSOFF_TRACER=y -+CONFIG_SCHED_TRACER=y -+CONFIG_STACK_TRACER=y -+CONFIG_BLK_DEV_IO_TRACE=y -+CONFIG_FUNCTION_PROFILER=y ++# CONFIG_KPROBE_EVENT is not set +CONFIG_KGDB=y +CONFIG_KGDB_KDB=y +CONFIG_KDB_KEYBOARD=y +CONFIG_STRICT_DEVMEM=y -+CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_SEQIV=m +CONFIG_CRYPTO_CBC=y ++CONFIG_CRYPTO_XTS=m +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_MD5=y @@ -1025,14 +1525,15 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_defconfig linux-rpi-bootc-3.2.23 +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_DES=y -+CONFIG_CRYPTO_DEFLATE=m +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y -diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_emergency_defconfig linux-rpi-bootc-3.2.23/arch/arm/configs/bcmrpi_emergency_defconfig ---- linux-3.2.23/arch/arm/configs/bcmrpi_emergency_defconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/configs/bcmrpi_emergency_defconfig 2012-07-15 20:28:26.408092453 +0200 +diff --git a/arch/arm/configs/bcmrpi_emergency_defconfig b/arch/arm/configs/bcmrpi_emergency_defconfig +new file mode 100644 +index 0000000..3b40c49 +--- /dev/null ++++ b/arch/arm/configs/bcmrpi_emergency_defconfig @@ -0,0 +1,532 @@ +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set @@ -1566,61 +2067,109 @@ diff -Naur linux-3.2.23/arch/arm/configs/bcmrpi_emergency_defconfig linux-rpi-bo +# CONFIG_CRYPTO_HW is not set +CONFIG_CRC_ITU_T=y +CONFIG_LIBCRC32C=y -diff -Naur linux-3.2.23/arch/arm/Kconfig linux-rpi-bootc-3.2.23/arch/arm/Kconfig ---- linux-3.2.23/arch/arm/Kconfig 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/arch/arm/Kconfig 2012-07-15 20:28:26.140087409 +0200 -@@ -955,6 +955,21 @@ - help - Support for ST's SPEAr platform (SPEAr3xx, SPEAr6xx and SPEAr13xx). +diff --git a/arch/arm/include/asm/fiq.h b/arch/arm/include/asm/fiq.h +index d493d0b..f1a131b 100644 +--- a/arch/arm/include/asm/fiq.h ++++ b/arch/arm/include/asm/fiq.h +@@ -42,6 +42,7 @@ extern void disable_fiq(int fiq); + /* helpers defined in fiqasm.S: */ + extern void __set_fiq_regs(unsigned long const *regs); + extern void __get_fiq_regs(unsigned long *regs); ++extern void __FIQ_Branch(unsigned long *regs); -+config ARCH_BCM2708 -+ bool "Broadcom BCM2708 family" + static inline void set_fiq_regs(struct pt_regs const *regs) + { +diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c +index 4c164ec..3841bde 100644 +--- a/arch/arm/kernel/fiq.c ++++ b/arch/arm/kernel/fiq.c +@@ -135,6 +135,7 @@ void disable_fiq(int fiq) + EXPORT_SYMBOL(set_fiq_handler); + EXPORT_SYMBOL(__set_fiq_regs); /* defined in fiqasm.S */ + EXPORT_SYMBOL(__get_fiq_regs); /* defined in fiqasm.S */ ++EXPORT_SYMBOL(__FIQ_Branch); /* defined in fiqasm.S */ + EXPORT_SYMBOL(claim_fiq); + EXPORT_SYMBOL(release_fiq); + EXPORT_SYMBOL(enable_fiq); +diff --git a/arch/arm/kernel/fiqasm.S b/arch/arm/kernel/fiqasm.S +index 207f9d6..5233d54 100644 +--- a/arch/arm/kernel/fiqasm.S ++++ b/arch/arm/kernel/fiqasm.S +@@ -47,3 +47,7 @@ ENTRY(__get_fiq_regs) + mov r0, r0 @ avoid hazard prior to ARMv4 + mov pc, lr + ENDPROC(__get_fiq_regs) ++ ++ENTRY(__FIQ_Branch) ++ mov pc, r8 ++ENDPROC(__FIQ_Branch) +diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig +new file mode 100644 +index 0000000..5593167 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/Kconfig +@@ -0,0 +1,32 @@ ++menu "Broadcom BCM2708 Implementations" ++ depends on ARCH_BCM2708 ++ ++config MACH_BCM2708 ++ bool "Broadcom BCM2708 Development Platform" + select CPU_V6 -+ select ARM_AMBA -+ select HAVE_CLK -+ select HAVE_SCHED_CLOCK -+ select NEED_MACH_MEMORY_H -+ select CLKDEV_LOOKUP -+ select GENERIC_CLOCKEVENTS -+ select ARM_ERRATA_411920 -+ select MACH_BCM2708 -+ select VC4 + help -+ This enables support for Broadcom BCM2708 boards. ++ Include support for the Broadcom(R) BCM2708 platform. + - config ARCH_VT8500 - bool "VIA/WonderMedia 85xx" - select CPU_ARM926T -@@ -1098,6 +1113,7 @@ - source "arch/arm/mach-vt8500/Kconfig" - - source "arch/arm/mach-w90x900/Kconfig" -+source "arch/arm/mach-bcm2708/Kconfig" - - # Definitions to make life easier - config ARCH_ACORN -diff -Naur linux-3.2.23/arch/arm/Kconfig.debug linux-rpi-bootc-3.2.23/arch/arm/Kconfig.debug ---- linux-3.2.23/arch/arm/Kconfig.debug 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/arch/arm/Kconfig.debug 2012-07-15 20:28:25.899082875 +0200 -@@ -247,6 +247,14 @@ - their output to the standard serial port on the RealView - PB1176 platform. - -+ config DEBUG_BCM2708_UART0 -+ bool "Broadcom BCM2708 UART0 (PL011)" -+ depends on MACH_BCM2708 -+ help -+ Say Y here if you want the debug print routines to direct -+ their output to UART 0. The port must have been initialised -+ by the boot-loader before use. ++config BCM2708_GPIO ++ bool "BCM2708 gpio support" ++ depends on MACH_BCM2708 ++ select ARCH_REQUIRE_GPIOLIB ++ default y ++ help ++ Include support for the Broadcom(R) BCM2708 gpio. + - endchoice - - config EARLY_PRINTK -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/armctrl.c linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/armctrl.c ---- linux-3.2.23/arch/arm/mach-bcm2708/armctrl.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/armctrl.c 2012-07-15 20:28:26.133087278 +0200 -@@ -0,0 +1,399 @@ ++config BCM2708_VCMEM ++ bool "Videocore Memory" ++ depends on MACH_BCM2708 ++ default y ++ help ++ Helper for videocore memory access and total size allocation. ++ ++config BCM2708_NOL2CACHE ++ bool "Videocore L2 cache disable" ++ depends on MACH_BCM2708 ++ default n ++ help ++ Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt. ++ ++endmenu +diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile +new file mode 100644 +index 0000000..164ecb2 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/Makefile +@@ -0,0 +1,8 @@ ++# ++# Makefile for the linux kernel. ++# ++ ++obj-$(CONFIG_MACH_BCM2708) += clock.o bcm2708.o armctrl.o vcio.o power.o dma.o ++obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o ++obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o ++ +diff --git a/arch/arm/mach-bcm2708/Makefile.boot b/arch/arm/mach-bcm2708/Makefile.boot +new file mode 100644 +index 0000000..67039c3 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/Makefile.boot +@@ -0,0 +1,3 @@ ++ zreladdr-y := 0x00008000 ++params_phys-y := 0x00000100 ++initrd_phys-y := 0x00800000 +diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c +new file mode 100644 +index 0000000..cdaa761 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/armctrl.c +@@ -0,0 +1,416 @@ +/* + * linux/arch/arm/mach-bcm2708/armctrl.c + * @@ -1682,12 +2231,20 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/armctrl.c linux-rpi-bootc-3.2.23/a + IO_ADDRESS(ARM_IRQ_DIBL3), + 0 + }; ++ ++ if(d->irq >= FIQ_START) ++ { ++ writel(0, __io(IO_ADDRESS(ARM_IRQ_FAST))); ++ } ++ else ++ { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) -+ unsigned int data = (unsigned int)irq_get_chip_data(d->irq); ++ unsigned int data = (unsigned int)irq_get_chip_data(d->irq); +#else -+ unsigned int data = (unsigned int)get_irq_chip_data(irq); ++ unsigned int data = (unsigned int)get_irq_chip_data(irq); +#endif -+ writel(1 << (data & 0x1f), __io(disables[(data >> 5) & 0x3])); ++ writel(1 << (data & 0x1f), __io(disables[(data >> 5) & 0x3])); ++ } +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) @@ -1702,12 +2259,21 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/armctrl.c linux-rpi-bootc-3.2.23/a + IO_ADDRESS(ARM_IRQ_ENBL3), + 0 + }; ++ ++ if(d->irq >= FIQ_START) ++ { ++ unsigned int data = (unsigned int)irq_get_chip_data(d->irq) - FIQ_START; ++ writel(0x80 | data, __io(IO_ADDRESS(ARM_IRQ_FAST))); ++ } ++ else ++ { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) -+ unsigned int data = (unsigned int)irq_get_chip_data(d->irq); ++ unsigned int data = (unsigned int)irq_get_chip_data(d->irq); +#else -+ unsigned int data = (unsigned int)get_irq_chip_data(irq); ++ unsigned int data = (unsigned int)get_irq_chip_data(irq); +#endif -+ writel(1 << (data & 0x1f), __io(enables[(data >> 5) & 0x3])); ++ writel(1 << (data & 0x1f), __io(enables[(data >> 5) & 0x3])); ++ } +} + +#if defined(CONFIG_PM) @@ -2002,7 +2568,7 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/armctrl.c linux-rpi-bootc-3.2.23/a + + for (irq = 0; irq < NR_IRQS; irq++) { + unsigned int data = irq; -+ if (irq >= INTERRUPT_JPEG) ++ if (irq >= INTERRUPT_JPEG && irq <= INTERRUPT_ARASANSDIO) + data = remap_irqs[irq - INTERRUPT_JPEG]; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38) @@ -2020,9 +2586,11 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/armctrl.c linux-rpi-bootc-3.2.23/a + armctrl_pm_register(base, irq_start, resume_sources); + return 0; +} -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/armctrl.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/armctrl.h ---- linux-3.2.23/arch/arm/mach-bcm2708/armctrl.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/armctrl.h 2012-07-15 20:28:26.130087221 +0200 +diff --git a/arch/arm/mach-bcm2708/armctrl.h b/arch/arm/mach-bcm2708/armctrl.h +new file mode 100644 +index 0000000..0aa916e +--- /dev/null ++++ b/arch/arm/mach-bcm2708/armctrl.h @@ -0,0 +1,27 @@ +/* + * linux/arch/arm/mach-bcm2708/armctrl.h @@ -2051,10 +2619,12 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/armctrl.h linux-rpi-bootc-3.2.23/a + u32 armctrl_sources, u32 resume_sources); + +#endif -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/bcm2708.c linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/bcm2708.c ---- linux-3.2.23/arch/arm/mach-bcm2708/bcm2708.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/bcm2708.c 2012-07-15 20:28:26.130087221 +0200 -@@ -0,0 +1,769 @@ +diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c +new file mode 100644 +index 0000000..6f63532 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/bcm2708.c +@@ -0,0 +1,814 @@ +/* + * linux/arch/arm/mach-bcm2708/bcm2708.c + * @@ -2089,6 +2659,7 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/bcm2708.c linux-rpi-bootc-3.2.23/a +#include +#include +#include ++#include + +#include +#include @@ -2126,6 +2697,9 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/bcm2708.c linux-rpi-bootc-3.2.23/a + */ +#define DMA_MASK_BITS_COMMON 32 + ++// use GPIO 4 for the one-wire GPIO pin, if enabled ++#define W1_GPIO 4 ++ +static DEFINE_CLOCK_DATA(cd); + +/* command line parameters */ @@ -2348,6 +2922,19 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/bcm2708.c linux-rpi-bootc-3.2.23/a +}; +#endif /* CONFIG_MMC_BCM2708 */ + ++#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) ++static struct w1_gpio_platform_data w1_gpio_pdata = { ++ .pin = W1_GPIO, ++ .is_open_drain = 0, ++}; ++ ++static struct platform_device w1_device = { ++ .name = "w1-gpio", ++ .id = -1, ++ .dev.platform_data = &w1_gpio_pdata, ++}; ++#endif ++ +static u64 fb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_fb_device = { @@ -2389,12 +2976,32 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/bcm2708.c linux-rpi-bootc-3.2.23/a + .flags = IORESOURCE_MEM, + }, + [1] = { -+ .start = IRQ_USB, -+ .end = IRQ_USB, ++ .start = MPHI_BASE, ++ .end = MPHI_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [2] = { ++ .start = IRQ_HOSTPORT, ++ .end = IRQ_HOSTPORT, + .flags = IORESOURCE_IRQ, + }, +}; + ++extern bool fiq_fix_enable; ++ ++static struct resource bcm2708_usb_resources_no_fiq_fix[] = { ++ [0] = { ++ .start = USB_BASE, ++ .end = USB_BASE + SZ_128K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = IRQ_USB, ++ .end = IRQ_USB, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ +static u64 usb_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON); + +static struct platform_device bcm2708_usb_device = { @@ -2649,11 +3256,19 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/bcm2708.c linux-rpi-bootc-3.2.23/a +#ifdef CONFIG_BCM2708_GPIO + bcm_register_device(&bcm2708_gpio_device); +#endif ++#if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) ++ platform_device_register(&w1_device); ++#endif + bcm_register_device(&bcm2708_systemtimer_device); +#ifdef CONFIG_MMC_BCM2708 + bcm_register_device(&bcm2708_mci_device); +#endif + bcm_register_device(&bcm2708_fb_device); ++ if (!fiq_fix_enable) ++ { ++ bcm2708_usb_device.resource = bcm2708_usb_resources_no_fiq_fix; ++ bcm2708_usb_device.num_resources = ARRAY_SIZE(bcm2708_usb_resources_no_fiq_fix); ++ } + bcm_register_device(&bcm2708_usb_device); + bcm_register_device(&bcm2708_uart1_device); + bcm_register_device(&bcm2708_powerman_device); @@ -2687,7 +3302,7 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/bcm2708.c linux-rpi-bootc-3.2.23/a +#endif +} + -+#define TIMER_PERIOD 10000 /* HZ in microsecs */ ++#define TIMER_PERIOD DIV_ROUND_CLOSEST(STC_FREQ_HZ, HZ) + +static void timer_set_mode(enum clock_event_mode mode, + struct clock_event_device *clk) @@ -2824,349 +3439,11 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/bcm2708.c linux-rpi-bootc-3.2.23/a + &bcm2708_timer,.init_machine = + bcm2708_init, MACHINE_END module_param(boardrev, uint, 0644); +module_param(serial, uint, 0644); -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/bcm2708_gpio.c linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/bcm2708_gpio.c ---- linux-3.2.23/arch/arm/mach-bcm2708/bcm2708_gpio.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/bcm2708_gpio.c 2012-07-15 20:28:26.130087221 +0200 -@@ -0,0 +1,336 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/bcm2708_gpio.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" -+#define DRIVER_NAME BCM_GPIO_DRIVER_NAME -+#define BCM_GPIO_USE_IRQ 1 -+ -+#define GPIOFSEL(x) (0x00+(x)*4) -+#define GPIOSET(x) (0x1c+(x)*4) -+#define GPIOCLR(x) (0x28+(x)*4) -+#define GPIOLEV(x) (0x34+(x)*4) -+#define GPIOEDS(x) (0x40+(x)*4) -+#define GPIOREN(x) (0x4c+(x)*4) -+#define GPIOFEN(x) (0x58+(x)*4) -+#define GPIOHEN(x) (0x64+(x)*4) -+#define GPIOLEN(x) (0x70+(x)*4) -+#define GPIOAREN(x) (0x7c+(x)*4) -+#define GPIOAFEN(x) (0x88+(x)*4) -+#define GPIOUD(x) (0x94+(x)*4) -+#define GPIOUDCLK(x) (0x98+(x)*4) -+ -+enum { GPIO_FSEL_INPUT, GPIO_FSEL_OUTPUT, -+ GPIO_FSEL_ALT5, GPIO_FSEL_ALT_4, -+ GPIO_FSEL_ALT0, GPIO_FSEL_ALT1, -+ GPIO_FSEL_ALT2, GPIO_FSEL_ALT3, }; -+ -+ /* Each of the two spinlocks protects a different set of hardware -+ * regiters and data structurs. This decouples the code of the IRQ from -+ * the GPIO code. This also makes the case of a GPIO routine call from -+ * the IRQ code simpler. -+ */ -+static DEFINE_SPINLOCK(lock); /* GPIO registers */ -+ -+ -+struct bcm2708_gpio { -+ struct list_head list; -+ void __iomem *base; -+ struct gpio_chip gc; -+ unsigned long rising; -+ unsigned long falling; -+}; -+ -+static int bcm2708_set_function(struct gpio_chip *gc, unsigned offset, int function) -+{ -+ struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); -+ unsigned long flags; -+ unsigned gpiodir; -+ unsigned gpio_bank = offset/10; -+ unsigned gpio_field_offset = (offset - 10*gpio_bank) * 3; -+ -+//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set_function %p (%d,%d)\n", gc, offset, function); -+ if (offset >= BCM_NR_GPIOS) -+ return -EINVAL; -+ -+ spin_lock_irqsave(&lock, flags); -+ -+ gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank)); -+ gpiodir &= ~(7 << gpio_field_offset); -+ gpiodir |= function << gpio_field_offset; -+ writel(gpiodir, gpio->base + GPIOFSEL(gpio_bank)); -+ spin_unlock_irqrestore(&lock, flags); -+ gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank)); -+ -+ return 0; -+} -+ -+ -+static int bcm2708_gpio_dir_in(struct gpio_chip *gc, unsigned offset) -+{ -+ return bcm2708_set_function(gc, offset, GPIO_FSEL_INPUT); -+} -+ -+static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value); -+static int bcm2708_gpio_dir_out(struct gpio_chip *gc, unsigned offset, int value) -+{ -+ int ret; -+ ret = bcm2708_set_function(gc, offset, GPIO_FSEL_OUTPUT); -+ if (ret >= 0) -+ bcm2708_gpio_set(gc, offset, value); -+ return ret; -+} -+ -+static int bcm2708_gpio_get(struct gpio_chip *gc, unsigned offset) -+{ -+ struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); -+ unsigned gpio_bank = offset/32; -+ unsigned gpio_field_offset = (offset - 32*gpio_bank); -+ unsigned lev; -+ -+ if (offset >= BCM_NR_GPIOS) -+ return 0; -+ lev = readl(gpio->base + GPIOLEV(gpio_bank)); -+//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_get %p (%d)=%d\n", gc, offset, 0x1 & (lev>>gpio_field_offset)); -+ return 0x1 & (lev>>gpio_field_offset); -+} -+ -+static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value) -+{ -+ struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); -+ unsigned gpio_bank = offset/32; -+ unsigned gpio_field_offset = (offset - 32*gpio_bank); -+//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set %p (%d=%d)\n", gc, offset, value); -+ if (offset >= BCM_NR_GPIOS) -+ return; -+ if (value) -+ writel(1<base + GPIOSET(gpio_bank)); -+ else -+ writel(1<base + GPIOCLR(gpio_bank)); -+} -+ -+/************************************************************************************************************************* -+ * bcm2708 GPIO IRQ -+ */ -+ -+ -+#if BCM_GPIO_USE_IRQ -+ -+#define IRQ_TO_GPIO(x) irq_to_gpio(x) -+ -+static int bcm2708_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) { -+ return gpio_to_irq(gpio); -+} -+ -+ -+static int bcm2708_gpio_irq_set_type(struct irq_data *d, unsigned type) { -+ unsigned irq = d->irq; -+ struct bcm2708_gpio *gpio=irq_get_chip_data(irq); -+ -+ if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) -+ return -EINVAL; -+ -+ if (type & IRQ_TYPE_EDGE_RISING) { -+ gpio->rising |= (1 << IRQ_TO_GPIO(irq)); -+ } else { -+ gpio->rising &= ~(1 << IRQ_TO_GPIO(irq)); -+ } -+ -+ if (type & IRQ_TYPE_EDGE_FALLING) { -+ gpio->falling |= (1 << IRQ_TO_GPIO(irq)); -+ } else { -+ gpio->falling &= ~(1 << IRQ_TO_GPIO(irq)); -+ } -+ return 0; -+} -+ -+static void bcm2708_gpio_irq_mask(struct irq_data *d) { -+ unsigned irq = d->irq; -+ struct bcm2708_gpio *gpio=irq_get_chip_data(irq); -+ unsigned gn = IRQ_TO_GPIO(irq); -+ unsigned gb = gn/32; -+ unsigned long rising=readl(gpio->base + GPIOREN(gb)); -+ unsigned long falling=readl(gpio->base + GPIOFEN(gb)); -+ -+ writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb)); -+ writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb)); -+} -+ -+static void bcm2708_gpio_irq_unmask(struct irq_data *d) { -+ unsigned irq = d->irq; -+ struct bcm2708_gpio *gpio=irq_get_chip_data(irq); -+ unsigned gn = IRQ_TO_GPIO(irq); -+ unsigned gb = gn/32; -+ unsigned long rising=readl(gpio->base + GPIOREN(gb)); -+ unsigned long falling=readl(gpio->base + GPIOFEN(gb)); -+ -+ gn=gn%32; -+ -+ writel(1 << gn, gpio->base + GPIOEDS(gb)); -+ -+ if(gpio->rising & (1 << gn)) { -+ writel(rising | (1 << gn), gpio->base + GPIOREN(gb)); -+ } else { -+ writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb)); -+ } -+ -+ if(gpio->falling & (1 << gn)) { -+ writel(falling | (1 << gn), gpio->base + GPIOFEN(gb)); -+ } else { -+ writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb)); -+ } -+} -+ -+static struct irq_chip bcm2708_irqchip = { -+ .name = "GPIO", -+ .irq_enable = bcm2708_gpio_irq_unmask, -+ .irq_disable = bcm2708_gpio_irq_mask, -+ .irq_unmask = bcm2708_gpio_irq_unmask, -+ .irq_mask = bcm2708_gpio_irq_mask, -+ .irq_set_type = bcm2708_gpio_irq_set_type, -+}; -+ -+static irqreturn_t bcm2708_gpio_interrupt(int irq, void *dev_id) { -+ unsigned long edsr; -+ unsigned bank; -+ int i; -+ unsigned gpio; -+ for(bank=0; bank<=1; bank++) { -+ edsr=readl(__io_address(GPIO_BASE)+GPIOEDS(bank)); -+ for_each_set_bit(i, &edsr, 32) { -+ gpio=i+bank*32; -+ generic_handle_irq(gpio_to_irq(gpio)); -+ } -+ writel(0xffffffff, __io_address(GPIO_BASE)+GPIOEDS(bank)); -+ } -+ return IRQ_HANDLED; -+} -+ -+static struct irqaction bcm2708_gpio_irq = { -+ .name = "BCM2708 GPIO catchall handler", -+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, -+ .handler = bcm2708_gpio_interrupt, -+}; -+ -+ -+static void bcm2708_gpio_irq_init(struct bcm2708_gpio *ucb) { -+ unsigned irq; -+ -+ ucb->gc.to_irq=bcm2708_gpio_to_irq; -+ -+ for (irq=GPIO_IRQ_START; irq<(GPIO_IRQ_START+GPIO_IRQS); irq++) { -+ irq_set_chip_data(irq, ucb); -+ irq_set_chip(irq, &bcm2708_irqchip); -+ set_irq_flags(irq, IRQF_VALID); -+ } -+ setup_irq(IRQ_GPIO3, &bcm2708_gpio_irq); -+} -+ -+#else -+ -+static void bcm2708_gpio_irq_init(struct bcm2708_gpio *ucb) { -+} -+ -+#endif /* #if BCM_GPIO_USE_IRQ ******************************************************************************************************************/ -+ -+static int bcm2708_gpio_probe(struct platform_device *dev) -+{ -+ struct bcm2708_gpio *ucb; -+ struct resource *res; -+ int err = 0; -+ -+ printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_probe %p\n", dev); -+ -+ ucb = kzalloc(sizeof(*ucb), GFP_KERNEL); -+ if (NULL == ucb) { -+ printk(KERN_ERR DRIVER_NAME ": failed to allocate " -+ "mailbox memory\n"); -+ err = -ENOMEM; -+ goto err; -+ } -+ -+ res = platform_get_resource(dev, IORESOURCE_MEM, 0); -+ -+ platform_set_drvdata(dev, ucb); -+ ucb->base = __io_address(GPIO_BASE); -+ -+ ucb->gc.label = "bcm2708_gpio"; -+ ucb->gc.base = 0; -+ ucb->gc.ngpio = BCM_NR_GPIOS; -+ ucb->gc.owner = THIS_MODULE; -+ -+ ucb->gc.direction_input = bcm2708_gpio_dir_in; -+ ucb->gc.direction_output = bcm2708_gpio_dir_out; -+ ucb->gc.get = bcm2708_gpio_get; -+ ucb->gc.set = bcm2708_gpio_set; -+ ucb->gc.can_sleep = 0; -+ -+ bcm2708_gpio_irq_init(ucb); -+ -+ err = gpiochip_add(&ucb->gc); -+ if (err) -+ goto err; -+ -+err: -+ return err; -+ -+} -+ -+static int bcm2708_gpio_remove(struct platform_device *dev) -+{ -+ int err = 0; -+ struct bcm2708_gpio *ucb = platform_get_drvdata(dev); -+ -+ printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_remove %p\n", dev); -+ -+ err = gpiochip_remove(&ucb->gc); -+ -+ platform_set_drvdata(dev, NULL); -+ kfree(ucb); -+ -+ return err; -+} -+ -+static struct platform_driver bcm2708_gpio_driver = { -+ .probe = bcm2708_gpio_probe, -+ .remove = bcm2708_gpio_remove, -+ .driver = { -+ .name = "bcm2708_gpio" -+ }, -+}; -+ -+static int __init bcm2708_gpio_init(void) -+{ -+ return platform_driver_register(&bcm2708_gpio_driver); -+} -+ -+static void __exit bcm2708_gpio_exit(void) -+{ -+ platform_driver_unregister(&bcm2708_gpio_driver); -+} -+ -+module_init(bcm2708_gpio_init); -+module_exit(bcm2708_gpio_exit); -+ -+MODULE_DESCRIPTION("Broadcom BCM2708 GPIO driver"); -+MODULE_LICENSE("GPL"); -+ -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/bcm2708.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/bcm2708.h ---- linux-3.2.23/arch/arm/mach-bcm2708/bcm2708.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/bcm2708.h 2012-07-15 20:28:26.133087278 +0200 +diff --git a/arch/arm/mach-bcm2708/bcm2708.h b/arch/arm/mach-bcm2708/bcm2708.h +new file mode 100644 +index 0000000..dfe8700 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/bcm2708.h @@ -0,0 +1,51 @@ +/* + * linux/arch/arm/mach-bcm2708/bcm2708.h @@ -3219,9 +3496,356 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/bcm2708.h linux-rpi-bootc-3.2.23/a +} + +#endif -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/clock.c linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/clock.c ---- linux-3.2.23/arch/arm/mach-bcm2708/clock.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/clock.c 2012-07-15 20:28:26.130087221 +0200 +diff --git a/arch/arm/mach-bcm2708/bcm2708_gpio.c b/arch/arm/mach-bcm2708/bcm2708_gpio.c +new file mode 100644 +index 0000000..6c81d9d +--- /dev/null ++++ b/arch/arm/mach-bcm2708/bcm2708_gpio.c +@@ -0,0 +1,339 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/bcm2708_gpio.c ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" ++#define DRIVER_NAME BCM_GPIO_DRIVER_NAME ++#define BCM_GPIO_USE_IRQ 1 ++ ++#define GPIOFSEL(x) (0x00+(x)*4) ++#define GPIOSET(x) (0x1c+(x)*4) ++#define GPIOCLR(x) (0x28+(x)*4) ++#define GPIOLEV(x) (0x34+(x)*4) ++#define GPIOEDS(x) (0x40+(x)*4) ++#define GPIOREN(x) (0x4c+(x)*4) ++#define GPIOFEN(x) (0x58+(x)*4) ++#define GPIOHEN(x) (0x64+(x)*4) ++#define GPIOLEN(x) (0x70+(x)*4) ++#define GPIOAREN(x) (0x7c+(x)*4) ++#define GPIOAFEN(x) (0x88+(x)*4) ++#define GPIOUD(x) (0x94+(x)*4) ++#define GPIOUDCLK(x) (0x98+(x)*4) ++ ++enum { GPIO_FSEL_INPUT, GPIO_FSEL_OUTPUT, ++ GPIO_FSEL_ALT5, GPIO_FSEL_ALT_4, ++ GPIO_FSEL_ALT0, GPIO_FSEL_ALT1, ++ GPIO_FSEL_ALT2, GPIO_FSEL_ALT3, ++}; ++ ++ /* Each of the two spinlocks protects a different set of hardware ++ * regiters and data structurs. This decouples the code of the IRQ from ++ * the GPIO code. This also makes the case of a GPIO routine call from ++ * the IRQ code simpler. ++ */ ++static DEFINE_SPINLOCK(lock); /* GPIO registers */ ++ ++struct bcm2708_gpio { ++ struct list_head list; ++ void __iomem *base; ++ struct gpio_chip gc; ++ unsigned long rising; ++ unsigned long falling; ++}; ++ ++static int bcm2708_set_function(struct gpio_chip *gc, unsigned offset, ++ int function) ++{ ++ struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); ++ unsigned long flags; ++ unsigned gpiodir; ++ unsigned gpio_bank = offset / 10; ++ unsigned gpio_field_offset = (offset - 10 * gpio_bank) * 3; ++ ++//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set_function %p (%d,%d)\n", gc, offset, function); ++ if (offset >= BCM_NR_GPIOS) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank)); ++ gpiodir &= ~(7 << gpio_field_offset); ++ gpiodir |= function << gpio_field_offset; ++ writel(gpiodir, gpio->base + GPIOFSEL(gpio_bank)); ++ spin_unlock_irqrestore(&lock, flags); ++ gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank)); ++ ++ return 0; ++} ++ ++static int bcm2708_gpio_dir_in(struct gpio_chip *gc, unsigned offset) ++{ ++ return bcm2708_set_function(gc, offset, GPIO_FSEL_INPUT); ++} ++ ++static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value); ++static int bcm2708_gpio_dir_out(struct gpio_chip *gc, unsigned offset, ++ int value) ++{ ++ int ret; ++ ret = bcm2708_set_function(gc, offset, GPIO_FSEL_OUTPUT); ++ if (ret >= 0) ++ bcm2708_gpio_set(gc, offset, value); ++ return ret; ++} ++ ++static int bcm2708_gpio_get(struct gpio_chip *gc, unsigned offset) ++{ ++ struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); ++ unsigned gpio_bank = offset / 32; ++ unsigned gpio_field_offset = (offset - 32 * gpio_bank); ++ unsigned lev; ++ ++ if (offset >= BCM_NR_GPIOS) ++ return 0; ++ lev = readl(gpio->base + GPIOLEV(gpio_bank)); ++//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_get %p (%d)=%d\n", gc, offset, 0x1 & (lev>>gpio_field_offset)); ++ return 0x1 & (lev >> gpio_field_offset); ++} ++ ++static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value) ++{ ++ struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc); ++ unsigned gpio_bank = offset / 32; ++ unsigned gpio_field_offset = (offset - 32 * gpio_bank); ++//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set %p (%d=%d)\n", gc, offset, value); ++ if (offset >= BCM_NR_GPIOS) ++ return; ++ if (value) ++ writel(1 << gpio_field_offset, gpio->base + GPIOSET(gpio_bank)); ++ else ++ writel(1 << gpio_field_offset, gpio->base + GPIOCLR(gpio_bank)); ++} ++ ++/************************************************************************************************************************* ++ * bcm2708 GPIO IRQ ++ */ ++ ++#if BCM_GPIO_USE_IRQ ++ ++#define IRQ_TO_GPIO(x) irq_to_gpio(x) ++ ++static int bcm2708_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) ++{ ++ return gpio_to_irq(gpio); ++} ++ ++static int bcm2708_gpio_irq_set_type(struct irq_data *d, unsigned type) ++{ ++ unsigned irq = d->irq; ++ struct bcm2708_gpio *gpio = irq_get_chip_data(irq); ++ ++ if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) ++ return -EINVAL; ++ ++ if (type & IRQ_TYPE_EDGE_RISING) { ++ gpio->rising |= (1 << IRQ_TO_GPIO(irq)); ++ } else { ++ gpio->rising &= ~(1 << IRQ_TO_GPIO(irq)); ++ } ++ ++ if (type & IRQ_TYPE_EDGE_FALLING) { ++ gpio->falling |= (1 << IRQ_TO_GPIO(irq)); ++ } else { ++ gpio->falling &= ~(1 << IRQ_TO_GPIO(irq)); ++ } ++ return 0; ++} ++ ++static void bcm2708_gpio_irq_mask(struct irq_data *d) ++{ ++ unsigned irq = d->irq; ++ struct bcm2708_gpio *gpio = irq_get_chip_data(irq); ++ unsigned gn = IRQ_TO_GPIO(irq); ++ unsigned gb = gn / 32; ++ unsigned long rising = readl(gpio->base + GPIOREN(gb)); ++ unsigned long falling = readl(gpio->base + GPIOFEN(gb)); ++ ++ writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb)); ++ writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb)); ++} ++ ++static void bcm2708_gpio_irq_unmask(struct irq_data *d) ++{ ++ unsigned irq = d->irq; ++ struct bcm2708_gpio *gpio = irq_get_chip_data(irq); ++ unsigned gn = IRQ_TO_GPIO(irq); ++ unsigned gb = gn / 32; ++ unsigned long rising = readl(gpio->base + GPIOREN(gb)); ++ unsigned long falling = readl(gpio->base + GPIOFEN(gb)); ++ ++ gn = gn % 32; ++ ++ writel(1 << gn, gpio->base + GPIOEDS(gb)); ++ ++ if (gpio->rising & (1 << gn)) { ++ writel(rising | (1 << gn), gpio->base + GPIOREN(gb)); ++ } else { ++ writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb)); ++ } ++ ++ if (gpio->falling & (1 << gn)) { ++ writel(falling | (1 << gn), gpio->base + GPIOFEN(gb)); ++ } else { ++ writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb)); ++ } ++} ++ ++static struct irq_chip bcm2708_irqchip = { ++ .name = "GPIO", ++ .irq_enable = bcm2708_gpio_irq_unmask, ++ .irq_disable = bcm2708_gpio_irq_mask, ++ .irq_unmask = bcm2708_gpio_irq_unmask, ++ .irq_mask = bcm2708_gpio_irq_mask, ++ .irq_set_type = bcm2708_gpio_irq_set_type, ++}; ++ ++static irqreturn_t bcm2708_gpio_interrupt(int irq, void *dev_id) ++{ ++ unsigned long edsr; ++ unsigned bank; ++ int i; ++ unsigned gpio; ++ for (bank = 0; bank <= 1; bank++) { ++ edsr = readl(__io_address(GPIO_BASE) + GPIOEDS(bank)); ++ for_each_set_bit(i, &edsr, 32) { ++ gpio = i + bank * 32; ++ generic_handle_irq(gpio_to_irq(gpio)); ++ } ++ writel(0xffffffff, __io_address(GPIO_BASE) + GPIOEDS(bank)); ++ } ++ return IRQ_HANDLED; ++} ++ ++static struct irqaction bcm2708_gpio_irq = { ++ .name = "BCM2708 GPIO catchall handler", ++ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, ++ .handler = bcm2708_gpio_interrupt, ++}; ++ ++static void bcm2708_gpio_irq_init(struct bcm2708_gpio *ucb) ++{ ++ unsigned irq; ++ ++ ucb->gc.to_irq = bcm2708_gpio_to_irq; ++ ++ for (irq = GPIO_IRQ_START; irq < (GPIO_IRQ_START + GPIO_IRQS); irq++) { ++ irq_set_chip_data(irq, ucb); ++ irq_set_chip(irq, &bcm2708_irqchip); ++ set_irq_flags(irq, IRQF_VALID); ++ } ++ setup_irq(IRQ_GPIO3, &bcm2708_gpio_irq); ++} ++ ++#else ++ ++static void bcm2708_gpio_irq_init(struct bcm2708_gpio *ucb) ++{ ++} ++ ++#endif /* #if BCM_GPIO_USE_IRQ ***************************************************************************************************************** */ ++ ++static int bcm2708_gpio_probe(struct platform_device *dev) ++{ ++ struct bcm2708_gpio *ucb; ++ struct resource *res; ++ int err = 0; ++ ++ printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_probe %p\n", dev); ++ ++ ucb = kzalloc(sizeof(*ucb), GFP_KERNEL); ++ if (NULL == ucb) { ++ printk(KERN_ERR DRIVER_NAME ": failed to allocate " ++ "mailbox memory\n"); ++ err = -ENOMEM; ++ goto err; ++ } ++ ++ res = platform_get_resource(dev, IORESOURCE_MEM, 0); ++ ++ platform_set_drvdata(dev, ucb); ++ ucb->base = __io_address(GPIO_BASE); ++ ++ ucb->gc.label = "bcm2708_gpio"; ++ ucb->gc.base = 0; ++ ucb->gc.ngpio = BCM_NR_GPIOS; ++ ucb->gc.owner = THIS_MODULE; ++ ++ ucb->gc.direction_input = bcm2708_gpio_dir_in; ++ ucb->gc.direction_output = bcm2708_gpio_dir_out; ++ ucb->gc.get = bcm2708_gpio_get; ++ ucb->gc.set = bcm2708_gpio_set; ++ ucb->gc.can_sleep = 0; ++ ++ bcm2708_gpio_irq_init(ucb); ++ ++ err = gpiochip_add(&ucb->gc); ++ if (err) ++ goto err; ++ ++err: ++ return err; ++ ++} ++ ++static int bcm2708_gpio_remove(struct platform_device *dev) ++{ ++ int err = 0; ++ struct bcm2708_gpio *ucb = platform_get_drvdata(dev); ++ ++ printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_remove %p\n", dev); ++ ++ err = gpiochip_remove(&ucb->gc); ++ ++ platform_set_drvdata(dev, NULL); ++ kfree(ucb); ++ ++ return err; ++} ++ ++static struct platform_driver bcm2708_gpio_driver = { ++ .probe = bcm2708_gpio_probe, ++ .remove = bcm2708_gpio_remove, ++ .driver = { ++ .name = "bcm2708_gpio"}, ++}; ++ ++static int __init bcm2708_gpio_init(void) ++{ ++ return platform_driver_register(&bcm2708_gpio_driver); ++} ++ ++static void __exit bcm2708_gpio_exit(void) ++{ ++ platform_driver_unregister(&bcm2708_gpio_driver); ++} ++ ++module_init(bcm2708_gpio_init); ++module_exit(bcm2708_gpio_exit); ++ ++MODULE_DESCRIPTION("Broadcom BCM2708 GPIO driver"); ++MODULE_LICENSE("GPL"); +diff --git a/arch/arm/mach-bcm2708/clock.c b/arch/arm/mach-bcm2708/clock.c +new file mode 100644 +index 0000000..4fc556e +--- /dev/null ++++ b/arch/arm/mach-bcm2708/clock.c @@ -0,0 +1,61 @@ +/* + * linux/arch/arm/mach-bcm2708/clock.c @@ -3284,9 +3908,11 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/clock.c linux-rpi-bootc-3.2.23/arc + return -EIO; +} +EXPORT_SYMBOL(clk_set_rate); -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/clock.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/clock.h ---- linux-3.2.23/arch/arm/mach-bcm2708/clock.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/clock.h 2012-07-15 20:28:26.131087240 +0200 +diff --git a/arch/arm/mach-bcm2708/clock.h b/arch/arm/mach-bcm2708/clock.h +new file mode 100644 +index 0000000..5f9d725 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/clock.h @@ -0,0 +1,24 @@ +/* + * linux/arch/arm/mach-bcm2708/clock.h @@ -3312,9 +3938,11 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/clock.h linux-rpi-bootc-3.2.23/arc +struct clk { + unsigned long rate; +}; -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/dma.c linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/dma.c ---- linux-3.2.23/arch/arm/mach-bcm2708/dma.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/dma.c 2012-07-15 20:28:26.133087278 +0200 +diff --git a/arch/arm/mach-bcm2708/dma.c b/arch/arm/mach-bcm2708/dma.c +new file mode 100644 +index 0000000..0b7a4f6 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/dma.c @@ -0,0 +1,397 @@ +/* + * linux/arch/arm/mach-bcm2708/dma.c @@ -3713,9 +4341,11 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/dma.c linux-rpi-bootc-3.2.23/arch/ +MODULE_LICENSE("GPL"); + +MODULE_PARM_DESC(dmachans, "Bitmap of DMA channels available to the ARM"); -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/arm_control.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/arm_control.h ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/arm_control.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/arm_control.h 2012-07-15 20:28:26.131087240 +0200 +diff --git a/arch/arm/mach-bcm2708/include/mach/arm_control.h b/arch/arm/mach-bcm2708/include/mach/arm_control.h +new file mode 100644 +index 0000000..a82bb92 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/arm_control.h @@ -0,0 +1,419 @@ +/* + * linux/arch/arm/mach-bcm2708/arm_control.h @@ -4136,9 +4766,11 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/arm_control.h linux-r +#define AJBTDO HW_REGISTER_RW(AJB_BASE+0x0c) + +#endif -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/arm_power.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/arm_power.h ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/arm_power.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/arm_power.h 2012-07-15 20:28:26.132087259 +0200 +diff --git a/arch/arm/mach-bcm2708/include/mach/arm_power.h b/arch/arm/mach-bcm2708/include/mach/arm_power.h +new file mode 100644 +index 0000000..aae9136 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/arm_power.h @@ -0,0 +1,60 @@ +/* + * linux/arch/arm/mach-bcm2708/include/mach/arm_power.h @@ -4200,9 +4832,11 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/arm_power.h linux-rpi +}; + +#endif -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/clkdev.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/clkdev.h ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/clkdev.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/clkdev.h 2012-07-15 20:28:26.132087259 +0200 +diff --git a/arch/arm/mach-bcm2708/include/mach/clkdev.h b/arch/arm/mach-bcm2708/include/mach/clkdev.h +new file mode 100644 +index 0000000..04b37a8 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/clkdev.h @@ -0,0 +1,7 @@ +#ifndef __ASM_MACH_CLKDEV_H +#define __ASM_MACH_CLKDEV_H @@ -4211,9 +4845,11 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/clkdev.h linux-rpi-bo +#define __clk_put(clk) do { } while (0) + +#endif -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/debug-macro.S linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/debug-macro.S ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/debug-macro.S 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/debug-macro.S 2012-07-15 20:28:26.132087259 +0200 +diff --git a/arch/arm/mach-bcm2708/include/mach/debug-macro.S b/arch/arm/mach-bcm2708/include/mach/debug-macro.S +new file mode 100644 +index 0000000..2d0dc1c +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/debug-macro.S @@ -0,0 +1,22 @@ +/* arch/arm/mach-bcm2708/include/mach/debug-macro.S + * @@ -4237,9 +4873,11 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/debug-macro.S linux-r + .endm + +#include -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/dma.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/dma.h ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/dma.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/dma.h 2012-07-15 20:28:26.131087240 +0200 +diff --git a/arch/arm/mach-bcm2708/include/mach/dma.h b/arch/arm/mach-bcm2708/include/mach/dma.h +new file mode 100644 +index 0000000..25e06d7 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/dma.h @@ -0,0 +1,84 @@ +/* + * linux/arch/arm/mach-bcm2708/include/mach/dma.h @@ -4325,9 +4963,11 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/dma.h linux-rpi-bootc + + +#endif /* _MACH_BCM2708_DMA_H */ -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/entry-macro.S linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/entry-macro.S ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/entry-macro.S 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/entry-macro.S 2012-07-15 20:28:26.132087259 +0200 +diff --git a/arch/arm/mach-bcm2708/include/mach/entry-macro.S b/arch/arm/mach-bcm2708/include/mach/entry-macro.S +new file mode 100644 +index 0000000..79b62d9 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/entry-macro.S @@ -0,0 +1,69 @@ +/* + * arch/arm/mach-bcm2708/include/mach/entry-macro.S @@ -4398,9 +5038,11 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/entry-macro.S linux-r +1020: @ EQ will be set if no irqs pending + + .endm -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/frc.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/frc.h ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/frc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/frc.h 2012-07-15 20:28:26.132087259 +0200 +diff --git a/arch/arm/mach-bcm2708/include/mach/frc.h b/arch/arm/mach-bcm2708/include/mach/frc.h +new file mode 100644 +index 0000000..dd51e07 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/frc.h @@ -0,0 +1,38 @@ +/* + * arch/arm/mach-bcm2708/include/mach/timex.h @@ -4440,10 +5082,12 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/frc.h linux-rpi-bootc +extern unsigned long long frc_clock_ticks63(void); + +#endif -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/gpio.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/gpio.h ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/gpio.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/gpio.h 2012-07-15 20:28:26.133087278 +0200 -@@ -0,0 +1,47 @@ +diff --git a/arch/arm/mach-bcm2708/include/mach/gpio.h b/arch/arm/mach-bcm2708/include/mach/gpio.h +new file mode 100644 +index 0000000..0b82f26 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/gpio.h +@@ -0,0 +1,48 @@ +/* + * arch/arm/mach-bcm2708/include/mach/gpio.h + * @@ -4491,9 +5135,12 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/gpio.h linux-rpi-boot +#endif /* CONFIG_GPIOLIB */ + +#endif -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/hardware.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/hardware.h ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/hardware.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/hardware.h 2012-07-15 20:28:26.132087259 +0200 ++ +diff --git a/arch/arm/mach-bcm2708/include/mach/hardware.h b/arch/arm/mach-bcm2708/include/mach/hardware.h +new file mode 100644 +index 0000000..c2954e8 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/hardware.h @@ -0,0 +1,28 @@ +/* + * arch/arm/mach-bcm2708/include/mach/hardware.h @@ -4523,9 +5170,11 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/hardware.h linux-rpi- +#include + +#endif -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/io.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/io.h ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/io.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/io.h 2012-07-15 20:28:26.132087259 +0200 +diff --git a/arch/arm/mach-bcm2708/include/mach/io.h b/arch/arm/mach-bcm2708/include/mach/io.h +new file mode 100644 +index 0000000..e8c7fca +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/io.h @@ -0,0 +1,28 @@ +/* + * arch/arm/mach-bcm2708/include/mach/io.h @@ -4555,10 +5204,12 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/io.h linux-rpi-bootc- +#define __mem_pci(a) (a) + +#endif -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/irqs.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/irqs.h ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/irqs.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/irqs.h 2012-07-15 20:28:26.131087240 +0200 -@@ -0,0 +1,196 @@ +diff --git a/arch/arm/mach-bcm2708/include/mach/irqs.h b/arch/arm/mach-bcm2708/include/mach/irqs.h +new file mode 100644 +index 0000000..9aaedf1 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/irqs.h +@@ -0,0 +1,199 @@ +/* + * arch/arm/mach-bcm2708/include/mach/irqs.h + * @@ -4667,97 +5318,102 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/irqs.h linux-rpi-boot +#define IRQ_PENDING1 (IRQ_ARMCTRL_START + INTERRUPT_PENDING1) +#define IRQ_PENDING2 (IRQ_ARMCTRL_START + INTERRUPT_PENDING2) + ++#define FIQ_START HARD_IRQS ++ +/* + * FIQ interrupts definitions are the same as the INT definitions. + */ -+#define FIQ_TIMER0 INT_TIMER0 -+#define FIQ_TIMER1 INT_TIMER1 -+#define FIQ_TIMER2 INT_TIMER2 -+#define FIQ_TIMER3 INT_TIMER3 -+#define FIQ_CODEC0 INT_CODEC0 -+#define FIQ_CODEC1 INT_CODEC1 -+#define FIQ_CODEC2 INT_CODEC2 -+#define FIQ_JPEG INT_JPEG -+#define FIQ_ISP INT_ISP -+#define FIQ_USB INT_USB -+#define FIQ_3D INT_3D -+#define FIQ_TRANSPOSER INT_TRANSPOSER -+#define FIQ_MULTICORESYNC0 INT_MULTICORESYNC0 -+#define FIQ_MULTICORESYNC1 INT_MULTICORESYNC1 -+#define FIQ_MULTICORESYNC2 INT_MULTICORESYNC2 -+#define FIQ_MULTICORESYNC3 INT_MULTICORESYNC3 -+#define FIQ_DMA0 INT_DMA0 -+#define FIQ_DMA1 INT_DMA1 -+#define FIQ_DMA2 INT_DMA2 -+#define FIQ_DMA3 INT_DMA3 -+#define FIQ_DMA4 INT_DMA4 -+#define FIQ_DMA5 INT_DMA5 -+#define FIQ_DMA6 INT_DMA6 -+#define FIQ_DMA7 INT_DMA7 -+#define FIQ_DMA8 INT_DMA8 -+#define FIQ_DMA9 INT_DMA9 -+#define FIQ_DMA10 INT_DMA10 -+#define FIQ_DMA11 INT_DMA11 -+#define FIQ_DMA12 INT_DMA12 -+#define FIQ_AUX INT_AUX -+#define FIQ_ARM INT_ARM -+#define FIQ_VPUDMA INT_VPUDMA -+#define FIQ_HOSTPORT INT_HOSTPORT -+#define FIQ_VIDEOSCALER INT_VIDEOSCALER -+#define FIQ_CCP2TX INT_CCP2TX -+#define FIQ_SDC INT_SDC -+#define FIQ_DSI0 INT_DSI0 -+#define FIQ_AVE INT_AVE -+#define FIQ_CAM0 INT_CAM0 -+#define FIQ_CAM1 INT_CAM1 -+#define FIQ_HDMI0 INT_HDMI0 -+#define FIQ_HDMI1 INT_HDMI1 -+#define FIQ_PIXELVALVE1 INT_PIXELVALVE1 -+#define FIQ_I2CSPISLV INT_I2CSPISLV -+#define FIQ_DSI1 INT_DSI1 -+#define FIQ_PWA0 INT_PWA0 -+#define FIQ_PWA1 INT_PWA1 -+#define FIQ_CPR INT_CPR -+#define FIQ_SMI INT_SMI -+#define FIQ_GPIO0 INT_GPIO0 -+#define FIQ_GPIO1 INT_GPIO1 -+#define FIQ_GPIO2 INT_GPIO2 -+#define FIQ_GPIO3 INT_GPIO3 -+#define FIQ_I2C INT_I2C -+#define FIQ_SPI INT_SPI -+#define FIQ_I2SPCM INT_I2SPCM -+#define FIQ_SDIO INT_SDIO -+#define FIQ_UART INT_UART -+#define FIQ_SLIMBUS INT_SLIMBUS -+#define FIQ_VEC INT_VEC -+#define FIQ_CPG INT_CPG -+#define FIQ_RNG INT_RNG -+#define FIQ_ARASANSDIO INT_ARASANSDIO -+#define FIQ_AVSPMON INT_AVSPMON ++#define FIQ_TIMER0 (FIQ_START+INTERRUPT_TIMER0) ++#define FIQ_TIMER1 (FIQ_START+INTERRUPT_TIMER1) ++#define FIQ_TIMER2 (FIQ_START+INTERRUPT_TIMER2) ++#define FIQ_TIMER3 (FIQ_START+INTERRUPT_TIMER3) ++#define FIQ_CODEC0 (FIQ_START+INTERRUPT_CODEC0) ++#define FIQ_CODEC1 (FIQ_START+INTERRUPT_CODEC1) ++#define FIQ_CODEC2 (FIQ_START+INTERRUPT_CODEC2) ++#define FIQ_JPEG (FIQ_START+INTERRUPT_JPEG) ++#define FIQ_ISP (FIQ_START+INTERRUPT_ISP) ++#define FIQ_USB (FIQ_START+INTERRUPT_USB) ++#define FIQ_3D (FIQ_START+INTERRUPT_3D) ++#define FIQ_TRANSPOSER (FIQ_START+INTERRUPT_TRANSPOSER) ++#define FIQ_MULTICORESYNC0 (FIQ_START+INTERRUPT_MULTICORESYNC0) ++#define FIQ_MULTICORESYNC1 (FIQ_START+INTERRUPT_MULTICORESYNC1) ++#define FIQ_MULTICORESYNC2 (FIQ_START+INTERRUPT_MULTICORESYNC2) ++#define FIQ_MULTICORESYNC3 (FIQ_START+INTERRUPT_MULTICORESYNC3) ++#define FIQ_DMA0 (FIQ_START+INTERRUPT_DMA0) ++#define FIQ_DMA1 (FIQ_START+INTERRUPT_DMA1) ++#define FIQ_DMA2 (FIQ_START+INTERRUPT_DMA2) ++#define FIQ_DMA3 (FIQ_START+INTERRUPT_DMA3) ++#define FIQ_DMA4 (FIQ_START+INTERRUPT_DMA4) ++#define FIQ_DMA5 (FIQ_START+INTERRUPT_DMA5) ++#define FIQ_DMA6 (FIQ_START+INTERRUPT_DMA6) ++#define FIQ_DMA7 (FIQ_START+INTERRUPT_DMA7) ++#define FIQ_DMA8 (FIQ_START+INTERRUPT_DMA8) ++#define FIQ_DMA9 (FIQ_START+INTERRUPT_DMA9) ++#define FIQ_DMA10 (FIQ_START+INTERRUPT_DMA10) ++#define FIQ_DMA11 (FIQ_START+INTERRUPT_DMA11) ++#define FIQ_DMA12 (FIQ_START+INTERRUPT_DMA12) ++#define FIQ_AUX (FIQ_START+INTERRUPT_AUX) ++#define FIQ_ARM (FIQ_START+INTERRUPT_ARM) ++#define FIQ_VPUDMA (FIQ_START+INTERRUPT_VPUDMA) ++#define FIQ_HOSTPORT (FIQ_START+INTERRUPT_HOSTPORT) ++#define FIQ_VIDEOSCALER (FIQ_START+INTERRUPT_VIDEOSCALER) ++#define FIQ_CCP2TX (FIQ_START+INTERRUPT_CCP2TX) ++#define FIQ_SDC (FIQ_START+INTERRUPT_SDC) ++#define FIQ_DSI0 (FIQ_START+INTERRUPT_DSI0) ++#define FIQ_AVE (FIQ_START+INTERRUPT_AVE) ++#define FIQ_CAM0 (FIQ_START+INTERRUPT_CAM0) ++#define FIQ_CAM1 (FIQ_START+INTERRUPT_CAM1) ++#define FIQ_HDMI0 (FIQ_START+INTERRUPT_HDMI0) ++#define FIQ_HDMI1 (FIQ_START+INTERRUPT_HDMI1) ++#define FIQ_PIXELVALVE1 (FIQ_START+INTERRUPT_PIXELVALVE1) ++#define FIQ_I2CSPISLV (FIQ_START+INTERRUPT_I2CSPISLV) ++#define FIQ_DSI1 (FIQ_START+INTERRUPT_DSI1) ++#define FIQ_PWA0 (FIQ_START+INTERRUPT_PWA0) ++#define FIQ_PWA1 (FIQ_START+INTERRUPT_PWA1) ++#define FIQ_CPR (FIQ_START+INTERRUPT_CPR) ++#define FIQ_SMI (FIQ_START+INTERRUPT_SMI) ++#define FIQ_GPIO0 (FIQ_START+INTERRUPT_GPIO0) ++#define FIQ_GPIO1 (FIQ_START+INTERRUPT_GPIO1) ++#define FIQ_GPIO2 (FIQ_START+INTERRUPT_GPIO2) ++#define FIQ_GPIO3 (FIQ_START+INTERRUPT_GPIO3) ++#define FIQ_I2C (FIQ_START+INTERRUPT_I2C) ++#define FIQ_SPI (FIQ_START+INTERRUPT_SPI) ++#define FIQ_I2SPCM (FIQ_START+INTERRUPT_I2SPCM) ++#define FIQ_SDIO (FIQ_START+INTERRUPT_SDIO) ++#define FIQ_UART (FIQ_START+INTERRUPT_UART) ++#define FIQ_SLIMBUS (FIQ_START+INTERRUPT_SLIMBUS) ++#define FIQ_VEC (FIQ_START+INTERRUPT_VEC) ++#define FIQ_CPG (FIQ_START+INTERRUPT_CPG) ++#define FIQ_RNG (FIQ_START+INTERRUPT_RNG) ++#define FIQ_ARASANSDIO (FIQ_START+INTERRUPT_ARASANSDIO) ++#define FIQ_AVSPMON (FIQ_START+INTERRUPT_AVSPMON) + -+#define FIQ_ARM_TIMER INT_ARM_TIMER -+#define FIQ_ARM_MAILBOX INT_ARM_MAILBOX -+#define FIQ_ARM_DOORBELL_0 INT_ARM_DOORBELL_0 -+#define FIQ_ARM_DOORBELL_1 INT_ARM_DOORBELL_1 -+#define FIQ_VPU0_HALTED INT_VPU0_HALTED -+#define FIQ_VPU1_HALTED INT_VPU1_HALTED -+#define FIQ_ILLEGAL_TYPE0 INT_ILLEGAL_TYPE0 -+#define FIQ_ILLEGAL_TYPE1 INT_ILLEGAL_TYPE1 -+#define FIQ_PENDING1 INT_PENDING1 -+#define FIQ_PENDING2 INT_PENDING2 ++#define FIQ_ARM_TIMER (FIQ_START+INTERRUPT_ARM_TIMER) ++#define FIQ_ARM_MAILBOX (FIQ_START+INTERRUPT_ARM_MAILBOX) ++#define FIQ_ARM_DOORBELL_0 (FIQ_START+INTERRUPT_ARM_DOORBELL_0) ++#define FIQ_ARM_DOORBELL_1 (FIQ_START+INTERRUPT_ARM_DOORBELL_1) ++#define FIQ_VPU0_HALTED (FIQ_START+INTERRUPT_VPU0_HALTED) ++#define FIQ_VPU1_HALTED (FIQ_START+INTERRUPT_VPU1_HALTED) ++#define FIQ_ILLEGAL_TYPE0 (FIQ_START+INTERRUPT_ILLEGAL_TYPE0) ++#define FIQ_ILLEGAL_TYPE1 (FIQ_START+INTERRUPT_ILLEGAL_TYPE1) ++#define FIQ_PENDING1 (FIQ_START+INTERRUPT_PENDING1) ++#define FIQ_PENDING2 (FIQ_START+INTERRUPT_PENDING2) ++ ++#define GPIO_IRQ_START (HARD_IRQS + FIQ_IRQS) + +#define HARD_IRQS (64 + 21) -+#define GPIO_IRQ_START HARD_IRQS ++#define FIQ_IRQS (64 + 21) ++#define GPIO_IRQS (32*5) + -+#define GPIO_IRQS 32*5 -+ -+#define NR_IRQS HARD_IRQS+GPIO_IRQS ++#define NR_IRQS HARD_IRQS+FIQ_IRQS+GPIO_IRQS + + +#endif /* _BCM2708_IRQS_H_ */ -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/memory.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/memory.h ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/memory.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/memory.h 2012-07-15 20:28:26.132087259 +0200 +diff --git a/arch/arm/mach-bcm2708/include/mach/memory.h b/arch/arm/mach-bcm2708/include/mach/memory.h +new file mode 100644 +index 0000000..5d47513 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/memory.h @@ -0,0 +1,64 @@ +/* + * arch/arm/mach-bcm2708/include/mach/memory.h @@ -4823,10 +5479,12 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/memory.h linux-rpi-bo +#define CONSISTENT_DMA_SIZE 0x00200000 + +#endif -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/platform.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/platform.h ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/platform.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/platform.h 2012-07-15 20:28:26.132087259 +0200 -@@ -0,0 +1,224 @@ +diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h +new file mode 100644 +index 0000000..9c5d334 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/platform.h +@@ -0,0 +1,225 @@ +/* + * arch/arm/mach-bcm2708/include/mach/platform.h + * @@ -4885,7 +5543,9 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/platform.h linux-rpi- + */ + +#define BCM2708_PERI_BASE 0x20000000 ++#define IC0_BASE (BCM2708_PERI_BASE + 0x2000) +#define ST_BASE (BCM2708_PERI_BASE + 0x3000) /* System Timer */ ++#define MPHI_BASE (BCM2708_PERI_BASE + 0x6000) /* Message -based Parallel Host Interface */ +#define DMA_BASE (BCM2708_PERI_BASE + 0x7000) /* DMA controller */ +#define ARM_BASE (BCM2708_PERI_BASE + 0xB000) /* BCM2708 ARM control block */ +#define PM_BASE (BCM2708_PERI_BASE + 0x100000) /* Power Management, Reset controller and Watchdog registers */ @@ -5032,10 +5692,7 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/platform.h linux-rpi- +#define PM_RSTC_WRCFG_CLR 0xffffffcf +#define PM_RSTC_WRCFG_SET 0x00000030 +#define PM_RSTC_WRCFG_FULL_RESET 0x00000020 -+#define PM_RSTC_RESET 0x00000102 -+ -+/* AMBA UART clock */ -+#define UART0_CLOCK 3000000 ++#define PM_RSTC_RESET 0x00000102 + +#define PM_RSTS_HADPOR_SET 0x00001000 +#define PM_RSTS_HADSRH_SET 0x00000400 @@ -5048,12 +5705,16 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/platform.h linux-rpi- +#define PM_RSTS_HADDRF_SET 0x00000002 +#define PM_RSTS_HADDRQ_SET 0x00000001 + ++#define UART0_CLOCK 3000000 ++ +#endif + +/* END */ -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/power.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/power.h ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/power.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/power.h 2012-07-15 20:28:26.132087259 +0200 +diff --git a/arch/arm/mach-bcm2708/include/mach/power.h b/arch/arm/mach-bcm2708/include/mach/power.h +new file mode 100644 +index 0000000..52b3b02 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/power.h @@ -0,0 +1,26 @@ +/* + * linux/arch/arm/mach-bcm2708/power.h @@ -5081,9 +5742,11 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/power.h linux-rpi-boo +extern int bcm_power_close(BCM_POWER_HANDLE_T handle); + +#endif -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/system.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/system.h ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/system.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/system.h 2012-07-15 20:28:26.132087259 +0200 +diff --git a/arch/arm/mach-bcm2708/include/mach/system.h b/arch/arm/mach-bcm2708/include/mach/system.h +new file mode 100644 +index 0000000..bc9d458 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/system.h @@ -0,0 +1,53 @@ +/* + * arch/arm/mach-bcm2708/include/mach/system.h @@ -5138,9 +5801,11 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/system.h linux-rpi-bo +} + +#endif -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/timex.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/timex.h ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/timex.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/timex.h 2012-07-15 20:28:26.132087259 +0200 +diff --git a/arch/arm/mach-bcm2708/include/mach/timex.h b/arch/arm/mach-bcm2708/include/mach/timex.h +new file mode 100644 +index 0000000..64a660c +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/timex.h @@ -0,0 +1,23 @@ +/* + * arch/arm/mach-bcm2708/include/mach/timex.h @@ -5165,10 +5830,12 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/timex.h linux-rpi-boo + */ + +#define CLOCK_TICK_RATE (1000000) -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/uncompress.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/uncompress.h ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/uncompress.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/uncompress.h 2012-07-15 20:28:26.131087240 +0200 -@@ -0,0 +1,84 @@ +diff --git a/arch/arm/mach-bcm2708/include/mach/uncompress.h b/arch/arm/mach-bcm2708/include/mach/uncompress.h +new file mode 100644 +index 0000000..5c43412 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/uncompress.h +@@ -0,0 +1,85 @@ +/* + * arch/arm/mach-bcn2708/include/mach/uncompress.h + * @@ -5253,55 +5920,12 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/uncompress.h linux-rp + * nothing to do + */ +#define arch_decomp_wdog() -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/vcio.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/vcio.h ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/vcio.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/vcio.h 2012-07-15 20:28:26.131087240 +0200 -@@ -0,0 +1,42 @@ -+/* -+ * arch/arm/mach-bcm2708/include/mach/vcio.h -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+#ifndef _MACH_BCM2708_VCIO_H -+#define _MACH_BCM2708_VCIO_H + -+/* Routines to handle I/O via the VideoCore "ARM control" registers -+ * (semaphores, doorbells, mailboxes) -+ */ -+ -+#define BCM_VCIO_DRIVER_NAME "bcm2708_vcio" -+ -+/* Constants shared with the ARM identifying separate mailbox channels */ -+#define MBOX_CHAN_POWER 0 /* for use by the power management interface */ -+#define MBOX_CHAN_FB 1 /* for use by the frame buffer */ -+#define MBOX_CHAN_VUART 2 /* for use by the virtual UART */ -+#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */ -+#define MBOX_CHAN_LEDS 4 /* for use by the leds interface */ -+#define MBOX_CHAN_BUTTONS 5 /* for use by the buttons interface */ -+#define MBOX_CHAN_TOUCH 6 /* for use by the touchscreen interface */ -+#define MBOX_CHAN_COUNT 7 -+ -+extern int /*rc*/ bcm_mailbox_read(unsigned chan, uint32_t *data28); -+extern int /*rc*/ bcm_mailbox_write(unsigned chan, uint32_t data28); -+ -+#endif -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/vc_mem.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/vc_mem.h ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/vc_mem.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/vc_mem.h 2012-07-15 20:28:26.131087240 +0200 +diff --git a/arch/arm/mach-bcm2708/include/mach/vc_mem.h b/arch/arm/mach-bcm2708/include/mach/vc_mem.h +new file mode 100644 +index 0000000..9d41c3a +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/vc_mem.h @@ -0,0 +1,35 @@ +/***************************************************************************** +* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. @@ -5338,9 +5962,60 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/vc_mem.h linux-rpi-bo + +#endif /* VC_MEM_H */ + -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/vmalloc.h linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/vmalloc.h ---- linux-3.2.23/arch/arm/mach-bcm2708/include/mach/vmalloc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/include/mach/vmalloc.h 2012-07-15 20:28:26.131087240 +0200 +diff --git a/arch/arm/mach-bcm2708/include/mach/vcio.h b/arch/arm/mach-bcm2708/include/mach/vcio.h +new file mode 100644 +index 0000000..ace4ea4 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/vcio.h +@@ -0,0 +1,43 @@ ++/* ++ * arch/arm/mach-bcm2708/include/mach/vcio.h ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifndef _MACH_BCM2708_VCIO_H ++#define _MACH_BCM2708_VCIO_H ++ ++/* Routines to handle I/O via the VideoCore "ARM control" registers ++ * (semaphores, doorbells, mailboxes) ++ */ ++ ++#define BCM_VCIO_DRIVER_NAME "bcm2708_vcio" ++ ++/* Constants shared with the ARM identifying separate mailbox channels */ ++#define MBOX_CHAN_POWER 0 /* for use by the power management interface */ ++#define MBOX_CHAN_FB 1 /* for use by the frame buffer */ ++#define MBOX_CHAN_VUART 2 /* for use by the virtual UART */ ++#define MBOX_CHAN_VCHIQ 3 /* for use by the VCHIQ interface */ ++#define MBOX_CHAN_LEDS 4 /* for use by the leds interface */ ++#define MBOX_CHAN_BUTTONS 5 /* for use by the buttons interface */ ++#define MBOX_CHAN_TOUCH 6 /* for use by the touchscreen interface */ ++#define MBOX_CHAN_PROPERTY 8 /* for use by the property channel */ ++#define MBOX_CHAN_COUNT 9 ++ ++extern int /*rc*/ bcm_mailbox_read(unsigned chan, uint32_t *data28); ++extern int /*rc*/ bcm_mailbox_write(unsigned chan, uint32_t data28); ++ ++#endif +diff --git a/arch/arm/mach-bcm2708/include/mach/vmalloc.h b/arch/arm/mach-bcm2708/include/mach/vmalloc.h +new file mode 100644 +index 0000000..502c617 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/include/mach/vmalloc.h @@ -0,0 +1,20 @@ +/* + * arch/arm/mach-bcm2708/include/mach/vmalloc.h @@ -5361,65 +6036,12 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/include/mach/vmalloc.h linux-rpi-b + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ -+#define VMALLOC_END (0xd8000000) -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/Kconfig linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/Kconfig ---- linux-3.2.23/arch/arm/mach-bcm2708/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/Kconfig 2012-07-15 20:28:26.130087221 +0200 -@@ -0,0 +1,32 @@ -+menu "Broadcom BCM2708 Implementations" -+ depends on ARCH_BCM2708 -+ -+config MACH_BCM2708 -+ bool "Broadcom BCM2708 Development Platform" -+ select CPU_V6 -+ help -+ Include support for the Broadcom(R) BCM2708 platform. -+ -+config BCM2708_GPIO -+ bool "BCM2708 gpio support" -+ depends on MACH_BCM2708 -+ select ARCH_REQUIRE_GPIOLIB -+ default y -+ help -+ Include support for the Broadcom(R) BCM2708 gpio. -+ -+config BCM2708_VCMEM -+ bool "Videocore Memory" -+ depends on MACH_BCM2708 -+ default y -+ help -+ Helper for videocore memory access and total size allocation. -+ -+config BCM2708_NOL2CACHE -+ bool "Videocore L2 cache disable" -+ depends on MACH_BCM2708 -+ default n -+ help -+ Do not allow ARM to use GPU's L2 cache. Requires disable_l2cache in config.txt. -+ -+endmenu -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/Makefile linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/Makefile ---- linux-3.2.23/arch/arm/mach-bcm2708/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/Makefile 2012-07-15 20:28:26.130087221 +0200 -@@ -0,0 +1,8 @@ -+# -+# Makefile for the linux kernel. -+# -+ -+obj-$(CONFIG_MACH_BCM2708) += clock.o bcm2708.o armctrl.o vcio.o power.o dma.o -+obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o -+obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o -+ -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/Makefile.boot linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/Makefile.boot ---- linux-3.2.23/arch/arm/mach-bcm2708/Makefile.boot 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/Makefile.boot 2012-07-15 20:28:26.130087221 +0200 -@@ -0,0 +1,3 @@ -+ zreladdr-y := 0x00008000 -+params_phys-y := 0x00000100 -+initrd_phys-y := 0x00800000 -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/power.c linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/power.c ---- linux-3.2.23/arch/arm/mach-bcm2708/power.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/power.c 2012-07-15 20:28:26.133087278 +0200 ++#define VMALLOC_END (0xe8000000) +diff --git a/arch/arm/mach-bcm2708/power.c b/arch/arm/mach-bcm2708/power.c +new file mode 100644 +index 0000000..256bf1a +--- /dev/null ++++ b/arch/arm/mach-bcm2708/power.c @@ -0,0 +1,194 @@ +/* + * linux/arch/arm/mach-bcm2708/power.c @@ -5615,318 +6237,12 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/power.c linux-rpi-bootc-3.2.23/arc +MODULE_AUTHOR("Phil Elwell"); +MODULE_DESCRIPTION("Interface to BCM2708 power management"); +MODULE_LICENSE("GPL"); -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/vcio.c linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/vcio.c ---- linux-3.2.23/arch/arm/mach-bcm2708/vcio.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/vcio.c 2012-07-15 20:28:26.130087221 +0200 -@@ -0,0 +1,304 @@ -+/* -+ * linux/arch/arm/mach-bcm2708/vcio.c -+ * -+ * Copyright (C) 2010 Broadcom -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This device provides a shared mechanism for writing to the mailboxes, -+ * semaphores, doorbells etc. that are shared between the ARM and the -+ * VideoCore processor -+ */ -+ -+#if defined(CONFIG_SERIAL_BCM_MBOX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -+#define SUPPORT_SYSRQ -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include -+#include -+ -+#define DRIVER_NAME BCM_VCIO_DRIVER_NAME -+ -+/* ---------------------------------------------------------------------- -+ * Mailbox -+ * -------------------------------------------------------------------- */ -+ -+/* offsets from a mail box base address */ -+#define MAIL_WRT 0x00 /* write - and next 4 words */ -+#define MAIL_RD 0x00 /* read - and next 4 words */ -+#define MAIL_POL 0x10 /* read without popping the fifo */ -+#define MAIL_SND 0x14 /* sender ID (bottom two bits) */ -+#define MAIL_STA 0x18 /* status */ -+#define MAIL_CNF 0x1C /* configuration */ -+ -+#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) -+#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) -+#define MBOX_CHAN(msg) ((msg) & 0xf) -+#define MBOX_DATA28(msg) ((msg) & ~0xf) -+#define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) -+ -+#define MBOX_MAGIC 0xd0d0c0de -+ -+struct vc_mailbox { -+ struct device *dev; /* parent device */ -+ void __iomem *status; -+ void __iomem *config; -+ void __iomem *read; -+ void __iomem *write; -+ uint32_t msg[MBOX_CHAN_COUNT]; -+ struct semaphore sema[MBOX_CHAN_COUNT]; -+ uint32_t magic; -+}; -+ -+static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, -+ uint32_t addr_mbox) -+{ -+ int i; -+ -+ mbox_out->dev = dev; -+ mbox_out->status = __io_address(addr_mbox + MAIL_STA); -+ mbox_out->config = __io_address(addr_mbox + MAIL_CNF); -+ mbox_out->read = __io_address(addr_mbox + MAIL_RD); -+ /* Write to the other mailbox */ -+ mbox_out->write = -+ __io_address((addr_mbox ^ ARM_0_MAIL0_WRT ^ ARM_0_MAIL1_WRT) + -+ MAIL_WRT); -+ -+ for (i = 0; i < MBOX_CHAN_COUNT; i++) { -+ mbox_out->msg[i] = 0; -+ sema_init(&mbox_out->sema[i], 0); -+ } -+ -+ /* Enable the interrupt on data reception */ -+ writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->config); -+ -+ mbox_out->magic = MBOX_MAGIC; -+} -+ -+static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) -+{ -+ int rc; -+ -+ if (mbox->magic != MBOX_MAGIC) -+ rc = -EINVAL; -+ else { -+ /* wait for the mailbox FIFO to have some space in it */ -+ while (0 != (readl(mbox->status) & ARM_MS_FULL)) -+ cpu_relax(); -+ -+ writel(MBOX_MSG(chan, data28), mbox->write); -+ rc = 0; -+ } -+ return rc; -+} -+ -+static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) -+{ -+ int rc; -+ -+ if (mbox->magic != MBOX_MAGIC) -+ rc = -EINVAL; -+ else { -+ down(&mbox->sema[chan]); -+ *data28 = MBOX_DATA28(mbox->msg[chan]); -+ mbox->msg[chan] = 0; -+ rc = 0; -+ } -+ return rc; -+} -+ -+static irqreturn_t mbox_irq(int irq, void *dev_id) -+{ -+ /* wait for the mailbox FIFO to have some data in it */ -+ struct vc_mailbox *mbox = (struct vc_mailbox *) dev_id; -+ int status = readl(mbox->status); -+ int ret = IRQ_NONE; -+ -+ while (!(status & ARM_MS_EMPTY)) { -+ uint32_t msg = readl(mbox->read); -+ int chan = MBOX_CHAN(msg); -+ if (chan < MBOX_CHAN_COUNT) { -+ if (mbox->msg[chan]) { -+ /* Overflow */ -+ printk(KERN_ERR DRIVER_NAME -+ ": mbox chan %d overflow - drop %08x\n", -+ chan, msg); -+ } else { -+ mbox->msg[chan] = (msg | 0xf); -+ up(&mbox->sema[chan]); -+ } -+ } else { -+ printk(KERN_ERR DRIVER_NAME -+ ": invalid channel selector (msg %08x)\n", msg); -+ } -+ ret = IRQ_HANDLED; -+ status = readl(mbox->status); -+ } -+ return ret; -+} -+ -+static struct irqaction mbox_irqaction = { -+ .name = "ARM Mailbox IRQ", -+ .flags = IRQF_DISABLED | IRQF_IRQPOLL, -+ .handler = mbox_irq, -+}; -+ -+/* ---------------------------------------------------------------------- -+ * Mailbox Methods -+ * -------------------------------------------------------------------- */ -+ -+static struct device *mbox_dev; /* we assume there's only one! */ -+ -+static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) -+{ -+ int rc; -+ -+ struct vc_mailbox *mailbox = dev_get_drvdata(dev); -+ device_lock(dev); -+ rc = mbox_write(mailbox, chan, data28); -+ device_unlock(dev); -+ -+ return rc; -+} -+ -+static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) -+{ -+ int rc; -+ -+ struct vc_mailbox *mailbox = dev_get_drvdata(dev); -+ device_lock(dev); -+ rc = mbox_read(mailbox, chan, data28); -+ device_unlock(dev); -+ -+ return rc; -+} -+ -+extern int bcm_mailbox_write(unsigned chan, uint32_t data28) -+{ -+ if (mbox_dev) -+ return dev_mbox_write(mbox_dev, chan, data28); -+ else -+ return -ENODEV; -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_write); -+ -+extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) -+{ -+ if (mbox_dev) -+ return dev_mbox_read(mbox_dev, chan, data28); -+ else -+ return -ENODEV; -+} -+EXPORT_SYMBOL_GPL(bcm_mailbox_read); -+ -+static void dev_mbox_register(const char *dev_name, struct device *dev) -+{ -+ mbox_dev = dev; -+} -+ -+/* ---------------------------------------------------------------------- -+ * Platform Device for Mailbox -+ * -------------------------------------------------------------------- */ -+ -+static int bcm_vcio_probe(struct platform_device *pdev) -+{ -+ int ret = 0; -+ struct vc_mailbox *mailbox; -+ -+ mailbox = kzalloc(sizeof(*mailbox), GFP_KERNEL); -+ if (NULL == mailbox) { -+ printk(KERN_ERR DRIVER_NAME ": failed to allocate " -+ "mailbox memory\n"); -+ ret = -ENOMEM; -+ } else { -+ struct resource *res; -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ if (res == NULL) { -+ printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " -+ "resource\n"); -+ ret = -ENODEV; -+ kfree(mailbox); -+ } else { -+ /* should be based on the registers from res really */ -+ mbox_init(mailbox, &pdev->dev, ARM_0_MAIL0_RD); -+ -+ platform_set_drvdata(pdev, mailbox); -+ dev_mbox_register(DRIVER_NAME, &pdev->dev); -+ -+ mbox_irqaction.dev_id = mailbox; -+ setup_irq(IRQ_ARM_MAILBOX, &mbox_irqaction); -+ printk(KERN_INFO DRIVER_NAME ": mailbox at %p\n", -+ __io_address(ARM_0_MAIL0_RD)); -+ } -+ } -+ return ret; -+} -+ -+static int bcm_vcio_remove(struct platform_device *pdev) -+{ -+ struct vc_mailbox *mailbox = platform_get_drvdata(pdev); -+ -+ platform_set_drvdata(pdev, NULL); -+ kfree(mailbox); -+ -+ return 0; -+} -+ -+static struct platform_driver bcm_mbox_driver = { -+ .probe = bcm_vcio_probe, -+ .remove = bcm_vcio_remove, -+ -+ .driver = { -+ .name = DRIVER_NAME, -+ .owner = THIS_MODULE, -+ }, -+}; -+ -+static int __init bcm_mbox_init(void) -+{ -+ int ret; -+ -+ printk(KERN_INFO "mailbox: Broadcom VideoCore Mailbox driver\n"); -+ -+ ret = platform_driver_register(&bcm_mbox_driver); -+ if (ret != 0) { -+ printk(KERN_ERR DRIVER_NAME ": failed to register " -+ "on platform\n"); -+ } -+ -+ return ret; -+} -+ -+static void __exit bcm_mbox_exit(void) -+{ -+ platform_driver_unregister(&bcm_mbox_driver); -+} -+ -+arch_initcall(bcm_mbox_init); /* Initialize early */ -+module_exit(bcm_mbox_exit); -+ -+MODULE_AUTHOR("Gray Girling"); -+MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); -+MODULE_LICENSE("GPL"); -+MODULE_ALIAS("platform:bcm-mbox"); -diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/vc_mem.c linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/vc_mem.c ---- linux-3.2.23/arch/arm/mach-bcm2708/vc_mem.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/arch/arm/mach-bcm2708/vc_mem.c 2012-07-15 20:28:26.133087278 +0200 -@@ -0,0 +1,466 @@ +diff --git a/arch/arm/mach-bcm2708/vc_mem.c b/arch/arm/mach-bcm2708/vc_mem.c +new file mode 100644 +index 0000000..775c213 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/vc_mem.c +@@ -0,0 +1,510 @@ +/***************************************************************************** +* Copyright 2010 - 2011 Broadcom Corporation. All rights reserved. +* @@ -5950,6 +6266,7 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/vc_mem.c linux-rpi-bootc-3.2.23/ar +#include +#include +#include ++#include + +#ifdef CONFIG_ARCH_KONA +#include @@ -5959,12 +6276,12 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/vc_mem.c linux-rpi-bootc-3.2.23/ar +#endif + +#include "mach/vc_mem.h" -+//#include "interface/vchiq_arm/vchiq_connected.h" ++#include + +#define DRIVER_NAME "vc-mem" + +// Uncomment to enable debug logging -+//#define ENABLE_DBG ++#define ENABLE_DBG + +#if defined(ENABLE_DBG) +#define LOG_DBG( fmt, ... ) printk( KERN_INFO fmt "\n", ##__VA_ARGS__ ) @@ -5996,23 +6313,8 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/vc_mem.c linux-rpi-bootc-3.2.23/ar + * bootloader (and/or kernel). When that happens, the values of these variables + * would be calculated and assigned in the init function. + */ -+#ifdef CONFIG_ARCH_KONA -+ -+#include -+unsigned long mm_vc_mem_phys_addr = VC_EMI; -+ -+#elif CONFIG_ARCH_BCM2708 -+ +// in the 2835 VC in mapped above ARM, but ARM has full access to VC space +unsigned long mm_vc_mem_phys_addr = 0x00000000; -+ -+#else -+ -+#include -+unsigned long mm_vc_mem_phys_addr = MM_ADDR_IO_VC_EMI; -+ -+#endif -+ +unsigned int mm_vc_mem_size = 0; +unsigned int mm_vc_mem_base = 0; + @@ -6054,6 +6356,64 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/vc_mem.c linux-rpi-bootc-3.2.23/ar + return 0; +} + ++ ++/* tag part of the message */ ++struct vc_msg_tag { ++ uint32_t tag_id; /* the message id */ ++ uint32_t buffer_size; /* size of the buffer (which in this case is always 8 bytes) */ ++ uint32_t data_size; /* amount of data being sent or received */ ++ uint32_t base; /* the address of memory base */ ++ uint32_t size; /* the size of memory in bytes */ ++}; ++ ++struct vc_set_msg { ++ uint32_t msg_size; /* simply, sizeof(struct vc_msg) */ ++ uint32_t request_code; /* holds various information like the success and number of bytes returned (refer to mailboxes wiki) */ ++ struct vc_msg_tag tag[2]; /* the array of tag structures above to make */ ++ uint32_t end_tag; /* an end identifier, should be set to NULL */ ++}; ++ ++#define VCMSG_GET_ARM_MEMORY 0x00010005 ++#define VCMSG_GET_VC_MEMORY 0x00010006 ++ ++static void vc_mem_update(void) ++{ ++ uint32_t success; ++ dma_addr_t vc_mem; /* the memory address accessed from videocore */ ++ struct vc_set_msg *get_mem; /* the memory address accessed from driver */ ++ ++ /* allocate some memory for the messages to use throughout the lifetime of the driver, use the larger of the two message structures */ ++ get_mem = (struct vc_set_msg *)dma_alloc_coherent(NULL, PAGE_ALIGN(sizeof(struct vc_set_msg)), &vc_mem, GFP_ATOMIC); ++ /* clear any garbage */ ++ memset(get_mem, 0, sizeof(struct vc_set_msg)); ++ /* create the message */ ++ get_mem->msg_size = sizeof(struct vc_set_msg); ++ get_mem->tag[0].tag_id = VCMSG_GET_VC_MEMORY; ++ get_mem->tag[0].buffer_size = 8; ++ get_mem->tag[0].data_size = 0; ++ get_mem->tag[1].tag_id = VCMSG_GET_ARM_MEMORY; ++ get_mem->tag[1].buffer_size = 8; ++ get_mem->tag[1].data_size = 0; ++ ++ /* send the message */ ++ wmb(); ++ bcm_mailbox_write(MBOX_CHAN_PROPERTY,(uint32_t)vc_mem); ++ bcm_mailbox_read(MBOX_CHAN_PROPERTY, &success); ++ rmb(); ++ ++ LOG_DBG("%s: resp %x, vcbase=%x vcsize=%x armbase=%x armsize=%x", __func__, get_mem->request_code, ++ get_mem->tag[0].base, get_mem->tag[0].size, get_mem->tag[1].base, get_mem->tag[1].size); ++ ++ /* check we're all good */ ++ if (get_mem->request_code & 0x80000000) { ++ mm_vc_mem_base = get_mem->tag[0].base; ++ mm_vc_mem_size = get_mem->tag[0].size+get_mem->tag[1].size; ++ mm_vc_mem_phys_addr = get_mem->tag[1].base; ++ } ++ dma_free_coherent(NULL, PAGE_ALIGN(sizeof(struct vc_set_msg)), (void *)get_mem, vc_mem); ++} ++ ++ +/**************************************************************************** +* +* vc_mem_get_size @@ -6063,7 +6423,7 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/vc_mem.c linux-rpi-bootc-3.2.23/ar +static void +vc_mem_get_size(void) +{ -+ mm_vc_mem_size = 256 * 1024 * 1024; // Static for now ++ vc_mem_update(); +} + +/**************************************************************************** @@ -6075,7 +6435,7 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/vc_mem.c linux-rpi-bootc-3.2.23/ar +static void +vc_mem_get_base(void) +{ -+ mm_vc_mem_base = 128 * 1024 * 1024; // Static for now ++ vc_mem_update(); +} + +/**************************************************************************** @@ -6393,21 +6753,334 @@ diff -Naur linux-3.2.23/arch/arm/mach-bcm2708/vc_mem.c linux-rpi-bootc-3.2.23/ar +module_exit(vc_mem_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Broadcom Corporation"); -diff -Naur linux-3.2.23/arch/arm/Makefile linux-rpi-bootc-3.2.23/arch/arm/Makefile ---- linux-3.2.23/arch/arm/Makefile 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/arch/arm/Makefile 2012-07-15 20:28:25.861082159 +0200 -@@ -198,6 +198,7 @@ - machine-$(CONFIG_MACH_SPEAR320) := spear3xx - machine-$(CONFIG_MACH_SPEAR600) := spear6xx - machine-$(CONFIG_ARCH_ZYNQ) := zynq -+machine-$(CONFIG_ARCH_BCM2708) := bcm2708 +diff --git a/arch/arm/mach-bcm2708/vcio.c b/arch/arm/mach-bcm2708/vcio.c +new file mode 100644 +index 0000000..3874051 +--- /dev/null ++++ b/arch/arm/mach-bcm2708/vcio.c +@@ -0,0 +1,304 @@ ++/* ++ * linux/arch/arm/mach-bcm2708/vcio.c ++ * ++ * Copyright (C) 2010 Broadcom ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This device provides a shared mechanism for writing to the mailboxes, ++ * semaphores, doorbells etc. that are shared between the ARM and the ++ * VideoCore processor ++ */ ++ ++#if defined(CONFIG_SERIAL_BCM_MBOX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) ++#define SUPPORT_SYSRQ ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#include ++ ++#define DRIVER_NAME BCM_VCIO_DRIVER_NAME ++ ++/* ---------------------------------------------------------------------- ++ * Mailbox ++ * -------------------------------------------------------------------- */ ++ ++/* offsets from a mail box base address */ ++#define MAIL_WRT 0x00 /* write - and next 4 words */ ++#define MAIL_RD 0x00 /* read - and next 4 words */ ++#define MAIL_POL 0x10 /* read without popping the fifo */ ++#define MAIL_SND 0x14 /* sender ID (bottom two bits) */ ++#define MAIL_STA 0x18 /* status */ ++#define MAIL_CNF 0x1C /* configuration */ ++ ++#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) ++#define MBOX_MSG_LSB(chan, data28) (((data28) << 4) | ((chan) & 0xf)) ++#define MBOX_CHAN(msg) ((msg) & 0xf) ++#define MBOX_DATA28(msg) ((msg) & ~0xf) ++#define MBOX_DATA28_LSB(msg) (((uint32_t)msg) >> 4) ++ ++#define MBOX_MAGIC 0xd0d0c0de ++ ++struct vc_mailbox { ++ struct device *dev; /* parent device */ ++ void __iomem *status; ++ void __iomem *config; ++ void __iomem *read; ++ void __iomem *write; ++ uint32_t msg[MBOX_CHAN_COUNT]; ++ struct semaphore sema[MBOX_CHAN_COUNT]; ++ uint32_t magic; ++}; ++ ++static void mbox_init(struct vc_mailbox *mbox_out, struct device *dev, ++ uint32_t addr_mbox) ++{ ++ int i; ++ ++ mbox_out->dev = dev; ++ mbox_out->status = __io_address(addr_mbox + MAIL_STA); ++ mbox_out->config = __io_address(addr_mbox + MAIL_CNF); ++ mbox_out->read = __io_address(addr_mbox + MAIL_RD); ++ /* Write to the other mailbox */ ++ mbox_out->write = ++ __io_address((addr_mbox ^ ARM_0_MAIL0_WRT ^ ARM_0_MAIL1_WRT) + ++ MAIL_WRT); ++ ++ for (i = 0; i < MBOX_CHAN_COUNT; i++) { ++ mbox_out->msg[i] = 0; ++ sema_init(&mbox_out->sema[i], 0); ++ } ++ ++ /* Enable the interrupt on data reception */ ++ writel(ARM_MC_IHAVEDATAIRQEN, mbox_out->config); ++ ++ mbox_out->magic = MBOX_MAGIC; ++} ++ ++static int mbox_write(struct vc_mailbox *mbox, unsigned chan, uint32_t data28) ++{ ++ int rc; ++ ++ if (mbox->magic != MBOX_MAGIC) ++ rc = -EINVAL; ++ else { ++ /* wait for the mailbox FIFO to have some space in it */ ++ while (0 != (readl(mbox->status) & ARM_MS_FULL)) ++ cpu_relax(); ++ ++ writel(MBOX_MSG(chan, data28), mbox->write); ++ rc = 0; ++ } ++ return rc; ++} ++ ++static int mbox_read(struct vc_mailbox *mbox, unsigned chan, uint32_t *data28) ++{ ++ int rc; ++ ++ if (mbox->magic != MBOX_MAGIC) ++ rc = -EINVAL; ++ else { ++ down(&mbox->sema[chan]); ++ *data28 = MBOX_DATA28(mbox->msg[chan]); ++ mbox->msg[chan] = 0; ++ rc = 0; ++ } ++ return rc; ++} ++ ++static irqreturn_t mbox_irq(int irq, void *dev_id) ++{ ++ /* wait for the mailbox FIFO to have some data in it */ ++ struct vc_mailbox *mbox = (struct vc_mailbox *) dev_id; ++ int status = readl(mbox->status); ++ int ret = IRQ_NONE; ++ ++ while (!(status & ARM_MS_EMPTY)) { ++ uint32_t msg = readl(mbox->read); ++ int chan = MBOX_CHAN(msg); ++ if (chan < MBOX_CHAN_COUNT) { ++ if (mbox->msg[chan]) { ++ /* Overflow */ ++ printk(KERN_ERR DRIVER_NAME ++ ": mbox chan %d overflow - drop %08x\n", ++ chan, msg); ++ } else { ++ mbox->msg[chan] = (msg | 0xf); ++ up(&mbox->sema[chan]); ++ } ++ } else { ++ printk(KERN_ERR DRIVER_NAME ++ ": invalid channel selector (msg %08x)\n", msg); ++ } ++ ret = IRQ_HANDLED; ++ status = readl(mbox->status); ++ } ++ return ret; ++} ++ ++static struct irqaction mbox_irqaction = { ++ .name = "ARM Mailbox IRQ", ++ .flags = IRQF_DISABLED | IRQF_IRQPOLL, ++ .handler = mbox_irq, ++}; ++ ++/* ---------------------------------------------------------------------- ++ * Mailbox Methods ++ * -------------------------------------------------------------------- */ ++ ++static struct device *mbox_dev; /* we assume there's only one! */ ++ ++static int dev_mbox_write(struct device *dev, unsigned chan, uint32_t data28) ++{ ++ int rc; ++ ++ struct vc_mailbox *mailbox = dev_get_drvdata(dev); ++ device_lock(dev); ++ rc = mbox_write(mailbox, chan, data28); ++ device_unlock(dev); ++ ++ return rc; ++} ++ ++static int dev_mbox_read(struct device *dev, unsigned chan, uint32_t *data28) ++{ ++ int rc; ++ ++ struct vc_mailbox *mailbox = dev_get_drvdata(dev); ++ device_lock(dev); ++ rc = mbox_read(mailbox, chan, data28); ++ device_unlock(dev); ++ ++ return rc; ++} ++ ++extern int bcm_mailbox_write(unsigned chan, uint32_t data28) ++{ ++ if (mbox_dev) ++ return dev_mbox_write(mbox_dev, chan, data28); ++ else ++ return -ENODEV; ++} ++EXPORT_SYMBOL_GPL(bcm_mailbox_write); ++ ++extern int bcm_mailbox_read(unsigned chan, uint32_t *data28) ++{ ++ if (mbox_dev) ++ return dev_mbox_read(mbox_dev, chan, data28); ++ else ++ return -ENODEV; ++} ++EXPORT_SYMBOL_GPL(bcm_mailbox_read); ++ ++static void dev_mbox_register(const char *dev_name, struct device *dev) ++{ ++ mbox_dev = dev; ++} ++ ++/* ---------------------------------------------------------------------- ++ * Platform Device for Mailbox ++ * -------------------------------------------------------------------- */ ++ ++static int bcm_vcio_probe(struct platform_device *pdev) ++{ ++ int ret = 0; ++ struct vc_mailbox *mailbox; ++ ++ mailbox = kzalloc(sizeof(*mailbox), GFP_KERNEL); ++ if (NULL == mailbox) { ++ printk(KERN_ERR DRIVER_NAME ": failed to allocate " ++ "mailbox memory\n"); ++ ret = -ENOMEM; ++ } else { ++ struct resource *res; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (res == NULL) { ++ printk(KERN_ERR DRIVER_NAME ": failed to obtain memory " ++ "resource\n"); ++ ret = -ENODEV; ++ kfree(mailbox); ++ } else { ++ /* should be based on the registers from res really */ ++ mbox_init(mailbox, &pdev->dev, ARM_0_MAIL0_RD); ++ ++ platform_set_drvdata(pdev, mailbox); ++ dev_mbox_register(DRIVER_NAME, &pdev->dev); ++ ++ mbox_irqaction.dev_id = mailbox; ++ setup_irq(IRQ_ARM_MAILBOX, &mbox_irqaction); ++ printk(KERN_INFO DRIVER_NAME ": mailbox at %p\n", ++ __io_address(ARM_0_MAIL0_RD)); ++ } ++ } ++ return ret; ++} ++ ++static int bcm_vcio_remove(struct platform_device *pdev) ++{ ++ struct vc_mailbox *mailbox = platform_get_drvdata(pdev); ++ ++ platform_set_drvdata(pdev, NULL); ++ kfree(mailbox); ++ ++ return 0; ++} ++ ++static struct platform_driver bcm_mbox_driver = { ++ .probe = bcm_vcio_probe, ++ .remove = bcm_vcio_remove, ++ ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init bcm_mbox_init(void) ++{ ++ int ret; ++ ++ printk(KERN_INFO "mailbox: Broadcom VideoCore Mailbox driver\n"); ++ ++ ret = platform_driver_register(&bcm_mbox_driver); ++ if (ret != 0) { ++ printk(KERN_ERR DRIVER_NAME ": failed to register " ++ "on platform\n"); ++ } ++ ++ return ret; ++} ++ ++static void __exit bcm_mbox_exit(void) ++{ ++ platform_driver_unregister(&bcm_mbox_driver); ++} ++ ++arch_initcall(bcm_mbox_init); /* Initialize early */ ++module_exit(bcm_mbox_exit); ++ ++MODULE_AUTHOR("Gray Girling"); ++MODULE_DESCRIPTION("ARM I/O to VideoCore processor"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:bcm-mbox"); +diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig +index 67f75a0..2c9ec3c 100644 +--- a/arch/arm/mm/Kconfig ++++ b/arch/arm/mm/Kconfig +@@ -390,7 +390,7 @@ config CPU_PJ4 - # Platform directory name. This list is sorted alphanumerically - # by CONFIG_* macro name. -diff -Naur linux-3.2.23/arch/arm/mm/alignment.c linux-rpi-bootc-3.2.23/arch/arm/mm/alignment.c ---- linux-3.2.23/arch/arm/mm/alignment.c 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/arch/arm/mm/alignment.c 2012-07-15 20:28:26.129087202 +0200 -@@ -855,9 +855,11 @@ + # ARMv6 + config CPU_V6 +- bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX ++ bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || MACH_BCM2708 + select CPU_32v6 + select CPU_ABRT_EV6 + select CPU_PABRT_V6 +diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c +index c335c76..118b667 100644 +--- a/arch/arm/mm/alignment.c ++++ b/arch/arm/mm/alignment.c +@@ -855,9 +855,11 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) case 0x08000000: /* ldm or stm, or thumb-2 32bit instruction */ if (thumb2_32b) handler = do_alignment_t32_to_handler(&instr, regs, &offset); @@ -6421,22 +7094,11 @@ diff -Naur linux-3.2.23/arch/arm/mm/alignment.c linux-rpi-bootc-3.2.23/arch/arm/ default: goto bad; -diff -Naur linux-3.2.23/arch/arm/mm/Kconfig linux-rpi-bootc-3.2.23/arch/arm/mm/Kconfig ---- linux-3.2.23/arch/arm/mm/Kconfig 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/arch/arm/mm/Kconfig 2012-07-15 20:28:26.120087033 +0200 -@@ -390,7 +390,7 @@ - - # ARMv6 - config CPU_V6 -- bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX -+ bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || MACH_BCM2708 - select CPU_32v6 - select CPU_ABRT_EV6 - select CPU_PABRT_V6 -diff -Naur linux-3.2.23/arch/arm/mm/proc-v6.S linux-rpi-bootc-3.2.23/arch/arm/mm/proc-v6.S ---- linux-3.2.23/arch/arm/mm/proc-v6.S 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/arch/arm/mm/proc-v6.S 2012-07-15 20:28:26.128087183 +0200 -@@ -70,10 +70,19 @@ +diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S +index d061d2f..436dc2c 100644 +--- a/arch/arm/mm/proc-v6.S ++++ b/arch/arm/mm/proc-v6.S +@@ -70,10 +70,19 @@ ENTRY(cpu_v6_reset) * * IRQs are already disabled. */ @@ -6459,10 +7121,43 @@ diff -Naur linux-3.2.23/arch/arm/mm/proc-v6.S linux-rpi-bootc-3.2.23/arch/arm/mm mov pc, lr ENTRY(cpu_v6_dcache_clean_area) -diff -Naur linux-3.2.23/drivers/i2c/busses/i2c-bcm2708.c linux-rpi-bootc-3.2.23/drivers/i2c/busses/i2c-bcm2708.c ---- linux-3.2.23/drivers/i2c/busses/i2c-bcm2708.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/i2c/busses/i2c-bcm2708.c 2012-07-15 20:29:11.415939334 +0200 -@@ -0,0 +1,379 @@ +diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig +index a3afac4..cbc62ff 100644 +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -308,6 +308,14 @@ config I2C_AU1550 + This driver can also be built as a module. If so, the module + will be called i2c-au1550. + ++config I2C_BCM2708 ++ tristate "BCM2708 BSC" ++ depends on MACH_BCM2708 ++ help ++ Enabling this option will add BSC (Broadcom Serial Controller) ++ support for the BCM2708. BSC is a Broadcom proprietary bus compatible ++ with I2C/TWI/SMBus. ++ + config I2C_BLACKFIN_TWI + tristate "Blackfin TWI I2C support" + depends on BLACKFIN +diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile +index fba6da6..4022671 100644 +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -30,6 +30,7 @@ obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o + # Embedded system I2C/SMBus host controller drivers + obj-$(CONFIG_I2C_AT91) += i2c-at91.o + obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o ++obj-$(CONFIG_I2C_BCM2708) += i2c-bcm2708.o + obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o + obj-$(CONFIG_I2C_CPM) += i2c-cpm.o + obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o +diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c +new file mode 100644 +index 0000000..70e8d29 +--- /dev/null ++++ b/drivers/i2c/busses/i2c-bcm2708.c +@@ -0,0 +1,396 @@ +/* + * Driver for Broadcom BCM2708 BSC Controllers + * @@ -6836,62 +7531,94 @@ diff -Naur linux-3.2.23/drivers/i2c/busses/i2c-bcm2708.c linux-rpi-bootc-3.2.23/ + .probe = bcm2708_i2c_probe, + .remove = __devexit_p(bcm2708_i2c_remove), +}; -+module_platform_driver(bcm2708_i2c_driver); ++ ++// module_platform_driver(bcm2708_i2c_driver); ++ ++ ++static int __init bcm2708_i2c_init(void) ++{ ++ return platform_driver_register(&bcm2708_i2c_driver); ++} ++ ++static void __exit bcm2708_i2c_exit(void) ++{ ++ platform_driver_unregister(&bcm2708_i2c_driver); ++} ++ ++module_init(bcm2708_i2c_init); ++module_exit(bcm2708_i2c_exit); ++ ++ + +MODULE_DESCRIPTION("BSC controller driver for Broadcom BCM2708"); +MODULE_AUTHOR("Chris Boot "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); -diff -Naur linux-3.2.23/drivers/i2c/busses/Kconfig linux-rpi-bootc-3.2.23/drivers/i2c/busses/Kconfig ---- linux-3.2.23/drivers/i2c/busses/Kconfig 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/i2c/busses/Kconfig 2012-07-15 20:29:12.757964595 +0200 -@@ -308,6 +308,14 @@ - This driver can also be built as a module. If so, the module - will be called i2c-au1550. - -+config I2C_BCM2708 -+ tristate "BCM2708 BSC" -+ depends on MACH_BCM2708 -+ help -+ Enabling this option will add BSC (Broadcom Serial Controller) -+ support for the BCM2708. BSC is a Broadcom proprietary bus compatible -+ with I2C/TWI/SMBus. -+ - config I2C_BLACKFIN_TWI - tristate "Blackfin TWI I2C support" - depends on BLACKFIN -diff -Naur linux-3.2.23/drivers/i2c/busses/Makefile linux-rpi-bootc-3.2.23/drivers/i2c/busses/Makefile ---- linux-3.2.23/drivers/i2c/busses/Makefile 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/i2c/busses/Makefile 2012-07-15 20:29:11.329937716 +0200 -@@ -30,6 +30,7 @@ - # Embedded system I2C/SMBus host controller drivers - obj-$(CONFIG_I2C_AT91) += i2c-at91.o - obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o -+obj-$(CONFIG_I2C_BCM2708) += i2c-bcm2708.o - obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o - obj-$(CONFIG_I2C_CPM) += i2c-cpm.o - obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o -diff -Naur linux-3.2.23/drivers/misc/Kconfig linux-rpi-bootc-3.2.23/drivers/misc/Kconfig ---- linux-3.2.23/drivers/misc/Kconfig 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/misc/Kconfig 2012-07-15 20:29:13.403976727 +0200 -@@ -508,5 +508,6 @@ +diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig +index 5664696..b4679ec 100644 +--- a/drivers/misc/Kconfig ++++ b/drivers/misc/Kconfig +@@ -508,5 +508,6 @@ source "drivers/misc/ti-st/Kconfig" source "drivers/misc/lis3lv02d/Kconfig" source "drivers/misc/carma/Kconfig" source "drivers/misc/altera-stapl/Kconfig" +source "drivers/misc/vc04_services/Kconfig" endif # MISC_DEVICES -diff -Naur linux-3.2.23/drivers/misc/Makefile linux-rpi-bootc-3.2.23/drivers/misc/Makefile ---- linux-3.2.23/drivers/misc/Makefile 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/misc/Makefile 2012-07-15 20:29:13.129971586 +0200 -@@ -48,3 +48,4 @@ +diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile +index b26495a..a06b534 100644 +--- a/drivers/misc/Makefile ++++ b/drivers/misc/Makefile +@@ -48,3 +48,4 @@ obj-y += lis3lv02d/ obj-y += carma/ obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ +obj-y += vc04_services/ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchi/connections/connection.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchi/connections/connection.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchi/connections/connection.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchi/connections/connection.h 2012-07-15 20:29:13.762983497 +0200 +diff --git a/drivers/misc/vc04_services/Kconfig b/drivers/misc/vc04_services/Kconfig +new file mode 100644 +index 0000000..d97a1e2 +--- /dev/null ++++ b/drivers/misc/vc04_services/Kconfig +@@ -0,0 +1,7 @@ ++config BCM2708_VCHIQ ++ tristate "Videocore VCHIQ" ++ depends on MACH_BCM2708 ++ default y ++ help ++ Helper for communication for VideoCore. ++ +diff --git a/drivers/misc/vc04_services/Makefile b/drivers/misc/vc04_services/Makefile +new file mode 100644 +index 0000000..ee53af7 +--- /dev/null ++++ b/drivers/misc/vc04_services/Makefile +@@ -0,0 +1,21 @@ ++obj-$(CONFIG_BCM2708_VCHIQ) += vchiq.o ++ ++vchiq-objs := \ ++ interface/vchiq_arm/vchiq_core.o \ ++ interface/vchiq_arm/vchiq_shim.o \ ++ interface/vchiq_arm/vchiq_util.o \ ++ interface/vchiq_arm/vchiq_arm.o \ ++ interface/vchiq_arm/vchiq_kern_lib.o \ ++ interface/vchiq_arm/vchiq_2835_arm.o \ ++ interface/vcos/linuxkernel/vcos_linuxkernel.o \ ++ interface/vcos/linuxkernel/vcos_thread_map.o \ ++ interface/vcos/linuxkernel/vcos_linuxkernel_cfg.o \ ++ interface/vcos/generic/vcos_generic_event_flags.o \ ++ interface/vcos/generic/vcos_logcat.o \ ++ interface/vcos/generic/vcos_mem_from_malloc.o \ ++ interface/vcos/generic/vcos_cmd.o ++ ++EXTRA_CFLAGS += -DVCOS_VERIFY_BKPTS=1 -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel ++ ++ ++ +diff --git a/drivers/misc/vc04_services/interface/vchi/connections/connection.h b/drivers/misc/vc04_services/interface/vchi/connections/connection.h +new file mode 100644 +index 0000000..2fe5742 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchi/connections/connection.h @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. @@ -7202,9 +7929,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchi/connections/co +#endif /* CONNECTION_H_ */ + +/****************************** End of file **********************************/ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h 2012-07-15 20:29:13.752983309 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h b/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h +new file mode 100644 +index 0000000..7701b15 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchi/message_drivers/message.h @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. @@ -7392,443 +8121,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchi/message_driver +#endif // _VCHI_MESSAGE_H_ + +/****************************** End of file ***********************************/ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h 2012-07-15 20:29:13.752983309 +0200 -@@ -0,0 +1,214 @@ -+/* -+ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+/*============================================================================= -+Contains the #defines for the number of servers / clients etc, these can be -+over-ridden from the platform makefile if needed -+=============================================================================*/ -+ -+#ifndef VCHI_CFG_H_ -+#define VCHI_CFG_H_ -+ -+/**************************************************************************************** -+ * Defines in this first section are part of the VCHI API and may be examined by VCHI -+ * services. -+ ***************************************************************************************/ -+ -+/* Required alignment of base addresses for bulk transfer, if unaligned transfers are not enabled */ -+/* Really determined by the message driver, and should be available from a run-time call. */ -+#ifndef VCHI_BULK_ALIGN -+# if __VCCOREVER__ >= 0x04000000 -+# define VCHI_BULK_ALIGN 32 // Allows for the need to do cache cleans -+# else -+# define VCHI_BULK_ALIGN 16 -+# endif -+#endif -+ -+/* Required length multiple for bulk transfers, if unaligned transfers are not enabled */ -+/* May be less than or greater than VCHI_BULK_ALIGN */ -+/* Really determined by the message driver, and should be available from a run-time call. */ -+#ifndef VCHI_BULK_GRANULARITY -+# if __VCCOREVER__ >= 0x04000000 -+# define VCHI_BULK_GRANULARITY 32 // Allows for the need to do cache cleans -+# else -+# define VCHI_BULK_GRANULARITY 16 -+# endif -+#endif -+ -+/* The largest possible message to be queued with vchi_msg_queue. */ -+#ifndef VCHI_MAX_MSG_SIZE -+# if defined VCHI_LOCAL_HOST_PORT -+# define VCHI_MAX_MSG_SIZE 16384 // makes file transfers fast, but should they be using bulk? -+# else -+# define VCHI_MAX_MSG_SIZE 4096 // NOTE: THIS MUST BE LARGER THAN OR EQUAL TO THE SIZE OF THE KHRONOS MERGE BUFFER!! -+# endif -+#endif -+ -+/****************************************************************************************** -+ * Defines below are system configuration options, and should not be used by VCHI services. -+ *****************************************************************************************/ -+ -+/* How many connections can we support? A localhost implementation uses 2 connections, -+ * 1 for host-app, 1 for VMCS, and these are hooked together by a loopback MPHI VCFW -+ * driver. */ -+#ifndef VCHI_MAX_NUM_CONNECTIONS -+# define VCHI_MAX_NUM_CONNECTIONS 3 -+#endif -+ -+/* How many services can we open per connection? Extending this doesn't cost processing time, just a small -+ * amount of static memory. */ -+#ifndef VCHI_MAX_SERVICES_PER_CONNECTION -+# define VCHI_MAX_SERVICES_PER_CONNECTION 36 -+#endif -+ -+/* Adjust if using a message driver that supports more logical TX channels */ -+#ifndef VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION -+# define VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION 9 // 1 MPHI + 8 CCP2 logical channels -+#endif -+ -+/* Adjust if using a message driver that supports more logical RX channels */ -+#ifndef VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION -+# define VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION 1 // 1 MPHI -+#endif -+ -+/* How many receive slots do we use. This times VCHI_MAX_MSG_SIZE gives the effective -+ * receive queue space, less message headers. */ -+#ifndef VCHI_NUM_READ_SLOTS -+# if defined(VCHI_LOCAL_HOST_PORT) -+# define VCHI_NUM_READ_SLOTS 4 -+# else -+# define VCHI_NUM_READ_SLOTS 48 -+# endif -+#endif -+ -+/* Do we utilise overrun facility for receive message slots? Can aid peer transmit -+ * performance. Only define on VideoCore end, talking to host. -+ */ -+//#define VCHI_MSG_RX_OVERRUN -+ -+/* How many transmit slots do we use. Generally don't need many, as the hardware driver -+ * underneath VCHI will usually have its own buffering. */ -+#ifndef VCHI_NUM_WRITE_SLOTS -+# define VCHI_NUM_WRITE_SLOTS 4 -+#endif -+ -+/* If a service has held or queued received messages in VCHI_XOFF_THRESHOLD or more slots, -+ * then it's taking up too much buffer space, and the peer service will be told to stop -+ * transmitting with an XOFF message. For this to be effective, the VCHI_NUM_READ_SLOTS -+ * needs to be considerably bigger than VCHI_NUM_WRITE_SLOTS, or the transmit latency -+ * is too high. */ -+#ifndef VCHI_XOFF_THRESHOLD -+# define VCHI_XOFF_THRESHOLD (VCHI_NUM_READ_SLOTS / 2) -+#endif -+ -+/* After we've sent an XOFF, the peer will be told to resume transmission once the local -+ * service has dequeued/released enough messages that it's now occupying -+ * VCHI_XON_THRESHOLD slots or fewer. */ -+#ifndef VCHI_XON_THRESHOLD -+# define VCHI_XON_THRESHOLD (VCHI_NUM_READ_SLOTS / 4) -+#endif -+ -+/* A size below which a bulk transfer omits the handshake completely and always goes -+ * via the message channel, if bulk auxiliary is being sent on that service. (The user -+ * can guarantee this by enabling unaligned transmits). -+ * Not API. */ -+#ifndef VCHI_MIN_BULK_SIZE -+# define VCHI_MIN_BULK_SIZE ( VCHI_MAX_MSG_SIZE / 2 < 4096 ? VCHI_MAX_MSG_SIZE / 2 : 4096 ) -+#endif -+ -+/* Maximum size of bulk transmission chunks, for each interface type. A trade-off between -+ * speed and latency; the smaller the chunk size the better change of messages and other -+ * bulk transmissions getting in when big bulk transfers are happening. Set to 0 to not -+ * break transmissions into chunks. -+ */ -+#ifndef VCHI_MAX_BULK_CHUNK_SIZE_MPHI -+# define VCHI_MAX_BULK_CHUNK_SIZE_MPHI (16 * 1024) -+#endif -+ -+/* NB Chunked CCP2 transmissions violate the letter of the CCP2 spec by using "JPEG8" mode -+ * with multiple-line frames. Only use if the receiver can cope. */ -+#ifndef VCHI_MAX_BULK_CHUNK_SIZE_CCP2 -+# define VCHI_MAX_BULK_CHUNK_SIZE_CCP2 0 -+#endif -+ -+/* How many TX messages can we have pending in our transmit slots. Once exhausted, -+ * vchi_msg_queue will be blocked. */ -+#ifndef VCHI_TX_MSG_QUEUE_SIZE -+# define VCHI_TX_MSG_QUEUE_SIZE 256 -+#endif -+ -+/* How many RX messages can we have parsed in the receive slots. Once exhausted, parsing -+ * will be suspended until older messages are dequeued/released. */ -+#ifndef VCHI_RX_MSG_QUEUE_SIZE -+# define VCHI_RX_MSG_QUEUE_SIZE 256 -+#endif -+ -+/* Really should be able to cope if we run out of received message descriptors, by -+ * suspending parsing as the comment above says, but we don't. This sweeps the issue -+ * under the carpet. */ -+#if VCHI_RX_MSG_QUEUE_SIZE < (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS -+# undef VCHI_RX_MSG_QUEUE_SIZE -+# define VCHI_RX_MSG_QUEUE_SIZE (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS -+#endif -+ -+/* How many bulk transmits can we have pending. Once exhausted, vchi_bulk_queue_transmit -+ * will be blocked. */ -+#ifndef VCHI_TX_BULK_QUEUE_SIZE -+# define VCHI_TX_BULK_QUEUE_SIZE 64 -+#endif -+ -+/* How many bulk receives can we have pending. Once exhausted, vchi_bulk_queue_receive -+ * will be blocked. */ -+#ifndef VCHI_RX_BULK_QUEUE_SIZE -+# define VCHI_RX_BULK_QUEUE_SIZE 64 -+#endif -+ -+/* A limit on how many outstanding bulk requests we expect the peer to give us. If -+ * the peer asks for more than this, VCHI will fail and assert. The number is determined -+ * by the peer's hardware - it's the number of outstanding requests that can be queued -+ * on all bulk channels. VC3's MPHI peripheral allows 16. */ -+#ifndef VCHI_MAX_PEER_BULK_REQUESTS -+# define VCHI_MAX_PEER_BULK_REQUESTS 32 -+#endif -+ -+/* Define VCHI_CCP2TX_MANUAL_POWER if the host tells us when to turn the CCP2 -+ * transmitter on and off. -+ */ -+/*#define VCHI_CCP2TX_MANUAL_POWER*/ -+ -+#ifndef VCHI_CCP2TX_MANUAL_POWER -+ -+/* Timeout (in milliseconds) for putting the CCP2TX interface into IDLE state. Set -+ * negative for no IDLE. -+ */ -+# ifndef VCHI_CCP2TX_IDLE_TIMEOUT -+# define VCHI_CCP2TX_IDLE_TIMEOUT 5 -+# endif -+ -+/* Timeout (in milliseconds) for putting the CCP2TX interface into OFF state. Set -+ * negative for no OFF. -+ */ -+# ifndef VCHI_CCP2TX_OFF_TIMEOUT -+# define VCHI_CCP2TX_OFF_TIMEOUT 1000 -+# endif -+ -+#endif /* VCHI_CCP2TX_MANUAL_POWER */ -+ -+#endif /* VCHI_CFG_H_ */ -+ -+/****************************** End of file **********************************/ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h 2012-07-15 20:29:13.751983290 +0200 -@@ -0,0 +1,56 @@ -+/* -+ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef VCHI_CFG_INTERNAL_H_ -+#define VCHI_CFG_INTERNAL_H_ -+ -+/**************************************************************************************** -+ * Control optimisation attempts. -+ ***************************************************************************************/ -+ -+// Don't use lots of short-term locks - use great long ones, reducing the overall locks-per-second -+#define VCHI_COARSE_LOCKING -+ -+// Avoid lock then unlock on exit from blocking queue operations (msg tx, bulk rx/tx) -+// (only relevant if VCHI_COARSE_LOCKING) -+#define VCHI_ELIDE_BLOCK_EXIT_LOCK -+ -+// Avoid lock on non-blocking peek -+// (only relevant if VCHI_COARSE_LOCKING) -+#define VCHI_AVOID_PEEK_LOCK -+ -+// Use one slot-handler thread per connection, rather than 1 thread dealing with all connections in rotation. -+#define VCHI_MULTIPLE_HANDLER_THREADS -+ -+// Put free descriptors onto the head of the free queue, rather than the tail, so that we don't thrash -+// our way through the pool of descriptors. -+#define VCHI_PUSH_FREE_DESCRIPTORS_ONTO_HEAD -+ -+// Don't issue a MSG_AVAILABLE callback for every single message. Possibly only safe if VCHI_COARSE_LOCKING. -+#define VCHI_FEWER_MSG_AVAILABLE_CALLBACKS -+ -+// Don't use message descriptors for TX messages that don't need them -+#define VCHI_MINIMISE_TX_MSG_DESCRIPTORS -+ -+// Nano-locks for multiqueue -+//#define VCHI_MQUEUE_NANOLOCKS -+ -+// Lock-free(er) dequeuing -+//#define VCHI_RX_NANOLOCKS -+ -+#endif /*VCHI_CFG_INTERNAL_H_*/ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi_common.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi_common.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi_common.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi_common.h 2012-07-15 20:29:13.751983290 +0200 -@@ -0,0 +1,152 @@ -+/* -+ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+/*============================================================================= -+Contains global defs used by submodules within vchi. -+=============================================================================*/ -+ -+#ifndef VCHI_COMMON_H_ -+#define VCHI_COMMON_H_ -+ -+ -+//flags used when sending messages (must be bitmapped) -+typedef enum -+{ -+ VCHI_FLAGS_NONE = 0x0, -+ VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE = 0x1, // waits for message to be received, or sent (NB. not the same as being seen on other side) -+ VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE = 0x2, // run a callback when message sent -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED = 0x4, // return once the transfer is in a queue ready to go -+ VCHI_FLAGS_ALLOW_PARTIAL = 0x8, -+ VCHI_FLAGS_BLOCK_UNTIL_DATA_READ = 0x10, -+ VCHI_FLAGS_CALLBACK_WHEN_DATA_READ = 0x20, -+ -+ VCHI_FLAGS_ALIGN_SLOT = 0x000080, // internal use only -+ VCHI_FLAGS_BULK_AUX_QUEUED = 0x010000, // internal use only -+ VCHI_FLAGS_BULK_AUX_COMPLETE = 0x020000, // internal use only -+ VCHI_FLAGS_BULK_DATA_QUEUED = 0x040000, // internal use only -+ VCHI_FLAGS_BULK_DATA_COMPLETE = 0x080000, // internal use only -+ VCHI_FLAGS_INTERNAL = 0xFF0000 -+} VCHI_FLAGS_T; -+ -+// constants for vchi_crc_control() -+typedef enum { -+ VCHI_CRC_NOTHING = -1, -+ VCHI_CRC_PER_SERVICE = 0, -+ VCHI_CRC_EVERYTHING = 1, -+} VCHI_CRC_CONTROL_T; -+ -+//callback reasons when an event occurs on a service -+typedef enum -+{ -+ VCHI_CALLBACK_REASON_MIN, -+ -+ //This indicates that there is data available -+ //handle is the msg id that was transmitted with the data -+ // When a message is received and there was no FULL message available previously, send callback -+ // Tasks get kicked by the callback, reset their event and try and read from the fifo until it fails -+ VCHI_CALLBACK_MSG_AVAILABLE, -+ VCHI_CALLBACK_MSG_SENT, -+ VCHI_CALLBACK_MSG_SPACE_AVAILABLE, // XXX not yet implemented -+ -+ // This indicates that a transfer from the other side has completed -+ VCHI_CALLBACK_BULK_RECEIVED, -+ //This indicates that data queued up to be sent has now gone -+ //handle is the msg id that was used when sending the data -+ VCHI_CALLBACK_BULK_SENT, -+ VCHI_CALLBACK_BULK_RX_SPACE_AVAILABLE, // XXX not yet implemented -+ VCHI_CALLBACK_BULK_TX_SPACE_AVAILABLE, // XXX not yet implemented -+ -+ VCHI_CALLBACK_SERVICE_CLOSED, -+ -+ // this side has sent XOFF to peer due to lack of data consumption by service -+ // (suggests the service may need to take some recovery action if it has -+ // been deliberately holding off consuming data) -+ VCHI_CALLBACK_SENT_XOFF, -+ VCHI_CALLBACK_SENT_XON, -+ -+ // indicates that a bulk transfer has finished reading the source buffer -+ VCHI_CALLBACK_BULK_DATA_READ, -+ -+ // power notification events (currently host side only) -+ VCHI_CALLBACK_PEER_OFF, -+ VCHI_CALLBACK_PEER_SUSPENDED, -+ VCHI_CALLBACK_PEER_ON, -+ VCHI_CALLBACK_PEER_RESUMED, -+ VCHI_CALLBACK_FORCED_POWER_OFF, -+ -+#ifdef USE_VCHIQ_ARM -+ // some extra notifications provided by vchiq_arm -+ VCHI_CALLBACK_SERVICE_OPENED, -+ VCHI_CALLBACK_BULK_RECEIVE_ABORTED, -+ VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, -+#endif -+ -+ VCHI_CALLBACK_REASON_MAX -+} VCHI_CALLBACK_REASON_T; -+ -+//Calback used by all services / bulk transfers -+typedef void (*VCHI_CALLBACK_T)( void *callback_param, //my service local param -+ VCHI_CALLBACK_REASON_T reason, -+ void *handle ); //for transmitting msg's only -+ -+ -+ -+/* -+ * Define vector struct for scatter-gather (vector) operations -+ * Vectors can be nested - if a vector element has negative length, then -+ * the data pointer is treated as pointing to another vector array, with -+ * '-vec_len' elements. Thus to append a header onto an existing vector, -+ * you can do this: -+ * -+ * void foo(const VCHI_MSG_VECTOR_T *v, int n) -+ * { -+ * VCHI_MSG_VECTOR_T nv[2]; -+ * nv[0].vec_base = my_header; -+ * nv[0].vec_len = sizeof my_header; -+ * nv[1].vec_base = v; -+ * nv[1].vec_len = -n; -+ * ... -+ * -+ */ -+typedef struct vchi_msg_vector { -+ const void *vec_base; -+ int32_t vec_len; -+} VCHI_MSG_VECTOR_T; -+ -+// Opaque type for a connection API -+typedef struct opaque_vchi_connection_api_t VCHI_CONNECTION_API_T; -+ -+// Opaque type for a message driver -+typedef struct opaque_vchi_message_driver_t VCHI_MESSAGE_DRIVER_T; -+ -+ -+// Iterator structure for reading ahead through received message queue. Allocated by client, -+// initialised by vchi_msg_look_ahead. Fields are for internal VCHI use only. -+// Iterates over messages in queue at the instant of the call to vchi_msg_lookahead - -+// will not proceed to messages received since. Behaviour is undefined if an iterator -+// is used again after messages for that service are removed/dequeued by any -+// means other than vchi_msg_iter_... calls on the iterator itself. -+typedef struct { -+ struct opaque_vchi_service_t *service; -+ void *last; -+ void *next; -+ void *remove; -+} VCHI_MSG_ITER_T; -+ -+ -+#endif // VCHI_COMMON_H_ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi.h 2012-07-15 20:29:13.751983290 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchi/vchi.h b/drivers/misc/vc04_services/interface/vchi/vchi.h +new file mode 100644 +index 0000000..e441d8c +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchi/vchi.h @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. @@ -8177,9 +8474,451 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi.h linux-r +#endif /* VCHI_H_ */ + +/****************************** End of file **********************************/ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi_mh.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi_mh.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi_mh.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi_mh.h 2012-07-15 20:29:13.750983271 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h b/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h +new file mode 100644 +index 0000000..a66e489 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchi/vchi_cfg.h +@@ -0,0 +1,214 @@ ++/* ++ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++/*============================================================================= ++Contains the #defines for the number of servers / clients etc, these can be ++over-ridden from the platform makefile if needed ++=============================================================================*/ ++ ++#ifndef VCHI_CFG_H_ ++#define VCHI_CFG_H_ ++ ++/**************************************************************************************** ++ * Defines in this first section are part of the VCHI API and may be examined by VCHI ++ * services. ++ ***************************************************************************************/ ++ ++/* Required alignment of base addresses for bulk transfer, if unaligned transfers are not enabled */ ++/* Really determined by the message driver, and should be available from a run-time call. */ ++#ifndef VCHI_BULK_ALIGN ++# if __VCCOREVER__ >= 0x04000000 ++# define VCHI_BULK_ALIGN 32 // Allows for the need to do cache cleans ++# else ++# define VCHI_BULK_ALIGN 16 ++# endif ++#endif ++ ++/* Required length multiple for bulk transfers, if unaligned transfers are not enabled */ ++/* May be less than or greater than VCHI_BULK_ALIGN */ ++/* Really determined by the message driver, and should be available from a run-time call. */ ++#ifndef VCHI_BULK_GRANULARITY ++# if __VCCOREVER__ >= 0x04000000 ++# define VCHI_BULK_GRANULARITY 32 // Allows for the need to do cache cleans ++# else ++# define VCHI_BULK_GRANULARITY 16 ++# endif ++#endif ++ ++/* The largest possible message to be queued with vchi_msg_queue. */ ++#ifndef VCHI_MAX_MSG_SIZE ++# if defined VCHI_LOCAL_HOST_PORT ++# define VCHI_MAX_MSG_SIZE 16384 // makes file transfers fast, but should they be using bulk? ++# else ++# define VCHI_MAX_MSG_SIZE 4096 // NOTE: THIS MUST BE LARGER THAN OR EQUAL TO THE SIZE OF THE KHRONOS MERGE BUFFER!! ++# endif ++#endif ++ ++/****************************************************************************************** ++ * Defines below are system configuration options, and should not be used by VCHI services. ++ *****************************************************************************************/ ++ ++/* How many connections can we support? A localhost implementation uses 2 connections, ++ * 1 for host-app, 1 for VMCS, and these are hooked together by a loopback MPHI VCFW ++ * driver. */ ++#ifndef VCHI_MAX_NUM_CONNECTIONS ++# define VCHI_MAX_NUM_CONNECTIONS 3 ++#endif ++ ++/* How many services can we open per connection? Extending this doesn't cost processing time, just a small ++ * amount of static memory. */ ++#ifndef VCHI_MAX_SERVICES_PER_CONNECTION ++# define VCHI_MAX_SERVICES_PER_CONNECTION 36 ++#endif ++ ++/* Adjust if using a message driver that supports more logical TX channels */ ++#ifndef VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION ++# define VCHI_MAX_BULK_TX_CHANNELS_PER_CONNECTION 9 // 1 MPHI + 8 CCP2 logical channels ++#endif ++ ++/* Adjust if using a message driver that supports more logical RX channels */ ++#ifndef VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION ++# define VCHI_MAX_BULK_RX_CHANNELS_PER_CONNECTION 1 // 1 MPHI ++#endif ++ ++/* How many receive slots do we use. This times VCHI_MAX_MSG_SIZE gives the effective ++ * receive queue space, less message headers. */ ++#ifndef VCHI_NUM_READ_SLOTS ++# if defined(VCHI_LOCAL_HOST_PORT) ++# define VCHI_NUM_READ_SLOTS 4 ++# else ++# define VCHI_NUM_READ_SLOTS 48 ++# endif ++#endif ++ ++/* Do we utilise overrun facility for receive message slots? Can aid peer transmit ++ * performance. Only define on VideoCore end, talking to host. ++ */ ++//#define VCHI_MSG_RX_OVERRUN ++ ++/* How many transmit slots do we use. Generally don't need many, as the hardware driver ++ * underneath VCHI will usually have its own buffering. */ ++#ifndef VCHI_NUM_WRITE_SLOTS ++# define VCHI_NUM_WRITE_SLOTS 4 ++#endif ++ ++/* If a service has held or queued received messages in VCHI_XOFF_THRESHOLD or more slots, ++ * then it's taking up too much buffer space, and the peer service will be told to stop ++ * transmitting with an XOFF message. For this to be effective, the VCHI_NUM_READ_SLOTS ++ * needs to be considerably bigger than VCHI_NUM_WRITE_SLOTS, or the transmit latency ++ * is too high. */ ++#ifndef VCHI_XOFF_THRESHOLD ++# define VCHI_XOFF_THRESHOLD (VCHI_NUM_READ_SLOTS / 2) ++#endif ++ ++/* After we've sent an XOFF, the peer will be told to resume transmission once the local ++ * service has dequeued/released enough messages that it's now occupying ++ * VCHI_XON_THRESHOLD slots or fewer. */ ++#ifndef VCHI_XON_THRESHOLD ++# define VCHI_XON_THRESHOLD (VCHI_NUM_READ_SLOTS / 4) ++#endif ++ ++/* A size below which a bulk transfer omits the handshake completely and always goes ++ * via the message channel, if bulk auxiliary is being sent on that service. (The user ++ * can guarantee this by enabling unaligned transmits). ++ * Not API. */ ++#ifndef VCHI_MIN_BULK_SIZE ++# define VCHI_MIN_BULK_SIZE ( VCHI_MAX_MSG_SIZE / 2 < 4096 ? VCHI_MAX_MSG_SIZE / 2 : 4096 ) ++#endif ++ ++/* Maximum size of bulk transmission chunks, for each interface type. A trade-off between ++ * speed and latency; the smaller the chunk size the better change of messages and other ++ * bulk transmissions getting in when big bulk transfers are happening. Set to 0 to not ++ * break transmissions into chunks. ++ */ ++#ifndef VCHI_MAX_BULK_CHUNK_SIZE_MPHI ++# define VCHI_MAX_BULK_CHUNK_SIZE_MPHI (16 * 1024) ++#endif ++ ++/* NB Chunked CCP2 transmissions violate the letter of the CCP2 spec by using "JPEG8" mode ++ * with multiple-line frames. Only use if the receiver can cope. */ ++#ifndef VCHI_MAX_BULK_CHUNK_SIZE_CCP2 ++# define VCHI_MAX_BULK_CHUNK_SIZE_CCP2 0 ++#endif ++ ++/* How many TX messages can we have pending in our transmit slots. Once exhausted, ++ * vchi_msg_queue will be blocked. */ ++#ifndef VCHI_TX_MSG_QUEUE_SIZE ++# define VCHI_TX_MSG_QUEUE_SIZE 256 ++#endif ++ ++/* How many RX messages can we have parsed in the receive slots. Once exhausted, parsing ++ * will be suspended until older messages are dequeued/released. */ ++#ifndef VCHI_RX_MSG_QUEUE_SIZE ++# define VCHI_RX_MSG_QUEUE_SIZE 256 ++#endif ++ ++/* Really should be able to cope if we run out of received message descriptors, by ++ * suspending parsing as the comment above says, but we don't. This sweeps the issue ++ * under the carpet. */ ++#if VCHI_RX_MSG_QUEUE_SIZE < (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS ++# undef VCHI_RX_MSG_QUEUE_SIZE ++# define VCHI_RX_MSG_QUEUE_SIZE (VCHI_MAX_MSG_SIZE/16 + 1) * VCHI_NUM_READ_SLOTS ++#endif ++ ++/* How many bulk transmits can we have pending. Once exhausted, vchi_bulk_queue_transmit ++ * will be blocked. */ ++#ifndef VCHI_TX_BULK_QUEUE_SIZE ++# define VCHI_TX_BULK_QUEUE_SIZE 64 ++#endif ++ ++/* How many bulk receives can we have pending. Once exhausted, vchi_bulk_queue_receive ++ * will be blocked. */ ++#ifndef VCHI_RX_BULK_QUEUE_SIZE ++# define VCHI_RX_BULK_QUEUE_SIZE 64 ++#endif ++ ++/* A limit on how many outstanding bulk requests we expect the peer to give us. If ++ * the peer asks for more than this, VCHI will fail and assert. The number is determined ++ * by the peer's hardware - it's the number of outstanding requests that can be queued ++ * on all bulk channels. VC3's MPHI peripheral allows 16. */ ++#ifndef VCHI_MAX_PEER_BULK_REQUESTS ++# define VCHI_MAX_PEER_BULK_REQUESTS 32 ++#endif ++ ++/* Define VCHI_CCP2TX_MANUAL_POWER if the host tells us when to turn the CCP2 ++ * transmitter on and off. ++ */ ++/*#define VCHI_CCP2TX_MANUAL_POWER*/ ++ ++#ifndef VCHI_CCP2TX_MANUAL_POWER ++ ++/* Timeout (in milliseconds) for putting the CCP2TX interface into IDLE state. Set ++ * negative for no IDLE. ++ */ ++# ifndef VCHI_CCP2TX_IDLE_TIMEOUT ++# define VCHI_CCP2TX_IDLE_TIMEOUT 5 ++# endif ++ ++/* Timeout (in milliseconds) for putting the CCP2TX interface into OFF state. Set ++ * negative for no OFF. ++ */ ++# ifndef VCHI_CCP2TX_OFF_TIMEOUT ++# define VCHI_CCP2TX_OFF_TIMEOUT 1000 ++# endif ++ ++#endif /* VCHI_CCP2TX_MANUAL_POWER */ ++ ++#endif /* VCHI_CFG_H_ */ ++ ++/****************************** End of file **********************************/ +diff --git a/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h b/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h +new file mode 100644 +index 0000000..958cc55 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchi/vchi_cfg_internal.h +@@ -0,0 +1,56 @@ ++/* ++ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef VCHI_CFG_INTERNAL_H_ ++#define VCHI_CFG_INTERNAL_H_ ++ ++/**************************************************************************************** ++ * Control optimisation attempts. ++ ***************************************************************************************/ ++ ++// Don't use lots of short-term locks - use great long ones, reducing the overall locks-per-second ++#define VCHI_COARSE_LOCKING ++ ++// Avoid lock then unlock on exit from blocking queue operations (msg tx, bulk rx/tx) ++// (only relevant if VCHI_COARSE_LOCKING) ++#define VCHI_ELIDE_BLOCK_EXIT_LOCK ++ ++// Avoid lock on non-blocking peek ++// (only relevant if VCHI_COARSE_LOCKING) ++#define VCHI_AVOID_PEEK_LOCK ++ ++// Use one slot-handler thread per connection, rather than 1 thread dealing with all connections in rotation. ++#define VCHI_MULTIPLE_HANDLER_THREADS ++ ++// Put free descriptors onto the head of the free queue, rather than the tail, so that we don't thrash ++// our way through the pool of descriptors. ++#define VCHI_PUSH_FREE_DESCRIPTORS_ONTO_HEAD ++ ++// Don't issue a MSG_AVAILABLE callback for every single message. Possibly only safe if VCHI_COARSE_LOCKING. ++#define VCHI_FEWER_MSG_AVAILABLE_CALLBACKS ++ ++// Don't use message descriptors for TX messages that don't need them ++#define VCHI_MINIMISE_TX_MSG_DESCRIPTORS ++ ++// Nano-locks for multiqueue ++//#define VCHI_MQUEUE_NANOLOCKS ++ ++// Lock-free(er) dequeuing ++//#define VCHI_RX_NANOLOCKS ++ ++#endif /*VCHI_CFG_INTERNAL_H_*/ +diff --git a/drivers/misc/vc04_services/interface/vchi/vchi_common.h b/drivers/misc/vc04_services/interface/vchi/vchi_common.h +new file mode 100644 +index 0000000..4057878 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchi/vchi_common.h +@@ -0,0 +1,152 @@ ++/* ++ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++/*============================================================================= ++Contains global defs used by submodules within vchi. ++=============================================================================*/ ++ ++#ifndef VCHI_COMMON_H_ ++#define VCHI_COMMON_H_ ++ ++ ++//flags used when sending messages (must be bitmapped) ++typedef enum ++{ ++ VCHI_FLAGS_NONE = 0x0, ++ VCHI_FLAGS_BLOCK_UNTIL_OP_COMPLETE = 0x1, // waits for message to be received, or sent (NB. not the same as being seen on other side) ++ VCHI_FLAGS_CALLBACK_WHEN_OP_COMPLETE = 0x2, // run a callback when message sent ++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED = 0x4, // return once the transfer is in a queue ready to go ++ VCHI_FLAGS_ALLOW_PARTIAL = 0x8, ++ VCHI_FLAGS_BLOCK_UNTIL_DATA_READ = 0x10, ++ VCHI_FLAGS_CALLBACK_WHEN_DATA_READ = 0x20, ++ ++ VCHI_FLAGS_ALIGN_SLOT = 0x000080, // internal use only ++ VCHI_FLAGS_BULK_AUX_QUEUED = 0x010000, // internal use only ++ VCHI_FLAGS_BULK_AUX_COMPLETE = 0x020000, // internal use only ++ VCHI_FLAGS_BULK_DATA_QUEUED = 0x040000, // internal use only ++ VCHI_FLAGS_BULK_DATA_COMPLETE = 0x080000, // internal use only ++ VCHI_FLAGS_INTERNAL = 0xFF0000 ++} VCHI_FLAGS_T; ++ ++// constants for vchi_crc_control() ++typedef enum { ++ VCHI_CRC_NOTHING = -1, ++ VCHI_CRC_PER_SERVICE = 0, ++ VCHI_CRC_EVERYTHING = 1, ++} VCHI_CRC_CONTROL_T; ++ ++//callback reasons when an event occurs on a service ++typedef enum ++{ ++ VCHI_CALLBACK_REASON_MIN, ++ ++ //This indicates that there is data available ++ //handle is the msg id that was transmitted with the data ++ // When a message is received and there was no FULL message available previously, send callback ++ // Tasks get kicked by the callback, reset their event and try and read from the fifo until it fails ++ VCHI_CALLBACK_MSG_AVAILABLE, ++ VCHI_CALLBACK_MSG_SENT, ++ VCHI_CALLBACK_MSG_SPACE_AVAILABLE, // XXX not yet implemented ++ ++ // This indicates that a transfer from the other side has completed ++ VCHI_CALLBACK_BULK_RECEIVED, ++ //This indicates that data queued up to be sent has now gone ++ //handle is the msg id that was used when sending the data ++ VCHI_CALLBACK_BULK_SENT, ++ VCHI_CALLBACK_BULK_RX_SPACE_AVAILABLE, // XXX not yet implemented ++ VCHI_CALLBACK_BULK_TX_SPACE_AVAILABLE, // XXX not yet implemented ++ ++ VCHI_CALLBACK_SERVICE_CLOSED, ++ ++ // this side has sent XOFF to peer due to lack of data consumption by service ++ // (suggests the service may need to take some recovery action if it has ++ // been deliberately holding off consuming data) ++ VCHI_CALLBACK_SENT_XOFF, ++ VCHI_CALLBACK_SENT_XON, ++ ++ // indicates that a bulk transfer has finished reading the source buffer ++ VCHI_CALLBACK_BULK_DATA_READ, ++ ++ // power notification events (currently host side only) ++ VCHI_CALLBACK_PEER_OFF, ++ VCHI_CALLBACK_PEER_SUSPENDED, ++ VCHI_CALLBACK_PEER_ON, ++ VCHI_CALLBACK_PEER_RESUMED, ++ VCHI_CALLBACK_FORCED_POWER_OFF, ++ ++#ifdef USE_VCHIQ_ARM ++ // some extra notifications provided by vchiq_arm ++ VCHI_CALLBACK_SERVICE_OPENED, ++ VCHI_CALLBACK_BULK_RECEIVE_ABORTED, ++ VCHI_CALLBACK_BULK_TRANSMIT_ABORTED, ++#endif ++ ++ VCHI_CALLBACK_REASON_MAX ++} VCHI_CALLBACK_REASON_T; ++ ++//Calback used by all services / bulk transfers ++typedef void (*VCHI_CALLBACK_T)( void *callback_param, //my service local param ++ VCHI_CALLBACK_REASON_T reason, ++ void *handle ); //for transmitting msg's only ++ ++ ++ ++/* ++ * Define vector struct for scatter-gather (vector) operations ++ * Vectors can be nested - if a vector element has negative length, then ++ * the data pointer is treated as pointing to another vector array, with ++ * '-vec_len' elements. Thus to append a header onto an existing vector, ++ * you can do this: ++ * ++ * void foo(const VCHI_MSG_VECTOR_T *v, int n) ++ * { ++ * VCHI_MSG_VECTOR_T nv[2]; ++ * nv[0].vec_base = my_header; ++ * nv[0].vec_len = sizeof my_header; ++ * nv[1].vec_base = v; ++ * nv[1].vec_len = -n; ++ * ... ++ * ++ */ ++typedef struct vchi_msg_vector { ++ const void *vec_base; ++ int32_t vec_len; ++} VCHI_MSG_VECTOR_T; ++ ++// Opaque type for a connection API ++typedef struct opaque_vchi_connection_api_t VCHI_CONNECTION_API_T; ++ ++// Opaque type for a message driver ++typedef struct opaque_vchi_message_driver_t VCHI_MESSAGE_DRIVER_T; ++ ++ ++// Iterator structure for reading ahead through received message queue. Allocated by client, ++// initialised by vchi_msg_look_ahead. Fields are for internal VCHI use only. ++// Iterates over messages in queue at the instant of the call to vchi_msg_lookahead - ++// will not proceed to messages received since. Behaviour is undefined if an iterator ++// is used again after messages for that service are removed/dequeued by any ++// means other than vchi_msg_iter_... calls on the iterator itself. ++typedef struct { ++ struct opaque_vchi_service_t *service; ++ void *last; ++ void *next; ++ void *remove; ++} VCHI_MSG_ITER_T; ++ ++ ++#endif // VCHI_COMMON_H_ +diff --git a/drivers/misc/vc04_services/interface/vchi/vchi_mh.h b/drivers/misc/vc04_services/interface/vchi/vchi_mh.h +new file mode 100644 +index 0000000..9bcf12e +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchi/vchi_mh.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -8208,9 +8947,77 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchi/vchi_mh.h linu +#define VCHI_MEM_HANDLE_INVALID 0 + +#endif -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c 2012-07-15 20:29:13.666981713 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h +new file mode 100644 +index 0000000..49d3087 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (c) 2010-2011 Broadcom. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef VCHIQ_VCHIQ_H ++#define VCHIQ_VCHIQ_H ++ ++#include "vchiq_if.h" ++#include "vchiq_util.h" ++#include "interface/vcos/vcos.h" ++ ++#endif ++ +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h +new file mode 100644 +index 0000000..959405e +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h +@@ -0,0 +1,27 @@ ++/* ++ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef VCHIQ_2835_H ++#define VCHIQ_2835_H ++ ++#include "vchiq_pagelist.h" ++ ++#define VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX 0 ++#define VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX 1 ++ ++#endif /* VCHIQ_2835_H */ +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +new file mode 100644 +index 0000000..35f6afe +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -0,0 +1,512 @@ +/* + * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. @@ -8724,40 +9531,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_283 + kfree(pagelist); +} + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835.h 2012-07-15 20:29:13.734982971 +0200 -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef VCHIQ_2835_H -+#define VCHIQ_2835_H -+ -+#include "vchiq_pagelist.h" -+ -+#define VCHIQ_PLATFORM_FRAGMENTS_OFFSET_IDX 0 -+#define VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX 1 -+ -+#endif /* VCHIQ_2835_H */ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c 2012-07-15 20:29:13.723982762 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c +new file mode 100644 +index 0000000..49a53ce +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -0,0 +1,1912 @@ +/* + * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. @@ -10671,9 +11449,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm +module_exit(vchiq_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Broadcom Corporation"); -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h 2012-07-15 20:29:13.674981835 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h +new file mode 100644 +index 0000000..24b42ff +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. @@ -10793,9 +11573,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_arm + + +#endif /* VCHIQ_ARM_H */ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h 2012-07-15 20:29:13.725982798 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h +new file mode 100644 +index 0000000..cd51d99 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. @@ -10840,9 +11622,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cfg +#endif + +#endif /* VCHIQ_CFG_H */ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c 2012-07-15 20:29:13.750983271 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c +new file mode 100644 +index 0000000..62e3006 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.c @@ -0,0 +1,101 @@ +/***************************************************************************** +* Copyright 2001 - 2010 Broadcom Corporation. All rights reserved. @@ -10945,9 +11729,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_con +} + +EXPORT_SYMBOL( vchiq_add_connected_callback ); -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h 2012-07-15 20:29:13.733982952 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h +new file mode 100644 +index 0000000..88cfa58 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_connected.h @@ -0,0 +1,32 @@ +/***************************************************************************** +* Copyright 2001 - 2010 Broadcom Corporation. All rights reserved. @@ -10981,9 +11767,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_con + +#endif /* VCHIQ_CONNECTED_H */ + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c 2012-07-15 20:29:13.749983252 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c +new file mode 100644 +index 0000000..749e7d4 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.c @@ -0,0 +1,2717 @@ +/* + * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. @@ -13702,9 +14490,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cor + } + return status; +} -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h 2012-07-15 20:29:13.724982778 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h +new file mode 100644 +index 0000000..37884bd +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_core.h @@ -0,0 +1,506 @@ +/* + * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. @@ -14212,40 +15002,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_cor +vchiq_platform_conn_state_changed(VCHIQ_STATE_T* state, VCHIQ_CONNSTATE_T oldstate, VCHIQ_CONNSTATE_T newstate); + +#endif -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq.h 2012-07-15 20:29:13.724982778 +0200 -@@ -0,0 +1,27 @@ -+/* -+ * Copyright (c) 2010-2011 Broadcom. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef VCHIQ_VCHIQ_H -+#define VCHIQ_VCHIQ_H -+ -+#include "vchiq_if.h" -+#include "vchiq_util.h" -+#include "interface/vcos/vcos.h" -+ -+#endif -+ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h 2012-07-15 20:29:13.725982798 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h +new file mode 100644 +index 0000000..42d471b +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. @@ -14402,9 +15163,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_if. +extern VCHIQ_STATUS_T vchiq_dump_phys_mem( VCHIQ_SERVICE_HANDLE_T service, void *ptr, size_t num_bytes ); + +#endif /* VCHIQ_IF_H */ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h 2012-07-15 20:29:13.742983121 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h +new file mode 100644 +index 0000000..06298bf +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioctl.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. @@ -14511,9 +15274,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ioc +#define VCHIQ_IOC_MAX 15 + +#endif -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c 2012-07-15 20:29:13.734982971 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c +new file mode 100644 +index 0000000..e1768e4 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_kern_lib.c @@ -0,0 +1,297 @@ +/***************************************************************************** +* Copyright 2001 - 2011 Broadcom Corporation. All rights reserved. @@ -14812,9 +15577,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_ker +EXPORT_SYMBOL(vchiq_open_service); +EXPORT_SYMBOL(vchiq_add_service_params); +EXPORT_SYMBOL(vchiq_open_service_params); -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_lib.c linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_lib.c ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_lib.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_lib.c 2012-07-15 20:29:13.726982820 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_lib.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_lib.c +new file mode 100644 +index 0000000..f1a8f42 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_lib.c @@ -0,0 +1,1628 @@ +/* + * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. @@ -16444,9 +17211,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_lib + free_msgbufs = buf; + vcos_mutex_unlock(&vchiq_lib_mutex); +} -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h 2012-07-15 20:29:13.733982952 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h +new file mode 100644 +index 0000000..a465b91 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_memdrv.h @@ -0,0 +1,45 @@ +/***************************************************************************** +* Copyright 2001 - 2010 Broadcom Corporation. All rights reserved. @@ -16493,9 +17262,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_mem +VCHIQ_STATUS_T vchiq_memdrv_initialise(void); + +#endif -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h 2012-07-15 20:29:13.723982762 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h +new file mode 100644 +index 0000000..e8d4e30 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pagelist.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. @@ -16540,9 +17311,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_pag +} FRAGMENTS_T; + +#endif /* VCHIQ_PAGELIST_H */ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c 2012-07-15 20:29:13.724982778 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c +new file mode 100644 +index 0000000..88cd86f +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shim.c @@ -0,0 +1,1001 @@ +/* + * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. @@ -17545,9 +18318,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_shi +EXPORT_SYMBOL(vchi_service_use); +EXPORT_SYMBOL(vchi_service_release); +#endif -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c 2012-07-15 20:29:13.750983271 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c +new file mode 100644 +index 0000000..20b67c3 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. @@ -17646,9 +18421,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_uti + + return header; +} -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h 2012-07-15 20:29:13.674981835 +0200 +diff --git a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h +new file mode 100644 +index 0000000..6e0c84b +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_util.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2010-2011 Broadcom Corporation. All rights reserved. @@ -17697,9 +18474,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_uti + +#endif + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_cmd.c linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_cmd.c ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_cmd.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_cmd.c 2012-07-15 20:29:13.594980335 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/generic/vcos_cmd.c b/drivers/misc/vc04_services/interface/vcos/generic/vcos_cmd.c +new file mode 100644 +index 0000000..447d577 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_cmd.c @@ -0,0 +1,681 @@ +/***************************************************************************** +* Copyright 2009 - 2011 Broadcom Corporation. All rights reserved. @@ -18382,9 +19161,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_c + return VCOS_SUCCESS; +} + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_common.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_common.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_common.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_common.h 2012-07-15 20:29:13.587980204 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/generic/vcos_common.h b/drivers/misc/vc04_services/interface/vcos/generic/vcos_common.h +new file mode 100644 +index 0000000..ce7816957 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_common.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -18473,9 +19254,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_c +VCOSPRE_ void VCOSPOST_ vcos_timer_init(void); +#endif + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_blockpool.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_blockpool.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_blockpool.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_blockpool.h 2012-07-15 20:29:13.595980354 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_blockpool.h b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_blockpool.h +new file mode 100644 +index 0000000..154b200 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_blockpool.h @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -18748,9 +19531,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_g +#endif +#endif /* VCOS_GENERIC_BLOCKPOOL_H */ + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_event_flags.c linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_event_flags.c ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_event_flags.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_event_flags.c 2012-07-15 20:29:13.594980335 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_event_flags.c b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_event_flags.c +new file mode 100644 +index 0000000..3948a57 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_event_flags.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -19063,9 +19848,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_g +} + +#endif -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_event_flags.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_event_flags.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_event_flags.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_event_flags.h 2012-07-15 20:29:13.597980392 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_event_flags.h b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_event_flags.h +new file mode 100644 +index 0000000..8776ebe +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_event_flags.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -19185,9 +19972,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_g +#endif +#endif + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_named_sem.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_named_sem.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_named_sem.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_named_sem.h 2012-07-15 20:29:13.596980373 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_named_sem.h b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_named_sem.h +new file mode 100644 +index 0000000..370562d +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_named_sem.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -19281,9 +20070,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_g +#endif + + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_quickslow_mutex.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_quickslow_mutex.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_quickslow_mutex.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_quickslow_mutex.h 2012-07-15 20:29:13.595980354 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_quickslow_mutex.h b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_quickslow_mutex.h +new file mode 100644 +index 0000000..bf7945c +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_quickslow_mutex.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -19371,9 +20162,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_g +#endif + + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_reentrant_mtx.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_reentrant_mtx.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_reentrant_mtx.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_reentrant_mtx.h 2012-07-15 20:29:13.595980354 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_reentrant_mtx.h b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_reentrant_mtx.h +new file mode 100644 +index 0000000..27563ea +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_reentrant_mtx.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -19461,9 +20254,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_g +#endif + + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_tls.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_tls.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_tls.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_tls.h 2012-07-15 20:29:13.571979902 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_tls.h b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_tls.h +new file mode 100644 +index 0000000..22c059a +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_generic_tls.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -19620,9 +20415,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_g +#endif + + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_joinable_thread_from_plain.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_joinable_thread_from_plain.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_joinable_thread_from_plain.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_joinable_thread_from_plain.h 2012-07-15 20:29:13.596980373 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/generic/vcos_joinable_thread_from_plain.h b/drivers/misc/vc04_services/interface/vcos/generic/vcos_joinable_thread_from_plain.h +new file mode 100644 +index 0000000..fd0e198 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_joinable_thread_from_plain.h @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -19838,9 +20635,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_j +} +#endif +#endif /* VCOS_JOINABLE_THREAD_FROM_PLAIN_H */ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_latch_from_sem.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_latch_from_sem.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_latch_from_sem.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_latch_from_sem.h 2012-07-15 20:29:13.596980373 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/generic/vcos_latch_from_sem.h b/drivers/misc/vc04_services/interface/vcos/generic/vcos_latch_from_sem.h +new file mode 100644 +index 0000000..ec9e07b +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_latch_from_sem.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -19901,9 +20700,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_l + +#endif /* VCOS_INLINE_BODIES */ + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_logcat.c linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_logcat.c ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_logcat.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_logcat.c 2012-07-15 20:29:13.593980317 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/generic/vcos_logcat.c b/drivers/misc/vc04_services/interface/vcos/generic/vcos_logcat.c +new file mode 100644 +index 0000000..8b05179 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_logcat.c @@ -0,0 +1,560 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -20465,9 +21266,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_l + } +} + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_mem_from_malloc.c linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_mem_from_malloc.c ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_mem_from_malloc.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_mem_from_malloc.c 2012-07-15 20:29:13.582980110 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/generic/vcos_mem_from_malloc.c b/drivers/misc/vc04_services/interface/vcos/generic/vcos_mem_from_malloc.c +new file mode 100644 +index 0000000..dd0574a +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_mem_from_malloc.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -20553,9 +21356,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_m + _vcos_platform_free(h->ptr); +} + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_mem_from_malloc.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_mem_from_malloc.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_mem_from_malloc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_mem_from_malloc.h 2012-07-15 20:29:13.571979902 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/generic/vcos_mem_from_malloc.h b/drivers/misc/vc04_services/interface/vcos/generic/vcos_mem_from_malloc.h +new file mode 100644 +index 0000000..8e2a18e +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_mem_from_malloc.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -20622,9 +21427,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_m +#endif /* VCOS_INLINE_BODIES */ + + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_mutexes_are_reentrant.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_mutexes_are_reentrant.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_mutexes_are_reentrant.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_mutexes_are_reentrant.h 2012-07-15 20:29:13.596980373 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/generic/vcos_mutexes_are_reentrant.h b/drivers/misc/vc04_services/interface/vcos/generic/vcos_mutexes_are_reentrant.h +new file mode 100644 +index 0000000..a6a52b4 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_mutexes_are_reentrant.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -20705,9 +21512,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_m + + + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_thread_reaper.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_thread_reaper.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_thread_reaper.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_thread_reaper.h 2012-07-15 20:29:13.588980223 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/generic/vcos_thread_reaper.h b/drivers/misc/vc04_services/interface/vcos/generic/vcos_thread_reaper.h +new file mode 100644 +index 0000000..655dc25 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/generic/vcos_thread_reaper.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -20755,9 +21564,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/generic/vcos_t +#endif + + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/stdint.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/stdint.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/stdint.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/stdint.h 2012-07-15 20:29:13.465977909 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/linuxkernel/stdint.h b/drivers/misc/vc04_services/interface/vcos/linuxkernel/stdint.h +new file mode 100644 +index 0000000..1db1ecb +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/linuxkernel/stdint.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -20790,9 +21601,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/st +#include /* includes integer types */ + +#endif /* _VCOS_PLATFORM_LINUX_STDINT_H */ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel.c linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel.c ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel.c 2012-07-15 20:29:13.472978040 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel.c b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel.c +new file mode 100644 +index 0000000..0385540 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel.c @@ -0,0 +1,627 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -21421,9 +22234,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vc +EXPORT_SYMBOL( vcos_verify_bkpts_enabled ); + +EXPORT_SYMBOL( vcos_strdup ); -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel_cfg.c linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel_cfg.c ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel_cfg.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel_cfg.c 2012-07-15 20:29:13.471978021 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel_cfg.c b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel_cfg.c +new file mode 100644 +index 0000000..e3f0840 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel_cfg.c @@ -0,0 +1,332 @@ +/***************************************************************************** +* Copyright 2009 - 2010 Broadcom Corporation. All rights reserved. @@ -21757,9 +22572,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vc + +EXPORT_SYMBOL_GPL( vcos_cfg_get_proc_entry ); + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel_misc.c linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel_misc.c ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel_misc.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel_misc.c 2012-07-15 20:29:13.472978040 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel_misc.c b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel_misc.c +new file mode 100644 +index 0000000..4a9cedf +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_linuxkernel_misc.c @@ -0,0 +1,111 @@ +/***************************************************************************** +* Copyright 2009 - 2010 Broadcom Corporation. All rights reserved. @@ -21872,9 +22689,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vc + +// END ######################################################################### +// ############################################################################# -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_mod_init.c linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_mod_init.c ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_mod_init.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_mod_init.c 2012-07-15 20:29:13.471978021 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_mod_init.c b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_mod_init.c +new file mode 100644 +index 0000000..6ffd755 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_mod_init.c @@ -0,0 +1,64 @@ +/***************************************************************************** +* Copyright 2006 - 2008 Broadcom Corporation. All rights reserved. @@ -21940,9 +22759,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vc +MODULE_LICENSE( "GPL" ); +MODULE_VERSION( "1.0" ); + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_platform.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_platform.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_platform.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_platform.h 2012-07-15 20:29:13.470978002 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_platform.h b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_platform.h +new file mode 100644 +index 0000000..381688e +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_platform.h @@ -0,0 +1,507 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -22451,9 +23272,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vc + +#endif /* VCOS_PLATFORM_H */ + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_platform_types.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_platform_types.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_platform_types.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_platform_types.h 2012-07-15 20:29:13.483978247 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_platform_types.h b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_platform_types.h +new file mode 100644 +index 0000000..5f82aaf +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_platform_types.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -22514,9 +23337,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vc +#define PRIx64 "llx" + +#endif -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_thread_map.c linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_thread_map.c ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_thread_map.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_thread_map.c 2012-07-15 20:29:13.484978266 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_thread_map.c b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_thread_map.c +new file mode 100644 +index 0000000..2d62589 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_thread_map.c @@ -0,0 +1,129 @@ +/***************************************************************************** +* Copyright 2009 - 2010 Broadcom Corporation. All rights reserved. @@ -22647,9 +23472,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vc + + return *vcos_thread_storage; +} -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_thread_map.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_thread_map.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_thread_map.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_thread_map.h 2012-07-15 20:29:13.483978247 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_thread_map.h b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_thread_map.h +new file mode 100644 +index 0000000..62963c1 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/linuxkernel/vcos_thread_map.h @@ -0,0 +1,39 @@ +/***************************************************************************** +* Copyright 2009 - 2010 Broadcom Corporation. All rights reserved. @@ -22690,9 +23517,229 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/linuxkernel/vc +VCOS_THREAD_T *vcos_kthread_current(void); + +#endif /*VCOS_THREAD_MAP_H */ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_assert.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_assert.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_assert.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_assert.h 2012-07-15 20:29:13.598980411 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos.h b/drivers/misc/vc04_services/interface/vcos/vcos.h +new file mode 100644 +index 0000000..e37d795 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos.h +@@ -0,0 +1,212 @@ ++/* ++ * Copyright (c) 2010-2011 Broadcom. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++/*============================================================================= ++VideoCore OS Abstraction Layer - public header file ++=============================================================================*/ ++ ++/** ++ * \mainpage OS Abstraction Layer ++ * ++ * \section intro Introduction ++ * ++ * This abstraction layer is here to allow the underlying OS to be easily changed (e.g. from ++ * Nucleus to ThreadX) and to aid in porting host applications to new targets. ++ * ++ * \subsection error Error handling ++ * ++ * Wherever possible, VCOS functions assert internally and return void. The only exceptions ++ * are creation functions (which might fail due to lack of resources) and functions that ++ * might timeout or fail due to lack of space. Errors that might be reported by the underlying ++ * OS API (e.g. invalid mutex) are treated as a programming error, and are merely asserted on. ++ * ++ * \section thread_synch Threads and synchronisation ++ * ++ * \subsection thread Threads ++ * ++ * The thread API is somewhat different to that found in Nucleus. In particular, threads ++ * cannot just be destroyed at arbitrary times and nor can they merely exit. This is so ++ * that the same API can be implemented across all interesting platforms without too much ++ * difficulty. See vcos_thread.h for details. Thread attributes are configured via ++ * the VCOS_THREAD_ATTR_T structure, found in vcos_thread_attr.h. ++ * ++ * \subsection sema Semaphores ++ * ++ * Counted semaphores (c.f. Nucleus NU_SEMAPHORE) are created with VCOS_SEMAPHORE_T. ++ * Under ThreadX on VideoCore, semaphores are implemented using VideoCore spinlocks, and ++ * so are quite a lot faster than ordinary ThreadX semaphores. See vcos_semaphore.h. ++ * ++ * \subsection mtx Mutexes ++ * ++ * Mutexes are used for locking. Attempts to take a mutex twice, or to unlock it ++ * in a different thread to the one in which it was locked should be expected to fail. ++ * Mutexes are not re-entrant (see vcos_reentrant_mutex.h for a slightly slower ++ * re-entrant mutex). ++ * ++ * \subsection evflags Event flags ++ * ++ * Event flags (the ThreadX name - also known as event groups under Nucleus) provide ++ * 32 flags which can be waited on by multiple clients, and signalled by multiple clients. ++ * A timeout can be specified. See vcos_event_flags.h. An alternative to this is the ++ * VCOS_EVENT_T (see vcos_event.h) which is akin to the Win32 auto-reset event, or a ++ * saturating counted semaphore. ++ * ++ * \subsection event Events ++ * ++ * A VCOS_EVENT_T is a bit like a saturating semaphore. No matter how many times it ++ * is signalled, the waiter will only wake up once. See vcos_event.h. You might think this ++ * is useful if you suspect that the cost of reading the semaphore count (perhaps via a ++ * system call) is expensive on your platform. ++ * ++ * \subsection tls Thread local storage ++ * ++ * Thread local storage is supported using vcos_tls.h. This is emulated on Nucleus ++ * and ThreadX. ++ * ++ * \section int Interrupts ++ * ++ * The legacy LISR/HISR scheme found in Nucleus is supported via the legacy ISR API, ++ * which is also supported on ThreadX. New code should avoid this, and old code should ++ * be migrated away from it, since it is slow. See vcos_legacy_isr.h. ++ * ++ * Registering an interrupt handler, and disabling/restoring interrupts, is handled ++ * using the functions in vcos_isr.h. ++ * ++ */ ++ ++/** ++ * \file vcos.h ++ * ++ * This is the top level header file. Clients include this. It pulls in the platform-specific ++ * header file (vcos_platform.h) together with header files defining the expected APIs, such ++ * as vcos_mutex.h, vcos_semaphore.h, etc. It is also possible to include these header files ++ * directly. ++ * ++ */ ++ ++#ifndef VCOS_H ++#define VCOS_H ++ ++#include "interface/vcos/vcos_assert.h" ++#include "vcos_types.h" ++#include "vcos_platform.h" ++ ++#ifndef VCOS_INIT_H ++#include "interface/vcos/vcos_init.h" ++#endif ++ ++#ifndef VCOS_SEMAPHORE_H ++#include "interface/vcos/vcos_semaphore.h" ++#endif ++ ++#ifndef VCOS_THREAD_H ++#include "interface/vcos/vcos_thread.h" ++#endif ++ ++#ifndef VCOS_MUTEX_H ++#include "interface/vcos/vcos_mutex.h" ++#endif ++ ++#ifndef VCOS_MEM_H ++#include "interface/vcos/vcos_mem.h" ++#endif ++ ++#ifndef VCOS_LOGGING_H ++#include "interface/vcos/vcos_logging.h" ++#endif ++ ++#ifndef VCOS_STRING_H ++#include "interface/vcos/vcos_string.h" ++#endif ++ ++#ifndef VCOS_EVENT_H ++#include "interface/vcos/vcos_event.h" ++#endif ++ ++#ifndef VCOS_THREAD_ATTR_H ++#include "interface/vcos/vcos_thread_attr.h" ++#endif ++ ++#ifndef VCOS_TLS_H ++#include "interface/vcos/vcos_tls.h" ++#endif ++ ++#ifndef VCOS_REENTRANT_MUTEX_H ++#include "interface/vcos/vcos_reentrant_mutex.h" ++#endif ++ ++#ifndef VCOS_NAMED_SEMAPHORE_H ++#include "interface/vcos/vcos_named_semaphore.h" ++#endif ++ ++#ifndef VCOS_QUICKSLOW_MUTEX_H ++#include "interface/vcos/vcos_quickslow_mutex.h" ++#endif ++ ++/* Headers with predicates */ ++ ++#if VCOS_HAVE_EVENT_FLAGS ++#include "interface/vcos/vcos_event_flags.h" ++#endif ++ ++#if VCOS_HAVE_QUEUE ++#include "interface/vcos/vcos_queue.h" ++#endif ++ ++#if VCOS_HAVE_LEGACY_ISR ++#include "interface/vcos/vcos_legacy_isr.h" ++#endif ++ ++#if VCOS_HAVE_TIMER ++#include "interface/vcos/vcos_timer.h" ++#endif ++ ++#if VCOS_HAVE_MEMPOOL ++#include "interface/vcos/vcos_mempool.h" ++#endif ++ ++#if VCOS_HAVE_ISR ++#include "interface/vcos/vcos_isr.h" ++#endif ++ ++#if VCOS_HAVE_ATOMIC_FLAGS ++#include "interface/vcos/vcos_atomic_flags.h" ++#endif ++ ++#if VCOS_HAVE_ONCE ++#include "interface/vcos/vcos_once.h" ++#endif ++ ++#if VCOS_HAVE_BLOCK_POOL ++#include "interface/vcos/vcos_blockpool.h" ++#endif ++ ++#if VCOS_HAVE_FILE ++#include "interface/vcos/vcos_file.h" ++#endif ++ ++#if VCOS_HAVE_CFG ++#include "interface/vcos/vcos_cfg.h" ++#endif ++ ++#if VCOS_HAVE_CMD ++#include "interface/vcos/vcos_cmd.h" ++#endif ++ ++#endif /* VCOS_H */ ++ +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_assert.h b/drivers/misc/vc04_services/interface/vcos/vcos_assert.h +new file mode 100644 +index 0000000..1e72dff +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_assert.h @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -22974,9 +24021,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_assert.h +#endif + +#endif /* VCOS_ASSERT_H */ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_atomic_flags.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_atomic_flags.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_atomic_flags.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_atomic_flags.h 2012-07-15 20:29:13.597980392 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_atomic_flags.h b/drivers/misc/vc04_services/interface/vcos/vcos_atomic_flags.h +new file mode 100644 +index 0000000..317abf3 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_atomic_flags.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -23061,9 +24110,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_atomic_fl +#endif + +#endif -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_build_info.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_build_info.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_build_info.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_build_info.h 2012-07-15 20:29:13.463977871 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_build_info.h b/drivers/misc/vc04_services/interface/vcos/vcos_build_info.h +new file mode 100644 +index 0000000..f3817f6 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_build_info.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -23088,9 +24139,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_build_inf +const char *vcos_get_build_time( void ); +const char *vcos_get_build_date( void ); + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_cfg.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_cfg.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_cfg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_cfg.h 2012-07-15 20:29:13.462977852 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_cfg.h b/drivers/misc/vc04_services/interface/vcos/vcos_cfg.h +new file mode 100644 +index 0000000..4423051 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_cfg.h @@ -0,0 +1,113 @@ +/***************************************************************************** +* Copyright 2009 - 2011 Broadcom Corporation. All rights reserved. @@ -23205,9 +24258,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_cfg.h lin +#endif +#endif + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_cmd.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_cmd.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_cmd.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_cmd.h 2012-07-15 20:29:13.502978604 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_cmd.h b/drivers/misc/vc04_services/interface/vcos/vcos_cmd.h +new file mode 100644 +index 0000000..29d5315 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_cmd.h @@ -0,0 +1,98 @@ +/***************************************************************************** +* Copyright 2009 - 2011 Broadcom Corporation. All rights reserved. @@ -23307,9 +24362,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_cmd.h lin + +#endif /* VCOS_CMD_H */ + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_ctype.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_ctype.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_ctype.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_ctype.h 2012-07-15 20:29:13.600980449 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_ctype.h b/drivers/misc/vc04_services/interface/vcos/vcos_ctype.h +new file mode 100644 +index 0000000..a270de8 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_ctype.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -23351,9 +24408,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_ctype.h l + +#endif + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_dlfcn.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_dlfcn.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_dlfcn.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_dlfcn.h 2012-07-15 20:29:13.598980411 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_dlfcn.h b/drivers/misc/vc04_services/interface/vcos/vcos_dlfcn.h +new file mode 100644 +index 0000000..0a683c0b +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_dlfcn.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -23435,9 +24494,125 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_dlfcn.h l +#endif + + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_event_flags.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_event_flags.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_event_flags.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_event_flags.h 2012-07-15 20:29:13.493978435 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_event.h b/drivers/misc/vc04_services/interface/vcos/vcos_event.h +new file mode 100644 +index 0000000..38612f9 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_event.h +@@ -0,0 +1,108 @@ ++/* ++ * Copyright (c) 2010-2011 Broadcom. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++/*============================================================================= ++VideoCore OS Abstraction Layer - public header file for events ++=============================================================================*/ ++ ++#ifndef VCOS_EVENT_H ++#define VCOS_EVENT_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "interface/vcos/vcos_types.h" ++#include "vcos_platform.h" ++ ++/** ++ * \file ++ * ++ * An event is akin to the Win32 auto-reset event. ++ * ++ * ++ * Signalling an event will wake up one waiting thread only. Once one ++ * thread has been woken the event atomically returns to the unsignalled ++ * state. ++ * ++ * If no threads are waiting on the event when it is signalled it remains ++ * signalled. ++ * ++ * This is almost, but not quite, completely unlike the "event flags" ++ * object based on Nucleus event groups and ThreadX event flags. ++ * ++ * In particular, it should be similar in speed to a semaphore, unlike ++ * the event flags. ++ */ ++ ++/** ++ * Create an event instance. ++ * ++ * @param event Filled in with constructed event. ++ * @param name Name of the event (for debugging) ++ * ++ * @return VCOS_SUCCESS on success, or error code. ++ */ ++VCOS_INLINE_DECL ++VCOS_STATUS_T vcos_event_create(VCOS_EVENT_T *event, const char *name); ++ ++#ifndef vcos_event_signal ++ ++/** ++ * Signal the event. The event will return to being unsignalled ++ * after exactly one waiting thread has been woken up. If no ++ * threads are waiting it remains signalled. ++ * ++ * @param event The event to signal ++ */ ++VCOS_INLINE_DECL ++void vcos_event_signal(VCOS_EVENT_T *event); ++ ++/** ++ * Wait for the event. ++ * ++ * @param event The event to wait for ++ * @return VCOS_SUCCESS on success, VCOS_EAGAIN if the wait was interrupted. ++ */ ++VCOS_INLINE_DECL ++VCOS_STATUS_T vcos_event_wait(VCOS_EVENT_T *event); ++ ++/** ++ * Try event, but don't block. ++ * ++ * @param event The event to try ++ * @return VCOS_SUCCESS on success, VCOS_EAGAIN if the event is not currently signalled ++ */ ++VCOS_INLINE_DECL ++VCOS_STATUS_T vcos_event_try(VCOS_EVENT_T *event); ++ ++#endif ++ ++/* ++ * Destroy an event. ++ */ ++VCOS_INLINE_DECL ++void vcos_event_delete(VCOS_EVENT_T *event); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif ++ ++ +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_event_flags.h b/drivers/misc/vc04_services/interface/vcos/vcos_event_flags.h +new file mode 100644 +index 0000000..9eee410 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_event_flags.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -23548,337 +24723,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_event_fla + +#endif + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_event.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_event.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_event.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_event.h 2012-07-15 20:29:13.501978585 +0200 -@@ -0,0 +1,108 @@ -+/* -+ * Copyright (c) 2010-2011 Broadcom. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+/*============================================================================= -+VideoCore OS Abstraction Layer - public header file for events -+=============================================================================*/ -+ -+#ifndef VCOS_EVENT_H -+#define VCOS_EVENT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include "interface/vcos/vcos_types.h" -+#include "vcos_platform.h" -+ -+/** -+ * \file -+ * -+ * An event is akin to the Win32 auto-reset event. -+ * -+ * -+ * Signalling an event will wake up one waiting thread only. Once one -+ * thread has been woken the event atomically returns to the unsignalled -+ * state. -+ * -+ * If no threads are waiting on the event when it is signalled it remains -+ * signalled. -+ * -+ * This is almost, but not quite, completely unlike the "event flags" -+ * object based on Nucleus event groups and ThreadX event flags. -+ * -+ * In particular, it should be similar in speed to a semaphore, unlike -+ * the event flags. -+ */ -+ -+/** -+ * Create an event instance. -+ * -+ * @param event Filled in with constructed event. -+ * @param name Name of the event (for debugging) -+ * -+ * @return VCOS_SUCCESS on success, or error code. -+ */ -+VCOS_INLINE_DECL -+VCOS_STATUS_T vcos_event_create(VCOS_EVENT_T *event, const char *name); -+ -+#ifndef vcos_event_signal -+ -+/** -+ * Signal the event. The event will return to being unsignalled -+ * after exactly one waiting thread has been woken up. If no -+ * threads are waiting it remains signalled. -+ * -+ * @param event The event to signal -+ */ -+VCOS_INLINE_DECL -+void vcos_event_signal(VCOS_EVENT_T *event); -+ -+/** -+ * Wait for the event. -+ * -+ * @param event The event to wait for -+ * @return VCOS_SUCCESS on success, VCOS_EAGAIN if the wait was interrupted. -+ */ -+VCOS_INLINE_DECL -+VCOS_STATUS_T vcos_event_wait(VCOS_EVENT_T *event); -+ -+/** -+ * Try event, but don't block. -+ * -+ * @param event The event to try -+ * @return VCOS_SUCCESS on success, VCOS_EAGAIN if the event is not currently signalled -+ */ -+VCOS_INLINE_DECL -+VCOS_STATUS_T vcos_event_try(VCOS_EVENT_T *event); -+ -+#endif -+ -+/* -+ * Destroy an event. -+ */ -+VCOS_INLINE_DECL -+void vcos_event_delete(VCOS_EVENT_T *event); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif -+ -+ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos.h 2012-07-15 20:29:13.554979584 +0200 -@@ -0,0 +1,212 @@ -+/* -+ * Copyright (c) 2010-2011 Broadcom. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+/*============================================================================= -+VideoCore OS Abstraction Layer - public header file -+=============================================================================*/ -+ -+/** -+ * \mainpage OS Abstraction Layer -+ * -+ * \section intro Introduction -+ * -+ * This abstraction layer is here to allow the underlying OS to be easily changed (e.g. from -+ * Nucleus to ThreadX) and to aid in porting host applications to new targets. -+ * -+ * \subsection error Error handling -+ * -+ * Wherever possible, VCOS functions assert internally and return void. The only exceptions -+ * are creation functions (which might fail due to lack of resources) and functions that -+ * might timeout or fail due to lack of space. Errors that might be reported by the underlying -+ * OS API (e.g. invalid mutex) are treated as a programming error, and are merely asserted on. -+ * -+ * \section thread_synch Threads and synchronisation -+ * -+ * \subsection thread Threads -+ * -+ * The thread API is somewhat different to that found in Nucleus. In particular, threads -+ * cannot just be destroyed at arbitrary times and nor can they merely exit. This is so -+ * that the same API can be implemented across all interesting platforms without too much -+ * difficulty. See vcos_thread.h for details. Thread attributes are configured via -+ * the VCOS_THREAD_ATTR_T structure, found in vcos_thread_attr.h. -+ * -+ * \subsection sema Semaphores -+ * -+ * Counted semaphores (c.f. Nucleus NU_SEMAPHORE) are created with VCOS_SEMAPHORE_T. -+ * Under ThreadX on VideoCore, semaphores are implemented using VideoCore spinlocks, and -+ * so are quite a lot faster than ordinary ThreadX semaphores. See vcos_semaphore.h. -+ * -+ * \subsection mtx Mutexes -+ * -+ * Mutexes are used for locking. Attempts to take a mutex twice, or to unlock it -+ * in a different thread to the one in which it was locked should be expected to fail. -+ * Mutexes are not re-entrant (see vcos_reentrant_mutex.h for a slightly slower -+ * re-entrant mutex). -+ * -+ * \subsection evflags Event flags -+ * -+ * Event flags (the ThreadX name - also known as event groups under Nucleus) provide -+ * 32 flags which can be waited on by multiple clients, and signalled by multiple clients. -+ * A timeout can be specified. See vcos_event_flags.h. An alternative to this is the -+ * VCOS_EVENT_T (see vcos_event.h) which is akin to the Win32 auto-reset event, or a -+ * saturating counted semaphore. -+ * -+ * \subsection event Events -+ * -+ * A VCOS_EVENT_T is a bit like a saturating semaphore. No matter how many times it -+ * is signalled, the waiter will only wake up once. See vcos_event.h. You might think this -+ * is useful if you suspect that the cost of reading the semaphore count (perhaps via a -+ * system call) is expensive on your platform. -+ * -+ * \subsection tls Thread local storage -+ * -+ * Thread local storage is supported using vcos_tls.h. This is emulated on Nucleus -+ * and ThreadX. -+ * -+ * \section int Interrupts -+ * -+ * The legacy LISR/HISR scheme found in Nucleus is supported via the legacy ISR API, -+ * which is also supported on ThreadX. New code should avoid this, and old code should -+ * be migrated away from it, since it is slow. See vcos_legacy_isr.h. -+ * -+ * Registering an interrupt handler, and disabling/restoring interrupts, is handled -+ * using the functions in vcos_isr.h. -+ * -+ */ -+ -+/** -+ * \file vcos.h -+ * -+ * This is the top level header file. Clients include this. It pulls in the platform-specific -+ * header file (vcos_platform.h) together with header files defining the expected APIs, such -+ * as vcos_mutex.h, vcos_semaphore.h, etc. It is also possible to include these header files -+ * directly. -+ * -+ */ -+ -+#ifndef VCOS_H -+#define VCOS_H -+ -+#include "interface/vcos/vcos_assert.h" -+#include "vcos_types.h" -+#include "vcos_platform.h" -+ -+#ifndef VCOS_INIT_H -+#include "interface/vcos/vcos_init.h" -+#endif -+ -+#ifndef VCOS_SEMAPHORE_H -+#include "interface/vcos/vcos_semaphore.h" -+#endif -+ -+#ifndef VCOS_THREAD_H -+#include "interface/vcos/vcos_thread.h" -+#endif -+ -+#ifndef VCOS_MUTEX_H -+#include "interface/vcos/vcos_mutex.h" -+#endif -+ -+#ifndef VCOS_MEM_H -+#include "interface/vcos/vcos_mem.h" -+#endif -+ -+#ifndef VCOS_LOGGING_H -+#include "interface/vcos/vcos_logging.h" -+#endif -+ -+#ifndef VCOS_STRING_H -+#include "interface/vcos/vcos_string.h" -+#endif -+ -+#ifndef VCOS_EVENT_H -+#include "interface/vcos/vcos_event.h" -+#endif -+ -+#ifndef VCOS_THREAD_ATTR_H -+#include "interface/vcos/vcos_thread_attr.h" -+#endif -+ -+#ifndef VCOS_TLS_H -+#include "interface/vcos/vcos_tls.h" -+#endif -+ -+#ifndef VCOS_REENTRANT_MUTEX_H -+#include "interface/vcos/vcos_reentrant_mutex.h" -+#endif -+ -+#ifndef VCOS_NAMED_SEMAPHORE_H -+#include "interface/vcos/vcos_named_semaphore.h" -+#endif -+ -+#ifndef VCOS_QUICKSLOW_MUTEX_H -+#include "interface/vcos/vcos_quickslow_mutex.h" -+#endif -+ -+/* Headers with predicates */ -+ -+#if VCOS_HAVE_EVENT_FLAGS -+#include "interface/vcos/vcos_event_flags.h" -+#endif -+ -+#if VCOS_HAVE_QUEUE -+#include "interface/vcos/vcos_queue.h" -+#endif -+ -+#if VCOS_HAVE_LEGACY_ISR -+#include "interface/vcos/vcos_legacy_isr.h" -+#endif -+ -+#if VCOS_HAVE_TIMER -+#include "interface/vcos/vcos_timer.h" -+#endif -+ -+#if VCOS_HAVE_MEMPOOL -+#include "interface/vcos/vcos_mempool.h" -+#endif -+ -+#if VCOS_HAVE_ISR -+#include "interface/vcos/vcos_isr.h" -+#endif -+ -+#if VCOS_HAVE_ATOMIC_FLAGS -+#include "interface/vcos/vcos_atomic_flags.h" -+#endif -+ -+#if VCOS_HAVE_ONCE -+#include "interface/vcos/vcos_once.h" -+#endif -+ -+#if VCOS_HAVE_BLOCK_POOL -+#include "interface/vcos/vcos_blockpool.h" -+#endif -+ -+#if VCOS_HAVE_FILE -+#include "interface/vcos/vcos_file.h" -+#endif -+ -+#if VCOS_HAVE_CFG -+#include "interface/vcos/vcos_cfg.h" -+#endif -+ -+#if VCOS_HAVE_CMD -+#include "interface/vcos/vcos_cmd.h" -+#endif -+ -+#endif /* VCOS_H */ -+ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_init.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_init.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_init.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_init.h 2012-07-15 20:29:13.607980580 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_init.h b/drivers/misc/vc04_services/interface/vcos/vcos_init.h +new file mode 100644 +index 0000000..9fc5eca +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_init.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -23934,9 +24783,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_init.h li +} +#endif + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_logging.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_logging.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_logging.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_logging.h 2012-07-15 20:29:13.516978868 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_logging.h b/drivers/misc/vc04_services/interface/vcos/vcos_logging.h +new file mode 100644 +index 0000000..9702822 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_logging.h @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -24228,9 +25079,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_logging.h +#endif /* VCOS_LOGGING_H */ + + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_lowlevel_thread.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_lowlevel_thread.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_lowlevel_thread.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_lowlevel_thread.h 2012-07-15 20:29:13.599980430 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_lowlevel_thread.h b/drivers/misc/vc04_services/interface/vcos/vcos_lowlevel_thread.h +new file mode 100644 +index 0000000..9473cec +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_lowlevel_thread.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -24350,9 +25203,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_lowlevel_ +#endif +#endif + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_mem.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_mem.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_mem.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_mem.h 2012-07-15 20:29:13.599980430 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_mem.h b/drivers/misc/vc04_services/interface/vcos/vcos_mem.h +new file mode 100644 +index 0000000..af16208 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_mem.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -24446,9 +25301,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_mem.h lin +#endif + + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_msgqueue.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_msgqueue.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_msgqueue.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_msgqueue.h 2012-07-15 20:29:13.600980449 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_msgqueue.h b/drivers/misc/vc04_services/interface/vcos/vcos_msgqueue.h +new file mode 100644 +index 0000000..f0ef70b +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_msgqueue.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -24618,9 +25475,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_msgqueue. +#endif + + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_mutex.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_mutex.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_mutex.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_mutex.h 2012-07-15 20:29:13.501978585 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_mutex.h b/drivers/misc/vc04_services/interface/vcos/vcos_mutex.h +new file mode 100644 +index 0000000..14387a8 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_mutex.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -24725,9 +25584,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_mutex.h l +} +#endif +#endif -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_once.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_once.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_once.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_once.h 2012-07-15 20:29:13.597980392 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_once.h b/drivers/misc/vc04_services/interface/vcos/vcos_once.h +new file mode 100644 +index 0000000..0533c10 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_once.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -24782,9 +25643,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_once.h li +#endif +#endif + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_semaphore.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_semaphore.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_semaphore.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_semaphore.h 2012-07-15 20:29:13.597980392 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_semaphore.h b/drivers/misc/vc04_services/interface/vcos/vcos_semaphore.h +new file mode 100644 +index 0000000..2760dd7 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_semaphore.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -24912,9 +25775,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_semaphore +#endif +#endif + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_stdbool.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_stdbool.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_stdbool.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_stdbool.h 2012-07-15 20:29:13.609980618 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_stdbool.h b/drivers/misc/vc04_services/interface/vcos/vcos_stdbool.h +new file mode 100644 +index 0000000..3c7669d +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_stdbool.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -24950,9 +25815,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_stdbool.h +#endif /* __cplusplus */ + +#endif -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_stdint.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_stdint.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_stdint.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_stdint.h 2012-07-15 20:29:13.600980449 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_stdint.h b/drivers/misc/vc04_services/interface/vcos/vcos_stdint.h +new file mode 100644 +index 0000000..c9a3e02 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_stdint.h @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -25157,9 +26024,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_stdint.h +#endif /* VCOS_STDINT_H */ + + -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_string.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_string.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_string.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_string.h 2012-07-15 20:29:13.598980411 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_string.h b/drivers/misc/vc04_services/interface/vcos/vcos_string.h +new file mode 100644 +index 0000000..c3d875f +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_string.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -25245,100 +26114,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_string.h +} +#endif +#endif -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_thread_attr.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_thread_attr.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_thread_attr.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_thread_attr.h 2012-07-15 20:29:13.554979584 +0200 -@@ -0,0 +1,87 @@ -+/* -+ * Copyright (c) 2010-2011 Broadcom. All rights reserved. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+/*============================================================================= -+VideoCore OS Abstraction Layer - thread attributes -+=============================================================================*/ -+ -+#ifndef VCOS_THREAD_ATTR_H -+#define VCOS_THREAD_ATTR_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** -+ * \file -+ * -+ * Attributes for thread creation. -+ * -+ */ -+ -+/** Initialize thread attribute struct. This call does not allocate memory, -+ * and so cannot fail. -+ * -+ */ -+VCOSPRE_ void VCOSPOST_ vcos_thread_attr_init(VCOS_THREAD_ATTR_T *attrs); -+ -+/** Set the stack address and size. If not set, a stack will be allocated automatically. -+ * -+ * This can only be set on some platforms. It will always be possible to set the stack -+ * address on VideoCore, but on host platforms, support may well not be available. -+ */ -+#if VCOS_CAN_SET_STACK_ADDR -+VCOS_INLINE_DECL -+void vcos_thread_attr_setstack(VCOS_THREAD_ATTR_T *attrs, void *addr, VCOS_UNSIGNED sz); -+#endif -+ -+/** Set the stack size. If not set, a default size will be used. Attempting to call this after having -+ * set the stack location with vcos_thread_attr_setstack() will result in undefined behaviour. -+ */ -+VCOS_INLINE_DECL -+void vcos_thread_attr_setstacksize(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED sz); -+ -+/** Set the task priority. If not set, a default value will be used. -+ */ -+VCOS_INLINE_DECL -+void vcos_thread_attr_setpriority(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED pri); -+ -+/** Set the task cpu affinity. If not set, the default will be used. -+ */ -+VCOS_INLINE_DECL -+void vcos_thread_attr_setaffinity(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED aff); -+ -+/** Set the timeslice. If not set the default will be used. -+ */ -+VCOS_INLINE_DECL -+void vcos_thread_attr_settimeslice(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED ts); -+ -+/** The thread entry function takes (argc,argv), as per Nucleus, with -+ * argc being 0. This may be withdrawn in a future release and should not -+ * be used in new code. -+ */ -+VCOS_INLINE_DECL -+void _vcos_thread_attr_setlegacyapi(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED legacy); -+ -+VCOS_INLINE_DECL -+void vcos_thread_attr_setautostart(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED autostart); -+ -+#ifdef __cplusplus -+} -+#endif -+#endif -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_thread.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_thread.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_thread.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_thread.h 2012-07-15 20:29:13.599980430 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_thread.h b/drivers/misc/vc04_services/interface/vcos/vcos_thread.h +new file mode 100644 +index 0000000..ee34648 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_thread.h @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -25610,9 +26390,104 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_thread.h +} +#endif +#endif -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_timer.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_timer.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_timer.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_timer.h 2012-07-15 20:29:13.599980430 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_thread_attr.h b/drivers/misc/vc04_services/interface/vcos/vcos_thread_attr.h +new file mode 100644 +index 0000000..375dd01 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_thread_attr.h +@@ -0,0 +1,87 @@ ++/* ++ * Copyright (c) 2010-2011 Broadcom. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++/*============================================================================= ++VideoCore OS Abstraction Layer - thread attributes ++=============================================================================*/ ++ ++#ifndef VCOS_THREAD_ATTR_H ++#define VCOS_THREAD_ATTR_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** ++ * \file ++ * ++ * Attributes for thread creation. ++ * ++ */ ++ ++/** Initialize thread attribute struct. This call does not allocate memory, ++ * and so cannot fail. ++ * ++ */ ++VCOSPRE_ void VCOSPOST_ vcos_thread_attr_init(VCOS_THREAD_ATTR_T *attrs); ++ ++/** Set the stack address and size. If not set, a stack will be allocated automatically. ++ * ++ * This can only be set on some platforms. It will always be possible to set the stack ++ * address on VideoCore, but on host platforms, support may well not be available. ++ */ ++#if VCOS_CAN_SET_STACK_ADDR ++VCOS_INLINE_DECL ++void vcos_thread_attr_setstack(VCOS_THREAD_ATTR_T *attrs, void *addr, VCOS_UNSIGNED sz); ++#endif ++ ++/** Set the stack size. If not set, a default size will be used. Attempting to call this after having ++ * set the stack location with vcos_thread_attr_setstack() will result in undefined behaviour. ++ */ ++VCOS_INLINE_DECL ++void vcos_thread_attr_setstacksize(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED sz); ++ ++/** Set the task priority. If not set, a default value will be used. ++ */ ++VCOS_INLINE_DECL ++void vcos_thread_attr_setpriority(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED pri); ++ ++/** Set the task cpu affinity. If not set, the default will be used. ++ */ ++VCOS_INLINE_DECL ++void vcos_thread_attr_setaffinity(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED aff); ++ ++/** Set the timeslice. If not set the default will be used. ++ */ ++VCOS_INLINE_DECL ++void vcos_thread_attr_settimeslice(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED ts); ++ ++/** The thread entry function takes (argc,argv), as per Nucleus, with ++ * argc being 0. This may be withdrawn in a future release and should not ++ * be used in new code. ++ */ ++VCOS_INLINE_DECL ++void _vcos_thread_attr_setlegacyapi(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED legacy); ++ ++VCOS_INLINE_DECL ++void vcos_thread_attr_setautostart(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED autostart); ++ ++#ifdef __cplusplus ++} ++#endif ++#endif +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_timer.h b/drivers/misc/vc04_services/interface/vcos/vcos_timer.h +new file mode 100644 +index 0000000..1612334 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_timer.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -25720,9 +26595,11 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_timer.h l +} +#endif +#endif -diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_types.h linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_types.h ---- linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_types.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_types.h 2012-07-15 20:29:13.497978511 +0200 +diff --git a/drivers/misc/vc04_services/interface/vcos/vcos_types.h b/drivers/misc/vc04_services/interface/vcos/vcos_types.h +new file mode 100644 +index 0000000..25de671 +--- /dev/null ++++ b/drivers/misc/vc04_services/interface/vcos/vcos_types.h @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2010-2011 Broadcom. All rights reserved. @@ -25935,46 +26812,24 @@ diff -Naur linux-3.2.23/drivers/misc/vc04_services/interface/vcos/vcos_types.h l +typedef vcos_fourcc_t FOURCC_T; + +#endif -diff -Naur linux-3.2.23/drivers/misc/vc04_services/Kconfig linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/Kconfig ---- linux-3.2.23/drivers/misc/vc04_services/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/Kconfig 2012-07-15 20:29:13.762983497 +0200 -@@ -0,0 +1,7 @@ -+config BCM2708_VCHIQ -+ tristate "Videocore VCHIQ" -+ depends on MACH_BCM2708 -+ default y -+ help -+ Helper for communication for VideoCore. -+ -diff -Naur linux-3.2.23/drivers/misc/vc04_services/Makefile linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/Makefile ---- linux-3.2.23/drivers/misc/vc04_services/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/misc/vc04_services/Makefile 2012-07-15 20:29:13.762983497 +0200 -@@ -0,0 +1,21 @@ -+obj-$(CONFIG_BCM2708_VCHIQ) += vchiq.o -+ -+vchiq-objs := \ -+ interface/vchiq_arm/vchiq_core.o \ -+ interface/vchiq_arm/vchiq_shim.o \ -+ interface/vchiq_arm/vchiq_util.o \ -+ interface/vchiq_arm/vchiq_arm.o \ -+ interface/vchiq_arm/vchiq_kern_lib.o \ -+ interface/vchiq_arm/vchiq_2835_arm.o \ -+ interface/vcos/linuxkernel/vcos_linuxkernel.o \ -+ interface/vcos/linuxkernel/vcos_thread_map.o \ -+ interface/vcos/linuxkernel/vcos_linuxkernel_cfg.o \ -+ interface/vcos/generic/vcos_generic_event_flags.o \ -+ interface/vcos/generic/vcos_logcat.o \ -+ interface/vcos/generic/vcos_mem_from_malloc.o \ -+ interface/vcos/generic/vcos_cmd.o -+ -+EXTRA_CFLAGS += -DVCOS_VERIFY_BKPTS=1 -DUSE_VCHIQ_ARM -D__VCCOREVER__=0x04000000 -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -+ -+ -+ -diff -Naur linux-3.2.23/drivers/mmc/core/core.c linux-rpi-bootc-3.2.23/drivers/mmc/core/core.c ---- linux-3.2.23/drivers/mmc/core/core.c 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/mmc/core/core.c 2012-07-15 20:29:21.657132039 +0200 -@@ -514,10 +514,14 @@ +diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c +index 34416d4..13cde4a 100644 +--- a/drivers/mmc/card/block.c ++++ b/drivers/mmc/card/block.c +@@ -1075,7 +1075,7 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, + brq->data.blocks = 1; + } + +- if (brq->data.blocks > 1 || do_rel_wr) { ++ if (brq->data.blocks > 1 || do_rel_wr || card->host->caps2 & MMC_CAP2_FORCE_MULTIBLOCK) { + /* SPI multiblock writes terminate using a special + * token, not a STOP_TRANSMISSION request. + */ +diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c +index 411a994..ad08933 100644 +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -514,10 +514,14 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) if (data->flags & MMC_DATA_WRITE) /* @@ -25992,9 +26847,78 @@ diff -Naur linux-3.2.23/drivers/mmc/core/core.c linux-rpi-bootc-3.2.23/drivers/m else limit_us = 100000; -diff -Naur linux-3.2.23/drivers/mmc/host/bcm2708_mci.c linux-rpi-bootc-3.2.23/drivers/mmc/host/bcm2708_mci.c ---- linux-3.2.23/drivers/mmc/host/bcm2708_mci.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/mmc/host/bcm2708_mci.c 2012-07-15 20:29:21.578130550 +0200 +diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig +index cf444b0..f8feea6 100644 +--- a/drivers/mmc/host/Kconfig ++++ b/drivers/mmc/host/Kconfig +@@ -229,6 +229,27 @@ config MMC_SDHCI_S3C_DMA + + YMMV. + ++config MMC_SDHCI_BCM2708 ++ tristate "SDHCI support on BCM2708" ++ depends on MMC_SDHCI && MACH_BCM2708 ++ select MMC_SDHCI_IO_ACCESSORS ++ help ++ This selects the Secure Digital Host Controller Interface (SDHCI) ++ often referrered to as the eMMC block. ++ ++ If you have a controller with this interface, say Y or M here. ++ ++ If unsure, say N. ++ ++config MMC_SDHCI_BCM2708_DMA ++ bool "DMA support on BCM2708 Arasan controller" ++ depends on MMC_SDHCI_BCM2708 && EXPERIMENTAL ++ help ++ Enable DMA support on the Arasan SDHCI controller in Broadcom 2708 ++ based chips. ++ ++ If unsure, say N. ++ + config MMC_OMAP + tristate "TI OMAP Multimedia Card Interface support" + depends on ARCH_OMAP +@@ -296,6 +317,14 @@ config MMC_ATMELMCI + If unsure, say N. + + endchoice ++config MMC_BCM2708 ++ tristate "BCM2708 Multimedia Card Interface support" ++ help ++ This selects the BCM2708 Multimedia Card Interface driver. If ++ you have a BCM2708 platform with a Multimedia Card ++ slot, say Y or M here. ++ ++ If unsure, say N. + + config MMC_ATMELMCI_DMA + bool "Atmel MCI DMA support" +diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile +index b4b83f3..eeb683c 100644 +--- a/drivers/mmc/host/Makefile ++++ b/drivers/mmc/host/Makefile +@@ -13,6 +13,7 @@ obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o + obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o + obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o + obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o ++obj-$(CONFIG_MMC_SDHCI_BCM2708) += sdhci-bcm2708.o + obj-$(CONFIG_MMC_WBSD) += wbsd.o + obj-$(CONFIG_MMC_AU1X) += au1xmmc.o + obj-$(CONFIG_MMC_OMAP) += omap.o +@@ -36,6 +37,7 @@ tmio_mmc_core-$(subst m,y,$(CONFIG_MMC_SDHI)) += tmio_mmc_dma.o + obj-$(CONFIG_MMC_SDHI) += sh_mobile_sdhi.o + obj-$(CONFIG_MMC_CB710) += cb710-mmc.o + obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o ++obj-$(CONFIG_MMC_BCM2708) += bcm2708_mci.o + obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o + obj-$(CONFIG_MMC_DW) += dw_mmc.o + obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o +diff --git a/drivers/mmc/host/bcm2708_mci.c b/drivers/mmc/host/bcm2708_mci.c +new file mode 100644 +index 0000000..3c7de96 +--- /dev/null ++++ b/drivers/mmc/host/bcm2708_mci.c @@ -0,0 +1,889 @@ +/* + * linux/drivers/mmc/host/bcm2708_mci.c - Broadcom BCM2708 MCI driver @@ -26885,9 +27809,11 @@ diff -Naur linux-3.2.23/drivers/mmc/host/bcm2708_mci.c linux-rpi-bootc-3.2.23/dr +MODULE_DESCRIPTION("BCM2708 Multimedia Card Interface driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:bcm2708_mci"); -diff -Naur linux-3.2.23/drivers/mmc/host/bcm2708_mci.h linux-rpi-bootc-3.2.23/drivers/mmc/host/bcm2708_mci.h ---- linux-3.2.23/drivers/mmc/host/bcm2708_mci.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/mmc/host/bcm2708_mci.h 2012-07-15 20:29:21.556130136 +0200 +diff --git a/drivers/mmc/host/bcm2708_mci.h b/drivers/mmc/host/bcm2708_mci.h +new file mode 100644 +index 0000000..b2851d9 +--- /dev/null ++++ b/drivers/mmc/host/bcm2708_mci.h @@ -0,0 +1,101 @@ +/* + * linux/drivers/mmc/host/bcm2708_mci.c - Broadcom BCM2708 MCI driver @@ -26990,75 +27916,12 @@ diff -Naur linux-3.2.23/drivers/mmc/host/bcm2708_mci.h linux-rpi-bootc-3.2.23/dr + kunmap_atomic(buffer, KM_BIO_SRC_IRQ); +// local_irq_restore(*flags); +} -diff -Naur linux-3.2.23/drivers/mmc/host/Kconfig linux-rpi-bootc-3.2.23/drivers/mmc/host/Kconfig ---- linux-3.2.23/drivers/mmc/host/Kconfig 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/mmc/host/Kconfig 2012-07-15 20:29:21.572130435 +0200 -@@ -229,6 +229,27 @@ - - YMMV. - -+config MMC_SDHCI_BCM2708 -+ tristate "SDHCI support on BCM2708" -+ depends on MMC_SDHCI && MACH_BCM2708 -+ select MMC_SDHCI_IO_ACCESSORS -+ help -+ This selects the Secure Digital Host Controller Interface (SDHCI) -+ often referrered to as the eMMC block. -+ -+ If you have a controller with this interface, say Y or M here. -+ -+ If unsure, say N. -+ -+config MMC_SDHCI_BCM2708_DMA -+ bool "DMA support on BCM2708 Arasan controller" -+ depends on MMC_SDHCI_BCM2708 && EXPERIMENTAL -+ help -+ Enable DMA support on the Arasan SDHCI controller in Broadcom 2708 -+ based chips. -+ -+ If unsure, say N. -+ - config MMC_OMAP - tristate "TI OMAP Multimedia Card Interface support" - depends on ARCH_OMAP -@@ -296,6 +317,14 @@ - If unsure, say N. - - endchoice -+config MMC_BCM2708 -+ tristate "BCM2708 Multimedia Card Interface support" -+ help -+ This selects the BCM2708 Multimedia Card Interface driver. If -+ you have a BCM2708 platform with a Multimedia Card -+ slot, say Y or M here. -+ -+ If unsure, say N. - - config MMC_ATMELMCI_DMA - bool "Atmel MCI DMA support" -diff -Naur linux-3.2.23/drivers/mmc/host/Makefile linux-rpi-bootc-3.2.23/drivers/mmc/host/Makefile ---- linux-3.2.23/drivers/mmc/host/Makefile 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/mmc/host/Makefile 2012-07-15 20:29:21.525129552 +0200 -@@ -13,6 +13,7 @@ - obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o - obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o - obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o -+obj-$(CONFIG_MMC_SDHCI_BCM2708) += sdhci-bcm2708.o - obj-$(CONFIG_MMC_WBSD) += wbsd.o - obj-$(CONFIG_MMC_AU1X) += au1xmmc.o - obj-$(CONFIG_MMC_OMAP) += omap.o -@@ -36,6 +37,7 @@ - obj-$(CONFIG_MMC_SDHI) += sh_mobile_sdhi.o - obj-$(CONFIG_MMC_CB710) += cb710-mmc.o - obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o -+obj-$(CONFIG_MMC_BCM2708) += bcm2708_mci.o - obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o - obj-$(CONFIG_MMC_DW) += dw_mmc.o - obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o -diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/drivers/mmc/host/sdhci-bcm2708.c ---- linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/mmc/host/sdhci-bcm2708.c 2012-07-15 20:29:21.576130512 +0200 -@@ -0,0 +1,1477 @@ +diff --git a/drivers/mmc/host/sdhci-bcm2708.c b/drivers/mmc/host/sdhci-bcm2708.c +new file mode 100644 +index 0000000..2703103 +--- /dev/null ++++ b/drivers/mmc/host/sdhci-bcm2708.c +@@ -0,0 +1,1532 @@ +/* + * sdhci-bcm2708.c Support for SDHCI device on BCM2708 + * Copyright (c) 2010 Broadcom @@ -27087,7 +27950,9 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ +#include +#include +#include ++#include +#include ++#include + +#include +#include @@ -27111,7 +27976,6 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ +#undef CONFIG_MMC_SDHCI_BCM2708_DMA +#define CONFIG_MMC_SDHCI_BCM2708_DMA y + -+#define USE_SYNC_AFTER_DMA +#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA +/* #define CHECK_DMA_USE */ +#endif @@ -27139,6 +28003,8 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ +#define POWER_LAZY_OFF 1 +#define POWER_ON 2 + ++#define REG_EXRDFIFO_EN 0x80 ++#define REG_EXRDFIFO_CFG 0x84 + +/*****************************************************************************\ + * * @@ -27196,6 +28062,9 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ + +static bool allow_highspeed = 1; +static int emmc_clock_freq = BCM2708_EMMC_CLOCK_FREQ; ++static bool sync_after_dma = 1; ++static bool missing_status = 1; ++bool enable_llm = 1; + +#if 0 +static void hptime_test(void) @@ -27292,7 +28161,12 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ + +static void sdhci_bcm2708_raw_writel(struct sdhci_host *host, u32 val, int reg) +{ ++ u32 ier; ++ +#if USE_SPACED_WRITES_2CLK ++ static bool timeout_disabled = false; ++ unsigned int ns_2clk = 0; ++ + /* The Arasan has a bugette whereby it may lose the content of + * successive writes to registers that are within two SD-card clock + * cycles of each other (a clock domain crossing problem). @@ -27304,7 +28178,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ + /* host->clock is the clock freq in Hz */ + static hptime_t last_write_hpt; + hptime_t now = hptime(); -+ unsigned int ns_2clk = 2000000000/host->clock; ++ ns_2clk = 2000000000/host->clock; + + if (now == last_write_hpt || now == last_write_hpt+1) { + /* we can't guarantee any significant time has @@ -27320,6 +28194,27 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ + } + last_write_hpt = now; + } ++#if USE_SOFTWARE_TIMEOUTS ++ /* The Arasan is clocked for timeouts using the SD clock which is too ++ * fast for ERASE commands and causes issues. So we disable timeouts ++ * for ERASE */ ++ if (host->cmd != NULL && host->cmd->opcode == MMC_ERASE && ++ reg == (SDHCI_COMMAND & ~3)) { ++ mod_timer(&host->timer, ++ jiffies + SOFTWARE_ERASE_TIMEOUT_SEC * HZ); ++ ier = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE); ++ ier &= ~SDHCI_INT_DATA_TIMEOUT; ++ writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE); ++ timeout_disabled = true; ++ ndelay(ns_2clk); ++ } else if (timeout_disabled) { ++ ier = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE); ++ ier |= SDHCI_INT_DATA_TIMEOUT; ++ writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE); ++ timeout_disabled = false; ++ ndelay(ns_2clk); ++ } ++#endif + writel(val, host->ioaddr + reg); +#else + void __iomem * regaddr = host->ioaddr + reg; @@ -27682,11 +28577,11 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ +sdhci_bcm2708_platdma_reset(struct sdhci_host *host, struct mmc_data *data) +{ + struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); -+ unsigned long flags; ++// unsigned long flags; + + BUG_ON(NULL == host); + -+ spin_lock_irqsave(&host->lock, flags); ++// spin_lock_irqsave(&host->lock, flags); + + if (host_priv->dma_wanted) { + if (NULL == data) { @@ -27766,7 +28661,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ +#endif + } + -+ spin_unlock_irqrestore(&host->lock, flags); ++// spin_unlock_irqrestore(&host->lock, flags); +} + + @@ -27779,11 +28674,11 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ + int sg_len; + int sg_ix; + int sg_todo; -+ unsigned long flags; ++// unsigned long flags; + + BUG_ON(NULL == host); + -+ spin_lock_irqsave(&host->lock, flags); ++// spin_lock_irqsave(&host->lock, flags); + data = host->data; + +#ifdef CHECK_DMA_USE @@ -27808,7 +28703,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ + + if (NULL == data) { + DBG("PDMA unused completion - status 0x%X\n", dma_cs); -+ spin_unlock_irqrestore(&host->lock, flags); ++// spin_unlock_irqrestore(&host->lock, flags); + return; + } + sg = data->sg; @@ -27865,34 +28760,34 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ + SDHCI_INT_SPACE_AVAIL); + } + } else { -+#ifdef USE_SYNC_AFTER_DMA -+ /* On the Arasan controller the stop command (which will be -+ scheduled after this completes) does not seem to work -+ properly if we allow it to be issued when we are -+ transferring data to/from the SD card. -+ We get CRC and DEND errors unless we wait for -+ the SD controller to finish reading/writing to the card. */ -+ u32 state_mask; -+ int timeout=5000; ++ if (sync_after_dma) { ++ /* On the Arasan controller the stop command (which will be ++ scheduled after this completes) does not seem to work ++ properly if we allow it to be issued when we are ++ transferring data to/from the SD card. ++ We get CRC and DEND errors unless we wait for ++ the SD controller to finish reading/writing to the card. */ ++ u32 state_mask; ++ int timeout=30*5000; + -+ DBG("PDMA over - sync card\n"); -+ if (data->flags & MMC_DATA_READ) -+ state_mask = SDHCI_DOING_READ; -+ else -+ state_mask = SDHCI_DOING_WRITE; ++ DBG("PDMA over - sync card\n"); ++ if (data->flags & MMC_DATA_READ) ++ state_mask = SDHCI_DOING_READ; ++ else ++ state_mask = SDHCI_DOING_WRITE; + -+ while (0 != (sdhci_bcm2708_raw_readl(host, SDHCI_PRESENT_STATE) -+ & state_mask) && --timeout > 0) -+ { -+ udelay(30); -+ continue; ++ while (0 != (sdhci_bcm2708_raw_readl(host, SDHCI_PRESENT_STATE) ++ & state_mask) && --timeout > 0) ++ { ++ udelay(1); ++ continue; ++ } ++ if (timeout <= 0) ++ printk(KERN_ERR"%s: final %s to SD card still " ++ "running\n", ++ mmc_hostname(host->mmc), ++ data->flags & MMC_DATA_READ? "read": "write"); + } -+ if (timeout <= 0) -+ printk(KERN_ERR"%s: final %s to SD card still " -+ "running\n", -+ mmc_hostname(host->mmc), -+ data->flags & MMC_DATA_READ? "read": "write"); -+#endif + if (host_priv->complete) { + (*host_priv->complete)(host); + DBG("PDMA %s complete\n", @@ -27901,7 +28796,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ + SDHCI_INT_SPACE_AVAIL); + } + } -+ spin_unlock_irqrestore(&host->lock, flags); ++// spin_unlock_irqrestore(&host->lock, flags); +} + +static irqreturn_t sdhci_bcm2708_dma_irq(int irq, void *dev_id) @@ -27910,12 +28805,11 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ + struct sdhci_host *host = dev_id; + struct sdhci_bcm2708_priv *host_priv = SDHCI_HOST_PRIV(host); + u32 dma_cs; /* control and status register */ -+ unsigned long flags; + + BUG_ON(NULL == dev_id); + BUG_ON(NULL == host_priv->dma_chan_base); + -+ spin_lock_irqsave(&host->lock, flags); ++ sdhci_spin_lock(host); + + dma_cs = readl(host_priv->dma_chan_base + BCM2708_DMA_CS); + @@ -27956,8 +28850,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ + + result = IRQ_HANDLED; + } -+ -+ spin_unlock_irqrestore(&host->lock, flags); ++ sdhci_spin_unlock(host); + + return result; +} @@ -28000,10 +28893,12 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ + int on = simple_strtol(buf, NULL, 0); + if (on) { + host->flags |= SDHCI_USE_PLATDMA; ++ sdhci_bcm2708_writel(host, 1, REG_EXRDFIFO_EN); + printk(KERN_INFO "%s: DMA enabled\n", + mmc_hostname(host->mmc)); + } else { + host->flags &= ~(SDHCI_USE_PLATDMA | SDHCI_REQ_USE_DMA); ++ sdhci_bcm2708_writel(host, 0, REG_EXRDFIFO_EN); + printk(KERN_INFO "%s: DMA disabled\n", + mmc_hostname(host->mmc)); + } @@ -28300,7 +29195,6 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ + .spurious_crc_acmd51 = sdhci_bcm2708_quirk_spurious_crc, + .voltage_broken = sdhci_bcm2708_quirk_voltage_broken, + .uhs_broken = sdhci_bcm2708_uhs_broken, -+ .missing_status = sdhci_bcm2708_missing_status, +}; + +/*****************************************************************************\ @@ -28339,16 +29233,24 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ + ret = PTR_ERR(host); + goto err; + } ++ if (missing_status) { ++ sdhci_bcm2708_ops.missing_status = sdhci_bcm2708_missing_status; ++ } ++ ++ printk("sdhci: %s low-latency mode\n",enable_llm?"Enable":"Disable"); + + host->hw_name = "BCM2708_Arasan"; + host->ops = &sdhci_bcm2708_ops; + host->irq = platform_get_irq(pdev, 0); ++ host->second_irq = 0; + + host->quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION | + SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | + SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | + SDHCI_QUIRK_MISSING_CAPS | -+ SDHCI_QUIRK_NO_HISPD_BIT; ++ SDHCI_QUIRK_NO_HISPD_BIT | ++ (sync_after_dma ? 0:SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12); ++ + +#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA + host->flags = SDHCI_USE_PLATDMA; @@ -28406,12 +29308,13 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ + } + host_priv->dma_chan = ret; + -+ ret = request_irq(host_priv->dma_irq, sdhci_bcm2708_dma_irq, -+ IRQF_SHARED, DRIVER_NAME " (dma)", host); ++ ret = request_irq(host_priv->dma_irq, sdhci_bcm2708_dma_irq,0,//IRQF_SHARED, ++ DRIVER_NAME " (dma)", host); + if (ret) { + dev_err(&pdev->dev, "cannot set DMA IRQ\n"); + goto err_add_dma_irq; + } ++ host->second_irq = host_priv->dma_irq; + DBG("DMA CBs %p handle %08X DMA%d %p DMA IRQ %d\n", + host_priv->cb_base, (unsigned)host_priv->cb_handle, + host_priv->dma_chan, host_priv->dma_chan_base, @@ -28419,6 +29322,9 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ + + if (allow_highspeed) + host->mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; ++ ++ /* single block writes cause data loss with some SD cards! */ ++ host->mmc->caps2 |= MMC_CAP2_FORCE_MULTIBLOCK; +#endif + + ret = sdhci_add_host(host); @@ -28430,6 +29336,12 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ + ret = device_create_file(&pdev->dev, &dev_attr_dma_wait); + ret = device_create_file(&pdev->dev, &dev_attr_status); + ++#ifdef CONFIG_MMC_SDHCI_BCM2708_DMA ++ /* enable extension fifo for paced DMA transfers */ ++ sdhci_bcm2708_writel(host, 1, REG_EXRDFIFO_EN); ++ sdhci_bcm2708_writel(host, 4, REG_EXRDFIFO_CFG); ++#endif ++ + printk(KERN_INFO "%s: BCM2708 SDHC host at 0x%08llx DMA %d IRQ %d\n", + mmc_hostname(host->mmc), (unsigned long long)iomem->start, + host_priv->dma_chan, host_priv->dma_irq); @@ -28526,6 +29438,9 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ + +module_param(allow_highspeed, bool, 0444); +module_param(emmc_clock_freq, int, 0444); ++module_param(sync_after_dma, bool, 0444); ++module_param(missing_status, bool, 0444); ++module_param(enable_llm, bool, 0444); + +MODULE_DESCRIPTION("Secure Digital Host Controller Interface platform driver"); +MODULE_AUTHOR("Broadcom "); @@ -28534,11 +29449,15 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci-bcm2708.c linux-rpi-bootc-3.2.23/ + +MODULE_PARM_DESC(allow_highspeed, "Allow high speed transfers modes"); +MODULE_PARM_DESC(emmc_clock_freq, "Specify the speed of emmc clock"); ++MODULE_PARM_DESC(sync_after_dma, "Block in driver until dma complete"); ++MODULE_PARM_DESC(missing_status, "Use the missing status quirk"); ++MODULE_PARM_DESC(enable_llm, "Enable low-latency mode"); + + -diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/mmc/host/sdhci.c ---- linux-3.2.23/drivers/mmc/host/sdhci.c 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/mmc/host/sdhci.c 2012-07-15 20:29:21.558130173 +0200 +diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c +index 6ce32a7..0562295 100644 +--- a/drivers/mmc/host/sdhci.c ++++ b/drivers/mmc/host/sdhci.c @@ -27,6 +27,7 @@ #include @@ -28547,7 +29466,127 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ #include "sdhci.h" -@@ -296,7 +297,7 @@ +@@ -120,6 +121,91 @@ static void sdhci_dumpregs(struct sdhci_host *host) + * Low level functions * + * * + \*****************************************************************************/ ++extern bool enable_llm; ++static int sdhci_locked=0; ++void sdhci_spin_lock(struct sdhci_host *host) ++{ ++ spin_lock(&host->lock); ++#ifdef CONFIG_PREEMPT ++ if(enable_llm) ++ { ++ disable_irq_nosync(host->irq); ++ if(host->second_irq) ++ disable_irq_nosync(host->second_irq); ++ local_irq_enable(); ++ } ++#endif ++} ++ ++void sdhci_spin_unlock(struct sdhci_host *host) ++{ ++#ifdef CONFIG_PREEMPT ++ if(enable_llm) ++ { ++ local_irq_disable(); ++ enable_irq(host->irq); ++ if(host->second_irq) ++ enable_irq(host->second_irq); ++ } ++#endif ++ spin_unlock(&host->lock); ++} ++ ++void sdhci_spin_lock_irqsave(struct sdhci_host *host,unsigned long *flags) ++{ ++#ifdef CONFIG_PREEMPT ++ if(enable_llm) ++ { ++ while(sdhci_locked) ++ { ++ preempt_schedule(); ++ } ++ spin_lock_irqsave(&host->lock,*flags); ++ disable_irq(host->irq); ++ if(host->second_irq) ++ disable_irq(host->second_irq); ++ local_irq_enable(); ++ } ++ else ++#endif ++ spin_lock_irqsave(&host->lock,*flags); ++} ++ ++void sdhci_spin_unlock_irqrestore(struct sdhci_host *host,unsigned long flags) ++{ ++#ifdef CONFIG_PREEMPT ++ if(enable_llm) ++ { ++ local_irq_disable(); ++ enable_irq(host->irq); ++ if(host->second_irq) ++ enable_irq(host->second_irq); ++ } ++#endif ++ spin_unlock_irqrestore(&host->lock,flags); ++} ++ ++static void sdhci_spin_enable_schedule(struct sdhci_host *host) ++{ ++#ifdef CONFIG_PREEMPT ++ if(enable_llm) ++ { ++ sdhci_locked = 1; ++ preempt_enable(); ++ } ++#endif ++} ++ ++static void sdhci_spin_disable_schedule(struct sdhci_host *host) ++{ ++#ifdef CONFIG_PREEMPT ++ if(enable_llm) ++ { ++ preempt_disable(); ++ sdhci_locked = 0; ++ } ++#endif ++} + + static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set) + { +@@ -206,7 +292,9 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask) + return; + } + timeout--; ++ sdhci_spin_enable_schedule(host); + mdelay(1); ++ sdhci_spin_disable_schedule(host); + } + + if (host->ops->platform_reset_exit) +@@ -269,7 +357,7 @@ static void sdhci_led_control(struct led_classdev *led, + struct sdhci_host *host = container_of(led, struct sdhci_host, led); + unsigned long flags; + +- spin_lock_irqsave(&host->lock, flags); ++ sdhci_spin_lock_irqsave(host, &flags); + + if (host->runtime_suspended) + goto out; +@@ -279,7 +367,7 @@ static void sdhci_led_control(struct led_classdev *led, + else + sdhci_activate_led(host); + out: +- spin_unlock_irqrestore(&host->lock, flags); ++ sdhci_spin_unlock_irqrestore(host, flags); + } + #endif + +@@ -296,7 +384,7 @@ static void sdhci_read_block_pio(struct sdhci_host *host) u32 uninitialized_var(scratch); u8 *buf; @@ -28556,7 +29595,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ blksize = host->data->blksz; chunk = 0; -@@ -341,7 +342,7 @@ +@@ -341,7 +429,7 @@ static void sdhci_write_block_pio(struct sdhci_host *host) u32 scratch; u8 *buf; @@ -28565,7 +29604,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ blksize = host->data->blksz; chunk = 0; -@@ -380,19 +381,28 @@ +@@ -380,19 +468,28 @@ static void sdhci_write_block_pio(struct sdhci_host *host) local_irq_restore(flags); } @@ -28597,7 +29636,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ /* * Some controllers (JMicron JMB38x) mess up the buffer bits -@@ -403,7 +413,7 @@ +@@ -403,7 +500,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host) (host->data->blocks == 1)) mask = ~0; @@ -28606,7 +29645,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY) udelay(100); -@@ -415,9 +425,11 @@ +@@ -415,9 +512,11 @@ static void sdhci_transfer_pio(struct sdhci_host *host) host->blocks--; if (host->blocks == 0) break; @@ -28619,7 +29658,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ } static char *sdhci_kmap_atomic(struct scatterlist *sg, unsigned long *flags) -@@ -690,7 +702,9 @@ +@@ -690,7 +789,9 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host) u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL; u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; @@ -28630,7 +29669,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ sdhci_clear_set_irqs(host, pio_irqs, dma_irqs); else sdhci_clear_set_irqs(host, dma_irqs, pio_irqs); -@@ -722,44 +736,25 @@ +@@ -722,44 +823,25 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) host->data_early = 0; host->data->bytes_xfered = 0; @@ -28683,7 +29722,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ int broken, i; struct scatterlist *sg; -@@ -818,7 +813,8 @@ +@@ -818,7 +900,8 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) */ WARN_ON(1); host->flags &= ~SDHCI_REQ_USE_DMA; @@ -28693,7 +29732,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ WARN_ON(sg_cnt != 1); sdhci_writel(host, sg_dma_address(data->sg), SDHCI_DMA_ADDRESS); -@@ -834,11 +830,13 @@ +@@ -834,11 +917,13 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) if (host->version >= SDHCI_SPEC_200) { ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); ctrl &= ~SDHCI_CTRL_DMA_MASK; @@ -28712,7 +29751,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); } -@@ -890,7 +888,8 @@ +@@ -890,7 +975,8 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, if (data->flags & MMC_DATA_READ) mode |= SDHCI_TRNS_READ; @@ -28722,7 +29761,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ mode |= SDHCI_TRNS_DMA; sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); -@@ -906,13 +905,16 @@ +@@ -906,13 +992,16 @@ static void sdhci_finish_data(struct sdhci_host *host) host->data = NULL; if (host->flags & SDHCI_REQ_USE_DMA) { @@ -28743,7 +29782,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ } /* -@@ -965,6 +967,12 @@ +@@ -965,6 +1054,12 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY)) mask |= SDHCI_DATA_INHIBIT; @@ -28756,9 +29795,13 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ /* We shouldn't wait for data inihibit for stop commands, even though they might use busy signaling */ if (host->mrq->data && (cmd == host->mrq->data->stop)) -@@ -982,10 +990,16 @@ +@@ -980,12 +1075,20 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) + return; + } timeout--; ++ sdhci_spin_enable_schedule(host); mdelay(1); ++ sdhci_spin_disable_schedule(host); } + DBG("send cmd %d - wait 0x%X irq 0x%x\n", cmd->opcode, mask, + sdhci_readl(host, SDHCI_INT_STATUS)); @@ -28773,7 +29816,17 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ sdhci_prepare_data(host, cmd); -@@ -1218,6 +1232,35 @@ +@@ -1150,7 +1253,9 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) + return; + } + timeout--; ++ sdhci_spin_enable_schedule(host); + mdelay(1); ++ sdhci_spin_disable_schedule(host); + } + + clk |= SDHCI_CLOCK_CARD_EN; +@@ -1218,6 +1323,35 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) mdelay(10); } @@ -28809,15 +29862,47 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ /*****************************************************************************\ * * * MMC callbacks * -@@ -1298,6 +1341,7 @@ +@@ -1234,7 +1368,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) + + sdhci_runtime_pm_get(host); + +- spin_lock_irqsave(&host->lock, flags); ++ sdhci_spin_lock_irqsave(host, &flags); + + WARN_ON(host->mrq != NULL); + +@@ -1276,9 +1410,9 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) + */ + if ((host->flags & SDHCI_NEEDS_RETUNING) && + !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { +- spin_unlock_irqrestore(&host->lock, flags); ++ sdhci_spin_unlock_irqrestore(host, flags); + sdhci_execute_tuning(mmc); +- spin_lock_irqsave(&host->lock, flags); ++ sdhci_spin_lock_irqsave(host, &flags); + + /* Restore original mmc_request structure */ + host->mrq = mrq; +@@ -1291,15 +1425,16 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) + } + + mmiowb(); +- spin_unlock_irqrestore(&host->lock, flags); ++ sdhci_spin_unlock_irqrestore(host, flags); + } + + static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) { unsigned long flags; u8 ctrl; + int rc; - spin_lock_irqsave(&host->lock, flags); +- spin_lock_irqsave(&host->lock, flags); ++ sdhci_spin_lock_irqsave(host, &flags); -@@ -1356,7 +1400,7 @@ + if (host->flags & SDHCI_DEVICE_DEAD) + goto out; +@@ -1356,7 +1491,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) else ctrl &= ~SDHCI_CTRL_HISPD; @@ -28826,10 +29911,22 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ u16 clk, ctrl_2; unsigned int clock; -@@ -1445,6 +1489,12 @@ +@@ -1364,7 +1499,8 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) + if ((ios->timing == MMC_TIMING_UHS_SDR50) || + (ios->timing == MMC_TIMING_UHS_SDR104) || + (ios->timing == MMC_TIMING_UHS_DDR50) || +- (ios->timing == MMC_TIMING_UHS_SDR25)) ++ (ios->timing == MMC_TIMING_UHS_SDR25) || ++ (ios->timing == MMC_TIMING_UHS_SDR12)) + ctrl |= SDHCI_CTRL_HISPD; + + ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); +@@ -1444,7 +1580,13 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) + out: mmiowb(); - spin_unlock_irqrestore(&host->lock, flags); +- spin_unlock_irqrestore(&host->lock, flags); ++ sdhci_spin_unlock_irqrestore(host, flags); + + if (ios->power_mode == MMC_POWER_OFF) { + do @@ -28839,7 +29936,55 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ } static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -@@ -1888,6 +1938,8 @@ +@@ -1461,7 +1603,7 @@ static int sdhci_check_ro(struct sdhci_host *host) + unsigned long flags; + int is_readonly; + +- spin_lock_irqsave(&host->lock, flags); ++ sdhci_spin_lock_irqsave(host, &flags); + + if (host->flags & SDHCI_DEVICE_DEAD) + is_readonly = 0; +@@ -1471,7 +1613,7 @@ static int sdhci_check_ro(struct sdhci_host *host) + is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE) + & SDHCI_WRITE_PROTECT); + +- spin_unlock_irqrestore(&host->lock, flags); ++ sdhci_spin_unlock_irqrestore(host, flags); + + /* This quirk needs to be replaced by a callback-function later */ + return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ? +@@ -1544,9 +1686,9 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) + struct sdhci_host *host = mmc_priv(mmc); + unsigned long flags; + +- spin_lock_irqsave(&host->lock, flags); ++ sdhci_spin_lock_irqsave(host, &flags); + sdhci_enable_sdio_irq_nolock(host, enable); +- spin_unlock_irqrestore(&host->lock, flags); ++ sdhci_spin_unlock_irqrestore(host, flags); + } + + static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, +@@ -1849,7 +1991,7 @@ static void sdhci_do_enable_preset_value(struct sdhci_host *host, bool enable) + if (host->version < SDHCI_SPEC_300) + return; + +- spin_lock_irqsave(&host->lock, flags); ++ sdhci_spin_lock_irqsave(host, &flags); + + ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); + +@@ -1867,7 +2009,7 @@ static void sdhci_do_enable_preset_value(struct sdhci_host *host, bool enable) + host->flags &= ~SDHCI_PV_ENABLED; + } + +- spin_unlock_irqrestore(&host->lock, flags); ++ sdhci_spin_unlock_irqrestore(host, flags); + } + + static void sdhci_enable_preset_value(struct mmc_host *mmc, bool enable) +@@ -1888,6 +2030,8 @@ static const struct mmc_host_ops sdhci_ops = { .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, .execute_tuning = sdhci_execute_tuning, .enable_preset_value = sdhci_enable_preset_value, @@ -28848,7 +29993,56 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ }; /*****************************************************************************\ -@@ -2000,7 +2052,7 @@ +@@ -1903,7 +2047,7 @@ static void sdhci_tasklet_card(unsigned long param) + + host = (struct sdhci_host*)param; + +- spin_lock_irqsave(&host->lock, flags); ++ sdhci_spin_lock_irqsave(host, &flags); + + /* Check host->mrq first in case we are runtime suspended */ + if (host->mrq && +@@ -1920,7 +2064,7 @@ static void sdhci_tasklet_card(unsigned long param) + tasklet_schedule(&host->finish_tasklet); + } + +- spin_unlock_irqrestore(&host->lock, flags); ++ sdhci_spin_unlock_irqrestore(host, flags); + + mmc_detect_change(host->mmc, msecs_to_jiffies(200)); + } +@@ -1933,14 +2077,14 @@ static void sdhci_tasklet_finish(unsigned long param) + + host = (struct sdhci_host*)param; + +- spin_lock_irqsave(&host->lock, flags); ++ sdhci_spin_lock_irqsave(host, &flags); + + /* + * If this tasklet gets rescheduled while running, it will + * be run again afterwards but without any active request. + */ + if (!host->mrq) { +- spin_unlock_irqrestore(&host->lock, flags); ++ sdhci_spin_unlock_irqrestore(host, flags); + return; + } + +@@ -1983,7 +2127,7 @@ static void sdhci_tasklet_finish(unsigned long param) + #endif + + mmiowb(); +- spin_unlock_irqrestore(&host->lock, flags); ++ sdhci_spin_unlock_irqrestore(host, flags); + + mmc_request_done(host->mmc, mrq); + sdhci_runtime_pm_put(host); +@@ -1996,11 +2140,11 @@ static void sdhci_timeout_timer(unsigned long data) + + host = (struct sdhci_host*)data; + +- spin_lock_irqsave(&host->lock, flags); ++ sdhci_spin_lock_irqsave(host, &flags); if (host->mrq) { pr_err("%s: Timeout waiting for hardware " @@ -28857,7 +30051,30 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ sdhci_dumpregs(host); if (host->data) { -@@ -2045,10 +2097,13 @@ +@@ -2017,7 +2161,7 @@ static void sdhci_timeout_timer(unsigned long data) + } + + mmiowb(); +- spin_unlock_irqrestore(&host->lock, flags); ++ sdhci_spin_unlock_irqrestore(host, flags); + } + + static void sdhci_tuning_timer(unsigned long data) +@@ -2027,11 +2171,11 @@ static void sdhci_tuning_timer(unsigned long data) + + host = (struct sdhci_host *)data; + +- spin_lock_irqsave(&host->lock, flags); ++ sdhci_spin_lock_irqsave(host, &flags); + + host->flags |= SDHCI_NEEDS_RETUNING; + +- spin_unlock_irqrestore(&host->lock, flags); ++ sdhci_spin_unlock_irqrestore(host, flags); + } + + /*****************************************************************************\ +@@ -2045,10 +2189,13 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) BUG_ON(intmask == 0); if (!host->cmd) { @@ -28875,7 +30092,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ return; } -@@ -2118,6 +2173,19 @@ +@@ -2118,6 +2265,19 @@ static void sdhci_show_adma_error(struct sdhci_host *host) static void sdhci_show_adma_error(struct sdhci_host *host) { } #endif @@ -28895,7 +30112,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) { BUG_ON(intmask == 0); -@@ -2144,34 +2212,57 @@ +@@ -2144,34 +2304,57 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) return; } } @@ -28968,7 +30185,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ /* * We currently don't do anything fancy with DMA -@@ -2200,18 +2291,8 @@ +@@ -2200,18 +2383,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) sdhci_writel(host, dmanow, SDHCI_DMA_ADDRESS); } @@ -28989,7 +30206,20 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ } } -@@ -2266,6 +2347,22 @@ +@@ -2222,10 +2395,10 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) + u32 intmask; + int cardint = 0; + +- spin_lock(&host->lock); ++ sdhci_spin_lock(host); + + if (host->runtime_suspended) { +- spin_unlock(&host->lock); ++ sdhci_spin_unlock(host); + pr_warning("%s: got irq while runtime suspended\n", + mmc_hostname(host->mmc)); + return IRQ_HANDLED; +@@ -2266,6 +2439,22 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) tasklet_schedule(&host->card_tasklet); } @@ -29012,7 +30242,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ if (intmask & SDHCI_INT_CMD_MASK) { sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, SDHCI_INT_STATUS); -@@ -2280,7 +2377,13 @@ +@@ -2280,7 +2469,13 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK); @@ -29027,7 +30257,16 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ if (intmask & SDHCI_INT_BUS_POWER) { pr_err("%s: Card is consuming too much power!\n", -@@ -2363,7 +2466,8 @@ +@@ -2307,7 +2502,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) + + mmiowb(); + out: +- spin_unlock(&host->lock); ++ sdhci_spin_unlock(host); + + /* + * We have to delay this as it calls back into the driver. +@@ -2363,7 +2558,8 @@ int sdhci_resume_host(struct sdhci_host *host) return ret; } @@ -29037,7 +30276,45 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ if (host->ops->enable_dma) host->ops->enable_dma(host); } -@@ -2570,14 +2674,16 @@ +@@ -2426,15 +2622,15 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host) + host->flags &= ~SDHCI_NEEDS_RETUNING; + } + +- spin_lock_irqsave(&host->lock, flags); ++ sdhci_spin_lock_irqsave(host, &flags); + sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK); +- spin_unlock_irqrestore(&host->lock, flags); ++ sdhci_spin_unlock_irqrestore(host, flags); + + synchronize_irq(host->irq); + +- spin_lock_irqsave(&host->lock, flags); ++ sdhci_spin_lock_irqsave(host, &flags); + host->runtime_suspended = true; +- spin_unlock_irqrestore(&host->lock, flags); ++ sdhci_spin_unlock_irqrestore(host, flags); + + return ret; + } +@@ -2466,7 +2662,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) + (host->tuning_mode == SDHCI_TUNING_MODE_1)) + host->flags |= SDHCI_NEEDS_RETUNING; + +- spin_lock_irqsave(&host->lock, flags); ++ sdhci_spin_lock_irqsave(host, &flags); + + host->runtime_suspended = false; + +@@ -2477,7 +2673,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) + /* Enable Card Detection */ + sdhci_enable_card_detection(host); + +- spin_unlock_irqrestore(&host->lock, flags); ++ sdhci_spin_unlock_irqrestore(host, flags); + + return ret; + } +@@ -2570,14 +2766,16 @@ int sdhci_add_host(struct sdhci_host *host) host->flags &= ~SDHCI_USE_ADMA; } @@ -29056,7 +30333,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ } } } -@@ -2688,7 +2794,7 @@ +@@ -2688,7 +2886,7 @@ int sdhci_add_host(struct sdhci_host *host) /* Auto-CMD23 stuff only works in ADMA or PIO. */ if ((host->version >= SDHCI_SPEC_300) && ((host->flags & SDHCI_USE_ADMA) || @@ -29065,12 +30342,12 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ host->flags |= SDHCI_AUTO_CMD23; DBG("%s: Auto-CMD23 available\n", mmc_hostname(mmc)); } else { -@@ -2821,6 +2927,12 @@ +@@ -2821,6 +3019,12 @@ int sdhci_add_host(struct sdhci_host *host) mmc->caps |= MMC_CAP_MAX_CURRENT_200; } + if(host->ops->voltage_broken) { -+ ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31; ++ ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34; + // Cannot support UHS modes is we are stuck at 3.3V; + mmc->caps &= ~(MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_DDR50); + } @@ -29078,7 +30355,16 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ mmc->ocr_avail = ocr_avail; mmc->ocr_avail_sdio = ocr_avail; if (host->ocr_avail_sdio) -@@ -2953,6 +3065,7 @@ +@@ -2915,7 +3119,7 @@ int sdhci_add_host(struct sdhci_host *host) + host->tuning_timer.function = sdhci_tuning_timer; + } + +- ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, ++ ret = request_irq(host->irq, sdhci_irq, 0,//IRQF_SHARED, + mmc_hostname(mmc), host); + if (ret) + goto untasklet; +@@ -2953,6 +3157,7 @@ int sdhci_add_host(struct sdhci_host *host) pr_info("%s: SDHCI controller on %s [%s] using %s\n", mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), @@ -29086,10 +30372,29 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.c linux-rpi-bootc-3.2.23/drivers/ (host->flags & SDHCI_USE_ADMA) ? "ADMA" : (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO"); -diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.h linux-rpi-bootc-3.2.23/drivers/mmc/host/sdhci.h ---- linux-3.2.23/drivers/mmc/host/sdhci.h 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/mmc/host/sdhci.h 2012-07-15 20:29:21.559130191 +0200 -@@ -273,6 +273,25 @@ +@@ -2979,7 +3184,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) + unsigned long flags; + + if (dead) { +- spin_lock_irqsave(&host->lock, flags); ++ sdhci_spin_lock_irqsave(host, &flags); + + host->flags |= SDHCI_DEVICE_DEAD; + +@@ -2991,7 +3196,7 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) + tasklet_schedule(&host->finish_tasklet); + } + +- spin_unlock_irqrestore(&host->lock, flags); ++ sdhci_spin_unlock_irqrestore(host, flags); + } + + sdhci_disable_card_detection(host); +diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h +index a04d4d0..c08882b 100644 +--- a/drivers/mmc/host/sdhci.h ++++ b/drivers/mmc/host/sdhci.h +@@ -273,6 +273,25 @@ struct sdhci_ops { void (*platform_reset_enter)(struct sdhci_host *host, u8 mask); void (*platform_reset_exit)(struct sdhci_host *host, u8 mask); int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs); @@ -29115,7 +30420,7 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.h linux-rpi-bootc-3.2.23/drivers/ void (*hw_reset)(struct sdhci_host *host); }; -@@ -379,6 +398,29 @@ +@@ -379,9 +398,38 @@ extern int sdhci_resume_host(struct sdhci_host *host); extern void sdhci_enable_irq_wakeups(struct sdhci_host *host); #endif @@ -29145,9 +30450,19 @@ diff -Naur linux-3.2.23/drivers/mmc/host/sdhci.h linux-rpi-bootc-3.2.23/drivers/ #ifdef CONFIG_PM_RUNTIME extern int sdhci_runtime_suspend_host(struct sdhci_host *host); extern int sdhci_runtime_resume_host(struct sdhci_host *host); -diff -Naur linux-3.2.23/drivers/net/usb/smsc95xx.c linux-rpi-bootc-3.2.23/drivers/net/usb/smsc95xx.c ---- linux-3.2.23/drivers/net/usb/smsc95xx.c 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/net/usb/smsc95xx.c 2012-07-15 20:29:39.445466746 +0200 + #endif + ++extern void sdhci_spin_lock_irqsave(struct sdhci_host *host,unsigned long *flags); ++extern void sdhci_spin_unlock_irqrestore(struct sdhci_host *host,unsigned long flags); ++extern void sdhci_spin_lock(struct sdhci_host *host); ++extern void sdhci_spin_unlock(struct sdhci_host *host); ++ ++ + #endif /* __SDHCI_HW_H */ +diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c +index 55b3218..5d2fec2 100644 +--- a/drivers/net/usb/smsc95xx.c ++++ b/drivers/net/usb/smsc95xx.c @@ -46,6 +46,7 @@ #define SMSC95XX_INTERNAL_PHY_ID (1) #define SMSC95XX_TX_OVERHEAD (8) @@ -29156,7 +30471,7 @@ diff -Naur linux-3.2.23/drivers/net/usb/smsc95xx.c linux-rpi-bootc-3.2.23/driver struct smsc95xx_priv { u32 mac_cr; -@@ -63,6 +64,10 @@ +@@ -63,6 +64,10 @@ static int turbo_mode = true; module_param(turbo_mode, bool, 0644); MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); @@ -29167,7 +30482,7 @@ diff -Naur linux-3.2.23/drivers/net/usb/smsc95xx.c linux-rpi-bootc-3.2.23/driver static int smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data) { u32 *buf = kmalloc(4, GFP_KERNEL); -@@ -600,8 +605,59 @@ +@@ -600,8 +605,59 @@ static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); } @@ -29227,7 +30542,7 @@ diff -Naur linux-3.2.23/drivers/net/usb/smsc95xx.c linux-rpi-bootc-3.2.23/driver /* try reading mac address from EEPROM */ if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, dev->net->dev_addr) == 0) { -@@ -1016,6 +1072,7 @@ +@@ -1016,6 +1072,7 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->ethtool_ops = &smsc95xx_ethtool_ops; dev->net->flags |= IFF_MULTICAST; dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD_CSUM; @@ -29235,10 +30550,506 @@ diff -Naur linux-3.2.23/drivers/net/usb/smsc95xx.c linux-rpi-bootc-3.2.23/driver return 0; } -diff -Naur linux-3.2.23/drivers/spi/Kconfig linux-rpi-bootc-3.2.23/drivers/spi/Kconfig ---- linux-3.2.23/drivers/spi/Kconfig 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/spi/Kconfig 2012-07-15 20:29:50.559675875 +0200 -@@ -74,6 +74,14 @@ +diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig +index abd3b71..f561d69 100644 +diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile +index 0a304b0..a042951 100644 +diff --git a/drivers/net/wireless/rtl8192cu/Kconfig b/drivers/net/wireless/rtl8192cu/Kconfig +new file mode 100755 +index 0000000..bee5ed6 +diff --git a/drivers/net/wireless/rtl8192cu/Makefile b/drivers/net/wireless/rtl8192cu/Makefile +new file mode 100755 +index 0000000..1b4e841 +diff --git a/drivers/net/wireless/rtl8192cu/clean b/drivers/net/wireless/rtl8192cu/clean +new file mode 100755 +index 0000000..34686a0 +\ No newline at end of file +diff --git a/drivers/net/wireless/rtl8192cu/core/efuse/rtw_efuse.c b/drivers/net/wireless/rtl8192cu/core/efuse/rtw_efuse.c +new file mode 100755 +index 0000000..4908d6e +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_br_ext.c b/drivers/net/wireless/rtl8192cu/core/rtw_br_ext.c +new file mode 100755 +index 0000000..1fcdf1e +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_cmd.c b/drivers/net/wireless/rtl8192cu/core/rtw_cmd.c +new file mode 100755 +index 0000000..513e8ab +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_debug.c b/drivers/net/wireless/rtl8192cu/core/rtw_debug.c +new file mode 100755 +index 0000000..96e5bd1 +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_eeprom.c b/drivers/net/wireless/rtl8192cu/core/rtw_eeprom.c +new file mode 100755 +index 0000000..4a0832b +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_ieee80211.c b/drivers/net/wireless/rtl8192cu/core/rtw_ieee80211.c +new file mode 100755 +index 0000000..2b85af9 +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_io.c b/drivers/net/wireless/rtl8192cu/core/rtw_io.c +new file mode 100755 +index 0000000..2efe719 +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_ioctl_query.c b/drivers/net/wireless/rtl8192cu/core/rtw_ioctl_query.c +new file mode 100755 +index 0000000..156640c +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_ioctl_rtl.c b/drivers/net/wireless/rtl8192cu/core/rtw_ioctl_rtl.c +new file mode 100755 +index 0000000..87348a2 +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_ioctl_set.c b/drivers/net/wireless/rtl8192cu/core/rtw_ioctl_set.c +new file mode 100755 +index 0000000..946d875 +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_iol.c b/drivers/net/wireless/rtl8192cu/core/rtw_iol.c +new file mode 100755 +index 0000000..ce3d1a9 +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_mlme.c b/drivers/net/wireless/rtl8192cu/core/rtw_mlme.c +new file mode 100755 +index 0000000..647d67a +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_mlme_ext.c b/drivers/net/wireless/rtl8192cu/core/rtw_mlme_ext.c +new file mode 100755 +index 0000000..7aaf136 +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_mp.c b/drivers/net/wireless/rtl8192cu/core/rtw_mp.c +new file mode 100755 +index 0000000..0cdc094 +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_mp_ioctl.c b/drivers/net/wireless/rtl8192cu/core/rtw_mp_ioctl.c +new file mode 100755 +index 0000000..a851568 +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_p2p.c b/drivers/net/wireless/rtl8192cu/core/rtw_p2p.c +new file mode 100755 +index 0000000..bdfcdf1 +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_pwrctrl.c b/drivers/net/wireless/rtl8192cu/core/rtw_pwrctrl.c +new file mode 100755 +index 0000000..92b3cb8 +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_recv.c b/drivers/net/wireless/rtl8192cu/core/rtw_recv.c +new file mode 100755 +index 0000000..0d5143b +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_rf.c b/drivers/net/wireless/rtl8192cu/core/rtw_rf.c +new file mode 100755 +index 0000000..665c7e5 +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_security.c b/drivers/net/wireless/rtl8192cu/core/rtw_security.c +new file mode 100755 +index 0000000..58601b6 +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_sta_mgt.c b/drivers/net/wireless/rtl8192cu/core/rtw_sta_mgt.c +new file mode 100755 +index 0000000..70b25c9 +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_wlan_util.c b/drivers/net/wireless/rtl8192cu/core/rtw_wlan_util.c +new file mode 100755 +index 0000000..539b74f +diff --git a/drivers/net/wireless/rtl8192cu/core/rtw_xmit.c b/drivers/net/wireless/rtl8192cu/core/rtw_xmit.c +new file mode 100755 +index 0000000..178a5b7 +diff --git a/drivers/net/wireless/rtl8192cu/hal/hal_init.c b/drivers/net/wireless/rtl8192cu/hal/hal_init.c +new file mode 100755 +index 0000000..edef678 +diff --git a/drivers/net/wireless/rtl8192cu/hal/rtl8192c/rtl8192c_cmd.c b/drivers/net/wireless/rtl8192cu/hal/rtl8192c/rtl8192c_cmd.c +new file mode 100755 +index 0000000..6c53f89 +diff --git a/drivers/net/wireless/rtl8192cu/hal/rtl8192c/rtl8192c_dm.c b/drivers/net/wireless/rtl8192cu/hal/rtl8192c/rtl8192c_dm.c +new file mode 100755 +index 0000000..1adeae2 +diff --git a/drivers/net/wireless/rtl8192cu/hal/rtl8192c/rtl8192c_hal_init.c b/drivers/net/wireless/rtl8192cu/hal/rtl8192c/rtl8192c_hal_init.c +new file mode 100755 +index 0000000..e3e2ae9 +diff --git a/drivers/net/wireless/rtl8192cu/hal/rtl8192c/rtl8192c_mp.c b/drivers/net/wireless/rtl8192cu/hal/rtl8192c/rtl8192c_mp.c +new file mode 100755 +index 0000000..28a8cc3 +diff --git a/drivers/net/wireless/rtl8192cu/hal/rtl8192c/rtl8192c_phycfg.c b/drivers/net/wireless/rtl8192cu/hal/rtl8192c/rtl8192c_phycfg.c +new file mode 100755 +index 0000000..d8394df +diff --git a/drivers/net/wireless/rtl8192cu/hal/rtl8192c/rtl8192c_rf6052.c b/drivers/net/wireless/rtl8192cu/hal/rtl8192c/rtl8192c_rf6052.c +new file mode 100755 +index 0000000..d17c23f +diff --git a/drivers/net/wireless/rtl8192cu/hal/rtl8192c/rtl8192c_rxdesc.c b/drivers/net/wireless/rtl8192cu/hal/rtl8192c/rtl8192c_rxdesc.c +new file mode 100755 +index 0000000..5aa6e61 +diff --git a/drivers/net/wireless/rtl8192cu/hal/rtl8192c/rtl8192c_sreset.c b/drivers/net/wireless/rtl8192cu/hal/rtl8192c/rtl8192c_sreset.c +new file mode 100755 +index 0000000..3f9adb5 +diff --git a/drivers/net/wireless/rtl8192cu/hal/rtl8192c/usb/Hal8192CUHWImg.c b/drivers/net/wireless/rtl8192cu/hal/rtl8192c/usb/Hal8192CUHWImg.c +new file mode 100755 +index 0000000..23969fc +diff --git a/drivers/net/wireless/rtl8192cu/hal/rtl8192c/usb/Hal8192CUHWImg_wowlan.c b/drivers/net/wireless/rtl8192cu/hal/rtl8192c/usb/Hal8192CUHWImg_wowlan.c +new file mode 100755 +index 0000000..27a31ce +diff --git a/drivers/net/wireless/rtl8192cu/hal/rtl8192c/usb/rtl8192cu_led.c b/drivers/net/wireless/rtl8192cu/hal/rtl8192c/usb/rtl8192cu_led.c +new file mode 100755 +index 0000000..6665648 +diff --git a/drivers/net/wireless/rtl8192cu/hal/rtl8192c/usb/rtl8192cu_recv.c b/drivers/net/wireless/rtl8192cu/hal/rtl8192c/usb/rtl8192cu_recv.c +new file mode 100755 +index 0000000..4285d60 +diff --git a/drivers/net/wireless/rtl8192cu/hal/rtl8192c/usb/rtl8192cu_xmit.c b/drivers/net/wireless/rtl8192cu/hal/rtl8192c/usb/rtl8192cu_xmit.c +new file mode 100755 +index 0000000..c276b51 +diff --git a/drivers/net/wireless/rtl8192cu/hal/rtl8192c/usb/usb_halinit.c b/drivers/net/wireless/rtl8192cu/hal/rtl8192c/usb/usb_halinit.c +new file mode 100755 +index 0000000..47be445 +diff --git a/drivers/net/wireless/rtl8192cu/hal/rtl8192c/usb/usb_ops_ce.c b/drivers/net/wireless/rtl8192cu/hal/rtl8192c/usb/usb_ops_ce.c +new file mode 100755 +index 0000000..4d01b3c +diff --git a/drivers/net/wireless/rtl8192cu/hal/rtl8192c/usb/usb_ops_linux.c b/drivers/net/wireless/rtl8192cu/hal/rtl8192c/usb/usb_ops_linux.c +new file mode 100755 +index 0000000..d6f3376 +diff --git a/drivers/net/wireless/rtl8192cu/hal/rtl8192c/usb/usb_ops_xp.c b/drivers/net/wireless/rtl8192cu/hal/rtl8192c/usb/usb_ops_xp.c +new file mode 100755 +index 0000000..82adeff +diff --git a/drivers/net/wireless/rtl8192cu/ifcfg-wlan0 b/drivers/net/wireless/rtl8192cu/ifcfg-wlan0 +new file mode 100755 +index 0000000..20dcbec +\ No newline at end of file +diff --git a/drivers/net/wireless/rtl8192cu/include/Hal8192CEHWImg.h b/drivers/net/wireless/rtl8192cu/include/Hal8192CEHWImg.h +new file mode 100755 +index 0000000..e7c6869 +diff --git a/drivers/net/wireless/rtl8192cu/include/Hal8192CPhyCfg.h b/drivers/net/wireless/rtl8192cu/include/Hal8192CPhyCfg.h +new file mode 100755 +index 0000000..2e76d2a +diff --git a/drivers/net/wireless/rtl8192cu/include/Hal8192CPhyReg.h b/drivers/net/wireless/rtl8192cu/include/Hal8192CPhyReg.h +new file mode 100755 +index 0000000..5f2d451 +diff --git a/drivers/net/wireless/rtl8192cu/include/Hal8192CUHWImg.h b/drivers/net/wireless/rtl8192cu/include/Hal8192CUHWImg.h +new file mode 100755 +index 0000000..2aced69 +diff --git a/drivers/net/wireless/rtl8192cu/include/Hal8192CUHWImg_wowlan.h b/drivers/net/wireless/rtl8192cu/include/Hal8192CUHWImg_wowlan.h +new file mode 100755 +index 0000000..ec52f45 +diff --git a/drivers/net/wireless/rtl8192cu/include/Hal8192DEHWImg.h b/drivers/net/wireless/rtl8192cu/include/Hal8192DEHWImg.h +new file mode 100755 +index 0000000..d99403c +diff --git a/drivers/net/wireless/rtl8192cu/include/Hal8192DETestHWImg.h b/drivers/net/wireless/rtl8192cu/include/Hal8192DETestHWImg.h +new file mode 100755 +index 0000000..0cb96e5 +diff --git a/drivers/net/wireless/rtl8192cu/include/Hal8192DPhyCfg.h b/drivers/net/wireless/rtl8192cu/include/Hal8192DPhyCfg.h +new file mode 100755 +index 0000000..8e14417 +diff --git a/drivers/net/wireless/rtl8192cu/include/Hal8192DPhyReg.h b/drivers/net/wireless/rtl8192cu/include/Hal8192DPhyReg.h +new file mode 100755 +index 0000000..bff455f +diff --git a/drivers/net/wireless/rtl8192cu/include/Hal8192DUHWImg.h b/drivers/net/wireless/rtl8192cu/include/Hal8192DUHWImg.h +new file mode 100755 +index 0000000..f43e9d1 +diff --git a/drivers/net/wireless/rtl8192cu/include/Hal8192DUHWImg_wowlan.h b/drivers/net/wireless/rtl8192cu/include/Hal8192DUHWImg_wowlan.h +new file mode 100755 +index 0000000..75aafee +diff --git a/drivers/net/wireless/rtl8192cu/include/Hal8192DUTestHWImg.h b/drivers/net/wireless/rtl8192cu/include/Hal8192DUTestHWImg.h +new file mode 100755 +index 0000000..3ce7a3d +diff --git a/drivers/net/wireless/rtl8192cu/include/autoconf.h b/drivers/net/wireless/rtl8192cu/include/autoconf.h +new file mode 100755 +index 0000000..4a50f8b +diff --git a/drivers/net/wireless/rtl8192cu/include/basic_types.h b/drivers/net/wireless/rtl8192cu/include/basic_types.h +new file mode 100755 +index 0000000..f880224 +diff --git a/drivers/net/wireless/rtl8192cu/include/byteorder/big_endian.h b/drivers/net/wireless/rtl8192cu/include/byteorder/big_endian.h +new file mode 100755 +index 0000000..eca68a6 +diff --git a/drivers/net/wireless/rtl8192cu/include/byteorder/generic.h b/drivers/net/wireless/rtl8192cu/include/byteorder/generic.h +new file mode 100755 +index 0000000..246ba89 +diff --git a/drivers/net/wireless/rtl8192cu/include/byteorder/little_endian.h b/drivers/net/wireless/rtl8192cu/include/byteorder/little_endian.h +new file mode 100755 +index 0000000..433045e +diff --git a/drivers/net/wireless/rtl8192cu/include/byteorder/swab.h b/drivers/net/wireless/rtl8192cu/include/byteorder/swab.h +new file mode 100755 +index 0000000..117c84d +diff --git a/drivers/net/wireless/rtl8192cu/include/byteorder/swabb.h b/drivers/net/wireless/rtl8192cu/include/byteorder/swabb.h +new file mode 100755 +index 0000000..1735349 +diff --git a/drivers/net/wireless/rtl8192cu/include/circ_buf.h b/drivers/net/wireless/rtl8192cu/include/circ_buf.h +new file mode 100755 +index 0000000..1bd4704 +diff --git a/drivers/net/wireless/rtl8192cu/include/cmd_osdep.h b/drivers/net/wireless/rtl8192cu/include/cmd_osdep.h +new file mode 100755 +index 0000000..077efa7 +diff --git a/drivers/net/wireless/rtl8192cu/include/drv_conf.h b/drivers/net/wireless/rtl8192cu/include/drv_conf.h +new file mode 100755 +index 0000000..a2b6cc4 +diff --git a/drivers/net/wireless/rtl8192cu/include/drv_types.h b/drivers/net/wireless/rtl8192cu/include/drv_types.h +new file mode 100755 +index 0000000..95e20cc +diff --git a/drivers/net/wireless/rtl8192cu/include/drv_types_ce.h b/drivers/net/wireless/rtl8192cu/include/drv_types_ce.h +new file mode 100755 +index 0000000..be0459d +diff --git a/drivers/net/wireless/rtl8192cu/include/drv_types_linux.h b/drivers/net/wireless/rtl8192cu/include/drv_types_linux.h +new file mode 100755 +index 0000000..db1c585 +diff --git a/drivers/net/wireless/rtl8192cu/include/drv_types_xp.h b/drivers/net/wireless/rtl8192cu/include/drv_types_xp.h +new file mode 100755 +index 0000000..2d51b1d +diff --git a/drivers/net/wireless/rtl8192cu/include/ethernet.h b/drivers/net/wireless/rtl8192cu/include/ethernet.h +new file mode 100755 +index 0000000..36e29c0 +diff --git a/drivers/net/wireless/rtl8192cu/include/farray.h b/drivers/net/wireless/rtl8192cu/include/farray.h +new file mode 100755 +index 0000000..79d2a42 +diff --git a/drivers/net/wireless/rtl8192cu/include/h2clbk.h b/drivers/net/wireless/rtl8192cu/include/h2clbk.h +new file mode 100755 +index 0000000..359c9e7 +diff --git a/drivers/net/wireless/rtl8192cu/include/hal_init.h b/drivers/net/wireless/rtl8192cu/include/hal_init.h +new file mode 100755 +index 0000000..ec48f83 +diff --git a/drivers/net/wireless/rtl8192cu/include/ieee80211.h b/drivers/net/wireless/rtl8192cu/include/ieee80211.h +new file mode 100755 +index 0000000..5c17a28 +diff --git a/drivers/net/wireless/rtl8192cu/include/ieee80211_ext.h b/drivers/net/wireless/rtl8192cu/include/ieee80211_ext.h +new file mode 100755 +index 0000000..0a966fa +diff --git a/drivers/net/wireless/rtl8192cu/include/if_ether.h b/drivers/net/wireless/rtl8192cu/include/if_ether.h +new file mode 100755 +index 0000000..045c067 +diff --git a/drivers/net/wireless/rtl8192cu/include/ioctl_cfg80211.h b/drivers/net/wireless/rtl8192cu/include/ioctl_cfg80211.h +new file mode 100755 +index 0000000..823e4a1 +diff --git a/drivers/net/wireless/rtl8192cu/include/ip.h b/drivers/net/wireless/rtl8192cu/include/ip.h +new file mode 100755 +index 0000000..5846347 +diff --git a/drivers/net/wireless/rtl8192cu/include/mlme_osdep.h b/drivers/net/wireless/rtl8192cu/include/mlme_osdep.h +new file mode 100755 +index 0000000..1583053 +diff --git a/drivers/net/wireless/rtl8192cu/include/mp_custom_oid.h b/drivers/net/wireless/rtl8192cu/include/mp_custom_oid.h +new file mode 100755 +index 0000000..5f86738 +diff --git a/drivers/net/wireless/rtl8192cu/include/nic_spec.h b/drivers/net/wireless/rtl8192cu/include/nic_spec.h +new file mode 100755 +index 0000000..18e7b2c +diff --git a/drivers/net/wireless/rtl8192cu/include/osdep_ce_service.h b/drivers/net/wireless/rtl8192cu/include/osdep_ce_service.h +new file mode 100755 +index 0000000..5f7c3e6 +diff --git a/drivers/net/wireless/rtl8192cu/include/osdep_intf.h b/drivers/net/wireless/rtl8192cu/include/osdep_intf.h +new file mode 100755 +index 0000000..86b3f1f +diff --git a/drivers/net/wireless/rtl8192cu/include/osdep_service.h b/drivers/net/wireless/rtl8192cu/include/osdep_service.h +new file mode 100755 +index 0000000..2802187 +diff --git a/drivers/net/wireless/rtl8192cu/include/pci_hal.h b/drivers/net/wireless/rtl8192cu/include/pci_hal.h +new file mode 100755 +index 0000000..1ee0ee2 +diff --git a/drivers/net/wireless/rtl8192cu/include/pci_ops.h b/drivers/net/wireless/rtl8192cu/include/pci_ops.h +new file mode 100755 +index 0000000..dd63f5f +diff --git a/drivers/net/wireless/rtl8192cu/include/pci_osintf.h b/drivers/net/wireless/rtl8192cu/include/pci_osintf.h +new file mode 100755 +index 0000000..09715af +diff --git a/drivers/net/wireless/rtl8192cu/include/recv_osdep.h b/drivers/net/wireless/rtl8192cu/include/recv_osdep.h +new file mode 100755 +index 0000000..536ed31 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtl8192c_cmd.h b/drivers/net/wireless/rtl8192cu/include/rtl8192c_cmd.h +new file mode 100755 +index 0000000..57ecadf +diff --git a/drivers/net/wireless/rtl8192cu/include/rtl8192c_dm.h b/drivers/net/wireless/rtl8192cu/include/rtl8192c_dm.h +new file mode 100755 +index 0000000..a13b5ff +diff --git a/drivers/net/wireless/rtl8192cu/include/rtl8192c_event.h b/drivers/net/wireless/rtl8192cu/include/rtl8192c_event.h +new file mode 100755 +index 0000000..a43f99f +diff --git a/drivers/net/wireless/rtl8192cu/include/rtl8192c_hal.h b/drivers/net/wireless/rtl8192cu/include/rtl8192c_hal.h +new file mode 100755 +index 0000000..cddd998 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtl8192c_led.h b/drivers/net/wireless/rtl8192cu/include/rtl8192c_led.h +new file mode 100755 +index 0000000..4ddd9c8 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtl8192c_recv.h b/drivers/net/wireless/rtl8192cu/include/rtl8192c_recv.h +new file mode 100755 +index 0000000..70a6d10 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtl8192c_rf.h b/drivers/net/wireless/rtl8192cu/include/rtl8192c_rf.h +new file mode 100755 +index 0000000..76c8a78 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtl8192c_spec.h b/drivers/net/wireless/rtl8192cu/include/rtl8192c_spec.h +new file mode 100755 +index 0000000..1e97b01 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtl8192c_sreset.h b/drivers/net/wireless/rtl8192cu/include/rtl8192c_sreset.h +new file mode 100755 +index 0000000..bd521c4 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtl8192c_xmit.h b/drivers/net/wireless/rtl8192cu/include/rtl8192c_xmit.h +new file mode 100755 +index 0000000..f4428af +diff --git a/drivers/net/wireless/rtl8192cu/include/rtl8192d_cmd.h b/drivers/net/wireless/rtl8192cu/include/rtl8192d_cmd.h +new file mode 100755 +index 0000000..f07a2bd +diff --git a/drivers/net/wireless/rtl8192cu/include/rtl8192d_dm.h b/drivers/net/wireless/rtl8192cu/include/rtl8192d_dm.h +new file mode 100755 +index 0000000..994d3e5 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtl8192d_hal.h b/drivers/net/wireless/rtl8192cu/include/rtl8192d_hal.h +new file mode 100755 +index 0000000..52be16b +diff --git a/drivers/net/wireless/rtl8192cu/include/rtl8192d_led.h b/drivers/net/wireless/rtl8192cu/include/rtl8192d_led.h +new file mode 100755 +index 0000000..95e20ac +diff --git a/drivers/net/wireless/rtl8192cu/include/rtl8192d_recv.h b/drivers/net/wireless/rtl8192cu/include/rtl8192d_recv.h +new file mode 100755 +index 0000000..f7b62bd +diff --git a/drivers/net/wireless/rtl8192cu/include/rtl8192d_rf.h b/drivers/net/wireless/rtl8192cu/include/rtl8192d_rf.h +new file mode 100755 +index 0000000..eea18b9 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtl8192d_spec.h b/drivers/net/wireless/rtl8192cu/include/rtl8192d_spec.h +new file mode 100755 +index 0000000..2d05559 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtl8192d_xmit.h b/drivers/net/wireless/rtl8192cu/include/rtl8192d_xmit.h +new file mode 100755 +index 0000000..2b1580f +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_android.h b/drivers/net/wireless/rtl8192cu/include/rtw_android.h +new file mode 100755 +index 0000000..e1a0432 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_br_ext.h b/drivers/net/wireless/rtl8192cu/include/rtw_br_ext.h +new file mode 100755 +index 0000000..9da3fdd +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_byteorder.h b/drivers/net/wireless/rtl8192cu/include/rtw_byteorder.h +new file mode 100755 +index 0000000..1313a25 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_cmd.h b/drivers/net/wireless/rtl8192cu/include/rtw_cmd.h +new file mode 100755 +index 0000000..0556d0b +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_debug.h b/drivers/net/wireless/rtl8192cu/include/rtw_debug.h +new file mode 100755 +index 0000000..7dc750b +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_eeprom.h b/drivers/net/wireless/rtl8192cu/include/rtw_eeprom.h +new file mode 100755 +index 0000000..9d31998 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_efuse.h b/drivers/net/wireless/rtl8192cu/include/rtw_efuse.h +new file mode 100755 +index 0000000..66be910 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_event.h b/drivers/net/wireless/rtl8192cu/include/rtw_event.h +new file mode 100755 +index 0000000..dd9f097 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_ht.h b/drivers/net/wireless/rtl8192cu/include/rtw_ht.h +new file mode 100755 +index 0000000..4dcad2b +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_io.h b/drivers/net/wireless/rtl8192cu/include/rtw_io.h +new file mode 100755 +index 0000000..b1f57c1 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_ioctl.h b/drivers/net/wireless/rtl8192cu/include/rtw_ioctl.h +new file mode 100755 +index 0000000..e6d34f0 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_ioctl_query.h b/drivers/net/wireless/rtl8192cu/include/rtw_ioctl_query.h +new file mode 100755 +index 0000000..e9ad16f1 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_ioctl_rtl.h b/drivers/net/wireless/rtl8192cu/include/rtw_ioctl_rtl.h +new file mode 100755 +index 0000000..1ea8f21 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_ioctl_set.h b/drivers/net/wireless/rtl8192cu/include/rtw_ioctl_set.h +new file mode 100755 +index 0000000..577af51 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_iol.h b/drivers/net/wireless/rtl8192cu/include/rtw_iol.h +new file mode 100755 +index 0000000..2750eb3 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_led.h b/drivers/net/wireless/rtl8192cu/include/rtw_led.h +new file mode 100755 +index 0000000..bef37df +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_mlme.h b/drivers/net/wireless/rtl8192cu/include/rtw_mlme.h +new file mode 100755 +index 0000000..05af290 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_mlme_ext.h b/drivers/net/wireless/rtl8192cu/include/rtw_mlme_ext.h +new file mode 100755 +index 0000000..d9a203f +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_mp.h b/drivers/net/wireless/rtl8192cu/include/rtw_mp.h +new file mode 100755 +index 0000000..a468714 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_mp_ioctl.h b/drivers/net/wireless/rtl8192cu/include/rtw_mp_ioctl.h +new file mode 100755 +index 0000000..e16df40 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_mp_phy_regdef.h b/drivers/net/wireless/rtl8192cu/include/rtw_mp_phy_regdef.h +new file mode 100755 +index 0000000..4906005 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_p2p.h b/drivers/net/wireless/rtl8192cu/include/rtw_p2p.h +new file mode 100755 +index 0000000..02edc6d +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_pwrctrl.h b/drivers/net/wireless/rtl8192cu/include/rtw_pwrctrl.h +new file mode 100755 +index 0000000..2b00beb +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_qos.h b/drivers/net/wireless/rtl8192cu/include/rtw_qos.h +new file mode 100755 +index 0000000..e35b77f +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_recv.h b/drivers/net/wireless/rtl8192cu/include/rtw_recv.h +new file mode 100755 +index 0000000..4208108 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_rf.h b/drivers/net/wireless/rtl8192cu/include/rtw_rf.h +new file mode 100755 +index 0000000..7414c1b6 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_security.h b/drivers/net/wireless/rtl8192cu/include/rtw_security.h +new file mode 100755 +index 0000000..02ef9b0 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_version.h b/drivers/net/wireless/rtl8192cu/include/rtw_version.h +new file mode 100644 +index 0000000..1a26560 +diff --git a/drivers/net/wireless/rtl8192cu/include/rtw_xmit.h b/drivers/net/wireless/rtl8192cu/include/rtw_xmit.h +new file mode 100755 +index 0000000..ef0c262 +diff --git a/drivers/net/wireless/rtl8192cu/include/sdio_hal.h b/drivers/net/wireless/rtl8192cu/include/sdio_hal.h +new file mode 100755 +index 0000000..51139bb +diff --git a/drivers/net/wireless/rtl8192cu/include/sdio_ops.h b/drivers/net/wireless/rtl8192cu/include/sdio_ops.h +new file mode 100755 +index 0000000..b1e9b63 +diff --git a/drivers/net/wireless/rtl8192cu/include/sdio_ops_ce.h b/drivers/net/wireless/rtl8192cu/include/sdio_ops_ce.h +new file mode 100755 +index 0000000..6b0c1a2 +diff --git a/drivers/net/wireless/rtl8192cu/include/sdio_ops_linux.h b/drivers/net/wireless/rtl8192cu/include/sdio_ops_linux.h +new file mode 100755 +index 0000000..c58ab08 +diff --git a/drivers/net/wireless/rtl8192cu/include/sdio_ops_xp.h b/drivers/net/wireless/rtl8192cu/include/sdio_ops_xp.h +new file mode 100755 +index 0000000..3569611 +diff --git a/drivers/net/wireless/rtl8192cu/include/sdio_osintf.h b/drivers/net/wireless/rtl8192cu/include/sdio_osintf.h +new file mode 100755 +index 0000000..099262b +diff --git a/drivers/net/wireless/rtl8192cu/include/sta_info.h b/drivers/net/wireless/rtl8192cu/include/sta_info.h +new file mode 100755 +index 0000000..8f01f21 +diff --git a/drivers/net/wireless/rtl8192cu/include/usb_hal.h b/drivers/net/wireless/rtl8192cu/include/usb_hal.h +new file mode 100755 +index 0000000..9cd21f3 +diff --git a/drivers/net/wireless/rtl8192cu/include/usb_ops.h b/drivers/net/wireless/rtl8192cu/include/usb_ops.h +new file mode 100755 +index 0000000..3868bc0 +diff --git a/drivers/net/wireless/rtl8192cu/include/usb_osintf.h b/drivers/net/wireless/rtl8192cu/include/usb_osintf.h +new file mode 100755 +index 0000000..8642aa2 +diff --git a/drivers/net/wireless/rtl8192cu/include/usb_vendor_req.h b/drivers/net/wireless/rtl8192cu/include/usb_vendor_req.h +new file mode 100755 +index 0000000..72864de +diff --git a/drivers/net/wireless/rtl8192cu/include/wifi.h b/drivers/net/wireless/rtl8192cu/include/wifi.h +new file mode 100755 +index 0000000..5ae1275 +diff --git a/drivers/net/wireless/rtl8192cu/include/wlan_bssdef.h b/drivers/net/wireless/rtl8192cu/include/wlan_bssdef.h +new file mode 100755 +index 0000000..fe555c6 +diff --git a/drivers/net/wireless/rtl8192cu/include/xmit_osdep.h b/drivers/net/wireless/rtl8192cu/include/xmit_osdep.h +new file mode 100755 +index 0000000..7d28d43 +diff --git a/drivers/net/wireless/rtl8192cu/os_dep/linux/ioctl_cfg80211.c b/drivers/net/wireless/rtl8192cu/os_dep/linux/ioctl_cfg80211.c +new file mode 100755 +index 0000000..b58e5c0 +diff --git a/drivers/net/wireless/rtl8192cu/os_dep/linux/ioctl_linux.c b/drivers/net/wireless/rtl8192cu/os_dep/linux/ioctl_linux.c +new file mode 100755 +index 0000000..7330160 +diff --git a/drivers/net/wireless/rtl8192cu/os_dep/linux/mlme_linux.c b/drivers/net/wireless/rtl8192cu/os_dep/linux/mlme_linux.c +new file mode 100755 +index 0000000..0175ea2 +diff --git a/drivers/net/wireless/rtl8192cu/os_dep/linux/os_intfs.c b/drivers/net/wireless/rtl8192cu/os_dep/linux/os_intfs.c +new file mode 100755 +index 0000000..61e4120 +diff --git a/drivers/net/wireless/rtl8192cu/os_dep/linux/pci_intf.c b/drivers/net/wireless/rtl8192cu/os_dep/linux/pci_intf.c +new file mode 100755 +index 0000000..0848297 +diff --git a/drivers/net/wireless/rtl8192cu/os_dep/linux/recv_linux.c b/drivers/net/wireless/rtl8192cu/os_dep/linux/recv_linux.c +new file mode 100755 +index 0000000..4a76c3f +diff --git a/drivers/net/wireless/rtl8192cu/os_dep/linux/rtw_android.c b/drivers/net/wireless/rtl8192cu/os_dep/linux/rtw_android.c +new file mode 100755 +index 0000000..aceaaa7 +diff --git a/drivers/net/wireless/rtl8192cu/os_dep/linux/sdio_intf.c b/drivers/net/wireless/rtl8192cu/os_dep/linux/sdio_intf.c +new file mode 100755 +index 0000000..52faefc +diff --git a/drivers/net/wireless/rtl8192cu/os_dep/linux/usb_intf.c b/drivers/net/wireless/rtl8192cu/os_dep/linux/usb_intf.c +new file mode 100755 +index 0000000..942ea08 +diff --git a/drivers/net/wireless/rtl8192cu/os_dep/linux/xmit_linux.c b/drivers/net/wireless/rtl8192cu/os_dep/linux/xmit_linux.c +new file mode 100755 +index 0000000..02eec93 +diff --git a/drivers/net/wireless/rtl8192cu/os_dep/osdep_service.c b/drivers/net/wireless/rtl8192cu/os_dep/osdep_service.c +new file mode 100755 +index 0000000..6e11379 +diff --git a/drivers/net/wireless/rtl8192cu/wlan0dhcp b/drivers/net/wireless/rtl8192cu/wlan0dhcp +new file mode 100755 +index 0000000..6043382 +diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig +index 7587796..4153631 100644 +--- a/drivers/spi/Kconfig ++++ b/drivers/spi/Kconfig +@@ -74,6 +74,14 @@ config SPI_ATMEL This selects a driver for the Atmel SPI Controller, present on many AT32 (AVR32) and AT91 (ARM) chips. @@ -29253,10 +31064,11 @@ diff -Naur linux-3.2.23/drivers/spi/Kconfig linux-rpi-bootc-3.2.23/drivers/spi/K config SPI_BFIN tristate "SPI controller driver for ADI Blackfin5xx" depends on BLACKFIN -diff -Naur linux-3.2.23/drivers/spi/Makefile linux-rpi-bootc-3.2.23/drivers/spi/Makefile ---- linux-3.2.23/drivers/spi/Makefile 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/spi/Makefile 2012-07-15 20:29:50.511674973 +0200 -@@ -14,6 +14,7 @@ +diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile +index 61c3261..2ff2985 100644 +--- a/drivers/spi/Makefile ++++ b/drivers/spi/Makefile +@@ -14,6 +14,7 @@ obj-$(CONFIG_SPI_ALTERA) += spi-altera.o obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o obj-$(CONFIG_SPI_ATH79) += spi-ath79.o obj-$(CONFIG_SPI_AU1550) += spi-au1550.o @@ -29264,10 +31076,12 @@ diff -Naur linux-3.2.23/drivers/spi/Makefile linux-rpi-bootc-3.2.23/drivers/spi/ obj-$(CONFIG_SPI_BFIN) += spi-bfin5xx.o obj-$(CONFIG_SPI_BFIN_SPORT) += spi-bfin-sport.o obj-$(CONFIG_SPI_BITBANG) += spi-bitbang.o -diff -Naur linux-3.2.23/drivers/spi/spi-bcm2708.c linux-rpi-bootc-3.2.23/drivers/spi/spi-bcm2708.c ---- linux-3.2.23/drivers/spi/spi-bcm2708.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/spi/spi-bcm2708.c 2012-07-15 20:29:50.590676460 +0200 -@@ -0,0 +1,579 @@ +diff --git a/drivers/spi/spi-bcm2708.c b/drivers/spi/spi-bcm2708.c +new file mode 100644 +index 0000000..ef8fef0 +--- /dev/null ++++ b/drivers/spi/spi-bcm2708.c +@@ -0,0 +1,594 @@ +/* + * Driver for Broadcom BCM2708 SPI Controllers + * @@ -29841,16 +31655,44 @@ diff -Naur linux-3.2.23/drivers/spi/spi-bcm2708.c linux-rpi-bootc-3.2.23/drivers + .probe = bcm2708_spi_probe, + .remove = __devexit_p(bcm2708_spi_remove), +}; -+module_platform_driver(bcm2708_spi_driver); ++ ++ ++static int __init bcm2708_spi_init(void) ++{ ++ return platform_driver_probe(&bcm2708_spi_driver, bcm2708_spi_probe); ++} ++module_init(bcm2708_spi_init); ++ ++static void __exit bcm2708_spi_exit(void) ++{ ++ platform_driver_unregister(&bcm2708_spi_driver); ++} ++module_exit(bcm2708_spi_exit); ++ ++ ++//module_platform_driver(bcm2708_spi_driver); + +MODULE_DESCRIPTION("SPI controller driver for Broadcom BCM2708"); +MODULE_AUTHOR("Chris Boot "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRV_NAME); -diff -Naur linux-3.2.23/drivers/usb/core/generic.c linux-rpi-bootc-3.2.23/drivers/usb/core/generic.c ---- linux-3.2.23/drivers/usb/core/generic.c 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/usb/core/generic.c 2012-07-15 20:29:20.586111884 +0200 -@@ -149,6 +149,7 @@ +diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile +index 75eca76..a6b7e41 100644 +--- a/drivers/usb/Makefile ++++ b/drivers/usb/Makefile +@@ -23,6 +23,7 @@ obj-$(CONFIG_USB_U132_HCD) += host/ + obj-$(CONFIG_USB_R8A66597_HCD) += host/ + obj-$(CONFIG_USB_HWA_HCD) += host/ + obj-$(CONFIG_USB_ISP1760_HCD) += host/ ++obj-$(CONFIG_USB_DWCOTG) += host/ + obj-$(CONFIG_USB_IMX21_HCD) += host/ + obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/ + +diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c +index 69ecd3c..0431b4e 100644 +--- a/drivers/usb/core/generic.c ++++ b/drivers/usb/core/generic.c +@@ -149,6 +149,7 @@ int usb_choose_configuration(struct usb_device *udev) dev_warn(&udev->dev, "no configuration chosen from %d choice%s\n", num_configs, plural(num_configs)); @@ -29858,10 +31700,19 @@ diff -Naur linux-3.2.23/drivers/usb/core/generic.c linux-rpi-bootc-3.2.23/driver } return i; } -diff -Naur linux-3.2.23/drivers/usb/core/hub.c linux-rpi-bootc-3.2.23/drivers/usb/core/hub.c ---- linux-3.2.23/drivers/usb/core/hub.c 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/usb/core/hub.c 2012-07-15 20:29:20.587111902 +0200 -@@ -1075,6 +1075,8 @@ +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index 52340cc..e00d65f 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -24,7 +24,6 @@ + #include + #include + #include +-#include + + #include + #include +@@ -1076,6 +1075,8 @@ static int hub_configure(struct usb_hub *hub, INIT_WORK(&hub->tt.clear_work, hub_tt_work); switch (hdev->descriptor.bDeviceProtocol) { case 0: @@ -29870,7 +31721,7 @@ diff -Naur linux-3.2.23/drivers/usb/core/hub.c linux-rpi-bootc-3.2.23/drivers/us break; case 1: dev_dbg(hub_dev, "Single TT\n"); -@@ -1091,6 +1093,7 @@ +@@ -1092,6 +1093,7 @@ static int hub_configure(struct usb_hub *hub, hub->tt.hub = hdev; break; case 3: @@ -29878,7 +31729,7 @@ diff -Naur linux-3.2.23/drivers/usb/core/hub.c linux-rpi-bootc-3.2.23/drivers/us /* USB 3.0 hubs don't have a TT */ break; default: -@@ -1720,6 +1723,12 @@ +@@ -1721,6 +1723,12 @@ static inline void announce_device(struct usb_device *udev) { } #endif #ifdef CONFIG_USB_OTG @@ -29891,7 +31742,7 @@ diff -Naur linux-3.2.23/drivers/usb/core/hub.c linux-rpi-bootc-3.2.23/drivers/us #include "otg_whitelist.h" #endif -@@ -1774,9 +1783,15 @@ +@@ -1775,9 +1783,15 @@ static int usb_enumerate_device_otg(struct usb_device *udev) dev_info(&udev->dev, "can't set HNP mode: %d\n", err); @@ -29908,7 +31759,7 @@ diff -Naur linux-3.2.23/drivers/usb/core/hub.c linux-rpi-bootc-3.2.23/drivers/us } } -@@ -1785,12 +1800,27 @@ +@@ -1786,12 +1800,27 @@ static int usb_enumerate_device_otg(struct usb_device *udev) /* Maybe it can talk to us, though we can't talk to it. * (Includes HNP test device.) */ @@ -29939,7 +31790,34 @@ diff -Naur linux-3.2.23/drivers/usb/core/hub.c linux-rpi-bootc-3.2.23/drivers/us goto fail; } fail: -@@ -2981,7 +3011,9 @@ +@@ -1898,14 +1927,6 @@ int usb_new_device(struct usb_device *udev) + /* Tell the world! */ + announce_device(udev); + +- if (udev->serial) +- add_device_randomness(udev->serial, strlen(udev->serial)); +- if (udev->product) +- add_device_randomness(udev->product, strlen(udev->product)); +- if (udev->manufacturer) +- add_device_randomness(udev->manufacturer, +- strlen(udev->manufacturer)); +- + device_enable_async_suspend(&udev->dev); + /* Register the device. The device driver is responsible + * for configuring the device and invoking the add-device +@@ -2442,9 +2463,9 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) + status = 0; + } else { + /* device has up to 10 msec to fully suspend */ +- dev_dbg(&udev->dev, "usb %ssuspend, wakeup %d\n", ++ /*dev_dbg(&udev->dev, "usb %ssuspend, wakeup %d\n", + (PMSG_IS_AUTO(msg) ? "auto-" : ""), +- udev->do_remote_wakeup); ++ udev->do_remote_wakeup);*/ + usb_set_device_state(udev, USB_STATE_SUSPENDED); + msleep(10); + } +@@ -2994,7 +3015,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, buf->bMaxPacketSize0 = 0; r = usb_control_msg(udev, usb_rcvaddr0pipe(), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, @@ -29950,7 +31828,7 @@ diff -Naur linux-3.2.23/drivers/usb/core/hub.c linux-rpi-bootc-3.2.23/drivers/us buf, GET_DESCRIPTOR_BUFSIZE, initial_descriptor_timeout); switch (buf->bMaxPacketSize0) { -@@ -3427,8 +3459,10 @@ +@@ -3440,8 +3463,10 @@ loop: release_devnum(udev); hub_free_dev(udev); usb_put_dev(udev); @@ -29963,10 +31841,11 @@ diff -Naur linux-3.2.23/drivers/usb/core/hub.c linux-rpi-bootc-3.2.23/drivers/us } if (hub->hdev->parent || !hcd->driver->port_handed_over || -diff -Naur linux-3.2.23/drivers/usb/core/message.c linux-rpi-bootc-3.2.23/drivers/usb/core/message.c ---- linux-3.2.23/drivers/usb/core/message.c 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/usb/core/message.c 2012-07-15 20:29:20.581111790 +0200 -@@ -1838,6 +1838,85 @@ +diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c +index ef116a5..113b44e 100644 +--- a/drivers/usb/core/message.c ++++ b/drivers/usb/core/message.c +@@ -1838,6 +1838,85 @@ free_interfaces: if (cp->string == NULL && !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) cp->string = usb_cache_string(dev, cp->desc.iConfiguration); @@ -30052,9 +31931,10 @@ diff -Naur linux-3.2.23/drivers/usb/core/message.c linux-rpi-bootc-3.2.23/driver /* Now that all the interfaces are set up, register them * to trigger binding of drivers to interfaces. probe() -diff -Naur linux-3.2.23/drivers/usb/core/otg_whitelist.h linux-rpi-bootc-3.2.23/drivers/usb/core/otg_whitelist.h ---- linux-3.2.23/drivers/usb/core/otg_whitelist.h 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/usb/core/otg_whitelist.h 2012-07-15 20:29:20.586111884 +0200 +diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h +index e8cdce5..3a0da17 100644 +--- a/drivers/usb/core/otg_whitelist.h ++++ b/drivers/usb/core/otg_whitelist.h @@ -19,33 +19,82 @@ static struct usb_device_id whitelist_table [] = { @@ -30144,20 +32024,14 @@ diff -Naur linux-3.2.23/drivers/usb/core/otg_whitelist.h linux-rpi-bootc-3.2.23/ static int is_targeted(struct usb_device *dev) { struct usb_device_id *id = whitelist_table; -@@ -55,58 +104,83 @@ +@@ -55,58 +104,83 @@ static int is_targeted(struct usb_device *dev) return 1; /* HNP test device is _never_ targeted (see OTG spec 6.6.6) */ - if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a && - le16_to_cpu(dev->descriptor.idProduct) == 0xbadd)) - return 0; -+ if (dev->descriptor.idVendor == 0x1a0a && -+ dev->descriptor.idProduct == 0xbadd) { -+ return 0; -+ } else if (!enable_whitelist) { -+ return 1; -+ } else { - +- - /* NOTE: can't use usb_match_id() since interface caches - * aren't set up yet. this is cut/paste from that code. - */ @@ -30191,6 +32065,13 @@ diff -Naur linux-3.2.23/drivers/usb/core/otg_whitelist.h linux-rpi-bootc-3.2.23/ - if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) && - (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) - continue; ++ if (dev->descriptor.idVendor == 0x1a0a && ++ dev->descriptor.idProduct == 0xbadd) { ++ return 0; ++ } else if (!enable_whitelist) { ++ return 1; ++ } else { ++ +#ifdef DEBUG + dev_dbg(&dev->dev, "device V:%04x P:%04x DC:%04x SC:%04x PR:%04x \n", + dev->descriptor.idVendor, @@ -30270,10 +32151,28 @@ diff -Naur linux-3.2.23/drivers/usb/core/otg_whitelist.h linux-rpi-bootc-3.2.23/ #endif } -diff -Naur linux-3.2.23/drivers/usb/gadget/file_storage.c linux-rpi-bootc-3.2.23/drivers/usb/gadget/file_storage.c ---- linux-3.2.23/drivers/usb/gadget/file_storage.c 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/usb/gadget/file_storage.c 2012-07-15 20:29:20.327107010 +0200 -@@ -573,8 +573,37 @@ +diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig +index 23a4473..12d27d2 100644 +--- a/drivers/usb/gadget/Kconfig ++++ b/drivers/usb/gadget/Kconfig +@@ -552,6 +552,12 @@ config USB_GADGET_SUPERSPEED + depends on USB_GADGET + depends on USB_GADGET_DUALSPEED + ++config USB_DWC_OTG_LPM ++ boolean "Enable LPM support" ++ depends on USB && EXPERIMENTAL ++ help ++ Enables LPM support. ++ + # + # USB Gadget Drivers + # +diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c +index db2d607..5090ae6 100644 +--- a/drivers/usb/gadget/file_storage.c ++++ b/drivers/usb/gadget/file_storage.c +@@ -573,8 +573,37 @@ config_desc = { .iConfiguration = FSG_STRING_CONFIG, .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, .bMaxPower = CONFIG_USB_GADGET_VBUS_DRAW / 2, @@ -30311,7 +32210,7 @@ diff -Naur linux-3.2.23/drivers/usb/gadget/file_storage.c linux-rpi-bootc-3.2.23 static struct usb_qualifier_descriptor dev_qualifier = { -@@ -984,13 +1013,29 @@ +@@ -984,13 +1013,29 @@ get_config: break; case USB_DT_BOS: @@ -30342,7 +32241,7 @@ diff -Naur linux-3.2.23/drivers/usb/gadget/file_storage.c linux-rpi-bootc-3.2.23 break; /* One config, two speeds */ -@@ -2640,6 +2685,9 @@ +@@ -2640,6 +2685,9 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) fsg_set_halt(fsg, fsg->bulk_out); halt_bulk_in_endpoint(fsg); } @@ -30352,7 +32251,7 @@ diff -Naur linux-3.2.23/drivers/usb/gadget/file_storage.c linux-rpi-bootc-3.2.23 return -EINVAL; } -@@ -2991,7 +3039,8 @@ +@@ -2991,7 +3039,8 @@ static void handle_exception(struct fsg_dev *fsg) * bulk endpoint, clear the halt now. (The SuperH UDC * requires this.) */ if (test_and_clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) @@ -30362,7 +32261,7 @@ diff -Naur linux-3.2.23/drivers/usb/gadget/file_storage.c linux-rpi-bootc-3.2.23 if (transport_is_bbb()) { if (fsg->ep0_req_tag == exception_req_tag) -@@ -3065,6 +3114,9 @@ +@@ -3065,6 +3114,9 @@ static int fsg_main_thread(void *fsg_) * that expects a __user pointer and it will work okay. */ set_fs(get_ds()); @@ -30372,7 +32271,7 @@ diff -Naur linux-3.2.23/drivers/usb/gadget/file_storage.c linux-rpi-bootc-3.2.23 /* The main loop */ while (fsg->state != FSG_STATE_TERMINATED) { if (exception_in_progress(fsg) || signal_pending(current)) { -@@ -3212,6 +3264,13 @@ +@@ -3212,6 +3264,13 @@ static int __init check_parameters(struct fsg_dev *fsg) gcnum = usb_gadget_controller_number(fsg->gadget); if (gcnum >= 0) mod_data.release = 0x0300 + gcnum; @@ -30386,7 +32285,7 @@ diff -Naur linux-3.2.23/drivers/usb/gadget/file_storage.c linux-rpi-bootc-3.2.23 else { WARNING(fsg, "controller '%s' not recognized\n", fsg->gadget->name); -@@ -3473,6 +3532,13 @@ +@@ -3473,6 +3532,13 @@ static int __init fsg_bind(struct usb_gadget *gadget) rc = -ENOMEM; @@ -30400,31 +32299,652 @@ diff -Naur linux-3.2.23/drivers/usb/gadget/file_storage.c linux-rpi-bootc-3.2.23 /* Allocate the request and buffer for endpoint 0 */ fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL); if (!req) -diff -Naur linux-3.2.23/drivers/usb/gadget/Kconfig linux-rpi-bootc-3.2.23/drivers/usb/gadget/Kconfig ---- linux-3.2.23/drivers/usb/gadget/Kconfig 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/usb/gadget/Kconfig 2012-07-15 20:29:20.412108609 +0200 -@@ -552,6 +552,12 @@ - depends on USB_GADGET - depends on USB_GADGET_DUALSPEED +diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig +index 060e0e2..c03ee48 100644 +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -556,6 +556,19 @@ config USB_HWA_HCD + To compile this driver a module, choose M here: the module + will be called "hwa-hc". -+config USB_DWC_OTG_LPM -+ boolean "Enable LPM support" -+ depends on USB && EXPERIMENTAL ++config USB_DWCOTG ++ tristate "Synopsis DWC host support" ++ depends on USB + help -+ Enables LPM support. ++ The Synopsis DWC controller is a dual-role ++ host/peripheral/OTG ("On The Go") USB controllers. + - # - # USB Gadget Drivers - # -diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c ---- linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c 2012-07-15 20:29:18.989081834 +0200 -@@ -0,0 +1,506 @@ ++ Enable this option to support this IP in host controller mode. ++ If unsure, say N. ++ ++ To compile this driver as a module, choose M here: the ++ modules built will be called dwc_otg and dwc_common_port. ++ + config USB_IMX21_HCD + tristate "i.MX21 HCD support" + depends on USB && ARM && ARCH_MXC +diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile +index 7ca290f..802dda6 100644 +--- a/drivers/usb/host/Makefile ++++ b/drivers/usb/host/Makefile +@@ -33,6 +33,8 @@ obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o + obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o + obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o + obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o ++ ++obj-$(CONFIG_USB_DWCOTG) += dwc_otg/ dwc_common_port/ + obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o + obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o + obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o +diff --git a/drivers/usb/host/dwc_common_port/Makefile b/drivers/usb/host/dwc_common_port/Makefile +new file mode 100644 +index 0000000..203c7ea +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/Makefile +@@ -0,0 +1,58 @@ ++# ++# Makefile for DWC_common library ++# ++ ++ifneq ($(KERNELRELEASE),) ++ ++EXTRA_CFLAGS += -DDWC_LINUX ++#EXTRA_CFLAGS += -DDEBUG ++#EXTRA_CFLAGS += -DDWC_DEBUG_REGS ++#EXTRA_CFLAGS += -DDWC_DEBUG_MEMORY ++ ++EXTRA_CFLAGS += -DDWC_LIBMODULE ++EXTRA_CFLAGS += -DDWC_CCLIB ++#EXTRA_CFLAGS += -DDWC_CRYPTOLIB ++EXTRA_CFLAGS += -DDWC_NOTIFYLIB ++EXTRA_CFLAGS += -DDWC_UTFLIB ++ ++obj-$(CONFIG_USB_DWCOTG) += dwc_common_port_lib.o ++dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \ ++ dwc_crypto.o dwc_notifier.o \ ++ dwc_common_linux.o dwc_mem.o ++ ++kernrelwd := $(subst ., ,$(KERNELRELEASE)) ++kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd)) ++ ++ifneq ($(kernrel3),2.6.20) ++# grayg - I only know that we use EXTRA_CFLAGS in 2.6.31 actually ++EXTRA_CFLAGS += $(CPPFLAGS) ++endif ++ ++else ++ ++ifeq ($(KDIR),) ++$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment) ++endif ++ ++ifeq ($(ARCH),) ++$(error Must give "ARCH=" on command line or in environment. Also, if \ ++ cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-") ++endif ++ ++ifeq ($(DOXYGEN),) ++DOXYGEN := doxygen ++endif ++ ++default: ++ $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++docs: $(wildcard *.[hc]) doc/doxygen.cfg ++ $(DOXYGEN) doc/doxygen.cfg ++ ++tags: $(wildcard *.[hc]) ++ $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h) ++ ++endif ++ ++clean: ++ rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/ +diff --git a/drivers/usb/host/dwc_common_port/Makefile.fbsd b/drivers/usb/host/dwc_common_port/Makefile.fbsd +new file mode 100644 +index 0000000..45db991 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/Makefile.fbsd +@@ -0,0 +1,17 @@ ++CFLAGS += -I/sys/i386/compile/GENERIC -I/sys/i386/include -I/usr/include ++CFLAGS += -DDWC_FREEBSD ++CFLAGS += -DDEBUG ++#CFLAGS += -DDWC_DEBUG_REGS ++#CFLAGS += -DDWC_DEBUG_MEMORY ++ ++#CFLAGS += -DDWC_LIBMODULE ++#CFLAGS += -DDWC_CCLIB ++#CFLAGS += -DDWC_CRYPTOLIB ++#CFLAGS += -DDWC_NOTIFYLIB ++#CFLAGS += -DDWC_UTFLIB ++ ++KMOD = dwc_common_port_lib ++SRCS = dwc_cc.c dwc_modpow.c dwc_dh.c dwc_crypto.c dwc_notifier.c \ ++ dwc_common_fbsd.c dwc_mem.c ++ ++.include +diff --git a/drivers/usb/host/dwc_common_port/Makefile.linux b/drivers/usb/host/dwc_common_port/Makefile.linux +new file mode 100644 +index 0000000..961df3f +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/Makefile.linux +@@ -0,0 +1,49 @@ ++# ++# Makefile for DWC_common library ++# ++ifneq ($(KERNELRELEASE),) ++ ++EXTRA_CFLAGS += -DDWC_LINUX ++#EXTRA_CFLAGS += -DDEBUG ++#EXTRA_CFLAGS += -DDWC_DEBUG_REGS ++#EXTRA_CFLAGS += -DDWC_DEBUG_MEMORY ++ ++EXTRA_CFLAGS += -DDWC_LIBMODULE ++EXTRA_CFLAGS += -DDWC_CCLIB ++EXTRA_CFLAGS += -DDWC_CRYPTOLIB ++EXTRA_CFLAGS += -DDWC_NOTIFYLIB ++EXTRA_CFLAGS += -DDWC_UTFLIB ++ ++obj-m := dwc_common_port_lib.o ++dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \ ++ dwc_crypto.o dwc_notifier.o \ ++ dwc_common_linux.o dwc_mem.o ++ ++else ++ ++ifeq ($(KDIR),) ++$(error Must give "KDIR=/path/to/kernel/source" on command line or in environment) ++endif ++ ++ifeq ($(ARCH),) ++$(error Must give "ARCH=" on command line or in environment. Also, if \ ++ cross-compiling, must give "CROSS_COMPILE=/path/to/compiler/plus/tool-prefix-") ++endif ++ ++ifeq ($(DOXYGEN),) ++DOXYGEN := doxygen ++endif ++ ++default: ++ $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++docs: $(wildcard *.[hc]) doc/doxygen.cfg ++ $(DOXYGEN) doc/doxygen.cfg ++ ++tags: $(wildcard *.[hc]) ++ $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h) ++ ++endif ++ ++clean: ++ rm -rf *.o *.ko .*.cmd *.mod.c .*.o.d .*.o.tmp modules.order Module.markers Module.symvers .tmp_versions/ +diff --git a/drivers/usb/host/dwc_common_port/changes.txt b/drivers/usb/host/dwc_common_port/changes.txt +new file mode 100644 +index 0000000..6740702 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/changes.txt +@@ -0,0 +1,174 @@ ++ ++dwc_read_reg32() and friends now take an additional parameter, a pointer to an ++IO context struct. The IO context struct should live in an os-dependent struct ++in your driver. As an example, the dwc_usb3 driver has an os-dependent struct ++named 'os_dep' embedded in the main device struct. So there these calls look ++like this: ++ ++ dwc_read_reg32(&usb3_dev->os_dep.ioctx, &pcd->dev_global_regs->dcfg); ++ ++ dwc_write_reg32(&usb3_dev->os_dep.ioctx, ++ &pcd->dev_global_regs->dcfg, 0); ++ ++Note that for the existing Linux driver ports, it is not necessary to actually ++define the 'ioctx' member in the os-dependent struct. Since Linux does not ++require an IO context, its macros for dwc_read_reg32() and friends do not ++use the context pointer, so it is optimized away by the compiler. But it is ++necessary to add the pointer parameter to all of the call sites, to be ready ++for any future ports (such as FreeBSD) which do require an IO context. ++ ++ ++Similarly, dwc_alloc(), dwc_alloc_atomic(), dwc_strdup(), and dwc_free() now ++take an additional parameter, a pointer to a memory context. Examples: ++ ++ addr = dwc_alloc(&usb3_dev->os_dep.memctx, size); ++ ++ dwc_free(&usb3_dev->os_dep.memctx, addr); ++ ++Again, for the Linux ports, it is not necessary to actually define the memctx ++member, but it is necessary to add the pointer parameter to all of the call ++sites. ++ ++ ++Same for dwc_dma_alloc() and dwc_dma_free(). Examples: ++ ++ virt_addr = dwc_dma_alloc(&usb3_dev->os_dep.dmactx, size, &phys_addr); ++ ++ dwc_dma_free(&usb3_dev->os_dep.dmactx, size, virt_addr, phys_addr); ++ ++ ++Same for dwc_mutex_alloc() and dwc_mutex_free(). Examples: ++ ++ mutex = dwc_mutex_alloc(&usb3_dev->os_dep.mtxctx); ++ ++ dwc_mutex_free(&usb3_dev->os_dep.mtxctx, mutex); ++ ++ ++Same for dwc_spinlock_alloc() and dwc_spinlock_free(). Examples: ++ ++ lock = dwc_spinlock_alloc(&usb3_dev->osdep.splctx); ++ ++ dwc_spinlock_free(&usb3_dev->osdep.splctx, lock); ++ ++ ++Same for dwc_timer_alloc(). Example: ++ ++ timer = dwc_timer_alloc(&usb3_dev->os_dep.tmrctx, "dwc_usb3_tmr1", ++ cb_func, cb_data); ++ ++ ++Same for dwc_waitq_alloc(). Example: ++ ++ waitq = dwc_waitq_alloc(&usb3_dev->os_dep.wtqctx); ++ ++ ++Same for dwc_thread_run(). Example: ++ ++ thread = dwc_thread_run(&usb3_dev->os_dep.thdctx, func, ++ "dwc_usb3_thd1", data); ++ ++ ++Same for dwc_workq_alloc(). Example: ++ ++ workq = dwc_workq_alloc(&usb3_dev->osdep.wkqctx, "dwc_usb3_wkq1"); ++ ++ ++Same for dwc_task_alloc(). Example: ++ ++ task = dwc_task_alloc(&usb3_dev->os_dep.tskctx, "dwc_usb3_tsk1", ++ cb_func, cb_data); ++ ++ ++In addition to the context pointer additions, a few core functions have had ++other changes made to their parameters: ++ ++The 'flags' parameter to dwc_spinlock_irqsave() and dwc_spinunlock_irqrestore() ++has been changed from a uint64_t to a dwc_irqflags_t. ++ ++dwc_thread_should_stop() now takes a 'dwc_thread_t *' parameter, because the ++FreeBSD equivalent of that function requires it. ++ ++And, in addition to the context pointer, dwc_task_alloc() also adds a ++'char *name' parameter, to be consistent with dwc_thread_run() and ++dwc_workq_alloc(), and because the FreeBSD equivalent of that function ++requires a unique name. ++ ++ ++Here is a complete list of the core functions that now take a pointer to a ++context as their first parameter: ++ ++ dwc_read_reg32 ++ dwc_read_reg64 ++ dwc_write_reg32 ++ dwc_write_reg64 ++ dwc_modify_reg32 ++ dwc_modify_reg64 ++ dwc_alloc ++ dwc_alloc_atomic ++ dwc_strdup ++ dwc_free ++ dwc_dma_alloc ++ dwc_dma_free ++ dwc_mutex_alloc ++ dwc_mutex_free ++ dwc_spinlock_alloc ++ dwc_spinlock_free ++ dwc_timer_alloc ++ dwc_waitq_alloc ++ dwc_thread_run ++ dwc_workq_alloc ++ dwc_task_alloc Also adds a 'char *name' as its 2nd parameter ++ ++And here are the core functions that have other changes to their parameters: ++ ++ dwc_spinlock_irqsave 'flags' param is now a 'dwc_irqflags_t *' ++ dwc_spinunlock_irqrestore 'flags' param is now a 'dwc_irqflags_t' ++ dwc_thread_should_stop Adds a 'dwc_thread_t *' parameter ++ ++ ++ ++The changes to the core functions also require some of the other library ++functions to change: ++ ++ dwc_cc_if_alloc() and dwc_cc_if_free() now take a 'void *memctx' ++ (for memory allocation) as the 1st param and a 'void *mtxctx' ++ (for mutex allocation) as the 2nd param. ++ ++ dwc_cc_clear(), dwc_cc_add(), dwc_cc_change(), dwc_cc_remove(), ++ dwc_cc_data_for_save(), and dwc_cc_restore_from_data() now take a ++ 'void *memctx' as the 1st param. ++ ++ dwc_dh_modpow(), dwc_dh_pk(), and dwc_dh_derive_keys() now take a ++ 'void *memctx' as the 1st param. ++ ++ dwc_modpow() now takes a 'void *memctx' as the 1st param. ++ ++ dwc_alloc_notification_manager() now takes a 'void *memctx' as the ++ 1st param and a 'void *wkqctx' (for work queue allocation) as the 2nd ++ param, and also now returns an integer value that is non-zero if ++ allocation of its data structures or work queue fails. ++ ++ dwc_register_notifier() now takes a 'void *memctx' as the 1st param. ++ ++ dwc_memory_debug_start() now takes a 'void *mem_ctx' as the first ++ param, and also now returns an integer value that is non-zero if ++ allocation of its data structures fails. ++ ++ ++ ++Other miscellaneous changes: ++ ++The DEBUG_MEMORY and DEBUG_REGS #define's have been renamed to ++DWC_DEBUG_MEMORY and DWC_DEBUG_REGS. ++ ++The following #define's have been added to allow selectively compiling library ++features: ++ ++ DWC_CCLIB ++ DWC_CRYPTOLIB ++ DWC_NOTIFYLIB ++ DWC_UTFLIB ++ ++A DWC_LIBMODULE #define has also been added. If this is not defined, then the ++module code in dwc_common_linux.c is not compiled in. This allows linking the ++library code directly into a driver module, instead of as a standalone module. +diff --git a/drivers/usb/host/dwc_common_port/doc/doxygen.cfg b/drivers/usb/host/dwc_common_port/doc/doxygen.cfg +new file mode 100644 +index 0000000..605b9da +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/doc/doxygen.cfg +@@ -0,0 +1,270 @@ ++# Doxyfile 1.4.5 ++ ++#--------------------------------------------------------------------------- ++# Project related configuration options ++#--------------------------------------------------------------------------- ++PROJECT_NAME = "Synopsys DWC Portability and Common Library for UWB" ++PROJECT_NUMBER = ++OUTPUT_DIRECTORY = doc ++CREATE_SUBDIRS = NO ++OUTPUT_LANGUAGE = English ++BRIEF_MEMBER_DESC = YES ++REPEAT_BRIEF = YES ++ABBREVIATE_BRIEF = "The $name class" \ ++ "The $name widget" \ ++ "The $name file" \ ++ is \ ++ provides \ ++ specifies \ ++ contains \ ++ represents \ ++ a \ ++ an \ ++ the ++ALWAYS_DETAILED_SEC = YES ++INLINE_INHERITED_MEMB = NO ++FULL_PATH_NAMES = NO ++STRIP_FROM_PATH = .. ++STRIP_FROM_INC_PATH = ++SHORT_NAMES = NO ++JAVADOC_AUTOBRIEF = YES ++MULTILINE_CPP_IS_BRIEF = NO ++DETAILS_AT_TOP = YES ++INHERIT_DOCS = YES ++SEPARATE_MEMBER_PAGES = NO ++TAB_SIZE = 8 ++ALIASES = ++OPTIMIZE_OUTPUT_FOR_C = YES ++OPTIMIZE_OUTPUT_JAVA = NO ++BUILTIN_STL_SUPPORT = NO ++DISTRIBUTE_GROUP_DOC = NO ++SUBGROUPING = NO ++#--------------------------------------------------------------------------- ++# Build related configuration options ++#--------------------------------------------------------------------------- ++EXTRACT_ALL = NO ++EXTRACT_PRIVATE = NO ++EXTRACT_STATIC = YES ++EXTRACT_LOCAL_CLASSES = NO ++EXTRACT_LOCAL_METHODS = NO ++HIDE_UNDOC_MEMBERS = NO ++HIDE_UNDOC_CLASSES = NO ++HIDE_FRIEND_COMPOUNDS = NO ++HIDE_IN_BODY_DOCS = NO ++INTERNAL_DOCS = NO ++CASE_SENSE_NAMES = YES ++HIDE_SCOPE_NAMES = NO ++SHOW_INCLUDE_FILES = NO ++INLINE_INFO = YES ++SORT_MEMBER_DOCS = NO ++SORT_BRIEF_DOCS = NO ++SORT_BY_SCOPE_NAME = NO ++GENERATE_TODOLIST = YES ++GENERATE_TESTLIST = YES ++GENERATE_BUGLIST = YES ++GENERATE_DEPRECATEDLIST= YES ++ENABLED_SECTIONS = ++MAX_INITIALIZER_LINES = 30 ++SHOW_USED_FILES = YES ++SHOW_DIRECTORIES = YES ++FILE_VERSION_FILTER = ++#--------------------------------------------------------------------------- ++# configuration options related to warning and progress messages ++#--------------------------------------------------------------------------- ++QUIET = YES ++WARNINGS = YES ++WARN_IF_UNDOCUMENTED = NO ++WARN_IF_DOC_ERROR = YES ++WARN_NO_PARAMDOC = YES ++WARN_FORMAT = "$file:$line: $text" ++WARN_LOGFILE = ++#--------------------------------------------------------------------------- ++# configuration options related to the input files ++#--------------------------------------------------------------------------- ++INPUT = . ++FILE_PATTERNS = *.c \ ++ *.cc \ ++ *.cxx \ ++ *.cpp \ ++ *.c++ \ ++ *.d \ ++ *.java \ ++ *.ii \ ++ *.ixx \ ++ *.ipp \ ++ *.i++ \ ++ *.inl \ ++ *.h \ ++ *.hh \ ++ *.hxx \ ++ *.hpp \ ++ *.h++ \ ++ *.idl \ ++ *.odl \ ++ *.cs \ ++ *.php \ ++ *.php3 \ ++ *.inc \ ++ *.m \ ++ *.mm \ ++ *.dox \ ++ *.py \ ++ *.C \ ++ *.CC \ ++ *.C++ \ ++ *.II \ ++ *.I++ \ ++ *.H \ ++ *.HH \ ++ *.H++ \ ++ *.CS \ ++ *.PHP \ ++ *.PHP3 \ ++ *.M \ ++ *.MM \ ++ *.PY ++RECURSIVE = NO ++EXCLUDE = ++EXCLUDE_SYMLINKS = NO ++EXCLUDE_PATTERNS = ++EXAMPLE_PATH = ++EXAMPLE_PATTERNS = * ++EXAMPLE_RECURSIVE = NO ++IMAGE_PATH = ++INPUT_FILTER = ++FILTER_PATTERNS = ++FILTER_SOURCE_FILES = NO ++#--------------------------------------------------------------------------- ++# configuration options related to source browsing ++#--------------------------------------------------------------------------- ++SOURCE_BROWSER = NO ++INLINE_SOURCES = NO ++STRIP_CODE_COMMENTS = YES ++REFERENCED_BY_RELATION = YES ++REFERENCES_RELATION = YES ++USE_HTAGS = NO ++VERBATIM_HEADERS = NO ++#--------------------------------------------------------------------------- ++# configuration options related to the alphabetical class index ++#--------------------------------------------------------------------------- ++ALPHABETICAL_INDEX = NO ++COLS_IN_ALPHA_INDEX = 5 ++IGNORE_PREFIX = ++#--------------------------------------------------------------------------- ++# configuration options related to the HTML output ++#--------------------------------------------------------------------------- ++GENERATE_HTML = YES ++HTML_OUTPUT = html ++HTML_FILE_EXTENSION = .html ++HTML_HEADER = ++HTML_FOOTER = ++HTML_STYLESHEET = ++HTML_ALIGN_MEMBERS = YES ++GENERATE_HTMLHELP = NO ++CHM_FILE = ++HHC_LOCATION = ++GENERATE_CHI = NO ++BINARY_TOC = NO ++TOC_EXPAND = NO ++DISABLE_INDEX = NO ++ENUM_VALUES_PER_LINE = 4 ++GENERATE_TREEVIEW = YES ++TREEVIEW_WIDTH = 250 ++#--------------------------------------------------------------------------- ++# configuration options related to the LaTeX output ++#--------------------------------------------------------------------------- ++GENERATE_LATEX = NO ++LATEX_OUTPUT = latex ++LATEX_CMD_NAME = latex ++MAKEINDEX_CMD_NAME = makeindex ++COMPACT_LATEX = NO ++PAPER_TYPE = a4wide ++EXTRA_PACKAGES = ++LATEX_HEADER = ++PDF_HYPERLINKS = NO ++USE_PDFLATEX = NO ++LATEX_BATCHMODE = NO ++LATEX_HIDE_INDICES = NO ++#--------------------------------------------------------------------------- ++# configuration options related to the RTF output ++#--------------------------------------------------------------------------- ++GENERATE_RTF = NO ++RTF_OUTPUT = rtf ++COMPACT_RTF = NO ++RTF_HYPERLINKS = NO ++RTF_STYLESHEET_FILE = ++RTF_EXTENSIONS_FILE = ++#--------------------------------------------------------------------------- ++# configuration options related to the man page output ++#--------------------------------------------------------------------------- ++GENERATE_MAN = NO ++MAN_OUTPUT = man ++MAN_EXTENSION = .3 ++MAN_LINKS = NO ++#--------------------------------------------------------------------------- ++# configuration options related to the XML output ++#--------------------------------------------------------------------------- ++GENERATE_XML = NO ++XML_OUTPUT = xml ++XML_SCHEMA = ++XML_DTD = ++XML_PROGRAMLISTING = YES ++#--------------------------------------------------------------------------- ++# configuration options for the AutoGen Definitions output ++#--------------------------------------------------------------------------- ++GENERATE_AUTOGEN_DEF = NO ++#--------------------------------------------------------------------------- ++# configuration options related to the Perl module output ++#--------------------------------------------------------------------------- ++GENERATE_PERLMOD = NO ++PERLMOD_LATEX = NO ++PERLMOD_PRETTY = YES ++PERLMOD_MAKEVAR_PREFIX = ++#--------------------------------------------------------------------------- ++# Configuration options related to the preprocessor ++#--------------------------------------------------------------------------- ++ENABLE_PREPROCESSING = YES ++MACRO_EXPANSION = NO ++EXPAND_ONLY_PREDEF = NO ++SEARCH_INCLUDES = YES ++INCLUDE_PATH = ++INCLUDE_FILE_PATTERNS = ++PREDEFINED = DEBUG DEBUG_MEMORY ++EXPAND_AS_DEFINED = ++SKIP_FUNCTION_MACROS = YES ++#--------------------------------------------------------------------------- ++# Configuration::additions related to external references ++#--------------------------------------------------------------------------- ++TAGFILES = ++GENERATE_TAGFILE = ++ALLEXTERNALS = NO ++EXTERNAL_GROUPS = YES ++PERL_PATH = /usr/bin/perl ++#--------------------------------------------------------------------------- ++# Configuration options related to the dot tool ++#--------------------------------------------------------------------------- ++CLASS_DIAGRAMS = YES ++HIDE_UNDOC_RELATIONS = YES ++HAVE_DOT = NO ++CLASS_GRAPH = YES ++COLLABORATION_GRAPH = YES ++GROUP_GRAPHS = YES ++UML_LOOK = NO ++TEMPLATE_RELATIONS = NO ++INCLUDE_GRAPH = NO ++INCLUDED_BY_GRAPH = YES ++CALL_GRAPH = NO ++GRAPHICAL_HIERARCHY = YES ++DIRECTORY_GRAPH = YES ++DOT_IMAGE_FORMAT = png ++DOT_PATH = ++DOTFILE_DIRS = ++MAX_DOT_GRAPH_DEPTH = 1000 ++DOT_TRANSPARENT = NO ++DOT_MULTI_TARGETS = NO ++GENERATE_LEGEND = YES ++DOT_CLEANUP = YES ++#--------------------------------------------------------------------------- ++# Configuration::additions related to the search engine ++#--------------------------------------------------------------------------- ++SEARCHENGINE = NO +diff --git a/drivers/usb/host/dwc_common_port/dwc_cc.c b/drivers/usb/host/dwc_common_port/dwc_cc.c +new file mode 100644 +index 0000000..613c901 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_cc.c +@@ -0,0 +1,532 @@ +/* ========================================================================= -+ * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_cc.c $ -+ * $Revision: #1 $ -+ * $Date: 2008/12/21 $ -+ * $Change: 1156609 $ ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.c $ ++ * $Revision: #4 $ ++ * $Date: 2010/11/04 $ ++ * $Change: 1621692 $ + * + * Synopsys Portability Library Software and documentation + * (hereinafter, "Software") is an Unsupported proprietary work of @@ -30455,6 +32975,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi-boot + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * ========================================================================= */ ++#ifdef DWC_CCLIB ++ +#include "dwc_cc.h" + +typedef struct dwc_cc @@ -30497,9 +33019,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi-boot +#define dump_bytes(x...) +#endif + -+static dwc_cc_t *alloc_cc(uint8_t *name, uint32_t length) ++static dwc_cc_t *alloc_cc(void *mem_ctx, uint8_t *name, uint32_t length) +{ -+ dwc_cc_t *cc = DWC_ALLOC(sizeof(dwc_cc_t)); ++ dwc_cc_t *cc = dwc_alloc(mem_ctx, sizeof(dwc_cc_t)); + if (!cc) { + return NULL; + } @@ -30507,19 +33029,24 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi-boot + + if (name) { + cc->length = length; -+ cc->name = DWC_ALLOC(length); ++ cc->name = dwc_alloc(mem_ctx, length); ++ if (!cc->name) { ++ dwc_free(mem_ctx, cc); ++ return NULL; ++ } ++ + DWC_MEMCPY(cc->name, name, length); + } + + return cc; +} + -+static void free_cc(dwc_cc_t *cc) ++static void free_cc(void *mem_ctx, dwc_cc_t *cc) +{ + if (cc->name) { -+ DWC_FREE(cc->name); ++ dwc_free(mem_ctx, cc->name); + } -+ DWC_FREE(cc); ++ dwc_free(mem_ctx, cc); +} + +static uint32_t next_uid(dwc_cc_if_t *cc_if) @@ -30591,7 +33118,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi-boot +} + +/* Internal cc_add */ -+static int32_t cc_add(dwc_cc_if_t *cc_if, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) ++static int32_t cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) +{ + dwc_cc_t *cc; + uint32_t uid; @@ -30604,11 +33132,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi-boot + } + + if (uid) { -+ DWC_DEBUG("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length); ++ DWC_DEBUGC("Replacing previous connection context id=%d name=%p name_len=%d", uid, name, length); + cc = cc_find(cc_if, uid); + } + else { -+ cc = alloc_cc(name, length); ++ cc = alloc_cc(mem_ctx, name, length); + cc->uid = next_uid(cc_if); + DWC_CIRCLEQ_INSERT_TAIL(&cc_if->list, cc, list_entry); + } @@ -30617,7 +33145,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi-boot + DWC_MEMCPY(&(cc->cdid[0]), cdid, 16); + DWC_MEMCPY(&(cc->ck[0]), ck, 16); + -+ DWC_DEBUG("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length); ++ DWC_DEBUGC("Added connection context id=%d name=%p name_len=%d", cc->uid, name, length); + dump_bytes("CHID", cc->chid, 16); + dump_bytes("CDID", cc->cdid, 16); + dump_bytes("CK", cc->ck, 16); @@ -30625,41 +33153,51 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi-boot +} + +/* Internal cc_clear */ -+static void cc_clear(dwc_cc_if_t *cc_if) ++static void cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if) +{ + while (!DWC_CIRCLEQ_EMPTY(&cc_if->list)) { + dwc_cc_t *cc = DWC_CIRCLEQ_FIRST(&cc_if->list); + DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry); -+ free_cc(cc); ++ free_cc(mem_ctx, cc); + } +} + -+dwc_cc_if_t *dwc_cc_if_alloc(dwc_notifier_t *notifier, unsigned is_host) ++dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx, ++ dwc_notifier_t *notifier, unsigned is_host) +{ + dwc_cc_if_t *cc_if = NULL; + + /* Allocate a common_cc_if structure */ -+ cc_if = DWC_ALLOC(sizeof(dwc_cc_if_t)); ++ cc_if = dwc_alloc(mem_ctx, sizeof(dwc_cc_if_t)); + -+ if(!cc_if) ++ if (!cc_if) + return NULL; + +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) + DWC_MUTEX_ALLOC_LINUX_DEBUG(cc_if->mutex); +#else -+ cc_if->mutex = DWC_MUTEX_ALLOC(); ++ cc_if->mutex = dwc_mutex_alloc(mtx_ctx); +#endif ++ if (!cc_if->mutex) { ++ dwc_free(mem_ctx, cc_if); ++ return NULL; ++ } ++ + DWC_CIRCLEQ_INIT(&cc_if->list); + cc_if->is_host = is_host; + cc_if->notifier = notifier; + return cc_if; +} + -+void dwc_cc_if_free(dwc_cc_if_t *cc_if) ++void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if) +{ ++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) + DWC_MUTEX_FREE(cc_if->mutex); -+ cc_clear(cc_if); -+ DWC_FREE(cc_if); ++#else ++ dwc_mutex_free(mtx_ctx, cc_if->mutex); ++#endif ++ cc_clear(mem_ctx, cc_if); ++ dwc_free(mem_ctx, cc_if); +} + +static void cc_changed(dwc_cc_if_t *cc_if) @@ -30669,37 +33207,38 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi-boot + } +} + -+void dwc_cc_clear(dwc_cc_if_t *cc_if) ++void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if) +{ + DWC_MUTEX_LOCK(cc_if->mutex); -+ cc_clear(cc_if); ++ cc_clear(mem_ctx, cc_if); + DWC_MUTEX_UNLOCK(cc_if->mutex); + cc_changed(cc_if); +} + -+int32_t dwc_cc_add(dwc_cc_if_t *cc_if, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) ++int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) +{ + uint32_t uid; + + DWC_MUTEX_LOCK(cc_if->mutex); -+ uid = cc_add(cc_if, chid, cdid, ck, name, length); ++ uid = cc_add(mem_ctx, cc_if, chid, cdid, ck, name, length); + DWC_MUTEX_UNLOCK(cc_if->mutex); + cc_changed(cc_if); + + return uid; +} + -+void dwc_cc_change(dwc_cc_if_t *cc_if, int32_t id, -+ uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) ++void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length) +{ + dwc_cc_t* cc; + -+ DWC_DEBUG("Change connection context %d", id); ++ DWC_DEBUGC("Change connection context %d", id); + + DWC_MUTEX_LOCK(cc_if->mutex); + cc = cc_find(cc_if, id); + if (!cc) { -+ DWC_ERROR("Uid %d not found in cc list", id); ++ DWC_ERROR("Uid %d not found in cc list\n", id); + DWC_MUTEX_UNLOCK(cc_if->mutex); + return; + } @@ -30716,9 +33255,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi-boot + + if (name) { + if (cc->name) { -+ DWC_FREE(cc->name); ++ dwc_free(mem_ctx, cc->name); ++ } ++ cc->name = dwc_alloc(mem_ctx, length); ++ if (!cc->name) { ++ DWC_ERROR("Out of memory in dwc_cc_change()\n"); ++ DWC_MUTEX_UNLOCK(cc_if->mutex); ++ return; + } -+ cc->name = DWC_ALLOC(length); + cc->length = length; + DWC_MEMCPY(cc->name, name, length); + } @@ -30727,34 +33271,34 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi-boot + + cc_changed(cc_if); + -+ DWC_DEBUG("Changed connection context id=%d\n", id); ++ DWC_DEBUGC("Changed connection context id=%d\n", id); + dump_bytes("New CHID", cc->chid, 16); + dump_bytes("New CDID", cc->cdid, 16); + dump_bytes("New CK", cc->ck, 16); +} + -+void dwc_cc_remove(dwc_cc_if_t *cc_if, int32_t id) ++void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id) +{ + dwc_cc_t *cc; + -+ DWC_DEBUG("Removing connection context %d", id); ++ DWC_DEBUGC("Removing connection context %d", id); + + DWC_MUTEX_LOCK(cc_if->mutex); + cc = cc_find(cc_if, id); + if (!cc) { -+ DWC_ERROR("Uid %d not found in cc list", id); ++ DWC_ERROR("Uid %d not found in cc list\n", id); + DWC_MUTEX_UNLOCK(cc_if->mutex); + return; + } + + DWC_CIRCLEQ_REMOVE_INIT(&cc_if->list, cc, list_entry); + DWC_MUTEX_UNLOCK(cc_if->mutex); -+ free_cc(cc); ++ free_cc(mem_ctx, cc); + + cc_changed(cc_if); +} + -+uint8_t *dwc_cc_data_for_save(dwc_cc_if_t *cc_if, unsigned int *length) ++uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, unsigned int *length) +{ + uint8_t *buf, *x; + uint8_t zero = 0; @@ -30767,9 +33311,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi-boot + return NULL; + } + -+ DWC_DEBUG("Creating data for saving (length=%d)", *length); ++ DWC_DEBUGC("Creating data for saving (length=%d)", *length); + -+ buf = DWC_ALLOC(*length); ++ buf = dwc_alloc(mem_ctx, *length); + if (!buf) { + *length = 0; + DWC_MUTEX_UNLOCK(cc_if->mutex); @@ -30800,7 +33344,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi-boot + return buf; +} + -+void dwc_cc_restore_from_data(dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length) ++void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *data, uint32_t length) +{ + uint8_t name_length; + uint8_t *name; @@ -30810,7 +33354,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi-boot + uint32_t i = 0; + + DWC_MUTEX_LOCK(cc_if->mutex); -+ cc_clear(cc_if); ++ cc_clear(mem_ctx, cc_if); + + while (i < length) { + chid = &data[i]; @@ -30834,11 +33378,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi-boot + /* check to see if we haven't overflown the buffer */ + if (i > length) { + DWC_ERROR("Data format error while attempting to load CCs " -+ "(nlen=%d, iter=%d, buflen=%d).", name_length, i, length); ++ "(nlen=%d, iter=%d, buflen=%d).\n", name_length, i, length); + break; + } + -+ cc_add(cc_if, chid, cdid, ck, name, name_length); ++ cc_add(mem_ctx, cc_if, chid, cdid, ck, name, name_length); + } + DWC_MUTEX_UNLOCK(cc_if->mutex); + @@ -30926,15 +33470,19 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.c linux-rpi-boot + + return retval; +} -diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.h linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.h ---- linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.h 2012-07-15 20:29:18.989081834 +0200 -@@ -0,0 +1,209 @@ ++ ++#endif /* DWC_CCLIB */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_cc.h b/drivers/usb/host/dwc_common_port/dwc_cc.h +new file mode 100644 +index 0000000..6b2bbaf +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_cc.h +@@ -0,0 +1,225 @@ +/* ========================================================================= -+ * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_cc.h $ -+ * $Revision: #1 $ -+ * $Date: 2008/12/21 $ -+ * $Change: 1156609 $ ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_cc.h $ ++ * $Revision: #4 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ + * + * Synopsys Portability Library Software and documentation + * (hereinafter, "Software") is an Unsupported proprietary work of @@ -30968,6 +33516,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.h linux-rpi-boot +#ifndef _DWC_CC_H_ +#define _DWC_CC_H_ + ++#ifdef __cplusplus ++extern "C" { ++#endif ++ +/** @file + * + * This file defines the Context Context library. @@ -31001,14 +33553,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.h linux-rpi-boot +/** This function allocates memory for a dwc_cc_if_t structure, initializes + * fields to default values, and returns a pointer to the structure or NULL on + * error. */ -+extern dwc_cc_if_t *dwc_cc_if_alloc(dwc_notifier_t *notifier, unsigned is_host); ++extern dwc_cc_if_t *dwc_cc_if_alloc(void *mem_ctx, void *mtx_ctx, ++ dwc_notifier_t *notifier, unsigned is_host); + +/** Frees the memory for the specified CC structure allocated from + * dwc_cc_if_alloc(). */ -+extern void dwc_cc_if_free(dwc_cc_if_t *cc_if); ++extern void dwc_cc_if_free(void *mem_ctx, void *mtx_ctx, dwc_cc_if_t *cc_if); + +/** Removes all contexts from the connection context list */ -+extern void dwc_cc_clear(dwc_cc_if_t *cc_if); ++extern void dwc_cc_clear(void *mem_ctx, dwc_cc_if_t *cc_if); + +/** Adds a connection context (CHID, CK, CDID, Name) to the connection context list. + * If a CHID already exists, the CK and name are overwritten. Statistics are @@ -31023,7 +33576,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.h linux-rpi-boot + * @param length The length othe unicode string. + * @return A unique identifier used to refer to this context that is valid for + * as long as this context is still in the list. */ -+extern int32_t dwc_cc_add(dwc_cc_if_t *cc_if, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length); ++extern int32_t dwc_cc_add(void *mem_ctx, dwc_cc_if_t *cc_if, uint8_t *chid, ++ uint8_t *cdid, uint8_t *ck, uint8_t *name, ++ uint8_t length); + +/** Changes the CHID, CK, CDID, or Name values of a connection context in the + * list, preserving any accumulated statistics. This would typically be called @@ -31039,12 +33594,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.h linux-rpi-boot + * indicates no change. + * @param name Host friendly name UTF16-LE. NULL indicates no change. + * @param length Length of name. */ -+extern void dwc_cc_change(dwc_cc_if_t *cc_if, int32_t id, uint8_t *chid, uint8_t *cdid, uint8_t *ck, uint8_t *name, uint8_t length); ++extern void dwc_cc_change(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id, ++ uint8_t *chid, uint8_t *cdid, uint8_t *ck, ++ uint8_t *name, uint8_t length); + +/** Remove the specified connection context. + * @param cc_if The cc_if structure. + * @param id The identifier of the connection context to remove. */ -+extern void dwc_cc_remove(dwc_cc_if_t *cc_if, int32_t id); ++extern void dwc_cc_remove(void *mem_ctx, dwc_cc_if_t *cc_if, int32_t id); + +/** Get a binary block of data for the connection context list and attributes. + * This data can be used by the OS specific driver to save the connection @@ -31052,8 +33609,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.h linux-rpi-boot + * + * @param cc_if The cc_if structure. + * @param length Return the length of the data buffer. -+ * @return A pointer to the data buffer. The memory for this buffer should be freed with DWC_FREE() after use. */ -+extern uint8_t *dwc_cc_data_for_save(dwc_cc_if_t *cc_if, unsigned int *length); ++ * @return A pointer to the data buffer. The memory for this buffer should be ++ * freed with DWC_FREE() after use. */ ++extern uint8_t *dwc_cc_data_for_save(void *mem_ctx, dwc_cc_if_t *cc_if, ++ unsigned int *length); + +/** Restore the connection context list from the binary data that was previously + * returned from a call to dwc_cc_data_for_save. This can be used by the OS specific @@ -31062,7 +33621,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.h linux-rpi-boot + * @param cc_if The cc_if structure. + * @param data The data bytes as returned from dwc_cc_data_for_save. + * @param length The length of the data. */ -+extern void dwc_cc_restore_from_data(dwc_cc_if_t *cc_if, uint8_t *data, unsigned int length); ++extern void dwc_cc_restore_from_data(void *mem_ctx, dwc_cc_if_t *cc_if, ++ uint8_t *data, unsigned int length); + +/** Find the connection context from the specified CHID. + * @@ -31137,116 +33697,39 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_cc.h linux-rpi-boot + +/** @} */ + ++#ifdef __cplusplus ++} ++#endif ++ +#endif /* _DWC_CC_H_ */ + -diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c ---- linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c 2012-07-15 20:29:18.989081834 +0200 -@@ -0,0 +1,1138 @@ -+#include "dwc_cc.h" -+#include "dwc_notifier.h" +diff --git a/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c b/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c +new file mode 100644 +index 0000000..6dd04b5 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_common_fbsd.c +@@ -0,0 +1,1308 @@ ++#include "dwc_os.h" ++#include "dwc_list.h" + -+#include -+#include -+#include -+#include -+ -+MODULE_DESCRIPTION("DWC Common Library - Portable version"); -+MODULE_AUTHOR("Synopsys Inc."); -+MODULE_LICENSE ("GPL"); -+ -+static int dwc_common_port_init_module(void) -+{ -+ printk( KERN_DEBUG "Module dwc_common_port init\n" ); -+#ifdef DEBUG_MEMORY -+ dwc_memory_debug_start(); ++#ifdef DWC_CCLIB ++# include "dwc_cc.h" +#endif -+ dwc_alloc_notification_manager(); -+ return 0; -+} + -+static void dwc_common_port_exit_module(void) -+{ -+ printk( KERN_DEBUG "Module dwc_common_port exit\n" ); -+ dwc_free_notification_manager(); -+#ifdef DEBUG_MEMORY -+ dwc_memory_debug_stop(); ++#ifdef DWC_CRYPTOLIB ++# include "dwc_modpow.h" ++# include "dwc_dh.h" ++# include "dwc_crypto.h" +#endif -+} + -+module_init(dwc_common_port_init_module); -+module_exit(dwc_common_port_exit_module); -+ -+/* CC */ -+EXPORT_SYMBOL(dwc_cc_if_alloc); -+EXPORT_SYMBOL(dwc_cc_if_free); -+EXPORT_SYMBOL(dwc_cc_clear); -+EXPORT_SYMBOL(dwc_cc_add); -+EXPORT_SYMBOL(dwc_cc_remove); -+EXPORT_SYMBOL(dwc_cc_change); -+EXPORT_SYMBOL(dwc_cc_data_for_save); -+EXPORT_SYMBOL(dwc_cc_restore_from_data); -+EXPORT_SYMBOL(dwc_cc_match_chid); -+EXPORT_SYMBOL(dwc_cc_match_cdid); -+EXPORT_SYMBOL(dwc_cc_ck); -+EXPORT_SYMBOL(dwc_cc_chid); -+EXPORT_SYMBOL(dwc_cc_cdid); -+EXPORT_SYMBOL(dwc_cc_name); -+ -+/* Notification */ -+EXPORT_SYMBOL(dwc_alloc_notification_manager); -+EXPORT_SYMBOL(dwc_free_notification_manager); -+EXPORT_SYMBOL(dwc_register_notifier); -+EXPORT_SYMBOL(dwc_unregister_notifier); -+EXPORT_SYMBOL(dwc_add_observer); -+EXPORT_SYMBOL(dwc_remove_observer); -+EXPORT_SYMBOL(dwc_notify); -+ -+/* Memory Debugging Routines */ -+#ifdef DEBUG_MEMORY -+EXPORT_SYMBOL(dwc_alloc_debug); -+EXPORT_SYMBOL(dwc_alloc_atomic_debug); -+EXPORT_SYMBOL(dwc_free_debug); -+EXPORT_SYMBOL(dwc_dma_alloc_debug); -+EXPORT_SYMBOL(dwc_dma_alloc_atomic_debug); -+EXPORT_SYMBOL(dwc_dma_free_debug); ++#ifdef DWC_NOTIFYLIB ++# include "dwc_notifier.h" +#endif + +/* OS-Level Implementations */ + -+/* This is the Linux kernel implementation of the DWC platform library. */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+#include -+#else -+#include -+#endif -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++/* This is the FreeBSD 7.0 kernel implementation of the DWC platform library. */ ++ + +/* MISC */ + @@ -31254,86 +33737,84 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu +{ + return memset(dest, byte, size); +} -+EXPORT_SYMBOL(DWC_MEMSET); + +void *DWC_MEMCPY(void *dest, void const *src, uint32_t size) +{ + return memcpy(dest, src, size); +} -+EXPORT_SYMBOL(DWC_MEMCPY); + +void *DWC_MEMMOVE(void *dest, void *src, uint32_t size) +{ -+ return memmove(dest, src, size); ++ bcopy(src, dest, size); ++ return dest; +} -+EXPORT_SYMBOL(DWC_MEMMOVE); + +int DWC_MEMCMP(void *m1, void *m2, uint32_t size) +{ + return memcmp(m1, m2, size); +} -+EXPORT_SYMBOL(DWC_MEMCMP); + +int DWC_STRNCMP(void *s1, void *s2, uint32_t size) +{ + return strncmp(s1, s2, size); +} -+EXPORT_SYMBOL(DWC_STRNCMP); + +int DWC_STRCMP(void *s1, void *s2) +{ + return strcmp(s1, s2); +} -+EXPORT_SYMBOL(DWC_STRCMP); + +int DWC_STRLEN(char const *str) +{ + return strlen(str); +} -+EXPORT_SYMBOL(DWC_STRLEN); + -+char *DWC_STRCPY(char *to, const char *from) ++char *DWC_STRCPY(char *to, char const *from) +{ + return strcpy(to, from); +} -+EXPORT_SYMBOL(DWC_STRCPY); + +char *DWC_STRDUP(char const *str) +{ + int len = DWC_STRLEN(str) + 1; + char *new = DWC_ALLOC_ATOMIC(len); ++ + if (!new) { + return NULL; + } ++ + DWC_MEMCPY(new, str, len); + return new; +} -+EXPORT_SYMBOL(DWC_STRDUP); + +int DWC_ATOI(char *str, int32_t *value) +{ + char *end = NULL; -+ *value = simple_strtol(str, &end, 0); ++ ++ *value = strtol(str, &end, 0); + if (*end == '\0') { + return 0; + } ++ + return -1; +} -+EXPORT_SYMBOL(DWC_ATOI); + +int DWC_ATOUI(char *str, uint32_t *value) +{ + char *end = NULL; -+ *value = simple_strtoul(str, &end, 0); ++ ++ *value = strtoul(str, &end, 0); + if (*end == '\0') { + return 0; + } ++ + return -1; +} -+EXPORT_SYMBOL(DWC_ATOUI); + + ++#ifdef DWC_UTFLIB +/* From usbstring.c */ ++ +int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len) +{ + int count = 0; @@ -31383,7 +33864,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu + // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx + // (uuuuu = wwww + 1) + // FIXME accept the surrogate code points (only) -+ + } else + goto fail; + } else @@ -31396,27 +33876,28 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu +fail: + return -1; +} -+EXPORT_SYMBOL(DWC_UTF8_TO_UTF16LE); ++ ++#endif /* DWC_UTFLIB */ ++ + +/* dwc_debug.h */ + +dwc_bool_t DWC_IN_IRQ(void) +{ -+ return in_irq(); ++// return in_irq(); ++ return 0; +} -+EXPORT_SYMBOL(DWC_IN_IRQ); + -+int DWC_IN_BH(void) ++dwc_bool_t DWC_IN_BH(void) +{ -+ return in_softirq(); ++// return in_softirq(); ++ return 0; +} -+EXPORT_SYMBOL(DWC_IN_BH); + +void DWC_VPRINTF(char *format, va_list args) +{ -+ vprintk(format, args); ++ vprintf(format, args); +} -+EXPORT_SYMBOL(DWC_VPRINTF); + +int DWC_VSNPRINTF(char *str, int size, char *format, va_list args) +{ @@ -31426,79 +33907,74 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu +void DWC_PRINTF(char *format, ...) +{ + va_list args; ++ + va_start(args, format); + DWC_VPRINTF(format, args); + va_end(args); +} -+EXPORT_SYMBOL(DWC_PRINTF); + +int DWC_SPRINTF(char *buffer, char *format, ...) +{ + int retval; + va_list args; ++ + va_start(args, format); + retval = vsprintf(buffer, format, args); + va_end(args); + return retval; +} -+EXPORT_SYMBOL(DWC_SPRINTF); + +int DWC_SNPRINTF(char *buffer, int size, char *format, ...) +{ + int retval; + va_list args; ++ + va_start(args, format); + retval = vsnprintf(buffer, size, format, args); + va_end(args); + return retval; +} -+EXPORT_SYMBOL(DWC_SNPRINTF); + +void __DWC_WARN(char *format, ...) +{ + va_list args; ++ + va_start(args, format); -+ DWC_PRINTF(KERN_WARNING); + DWC_VPRINTF(format, args); + va_end(args); +} -+EXPORT_SYMBOL(__DWC_WARN); + +void __DWC_ERROR(char *format, ...) +{ + va_list args; ++ + va_start(args, format); -+ DWC_PRINTF(KERN_ERR); + DWC_VPRINTF(format, args); + va_end(args); +} -+EXPORT_SYMBOL(__DWC_ERROR); + +void DWC_EXCEPTION(char *format, ...) +{ + va_list args; ++ + va_start(args, format); -+ DWC_PRINTF(KERN_ERR); + DWC_VPRINTF(format, args); + va_end(args); -+ BUG_ON(1); ++// BUG_ON(1); ??? +} -+EXPORT_SYMBOL(DWC_EXCEPTION); + +#ifdef DEBUG +void __DWC_DEBUG(char *format, ...) +{ + va_list args; ++ + va_start(args, format); -+ DWC_PRINTF(KERN_DEBUG); + DWC_VPRINTF(format, args); + va_end(args); +} -+EXPORT_SYMBOL(__DWC_DEBUG); +#endif + + -+ +/* dwc_mem.h */ + +#if 0 @@ -31516,42 +33992,1390 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu + dma_pool_destroy((struct dma_pool *)pool); +} + -+void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, U64 *dma_addr) ++void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr) +{ -+ return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr); ++// return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr); ++ return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr); +} + -+void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, U64 *dma_addr) ++void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr) +{ + void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr); -+ memset(); ++ memset(..); +} + +void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr) +{ + dma_pool_free(pool, vaddr, daddr); +} -+ +#endif + -+void *__DWC_DMA_ALLOC(uint32_t size, dwc_dma_t *dma_addr) ++static void dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) +{ -+ void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_KERNEL); ++ if (error) ++ return; ++ *(bus_addr_t *)arg = segs[0].ds_addr; ++} ++ ++void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) ++{ ++ dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx; ++ int error; ++ ++ error = bus_dma_tag_create( ++#if __FreeBSD_version >= 700000 ++ bus_get_dma_tag(dma->dev), /* parent */ ++#else ++ NULL, /* parent */ ++#endif ++ 4, 0, /* alignment, bounds */ ++ BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ ++ BUS_SPACE_MAXADDR, /* highaddr */ ++ NULL, NULL, /* filter, filterarg */ ++ size, /* maxsize */ ++ 1, /* nsegments */ ++ size, /* maxsegsize */ ++ 0, /* flags */ ++ NULL, /* lockfunc */ ++ NULL, /* lockarg */ ++ &dma->dma_tag); ++ if (error) { ++ device_printf(dma->dev, "%s: bus_dma_tag_create failed: %d\n", ++ __func__, error); ++ goto fail_0; ++ } ++ ++ error = bus_dmamem_alloc(dma->dma_tag, &dma->dma_vaddr, ++ BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &dma->dma_map); ++ if (error) { ++ device_printf(dma->dev, "%s: bus_dmamem_alloc(%ju) failed: %d\n", ++ __func__, (uintmax_t)size, error); ++ goto fail_1; ++ } ++ ++ dma->dma_paddr = 0; ++ error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, size, ++ dmamap_cb, &dma->dma_paddr, BUS_DMA_NOWAIT); ++ if (error || dma->dma_paddr == 0) { ++ device_printf(dma->dev, "%s: bus_dmamap_load failed: %d\n", ++ __func__, error); ++ goto fail_2; ++ } ++ ++ *dma_addr = dma->dma_paddr; ++ return dma->dma_vaddr; ++ ++fail_2: ++ bus_dmamap_unload(dma->dma_tag, dma->dma_map); ++fail_1: ++ bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); ++ bus_dma_tag_destroy(dma->dma_tag); ++fail_0: ++ dma->dma_map = NULL; ++ dma->dma_tag = NULL; ++ ++ return NULL; ++} ++ ++void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr) ++{ ++ dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx; ++ ++ if (dma->dma_tag == NULL) ++ return; ++ if (dma->dma_map != NULL) { ++ bus_dmamap_sync(dma->dma_tag, dma->dma_map, ++ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); ++ bus_dmamap_unload(dma->dma_tag, dma->dma_map); ++ bus_dmamem_free(dma->dma_tag, dma->dma_vaddr, dma->dma_map); ++ dma->dma_map = NULL; ++ } ++ ++ bus_dma_tag_destroy(dma->dma_tag); ++ dma->dma_tag = NULL; ++} ++ ++void *__DWC_ALLOC(void *mem_ctx, uint32_t size) ++{ ++ return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO); ++} ++ ++void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size) ++{ ++ return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO); ++} ++ ++void __DWC_FREE(void *mem_ctx, void *addr) ++{ ++ free(addr, M_DEVBUF); ++} ++ ++ ++#ifdef DWC_CRYPTOLIB ++/* dwc_crypto.h */ ++ ++void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length) ++{ ++ get_random_bytes(buffer, length); ++} ++ ++int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out) ++{ ++ struct crypto_blkcipher *tfm; ++ struct blkcipher_desc desc; ++ struct scatterlist sgd; ++ struct scatterlist sgs; ++ ++ tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); ++ if (tfm == NULL) { ++ printk("failed to load transform for aes CBC\n"); ++ return -1; ++ } ++ ++ crypto_blkcipher_setkey(tfm, key, keylen); ++ crypto_blkcipher_set_iv(tfm, iv, 16); ++ ++ sg_init_one(&sgd, out, messagelen); ++ sg_init_one(&sgs, message, messagelen); ++ ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) { ++ crypto_free_blkcipher(tfm); ++ DWC_ERROR("AES CBC encryption failed"); ++ return -1; ++ } ++ ++ crypto_free_blkcipher(tfm); ++ return 0; ++} ++ ++int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, len); ++ crypto_hash_digest(&desc, &sg, len, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++ ++int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, ++ uint8_t *key, uint32_t keylen, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, messagelen); ++ crypto_hash_setkey(tfm, key, keylen); ++ crypto_hash_digest(&desc, &sg, messagelen, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++ ++#endif /* DWC_CRYPTOLIB */ ++ ++ ++/* Byte Ordering Conversions */ ++ ++uint32_t DWC_CPU_TO_LE32(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_CPU_TO_BE32(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_LE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_BE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint16_t DWC_CPU_TO_LE16(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_CPU_TO_BE16(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_LE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_BE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++ ++/* Registers */ ++ ++uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ return bus_space_read_4(io->iot, io->ioh, ior); ++} ++ ++#if 0 ++uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ return bus_space_read_8(io->iot, io->ioh, ior); ++} ++#endif ++ ++void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_4(io->iot, io->ioh, ior, value); ++} ++ ++#if 0 ++void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_8(io->iot, io->ioh, ior, value); ++} ++#endif ++ ++void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, ++ uint32_t set_mask) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_4(io->iot, io->ioh, ior, ++ (bus_space_read_4(io->iot, io->ioh, ior) & ++ ~clear_mask) | set_mask); ++} ++ ++#if 0 ++void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, ++ uint64_t set_mask) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_8(io->iot, io->ioh, ior, ++ (bus_space_read_8(io->iot, io->ioh, ior) & ++ ~clear_mask) | set_mask); ++} ++#endif ++ ++ ++/* Locking */ ++ ++dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void) ++{ ++ struct mtx *sl = DWC_ALLOC(sizeof(*sl)); ++ ++ if (!sl) { ++ DWC_ERROR("Cannot allocate memory for spinlock"); ++ return NULL; ++ } ++ ++ mtx_init(sl, "dw3spn", NULL, MTX_SPIN); ++ return (dwc_spinlock_t *)sl; ++} ++ ++void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock) ++{ ++ struct mtx *sl = (struct mtx *)lock; ++ ++ mtx_destroy(sl); ++ DWC_FREE(sl); ++} ++ ++void DWC_SPINLOCK(dwc_spinlock_t *lock) ++{ ++ mtx_lock_spin((struct mtx *)lock); // ??? ++} ++ ++void DWC_SPINUNLOCK(dwc_spinlock_t *lock) ++{ ++ mtx_unlock_spin((struct mtx *)lock); // ??? ++} ++ ++void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags) ++{ ++ mtx_lock_spin((struct mtx *)lock); ++} ++ ++void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags) ++{ ++ mtx_unlock_spin((struct mtx *)lock); ++} ++ ++dwc_mutex_t *DWC_MUTEX_ALLOC(void) ++{ ++ struct mtx *m; ++ dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mtx)); ++ ++ if (!mutex) { ++ DWC_ERROR("Cannot allocate memory for mutex"); ++ return NULL; ++ } ++ ++ m = (struct mtx *)mutex; ++ mtx_init(m, "dw3mtx", NULL, MTX_DEF); ++ return mutex; ++} ++ ++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++#else ++void DWC_MUTEX_FREE(dwc_mutex_t *mutex) ++{ ++ mtx_destroy((struct mtx *)mutex); ++ DWC_FREE(mutex); ++} ++#endif ++ ++void DWC_MUTEX_LOCK(dwc_mutex_t *mutex) ++{ ++ struct mtx *m = (struct mtx *)mutex; ++ ++ mtx_lock(m); ++} ++ ++int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex) ++{ ++ struct mtx *m = (struct mtx *)mutex; ++ ++ return mtx_trylock(m); ++} ++ ++void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex) ++{ ++ struct mtx *m = (struct mtx *)mutex; ++ ++ mtx_unlock(m); ++} ++ ++ ++/* Timing */ ++ ++void DWC_UDELAY(uint32_t usecs) ++{ ++ DELAY(usecs); ++} ++ ++void DWC_MDELAY(uint32_t msecs) ++{ ++ do { ++ DELAY(1000); ++ } while (--msecs); ++} ++ ++void DWC_MSLEEP(uint32_t msecs) ++{ ++ struct timeval tv; ++ ++ tv.tv_sec = msecs / 1000; ++ tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000; ++ pause("dw3slp", tvtohz(&tv)); ++} ++ ++uint32_t DWC_TIME(void) ++{ ++ struct timeval tv; ++ ++ microuptime(&tv); // or getmicrouptime? (less precise, but faster) ++ return tv.tv_sec * 1000 + tv.tv_usec / 1000; ++} ++ ++ ++/* Timers */ ++ ++struct dwc_timer { ++ struct callout t; ++ char *name; ++ dwc_spinlock_t *lock; ++ dwc_timer_callback_t cb; ++ void *data; ++}; ++ ++dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data) ++{ ++ dwc_timer_t *t = DWC_ALLOC(sizeof(*t)); ++ ++ if (!t) { ++ DWC_ERROR("Cannot allocate memory for timer"); ++ return NULL; ++ } ++ ++ callout_init(&t->t, 1); ++ ++ t->name = DWC_STRDUP(name); ++ if (!t->name) { ++ DWC_ERROR("Cannot allocate memory for timer->name"); ++ goto no_name; ++ } ++ ++ t->lock = DWC_SPINLOCK_ALLOC(); ++ if (!t->lock) { ++ DWC_ERROR("Cannot allocate memory for lock"); ++ goto no_lock; ++ } ++ ++ t->cb = cb; ++ t->data = data; ++ ++ return t; ++ ++ no_lock: ++ DWC_FREE(t->name); ++ no_name: ++ DWC_FREE(t); ++ ++ return NULL; ++} ++ ++void DWC_TIMER_FREE(dwc_timer_t *timer) ++{ ++ callout_stop(&timer->t); ++ DWC_SPINLOCK_FREE(timer->lock); ++ DWC_FREE(timer->name); ++ DWC_FREE(timer); ++} ++ ++void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time) ++{ ++ struct timeval tv; ++ ++ tv.tv_sec = time / 1000; ++ tv.tv_usec = (time - tv.tv_sec * 1000) * 1000; ++ callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data); ++} ++ ++void DWC_TIMER_CANCEL(dwc_timer_t *timer) ++{ ++ callout_stop(&timer->t); ++} ++ ++ ++/* Wait Queues */ ++ ++struct dwc_waitq { ++ struct mtx lock; ++ int abort; ++}; ++ ++dwc_waitq_t *DWC_WAITQ_ALLOC(void) ++{ ++ dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ DWC_ERROR("Cannot allocate memory for waitqueue"); ++ return NULL; ++ } ++ ++ mtx_init(&wq->lock, "dw3wtq", NULL, MTX_DEF); ++ wq->abort = 0; ++ ++ return wq; ++} ++ ++void DWC_WAITQ_FREE(dwc_waitq_t *wq) ++{ ++ mtx_destroy(&wq->lock); ++ DWC_FREE(wq); ++} ++ ++int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data) ++{ ++// intrmask_t ipl; ++ int result = 0; ++ ++ mtx_lock(&wq->lock); ++// ipl = splbio(); ++ ++ /* Skip the sleep if already aborted or triggered */ ++ if (!wq->abort && !cond(data)) { ++// splx(ipl); ++ result = msleep(wq, &wq->lock, PCATCH, "dw3wat", 0); // infinite timeout ++// ipl = splbio(); ++ } ++ ++ if (result == ERESTART) { // signaled - restart ++ result = -DWC_E_RESTART; ++ ++ } else if (result == EINTR) { // signaled - interrupt ++ result = -DWC_E_ABORT; ++ ++ } else if (wq->abort) { ++ result = -DWC_E_ABORT; ++ ++ } else { ++ result = 0; ++ } ++ ++ wq->abort = 0; ++// splx(ipl); ++ mtx_unlock(&wq->lock); ++ return result; ++} ++ ++int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, ++ void *data, int32_t msecs) ++{ ++ struct timeval tv, tv1, tv2; ++// intrmask_t ipl; ++ int result = 0; ++ ++ tv.tv_sec = msecs / 1000; ++ tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000; ++ ++ mtx_lock(&wq->lock); ++// ipl = splbio(); ++ ++ /* Skip the sleep if already aborted or triggered */ ++ if (!wq->abort && !cond(data)) { ++// splx(ipl); ++ getmicrouptime(&tv1); ++ result = msleep(wq, &wq->lock, PCATCH, "dw3wto", tvtohz(&tv)); ++ getmicrouptime(&tv2); ++// ipl = splbio(); ++ } ++ ++ if (result == 0) { // awoken ++ if (wq->abort) { ++ result = -DWC_E_ABORT; ++ } else { ++ tv2.tv_usec -= tv1.tv_usec; ++ if (tv2.tv_usec < 0) { ++ tv2.tv_usec += 1000000; ++ tv2.tv_sec--; ++ } ++ ++ tv2.tv_sec -= tv1.tv_sec; ++ result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000; ++ result = msecs - result; ++ if (result <= 0) ++ result = 1; ++ } ++ } else if (result == ERESTART) { // signaled - restart ++ result = -DWC_E_RESTART; ++ ++ } else if (result == EINTR) { // signaled - interrupt ++ result = -DWC_E_ABORT; ++ ++ } else { // timed out ++ result = -DWC_E_TIMEOUT; ++ } ++ ++ wq->abort = 0; ++// splx(ipl); ++ mtx_unlock(&wq->lock); ++ return result; ++} ++ ++void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq) ++{ ++ wakeup(wq); ++} ++ ++void DWC_WAITQ_ABORT(dwc_waitq_t *wq) ++{ ++// intrmask_t ipl; ++ ++ mtx_lock(&wq->lock); ++// ipl = splbio(); ++ wq->abort = 1; ++ wakeup(wq); ++// splx(ipl); ++ mtx_unlock(&wq->lock); ++} ++ ++ ++/* Threading */ ++ ++struct dwc_thread { ++ struct proc *proc; ++ int abort; ++}; ++ ++dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data) ++{ ++ int retval; ++ dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread)); ++ ++ if (!thread) { ++ return NULL; ++ } ++ ++ thread->abort = 0; ++ retval = kthread_create((void (*)(void *))func, data, &thread->proc, ++ RFPROC | RFNOWAIT, 0, "%s", name); ++ if (retval) { ++ DWC_FREE(thread); ++ return NULL; ++ } ++ ++ return thread; ++} ++ ++int DWC_THREAD_STOP(dwc_thread_t *thread) ++{ ++ int retval; ++ ++ thread->abort = 1; ++ retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz); ++ ++ if (retval == 0) { ++ /* DWC_THREAD_EXIT() will free the thread struct */ ++ return 0; ++ } ++ ++ /* NOTE: We leak the thread struct if thread doesn't die */ ++ ++ if (retval == EWOULDBLOCK) { ++ return -DWC_E_TIMEOUT; ++ } ++ ++ return -DWC_E_UNKNOWN; ++} ++ ++dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread) ++{ ++ return thread->abort; ++} ++ ++void DWC_THREAD_EXIT(dwc_thread_t *thread) ++{ ++ wakeup(&thread->abort); ++ DWC_FREE(thread); ++ kthread_exit(0); ++} ++ ++ ++/* tasklets ++ - Runs in interrupt context (cannot sleep) ++ - Each tasklet runs on a single CPU [ How can we ensure this on FreeBSD? Does it matter? ] ++ - Different tasklets can be running simultaneously on different CPUs [ shouldn't matter ] ++ */ ++struct dwc_tasklet { ++ struct task t; ++ dwc_tasklet_callback_t cb; ++ void *data; ++}; ++ ++static void tasklet_callback(void *data, int pending) // what to do with pending ??? ++{ ++ dwc_tasklet_t *task = (dwc_tasklet_t *)data; ++ ++ task->cb(task->data); ++} ++ ++dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data) ++{ ++ dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task)); ++ ++ if (task) { ++ task->cb = cb; ++ task->data = data; ++ TASK_INIT(&task->t, 0, tasklet_callback, task); ++ } else { ++ DWC_ERROR("Cannot allocate memory for tasklet"); ++ } ++ ++ return task; ++} ++ ++void DWC_TASK_FREE(dwc_tasklet_t *task) ++{ ++ taskqueue_drain(taskqueue_fast, &task->t); // ??? ++ DWC_FREE(task); ++} ++ ++void DWC_TASK_SCHEDULE(dwc_tasklet_t *task) ++{ ++ /* Uses predefined system queue */ ++ taskqueue_enqueue_fast(taskqueue_fast, &task->t); ++} ++ ++ ++/* workqueues ++ - Runs in process context (can sleep) ++ */ ++typedef struct work_container { ++ dwc_work_callback_t cb; ++ void *data; ++ dwc_workq_t *wq; ++ char *name; ++ int hz; ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_ENTRY(work_container) entry; ++#endif ++ struct task task; ++} work_container_t; ++ ++#ifdef DEBUG ++DWC_CIRCLEQ_HEAD(work_container_queue, work_container); ++#endif ++ ++struct dwc_workq { ++ struct taskqueue *taskq; ++ dwc_spinlock_t *lock; ++ dwc_waitq_t *waitq; ++ int pending; ++ ++#ifdef DEBUG ++ struct work_container_queue entries; ++#endif ++}; ++ ++static void do_work(void *data, int pending) // what to do with pending ??? ++{ ++ work_container_t *container = (work_container_t *)data; ++ dwc_workq_t *wq = container->wq; ++ dwc_irqflags_t flags; ++ ++ if (container->hz) { ++ pause("dw3wrk", container->hz); ++ } ++ ++ container->cb(container->data); ++ DWC_DEBUG("Work done: %s, container=%p", container->name, container); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry); ++#endif ++ if (container->name) ++ DWC_FREE(container->name); ++ DWC_FREE(container); ++ wq->pending--; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++} ++ ++static int work_done(void *data) ++{ ++ dwc_workq_t *workq = (dwc_workq_t *)data; ++ ++ return workq->pending == 0; ++} ++ ++int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout) ++{ ++ return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout); ++} ++ ++dwc_workq_t *DWC_WORKQ_ALLOC(char *name) ++{ ++ dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ DWC_ERROR("Cannot allocate memory for workqueue"); ++ return NULL; ++ } ++ ++ wq->taskq = taskqueue_create(name, M_NOWAIT, taskqueue_thread_enqueue, &wq->taskq); ++ if (!wq->taskq) { ++ DWC_ERROR("Cannot allocate memory for taskqueue"); ++ goto no_taskq; ++ } ++ ++ wq->pending = 0; ++ ++ wq->lock = DWC_SPINLOCK_ALLOC(); ++ if (!wq->lock) { ++ DWC_ERROR("Cannot allocate memory for spinlock"); ++ goto no_lock; ++ } ++ ++ wq->waitq = DWC_WAITQ_ALLOC(); ++ if (!wq->waitq) { ++ DWC_ERROR("Cannot allocate memory for waitqueue"); ++ goto no_waitq; ++ } ++ ++ taskqueue_start_threads(&wq->taskq, 1, PWAIT, "%s taskq", "dw3tsk"); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_INIT(&wq->entries); ++#endif ++ return wq; ++ ++ no_waitq: ++ DWC_SPINLOCK_FREE(wq->lock); ++ no_lock: ++ taskqueue_free(wq->taskq); ++ no_taskq: ++ DWC_FREE(wq); ++ ++ return NULL; ++} ++ ++void DWC_WORKQ_FREE(dwc_workq_t *wq) ++{ ++#ifdef DEBUG ++ dwc_irqflags_t flags; ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ ++ if (wq->pending != 0) { ++ struct work_container *container; ++ ++ DWC_ERROR("Destroying work queue with pending work"); ++ ++ DWC_CIRCLEQ_FOREACH(container, &wq->entries, entry) { ++ DWC_ERROR("Work %s still pending", container->name); ++ } ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++#endif ++ DWC_WAITQ_FREE(wq->waitq); ++ DWC_SPINLOCK_FREE(wq->lock); ++ taskqueue_free(wq->taskq); ++ DWC_FREE(wq); ++} ++ ++void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data, ++ char *format, ...) ++{ ++ dwc_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++ ++ container = DWC_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ DWC_ERROR("Cannot allocate memory for container"); ++ return; ++ } ++ ++ container->name = DWC_STRDUP(name); ++ if (!container->name) { ++ DWC_ERROR("Cannot allocate memory for container->name"); ++ DWC_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ container->hz = 0; ++ ++ DWC_DEBUG("Queueing work: %s, container=%p", container->name, container); ++ ++ TASK_INIT(&container->task, 0, do_work, container); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); ++#endif ++ taskqueue_enqueue_fast(wq->taskq, &container->task); ++} ++ ++void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb, ++ void *data, uint32_t time, char *format, ...) ++{ ++ dwc_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ struct timeval tv; ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++ ++ container = DWC_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ DWC_ERROR("Cannot allocate memory for container"); ++ return; ++ } ++ ++ container->name = DWC_STRDUP(name); ++ if (!container->name) { ++ DWC_ERROR("Cannot allocate memory for container->name"); ++ DWC_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ ++ tv.tv_sec = time / 1000; ++ tv.tv_usec = (time - tv.tv_sec * 1000) * 1000; ++ container->hz = tvtohz(&tv); ++ ++ DWC_DEBUG("Queueing work: %s, container=%p", container->name, container); ++ ++ TASK_INIT(&container->task, 0, do_work, container); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); ++#endif ++ taskqueue_enqueue_fast(wq->taskq, &container->task); ++} ++ ++int DWC_WORKQ_PENDING(dwc_workq_t *wq) ++{ ++ return wq->pending; ++} +diff --git a/drivers/usb/host/dwc_common_port/dwc_common_linux.c b/drivers/usb/host/dwc_common_port/dwc_common_linux.c +new file mode 100644 +index 0000000..f00a9ff +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c +@@ -0,0 +1,1421 @@ ++#include ++#include ++#include ++#include ++ ++#ifdef DWC_CCLIB ++# include "dwc_cc.h" ++#endif ++ ++#ifdef DWC_CRYPTOLIB ++# include "dwc_modpow.h" ++# include "dwc_dh.h" ++# include "dwc_crypto.h" ++#endif ++ ++#ifdef DWC_NOTIFYLIB ++# include "dwc_notifier.h" ++#endif ++ ++/* OS-Level Implementations */ ++ ++/* This is the Linux kernel implementation of the DWC platform library. */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) ++# include ++#else ++# include ++#endif ++ ++#include ++#include ++#include ++#include ++ ++#include "dwc_os.h" ++#include "dwc_list.h" ++ ++ ++/* MISC */ ++ ++void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size) ++{ ++ return memset(dest, byte, size); ++} ++ ++void *DWC_MEMCPY(void *dest, void const *src, uint32_t size) ++{ ++ return memcpy(dest, src, size); ++} ++ ++void *DWC_MEMMOVE(void *dest, void *src, uint32_t size) ++{ ++ return memmove(dest, src, size); ++} ++ ++int DWC_MEMCMP(void *m1, void *m2, uint32_t size) ++{ ++ return memcmp(m1, m2, size); ++} ++ ++int DWC_STRNCMP(void *s1, void *s2, uint32_t size) ++{ ++ return strncmp(s1, s2, size); ++} ++ ++int DWC_STRCMP(void *s1, void *s2) ++{ ++ return strcmp(s1, s2); ++} ++ ++int DWC_STRLEN(char const *str) ++{ ++ return strlen(str); ++} ++ ++char *DWC_STRCPY(char *to, char const *from) ++{ ++ return strcpy(to, from); ++} ++ ++char *DWC_STRDUP(char const *str) ++{ ++ int len = DWC_STRLEN(str) + 1; ++ char *new = DWC_ALLOC_ATOMIC(len); ++ ++ if (!new) { ++ return NULL; ++ } ++ ++ DWC_MEMCPY(new, str, len); ++ return new; ++} ++ ++int DWC_ATOI(const char *str, int32_t *value) ++{ ++ char *end = NULL; ++ ++ *value = simple_strtol(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++int DWC_ATOUI(const char *str, uint32_t *value) ++{ ++ char *end = NULL; ++ ++ *value = simple_strtoul(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++ ++#ifdef DWC_UTFLIB ++/* From usbstring.c */ ++ ++int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len) ++{ ++ int count = 0; ++ u8 c; ++ u16 uchar; ++ ++ /* this insists on correct encodings, though not minimal ones. ++ * BUT it currently rejects legit 4-byte UTF-8 code points, ++ * which need surrogate pairs. (Unicode 3.1 can use them.) ++ */ ++ while (len != 0 && (c = (u8) *s++) != 0) { ++ if (unlikely(c & 0x80)) { ++ // 2-byte sequence: ++ // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx ++ if ((c & 0xe0) == 0xc0) { ++ uchar = (c & 0x1f) << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ // 3-byte sequence (most CJKV characters): ++ // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx ++ } else if ((c & 0xf0) == 0xe0) { ++ uchar = (c & 0x0f) << 12; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ /* no bogus surrogates */ ++ if (0xd800 <= uchar && uchar <= 0xdfff) ++ goto fail; ++ ++ // 4-byte sequence (surrogate pairs, currently rare): ++ // 11101110wwwwzzzzyy + 110111yyyyxxxxxx ++ // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx ++ // (uuuuu = wwww + 1) ++ // FIXME accept the surrogate code points (only) ++ } else ++ goto fail; ++ } else ++ uchar = c; ++ put_unaligned (cpu_to_le16 (uchar), cp++); ++ count++; ++ len--; ++ } ++ return count; ++fail: ++ return -1; ++} ++#endif /* DWC_UTFLIB */ ++ ++ ++/* dwc_debug.h */ ++ ++dwc_bool_t DWC_IN_IRQ(void) ++{ ++ return in_irq(); ++} ++ ++dwc_bool_t DWC_IN_BH(void) ++{ ++ return in_softirq(); ++} ++ ++void DWC_VPRINTF(char *format, va_list args) ++{ ++ vprintk(format, args); ++} ++ ++int DWC_VSNPRINTF(char *str, int size, char *format, va_list args) ++{ ++ return vsnprintf(str, size, format, args); ++} ++ ++void DWC_PRINTF(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++int DWC_SPRINTF(char *buffer, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsprintf(buffer, format, args); ++ va_end(args); ++ return retval; ++} ++ ++int DWC_SNPRINTF(char *buffer, int size, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsnprintf(buffer, size, format, args); ++ va_end(args); ++ return retval; ++} ++ ++void __DWC_WARN(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_PRINTF(KERN_WARNING); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void __DWC_ERROR(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_PRINTF(KERN_ERR); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void DWC_EXCEPTION(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_PRINTF(KERN_ERR); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++ BUG_ON(1); ++} ++ ++#ifdef DEBUG ++void __DWC_DEBUG(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_PRINTF(KERN_DEBUG); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++#endif ++ ++ ++/* dwc_mem.h */ ++ ++#if 0 ++dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, ++ uint32_t align, ++ uint32_t alloc) ++{ ++ struct dma_pool *pool = dma_pool_create("Pool", NULL, ++ size, align, alloc); ++ return (dwc_pool_t *)pool; ++} ++ ++void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool) ++{ ++ dma_pool_destroy((struct dma_pool *)pool); ++} ++ ++void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr) ++{ ++ return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr); ++} ++ ++void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr) ++{ ++ void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr); ++ memset(..); ++} ++ ++void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr) ++{ ++ dma_pool_free(pool, vaddr, daddr); ++} ++#endif ++ ++void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) ++{ ++#ifdef xxCOSIM /* Only works for 32-bit cosim */ ++ void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL); ++#else ++ void *buf = dma_alloc_coherent(dma_ctx, (size_t)size, dma_addr, GFP_KERNEL | GFP_DMA32); ++#endif + if (!buf) { + return NULL; + } ++ + memset(buf, 0, (size_t)size); + return buf; +} -+EXPORT_SYMBOL(__DWC_DMA_ALLOC); + -+void __DWC_DMA_FREE(uint32_t size, void *virt_addr, dwc_dma_t dma_addr) -+{ -+ dma_free_coherent(NULL, size, virt_addr, dma_addr); -+} -+EXPORT_SYMBOL(__DWC_DMA_FREE); -+ -+void *__DWC_DMA_ALLOC_ATOMIC(uint32_t size, dwc_dma_t *dma_addr) ++void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) +{ + void *buf = dma_alloc_coherent(NULL, (size_t)size, dma_addr, GFP_ATOMIC); + if (!buf) { @@ -31560,119 +35384,199 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu + memset(buf, 0, (size_t)size); + return buf; +} -+EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC); + -+void *__DWC_ALLOC(uint32_t size) ++void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr) ++{ ++ dma_free_coherent(dma_ctx, size, virt_addr, dma_addr); ++} ++ ++void *__DWC_ALLOC(void *mem_ctx, uint32_t size) +{ + return kzalloc(size, GFP_KERNEL); +} -+EXPORT_SYMBOL(__DWC_ALLOC); + -+void *__DWC_ALLOC_ATOMIC(uint32_t size) ++void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size) +{ + return kzalloc(size, GFP_ATOMIC); +} -+EXPORT_SYMBOL(__DWC_ALLOC_ATOMIC); + -+void __DWC_FREE(void *addr) ++void __DWC_FREE(void *mem_ctx, void *addr) +{ + kfree(addr); +} -+EXPORT_SYMBOL(__DWC_FREE); + -+/* Byte Ordering Conversions. */ -+uint32_t DWC_CPU_TO_LE32(void *p) ++ ++#ifdef DWC_CRYPTOLIB ++/* dwc_crypto.h */ ++ ++void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length) ++{ ++ get_random_bytes(buffer, length); ++} ++ ++int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out) ++{ ++ struct crypto_blkcipher *tfm; ++ struct blkcipher_desc desc; ++ struct scatterlist sgd; ++ struct scatterlist sgs; ++ ++ tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); ++ if (tfm == NULL) { ++ printk("failed to load transform for aes CBC\n"); ++ return -1; ++ } ++ ++ crypto_blkcipher_setkey(tfm, key, keylen); ++ crypto_blkcipher_set_iv(tfm, iv, 16); ++ ++ sg_init_one(&sgd, out, messagelen); ++ sg_init_one(&sgs, message, messagelen); ++ ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) { ++ crypto_free_blkcipher(tfm); ++ DWC_ERROR("AES CBC encryption failed"); ++ return -1; ++ } ++ ++ crypto_free_blkcipher(tfm); ++ return 0; ++} ++ ++int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ DWC_ERROR("Failed to load transform for sha256: %ld\n", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, len); ++ crypto_hash_digest(&desc, &sg, len, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++ ++int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, ++ uint8_t *key, uint32_t keylen, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ DWC_ERROR("Failed to load transform for hmac(sha256): %ld\n", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, messagelen); ++ crypto_hash_setkey(tfm, key, keylen); ++ crypto_hash_digest(&desc, &sg, messagelen, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++#endif /* DWC_CRYPTOLIB */ ++ ++ ++/* Byte Ordering Conversions */ ++ ++uint32_t DWC_CPU_TO_LE32(uint32_t *p) +{ +#ifdef __LITTLE_ENDIAN -+ return *((uint32_t *)p); ++ return *p; +#else + uint8_t *u_p = (uint8_t *)p; + + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); +#endif +} -+EXPORT_SYMBOL(DWC_CPU_TO_LE32); + -+uint32_t DWC_CPU_TO_BE32(void *p) ++uint32_t DWC_CPU_TO_BE32(uint32_t *p) +{ +#ifdef __BIG_ENDIAN -+ return *((uint32_t *)p); ++ return *p; +#else + uint8_t *u_p = (uint8_t *)p; + + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); +#endif +} -+EXPORT_SYMBOL(DWC_CPU_TO_BE32); + -+uint32_t DWC_LE32_TO_CPU(void *p) ++uint32_t DWC_LE32_TO_CPU(uint32_t *p) +{ +#ifdef __LITTLE_ENDIAN -+ return *((uint32_t *)p); -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ -+ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); -+ -+#endif -+} -+EXPORT_SYMBOL(DWC_LE32_TO_CPU); -+ -+uint32_t DWC_BE32_TO_CPU(void *p) -+{ -+#ifdef __BIG_ENDIAN -+ return *((uint32_t *)p); ++ return *p; +#else + uint8_t *u_p = (uint8_t *)p; + + return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); +#endif +} -+EXPORT_SYMBOL(DWC_BE32_TO_CPU); + -+uint16_t DWC_CPU_TO_LE16(void *p) -+{ -+#ifdef __LITTLE_ENDIAN -+ return *((uint16_t *)p); -+#else -+ uint8_t *u_p = (uint8_t *)p; -+ return (u_p[1] | (u_p[0] << 8)); -+#endif -+} -+EXPORT_SYMBOL(DWC_CPU_TO_LE16); -+ -+uint16_t DWC_CPU_TO_BE16(void *p) ++uint32_t DWC_BE32_TO_CPU(uint32_t *p) +{ +#ifdef __BIG_ENDIAN -+ return *((uint16_t *)p); ++ return *p; +#else + uint8_t *u_p = (uint8_t *)p; -+ return (u_p[1] | (u_p[0] << 8)); ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); +#endif +} -+EXPORT_SYMBOL(DWC_CPU_TO_BE16); + -+uint16_t DWC_LE16_TO_CPU(void *p) ++uint16_t DWC_CPU_TO_LE16(uint16_t *p) +{ +#ifdef __LITTLE_ENDIAN -+ return *((uint16_t *)p); ++ return *p; +#else + uint8_t *u_p = (uint8_t *)p; + return (u_p[1] | (u_p[0] << 8)); +#endif +} -+EXPORT_SYMBOL(DWC_LE16_TO_CPU); + -+uint16_t DWC_BE16_TO_CPU(void *p) ++uint16_t DWC_CPU_TO_BE16(uint16_t *p) +{ +#ifdef __BIG_ENDIAN -+ return *((uint16_t *p)p); ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_LE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_BE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; +#else + uint8_t *u_p = (uint8_t *)p; + return (u_p[1] | (u_p[0] << 8)); +#endif +} -+EXPORT_SYMBOL(DWC_BE16_TO_CPU); + + +/* Registers */ @@ -31681,7 +35585,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu +{ + return readl(reg); +} -+EXPORT_SYMBOL(DWC_READ_REG32); + +#if 0 +uint64_t DWC_READ_REG64(uint64_t volatile *reg) @@ -31693,7 +35596,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu +{ + writel(value, reg); +} -+EXPORT_SYMBOL(DWC_WRITE_REG32); + +#if 0 +void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value) @@ -31703,216 +35605,33 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu + +void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask) +{ -+ writel( (readl(reg) & ~clear_mask) | set_mask, reg ); ++ writel((readl(reg) & ~clear_mask) | set_mask, reg); +} -+EXPORT_SYMBOL(DWC_MODIFY_REG32); + +#if 0 -+void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t value) ++void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask) +{ +} +#endif + + -+ -+/* Threading */ -+ -+typedef struct work_container -+{ -+ dwc_work_callback_t cb; -+ void *data; -+ dwc_workq_t *wq; -+ char *name; -+ -+#ifdef DEBUG -+ DWC_CIRCLEQ_ENTRY(work_container) entry; -+#endif -+ -+ struct delayed_work work; -+} work_container_t; -+ -+#ifdef DEBUG -+DWC_CIRCLEQ_HEAD(work_container_queue, work_container); -+#endif -+ -+struct dwc_workq -+{ -+ struct workqueue_struct *wq; -+ int pending; -+ dwc_spinlock_t *lock; -+ dwc_waitq_t *waitq; -+ -+#ifdef DEBUG -+ struct work_container_queue entries; -+#endif -+}; -+ -+static void do_work(struct work_struct *work) -+{ -+ int64_t flags; -+ struct delayed_work *dw = container_of(work, struct delayed_work, work); -+ work_container_t *container = container_of(dw, struct work_container, work); -+ dwc_workq_t *wq = container->wq; -+ -+ container->cb(container->data); -+ -+#ifdef DEBUG -+ DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry); -+#endif -+ -+ if (container->name) { -+ DWC_DEBUG("Work done: %s, container=%p", -+ container->name, container); //GRAYG -+ DWC_FREE(container->name); -+ } -+ DWC_FREE(container); -+ -+ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -+ wq->pending --; -+ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -+ DWC_WAITQ_TRIGGER(wq->waitq); -+} -+ -+static int work_done(void *data) -+{ -+ dwc_workq_t *workq = (dwc_workq_t *)data; -+ return workq->pending == 0; -+} -+ -+int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout) -+{ -+ return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout); -+} -+EXPORT_SYMBOL(DWC_WORKQ_WAIT_WORK_DONE); -+ -+dwc_workq_t *DWC_WORKQ_ALLOC(char *name) -+{ -+ dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq)); -+ wq->wq = create_singlethread_workqueue(name); -+ wq->pending = 0; -+ wq->lock = DWC_SPINLOCK_ALLOC(); -+ wq->waitq = DWC_WAITQ_ALLOC(); -+#ifdef DEBUG -+ DWC_CIRCLEQ_INIT(&wq->entries); -+#endif -+ return wq; -+} -+EXPORT_SYMBOL(DWC_WORKQ_ALLOC); -+ -+void DWC_WORKQ_FREE(dwc_workq_t *wq) -+{ -+#ifdef DEBUG -+ if (wq->pending != 0) { -+ struct work_container *wc; -+ DWC_ERROR("Destroying work queue with pending work"); -+ DWC_CIRCLEQ_FOREACH(wc, &wq->entries, entry) { -+ DWC_ERROR("Work %s still pending", wc->name); -+ } -+ } -+#endif -+ destroy_workqueue((struct workqueue_struct *)wq->wq); -+ DWC_SPINLOCK_FREE(wq->lock); -+ DWC_WAITQ_FREE(wq->waitq); -+ DWC_FREE(wq); -+} -+EXPORT_SYMBOL(DWC_WORKQ_FREE); -+ -+void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t work_cb, void *data, char *format, ...) -+{ -+ int64_t flags; -+ work_container_t *container; -+ static char name[128]; -+ -+ va_list args; -+ va_start(args, format); -+ if (format) -+ DWC_VSNPRINTF(name, 128, format, args); -+ va_end(args); -+ -+ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -+ wq->pending ++; -+ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -+ DWC_WAITQ_TRIGGER(wq->waitq); -+ -+ container = DWC_ALLOC_ATOMIC(sizeof(*container)); -+ -+ container->data = data; -+ container->cb = work_cb; -+ container->wq = wq; -+ if (format) { -+ container->name = DWC_STRDUP(name); -+ DWC_DEBUG("Queueing work: %s, contianer=%p", -+ container->name, container); -+ } else -+ container->name = NULL; -+ -+ INIT_WORK(&container->work.work, do_work); -+ -+#ifdef DEBUG -+ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); -+#endif -+ -+ queue_work(wq->wq, &container->work.work); -+ -+} -+EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE); -+ -+void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t work_cb, void *data, uint32_t time, char *format, ...) -+{ -+ int64_t flags; -+ work_container_t *container; -+ static char name[128]; -+ -+ va_list args; -+ va_start(args, format); -+ if (format) -+ DWC_VSNPRINTF(name, 128, format, args); -+ va_end(args); -+ -+ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); -+ wq->pending ++; -+ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); -+ DWC_WAITQ_TRIGGER(wq->waitq); -+ -+ container = DWC_ALLOC_ATOMIC(sizeof(*container)); -+ -+ container->data = data; -+ container->cb = work_cb; -+ container->wq = wq; -+ if (format) { //GRAYG -+ container->name = DWC_STRDUP(name); -+ DWC_DEBUG("Queueing work: %s, contianer=%p", -+ container->name, container); -+ } else -+ container->name = NULL; -+ INIT_DELAYED_WORK(&container->work, do_work); -+ -+#ifdef DEBUG -+ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); -+#endif -+ -+ queue_delayed_work(wq->wq, &container->work, msecs_to_jiffies(time)); -+ -+} -+EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE_DELAYED); -+ -+ -+int DWC_WORKQ_PENDING(dwc_workq_t *wq) -+{ -+ return wq->pending; -+} -+EXPORT_SYMBOL(DWC_WORKQ_PENDING); ++/* Locking */ + +dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void) +{ + spinlock_t *sl = (spinlock_t *)1; ++ +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) + sl = DWC_ALLOC(sizeof(*sl)); ++ if (!sl) { ++ DWC_ERROR("Cannot allocate memory for spinlock\n"); ++ return NULL; ++ } ++ + spin_lock_init(sl); +#endif + return (dwc_spinlock_t *)sl; +} -+EXPORT_SYMBOL(DWC_SPINLOCK_ALLOC); + +void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock) +{ @@ -31920,7 +35639,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu + DWC_FREE(lock); +#endif +} -+EXPORT_SYMBOL(DWC_SPINLOCK_FREE); + +void DWC_SPINLOCK(dwc_spinlock_t *lock) +{ @@ -31928,7 +35646,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu + spin_lock((spinlock_t *)lock); +#endif +} -+EXPORT_SYMBOL(DWC_SPINLOCK); + +void DWC_SPINUNLOCK(dwc_spinlock_t *lock) +{ @@ -31936,39 +35653,42 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu + spin_unlock((spinlock_t *)lock); +#endif +} -+EXPORT_SYMBOL(DWC_SPINUNLOCK); + -+void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, uint64_t *flags) ++void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags) +{ -+ unsigned long f; ++ dwc_irqflags_t f; ++ +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -+ spin_lock_irqsave((spinlock_t *)lock, f); ++ spin_lock_irqsave((spinlock_t *)lock, f); +#else + local_irq_save(f); +#endif -+ *flags = f; ++ *flags = f; +} -+EXPORT_SYMBOL(DWC_SPINLOCK_IRQSAVE); + -+void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, uint64_t flags) ++void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags) +{ +#if defined(CONFIG_PREEMPT) || defined(CONFIG_SMP) -+ spin_unlock_irqrestore((spinlock_t *)lock, flags); ++ spin_unlock_irqrestore((spinlock_t *)lock, flags); +#else -+ // in kernel 2.6.31, at least, we check for unsigned long -+ local_irq_restore((unsigned long)flags); ++ local_irq_restore(flags); +#endif +} -+EXPORT_SYMBOL(DWC_SPINUNLOCK_IRQRESTORE); + +dwc_mutex_t *DWC_MUTEX_ALLOC(void) +{ -+ dwc_mutex_t *mutex = (dwc_mutex_t*)DWC_ALLOC(sizeof(struct mutex)); -+ struct mutex *m = (struct mutex *)mutex; ++ struct mutex *m; ++ dwc_mutex_t *mutex = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); ++ ++ if (!mutex) { ++ DWC_ERROR("Cannot allocate memory for mutex\n"); ++ return NULL; ++ } ++ ++ m = (struct mutex *)mutex; + mutex_init(m); + return mutex; +} -+EXPORT_SYMBOL(DWC_MUTEX_ALLOC); + +#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) +#else @@ -31977,7 +35697,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu + mutex_destroy((struct mutex *)mutex); + DWC_FREE(mutex); +} -+EXPORT_SYMBOL(DWC_MUTEX_FREE); +#endif + +void DWC_MUTEX_LOCK(dwc_mutex_t *mutex) @@ -31985,48 +35704,46 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu + struct mutex *m = (struct mutex *)mutex; + mutex_lock(m); +} -+EXPORT_SYMBOL(DWC_MUTEX_LOCK); + +int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex) +{ + struct mutex *m = (struct mutex *)mutex; + return mutex_trylock(m); +} -+EXPORT_SYMBOL(DWC_MUTEX_TRYLOCK); + +void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex) +{ + struct mutex *m = (struct mutex *)mutex; + mutex_unlock(m); +} -+EXPORT_SYMBOL(DWC_MUTEX_UNLOCK); + -+dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t thread_function, char *name, void *data) -+{ -+ struct task_struct *thread = kthread_run(thread_function, data, name); -+ if (thread == ERR_PTR(-ENOMEM)) { -+ return NULL; -+ } -+ return (dwc_thread_t *)thread; -+} -+EXPORT_SYMBOL(DWC_THREAD_RUN); + -+int DWC_THREAD_STOP(dwc_thread_t *thread) -+{ -+ return kthread_stop((struct task_struct *)thread); -+} -+EXPORT_SYMBOL(DWC_THREAD_STOP); ++/* Timing */ + -+dwc_bool_t DWC_THREAD_SHOULD_STOP() ++void DWC_UDELAY(uint32_t usecs) +{ -+ return kthread_should_stop(); ++ udelay(usecs); +} -+EXPORT_SYMBOL(DWC_THREAD_SHOULD_STOP); ++ ++void DWC_MDELAY(uint32_t msecs) ++{ ++ mdelay(msecs); ++} ++ ++void DWC_MSLEEP(uint32_t msecs) ++{ ++ msleep(msecs); ++} ++ ++uint32_t DWC_TIME(void) ++{ ++ return jiffies_to_msecs(jiffies); ++} ++ + +/* Timers */ + -+struct dwc_timer -+{ ++struct dwc_timer { + struct timer_list *t; + char *name; + dwc_timer_callback_t cb; @@ -32035,39 +35752,27 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu + dwc_spinlock_t *lock; +}; + -+static void set_scheduled(dwc_timer_t *t, int s) -+{ -+ uint64_t flags; -+ DWC_SPINLOCK_IRQSAVE(t->lock, &flags); -+ t->scheduled = s; -+ DWC_SPINUNLOCK_IRQRESTORE(t->lock, flags); -+} -+ -+static int get_scheduled(dwc_timer_t *t) -+{ -+ int s; -+ uint64_t flags; -+ DWC_SPINLOCK_IRQSAVE(t->lock, &flags); -+ s = t->scheduled; -+ DWC_SPINUNLOCK_IRQRESTORE(t->lock, flags); -+ return s; -+} -+ +static void timer_callback(unsigned long data) +{ + dwc_timer_t *timer = (dwc_timer_t *)data; -+ set_scheduled(timer, 0); -+ /*DWC_DEBUG("Timer %s callback", timer->name);*/ ++ dwc_irqflags_t flags; ++ ++ DWC_SPINLOCK_IRQSAVE(timer->lock, &flags); ++ timer->scheduled = 0; ++ DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags); ++ DWC_DEBUGC("Timer %s callback", timer->name); + timer->cb(timer->data); +} + +dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data) +{ + dwc_timer_t *t = DWC_ALLOC(sizeof(*t)); ++ + if (!t) { + DWC_ERROR("Cannot allocate memory for timer"); + return NULL; + } ++ + t->t = DWC_ALLOC(sizeof(*t->t)); + if (!t->t) { + DWC_ERROR("Cannot allocate memory for timer->t"); @@ -32085,6 +35790,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu + DWC_ERROR("Cannot allocate memory for lock"); + goto no_lock; + } ++ + t->scheduled = 0; + t->t->base = &boot_tvec_bases; + t->t->expires = jiffies; @@ -32103,46 +35809,179 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu + DWC_FREE(t); + return NULL; +} -+EXPORT_SYMBOL(DWC_TIMER_ALLOC); + +void DWC_TIMER_FREE(dwc_timer_t *timer) +{ -+ if (get_scheduled(timer)) { ++ dwc_irqflags_t flags; ++ ++ DWC_SPINLOCK_IRQSAVE(timer->lock, &flags); ++ ++ if (timer->scheduled) { + del_timer(timer->t); ++ timer->scheduled = 0; + } + ++ DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags); + DWC_SPINLOCK_FREE(timer->lock); + DWC_FREE(timer->t); + DWC_FREE(timer->name); + DWC_FREE(timer); +} -+EXPORT_SYMBOL(DWC_TIMER_FREE); + +void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time) +{ -+ if (!get_scheduled(timer)) { -+ set_scheduled(timer, 1); -+ //cgg: DWC_DEBUG("Scheduling timer %s to expire in +%d msec", timer->name, time); ++ dwc_irqflags_t flags; ++ ++ DWC_SPINLOCK_IRQSAVE(timer->lock, &flags); ++ ++ if (!timer->scheduled) { ++ timer->scheduled = 1; ++ DWC_DEBUGC("Scheduling timer %s to expire in +%d msec", timer->name, time); + timer->t->expires = jiffies + msecs_to_jiffies(time); + add_timer(timer->t); -+ } -+ else { -+ //cgg: DWC_DEBUG("Modifying timer %s to expire in +%d msec", timer->name, time); ++ } else { ++ DWC_DEBUGC("Modifying timer %s to expire in +%d msec", timer->name, time); + mod_timer(timer->t, jiffies + msecs_to_jiffies(time)); + } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(timer->lock, flags); +} -+EXPORT_SYMBOL(DWC_TIMER_SCHEDULE); + +void DWC_TIMER_CANCEL(dwc_timer_t *timer) +{ + del_timer(timer->t); +} -+EXPORT_SYMBOL(DWC_TIMER_CANCEL); + -+struct dwc_tasklet ++ ++/* Wait Queues */ ++ ++struct dwc_waitq { ++ wait_queue_head_t queue; ++ int abort; ++}; ++ ++dwc_waitq_t *DWC_WAITQ_ALLOC(void) +{ ++ dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ DWC_ERROR("Cannot allocate memory for waitqueue\n"); ++ return NULL; ++ } ++ ++ init_waitqueue_head(&wq->queue); ++ wq->abort = 0; ++ return wq; ++} ++ ++void DWC_WAITQ_FREE(dwc_waitq_t *wq) ++{ ++ DWC_FREE(wq); ++} ++ ++int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data) ++{ ++ int result = wait_event_interruptible(wq->queue, ++ cond(data) || wq->abort); ++ if (result == -ERESTARTSYS) { ++ wq->abort = 0; ++ return -DWC_E_RESTART; ++ } ++ ++ if (wq->abort == 1) { ++ wq->abort = 0; ++ return -DWC_E_ABORT; ++ } ++ ++ wq->abort = 0; ++ ++ if (result == 0) { ++ return 0; ++ } ++ ++ return -DWC_E_UNKNOWN; ++} ++ ++int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, ++ void *data, int32_t msecs) ++{ ++ int32_t tmsecs; ++ int result = wait_event_interruptible_timeout(wq->queue, ++ cond(data) || wq->abort, ++ msecs_to_jiffies(msecs)); ++ if (result == -ERESTARTSYS) { ++ wq->abort = 0; ++ return -DWC_E_RESTART; ++ } ++ ++ if (wq->abort == 1) { ++ wq->abort = 0; ++ return -DWC_E_ABORT; ++ } ++ ++ wq->abort = 0; ++ ++ if (result > 0) { ++ tmsecs = jiffies_to_msecs(result); ++ if (!tmsecs) { ++ return 1; ++ } ++ ++ return tmsecs; ++ } ++ ++ if (result == 0) { ++ return -DWC_E_TIMEOUT; ++ } ++ ++ return -DWC_E_UNKNOWN; ++} ++ ++void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq) ++{ ++ wq->abort = 0; ++ wake_up_interruptible(&wq->queue); ++} ++ ++void DWC_WAITQ_ABORT(dwc_waitq_t *wq) ++{ ++ wq->abort = 1; ++ wake_up_interruptible(&wq->queue); ++} ++ ++ ++/* Threading */ ++ ++dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data) ++{ ++ struct task_struct *thread = kthread_run(func, data, name); ++ ++ if (thread == ERR_PTR(-ENOMEM)) { ++ return NULL; ++ } ++ ++ return (dwc_thread_t *)thread; ++} ++ ++int DWC_THREAD_STOP(dwc_thread_t *thread) ++{ ++ return kthread_stop((struct task_struct *)thread); ++} ++ ++dwc_bool_t DWC_THREAD_SHOULD_STOP(void) ++{ ++ return kthread_should_stop(); ++} ++ ++ ++/* tasklets ++ - run in interrupt context (cannot sleep) ++ - each tasklet runs on a single CPU ++ - different tasklets can be running simultaneously on different CPUs ++ */ ++struct dwc_tasklet { + struct tasklet_struct t; -+ dwc_tasklet_callback_t cb; ++ dwc_tasklet_callback_t cb; + void *data; +}; + @@ -32152,139 +35991,2586 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_common_linux.c linu + t->cb(t->data); +} + -+dwc_tasklet_t *DWC_TASK_ALLOC(dwc_tasklet_callback_t cb, void *data) ++dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data) +{ + dwc_tasklet_t *t = DWC_ALLOC(sizeof(*t)); -+ -+ if(t) { -+ t->data = data; ++ ++ if (t) { + t->cb = cb; ++ t->data = data; + tasklet_init(&t->t, tasklet_callback, (unsigned long)t); + } else { + DWC_ERROR("Cannot allocate memory for tasklet\n"); + } -+ ++ + return t; +} -+EXPORT_SYMBOL(DWC_TASK_ALLOC); + -+void DWC_TASK_FREE(dwc_tasklet_t *t) ++void DWC_TASK_FREE(dwc_tasklet_t *task) +{ -+ DWC_FREE(t); ++ DWC_FREE(task); +} -+EXPORT_SYMBOL(DWC_TASK_FREE); + +void DWC_TASK_SCHEDULE(dwc_tasklet_t *task) +{ + tasklet_schedule(&task->t); +} ++ ++ ++/* workqueues ++ - run in process context (can sleep) ++ */ ++typedef struct work_container { ++ dwc_work_callback_t cb; ++ void *data; ++ dwc_workq_t *wq; ++ char *name; ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_ENTRY(work_container) entry; ++#endif ++ struct delayed_work work; ++} work_container_t; ++ ++#ifdef DEBUG ++DWC_CIRCLEQ_HEAD(work_container_queue, work_container); ++#endif ++ ++struct dwc_workq { ++ struct workqueue_struct *wq; ++ dwc_spinlock_t *lock; ++ dwc_waitq_t *waitq; ++ int pending; ++ ++#ifdef DEBUG ++ struct work_container_queue entries; ++#endif ++}; ++ ++static void do_work(struct work_struct *work) ++{ ++ dwc_irqflags_t flags; ++ struct delayed_work *dw = container_of(work, struct delayed_work, work); ++ work_container_t *container = container_of(dw, struct work_container, work); ++ dwc_workq_t *wq = container->wq; ++ ++ container->cb(container->data); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_REMOVE(&wq->entries, container, entry); ++#endif ++ DWC_DEBUGC("Work done: %s, container=%p", container->name, container); ++ if (container->name) { ++ DWC_FREE(container->name); ++ } ++ DWC_FREE(container); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending--; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++} ++ ++static int work_done(void *data) ++{ ++ dwc_workq_t *workq = (dwc_workq_t *)data; ++ return workq->pending == 0; ++} ++ ++int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout) ++{ ++ return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout); ++} ++ ++dwc_workq_t *DWC_WORKQ_ALLOC(char *name) ++{ ++ dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ return NULL; ++ } ++ ++ wq->wq = create_singlethread_workqueue(name); ++ if (!wq->wq) { ++ goto no_wq; ++ } ++ ++ wq->pending = 0; ++ ++ wq->lock = DWC_SPINLOCK_ALLOC(); ++ if (!wq->lock) { ++ goto no_lock; ++ } ++ ++ wq->waitq = DWC_WAITQ_ALLOC(); ++ if (!wq->waitq) { ++ goto no_waitq; ++ } ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_INIT(&wq->entries); ++#endif ++ return wq; ++ ++ no_waitq: ++ DWC_SPINLOCK_FREE(wq->lock); ++ no_lock: ++ destroy_workqueue(wq->wq); ++ no_wq: ++ DWC_FREE(wq); ++ ++ return NULL; ++} ++ ++void DWC_WORKQ_FREE(dwc_workq_t *wq) ++{ ++#ifdef DEBUG ++ if (wq->pending != 0) { ++ struct work_container *wc; ++ DWC_ERROR("Destroying work queue with pending work"); ++ DWC_CIRCLEQ_FOREACH(wc, &wq->entries, entry) { ++ DWC_ERROR("Work %s still pending", wc->name); ++ } ++ } ++#endif ++ destroy_workqueue(wq->wq); ++ DWC_SPINLOCK_FREE(wq->lock); ++ DWC_WAITQ_FREE(wq->waitq); ++ DWC_FREE(wq); ++} ++ ++void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data, ++ char *format, ...) ++{ ++ dwc_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++ ++ container = DWC_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ DWC_ERROR("Cannot allocate memory for container\n"); ++ return; ++ } ++ ++ container->name = DWC_STRDUP(name); ++ if (!container->name) { ++ DWC_ERROR("Cannot allocate memory for container->name\n"); ++ DWC_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container); ++ INIT_WORK(&container->work.work, do_work); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); ++#endif ++ queue_work(wq->wq, &container->work.work); ++} ++ ++void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb, ++ void *data, uint32_t time, char *format, ...) ++{ ++ dwc_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++ ++ container = DWC_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ DWC_ERROR("Cannot allocate memory for container\n"); ++ return; ++ } ++ ++ container->name = DWC_STRDUP(name); ++ if (!container->name) { ++ DWC_ERROR("Cannot allocate memory for container->name\n"); ++ DWC_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ DWC_DEBUGC("Queueing work: %s, container=%p", container->name, container); ++ INIT_DELAYED_WORK(&container->work, do_work); ++ ++#ifdef DEBUG ++ DWC_CIRCLEQ_INSERT_TAIL(&wq->entries, container, entry); ++#endif ++ queue_delayed_work(wq->wq, &container->work, msecs_to_jiffies(time)); ++} ++ ++int DWC_WORKQ_PENDING(dwc_workq_t *wq) ++{ ++ return wq->pending; ++} ++ ++ ++#ifdef DWC_LIBMODULE ++ ++#ifdef DWC_CCLIB ++/* CC */ ++EXPORT_SYMBOL(dwc_cc_if_alloc); ++EXPORT_SYMBOL(dwc_cc_if_free); ++EXPORT_SYMBOL(dwc_cc_clear); ++EXPORT_SYMBOL(dwc_cc_add); ++EXPORT_SYMBOL(dwc_cc_remove); ++EXPORT_SYMBOL(dwc_cc_change); ++EXPORT_SYMBOL(dwc_cc_data_for_save); ++EXPORT_SYMBOL(dwc_cc_restore_from_data); ++EXPORT_SYMBOL(dwc_cc_match_chid); ++EXPORT_SYMBOL(dwc_cc_match_cdid); ++EXPORT_SYMBOL(dwc_cc_ck); ++EXPORT_SYMBOL(dwc_cc_chid); ++EXPORT_SYMBOL(dwc_cc_cdid); ++EXPORT_SYMBOL(dwc_cc_name); ++#endif /* DWC_CCLIB */ ++ ++#ifdef DWC_CRYPTOLIB ++# ifndef CONFIG_MACH_IPMATE ++/* Modpow */ ++EXPORT_SYMBOL(dwc_modpow); ++ ++/* DH */ ++EXPORT_SYMBOL(dwc_dh_modpow); ++EXPORT_SYMBOL(dwc_dh_derive_keys); ++EXPORT_SYMBOL(dwc_dh_pk); ++# endif /* CONFIG_MACH_IPMATE */ ++ ++/* Crypto */ ++EXPORT_SYMBOL(dwc_wusb_aes_encrypt); ++EXPORT_SYMBOL(dwc_wusb_cmf); ++EXPORT_SYMBOL(dwc_wusb_prf); ++EXPORT_SYMBOL(dwc_wusb_fill_ccm_nonce); ++EXPORT_SYMBOL(dwc_wusb_gen_nonce); ++EXPORT_SYMBOL(dwc_wusb_gen_key); ++EXPORT_SYMBOL(dwc_wusb_gen_mic); ++#endif /* DWC_CRYPTOLIB */ ++ ++/* Notification */ ++#ifdef DWC_NOTIFYLIB ++EXPORT_SYMBOL(dwc_alloc_notification_manager); ++EXPORT_SYMBOL(dwc_free_notification_manager); ++EXPORT_SYMBOL(dwc_register_notifier); ++EXPORT_SYMBOL(dwc_unregister_notifier); ++EXPORT_SYMBOL(dwc_add_observer); ++EXPORT_SYMBOL(dwc_remove_observer); ++EXPORT_SYMBOL(dwc_notify); ++#endif ++ ++/* Memory Debugging Routines */ ++#ifdef DWC_DEBUG_MEMORY ++EXPORT_SYMBOL(dwc_alloc_debug); ++EXPORT_SYMBOL(dwc_alloc_atomic_debug); ++EXPORT_SYMBOL(dwc_free_debug); ++EXPORT_SYMBOL(dwc_dma_alloc_debug); ++EXPORT_SYMBOL(dwc_dma_free_debug); ++#endif ++ ++EXPORT_SYMBOL(DWC_MEMSET); ++EXPORT_SYMBOL(DWC_MEMCPY); ++EXPORT_SYMBOL(DWC_MEMMOVE); ++EXPORT_SYMBOL(DWC_MEMCMP); ++EXPORT_SYMBOL(DWC_STRNCMP); ++EXPORT_SYMBOL(DWC_STRCMP); ++EXPORT_SYMBOL(DWC_STRLEN); ++EXPORT_SYMBOL(DWC_STRCPY); ++EXPORT_SYMBOL(DWC_STRDUP); ++EXPORT_SYMBOL(DWC_ATOI); ++EXPORT_SYMBOL(DWC_ATOUI); ++ ++#ifdef DWC_UTFLIB ++EXPORT_SYMBOL(DWC_UTF8_TO_UTF16LE); ++#endif /* DWC_UTFLIB */ ++ ++EXPORT_SYMBOL(DWC_IN_IRQ); ++EXPORT_SYMBOL(DWC_IN_BH); ++EXPORT_SYMBOL(DWC_VPRINTF); ++EXPORT_SYMBOL(DWC_VSNPRINTF); ++EXPORT_SYMBOL(DWC_PRINTF); ++EXPORT_SYMBOL(DWC_SPRINTF); ++EXPORT_SYMBOL(DWC_SNPRINTF); ++EXPORT_SYMBOL(__DWC_WARN); ++EXPORT_SYMBOL(__DWC_ERROR); ++EXPORT_SYMBOL(DWC_EXCEPTION); ++ ++#ifdef DEBUG ++EXPORT_SYMBOL(__DWC_DEBUG); ++#endif ++ ++EXPORT_SYMBOL(__DWC_DMA_ALLOC); ++EXPORT_SYMBOL(__DWC_DMA_ALLOC_ATOMIC); ++EXPORT_SYMBOL(__DWC_DMA_FREE); ++EXPORT_SYMBOL(__DWC_ALLOC); ++EXPORT_SYMBOL(__DWC_ALLOC_ATOMIC); ++EXPORT_SYMBOL(__DWC_FREE); ++ ++#ifdef DWC_CRYPTOLIB ++EXPORT_SYMBOL(DWC_RANDOM_BYTES); ++EXPORT_SYMBOL(DWC_AES_CBC); ++EXPORT_SYMBOL(DWC_SHA256); ++EXPORT_SYMBOL(DWC_HMAC_SHA256); ++#endif ++ ++EXPORT_SYMBOL(DWC_CPU_TO_LE32); ++EXPORT_SYMBOL(DWC_CPU_TO_BE32); ++EXPORT_SYMBOL(DWC_LE32_TO_CPU); ++EXPORT_SYMBOL(DWC_BE32_TO_CPU); ++EXPORT_SYMBOL(DWC_CPU_TO_LE16); ++EXPORT_SYMBOL(DWC_CPU_TO_BE16); ++EXPORT_SYMBOL(DWC_LE16_TO_CPU); ++EXPORT_SYMBOL(DWC_BE16_TO_CPU); ++EXPORT_SYMBOL(DWC_READ_REG32); ++EXPORT_SYMBOL(DWC_WRITE_REG32); ++EXPORT_SYMBOL(DWC_MODIFY_REG32); ++ ++#if 0 ++EXPORT_SYMBOL(DWC_READ_REG64); ++EXPORT_SYMBOL(DWC_WRITE_REG64); ++EXPORT_SYMBOL(DWC_MODIFY_REG64); ++#endif ++ ++EXPORT_SYMBOL(DWC_SPINLOCK_ALLOC); ++EXPORT_SYMBOL(DWC_SPINLOCK_FREE); ++EXPORT_SYMBOL(DWC_SPINLOCK); ++EXPORT_SYMBOL(DWC_SPINUNLOCK); ++EXPORT_SYMBOL(DWC_SPINLOCK_IRQSAVE); ++EXPORT_SYMBOL(DWC_SPINUNLOCK_IRQRESTORE); ++EXPORT_SYMBOL(DWC_MUTEX_ALLOC); ++ ++#if (!defined(DWC_LINUX) || !defined(CONFIG_DEBUG_MUTEXES)) ++EXPORT_SYMBOL(DWC_MUTEX_FREE); ++#endif ++ ++EXPORT_SYMBOL(DWC_MUTEX_LOCK); ++EXPORT_SYMBOL(DWC_MUTEX_TRYLOCK); ++EXPORT_SYMBOL(DWC_MUTEX_UNLOCK); ++EXPORT_SYMBOL(DWC_UDELAY); ++EXPORT_SYMBOL(DWC_MDELAY); ++EXPORT_SYMBOL(DWC_MSLEEP); ++EXPORT_SYMBOL(DWC_TIME); ++EXPORT_SYMBOL(DWC_TIMER_ALLOC); ++EXPORT_SYMBOL(DWC_TIMER_FREE); ++EXPORT_SYMBOL(DWC_TIMER_SCHEDULE); ++EXPORT_SYMBOL(DWC_TIMER_CANCEL); ++EXPORT_SYMBOL(DWC_WAITQ_ALLOC); ++EXPORT_SYMBOL(DWC_WAITQ_FREE); ++EXPORT_SYMBOL(DWC_WAITQ_WAIT); ++EXPORT_SYMBOL(DWC_WAITQ_WAIT_TIMEOUT); ++EXPORT_SYMBOL(DWC_WAITQ_TRIGGER); ++EXPORT_SYMBOL(DWC_WAITQ_ABORT); ++EXPORT_SYMBOL(DWC_THREAD_RUN); ++EXPORT_SYMBOL(DWC_THREAD_STOP); ++EXPORT_SYMBOL(DWC_THREAD_SHOULD_STOP); ++EXPORT_SYMBOL(DWC_TASK_ALLOC); ++EXPORT_SYMBOL(DWC_TASK_FREE); +EXPORT_SYMBOL(DWC_TASK_SCHEDULE); ++EXPORT_SYMBOL(DWC_WORKQ_WAIT_WORK_DONE); ++EXPORT_SYMBOL(DWC_WORKQ_ALLOC); ++EXPORT_SYMBOL(DWC_WORKQ_FREE); ++EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE); ++EXPORT_SYMBOL(DWC_WORKQ_SCHEDULE_DELAYED); ++EXPORT_SYMBOL(DWC_WORKQ_PENDING); ++ ++static int dwc_common_port_init_module(void) ++{ ++ int result = 0; ++ ++ printk(KERN_DEBUG "Module dwc_common_port init\n" ); ++ ++#ifdef DWC_DEBUG_MEMORY ++ result = dwc_memory_debug_start(NULL); ++ if (result) { ++ printk(KERN_ERR ++ "dwc_memory_debug_start() failed with error %d\n", ++ result); ++ return result; ++ } ++#endif ++ ++#ifdef DWC_NOTIFYLIB ++ result = dwc_alloc_notification_manager(NULL, NULL); ++ if (result) { ++ printk(KERN_ERR ++ "dwc_alloc_notification_manager() failed with error %d\n", ++ result); ++ return result; ++ } ++#endif ++ return result; ++} ++ ++static void dwc_common_port_exit_module(void) ++{ ++ printk(KERN_DEBUG "Module dwc_common_port exit\n" ); ++ ++#ifdef DWC_NOTIFYLIB ++ dwc_free_notification_manager(); ++#endif ++ ++#ifdef DWC_DEBUG_MEMORY ++ dwc_memory_debug_stop(); ++#endif ++} ++ ++module_init(dwc_common_port_init_module); ++module_exit(dwc_common_port_exit_module); ++ ++MODULE_DESCRIPTION("DWC Common Library - Portable version"); ++MODULE_AUTHOR("Synopsys Inc."); ++MODULE_LICENSE ("GPL"); ++ ++#endif /* DWC_LIBMODULE */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c b/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c +new file mode 100644 +index 0000000..49b07e1 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_common_nbsd.c +@@ -0,0 +1,1275 @@ ++#include "dwc_os.h" ++#include "dwc_list.h" ++ ++#ifdef DWC_CCLIB ++# include "dwc_cc.h" ++#endif ++ ++#ifdef DWC_CRYPTOLIB ++# include "dwc_modpow.h" ++# include "dwc_dh.h" ++# include "dwc_crypto.h" ++#endif ++ ++#ifdef DWC_NOTIFYLIB ++# include "dwc_notifier.h" ++#endif ++ ++/* OS-Level Implementations */ ++ ++/* This is the NetBSD 4.0.1 kernel implementation of the DWC platform library. */ ++ ++ ++/* MISC */ ++ ++void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size) ++{ ++ return memset(dest, byte, size); ++} ++ ++void *DWC_MEMCPY(void *dest, void const *src, uint32_t size) ++{ ++ return memcpy(dest, src, size); ++} ++ ++void *DWC_MEMMOVE(void *dest, void *src, uint32_t size) ++{ ++ bcopy(src, dest, size); ++ return dest; ++} ++ ++int DWC_MEMCMP(void *m1, void *m2, uint32_t size) ++{ ++ return memcmp(m1, m2, size); ++} ++ ++int DWC_STRNCMP(void *s1, void *s2, uint32_t size) ++{ ++ return strncmp(s1, s2, size); ++} ++ ++int DWC_STRCMP(void *s1, void *s2) ++{ ++ return strcmp(s1, s2); ++} ++ ++int DWC_STRLEN(char const *str) ++{ ++ return strlen(str); ++} ++ ++char *DWC_STRCPY(char *to, char const *from) ++{ ++ return strcpy(to, from); ++} ++ ++char *DWC_STRDUP(char const *str) ++{ ++ int len = DWC_STRLEN(str) + 1; ++ char *new = DWC_ALLOC_ATOMIC(len); ++ ++ if (!new) { ++ return NULL; ++ } ++ ++ DWC_MEMCPY(new, str, len); ++ return new; ++} ++ ++int DWC_ATOI(char *str, int32_t *value) ++{ ++ char *end = NULL; ++ ++ /* NetBSD doesn't have 'strtol' in the kernel, but 'strtoul' ++ * should be equivalent on 2's complement machines ++ */ ++ *value = strtoul(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++int DWC_ATOUI(char *str, uint32_t *value) ++{ ++ char *end = NULL; ++ ++ *value = strtoul(str, &end, 0); ++ if (*end == '\0') { ++ return 0; ++ } ++ ++ return -1; ++} ++ ++ ++#ifdef DWC_UTFLIB ++/* From usbstring.c */ ++ ++int DWC_UTF8_TO_UTF16LE(uint8_t const *s, uint16_t *cp, unsigned len) ++{ ++ int count = 0; ++ u8 c; ++ u16 uchar; ++ ++ /* this insists on correct encodings, though not minimal ones. ++ * BUT it currently rejects legit 4-byte UTF-8 code points, ++ * which need surrogate pairs. (Unicode 3.1 can use them.) ++ */ ++ while (len != 0 && (c = (u8) *s++) != 0) { ++ if (unlikely(c & 0x80)) { ++ // 2-byte sequence: ++ // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx ++ if ((c & 0xe0) == 0xc0) { ++ uchar = (c & 0x1f) << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ // 3-byte sequence (most CJKV characters): ++ // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx ++ } else if ((c & 0xf0) == 0xe0) { ++ uchar = (c & 0x0f) << 12; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c << 6; ++ ++ c = (u8) *s++; ++ if ((c & 0xc0) != 0xc0) ++ goto fail; ++ c &= 0x3f; ++ uchar |= c; ++ ++ /* no bogus surrogates */ ++ if (0xd800 <= uchar && uchar <= 0xdfff) ++ goto fail; ++ ++ // 4-byte sequence (surrogate pairs, currently rare): ++ // 11101110wwwwzzzzyy + 110111yyyyxxxxxx ++ // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx ++ // (uuuuu = wwww + 1) ++ // FIXME accept the surrogate code points (only) ++ } else ++ goto fail; ++ } else ++ uchar = c; ++ put_unaligned (cpu_to_le16 (uchar), cp++); ++ count++; ++ len--; ++ } ++ return count; ++fail: ++ return -1; ++} ++ ++#endif /* DWC_UTFLIB */ ++ ++ ++/* dwc_debug.h */ ++ ++dwc_bool_t DWC_IN_IRQ(void) ++{ ++// return in_irq(); ++ return 0; ++} ++ ++dwc_bool_t DWC_IN_BH(void) ++{ ++// return in_softirq(); ++ return 0; ++} ++ ++void DWC_VPRINTF(char *format, va_list args) ++{ ++ vprintf(format, args); ++} ++ ++int DWC_VSNPRINTF(char *str, int size, char *format, va_list args) ++{ ++ return vsnprintf(str, size, format, args); ++} ++ ++void DWC_PRINTF(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++int DWC_SPRINTF(char *buffer, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsprintf(buffer, format, args); ++ va_end(args); ++ return retval; ++} ++ ++int DWC_SNPRINTF(char *buffer, int size, char *format, ...) ++{ ++ int retval; ++ va_list args; ++ ++ va_start(args, format); ++ retval = vsnprintf(buffer, size, format, args); ++ va_end(args); ++ return retval; ++} ++ ++void __DWC_WARN(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void __DWC_ERROR(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++ ++void DWC_EXCEPTION(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++// BUG_ON(1); ??? ++} ++ ++#ifdef DEBUG ++void __DWC_DEBUG(char *format, ...) ++{ ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VPRINTF(format, args); ++ va_end(args); ++} ++#endif ++ ++ ++/* dwc_mem.h */ ++ ++#if 0 ++dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, ++ uint32_t align, ++ uint32_t alloc) ++{ ++ struct dma_pool *pool = dma_pool_create("Pool", NULL, ++ size, align, alloc); ++ return (dwc_pool_t *)pool; ++} ++ ++void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool) ++{ ++ dma_pool_destroy((struct dma_pool *)pool); ++} ++ ++void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr) ++{ ++// return dma_pool_alloc((struct dma_pool *)pool, GFP_KERNEL, dma_addr); ++ return dma_pool_alloc((struct dma_pool *)pool, M_WAITOK, dma_addr); ++} ++ ++void *DWC_DMA_POOL_ZALLOC(dwc_pool_t *pool, uint64_t *dma_addr) ++{ ++ void *vaddr = DWC_DMA_POOL_ALLOC(pool, dma_addr); ++ memset(..); ++} ++ ++void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr) ++{ ++ dma_pool_free(pool, vaddr, daddr); ++} ++#endif ++ ++void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr) ++{ ++ dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx; ++ int error; ++ ++ error = bus_dmamem_alloc(dma->dma_tag, size, 1, size, dma->segs, ++ sizeof(dma->segs) / sizeof(dma->segs[0]), ++ &dma->nsegs, BUS_DMA_NOWAIT); ++ if (error) { ++ printf("%s: bus_dmamem_alloc(%ju) failed: %d\n", __func__, ++ (uintmax_t)size, error); ++ goto fail_0; ++ } ++ ++ error = bus_dmamem_map(dma->dma_tag, dma->segs, dma->nsegs, size, ++ (caddr_t *)&dma->dma_vaddr, ++ BUS_DMA_NOWAIT | BUS_DMA_COHERENT); ++ if (error) { ++ printf("%s: bus_dmamem_map failed: %d\n", __func__, error); ++ goto fail_1; ++ } ++ ++ error = bus_dmamap_create(dma->dma_tag, size, 1, size, 0, ++ BUS_DMA_NOWAIT, &dma->dma_map); ++ if (error) { ++ printf("%s: bus_dmamap_create failed: %d\n", __func__, error); ++ goto fail_2; ++ } ++ ++ error = bus_dmamap_load(dma->dma_tag, dma->dma_map, dma->dma_vaddr, ++ size, NULL, BUS_DMA_NOWAIT); ++ if (error) { ++ printf("%s: bus_dmamap_load failed: %d\n", __func__, error); ++ goto fail_3; ++ } ++ ++ dma->dma_paddr = (bus_addr_t)dma->segs[0].ds_addr; ++ *dma_addr = dma->dma_paddr; ++ return dma->dma_vaddr; ++ ++fail_3: ++ bus_dmamap_destroy(dma->dma_tag, dma->dma_map); ++fail_2: ++ bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size); ++fail_1: ++ bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs); ++fail_0: ++ dma->dma_map = NULL; ++ dma->dma_vaddr = NULL; ++ dma->nsegs = 0; ++ ++ return NULL; ++} ++ ++void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr) ++{ ++ dwc_dmactx_t *dma = (dwc_dmactx_t *)dma_ctx; ++ ++ if (dma->dma_map != NULL) { ++ bus_dmamap_sync(dma->dma_tag, dma->dma_map, 0, size, ++ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); ++ bus_dmamap_unload(dma->dma_tag, dma->dma_map); ++ bus_dmamap_destroy(dma->dma_tag, dma->dma_map); ++ bus_dmamem_unmap(dma->dma_tag, dma->dma_vaddr, size); ++ bus_dmamem_free(dma->dma_tag, dma->segs, dma->nsegs); ++ dma->dma_paddr = 0; ++ dma->dma_map = NULL; ++ dma->dma_vaddr = NULL; ++ dma->nsegs = 0; ++ } ++} ++ ++void *__DWC_ALLOC(void *mem_ctx, uint32_t size) ++{ ++ return malloc(size, M_DEVBUF, M_WAITOK | M_ZERO); ++} ++ ++void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size) ++{ ++ return malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO); ++} ++ ++void __DWC_FREE(void *mem_ctx, void *addr) ++{ ++ free(addr, M_DEVBUF); ++} ++ ++ ++#ifdef DWC_CRYPTOLIB ++/* dwc_crypto.h */ ++ ++void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length) ++{ ++ get_random_bytes(buffer, length); ++} ++ ++int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out) ++{ ++ struct crypto_blkcipher *tfm; ++ struct blkcipher_desc desc; ++ struct scatterlist sgd; ++ struct scatterlist sgs; ++ ++ tfm = crypto_alloc_blkcipher("cbc(aes)", 0, CRYPTO_ALG_ASYNC); ++ if (tfm == NULL) { ++ printk("failed to load transform for aes CBC\n"); ++ return -1; ++ } ++ ++ crypto_blkcipher_setkey(tfm, key, keylen); ++ crypto_blkcipher_set_iv(tfm, iv, 16); ++ ++ sg_init_one(&sgd, out, messagelen); ++ sg_init_one(&sgs, message, messagelen); ++ ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ if (crypto_blkcipher_encrypt(&desc, &sgd, &sgs, messagelen)) { ++ crypto_free_blkcipher(tfm); ++ DWC_ERROR("AES CBC encryption failed"); ++ return -1; ++ } ++ ++ crypto_free_blkcipher(tfm); ++ return 0; ++} ++ ++int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ DWC_ERROR("Failed to load transform for sha256: %ld", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, len); ++ crypto_hash_digest(&desc, &sg, len, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++ ++int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, ++ uint8_t *key, uint32_t keylen, uint8_t *out) ++{ ++ struct crypto_hash *tfm; ++ struct hash_desc desc; ++ struct scatterlist sg; ++ ++ tfm = crypto_alloc_hash("hmac(sha256)", 0, CRYPTO_ALG_ASYNC); ++ if (IS_ERR(tfm)) { ++ DWC_ERROR("Failed to load transform for hmac(sha256): %ld", PTR_ERR(tfm)); ++ return 0; ++ } ++ desc.tfm = tfm; ++ desc.flags = 0; ++ ++ sg_init_one(&sg, message, messagelen); ++ crypto_hash_setkey(tfm, key, keylen); ++ crypto_hash_digest(&desc, &sg, messagelen, out); ++ crypto_free_hash(tfm); ++ ++ return 1; ++} ++ ++#endif /* DWC_CRYPTOLIB */ ++ ++ ++/* Byte Ordering Conversions */ ++ ++uint32_t DWC_CPU_TO_LE32(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_CPU_TO_BE32(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_LE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint32_t DWC_BE32_TO_CPU(uint32_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ ++ return (u_p[3] | (u_p[2] << 8) | (u_p[1] << 16) | (u_p[0] << 24)); ++#endif ++} ++ ++uint16_t DWC_CPU_TO_LE16(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_CPU_TO_BE16(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_LE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __LITTLE_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++uint16_t DWC_BE16_TO_CPU(uint16_t *p) ++{ ++#ifdef __BIG_ENDIAN ++ return *p; ++#else ++ uint8_t *u_p = (uint8_t *)p; ++ return (u_p[1] | (u_p[0] << 8)); ++#endif ++} ++ ++ ++/* Registers */ ++ ++uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ return bus_space_read_4(io->iot, io->ioh, ior); ++} ++ ++#if 0 ++uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ return bus_space_read_8(io->iot, io->ioh, ior); ++} ++#endif ++ ++void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_4(io->iot, io->ioh, ior, value); ++} ++ ++#if 0 ++void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_8(io->iot, io->ioh, ior, value); ++} ++#endif ++ ++void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, ++ uint32_t set_mask) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_4(io->iot, io->ioh, ior, ++ (bus_space_read_4(io->iot, io->ioh, ior) & ++ ~clear_mask) | set_mask); ++} ++ ++#if 0 ++void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, ++ uint64_t set_mask) ++{ ++ dwc_ioctx_t *io = (dwc_ioctx_t *)io_ctx; ++ bus_size_t ior = (bus_size_t)reg; ++ ++ bus_space_write_8(io->iot, io->ioh, ior, ++ (bus_space_read_8(io->iot, io->ioh, ior) & ++ ~clear_mask) | set_mask); ++} ++#endif ++ ++ ++/* Locking */ ++ ++dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void) ++{ ++ struct simplelock *sl = DWC_ALLOC(sizeof(*sl)); ++ ++ if (!sl) { ++ DWC_ERROR("Cannot allocate memory for spinlock"); ++ return NULL; ++ } ++ ++ simple_lock_init(sl); ++ return (dwc_spinlock_t *)sl; ++} ++ ++void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock) ++{ ++ struct simplelock *sl = (struct simplelock *)lock; ++ ++ DWC_FREE(sl); ++} ++ ++void DWC_SPINLOCK(dwc_spinlock_t *lock) ++{ ++ simple_lock((struct simplelock *)lock); ++} ++ ++void DWC_SPINUNLOCK(dwc_spinlock_t *lock) ++{ ++ simple_unlock((struct simplelock *)lock); ++} ++ ++void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags) ++{ ++ simple_lock((struct simplelock *)lock); ++ *flags = splbio(); ++} ++ ++void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags) ++{ ++ splx(flags); ++ simple_unlock((struct simplelock *)lock); ++} ++ ++dwc_mutex_t *DWC_MUTEX_ALLOC(void) ++{ ++ dwc_mutex_t *mutex = DWC_ALLOC(sizeof(struct lock)); ++ ++ if (!mutex) { ++ DWC_ERROR("Cannot allocate memory for mutex"); ++ return NULL; ++ } ++ ++ lockinit((struct lock *)mutex, 0, "dw3mtx", 0, 0); ++ return mutex; ++} ++ ++#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++#else ++void DWC_MUTEX_FREE(dwc_mutex_t *mutex) ++{ ++ DWC_FREE(mutex); ++} ++#endif ++ ++void DWC_MUTEX_LOCK(dwc_mutex_t *mutex) ++{ ++ lockmgr((struct lock *)mutex, LK_EXCLUSIVE, NULL); ++} ++ ++int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex) ++{ ++ int status; ++ ++ status = lockmgr((struct lock *)mutex, LK_EXCLUSIVE | LK_NOWAIT, NULL); ++ return status == 0; ++} ++ ++void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex) ++{ ++ lockmgr((struct lock *)mutex, LK_RELEASE, NULL); ++} ++ + +/* Timing */ + +void DWC_UDELAY(uint32_t usecs) +{ -+ udelay(usecs); ++ DELAY(usecs); +} -+EXPORT_SYMBOL(DWC_UDELAY); + +void DWC_MDELAY(uint32_t msecs) +{ -+ mdelay(msecs); ++ do { ++ DELAY(1000); ++ } while (--msecs); +} -+EXPORT_SYMBOL(DWC_MDELAY); + +void DWC_MSLEEP(uint32_t msecs) +{ -+ msleep(msecs); ++ struct timeval tv; ++ ++ tv.tv_sec = msecs / 1000; ++ tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000; ++ tsleep(&tv, 0, "dw3slp", tvtohz(&tv)); +} -+EXPORT_SYMBOL(DWC_MSLEEP); + +uint32_t DWC_TIME(void) +{ -+ return jiffies_to_msecs(jiffies); ++ struct timeval tv; ++ ++ microuptime(&tv); // or getmicrouptime? (less precise, but faster) ++ return tv.tv_sec * 1000 + tv.tv_usec / 1000; ++} ++ ++ ++/* Timers */ ++ ++struct dwc_timer { ++ struct callout t; ++ char *name; ++ dwc_spinlock_t *lock; ++ dwc_timer_callback_t cb; ++ void *data; ++}; ++ ++dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data) ++{ ++ dwc_timer_t *t = DWC_ALLOC(sizeof(*t)); ++ ++ if (!t) { ++ DWC_ERROR("Cannot allocate memory for timer"); ++ return NULL; ++ } ++ ++ callout_init(&t->t); ++ ++ t->name = DWC_STRDUP(name); ++ if (!t->name) { ++ DWC_ERROR("Cannot allocate memory for timer->name"); ++ goto no_name; ++ } ++ ++ t->lock = DWC_SPINLOCK_ALLOC(); ++ if (!t->lock) { ++ DWC_ERROR("Cannot allocate memory for timer->lock"); ++ goto no_lock; ++ } ++ ++ t->cb = cb; ++ t->data = data; ++ ++ return t; ++ ++ no_lock: ++ DWC_FREE(t->name); ++ no_name: ++ DWC_FREE(t); ++ ++ return NULL; ++} ++ ++void DWC_TIMER_FREE(dwc_timer_t *timer) ++{ ++ callout_stop(&timer->t); ++ DWC_SPINLOCK_FREE(timer->lock); ++ DWC_FREE(timer->name); ++ DWC_FREE(timer); ++} ++ ++void DWC_TIMER_SCHEDULE(dwc_timer_t *timer, uint32_t time) ++{ ++ struct timeval tv; ++ ++ tv.tv_sec = time / 1000; ++ tv.tv_usec = (time - tv.tv_sec * 1000) * 1000; ++ callout_reset(&timer->t, tvtohz(&tv), timer->cb, timer->data); ++} ++ ++void DWC_TIMER_CANCEL(dwc_timer_t *timer) ++{ ++ callout_stop(&timer->t); +} -+EXPORT_SYMBOL(DWC_TIME); + + +/* Wait Queues */ + -+struct dwc_waitq -+{ -+ wait_queue_head_t queue; ++struct dwc_waitq { ++ struct simplelock lock; + int abort; +}; + +dwc_waitq_t *DWC_WAITQ_ALLOC(void) +{ + dwc_waitq_t *wq = DWC_ALLOC(sizeof(*wq)); -+ init_waitqueue_head(&wq->queue); ++ ++ if (!wq) { ++ DWC_ERROR("Cannot allocate memory for waitqueue"); ++ return NULL; ++ } ++ ++ simple_lock_init(&wq->lock); + wq->abort = 0; ++ + return wq; +} -+EXPORT_SYMBOL(DWC_WAITQ_ALLOC); + +void DWC_WAITQ_FREE(dwc_waitq_t *wq) +{ + DWC_FREE(wq); +} -+EXPORT_SYMBOL(DWC_WAITQ_FREE); + -+static int32_t check_result(dwc_waitq_t *wq, int result) -+{ int32_t msecs; -+ if (result > 0) { -+ msecs = jiffies_to_msecs(result); -+ if (!msecs) { -+ return 1; ++int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data) ++{ ++ int ipl; ++ int result = 0; ++ ++ simple_lock(&wq->lock); ++ ipl = splbio(); ++ ++ /* Skip the sleep if already aborted or triggered */ ++ if (!wq->abort && !cond(data)) { ++ splx(ipl); ++ result = ltsleep(wq, PCATCH, "dw3wat", 0, &wq->lock); // infinite timeout ++ ipl = splbio(); ++ } ++ ++ if (result == 0) { // awoken ++ if (wq->abort) { ++ wq->abort = 0; ++ result = -DWC_E_ABORT; ++ } else { ++ result = 0; ++ } ++ ++ splx(ipl); ++ simple_unlock(&wq->lock); ++ } else { ++ wq->abort = 0; ++ splx(ipl); ++ simple_unlock(&wq->lock); ++ ++ if (result == ERESTART) { // signaled - restart ++ result = -DWC_E_RESTART; ++ } else { // signaled - must be EINTR ++ result = -DWC_E_ABORT; + } -+ return msecs; + } + -+ if (result == 0) { ++ return result; ++} ++ ++int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, ++ void *data, int32_t msecs) ++{ ++ struct timeval tv, tv1, tv2; ++ int ipl; ++ int result = 0; ++ ++ tv.tv_sec = msecs / 1000; ++ tv.tv_usec = (msecs - tv.tv_sec * 1000) * 1000; ++ ++ simple_lock(&wq->lock); ++ ipl = splbio(); ++ ++ /* Skip the sleep if already aborted or triggered */ ++ if (!wq->abort && !cond(data)) { ++ splx(ipl); ++ getmicrouptime(&tv1); ++ result = ltsleep(wq, PCATCH, "dw3wto", tvtohz(&tv), &wq->lock); ++ getmicrouptime(&tv2); ++ ipl = splbio(); ++ } ++ ++ if (result == 0) { // awoken ++ if (wq->abort) { ++ wq->abort = 0; ++ splx(ipl); ++ simple_unlock(&wq->lock); ++ result = -DWC_E_ABORT; ++ } else { ++ splx(ipl); ++ simple_unlock(&wq->lock); ++ ++ tv2.tv_usec -= tv1.tv_usec; ++ if (tv2.tv_usec < 0) { ++ tv2.tv_usec += 1000000; ++ tv2.tv_sec--; ++ } ++ ++ tv2.tv_sec -= tv1.tv_sec; ++ result = tv2.tv_sec * 1000 + tv2.tv_usec / 1000; ++ result = msecs - result; ++ if (result <= 0) ++ result = 1; ++ } ++ } else { ++ wq->abort = 0; ++ splx(ipl); ++ simple_unlock(&wq->lock); ++ ++ if (result == ERESTART) { // signaled - restart ++ result = -DWC_E_RESTART; ++ ++ } else if (result == EINTR) { // signaled - interrupt ++ result = -DWC_E_ABORT; ++ ++ } else { // timed out ++ result = -DWC_E_TIMEOUT; ++ } ++ } ++ ++ return result; ++} ++ ++void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq) ++{ ++ wakeup(wq); ++} ++ ++void DWC_WAITQ_ABORT(dwc_waitq_t *wq) ++{ ++ int ipl; ++ ++ simple_lock(&wq->lock); ++ ipl = splbio(); ++ wq->abort = 1; ++ wakeup(wq); ++ splx(ipl); ++ simple_unlock(&wq->lock); ++} ++ ++ ++/* Threading */ ++ ++struct dwc_thread { ++ struct proc *proc; ++ int abort; ++}; ++ ++dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data) ++{ ++ int retval; ++ dwc_thread_t *thread = DWC_ALLOC(sizeof(*thread)); ++ ++ if (!thread) { ++ return NULL; ++ } ++ ++ thread->abort = 0; ++ retval = kthread_create1((void (*)(void *))func, data, &thread->proc, ++ "%s", name); ++ if (retval) { ++ DWC_FREE(thread); ++ return NULL; ++ } ++ ++ return thread; ++} ++ ++int DWC_THREAD_STOP(dwc_thread_t *thread) ++{ ++ int retval; ++ ++ thread->abort = 1; ++ retval = tsleep(&thread->abort, 0, "dw3stp", 60 * hz); ++ ++ if (retval == 0) { ++ /* DWC_THREAD_EXIT() will free the thread struct */ ++ return 0; ++ } ++ ++ /* NOTE: We leak the thread struct if thread doesn't die */ ++ ++ if (retval == EWOULDBLOCK) { + return -DWC_E_TIMEOUT; + } + -+ if ((result == -ERESTARTSYS) || (wq->abort == 1)) { -+ return -DWC_E_ABORT; -+ } -+ + return -DWC_E_UNKNOWN; +} + -+int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t condition, void *data) ++dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread) +{ -+ int result = wait_event_interruptible(wq->queue, -+ condition(data) || wq->abort); -+ return check_result(wq, result); ++ return thread->abort; +} -+EXPORT_SYMBOL(DWC_WAITQ_WAIT); + -+int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t condition, -+ void *data, int32_t msecs) ++void DWC_THREAD_EXIT(dwc_thread_t *thread) +{ -+ int result = wait_event_interruptible_timeout(wq->queue, -+ condition(data) || wq->abort, -+ msecs_to_jiffies(msecs)); -+ return check_result(wq, result); ++ wakeup(&thread->abort); ++ DWC_FREE(thread); ++ kthread_exit(0); +} -+EXPORT_SYMBOL(DWC_WAITQ_WAIT_TIMEOUT); + -+void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq) -+{ -+ wake_up_interruptible(&wq->queue); -+} -+EXPORT_SYMBOL(DWC_WAITQ_TRIGGER); ++/* tasklets ++ - Runs in interrupt context (cannot sleep) ++ - Each tasklet runs on a single CPU ++ - Different tasklets can be running simultaneously on different CPUs ++ [ On NetBSD there is no corresponding mechanism, drivers don't have bottom- ++ halves. So we just call the callback directly from DWC_TASK_SCHEDULE() ] ++ */ ++struct dwc_tasklet { ++ dwc_tasklet_callback_t cb; ++ void *data; ++}; + -+void DWC_WAITQ_ABORT(dwc_waitq_t *wq) ++static void tasklet_callback(void *data) +{ -+ wq->abort = 1; -+ DWC_WAITQ_TRIGGER(wq); ++ dwc_tasklet_t *task = (dwc_tasklet_t *)data; ++ ++ task->cb(task->data); +} -+EXPORT_SYMBOL(DWC_WAITQ_ABORT); -diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h ---- linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h 2012-07-15 20:29:18.990081853 +0200 -@@ -0,0 +1,616 @@ ++ ++dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data) ++{ ++ dwc_tasklet_t *task = DWC_ALLOC(sizeof(*task)); ++ ++ if (task) { ++ task->cb = cb; ++ task->data = data; ++ } else { ++ DWC_ERROR("Cannot allocate memory for tasklet"); ++ } ++ ++ return task; ++} ++ ++void DWC_TASK_FREE(dwc_tasklet_t *task) ++{ ++ DWC_FREE(task); ++} ++ ++void DWC_TASK_SCHEDULE(dwc_tasklet_t *task) ++{ ++ tasklet_callback(task); ++} ++ ++ ++/* workqueues ++ - Runs in process context (can sleep) ++ */ ++typedef struct work_container { ++ dwc_work_callback_t cb; ++ void *data; ++ dwc_workq_t *wq; ++ char *name; ++ int hz; ++ struct work task; ++} work_container_t; ++ ++struct dwc_workq { ++ struct workqueue *taskq; ++ dwc_spinlock_t *lock; ++ dwc_waitq_t *waitq; ++ int pending; ++ struct work_container *container; ++}; ++ ++static void do_work(struct work *task, void *data) ++{ ++ dwc_workq_t *wq = (dwc_workq_t *)data; ++ work_container_t *container = wq->container; ++ dwc_irqflags_t flags; ++ ++ if (container->hz) { ++ tsleep(container, 0, "dw3wrk", container->hz); ++ } ++ ++ container->cb(container->data); ++ DWC_DEBUG("Work done: %s, container=%p", container->name, container); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ if (container->name) ++ DWC_FREE(container->name); ++ DWC_FREE(container); ++ wq->pending--; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++} ++ ++static int work_done(void *data) ++{ ++ dwc_workq_t *workq = (dwc_workq_t *)data; ++ ++ return workq->pending == 0; ++} ++ ++int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout) ++{ ++ return DWC_WAITQ_WAIT_TIMEOUT(workq->waitq, work_done, workq, timeout); ++} ++ ++dwc_workq_t *DWC_WORKQ_ALLOC(char *name) ++{ ++ int result; ++ dwc_workq_t *wq = DWC_ALLOC(sizeof(*wq)); ++ ++ if (!wq) { ++ DWC_ERROR("Cannot allocate memory for workqueue"); ++ return NULL; ++ } ++ ++ result = workqueue_create(&wq->taskq, name, do_work, wq, 0 /*PWAIT*/, ++ IPL_BIO, 0); ++ if (result) { ++ DWC_ERROR("Cannot create workqueue"); ++ goto no_taskq; ++ } ++ ++ wq->pending = 0; ++ ++ wq->lock = DWC_SPINLOCK_ALLOC(); ++ if (!wq->lock) { ++ DWC_ERROR("Cannot allocate memory for spinlock"); ++ goto no_lock; ++ } ++ ++ wq->waitq = DWC_WAITQ_ALLOC(); ++ if (!wq->waitq) { ++ DWC_ERROR("Cannot allocate memory for waitqueue"); ++ goto no_waitq; ++ } ++ ++ return wq; ++ ++ no_waitq: ++ DWC_SPINLOCK_FREE(wq->lock); ++ no_lock: ++ workqueue_destroy(wq->taskq); ++ no_taskq: ++ DWC_FREE(wq); ++ ++ return NULL; ++} ++ ++void DWC_WORKQ_FREE(dwc_workq_t *wq) ++{ ++#ifdef DEBUG ++ dwc_irqflags_t flags; ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ ++ if (wq->pending != 0) { ++ struct work_container *container = wq->container; ++ ++ DWC_ERROR("Destroying work queue with pending work"); ++ ++ if (container && container->name) { ++ DWC_ERROR("Work %s still pending", container->name); ++ } ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++#endif ++ DWC_WAITQ_FREE(wq->waitq); ++ DWC_SPINLOCK_FREE(wq->lock); ++ workqueue_destroy(wq->taskq); ++ DWC_FREE(wq); ++} ++ ++void DWC_WORKQ_SCHEDULE(dwc_workq_t *wq, dwc_work_callback_t cb, void *data, ++ char *format, ...) ++{ ++ dwc_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++ ++ container = DWC_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ DWC_ERROR("Cannot allocate memory for container"); ++ return; ++ } ++ ++ container->name = DWC_STRDUP(name); ++ if (!container->name) { ++ DWC_ERROR("Cannot allocate memory for container->name"); ++ DWC_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ container->hz = 0; ++ wq->container = container; ++ ++ DWC_DEBUG("Queueing work: %s, container=%p", container->name, container); ++ workqueue_enqueue(wq->taskq, &container->task); ++} ++ ++void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *wq, dwc_work_callback_t cb, ++ void *data, uint32_t time, char *format, ...) ++{ ++ dwc_irqflags_t flags; ++ work_container_t *container; ++ static char name[128]; ++ struct timeval tv; ++ va_list args; ++ ++ va_start(args, format); ++ DWC_VSNPRINTF(name, 128, format, args); ++ va_end(args); ++ ++ DWC_SPINLOCK_IRQSAVE(wq->lock, &flags); ++ wq->pending++; ++ DWC_SPINUNLOCK_IRQRESTORE(wq->lock, flags); ++ DWC_WAITQ_TRIGGER(wq->waitq); ++ ++ container = DWC_ALLOC_ATOMIC(sizeof(*container)); ++ if (!container) { ++ DWC_ERROR("Cannot allocate memory for container"); ++ return; ++ } ++ ++ container->name = DWC_STRDUP(name); ++ if (!container->name) { ++ DWC_ERROR("Cannot allocate memory for container->name"); ++ DWC_FREE(container); ++ return; ++ } ++ ++ container->cb = cb; ++ container->data = data; ++ container->wq = wq; ++ tv.tv_sec = time / 1000; ++ tv.tv_usec = (time - tv.tv_sec * 1000) * 1000; ++ container->hz = tvtohz(&tv); ++ wq->container = container; ++ ++ DWC_DEBUG("Queueing work: %s, container=%p", container->name, container); ++ workqueue_enqueue(wq->taskq, &container->task); ++} ++ ++int DWC_WORKQ_PENDING(dwc_workq_t *wq) ++{ ++ return wq->pending; ++} +diff --git a/drivers/usb/host/dwc_common_port/dwc_crypto.c b/drivers/usb/host/dwc_common_port/dwc_crypto.c +new file mode 100644 +index 0000000..3b03532 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_crypto.c +@@ -0,0 +1,308 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.c $ ++ * $Revision: #5 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY ++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE ++ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================= */ ++ ++/** @file ++ * This file contains the WUSB cryptographic routines. ++ */ ++ ++#ifdef DWC_CRYPTOLIB ++ ++#include "dwc_crypto.h" ++#include "usb.h" ++ ++#ifdef DEBUG ++static inline void dump_bytes(char *name, uint8_t *bytes, int len) ++{ ++ int i; ++ DWC_PRINTF("%s: ", name); ++ for (i=0; idst == src, then the bytes will be encrypted ++ * in-place. ++ * ++ * @return 0 on success, negative error code on error. ++ */ ++int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst) ++{ ++ u8 block_t[16]; ++ DWC_MEMSET(block_t, 0, 16); ++ ++ return DWC_AES_CBC(src, 16, key, 16, block_t, dst); ++} ++ ++/** ++ * The CCM-MAC-FUNCTION described in section 6.5 of the WUSB spec. ++ * This function takes a data string and returns the encrypted CBC ++ * Counter-mode MIC. ++ * ++ * @param key The 128-bit symmetric key. ++ * @param nonce The CCM nonce. ++ * @param label The unique 14-byte ASCII text label. ++ * @param bytes The byte array to be encrypted. ++ * @param len Length of the byte array. ++ * @param result Byte array to receive the 8-byte encrypted MIC. ++ */ ++void dwc_wusb_cmf(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ u8 block_m[16]; ++ u8 block_x[16]; ++ u8 block_t[8]; ++ int idx, blkNum; ++ u16 la = (u16)(len + 14); ++ ++ /* Set the AES-128 key */ ++ //dwc_aes_setkey(tfm, key, 16); ++ ++ /* Fill block B0 from flags = 0x59, N, and l(m) = 0 */ ++ block_m[0] = 0x59; ++ for (idx = 0; idx < 13; idx++) ++ block_m[idx + 1] = nonce[idx]; ++ block_m[14] = 0; ++ block_m[15] = 0; ++ ++ /* Produce the CBC IV */ ++ dwc_wusb_aes_encrypt(block_m, key, block_x); ++ show_block(block_m, "CBC IV in: ", "\n", 0); ++ show_block(block_x, "CBC IV out:", "\n", 0); ++ ++ /* Fill block B1 from l(a) = Blen + 14, and A */ ++ block_x[0] ^= (u8)(la >> 8); ++ block_x[1] ^= (u8)la; ++ for (idx = 0; idx < 14; idx++) ++ block_x[idx + 2] ^= label[idx]; ++ show_block(block_x, "After xor: ", "b1\n", 16); ++ ++ dwc_wusb_aes_encrypt(block_x, key, block_x); ++ show_block(block_x, "After AES: ", "b1\n", 16); ++ ++ idx = 0; ++ blkNum = 0; ++ ++ /* Fill remaining blocks with B */ ++ while (len-- > 0) { ++ block_x[idx] ^= *bytes++; ++ if (++idx >= 16) { ++ idx = 0; ++ show_block(block_x, "After xor: ", "\n", blkNum); ++ dwc_wusb_aes_encrypt(block_x, key, block_x); ++ show_block(block_x, "After AES: ", "\n", blkNum); ++ blkNum++; ++ } ++ } ++ ++ /* Handle partial last block */ ++ if (idx > 0) { ++ show_block(block_x, "After xor: ", "\n", blkNum); ++ dwc_wusb_aes_encrypt(block_x, key, block_x); ++ show_block(block_x, "After AES: ", "\n", blkNum); ++ } ++ ++ /* Save the MIC tag */ ++ DWC_MEMCPY(block_t, block_x, 8); ++ show_block(block_t, "MIC tag : ", NULL, 8); ++ ++ /* Fill block A0 from flags = 0x01, N, and counter = 0 */ ++ block_m[0] = 0x01; ++ block_m[14] = 0; ++ block_m[15] = 0; ++ ++ /* Encrypt the counter */ ++ dwc_wusb_aes_encrypt(block_m, key, block_x); ++ show_block(block_x, "CTR[MIC] : ", NULL, 8); ++ ++ /* XOR with MIC tag */ ++ for (idx = 0; idx < 8; idx++) { ++ block_t[idx] ^= block_x[idx]; ++ } ++ ++ /* Return result to caller */ ++ DWC_MEMCPY(result, block_t, 8); ++ show_block(result, "CCM-MIC : ", NULL, 8); ++ ++} ++ ++/** ++ * The PRF function described in section 6.5 of the WUSB spec. This function ++ * concatenates MIC values returned from dwc_cmf() to create a value of ++ * the requested length. ++ * ++ * @param prf_len Length of the PRF function in bits (64, 128, or 256). ++ * @param key, nonce, label, bytes, len Same as for dwc_cmf(). ++ * @param result Byte array to receive the result. ++ */ ++void dwc_wusb_prf(int prf_len, u8 *key, ++ u8 *nonce, char *label, u8 *bytes, int len, u8 *result) ++{ ++ int i; ++ ++ nonce[0] = 0; ++ for (i = 0; i < prf_len >> 6; i++, nonce[0]++) { ++ dwc_wusb_cmf(key, nonce, label, bytes, len, result); ++ result += 8; ++ } ++} ++ ++/** ++ * Fills in CCM Nonce per the WUSB spec. ++ * ++ * @param[in] haddr Host address. ++ * @param[in] daddr Device address. ++ * @param[in] tkid Session Key(PTK) identifier. ++ * @param[out] nonce Pointer to where the CCM Nonce output is to be written. ++ */ ++void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid, ++ uint8_t *nonce) ++{ ++ ++ DWC_DEBUG("%s %x %x\n", __func__, daddr, haddr); ++ ++ DWC_MEMSET(&nonce[0], 0, 16); ++ ++ DWC_MEMCPY(&nonce[6], tkid, 3); ++ nonce[9] = daddr & 0xFF; ++ nonce[10] = (daddr >> 8) & 0xFF; ++ nonce[11] = haddr & 0xFF; ++ nonce[12] = (haddr >> 8) & 0xFF; ++ ++ dump_bytes("CCM nonce", nonce, 16); ++} ++ ++/** ++ * Generates a 16-byte cryptographic-grade random number for the Host/Device ++ * Nonce. ++ */ ++void dwc_wusb_gen_nonce(uint16_t addr, uint8_t *nonce) ++{ ++ uint8_t inonce[16]; ++ uint32_t temp[4]; ++ ++ /* Fill in the Nonce */ ++ DWC_MEMSET(&inonce[0], 0, sizeof(inonce)); ++ inonce[9] = addr & 0xFF; ++ inonce[10] = (addr >> 8) & 0xFF; ++ inonce[11] = inonce[9]; ++ inonce[12] = inonce[10]; ++ ++ /* Collect "randomness samples" */ ++ DWC_RANDOM_BYTES((uint8_t *)temp, 16); ++ ++ dwc_wusb_prf_128((uint8_t *)temp, nonce, ++ "Random Numbers", (uint8_t *)temp, sizeof(temp), ++ nonce); ++} ++ ++/** ++ * Generates the Session Key (PTK) and Key Confirmation Key (KCK) per the ++ * WUSB spec. ++ * ++ * @param[in] ccm_nonce Pointer to CCM Nonce. ++ * @param[in] mk Master Key to derive the session from ++ * @param[in] hnonce Pointer to Host Nonce. ++ * @param[in] dnonce Pointer to Device Nonce. ++ * @param[out] kck Pointer to where the KCK output is to be written. ++ * @param[out] ptk Pointer to where the PTK output is to be written. ++ */ ++void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, uint8_t *hnonce, ++ uint8_t *dnonce, uint8_t *kck, uint8_t *ptk) ++{ ++ uint8_t idata[32]; ++ uint8_t odata[32]; ++ ++ dump_bytes("ck", mk, 16); ++ dump_bytes("hnonce", hnonce, 16); ++ dump_bytes("dnonce", dnonce, 16); ++ ++ /* The data is the HNonce and DNonce concatenated */ ++ DWC_MEMCPY(&idata[0], hnonce, 16); ++ DWC_MEMCPY(&idata[16], dnonce, 16); ++ ++ dwc_wusb_prf_256(mk, ccm_nonce, "Pair-wise keys", idata, 32, odata); ++ ++ /* Low 16 bytes of the result is the KCK, high 16 is the PTK */ ++ DWC_MEMCPY(kck, &odata[0], 16); ++ DWC_MEMCPY(ptk, &odata[16], 16); ++ ++ dump_bytes("kck", kck, 16); ++ dump_bytes("ptk", ptk, 16); ++} ++ ++/** ++ * Generates the Message Integrity Code over the Handshake data per the ++ * WUSB spec. ++ * ++ * @param ccm_nonce Pointer to CCM Nonce. ++ * @param kck Pointer to Key Confirmation Key. ++ * @param data Pointer to Handshake data to be checked. ++ * @param mic Pointer to where the MIC output is to be written. ++ */ ++void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t *kck, ++ uint8_t *data, uint8_t *mic) ++{ ++ ++ dwc_wusb_prf_64(kck, ccm_nonce, "out-of-bandMIC", ++ data, WUSB_HANDSHAKE_LEN_FOR_MIC, mic); ++} ++ ++#endif /* DWC_CRYPTOLIB */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_crypto.h b/drivers/usb/host/dwc_common_port/dwc_crypto.h +new file mode 100644 +index 0000000..26fcddc +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_crypto.h +@@ -0,0 +1,111 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.h $ ++ * $Revision: #3 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY ++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE ++ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================= */ ++ ++#ifndef _DWC_CRYPTO_H_ ++#define _DWC_CRYPTO_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** @file ++ * ++ * This file contains declarations for the WUSB Cryptographic routines as ++ * defined in the WUSB spec. They are only to be used internally by the DWC UWB ++ * modules. ++ */ ++ ++#include "dwc_os.h" ++ ++int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst); ++ ++void dwc_wusb_cmf(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result); ++void dwc_wusb_prf(int prf_len, u8 *key, ++ u8 *nonce, char *label, u8 *bytes, int len, u8 *result); ++ ++/** ++ * The PRF-64 function described in section 6.5 of the WUSB spec. ++ * ++ * @param key, nonce, label, bytes, len, result Same as for dwc_prf(). ++ */ ++static inline void dwc_wusb_prf_64(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ dwc_wusb_prf(64, key, nonce, label, bytes, len, result); ++} ++ ++/** ++ * The PRF-128 function described in section 6.5 of the WUSB spec. ++ * ++ * @param key, nonce, label, bytes, len, result Same as for dwc_prf(). ++ */ ++static inline void dwc_wusb_prf_128(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ dwc_wusb_prf(128, key, nonce, label, bytes, len, result); ++} ++ ++/** ++ * The PRF-256 function described in section 6.5 of the WUSB spec. ++ * ++ * @param key, nonce, label, bytes, len, result Same as for dwc_prf(). ++ */ ++static inline void dwc_wusb_prf_256(u8 *key, u8 *nonce, ++ char *label, u8 *bytes, int len, u8 *result) ++{ ++ dwc_wusb_prf(256, key, nonce, label, bytes, len, result); ++} ++ ++ ++void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid, ++ uint8_t *nonce); ++void dwc_wusb_gen_nonce(uint16_t addr, ++ uint8_t *nonce); ++ ++void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, ++ uint8_t *hnonce, uint8_t *dnonce, ++ uint8_t *kck, uint8_t *ptk); ++ ++ ++void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t ++ *kck, uint8_t *data, uint8_t *mic); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_CRYPTO_H_ */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_dh.c b/drivers/usb/host/dwc_common_port/dwc_dh.c +new file mode 100644 +index 0000000..997f753 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_dh.c +@@ -0,0 +1,291 @@ ++/* ========================================================================= ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.c $ ++ * $Revision: #3 $ ++ * $Date: 2010/09/28 $ ++ * $Change: 1596182 $ ++ * ++ * Synopsys Portability Library Software and documentation ++ * (hereinafter, "Software") is an Unsupported proprietary work of ++ * Synopsys, Inc. unless otherwise expressly agreed to in writing ++ * between Synopsys and you. ++ * ++ * The Software IS NOT an item of Licensed Software or Licensed Product ++ * under any End User Software License Agreement or Agreement for ++ * Licensed Product with Synopsys or any supplement thereto. You are ++ * permitted to use and redistribute this Software in source and binary ++ * forms, with or without modification, provided that redistributions ++ * of source code must retain this notice. You may not view, use, ++ * disclose, copy or distribute this file or any information contained ++ * herein except pursuant to this license grant from Synopsys. If you ++ * do not agree with this notice, including the disclaimer below, then ++ * you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" ++ * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL ++ * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ++ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ++ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ++ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY ++ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE ++ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================= */ ++#ifdef DWC_CRYPTOLIB ++ ++#ifndef CONFIG_MACH_IPMATE ++ ++#include "dwc_dh.h" ++#include "dwc_modpow.h" ++ ++#ifdef DEBUG ++/* This function prints out a buffer in the format described in the Association ++ * Model specification. */ ++static void dh_dump(char *str, void *_num, int len) ++{ ++ uint8_t *num = _num; ++ int i; ++ DWC_PRINTF("%s\n", str); ++ for (i = 0; i < len; i ++) { ++ DWC_PRINTF("%02x", num[i]); ++ if (((i + 1) % 2) == 0) DWC_PRINTF(" "); ++ if (((i + 1) % 26) == 0) DWC_PRINTF("\n"); ++ } ++ ++ DWC_PRINTF("\n"); ++} ++#else ++#define dh_dump(_x...) do {; } while(0) ++#endif ++ ++/* Constant g value */ ++static __u32 dh_g[] = { ++ 0x02000000, ++}; ++ ++/* Constant p value */ ++static __u32 dh_p[] = { ++ 0xFFFFFFFF, 0xFFFFFFFF, 0xA2DA0FC9, 0x34C26821, 0x8B62C6C4, 0xD11CDC80, 0x084E0229, 0x74CC678A, ++ 0xA6BE0B02, 0x229B133B, 0x79084A51, 0xDD04348E, 0xB31995EF, 0x1B433ACD, 0x6D0A2B30, 0x37145FF2, ++ 0x6D35E14F, 0x45C2516D, 0x76B585E4, 0xC67E5E62, 0xE9424CF4, 0x6BED37A6, 0xB65CFF0B, 0xEDB706F4, ++ 0xFB6B38EE, 0xA59F895A, 0x11249FAE, 0xE61F4B7C, 0x51662849, 0x3D5BE4EC, 0xB87C00C2, 0x05BF63A1, ++ 0x3648DA98, 0x9AD3551C, 0xA83F1669, 0x5FCF24FD, 0x235D6583, 0x96ADA3DC, 0x56F3621C, 0xBB528520, ++ 0x0729D59E, 0x6D969670, 0x4E350C67, 0x0498BC4A, 0x086C74F1, 0x7C2118CA, 0x465E9032, 0x3BCE362E, ++ 0x2C779EE3, 0x03860E18, 0xA283279B, 0x8FA207EC, 0xF05DC5B5, 0xC9524C6F, 0xF6CB2BDE, 0x18175895, ++ 0x7C499539, 0xE56A95EA, 0x1826D215, 0x1005FA98, 0x5A8E7215, 0x2DC4AA8A, 0x0D1733AD, 0x337A5004, ++ 0xAB2155A8, 0x64BA1CDF, 0x0485FBEC, 0x0AEFDB58, 0x5771EA8A, 0x7D0C065D, 0x850F97B3, 0xC7E4E1A6, ++ 0x8CAEF5AB, 0xD73309DB, 0xE0948C1E, 0x9D61254A, 0x26D2E3CE, 0x6BEED21A, 0x06FA2FF1, 0x64088AD9, ++ 0x730276D8, 0x646AC83E, 0x182B1F52, 0x0C207B17, 0x5717E1BB, 0x6C5D617A, 0xC0880977, 0xE246D9BA, ++ 0xA04FE208, 0x31ABE574, 0xFC5BDB43, 0x8E10FDE0, 0x20D1824B, 0xCAD23AA9, 0xFFFFFFFF, 0xFFFFFFFF, ++}; ++ ++static void dh_swap_bytes(void *_in, void *_out, uint32_t len) ++{ ++ uint8_t *in = _in; ++ uint8_t *out = _out; ++ int i; ++ for (i=0; inext = (link); \ + (link)->prev = (link); \ -+} while(0) ++} while (0) + +#define DWC_LIST_FIRST(link) ((link)->next) +#define DWC_LIST_LAST(link) ((link)->prev) @@ -32400,42 +38689,95 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo +#define DWC_LIST_PREV(link) ((link)->prev) +#define DWC_LIST_EMPTY(link) \ + (DWC_LIST_FIRST(link) == DWC_LIST_END(link)) -+#define DWC_LIST_ENTRY(link, type, field) (type *) \ -+ ((uint8_t *)(link) - (size_t)(&((type *)0)->field)) ++#define DWC_LIST_ENTRY(link, type, field) \ ++ (type *)((uint8_t *)(link) - (size_t)(&((type *)0)->field)) + ++#if 0 +#define DWC_LIST_INSERT_HEAD(list, link) do { \ + (link)->next = (list)->next; \ + (link)->prev = (list); \ -+ (list)->next->prev = link; \ -+ (list)->next = link; \ -+} while(0) ++ (list)->next->prev = (link); \ ++ (list)->next = (link); \ ++} while (0) + +#define DWC_LIST_INSERT_TAIL(list, link) do { \ -+ (link)->next = list; \ ++ (link)->next = (list); \ + (link)->prev = (list)->prev; \ -+ (list)->prev->next = link; \ -+ (list)->prev = link; \ -+} while(0) ++ (list)->prev->next = (link); \ ++ (list)->prev = (link); \ ++} while (0) ++#else ++#define DWC_LIST_INSERT_HEAD(list, link) do { \ ++ dwc_list_link_t *__next__ = (list)->next; \ ++ __next__->prev = (link); \ ++ (link)->next = __next__; \ ++ (link)->prev = (list); \ ++ (list)->next = (link); \ ++} while (0) ++ ++#define DWC_LIST_INSERT_TAIL(list, link) do { \ ++ dwc_list_link_t *__prev__ = (list)->prev; \ ++ (list)->prev = (link); \ ++ (link)->next = (list); \ ++ (link)->prev = __prev__; \ ++ __prev__->next = (link); \ ++} while (0) ++#endif ++ ++#if 0 ++static inline void __list_add(struct list_head *new, ++ struct list_head *prev, ++ struct list_head *next) ++{ ++ next->prev = new; ++ new->next = next; ++ new->prev = prev; ++ prev->next = new; ++} ++ ++static inline void list_add(struct list_head *new, struct list_head *head) ++{ ++ __list_add(new, head, head->next); ++} ++ ++static inline void list_add_tail(struct list_head *new, struct list_head *head) ++{ ++ __list_add(new, head->prev, head); ++} ++ ++static inline void __list_del(struct list_head * prev, struct list_head * next) ++{ ++ next->prev = prev; ++ prev->next = next; ++} ++ ++static inline void list_del(struct list_head *entry) ++{ ++ __list_del(entry->prev, entry->next); ++ entry->next = LIST_POISON1; ++ entry->prev = LIST_POISON2; ++} ++#endif + +#define DWC_LIST_REMOVE(link) do { \ + (link)->next->prev = (link)->prev; \ + (link)->prev->next = (link)->next; \ -+} while(0) ++} while (0) + +#define DWC_LIST_REMOVE_INIT(link) do { \ + DWC_LIST_REMOVE(link); \ + DWC_LIST_INIT(link); \ -+} while(0) ++} while (0) + +#define DWC_LIST_MOVE_HEAD(list, link) do { \ + DWC_LIST_REMOVE(link); \ + DWC_LIST_INSERT_HEAD(list, link); \ -+} while(0) ++} while (0) + +#define DWC_LIST_MOVE_TAIL(list, link) do { \ + DWC_LIST_REMOVE(link); \ + DWC_LIST_INSERT_TAIL(list, link); \ -+} while(0) ++} while (0) + +#define DWC_LIST_FOREACH(var, list) \ + for((var) = DWC_LIST_FIRST(list); \ @@ -32443,9 +38785,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo + (var) = DWC_LIST_NEXT(var)) + +#define DWC_LIST_FOREACH_SAFE(var, var2, list) \ -+ for((var) = DWC_LIST_FIRST(list), var2 = DWC_LIST_NEXT(var); \ ++ for((var) = DWC_LIST_FIRST(list), (var2) = DWC_LIST_NEXT(var); \ + (var) != DWC_LIST_END(list); \ -+ (var) = (var2), var2 = DWC_LIST_NEXT(var2)) ++ (var) = (var2), (var2) = DWC_LIST_NEXT(var2)) + +#define DWC_LIST_FOREACH_REVERSE(var, list) \ + for((var) = DWC_LIST_LAST(list); \ @@ -32459,15 +38801,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo +struct name { \ + struct type *slh_first; /* first element */ \ +} -+ -+#define DWC_SLIST_HEAD_INITIALIZER(head) \ ++ ++#define DWC_SLIST_HEAD_INITIALIZER(head) \ + { NULL } -+ ++ +#define DWC_SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} -+ ++ +/* + * Singly-linked List access methods. + */ @@ -32476,13 +38818,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo +#define DWC_SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) +#define DWC_SLIST_NEXT(elm, field) ((elm)->field.sle_next) + -+#define DWC_SLIST_FOREACH(var, head, field) \ ++#define DWC_SLIST_FOREACH(var, head, field) \ + for((var) = SLIST_FIRST(head); \ + (var) != SLIST_END(head); \ + (var) = SLIST_NEXT(var, field)) + -+#define DWC_SLIST_FOREACH_PREVPTR(var, varp, head, field) \ -+ for ((varp) = &SLIST_FIRST((head)); \ ++#define DWC_SLIST_FOREACH_PREVPTR(var, varp, head, field) \ ++ for((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != SLIST_END(head); \ + (varp) = &SLIST_NEXT((var), field)) + @@ -32493,7 +38835,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo + SLIST_FIRST(head) = SLIST_END(head); \ +} + -+#define DWC_SLIST_INSERT_AFTER(slistelm, elm, field) do { \ ++#define DWC_SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ +} while (0) @@ -32524,88 +38866,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo + } \ +} while (0) + -+#if 0 -+ -+/* -+ * List definitions. -+ */ -+#define DWC_LIST_HEAD(name, type) \ -+struct name { \ -+ struct type *lh_first; /* first element */ \ -+} -+ -+#define DWC_LIST_HEAD_INITIALIZER(head) \ -+ { NULL } -+ -+#define DWC_LIST_ENTRY(type) \ -+struct { \ -+ struct type *le_next; /* next element */ \ -+ struct type **le_prev; /* address of previous next element */ \ -+} -+ -+/* -+ * List access methods -+ */ -+#define DWC_LIST_FIRST(head) ((head)->lh_first) -+#define DWC_LIST_END(head) NULL -+#define DWC_LIST_EMPTY(head) (DWC_LIST_FIRST(head) == DWC_LIST_END(head)) -+#define DWC_LIST_NEXT(elm, field) ((elm)->field.le_next) -+ -+#define DWC_LIST_FOREACH(var, head, field) \ -+ for((var) = DWC_LIST_FIRST(head); \ -+ (var)!= DWC_LIST_END(head); \ -+ (var) = DWC_LIST_NEXT(var, field)) -+#define DWC_LIST_FOREACH_SAFE(var, var2, head, field) \ -+ for((var) = DWC_LIST_FIRST(head), var2 = DWC_LIST_NEXT(var, field); \ -+ (var) != DWC_LIST_END(head); \ -+ (var) = var2, var2 = DWC_LIST_NEXT(var, field)) -+ -+/* -+ * List functions. -+ */ -+#define DWC_LIST_INIT(head) do { \ -+ DWC_LIST_FIRST(head) = DWC_LIST_END(head); \ -+} while (0) -+ -+#define DWC_LIST_INSERT_AFTER(listelm, elm, field) do { \ -+ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ -+ (listelm)->field.le_next->field.le_prev = \ -+ &(elm)->field.le_next; \ -+ (listelm)->field.le_next = (elm); \ -+ (elm)->field.le_prev = &(listelm)->field.le_next; \ -+} while (0) -+ -+#define DWC_LIST_INSERT_BEFORE(listelm, elm, field) do { \ -+ (elm)->field.le_prev = (listelm)->field.le_prev; \ -+ (elm)->field.le_next = (listelm); \ -+ *(listelm)->field.le_prev = (elm); \ -+ (listelm)->field.le_prev = &(elm)->field.le_next; \ -+} while (0) -+ -+#define DWC_LIST_INSERT_HEAD(head, elm, field) do { \ -+ if (((elm)->field.le_next = (head)->lh_first) != NULL) \ -+ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ -+ (head)->lh_first = (elm); \ -+ (elm)->field.le_prev = &(head)->lh_first; \ -+} while (0) -+ -+#define DWC_LIST_REMOVE(elm, field) do { \ -+ if ((elm)->field.le_next != NULL) \ -+ (elm)->field.le_next->field.le_prev = \ -+ (elm)->field.le_prev; \ -+ *(elm)->field.le_prev = (elm)->field.le_next; \ -+} while (0) -+ -+#define DWC_LIST_REPLACE(elm, elm2, field) do { \ -+ if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ -+ (elm2)->field.le_next->field.le_prev = \ -+ &(elm2)->field.le_next; \ -+ (elm2)->field.le_prev = (elm)->field.le_prev; \ -+ *(elm2)->field.le_prev = (elm2); \ -+} while (0) -+ -+#endif -+ +/* + * Simple queue definitions. + */ @@ -32615,7 +38875,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo + struct type **sqh_last; /* addr of last next element */ \ +} + -+#define DWC_SIMPLEQ_HEAD_INITIALIZER(head) \ ++#define DWC_SIMPLEQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).sqh_first } + +#define DWC_SIMPLEQ_ENTRY(type) \ @@ -32639,7 +38899,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo +/* + * Simple queue functions. + */ -+#define DWC_SIMPLEQ_INIT(head) do { \ ++#define DWC_SIMPLEQ_INIT(head) do { \ + (head)->sqh_first = NULL; \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (0) @@ -32656,7 +38916,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (0) + -+#define DWC_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ ++#define DWC_SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (listelm)->field.sqe_next = (elm); \ @@ -32670,13 +38930,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo +/* + * Tail queue definitions. + */ -+#define DWC_TAILQ_HEAD(name, type) \ ++#define DWC_TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + -+#define DWC_TAILQ_HEAD_INITIALIZER(head) \ ++#define DWC_TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define DWC_TAILQ_ENTRY(type) \ @@ -32685,12 +38945,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo + struct type **tqe_prev; /* address of previous next element */ \ +} + -+/* -+ * tail queue access methods ++/* ++ * tail queue access methods + */ +#define DWC_TAILQ_FIRST(head) ((head)->tqh_first) -+#define DWC_TAILQ_END(head) NULL -+#define DWC_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) ++#define DWC_TAILQ_END(head) NULL ++#define DWC_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define DWC_TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +/* XXX */ @@ -32699,7 +38959,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo +#define DWC_TAILQ_EMPTY(head) \ + (TAILQ_FIRST(head) == TAILQ_END(head)) + -+#define DWC_TAILQ_FOREACH(var, head, field) \ ++#define DWC_TAILQ_FOREACH(var, head, field) \ + for((var) = TAILQ_FIRST(head); \ + (var) != TAILQ_END(head); \ + (var) = TAILQ_NEXT(var, field)) @@ -32712,7 +38972,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo +/* + * Tail queue functions. + */ -+#define DWC_TAILQ_INIT(head) do { \ ++#define DWC_TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (0) @@ -32744,7 +39004,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (0) + -+#define DWC_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ ++#define DWC_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ @@ -32779,7 +39039,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo + struct type *cqh_last; /* last element */ \ +} + -+#define DWC_CIRCLEQ_HEAD_INITIALIZER(head) \ ++#define DWC_CIRCLEQ_HEAD_INITIALIZER(head) \ + { DWC_CIRCLEQ_END(&head), DWC_CIRCLEQ_END(&head) } + +#define DWC_CIRCLEQ_ENTRY(type) \ @@ -32789,7 +39049,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo +} + +/* -+ * Circular queue access methods ++ * Circular queue access methods + */ +#define DWC_CIRCLEQ_FIRST(head) ((head)->cqh_first) +#define DWC_CIRCLEQ_LAST(head) ((head)->cqh_last) @@ -32803,33 +39063,33 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo + +#define DWC_CIRCLEQ_FOREACH(var, head, field) \ + for((var) = DWC_CIRCLEQ_FIRST(head); \ -+ (var) != DWC_CIRCLEQ_END(head); \ ++ (var) != DWC_CIRCLEQ_END(head); \ + (var) = DWC_CIRCLEQ_NEXT(var, field)) + -+#define DWC_CIRCLEQ_FOREACH_SAFE(var, var2, head, field) \ -+ for((var) = DWC_CIRCLEQ_FIRST(head), var2 = DWC_CIRCLEQ_NEXT(var, field); \ ++#define DWC_CIRCLEQ_FOREACH_SAFE(var, var2, head, field) \ ++ for((var) = DWC_CIRCLEQ_FIRST(head), var2 = DWC_CIRCLEQ_NEXT(var, field); \ + (var) != DWC_CIRCLEQ_END(head); \ + (var) = var2, var2 = DWC_CIRCLEQ_NEXT(var, field)) + +#define DWC_CIRCLEQ_FOREACH_REVERSE(var, head, field) \ -+ for((var) = DWC_CIRCLEQ_LAST(head); \ -+ (var) != DWC_CIRCLEQ_END(head); \ ++ for((var) = DWC_CIRCLEQ_LAST(head); \ ++ (var) != DWC_CIRCLEQ_END(head); \ + (var) = DWC_CIRCLEQ_PREV(var, field)) + +/* + * Circular queue functions. + */ -+#define DWC_CIRCLEQ_INIT(head) do { \ -+ (head)->cqh_first = DWC_CIRCLEQ_END(head); \ -+ (head)->cqh_last = DWC_CIRCLEQ_END(head); \ ++#define DWC_CIRCLEQ_INIT(head) do { \ ++ (head)->cqh_first = DWC_CIRCLEQ_END(head); \ ++ (head)->cqh_last = DWC_CIRCLEQ_END(head); \ +} while (0) + -+#define DWC_CIRCLEQ_INIT_ENTRY(elm, field) do { \ -+ (elm)->field.cqe_next = NULL; \ -+ (elm)->field.cqe_prev = NULL; \ ++#define DWC_CIRCLEQ_INIT_ENTRY(elm, field) do { \ ++ (elm)->field.cqe_next = NULL; \ ++ (elm)->field.cqe_prev = NULL; \ +} while (0) + -+#define DWC_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ ++#define DWC_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm)->field.cqe_next; \ + (elm)->field.cqe_prev = (listelm); \ + if ((listelm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \ @@ -32839,7 +39099,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo + (listelm)->field.cqe_next = (elm); \ +} while (0) + -+#define DWC_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ ++#define DWC_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ + (elm)->field.cqe_next = (listelm); \ + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ + if ((listelm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \ @@ -32869,51 +39129,57 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_list.h linux-rpi-bo + (head)->cqh_last = (elm); \ +} while (0) + -+#define DWC_CIRCLEQ_REMOVE(head, elm, field) do { \ -+ if ((elm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \ ++#define DWC_CIRCLEQ_REMOVE(head, elm, field) do { \ ++ if ((elm)->field.cqe_next == DWC_CIRCLEQ_END(head)) \ + (head)->cqh_last = (elm)->field.cqe_prev; \ + else \ + (elm)->field.cqe_next->field.cqe_prev = \ + (elm)->field.cqe_prev; \ -+ if ((elm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \ ++ if ((elm)->field.cqe_prev == DWC_CIRCLEQ_END(head)) \ + (head)->cqh_first = (elm)->field.cqe_next; \ + else \ + (elm)->field.cqe_prev->field.cqe_next = \ + (elm)->field.cqe_next; \ +} while (0) + -+#define DWC_CIRCLEQ_REMOVE_INIT(head, elm, field) do { \ -+ DWC_CIRCLEQ_REMOVE(head, elm, field); \ -+ DWC_CIRCLEQ_INIT_ENTRY(elm, field); \ ++#define DWC_CIRCLEQ_REMOVE_INIT(head, elm, field) do { \ ++ DWC_CIRCLEQ_REMOVE(head, elm, field); \ ++ DWC_CIRCLEQ_INIT_ENTRY(elm, field); \ +} while (0) + -+#define DWC_CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ ++#define DWC_CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ -+ DWC_CIRCLEQ_END(head)) \ ++ DWC_CIRCLEQ_END(head)) \ + (head).cqh_last = (elm2); \ + else \ + (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ + if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ -+ DWC_CIRCLEQ_END(head)) \ ++ DWC_CIRCLEQ_END(head)) \ + (head).cqh_first = (elm2); \ + else \ + (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ +} while (0) + -+#endif /* !_SYS_QUEUE_H_ */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_mem.c linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/dwc_mem.c ---- linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_mem.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/dwc_mem.c 2012-07-15 20:29:18.989081834 +0200 -@@ -0,0 +1,172 @@ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _DWC_LIST_H_ */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_mem.c b/drivers/usb/host/dwc_common_port/dwc_mem.c +new file mode 100644 +index 0000000..ad645ff +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_mem.c +@@ -0,0 +1,245 @@ ++/* Memory Debugging */ ++#ifdef DWC_DEBUG_MEMORY ++ +#include "dwc_os.h" +#include "dwc_list.h" + -+/* Memory Debugging */ -+#ifdef DEBUG_MEMORY -+ -+struct allocation -+{ ++struct allocation { + void *addr; ++ void *ctx; + char *func; + int line; + uint32_t size; @@ -32923,8 +39189,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_mem.c linux-rpi-boo + +DWC_CIRCLEQ_HEAD(allocation_queue, allocation); + -+struct allocation_manager -+{ ++struct allocation_manager { ++ void *mem_ctx; + struct allocation_queue allocations; + + /* statistics */ @@ -32932,160 +39198,918 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_mem.c linux-rpi-boo + int num_freed; + int num_active; + uint32_t total; -+ uint32_t current; ++ uint32_t cur; + uint32_t max; +}; + -+ +static struct allocation_manager *manager = NULL; + -+static void add_allocation(uint32_t size, char const* func, int line, void *addr, int dma) ++static int add_allocation(void *ctx, uint32_t size, char const *func, int line, void *addr, ++ int dma) +{ -+ struct allocation *a = __DWC_ALLOC_ATOMIC(sizeof(*a)); -+ a->func = __DWC_ALLOC_ATOMIC(DWC_STRLEN(func)+1); -+ DWC_MEMCPY(a->func, func, DWC_STRLEN(func)+1); ++ struct allocation *a; ++ ++ DWC_ASSERT(manager != NULL, "manager not allocated"); ++ ++ a = __DWC_ALLOC_ATOMIC(manager->mem_ctx, sizeof(*a)); ++ if (!a) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ a->func = __DWC_ALLOC_ATOMIC(manager->mem_ctx, DWC_STRLEN(func) + 1); ++ if (!a->func) { ++ __DWC_FREE(manager->mem_ctx, a); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ DWC_MEMCPY(a->func, func, DWC_STRLEN(func) + 1); ++ a->addr = addr; ++ a->ctx = ctx; + a->line = line; + a->size = size; -+ a->addr = addr; + a->dma = dma; + DWC_CIRCLEQ_INSERT_TAIL(&manager->allocations, a, entry); + + /* Update stats */ -+ manager->num ++; -+ manager->num_active ++; ++ manager->num++; ++ manager->num_active++; + manager->total += size; -+ manager->current += size; -+ if (manager->max < manager->current) { -+ manager->max = manager->current; ++ manager->cur += size; ++ ++ if (manager->max < manager->cur) { ++ manager->max = manager->cur; + } ++ ++ return 0; +} + -+static struct allocation *find_allocation(void *addr) ++static struct allocation *find_allocation(void *ctx, void *addr) +{ + struct allocation *a; ++ + DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { -+ if (a->addr == addr) { ++ if (a->ctx == ctx && a->addr == addr) { + return a; + } + } ++ + return NULL; +} + -+static void free_allocation(void *addr, char const* func, int line) ++static void free_allocation(void *ctx, void *addr, char const *func, int line) +{ -+ struct allocation *a = find_allocation(addr); -+ if (!a && func && (line >= 0)) { -+ DWC_ASSERT(0, "Free of address %p that was never allocated or already freed %s:%d", addr, func, line); ++ struct allocation *a = find_allocation(ctx, addr); ++ ++ if (!a) { ++ DWC_ASSERT(0, ++ "Free of address %p that was never allocated or already freed %s:%d", ++ addr, func, line); + return; + } ++ + DWC_CIRCLEQ_REMOVE(&manager->allocations, a, entry); + -+ manager->num_active --; -+ manager->num_freed ++; -+ manager->current -= a->size; -+ __DWC_FREE(a->func); -+ __DWC_FREE(a); ++ manager->num_active--; ++ manager->num_freed++; ++ manager->cur -= a->size; ++ __DWC_FREE(manager->mem_ctx, a->func); ++ __DWC_FREE(manager->mem_ctx, a); +} + -+void dwc_memory_debug_start(void) ++int dwc_memory_debug_start(void *mem_ctx) +{ + DWC_ASSERT(manager == NULL, "Memory debugging has already started\n"); -+ if (manager == NULL) { -+ manager = __DWC_ALLOC(sizeof(*manager)); ++ ++ if (manager) { ++ return -DWC_E_BUSY; ++ } ++ ++ manager = __DWC_ALLOC(mem_ctx, sizeof(*manager)); ++ if (!manager) { ++ return -DWC_E_NO_MEMORY; + } + + DWC_CIRCLEQ_INIT(&manager->allocations); ++ manager->mem_ctx = mem_ctx; + manager->num = 0; + manager->num_freed = 0; + manager->num_active = 0; + manager->total = 0; -+ manager->current = 0; ++ manager->cur = 0; + manager->max = 0; ++ ++ return 0; +} + +void dwc_memory_debug_stop(void) +{ + struct allocation *a; ++ + dwc_memory_debug_report(); + + DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { + DWC_ERROR("Memory leaked from %s:%d\n", a->func, a->line); -+ free_allocation(a->addr, NULL, -1); ++ free_allocation(a->ctx, a->addr, NULL, -1); + } + -+ __DWC_FREE(manager); ++ __DWC_FREE(manager->mem_ctx, manager); +} + +void dwc_memory_debug_report(void) +{ + struct allocation *a; ++ + DWC_PRINTF("\n\n\n----------------- Memory Debugging Report -----------------\n\n"); + DWC_PRINTF("Num Allocations = %d\n", manager->num); + DWC_PRINTF("Freed = %d\n", manager->num_freed); + DWC_PRINTF("Active = %d\n", manager->num_active); -+ DWC_PRINTF("Current Memory Used = %d\n", manager->current); ++ DWC_PRINTF("Current Memory Used = %d\n", manager->cur); + DWC_PRINTF("Total Memory Used = %d\n", manager->total); + DWC_PRINTF("Maximum Memory Used at Once = %d\n", manager->max); + DWC_PRINTF("Unfreed allocations:\n"); + + DWC_CIRCLEQ_FOREACH(a, &manager->allocations, entry) { -+ DWC_PRINTF(" addr=%p, size=%d from %s:%d, DMA=%d\n", a->addr, a->size, a->func, a->line, a->dma); ++ DWC_PRINTF(" addr=%p, size=%d from %s:%d, DMA=%d\n", ++ a->addr, a->size, a->func, a->line, a->dma); + } +} + -+ -+ +/* The replacement functions */ -+void *dwc_alloc_debug(uint32_t size, char const* func, int line) ++void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line) +{ -+ void *addr = __DWC_ALLOC(size); -+ add_allocation(size, func, line, addr, 0); ++ void *addr = __DWC_ALLOC(mem_ctx, size); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(mem_ctx, size, func, line, addr, 0)) { ++ __DWC_FREE(mem_ctx, addr); ++ return NULL; ++ } ++ + return addr; +} + -+void *dwc_alloc_atomic_debug(uint32_t size, char const* func, int line) ++void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, ++ int line) +{ -+ void *addr = __DWC_ALLOC_ATOMIC(size); -+ add_allocation(size, func, line, addr, 0); ++ void *addr = __DWC_ALLOC_ATOMIC(mem_ctx, size); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(mem_ctx, size, func, line, addr, 0)) { ++ __DWC_FREE(mem_ctx, addr); ++ return NULL; ++ } ++ + return addr; +} + -+void dwc_free_debug(void *addr, char const* func, int line) ++void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line) +{ -+ free_allocation(addr, func, line); -+ __DWC_FREE(addr); ++ free_allocation(mem_ctx, addr, func, line); ++ __DWC_FREE(mem_ctx, addr); +} + -+void *dwc_dma_alloc_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line) ++void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr, ++ char const *func, int line) +{ -+ void *addr = __DWC_DMA_ALLOC(size, dma_addr); -+ add_allocation(size, func, line, addr, 1); ++ void *addr = __DWC_DMA_ALLOC(dma_ctx, size, dma_addr); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(dma_ctx, size, func, line, addr, 1)) { ++ __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr); ++ return NULL; ++ } ++ + return addr; +} + -+void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line) ++void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, ++ dwc_dma_t *dma_addr, char const *func, int line) +{ -+ void *addr = __DWC_DMA_ALLOC_ATOMIC(size, dma_addr); -+ add_allocation(size, func, line, addr, 1); ++ void *addr = __DWC_DMA_ALLOC_ATOMIC(dma_ctx, size, dma_addr); ++ ++ if (!addr) { ++ return NULL; ++ } ++ ++ if (add_allocation(dma_ctx, size, func, line, addr, 1)) { ++ __DWC_DMA_FREE(dma_ctx, size, addr, *dma_addr); ++ return NULL; ++ } ++ + return addr; +} + -+void dwc_dma_free_debug(uint32_t size, void *virt_addr, dwc_dma_t dma_addr, char const *func, int line) ++void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr, ++ dwc_dma_t dma_addr, char const *func, int line) +{ -+ free_allocation(virt_addr, func, line); -+ __DWC_DMA_FREE(size, virt_addr, dma_addr); ++ free_allocation(dma_ctx, virt_addr, func, line); ++ __DWC_DMA_FREE(dma_ctx, size, virt_addr, dma_addr); +} + -+#endif /* DEBUG_MEMORY */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.c ---- linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.c 2012-07-15 20:29:18.989081834 +0200 -@@ -0,0 +1,256 @@ ++#endif /* DWC_DEBUG_MEMORY */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_modpow.c b/drivers/usb/host/dwc_common_port/dwc_modpow.c +new file mode 100644 +index 0000000..b7c456b +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_modpow.c +@@ -0,0 +1,636 @@ ++/* Bignum routines adapted from PUTTY sources. PuTTY copyright notice follows. ++ * ++ * PuTTY is copyright 1997-2007 Simon Tatham. ++ * ++ * Portions copyright Robert de Bath, Joris van Rantwijk, Delian ++ * Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, ++ * Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus ++ * Kuhn, and CORE SDI S.A. ++ * ++ * Permission is hereby granted, free of charge, to any person ++ * obtaining a copy of this software and associated documentation files ++ * (the "Software"), to deal in the Software without restriction, ++ * including without limitation the rights to use, copy, modify, merge, ++ * publish, distribute, sublicense, and/or sell copies of the Software, ++ * and to permit persons to whom the Software is furnished to do so, ++ * subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be ++ * included in all copies or substantial portions of the Software. ++ ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, ++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND ++ * NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE ++ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF ++ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION ++ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ++ * ++ */ ++#ifdef DWC_CRYPTOLIB ++ ++#ifndef CONFIG_MACH_IPMATE ++ ++#include "dwc_modpow.h" ++ ++#define BIGNUM_INT_MASK 0xFFFFFFFFUL ++#define BIGNUM_TOP_BIT 0x80000000UL ++#define BIGNUM_INT_BITS 32 ++ ++ ++static void *snmalloc(void *mem_ctx, size_t n, size_t size) ++{ ++ void *p; ++ size *= n; ++ if (size == 0) size = 1; ++ p = dwc_alloc(mem_ctx, size); ++ return p; ++} ++ ++#define snewn(ctx, n, type) ((type *)snmalloc((ctx), (n), sizeof(type))) ++#define sfree dwc_free ++ ++/* ++ * Usage notes: ++ * * Do not call the DIVMOD_WORD macro with expressions such as array ++ * subscripts, as some implementations object to this (see below). ++ * * Note that none of the division methods below will cope if the ++ * quotient won't fit into BIGNUM_INT_BITS. Callers should be careful ++ * to avoid this case. ++ * If this condition occurs, in the case of the x86 DIV instruction, ++ * an overflow exception will occur, which (according to a correspondent) ++ * will manifest on Windows as something like ++ * 0xC0000095: Integer overflow ++ * The C variant won't give the right answer, either. ++ */ ++ ++#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2) ++ ++#if defined __GNUC__ && defined __i386__ ++#define DIVMOD_WORD(q, r, hi, lo, w) \ ++ __asm__("div %2" : \ ++ "=d" (r), "=a" (q) : \ ++ "r" (w), "d" (hi), "a" (lo)) ++#else ++#define DIVMOD_WORD(q, r, hi, lo, w) do { \ ++ BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \ ++ q = n / w; \ ++ r = n % w; \ ++} while (0) ++#endif ++ ++// q = n / w; ++// r = n % w; ++ ++#define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8) ++ ++#define BIGNUM_INTERNAL ++ ++static Bignum newbn(void *mem_ctx, int length) ++{ ++ Bignum b = snewn(mem_ctx, length + 1, BignumInt); ++ //if (!b) ++ //abort(); /* FIXME */ ++ DWC_MEMSET(b, 0, (length + 1) * sizeof(*b)); ++ b[0] = length; ++ return b; ++} ++ ++void freebn(void *mem_ctx, Bignum b) ++{ ++ /* ++ * Burn the evidence, just in case. ++ */ ++ DWC_MEMSET(b, 0, sizeof(b[0]) * (b[0] + 1)); ++ sfree(mem_ctx, b); ++} ++ ++/* ++ * Compute c = a * b. ++ * Input is in the first len words of a and b. ++ * Result is returned in the first 2*len words of c. ++ */ ++static void internal_mul(BignumInt *a, BignumInt *b, ++ BignumInt *c, int len) ++{ ++ int i, j; ++ BignumDblInt t; ++ ++ for (j = 0; j < 2 * len; j++) ++ c[j] = 0; ++ ++ for (i = len - 1; i >= 0; i--) { ++ t = 0; ++ for (j = len - 1; j >= 0; j--) { ++ t += MUL_WORD(a[i], (BignumDblInt) b[j]); ++ t += (BignumDblInt) c[i + j + 1]; ++ c[i + j + 1] = (BignumInt) t; ++ t = t >> BIGNUM_INT_BITS; ++ } ++ c[i] = (BignumInt) t; ++ } ++} ++ ++static void internal_add_shifted(BignumInt *number, ++ unsigned n, int shift) ++{ ++ int word = 1 + (shift / BIGNUM_INT_BITS); ++ int bshift = shift % BIGNUM_INT_BITS; ++ BignumDblInt addend; ++ ++ addend = (BignumDblInt)n << bshift; ++ ++ while (addend) { ++ addend += number[word]; ++ number[word] = (BignumInt) addend & BIGNUM_INT_MASK; ++ addend >>= BIGNUM_INT_BITS; ++ word++; ++ } ++} ++ ++/* ++ * Compute a = a % m. ++ * Input in first alen words of a and first mlen words of m. ++ * Output in first alen words of a ++ * (of which first alen-mlen words will be zero). ++ * The MSW of m MUST have its high bit set. ++ * Quotient is accumulated in the `quotient' array, which is a Bignum ++ * rather than the internal bigendian format. Quotient parts are shifted ++ * left by `qshift' before adding into quot. ++ */ ++static void internal_mod(BignumInt *a, int alen, ++ BignumInt *m, int mlen, ++ BignumInt *quot, int qshift) ++{ ++ BignumInt m0, m1; ++ unsigned int h; ++ int i, k; ++ ++ m0 = m[0]; ++ if (mlen > 1) ++ m1 = m[1]; ++ else ++ m1 = 0; ++ ++ for (i = 0; i <= alen - mlen; i++) { ++ BignumDblInt t; ++ unsigned int q, r, c, ai1; ++ ++ if (i == 0) { ++ h = 0; ++ } else { ++ h = a[i - 1]; ++ a[i - 1] = 0; ++ } ++ ++ if (i == alen - 1) ++ ai1 = 0; ++ else ++ ai1 = a[i + 1]; ++ ++ /* Find q = h:a[i] / m0 */ ++ if (h >= m0) { ++ /* ++ * Special case. ++ * ++ * To illustrate it, suppose a BignumInt is 8 bits, and ++ * we are dividing (say) A1:23:45:67 by A1:B2:C3. Then ++ * our initial division will be 0xA123 / 0xA1, which ++ * will give a quotient of 0x100 and a divide overflow. ++ * However, the invariants in this division algorithm ++ * are not violated, since the full number A1:23:... is ++ * _less_ than the quotient prefix A1:B2:... and so the ++ * following correction loop would have sorted it out. ++ * ++ * In this situation we set q to be the largest ++ * quotient we _can_ stomach (0xFF, of course). ++ */ ++ q = BIGNUM_INT_MASK; ++ } else { ++ /* Macro doesn't want an array subscript expression passed ++ * into it (see definition), so use a temporary. */ ++ BignumInt tmplo = a[i]; ++ DIVMOD_WORD(q, r, h, tmplo, m0); ++ ++ /* Refine our estimate of q by looking at ++ h:a[i]:a[i+1] / m0:m1 */ ++ t = MUL_WORD(m1, q); ++ if (t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) { ++ q--; ++ t -= m1; ++ r = (r + m0) & BIGNUM_INT_MASK; /* overflow? */ ++ if (r >= (BignumDblInt) m0 && ++ t > ((BignumDblInt) r << BIGNUM_INT_BITS) + ai1) q--; ++ } ++ } ++ ++ /* Subtract q * m from a[i...] */ ++ c = 0; ++ for (k = mlen - 1; k >= 0; k--) { ++ t = MUL_WORD(q, m[k]); ++ t += c; ++ c = (unsigned)(t >> BIGNUM_INT_BITS); ++ if ((BignumInt) t > a[i + k]) ++ c++; ++ a[i + k] -= (BignumInt) t; ++ } ++ ++ /* Add back m in case of borrow */ ++ if (c != h) { ++ t = 0; ++ for (k = mlen - 1; k >= 0; k--) { ++ t += m[k]; ++ t += a[i + k]; ++ a[i + k] = (BignumInt) t; ++ t = t >> BIGNUM_INT_BITS; ++ } ++ q--; ++ } ++ if (quot) ++ internal_add_shifted(quot, q, qshift + BIGNUM_INT_BITS * (alen - mlen - i)); ++ } ++} ++ ++/* ++ * Compute p % mod. ++ * The most significant word of mod MUST be non-zero. ++ * We assume that the result array is the same size as the mod array. ++ * We optionally write out a quotient if `quotient' is non-NULL. ++ * We can avoid writing out the result if `result' is NULL. ++ */ ++void bigdivmod(void *mem_ctx, Bignum p, Bignum mod, Bignum result, Bignum quotient) ++{ ++ BignumInt *n, *m; ++ int mshift; ++ int plen, mlen, i, j; ++ ++ /* Allocate m of size mlen, copy mod to m */ ++ /* We use big endian internally */ ++ mlen = mod[0]; ++ m = snewn(mem_ctx, mlen, BignumInt); ++ //if (!m) ++ //abort(); /* FIXME */ ++ for (j = 0; j < mlen; j++) ++ m[j] = mod[mod[0] - j]; ++ ++ /* Shift m left to make msb bit set */ ++ for (mshift = 0; mshift < BIGNUM_INT_BITS-1; mshift++) ++ if ((m[0] << mshift) & BIGNUM_TOP_BIT) ++ break; ++ if (mshift) { ++ for (i = 0; i < mlen - 1; i++) ++ m[i] = (m[i] << mshift) | (m[i + 1] >> (BIGNUM_INT_BITS - mshift)); ++ m[mlen - 1] = m[mlen - 1] << mshift; ++ } ++ ++ plen = p[0]; ++ /* Ensure plen > mlen */ ++ if (plen <= mlen) ++ plen = mlen + 1; ++ ++ /* Allocate n of size plen, copy p to n */ ++ n = snewn(mem_ctx, plen, BignumInt); ++ //if (!n) ++ //abort(); /* FIXME */ ++ for (j = 0; j < plen; j++) ++ n[j] = 0; ++ for (j = 1; j <= (int)p[0]; j++) ++ n[plen - j] = p[j]; ++ ++ /* Main computation */ ++ internal_mod(n, plen, m, mlen, quotient, mshift); ++ ++ /* Fixup result in case the modulus was shifted */ ++ if (mshift) { ++ for (i = plen - mlen - 1; i < plen - 1; i++) ++ n[i] = (n[i] << mshift) | (n[i + 1] >> (BIGNUM_INT_BITS - mshift)); ++ n[plen - 1] = n[plen - 1] << mshift; ++ internal_mod(n, plen, m, mlen, quotient, 0); ++ for (i = plen - 1; i >= plen - mlen; i--) ++ n[i] = (n[i] >> mshift) | (n[i - 1] << (BIGNUM_INT_BITS - mshift)); ++ } ++ ++ /* Copy result to buffer */ ++ if (result) { ++ for (i = 1; i <= (int)result[0]; i++) { ++ int j = plen - i; ++ result[i] = j >= 0 ? n[j] : 0; ++ } ++ } ++ ++ /* Free temporary arrays */ ++ for (i = 0; i < mlen; i++) ++ m[i] = 0; ++ sfree(mem_ctx, m); ++ for (i = 0; i < plen; i++) ++ n[i] = 0; ++ sfree(mem_ctx, n); ++} ++ ++/* ++ * Simple remainder. ++ */ ++Bignum bigmod(void *mem_ctx, Bignum a, Bignum b) ++{ ++ Bignum r = newbn(mem_ctx, b[0]); ++ bigdivmod(mem_ctx, a, b, r, NULL); ++ return r; ++} ++ ++/* ++ * Compute (base ^ exp) % mod. ++ */ ++Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod) ++{ ++ BignumInt *a, *b, *n, *m; ++ int mshift; ++ int mlen, i, j; ++ Bignum base, result; ++ ++ /* ++ * The most significant word of mod needs to be non-zero. It ++ * should already be, but let's make sure. ++ */ ++ //assert(mod[mod[0]] != 0); ++ ++ /* ++ * Make sure the base is smaller than the modulus, by reducing ++ * it modulo the modulus if not. ++ */ ++ base = bigmod(mem_ctx, base_in, mod); ++ ++ /* Allocate m of size mlen, copy mod to m */ ++ /* We use big endian internally */ ++ mlen = mod[0]; ++ m = snewn(mem_ctx, mlen, BignumInt); ++ //if (!m) ++ //abort(); /* FIXME */ ++ for (j = 0; j < mlen; j++) ++ m[j] = mod[mod[0] - j]; ++ ++ /* Shift m left to make msb bit set */ ++ for (mshift = 0; mshift < BIGNUM_INT_BITS - 1; mshift++) ++ if ((m[0] << mshift) & BIGNUM_TOP_BIT) ++ break; ++ if (mshift) { ++ for (i = 0; i < mlen - 1; i++) ++ m[i] = ++ (m[i] << mshift) | (m[i + 1] >> ++ (BIGNUM_INT_BITS - mshift)); ++ m[mlen - 1] = m[mlen - 1] << mshift; ++ } ++ ++ /* Allocate n of size mlen, copy base to n */ ++ n = snewn(mem_ctx, mlen, BignumInt); ++ //if (!n) ++ //abort(); /* FIXME */ ++ i = mlen - base[0]; ++ for (j = 0; j < i; j++) ++ n[j] = 0; ++ for (j = 0; j < base[0]; j++) ++ n[i + j] = base[base[0] - j]; ++ ++ /* Allocate a and b of size 2*mlen. Set a = 1 */ ++ a = snewn(mem_ctx, 2 * mlen, BignumInt); ++ //if (!a) ++ //abort(); /* FIXME */ ++ b = snewn(mem_ctx, 2 * mlen, BignumInt); ++ //if (!b) ++ //abort(); /* FIXME */ ++ for (i = 0; i < 2 * mlen; i++) ++ a[i] = 0; ++ a[2 * mlen - 1] = 1; ++ ++ /* Skip leading zero bits of exp. */ ++ i = 0; ++ j = BIGNUM_INT_BITS - 1; ++ while (i < exp[0] && (exp[exp[0] - i] & (1 << j)) == 0) { ++ j--; ++ if (j < 0) { ++ i++; ++ j = BIGNUM_INT_BITS - 1; ++ } ++ } ++ ++ /* Main computation */ ++ while (i < exp[0]) { ++ while (j >= 0) { ++ internal_mul(a + mlen, a + mlen, b, mlen); ++ internal_mod(b, mlen * 2, m, mlen, NULL, 0); ++ if ((exp[exp[0] - i] & (1 << j)) != 0) { ++ internal_mul(b + mlen, n, a, mlen); ++ internal_mod(a, mlen * 2, m, mlen, NULL, 0); ++ } else { ++ BignumInt *t; ++ t = a; ++ a = b; ++ b = t; ++ } ++ j--; ++ } ++ i++; ++ j = BIGNUM_INT_BITS - 1; ++ } ++ ++ /* Fixup result in case the modulus was shifted */ ++ if (mshift) { ++ for (i = mlen - 1; i < 2 * mlen - 1; i++) ++ a[i] = ++ (a[i] << mshift) | (a[i + 1] >> ++ (BIGNUM_INT_BITS - mshift)); ++ a[2 * mlen - 1] = a[2 * mlen - 1] << mshift; ++ internal_mod(a, mlen * 2, m, mlen, NULL, 0); ++ for (i = 2 * mlen - 1; i >= mlen; i--) ++ a[i] = ++ (a[i] >> mshift) | (a[i - 1] << ++ (BIGNUM_INT_BITS - mshift)); ++ } ++ ++ /* Copy result to buffer */ ++ result = newbn(mem_ctx, mod[0]); ++ for (i = 0; i < mlen; i++) ++ result[result[0] - i] = a[i + mlen]; ++ while (result[0] > 1 && result[result[0]] == 0) ++ result[0]--; ++ ++ /* Free temporary arrays */ ++ for (i = 0; i < 2 * mlen; i++) ++ a[i] = 0; ++ sfree(mem_ctx, a); ++ for (i = 0; i < 2 * mlen; i++) ++ b[i] = 0; ++ sfree(mem_ctx, b); ++ for (i = 0; i < mlen; i++) ++ m[i] = 0; ++ sfree(mem_ctx, m); ++ for (i = 0; i < mlen; i++) ++ n[i] = 0; ++ sfree(mem_ctx, n); ++ ++ freebn(mem_ctx, base); ++ ++ return result; ++} ++ ++ ++#ifdef UNITTEST ++ ++static __u32 dh_p[] = { ++ 96, ++ 0xFFFFFFFF, ++ 0xFFFFFFFF, ++ 0xA93AD2CA, ++ 0x4B82D120, ++ 0xE0FD108E, ++ 0x43DB5BFC, ++ 0x74E5AB31, ++ 0x08E24FA0, ++ 0xBAD946E2, ++ 0x770988C0, ++ 0x7A615D6C, ++ 0xBBE11757, ++ 0x177B200C, ++ 0x521F2B18, ++ 0x3EC86A64, ++ 0xD8760273, ++ 0xD98A0864, ++ 0xF12FFA06, ++ 0x1AD2EE6B, ++ 0xCEE3D226, ++ 0x4A25619D, ++ 0x1E8C94E0, ++ 0xDB0933D7, ++ 0xABF5AE8C, ++ 0xA6E1E4C7, ++ 0xB3970F85, ++ 0x5D060C7D, ++ 0x8AEA7157, ++ 0x58DBEF0A, ++ 0xECFB8504, ++ 0xDF1CBA64, ++ 0xA85521AB, ++ 0x04507A33, ++ 0xAD33170D, ++ 0x8AAAC42D, ++ 0x15728E5A, ++ 0x98FA0510, ++ 0x15D22618, ++ 0xEA956AE5, ++ 0x3995497C, ++ 0x95581718, ++ 0xDE2BCBF6, ++ 0x6F4C52C9, ++ 0xB5C55DF0, ++ 0xEC07A28F, ++ 0x9B2783A2, ++ 0x180E8603, ++ 0xE39E772C, ++ 0x2E36CE3B, ++ 0x32905E46, ++ 0xCA18217C, ++ 0xF1746C08, ++ 0x4ABC9804, ++ 0x670C354E, ++ 0x7096966D, ++ 0x9ED52907, ++ 0x208552BB, ++ 0x1C62F356, ++ 0xDCA3AD96, ++ 0x83655D23, ++ 0xFD24CF5F, ++ 0x69163FA8, ++ 0x1C55D39A, ++ 0x98DA4836, ++ 0xA163BF05, ++ 0xC2007CB8, ++ 0xECE45B3D, ++ 0x49286651, ++ 0x7C4B1FE6, ++ 0xAE9F2411, ++ 0x5A899FA5, ++ 0xEE386BFB, ++ 0xF406B7ED, ++ 0x0BFF5CB6, ++ 0xA637ED6B, ++ 0xF44C42E9, ++ 0x625E7EC6, ++ 0xE485B576, ++ 0x6D51C245, ++ 0x4FE1356D, ++ 0xF25F1437, ++ 0x302B0A6D, ++ 0xCD3A431B, ++ 0xEF9519B3, ++ 0x8E3404DD, ++ 0x514A0879, ++ 0x3B139B22, ++ 0x020BBEA6, ++ 0x8A67CC74, ++ 0x29024E08, ++ 0x80DC1CD1, ++ 0xC4C6628B, ++ 0x2168C234, ++ 0xC90FDAA2, ++ 0xFFFFFFFF, ++ 0xFFFFFFFF, ++}; ++ ++static __u32 dh_a[] = { ++ 8, ++ 0xdf367516, ++ 0x86459caa, ++ 0xe2d459a4, ++ 0xd910dae0, ++ 0x8a8b5e37, ++ 0x67ab31c6, ++ 0xf0b55ea9, ++ 0x440051d6, ++}; ++ ++static __u32 dh_b[] = { ++ 8, ++ 0xded92656, ++ 0xe07a048a, ++ 0x6fa452cd, ++ 0x2df89d30, ++ 0xc75f1b0f, ++ 0x8ce3578f, ++ 0x7980a324, ++ 0x5daec786, ++}; ++ ++static __u32 dh_g[] = { ++ 1, ++ 2, ++}; ++ ++int main(void) ++{ ++ int i; ++ __u32 *k; ++ k = dwc_modpow(NULL, dh_g, dh_a, dh_p); ++ ++ printf("\n\n"); ++ for (i=0; i> 16; ++ printf("%04x %04x ", m, l); ++ if (!((i + 1)%13)) printf("\n"); ++ } ++ printf("\n\n"); ++ ++ if ((k[0] == 0x60) && (k[1] == 0x28e490e5) && (k[0x60] == 0x5a0d3d4e)) { ++ printf("PASS\n\n"); ++ } ++ else { ++ printf("FAIL\n\n"); ++ } ++ ++} ++ ++#endif /* UNITTEST */ ++ ++#endif /* CONFIG_MACH_IPMATE */ ++ ++#endif /*DWC_CRYPTOLIB */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_modpow.h b/drivers/usb/host/dwc_common_port/dwc_modpow.h +new file mode 100644 +index 0000000..64f00c2 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_modpow.h +@@ -0,0 +1,34 @@ ++/* ++ * dwc_modpow.h ++ * See dwc_modpow.c for license and changes ++ */ ++#ifndef _DWC_MODPOW_H ++#define _DWC_MODPOW_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "dwc_os.h" ++ ++/** @file ++ * ++ * This file defines the module exponentiation function which is only used ++ * internally by the DWC UWB modules for calculation of PKs during numeric ++ * association. The routine is taken from the PUTTY, an open source terminal ++ * emulator. The PUTTY License is preserved in the dwc_modpow.c file. ++ * ++ */ ++ ++typedef uint32_t BignumInt; ++typedef uint64_t BignumDblInt; ++typedef BignumInt *Bignum; ++ ++/* Compute modular exponentiaion */ ++extern Bignum dwc_modpow(void *mem_ctx, Bignum base_in, Bignum exp, Bignum mod); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _LINUX_BIGNUM_H */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_notifier.c b/drivers/usb/host/dwc_common_port/dwc_notifier.c +new file mode 100644 +index 0000000..8b3772a +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_notifier.c +@@ -0,0 +1,319 @@ ++#ifdef DWC_NOTIFYLIB ++ +#include "dwc_notifier.h" +#include "dwc_list.h" + -+typedef struct dwc_observer -+{ ++typedef struct dwc_observer { + void *observer; + dwc_notifier_callback_t callback; + void *data; @@ -33095,8 +40119,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-rp + +DWC_CIRCLEQ_HEAD(observer_queue, dwc_observer); + -+typedef struct dwc_notifier -+{ ++typedef struct dwc_notifier { ++ void *mem_ctx; + void *object; + struct observer_queue observers; + DWC_CIRCLEQ_ENTRY(dwc_notifier) list_entry; @@ -33104,30 +40128,43 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-rp + +DWC_CIRCLEQ_HEAD(notifier_queue, dwc_notifier); + -+typedef struct manager -+{ ++typedef struct manager { ++ void *mem_ctx; ++ void *wkq_ctx; + dwc_workq_t *wq; -+ dwc_mutex_t *mutex; ++// dwc_mutex_t *mutex; + struct notifier_queue notifiers; +} manager_t; + +static manager_t *manager = NULL; + -+static void create_manager(void) ++static int create_manager(void *mem_ctx, void *wkq_ctx) +{ -+ manager = DWC_ALLOC(sizeof(manager_t)); ++ manager = dwc_alloc(mem_ctx, sizeof(manager_t)); ++ if (!manager) { ++ return -DWC_E_NO_MEMORY; ++ } ++ + DWC_CIRCLEQ_INIT(&manager->notifiers); -+ manager->wq = DWC_WORKQ_ALLOC("DWC Notification WorkQ"); ++ ++ manager->wq = dwc_workq_alloc(wkq_ctx, "DWC Notification WorkQ"); ++ if (!manager->wq) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ return 0; +} + +static void free_manager(void) +{ -+ DWC_WORKQ_FREE(manager->wq); ++ dwc_workq_free(manager->wq); ++ + /* All notifiers must have unregistered themselves before this module + * can be removed. Hitting this assertion indicates a programmer + * error. */ -+ DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&manager->notifiers), "Notification manager being freed before all notifiers have been removed"); -+ DWC_FREE(manager); ++ DWC_ASSERT(DWC_CIRCLEQ_EMPTY(&manager->notifiers), ++ "Notification manager being freed before all notifiers have been removed"); ++ dwc_free(manager->mem_ctx, manager); +} + +#ifdef DEBUG @@ -33135,12 +40172,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-rp +{ + notifier_t *n; + observer_t *o; ++ + DWC_ASSERT(manager, "Notification manager not found"); -+ DWC_DEBUG("List of all notifiers and observers:"); ++ ++ DWC_DEBUG("List of all notifiers and observers:\n"); + DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) { -+ DWC_DEBUG("Notifier %p has observers:", n->object); ++ DWC_DEBUG("Notifier %p has observers:\n", n->object); + DWC_CIRCLEQ_FOREACH(o, &n->observers, list_entry) { -+ DWC_DEBUG(" %p watching %s", o->observer, o->notification); ++ DWC_DEBUG(" %p watching %s\n", o->observer, o->notification); + } + } +} @@ -33148,9 +40187,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-rp +#define dump_manager(...) +#endif + -+static observer_t *alloc_observer(void *observer, char *notification, dwc_notifier_callback_t callback, void *data) ++static observer_t *alloc_observer(void *mem_ctx, void *observer, char *notification, ++ dwc_notifier_callback_t callback, void *data) +{ -+ observer_t *new_observer = DWC_ALLOC(sizeof(observer_t)); ++ observer_t *new_observer = dwc_alloc(mem_ctx, sizeof(observer_t)); ++ ++ if (!new_observer) { ++ return NULL; ++ } ++ + DWC_CIRCLEQ_INIT_ENTRY(new_observer, list_entry); + new_observer->observer = observer; + new_observer->notification = notification; @@ -33159,12 +40204,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-rp + return new_observer; +} + -+static void free_observer(observer_t *observer) ++static void free_observer(void *mem_ctx, observer_t *observer) +{ -+ DWC_FREE(observer); ++ dwc_free(mem_ctx, observer); +} + -+static notifier_t *alloc_notifier(void *object) ++static notifier_t *alloc_notifier(void *mem_ctx, void *object) +{ + notifier_t *notifier; + @@ -33172,10 +40217,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-rp + return NULL; + } + -+ notifier = DWC_ALLOC(sizeof(notifier_t)); ++ notifier = dwc_alloc(mem_ctx, sizeof(notifier_t)); ++ if (!notifier) { ++ return NULL; ++ } ++ + DWC_CIRCLEQ_INIT(¬ifier->observers); + DWC_CIRCLEQ_INIT_ENTRY(notifier, list_entry); + ++ notifier->mem_ctx = mem_ctx; + notifier->object = object; + return notifier; +} @@ -33183,30 +40233,36 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-rp +static void free_notifier(notifier_t *notifier) +{ + observer_t *observer; ++ + DWC_CIRCLEQ_FOREACH(observer, ¬ifier->observers, list_entry) { -+ free_observer(observer); ++ free_observer(notifier->mem_ctx, observer); + } -+ DWC_FREE(notifier); ++ ++ dwc_free(notifier->mem_ctx, notifier); +} + +static notifier_t *find_notifier(void *object) +{ + notifier_t *notifier; ++ ++ DWC_ASSERT(manager, "Notification manager not found"); ++ + if (!object) { + return NULL; + } -+ DWC_ASSERT(manager, "Notification manager not found"); ++ + DWC_CIRCLEQ_FOREACH(notifier, &manager->notifiers, list_entry) { + if (notifier->object == object) { + return notifier; + } + } ++ + return NULL; +} + -+void dwc_alloc_notification_manager(void) ++int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx) +{ -+ create_manager(); ++ return create_manager(mem_ctx, wkq_ctx); +} + +void dwc_free_notification_manager(void) @@ -33214,18 +40270,24 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-rp + free_manager(); +} + -+dwc_notifier_t *dwc_register_notifier(void *object) ++dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object) +{ -+ notifier_t *notifier = find_notifier(object); ++ notifier_t *notifier; ++ + DWC_ASSERT(manager, "Notification manager not found"); ++ ++ notifier = find_notifier(object); + if (notifier) { -+ DWC_ERROR("Notifier %p is already registered", object); ++ DWC_ERROR("Notifier %p is already registered\n", object); + return NULL; + } + -+ notifier = alloc_notifier(object); -+ DWC_CIRCLEQ_INSERT_TAIL(&manager->notifiers, notifier, list_entry); ++ notifier = alloc_notifier(mem_ctx, object); ++ if (!notifier) { ++ return NULL; ++ } + ++ DWC_CIRCLEQ_INSERT_TAIL(&manager->notifiers, notifier, list_entry); + + DWC_INFO("Notifier %p registered", object); + dump_manager(); @@ -33236,13 +40298,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-rp +void dwc_unregister_notifier(dwc_notifier_t *notifier) +{ + DWC_ASSERT(manager, "Notification manager not found"); ++ + if (!DWC_CIRCLEQ_EMPTY(¬ifier->observers)) { + observer_t *o; -+ DWC_ERROR("Notifier %p has active observers when removing", notifier->object); ++ ++ DWC_ERROR("Notifier %p has active observers when removing\n", notifier->object); + DWC_CIRCLEQ_FOREACH(o, ¬ifier->observers, list_entry) { -+ DWC_DEBUG(" %p watching %s", o->observer, o->notification); ++ DWC_DEBUGC(" %p watching %s\n", o->observer, o->notification); + } -+ DWC_ASSERT(DWC_CIRCLEQ_EMPTY(¬ifier->observers), "Notifier %p has active observers when removing", notifier); ++ ++ DWC_ASSERT(DWC_CIRCLEQ_EMPTY(¬ifier->observers), ++ "Notifier %p has active observers when removing", notifier); + } + + DWC_CIRCLEQ_REMOVE_INIT(&manager->notifiers, notifier, list_entry); @@ -33253,16 +40319,21 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-rp +} + +/* Add an observer to observe the notifier for a particular state, event, or notification. */ -+int dwc_add_observer(void *observer, void *object, char *notification, dwc_notifier_callback_t callback, void *data) ++int dwc_add_observer(void *observer, void *object, char *notification, ++ dwc_notifier_callback_t callback, void *data) +{ + notifier_t *notifier = find_notifier(object); + observer_t *new_observer; ++ + if (!notifier) { -+ DWC_ERROR("Notifier %p is not found when adding observer", object); -+ return -1; ++ DWC_ERROR("Notifier %p is not found when adding observer\n", object); ++ return -DWC_E_INVALID; + } + -+ new_observer = alloc_observer(observer, notification, callback, data); ++ new_observer = alloc_observer(notifier->mem_ctx, observer, notification, callback, data); ++ if (!new_observer) { ++ return -DWC_E_NO_MEMORY; ++ } + + DWC_CIRCLEQ_INSERT_TAIL(¬ifier->observers, new_observer, list_entry); + @@ -33276,16 +40347,19 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-rp +int dwc_remove_observer(void *observer) +{ + notifier_t *n; ++ + DWC_ASSERT(manager, "Notification manager not found"); ++ + DWC_CIRCLEQ_FOREACH(n, &manager->notifiers, list_entry) { + observer_t *o; + observer_t *o2; ++ + DWC_CIRCLEQ_FOREACH_SAFE(o, o2, &n->observers, list_entry) { + if (o->observer == observer) { + DWC_CIRCLEQ_REMOVE_INIT(&n->observers, o, list_entry); + DWC_INFO("Removing observer %p from notifier %p watching notification %s:", + o->observer, n->object, o->notification); -+ free_observer(o); ++ free_observer(n->mem_ctx, o); + } + } + } @@ -33294,42 +40368,53 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-rp + return 0; +} + -+typedef struct callback_data -+{ ++typedef struct callback_data { ++ void *mem_ctx; + dwc_notifier_callback_t cb; + void *observer; + void *data; + void *object; -+ void *notification; ++ char *notification; + void *notification_data; +} cb_data_t; + +static void cb_task(void *data) +{ + cb_data_t *cb = (cb_data_t *)data; ++ + cb->cb(cb->object, cb->notification, cb->observer, cb->notification_data, cb->data); -+ DWC_FREE(cb); ++ dwc_free(cb->mem_ctx, cb); +} + +void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data) +{ + observer_t *o; ++ + DWC_ASSERT(manager, "Notification manager not found"); ++ + DWC_CIRCLEQ_FOREACH(o, ¬ifier->observers, list_entry) { + int len = DWC_STRLEN(notification); ++ + if (DWC_STRLEN(o->notification) != len) { + continue; + } + + if (DWC_STRNCMP(o->notification, notification, len) == 0) { -+ cb_data_t *cb_data = DWC_ALLOC(sizeof(cb_data_t)); ++ cb_data_t *cb_data = dwc_alloc(notifier->mem_ctx, sizeof(cb_data_t)); ++ ++ if (!cb_data) { ++ DWC_ERROR("Failed to allocate callback data\n"); ++ return; ++ } ++ ++ cb_data->mem_ctx = notifier->mem_ctx; + cb_data->cb = o->callback; + cb_data->observer = o->observer; + cb_data->data = o->data; + cb_data->object = notifier->object; + cb_data->notification = notification; + cb_data->notification_data = notification_data; -+ DWC_DEBUG("Observer found %p for notification %s", o->observer, notification); ++ DWC_DEBUGC("Observer found %p for notification %s\n", o->observer, notification); + DWC_WORKQ_SCHEDULE(manager->wq, cb_task, cb_data, + "Notify callback from %p for Notification %s, to observer %p", + cb_data->object, notification, cb_data->observer); @@ -33337,14 +40422,21 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.c linux-rp + } +} + -diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.h linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.h ---- linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.h 2012-07-15 20:29:18.989081834 +0200 -@@ -0,0 +1,112 @@ ++#endif /* DWC_NOTIFYLIB */ +diff --git a/drivers/usb/host/dwc_common_port/dwc_notifier.h b/drivers/usb/host/dwc_common_port/dwc_notifier.h +new file mode 100644 +index 0000000..4a8cdfe +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_notifier.h +@@ -0,0 +1,122 @@ + +#ifndef __DWC_NOTIFIER_H__ +#define __DWC_NOTIFIER_H__ + ++#ifdef __cplusplus ++extern "C" { ++#endif ++ +#include "dwc_os.h" + +/** @file @@ -33409,21 +40501,22 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.h linux-rp + * the documentation of the observable module with the notifications. + * @param user_data This is any custom data that the observer provided when + * adding itself as an observer to the notification. */ -+typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer, void *notification_data, void *user_data); ++typedef void (*dwc_notifier_callback_t)(void *object, char *notification, void *observer, ++ void *notification_data, void *user_data); + +/** Brings up the notification manager. */ -+extern void dwc_alloc_notification_manager(void); ++extern int dwc_alloc_notification_manager(void *mem_ctx, void *wkq_ctx); +/** Brings down the notification manager. */ +extern void dwc_free_notification_manager(void); + -+/** This function register an observable module. A dwc_notifier_t object is ++/** This function registers an observable module. A dwc_notifier_t object is + * returned to the observable module. This is an opaque object that is used by + * the observable module to trigger notifications. This object should only be + * accessible to functions that are authorized to trigger notifications for this + * module. Observers do not need this object. */ -+extern dwc_notifier_t *dwc_register_notifier(void *object); ++extern dwc_notifier_t *dwc_register_notifier(void *mem_ctx, void *object); + -+/** This function unregister an observable module. All observers have to be ++/** This function unregisters an observable module. All observers have to be + * removed prior to unregistration. */ +extern void dwc_unregister_notifier(dwc_notifier_t *notifier); + @@ -33435,7 +40528,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.h linux-rp + * @param notification The notification to observe + * @param callback The callback function to call + * @param user_data Any additional user data to pass into the callback function */ -+extern int dwc_add_observer(void *observer, void *object, char *notification, dwc_notifier_callback_t callback, void *user_data); ++extern int dwc_add_observer(void *observer, void *object, char *notification, ++ dwc_notifier_callback_t callback, void *user_data); + +/** Removes the specified observer from all notifications that it is currently + * observing. */ @@ -33452,16 +40546,22 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_notifier.h linux-rp + */ +void dwc_notify(dwc_notifier_t *notifier, char *notification, void *notification_data); + ++#ifdef __cplusplus ++} ++#endif ++ +#endif /* __DWC_NOTIFIER_H__ */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h ---- linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h 2012-07-15 20:29:18.989081834 +0200 -@@ -0,0 +1,925 @@ +diff --git a/drivers/usb/host/dwc_common_port/dwc_os.h b/drivers/usb/host/dwc_common_port/dwc_os.h +new file mode 100644 +index 0000000..308ddd5 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/dwc_os.h +@@ -0,0 +1,1260 @@ +/* ========================================================================= -+ * $File: //dwh/usb_iip/dev/software/dwc_common_port/dwc_os.h $ -+ * $Revision: #2 $ -+ * $Date: 2009/04/02 $ -+ * $Change: 1224130 $ ++ * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_os.h $ ++ * $Revision: #14 $ ++ * $Date: 2010/11/04 $ ++ * $Change: 1621695 $ + * + * Synopsys Portability Library Software and documentation + * (hereinafter, "Software") is an Unsupported proprietary work of @@ -33495,6 +40595,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot +#ifndef _DWC_OS_H_ +#define _DWC_OS_H_ + ++#ifdef __cplusplus ++extern "C" { ++#endif ++ +/** @file + * + * DWC portability library, low level os-wrapper functions @@ -33510,12 +40614,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + */ + +#ifdef DWC_LINUX -+# include -+# ifdef CONFIG_DEBUG_MUTEXES -+# include -+# endif -+#else -+# include ++# include ++# ifdef CONFIG_DEBUG_MUTEXES ++# include ++# endif ++# include ++# include ++#endif ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++# include +#endif + + @@ -33526,29 +40634,58 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot +#define YES 1 +#define NO 0 + -+/** @todo make them positive and return the negative error code */ ++#ifdef DWC_LINUX ++ +/** @name Error Codes */ -+#define DWC_E_INVALID 1001 -+#define DWC_E_NO_MEMORY 1002 -+#define DWC_E_NO_DEVICE 1003 -+#define DWC_E_NOT_SUPPORTED 1004 -+#define DWC_E_TIMEOUT 1005 -+#define DWC_E_BUSY 1006 -+#define DWC_E_AGAIN 1007 -+#define DWC_E_RESTART 1008 -+#define DWC_E_ABORT 1009 -+#define DWC_E_SHUTDOWN 1010 -+#define DWC_E_NO_DATA 1011 -+#define DWC_E_DISCONNECT 2000 -+#define DWC_E_UNKNOWN 3000 -+#define DWC_E_NO_STREAM_RES 4001 -+#define DWC_E_COMMUNICATION 4002 -+#define DWC_E_OVERFLOW 4003 -+#define DWC_E_PROTOCOL 4004 -+#define DWC_E_IN_PROGRESS 4005 -+#define DWC_E_PIPE 4006 -+#define DWC_E_IO 4007 -+#define DWC_E_NO_SPACE 4008 ++#define DWC_E_INVALID EINVAL ++#define DWC_E_NO_MEMORY ENOMEM ++#define DWC_E_NO_DEVICE ENODEV ++#define DWC_E_NOT_SUPPORTED EOPNOTSUPP ++#define DWC_E_TIMEOUT ETIMEDOUT ++#define DWC_E_BUSY EBUSY ++#define DWC_E_AGAIN EAGAIN ++#define DWC_E_RESTART ERESTART ++#define DWC_E_ABORT ECONNABORTED ++#define DWC_E_SHUTDOWN ESHUTDOWN ++#define DWC_E_NO_DATA ENODATA ++#define DWC_E_DISCONNECT ECONNRESET ++#define DWC_E_UNKNOWN EINVAL ++#define DWC_E_NO_STREAM_RES ENOSR ++#define DWC_E_COMMUNICATION ECOMM ++#define DWC_E_OVERFLOW EOVERFLOW ++#define DWC_E_PROTOCOL EPROTO ++#define DWC_E_IN_PROGRESS EINPROGRESS ++#define DWC_E_PIPE EPIPE ++#define DWC_E_IO EIO ++#define DWC_E_NO_SPACE ENOSPC ++ ++#else ++ ++/** @name Error Codes */ ++#define DWC_E_INVALID 1001 ++#define DWC_E_NO_MEMORY 1002 ++#define DWC_E_NO_DEVICE 1003 ++#define DWC_E_NOT_SUPPORTED 1004 ++#define DWC_E_TIMEOUT 1005 ++#define DWC_E_BUSY 1006 ++#define DWC_E_AGAIN 1007 ++#define DWC_E_RESTART 1008 ++#define DWC_E_ABORT 1009 ++#define DWC_E_SHUTDOWN 1010 ++#define DWC_E_NO_DATA 1011 ++#define DWC_E_DISCONNECT 2000 ++#define DWC_E_UNKNOWN 3000 ++#define DWC_E_NO_STREAM_RES 4001 ++#define DWC_E_COMMUNICATION 4002 ++#define DWC_E_OVERFLOW 4003 ++#define DWC_E_PROTOCOL 4004 ++#define DWC_E_IN_PROGRESS 4005 ++#define DWC_E_PIPE 4006 ++#define DWC_E_IO 4007 ++#define DWC_E_NO_SPACE 4008 ++ ++#endif ++ + +/** @name Tracing/Logging Functions + * @@ -33559,8 +40696,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + * expensive on your system. By default undefining the DEBUG macro already + * no-ops some of these functions. */ + -+#include -+ +/** Returns non-zero if in interrupt context. */ +extern dwc_bool_t DWC_IN_IRQ(void); +#define dwc_in_irq DWC_IN_IRQ @@ -33570,6 +40705,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + return DWC_IN_IRQ() ? "IRQ" : ""; +} + ++/** Returns non-zero if in bottom-half context. */ ++extern dwc_bool_t DWC_IN_BH(void); ++#define dwc_in_bh DWC_IN_BH ++ ++/** Returns "BH" if DWC_IN_BH is true. */ ++static inline char *dwc_bh(void) { ++ return DWC_IN_BH() ? "BH" : ""; ++} ++ +/** + * A vprintf() clone. Just call vprintf if you've got it. + */ @@ -33591,7 +40735,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot +#ifdef __GNUC__ + __attribute__ ((format(printf, 1, 2))); +#else -+ ; ++ ; +#endif +#define dwc_printf DWC_PRINTF + @@ -33600,9 +40744,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + */ +extern int DWC_SPRINTF(char *string, char *format, ...) +#ifdef __GNUC__ -+ __attribute__ ((format(printf, 2, 3))); ++ __attribute__ ((format(printf, 2, 3))); +#else -+ ; ++ ; +#endif +#define dwc_sprintf DWC_SPRINTF + @@ -33611,9 +40755,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + */ +extern int DWC_SNPRINTF(char *string, int size, char *format, ...) +#ifdef __GNUC__ -+ __attribute__ ((format(printf, 3, 4))); ++ __attribute__ ((format(printf, 3, 4))); +#else -+ ; ++ ; +#endif +#define dwc_snprintf DWC_SNPRINTF + @@ -33626,23 +40770,23 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + */ +extern void __DWC_WARN(char *format, ...) +#ifdef __GNUC__ -+ __attribute__ ((format(printf, 1, 2))); ++ __attribute__ ((format(printf, 1, 2))); +#else -+ ; ++ ; +#endif + +/** + * Prints an error message. On systems that don't differentiate between errors + * and regular log messages, just print it. Indicates that something went wrong -+ * with the driver, but it can be recovered from. Works like printf(). ++ * with the driver. Works like printf(). + * + * Use the DWC_ERROR macro to call this function. + */ +extern void __DWC_ERROR(char *format, ...) +#ifdef __GNUC__ -+ __attribute__ ((format(printf, 1, 2))); ++ __attribute__ ((format(printf, 1, 2))); +#else -+ ; ++ ; +#endif + +/** @@ -33655,12 +40799,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + */ +extern void DWC_EXCEPTION(char *format, ...) +#ifdef __GNUC__ -+ __attribute__ ((format(printf, 1, 2))); ++ __attribute__ ((format(printf, 1, 2))); +#else -+ ; ++ ; +#endif +#define dwc_exception DWC_EXCEPTION + ++#ifndef DWC_OTG_DEBUG_LEV ++#define DWC_OTG_DEBUG_LEV 0 ++#endif ++ +#ifdef DEBUG +/** + * Prints out a debug message. Used for logging/trace messages. @@ -33669,120 +40817,203 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + */ +extern void __DWC_DEBUG(char *format, ...) +#ifdef __GNUC__ -+ __attribute__ ((format(printf, 1, 2))); ++ __attribute__ ((format(printf, 1, 2))); +#else -+ ; ++ ; +#endif +#else +#define __DWC_DEBUG printk -+#include +#endif + +/** + * Prints out a Debug message. + */ -+#define DWC_DEBUG(_format, _args...) __DWC_DEBUG("DEBUG:%s:%s: " _format "\n", __func__, dwc_irq(), ## _args) ++#define DWC_DEBUG(_format, _args...) __DWC_DEBUG("DEBUG:%s:%s: " _format "\n", \ ++ __func__, dwc_irq(), ## _args) +#define dwc_debug DWC_DEBUG +/** ++ * Prints out a Debug message if enabled at compile time. ++ */ ++#if DWC_OTG_DEBUG_LEV > 0 ++#define DWC_DEBUGC(_format, _args...) DWC_DEBUG(_format, ##_args ) ++#else ++#define DWC_DEBUGC(_format, _args...) ++#endif ++#define dwc_debugc DWC_DEBUGC ++/** + * Prints out an informative message. + */ -+#define DWC_INFO(_format, _args...) DWC_PRINTF("INFO:%s: " _format "\n", dwc_irq(), ## _args) ++#define DWC_INFO(_format, _args...) DWC_PRINTF("INFO:%s: " _format "\n", \ ++ dwc_irq(), ## _args) +#define dwc_info DWC_INFO +/** ++ * Prints out an informative message if enabled at compile time. ++ */ ++#if DWC_OTG_DEBUG_LEV > 1 ++#define DWC_INFOC(_format, _args...) DWC_INFO(_format, ##_args ) ++#else ++#define DWC_INFOC(_format, _args...) ++#endif ++#define dwc_infoc DWC_INFOC ++/** + * Prints out a warning message. + */ -+#define DWC_WARN(_format, _args...) __DWC_WARN("WARN:%s:%s:%d: " _format "\n", dwc_irq(), __func__, __LINE__, ## _args) ++#define DWC_WARN(_format, _args...) __DWC_WARN("WARN:%s:%s:%d: " _format "\n", \ ++ dwc_irq(), __func__, __LINE__, ## _args) +#define dwc_warn DWC_WARN +/** + * Prints out an error message. + */ -+#define DWC_ERROR(_format, _args...) __DWC_ERROR("ERROR:%s:%s:%d: " _format "\n", dwc_irq(), __func__, __LINE__, ## _args) ++#define DWC_ERROR(_format, _args...) __DWC_ERROR("ERROR:%s:%s:%d: " _format "\n", \ ++ dwc_irq(), __func__, __LINE__, ## _args) +#define dwc_error DWC_ERROR + -+#define DWC_PROTO_ERROR(_format, _args...) __DWC_WARN("ERROR:%s:%s:%d: " _format "\n", dwc_irq(), __func__, __LINE__, ## _args) ++#define DWC_PROTO_ERROR(_format, _args...) __DWC_WARN("ERROR:%s:%s:%d: " _format "\n", \ ++ dwc_irq(), __func__, __LINE__, ## _args) +#define dwc_proto_error DWC_PROTO_ERROR + +#ifdef DEBUG +/** Prints out a exception error message if the _expr expression fails. Disabled + * if DEBUG is not enabled. */ -+#define DWC_ASSERT(_expr, _format, _args...) if (!(_expr)) { DWC_EXCEPTION("%s:%s:%d: " _format "\n", dwc_irq(), __FILE__, __LINE__, ## _args); } ++#define DWC_ASSERT(_expr, _format, _args...) do { \ ++ if (!(_expr)) { DWC_EXCEPTION("%s:%s:%d: " _format "\n", dwc_irq(), \ ++ __FILE__, __LINE__, ## _args); } \ ++ } while (0) +#else +#define DWC_ASSERT(_x...) +#endif +#define dwc_assert DWC_ASSERT + -+/** @name Byter Ordering ++ ++/** @name Byte Ordering + * The following functions are for conversions between processor's byte ordering + * and specific ordering you want. + */ + +/** Converts 32 bit data in CPU byte ordering to little endian. */ -+extern uint32_t DWC_CPU_TO_LE32(void *p); ++extern uint32_t DWC_CPU_TO_LE32(uint32_t *p); +#define dwc_cpu_to_le32 DWC_CPU_TO_LE32 ++ +/** Converts 32 bit data in CPU byte orderint to big endian. */ -+extern uint32_t DWC_CPU_TO_BE32(void *p); ++extern uint32_t DWC_CPU_TO_BE32(uint32_t *p); +#define dwc_cpu_to_be32 DWC_CPU_TO_BE32 + +/** Converts 32 bit little endian data to CPU byte ordering. */ -+extern uint32_t DWC_LE32_TO_CPU(void *p); ++extern uint32_t DWC_LE32_TO_CPU(uint32_t *p); +#define dwc_le32_to_cpu DWC_LE32_TO_CPU ++ +/** Converts 32 bit big endian data to CPU byte ordering. */ -+extern uint32_t DWC_BE32_TO_CPU(void *p); ++extern uint32_t DWC_BE32_TO_CPU(uint32_t *p); +#define dwc_be32_to_cpu DWC_BE32_TO_CPU + +/** Converts 16 bit data in CPU byte ordering to little endian. */ -+extern uint16_t DWC_CPU_TO_LE16(void *p); ++extern uint16_t DWC_CPU_TO_LE16(uint16_t *p); +#define dwc_cpu_to_le16 DWC_CPU_TO_LE16 ++ +/** Converts 16 bit data in CPU byte orderint to big endian. */ -+extern uint16_t DWC_CPU_TO_BE16(void *p); ++extern uint16_t DWC_CPU_TO_BE16(uint16_t *p); +#define dwc_cpu_to_be16 DWC_CPU_TO_BE16 + +/** Converts 16 bit little endian data to CPU byte ordering. */ -+extern uint16_t DWC_LE16_TO_CPU(void *p); ++extern uint16_t DWC_LE16_TO_CPU(uint16_t *p); +#define dwc_le16_to_cpu DWC_LE16_TO_CPU ++ +/** Converts 16 bit bi endian data to CPU byte ordering. */ -+extern uint16_t DWC_BE16_TO_CPU(void *p); ++extern uint16_t DWC_BE16_TO_CPU(uint16_t *p); +#define dwc_be16_to_cpu DWC_BE16_TO_CPU + ++ +/** @name Register Read/Write + * -+ * The following five functions should be implemented to read/write registers of ++ * The following six functions should be implemented to read/write registers of + * 32-bit and 64-bit sizes. All modules use this to read/write register values. + * The reg value is a pointer to the register calculated from the void *base + * variable passed into the driver when it is started. */ + ++#ifdef DWC_LINUX ++/* Linux doesn't need any extra parameters for register read/write, so we ++ * just throw away the IO context parameter. ++ */ +/** Reads the content of a 32-bit register. */ +extern uint32_t DWC_READ_REG32(uint32_t volatile *reg); -+#define dwc_read_reg32 DWC_READ_REG32 ++#define dwc_read_reg32(_ctx_,_reg_) DWC_READ_REG32(_reg_) ++ +/** Reads the content of a 64-bit register. */ +extern uint64_t DWC_READ_REG64(uint64_t volatile *reg); -+#define dwc_read_reg64 DWC_READ_REG64 ++#define dwc_read_reg64(_ctx_,_reg_) DWC_READ_REG64(_reg_) ++ +/** Writes to a 32-bit register. */ +extern void DWC_WRITE_REG32(uint32_t volatile *reg, uint32_t value); -+#define dwc_write_reg32 DWC_WRITE_REG32 ++#define dwc_write_reg32(_ctx_,_reg_,_val_) DWC_WRITE_REG32(_reg_, _val_) ++ +/** Writes to a 64-bit register. */ +extern void DWC_WRITE_REG64(uint64_t volatile *reg, uint64_t value); -+#define dwc_write_reg64 DWC_WRITE_REG64 -+/** ++#define dwc_write_reg64(_ctx_,_reg_,_val_) DWC_WRITE_REG64(_reg_, _val_) ++ ++/** + * Modify bit values in a register. Using the + * algorithm: (reg_contents & ~clear_mask) | set_mask. + */ +extern void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask); ++#define dwc_modify_reg32(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG32(_reg_,_cmsk_,_smsk_) ++extern void DWC_MODIFY_REG64(uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask); ++#define dwc_modify_reg64(_ctx_,_reg_,_cmsk_,_smsk_) DWC_MODIFY_REG64(_reg_,_cmsk_,_smsk_) ++ ++#endif /* DWC_LINUX */ ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++typedef struct dwc_ioctx { ++ struct device *dev; ++ bus_space_tag_t iot; ++ bus_space_handle_t ioh; ++} dwc_ioctx_t; ++ ++/** BSD needs two extra parameters for register read/write, so we pass ++ * them in using the IO context parameter. ++ */ ++/** Reads the content of a 32-bit register. */ ++extern uint32_t DWC_READ_REG32(void *io_ctx, uint32_t volatile *reg); ++#define dwc_read_reg32 DWC_READ_REG32 ++ ++/** Reads the content of a 64-bit register. */ ++extern uint64_t DWC_READ_REG64(void *io_ctx, uint64_t volatile *reg); ++#define dwc_read_reg64 DWC_READ_REG64 ++ ++/** Writes to a 32-bit register. */ ++extern void DWC_WRITE_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t value); ++#define dwc_write_reg32 DWC_WRITE_REG32 ++ ++/** Writes to a 64-bit register. */ ++extern void DWC_WRITE_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t value); ++#define dwc_write_reg64 DWC_WRITE_REG64 ++ ++/** ++ * Modify bit values in a register. Using the ++ * algorithm: (reg_contents & ~clear_mask) | set_mask. ++ */ ++extern void DWC_MODIFY_REG32(void *io_ctx, uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask); +#define dwc_modify_reg32 DWC_MODIFY_REG32 ++extern void DWC_MODIFY_REG64(void *io_ctx, uint64_t volatile *reg, uint64_t clear_mask, uint64_t set_mask); ++#define dwc_modify_reg64 DWC_MODIFY_REG64 ++ ++#endif /* DWC_FREEBSD || DWC_NETBSD */ + +/** @cond */ + -+/** @name Some convenience MACROS used internally. Define DEBUG_REGS to log the ++/** @name Some convenience MACROS used internally. Define DWC_DEBUG_REGS to log the + * register writes. */ + -+#ifdef DEBUG_REGS ++#ifdef DWC_LINUX ++ ++# ifdef DWC_DEBUG_REGS + +#define dwc_define_read_write_reg_n(_reg,_container_type) \ +static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \ + return DWC_READ_REG32(&container->regs->_reg[num]); \ +} \ +static inline void dwc_write_##_reg##_n(_container_type *container, int num, uint32_t data) { \ -+ DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, &(((uint32_t*)container->regs->_reg)[num]), data); \ ++ DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \ ++ &(((uint32_t*)container->regs->_reg)[num]), data); \ + DWC_WRITE_REG32(&(((uint32_t*)container->regs->_reg)[num]), data); \ +} + @@ -33791,11 +41022,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + return DWC_READ_REG32(&container->regs->_reg); \ +} \ +static inline void dwc_write_##_reg(_container_type *container, uint32_t data) { \ -+ DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \ ++ DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \ + DWC_WRITE_REG32(&container->regs->_reg, data); \ +} + -+#else ++# else /* DWC_DEBUG_REGS */ + +#define dwc_define_read_write_reg_n(_reg,_container_type) \ +static inline uint32_t dwc_read_##_reg##_n(_container_type *container, int num) { \ @@ -33813,11 +41044,59 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + DWC_WRITE_REG32(&container->regs->_reg, data); \ +} + -+#endif ++# endif /* DWC_DEBUG_REGS */ ++ ++#endif /* DWC_LINUX */ ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++ ++# ifdef DWC_DEBUG_REGS ++ ++#define dwc_define_read_write_reg_n(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \ ++ return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \ ++} \ ++static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \ ++ DWC_DEBUG("WRITING %8s[%d]: %p: %08x", #_reg, num, \ ++ &(((uint32_t*)container->regs->_reg)[num]), data); \ ++ DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \ ++} ++ ++#define dwc_define_read_write_reg(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \ ++ return DWC_READ_REG32(io_ctx, &container->regs->_reg); \ ++} \ ++static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \ ++ DWC_DEBUG("WRITING %11s: %p: %08x", #_reg, &container->regs->_reg, data); \ ++ DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \ ++} ++ ++# else /* DWC_DEBUG_REGS */ ++ ++#define dwc_define_read_write_reg_n(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg##_n(void *io_ctx, _container_type *container, int num) { \ ++ return DWC_READ_REG32(io_ctx, &container->regs->_reg[num]); \ ++} \ ++static inline void dwc_write_##_reg##_n(void *io_ctx, _container_type *container, int num, uint32_t data) { \ ++ DWC_WRITE_REG32(io_ctx, &(((uint32_t*)container->regs->_reg)[num]), data); \ ++} ++ ++#define dwc_define_read_write_reg(_reg,_container_type) \ ++static inline uint32_t dwc_read_##_reg(void *io_ctx, _container_type *container) { \ ++ return DWC_READ_REG32(io_ctx, &container->regs->_reg); \ ++} \ ++static inline void dwc_write_##_reg(void *io_ctx, _container_type *container, uint32_t data) { \ ++ DWC_WRITE_REG32(io_ctx, &container->regs->_reg, data); \ ++} ++ ++# endif /* DWC_DEBUG_REGS */ ++ ++#endif /* DWC_FREEBSD || DWC_NETBSD */ + +/** @endcond */ + + ++#ifdef DWC_CRYPTOLIB +/** @name Crypto Functions + * + * These are the low-level cryptographic functions used by the driver. */ @@ -33825,16 +41104,21 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot +/** Perform AES CBC */ +extern int DWC_AES_CBC(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t iv[16], uint8_t *out); +#define dwc_aes_cbc DWC_AES_CBC ++ +/** Fill the provided buffer with random bytes. These should be cryptographic grade random numbers. */ +extern void DWC_RANDOM_BYTES(uint8_t *buffer, uint32_t length); +#define dwc_random_bytes DWC_RANDOM_BYTES ++ +/** Perform the SHA-256 hash function */ +extern int DWC_SHA256(uint8_t *message, uint32_t len, uint8_t *out); +#define dwc_sha256 DWC_SHA256 ++ +/** Calculated the HMAC-SHA256 */ +extern int DWC_HMAC_SHA256(uint8_t *message, uint32_t messagelen, uint8_t *key, uint32_t keylen, uint8_t *out); +#define dwc_hmac_sha256 DWC_HMAC_SHA256 + ++#endif /* DWC_CRYPTOLIB */ ++ + +/** @name Memory Allocation + * @@ -33843,7 +41127,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + * of the memory debugging routines need to be implemented. The allocation + * routines all ZERO the contents of the memory. + * -+ * Defining DEBUG_MEMORY turns on memory debugging and statistic gathering. ++ * Defining DWC_DEBUG_MEMORY turns on memory debugging and statistic gathering. + * This checks for memory leaks, keeping track of alloc/free pairs. It also + * keeps track of how much memory the driver is using at any given time. */ + @@ -33853,9 +41137,38 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + +#define DWC_INVALID_DMA_ADDR 0x0 + -+typedef uint32_t dwc_dma_t; ++#ifdef DWC_LINUX ++/** Type for a DMA address */ ++typedef dma_addr_t dwc_dma_t; ++#endif + -+/** @todo these functions will be added in the future */ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++typedef bus_addr_t dwc_dma_t; ++#endif ++ ++#ifdef DWC_FREEBSD ++typedef struct dwc_dmactx { ++ struct device *dev; ++ bus_dma_tag_t dma_tag; ++ bus_dmamap_t dma_map; ++ bus_addr_t dma_paddr; ++ void *dma_vaddr; ++} dwc_dmactx_t; ++#endif ++ ++#ifdef DWC_NETBSD ++typedef struct dwc_dmactx { ++ struct device *dev; ++ bus_dma_tag_t dma_tag; ++ bus_dmamap_t dma_map; ++ bus_dma_segment_t segs[1]; ++ int nsegs; ++ bus_addr_t dma_paddr; ++ void *dma_vaddr; ++} dwc_dmactx_t; ++#endif ++ ++/* @todo these functions will be added in the future */ +#if 0 +/** + * Creates a DMA pool from which you can allocate DMA buffers. Buffers @@ -33875,79 +41188,121 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + * when you are done with it. + */ +extern dwc_pool_t *DWC_DMA_POOL_CREATE(uint32_t size, uint32_t align, uint32_t boundary); ++ +/** + * Destroy a DMA pool. All buffers allocated from that pool must be freed first. + */ +extern void DWC_DMA_POOL_DESTROY(dwc_pool_t *pool); ++ +/** + * Allocate a buffer from the specified DMA pool and zeros its contents. + */ +extern void *DWC_DMA_POOL_ALLOC(dwc_pool_t *pool, uint64_t *dma_addr); ++ +/** + * Free a previously allocated buffer from the DMA pool. + */ +extern void DWC_DMA_POOL_FREE(dwc_pool_t *pool, void *vaddr, void *daddr); +#endif + -+ +/** Allocates a DMA capable buffer and zeroes its contents. */ -+extern void *__DWC_DMA_ALLOC(uint32_t size, dwc_dma_t *dma_addr); ++extern void *__DWC_DMA_ALLOC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr); + +/** Allocates a DMA capable buffer and zeroes its contents in atomic contest */ -+extern void *__DWC_DMA_ALLOC_ATOMIC(uint32_t size, dwc_dma_t *dma_addr); ++extern void *__DWC_DMA_ALLOC_ATOMIC(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr); + -+/** Frees a previosly allocated buffer. */ -+extern void __DWC_DMA_FREE(uint32_t size, void *virt_addr, dwc_dma_t dma_addr); ++/** Frees a previously allocated buffer. */ ++extern void __DWC_DMA_FREE(void *dma_ctx, uint32_t size, void *virt_addr, dwc_dma_t dma_addr); + +/** Allocates a block of memory and zeroes its contents. */ -+extern void *__DWC_ALLOC(uint32_t size); ++extern void *__DWC_ALLOC(void *mem_ctx, uint32_t size); + +/** Allocates a block of memory and zeroes its contents, in an atomic manner + * which can be used inside interrupt context. The size should be sufficiently + * small, a few KB at most, such that failures are not likely to occur. Can just call + * __DWC_ALLOC if it is atomic. */ -+extern void *__DWC_ALLOC_ATOMIC(uint32_t size); ++extern void *__DWC_ALLOC_ATOMIC(void *mem_ctx, uint32_t size); + +/** Frees a previously allocated buffer. */ -+extern void __DWC_FREE(void *addr); ++extern void __DWC_FREE(void *mem_ctx, void *addr); + -+#ifndef DEBUG_MEMORY ++#ifndef DWC_DEBUG_MEMORY + -+#define DWC_ALLOC(_size_) __DWC_ALLOC(_size_) -+#define DWC_ALLOC_ATOMIC(_size_) __DWC_ALLOC_ATOMIC(_size_) -+#define DWC_FREE(_addr_) __DWC_FREE(_addr_) -+#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(_size_,_dma_) -+#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) -+#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(_size_,_virt_,_dma_) ++#define DWC_ALLOC(_size_) __DWC_ALLOC(NULL, _size_) ++#define DWC_ALLOC_ATOMIC(_size_) __DWC_ALLOC_ATOMIC(NULL, _size_) ++#define DWC_FREE(_addr_) __DWC_FREE(NULL, _addr_) + -+#else ++# ifdef DWC_LINUX ++#define DWC_DMA_ALLOC(_size_,_dma_) __DWC_DMA_ALLOC(NULL, _size_, _dma_) ++#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) __DWC_DMA_ALLOC_ATOMIC(NULL, _size_,_dma_) ++#define DWC_DMA_FREE(_size_,_virt_,_dma_) __DWC_DMA_FREE(NULL, _size_, _virt_, _dma_) ++# endif + -+extern void *dwc_alloc_debug(uint32_t size, char const *func, int line); -+extern void *dwc_alloc_atomic_debug(uint32_t size, char const *func, int line); -+extern void dwc_free_debug(void *addr, char const *func, int line); -+extern void *dwc_dma_alloc_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line); ++# if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++#define DWC_DMA_ALLOC __DWC_DMA_ALLOC ++#define DWC_DMA_FREE __DWC_DMA_FREE ++# endif +extern void *dwc_dma_alloc_atomic_debug(uint32_t size, dwc_dma_t *dma_addr, char const *func, int line); -+extern void dwc_dma_free_debug(uint32_t size, void *virt_addr, dwc_dma_t dma_addr, char const *func, int line); + -+extern void dwc_memory_debug_start(void); ++#else /* DWC_DEBUG_MEMORY */ ++ ++extern void *dwc_alloc_debug(void *mem_ctx, uint32_t size, char const *func, int line); ++extern void *dwc_alloc_atomic_debug(void *mem_ctx, uint32_t size, char const *func, int line); ++extern void dwc_free_debug(void *mem_ctx, void *addr, char const *func, int line); ++extern void *dwc_dma_alloc_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr, ++ char const *func, int line); ++extern void *dwc_dma_alloc_atomic_debug(void *dma_ctx, uint32_t size, dwc_dma_t *dma_addr, ++ char const *func, int line); ++extern void dwc_dma_free_debug(void *dma_ctx, uint32_t size, void *virt_addr, ++ dwc_dma_t dma_addr, char const *func, int line); ++ ++extern int dwc_memory_debug_start(void *mem_ctx); +extern void dwc_memory_debug_stop(void); +extern void dwc_memory_debug_report(void); + -+#define DWC_ALLOC(_size_) (dwc_alloc_debug(_size_, __func__, __LINE__)) -+#define DWC_ALLOC_ATOMIC(_size_) (dwc_alloc_atomic_debug(_size_, __func__, __LINE__)) -+#define DWC_FREE(_addr_) (dwc_free_debug(_addr_, __func__, __LINE__)) -+#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(_size_, _dma_, __func__, __LINE__) -+#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(_size_, _dma_, __func__, __LINE__) -+#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(_size_, _virt_, _dma_, __func__, __LINE__) ++#define DWC_ALLOC(_size_) dwc_alloc_debug(NULL, _size_, __func__, __LINE__) ++#define DWC_ALLOC_ATOMIC(_size_) dwc_alloc_atomic_debug(NULL, _size_, \ ++ __func__, __LINE__) ++#define DWC_FREE(_addr_) dwc_free_debug(NULL, _addr_, __func__, __LINE__) + -+#endif /* DEBUG_MEMORY */ ++# ifdef DWC_LINUX ++#define DWC_DMA_ALLOC(_size_,_dma_) dwc_dma_alloc_debug(NULL, _size_, \ ++ _dma_, __func__, __LINE__) ++#define DWC_DMA_ALLOC_ATOMIC(_size_,_dma_) dwc_dma_alloc_atomic_debug(NULL, _size_, \ ++ _dma_, __func__, __LINE__) ++#define DWC_DMA_FREE(_size_,_virt_,_dma_) dwc_dma_free_debug(NULL, _size_, \ ++ _virt_, _dma_, __func__, __LINE__) ++# endif + -+#define dwc_alloc DWC_ALLOC -+#define dwc_alloc_atomic DWC_ALLOC_ATOMIC -+#define dwc_free DWC_FREE ++# if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++#define DWC_DMA_ALLOC(_ctx_,_size_,_dma_) dwc_dma_alloc_debug(_ctx_, _size_, \ ++ _dma_, __func__, __LINE__) ++#define DWC_DMA_FREE(_ctx_,_size_,_virt_,_dma_) dwc_dma_free_debug(_ctx_, _size_, \ ++ _virt_, _dma_, __func__, __LINE__) ++# endif ++ ++#endif /* DWC_DEBUG_MEMORY */ ++ ++#define dwc_alloc(_ctx_,_size_) DWC_ALLOC(_size_) ++#define dwc_alloc_atomic(_ctx_,_size_) DWC_ALLOC_ATOMIC(_size_) ++#define dwc_free(_ctx_,_addr_) DWC_FREE(_addr_) ++ ++#ifdef DWC_LINUX ++/* Linux doesn't need any extra parameters for DMA buffer allocation, so we ++ * just throw away the DMA context parameter. ++ */ ++#define dwc_dma_alloc(_ctx_,_size_,_dma_) DWC_DMA_ALLOC(_size_, _dma_) ++#define dwc_dma_alloc_atomic(_ctx_,_size_,_dma_) DWC_DMA_ALLOC_ATOMIC(_size_, _dma_) ++#define dwc_dma_free(_ctx_,_size_,_virt_,_dma_) DWC_DMA_FREE(_size_, _virt_, _dma_) ++#endif ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++/** BSD needs several extra parameters for DMA buffer allocation, so we pass ++ * them in using the DMA context parameter. ++ */ +#define dwc_dma_alloc DWC_DMA_ALLOC -+#define dwc_dma_alloc_atomic DWC_DMA_ALLOC_ATOMIC +#define dwc_dma_free DWC_DMA_FREE ++#endif + + +/** @name Memory and String Processing */ @@ -33955,24 +41310,31 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot +/** memset() clone */ +extern void *DWC_MEMSET(void *dest, uint8_t byte, uint32_t size); +#define dwc_memset DWC_MEMSET ++ +/** memcpy() clone */ +extern void *DWC_MEMCPY(void *dest, void const *src, uint32_t size); +#define dwc_memcpy DWC_MEMCPY ++ +/** memmove() clone */ +extern void *DWC_MEMMOVE(void *dest, void *src, uint32_t size); +#define dwc_memmove DWC_MEMMOVE ++ +/** memcmp() clone */ +extern int DWC_MEMCMP(void *m1, void *m2, uint32_t size); +#define dwc_memcmp DWC_MEMCMP ++ +/** strcmp() clone */ +extern int DWC_STRCMP(void *s1, void *s2); +#define dwc_strcmp DWC_STRCMP ++ +/** strncmp() clone */ +extern int DWC_STRNCMP(void *s1, void *s2, uint32_t size); +#define dwc_strncmp DWC_STRNCMP ++ +/** strlen() clone, for NULL terminated ASCII strings */ +extern int DWC_STRLEN(char const *str); +#define dwc_strlen DWC_STRLEN ++ +/** strcpy() clone, for NULL terminated ASCII strings */ +extern char *DWC_STRCPY(char *to, const char *from); +#define dwc_strcpy DWC_STRCPY @@ -33982,7 +41344,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + * calling a predefined strdup. Otherwise the memory allocated by this routine + * will not be seen by the debugging routines. */ +extern char *DWC_STRDUP(char const *str); -+#define dwc_strdup DWC_STRDUP ++#define dwc_strdup(_ctx_,_str_) DWC_STRDUP(_str_) + +/** NOT an atoi() clone. Read the description carefully. Returns an integer + * converted from the string str in base 10 unless the string begins with a "0x" @@ -33994,14 +41356,19 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + * conversion are undefined. On sucess it returns 0. Overflow conditions are + * undefined. An example implementation using atoi() can be referenced from the + * Linux implementation. */ -+extern int DWC_ATOI(char *str, int32_t *value); ++extern int DWC_ATOI(const char *str, int32_t *value); +#define dwc_atoi DWC_ATOI ++ +/** Same as above but for unsigned. */ -+extern int DWC_ATOUI(char *str, uint32_t *value); ++extern int DWC_ATOUI(const char *str, uint32_t *value); +#define dwc_atoui DWC_ATOUI ++ ++#ifdef DWC_UTFLIB +/** This routine returns a UTF16LE unicode encoded string from a UTF8 string. */ +extern int DWC_UTF8_TO_UTF16LE(uint8_t const *utf8string, uint16_t *utf16string, unsigned len); +#define dwc_utf8_to_utf16le DWC_UTF8_TO_UTF16LE ++#endif ++ + +/** @name Wait queues + * @@ -34011,6 +41378,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + * unblocked and the condition will be check again. Waitqs should be triggered + * every time a condition can potentially change.*/ +struct dwc_waitq; ++ ++/** Type for a waitq */ +typedef struct dwc_waitq dwc_waitq_t; + +/** The type of waitq condition callback function. This is called every time @@ -34019,7 +41388,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + +/** Allocate a waitq */ +extern dwc_waitq_t *DWC_WAITQ_ALLOC(void); -+#define dwc_waitq_alloc DWC_WAITQ_ALLOC ++#define dwc_waitq_alloc(_ctx_) DWC_WAITQ_ALLOC() ++ +/** Free a waitq */ +extern void DWC_WAITQ_FREE(dwc_waitq_t *wq); +#define dwc_waitq_free DWC_WAITQ_FREE @@ -34027,23 +41397,28 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot +/** Check the condition and if it is false, block on the waitq. When unblocked, check the + * condition again. The function returns when the condition becomes true. The return value + * is 0 on condition true, DWC_WAITQ_ABORTED on abort or killed, or DWC_WAITQ_UNKNOWN on error. */ -+extern int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t condition, void *data); -+#define dwc_waitq_wait DWC_WAITQ_WAIT; ++extern int32_t DWC_WAITQ_WAIT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, void *data); ++#define dwc_waitq_wait DWC_WAITQ_WAIT ++ +/** Check the condition and if it is false, block on the waitq. When unblocked, + * check the condition again. The function returns when the condition become + * true or the timeout has passed. The return value is 0 on condition true or + * DWC_TIMED_OUT on timeout, or DWC_WAITQ_ABORTED, or DWC_WAITQ_UNKNOWN on + * error. */ -+extern int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t condition, void *data, int32_t msecs); ++extern int32_t DWC_WAITQ_WAIT_TIMEOUT(dwc_waitq_t *wq, dwc_waitq_condition_t cond, ++ void *data, int32_t msecs); +#define dwc_waitq_wait_timeout DWC_WAITQ_WAIT_TIMEOUT ++ +/** Trigger a waitq, unblocking all processes. This should be called whenever a condition + * has potentially changed. */ +extern void DWC_WAITQ_TRIGGER(dwc_waitq_t *wq); +#define dwc_waitq_trigger DWC_WAITQ_TRIGGER ++ +/** Unblock all processes waiting on the waitq with an ABORTED result. */ +extern void DWC_WAITQ_ABORT(dwc_waitq_t *wq); +#define dwc_waitq_abort DWC_WAITQ_ABORT + ++ +/** @name Threads + * + * A thread must be explicitly stopped. It must check DWC_THREAD_SHOULD_STOP @@ -34052,6 +41427,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + */ + +struct dwc_thread; ++ ++/** Type for a thread */ +typedef struct dwc_thread dwc_thread_t; + +/** The thread function */ @@ -34059,21 +41436,42 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + +/** Create a thread and start it running the thread_function. Returns a handle + * to the thread */ -+extern dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t thread_function, char *name, void *data); -+#define dwc_thread_run DWC_THREAD_RUN ++extern dwc_thread_t *DWC_THREAD_RUN(dwc_thread_function_t func, char *name, void *data); ++#define dwc_thread_run(_ctx_,_func_,_name_,_data_) DWC_THREAD_RUN(_func_, _name_, _data_) ++ +/** Stops a thread. Return the value returned by the thread. Or will return + * DWC_ABORT if the thread never started. */ +extern int DWC_THREAD_STOP(dwc_thread_t *thread); +#define dwc_thread_stop DWC_THREAD_STOP ++ +/** Signifies to the thread that it must stop. */ ++#ifdef DWC_LINUX ++/* Linux doesn't need any parameters for kthread_should_stop() */ +extern dwc_bool_t DWC_THREAD_SHOULD_STOP(void); ++#define dwc_thread_should_stop(_thrd_) DWC_THREAD_SHOULD_STOP() ++ ++/* No thread_exit function in Linux */ ++#define dwc_thread_exit(_thrd_) ++#endif ++ ++#if defined(DWC_FREEBSD) || defined(DWC_NETBSD) ++/** BSD needs the thread pointer for kthread_suspend_check() */ ++extern dwc_bool_t DWC_THREAD_SHOULD_STOP(dwc_thread_t *thread); +#define dwc_thread_should_stop DWC_THREAD_SHOULD_STOP + ++/** The thread must call this to exit. */ ++extern void DWC_THREAD_EXIT(dwc_thread_t *thread); ++#define dwc_thread_exit DWC_THREAD_EXIT ++#endif ++ ++ +/** @name Work queues + * + * Workqs are used to queue a callback function to be called at some later time, + * in another thread. */ +struct dwc_workq; ++ ++/** Type for a workq */ +typedef struct dwc_workq dwc_workq_t; + +/** The type of the callback function to be called. */ @@ -34081,33 +41479,38 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + +/** Allocate a workq */ +extern dwc_workq_t *DWC_WORKQ_ALLOC(char *name); -+#define dwc_workq_alloc DWC_WORKQ_ALLOC ++#define dwc_workq_alloc(_ctx_,_name_) DWC_WORKQ_ALLOC(_name_) ++ +/** Free a workq. All work must be completed before being freed. */ +extern void DWC_WORKQ_FREE(dwc_workq_t *workq); +#define dwc_workq_free DWC_WORKQ_FREE ++ +/** Schedule a callback on the workq, passing in data. The function will be + * scheduled at some later time. */ -+extern void DWC_WORKQ_SCHEDULE(dwc_workq_t *workq, dwc_work_callback_t work_cb, void *data, char *format, ...) ++extern void DWC_WORKQ_SCHEDULE(dwc_workq_t *workq, dwc_work_callback_t cb, ++ void *data, char *format, ...) +#ifdef __GNUC__ + __attribute__ ((format(printf, 4, 5))); +#else -+ ; ++ ; +#endif +#define dwc_workq_schedule DWC_WORKQ_SCHEDULE + -+/** Schedule a callback on the workq, that will be called until at least ++/** Schedule a callback on the workq, that will be called until at least + * given number miliseconds have passed. */ -+extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t work_cb, void *data, uint32_t time, char *format, ...) ++extern void DWC_WORKQ_SCHEDULE_DELAYED(dwc_workq_t *workq, dwc_work_callback_t cb, ++ void *data, uint32_t time, char *format, ...) +#ifdef __GNUC__ + __attribute__ ((format(printf, 5, 6))); +#else -+ ; ++ ; +#endif +#define dwc_workq_schedule_delayed DWC_WORKQ_SCHEDULE_DELAYED + +/** The number of processes in the workq */ +extern int DWC_WORKQ_PENDING(dwc_workq_t *workq); +#define dwc_workq_pending DWC_WORKQ_PENDING ++ +/** Blocks until all the work in the workq is complete or timed out. Returns < + * 0 on timeout. */ +extern int DWC_WORKQ_WAIT_WORK_DONE(dwc_workq_t *workq, int timeout); @@ -34118,14 +41521,22 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + * + */ +struct dwc_tasklet; ++ ++/** Type for a tasklet */ +typedef struct dwc_tasklet dwc_tasklet_t; + ++/** The type of the callback function to be called */ +typedef void (*dwc_tasklet_callback_t)(void *data); + -+extern dwc_tasklet_t *DWC_TASK_ALLOC(dwc_tasklet_callback_t cb, void *data); -+#define dwc_task_alloc DWC_TASK_ALLOC -+extern void DWC_TASK_FREE(dwc_tasklet_t *t); ++/** Allocates a tasklet */ ++extern dwc_tasklet_t *DWC_TASK_ALLOC(char *name, dwc_tasklet_callback_t cb, void *data); ++#define dwc_task_alloc(_ctx_,_name_,_cb_,_data_) DWC_TASK_ALLOC(_name_, _cb_, _data_) ++ ++/** Frees a tasklet */ ++extern void DWC_TASK_FREE(dwc_tasklet_t *task); +#define dwc_task_free DWC_TASK_FREE ++ ++/** Schedules a tasklet to run */ +extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task); +#define dwc_task_schedule DWC_TASK_SCHEDULE + @@ -34135,12 +41546,18 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + * Callbacks must be small and atomic. + */ +struct dwc_timer; ++ ++/** Type for a timer */ +typedef struct dwc_timer dwc_timer_t; + ++/** The type of the callback function to be called */ +typedef void (*dwc_timer_callback_t)(void *data); + ++/** Allocates a timer */ +extern dwc_timer_t *DWC_TIMER_ALLOC(char *name, dwc_timer_callback_t cb, void *data); -+#define dwc_timer_alloc DWC_TIMER_ALLOC ++#define dwc_timer_alloc(_ctx_,_name_,_cb_,_data_) DWC_TIMER_ALLOC(_name_,_cb_,_data_) ++ ++/** Frees a timer */ +extern void DWC_TIMER_FREE(dwc_timer_t *timer); +#define dwc_timer_free DWC_TIMER_FREE + @@ -34157,7 +41574,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot +#define dwc_timer_cancel DWC_TIMER_CANCEL + + -+ +/** @name Spinlocks + * + * These locks are used when the work between the lock/unlock is atomic and @@ -34170,25 +41586,30 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + * change, and so you never have to lock between processes. */ + +struct dwc_spinlock; ++ ++/** Type for a spinlock */ +typedef struct dwc_spinlock dwc_spinlock_t; + ++/** Type for the 'flags' argument to spinlock funtions */ ++typedef unsigned long dwc_irqflags_t; ++ +/** Returns an initialized lock variable. This function should allocate and + * initialize the OS-specific data structure used for locking. This data + * structure is to be used for the DWC_LOCK and DWC_UNLOCK functions and should + * be freed by the DWC_FREE_LOCK when it is no longer used. */ +extern dwc_spinlock_t *DWC_SPINLOCK_ALLOC(void); -+#define dwc_spinlock_alloc DWC_SPINLOCK_ALLOC ++#define dwc_spinlock_alloc(_ctx_) DWC_SPINLOCK_ALLOC() + +/** Frees an initialized lock variable. */ +extern void DWC_SPINLOCK_FREE(dwc_spinlock_t *lock); -+#define dwc_spinlock_free DWC_SPINLOCK_FREE ++#define dwc_spinlock_free(_ctx_,_lock_) DWC_SPINLOCK_FREE(_lock_) + +/** Disables interrupts and blocks until it acquires the lock. + * + * @param lock Pointer to the spinlock. + * @param flags Unsigned long for irq flags storage. + */ -+extern void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, uint64_t *flags); ++extern void DWC_SPINLOCK_IRQSAVE(dwc_spinlock_t *lock, dwc_irqflags_t *flags); +#define dwc_spinlock_irqsave DWC_SPINLOCK_IRQSAVE + +/** Re-enables the interrupt and releases the lock. @@ -34197,7 +41618,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + * @param flags Unsigned long for irq flags storage. Must be the same as was + * passed into DWC_LOCK. + */ -+extern void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, uint64_t flags); ++extern void DWC_SPINUNLOCK_IRQRESTORE(dwc_spinlock_t *lock, dwc_irqflags_t flags); +#define dwc_spinunlock_irqrestore DWC_SPINUNLOCK_IRQRESTORE + +/** Blocks until it acquires the lock. @@ -34214,6 +41635,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot +extern void DWC_SPINUNLOCK(dwc_spinlock_t *lock); +#define dwc_spinunlock DWC_SPINUNLOCK + ++ +/** @name Mutexes + * + * Unlike spinlocks Mutexes lock only between processes and the work between the @@ -34221,43 +41643,49 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + */ + +struct dwc_mutex; -+typedef struct dwc_mutex dwc_mutex_t; + ++/** Type for a mutex */ ++typedef struct dwc_mutex dwc_mutex_t; + +/* For Linux Mutex Debugging make it inline because the debugging routines use + * the symbol to determine recursive locking. This makes it falsely think + * recursive locking occurs. */ -+#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES) +#define DWC_MUTEX_ALLOC_LINUX_DEBUG(__mutexp) ({ \ + __mutexp = (dwc_mutex_t *)DWC_ALLOC(sizeof(struct mutex)); \ + mutex_init((struct mutex *)__mutexp); \ +}) +#endif ++ ++/** Allocate a mutex */ +extern dwc_mutex_t *DWC_MUTEX_ALLOC(void); -+#define dwc_mutex_alloc DWC_MUTEX_ALLOC ++#define dwc_mutex_alloc(_ctx_) DWC_MUTEX_ALLOC() + +/* For memory leak debugging when using Linux Mutex Debugging */ -+#if (defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES)) ++#if defined(DWC_LINUX) && defined(CONFIG_DEBUG_MUTEXES) +#define DWC_MUTEX_FREE(__mutexp) do { \ + mutex_destroy((struct mutex *)__mutexp); \ + DWC_FREE(__mutexp); \ +} while(0) +#else ++/** Free a mutex */ +extern void DWC_MUTEX_FREE(dwc_mutex_t *mutex); -+#define dwc_mutex_free DWC_MUTEX_FREE ++#define dwc_mutex_free(_ctx_,_mutex_) DWC_MUTEX_FREE(_mutex_) +#endif + ++/** Lock a mutex */ +extern void DWC_MUTEX_LOCK(dwc_mutex_t *mutex); +#define dwc_mutex_lock DWC_MUTEX_LOCK ++ +/** Non-blocking lock returns 1 on successful lock. */ +extern int DWC_MUTEX_TRYLOCK(dwc_mutex_t *mutex); +#define dwc_mutex_trylock DWC_MUTEX_TRYLOCK ++ ++/** Unlock a mutex */ +extern void DWC_MUTEX_UNLOCK(dwc_mutex_t *mutex); +#define dwc_mutex_unlock DWC_MUTEX_UNLOCK + + -+ -+ +/** @name Time */ + +/** Microsecond delay. @@ -34282,15 +41710,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot +extern void DWC_MSLEEP(uint32_t msecs); +#define dwc_msleep DWC_MSLEEP + ++/** ++ * Returns number of milliseconds since boot. ++ */ +extern uint32_t DWC_TIME(void); +#define dwc_time DWC_TIME + -+#endif // _DWC_OS_H_ + + + -+ -+/** @mainpage DWC Portability and Common Library ++/* @mainpage DWC Portability and Common Library + * + * This is the documentation for the DWC Portability and Common Library. + * @@ -34382,100 +41811,18 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/dwc_os.h linux-rpi-boot + * threading should be able to be implemented with the defined behavior. + * + */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/Makefile linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/Makefile ---- linux-3.2.23/drivers/usb/host/dwc_common_port/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/Makefile 2012-07-15 20:29:18.989081834 +0200 -@@ -0,0 +1,46 @@ -+# -+# Makefile for DWC_common library -+# + -+ifneq ($(KERNELRELEASE),) ++#ifdef __cplusplus ++} ++#endif + -+#CPPFLAGS += -DDEBUG_MEMORY -+ -+ifeq ($(CONFIG_USB_DEBUG),y) -+CPPFLAGS += -DDEBUG -+endif -+CPPFLAGS += -DDWC_LINUX -+ -+obj-$(CONFIG_USB_DWCOTG) += dwc_common_port_lib.o -+dwc_common_port_lib-objs := dwc_cc.o \ -+ dwc_notifier.o \ -+ dwc_common_linux.o dwc_mem.o -+ -+kernrelwd := $(subst ., ,$(KERNELRELEASE)) -+kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd)) -+ -+ifneq ($(kernrel3),2.6.20) -+# grayg - I only know that we use EXTRA_CFLAGS in 2.6.31 actually -+EXTRA_CFLAGS += $(CPPFLAGS) -+endif -+ -+else -+ -+ifeq ($(DOXYGEN),) -+DOXYGEN := $(DOXYGEN) -+endif -+ -+default: -+ $(MAKE) -C$(KDIR) M=$(PWD) modules -+ -+docs: $(wildcard *.[hc]) doc/doxygen.cfg -+ $(DOXYGEN) doc/doxygen.cfg -+ -+tags: $(wildcard *.[hc]) -+ $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h) -+ -+endif -+ -+clean: -+ rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers -+ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/Makefile.linux linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/Makefile.linux ---- linux-3.2.23/drivers/usb/host/dwc_common_port/Makefile.linux 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/Makefile.linux 2012-07-15 20:29:18.989081834 +0200 -@@ -0,0 +1,36 @@ -+# -+# Makefile for DWC_common library -+# -+ifneq ($(KERNELRELEASE),) -+ -+#CPPFLAGS += -DDEBUG_MEMORY -+ -+#CPPFLAGS += -DDEBUG -+CPPFLAGS += -DDWC_LINUX -+ -+obj-m := dwc_common_port_lib.o -+dwc_common_port_lib-objs := dwc_cc.o dwc_modpow.o dwc_dh.o \ -+ dwc_crypto.o dwc_notifier.o \ -+ dwc_common_linux.o dwc_mem.o -+ -+else -+ -+ -+ifeq ($(DOXYGEN),) -+DOXYGEN := $(DOXYGEN) -+endif -+ -+default: -+ $(MAKE) -C$(KDIR) M=$(PWD) modules -+ -+docs: $(wildcard *.[hc]) doc/doxygen.cfg -+ $(DOXYGEN) doc/doxygen.cfg -+ -+tags: $(wildcard *.[hc]) -+ $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h) -+ -+endif -+ -+clean: -+ rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers -+ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/usb.h ---- linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_common_port/usb.h 2012-07-15 20:29:18.989081834 +0200 -@@ -0,0 +1,850 @@ ++#endif /* _DWC_OS_H_ */ +diff --git a/drivers/usb/host/dwc_common_port/usb.h b/drivers/usb/host/dwc_common_port/usb.h +new file mode 100644 +index 0000000..27bda82 +--- /dev/null ++++ b/drivers/usb/host/dwc_common_port/usb.h +@@ -0,0 +1,946 @@ +/* + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. @@ -34519,7 +41866,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3 +#ifndef _USB_H_ +#define _USB_H_ + -+#include "dwc_os.h" ++#ifdef __cplusplus ++extern "C" { ++#endif + +/* + * The USB records contain some unaligned little-endian word @@ -34532,6 +41881,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3 +typedef u_int8_t uDWord[4]; + +#define USETW2(w,h,l) ((w)[0] = (u_int8_t)(l), (w)[1] = (u_int8_t)(h)) ++#define UCONSTW(x) { (x) & 0xff, ((x) >> 8) & 0xff } ++#define UCONSTDW(x) { (x) & 0xff, ((x) >> 8) & 0xff, \ ++ ((x) >> 16) & 0xff, ((x) >> 24) & 0xff } + +#if 1 +#define UGETW(w) ((w)[0] | ((w)[1] << 8)) @@ -34552,6 +41904,21 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3 +#define USETDW(w,v) (*(u_int32_t *)(w) = (v)) +#endif + ++/* ++ * Macros for accessing UAS IU fields, which are big-endian ++ */ ++#define IUSETW2(w,h,l) ((w)[0] = (u_int8_t)(h), (w)[1] = (u_int8_t)(l)) ++#define IUCONSTW(x) { ((x) >> 8) & 0xff, (x) & 0xff } ++#define IUCONSTDW(x) { ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \ ++ ((x) >> 8) & 0xff, (x) & 0xff } ++#define IUGETW(w) (((w)[0] << 8) | (w)[1]) ++#define IUSETW(w,v) ((w)[0] = (u_int8_t)((v) >> 8), (w)[1] = (u_int8_t)(v)) ++#define IUGETDW(w) (((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3]) ++#define IUSETDW(w,v) ((w)[0] = (u_int8_t)((v) >> 24), \ ++ (w)[1] = (u_int8_t)((v) >> 16), \ ++ (w)[2] = (u_int8_t)((v) >> 8), \ ++ (w)[3] = (u_int8_t)(v)) ++ +#define UPACKED __attribute__((__packed__)) + +typedef struct { @@ -34618,6 +41985,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3 +#define UDESC_STRING 0x03 +#define UDESC_INTERFACE 0x04 +#define UDESC_ENDPOINT 0x05 ++#define UDESC_SS_USB_COMPANION 0x30 +#define UDESC_DEVICE_QUALIFIER 0x06 +#define UDESC_OTHER_SPEED_CONFIGURATION 0x07 +#define UDESC_INTERFACE_POWER 0x08 @@ -34635,6 +42003,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3 +#define WUDESC_BOS 0x0f +#define WUDESC_DEVICE_CAPABILITY 0x10 +#define WUDESC_WIRELESS_ENDPOINT_COMPANION 0x11 ++#define UDESC_BOS 0x0f ++#define UDESC_DEVICE_CAPABILITY 0x10 +#define UDESC_CS_DEVICE 0x21 /* class specific */ +#define UDESC_CS_CONFIG 0x22 +#define UDESC_CS_STRING 0x23 @@ -34655,11 +42025,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3 +#define WUR_SET_SECURITY_DATA 0x12 +#define WUR_GET_SECURITY_DATA 0x13 +#define WUR_SET_WUSB_DATA 0x14 -+#define WUDATA_DRPIE_INFO 0x01 -+#define WUDATA_TRANSMIT_DATA 0x02 -+#define WUDATA_TRANSMIT_PARAMS 0x03 -+#define WUDATA_RECEIVE_PARAMS 0x04 -+#define WUDATA_TRANSMIT_POWER 0x05 ++#define WUDATA_DRPIE_INFO 0x01 ++#define WUDATA_TRANSMIT_DATA 0x02 ++#define WUDATA_TRANSMIT_PARAMS 0x03 ++#define WUDATA_RECEIVE_PARAMS 0x04 ++#define WUDATA_TRANSMIT_POWER 0x05 +#define WUR_LOOPBACK_DATA_WRITE 0x15 +#define WUR_LOOPBACK_DATA_READ 0x16 +#define WUR_SET_INTERFACE_DS 0x17 @@ -34671,11 +42041,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3 +#define UF_DEVICE_B_HNP_ENABLE 3 +#define UF_DEVICE_A_HNP_SUPPORT 4 +#define UF_DEVICE_A_ALT_HNP_SUPPORT 5 -+#define WUF_WUSB 3 -+#define WUF_TX_DRPIE 0x0 -+#define WUF_DEV_XMIT_PACKET 0x1 -+#define WUF_COUNT_PACKETS 0x2 -+#define WUF_CAPTURE_PACKETS 0x3 ++#define WUF_WUSB 3 ++#define WUF_TX_DRPIE 0x0 ++#define WUF_DEV_XMIT_PACKET 0x1 ++#define WUF_COUNT_PACKETS 0x2 ++#define WUF_CAPTURE_PACKETS 0x3 ++#define UF_FUNCTION_SUSPEND 0 ++#define UF_U1_ENABLE 48 ++#define UF_U2_ENABLE 49 ++#define UF_LTM_ENABLE 50 + +/* Class requests from the USB 2.0 hub spec, table 11-15 */ +#define UCR_CLEAR_HUB_FEATURE (0x2000 | UR_CLEAR_FEATURE) @@ -34687,6 +42061,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3 +#define UCR_SET_PORT_FEATURE (0x2300 | UR_SET_FEATURE) +#define UCR_SET_AND_TEST_PORT_FEATURE (0xa300 | UR_SET_AND_TEST_FEATURE) + ++#ifdef _MSC_VER ++#include ++#endif ++ +typedef struct { + uByte bLength; + uByte bDescriptorType; @@ -34696,6 +42074,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3 +typedef struct { + uByte bLength; + uByte bDescriptorType; ++} UPACKED usb_descriptor_header_t; ++ ++typedef struct { ++ uByte bLength; ++ uByte bDescriptorType; + uWord bcdUSB; +#define UD_USB_2_0 0x0200 +#define UD_IS_USB2(d) (UGETW((d)->bcdUSB) >= UD_USB_2_0) @@ -34721,6 +42104,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3 + uByte bNumInterface; + uByte bConfigurationValue; + uByte iConfiguration; ++#define UC_ATT_ONE (1 << 7) /* must be set */ ++#define UC_ATT_SELFPOWER (1 << 6) /* self powered */ ++#define UC_ATT_WAKEUP (1 << 5) /* can wakeup */ ++#define UC_ATT_BATTERY (1 << 4) /* battery powered */ + uByte bmAttributes; +#define UC_BUS_POWERED 0x80 +#define UC_SELF_POWERED 0x40 @@ -34770,6 +42157,19 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3 +} UPACKED usb_endpoint_descriptor_t; +#define USB_ENDPOINT_DESCRIPTOR_SIZE 7 + ++typedef struct ss_endpoint_companion_descriptor { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bMaxBurst; ++#define USSE_GET_MAX_STREAMS(a) ((a) & 0x1f) ++#define USSE_SET_MAX_STREAMS(a, b) ((a) | ((b) & 0x1f)) ++#define USSE_GET_MAX_PACKET_NUM(a) ((a) & 0x03) ++#define USSE_SET_MAX_PACKET_NUM(a, b) ((a) | ((b) & 0x03)) ++ uByte bmAttributes; ++ uWord wBytesPerInterval; ++} UPACKED ss_endpoint_companion_descriptor_t; ++#define USB_SS_ENDPOINT_COMPANION_DESCRIPTOR_SIZE 6 ++ +typedef struct { + uByte bLength; + uByte bDescriptorType; @@ -34898,6 +42298,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3 +#define UPS_C_PORT_RESET 0x0010 +} UPACKED usb_port_status_t; + ++#ifdef _MSC_VER ++#include ++#endif ++ +/* Device class codes */ +#define UDCLASS_IN_INTERFACE 0x00 +#define UDCLASS_COMM 0x02 @@ -34921,13 +42325,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3 +#define UISUBCLASS_MIDISTREAM 3 + +#define UICLASS_CDC 0x02 /* communication */ -+#define UISUBCLASS_DIRECT_LINE_CONTROL_MODEL 1 ++#define UISUBCLASS_DIRECT_LINE_CONTROL_MODEL 1 +#define UISUBCLASS_ABSTRACT_CONTROL_MODEL 2 -+#define UISUBCLASS_TELEPHONE_CONTROL_MODEL 3 -+#define UISUBCLASS_MULTICHANNEL_CONTROL_MODEL 4 -+#define UISUBCLASS_CAPI_CONTROLMODEL 5 -+#define UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6 -+#define UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7 ++#define UISUBCLASS_TELEPHONE_CONTROL_MODEL 3 ++#define UISUBCLASS_MULTICHANNEL_CONTROL_MODEL 4 ++#define UISUBCLASS_CAPI_CONTROLMODEL 5 ++#define UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL 6 ++#define UISUBCLASS_ATM_NETWORKING_CONTROL_MODEL 7 +#define UIPROTO_CDC_AT 1 + +#define UICLASS_HID 0x03 @@ -34997,7 +42401,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3 + +#define UICLASS_VENDOR 0xff + -+ +#define USB_HUB_MAX_DEPTH 5 + +/* @@ -35036,7 +42439,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3 + +#define USB_BUS_RESET_DELAY 100 /* ms XXX?*/ + -+ +#define USB_UNCONFIG_NO 0 +#define USB_UNCONFIG_INDEX (-1) + @@ -35116,9 +42518,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3 + u_int8_t udi_protocol; + u_int8_t udi_config; + u_int8_t udi_speed; -+#define USB_SPEED_LOW 1 -+#define USB_SPEED_FULL 2 -+#define USB_SPEED_HIGH 3 ++#define USB_SPEED_UNKNOWN 0 ++#define USB_SPEED_LOW 1 ++#define USB_SPEED_FULL 2 ++#define USB_SPEED_HIGH 3 ++#define USB_SPEED_VARIABLE 4 ++#define USB_SPEED_SUPER 5 + int udi_power; /* power consumption in mA, 0 if selfpowered */ + int udi_nports; + char udi_devnames[USB_MAX_DEVNAMES][USB_MAX_DEVNAMELEN]; @@ -35138,17 +42543,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3 + u_long uds_requests[4]; /* indexed by transfer type UE_* */ +}; + -+ -+ -+ +#define WUSB_MIN_IE 0x80 +#define WUSB_WCTA_IE 0x80 +#define WUSB_WCONNECTACK_IE 0x81 +#define WUSB_WHOSTINFO_IE 0x82 +#define WUHI_GET_CA(_bmAttributes_) ((_bmAttributes_) & 0x3) -+#define WUHI_CA_RECONN 0x00 -+#define WUHI_CA_LIMITED 0x01 -+#define WUHI_CA_ALL 0x03 ++#define WUHI_CA_RECONN 0x00 ++#define WUHI_CA_LIMITED 0x01 ++#define WUHI_CA_ALL 0x03 +#define WUHI_GET_MLSI(_bmAttributes_) (((_bmAttributes_) & 0x38) >> 3) +#define WUSB_WCHCHANGEANNOUNCE_IE 0x83 +#define WUSB_WDEV_DISCONNECT_IE 0x84 @@ -35179,156 +42581,516 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_common_port/usb.h linux-rpi-bootc-3 +#define WUSB_DN_ALIVE 0x07 +#define WUSB_DN_MAX 0x07 + ++#ifdef _MSC_VER ++#include ++#endif + +/* WUSB Handshake Data. Used during the SET/GET HANDSHAKE requests */ +typedef struct wusb_hndshk_data { -+ uint8_t bMessageNumber; -+ uint8_t bStatus; -+ uint8_t tTKID[3]; -+ uint8_t bReserved; -+ uint8_t CDID[16]; -+ uint8_t Nonce[16]; -+ uint8_t MIC[8]; ++ uByte bMessageNumber; ++ uByte bStatus; ++ uByte tTKID[3]; ++ uByte bReserved; ++ uByte CDID[16]; ++ uByte Nonce[16]; ++ uByte MIC[8]; +} UPACKED wusb_hndshk_data_t; +#define WUSB_HANDSHAKE_LEN_FOR_MIC 38 + +/* WUSB Connection Context */ +typedef struct wusb_conn_context { -+ uint8_t CHID [16]; -+ uint8_t CDID [16]; -+ uint8_t CK [16]; ++ uByte CHID [16]; ++ uByte CDID [16]; ++ uByte CK [16]; +} UPACKED wusb_conn_context_t; + +/* WUSB Security Descriptor */ +typedef struct wusb_security_desc { -+ uint8_t bLength; -+ uint8_t bDescriptorType; -+ uint16_t wTotalLength; -+ uint8_t bNumEncryptionTypes; ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wTotalLength; ++ uByte bNumEncryptionTypes; +} UPACKED wusb_security_desc_t; + +/* WUSB Encryption Type Descriptor */ +typedef struct wusb_encrypt_type_desc { -+ uint8_t bLength; -+ uint8_t bDescriptorType; ++ uByte bLength; ++ uByte bDescriptorType; + -+ uint8_t bEncryptionType; -+#define WUETD_UNSECURE 0 ++ uByte bEncryptionType; ++#define WUETD_UNSECURE 0 +#define WUETD_WIRED 1 +#define WUETD_CCM_1 2 +#define WUETD_RSA_1 3 + -+ uint8_t bEncryptionValue; -+ uint8_t bAuthKeyIndex; ++ uByte bEncryptionValue; ++ uByte bAuthKeyIndex; +} UPACKED wusb_encrypt_type_desc_t; + +/* WUSB Key Descriptor */ +typedef struct wusb_key_desc { -+ uint8_t bLength; -+ uint8_t bDescriptorType; -+ uint8_t tTKID[3]; -+ uint8_t bReserved; -+ uint8_t KeyData[1]; /* variable length */ ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte tTKID[3]; ++ uByte bReserved; ++ uByte KeyData[1]; /* variable length */ +} UPACKED wusb_key_desc_t; + +/* WUSB BOS Descriptor (Binary device Object Store) */ +typedef struct wusb_bos_desc { -+ uint8_t bLength; -+ uint8_t bDescriptorType; -+ uint16_t wTotalLength; -+ uint8_t bNumDeviceCaps; ++ uByte bLength; ++ uByte bDescriptorType; ++ uWord wTotalLength; ++ uByte bNumDeviceCaps; +} UPACKED wusb_bos_desc_t; + ++#define USB_DEVICE_CAPABILITY_20_EXTENSION 0x02 ++typedef struct usb_dev_cap_20_ext_desc { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++#define USB_20_EXT_LPM 0x02 ++ uDWord bmAttributes; ++} UPACKED usb_dev_cap_20_ext_desc_t; ++ ++#define USB_DEVICE_CAPABILITY_SS_USB 0x03 ++typedef struct usb_dev_cap_ss_usb { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++#define USB_DC_SS_USB_LTM_CAPABLE 0x02 ++ uByte bmAttributes; ++#define USB_DC_SS_USB_SPEED_SUPPORT_LOW 0x01 ++#define USB_DC_SS_USB_SPEED_SUPPORT_FULL 0x02 ++#define USB_DC_SS_USB_SPEED_SUPPORT_HIGH 0x04 ++#define USB_DC_SS_USB_SPEED_SUPPORT_SS 0x08 ++ uWord wSpeedsSupported; ++ uByte bFunctionalitySupport; ++ uByte bU1DevExitLat; ++ uWord wU2DevExitLat; ++} UPACKED usb_dev_cap_ss_usb_t; ++ ++#define USB_DEVICE_CAPABILITY_CONTAINER_ID 0x04 ++typedef struct usb_dev_cap_container_id { ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++ uByte bReserved; ++ uByte containerID[16]; ++} UPACKED usb_dev_cap_container_id_t; + +/* Device Capability Type Codes */ +#define WUSB_DEVICE_CAPABILITY_WIRELESS_USB 0x01 + +/* Device Capability Descriptor */ +typedef struct wusb_dev_cap_desc { -+ uint8_t bLength; -+ uint8_t bDescriptorType; -+ uint8_t bDevCapabilityType; -+ uint8_t caps[1]; /* Variable length */ ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++ uByte caps[1]; /* Variable length */ +} UPACKED wusb_dev_cap_desc_t; + +/* Device Capability Descriptor */ +typedef struct wusb_dev_cap_uwb_desc { -+ uint8_t bLength; -+ uint8_t bDescriptorType; -+ uint8_t bDevCapabilityType; -+ uint8_t bmAttributes; -+ uint16_t wPHYRates; /* Bitmap */ -+ uint8_t bmTFITXPowerInfo; -+ uint8_t bmFFITXPowerInfo; -+ uint16_t bmBandGroup; -+ uint8_t bReserved; ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bDevCapabilityType; ++ uByte bmAttributes; ++ uWord wPHYRates; /* Bitmap */ ++ uByte bmTFITXPowerInfo; ++ uByte bmFFITXPowerInfo; ++ uWord bmBandGroup; ++ uByte bReserved; +} UPACKED wusb_dev_cap_uwb_desc_t; + +/* Wireless USB Endpoint Companion Descriptor */ +typedef struct wusb_endpoint_companion_desc { -+ uint8_t bLength; -+ uint8_t bDescriptorType; -+ uint8_t bMaxBurst; -+ uint8_t bMaxSequence; -+ uint16_t wMaxStreamDelay; -+ uint16_t wOverTheAirPacketSize; -+ uint8_t bOverTheAirInterval; -+ uint8_t bmCompAttributes; ++ uByte bLength; ++ uByte bDescriptorType; ++ uByte bMaxBurst; ++ uByte bMaxSequence; ++ uWord wMaxStreamDelay; ++ uWord wOverTheAirPacketSize; ++ uByte bOverTheAirInterval; ++ uByte bmCompAttributes; +} UPACKED wusb_endpoint_companion_desc_t; + -+ +/* Wireless USB Numeric Association M1 Data Structure */ +typedef struct wusb_m1_data { -+ uint8_t version; -+ uint16_t langId; -+ uint8_t deviceFriendlyNameLength; -+ uint8_t sha_256_m3[32]; -+ uint8_t deviceFriendlyName[256]; ++ uByte version; ++ uWord langId; ++ uByte deviceFriendlyNameLength; ++ uByte sha_256_m3[32]; ++ uByte deviceFriendlyName[256]; +} UPACKED wusb_m1_data_t; + +typedef struct wusb_m2_data { -+ uint8_t version; -+ uint16_t langId; -+ uint8_t hostFriendlyNameLength; -+ uint8_t pkh[384]; -+ uint8_t hostFriendlyName[256]; ++ uByte version; ++ uWord langId; ++ uByte hostFriendlyNameLength; ++ uByte pkh[384]; ++ uByte hostFriendlyName[256]; +} UPACKED wusb_m2_data_t; + +typedef struct wusb_m3_data { -+ uint8_t pkd[384]; -+ uint8_t nd; ++ uByte pkd[384]; ++ uByte nd; +} UPACKED wusb_m3_data_t; + +typedef struct wusb_m4_data { -+ uint32_t _attributeTypeIdAndLength_1; -+ uint16_t associationTypeId; ++ uDWord _attributeTypeIdAndLength_1; ++ uWord associationTypeId; + -+ uint32_t _attributeTypeIdAndLength_2; -+ uint16_t associationSubTypeId; ++ uDWord _attributeTypeIdAndLength_2; ++ uWord associationSubTypeId; + -+ uint32_t _attributeTypeIdAndLength_3; -+ uint32_t length; ++ uDWord _attributeTypeIdAndLength_3; ++ uDWord length; + -+ uint32_t _attributeTypeIdAndLength_4; -+ uint32_t associationStatus; ++ uDWord _attributeTypeIdAndLength_4; ++ uDWord associationStatus; + -+ uint32_t _attributeTypeIdAndLength_5; -+ uint8_t chid[16]; ++ uDWord _attributeTypeIdAndLength_5; ++ uByte chid[16]; + -+ uint32_t _attributeTypeIdAndLength_6; -+ uint8_t cdid[16]; ++ uDWord _attributeTypeIdAndLength_6; ++ uByte cdid[16]; + -+ uint32_t _attributeTypeIdAndLength_7; -+ uint8_t bandGroups[2]; ++ uDWord _attributeTypeIdAndLength_7; ++ uByte bandGroups[2]; +} UPACKED wusb_m4_data_t; + ++#ifdef _MSC_VER ++#include ++#endif + -+ ++#ifdef __cplusplus ++} ++#endif + +#endif /* _USB_H_ */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dummy_audio.c linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dummy_audio.c ---- linux-3.2.23/drivers/usb/host/dwc_otg/dummy_audio.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dummy_audio.c 2012-07-15 20:29:19.078083509 +0200 +diff --git a/drivers/usb/host/dwc_otg/Makefile b/drivers/usb/host/dwc_otg/Makefile +new file mode 100644 +index 0000000..6bd6a2e +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/Makefile +@@ -0,0 +1,81 @@ ++# ++# Makefile for DWC_otg Highspeed USB controller driver ++# ++ ++ifneq ($(KERNELRELEASE),) ++ ++# Use the BUS_INTERFACE variable to compile the software for either ++# PCI(PCI_INTERFACE) or LM(LM_INTERFACE) bus. ++ifeq ($(BUS_INTERFACE),) ++# BUS_INTERFACE = -DPCI_INTERFACE ++# BUS_INTERFACE = -DLM_INTERFACE ++ BUS_INTERFACE = -DPLATFORM_INTERFACE ++endif ++ ++#EXTRA_CFLAGS += -DDEBUG ++#EXTRA_CFLAGS += -DDWC_OTG_DEBUGLEV=1 # reduce common debug msgs ++ ++# Use one of the following flags to compile the software in host-only or ++# device-only mode. ++#EXTRA_CFLAGS += -DDWC_HOST_ONLY ++#EXTRA_CFLAGS += -DDWC_DEVICE_ONLY ++ ++EXTRA_CFLAGS += -Dlinux -DDWC_HS_ELECT_TST ++#EXTRA_CFLAGS += -DDWC_EN_ISOC ++EXTRA_CFLAGS += -I$(obj)/../dwc_common_port ++#EXTRA_CFLAGS += -I$(PORTLIB) ++EXTRA_CFLAGS += -DDWC_LINUX ++EXTRA_CFLAGS += $(CFI) ++EXTRA_CFLAGS += $(BUS_INTERFACE) ++#EXTRA_CFLAGS += -DDWC_DEV_SRPCAP ++ ++obj-$(CONFIG_USB_DWCOTG) += dwc_otg.o ++ ++dwc_otg-objs := dwc_otg_driver.o dwc_otg_attr.o ++dwc_otg-objs += dwc_otg_cil.o dwc_otg_cil_intr.o ++dwc_otg-objs += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o ++dwc_otg-objs += dwc_otg_hcd.o dwc_otg_hcd_linux.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o dwc_otg_hcd_ddma.o ++dwc_otg-objs += dwc_otg_adp.o ++dwc_otg-objs += dwc_otg_mphi_fix.o ++ifneq ($(CFI),) ++dwc_otg-objs += dwc_otg_cfi.o ++endif ++ ++kernrelwd := $(subst ., ,$(KERNELRELEASE)) ++kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd)) ++ ++ifneq ($(kernrel3),2.6.20) ++EXTRA_CFLAGS += $(CPPFLAGS) ++endif ++ ++else ++ ++PWD := $(shell pwd) ++PORTLIB := $(PWD)/../dwc_common_port ++ ++# Command paths ++CTAGS := $(CTAGS) ++DOXYGEN := $(DOXYGEN) ++ ++default: portlib ++ $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ ++install: default ++ $(MAKE) -C$(KDIR) M=$(PORTLIB) modules_install ++ $(MAKE) -C$(KDIR) M=$(PWD) modules_install ++ ++portlib: ++ $(MAKE) -C$(KDIR) M=$(PORTLIB) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules ++ cp $(PORTLIB)/Module.symvers $(PWD)/ ++ ++docs: $(wildcard *.[hc]) doc/doxygen.cfg ++ $(DOXYGEN) doc/doxygen.cfg ++ ++tags: $(wildcard *.[hc]) ++ $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h) ++ ++ ++clean: ++ rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions Module.symvers ++ ++endif +diff --git a/drivers/usb/host/dwc_otg/doc/doxygen.cfg b/drivers/usb/host/dwc_otg/doc/doxygen.cfg +new file mode 100644 +index 0000000..537c676 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/doc/doxygen.cfg +@@ -0,0 +1,224 @@ ++# Doxyfile 1.3.9.1 ++ ++#--------------------------------------------------------------------------- ++# Project related configuration options ++#--------------------------------------------------------------------------- ++PROJECT_NAME = "DesignWare USB 2.0 OTG Controller (DWC_otg) Device Driver" ++PROJECT_NUMBER = v3.00a ++OUTPUT_DIRECTORY = ./doc/ ++CREATE_SUBDIRS = NO ++OUTPUT_LANGUAGE = English ++BRIEF_MEMBER_DESC = YES ++REPEAT_BRIEF = YES ++ABBREVIATE_BRIEF = "The $name class" \ ++ "The $name widget" \ ++ "The $name file" \ ++ is \ ++ provides \ ++ specifies \ ++ contains \ ++ represents \ ++ a \ ++ an \ ++ the ++ALWAYS_DETAILED_SEC = NO ++INLINE_INHERITED_MEMB = NO ++FULL_PATH_NAMES = NO ++STRIP_FROM_PATH = ++STRIP_FROM_INC_PATH = ++SHORT_NAMES = NO ++JAVADOC_AUTOBRIEF = YES ++MULTILINE_CPP_IS_BRIEF = NO ++INHERIT_DOCS = YES ++DISTRIBUTE_GROUP_DOC = NO ++TAB_SIZE = 8 ++ALIASES = ++OPTIMIZE_OUTPUT_FOR_C = YES ++OPTIMIZE_OUTPUT_JAVA = NO ++SUBGROUPING = YES ++#--------------------------------------------------------------------------- ++# Build related configuration options ++#--------------------------------------------------------------------------- ++EXTRACT_ALL = NO ++EXTRACT_PRIVATE = YES ++EXTRACT_STATIC = YES ++EXTRACT_LOCAL_CLASSES = YES ++EXTRACT_LOCAL_METHODS = NO ++HIDE_UNDOC_MEMBERS = NO ++HIDE_UNDOC_CLASSES = NO ++HIDE_FRIEND_COMPOUNDS = NO ++HIDE_IN_BODY_DOCS = NO ++INTERNAL_DOCS = NO ++CASE_SENSE_NAMES = NO ++HIDE_SCOPE_NAMES = NO ++SHOW_INCLUDE_FILES = YES ++INLINE_INFO = YES ++SORT_MEMBER_DOCS = NO ++SORT_BRIEF_DOCS = NO ++SORT_BY_SCOPE_NAME = NO ++GENERATE_TODOLIST = YES ++GENERATE_TESTLIST = YES ++GENERATE_BUGLIST = YES ++GENERATE_DEPRECATEDLIST= YES ++ENABLED_SECTIONS = ++MAX_INITIALIZER_LINES = 30 ++SHOW_USED_FILES = YES ++SHOW_DIRECTORIES = YES ++#--------------------------------------------------------------------------- ++# configuration options related to warning and progress messages ++#--------------------------------------------------------------------------- ++QUIET = YES ++WARNINGS = YES ++WARN_IF_UNDOCUMENTED = NO ++WARN_IF_DOC_ERROR = YES ++WARN_FORMAT = "$file:$line: $text" ++WARN_LOGFILE = ++#--------------------------------------------------------------------------- ++# configuration options related to the input files ++#--------------------------------------------------------------------------- ++INPUT = . ++FILE_PATTERNS = *.c \ ++ *.h \ ++ ./linux/*.c \ ++ ./linux/*.h ++RECURSIVE = NO ++EXCLUDE = ./test/ \ ++ ./dwc_otg/.AppleDouble/ ++EXCLUDE_SYMLINKS = YES ++EXCLUDE_PATTERNS = *.mod.* ++EXAMPLE_PATH = ++EXAMPLE_PATTERNS = * ++EXAMPLE_RECURSIVE = NO ++IMAGE_PATH = ++INPUT_FILTER = ++FILTER_PATTERNS = ++FILTER_SOURCE_FILES = NO ++#--------------------------------------------------------------------------- ++# configuration options related to source browsing ++#--------------------------------------------------------------------------- ++SOURCE_BROWSER = YES ++INLINE_SOURCES = NO ++STRIP_CODE_COMMENTS = YES ++REFERENCED_BY_RELATION = NO ++REFERENCES_RELATION = NO ++VERBATIM_HEADERS = NO ++#--------------------------------------------------------------------------- ++# configuration options related to the alphabetical class index ++#--------------------------------------------------------------------------- ++ALPHABETICAL_INDEX = NO ++COLS_IN_ALPHA_INDEX = 5 ++IGNORE_PREFIX = ++#--------------------------------------------------------------------------- ++# configuration options related to the HTML output ++#--------------------------------------------------------------------------- ++GENERATE_HTML = YES ++HTML_OUTPUT = html ++HTML_FILE_EXTENSION = .html ++HTML_HEADER = ++HTML_FOOTER = ++HTML_STYLESHEET = ++HTML_ALIGN_MEMBERS = YES ++GENERATE_HTMLHELP = NO ++CHM_FILE = ++HHC_LOCATION = ++GENERATE_CHI = NO ++BINARY_TOC = NO ++TOC_EXPAND = NO ++DISABLE_INDEX = NO ++ENUM_VALUES_PER_LINE = 4 ++GENERATE_TREEVIEW = YES ++TREEVIEW_WIDTH = 250 ++#--------------------------------------------------------------------------- ++# configuration options related to the LaTeX output ++#--------------------------------------------------------------------------- ++GENERATE_LATEX = NO ++LATEX_OUTPUT = latex ++LATEX_CMD_NAME = latex ++MAKEINDEX_CMD_NAME = makeindex ++COMPACT_LATEX = NO ++PAPER_TYPE = a4wide ++EXTRA_PACKAGES = ++LATEX_HEADER = ++PDF_HYPERLINKS = NO ++USE_PDFLATEX = NO ++LATEX_BATCHMODE = NO ++LATEX_HIDE_INDICES = NO ++#--------------------------------------------------------------------------- ++# configuration options related to the RTF output ++#--------------------------------------------------------------------------- ++GENERATE_RTF = NO ++RTF_OUTPUT = rtf ++COMPACT_RTF = NO ++RTF_HYPERLINKS = NO ++RTF_STYLESHEET_FILE = ++RTF_EXTENSIONS_FILE = ++#--------------------------------------------------------------------------- ++# configuration options related to the man page output ++#--------------------------------------------------------------------------- ++GENERATE_MAN = NO ++MAN_OUTPUT = man ++MAN_EXTENSION = .3 ++MAN_LINKS = NO ++#--------------------------------------------------------------------------- ++# configuration options related to the XML output ++#--------------------------------------------------------------------------- ++GENERATE_XML = NO ++XML_OUTPUT = xml ++XML_SCHEMA = ++XML_DTD = ++XML_PROGRAMLISTING = YES ++#--------------------------------------------------------------------------- ++# configuration options for the AutoGen Definitions output ++#--------------------------------------------------------------------------- ++GENERATE_AUTOGEN_DEF = NO ++#--------------------------------------------------------------------------- ++# configuration options related to the Perl module output ++#--------------------------------------------------------------------------- ++GENERATE_PERLMOD = NO ++PERLMOD_LATEX = NO ++PERLMOD_PRETTY = YES ++PERLMOD_MAKEVAR_PREFIX = ++#--------------------------------------------------------------------------- ++# Configuration options related to the preprocessor ++#--------------------------------------------------------------------------- ++ENABLE_PREPROCESSING = YES ++MACRO_EXPANSION = YES ++EXPAND_ONLY_PREDEF = YES ++SEARCH_INCLUDES = YES ++INCLUDE_PATH = ++INCLUDE_FILE_PATTERNS = ++PREDEFINED = DEVICE_ATTR DWC_EN_ISOC ++EXPAND_AS_DEFINED = DWC_OTG_DEVICE_ATTR_BITFIELD_SHOW DWC_OTG_DEVICE_ATTR_BITFIELD_STORE DWC_OTG_DEVICE_ATTR_BITFIELD_RW DWC_OTG_DEVICE_ATTR_BITFIELD_RO DWC_OTG_DEVICE_ATTR_REG_SHOW DWC_OTG_DEVICE_ATTR_REG_STORE DWC_OTG_DEVICE_ATTR_REG32_RW DWC_OTG_DEVICE_ATTR_REG32_RO DWC_EN_ISOC ++SKIP_FUNCTION_MACROS = NO ++#--------------------------------------------------------------------------- ++# Configuration::additions related to external references ++#--------------------------------------------------------------------------- ++TAGFILES = ++GENERATE_TAGFILE = ++ALLEXTERNALS = NO ++EXTERNAL_GROUPS = YES ++PERL_PATH = /usr/bin/perl ++#--------------------------------------------------------------------------- ++# Configuration options related to the dot tool ++#--------------------------------------------------------------------------- ++CLASS_DIAGRAMS = YES ++HIDE_UNDOC_RELATIONS = YES ++HAVE_DOT = NO ++CLASS_GRAPH = YES ++COLLABORATION_GRAPH = YES ++UML_LOOK = NO ++TEMPLATE_RELATIONS = NO ++INCLUDE_GRAPH = YES ++INCLUDED_BY_GRAPH = YES ++CALL_GRAPH = NO ++GRAPHICAL_HIERARCHY = YES ++DOT_IMAGE_FORMAT = png ++DOT_PATH = ++DOTFILE_DIRS = ++MAX_DOT_GRAPH_DEPTH = 1000 ++GENERATE_LEGEND = YES ++DOT_CLEANUP = YES ++#--------------------------------------------------------------------------- ++# Configuration::additions related to the search engine ++#--------------------------------------------------------------------------- ++SEARCHENGINE = NO +diff --git a/drivers/usb/host/dwc_otg/dummy_audio.c b/drivers/usb/host/dwc_otg/dummy_audio.c +new file mode 100644 +index 0000000..530ac8b +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dummy_audio.c @@ -0,0 +1,1575 @@ +/* + * zero.c -- Gadget Zero, for USB development @@ -36905,9 +44667,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dummy_audio.c linux-rpi-bootc-3 + remove_proc_entry("isoc_test", NULL); +} +module_exit (cleanup); -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_cfi_common.h linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_cfi_common.h ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_cfi_common.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_cfi_common.h 2012-07-15 20:29:19.078083509 +0200 +diff --git a/drivers/usb/host/dwc_otg/dwc_cfi_common.h b/drivers/usb/host/dwc_otg/dwc_cfi_common.h +new file mode 100644 +index 0000000..be56af4 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_cfi_common.h @@ -0,0 +1,142 @@ +/* ========================================================================== + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, @@ -37051,15 +44815,963 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_cfi_common.h linux-rpi-boot +typedef struct cfi_string cfi_string_t; + +#endif -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c 2012-07-15 20:29:19.198085765 +0200 -@@ -0,0 +1,1316 @@ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_adp.c b/drivers/usb/host/dwc_otg/dwc_otg_adp.c +new file mode 100644 +index 0000000..0877472 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_adp.c +@@ -0,0 +1,854 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.c $ ++ * $Revision: #12 $ ++ * $Date: 2011/10/26 $ ++ * $Change: 1873028 $ ++ * ++ * 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 ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++#include "dwc_os.h" ++#include "dwc_otg_regs.h" ++#include "dwc_otg_cil.h" ++#include "dwc_otg_adp.h" ++ ++/** @file ++ * ++ * This file contains the most of the Attach Detect Protocol implementation for ++ * the driver to support OTG Rev2.0. ++ * ++ */ ++ ++void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value) ++{ ++ adpctl_data_t adpctl; ++ ++ adpctl.d32 = value; ++ adpctl.b.ar = 0x2; ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32); ++ ++ while (adpctl.b.ar) { ++ adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl); ++ } ++ ++} ++ ++/** ++ * Function is called to read ADP registers ++ */ ++uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ adpctl.d32 = 0; ++ adpctl.b.ar = 0x1; ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->adpctl, adpctl.d32); ++ ++ while (adpctl.b.ar) { ++ adpctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->adpctl); ++ } ++ ++ return adpctl.d32; ++} ++ ++/** ++ * Function is called to read ADPCTL register and filter Write-clear bits ++ */ ++uint32_t dwc_otg_adp_read_reg_filter(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ adpctl.b.adp_tmout_int = 0; ++ adpctl.b.adp_prb_int = 0; ++ adpctl.b.adp_tmout_int = 0; ++ ++ return adpctl.d32; ++} ++ ++/** ++ * Function is called to write ADP registers ++ */ ++void dwc_otg_adp_modify_reg(dwc_otg_core_if_t * core_if, uint32_t clr, ++ uint32_t set) ++{ ++ dwc_otg_adp_write_reg(core_if, ++ (dwc_otg_adp_read_reg(core_if) & (~clr)) | set); ++} ++ ++static void adp_sense_timeout(void *ptr) ++{ ++ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; ++ core_if->adp.sense_timer_started = 0; ++ DWC_PRINTF("ADP SENSE TIMEOUT\n"); ++ if (core_if->adp_enable) { ++ dwc_otg_adp_sense_stop(core_if); ++ dwc_otg_adp_probe_start(core_if); ++ } ++} ++ ++/** ++ * This function is called when the ADP vbus timer expires. Timeout is 1.1s. ++ */ ++static void adp_vbuson_timeout(void *ptr) ++{ ++ gpwrdn_data_t gpwrdn; ++ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ DWC_PRINTF("%s: 1.1 seconds expire after turning on VBUS\n",__FUNCTION__); ++ if (core_if) { ++ core_if->adp.vbuson_timer_started = 0; ++ /* Turn off vbus */ ++ hprt0.b.prtpwr = 1; ++ DWC_MODIFY_REG32(core_if->host_if->hprt0, hprt0.d32, 0); ++ gpwrdn.d32 = 0; ++ ++ /* Power off the core */ ++ if (core_if->power_down == 2) { ++ /* Enable Wakeup Logic */ ++// gpwrdn.b.wkupactiv = 1; ++ gpwrdn.b.pmuactv = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, ++ gpwrdn.d32); ++ ++ /* Suspend the Phy Clock */ ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ /* Switch on VDD */ ++// gpwrdn.b.wkupactiv = 1; ++ gpwrdn.b.pmuactv = 1; ++ gpwrdn.b.pwrdnrstn = 1; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, ++ gpwrdn.d32); ++ } else { ++ /* Enable Power Down Logic */ ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ /* Power off the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ } ++ ++ /* Unmask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ ++ dwc_otg_adp_probe_start(core_if); ++ dwc_otg_dump_global_registers(core_if); ++ dwc_otg_dump_host_registers(core_if); ++ } ++ ++} ++ ++/** ++ * Start the ADP Initial Probe timer to detect if Port Connected interrupt is ++ * not asserted within 1.1 seconds. ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++void dwc_otg_adp_vbuson_timer_start(dwc_otg_core_if_t * core_if) ++{ ++ core_if->adp.vbuson_timer_started = 1; ++ if (core_if->adp.vbuson_timer) ++ { ++ DWC_PRINTF("SCHEDULING VBUSON TIMER\n"); ++ /* 1.1 secs + 60ms necessary for cil_hcd_start*/ ++ DWC_TIMER_SCHEDULE(core_if->adp.vbuson_timer, 1160); ++ } else { ++ DWC_WARN("VBUSON_TIMER = %p\n",core_if->adp.vbuson_timer); ++ } ++} ++ ++#if 0 ++/** ++ * Masks all DWC OTG core interrupts ++ * ++ */ ++static void mask_all_interrupts(dwc_otg_core_if_t * core_if) ++{ ++ int i; ++ gahbcfg_data_t ahbcfg = {.d32 = 0 }; ++ ++ /* Mask Host Interrupts */ ++ ++ /* Clear and disable HCINTs */ ++ for (i = 0; i < core_if->core_params->host_channels; i++) { ++ DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, 0); ++ DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcint, 0xFFFFFFFF); ++ ++ } ++ ++ /* Clear and disable HAINT */ ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, 0x0000); ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haint, 0xFFFFFFFF); ++ ++ /* Mask Device Interrupts */ ++ if (!core_if->multiproc_int_enable) { ++ /* Clear and disable IN Endpoint interrupts */ ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, 0); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]-> ++ diepint, 0xFFFFFFFF); ++ } ++ ++ /* Clear and disable OUT Endpoint interrupts */ ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, 0); ++ for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]-> ++ doepint, 0xFFFFFFFF); ++ } ++ ++ /* Clear and disable DAINT */ ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daint, ++ 0xFFFFFFFF); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, 0); ++ } else { ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs-> ++ diepeachintmsk[i], 0); ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]-> ++ diepint, 0xFFFFFFFF); ++ } ++ ++ for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs-> ++ doepeachintmsk[i], 0); ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]-> ++ doepint, 0xFFFFFFFF); ++ } ++ ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachintmsk, ++ 0); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->deachint, ++ 0xFFFFFFFF); ++ ++ } ++ ++ /* Disable interrupts */ ++ ahbcfg.b.glblintrmsk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0); ++ ++ /* Disable all interrupts. */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0); ++ ++ /* Clear any pending interrupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Clear any pending OTG Interrupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gotgint, 0xFFFFFFFF); ++} ++ ++/** ++ * Unmask Port Connection Detected interrupt ++ * ++ */ ++static void unmask_conn_det_intr(dwc_otg_core_if_t * core_if) ++{ ++ gintmsk_data_t gintmsk = {.d32 = 0,.b.portintr = 1 }; ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32); ++} ++#endif ++ ++/** ++ * Starts the ADP Probing ++ * ++ * @param core_if the pointer to core_if structure. ++ */ ++uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if) ++{ ++ ++ adpctl_data_t adpctl = {.d32 = 0}; ++ gpwrdn_data_t gpwrdn; ++#if 0 ++ adpctl_data_t adpctl_int = {.d32 = 0, .b.adp_prb_int = 1, ++ .b.adp_sns_int = 1, b.adp_tmout_int}; ++#endif ++ dwc_otg_disable_global_interrupts(core_if); ++ DWC_PRINTF("ADP Probe Start\n"); ++ core_if->adp.probe_enabled = 1; ++ ++ adpctl.b.adpres = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ while (adpctl.b.adpres) { ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ } ++ ++ adpctl.d32 = 0; ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ /* In Host mode unmask SRP detected interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.sts_chngint_msk = 1; ++ if (!gpwrdn.b.idsts) { ++ gpwrdn.b.srp_det_msk = 1; ++ } ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ ++ adpctl.b.adp_tmout_int_msk = 1; ++ adpctl.b.adp_prb_int_msk = 1; ++ adpctl.b.prb_dschg = 1; ++ adpctl.b.prb_delta = 1; ++ adpctl.b.prb_per = 1; ++ adpctl.b.adpen = 1; ++ adpctl.b.enaprb = 1; ++ ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ DWC_PRINTF("ADP Probe Finish\n"); ++ return 0; ++} ++ ++/** ++ * Starts the ADP Sense timer to detect if ADP Sense interrupt is not asserted ++ * within 3 seconds. ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++void dwc_otg_adp_sense_timer_start(dwc_otg_core_if_t * core_if) ++{ ++ core_if->adp.sense_timer_started = 1; ++ DWC_TIMER_SCHEDULE(core_if->adp.sense_timer, 3000 /* 3 secs */ ); ++} ++ ++/** ++ * Starts the ADP Sense ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ DWC_PRINTF("ADP Sense Start\n"); ++ ++ /* Unmask ADP sense interrupt and mask all other from the core */ ++ adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if); ++ adpctl.b.adp_sns_int_msk = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ dwc_otg_disable_global_interrupts(core_if); // vahrama ++ ++ /* Set ADP reset bit*/ ++ adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if); ++ adpctl.b.adpres = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ while (adpctl.b.adpres) { ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ } ++ ++ adpctl.b.adpres = 0; ++ adpctl.b.adpen = 1; ++ adpctl.b.enasns = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ dwc_otg_adp_sense_timer_start(core_if); ++ ++ return 0; ++} ++ ++/** ++ * Stops the ADP Probing ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if) ++{ ++ ++ adpctl_data_t adpctl; ++ DWC_PRINTF("Stop ADP probe\n"); ++ core_if->adp.probe_enabled = 0; ++ core_if->adp.probe_counter = 0; ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ ++ adpctl.b.adpen = 0; ++ adpctl.b.adp_prb_int = 1; ++ adpctl.b.adp_tmout_int = 1; ++ adpctl.b.adp_sns_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * Stops the ADP Sensing ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ ++ core_if->adp.sense_enabled = 0; ++ ++ adpctl.d32 = dwc_otg_adp_read_reg_filter(core_if); ++ adpctl.b.enasns = 0; ++ adpctl.b.adp_sns_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * Called to turn on the VBUS after initial ADP probe in host mode. ++ * If port power was already enabled in cil_hcd_start function then ++ * only schedule a timer. ++ * ++ * @param core_if the pointer to core_if structure. ++ */ ++void dwc_otg_adp_turnon_vbus(dwc_otg_core_if_t * core_if) ++{ ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ DWC_PRINTF("Turn on VBUS for 1.1s, port power is %d\n", hprt0.b.prtpwr); ++ ++ if (hprt0.b.prtpwr == 0) { ++ hprt0.b.prtpwr = 1; ++ //DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } ++ ++ dwc_otg_adp_vbuson_timer_start(core_if); ++} ++ ++/** ++ * Called right after driver is loaded ++ * to perform initial actions for ADP ++ * ++ * @param core_if the pointer to core_if structure. ++ * @param is_host - flag for current mode of operation either from GINTSTS or GPWRDN ++ */ ++void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host) ++{ ++ gpwrdn_data_t gpwrdn; ++ ++ DWC_PRINTF("ADP Initial Start\n"); ++ core_if->adp.adp_started = 1; ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ dwc_otg_disable_global_interrupts(core_if); ++ if (is_host) { ++ DWC_PRINTF("HOST MODE\n"); ++ /* Enable Power Down Logic Interrupt*/ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ /* Initialize first ADP probe to obtain Ramp Time value */ ++ core_if->adp.initial_probe = 1; ++ dwc_otg_adp_probe_start(core_if); ++ } else { ++ gotgctl_data_t gotgctl; ++ gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ DWC_PRINTF("DEVICE MODE\n"); ++ if (gotgctl.b.bsesvld == 0) { ++ /* Enable Power Down Logic Interrupt*/ ++ gpwrdn.d32 = 0; ++ DWC_PRINTF("VBUS is not valid - start ADP probe\n"); ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ core_if->adp.initial_probe = 1; ++ dwc_otg_adp_probe_start(core_if); ++ } else { ++ DWC_PRINTF("VBUS is valid - initialize core as a Device\n"); ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ dwc_otg_dump_global_registers(core_if); ++ dwc_otg_dump_dev_registers(core_if); ++ } ++ } ++} ++ ++void dwc_otg_adp_init(dwc_otg_core_if_t * core_if) ++{ ++ core_if->adp.adp_started = 0; ++ core_if->adp.initial_probe = 0; ++ core_if->adp.probe_timer_values[0] = -1; ++ core_if->adp.probe_timer_values[1] = -1; ++ core_if->adp.probe_enabled = 0; ++ core_if->adp.sense_enabled = 0; ++ core_if->adp.sense_timer_started = 0; ++ core_if->adp.vbuson_timer_started = 0; ++ core_if->adp.probe_counter = 0; ++ core_if->adp.gpwrdn = 0; ++ core_if->adp.attached = DWC_OTG_ADP_UNKOWN; ++ /* Initialize timers */ ++ core_if->adp.sense_timer = ++ DWC_TIMER_ALLOC("ADP SENSE TIMER", adp_sense_timeout, core_if); ++ core_if->adp.vbuson_timer = ++ DWC_TIMER_ALLOC("ADP VBUS ON TIMER", adp_vbuson_timeout, core_if); ++ if (!core_if->adp.sense_timer || !core_if->adp.vbuson_timer) ++ { ++ DWC_ERROR("Could not allocate memory for ADP timers\n"); ++ } ++} ++ ++void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = { .d32 = 0 }; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ if (core_if->adp.probe_enabled) ++ dwc_otg_adp_probe_stop(core_if); ++ if (core_if->adp.sense_enabled) ++ dwc_otg_adp_sense_stop(core_if); ++ if (core_if->adp.sense_timer_started) ++ DWC_TIMER_CANCEL(core_if->adp.sense_timer); ++ if (core_if->adp.vbuson_timer_started) ++ DWC_TIMER_CANCEL(core_if->adp.vbuson_timer); ++ DWC_TIMER_FREE(core_if->adp.sense_timer); ++ DWC_TIMER_FREE(core_if->adp.vbuson_timer); ++} ++ ++///////////////////////////////////////////////////////////////////// ++////////////// ADP Interrupt Handlers /////////////////////////////// ++///////////////////////////////////////////////////////////////////// ++/** ++ * This function sets Ramp Timer values ++ */ ++static uint32_t set_timer_value(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ if (core_if->adp.probe_timer_values[0] == -1) { ++ core_if->adp.probe_timer_values[0] = val; ++ core_if->adp.probe_timer_values[1] = -1; ++ return 1; ++ } else { ++ core_if->adp.probe_timer_values[1] = ++ core_if->adp.probe_timer_values[0]; ++ core_if->adp.probe_timer_values[0] = val; ++ return 0; ++ } ++} ++ ++/** ++ * This function compares Ramp Timer values ++ */ ++static uint32_t compare_timer_values(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t diff; ++ if (core_if->adp.probe_timer_values[0]>=core_if->adp.probe_timer_values[1]) ++ diff = core_if->adp.probe_timer_values[0]-core_if->adp.probe_timer_values[1]; ++ else ++ diff = core_if->adp.probe_timer_values[1]-core_if->adp.probe_timer_values[0]; ++ if(diff < 2) { ++ return 0; ++ } else { ++ return 1; ++ } ++} ++ ++/** ++ * This function handles ADP Probe Interrupts ++ */ ++static int32_t dwc_otg_adp_handle_prb_intr(dwc_otg_core_if_t * core_if, ++ uint32_t val) ++{ ++ adpctl_data_t adpctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn, temp; ++ adpctl.d32 = val; ++ ++ temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ core_if->adp.probe_counter++; ++ core_if->adp.gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (adpctl.b.rtim == 0 && !temp.b.idsts){ ++ DWC_PRINTF("RTIM value is 0\n"); ++ goto exit; ++ } ++ if (set_timer_value(core_if, adpctl.b.rtim) && ++ core_if->adp.initial_probe) { ++ core_if->adp.initial_probe = 0; ++ dwc_otg_adp_probe_stop(core_if); ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* check which value is for device mode and which for Host mode */ ++ if (!temp.b.idsts) { /* considered host mode value is 0 */ ++ /* ++ * Turn on VBUS after initial ADP probe. ++ */ ++ core_if->op_state = A_HOST; ++ dwc_otg_enable_global_interrupts(core_if); ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_hcd_start(core_if); ++ dwc_otg_adp_turnon_vbus(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ } else { ++ /* ++ * Initiate SRP after initial ADP probe. ++ */ ++ dwc_otg_enable_global_interrupts(core_if); ++ dwc_otg_initiate_srp(core_if); ++ } ++ } else if (core_if->adp.probe_counter > 2){ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (compare_timer_values(core_if)) { ++ DWC_PRINTF("Difference in timer values !!! \n"); ++// core_if->adp.attached = DWC_OTG_ADP_ATTACHED; ++ dwc_otg_adp_probe_stop(core_if); ++ ++ /* Power on the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ /* check which value is for device mode and which for Host mode */ ++ if (!temp.b.idsts) { /* considered host mode value is 0 */ ++ /* Disable Interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Host mode. ++ */ ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } else { ++ gotgctl_data_t gotgctl; ++ /* Mask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* Disable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Device mode. ++ */ ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ ++ gotgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ if (!gotgctl.b.bsesvld) { ++ dwc_otg_initiate_srp(core_if); ++ } ++ } ++ } ++ if (core_if->power_down == 2) { ++ if (gpwrdn.b.bsessvld) { ++ /* Mask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Disable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Device mode. ++ */ ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } ++ } ++ } ++exit: ++ /* Clear interrupt */ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ adpctl.b.adp_prb_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * This function hadles ADP Sense Interrupt ++ */ ++static int32_t dwc_otg_adp_handle_sns_intr(dwc_otg_core_if_t * core_if) ++{ ++ adpctl_data_t adpctl; ++ /* Stop ADP Sense timer */ ++ DWC_TIMER_CANCEL(core_if->adp.sense_timer); ++ ++ /* Restart ADP Sense timer */ ++ dwc_otg_adp_sense_timer_start(core_if); ++ ++ /* Clear interrupt */ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ adpctl.b.adp_sns_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * This function handles ADP Probe Interrupts ++ */ ++static int32_t dwc_otg_adp_handle_prb_tmout_intr(dwc_otg_core_if_t * core_if, ++ uint32_t val) ++{ ++ adpctl_data_t adpctl = {.d32 = 0 }; ++ adpctl.d32 = val; ++ set_timer_value(core_if, adpctl.b.rtim); ++ ++ /* Clear interrupt */ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ adpctl.b.adp_tmout_int = 1; ++ dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ ++ return 0; ++} ++ ++/** ++ * ADP Interrupt handler. ++ * ++ */ ++int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if) ++{ ++ int retval = 0; ++ adpctl_data_t adpctl = {.d32 = 0}; ++ ++ adpctl.d32 = dwc_otg_adp_read_reg(core_if); ++ DWC_PRINTF("ADPCTL = %08x\n",adpctl.d32); ++ ++ if (adpctl.b.adp_sns_int & adpctl.b.adp_sns_int_msk) { ++ DWC_PRINTF("ADP Sense interrupt\n"); ++ retval |= dwc_otg_adp_handle_sns_intr(core_if); ++ } ++ if (adpctl.b.adp_tmout_int & adpctl.b.adp_tmout_int_msk) { ++ DWC_PRINTF("ADP timeout interrupt\n"); ++ retval |= dwc_otg_adp_handle_prb_tmout_intr(core_if, adpctl.d32); ++ } ++ if (adpctl.b.adp_prb_int & adpctl.b.adp_prb_int_msk) { ++ DWC_PRINTF("ADP Probe interrupt\n"); ++ adpctl.b.adp_prb_int = 1; ++ retval |= dwc_otg_adp_handle_prb_intr(core_if, adpctl.d32); ++ } ++ ++// dwc_otg_adp_modify_reg(core_if, adpctl.d32, 0); ++ //dwc_otg_adp_write_reg(core_if, adpctl.d32); ++ DWC_PRINTF("RETURN FROM ADP ISR\n"); ++ ++ return retval; ++} ++ ++/** ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if) ++{ ++ ++#ifndef DWC_HOST_ONLY ++ hprt0_data_t hprt0; ++ gpwrdn_data_t gpwrdn; ++ DWC_DEBUGPL(DBG_ANY, "++ Power Down Logic Session Request Interrupt++\n"); ++ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ /* check which value is for device mode and which for Host mode */ ++ if (!gpwrdn.b.idsts) { /* considered host mode value is 0 */ ++ DWC_PRINTF("SRP: Host mode\n"); ++ ++ if (core_if->adp_enable) { ++ dwc_otg_adp_probe_stop(core_if); ++ ++ /* Power on the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++ ++ /* Turn on the port power bit. */ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 1; ++ 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. */ ++ cil_hcd_session_start(core_if); ++ } else { ++ DWC_PRINTF("SRP: Device mode %s\n", __FUNCTION__); ++ if (core_if->adp_enable) { ++ dwc_otg_adp_probe_stop(core_if); ++ ++ /* Power on the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 0; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, ++ gpwrdn.d32); ++ ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } ++ } ++#endif ++ return 1; ++} +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_adp.h b/drivers/usb/host/dwc_otg/dwc_otg_adp.h +new file mode 100644 +index 0000000..d8c3f85 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_adp.h +@@ -0,0 +1,80 @@ ++/* ========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_adp.h $ ++ * $Revision: #7 $ ++ * $Date: 2011/10/24 $ ++ * $Change: 1871159 $ ++ * ++ * 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 ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++ ++#ifndef __DWC_OTG_ADP_H__ ++#define __DWC_OTG_ADP_H__ ++ ++/** ++ * @file ++ * ++ * This file contains the Attach Detect Protocol interfaces and defines ++ * (functions) and structures for Linux. ++ * ++ */ ++ ++#define DWC_OTG_ADP_UNATTACHED 0 ++#define DWC_OTG_ADP_ATTACHED 1 ++#define DWC_OTG_ADP_UNKOWN 2 ++ ++typedef struct dwc_otg_adp { ++ uint32_t adp_started; ++ uint32_t initial_probe; ++ int32_t probe_timer_values[2]; ++ uint32_t probe_enabled; ++ uint32_t sense_enabled; ++ dwc_timer_t *sense_timer; ++ uint32_t sense_timer_started; ++ dwc_timer_t *vbuson_timer; ++ uint32_t vbuson_timer_started; ++ uint32_t attached; ++ uint32_t probe_counter; ++ uint32_t gpwrdn; ++} dwc_otg_adp_t; ++ ++/** ++ * Attach Detect Protocol functions ++ */ ++ ++extern void dwc_otg_adp_write_reg(dwc_otg_core_if_t * core_if, uint32_t value); ++extern uint32_t dwc_otg_adp_read_reg(dwc_otg_core_if_t * core_if); ++extern uint32_t dwc_otg_adp_probe_start(dwc_otg_core_if_t * core_if); ++extern uint32_t dwc_otg_adp_sense_start(dwc_otg_core_if_t * core_if); ++extern uint32_t dwc_otg_adp_probe_stop(dwc_otg_core_if_t * core_if); ++extern uint32_t dwc_otg_adp_sense_stop(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host); ++extern void dwc_otg_adp_init(dwc_otg_core_if_t * core_if); ++extern void dwc_otg_adp_remove(dwc_otg_core_if_t * core_if); ++extern int32_t dwc_otg_adp_handle_intr(dwc_otg_core_if_t * core_if); ++extern int32_t dwc_otg_adp_handle_srp_intr(dwc_otg_core_if_t * core_if); ++ ++#endif //__DWC_OTG_ADP_H__ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.c b/drivers/usb/host/dwc_otg/dwc_otg_attr.c +new file mode 100644 +index 0000000..95eb7f8 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.c +@@ -0,0 +1,1210 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.c $ -+ * $Revision: #35 $ -+ * $Date: 2009/04/03 $ -+ * $Change: 1225160 $ ++ * $Revision: #44 $ ++ * $Date: 2010/11/29 $ ++ * $Change: 1636033 $ + * + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless @@ -37270,6 +45982,37 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + + + ++ rem_wakeup_pwrdn ++ On read, shows the status core - hibernated or not. On write, initiates ++ a remote wakeup of the device from Hibernation. ++ Read/Write ++ ++ ++ ++ mode_ch_tim_en ++ This bit is used to enable or disable the host core to wait for 200 PHY ++ clock cycles at the end of Resume to change the opmode signal to the PHY to 00 ++ after Suspend or LPM. ++ Read/Write ++ ++ ++ ++ fr_interval ++ On read, shows the value of HFIR Frame Interval. On write, dynamically ++ reload HFIR register during runtime. The application can write a value to this ++ register only after the Port Enable bit of the Host Port Control and Status ++ register (HPRT.PrtEnaPort) has been set ++ Read/Write ++ ++ ++ ++ disconnect_us ++ On read, shows the status of disconnect_device_us. On write, sets disconnect_us ++ which causes soft disconnect for 100us. Applicable only for device mode of operation. ++ Read/Write ++ ++ ++ + regdump + Dumps the contents of core registers. + Read @@ -37319,12 +46062,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + + + -+ sleep_local_dev -+ Generetates sleep signaling. Applicable only in host mode. -+ Write -+ -+ -+ + sleep_status + Shows sleep status of device. + Read @@ -37340,36 +46077,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + echo 0 > /sys/devices/lm0/buspower + */ + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include /* permission constants */ -+#include -+#include -+#include -+#include -+ -+ -+#ifdef LM_INTERFACE -+#include -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+#include -+#else -+/* in 2.6.31, at least, we seem to have lost the generic LM infrastructure - -+ here we use definitions stolen from arm-integrator headers -+*/ -+#include -+#endif -+#elif defined(PLATFORM_INTERFACE) -+#include -+#endif -+ -+#include -+ ++#include "dwc_otg_os_dep.h" +#include "dwc_os.h" +#include "dwc_otg_driver.h" +#include "dwc_otg_attr.h" @@ -37538,24 +46246,24 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- +/**@{*/ + +/** ++ * Helper function returning the otg_device structure of the given device ++ */ ++static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev) ++{ ++ dwc_otg_device_t *otg_dev; ++ DWC_OTG_GETDRVDEV(otg_dev, _dev); ++ return otg_dev; ++} ++ ++/** + * Show the register offset of the Register Access. + */ +static ssize_t regoffset_show(struct device *_dev, + struct device_attribute *attr, char *buf) +{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = container_of(_dev, -+ struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + return snprintf(buf, sizeof("0xFFFFFFFF\n") + 1, "0x%08x\n", -+ otg_dev->reg_offset); ++ otg_dev->os_dep.reg_offset); +} + +/** @@ -37565,20 +46273,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + struct device_attribute *attr, + const char *buf, size_t count) +{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = container_of(_dev, -+ struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + uint32_t offset = simple_strtoul(buf, NULL, 16); -+ if (offset < SZ_256K) { -+ otg_dev->reg_offset = offset; ++#if defined(LM_INTERFACE) || defined(PLATFORM_INTERFACE) ++ if (offset < SZ_256K) { ++#elif defined(PCI_INTERFACE) ++ if (offset < 0x00040000) { ++#endif ++ otg_dev->os_dep.reg_offset = offset; + } else { + dev_err(_dev, "invalid offset\n"); + } @@ -37595,31 +46297,21 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- +static ssize_t regvalue_show(struct device *_dev, + struct device_attribute *attr, char *buf) +{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + uint32_t val; + volatile uint32_t *addr; + -+ if (otg_dev->reg_offset != 0xFFFFFFFF && 0 != otg_dev->base) { ++ if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) { + /* Calculate the address */ -+ addr = (uint32_t *) (otg_dev->reg_offset + -+ (uint8_t *) otg_dev->base); -+ val = dwc_read_reg32(addr); ++ addr = (uint32_t *) (otg_dev->os_dep.reg_offset + ++ (uint8_t *) otg_dev->os_dep.base); ++ val = DWC_READ_REG32(addr); + return snprintf(buf, + sizeof("Reg@0xFFFFFFFF = 0xFFFFFFFF\n") + 1, -+ "Reg@0x%06x = 0x%08x\n", otg_dev->reg_offset, ++ "Reg@0x%06x = 0x%08x\n", otg_dev->os_dep.reg_offset, + val); + } else { -+ dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->reg_offset); ++ dev_err(_dev, "Invalid offset (0x%0x)\n", otg_dev->os_dep.reg_offset); + return sprintf(buf, "invalid offset\n"); + } +} @@ -37633,28 +46325,18 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + struct device_attribute *attr, + const char *buf, size_t count) +{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + volatile uint32_t *addr; + uint32_t val = simple_strtoul(buf, NULL, 16); + //dev_dbg(_dev, "Offset=0x%08x Val=0x%08x\n", otg_dev->reg_offset, val); -+ if (otg_dev->reg_offset != 0xFFFFFFFF && 0 != otg_dev->base) { ++ if (otg_dev->os_dep.reg_offset != 0xFFFFFFFF && 0 != otg_dev->os_dep.base) { + /* Calculate the address */ -+ addr = (uint32_t *) (otg_dev->reg_offset + -+ (uint8_t *) otg_dev->base); -+ dwc_write_reg32(addr, val); ++ addr = (uint32_t *) (otg_dev->os_dep.reg_offset + ++ (uint8_t *) otg_dev->os_dep.base); ++ DWC_WRITE_REG32(addr, val); + } else { + dev_err(_dev, "Invalid Register Offset (0x%08x)\n", -+ otg_dev->reg_offset); ++ otg_dev->os_dep.reg_offset); + } + return count; +} @@ -37666,7 +46348,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + */ +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode, "Mode"); +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable, "HNPCapable"); -+DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, "Mode"); ++DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable, "SRPCapable"); +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hsic_connect, "HSIC Connect"); +DWC_OTG_DEVICE_ATTR_BITFIELD_RW(inv_sel_hsic, "Invert Select HSIC"); + @@ -37712,16 +46394,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- +static ssize_t hnp_show(struct device *_dev, + struct device_attribute *attr, char *buf) +{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + return sprintf(buf, "HstNegScs = 0x%x\n", + dwc_otg_get_hnpstatus(otg_dev->core_if)); +} @@ -37733,16 +46406,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + struct device_attribute *attr, + const char *buf, size_t count) +{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + uint32_t in = simple_strtoul(buf, NULL, 16); + dwc_otg_set_hnpreq(otg_dev->core_if, in); + return count; @@ -37760,16 +46424,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + struct device_attribute *attr, char *buf) +{ +#ifndef DWC_HOST_ONLY -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + return sprintf(buf, "SesReqScs = 0x%x\n", + dwc_otg_get_srpstatus(otg_dev->core_if)); +#else @@ -37785,16 +46440,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + const char *buf, size_t count) +{ +#ifndef DWC_HOST_ONLY -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + dwc_otg_pcd_initiate_srp(otg_dev->pcd); +#endif + return count; @@ -37811,16 +46457,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- +static ssize_t buspower_show(struct device *_dev, + struct device_attribute *attr, char *buf) +{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + return sprintf(buf, "Bus Power = 0x%x\n", + dwc_otg_get_prtpower(otg_dev->core_if)); +} @@ -37832,16 +46469,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + struct device_attribute *attr, + const char *buf, size_t count) +{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + uint32_t on = simple_strtoul(buf, NULL, 16); + dwc_otg_set_prtpower(otg_dev->core_if, on); + return count; @@ -37858,17 +46486,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- +static ssize_t bussuspend_show(struct device *_dev, + struct device_attribute *attr, char *buf) +{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + return sprintf(buf, "Bus Suspend = 0x%x\n", + dwc_otg_get_prtsuspend(otg_dev->core_if)); +} @@ -37880,17 +46498,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + struct device_attribute *attr, + const char *buf, size_t count) +{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + uint32_t in = simple_strtoul(buf, NULL, 16); + dwc_otg_set_prtsuspend(otg_dev->core_if, in); + return count; @@ -37899,22 +46507,65 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- +DEVICE_ATTR(bussuspend, 0644, bussuspend_show, bussuspend_store); + +/** ++ * Show the Mode Change Ready Timer status ++ */ ++static ssize_t mode_ch_tim_en_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ return sprintf(buf, "Mode Change Ready Timer Enable = 0x%x\n", ++ dwc_otg_get_mode_ch_tim(otg_dev->core_if)); ++} ++ ++/** ++ * Set the Mode Change Ready Timer status ++ */ ++static ssize_t mode_ch_tim_en_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ uint32_t in = simple_strtoul(buf, NULL, 16); ++ dwc_otg_set_mode_ch_tim(otg_dev->core_if, in); ++ return count; ++} ++ ++DEVICE_ATTR(mode_ch_tim_en, 0644, mode_ch_tim_en_show, mode_ch_tim_en_store); ++ ++/** ++ * Show the value of HFIR Frame Interval bitfield ++ */ ++static ssize_t fr_interval_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ return sprintf(buf, "Frame Interval = 0x%x\n", ++ dwc_otg_get_fr_interval(otg_dev->core_if)); ++} ++ ++/** ++ * Set the HFIR Frame Interval value ++ */ ++static ssize_t fr_interval_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ uint32_t in = simple_strtoul(buf, NULL, 10); ++ dwc_otg_set_fr_interval(otg_dev->core_if, in); ++ return count; ++} ++ ++DEVICE_ATTR(fr_interval, 0644, fr_interval_show, fr_interval_store); ++ ++/** + * Show the status of Remote Wakeup. + */ +static ssize_t remote_wakeup_show(struct device *_dev, + struct device_attribute *attr, char *buf) +{ +#ifndef DWC_HOST_ONLY -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + + return sprintf(buf, + "Remote Wakeup Sig = %d Enabled = %d LPM Remote Wakeup = %d\n", @@ -37937,17 +46588,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + const char *buf, size_t count) +{ +#ifndef DWC_HOST_ONLY -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + uint32_t val = simple_strtoul(buf, NULL, 16); + + if (val & 1) { @@ -37963,22 +46604,69 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + remote_wakeup_store); + +/** ++ * Show the whether core is hibernated or not. ++ */ ++static ssize_t rem_wakeup_pwrdn_show(struct device *_dev, ++ struct device_attribute *attr, char *buf) ++{ ++#ifndef DWC_HOST_ONLY ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ ++ if (dwc_otg_get_core_state(otg_dev->core_if)) { ++ DWC_PRINTF("Core is in hibernation\n"); ++ } else { ++ DWC_PRINTF("Core is not in hibernation\n"); ++ } ++#endif /* DWC_HOST_ONLY */ ++ return 0; ++} ++ ++extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int rem_wakeup, int reset); ++ ++/** ++ * Initiate a remote wakeup of the device to exit from hibernation. ++ */ ++static ssize_t rem_wakeup_pwrdn_store(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++#ifndef DWC_HOST_ONLY ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ dwc_otg_device_hibernation_restore(otg_dev->core_if, 1, 0); ++#endif ++ return count; ++} ++ ++DEVICE_ATTR(rem_wakeup_pwrdn, S_IRUGO | S_IWUSR, rem_wakeup_pwrdn_show, ++ rem_wakeup_pwrdn_store); ++ ++static ssize_t disconnect_us(struct device *_dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ ++#ifndef DWC_HOST_ONLY ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); ++ uint32_t val = simple_strtoul(buf, NULL, 16); ++ DWC_PRINTF("The Passed value is %04x\n", val); ++ ++ dwc_otg_pcd_disconnect_us(otg_dev->pcd, 50); ++ ++#endif /* DWC_HOST_ONLY */ ++ return count; ++} ++ ++DEVICE_ATTR(disconnect_us, S_IWUSR, 0, disconnect_us); ++ ++/** + * Dump global registers and either host or device registers (depending on the + * current mode of the core). + */ +static ssize_t regdump_show(struct device *_dev, + struct device_attribute *attr, char *buf) +{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + + dwc_otg_dump_global_registers(otg_dev->core_if); + if (dwc_otg_is_host_mode(otg_dev->core_if)) { @@ -37999,16 +46687,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- +static ssize_t spramdump_show(struct device *_dev, + struct device_attribute *attr, char *buf) +{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + + dwc_otg_dump_spram(otg_dev->core_if); + @@ -38024,17 +46703,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + struct device_attribute *attr, char *buf) +{ +#ifndef DWC_DEVICE_ONLY -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + dwc_otg_hcd_dump_state(otg_dev->hcd); +#endif /* DWC_DEVICE_ONLY */ + return sprintf(buf, "HCD Dump\n"); @@ -38051,16 +46720,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + struct device_attribute *attr, char *buf) +{ +#ifndef DWC_DEVICE_ONLY -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + + dwc_otg_hcd_dump_frrem(otg_dev->hcd); +#endif /* DWC_DEVICE_ONLY */ @@ -38078,17 +46738,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- +static ssize_t rd_reg_test_show(struct device *_dev, + struct device_attribute *attr, char *buf) +{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + int i; + int time; + int start_jiffies; @@ -38114,17 +46764,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- +static ssize_t wr_reg_test_show(struct device *_dev, + struct device_attribute *attr, char *buf) +{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + uint32_t reg_val; + int i; + int time; @@ -38153,16 +46793,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- +static ssize_t lpmresp_show(struct device *_dev, + struct device_attribute *attr, char *buf) +{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + + if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) + return sprintf(buf, "** LPM is DISABLED **\n"); @@ -38181,17 +46812,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + struct device_attribute *attr, + const char *buf, size_t count) +{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + uint32_t val = simple_strtoul(buf, NULL, 16); + + if (!dwc_otg_get_param_lpm_enable(otg_dev->core_if)) { @@ -38214,18 +46835,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- +static ssize_t sleepstatus_show(struct device *_dev, + struct device_attribute *attr, char *buf) +{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ -+ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + return sprintf(buf, "Sleep Status = %d\n", + dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)); +} @@ -38237,17 +46847,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + struct device_attribute *attr, + const char *buf, size_t count) +{ -+#ifdef LM_INTERFACE -+ struct lm_device *lm_dev = container_of(_dev, struct lm_device, dev); -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(lm_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = dev_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platform_dev = -+ container_of(_dev, struct platform_device, dev); -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(platform_dev); -+#endif -+ ++ dwc_otg_device_t *otg_dev = dwc_otg_drvdev(_dev); + dwc_otg_core_if_t *core_if = otg_dev->core_if; + + if (dwc_otg_get_lpm_portsleepstatus(otg_dev->core_if)) { @@ -38264,23 +46864,22 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- +DEVICE_ATTR(sleep_status, S_IRUGO | S_IWUSR, sleepstatus_show, + sleepstatus_store); + -+#endif /* CONFIG_USB_DWC_OTG_LPM_ENABLE */ ++#endif /* CONFIG_USB_DWC_OTG_LPM_ENABLE */ + +/**@}*/ + +/** + * Create the device files + */ -+void dwc_otg_attr_create ( ++void dwc_otg_attr_create( +#ifdef LM_INTERFACE + struct lm_device *dev +#elif defined(PCI_INTERFACE) + struct pci_dev *dev +#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *dev ++ struct platform_device *dev +#endif -+ ) -+ ++ ) +{ + int error; + @@ -38295,6 +46894,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + error = device_create_file(&dev->dev, &dev_attr_srp); + error = device_create_file(&dev->dev, &dev_attr_buspower); + error = device_create_file(&dev->dev, &dev_attr_bussuspend); ++ error = device_create_file(&dev->dev, &dev_attr_mode_ch_tim_en); ++ error = device_create_file(&dev->dev, &dev_attr_fr_interval); + error = device_create_file(&dev->dev, &dev_attr_busconnected); + error = device_create_file(&dev->dev, &dev_attr_gotgctl); + error = device_create_file(&dev->dev, &dev_attr_gusbcfg); @@ -38309,6 +46910,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + error = device_create_file(&dev->dev, &dev_attr_hptxfsiz); + error = device_create_file(&dev->dev, &dev_attr_hprt0); + error = device_create_file(&dev->dev, &dev_attr_remote_wakeup); ++ error = device_create_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn); ++ error = device_create_file(&dev->dev, &dev_attr_disconnect_us); + error = device_create_file(&dev->dev, &dev_attr_regdump); + error = device_create_file(&dev->dev, &dev_attr_spramdump); + error = device_create_file(&dev->dev, &dev_attr_hcddump); @@ -38324,7 +46927,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- +/** + * Remove the device files + */ -+void dwc_otg_attr_remove ( ++void dwc_otg_attr_remove( +#ifdef LM_INTERFACE + struct lm_device *dev +#elif defined(PCI_INTERFACE) @@ -38332,8 +46935,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- +#elif defined(PLATFORM_INTERFACE) + struct platform_device *dev +#endif -+ ) -+ ++ ) +{ + device_remove_file(&dev->dev, &dev_attr_regoffset); + device_remove_file(&dev->dev, &dev_attr_regvalue); @@ -38346,6 +46948,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + device_remove_file(&dev->dev, &dev_attr_srp); + device_remove_file(&dev->dev, &dev_attr_buspower); + device_remove_file(&dev->dev, &dev_attr_bussuspend); ++ device_remove_file(&dev->dev, &dev_attr_mode_ch_tim_en); ++ device_remove_file(&dev->dev, &dev_attr_fr_interval); + device_remove_file(&dev->dev, &dev_attr_busconnected); + device_remove_file(&dev->dev, &dev_attr_gotgctl); + device_remove_file(&dev->dev, &dev_attr_gusbcfg); @@ -38360,6 +46964,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + device_remove_file(&dev->dev, &dev_attr_hptxfsiz); + device_remove_file(&dev->dev, &dev_attr_hprt0); + device_remove_file(&dev->dev, &dev_attr_remote_wakeup); ++ device_remove_file(&dev->dev, &dev_attr_rem_wakeup_pwrdn); ++ device_remove_file(&dev->dev, &dev_attr_disconnect_us); + device_remove_file(&dev->dev, &dev_attr_regdump); + device_remove_file(&dev->dev, &dev_attr_spramdump); + device_remove_file(&dev->dev, &dev_attr_hcddump); @@ -38371,15 +46977,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.c linux-rpi-bootc- + device_remove_file(&dev->dev, &dev_attr_sleep_status); +#endif +} -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.h linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.h ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.h 2012-07-15 20:29:19.065083268 +0200 -@@ -0,0 +1,88 @@ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_attr.h b/drivers/usb/host/dwc_otg/dwc_otg_attr.h +new file mode 100644 +index 0000000..fc14d94 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_attr.h +@@ -0,0 +1,89 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_attr.h $ -+ * $Revision: #11 $ -+ * $Date: 2009/04/03 $ -+ * $Change: 1225160 $ ++ * $Revision: #13 $ ++ * $Date: 2010/06/21 $ ++ * $Change: 1532021 $ + * + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless @@ -38424,6 +47032,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.h linux-rpi-bootc- +extern struct device_attribute dev_attr_srp; +extern struct device_attribute dev_attr_buspower; +extern struct device_attribute dev_attr_bussuspend; ++extern struct device_attribute dev_attr_mode_ch_tim_en; ++extern struct device_attribute dev_attr_fr_interval; +extern struct device_attribute dev_attr_busconnected; +extern struct device_attribute dev_attr_gotgctl; +extern struct device_attribute dev_attr_gusbcfg; @@ -38439,33 +47049,34 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_attr.h linux-rpi-bootc- +extern struct device_attribute dev_attr_hprt0; +#ifdef CONFIG_USB_DWC_OTG_LPM +extern struct device_attribute dev_attr_lpm_response; -+extern struct device_attribute dev_attr_sleep_local_dev; +extern struct device_attribute devi_attr_sleep_status; +#endif + -+void dwc_otg_attr_create ( ++void dwc_otg_attr_create( +#ifdef LM_INTERFACE -+ struct lm_device *dev ++ struct lm_device *dev +#elif defined(PCI_INTERFACE) -+ struct pci_dev *dev ++ struct pci_dev *dev +#elif defined(PLATFORM_INTERFACE) + struct platform_device *dev +#endif -+ ); ++ ); + -+void dwc_otg_attr_remove ( ++void dwc_otg_attr_remove( +#ifdef LM_INTERFACE -+ struct lm_device *dev ++ struct lm_device *dev +#elif defined(PCI_INTERFACE) -+ struct pci_dev *dev ++ struct pci_dev *dev +#elif defined(PLATFORM_INTERFACE) + struct platform_device *dev +#endif -+ ); ++ ); +#endif -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c 2012-07-15 20:29:19.180085427 +0200 +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cfi.c b/drivers/usb/host/dwc_otg/dwc_otg_cfi.c +new file mode 100644 +index 0000000..a9878d6 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.c @@ -0,0 +1,1876 @@ +/* ========================================================================== + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, @@ -38497,7 +47108,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 + +/** @file + * -+ * This file contains the most of the CFI implementation for the OTG. ++ * This file contains the most of the CFI(Core Feature Interface) ++ * implementation for the OTG. + */ + +#ifdef DWC_UTE_CFI @@ -38754,7 +47366,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 + if (wValue == 0) { + /* @TODO - MAS - fix the access to the base field */ + regaddr = 0; -+ //regaddr = (uint32_t) pcd->otg_dev->base; ++ //regaddr = (uint32_t) pcd->otg_dev->os_dep.base; + //GET_CORE_IF(pcd)->co + regaddr |= wIndex; + } else { @@ -38762,7 +47374,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 + } + + /* Read a 32-bit value of the memory at the regaddr */ -+ regval = dwc_read_reg32((uint32_t *) regaddr); ++ regval = DWC_READ_REG32((uint32_t *) regaddr); + + ep = &pcd->ep0; + dwc_memcpy(cfi->buf_in.buf, ®val, sizeof(uint32_t)); @@ -38875,13 +47487,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 + CFI_INFO("%s\n", __func__); + + if (cfiobj->buf_in.buf) { -+ dwc_dma_free(CFI_IN_BUF_LEN, cfiobj->buf_in.buf, ++ DWC_DMA_FREE(CFI_IN_BUF_LEN, cfiobj->buf_in.buf, + cfiobj->buf_in.addr); + cfiobj->buf_in.buf = NULL; + } + + if (cfiobj->buf_out.buf) { -+ dwc_dma_free(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf, ++ DWC_DMA_FREE(CFI_OUT_BUF_LEN, cfiobj->buf_out.buf, + cfiobj->buf_out.addr); + cfiobj->buf_out.buf = NULL; + } @@ -38900,21 +47512,21 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 +static void cfi_free_ep_bs_dyn_data(cfi_ep_t * cfiep) +{ + if (cfiep->bm_sg) { -+ dwc_free(cfiep->bm_sg); ++ DWC_FREE(cfiep->bm_sg); + cfiep->bm_sg = NULL; + } + + if (cfiep->bm_align) { -+ dwc_free(cfiep->bm_align); ++ DWC_FREE(cfiep->bm_align); + cfiep->bm_align = NULL; + } + + if (cfiep->bm_concat) { + if (NULL != cfiep->bm_concat->wTxBytes) { -+ dwc_free(cfiep->bm_concat->wTxBytes); ++ DWC_FREE(cfiep->bm_concat->wTxBytes); + cfiep->bm_concat->wTxBytes = NULL; + } -+ dwc_free(cfiep->bm_concat); ++ DWC_FREE(cfiep->bm_concat); + cfiep->bm_concat = NULL; + } +} @@ -38928,7 +47540,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 +{ + int retval = 0; + -+ cfiep->bm_sg = dwc_alloc(sizeof(ddma_sg_buffer_setup_t)); ++ cfiep->bm_sg = DWC_ALLOC(sizeof(ddma_sg_buffer_setup_t)); + if (NULL == cfiep->bm_sg) { + CFI_INFO("Failed to allocate memory for SG feature value\n"); + return -DWC_E_NO_MEMORY; @@ -38939,21 +47551,21 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 + * memory for the wTxBytes field - it will be done in the set_feature_value + * request handler. + */ -+ cfiep->bm_concat = dwc_alloc(sizeof(ddma_concat_buffer_setup_t)); ++ cfiep->bm_concat = DWC_ALLOC(sizeof(ddma_concat_buffer_setup_t)); + if (NULL == cfiep->bm_concat) { + CFI_INFO + ("Failed to allocate memory for CONCATENATION feature value\n"); -+ dwc_free(cfiep->bm_sg); ++ DWC_FREE(cfiep->bm_sg); + return -DWC_E_NO_MEMORY; + } + dwc_memset(cfiep->bm_concat, 0, sizeof(ddma_concat_buffer_setup_t)); + -+ cfiep->bm_align = dwc_alloc(sizeof(ddma_align_buffer_setup_t)); ++ cfiep->bm_align = DWC_ALLOC(sizeof(ddma_align_buffer_setup_t)); + if (NULL == cfiep->bm_align) { + CFI_INFO + ("Failed to allocate memory for Alignment feature value\n"); -+ dwc_free(cfiep->bm_sg); -+ dwc_free(cfiep->bm_concat); ++ DWC_FREE(cfiep->bm_sg); ++ DWC_FREE(cfiep->bm_concat); + return -DWC_E_NO_MEMORY; + } + dwc_memset(cfiep->bm_align, 0, sizeof(ddma_align_buffer_setup_t)); @@ -38985,7 +47597,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 + + if (NULL == cfiep) { + /* Allocate a cfi_ep_t object */ -+ cfiep = dwc_alloc(sizeof(cfi_ep_t)); ++ cfiep = DWC_ALLOC(sizeof(cfi_ep_t)); + if (NULL == cfiep) { + CFI_INFO + ("Unable to allocate memory for in function %s\n", @@ -38999,12 +47611,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 + + /* Allocate the DMA Descriptors chain of MAX_DMA_DESCS_PER_EP count */ + ep->dwc_ep.descs = -+ dwc_dma_alloc(MAX_DMA_DESCS_PER_EP * ++ DWC_DMA_ALLOC(MAX_DMA_DESCS_PER_EP * + sizeof(dwc_otg_dma_desc_t), + &ep->dwc_ep.descs_dma_addr); + + if (NULL == ep->dwc_ep.descs) { -+ dwc_free(cfiep); ++ DWC_FREE(cfiep); + return -DWC_E_NO_MEMORY; + } + @@ -39065,7 +47677,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 + reg_value = *((uint32_t *) buf); + if (wValue == 0) { + addr = 0; -+ //addr = (uint32_t) pcd->otg_dev->base; ++ //addr = (uint32_t) pcd->otg_dev->os_dep.base; + addr += wIndex; + } else { + addr = (wValue << 16) | wIndex; @@ -39260,7 +47872,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 + struct dwc_otg_pcd_ep *ep, dma_addr_t * dma, + unsigned size, gfp_t flags) +{ -+ return dwc_dma_alloc(size, dma); ++ return DWC_DMA_ALLOC(size, dma); +} + +/** @@ -39272,7 +47884,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 + + /* Allocate a buffer for IN XFERs */ + cfiobj->buf_in.buf = -+ dwc_dma_alloc(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr); ++ DWC_DMA_ALLOC(CFI_IN_BUF_LEN, &cfiobj->buf_in.addr); + if (NULL == cfiobj->buf_in.buf) { + CFI_INFO("Unable to allocate buffer for INs\n"); + return -DWC_E_NO_MEMORY; @@ -39280,7 +47892,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 + + /* Allocate a buffer for OUT XFERs */ + cfiobj->buf_out.buf = -+ dwc_dma_alloc(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr); ++ DWC_DMA_ALLOC(CFI_OUT_BUF_LEN, &cfiobj->buf_out.addr); + if (NULL == cfiobj->buf_out.buf) { + CFI_INFO("Unable to allocate buffer for OUT\n"); + return -DWC_E_NO_MEMORY; @@ -39394,7 +48006,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 +{ + /* First we need to free the wTxBytes field */ + if (cfiep->bm_concat->wTxBytes) { -+ dwc_free(cfiep->bm_concat->wTxBytes); ++ DWC_FREE(cfiep->bm_concat->wTxBytes); + cfiep->bm_concat->wTxBytes = NULL; + } + @@ -39453,8 +48065,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 + params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - + 1]; + params->dev_tx_fifo_size[ep->dwc_ep.tx_fifo_num - 1] = -+ GET_CORE_IF(pcd)->init_txfsiz[ep->dwc_ep. -+ tx_fifo_num - 1]; ++ GET_CORE_IF(pcd)->init_txfsiz[ep-> ++ dwc_ep.tx_fifo_num - ++ 1]; + } + } + @@ -39473,13 +48086,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 + int i; + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; + i++) { -+ core_if->core_params-> -+ dev_tx_fifo_size[i] = tx_siz[i]; ++ core_if-> ++ core_params->dev_tx_fifo_size[i] = ++ tx_siz[i]; + } + } else { -+ params->dev_tx_fifo_size[ep->dwc_ep. -+ tx_fifo_num - 1] = -+ tx_siz[0]; ++ params->dev_tx_fifo_size[ep-> ++ dwc_ep.tx_fifo_num - ++ 1] = tx_siz[0]; + } + } + retval = -DWC_E_INVALID; @@ -39818,12 +48432,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 + + /* Free the previously allocated storage for the wTxBytes */ + if (ep->bm_concat->wTxBytes) { -+ dwc_free(ep->bm_concat->wTxBytes); ++ DWC_FREE(ep->bm_concat->wTxBytes); + } + + /* Allocate a new storage for the wTxBytes field */ + ep->bm_concat->wTxBytes = -+ dwc_alloc(sizeof(uint16_t) * pConcatValHdr->bDescCount); ++ DWC_ALLOC(sizeof(uint16_t) * pConcatValHdr->bDescCount); + if (NULL == ep->bm_concat->wTxBytes) { + CFI_INFO("%s: Unable to allocate memory\n", __func__); + return -DWC_E_NO_MEMORY; @@ -39915,16 +48529,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 + + switch (wValue >> 8) { + case 0: -+ return (GET_CORE_IF(pcd)-> -+ pwron_txfsiz[ep->dwc_ep.tx_fifo_num - 1] < -+ 768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep->dwc_ep. -+ tx_fifo_num - -+ 1] : 32768; ++ return (GET_CORE_IF(pcd)->pwron_txfsiz ++ [ep->dwc_ep.tx_fifo_num - 1] < ++ 768) ? GET_CORE_IF(pcd)->pwron_txfsiz[ep-> ++ dwc_ep.tx_fifo_num ++ - 1] : 32768; + break; + case 1: -+ return GET_CORE_IF(pcd)->core_params->dev_tx_fifo_size[ep-> -+ dwc_ep. -+ num - 1]; ++ return GET_CORE_IF(pcd)->core_params-> ++ dev_tx_fifo_size[ep->dwc_ep.num - 1]; + break; + default: + return -DWC_E_INVALID; @@ -40021,65 +48634,63 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 + + /* Configure data FIFO sizes */ + if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { -+ rx_fsz_bak = dwc_read_reg32(&global_regs->grxfsiz); ++ rx_fsz_bak = DWC_READ_REG32(&global_regs->grxfsiz); + rx_fifo_size = params->dev_rx_fifo_size; -+ dwc_write_reg32(&global_regs->grxfsiz, rx_fifo_size); ++ DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size); + + /* + * Tx FIFOs These FIFOs are numbered from 1 to 15. + * Indexes of the FIFO size module parameters in the + * dev_tx_fifo_size array and the FIFO size registers in -+ * the dptxfsiz_dieptxf array run from 0 to 14. ++ * the dtxfsiz array run from 0 to 14. + */ + + /* Non-periodic Tx FIFO */ -+ nptxfsz_bak = dwc_read_reg32(&global_regs->gnptxfsiz); ++ nptxfsz_bak = DWC_READ_REG32(&global_regs->gnptxfsiz); + nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; + start_address = params->dev_rx_fifo_size; + nptxfifosize.b.startaddr = start_address; + -+ dwc_write_reg32(&global_regs->gnptxfsiz, nptxfifosize.d32); ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32); + + start_address += nptxfifosize.b.depth; + + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { -+ txfsz_bak[i] = -+ dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]); ++ txfsz_bak[i] = DWC_READ_REG32(&global_regs->dtxfsiz[i]); + + txfifosize[i].b.depth = params->dev_tx_fifo_size[i]; + txfifosize[i].b.startaddr = start_address; -+ dwc_write_reg32(&global_regs->dptxfsiz_dieptxf[i], ++ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], + txfifosize[i].d32); + + start_address += txfifosize[i].b.depth; + } + + /** Check if register values are set correctly */ -+ if (rx_fifo_size != dwc_read_reg32(&global_regs->grxfsiz)) { ++ if (rx_fifo_size != DWC_READ_REG32(&global_regs->grxfsiz)) { + retval = 0; + } + -+ if (nptxfifosize.d32 != dwc_read_reg32(&global_regs->gnptxfsiz)) { ++ if (nptxfifosize.d32 != DWC_READ_REG32(&global_regs->gnptxfsiz)) { + retval = 0; + } + + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { + if (txfifosize[i].d32 != -+ dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i])) { ++ DWC_READ_REG32(&global_regs->dtxfsiz[i])) { + retval = 0; + } + } + + /** If register values are not set correctly, reset old values */ + if (retval == 0) { -+ dwc_write_reg32(&global_regs->grxfsiz, rx_fsz_bak); ++ DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fsz_bak); + + /* Non-periodic Tx FIFO */ -+ dwc_write_reg32(&global_regs->gnptxfsiz, nptxfsz_bak); ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfsz_bak); + + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { -+ dwc_write_reg32(&global_regs-> -+ dptxfsiz_dieptxf[i], ++ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], + txfsz_bak[i]); + } + } @@ -40342,16 +48953,18 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.c linux-rpi-bootc-3 + return retval; +} + -+#endif //DWC_UTE_CFI -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.h ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.h 2012-07-15 20:29:19.104083997 +0200 -@@ -0,0 +1,319 @@ ++#endif //DWC_UTE_CFI +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cfi.h b/drivers/usb/host/dwc_otg/dwc_otg_cfi.h +new file mode 100644 +index 0000000..cbccdab +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_cfi.h +@@ -0,0 +1,320 @@ +/* ========================================================================== + * 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 + * with Synopsys or any supplement thereto. You are permitted to use and @@ -40361,7 +48974,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-rpi-bootc-3 + * any information contained herein except pursuant to this license grant from + * Synopsys. If you do not agree with this notice, including the disclaimer + * below, then you are not authorized to use the Software. -+ * ++ * + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -40382,10 +48995,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-rpi-bootc-3 +#include "dwc_cfi_common.h" + +/** -+ * @file -+ * -+ * This file contains the CFI related OTG PCD specific common constants, interfaces -+ * (functions and macros) and data structures. ++ * @file ++ * This file contains the CFI related OTG PCD specific common constants, ++ * interfaces(functions and macros) and data structures.The CFI Protocol is an ++ * optional interface for internal testing purposes that a DUT may implement to ++ * support testing of configurable features. + * + */ + @@ -40419,7 +49033,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-rpi-bootc-3 +#define max(x,y) ({ \ + x > y ? x : y; }) + -+/** ++/** + * Descriptor DMA SG Buffer setup structure (SG buffer). This structure is + * also used for setting up a buffer for Circular DDMA. + */ @@ -40483,7 +49097,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-rpi-bootc-3 + +/** + * struct cfi_usb_ctrlrequest - the CFI implementation of the struct usb_ctrlrequest -+ * This structure encapsulates the standard usb_ctrlrequest and adds a pointer ++ * This structure encapsulates the standard usb_ctrlrequest and adds a pointer + * to the data returned in the data stage of a 3-stage Control Write requests. + */ +struct cfi_usb_ctrlrequest { @@ -40499,7 +49113,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-rpi-bootc-3 + +/** + * The CFI wrapper of the enabled and activated dwc_otg_pcd_ep structures. -+ * This structure is used to store the buffer setup data for any ++ * This structure is used to store the buffer setup data for any + * enabled endpoint in the PCD. + */ +struct cfi_ep { @@ -40519,7 +49133,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-rpi-bootc-3 + ddma_align_buffer_setup_t *bm_align; + /* XFER length */ + uint32_t xfer_len; -+ /* ++ /* + * Count of DMA descriptors currently used. + * The total should not exceed the MAX_DMA_DESCS_PER_EP value + * defined in the dwc_otg_cil.h @@ -40539,7 +49153,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-rpi-bootc-3 + +/** + * This is the interface for the CFI operations. -+ * ++ * + * @param ep_enable Called when any endpoint is enabled and activated. + * @param release Called when the CFI object is released and it needs to correctly + * deallocate the dynamic memory @@ -40578,12 +49192,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-rpi-bootc-3 + /* This flag shall control the propagation of a specific request + * to the gadget's processing routines. + * 0 - no gadget handling -+ * 1 - the gadget needs to know about this request (w/o completing a status ++ * 1 - the gadget needs to know about this request (w/o completing a status + * phase - just return a 0 to the _setup callback) + */ + uint8_t need_gadget_att; + -+ /* Flag indicating whether the status IN phase needs to be ++ /* Flag indicating whether the status IN phase needs to be + * completed by the PCD + */ + uint8_t need_status_in_complete; @@ -40665,21 +49279,23 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cfi.h linux-rpi-bootc-3 + +int cfi_setup(struct dwc_otg_pcd *pcd, struct cfi_usb_ctrlrequest *ctrl); + -+#endif /* (__DWC_OTG_CFI_H__) */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c 2012-07-15 20:29:19.065083268 +0200 -@@ -0,0 +1,5410 @@ ++#endif /* (__DWC_OTG_CFI_H__) */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.c b/drivers/usb/host/dwc_otg/dwc_otg_cil.c +new file mode 100644 +index 0000000..9b67537 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.c +@@ -0,0 +1,7151 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.c $ -+ * $Revision: #159 $ -+ * $Date: 2009/04/21 $ -+ * $Change: 1237465 $ ++ * $Revision: #191 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ + * + * 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 + * with Synopsys or any supplement thereto. You are permitted to use and @@ -40689,7 +49305,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + * any information contained herein except pursuant to this license grant from + * Synopsys. If you do not agree with this notice, including the disclaimer + * below, then you are not authorized to use the Software. -+ * ++ * + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -40703,7 +49319,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + * DAMAGE. + * ========================================================================== */ + -+/** @file ++/** @file + * + * The Core Interface Layer provides basic services for accessing and + * managing the DWC_otg hardware. These services are used by both the @@ -40723,7 +49339,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + * + * The Core Interface Layer has the following requirements: + * - Provides basic controller operations. -+ * - Minimal use of OS services. ++ * - Minimal use of OS services. + * - The OS services used will be abstracted by using inline functions + * or macros. + * @@ -40735,12 +49351,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + +static int dwc_otg_setup_params(dwc_otg_core_if_t * core_if); + -+/** ++/** + * This function is called to initialize the DWC_otg CSR data -+ * structures. The register addresses in the device and host ++ * structures. The register addresses in the device and host + * structures are initialized from the base address supplied by the -+ * caller. The calling function must make the OS calls to get the -+ * base address of the DWC_otg controller registers. The core_params ++ * caller. The calling function must make the OS calls to get the ++ * base address of the DWC_otg controller registers. The core_params + * argument holds the parameters that specify how the core should be + * configured. + * @@ -40757,9 +49373,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, reg_base_addr); + -+ core_if = dwc_alloc(sizeof(dwc_otg_core_if_t)); ++ core_if = DWC_ALLOC(sizeof(dwc_otg_core_if_t)); + -+ if (core_if == 0) { ++ if (core_if == NULL) { + DWC_DEBUGPL(DBG_CIL, + "Allocation of dwc_otg_core_if_t failed\n"); + return 0; @@ -40769,11 +49385,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* + * Allocate the Device Mode structures. + */ -+ dev_if = dwc_alloc(sizeof(dwc_otg_dev_if_t)); ++ dev_if = DWC_ALLOC(sizeof(dwc_otg_dev_if_t)); + -+ if (dev_if == 0) { ++ if (dev_if == NULL) { + DWC_DEBUGPL(DBG_CIL, "Allocation of dwc_otg_dev_if_t failed\n"); -+ dwc_free(core_if); ++ DWC_FREE(core_if); + return 0; + } + @@ -40802,13 +49418,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* + * Allocate the Host Mode structures. + */ -+ host_if = dwc_alloc(sizeof(dwc_otg_host_if_t)); ++ host_if = DWC_ALLOC(sizeof(dwc_otg_host_if_t)); + -+ if (host_if == 0) { ++ if (host_if == NULL) { + DWC_DEBUGPL(DBG_CIL, + "Allocation of dwc_otg_host_if_t failed\n"); -+ dwc_free(dev_if); -+ dwc_free(core_if); ++ DWC_FREE(dev_if); ++ DWC_FREE(core_if); + return 0; + } + @@ -40833,8 +49449,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + core_if->data_fifo[i] = + (uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET + + (i * DWC_OTG_DATA_FIFO_SIZE)); -+ DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08x\n", -+ i, (unsigned)core_if->data_fifo[i]); ++ DWC_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08lx\n", ++ i, (unsigned long)core_if->data_fifo[i]); + } + + core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET); @@ -40846,13 +49462,28 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + * easy access later. + */ + core_if->hwcfg1.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->ghwcfg1); ++ DWC_READ_REG32(&core_if->core_global_regs->ghwcfg1); + core_if->hwcfg2.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->ghwcfg2); ++ DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2); + core_if->hwcfg3.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->ghwcfg3); ++ DWC_READ_REG32(&core_if->core_global_regs->ghwcfg3); + core_if->hwcfg4.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->ghwcfg4); ++ DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4); ++ ++ /* Force host mode to get HPTXFSIZ exact power on value */ ++ { ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gusbcfg.b.force_host_mode = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ dwc_mdelay(100); ++ core_if->hptxfsiz.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz); ++ gusbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gusbcfg.b.force_host_mode = 0; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ dwc_mdelay(100); ++ } + + DWC_DEBUGPL(DBG_CILV, "hwcfg1=%08x\n", core_if->hwcfg1.d32); + DWC_DEBUGPL(DBG_CILV, "hwcfg2=%08x\n", core_if->hwcfg2.d32); @@ -40860,9 +49491,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + DWC_DEBUGPL(DBG_CILV, "hwcfg4=%08x\n", core_if->hwcfg4.d32); + + core_if->hcfg.d32 = -+ dwc_read_reg32(&core_if->host_if->host_global_regs->hcfg); ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); + core_if->dcfg.d32 = -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg); ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); + + DWC_DEBUGPL(DBG_CILV, "hcfg=%08x\n", core_if->hcfg.d32); + DWC_DEBUGPL(DBG_CILV, "dcfg=%08x\n", core_if->dcfg.d32); @@ -40896,13 +49527,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + core_if->wq_otg = DWC_WORKQ_ALLOC("dwc_otg"); + if (core_if->wq_otg == 0) { + DWC_WARN("DWC_WORKQ_ALLOC failed\n"); -+ dwc_free(host_if); -+ dwc_free(dev_if); -+ dwc_free(core_if); ++ DWC_FREE(host_if); ++ DWC_FREE(dev_if); ++ DWC_FREE(core_if); + return 0; + } + -+ core_if->snpsid = dwc_read_reg32(&core_if->core_global_regs->gsnpsid); ++ core_if->snpsid = DWC_READ_REG32(&core_if->core_global_regs->gsnpsid); + + DWC_PRINTF("Core Release: %x.%x%x%x\n", + (core_if->snpsid >> 12 & 0xF), @@ -40913,10 +49544,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + w_wakeup_detected, core_if); + if (core_if->wkp_timer == 0) { + DWC_WARN("DWC_TIMER_ALLOC failed\n"); -+ dwc_free(host_if); -+ dwc_free(dev_if); ++ DWC_FREE(host_if); ++ DWC_FREE(dev_if); + DWC_WORKQ_FREE(core_if->wq_otg); -+ dwc_free(core_if); ++ DWC_FREE(core_if); + return 0; + } + @@ -40924,37 +49555,59 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + DWC_WARN("Error while setting core params\n"); + } + ++ core_if->hibernation_suspend = 0; ++ ++ /** ADP initialization */ ++ dwc_otg_adp_init(core_if); ++ + return core_if; +} + +/** + * This function frees the structures allocated by dwc_otg_cil_init(). -+ * ++ * + * @param core_if The core interface pointer returned from + * dwc_otg_cil_init(). + * + */ +void dwc_otg_cil_remove(dwc_otg_core_if_t * core_if) +{ ++ dctl_data_t dctl = {.d32 = 0 }; + DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if); + + /* Disable all interrupts */ -+ dwc_modify_reg32(&core_if->core_global_regs->gahbcfg, 1, 0); -+ dwc_write_reg32(&core_if->core_global_regs->gintmsk, 0); ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 1, 0); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0); ++ ++ dctl.b.sftdiscon = 1; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, ++ dctl.d32); ++ } + + if (core_if->wq_otg) { + DWC_WORKQ_WAIT_WORK_DONE(core_if->wq_otg, 500); + DWC_WORKQ_FREE(core_if->wq_otg); + } + if (core_if->dev_if) { -+ dwc_free(core_if->dev_if); ++ DWC_FREE(core_if->dev_if); + } + if (core_if->host_if) { -+ dwc_free(core_if->host_if); ++ DWC_FREE(core_if->host_if); + } -+ dwc_free(core_if); -+ DWC_TIMER_FREE(core_if->wkp_timer); -+ DWC_FREE(core_if->core_params); ++ ++ /** Remove ADP Stuff */ ++ dwc_otg_adp_remove(core_if); ++ if (core_if->core_params) { ++ DWC_FREE(core_if->core_params); ++ } ++ if (core_if->wkp_timer) { ++ DWC_TIMER_FREE(core_if->wkp_timer); ++ } ++ if (core_if->srp_timer) { ++ DWC_TIMER_FREE(core_if->srp_timer); ++ } ++ DWC_FREE(core_if); +} + +/** @@ -40967,7 +49620,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 +{ + gahbcfg_data_t ahbcfg = {.d32 = 0 }; + ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ -+ dwc_modify_reg32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32); ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32); +} + +/** @@ -40979,9 +49632,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 +void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t * core_if) +{ + gahbcfg_data_t ahbcfg = {.d32 = 0 }; -+ ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */ -+ DWC_PRINTF("%x -> %x\n", (unsigned int)&core_if->core_global_regs->gahbcfg, ahbcfg.d32); -+ dwc_modify_reg32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0); ++ ahbcfg.b.glblintrmsk = 1; /* Disable interrupts */ ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0); +} + +/** @@ -40997,13 +49649,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + gintmsk_data_t intr_mask = {.d32 = 0 }; + + /* Clear any pending OTG Interrupts */ -+ dwc_write_reg32(&global_regs->gotgint, 0xFFFFFFFF); ++ DWC_WRITE_REG32(&global_regs->gotgint, 0xFFFFFFFF); + + /* Clear any pending interrupts */ -+ dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF); ++ DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF); + -+ /* -+ * Enable the interrupts in the GINTMSK. ++ /* ++ * Enable the interrupts in the GINTMSK. + */ + intr_mask.b.modemismatch = 1; + intr_mask.b.otgintr = 1; @@ -41014,7 +49666,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + intr_mask.b.conidstschng = 1; + intr_mask.b.wkupintr = 1; -+ intr_mask.b.disconnect = 1; ++ intr_mask.b.disconnect = 0; + intr_mask.b.usbsuspend = 1; + intr_mask.b.sessreqintr = 1; +#ifdef CONFIG_USB_DWC_OTG_LPM @@ -41022,7 +49674,709 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + intr_mask.b.lpmtranrcvd = 1; + } +#endif -+ dwc_write_reg32(&global_regs->gintmsk, intr_mask.d32); ++ DWC_WRITE_REG32(&global_regs->gintmsk, intr_mask.d32); ++} ++ ++/* ++ * The restore operation is modified to support Synopsys Emulated Powerdown and ++ * Hibernation. This function is for exiting from Device mode hibernation by ++ * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup. ++ * @param core_if Programming view of DWC_otg controller. ++ * @param rem_wakeup - indicates whether resume is initiated by Device or Host. ++ * @param reset - indicates whether resume is initiated by Reset. ++ */ ++int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int rem_wakeup, int reset) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ ++ int timeout = 2000; ++ ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ DWC_DEBUGPL(DBG_PCD, "%s called\n", __FUNCTION__); ++ /* Switch-on voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Assert Restore signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ if (rem_wakeup) { ++ dwc_udelay(70); ++ } ++ ++ /* Deassert Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Mask interrupts from gpwrdn */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.connect_det_msk = 1; ++ gpwrdn.b.srp_det_msk = 1; ++ gpwrdn.b.disconn_det_msk = 1; ++ gpwrdn.b.rst_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Indicates that we are going out from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* ++ * Set Restore Essential Regs bit in PCGCCTL register, restore_mode = 1 ++ * indicates restore from remote_wakeup ++ */ ++ restore_essential_regs(core_if, rem_wakeup, 0); ++ ++ /* ++ * Wait a little for seeing new value of variable hibernation_suspend if ++ * Restore done interrupt received before polling ++ */ ++ dwc_udelay(10); ++ ++ if (core_if->hibernation_suspend == 0) { ++ /* ++ * Wait For Restore_done Interrupt. This mechanism of polling the ++ * interrupt is introduced to avoid any possible race conditions ++ */ ++ do { ++ gintsts_data_t gintsts; ++ gintsts.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (gintsts.b.restoredone) { ++ gintsts.d32 = 0; ++ gintsts.b.restoredone = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, gintsts.d32); ++ DWC_PRINTF("Restore Done Interrupt seen\n"); ++ break; ++ } ++ dwc_udelay(10); ++ } while (--timeout); ++ if (!timeout) { ++ DWC_PRINTF("Restore Done interrupt wasn't generated here\n"); ++ } ++ } ++ /* Clear all pending interupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* De-assert Restore */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ if (!rem_wakeup) { ++ pcgcctl.d32 = 0; ++ pcgcctl.b.rstpdwnmodule = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ } ++ ++ /* Restore GUSBCFG and DCFG */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, ++ core_if->gr_backup->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, ++ core_if->dr_backup->dcfg); ++ ++ /* De-assert Wakeup Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ if (!rem_wakeup) { ++ /* Set Device programming done bit */ ++ dctl.b.pwronprgdone = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } else { ++ /* Start Remote Wakeup Signaling */ ++ dctl.d32 = core_if->dr_backup->dctl; ++ dctl.b.rmtwkupsig = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++ } ++ ++ dwc_mdelay(2); ++ /* Clear all pending interupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Restore global registers */ ++ dwc_otg_restore_global_regs(core_if); ++ /* Restore device global registers */ ++ dwc_otg_restore_dev_regs(core_if, rem_wakeup); ++ ++ if (rem_wakeup) { ++ dwc_mdelay(7); ++ dctl.d32 = 0; ++ dctl.b.rmtwkupsig = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); ++ } ++ ++ core_if->hibernation_suspend = 0; ++ /* The core will be in ON STATE */ ++ core_if->lx_state = DWC_OTG_L0; ++ DWC_PRINTF("Hibernation recovery completes here\n"); ++ ++ return 1; ++} ++ ++/* ++ * The restore operation is modified to support Synopsys Emulated Powerdown and ++ * Hibernation. This function is for exiting from Host mode hibernation by ++ * Host Initiated Resume/Reset and Device Initiated Remote-Wakeup. ++ * @param core_if Programming view of DWC_otg controller. ++ * @param rem_wakeup - indicates whether resume is initiated by Device or Host. ++ * @param reset - indicates whether resume is initiated by Reset. ++ */ ++int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int rem_wakeup, int reset) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ hprt0_data_t hprt0 = {.d32 = 0 }; ++ ++ int timeout = 2000; ++ ++ DWC_DEBUGPL(DBG_HCD, "%s called\n", __FUNCTION__); ++ /* Switch-on voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Assert Restore signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ if (!rem_wakeup) { ++ dwc_udelay(50); ++ } ++ ++ /* Deassert Reset core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.connect_det_msk = 1; ++ gpwrdn.b.srp_det_msk = 1; ++ gpwrdn.b.disconn_det_msk = 1; ++ gpwrdn.b.rst_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Indicates that we are going out from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Set Restore Essential Regs bit in PCGCCTL register */ ++ restore_essential_regs(core_if, rem_wakeup, 1); ++ ++ /* Wait a little for seeing new value of variable hibernation_suspend if ++ * Restore done interrupt received before polling */ ++ dwc_udelay(10); ++ ++ if (core_if->hibernation_suspend == 0) { ++ /* Wait For Restore_done Interrupt. This mechanism of polling the ++ * interrupt is introduced to avoid any possible race conditions ++ */ ++ do { ++ gintsts_data_t gintsts; ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (gintsts.b.restoredone) { ++ gintsts.d32 = 0; ++ gintsts.b.restoredone = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ DWC_DEBUGPL(DBG_HCD,"Restore Done Interrupt seen\n"); ++ break; ++ } ++ dwc_udelay(10); ++ } while (--timeout); ++ if (!timeout) { ++ DWC_WARN("Restore Done interrupt wasn't generated\n"); ++ } ++ } ++ ++ /* Set the flag's value to 0 again after receiving restore done interrupt */ ++ core_if->hibernation_suspend = 0; ++ ++ /* This step is not described in functional spec but if not wait for this ++ * delay, mismatch interrupts occurred because just after restore core is ++ * in Device mode(gintsts.curmode == 0) */ ++ dwc_mdelay(100); ++ ++ /* Clear all pending interrupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* De-assert Restore */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Restore GUSBCFG and HCFG */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, ++ core_if->gr_backup->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, ++ core_if->hr_backup->hcfg_local); ++ ++ /* De-assert Wakeup Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Start the Resume operation by programming HPRT0 */ ++ hprt0.d32 = core_if->hr_backup->hprt0_local; ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtena = 0; ++ hprt0.b.prtsusp = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ DWC_PRINTF("Resume Starts Now\n"); ++ if (!reset) { // Indicates it is Resume Operation ++ hprt0.d32 = core_if->hr_backup->hprt0_local; ++ hprt0.b.prtres = 1; ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtena = 0; ++ hprt0.b.prtsusp = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ if (!rem_wakeup) ++ hprt0.b.prtres = 0; ++ /* Wait for Resume time and then program HPRT again */ ++ dwc_mdelay(100); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ } else { // Indicates it is Reset Operation ++ hprt0.d32 = core_if->hr_backup->hprt0_local; ++ hprt0.b.prtrst = 1; ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtena = 0; ++ hprt0.b.prtsusp = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ /* Wait for Reset time and then program HPRT again */ ++ dwc_mdelay(60); ++ hprt0.b.prtrst = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } ++ /* Clear all interrupt status */ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtconndet = 1; ++ hprt0.b.prtenchng = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ ++ /* Clear all pending interupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Restore global registers */ ++ dwc_otg_restore_global_regs(core_if); ++ /* Restore host global registers */ ++ dwc_otg_restore_host_regs(core_if, reset); ++ ++ /* The core will be in ON STATE */ ++ core_if->lx_state = DWC_OTG_L0; ++ DWC_PRINTF("Hibernation recovery is complete here\n"); ++ return 0; ++} ++ ++/** Saves some register values into system memory. */ ++int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ int i; ++ ++ gr = core_if->gr_backup; ++ if (!gr) { ++ gr = DWC_ALLOC(sizeof(*gr)); ++ if (!gr) { ++ return -DWC_E_NO_MEMORY; ++ } ++ core_if->gr_backup = gr; ++ } ++ ++ gr->gotgctl_local = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ gr->gahbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg); ++ gr->gusbcfg_local = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ gr->grxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); ++ gr->gnptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz); ++ gr->hptxfsiz_local = DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ gr->glpmcfg_local = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++#endif ++ gr->gi2cctl_local = DWC_READ_REG32(&core_if->core_global_regs->gi2cctl); ++ gr->pcgcctl_local = DWC_READ_REG32(core_if->pcgcctl); ++ gr->gdfifocfg_local = ++ DWC_READ_REG32(&core_if->core_global_regs->gdfifocfg); ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ gr->dtxfsiz_local[i] = ++ DWC_READ_REG32(&(core_if->core_global_regs->dtxfsiz[i])); ++ } ++ ++ DWC_DEBUGPL(DBG_ANY, "===========Backing Global registers==========\n"); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gotgctl = %08x\n", gr->gotgctl_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk = %08x\n", gr->gintmsk_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gahbcfg = %08x\n", gr->gahbcfg_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gusbcfg = %08x\n", gr->gusbcfg_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up grxfsiz = %08x\n", gr->grxfsiz_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gnptxfsiz = %08x\n", ++ gr->gnptxfsiz_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up hptxfsiz = %08x\n", ++ gr->hptxfsiz_local); ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ DWC_DEBUGPL(DBG_ANY, "Backed up glpmcfg = %08x\n", gr->glpmcfg_local); ++#endif ++ DWC_DEBUGPL(DBG_ANY, "Backed up gi2cctl = %08x\n", gr->gi2cctl_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up pcgcctl = %08x\n", gr->pcgcctl_local); ++ DWC_DEBUGPL(DBG_ANY,"Backed up gdfifocfg = %08x\n",gr->gdfifocfg_local); ++ ++ return 0; ++} ++ ++/** Saves GINTMSK register before setting the msk bits. */ ++int dwc_otg_save_gintmsk_reg(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ ++ gr = core_if->gr_backup; ++ if (!gr) { ++ gr = DWC_ALLOC(sizeof(*gr)); ++ if (!gr) { ++ return -DWC_E_NO_MEMORY; ++ } ++ core_if->gr_backup = gr; ++ } ++ ++ gr->gintmsk_local = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ ++ DWC_DEBUGPL(DBG_ANY,"=============Backing GINTMSK registers============\n"); ++ DWC_DEBUGPL(DBG_ANY, "Backed up gintmsk = %08x\n", gr->gintmsk_local); ++ ++ return 0; ++} ++ ++int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_dev_regs_backup *dr; ++ int i; ++ ++ dr = core_if->dr_backup; ++ if (!dr) { ++ dr = DWC_ALLOC(sizeof(*dr)); ++ if (!dr) { ++ return -DWC_E_NO_MEMORY; ++ } ++ core_if->dr_backup = dr; ++ } ++ ++ dr->dcfg = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ dr->dctl = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ dr->daintmsk = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk); ++ dr->diepmsk = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->diepmsk); ++ dr->doepmsk = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->doepmsk); ++ ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ dr->diepctl[i] = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl); ++ dr->dieptsiz[i] = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz); ++ dr->diepdma[i] = ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma); ++ } ++ ++ DWC_DEBUGPL(DBG_ANY, ++ "=============Backing Host registers==============\n"); ++ DWC_DEBUGPL(DBG_ANY, "Backed up dcfg = %08x\n", dr->dcfg); ++ DWC_DEBUGPL(DBG_ANY, "Backed up dctl = %08x\n", dr->dctl); ++ DWC_DEBUGPL(DBG_ANY, "Backed up daintmsk = %08x\n", ++ dr->daintmsk); ++ DWC_DEBUGPL(DBG_ANY, "Backed up diepmsk = %08x\n", dr->diepmsk); ++ DWC_DEBUGPL(DBG_ANY, "Backed up doepmsk = %08x\n", dr->doepmsk); ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ DWC_DEBUGPL(DBG_ANY, "Backed up diepctl[%d] = %08x\n", i, ++ dr->diepctl[i]); ++ DWC_DEBUGPL(DBG_ANY, "Backed up dieptsiz[%d] = %08x\n", ++ i, dr->dieptsiz[i]); ++ DWC_DEBUGPL(DBG_ANY, "Backed up diepdma[%d] = %08x\n", i, ++ dr->diepdma[i]); ++ } ++ ++ return 0; ++} ++ ++int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_host_regs_backup *hr; ++ int i; ++ ++ hr = core_if->hr_backup; ++ if (!hr) { ++ hr = DWC_ALLOC(sizeof(*hr)); ++ if (!hr) { ++ return -DWC_E_NO_MEMORY; ++ } ++ core_if->hr_backup = hr; ++ } ++ ++ hr->hcfg_local = ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ hr->haintmsk_local = ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk); ++ for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) { ++ hr->hcintmsk_local[i] = ++ DWC_READ_REG32(&core_if->host_if->hc_regs[i]->hcintmsk); ++ } ++ hr->hprt0_local = DWC_READ_REG32(core_if->host_if->hprt0); ++ hr->hfir_local = ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir); ++ ++ DWC_DEBUGPL(DBG_ANY, ++ "=============Backing Host registers===============\n"); ++ DWC_DEBUGPL(DBG_ANY, "Backed up hcfg = %08x\n", ++ hr->hcfg_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up haintmsk = %08x\n", hr->haintmsk_local); ++ for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) { ++ DWC_DEBUGPL(DBG_ANY, "Backed up hcintmsk[%02d]=%08x\n", i, ++ hr->hcintmsk_local[i]); ++ } ++ DWC_DEBUGPL(DBG_ANY, "Backed up hprt0 = %08x\n", ++ hr->hprt0_local); ++ DWC_DEBUGPL(DBG_ANY, "Backed up hfir = %08x\n", ++ hr->hfir_local); ++ ++ return 0; ++} ++ ++int dwc_otg_restore_global_regs(dwc_otg_core_if_t *core_if) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ int i; ++ ++ gr = core_if->gr_backup; ++ if (!gr) { ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, gr->gotgctl_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gr->gintmsk_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gr->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gr->gahbcfg_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, gr->grxfsiz_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, ++ gr->gnptxfsiz_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->hptxfsiz, ++ gr->hptxfsiz_local); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gdfifocfg, ++ gr->gdfifocfg_local); ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ DWC_WRITE_REG32(&core_if->core_global_regs->dtxfsiz[i], ++ gr->dtxfsiz_local[i]); ++ } ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, 0x0000100A); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, ++ (gr->gahbcfg_local)); ++ return 0; ++} ++ ++int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, int rem_wakeup) ++{ ++ struct dwc_otg_dev_regs_backup *dr; ++ int i; ++ ++ dr = core_if->dr_backup; ++ ++ if (!dr) { ++ return -DWC_E_INVALID; ++ } ++ ++ if (!rem_wakeup) { ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ dr->dctl); ++ } ++ ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->daintmsk, dr->daintmsk); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->diepmsk, dr->diepmsk); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->doepmsk, dr->doepmsk); ++ ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->dieptsiz, dr->dieptsiz[i]); ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepdma, dr->diepdma[i]); ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[i]->diepctl, dr->diepctl[i]); ++ } ++ ++ return 0; ++} ++ ++int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset) ++{ ++ struct dwc_otg_host_regs_backup *hr; ++ int i; ++ hr = core_if->hr_backup; ++ ++ if (!hr) { ++ return -DWC_E_INVALID; ++ } ++ ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hr->hcfg_local); ++ //if (!reset) ++ //{ ++ // DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hr->hfir_local); ++ //} ++ ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->haintmsk, ++ hr->haintmsk_local); ++ for (i = 0; i < dwc_otg_get_param_host_channels(core_if); ++i) { ++ DWC_WRITE_REG32(&core_if->host_if->hc_regs[i]->hcintmsk, ++ hr->hcintmsk_local[i]); ++ } ++ ++ return 0; ++} ++ ++int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ ++ gr = core_if->gr_backup; ++ ++ /* Restore values for LPM and I2C */ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, gr->glpmcfg_local); ++#endif ++ DWC_WRITE_REG32(&core_if->core_global_regs->gi2cctl, gr->gi2cctl_local); ++ ++ return 0; ++} ++ ++int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode, int is_host) ++{ ++ struct dwc_otg_global_regs_backup *gr; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gahbcfg_data_t gahbcfg = {.d32 = 0 }; ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ /* Restore LPM and I2C registers */ ++ restore_lpm_i2c_regs(core_if); ++ ++ /* Set PCGCCTL to 0 */ ++ DWC_WRITE_REG32(core_if->pcgcctl, 0x00000000); ++ ++ gr = core_if->gr_backup; ++ /* Load restore values for [31:14] bits */ ++ DWC_WRITE_REG32(core_if->pcgcctl, ++ ((gr->pcgcctl_local & 0xffffc000) | 0x00020000)); ++ ++ /* Umnask global Interrupt in GAHBCFG and restore it */ ++ gahbcfg.d32 = gr->gahbcfg_local; ++ gahbcfg.b.glblintrmsk = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32); ++ ++ /* Clear all pending interupts */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ ++ /* Unmask restore done interrupt */ ++ gintmsk.b.restoredone = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk.d32); ++ ++ /* Restore GUSBCFG and HCFG/DCFG */ ++ gusbcfg.d32 = core_if->gr_backup->gusbcfg_local; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, gusbcfg.d32); ++ ++ if (is_host) { ++ hcfg_data_t hcfg = {.d32 = 0 }; ++ hcfg.d32 = core_if->hr_backup->hcfg_local; ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, ++ hcfg.d32); ++ ++ /* Load restore values for [31:14] bits */ ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local | 0x00020000; ++ ++ if (rmode) ++ pcgcctl.b.restoremode = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ dwc_udelay(10); ++ ++ /* Load restore values for [31:14] bits and set EssRegRestored bit */ ++ pcgcctl.d32 = gr->pcgcctl_local | 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.b.ess_reg_restored = 1; ++ if (rmode) ++ pcgcctl.b.restoremode = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ } else { ++ dcfg_data_t dcfg = {.d32 = 0 }; ++ dcfg.d32 = core_if->dr_backup->dcfg; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ /* Load restore values for [31:14] bits */ ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local | 0x00020000; ++ if (!rmode) { ++ pcgcctl.d32 |= 0x208; ++ } ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ dwc_udelay(10); ++ ++ /* Load restore values for [31:14] bits */ ++ pcgcctl.d32 = gr->pcgcctl_local & 0xffffc000; ++ pcgcctl.d32 = gr->pcgcctl_local | 0x00020000; ++ pcgcctl.b.ess_reg_restored = 1; ++ if (!rmode) ++ pcgcctl.d32 |= 0x208; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ } ++ ++ return 0; +} + +/** @@ -41046,9 +50400,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + } + + DWC_DEBUGPL(DBG_CIL, "Initializing HCFG.FSLSPClkSel to 0x%1x\n", val); -+ hcfg.d32 = dwc_read_reg32(&core_if->host_if->host_global_regs->hcfg); ++ hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); + hcfg.b.fslspclksel = val; -+ dwc_write_reg32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32); +} + +/** @@ -41076,14 +50430,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + DWC_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val); + -+ dcfg.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg); ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); + dcfg.b.devspd = val; -+ dwc_write_reg32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); +} + +/** + * This function calculates the number of IN EPS -+ * using GHWCFG1 and GHWCFG2 registers values ++ * using GHWCFG1 and GHWCFG2 registers values + * + * @param core_if Programming view of the DWC_otg controller + */ @@ -41112,7 +50466,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + +/** + * This function calculates the number of OUT EPS -+ * using GHWCFG1 and GHWCFG2 registers values ++ * using GHWCFG1 and GHWCFG2 registers values + * + * @param core_if Programming view of the DWC_otg controller + */ @@ -41152,8 +50506,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + core_if, global_regs); + + /* Common Initialization */ -+ -+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); ++ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); + + /* Program the ULPI External VBUS bit if needed */ + usbcfg.b.ulpi_ext_vbus_drv = @@ -41163,11 +50516,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* Set external TS Dline pulsing */ + usbcfg.b.term_sel_dl_pulse = + (core_if->core_params->ts_dline == 1) ? 1 : 0; -+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); + + /* Reset the Controller */ + dwc_otg_core_reset(core_if); + ++ core_if->adp_enable = core_if->core_params->adp_supp_enable; ++ core_if->power_down = core_if->core_params->power_down; ++ core_if->otg_sts = 0; ++ + /* Initialize parameters from Hardware configuration registers. */ + dev_if->num_in_eps = calc_num_in_eps(core_if); + dev_if->num_out_eps = calc_num_out_eps(core_if); @@ -41177,22 +50534,22 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { + dev_if->perio_tx_fifo_size[i] = -+ dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]) >> 16; ++ DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16; + DWC_DEBUGPL(DBG_CIL, "Periodic Tx FIFO SZ #%d=0x%0x\n", + i, dev_if->perio_tx_fifo_size[i]); + } + + for (i = 0; i < core_if->hwcfg4.b.num_in_eps; i++) { + dev_if->tx_fifo_size[i] = -+ dwc_read_reg32(&global_regs->dptxfsiz_dieptxf[i]) >> 16; ++ DWC_READ_REG32(&global_regs->dtxfsiz[i]) >> 16; + DWC_DEBUGPL(DBG_CIL, "Tx FIFO SZ #%d=0x%0x\n", -+ i, dev_if->perio_tx_fifo_size[i]); ++ i, dev_if->tx_fifo_size[i]); + } + + core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth; -+ core_if->rx_fifo_size = dwc_read_reg32(&global_regs->grxfsiz); ++ core_if->rx_fifo_size = DWC_READ_REG32(&global_regs->grxfsiz); + core_if->nperio_tx_fifo_size = -+ dwc_read_reg32(&global_regs->gnptxfsiz) >> 16; ++ DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16; + + DWC_DEBUGPL(DBG_CIL, "Total FIFO SZ=%d\n", core_if->total_fifo_size); + DWC_DEBUGPL(DBG_CIL, "Rx FIFO SZ=%d\n", core_if->rx_fifo_size); @@ -41210,9 +50567,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + if (!core_if->phy_init_done) { + core_if->phy_init_done = 1; + DWC_DEBUGPL(DBG_CIL, "FS_PHY detected\n"); -+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); ++ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); + usbcfg.b.physel = 1; -+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); + + /* Reset after a PHY select */ + dwc_otg_core_reset(core_if); @@ -41230,17 +50587,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + if (core_if->core_params->i2c_enable) { + DWC_DEBUGPL(DBG_CIL, "FS_PHY Enabling I2c\n"); + /* Program GUSBCFG.OtgUtmifsSel to I2C */ -+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); ++ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); + usbcfg.b.otgutmifssel = 1; -+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); + + /* Program GI2CCTL.I2CEn */ -+ i2cctl.d32 = dwc_read_reg32(&global_regs->gi2cctl); ++ i2cctl.d32 = DWC_READ_REG32(&global_regs->gi2cctl); + i2cctl.b.i2cdevaddr = 1; + i2cctl.b.i2cen = 0; -+ dwc_write_reg32(&global_regs->gi2cctl, i2cctl.d32); ++ DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32); + i2cctl.b.i2cen = 1; -+ dwc_write_reg32(&global_regs->gi2cctl, i2cctl.d32); ++ DWC_WRITE_REG32(&global_regs->gi2cctl, i2cctl.d32); + } + + } /* endif speed == DWC_SPEED_PARAM_FULL */ @@ -41251,24 +50608,26 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* HS PHY parameters. These parameters are preserved + * during soft reset so only program the first time. Do + * a soft reset immediately after setting phyif. */ -+ usbcfg.b.ulpi_utmi_sel = core_if->core_params->phy_type; -+ if (usbcfg.b.ulpi_utmi_sel == 1) { ++ ++ if (core_if->core_params->phy_type == 2) { + /* ULPI interface */ ++ usbcfg.b.ulpi_utmi_sel = 1; + usbcfg.b.phyif = 0; + usbcfg.b.ddrsel = + core_if->core_params->phy_ulpi_ddr; -+ } else { ++ } else if (core_if->core_params->phy_type == 1) { + /* UTMI+ interface */ ++ usbcfg.b.ulpi_utmi_sel = 0; + if (core_if->core_params->phy_utmi_width == 16) { + usbcfg.b.phyif = 1; + + } else { + usbcfg.b.phyif = 0; + } -+ ++ } else { ++ DWC_ERROR("FS PHY TYPE\n"); + } -+ -+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); + /* Reset after setting the PHY parameters */ + dwc_otg_core_reset(core_if); + } @@ -41278,15 +50637,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + (core_if->hwcfg2.b.fs_phy_type == 1) && + (core_if->core_params->ulpi_fs_ls)) { + DWC_DEBUGPL(DBG_CIL, "Setting ULPI FSLS\n"); -+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); ++ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); + usbcfg.b.ulpi_fsls = 1; + usbcfg.b.ulpi_clk_sus_m = 1; -+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); + } else { -+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); ++ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); + usbcfg.b.ulpi_fsls = 0; + usbcfg.b.ulpi_clk_sus_m = 0; -+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); + } + + /* Program the GAHBCFG Register. */ @@ -41318,8 +50677,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + case DWC_INT_DMA_ARCH: + DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n"); -+ /*ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR; */ -+ ahbcfg.b.hburstlen = (1<<3)|(0<<0); /* WRESP=1, max 4 beats */ ++ /* Old value was DWC_GAHBCFG_INT_DMA_BURST_INCR - done for ++ Host mode ISOC in issue fix - vahrama */ ++ /* Broadcom had altered to (1<<3)|(0<<0) - WRESP=1, max 4 beats */ ++ ahbcfg.b.hburstlen = (1<<3)|(0<<0);//DWC_GAHBCFG_INT_DMA_BURST_INCR4; + core_if->dma_enable = (core_if->core_params->dma_enable != 0); + core_if->dma_desc_enable = + (core_if->core_params->dma_desc_enable != 0); @@ -41337,9 +50698,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + DWC_PRINTF("Using Slave mode\n"); + core_if->dma_desc_enable = 0; + } ++ ++ if (core_if->core_params->ahb_single) { ++ ahbcfg.b.ahbsingle = 1; ++ } + + ahbcfg.b.dmaenable = core_if->dma_enable; -+ dwc_write_reg32(&global_regs->gahbcfg, ahbcfg.d32); ++ DWC_WRITE_REG32(&global_regs->gahbcfg, ahbcfg.d32); + + core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en; + @@ -41350,10 +50715,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + DWC_PRINTF("Multiprocessor Interrupt Enhancement - %s\n", + ((core_if->multiproc_int_enable) ? "enabled" : "disabled")); + -+ /* -+ * Program the GUSBCFG register. ++ /* ++ * Program the GUSBCFG register. + */ -+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); ++ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); + + switch (core_if->hwcfg2.b.op_mode) { + case DWC_MODE_HNP_SRP_CAPABLE: @@ -41397,7 +50762,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + break; + } + -+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32); ++ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32); + +#ifdef CONFIG_USB_DWC_OTG_LPM + if (core_if->core_params->lpm_enable) { @@ -41412,7 +50777,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* Retry 3 times */ + lpmcfg.b.retry_count = 3; + -+ dwc_modify_reg32(&core_if->core_global_regs->glpmcfg, ++ DWC_MODIFY_REG32(&core_if->core_global_regs->glpmcfg, + 0, lpmcfg.d32); + + } @@ -41420,9 +50785,20 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + if (core_if->core_params->ic_usb_cap) { + gusbcfg_data_t gusbcfg = {.d32 = 0 }; + gusbcfg.b.ic_usb_cap = 1; -+ dwc_modify_reg32(&core_if->core_global_regs->gusbcfg, ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gusbcfg, + 0, gusbcfg.d32); + } ++ { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gotgctl.b.otgver = core_if->core_params->otg_ver; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gotgctl, 0, ++ gotgctl.d32); ++ /* Set OTG version supported */ ++ core_if->otg_ver = core_if->core_params->otg_ver; ++ DWC_PRINTF("OTG VER PARAM: %d, OTG VER FLAG: %d\n", ++ core_if->core_params->otg_ver, core_if->otg_ver); ++ } ++ + + /* Enable common interrupts */ + dwc_otg_enable_common_interrupts(core_if); @@ -41441,7 +50817,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + } +} + -+/** ++/** + * This function enables the Device mode interrupts. + * + * @param core_if Programming view of DWC_otg controller @@ -41454,10 +50830,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + DWC_DEBUGPL(DBG_CIL, "%s()\n", __func__); + + /* Disable all interrupts. */ -+ dwc_write_reg32(&global_regs->gintmsk, 0); ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); + + /* Clear any pending interrupts */ -+ dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF); ++ DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF); + + /* Enable the common interrupts */ + dwc_otg_enable_common_interrupts(core_if); @@ -41465,6 +50841,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* Enable interrupts */ + intr_mask.b.usbreset = 1; + intr_mask.b.enumdone = 1; ++ /* Disable Disconnect interrupt in Device mode */ ++ intr_mask.b.disconnect = 0; + + if (!core_if->multiproc_int_enable) { + intr_mask.b.inepintr = 1; @@ -41476,15 +50854,36 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + if (core_if->en_multiple_tx_fifo == 0) { + intr_mask.b.epmismatch = 1; + } ++ ++ //intr_mask.b.incomplisoout = 1; ++ intr_mask.b.incomplisoin = 1; ++ ++/* Enable the ignore frame number for ISOC xfers - MAS */ ++/* Disable to support high bandwith ISOC transfers - manukz */ ++#if 0 ++#ifdef DWC_UTE_PER_IO ++ if (core_if->dma_enable) { ++ if (core_if->dma_desc_enable) { ++ dctl_data_t dctl1 = {.d32 = 0 }; ++ dctl1.b.ifrmnum = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, 0, dctl1.d32); ++ DWC_DEBUG("----Enabled Ignore frame number (0x%08x)", ++ DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dctl)); ++ } ++ } ++#endif ++#endif +#ifdef DWC_EN_ISOC + if (core_if->dma_enable) { + if (core_if->dma_desc_enable == 0) { + if (core_if->pti_enh_enable) { + dctl_data_t dctl = {.d32 = 0 }; + dctl.b.ifrmnum = 1; -+ dwc_modify_reg32(&core_if->dev_if-> -+ dev_global_regs->dctl, 0, -+ dctl.d32); ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dctl, ++ 0, dctl.d32); + } else { + intr_mask.b.incomplisoin = 1; + intr_mask.b.incomplisoout = 1; @@ -41494,7 +50893,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + intr_mask.b.incomplisoin = 1; + intr_mask.b.incomplisoout = 1; + } -+#endif /* DWC_EN_ISOC */ ++#endif /* DWC_EN_ISOC */ + + /** @todo NGS: Should this be a module parameter? */ +#ifdef USE_PERIODIC_EP @@ -41504,16 +50903,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + intr_mask.b.incomplisoout = 1; +#endif + -+ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); + + DWC_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__, -+ dwc_read_reg32(&global_regs->gintmsk)); ++ DWC_READ_REG32(&global_regs->gintmsk)); +} + +/** + * This function initializes the DWC_otg controller registers for + * device mode. -+ * ++ * + * @param core_if Programming view of DWC_otg controller + * + */ @@ -41524,23 +50923,38 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + dwc_otg_dev_if_t *dev_if = core_if->dev_if; + dwc_otg_core_params_t *params = core_if->core_params; + dcfg_data_t dcfg = {.d32 = 0 }; ++ depctl_data_t diepctl = {.d32 = 0 }; + grstctl_t resetctl = {.d32 = 0 }; + uint32_t rx_fifo_size; + fifosize_data_t nptxfifosize; + fifosize_data_t txfifosize; + dthrctl_data_t dthrctl; + fifosize_data_t ptxfifosize; ++ uint16_t rxfsiz, nptxfsiz; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ hwcfg3_data_t hwcfg3 = {.d32 = 0 }; + + /* Restart the Phy Clock */ -+ dwc_write_reg32(core_if->pcgcctl, 0); ++ DWC_WRITE_REG32(core_if->pcgcctl, 0); + + /* Device configuration register */ + init_devspd(core_if); -+ dcfg.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dcfg); ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); + dcfg.b.descdma = (core_if->dma_desc_enable) ? 1 : 0; + dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80; ++ /* Enable Device OUT NAK in case of DDMA mode*/ ++ if (core_if->core_params->dev_out_nak) { ++ dcfg.b.endevoutnak = 1; ++ } + -+ dwc_write_reg32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ if (core_if->core_params->cont_on_bna) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.b.encontonbna = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } ++ ++ ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); + + /* Configure data FIFO sizes */ + if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { @@ -41553,17 +50967,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + /* Rx FIFO */ + DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->grxfsiz)); ++ DWC_READ_REG32(&global_regs->grxfsiz)); + +#ifdef DWC_UTE_CFI -+ core_if->pwron_rxfsiz = dwc_read_reg32(&global_regs->grxfsiz); ++ core_if->pwron_rxfsiz = DWC_READ_REG32(&global_regs->grxfsiz); + core_if->init_rxfsiz = params->dev_rx_fifo_size; +#endif + rx_fifo_size = params->dev_rx_fifo_size; -+ dwc_write_reg32(&global_regs->grxfsiz, rx_fifo_size); ++ DWC_WRITE_REG32(&global_regs->grxfsiz, rx_fifo_size); + + DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->grxfsiz)); ++ DWC_READ_REG32(&global_regs->grxfsiz)); + + /** Set Periodic Tx FIFO Mask all bits 0 */ + core_if->p_tx_msk = 0; @@ -41574,16 +50988,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + if (core_if->en_multiple_tx_fifo == 0) { + /* Non-periodic Tx FIFO */ + DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->gnptxfsiz)); ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); + + nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; + nptxfifosize.b.startaddr = params->dev_rx_fifo_size; + -+ dwc_write_reg32(&global_regs->gnptxfsiz, ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, + nptxfifosize.d32); + + DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->gnptxfsiz)); ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); + + /**@todo NGS: Fix Periodic FIFO Sizing! */ + /* @@ -41595,24 +51009,18 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /** @todo Finish debug of this */ + ptxfifosize.b.startaddr = + nptxfifosize.b.startaddr + nptxfifosize.b.depth; -+ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; -+ i++) { ++ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { + ptxfifosize.b.depth = + params->dev_perio_tx_fifo_size[i]; + DWC_DEBUGPL(DBG_CIL, -+ "initial dptxfsiz_dieptxf[%d]=%08x\n", -+ i, -+ dwc_read_reg32(&global_regs-> -+ dptxfsiz_dieptxf ++ "initial dtxfsiz[%d]=%08x\n", i, ++ DWC_READ_REG32(&global_regs->dtxfsiz + [i])); -+ dwc_write_reg32(&global_regs-> -+ dptxfsiz_dieptxf[i], ++ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], + ptxfifosize.d32); -+ DWC_DEBUGPL(DBG_CIL, -+ "new dptxfsiz_dieptxf[%d]=%08x\n", ++ DWC_DEBUGPL(DBG_CIL, "new dtxfsiz[%d]=%08x\n", + i, -+ dwc_read_reg32(&global_regs-> -+ dptxfsiz_dieptxf ++ DWC_READ_REG32(&global_regs->dtxfsiz + [i])); + ptxfifosize.b.startaddr += ptxfifosize.b.depth; + } @@ -41621,27 +51029,27 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + * Tx FIFOs These FIFOs are numbered from 1 to 15. + * Indexes of the FIFO size module parameters in the + * dev_tx_fifo_size array and the FIFO size registers in -+ * the dptxfsiz_dieptxf array run from 0 to 14. ++ * the dtxfsiz array run from 0 to 14. + */ + + /* Non-periodic Tx FIFO */ + DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->gnptxfsiz)); ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); + +#ifdef DWC_UTE_CFI + core_if->pwron_gnptxfsiz = -+ (dwc_read_reg32(&global_regs->gnptxfsiz) >> 16); ++ (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16); + core_if->init_gnptxfsiz = + params->dev_nperio_tx_fifo_size; +#endif + nptxfifosize.b.depth = params->dev_nperio_tx_fifo_size; + nptxfifosize.b.startaddr = params->dev_rx_fifo_size; + -+ dwc_write_reg32(&global_regs->gnptxfsiz, ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, + nptxfifosize.d32); + + DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->gnptxfsiz)); ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); + + txfifosize.b.startaddr = + nptxfifosize.b.startaddr + nptxfifosize.b.depth; @@ -41652,69 +51060,102 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + params->dev_tx_fifo_size[i]; + + DWC_DEBUGPL(DBG_CIL, -+ "initial dptxfsiz_dieptxf[%d]=%08x\n", ++ "initial dtxfsiz[%d]=%08x\n", + i, -+ dwc_read_reg32(&global_regs-> -+ dptxfsiz_dieptxf ++ DWC_READ_REG32(&global_regs->dtxfsiz + [i])); + +#ifdef DWC_UTE_CFI + core_if->pwron_txfsiz[i] = -+ (dwc_read_reg32 -+ (&global_regs->dptxfsiz_dieptxf[i]) >> 16); ++ (DWC_READ_REG32 ++ (&global_regs->dtxfsiz[i]) >> 16); + core_if->init_txfsiz[i] = + params->dev_tx_fifo_size[i]; +#endif -+ dwc_write_reg32(&global_regs-> -+ dptxfsiz_dieptxf[i], ++ DWC_WRITE_REG32(&global_regs->dtxfsiz[i], + txfifosize.d32); + + DWC_DEBUGPL(DBG_CIL, -+ "new dptxfsiz_dieptxf[%d]=%08x\n", ++ "new dtxfsiz[%d]=%08x\n", + i, -+ dwc_read_reg32(&global_regs-> -+ dptxfsiz_dieptxf ++ DWC_READ_REG32(&global_regs->dtxfsiz + [i])); + + txfifosize.b.startaddr += txfifosize.b.depth; + } ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) { ++ /* Calculating DFIFOCFG for Device mode to include RxFIFO and NPTXFIFO */ ++ gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg); ++ hwcfg3.d32 = DWC_READ_REG32(&global_regs->ghwcfg3); ++ gdfifocfg.b.gdfifocfg = (DWC_READ_REG32(&global_regs->ghwcfg3) >> 16); ++ DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); ++ rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff); ++ nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16); ++ gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz; ++ DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); ++ } + } -+ } -+ /* Flush the FIFOs */ -+ dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ -+ dwc_otg_flush_rx_fifo(core_if); + -+ /* Flush the Learning Queue. */ -+ resetctl.b.intknqflsh = 1; -+ dwc_write_reg32(&core_if->core_global_regs->grstctl, resetctl.d32); ++ /* Flush the FIFOs */ ++ dwc_otg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */ ++ dwc_otg_flush_rx_fifo(core_if); + -+ /* Clear all pending Device Interrupts */ -+ /** @todo - if the condition needed to be checked -+ * or in any case all pending interrutps should be cleared? -+ */ -+ if (core_if->multiproc_int_enable) { -+ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { -+ dwc_write_reg32(&dev_if->dev_global_regs-> -+ diepeachintmsk[i], 0); ++ /* Flush the Learning Queue. */ ++ resetctl.b.intknqflsh = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); ++ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) { ++ core_if->start_predict = 0; ++ for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) { ++ core_if->nextep_seq[i] = 0xff; // 0xff - EP not active ++ } ++ core_if->nextep_seq[0] = 0; ++ core_if->first_in_nextep_seq = 0; ++ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); ++ diepctl.b.nextep = 0; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); ++ ++ /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */ ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt = 2; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_CILV,"%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_CILV, "%2d ", core_if->nextep_seq[i]); ++ } ++ DWC_DEBUGPL(DBG_CILV,"\n"); ++ } ++ ++ /* Clear all pending Device Interrupts */ ++ /** @todo - if the condition needed to be checked ++ * or in any case all pending interrutps should be cleared? ++ */ ++ if (core_if->multiproc_int_enable) { ++ for (i = 0; i < core_if->dev_if->num_in_eps; ++i) { ++ DWC_WRITE_REG32(&dev_if-> ++ dev_global_regs->diepeachintmsk[i], 0); ++ } + } + + for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { -+ dwc_write_reg32(&dev_if->dev_global_regs-> -+ doepeachintmsk[i], 0); ++ DWC_WRITE_REG32(&dev_if-> ++ dev_global_regs->doepeachintmsk[i], 0); + } + -+ dwc_write_reg32(&dev_if->dev_global_regs->deachint, 0xFFFFFFFF); -+ dwc_write_reg32(&dev_if->dev_global_regs->deachintmsk, 0); ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->deachint, 0xFFFFFFFF); ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, 0); + } else { -+ dwc_write_reg32(&dev_if->dev_global_regs->diepmsk, 0); -+ dwc_write_reg32(&dev_if->dev_global_regs->doepmsk, 0); -+ dwc_write_reg32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF); -+ dwc_write_reg32(&dev_if->dev_global_regs->daintmsk, 0); ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, 0); ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, 0); ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF); ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, 0); + } + + for (i = 0; i <= dev_if->num_in_eps; i++) { + depctl_data_t depctl; -+ depctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl); ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); + if (depctl.b.epena) { + depctl.d32 = 0; + depctl.b.epdis = 1; @@ -41723,29 +51164,55 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + depctl.d32 = 0; + } + -+ dwc_write_reg32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); + -+ dwc_write_reg32(&dev_if->in_ep_regs[i]->dieptsiz, 0); -+ dwc_write_reg32(&dev_if->in_ep_regs[i]->diepdma, 0); -+ dwc_write_reg32(&dev_if->in_ep_regs[i]->diepint, 0xFF); ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, 0); ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, 0); ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepint, 0xFF); + } + + for (i = 0; i <= dev_if->num_out_eps; i++) { + depctl_data_t depctl; -+ depctl.d32 = dwc_read_reg32(&dev_if->out_ep_regs[i]->doepctl); ++ depctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); + if (depctl.b.epena) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ gintmsk_data_t gintsts = {.d32 = 0 }; ++ doepint_data_t doepint = {.d32 = 0 }; ++ dctl.b.sgoutnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ do { ++ dwc_udelay(10); ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ } while (!gintsts.b.goutnakeff); ++ gintsts.d32 = 0; ++ gintsts.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ + depctl.d32 = 0; + depctl.b.epdis = 1; + depctl.b.snak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepctl, depctl.d32); ++ do { ++ dwc_udelay(10); ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[i]->doepint); ++ } while (!doepint.b.epdisabled); ++ ++ doepint.b.epdisabled = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[i]->doepint, doepint.d32); ++ ++ dctl.d32 = 0; ++ dctl.b.cgoutnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); + } else { + depctl.d32 = 0; + } + -+ dwc_write_reg32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32); ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, depctl.d32); + -+ dwc_write_reg32(&dev_if->out_ep_regs[i]->doeptsiz, 0); -+ dwc_write_reg32(&dev_if->out_ep_regs[i]->doepdma, 0); -+ dwc_write_reg32(&dev_if->out_ep_regs[i]->doepint, 0xFF); ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doeptsiz, 0); ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepdma, 0); ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepint, 0xFF); + } + + if (core_if->en_multiple_tx_fifo && core_if->dma_enable) { @@ -41766,7 +51233,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + dthrctl.b.rx_thr_len = dev_if->rx_thr_length; + dthrctl.b.ahb_thr_ratio = params->ahb_thr_ratio; + -+ dwc_write_reg32(&dev_if->dev_global_regs->dtknqr3_dthrctl, ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dtknqr3_dthrctl, + dthrctl.d32); + + DWC_DEBUGPL(DBG_CIL, @@ -41783,10 +51250,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + diepmsk_data_t msk = {.d32 = 0 }; + msk.b.txfifoundrn = 1; + if (core_if->multiproc_int_enable) { -+ dwc_modify_reg32(&dev_if->dev_global_regs-> ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs-> + diepeachintmsk[0], msk.d32, msk.d32); + } else { -+ dwc_modify_reg32(&dev_if->dev_global_regs->diepmsk, ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, + msk.d32, msk.d32); + } + } @@ -41795,11 +51262,18 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* Set NAK on Babble */ + dctl_data_t dctl = {.d32 = 0 }; + dctl.b.nakonbble = 1; -+ dwc_modify_reg32(&dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } ++ ++ if (core_if->snpsid >= OTG_CORE_REV_2_94a) { ++ dctl_data_t dctl = {.d32 = 0 }; ++ dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl); ++ dctl.b.sftdiscon = 0; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32); + } +} + -+/** ++/** + * This function enables the Host mode interrupts. + * + * @param core_if Programming view of DWC_otg controller @@ -41812,10 +51286,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + DWC_DEBUGPL(DBG_CIL, "%s(%p)\n", __func__, core_if); + + /* Disable all interrupts. */ -+ dwc_write_reg32(&global_regs->gintmsk, 0); ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); + + /* Clear any pending interrupts. */ -+ dwc_write_reg32(&global_regs->gintsts, 0xFFFFFFFF); ++ DWC_WRITE_REG32(&global_regs->gintsts, 0xFFFFFFFF); + + /* Enable the common interrupts */ + dwc_otg_enable_common_interrupts(core_if); @@ -41824,17 +51298,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + * Enable host mode interrupts without disturbing common + * interrupts. + */ -+ -+ /* Do not need sof interrupt for Descriptor DMA*/ -+ if (!core_if->dma_desc_enable) -+ intr_mask.b.sofintr = 1; ++ ++ intr_mask.b.disconnect = 1; + intr_mask.b.portintr = 1; + intr_mask.b.hcintr = 1; + -+ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, intr_mask.d32); +} + -+/** ++/** + * This function disables the Host Mode interrupts. + * + * @param core_if Programming view of DWC_otg controller @@ -41856,7 +51328,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + intr_mask.b.ptxfempty = 1; + intr_mask.b.nptxfempty = 1; + -+ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, 0); ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, 0); +} + +/** @@ -41878,9 +51350,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + hprt0_data_t hprt0 = {.d32 = 0 }; + fifosize_data_t nptxfifosize; + fifosize_data_t ptxfifosize; ++ uint16_t rxfsiz, nptxfsiz, hptxfsiz; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; + int i; + hcchar_data_t hcchar; + hcfg_data_t hcfg; ++ hfir_data_t hfir; + dwc_otg_hc_regs_t *hc_regs; + int num_channels; + gotgctl_data_t gotgctl = {.d32 = 0 }; @@ -41888,38 +51363,52 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + DWC_DEBUGPL(DBG_CILV, "%s(%p)\n", __func__, core_if); + + /* Restart the Phy Clock */ -+ dwc_write_reg32(core_if->pcgcctl, 0); ++ DWC_WRITE_REG32(core_if->pcgcctl, 0); + + /* Initialize Host Configuration Register */ + init_fslspclksel(core_if); + if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) { -+ hcfg.d32 = dwc_read_reg32(&host_if->host_global_regs->hcfg); ++ hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg); + hcfg.b.fslssupp = 1; -+ dwc_write_reg32(&host_if->host_global_regs->hcfg, hcfg.d32); -+ ++ DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32); ++ ++ } ++ ++ /* This bit allows dynamic reloading of the HFIR register ++ * during runtime. This bit needs to be programmed during ++ * initial configuration and its value must not be changed ++ * during runtime.*/ ++ if (core_if->core_params->reload_ctl == 1) { ++ hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir); ++ hfir.b.hfirrldctrl = 1; ++ DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32); + } + + if (core_if->core_params->dma_desc_enable) { -+ uint8_t op_mode = core_if->hwcfg2.b.op_mode; -+ if (!(core_if->hwcfg4.b.desc_dma && (core_if->snpsid >= OTG_CORE_REV_2_90a) && -+ ((op_mode == DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) || -+ (op_mode == DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) || -+ (op_mode == DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG) || -+ (op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST) || -+ (op_mode == DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST)))) { -+ -+ DWC_ERROR("Host can't operate in Descriptor DMA mode.\n" -+ "Either core version is below 2.90a or " -+ "GHWCFG2, GHWCFG4 registers' values do not allow Descriptor DMA in host mode.\n" -+ "To run the driver in Buffer DMA host mode set dma_desc_enable " -+ "module parameter to 0.\n"); -+ return; -+ } -+ hcfg.d32 = dwc_read_reg32(&host_if->host_global_regs->hcfg); ++ uint8_t op_mode = core_if->hwcfg2.b.op_mode; ++ if (! ++ (core_if->hwcfg4.b.desc_dma ++ && (core_if->snpsid >= OTG_CORE_REV_2_90a) ++ && ((op_mode == DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ++ || (op_mode == DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) ++ || (op_mode == ++ DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG) ++ || (op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST) ++ || (op_mode == ++ DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST)))) { ++ ++ DWC_ERROR("Host can't operate in Descriptor DMA mode.\n" ++ "Either core version is below 2.90a or " ++ "GHWCFG2, GHWCFG4 registers' values do not allow Descriptor DMA in host mode.\n" ++ "To run the driver in Buffer DMA host mode set dma_desc_enable " ++ "module parameter to 0.\n"); ++ return; ++ } ++ hcfg.d32 = DWC_READ_REG32(&host_if->host_global_regs->hcfg); + hcfg.b.descdma = 1; -+ dwc_write_reg32(&host_if->host_global_regs->hcfg, hcfg.d32); ++ DWC_WRITE_REG32(&host_if->host_global_regs->hcfg, hcfg.d32); + } -+ ++ + /* Configure data FIFO sizes */ + if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) { + DWC_DEBUGPL(DBG_CIL, "Total FIFO Size=%d\n", @@ -41933,65 +51422,80 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + /* Rx FIFO */ + DWC_DEBUGPL(DBG_CIL, "initial grxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->grxfsiz)); -+ dwc_write_reg32(&global_regs->grxfsiz, ++ DWC_READ_REG32(&global_regs->grxfsiz)); ++ DWC_WRITE_REG32(&global_regs->grxfsiz, + params->host_rx_fifo_size); + DWC_DEBUGPL(DBG_CIL, "new grxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->grxfsiz)); ++ DWC_READ_REG32(&global_regs->grxfsiz)); + + /* Non-periodic Tx FIFO */ + DWC_DEBUGPL(DBG_CIL, "initial gnptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->gnptxfsiz)); ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); + nptxfifosize.b.depth = params->host_nperio_tx_fifo_size; + nptxfifosize.b.startaddr = params->host_rx_fifo_size; -+ dwc_write_reg32(&global_regs->gnptxfsiz, nptxfifosize.d32); ++ DWC_WRITE_REG32(&global_regs->gnptxfsiz, nptxfifosize.d32); + DWC_DEBUGPL(DBG_CIL, "new gnptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->gnptxfsiz)); ++ DWC_READ_REG32(&global_regs->gnptxfsiz)); + + /* Periodic Tx FIFO */ + DWC_DEBUGPL(DBG_CIL, "initial hptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->hptxfsiz)); ++ DWC_READ_REG32(&global_regs->hptxfsiz)); + ptxfifosize.b.depth = params->host_perio_tx_fifo_size; + ptxfifosize.b.startaddr = + nptxfifosize.b.startaddr + nptxfifosize.b.depth; -+ dwc_write_reg32(&global_regs->hptxfsiz, ptxfifosize.d32); ++ DWC_WRITE_REG32(&global_regs->hptxfsiz, ptxfifosize.d32); + DWC_DEBUGPL(DBG_CIL, "new hptxfsiz=%08x\n", -+ dwc_read_reg32(&global_regs->hptxfsiz)); ++ DWC_READ_REG32(&global_regs->hptxfsiz)); ++ ++ if (core_if->en_multiple_tx_fifo ++ && core_if->snpsid <= OTG_CORE_REV_2_94a) { ++ /* Global DFIFOCFG calculation for Host mode - include RxFIFO, NPTXFIFO and HPTXFIFO */ ++ gdfifocfg.d32 = DWC_READ_REG32(&global_regs->gdfifocfg); ++ rxfsiz = (DWC_READ_REG32(&global_regs->grxfsiz) & 0x0000ffff); ++ nptxfsiz = (DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16); ++ hptxfsiz = (DWC_READ_REG32(&global_regs->hptxfsiz) >> 16); ++ gdfifocfg.b.epinfobase = rxfsiz + nptxfsiz + hptxfsiz; ++ DWC_WRITE_REG32(&global_regs->gdfifocfg, gdfifocfg.d32); ++ } + } + ++ /* TODO - check this */ ++ /* Clear Host Set HNP Enable in the OTG Control Register */ ++ gotgctl.b.hstsethnpen = 1; ++ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); ++ /* Make sure the FIFOs are flushed. */ ++ dwc_otg_flush_tx_fifo(core_if, 0x10 /* all TX FIFOs */ ); ++ dwc_otg_flush_rx_fifo(core_if); ++ + /* Clear Host Set HNP Enable in the OTG Control Register */ + gotgctl.b.hstsethnpen = 1; -+ dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0); ++ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); + -+ /* Make sure the FIFOs are flushed. */ -+ dwc_otg_flush_tx_fifo(core_if, 0x10 /* all Tx FIFOs */ ); -+ dwc_otg_flush_rx_fifo(core_if); -+ -+ if(!core_if->core_params->dma_desc_enable) { ++ if (!core_if->core_params->dma_desc_enable) { + /* Flush out any leftover queued requests. */ + num_channels = core_if->core_params->host_channels; -+ ++ + for (i = 0; i < num_channels; i++) { + hc_regs = core_if->host_if->hc_regs[i]; -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + hcchar.b.chen = 0; + hcchar.b.chdis = 1; + hcchar.b.epdir = 0; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); + } + + /* Halt all channels to put them into a known state. */ + for (i = 0; i < num_channels; i++) { + int count = 0; + hc_regs = core_if->host_if->hc_regs[i]; -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + hcchar.b.chen = 1; + hcchar.b.chdis = 1; + hcchar.b.epdir = 0; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); + DWC_DEBUGPL(DBG_HCDV, "%s: Halt channel %d regs %p\n", __func__, i, hc_regs); + do { -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + if (++count > 1000) { + DWC_ERROR + ("%s: Unable to clear halt on channel %d (timeout HCCHAR 0x%X @%p)\n", @@ -42002,7 +51506,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + } while (hcchar.b.chen); + } + } -+ ++ + /* Turn on the vbus power. */ + DWC_PRINTF("Init: Port Power? op_state=%d\n", core_if->op_state); + if (core_if->op_state == A_HOST) { @@ -42010,7 +51514,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + DWC_PRINTF("Init: Power Port (%d)\n", hprt0.b.prtpwr); + if (hprt0.b.prtpwr == 0) { + hprt0.b.prtpwr = 1; -+ dwc_write_reg32(host_if->hprt0, hprt0.d32); ++ DWC_WRITE_REG32(host_if->hprt0, hprt0.d32); + } + } + @@ -42041,7 +51545,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* Clear old interrupt conditions for this host channel. */ + hc_intr_mask.d32 = 0xFFFFFFFF; + hc_intr_mask.b.reserved14_31 = 0; -+ dwc_write_reg32(&hc_regs->hcint, hc_intr_mask.d32); ++ DWC_WRITE_REG32(&hc_regs->hcint, hc_intr_mask.d32); + + /* Enable channel interrupts required for this transfer. */ + hc_intr_mask.d32 = 0; @@ -42051,10 +51555,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + if (!core_if->dma_desc_enable) + hc_intr_mask.b.ahberr = 1; + else { -+ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) + hc_intr_mask.b.xfercompl = 1; + } -+ ++ + if (hc->error_state && !hc->do_split && + hc->ep_type != DWC_OTG_EP_TYPE_ISOC) { + hc_intr_mask.b.ack = 1; @@ -42130,15 +51634,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + break; + } + } -+ dwc_write_reg32(&hc_regs->hcintmsk, hc_intr_mask.d32); ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, hc_intr_mask.d32); + + /* Enable the top level host channel interrupt. */ + intr_enable = (1 << hc_num); -+ dwc_modify_reg32(&host_if->host_global_regs->haintmsk, 0, intr_enable); ++ DWC_MODIFY_REG32(&host_if->host_global_regs->haintmsk, 0, intr_enable); + + /* Make sure host channel interrupts are enabled. */ + gintmsk.b.hcintr = 1; -+ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32); ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32); + + /* + * Program the HCCHARn register with the endpoint characteristics for @@ -42152,16 +51656,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + hcchar.b.eptype = hc->ep_type; + hcchar.b.mps = hc->max_packet; + -+ dwc_write_reg32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32); ++ DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32); + -+ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); -+ DWC_DEBUGPL(DBG_HCDV, " Dev Addr: %d\n", hcchar.b.devaddr); -+ DWC_DEBUGPL(DBG_HCDV, " Ep Num: %d\n", hcchar.b.epnum); -+ DWC_DEBUGPL(DBG_HCDV, " Is In: %d\n", hcchar.b.epdir); -+ DWC_DEBUGPL(DBG_HCDV, " Is Low Speed: %d\n", hcchar.b.lspddev); -+ DWC_DEBUGPL(DBG_HCDV, " Ep Type: %d\n", hcchar.b.eptype); -+ DWC_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n", hcchar.b.mps); -+ DWC_DEBUGPL(DBG_HCDV, " Multi Cnt: %d\n", hcchar.b.multicnt); ++ DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d, Dev Addr %d, EP #%d\n", ++ __func__, hc->hc_num, hcchar.b.devaddr, hcchar.b.epnum); ++ DWC_DEBUGPL(DBG_HCDV, " Is In %d, Is Low Speed %d, EP Type %d, " ++ "Max Pkt %d, Multi Cnt %d\n", ++ hcchar.b.epdir, hcchar.b.lspddev, hcchar.b.eptype, ++ hcchar.b.mps, hcchar.b.multicnt); + + /* + * Program the HCSPLIT register for SPLITs @@ -42175,15 +51677,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + hcsplt.b.xactpos = hc->xact_pos; + hcsplt.b.hubaddr = hc->hub_addr; + hcsplt.b.prtaddr = hc->port_addr; -+ DWC_DEBUGPL(DBG_HCDV, " comp split %d\n", hc->complete_split); -+ DWC_DEBUGPL(DBG_HCDV, " xact pos %d\n", hc->xact_pos); -+ DWC_DEBUGPL(DBG_HCDV, " hub addr %d\n", hc->hub_addr); -+ DWC_DEBUGPL(DBG_HCDV, " port addr %d\n", hc->port_addr); -+ DWC_DEBUGPL(DBG_HCDV, " is_in %d\n", hc->ep_is_in); -+ DWC_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n", hcchar.b.mps); -+ DWC_DEBUGPL(DBG_HCDV, " xferlen: %d\n", hc->xfer_len); ++ DWC_DEBUGPL(DBG_HCDV, "\t comp split %d\n", hc->complete_split); ++ DWC_DEBUGPL(DBG_HCDV, "\t xact pos %d\n", hc->xact_pos); ++ DWC_DEBUGPL(DBG_HCDV, "\t hub addr %d\n", hc->hub_addr); ++ DWC_DEBUGPL(DBG_HCDV, "\t port addr %d\n", hc->port_addr); ++ DWC_DEBUGPL(DBG_HCDV, "\t is_in %d\n", hc->ep_is_in); ++ DWC_DEBUGPL(DBG_HCDV, "\t Max Pkt: %d\n", hcchar.b.mps); ++ DWC_DEBUGPL(DBG_HCDV, "\t xferlen: %d\n", hc->xfer_len); + } -+ dwc_write_reg32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32); ++ DWC_WRITE_REG32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32); + +} + @@ -42224,7 +51726,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + dwc_otg_core_global_regs_t *global_regs; + dwc_otg_host_global_regs_t *host_global_regs; + -+ DWC_DEBUGPL(DBG_HW2937, " dwc_otg_hc_halt(%d)\n", hc->hc_num); + hc_regs = core_if->host_if->hc_regs[hc->hc_num]; + global_regs = core_if->core_global_regs; + host_global_regs = core_if->host_if->host_global_regs; @@ -42243,14 +51744,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + hcintmsk_data_t hcintmsk; + hcintmsk.d32 = 0; + hcintmsk.b.chhltd = 1; -+ dwc_write_reg32(&hc_regs->hcintmsk, hcintmsk.d32); ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, hcintmsk.d32); + + /* + * Make sure no other interrupts besides halt are currently + * pending. Handling another interrupt could cause a crash due + * to the QTD and QH state. + */ -+ dwc_write_reg32(&hc_regs->hcint, ~hcintmsk.d32); ++ DWC_WRITE_REG32(&hc_regs->hcint, ~hcintmsk.d32); + + /* + * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR @@ -42259,7 +51760,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + */ + hc->halt_status = halt_status; + -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + if (hcchar.b.chen == 0) { + /* + * The channel is either already halted or it hasn't @@ -42290,32 +51791,32 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + return; + } + -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); -+ ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); ++ + /* No need to set the bit in DDMA for disabling the channel */ -+ //TODO check it everywhere channel is disabled -+ if(!core_if->core_params->dma_desc_enable) ++ //TODO check it everywhere channel is disabled ++ if (!core_if->core_params->dma_desc_enable) + hcchar.b.chen = 1; + hcchar.b.chdis = 1; -+ ++ + if (!core_if->dma_enable) { + /* Check for space in the request queue to issue the halt. */ + if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL || + hc->ep_type == DWC_OTG_EP_TYPE_BULK) { -+ nptxsts.d32 = dwc_read_reg32(&global_regs->gnptxsts); ++ nptxsts.d32 = DWC_READ_REG32(&global_regs->gnptxsts); + if (nptxsts.b.nptxqspcavail == 0) { + hcchar.b.chen = 0; + } + } else { + hptxsts.d32 = -+ dwc_read_reg32(&host_global_regs->hptxsts); ++ DWC_READ_REG32(&host_global_regs->hptxsts); + if ((hptxsts.b.ptxqspcavail == 0) + || (core_if->queuing_high_bandwidth)) { + hcchar.b.chen = 0; + } + } + } -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); + + hc->halt_status = halt_status; + @@ -42353,8 +51854,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + * conditions. + */ + hc_regs = core_if->host_if->hc_regs[hc->hc_num]; -+ dwc_write_reg32(&hc_regs->hcintmsk, 0); -+ dwc_write_reg32(&hc_regs->hcint, 0xFFFFFFFF); ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0); ++ DWC_WRITE_REG32(&hc_regs->hcint, 0xFFFFFFFF); +#ifdef DEBUG + DWC_TIMER_CANCEL(core_if->hc_xfer_timer[hc->hc_num]); +#endif @@ -42377,7 +51878,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { + hfnum_data_t hfnum; + hfnum.d32 = -+ dwc_read_reg32(&core_if->host_if->host_global_regs->hfnum); ++ DWC_READ_REG32(&core_if->host_if->host_global_regs->hfnum); + + /* 1 if _next_ frame is odd, 0 if it's even */ + hcchar->b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1; @@ -42407,36 +51908,85 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 +#ifdef DEBUG +void hc_xfer_timeout(void *ptr) +{ -+ hc_xfer_info_t *xfer_info = (hc_xfer_info_t *) ptr; -+ int hc_num = xfer_info->hc->hc_num; ++ hc_xfer_info_t *xfer_info = NULL; ++ int hc_num = 0; ++ ++ if (ptr) ++ xfer_info = (hc_xfer_info_t *) ptr; ++ ++ if (!xfer_info->hc) { ++ DWC_ERROR("xfer_info->hc = %p\n", xfer_info->hc); ++ return; ++ } ++ ++ hc_num = xfer_info->hc->hc_num; + DWC_WARN("%s: timeout on channel %d\n", __func__, hc_num); + DWC_WARN(" start_hcchar_val 0x%08x\n", + xfer_info->core_if->start_hcchar_val[hc_num]); +} +#endif + ++void ep_xfer_timeout(void *ptr) ++{ ++ ep_xfer_info_t *xfer_info = NULL; ++ int ep_num = 0; ++ dctl_data_t dctl = {.d32 = 0 }; ++ gintsts_data_t gintsts = {.d32 = 0 }; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ ++ if (ptr) ++ xfer_info = (ep_xfer_info_t *) ptr; ++ ++ if (!xfer_info->ep) { ++ DWC_ERROR("xfer_info->ep = %p\n", xfer_info->ep); ++ return; ++ } ++ ++ ep_num = xfer_info->ep->num; ++ DWC_WARN("%s: timeout on endpoit %d\n", __func__, ep_num); ++ /* Put the sate to 2 as it was time outed */ ++ xfer_info->state = 2; ++ ++ dctl.d32 = ++ DWC_READ_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl); ++ gintsts.d32 = ++ DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintsts); ++ gintmsk.d32 = ++ DWC_READ_REG32(&xfer_info->core_if->core_global_regs->gintmsk); ++ ++ if (!gintmsk.b.goutnakeff) { ++ /* Unmask it */ ++ gintmsk.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&xfer_info->core_if->core_global_regs->gintmsk, ++ gintmsk.d32); ++ ++ } ++ ++ if (!gintsts.b.goutnakeff) { ++ dctl.b.sgoutnak = 1; ++ } ++ DWC_WRITE_REG32(&xfer_info->core_if->dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ ++} ++ +void set_pid_isoc(dwc_hc_t * hc) +{ + /* Set up the initial PID for the transfer. */ + if (hc->speed == DWC_OTG_EP_SPEED_HIGH) { + if (hc->ep_is_in) { + if (hc->multi_count == 1) { -+ hc->data_pid_start = -+ DWC_OTG_HC_PID_DATA0; ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA0; + } else if (hc->multi_count == 2) { -+ hc->data_pid_start = -+ DWC_OTG_HC_PID_DATA1; ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA1; + } else { -+ hc->data_pid_start = -+ DWC_OTG_HC_PID_DATA2; ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA2; + } + } else { + if (hc->multi_count == 1) { -+ hc->data_pid_start = -+ DWC_OTG_HC_PID_DATA0; ++ hc->data_pid_start = DWC_OTG_HC_PID_DATA0; + } else { -+ hc->data_pid_start = -+ DWC_OTG_HC_PID_MDATA; ++ hc->data_pid_start = DWC_OTG_HC_PID_MDATA; + } + } + } else { @@ -42571,7 +52121,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + hc->start_pkt_count = num_packets; + hctsiz.b.pktcnt = num_packets; + hctsiz.b.pid = hc->data_pid_start; -+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); + + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); + DWC_DEBUGPL(DBG_HCDV, " Xfer Size: %d\n", hctsiz.b.xfersize); @@ -42583,20 +52133,20 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + if (hc->align_buff) { + dma_addr = hc->align_buff; + } else { -+ dma_addr = (uint32_t)hc->xfer_buff; ++ dma_addr = ((unsigned long)hc->xfer_buff & 0xffffffff); + } -+ dwc_write_reg32(&hc_regs->hcdma, dma_addr); ++ DWC_WRITE_REG32(&hc_regs->hcdma, dma_addr); + } + + /* Start the split */ + if (hc->do_split) { + hcsplt_data_t hcsplt; -+ hcsplt.d32 = dwc_read_reg32(&hc_regs->hcsplt); ++ hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt); + hcsplt.b.spltena = 1; -+ dwc_write_reg32(&hc_regs->hcsplt, hcsplt.d32); ++ DWC_WRITE_REG32(&hc_regs->hcsplt, hcsplt.d32); + } + -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + hcchar.b.multicnt = hc->multi_count; + hc_set_even_odd_frame(core_if, hc, &hcchar); +#ifdef DEBUG @@ -42610,7 +52160,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* Set host channel enable after all other setup is complete. */ + hcchar.b.chen = 1; + hcchar.b.chdis = 0; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); + + hc->xfer_started = 1; + hc->requests++; @@ -42625,6 +52175,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + hc->hc_num, core_if);//GRAYG + core_if->hc_xfer_info[hc->hc_num].core_if = core_if; + core_if->hc_xfer_info[hc->hc_num].hc = hc; ++ + /* Start a timer for this transfer. */ + DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000); + } @@ -42632,7 +52183,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 +} + +/** -+ * This function does the setup for a data transfer for a host channel ++ * This function does the setup for a data transfer for a host channel + * and starts the transfer in Descriptor DMA mode. + * + * Initializes HCTSIZ register. For a PING transfer the Do Ping bit is set. @@ -42647,40 +52198,40 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + */ +void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc) +{ -+ dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; ++ dwc_otg_hc_regs_t *hc_regs = core_if->host_if->hc_regs[hc->hc_num]; + hcchar_data_t hcchar; + hctsiz_data_t hctsiz; -+ hcdma_data_t hcdma; -+ ++ hcdma_data_t hcdma; ++ + hctsiz.d32 = 0; + -+ if (hc->do_ping && !hc->ep_is_in) ++ if (hc->do_ping) + hctsiz.b_ddma.dopng = 1; + + if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) + set_pid_isoc(hc); -+ ++ + /* Packet Count and Xfer Size are not used in Descriptor DMA mode */ + hctsiz.b_ddma.pid = hc->data_pid_start; -+ hctsiz.b_ddma.ntd = hc->ntd - 1; /* 0 - 1 descriptor, 1 - 2 descriptors, etc. */ -+ hctsiz.b_ddma.schinfo = hc->schinfo; /* Non-zero only for high-speed interrupt endpoints */ -+ ++ hctsiz.b_ddma.ntd = hc->ntd - 1; /* 0 - 1 descriptor, 1 - 2 descriptors, etc. */ ++ hctsiz.b_ddma.schinfo = hc->schinfo; /* Non-zero only for high-speed interrupt endpoints */ ++ + DWC_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, hc->hc_num); + DWC_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid); -+ DWC_DEBUGPL(DBG_HCDV, " NTD: %d\n", hctsiz.b_ddma.ntd); ++ DWC_DEBUGPL(DBG_HCDV, " NTD: %d\n", hctsiz.b_ddma.ntd); + -+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); + + hcdma.d32 = 0; -+ hcdma.b.dma_addr = ((uint32_t)hc->desc_list_addr) >> 11; -+ ++ hcdma.b.dma_addr = ((uint32_t) hc->desc_list_addr) >> 11; ++ + /* Always start from first descriptor. */ + hcdma.b.ctd = 0; -+ dwc_write_reg32(&hc_regs->hcdma, hcdma.d32); ++ DWC_WRITE_REG32(&hc_regs->hcdma, hcdma.d32); + -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + hcchar.b.multicnt = hc->multi_count; -+ ++ +#ifdef DEBUG + core_if->start_hcchar_val[hc->hc_num] = hcchar.d32; + if (hcchar.b.chdis) { @@ -42692,14 +52243,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* Set host channel enable after all other setup is complete. */ + hcchar.b.chen = 1; + hcchar.b.chdis = 0; -+ -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); + + hc->xfer_started = 1; + hc->requests++; -+ ++ +#ifdef DEBUG -+ if ((hc->ep_type != DWC_OTG_EP_TYPE_INTR) && (hc->ep_type != DWC_OTG_EP_TYPE_ISOC)) { ++ if ((hc->ep_type != DWC_OTG_EP_TYPE_INTR) ++ && (hc->ep_type != DWC_OTG_EP_TYPE_ISOC)) { + DWC_DEBUGPL(DBG_HCDV, "DMA transfer %d from core_if %p\n", + hc->hc_num, core_if);//GRAYG + core_if->hc_xfer_info[hc->hc_num].core_if = core_if; @@ -42707,11 +52259,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* Start a timer for this transfer. */ + DWC_TIMER_SCHEDULE(core_if->hc_xfer_timer[hc->hc_num], 10000); + } -+ +#endif -+ ++ +} -+ ++ +/** + * This function continues a data transfer that was started by previous call + * to dwc_otg_hc_start_transfer. The caller must ensure there is @@ -42754,13 +52305,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + dwc_otg_hc_regs_t *hc_regs = + core_if->host_if->hc_regs[hc->hc_num]; + -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + hc_set_even_odd_frame(core_if, hc, &hcchar); + hcchar.b.chen = 1; + hcchar.b.chdis = 0; + DWC_DEBUGPL(DBG_HCDV, " IN xfer: hcchar = 0x%08x\n", + hcchar.d32); -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); + hc->requests++; + return 1; + } else { @@ -42771,7 +52322,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + hcchar_data_t hcchar; + dwc_otg_hc_regs_t *hc_regs; + hc_regs = core_if->host_if->hc_regs[hc->hc_num]; -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + hc_set_even_odd_frame(core_if, hc, &hcchar); + } + @@ -42800,12 +52351,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + hctsiz.d32 = 0; + hctsiz.b.dopng = 1; + hctsiz.b.pktcnt = 1; -+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); + -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + hcchar.b.chen = 1; + hcchar.b.chdis = 0; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); +} + +/* @@ -42840,7 +52391,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + if ((((unsigned long)data_buff) & 0x3) == 0) { + /* xfer_buff is DWORD aligned. */ + for (i = 0; i < dword_count; i++, data_buff++) { -+ dwc_write_reg32(data_fifo, *data_buff); ++ DWC_WRITE_REG32(data_fifo, *data_buff); + } + } else { + /* xfer_buff is not DWORD aligned. */ @@ -42849,7 +52400,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + data = + (data_buff[0] | data_buff[1] << 8 | data_buff[2] << + 16 | data_buff[3] << 24); -+ dwc_write_reg32(data_fifo, data); ++ DWC_WRITE_REG32(data_fifo, data); + } + } + @@ -42858,21 +52409,62 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 +} + +/** -+ * Gets the current USB frame number. This is the frame number from the last -+ * SOF packet. ++ * Gets the current USB frame number. This is the frame number from the last ++ * SOF packet. + */ +uint32_t dwc_otg_get_frame_number(dwc_otg_core_if_t * core_if) +{ + dsts_data_t dsts; -+ 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); + + /* read current frame/microframe number from DSTS register */ + return dsts.b.soffn; +} + +/** -+ * This function reads a setup packet from the Rx FIFO into the destination -+ * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl) ++ * Calculates and gets the frame Interval value of HFIR register according PHY ++ * type and speed.The application can modify a value of HFIR register only after ++ * the Port Enable bit of the Host Port Control and Status register ++ * (HPRT.PrtEnaPort) has been set. ++*/ ++ ++uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if) ++{ ++ gusbcfg_data_t usbcfg; ++ hwcfg2_data_t hwcfg2; ++ hprt0_data_t hprt0; ++ int clock = 60; // default value ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); ++ hwcfg2.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2); ++ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); ++ if (!usbcfg.b.physel && usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif) ++ clock = 60; ++ if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 3) ++ clock = 48; ++ if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel && ++ !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif) ++ clock = 30; ++ if (!usbcfg.b.phylpwrclksel && !usbcfg.b.physel && ++ !usbcfg.b.ulpi_utmi_sel && !usbcfg.b.phyif) ++ clock = 60; ++ if (usbcfg.b.phylpwrclksel && !usbcfg.b.physel && ++ !usbcfg.b.ulpi_utmi_sel && usbcfg.b.phyif) ++ clock = 48; ++ if (usbcfg.b.physel && !usbcfg.b.phyif && hwcfg2.b.fs_phy_type == 2) ++ clock = 48; ++ if (usbcfg.b.physel && hwcfg2.b.fs_phy_type == 1) ++ clock = 48; ++ if (hprt0.b.prtspd == 0) ++ /* High speed case */ ++ return 125 * clock; ++ else ++ /* FS/LS case */ ++ return 1000 * clock; ++} ++ ++/** ++ * This function reads a setup packet from the Rx FIFO into the destination ++ * buffer. This function is called from the Rx Status Queue Level (RxStsQLvl) + * Interrupt routine when a SETUP packet has been received in Slave mode. + * + * @param core_if Programming view of DWC_otg controller. @@ -42880,16 +52472,25 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + */ +void dwc_otg_read_setup_packet(dwc_otg_core_if_t * core_if, uint32_t * dest) +{ ++ device_grxsts_data_t status; + /* Get the 8 bytes of a setup transaction data */ + + /* Pop 2 DWORDS off the receive data FIFO into memory */ -+ dest[0] = dwc_read_reg32(core_if->data_fifo[0]); -+ dest[1] = dwc_read_reg32(core_if->data_fifo[0]); ++ dest[0] = DWC_READ_REG32(core_if->data_fifo[0]); ++ dest[1] = DWC_READ_REG32(core_if->data_fifo[0]); ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ status.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->grxstsp); ++ DWC_DEBUGPL(DBG_ANY, ++ "EP:%d BCnt:%d " "pktsts:%x Frame:%d(0x%0x)\n", ++ status.b.epnum, status.b.bcnt, status.b.pktsts, ++ status.b.fn, status.b.fn); ++ } +} + +/** -+ * This function enables EP0 OUT to receive SETUP packets and configures EP0 -+ * IN for transmitting packets. It is normally called when the ++ * This function enables EP0 OUT to receive SETUP packets and configures EP0 ++ * IN for transmitting packets. It is normally called when the + * "Enumeration Done" interrupt occurs. + * + * @param core_if Programming view of DWC_otg controller. @@ -42903,10 +52504,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + depctl_data_t doepctl; + dctl_data_t dctl = {.d32 = 0 }; + ++ ep->stp_rollover = 0; + /* Read the Device Status and Endpoint 0 Control registers */ -+ dsts.d32 = dwc_read_reg32(&dev_if->dev_global_regs->dsts); -+ diepctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl); -+ doepctl.d32 = dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl); ++ dsts.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dsts); ++ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); ++ doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl); + + /* Set the MPS of the IN EP based on the enumeration speed */ + switch (dsts.b.enumspd) { @@ -42920,28 +52522,30 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + break; + } + -+ dwc_write_reg32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); + + /* Enable OUT EP for receive */ ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) { + doepctl.b.epena = 1; -+ dwc_write_reg32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); -+ ++ 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_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_READ_REG32(&dev_if->in_ep_regs[0]->diepctl)); +#endif + dctl.b.cgnpinnak = 1; + -+ dwc_modify_reg32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); + DWC_DEBUGPL(DBG_PCDV, "dctl=%0x\n", -+ dwc_read_reg32(&dev_if->dev_global_regs->dctl)); ++ DWC_READ_REG32(&dev_if->dev_global_regs->dctl)); ++ +} + +/** + * This function activates an EP. The Device EP control register for -+ * the EP is configured as defined in the ep structure. Note: This ++ * the EP is configured as defined in the ep structure. Note: This + * function is not used for EP0. + * + * @param core_if Programming view of DWC_otg controller. @@ -42953,10 +52557,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + depctl_data_t depctl; + volatile uint32_t *addr; + daint_data_t daintmsk = {.d32 = 0 }; ++ dcfg_data_t dcfg; ++ uint8_t i; + + DWC_DEBUGPL(DBG_PCDV, "%s() EP%d-%s\n", __func__, ep->num, + (ep->is_in ? "IN" : "OUT")); + ++#ifdef DWC_UTE_PER_IO ++ ep->xiso_frame_num = 0xFFFFFFFF; ++ ep->xiso_active_xfers = 0; ++ ep->xiso_queued_xfers = 0; ++#endif + /* Read DEPCTLn register */ + if (ep->is_in == 1) { + addr = &dev_if->in_ep_regs[ep->num]->diepctl; @@ -42968,21 +52579,45 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + /* If the EP is already active don't change the EP Control + * register. */ -+ depctl.d32 = dwc_read_reg32(addr); ++ depctl.d32 = DWC_READ_REG32(addr); + if (!depctl.b.usbactep) { + depctl.b.mps = ep->maxpacket; + depctl.b.eptype = ep->type; + depctl.b.txfnum = ep->tx_fifo_num; + + if (ep->type == DWC_OTG_EP_TYPE_ISOC) { -+ depctl.b.setd0pid = 1; // ??? ++ depctl.b.setd0pid = 1; // ??? + } else { + depctl.b.setd0pid = 1; + } + depctl.b.usbactep = 1; + -+ dwc_write_reg32(addr, depctl.d32); -+ DWC_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", dwc_read_reg32(addr)); ++ /* Update nextep_seq array and EPMSCNT in DCFG*/ ++ if (!(depctl.b.eptype & 1) && (ep->is_in == 1)) { // NP IN EP ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ if (core_if->nextep_seq[i] == core_if->first_in_nextep_seq) ++ break; ++ } ++ core_if->nextep_seq[i] = ep->num; ++ core_if->nextep_seq[ep->num] = core_if->first_in_nextep_seq; ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt++; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_PCDV, "%2d\n", ++ core_if->nextep_seq[i]); ++ } ++ ++ } ++ ++ ++ DWC_WRITE_REG32(addr, depctl.d32); ++ DWC_DEBUGPL(DBG_PCDV, "DEPCTL=%08x\n", DWC_READ_REG32(addr)); + } + + /* Enable the Interrupt for this EP */ @@ -42994,17 +52629,26 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + diepmsk.b.epdisabled = 1; + diepmsk.b.ahberr = 1; + diepmsk.b.intknepmis = 1; ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) ++ diepmsk.b.intknepmis = 0; + diepmsk.b.txfifoundrn = 1; //????? ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ diepmsk.b.nak = 1; ++ } + ++ ++ ++/* + if (core_if->dma_desc_enable) { + diepmsk.b.bna = 1; + } ++*/ +/* -+ if(core_if->dma_enable) { ++ if (core_if->dma_enable) { + doepmsk.b.nak = 1; + } +*/ -+ dwc_write_reg32(&dev_if->dev_global_regs-> ++ DWC_WRITE_REG32(&dev_if->dev_global_regs-> + diepeachintmsk[ep->num], diepmsk.d32); + + } else { @@ -43012,35 +52656,52 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + doepmsk.b.xfercompl = 1; + doepmsk.b.ahberr = 1; + doepmsk.b.epdisabled = 1; ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) ++ doepmsk.b.outtknepdis = 1; ++ ++/* + + if (core_if->dma_desc_enable) { + doepmsk.b.bna = 1; + } ++*/ +/* + doepmsk.b.babble = 1; + doepmsk.b.nyet = 1; + doepmsk.b.nak = 1; +*/ -+ dwc_write_reg32(&dev_if->dev_global_regs-> ++ DWC_WRITE_REG32(&dev_if->dev_global_regs-> + doepeachintmsk[ep->num], doepmsk.d32); + } -+ dwc_modify_reg32(&dev_if->dev_global_regs->deachintmsk, ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->deachintmsk, + 0, daintmsk.d32); + } else { -+ dwc_modify_reg32(&dev_if->dev_global_regs->daintmsk, ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (ep->is_in) { ++ diepmsk_data_t diepmsk = {.d32 = 0 }; ++ diepmsk.b.nak = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->diepmsk, 0, diepmsk.d32); ++ } else { ++ doepmsk_data_t doepmsk = {.d32 = 0 }; ++ doepmsk.b.outtknepdis = 1; ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->doepmsk, 0, doepmsk.d32); ++ } ++ } ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->daintmsk, + 0, daintmsk.d32); + } + + DWC_DEBUGPL(DBG_PCDV, "DAINTMSK=%0x\n", -+ dwc_read_reg32(&dev_if->dev_global_regs->daintmsk)); ++ DWC_READ_REG32(&dev_if->dev_global_regs->daintmsk)); + + ep->stall_clear_flag = 0; ++ + return; +} + +/** -+ * This function deactivates an EP. This is done by clearing the USB Active -+ * EP bit in the Device EP control register. Note: This function is not used ++ * This function deactivates an EP. This is done by clearing the USB Active ++ * EP bit in the Device EP control register. Note: This function is not used + * for EP0. EP0 cannot be deactivated. + * + * @param core_if Programming view of DWC_otg controller. @@ -43051,6 +52712,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + depctl_data_t depctl = {.d32 = 0 }; + volatile uint32_t *addr; + daint_data_t daintmsk = {.d32 = 0 }; ++ dcfg_data_t dcfg; ++ uint8_t i = 0; ++ ++#ifdef DWC_UTE_PER_IO ++ ep->xiso_frame_num = 0xFFFFFFFF; ++ ep->xiso_active_xfers = 0; ++ ep->xiso_queued_xfers = 0; ++#endif + + /* Read DEPCTLn register */ + if (ep->is_in == 1) { @@ -43061,31 +52730,128 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + daintmsk.ep.out = 1 << ep->num; + } + -+ depctl.d32 = dwc_read_reg32(addr); ++ depctl.d32 = DWC_READ_REG32(addr); + + depctl.b.usbactep = 0; ++ ++ /* Update nextep_seq array and EPMSCNT in DCFG*/ ++ if (!(depctl.b.eptype & 1) && ep->is_in == 1) { // NP EP IN ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ if (core_if->nextep_seq[i] == ep->num) ++ break; ++ } ++ core_if->nextep_seq[i] = core_if->nextep_seq[ep->num]; ++ if (core_if->first_in_nextep_seq == ep->num) ++ core_if->first_in_nextep_seq = i; ++ core_if->nextep_seq[ep->num] = 0xff; ++ depctl.b.nextep = 0; ++ dcfg.d32 = ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt--; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, ++ dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); ++ } ++ } ++ ++ if (ep->is_in == 1) ++ depctl.b.txfnum = 0; + + if (core_if->dma_desc_enable) + depctl.b.epdis = 1; + -+ dwc_write_reg32(addr, depctl.d32); ++ DWC_WRITE_REG32(addr, depctl.d32); ++ depctl.d32 = DWC_READ_REG32(addr); ++ if (core_if->dma_enable && ep->type == DWC_OTG_EP_TYPE_ISOC ++ && depctl.b.epena) { ++ depctl_data_t depctl = {.d32 = 0}; ++ if (ep->is_in) { ++ diepint_data_t diepint = {.d32 = 0}; ++ ++ depctl.b.snak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepctl, depctl.d32); ++ do { ++ dwc_udelay(10); ++ diepint.d32 = ++ DWC_READ_REG32(&core_if-> ++ dev_if->in_ep_regs[ep->num]-> ++ diepint); ++ } while (!diepint.b.inepnakeff); ++ diepint.b.inepnakeff = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepint, diepint.d32); ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepctl, depctl.d32); ++ do { ++ dwc_udelay(10); ++ diepint.d32 = ++ DWC_READ_REG32(&core_if-> ++ dev_if->in_ep_regs[ep->num]-> ++ diepint); ++ } while (!diepint.b.epdisabled); ++ diepint.b.epdisabled = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ diepint, diepint.d32); ++ } else { ++ dctl_data_t dctl = {.d32 = 0}; ++ gintmsk_data_t gintsts = {.d32 = 0}; ++ doepint_data_t doepint = {.d32 = 0}; ++ dctl.b.sgoutnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> ++ dctl, 0, dctl.d32); ++ do { ++ dwc_udelay(10); ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ } while (!gintsts.b.goutnakeff); ++ gintsts.d32 = 0; ++ gintsts.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ depctl.d32 = 0; ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepctl, depctl.d32); ++ do ++ { ++ dwc_udelay(10); ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->num]->doepint); ++ } while (!doepint.b.epdisabled); ++ ++ doepint.b.epdisabled = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]->doepint, doepint.d32); ++ ++ dctl.d32 = 0; ++ dctl.b.cgoutnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ } ++ } + + /* Disable the Interrupt for this EP */ + if (core_if->multiproc_int_enable) { -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs->deachintmsk, ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->deachintmsk, + daintmsk.d32, 0); + + if (ep->is_in == 1) { -+ dwc_write_reg32(&core_if->dev_if->dev_global_regs-> ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs-> + diepeachintmsk[ep->num], 0); + } else { -+ dwc_write_reg32(&core_if->dev_if->dev_global_regs-> ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs-> + doepeachintmsk[ep->num], 0); + } + } else { -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs->daintmsk, ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->daintmsk, + daintmsk.d32, 0); + } ++ +} + +/** @@ -43100,28 +52866,51 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + uint32_t offset; + uint32_t xfer_est; + int i; ++ unsigned maxxfer_local, total_len; ++ ++ if (!ep->is_in && ep->type == DWC_OTG_EP_TYPE_INTR && ++ (ep->maxpacket%4)) { ++ maxxfer_local = ep->maxpacket; ++ total_len = ep->xfer_len; ++ } else { ++ maxxfer_local = ep->maxxfer; ++ total_len = ep->total_len; ++ } ++ ++ ep->desc_cnt = (total_len / maxxfer_local) + ++ ((total_len % maxxfer_local) ? 1 : 0); + -+ ep->desc_cnt = (ep->total_len / ep->maxxfer) + -+ ((ep->total_len % ep->maxxfer) ? 1 : 0); + if (!ep->desc_cnt) + ep->desc_cnt = 1; + ++ if (ep->desc_cnt > MAX_DMA_DESC_CNT) ++ ep->desc_cnt = MAX_DMA_DESC_CNT; ++ + dma_desc = ep->desc_addr; -+ xfer_est = ep->total_len; ++ if (maxxfer_local == ep->maxpacket) { ++ if ((total_len % maxxfer_local) && ++ (total_len/maxxfer_local < MAX_DMA_DESC_CNT)) { ++ xfer_est = (ep->desc_cnt - 1) * maxxfer_local + ++ (total_len % maxxfer_local); ++ } else ++ xfer_est = ep->desc_cnt * maxxfer_local; ++ } else ++ xfer_est = total_len; + offset = 0; + for (i = 0; i < ep->desc_cnt; ++i) { + /** DMA Descriptor Setup */ -+ if (xfer_est > ep->maxxfer) { ++ if (xfer_est > maxxfer_local) { + dma_desc->status.b.bs = BS_HOST_BUSY; + dma_desc->status.b.l = 0; + dma_desc->status.b.ioc = 0; + dma_desc->status.b.sp = 0; -+ dma_desc->status.b.bytes = ep->maxxfer; ++ dma_desc->status.b.bytes = maxxfer_local; + dma_desc->buf = ep->dma_addr + offset; ++ dma_desc->status.b.sts = 0; + dma_desc->status.b.bs = BS_HOST_READY; + -+ xfer_est -= ep->maxxfer; -+ offset += ep->maxxfer; ++ xfer_est -= maxxfer_local; ++ offset += maxxfer_local; + } else { + dma_desc->status.b.bs = BS_HOST_BUSY; + dma_desc->status.b.l = 1; @@ -43133,20 +52922,75 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + sent_zlp) ? 1 : 0); + dma_desc->status.b.bytes = xfer_est; + } else { -+ dma_desc->status.b.bytes = -+ xfer_est + ((4 - (xfer_est & 0x3)) & 0x3); ++ if (maxxfer_local == ep->maxpacket) ++ dma_desc->status.b.bytes = xfer_est; ++ else ++ dma_desc->status.b.bytes = ++ xfer_est + ((4 - (xfer_est & 0x3)) & 0x3); + } + + dma_desc->buf = ep->dma_addr + offset; ++ dma_desc->status.b.sts = 0; + dma_desc->status.b.bs = BS_HOST_READY; + } + dma_desc++; + } +} ++/** ++ * This function is called when to write ISOC data into appropriate dedicated ++ * periodic FIFO. ++ */ ++static int32_t write_isoc_tx_fifo(dwc_otg_core_if_t * core_if, dwc_ep_t * dwc_ep) ++{ ++ dwc_otg_dev_if_t *dev_if = core_if->dev_if; ++ dwc_otg_dev_in_ep_regs_t *ep_regs; ++ dtxfsts_data_t txstatus = {.d32 = 0 }; ++ uint32_t len = 0; ++ int epnum = dwc_ep->num; ++ int dwords; + ++ DWC_DEBUGPL(DBG_PCD, "Dedicated TxFifo Empty: %d \n", epnum); ++ ++ ep_regs = core_if->dev_if->in_ep_regs[epnum]; ++ ++ len = dwc_ep->xfer_len - dwc_ep->xfer_count; ++ ++ if (len > dwc_ep->maxpacket) { ++ len = dwc_ep->maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ ++ /* 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); ++ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, txstatus.d32); ++ ++ while (txstatus.b.txfspcavail > dwords && ++ dwc_ep->xfer_count < dwc_ep->xfer_len && dwc_ep->xfer_len != 0) { ++ /* Write the FIFO */ ++ dwc_otg_ep_write_packet(core_if, dwc_ep, 0); ++ ++ len = dwc_ep->xfer_len - dwc_ep->xfer_count; ++ if (len > dwc_ep->maxpacket) { ++ len = dwc_ep->maxpacket; ++ } ++ ++ dwords = (len + 3) / 4; ++ txstatus.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); ++ DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum, ++ txstatus.d32); ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts)); ++ ++ return 1; ++} +/** + * This function does the setup for a data transfer for an EP and -+ * starts the transfer. For an IN transfer, the packets will be ++ * 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. + * @@ -43174,21 +53018,26 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + gnptxsts_data_t gtxstatus; + + gtxstatus.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->gnptxsts); ++ DWC_READ_REG32(&core_if->core_global_regs->gnptxsts); + + if (core_if->en_multiple_tx_fifo == 0 -+ && gtxstatus.b.nptxqspcavail == 0) { ++ && gtxstatus.b.nptxqspcavail == 0 && !core_if->dma_enable) { +#ifdef DEBUG + DWC_PRINTF("TX Queue Full (0x%0x)\n", gtxstatus.d32); +#endif + return; + } + -+ depctl.d32 = dwc_read_reg32(&(in_regs->diepctl)); -+ deptsiz.d32 = dwc_read_reg32(&(in_regs->dieptsiz)); ++ depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl)); ++ deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz)); ++ ++ if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT) ++ ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? ++ ep->maxxfer : (ep->total_len - ep->xfer_len); ++ else ++ ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len - ep->xfer_len)) ? ++ MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len); + -+ ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? -+ ep->maxxfer : (ep->total_len - ep->xfer_len); + + /* Zero Length Packet? */ + if ((ep->xfer_len - ep->xfer_count) == 0) { @@ -43198,93 +53047,120 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* Program the transfer size and packet count + * as follows: xfersize = N * maxpacket + + * short_packet pktcnt = N + (short_packet -+ * exist ? 1 : 0) ++ * exist ? 1 : 0) + */ + deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count; + deptsiz.b.pktcnt = + (ep->xfer_len - ep->xfer_count - 1 + + ep->maxpacket) / ep->maxpacket; ++ if (deptsiz.b.pktcnt > MAX_PKT_CNT) { ++ deptsiz.b.pktcnt = MAX_PKT_CNT; ++ deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; ++ } ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) ++ deptsiz.b.mc = deptsiz.b.pktcnt; + } + + /* Write the DMA register */ + if (core_if->dma_enable) { + if (core_if->dma_desc_enable == 0) { -+ dwc_write_reg32(&in_regs->dieptsiz, ++ if (ep->type != DWC_OTG_EP_TYPE_ISOC) ++ deptsiz.b.mc = 1; ++ DWC_WRITE_REG32(&in_regs->dieptsiz, + deptsiz.d32); -+ dwc_write_reg32(&(in_regs->diepdma), ++ DWC_WRITE_REG32(&(in_regs->diepdma), + (uint32_t) ep->dma_addr); + } else { +#ifdef DWC_UTE_CFI + /* The descriptor chain should be already initialized by now */ + if (ep->buff_mode != BM_STANDARD) { -+ dwc_write_reg32(&in_regs->diepdma, ++ DWC_WRITE_REG32(&in_regs->diepdma, + ep->descs_dma_addr); + } else { +#endif -+ init_dma_desc_chain(core_if, ep); ++ init_dma_desc_chain(core_if, ep); + /** DIEPDMAn Register write */ -+ dwc_write_reg32(&in_regs->diepdma, -+ ep->dma_desc_addr); ++ DWC_WRITE_REG32(&in_regs->diepdma, ++ ep->dma_desc_addr); +#ifdef DWC_UTE_CFI -+ } ++ } +#endif + } + } else { -+ dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); ++ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); + if (ep->type != DWC_OTG_EP_TYPE_ISOC) { -+ /** ++ /** + * Enable the Non-Periodic Tx FIFO empty interrupt, + * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode, + * the data will be written into the fifo by the ISR. + */ + 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, -+ intr_mask.d32); ++ DWC_MODIFY_REG32 ++ (&core_if->core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); + } else { + /* Enable the Tx FIFO Empty Interrupt for this EP */ + if (ep->xfer_len > 0) { + uint32_t fifoemptymsk = 0; + fifoemptymsk = 1 << ep->num; -+ dwc_modify_reg32(&core_if-> -+ dev_if-> -+ dev_global_regs-> -+ dtknqr4_fifoemptymsk, -+ 0, -+ fifoemptymsk); ++ DWC_MODIFY_REG32 ++ (&core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk, ++ 0, fifoemptymsk); + + } + } ++ } else { ++ write_isoc_tx_fifo(core_if, ep); ++ } ++ } ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; ++ ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ dsts_data_t dsts = {.d32 = 0}; ++ if (ep->bInterval == 1) { ++ dsts.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dsts); ++ ep->frame_num = dsts.b.soffn + ep->bInterval; ++ if (ep->frame_num > 0x3FFF) { ++ ep->frm_overrun = 1; ++ ep->frame_num &= 0x3FFF; ++ } else ++ ep->frm_overrun = 0; ++ if (ep->frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ } else { ++ depctl.b.setd0pid = 1; ++ } + } + } -+ + /* EP enable, IN data in FIFO */ + depctl.b.cnak = 1; + depctl.b.epena = 1; -+ dwc_write_reg32(&in_regs->diepctl, depctl.d32); -+ -+ depctl.d32 = -+ dwc_read_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl); -+ depctl.b.nextep = ep->num; -+ dwc_write_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl, -+ depctl.d32); ++ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); + + } else { + /* OUT endpoint */ + dwc_otg_dev_out_ep_regs_t *out_regs = + core_if->dev_if->out_ep_regs[ep->num]; + -+ depctl.d32 = dwc_read_reg32(&(out_regs->doepctl)); -+ deptsiz.d32 = dwc_read_reg32(&(out_regs->doeptsiz)); ++ depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl)); ++ deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz)); + -+ ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? -+ ep->maxxfer : (ep->total_len - ep->xfer_len); ++ if (!core_if->dma_desc_enable) { ++ if (ep->maxpacket > ep->maxxfer / MAX_PKT_CNT) ++ ep->xfer_len += (ep->maxxfer < (ep->total_len - ep->xfer_len)) ? ++ ep->maxxfer : (ep->total_len - ep->xfer_len); ++ else ++ ep->xfer_len += (MAX_PKT_CNT * ep->maxpacket < (ep->total_len ++ - ep->xfer_len)) ? MAX_PKT_CNT * ep->maxpacket : (ep->total_len - ep->xfer_len); ++ } + + /* Program the transfer size and packet count as follows: -+ * -+ * pktcnt = N ++ * ++ * pktcnt = N + * xfersize = N * maxpacket + */ + if ((ep->xfer_len - ep->xfer_count) == 0) { @@ -43295,8 +53171,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + deptsiz.b.pktcnt = + (ep->xfer_len - ep->xfer_count + + (ep->maxpacket - 1)) / ep->maxpacket; -+ ep->xfer_len = -+ deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count; ++ if (deptsiz.b.pktcnt > MAX_PKT_CNT) { ++ deptsiz.b.pktcnt = MAX_PKT_CNT; ++ } ++ if (!core_if->dma_desc_enable) { ++ ep->xfer_len = ++ deptsiz.b.pktcnt * ep->maxpacket + ep->xfer_count; ++ } + deptsiz.b.xfersize = ep->xfer_len - ep->xfer_count; + } + @@ -43305,47 +53186,96 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + if (core_if->dma_enable) { + if (!core_if->dma_desc_enable) { -+ dwc_write_reg32(&out_regs->doeptsiz, ++ DWC_WRITE_REG32(&out_regs->doeptsiz, + deptsiz.d32); + -+ dwc_write_reg32(&(out_regs->doepdma), ++ DWC_WRITE_REG32(&(out_regs->doepdma), + (uint32_t) ep->dma_addr); + } else { +#ifdef DWC_UTE_CFI + /* The descriptor chain should be already initialized by now */ + if (ep->buff_mode != BM_STANDARD) { -+ dwc_write_reg32(&out_regs->doepdma, ++ DWC_WRITE_REG32(&out_regs->doepdma, + ep->descs_dma_addr); + } else { +#endif ++ /** This is used for interrupt out transfers*/ ++ if (!ep->xfer_len) ++ ep->xfer_len = ep->total_len; ++ init_dma_desc_chain(core_if, ep); + -+ init_dma_desc_chain(core_if, ep); -+ ++ if (core_if->core_params->dev_out_nak) { ++ if (ep->type == DWC_OTG_EP_TYPE_BULK) { ++ deptsiz.b.pktcnt = (ep->total_len + ++ (ep->maxpacket - 1)) / ep->maxpacket; ++ deptsiz.b.xfersize = ep->total_len; ++ /* Remember initial value of doeptsiz */ ++ core_if->start_doeptsiz_val[ep->num] = deptsiz.d32; ++ DWC_WRITE_REG32(&out_regs->doeptsiz, ++ deptsiz.d32); ++ } ++ } + /** DOEPDMAn Register write */ -+ dwc_write_reg32(&out_regs->doepdma, -+ ep->dma_desc_addr); ++ DWC_WRITE_REG32(&out_regs->doepdma, ++ ep->dma_desc_addr); +#ifdef DWC_UTE_CFI + } +#endif + } + } else { -+ dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32); ++ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); ++ } ++ ++ if (ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ dsts_data_t dsts = {.d32 = 0}; ++ if (ep->bInterval == 1) { ++ dsts.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dsts); ++ ep->frame_num = dsts.b.soffn + ep->bInterval; ++ if (ep->frame_num > 0x3FFF) { ++ ep->frm_overrun = 1; ++ ep->frame_num &= 0x3FFF; ++ } else ++ ep->frm_overrun = 0; ++ ++ if (ep->frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ } else { ++ depctl.b.setd0pid = 1; ++ } ++ } + } + + /* EP enable */ + depctl.b.cnak = 1; + depctl.b.epena = 1; + -+ dwc_write_reg32(&out_regs->doepctl, depctl.d32); ++ DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32); + + DWC_DEBUGPL(DBG_PCD, "DOEPCTL=%08x DOEPTSIZ=%08x\n", -+ dwc_read_reg32(&out_regs->doepctl), -+ dwc_read_reg32(&out_regs->doeptsiz)); ++ DWC_READ_REG32(&out_regs->doepctl), ++ DWC_READ_REG32(&out_regs->doeptsiz)); + DWC_DEBUGPL(DBG_PCD, "DAINTMSK=%08x GINTMSK=%08x\n", -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs-> ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs-> + daintmsk), -+ dwc_read_reg32(&core_if->core_global_regs-> ++ DWC_READ_REG32(&core_if->core_global_regs-> + gintmsk)); ++ ++ /* Timer is scheduling only for out bulk transfers for ++ * "Device DDMA OUT NAK Enhancement" feature to inform user ++ * about received data payload in case of timeout ++ */ ++ if (core_if->core_params->dev_out_nak) { ++ if (ep->type == DWC_OTG_EP_TYPE_BULK) { ++ core_if->ep_xfer_info[ep->num].core_if = core_if; ++ core_if->ep_xfer_info[ep->num].ep = ep; ++ core_if->ep_xfer_info[ep->num].state = 1; ++ ++ /* Start a timer for this transfer. */ ++ DWC_TIMER_SCHEDULE(core_if->ep_xfer_timer[ep->num], 10000); ++ } ++ } + } +} + @@ -43372,8 +53302,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + dwc_otg_dev_in_ep_regs_t *in_regs = + core_if->dev_if->in_ep_regs[ep->num]; + -+ depctl.d32 = dwc_read_reg32(&(in_regs->diepctl)); -+ deptsiz.d32 = dwc_read_reg32(&(in_regs->dieptsiz)); ++ depctl.d32 = DWC_READ_REG32(&(in_regs->diepctl)); ++ deptsiz.d32 = DWC_READ_REG32(&(in_regs->dieptsiz)); + + deptsiz.b.xfersize = 0; + deptsiz.b.pktcnt = 1; @@ -43381,54 +53311,50 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* Write the DMA register */ + if (core_if->dma_enable) { + if (core_if->dma_desc_enable == 0) { -+ dwc_write_reg32(&in_regs->dieptsiz, ++ deptsiz.b.mc = 1; ++ DWC_WRITE_REG32(&in_regs->dieptsiz, + deptsiz.d32); -+ dwc_write_reg32(&(in_regs->diepdma), ++ DWC_WRITE_REG32(&(in_regs->diepdma), + (uint32_t) ep->dma_addr); + } + } else { -+ dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); -+ /** ++ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); ++ /** + * Enable the Non-Periodic Tx FIFO empty interrupt, + * or the Tx FIFO epmty interrupt in dedicated Tx FIFO mode, + * the data will be written into the fifo by the ISR. + */ + 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, -+ intr_mask.d32); ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); + } else { + /* Enable the Tx FIFO Empty Interrupt for this EP */ + if (ep->xfer_len > 0) { + uint32_t fifoemptymsk = 0; + fifoemptymsk = 1 << ep->num; -+ dwc_modify_reg32(&core_if->dev_if-> -+ dev_global_regs-> -+ dtknqr4_fifoemptymsk, ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, + 0, fifoemptymsk); + } + } + } + ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; + /* EP enable, IN data in FIFO */ + depctl.b.cnak = 1; + depctl.b.epena = 1; -+ dwc_write_reg32(&in_regs->diepctl, depctl.d32); -+ -+ depctl.d32 = -+ dwc_read_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl); -+ depctl.b.nextep = ep->num; -+ dwc_write_reg32(&core_if->dev_if->in_ep_regs[0]->diepctl, -+ depctl.d32); ++ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); + + } else { + /* OUT endpoint */ + dwc_otg_dev_out_ep_regs_t *out_regs = + core_if->dev_if->out_ep_regs[ep->num]; + -+ depctl.d32 = dwc_read_reg32(&(out_regs->doepctl)); -+ deptsiz.d32 = dwc_read_reg32(&(out_regs->doeptsiz)); ++ depctl.d32 = DWC_READ_REG32(&(out_regs->doepctl)); ++ deptsiz.d32 = DWC_READ_REG32(&(out_regs->doeptsiz)); + + /* Zero Length Packet */ + deptsiz.b.xfersize = ep->maxpacket; @@ -43436,21 +53362,21 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + if (core_if->dma_enable) { + if (!core_if->dma_desc_enable) { -+ dwc_write_reg32(&out_regs->doeptsiz, ++ DWC_WRITE_REG32(&out_regs->doeptsiz, + deptsiz.d32); + -+ dwc_write_reg32(&(out_regs->doepdma), ++ DWC_WRITE_REG32(&(out_regs->doepdma), + (uint32_t) ep->dma_addr); + } + } else { -+ dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32); ++ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); + } + + /* EP enable */ + depctl.b.cnak = 1; + depctl.b.epena = 1; + -+ dwc_write_reg32(&out_regs->doepctl, depctl.d32); ++ DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32); + + } +} @@ -43485,15 +53411,26 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + gnptxsts_data_t gtxstatus; + ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ depctl.d32 = DWC_READ_REG32(&in_regs->diepctl); ++ if (depctl.b.epena) ++ return; ++ } ++ + gtxstatus.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->gnptxsts); ++ DWC_READ_REG32(&core_if->core_global_regs->gnptxsts); ++ ++ /* If dedicated FIFO every time flush fifo before enable ep*/ ++ if (core_if->en_multiple_tx_fifo && core_if->snpsid >= OTG_CORE_REV_3_00a) ++ dwc_otg_flush_tx_fifo(core_if, ep->tx_fifo_num); + + if (core_if->en_multiple_tx_fifo == 0 -+ && gtxstatus.b.nptxqspcavail == 0) { ++ && gtxstatus.b.nptxqspcavail == 0 ++ && !core_if->dma_enable) { +#ifdef DEBUG -+ deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz); ++ deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz); + DWC_DEBUGPL(DBG_PCD, "DIEPCTL0=%0x\n", -+ dwc_read_reg32(&in_regs->diepctl)); ++ DWC_READ_REG32(&in_regs->diepctl)); + DWC_DEBUGPL(DBG_PCD, "DIEPTSIZ0=%0x (sz=%d, pcnt=%d)\n", + deptsiz.d32, + deptsiz.b.xfersize, deptsiz.b.pktcnt); @@ -43503,8 +53440,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + return; + } + -+ depctl.d32 = dwc_read_reg32(&in_regs->diepctl); -+ deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz); ++ depctl.d32 = DWC_READ_REG32(&in_regs->diepctl); ++ deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz); + + /* Zero Length Packet? */ + if (ep->xfer_len == 0) { @@ -43514,7 +53451,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* Program the transfer size and packet count + * as follows: xfersize = N * maxpacket + + * short_packet pktcnt = N + (short_packet -+ * exist ? 1 : 0) ++ * exist ? 1 : 0) + */ + if (ep->xfer_len > ep->maxpacket) { + ep->xfer_len = ep->maxpacket; @@ -43533,10 +53470,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* Write the DMA register */ + if (core_if->dma_enable) { + if (core_if->dma_desc_enable == 0) { -+ dwc_write_reg32(&in_regs->dieptsiz, ++ DWC_WRITE_REG32(&in_regs->dieptsiz, + deptsiz.d32); + -+ dwc_write_reg32(&(in_regs->diepdma), ++ DWC_WRITE_REG32(&(in_regs->diepdma), + (uint32_t) ep->dma_addr); + } else { + dma_desc = core_if->dev_if->in_desc_addr; @@ -43549,40 +53486,42 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + (ep->xfer_len == ep->maxpacket) ? 0 : 1; + dma_desc->status.b.bytes = ep->xfer_len; + dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; + dma_desc->status.b.bs = BS_HOST_READY; + + /** DIEPDMA0 Register write */ -+ dwc_write_reg32(&in_regs->diepdma, -+ core_if->dev_if-> -+ dma_in_desc_addr); ++ DWC_WRITE_REG32(&in_regs->diepdma, ++ core_if-> ++ dev_if->dma_in_desc_addr); + } + } else { -+ dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); ++ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); + } + ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; + /* EP enable, IN data in FIFO */ + depctl.b.cnak = 1; + depctl.b.epena = 1; -+ dwc_write_reg32(&in_regs->diepctl, depctl.d32); ++ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); + -+ /** ++ /** + * Enable the Non-Periodic Tx FIFO empty interrupt, the + * data will be written into the fifo by the ISR. + */ + if (!core_if->dma_enable) { + 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, -+ intr_mask.d32); ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); + } else { + /* Enable the Tx FIFO Empty Interrupt for this EP */ + if (ep->xfer_len > 0) { + uint32_t fifoemptymsk = 0; + fifoemptymsk |= 1 << ep->num; -+ dwc_modify_reg32(&core_if->dev_if-> -+ dev_global_regs-> -+ dtknqr4_fifoemptymsk, ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, + 0, fifoemptymsk); + } + } @@ -43592,8 +53531,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + dwc_otg_dev_out_ep_regs_t *out_regs = + core_if->dev_if->out_ep_regs[0]; + -+ depctl.d32 = dwc_read_reg32(&out_regs->doepctl); -+ deptsiz.d32 = dwc_read_reg32(&out_regs->doeptsiz); ++ depctl.d32 = DWC_READ_REG32(&out_regs->doepctl); ++ deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz); + + /* Program the transfer size and packet count as follows: + * xfersize = N * (maxpacket + 4 - (maxpacket % 4)) @@ -43601,41 +53540,48 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* Zero Length Packet */ + deptsiz.b.xfersize = ep->maxpacket; + deptsiz.b.pktcnt = 1; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) ++ deptsiz.b.supcnt = 3; + + DWC_DEBUGPL(DBG_PCDV, "len=%d xfersize=%d pktcnt=%d\n", + ep->xfer_len, deptsiz.b.xfersize, deptsiz.b.pktcnt); + + if (core_if->dma_enable) { + if (!core_if->dma_desc_enable) { -+ dwc_write_reg32(&out_regs->doeptsiz, ++ DWC_WRITE_REG32(&out_regs->doeptsiz, + deptsiz.d32); + -+ dwc_write_reg32(&(out_regs->doepdma), ++ DWC_WRITE_REG32(&(out_regs->doepdma), + (uint32_t) ep->dma_addr); + } else { + dma_desc = core_if->dev_if->out_desc_addr; + + /** DMA Descriptor Setup */ + dma_desc->status.b.bs = BS_HOST_BUSY; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ dma_desc->status.b.mtrf = 0; ++ dma_desc->status.b.sr = 0; ++ } + dma_desc->status.b.l = 1; + dma_desc->status.b.ioc = 1; + dma_desc->status.b.bytes = ep->maxpacket; + dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; + dma_desc->status.b.bs = BS_HOST_READY; + + /** DOEPDMA0 Register write */ -+ dwc_write_reg32(&out_regs->doepdma, ++ DWC_WRITE_REG32(&out_regs->doepdma, + core_if->dev_if-> + dma_out_desc_addr); + } + } else { -+ dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32); ++ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); + } + + /* EP enable */ + depctl.b.cnak = 1; + depctl.b.epena = 1; -+ dwc_write_reg32(&(out_regs->doepctl), depctl.d32); ++ DWC_WRITE_REG32(&(out_regs->doepctl), depctl.d32); + } +} + @@ -43661,17 +53607,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + gnptxsts_data_t tx_status = {.d32 = 0 }; + + tx_status.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->gnptxsts); ++ DWC_READ_REG32(&core_if->core_global_regs->gnptxsts); + /** @todo Should there be check for room in the Tx + * Status Queue. If not remove the code above this comment. */ + -+ depctl.d32 = dwc_read_reg32(&in_regs->diepctl); -+ deptsiz.d32 = dwc_read_reg32(&in_regs->dieptsiz); ++ depctl.d32 = DWC_READ_REG32(&in_regs->diepctl); ++ deptsiz.d32 = DWC_READ_REG32(&in_regs->dieptsiz); + + /* Program the transfer size and packet count + * as follows: xfersize = N * maxpacket + + * short_packet pktcnt = N + (short_packet -+ * exist ? 1 : 0) ++ * exist ? 1 : 0) + */ + + if (core_if->dma_desc_enable == 0) { @@ -43685,7 +53631,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + } else { + ep->xfer_len = deptsiz.b.xfersize; + } -+ dwc_write_reg32(&in_regs->dieptsiz, deptsiz.d32); ++ DWC_WRITE_REG32(&in_regs->dieptsiz, deptsiz.d32); + } else { + ep->xfer_len = + (ep->total_len - ep->xfer_count) > @@ -43702,10 +53648,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + (ep->xfer_len == ep->maxpacket) ? 0 : 1; + dma_desc->status.b.bytes = ep->xfer_len; + dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; + dma_desc->status.b.bs = BS_HOST_READY; + + /** DIEPDMA0 Register write */ -+ dwc_write_reg32(&in_regs->diepdma, ++ DWC_WRITE_REG32(&in_regs->diepdma, + core_if->dev_if->dma_in_desc_addr); + } + @@ -43717,16 +53664,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* Write the DMA register */ + if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) { + if (core_if->dma_desc_enable == 0) -+ dwc_write_reg32(&(in_regs->diepdma), ++ DWC_WRITE_REG32(&(in_regs->diepdma), + (uint32_t) ep->dma_addr); + } -+ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) ++ depctl.b.nextep = core_if->nextep_seq[ep->num]; + /* EP enable, IN data in FIFO */ + depctl.b.cnak = 1; + depctl.b.epena = 1; -+ dwc_write_reg32(&in_regs->diepctl, depctl.d32); ++ DWC_WRITE_REG32(&in_regs->diepctl, depctl.d32); + -+ /** ++ /** + * Enable the Non-Periodic Tx FIFO empty interrupt, the + * data will be written into the fifo by the ISR. + */ @@ -43734,18 +53682,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + if (core_if->en_multiple_tx_fifo == 0) { + /* First clear it from GINTSTS */ + intr_mask.b.nptxfempty = 1; -+ dwc_modify_reg32(&core_if->core_global_regs-> -+ gintmsk, intr_mask.d32, -+ intr_mask.d32); ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); + + } else { + /* Enable the Tx FIFO Empty Interrupt for this EP */ + if (ep->xfer_len > 0) { + uint32_t fifoemptymsk = 0; + fifoemptymsk |= 1 << ep->num; -+ dwc_modify_reg32(&core_if->dev_if-> -+ dev_global_regs-> -+ dtknqr4_fifoemptymsk, ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, + 0, fifoemptymsk); + } + } @@ -43754,19 +53701,19 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + dwc_otg_dev_out_ep_regs_t *out_regs = + core_if->dev_if->out_ep_regs[0]; + -+ depctl.d32 = dwc_read_reg32(&out_regs->doepctl); -+ deptsiz.d32 = dwc_read_reg32(&out_regs->doeptsiz); ++ depctl.d32 = DWC_READ_REG32(&out_regs->doepctl); ++ deptsiz.d32 = DWC_READ_REG32(&out_regs->doeptsiz); + + /* Program the transfer size and packet count + * as follows: xfersize = N * maxpacket + + * short_packet pktcnt = N + (short_packet -+ * exist ? 1 : 0) ++ * exist ? 1 : 0) + */ + deptsiz.b.xfersize = ep->maxpacket; + deptsiz.b.pktcnt = 1; + + if (core_if->dma_desc_enable == 0) { -+ dwc_write_reg32(&out_regs->doeptsiz, deptsiz.d32); ++ DWC_WRITE_REG32(&out_regs->doeptsiz, deptsiz.d32); + } else { + dma_desc = core_if->dev_if->out_desc_addr; + @@ -43776,10 +53723,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + dma_desc->status.b.ioc = 1; + dma_desc->status.b.bytes = ep->maxpacket; + dma_desc->buf = ep->dma_addr; ++ dma_desc->status.b.sts = 0; + dma_desc->status.b.bs = BS_HOST_READY; + + /** DOEPDMA0 Register write */ -+ dwc_write_reg32(&out_regs->doepdma, ++ DWC_WRITE_REG32(&out_regs->doepdma, + core_if->dev_if->dma_out_desc_addr); + } + @@ -43791,14 +53739,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* Write the DMA register */ + if (core_if->hwcfg2.b.architecture == DWC_INT_DMA_ARCH) { + if (core_if->dma_desc_enable == 0) -+ dwc_write_reg32(&(out_regs->doepdma), ++ DWC_WRITE_REG32(&(out_regs->doepdma), + (uint32_t) ep->dma_addr); ++ + } + + /* EP enable, IN data in FIFO */ + depctl.b.cnak = 1; + depctl.b.epena = 1; -+ dwc_write_reg32(&out_regs->doepctl, depctl.d32); ++ DWC_WRITE_REG32(&out_regs->doepctl, depctl.d32); + + } +} @@ -43836,7 +53785,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + +/** + * This function writes a packet into the Tx FIFO associated with the -+ * EP. For non-periodic EPs the non-periodic Tx FIFO is written. For ++ * EP. For non-periodic EPs the non-periodic Tx FIFO is written. For + * periodic EPs the periodic Tx FIFO associated with the EP is written + * with all packets for the next micro-frame. + * @@ -43849,15 +53798,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 +{ + /** + * The buffer is padded to DWORD on a per packet basis in -+ * slave/dma mode if the MPS is not DWORD aligned. The last ++ * slave/dma mode if the MPS is not DWORD aligned. The last + * packet, if short, is also padded to a multiple of DWORD. + * -+ * ep->xfer_buff always starts DWORD aligned in memory and is a ++ * ep->xfer_buff always starts DWORD aligned in memory and is a + * multiple of DWORD in length + * + * ep->xfer_len can be any number of bytes + * -+ * ep->xfer_count is a multiple of ep->maxpacket until the last ++ * ep->xfer_count is a multiple of ep->maxpacket until the last + * packet + * + * FIFO access is DWORD */ @@ -43900,7 +53849,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + if (!dma) { + for (i = 0; i < dword_count; i++, data_buff++) { -+ dwc_write_reg32(fifo, *data_buff); ++ DWC_WRITE_REG32(fifo, *data_buff); + } + } + @@ -43909,7 +53858,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + ep->dma_addr += byte_count; +} + -+/** ++/** + * Set the EP STALL. + * + * @param core_if Programming view of DWC_otg controller. @@ -43925,29 +53874,29 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + if (ep->is_in == 1) { + depctl_addr = &(core_if->dev_if->in_ep_regs[ep->num]->diepctl); -+ depctl.d32 = dwc_read_reg32(depctl_addr); ++ depctl.d32 = DWC_READ_REG32(depctl_addr); + + /* set the disable and stall bits */ + if (depctl.b.epena) { + depctl.b.epdis = 1; + } + depctl.b.stall = 1; -+ dwc_write_reg32(depctl_addr, depctl.d32); ++ DWC_WRITE_REG32(depctl_addr, depctl.d32); + } else { + depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl); -+ depctl.d32 = dwc_read_reg32(depctl_addr); ++ depctl.d32 = DWC_READ_REG32(depctl_addr); + + /* set the stall bit */ + depctl.b.stall = 1; -+ dwc_write_reg32(depctl_addr, depctl.d32); ++ DWC_WRITE_REG32(depctl_addr, depctl.d32); + } + -+ DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", dwc_read_reg32(depctl_addr)); ++ DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr)); + + return; +} + -+/** ++/** + * Clear the EP STALL. + * + * @param core_if Programming view of DWC_otg controller. @@ -43967,12 +53916,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + depctl_addr = &(core_if->dev_if->out_ep_regs[ep->num]->doepctl); + } + -+ depctl.d32 = dwc_read_reg32(depctl_addr); ++ depctl.d32 = DWC_READ_REG32(depctl_addr); + + /* clear the stall bits */ + depctl.b.stall = 0; + -+ /* ++ /* + * USB Spec 9.4.5: For endpoints using data toggle, regardless + * of whether an endpoint has the Halt feature set, a + * ClearFeature(ENDPOINT_HALT) request always results in the @@ -43983,14 +53932,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + depctl.b.setd0pid = 1; /* DATA0 */ + } + -+ dwc_write_reg32(depctl_addr, depctl.d32); -+ DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", dwc_read_reg32(depctl_addr)); ++ DWC_WRITE_REG32(depctl_addr, depctl.d32); ++ DWC_DEBUGPL(DBG_PCD, "DEPCTL=%0x\n", DWC_READ_REG32(depctl_addr)); + return; +} + -+/** ++/** + * This function reads a packet from the Rx FIFO into the destination -+ * buffer. To read SETUP data use dwc_otg_read_setup_packet. ++ * buffer. To read SETUP data use dwc_otg_read_setup_packet. + * + * @param core_if Programming view of DWC_otg controller. + * @param dest Destination buffer for the packet. @@ -44015,7 +53964,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + core_if, dest, bytes); + + for (i = 0; i < word_count; i++, data_buff++) { -+ *data_buff = dwc_read_reg32(fifo); ++ *data_buff = DWC_READ_REG32(fifo); + } + + return; @@ -44033,119 +53982,125 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + DWC_PRINTF("Device Global Registers\n"); + addr = &core_if->dev_if->dev_global_regs->dcfg; -+ DWC_PRINTF("DCFG @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("DCFG @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->dev_if->dev_global_regs->dctl; -+ DWC_PRINTF("DCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("DCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->dev_if->dev_global_regs->dsts; -+ DWC_PRINTF("DSTS @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("DSTS @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->dev_if->dev_global_regs->diepmsk; -+ DWC_PRINTF("DIEPMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("DIEPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->dev_if->dev_global_regs->doepmsk; -+ DWC_PRINTF("DOEPMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("DOEPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->dev_if->dev_global_regs->daint; -+ DWC_PRINTF("DAINT @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("DAINT @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->dev_if->dev_global_regs->daintmsk; -+ DWC_PRINTF("DAINTMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("DAINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->dev_if->dev_global_regs->dtknqr1; -+ DWC_PRINTF("DTKNQR1 @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("DTKNQR1 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + if (core_if->hwcfg2.b.dev_token_q_depth > 6) { + addr = &core_if->dev_if->dev_global_regs->dtknqr2; -+ DWC_PRINTF("DTKNQR2 @0x%08X : 0x%08X\n", -+ (uint32_t) addr, dwc_read_reg32(addr)); ++ DWC_PRINTF("DTKNQR2 @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + } + + addr = &core_if->dev_if->dev_global_regs->dvbusdis; -+ DWC_PRINTF("DVBUSID @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("DVBUSID @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + + addr = &core_if->dev_if->dev_global_regs->dvbuspulse; -+ DWC_PRINTF("DVBUSPULSE @0x%08X : 0x%08X\n", -+ (uint32_t) addr, dwc_read_reg32(addr)); ++ DWC_PRINTF("DVBUSPULSE @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + -+ addr = &core_if->dev_if->dev_global_regs->dtknqr3_dthrctl; -+ DWC_PRINTF("DTKNQR3_DTHRCTL @0x%08X : 0x%08X\n", -+ (uint32_t) addr, dwc_read_reg32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->dtknqr3_dthrctl; ++ DWC_PRINTF("DTKNQR3_DTHRCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + + if (core_if->hwcfg2.b.dev_token_q_depth > 22) { + addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk; -+ DWC_PRINTF("DTKNQR4 @0x%08X : 0x%08X\n", -+ (uint32_t) addr, dwc_read_reg32(addr)); ++ DWC_PRINTF("DTKNQR4 @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + } + + addr = &core_if->dev_if->dev_global_regs->dtknqr4_fifoemptymsk; -+ DWC_PRINTF("FIFOEMPMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("FIFOEMPMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + -+ addr = &core_if->dev_if->dev_global_regs->deachint; -+ DWC_PRINTF("DEACHINT @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->dev_global_regs->deachintmsk; -+ DWC_PRINTF("DEACHINTMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ if (core_if->hwcfg2.b.multi_proc_int) { + -+ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { -+ addr = &core_if->dev_if->dev_global_regs->diepeachintmsk[i]; -+ DWC_PRINTF("DIEPEACHINTMSK[%d] @0x%08X : 0x%08X\n", i, -+ (uint32_t) addr, dwc_read_reg32(addr)); -+ } ++ addr = &core_if->dev_if->dev_global_regs->deachint; ++ DWC_PRINTF("DEACHINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ addr = &core_if->dev_if->dev_global_regs->deachintmsk; ++ DWC_PRINTF("DEACHINTMSK @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + -+ for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { -+ addr = &core_if->dev_if->dev_global_regs->doepeachintmsk[i]; -+ DWC_PRINTF("DOEPEACHINTMSK[%d] @0x%08X : 0x%08X\n", i, -+ (uint32_t) addr, dwc_read_reg32(addr)); ++ for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ addr = ++ &core_if->dev_if-> ++ dev_global_regs->diepeachintmsk[i]; ++ DWC_PRINTF("DIEPEACHINTMSK[%d] @0x%08lX : 0x%08X\n", ++ i, (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ } ++ ++ for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { ++ addr = ++ &core_if->dev_if-> ++ dev_global_regs->doepeachintmsk[i]; ++ DWC_PRINTF("DOEPEACHINTMSK[%d] @0x%08lX : 0x%08X\n", ++ i, (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ } + } + + for (i = 0; i <= core_if->dev_if->num_in_eps; i++) { + DWC_PRINTF("Device IN EP %d Registers\n", i); + addr = &core_if->dev_if->in_ep_regs[i]->diepctl; -+ DWC_PRINTF("DIEPCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("DIEPCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->dev_if->in_ep_regs[i]->diepint; -+ DWC_PRINTF("DIEPINT @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("DIEPINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->dev_if->in_ep_regs[i]->dieptsiz; -+ DWC_PRINTF("DIETSIZ @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("DIETSIZ @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->dev_if->in_ep_regs[i]->diepdma; -+ DWC_PRINTF("DIEPDMA @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("DIEPDMA @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->dev_if->in_ep_regs[i]->dtxfsts; -+ DWC_PRINTF("DTXFSTS @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("DTXFSTS @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->dev_if->in_ep_regs[i]->diepdmab; -+ DWC_PRINTF("DIEPDMAB @0x%08X : 0x%08X\n", (uint32_t) addr, -+ 0 /*dwc_read_reg32(addr) */ ); ++ DWC_PRINTF("DIEPDMAB @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, 0 /*DWC_READ_REG32(addr) */ ); + } + + for (i = 0; i <= core_if->dev_if->num_out_eps; i++) { + DWC_PRINTF("Device OUT EP %d Registers\n", i); + addr = &core_if->dev_if->out_ep_regs[i]->doepctl; -+ DWC_PRINTF("DOEPCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); -+ addr = &core_if->dev_if->out_ep_regs[i]->doepfn; -+ DWC_PRINTF("DOEPFN @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("DOEPCTL @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->dev_if->out_ep_regs[i]->doepint; -+ DWC_PRINTF("DOEPINT @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("DOEPINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->dev_if->out_ep_regs[i]->doeptsiz; -+ DWC_PRINTF("DOETSIZ @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("DOETSIZ @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->dev_if->out_ep_regs[i]->doepdma; -+ DWC_PRINTF("DOEPDMA @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("DOEPDMA @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + if (core_if->dma_enable) { /* Don't access this register in SLAVE mode */ + addr = &core_if->dev_if->out_ep_regs[i]->doepdmab; -+ DWC_PRINTF("DOEPDMAB @0x%08X : 0x%08X\n", -+ (uint32_t) addr, dwc_read_reg32(addr)); ++ DWC_PRINTF("DOEPDMAB @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + } + + } @@ -44162,15 +54117,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + DWC_PRINTF("SPRAM Data:\n"); + start_addr = (void *)core_if->core_global_regs; -+ DWC_PRINTF("Base Address: 0x%8X\n", (uint32_t) start_addr); ++ DWC_PRINTF("Base Address: 0x%8lX\n", (unsigned long)start_addr); + start_addr += 0x00028000; + end_addr = (void *)core_if->core_global_regs; + end_addr += 0x000280e0; + + for (addr = start_addr; addr < end_addr; addr += 16) { + DWC_PRINTF -+ ("0x%8X:\t%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\n", -+ (uint32_t) addr, addr[0], addr[1], addr[2], addr[3], ++ ("0x%8lX:\t%2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X %2X\n", ++ (unsigned long)addr, addr[0], addr[1], addr[2], addr[3], + addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], + addr[10], addr[11], addr[12], addr[13], addr[14], addr[15] + ); @@ -44191,57 +54146,58 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + DWC_PRINTF("Host Global Registers\n"); + addr = &core_if->host_if->host_global_regs->hcfg; -+ DWC_PRINTF("HCFG @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("HCFG @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->host_if->host_global_regs->hfir; -+ DWC_PRINTF("HFIR @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("HFIR @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->host_if->host_global_regs->hfnum; -+ DWC_PRINTF("HFNUM @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("HFNUM @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->host_if->host_global_regs->hptxsts; -+ DWC_PRINTF("HPTXSTS @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("HPTXSTS @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->host_if->host_global_regs->haint; -+ DWC_PRINTF("HAINT @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("HAINT @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->host_if->host_global_regs->haintmsk; -+ DWC_PRINTF("HAINTMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("HAINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + if (core_if->dma_desc_enable) { + addr = &core_if->host_if->host_global_regs->hflbaddr; -+ DWC_PRINTF("HFLBADDR @0x%08X : 0x%08X\n",(uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("HFLBADDR @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + } -+ ++ + addr = core_if->host_if->hprt0; -+ DWC_PRINTF("HPRT0 @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("HPRT0 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + + for (i = 0; i < core_if->core_params->host_channels; i++) { + DWC_PRINTF("Host Channel %d Specific Registers\n", i); + addr = &core_if->host_if->hc_regs[i]->hcchar; -+ DWC_PRINTF("HCCHAR @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("HCCHAR @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->host_if->hc_regs[i]->hcsplt; -+ DWC_PRINTF("HCSPLT @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("HCSPLT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->host_if->hc_regs[i]->hcint; -+ DWC_PRINTF("HCINT @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("HCINT @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->host_if->hc_regs[i]->hcintmsk; -+ DWC_PRINTF("HCINTMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("HCINTMSK @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->host_if->hc_regs[i]->hctsiz; -+ DWC_PRINTF("HCTSIZ @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("HCTSIZ @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->host_if->hc_regs[i]->hcdma; -+ DWC_PRINTF("HCDMA @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("HCDMA @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + if (core_if->dma_desc_enable) { -+ addr=&core_if->host_if->hc_regs[i]->hcdmab; -+ DWC_PRINTF("HCDMAB @0x%08X : 0x%08X\n",(uint32_t) addr, dwc_read_reg32(addr)); -+ } ++ addr = &core_if->host_if->hc_regs[i]->hcdmab; ++ DWC_PRINTF("HCDMAB @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); ++ } + + } + return; @@ -44254,85 +54210,102 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + */ +void dwc_otg_dump_global_registers(dwc_otg_core_if_t * core_if) +{ -+ int i; ++ int i, ep_num; + volatile uint32_t *addr; ++ char *txfsiz; + + DWC_PRINTF("Core Global Registers\n"); + addr = &core_if->core_global_regs->gotgctl; -+ DWC_PRINTF("GOTGCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GOTGCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->gotgint; -+ DWC_PRINTF("GOTGINT @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GOTGINT @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->gahbcfg; -+ DWC_PRINTF("GAHBCFG @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GAHBCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->gusbcfg; -+ DWC_PRINTF("GUSBCFG @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GUSBCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->grstctl; -+ DWC_PRINTF("GRSTCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GRSTCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->gintsts; -+ DWC_PRINTF("GINTSTS @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GINTSTS @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->gintmsk; -+ DWC_PRINTF("GINTMSK @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GINTMSK @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->grxstsr; -+ DWC_PRINTF("GRXSTSR @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GRXSTSR @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->grxfsiz; -+ DWC_PRINTF("GRXFSIZ @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GRXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->gnptxfsiz; -+ DWC_PRINTF("GNPTXFSIZ @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GNPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->gnptxsts; -+ DWC_PRINTF("GNPTXSTS @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GNPTXSTS @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->gi2cctl; -+ DWC_PRINTF("GI2CCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GI2CCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->gpvndctl; -+ DWC_PRINTF("GPVNDCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GPVNDCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->ggpio; -+ DWC_PRINTF("GGPIO @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GGPIO @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->guid; -+ DWC_PRINTF("GUID @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GUID @0x%08lX : 0x%08X\n", ++ (unsigned long)addr, DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->gsnpsid; -+ DWC_PRINTF("GSNPSID @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GSNPSID @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->ghwcfg1; -+ DWC_PRINTF("GHWCFG1 @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GHWCFG1 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->ghwcfg2; -+ DWC_PRINTF("GHWCFG2 @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GHWCFG2 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->ghwcfg3; -+ DWC_PRINTF("GHWCFG3 @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GHWCFG3 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->ghwcfg4; -+ DWC_PRINTF("GHWCFG4 @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GHWCFG4 @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + addr = &core_if->core_global_regs->glpmcfg; -+ DWC_PRINTF("GLPMCFG @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("GLPMCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gpwrdn; ++ DWC_PRINTF("GPWRDN @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->gdfifocfg; ++ DWC_PRINTF("GDFIFOCFG @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); ++ addr = &core_if->core_global_regs->adpctl; ++ DWC_PRINTF("ADPCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ dwc_otg_adp_read_reg(core_if)); + addr = &core_if->core_global_regs->hptxfsiz; -+ DWC_PRINTF("HPTXFSIZ @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("HPTXFSIZ @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); + -+ for (i = 0; i < core_if->hwcfg4.b.num_dev_perio_in_ep; i++) { -+ addr = &core_if->core_global_regs->dptxfsiz_dieptxf[i]; -+ DWC_PRINTF("DPTXFSIZ[%d] @0x%08X : 0x%08X\n", i, -+ (uint32_t) addr, dwc_read_reg32(addr)); ++ if (core_if->en_multiple_tx_fifo == 0) { ++ ep_num = core_if->hwcfg4.b.num_dev_perio_in_ep; ++ txfsiz = "DPTXFSIZ"; ++ } else { ++ ep_num = core_if->hwcfg4.b.num_in_eps; ++ txfsiz = "DIENPTXF"; ++ } ++ for (i = 0; i < ep_num; i++) { ++ addr = &core_if->core_global_regs->dtxfsiz[i]; ++ DWC_PRINTF("%s[%d] @0x%08lX : 0x%08X\n", txfsiz, i + 1, ++ (unsigned long)addr, DWC_READ_REG32(addr)); + } + addr = core_if->pcgcctl; -+ DWC_PRINTF("PCGCCTL @0x%08X : 0x%08X\n", (uint32_t) addr, -+ dwc_read_reg32(addr)); ++ DWC_PRINTF("PCGCCTL @0x%08lX : 0x%08X\n", (unsigned long)addr, ++ DWC_READ_REG32(addr)); +} + +/** @@ -44351,14 +54324,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + greset.b.txfflsh = 1; + greset.b.txfnum = num; -+ dwc_write_reg32(&global_regs->grstctl, greset.d32); ++ DWC_WRITE_REG32(&global_regs->grstctl, greset.d32); + + do { -+ greset.d32 = dwc_read_reg32(&global_regs->grstctl); ++ greset.d32 = DWC_READ_REG32(&global_regs->grstctl); + if (++count > 10000) { + DWC_WARN("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n", + __func__, greset.d32, -+ dwc_read_reg32(&global_regs->gnptxsts)); ++ DWC_READ_REG32(&global_regs->gnptxsts)); + break; + } + dwc_udelay(1); @@ -44381,13 +54354,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + DWC_DEBUGPL((DBG_CIL | DBG_PCDV), "%s\n", __func__); + /* -+ * ++ * + */ + greset.b.rxfflsh = 1; -+ dwc_write_reg32(&global_regs->grstctl, greset.d32); ++ DWC_WRITE_REG32(&global_regs->grstctl, greset.d32); + + do { -+ greset.d32 = dwc_read_reg32(&global_regs->grstctl); ++ greset.d32 = DWC_READ_REG32(&global_regs->grstctl); + if (++count > 10000) { + DWC_WARN("%s() HANG! GRSTCTL=%0x\n", __func__, + greset.d32); @@ -44414,7 +54387,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* Wait for AHB master IDLE state. */ + do { + dwc_udelay(10); -+ greset.d32 = dwc_read_reg32(&global_regs->grstctl); ++ greset.d32 = DWC_READ_REG32(&global_regs->grstctl); + if (++count > 100000) { + DWC_WARN("%s() HANG! AHB Idle GRSTCTL=%0x\n", __func__, + greset.d32); @@ -44426,9 +54399,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* Core Soft Reset */ + count = 0; + greset.b.csftrst = 1; -+ dwc_write_reg32(&global_regs->grstctl, greset.d32); ++ DWC_WRITE_REG32(&global_regs->grstctl, greset.d32); + do { -+ greset.d32 = dwc_read_reg32(&global_regs->grstctl); ++ greset.d32 = DWC_READ_REG32(&global_regs->grstctl); + if (++count > 10000) { + DWC_WARN("%s() HANG! Soft Reset GRSTCTL=%0x\n", + __func__, greset.d32); @@ -44453,7 +54426,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 +} + +/** -+ * Register HCD callbacks. The callbacks are used to start and stop ++ * Register HCD callbacks. The callbacks are used to start and stop + * the HCD for interrupt processing. + * + * @param core_if Programming view of DWC_otg controller. @@ -44468,7 +54441,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 +} + +/** -+ * Register PCD callbacks. The callbacks are used to start and stop ++ * Register PCD callbacks. The callbacks are used to start and stop + * the PCD for interrupt processing. + * + * @param core_if Programming view of DWC_otg controller. @@ -44514,7 +54487,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* 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(&core_if->dev_if->in_ep_regs[ep->num]->dtxfsts); ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dtxfsts); + DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", ep->num, txstatus.d32); + + while (txstatus.b.txfspcavail > dwords && @@ -44529,7 +54502,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + dwords = (len + 3) / 4; + txstatus.d32 = -+ dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ DWC_READ_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> + dtxfsts); + DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", ep->num, + txstatus.d32); @@ -44566,18 +54539,18 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + /* Program the transfer size and packet count + * as follows: xfersize = N * maxpacket + + * short_packet pktcnt = N + (short_packet -+ * exist ? 1 : 0) ++ * exist ? 1 : 0) + */ + deptsiz.b.xfersize = ep->xfer_len; + deptsiz.b.pktcnt = + (ep->xfer_len - 1 + ep->maxpacket) / ep->maxpacket; + deptsiz.b.mc = deptsiz.b.pktcnt; -+ dwc_write_reg32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz, ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]->dieptsiz, + deptsiz.d32); + + /* Write the DMA register */ + if (core_if->dma_enable) { -+ dwc_write_reg32(& ++ DWC_WRITE_REG32(& + (core_if->dev_if->in_ep_regs[ep->num]-> + diepdma), (uint32_t) ep->dma_addr); + } @@ -44586,13 +54559,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + (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); ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->num]->doeptsiz, deptsiz.d32); + + if (core_if->dma_enable) { -+ dwc_write_reg32(& -+ (core_if->dev_if->out_ep_regs[ep->num]-> -+ doepdma), (uint32_t) ep->dma_addr); ++ DWC_WRITE_REG32(& ++ (core_if->dev_if-> ++ out_ep_regs[ep->num]->doepdma), ++ (uint32_t) ep->dma_addr); + } + } + @@ -44601,7 +54575,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + depctl.d32 = 0; + if (ep->bInterval == 1) { + dsts.d32 = -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs->dsts); ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dsts); + ep->next_frame = dsts.b.soffn + ep->bInterval; + + if (ep->next_frame & 0x1) { @@ -44621,15 +54595,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + depctl.b.epena = 1; + depctl.b.cnak = 1; + -+ dwc_modify_reg32(addr, 0, depctl.d32); -+ depctl.d32 = dwc_read_reg32(addr); ++ DWC_MODIFY_REG32(addr, 0, depctl.d32); ++ depctl.d32 = DWC_READ_REG32(addr); + + if (ep->is_in && core_if->dma_enable == 0) { + write_isoc_frame_data(core_if, ep); + } + +} -+#endif /* DWC_EN_ISOC */ ++#endif /* DWC_EN_ISOC */ + +static void dwc_otg_set_uninitialized(int32_t * p, int size) +{ @@ -44720,8 +54694,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + dwc_param_tx_thr_length_default); + dwc_otg_set_param_rx_thr_length(core_if, + dwc_param_rx_thr_length_default); -+ dwc_otg_set_param_ahb_thr_ratio(core_if, dwc_param_ahb_thr_ratio_default); ++ dwc_otg_set_param_ahb_thr_ratio(core_if, ++ dwc_param_ahb_thr_ratio_default); ++ dwc_otg_set_param_power_down(core_if, dwc_param_power_down_default); ++ dwc_otg_set_param_reload_ctl(core_if, dwc_param_reload_ctl_default); ++ dwc_otg_set_param_dev_out_nak(core_if, dwc_param_dev_out_nak_default); ++ dwc_otg_set_param_cont_on_bna(core_if, dwc_param_cont_on_bna_default); ++ dwc_otg_set_param_ahb_single(core_if, dwc_param_ahb_single_default); ++ dwc_otg_set_param_otg_ver(core_if, dwc_param_otg_ver_default); ++ dwc_otg_set_param_adp_enable(core_if, dwc_param_adp_enable_default); + DWC_PRINTF("Finished setting default values for core params\n"); ++ + return 0; +} + @@ -44762,7 +54745,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + && (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_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) { + valid = 0; + } + break; @@ -44791,7 +54774,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + } + + core_if->core_params->otg_cap = val; -+ out: ++out: + return retval; +} + @@ -44960,11 +54943,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + return -DWC_E_INVALID; + } + -+ if (val > dwc_read_reg32(&core_if->core_global_regs->grxfsiz)) { -+ if(dwc_otg_param_initialized(core_if->core_params->dev_rx_fifo_size)) { ++ if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) { ++ if (dwc_otg_param_initialized(core_if->core_params->dev_rx_fifo_size)) { + DWC_WARN("%d invalid for dev_rx_fifo_size parameter\n", val); + } -+ val = dwc_read_reg32(&core_if->core_global_regs->grxfsiz); ++ val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); + retval = -DWC_E_INVALID; + } + @@ -44988,7 +54971,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + return -DWC_E_INVALID; + } + -+ if (val > (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> 16)) { ++ if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) { + if (dwc_otg_param_initialized + (core_if->core_params->dev_nperio_tx_fifo_size)) { + DWC_ERROR @@ -44996,7 +54979,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + val); + } + val = -+ (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> ++ (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> + 16); + retval = -DWC_E_INVALID; + } @@ -45021,14 +55004,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + return -DWC_E_INVALID; + } + -+ if (val > dwc_read_reg32(&core_if->core_global_regs->grxfsiz)) { ++ if (val > DWC_READ_REG32(&core_if->core_global_regs->grxfsiz)) { + if (dwc_otg_param_initialized + (core_if->core_params->host_rx_fifo_size)) { + DWC_ERROR + ("%d invalid for host_rx_fifo_size. Check HW configuration.\n", + val); + } -+ val = dwc_read_reg32(&core_if->core_global_regs->grxfsiz); ++ val = DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); + retval = -DWC_E_INVALID; + } + @@ -45053,7 +55036,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + return -DWC_E_INVALID; + } + -+ if (val > (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> 16)) { ++ if (val > (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> 16)) { + if (dwc_otg_param_initialized + (core_if->core_params->host_nperio_tx_fifo_size)) { + DWC_ERROR @@ -45061,7 +55044,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + val); + } + val = -+ (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> ++ (DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz) >> + 16); + retval = -DWC_E_INVALID; + } @@ -45085,17 +55068,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + return -DWC_E_INVALID; + } + -+ if (val > -+ ((dwc_read_reg32(&core_if->core_global_regs->hptxfsiz) >> 16))) { ++ if (val > ((core_if->hptxfsiz.d32) >> 16)) { + if (dwc_otg_param_initialized + (core_if->core_params->host_perio_tx_fifo_size)) { + DWC_ERROR + ("%d invalid for host_perio_tx_fifo_size. Check HW configuration.\n", + val); + } -+ val = -+ (dwc_read_reg32(&core_if->core_global_regs->hptxfsiz) >> -+ 16); ++ val = (core_if->hptxfsiz.d32) >> 16; + retval = -DWC_E_INVALID; + } + @@ -45324,9 +55304,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + + if ((val == DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ) + && (dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS)) { -+ if(dwc_otg_param_initialized(core_if->core_params->host_ls_low_power_phy_clk)) { -+ DWC_ERROR("%d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n", -+ val); ++ if (dwc_otg_param_initialized ++ (core_if->core_params->host_ls_low_power_phy_clk)) { ++ DWC_ERROR ++ ("%d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n", ++ val); + } + val = + (dwc_otg_get_param_phy_type(core_if) == @@ -45441,9 +55423,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + } +#ifndef NO_FS_PHY_HW_CHECK + if (val == 1 && core_if->hwcfg3.b.i2c == 0) { -+ if(dwc_otg_param_initialized(core_if->core_params->i2c_enable)) { -+ DWC_ERROR("%d invalid for i2c_enable. Check HW configuration.\n", -+ val); ++ if (dwc_otg_param_initialized(core_if->core_params->i2c_enable)) { ++ DWC_ERROR ++ ("%d invalid for i2c_enable. Check HW configuration.\n", ++ val); + } + val = 0; + retval = -DWC_E_INVALID; @@ -45470,12 +55453,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + return -DWC_E_INVALID; + } + -+ if (val > (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[fifo_num]))) { -+ if(dwc_otg_param_initialized(core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) { -+ DWC_ERROR("`%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n", -+ val, fifo_num); ++ if (val > ++ (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) { ++ DWC_ERROR ++ ("`%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n", ++ val, fifo_num); + } -+ val = (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[fifo_num])); ++ val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num])); + retval = -DWC_E_INVALID; + } + @@ -45500,9 +55486,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + } + + if (val == 1 && core_if->hwcfg4.b.ded_fifo_en == 0) { -+ if(dwc_otg_param_initialized(core_if->core_params->en_multiple_tx_fifo)) { -+ DWC_ERROR("%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n", -+ val); ++ if (dwc_otg_param_initialized ++ (core_if->core_params->en_multiple_tx_fifo)) { ++ DWC_ERROR ++ ("%d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n", ++ val); + } + val = 0; + retval = -DWC_E_INVALID; @@ -45528,12 +55516,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + return -DWC_E_INVALID; + } + -+ if (val > (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[fifo_num]))) { -+ if(dwc_otg_param_initialized(core_if->core_params->dev_tx_fifo_size[fifo_num])) { -+ DWC_ERROR("`%d' invalid for parameter `dev_tx_fifo_size_%d'. Check HW configuration.\n", -+ val, fifo_num); ++ if (val > ++ (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num]))) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->dev_tx_fifo_size[fifo_num])) { ++ DWC_ERROR ++ ("`%d' invalid for parameter `dev_tx_fifo_size_%d'. Check HW configuration.\n", ++ val, fifo_num); + } -+ val = (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[fifo_num])); ++ val = (DWC_READ_REG32(&core_if->core_global_regs->dtxfsiz[fifo_num])); + retval = -DWC_E_INVALID; + } + @@ -45560,9 +55551,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + if ((val != 0) && + (!dwc_otg_get_param_dma_enable(core_if) || + !core_if->hwcfg4.b.ded_fifo_en)) { -+ if(dwc_otg_param_initialized(core_if->core_params->thr_ctl)) { -+ DWC_ERROR("%d invalid for parameter thr_ctl. Check HW configuration.\n", -+ val); ++ if (dwc_otg_param_initialized(core_if->core_params->thr_ctl)) { ++ DWC_ERROR ++ ("%d invalid for parameter thr_ctl. Check HW configuration.\n", ++ val); + } + val = 0; + retval = -DWC_E_INVALID; @@ -45588,9 +55580,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + } + + if (val && !core_if->hwcfg3.b.otg_lpm_en) { -+ if(dwc_otg_param_initialized(core_if->core_params->lpm_enable)) { -+ DWC_ERROR("%d invalid for parameter lpm_enable. Check HW configuration.\n", -+ val); ++ if (dwc_otg_param_initialized(core_if->core_params->lpm_enable)) { ++ DWC_ERROR ++ ("%d invalid for parameter lpm_enable. Check HW configuration.\n", ++ val); + } + val = 0; + retval = -DWC_E_INVALID; @@ -45670,7 +55663,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + } + if (val && (core_if->snpsid < OTG_CORE_REV_2_72a)) { + if (dwc_otg_param_initialized(core_if->core_params->pti_enable)) { -+ DWC_ERROR("%d invalid for parameter pti_enable. Check HW configuration.\n", ++ DWC_ERROR ++ ("%d invalid for parameter pti_enable. Check HW configuration.\n", + val); + } + retval = -DWC_E_INVALID; @@ -45694,7 +55688,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + } + if (val && (core_if->hwcfg2.b.multi_proc_int == 0)) { + if (dwc_otg_param_initialized(core_if->core_params->mpi_enable)) { -+ DWC_ERROR("%d invalid for parameter mpi_enable. Check HW configuration.\n", ++ DWC_ERROR ++ ("%d invalid for parameter mpi_enable. Check HW configuration.\n", + val); + } + retval = -DWC_E_INVALID; @@ -45709,8 +55704,37 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + return core_if->core_params->mpi_enable; +} + -+int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if, -+ int32_t val) ++int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `adp_enable'\n", val); ++ return -DWC_E_INVALID; ++ } ++ if (val && (core_if->hwcfg3.b.adp_supp == 0)) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->adp_supp_enable)) { ++ DWC_ERROR ++ ("%d invalid for parameter adp_enable. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->adp_supp_enable = val; ++ /*Set OTG version 2.0 in case of enabling ADP*/ ++ if (val) ++ dwc_otg_set_param_otg_ver(core_if, 1); ++ ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->adp_supp_enable; ++} ++ ++int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if, int32_t val) +{ + int retval = 0; + if (DWC_OTG_PARAM_TEST(val, 0, 1)) { @@ -45719,9 +55743,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + return -DWC_E_INVALID; + } + -+ if (val && (core_if->hwcfg3.b.otg_enable_ic_usb == 0)) { ++ if (val && (core_if->hwcfg2.b.otg_enable_ic_usb == 0)) { + if (dwc_otg_param_initialized(core_if->core_params->ic_usb_cap)) { -+ DWC_ERROR("%d invalid for parameter ic_usb_cap. Check HW configuration.\n", ++ DWC_ERROR ++ ("%d invalid for parameter ic_usb_cap. Check HW configuration.\n", + val); + } + retval = -DWC_E_INVALID; @@ -45730,6 +55755,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + core_if->core_params->ic_usb_cap = val; + return retval; +} ++ +int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if) +{ + return core_if->core_params->ic_usb_cap; @@ -45740,20 +55766,27 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + int retval = 0; + int valid = 1; + -+ if(DWC_OTG_PARAM_TEST(val, 0, 3)) { ++ if (DWC_OTG_PARAM_TEST(val, 0, 3)) { + DWC_WARN("`%d' invalid for parameter `ahb_thr_ratio'\n", val); + DWC_WARN("ahb_thr_ratio must be 0 - 3\n"); + return -DWC_E_INVALID; + } + -+ if(val && (core_if->snpsid < OTG_CORE_REV_2_81a || !dwc_otg_get_param_thr_ctl(core_if))) { ++ if (val ++ && (core_if->snpsid < OTG_CORE_REV_2_81a ++ || !dwc_otg_get_param_thr_ctl(core_if))) { + valid = 0; -+ } else if(val && ((dwc_otg_get_param_tx_thr_length(core_if) / (1 << val)) < 4)) { ++ } else if (val ++ && ((dwc_otg_get_param_tx_thr_length(core_if) / (1 << val)) < ++ 4)) { + valid = 0; + } -+ if(valid == 0) { -+ if(dwc_otg_param_initialized(core_if->core_params->ahb_thr_ratio)) { -+ DWC_ERROR("%d invalid for parameter ahb_thr_ratio. Chack HW configuration.\n", val); ++ if (valid == 0) { ++ if (dwc_otg_param_initialized ++ (core_if->core_params->ahb_thr_ratio)) { ++ DWC_ERROR ++ ("%d invalid for parameter ahb_thr_ratio. Check HW configuration.\n", ++ val); + } + retval = -DWC_E_INVALID; + val = 0; @@ -45762,32 +55795,221 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + core_if->core_params->ahb_thr_ratio = val; + return retval; +} ++ +int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if) +{ + return core_if->core_params->ahb_thr_ratio; +} + ++int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ hwcfg4_data_t hwcfg4 = {.d32 = 0 }; ++ hwcfg4.d32 = DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4); ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 3)) { ++ DWC_WARN("`%d' invalid for parameter `power_down'\n", val); ++ DWC_WARN("power_down must be 0 - 2\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 2) && (core_if->snpsid < OTG_CORE_REV_2_91a)) { ++ valid = 0; ++ } ++ if ((val == 3) ++ && ((core_if->snpsid < OTG_CORE_REV_3_00a) ++ || (hwcfg4.b.xhiber == 0))) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->power_down)) { ++ DWC_ERROR ++ ("%d invalid for parameter power_down. Check HW configuration.\n", ++ val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->power_down = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->power_down; ++} ++ ++int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `reload_ctl'\n", val); ++ DWC_WARN("reload_ctl must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_92a)) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->reload_ctl)) { ++ DWC_ERROR("%d invalid for parameter reload_ctl." ++ "Check HW configuration.\n", val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->reload_ctl = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->reload_ctl; ++} ++ ++int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `dev_out_nak'\n", val); ++ DWC_WARN("dev_out_nak must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_93a) || ++ !(core_if->core_params->dma_desc_enable))) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->dev_out_nak)) { ++ DWC_ERROR("%d invalid for parameter dev_out_nak." ++ "Check HW configuration.\n", val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->dev_out_nak = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->dev_out_nak; ++} ++ ++int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `cont_on_bna'\n", val); ++ DWC_WARN("cont_on_bna must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && ((core_if->snpsid < OTG_CORE_REV_2_94a) || ++ !(core_if->core_params->dma_desc_enable))) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->cont_on_bna)) { ++ DWC_ERROR("%d invalid for parameter cont_on_bna." ++ "Check HW configuration.\n", val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->cont_on_bna = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->cont_on_bna; ++} ++ ++int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ int valid = 1; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `ahb_single'\n", val); ++ DWC_WARN("ahb_single must be 0 or 1\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ if ((val == 1) && (core_if->snpsid < OTG_CORE_REV_2_94a)) { ++ valid = 0; ++ } ++ if (valid == 0) { ++ if (dwc_otg_param_initialized(core_if->core_params->ahb_single)) { ++ DWC_ERROR("%d invalid for parameter ahb_single." ++ "Check HW configuration.\n", val); ++ } ++ retval = -DWC_E_INVALID; ++ val = 0; ++ } ++ core_if->core_params->ahb_single = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->ahb_single; ++} ++ ++int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val) ++{ ++ int retval = 0; ++ ++ if (DWC_OTG_PARAM_TEST(val, 0, 1)) { ++ DWC_WARN("`%d' invalid for parameter `otg_ver'\n", val); ++ DWC_WARN ++ ("otg_ver must be 0(for OTG 1.3 support) or 1(for OTG 2.0 support)\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ core_if->core_params->otg_ver = val; ++ return retval; ++} ++ ++int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->core_params->otg_ver; ++} + +uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t * core_if) +{ + gotgctl_data_t otgctl; -+ otgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl); ++ otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); + return otgctl.b.hstnegscs; +} + +uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t * core_if) +{ + gotgctl_data_t otgctl; -+ otgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl); ++ otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); + return otgctl.b.sesreqscs; +} + +void dwc_otg_set_hnpreq(dwc_otg_core_if_t * core_if, uint32_t val) +{ -+ gotgctl_data_t otgctl; -+ otgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl); -+ otgctl.b.hnpreq = val; -+ dwc_write_reg32(&core_if->core_global_regs->gotgctl, otgctl.d32); ++ if(core_if->otg_ver == 0) { ++ gotgctl_data_t otgctl; ++ otgctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->gotgctl); ++ otgctl.b.hnpreq = val; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, otgctl.d32); ++ } else { ++ core_if->otg_sts = val; ++ } +} + +uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t * core_if) @@ -45797,45 +56019,47 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + +uint32_t dwc_otg_get_mode(dwc_otg_core_if_t * core_if) +{ -+ gotgctl_data_t otgctl; -+ otgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl); -+ return otgctl.b.currmod; ++ gintsts_data_t gintsts; ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ return gintsts.b.curmode; +} + +uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t * core_if) +{ + gusbcfg_data_t usbcfg; -+ usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg); ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); + return usbcfg.b.hnpcap; +} + +void dwc_otg_set_hnpcapable(dwc_otg_core_if_t * core_if, uint32_t val) +{ + gusbcfg_data_t usbcfg; -+ usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg); ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); + usbcfg.b.hnpcap = val; -+ dwc_write_reg32(&core_if->core_global_regs->gusbcfg, usbcfg.d32); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32); +} + +uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t * core_if) +{ + gusbcfg_data_t usbcfg; -+ usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg); ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); + return usbcfg.b.srpcap; +} + +void dwc_otg_set_srpcapable(dwc_otg_core_if_t * core_if, uint32_t val) +{ + gusbcfg_data_t usbcfg; -+ usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg); ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); + usbcfg.b.srpcap = val; -+ dwc_write_reg32(&core_if->core_global_regs->gusbcfg, usbcfg.d32); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, usbcfg.d32); +} + +uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t * core_if) +{ + dcfg_data_t dcfg; -+ dcfg.d32 = -1; //GRAYG ++ /* originally: dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); */ ++ ++ dcfg.d32 = -1; //GRAYG + DWC_DEBUGPL(DBG_CILV, "%s - core_if(%p)\n", __func__, core_if); + if (NULL == core_if) + DWC_ERROR("reg request with NULL core_if\n"); @@ -45855,7 +56079,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 + core_if, core_if->dev_if, + core_if->dev_if->dev_global_regs, + &core_if->dev_if->dev_global_regs->dcfg); -+ dcfg.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg); ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); + } + return dcfg.b.devspd; +} @@ -45863,45 +56087,50 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 +void dwc_otg_set_devspeed(dwc_otg_core_if_t * core_if, uint32_t val) +{ + dcfg_data_t dcfg; -+ dcfg.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dcfg); ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); + dcfg.b.devspd = val; -+ dwc_write_reg32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32); +} + +uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t * core_if) +{ + hprt0_data_t hprt0; -+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0); ++ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); + return hprt0.b.prtconnsts; +} + +uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t * core_if) +{ + dsts_data_t dsts; -+ 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); + return dsts.b.enumspd; +} + +uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if) +{ + hprt0_data_t hprt0; -+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0); ++ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); + return hprt0.b.prtpwr; + +} + ++uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if) ++{ ++ return core_if->hibernation_suspend; ++} ++ +void dwc_otg_set_prtpower(dwc_otg_core_if_t * core_if, uint32_t val) +{ + hprt0_data_t hprt0; -+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); + hprt0.b.prtpwr = val; -+ dwc_write_reg32(core_if->host_if->hprt0, val); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); +} + +uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t * core_if) +{ + hprt0_data_t hprt0; -+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0); ++ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); + return hprt0.b.prtsusp; + +} @@ -45909,30 +56138,119 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 +void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val) +{ + hprt0_data_t hprt0; -+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); + hprt0.b.prtsusp = val; -+ dwc_write_reg32(core_if->host_if->hprt0, val); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++} ++ ++uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if) ++{ ++ hfir_data_t hfir; ++ hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir); ++ return hfir.b.frint; ++ ++} ++ ++void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ hfir_data_t hfir; ++ uint32_t fram_int; ++ fram_int = calc_frame_interval(core_if); ++ hfir.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hfir); ++ if (!core_if->core_params->reload_ctl) { ++ DWC_WARN("\nCannot reload HFIR register.HFIR.HFIRRldCtrl bit is" ++ "not set to 1.\nShould load driver with reload_ctl=1" ++ " module parameter\n"); ++ return; ++ } ++ switch (fram_int) { ++ case 3750: ++ if ((val < 3350) || (val > 4150)) { ++ DWC_WARN("HFIR interval for HS core and 30 MHz" ++ "clock freq should be from 3350 to 4150\n"); ++ return; ++ } ++ break; ++ case 30000: ++ if ((val < 26820) || (val > 33180)) { ++ DWC_WARN("HFIR interval for FS/LS core and 30 MHz" ++ "clock freq should be from 26820 to 33180\n"); ++ return; ++ } ++ break; ++ case 6000: ++ if ((val < 5360) || (val > 6640)) { ++ DWC_WARN("HFIR interval for HS core and 48 MHz" ++ "clock freq should be from 5360 to 6640\n"); ++ return; ++ } ++ break; ++ case 48000: ++ if ((val < 42912) || (val > 53088)) { ++ DWC_WARN("HFIR interval for FS/LS core and 48 MHz" ++ "clock freq should be from 42912 to 53088\n"); ++ return; ++ } ++ break; ++ case 7500: ++ if ((val < 6700) || (val > 8300)) { ++ DWC_WARN("HFIR interval for HS core and 60 MHz" ++ "clock freq should be from 6700 to 8300\n"); ++ return; ++ } ++ break; ++ case 60000: ++ if ((val < 53640) || (val > 65536)) { ++ DWC_WARN("HFIR interval for FS/LS core and 60 MHz" ++ "clock freq should be from 53640 to 65536\n"); ++ return; ++ } ++ break; ++ default: ++ DWC_WARN("Unknown frame interval\n"); ++ return; ++ break; ++ ++ } ++ hfir.b.frint = val; ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hfir, hfir.d32); ++} ++ ++uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if) ++{ ++ hcfg_data_t hcfg; ++ hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ return hcfg.b.modechtimen; ++ ++} ++ ++void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val) ++{ ++ hcfg_data_t hcfg; ++ hcfg.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->hcfg); ++ hcfg.b.modechtimen = val; ++ DWC_WRITE_REG32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32); +} + +void dwc_otg_set_prtresume(dwc_otg_core_if_t * core_if, uint32_t val) +{ + hprt0_data_t hprt0; -+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); + hprt0.b.prtres = val; -+ dwc_write_reg32(core_if->host_if->hprt0, val); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); +} + +uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t * core_if) +{ + dctl_data_t dctl; -+ dctl.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dctl); ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); + return dctl.b.rmtwkupsig; +} + +uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t * core_if) +{ + glpmcfg_data_t lpmcfg; -+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); + + DWC_ASSERT(! + ((core_if->lx_state == DWC_OTG_L1) ^ lpmcfg.b.prt_sleep_sts), @@ -45945,44 +56263,44 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 +uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t * core_if) +{ + glpmcfg_data_t lpmcfg; -+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); + return lpmcfg.b.rem_wkup_en; +} + +uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t * core_if) +{ + glpmcfg_data_t lpmcfg; -+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); + return lpmcfg.b.appl_resp; +} + +void dwc_otg_set_lpmresponse(dwc_otg_core_if_t * core_if, uint32_t val) +{ + glpmcfg_data_t lpmcfg; -+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); + lpmcfg.b.appl_resp = val; -+ dwc_write_reg32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); +} + +uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t * core_if) +{ + glpmcfg_data_t lpmcfg; -+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); + return lpmcfg.b.hsic_connect; +} + +void dwc_otg_set_hsic_connect(dwc_otg_core_if_t * core_if, uint32_t val) +{ + glpmcfg_data_t lpmcfg; -+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); + lpmcfg.b.hsic_connect = val; -+ dwc_write_reg32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); +} + +uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t * core_if) +{ + glpmcfg_data_t lpmcfg; -+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); + return lpmcfg.b.inv_sel_hsic; + +} @@ -45990,110 +56308,151 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.c linux-rpi-bootc-3 +void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t * core_if, uint32_t val) +{ + glpmcfg_data_t lpmcfg; -+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); + lpmcfg.b.inv_sel_hsic = val; -+ dwc_write_reg32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); +} + +uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t * core_if) +{ -+ return dwc_read_reg32(&core_if->core_global_regs->gotgctl); ++ return DWC_READ_REG32(&core_if->core_global_regs->gotgctl); +} + +void dwc_otg_set_gotgctl(dwc_otg_core_if_t * core_if, uint32_t val) +{ -+ dwc_write_reg32(&core_if->core_global_regs->gotgctl, val); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gotgctl, val); +} + +uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t * core_if) +{ -+ return dwc_read_reg32(&core_if->core_global_regs->gusbcfg); ++ return DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); +} + +void dwc_otg_set_gusbcfg(dwc_otg_core_if_t * core_if, uint32_t val) +{ -+ dwc_write_reg32(&core_if->core_global_regs->gusbcfg, val); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, val); +} + +uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t * core_if) +{ -+ return dwc_read_reg32(&core_if->core_global_regs->grxfsiz); ++ return DWC_READ_REG32(&core_if->core_global_regs->grxfsiz); +} + +void dwc_otg_set_grxfsiz(dwc_otg_core_if_t * core_if, uint32_t val) +{ -+ dwc_write_reg32(&core_if->core_global_regs->grxfsiz, val); ++ DWC_WRITE_REG32(&core_if->core_global_regs->grxfsiz, val); +} + +uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t * core_if) +{ -+ return dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz); ++ return DWC_READ_REG32(&core_if->core_global_regs->gnptxfsiz); +} + +void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t * core_if, uint32_t val) +{ -+ dwc_write_reg32(&core_if->core_global_regs->gnptxfsiz, val); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gnptxfsiz, val); +} + +uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t * core_if) +{ -+ return dwc_read_reg32(&core_if->core_global_regs->gpvndctl); ++ return DWC_READ_REG32(&core_if->core_global_regs->gpvndctl); +} + +void dwc_otg_set_gpvndctl(dwc_otg_core_if_t * core_if, uint32_t val) +{ -+ dwc_write_reg32(&core_if->core_global_regs->gpvndctl, val); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gpvndctl, val); +} + +uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t * core_if) +{ -+ return dwc_read_reg32(&core_if->core_global_regs->ggpio); ++ return DWC_READ_REG32(&core_if->core_global_regs->ggpio); +} + +void dwc_otg_set_ggpio(dwc_otg_core_if_t * core_if, uint32_t val) +{ -+ dwc_write_reg32(&core_if->core_global_regs->ggpio, val); ++ DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, val); +} + +uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t * core_if) +{ -+ return dwc_read_reg32(core_if->host_if->hprt0); ++ return DWC_READ_REG32(core_if->host_if->hprt0); + +} + +void dwc_otg_set_hprt0(dwc_otg_core_if_t * core_if, uint32_t val) +{ -+ dwc_write_reg32(core_if->host_if->hprt0, val); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, val); +} + +uint32_t dwc_otg_get_guid(dwc_otg_core_if_t * core_if) +{ -+ return dwc_read_reg32(&core_if->core_global_regs->guid); ++ return DWC_READ_REG32(&core_if->core_global_regs->guid); +} + +void dwc_otg_set_guid(dwc_otg_core_if_t * core_if, uint32_t val) +{ -+ dwc_write_reg32(&core_if->core_global_regs->guid, val); ++ DWC_WRITE_REG32(&core_if->core_global_regs->guid, val); +} + +uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t * core_if) +{ -+ return dwc_read_reg32(&core_if->core_global_regs->hptxfsiz); ++ return DWC_READ_REG32(&core_if->core_global_regs->hptxfsiz); +} -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h 2012-07-15 20:29:19.070083357 +0200 -@@ -0,0 +1,1143 @@ ++ ++uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if) ++{ ++ return ((core_if->otg_ver == 1) ? (uint16_t)0x0200 : (uint16_t)0x0103); ++} ++ ++/** ++ * Start the SRP timer to detect when the SRP does not complete within ++ * 6 seconds. ++ * ++ * @param core_if the pointer to core_if strucure. ++ */ ++void dwc_otg_pcd_start_srp_timer(dwc_otg_core_if_t * core_if) ++{ ++ core_if->srp_timer_started = 1; ++ DWC_TIMER_SCHEDULE(core_if->srp_timer, 6000 /* 6 secs */ ); ++} ++ ++void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if) ++{ ++ uint32_t *addr = (uint32_t *) & (core_if->core_global_regs->gotgctl); ++ gotgctl_data_t mem; ++ gotgctl_data_t val; ++ ++ val.d32 = DWC_READ_REG32(addr); ++ if (val.b.sesreq) { ++ DWC_ERROR("Session Request Already active!\n"); ++ return; ++ } ++ ++ DWC_INFO("Session Request Initated\n"); //NOTICE ++ mem.d32 = DWC_READ_REG32(addr); ++ mem.b.sesreq = 1; ++ DWC_WRITE_REG32(addr, mem.d32); ++ ++ /* Start the SRP timer */ ++ dwc_otg_pcd_start_srp_timer(core_if); ++ return; ++} +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil.h b/drivers/usb/host/dwc_otg/dwc_otg_cil.h +new file mode 100644 +index 0000000..d367cd1 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.h +@@ -0,0 +1,1464 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil.h $ -+ * $Revision: #99 $ -+ * $Date: 2009/04/21 $ -+ * $Change: 1237466 $ ++ * $Revision: #123 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ + * + * 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 + * with Synopsys or any supplement thereto. You are permitted to use and @@ -46103,7 +56462,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + * any information contained herein except pursuant to this license grant from + * Synopsys. If you do not agree with this notice, including the disclaimer + * below, then you are not authorized to use the Software. -+ * ++ * + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -46120,15 +56479,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 +#if !defined(__DWC_CIL_H__) +#define __DWC_CIL_H__ + -+//#define HW2937_WORKAROUND -+#define DBG_HW2937 0x400 -+ -+#include "dwc_os.h" +#include "dwc_list.h" +#include "dwc_otg_dbg.h" +#include "dwc_otg_regs.h" + +#include "dwc_otg_core_if.h" ++#include "dwc_otg_adp.h" + +/** + * @file @@ -46149,16 +56505,21 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + BM_CIRCULAR = 3, /* data buffer uses the circular DMA mode */ + BM_ALIGN = 4 /* data buffer is in buffer alignment mode */ +} data_buffer_mode_e; -+#endif //DWC_UTE_CFI ++#endif //DWC_UTE_CFI + -+/** Macros defined for DWC OTG HW Release verison */ ++/** Macros defined for DWC OTG HW Release version */ + +#define OTG_CORE_REV_2_60a 0x4F54260A +#define OTG_CORE_REV_2_71a 0x4F54271A +#define OTG_CORE_REV_2_72a 0x4F54272A +#define OTG_CORE_REV_2_80a 0x4F54280A +#define OTG_CORE_REV_2_81a 0x4F54281A -+#define OTG_CORE_REV_2_90a 0x4F54290A ++#define OTG_CORE_REV_2_90a 0x4F54290A ++#define OTG_CORE_REV_2_91a 0x4F54291A ++#define OTG_CORE_REV_2_92a 0x4F54292A ++#define OTG_CORE_REV_2_93a 0x4F54293A ++#define OTG_CORE_REV_2_94a 0x4F54294A ++#define OTG_CORE_REV_3_00a 0x4F54300A + +/** + * Information for each ISOC packet. @@ -46182,8 +56543,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + /** EP active. */ + unsigned active:1; + -+ /** Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic Tx FIFO -+ If dedicated Tx FIFOs are enabled for all IN Eps - Tx FIFO # FOR IN EPs*/ ++ /** ++ * Periodic Tx FIFO # for IN EPs For INTR EP set to 0 to use non-periodic ++ * Tx FIFO. If dedicated Tx FIFOs are enabled Tx FIFO # FOR IN EPs*/ + unsigned tx_fifo_num:4; + /** EP type: 0 - Control, 1 - ISOC, 2 - BULK, 3 - INTR */ + unsigned type:2; @@ -46230,6 +56592,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + /** stall clear flag */ + unsigned stall_clear_flag:1; + ++ /** SETUP pkt cnt rollover flag for EP0 out*/ ++ unsigned stp_rollover; ++ +#ifdef DWC_UTE_CFI + /* The buffer mode */ + data_buffer_mode_e buff_mode; @@ -46245,9 +56610,27 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + uint32_t cfi_req_len; +#endif //DWC_UTE_CFI + ++/** Max DMA Descriptor count for any EP */ ++#define MAX_DMA_DESC_CNT 256 + /** Allocated DMA Desc count */ + uint32_t desc_cnt; ++ ++ /** bInterval */ ++ uint32_t bInterval; ++ /** Next frame num to setup next ISOC transfer */ ++ uint32_t frame_num; ++ /** Indicates SOF number overrun in DSTS */ ++ uint8_t frm_overrun; + ++#ifdef DWC_UTE_PER_IO ++ /** Next frame num for which will be setup DMA Desc */ ++ uint32_t xiso_frame_num; ++ /** bInterval */ ++ uint32_t xiso_bInterval; ++ /** Count of currently active transfers - shall be either 0 or 1 */ ++ int xiso_active_xfers; ++ int xiso_queued_xfers; ++#endif +#ifdef DWC_EN_ISOC + /** + * Variables specific for ISOC EPs @@ -46316,9 +56699,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + DWC_OTG_HC_XFER_AHB_ERR, + DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE, + DWC_OTG_HC_XFER_URB_DEQUEUE -+#ifdef HW2937_WORKAROUND -+ , DWC_OTG_HC_XFER_PAUSE_IN -+#endif +} dwc_otg_halt_status_e; + +/** @@ -46387,7 +56767,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + + /** Pointer to the current transfer buffer position. */ + uint8_t *xfer_buff; -+ /** ++ /** + * In Buffer DMA mode this buffer will be used + * if xfer_buff is not DWORD aligned. + */ @@ -46444,9 +56824,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + uint8_t hub_addr; /**< Address of high speed hub */ + + uint8_t port_addr; /**< Port of the low/full speed device */ -+ /** Split transaction position ++ /** Split transaction position + * One of the following values: -+ * - DWC_HCSPLIT_XACTPOS_MID ++ * - DWC_HCSPLIT_XACTPOS_MID + * - DWC_HCSPLIT_XACTPOS_BEGIN + * - DWC_HCSPLIT_XACTPOS_END + * - DWC_HCSPLIT_XACTPOS_ALL */ @@ -46470,19 +56850,19 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + + /** Entry in list of host channels. */ + DWC_CIRCLEQ_ENTRY(dwc_hc) hc_list_entry; -+ ++ + /** @name Descriptor DMA support */ + /** @{ */ -+ ++ + /** Number of Transfer Descriptors */ + uint16_t ntd; -+ ++ + /** Descriptor List DMA address */ + dwc_dma_t desc_list_addr; -+ ++ + /** Scheduling micro-frame bitmap. */ + uint8_t schinfo; -+ ++ + /** @} */ +} dwc_hc_t; + @@ -46512,9 +56892,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + int32_t dma_enable; + + /** -+ * When DMA mode is enabled specifies whether to use address DMA or DMA Descritor mode for accessing the data -+ * FIFOs in device mode. The driver will automatically detect the value for this -+ * parameter if none is specified. ++ * When DMA mode is enabled specifies whether to use address DMA or DMA ++ * Descriptor mode for accessing the data FIFOs in device mode. The driver ++ * will automatically detect the value for this if none is specified. + * 0 - address DMA + * 1 - DMA Descriptor(default, if available) + */ @@ -46533,7 +56913,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + * 1 - Full Speed + */ + int32_t speed; -+ /** Specifies whether low power mode is supported when attached ++ /** Specifies whether low power mode is supported when attached + * to a Full Speed or Low Speed device in host mode. + * 0 - Don't support low power mode (default) + * 1 - Support low power mode @@ -46542,7 +56922,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + + /** Specifies the PHY clock rate in low power mode when connected to a + * Low Speed device in host mode. This parameter is applicable only if -+ * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS ++ * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS + * then defaults to 6 MHZ otherwise 48 MHZ. + * + * 0 - 48 MHz @@ -46556,21 +56936,21 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + */ + int32_t enable_dynamic_fifo; + -+ /** Total number of 4-byte words in the data FIFO memory. This -+ * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic ++ /** Total number of 4-byte words in the data FIFO memory. This ++ * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic + * Tx FIFOs. + * 32 to 32768 (default 8192) + * Note: The total FIFO memory depth in the FPGA configuration is 8192. + */ + int32_t data_fifo_size; + -+ /** Number of 4-byte words in the Rx FIFO in device mode when dynamic ++ /** Number of 4-byte words in the Rx FIFO in device mode when dynamic + * FIFO sizing is enabled. + * 16 to 32768 (default 1064) + */ + int32_t dev_rx_fifo_size; + -+ /** Number of 4-byte words in the non-periodic Tx FIFO in device mode ++ /** Number of 4-byte words in the non-periodic Tx FIFO in device mode + * when dynamic FIFO sizing is enabled. + * 16 to 32768 (default 1024) + */ @@ -46582,52 +56962,52 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + */ + uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS]; + -+ /** Number of 4-byte words in the Rx FIFO in host mode when dynamic ++ /** Number of 4-byte words in the Rx FIFO in host mode when dynamic + * FIFO sizing is enabled. -+ * 16 to 32768 (default 1024) ++ * 16 to 32768 (default 1024) + */ + int32_t host_rx_fifo_size; + -+ /** Number of 4-byte words in the non-periodic Tx FIFO in host mode -+ * when Dynamic FIFO sizing is enabled in the core. ++ /** Number of 4-byte words in the non-periodic Tx FIFO in host mode ++ * when Dynamic FIFO sizing is enabled in the core. + * 16 to 32768 (default 1024) + */ + int32_t host_nperio_tx_fifo_size; + -+ /** Number of 4-byte words in the host periodic Tx FIFO when dynamic -+ * FIFO sizing is enabled. ++ /** Number of 4-byte words in the host periodic Tx FIFO when dynamic ++ * FIFO sizing is enabled. + * 16 to 32768 (default 1024) + */ + int32_t host_perio_tx_fifo_size; + -+ /** The maximum transfer size supported in bytes. ++ /** The maximum transfer size supported in bytes. + * 2047 to 65,535 (default 65,535) + */ + int32_t max_transfer_size; + -+ /** The maximum number of packets in a transfer. ++ /** The maximum number of packets in a transfer. + * 15 to 511 (default 511) + */ + int32_t max_packet_count; + -+ /** The number of host channel registers to use. -+ * 1 to 16 (default 12) ++ /** The number of host channel registers to use. ++ * 1 to 16 (default 12) + * Note: The FPGA configuration supports a maximum of 12 host channels. + */ + int32_t host_channels; + -+ /** The number of endpoints in addition to EP0 available for device -+ * mode operations. -+ * 1 to 15 (default 6 IN and OUT) -+ * Note: The FPGA configuration supports a maximum of 6 IN and OUT ++ /** The number of endpoints in addition to EP0 available for device ++ * mode operations. ++ * 1 to 15 (default 6 IN and OUT) ++ * Note: The FPGA configuration supports a maximum of 6 IN and OUT + * endpoints in addition to EP0. + */ + int32_t dev_endpoints; + -+ /** ++ /** + * Specifies the type of PHY interface to use. By default, the driver + * will automatically detect the phy_type. -+ * ++ * + * 0 - Full Speed PHY + * 1 - UTMI+ (default) + * 2 - ULPI @@ -46635,13 +57015,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + int32_t phy_type; + + /** -+ * Specifies the UTMI+ Data Width. This parameter is ++ * Specifies the UTMI+ Data Width. This parameter is + * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI + * PHY_TYPE, this parameter indicates the data width between + * the MAC and the ULPI Wrapper.) Also, this parameter is + * applicable only if the OTG_HSPHY_WIDTH cC parameter was set + * to "8 and 16 bits", meaning that the core has been -+ * configured to work at either data path width. ++ * configured to work at either data path width. + * + * 8 or 16 bits (default 16) + */ @@ -46651,7 +57031,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + * Specifies whether the ULPI operates at double or single + * data rate. This parameter is only applicable if PHY_TYPE is + * ULPI. -+ * ++ * + * 0 - single data rate ULPI interface with 8 bit wide data + * bus (default) + * 1 - double data rate ULPI interface with 4 bit wide data @@ -46660,7 +57040,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + int32_t phy_ulpi_ddr; + + /** -+ * Specifies whether to use the internal or external supply to ++ * Specifies whether to use the internal or external supply to + * drive the vbus with a ULPI phy. + */ + int32_t phy_ulpi_ext_vbus; @@ -46678,9 +57058,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + int32_t ts_dline; + + /** -+ * Specifies whether dedicated transmit FIFOs are ++ * Specifies whether dedicated transmit FIFOs are + * enabled for non periodic IN endpoints in device mode -+ * 0 - No ++ * 0 - No + * 1 - Yes + */ + int32_t en_multiple_tx_fifo; @@ -46691,19 +57071,19 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + */ + uint32_t dev_tx_fifo_size[MAX_TX_FIFOS]; + -+ /** Thresholding enable flag- ++ /** Thresholding enable flag- + * bit 0 - enable non-ISO Tx thresholding + * bit 1 - enable ISO Tx thresholding + * bit 2 - enable Rx thresholding + */ + uint32_t thr_ctl; + -+ /** Thresholding length for Tx ++ /** Thresholding length for Tx + * FIFOs in 32 bit DWORDs + */ + uint32_t tx_thr_length; + -+ /** Thresholding length for Rx ++ /** Thresholding length for Rx + * FIFOs in 32 bit DWORDs + */ + uint32_t rx_thr_length; @@ -46713,14 +57093,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + */ + int32_t lpm_enable; + -+ /** Per Transfer Interrupt ++ /** Per Transfer Interrupt + * mode enable flag + * 1 - Enabled + * 0 - Disabled + */ + int32_t pti_enable; + -+ /** Multi Processor Interrupt ++ /** Multi Processor Interrupt + * mode enable flag + * 1 - Enabled + * 0 - Disabled @@ -46741,6 +57121,53 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + */ + int32_t ahb_thr_ratio; + ++ /** ADP Support ++ * 1 - Enabled ++ * 0 - Disabled ++ */ ++ int32_t adp_supp_enable; ++ ++ /** HFIR Reload Control ++ * 0 - The HFIR cannot be reloaded dynamically. ++ * 1 - Allow dynamic reloading of the HFIR register during runtime. ++ */ ++ int32_t reload_ctl; ++ ++ /** DCFG: Enable device Out NAK ++ * 0 - The core does not set NAK after Bulk Out transfer complete. ++ * 1 - The core sets NAK after Bulk OUT transfer complete. ++ */ ++ int32_t dev_out_nak; ++ ++ /** DCFG: Enable Continue on BNA ++ * After receiving BNA interrupt the core disables the endpoint,when the ++ * endpoint is re-enabled by the application the core starts processing ++ * 0 - from the DOEPDMA descriptor ++ * 1 - from the descriptor which received the BNA. ++ */ ++ int32_t cont_on_bna; ++ ++ /** GAHBCFG: AHB Single Support ++ * This bit when programmed supports SINGLE transfers for remainder ++ * data in a transfer for DMA mode of operation. ++ * 0 - in this case the remainder data will be sent using INCR burst size. ++ * 1 - in this case the remainder data will be sent using SINGLE burst size. ++ */ ++ int32_t ahb_single; ++ ++ /** Core Power down mode ++ * 0 - No Power Down is enabled ++ * 1 - Reserved ++ * 2 - Complete Power Down (Hibernation) ++ */ ++ int32_t power_down; ++ ++ /** OTG revision supported ++ * 0 - OTG 1.3 revision ++ * 1 - OTG 2.0 revision ++ */ ++ int32_t otg_ver; ++ +} dwc_otg_core_params_t; + +#ifdef DEBUG @@ -46750,6 +57177,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + dwc_hc_t *hc; +} hc_xfer_info_t; +#endif ++ ++typedef struct ep_xfer_info { ++ struct dwc_otg_core_if *core_if; ++ dwc_ep_t *ep; ++ uint8_t state; ++} ep_xfer_info_t; +/* + * Device States + */ @@ -46764,6 +57197,44 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + DWC_OTG_L3 +} dwc_otg_lx_state_e; + ++struct dwc_otg_global_regs_backup { ++ uint32_t gotgctl_local; ++ uint32_t gintmsk_local; ++ uint32_t gahbcfg_local; ++ uint32_t gusbcfg_local; ++ uint32_t grxfsiz_local; ++ uint32_t gnptxfsiz_local; ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ uint32_t glpmcfg_local; ++#endif ++ uint32_t gi2cctl_local; ++ uint32_t hptxfsiz_local; ++ uint32_t pcgcctl_local; ++ uint32_t gdfifocfg_local; ++ uint32_t dtxfsiz_local[MAX_EPS_CHANNELS]; ++ uint32_t gpwrdn_local; ++ uint32_t xhib_pcgcctl; ++ uint32_t xhib_gpwrdn; ++}; ++ ++struct dwc_otg_host_regs_backup { ++ uint32_t hcfg_local; ++ uint32_t haintmsk_local; ++ uint32_t hcintmsk_local[MAX_EPS_CHANNELS]; ++ uint32_t hprt0_local; ++ uint32_t hfir_local; ++}; ++ ++struct dwc_otg_dev_regs_backup { ++ uint32_t dcfg; ++ uint32_t dctl; ++ uint32_t daintmsk; ++ uint32_t diepmsk; ++ uint32_t doepmsk; ++ uint32_t diepctl[MAX_EPS_CHANNELS]; ++ uint32_t dieptsiz[MAX_EPS_CHANNELS]; ++ uint32_t diepdma[MAX_EPS_CHANNELS]; ++}; +/** + * The dwc_otg_core_if structure contains information needed to manage + * the DWC_otg controller acting in either host or device mode. It @@ -46795,7 +57266,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + */ + uint8_t srp_success; + uint8_t srp_timer_started; ++ /** Timer for SRP. If it expires before SRP is successful ++ * clear the SRP. */ ++ dwc_timer_t *srp_timer; + ++#ifdef DWC_DEV_SRPCAP ++ /* This timer is needed to power on the hibernated host core if SRP is not ++ * initiated on connected SRP capable device for limited period of time ++ */ ++ uint8_t pwron_timer_started; ++ dwc_timer_t *pwron_timer; ++#endif + /* Common configuration information */ + /** Power and Clock Gating Control Register */ + volatile uint32_t *pcgcctl; @@ -46837,6 +57318,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + hwcfg2_data_t hwcfg2; + hwcfg3_data_t hwcfg3; + hwcfg4_data_t hwcfg4; ++ fifosize_data_t hptxfsiz; + + /** Host and Device Configuration -- stored here for convenience.*/ + hcfg_data_t hcfg; @@ -46883,7 +57365,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + + /** Timer object used for handling "Wakeup Detected" Interrupt */ + dwc_timer_t *wkp_timer; -+ ++ /** This arrays used for debug purposes for DEV OUT NAK enhancement */ ++ uint32_t start_doeptsiz_val[MAX_EPS_CHANNELS]; ++ ep_xfer_info_t ep_xfer_info[MAX_EPS_CHANNELS]; ++ dwc_timer_t *ep_xfer_timer[MAX_EPS_CHANNELS]; +#ifdef DEBUG + uint32_t start_hcchar_val[MAX_EPS_CHANNELS]; + @@ -46911,6 +57396,51 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + /** Lx state of device */ + dwc_otg_lx_state_e lx_state; + ++ /** Saved Core Global registers */ ++ struct dwc_otg_global_regs_backup *gr_backup; ++ /** Saved Host registers */ ++ struct dwc_otg_host_regs_backup *hr_backup; ++ /** Saved Device registers */ ++ struct dwc_otg_dev_regs_backup *dr_backup; ++ ++ /** Power Down Enable */ ++ uint32_t power_down; ++ ++ /** ADP support Enable */ ++ uint32_t adp_enable; ++ ++ /** ADP structure object */ ++ dwc_otg_adp_t adp; ++ ++ /** hibernation/suspend flag */ ++ int hibernation_suspend; ++ ++ /** Device mode extended hibernation flag */ ++ int xhib; ++ ++ /** OTG revision supported */ ++ uint32_t otg_ver; ++ ++ /** OTG status flag used for HNP polling */ ++ uint8_t otg_sts; ++ ++ /** Pointer to either hcd->lock or pcd->lock */ ++ dwc_spinlock_t *lock; ++ ++ /** Start predict NextEP based on Learning Queue if equal 1, ++ * also used as counter of disabled NP IN EP's */ ++ uint8_t start_predict; ++ ++ /** NextEp sequence, including EP0: nextep_seq[] = EP if non-periodic and ++ * active, 0xff otherwise */ ++ uint8_t nextep_seq[MAX_EPS_CHANNELS]; ++ ++ /** Index of fisrt EP in nextep_seq array which should be re-enabled **/ ++ uint8_t first_in_nextep_seq; ++ ++ /** Frame number while entering to ISR - needed for ISOCs **/ ++ uint32_t frame_num; ++ +}; + +#ifdef DEBUG @@ -46921,13 +57451,40 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 +#endif + +/* -+ * The following functions are functions for works ++ * This function is called when transfer is timed out on endpoint. ++ */ ++extern void ep_xfer_timeout(void *ptr); ++ ++/* ++ * The following functions are functions for works + * using during handling some interrupts + */ +extern void w_conn_id_status_change(void *p); + +extern void w_wakeup_detected(void *p); + ++/** Saves global register values into system memory. */ ++extern int dwc_otg_save_global_regs(dwc_otg_core_if_t * core_if); ++/** Saves device register values into system memory. */ ++extern int dwc_otg_save_dev_regs(dwc_otg_core_if_t * core_if); ++/** Saves host register values into system memory. */ ++extern int dwc_otg_save_host_regs(dwc_otg_core_if_t * core_if); ++/** Restore global register values. */ ++extern int dwc_otg_restore_global_regs(dwc_otg_core_if_t * core_if); ++/** Restore host register values. */ ++extern int dwc_otg_restore_host_regs(dwc_otg_core_if_t * core_if, int reset); ++/** Restore device register values. */ ++extern int dwc_otg_restore_dev_regs(dwc_otg_core_if_t * core_if, ++ int rem_wakeup); ++extern int restore_lpm_i2c_regs(dwc_otg_core_if_t * core_if); ++extern int restore_essential_regs(dwc_otg_core_if_t * core_if, int rmode, ++ int is_host); ++ ++extern int dwc_otg_host_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int restore_mode, int reset); ++extern int dwc_otg_device_hibernation_restore(dwc_otg_core_if_t * core_if, ++ int rem_wakeup, int reset); ++ +/* + * The following functions support initialization of the CIL driver component + * and the DWC_otg controller. @@ -46967,7 +57524,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + dwc_ep_t * ep); +extern void dwc_otg_iso_ep_start_buf_transfer(dwc_otg_core_if_t * core_if, + dwc_ep_t * ep); -+#endif /* DWC_EN_ISOC */ ++#endif /* DWC_EN_ISOC */ +/**@}*/ + +/** @name Host CIL Functions @@ -46989,14 +57546,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 +extern void dwc_otg_enable_host_interrupts(dwc_otg_core_if_t * _core_if); +extern void dwc_otg_disable_host_interrupts(dwc_otg_core_if_t * _core_if); + -+extern void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, dwc_hc_t * hc); ++extern void dwc_otg_hc_start_transfer_ddma(dwc_otg_core_if_t * core_if, ++ dwc_hc_t * hc); ++ ++extern uint32_t calc_frame_interval(dwc_otg_core_if_t * core_if); + +/* Macro used to clear one channel interrupt */ +#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) + +/* @@ -47010,18 +57570,18 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 +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) -+ ++ +/** -+ * This function Reads HPRT0 in preparation to modify. It keeps the ++ * This function Reads HPRT0 in preparation to modify. It keeps the + * WC bits 0 so that if they are read as 1, they won't clear when you -+ * write it back ++ * write it back + */ +static inline uint32_t dwc_otg_read_hprt0(dwc_otg_core_if_t * _core_if) +{ + hprt0_data_t hprt0; -+ hprt0.d32 = dwc_read_reg32(_core_if->host_if->hprt0); ++ hprt0.d32 = DWC_READ_REG32(_core_if->host_if->hprt0); + hprt0.b.prtena = 0; + hprt0.b.prtconndet = 0; + hprt0.b.prtenchng = 0; @@ -47049,8 +57609,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + */ +static inline uint32_t dwc_otg_read_core_intr(dwc_otg_core_if_t * core_if) +{ -+ return (dwc_read_reg32(&core_if->core_global_regs->gintsts) & -+ dwc_read_reg32(&core_if->core_global_regs->gintmsk)); ++ return (DWC_READ_REG32(&core_if->core_global_regs->gintsts) & ++ DWC_READ_REG32(&core_if->core_global_regs->gintmsk)); +} + +/** @@ -47058,7 +57618,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + */ +static inline uint32_t dwc_otg_read_otg_intr(dwc_otg_core_if_t * core_if) +{ -+ return (dwc_read_reg32(&core_if->core_global_regs->gotgint)); ++ return (DWC_READ_REG32(&core_if->core_global_regs->gotgint)); +} + +/** @@ -47072,13 +57632,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + uint32_t v; + + if (core_if->multiproc_int_enable) { -+ v = dwc_read_reg32(&core_if->dev_if->dev_global_regs-> -+ deachint) & dwc_read_reg32(&core_if->dev_if-> -+ dev_global_regs-> -+ deachintmsk); ++ v = DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->deachint) & ++ DWC_READ_REG32(&core_if-> ++ dev_if->dev_global_regs->deachintmsk); + } else { -+ v = dwc_read_reg32(&core_if->dev_if->dev_global_regs->daint) & -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs->daintmsk); ++ v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) & ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk); + } + return (v & 0xffff); +} @@ -47093,13 +57653,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + uint32_t v; + + if (core_if->multiproc_int_enable) { -+ v = dwc_read_reg32(&core_if->dev_if->dev_global_regs-> -+ deachint) & dwc_read_reg32(&core_if->dev_if-> -+ dev_global_regs-> -+ deachintmsk); ++ v = DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->deachint) & ++ DWC_READ_REG32(&core_if-> ++ dev_if->dev_global_regs->deachintmsk); + } else { -+ v = dwc_read_reg32(&core_if->dev_if->dev_global_regs->daint) & -+ dwc_read_reg32(&core_if->dev_if->dev_global_regs->daintmsk); ++ v = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daint) & ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs->daintmsk); + } + + return ((v & 0xffff0000) >> 16); @@ -47116,20 +57676,20 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + + if (core_if->multiproc_int_enable) { + msk = -+ dwc_read_reg32(&dev_if->dev_global_regs-> -+ diepeachintmsk[ep->num]); ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->diepeachintmsk[ep->num]); + emp = -+ dwc_read_reg32(&dev_if->dev_global_regs-> -+ dtknqr4_fifoemptymsk); ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->dtknqr4_fifoemptymsk); + msk |= ((emp >> ep->num) & 0x1) << 7; -+ v = dwc_read_reg32(&dev_if->in_ep_regs[ep->num]->diepint) & msk; ++ v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk; + } else { -+ msk = dwc_read_reg32(&dev_if->dev_global_regs->diepmsk); ++ msk = DWC_READ_REG32(&dev_if->dev_global_regs->diepmsk); + emp = -+ dwc_read_reg32(&dev_if->dev_global_regs-> -+ dtknqr4_fifoemptymsk); ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->dtknqr4_fifoemptymsk); + msk |= ((emp >> ep->num) & 0x1) << 7; -+ v = dwc_read_reg32(&dev_if->in_ep_regs[ep->num]->diepint) & msk; ++ v = DWC_READ_REG32(&dev_if->in_ep_regs[ep->num]->diepint) & msk; + } + + return v; @@ -47147,20 +57707,20 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + + if (_core_if->multiproc_int_enable) { + msk.d32 = -+ dwc_read_reg32(&dev_if->dev_global_regs-> -+ doepeachintmsk[_ep->num]); ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->doepeachintmsk[_ep->num]); + if (_core_if->pti_enh_enable) { + msk.b.pktdrpsts = 1; + } -+ v = dwc_read_reg32(&dev_if->out_ep_regs[_ep->num]-> -+ doepint) & msk.d32; ++ v = DWC_READ_REG32(&dev_if-> ++ out_ep_regs[_ep->num]->doepint) & msk.d32; + } else { -+ msk.d32 = dwc_read_reg32(&dev_if->dev_global_regs->doepmsk); ++ msk.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->doepmsk); + if (_core_if->pti_enh_enable) { + msk.b.pktdrpsts = 1; + } -+ v = dwc_read_reg32(&dev_if->out_ep_regs[_ep->num]-> -+ doepint) & msk.d32; ++ v = DWC_READ_REG32(&dev_if-> ++ out_ep_regs[_ep->num]->doepint) & msk.d32; + } + return v; +} @@ -47171,30 +57731,30 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 +static inline uint32_t dwc_otg_read_host_all_channels_intr(dwc_otg_core_if_t * + _core_if) +{ -+ return (dwc_read_reg32(&_core_if->host_if->host_global_regs->haint)); ++ return (DWC_READ_REG32(&_core_if->host_if->host_global_regs->haint)); +} + +static inline uint32_t dwc_otg_read_host_channel_intr(dwc_otg_core_if_t * + _core_if, dwc_hc_t * _hc) +{ -+ return (dwc_read_reg32 ++ return (DWC_READ_REG32 + (&_core_if->host_if->hc_regs[_hc->hc_num]->hcint)); +} + +/** + * This function returns the mode of the operation, host or device. + * -+ * @return 0 - Device Mode, 1 - Host Mode ++ * @return 0 - Device Mode, 1 - Host Mode + */ +static inline uint32_t dwc_otg_mode(dwc_otg_core_if_t * _core_if) +{ -+ return (dwc_read_reg32(&_core_if->core_global_regs->gintsts) & 0x1); ++ return (DWC_READ_REG32(&_core_if->core_global_regs->gintsts) & 0x1); +} + +/**@}*/ + +/** -+ * DWC_otg CIL callback structure. This structure allows the HCD and ++ * DWC_otg CIL callback structure. This structure allows the HCD and + * PCD to register functions used for starting and stopping the PCD + * and HCD for role change on for a DRD. + */ @@ -47226,16 +57786,138 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil.h linux-rpi-bootc-3 + dwc_otg_cil_callbacks_t * _cb, + void *_p); + ++void dwc_otg_initiate_srp(dwc_otg_core_if_t * core_if); ++ ++////////////////////////////////////////////////////////////////////// ++/** Start the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_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); ++ } ++} ++ ++/** Stop the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_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); ++ } ++} ++ ++/** Disconnect the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_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); ++ } ++} ++ ++/** Inform the HCD the a New Session has begun. Helper function for ++ * using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_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); ++ } ++} ++ ++#ifdef CONFIG_USB_DWC_OTG_LPM ++/** ++ * Inform the HCD about LPM sleep. ++ * Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_sleep(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->sleep) { ++ core_if->hcd_cb->sleep(core_if->hcd_cb->p); ++ } ++} +#endif -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c 2012-07-15 20:29:19.135084581 +0200 -@@ -0,0 +1,846 @@ ++ ++/** Resume the HCD. Helper function for using the HCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_hcd_resume(dwc_otg_core_if_t * core_if) ++{ ++ if (core_if->hcd_cb && core_if->hcd_cb->resume_wakeup) { ++ core_if->hcd_cb->resume_wakeup(core_if->hcd_cb->p); ++ } ++} ++ ++/** Start the PCD. Helper function for using the PCD callbacks. ++ * ++ * @param core_if Programming view of DWC_otg controller. ++ */ ++static inline void cil_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 cil_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 cil_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 cil_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); ++ } ++} ++ ++////////////////////////////////////////////////////////////////////// ++ ++#endif +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c +new file mode 100644 +index 0000000..b861b55 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c +@@ -0,0 +1,1571 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_cil_intr.c $ -+ * $Revision: #15 $ -+ * $Date: 2009/04/15 $ -+ * $Change: 1234129 $ ++ * $Revision: #32 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ + * + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless @@ -47275,6 +57957,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo +#include "dwc_os.h" +#include "dwc_otg_regs.h" +#include "dwc_otg_cil.h" ++#include "dwc_otg_driver.h" ++#include "dwc_otg_pcd.h" ++#include "dwc_otg_hcd.h" ++#include "dwc_otg_mphi_fix.h" ++ ++extern bool fiq_fix_enable; + +#ifdef DEBUG +inline const char *op_state_str(dwc_otg_core_if_t * core_if) @@ -47300,125 +57988,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + /* 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; +} + -+/** 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) -+{ -+ 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) -+{ -+ 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); -+ } -+} -+ -+/** Inform the HCD the a New Session has begun. Helper function for -+ * 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); -+ } -+} -+ -+#ifdef CONFIG_USB_DWC_OTG_LPM -+/** -+ * Inform the HCD about LPM sleep. -+ * Helper function for using the HCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void hcd_sleep(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->hcd_cb && core_if->hcd_cb->sleep) { -+ core_if->hcd_cb->sleep(core_if->hcd_cb->p); -+ } -+} -+#endif -+ -+/** Resume the HCD. Helper function for using the HCD callbacks. -+ * -+ * @param core_if Programming view of DWC_otg controller. -+ */ -+static inline void hcd_resume(dwc_otg_core_if_t * core_if) -+{ -+ if (core_if->hcd_cb && core_if->hcd_cb->resume_wakeup) { -+ core_if->hcd_cb->resume_wakeup(core_if->hcd_cb->p); -+ } -+} -+ -+/** 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); -+ } -+} -+ -+/** 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); -+ } -+} -+ -+/** 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); -+ } -+} -+ -+/** 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); -+ } -+} -+ +/** + * This function handles the OTG Interrupts. It reads the OTG + * Interrupt Register (GOTGINT) to determine what interrupt has @@ -47432,9 +58005,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + gotgint_data_t gotgint; + gotgctl_data_t gotgctl; + gintmsk_data_t gintmsk; ++ gpwrdn_data_t gpwrdn; + -+ gotgint.d32 = dwc_read_reg32(&global_regs->gotgint); -+ gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); ++ 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)); + @@ -47442,10 +58016,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + DWC_DEBUGPL(DBG_ANY, " ++OTG Interrupt: " + "Session End Detected++ (%s)\n", + op_state_str(core_if)); -+ gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); ++ gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); + + if (core_if->op_state == B_HOST) { -+ pcd_start(core_if); ++ cil_pcd_start(core_if); + core_if->op_state = B_PERIPHERAL; + } else { + /* If not B_HOST and Device HNP still set. HNP @@ -47460,26 +58034,50 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + /* Reset PCD and Gadget driver to a + * clean state. */ + core_if->lx_state = DWC_OTG_L0; -+ pcd_stop(core_if); ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ DWC_SPINLOCK(core_if->lock); ++ ++ if (core_if->adp_enable) { ++ if (core_if->power_down == 2) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, gpwrdn.d32, 0); ++ } ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++ dwc_otg_adp_sense_start(core_if); ++ } + } ++ + gotgctl.d32 = 0; + gotgctl.b.devhnpen = 1; -+ dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0); ++ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); + } + if (gotgint.b.sesreqsucstschng) { + 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; + } else { -+ pcd_resume(core_if); ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_resume(core_if); ++ DWC_SPINLOCK(core_if->lock); + /* 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); + } + } @@ -47487,7 +58085,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + if (gotgint.b.hstnegsucstschng) { + /* Print statements during the HNP interrupt handling + * can cause it to fail.*/ -+ gotgctl.d32 = dwc_read_reg32(&global_regs->gotgctl); ++ gotgctl.d32 = DWC_READ_REG32(&global_regs->gotgctl); ++ /* WA for 3.00a- HW is not setting cur_mode, even sometimes ++ * this does not help*/ ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) ++ dwc_udelay(100); + if (gotgctl.b.hstnegscs) { + if (dwc_otg_is_host_mode(core_if)) { + core_if->op_state = B_HOST; @@ -47503,20 +58105,23 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + */ + gintmsk.d32 = 0; + gintmsk.b.sofintr = 1; -+ dwc_modify_reg32(&global_regs->gintmsk, ++ DWC_MODIFY_REG32(&global_regs->gintmsk, + gintmsk.d32, 0); -+ pcd_stop(core_if); ++ /* Call callback function with spin lock released */ ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); + /* + * Initialize the Core for Host mode. + */ -+ hcd_start(core_if); ++ cil_hcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); + core_if->op_state = B_HOST; + } + } else { + gotgctl.d32 = 0; + gotgctl.b.hnpreq = 1; + gotgctl.b.devhnpen = 1; -+ dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0); ++ DWC_MODIFY_REG32(&global_regs->gotgctl, gotgctl.d32, 0); + DWC_DEBUGPL(DBG_ANY, "HNP Failed\n"); + __DWC_ERROR("Device Not Connected/Responding\n"); + } @@ -47534,8 +58139,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + 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); ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_hcd_disconnect(core_if); ++ cil_pcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); + core_if->op_state = A_PERIPHERAL; + } else { + /* @@ -47549,9 +58156,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + */ + gintmsk.d32 = 0; + gintmsk.b.sofintr = 1; -+ dwc_modify_reg32(&global_regs->gintmsk, gintmsk.d32, 0); -+ pcd_stop(core_if); -+ hcd_start(core_if); ++ DWC_MODIFY_REG32(&global_regs->gintmsk, gintmsk.d32, 0); ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ cil_hcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); + core_if->op_state = A_HOST; + } + } @@ -47564,7 +58173,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + } + + /* 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; +} @@ -47575,7 +58184,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + uint32_t count = 0; + 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); + DWC_DEBUGPL(DBG_CIL, "gotgctl=%0x\n", gotgctl.d32); + DWC_DEBUGPL(DBG_CIL, "gotgctl.b.conidsts=%d\n", gotgctl.b.conidsts); + @@ -47595,7 +58204,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + core_if->op_state = B_PERIPHERAL; + dwc_otg_core_init(core_if); + dwc_otg_enable_global_interrupts(core_if); -+ pcd_start(core_if); ++ cil_pcd_start(core_if); + } else { + /* A-Device connector (Host Mode) */ + while (!dwc_otg_is_host_mode(core_if)) { @@ -47614,7 +58223,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + */ + dwc_otg_core_init(core_if); + dwc_otg_enable_global_interrupts(core_if); -+ hcd_start(core_if); ++ cil_hcd_start(core_if); + } +} + @@ -47622,7 +58231,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + * This function handles the Connector ID Status Change Interrupt. It + * reads the OTG Interrupt Register (GOTCTL) to determine whether this + * is a Device to Host Mode transition or a Host Mode to Device -+ * Transition. ++ * Transition. + * + * This only occurs when the cable is connected/removed from the PHY + * connector. @@ -47643,21 +58252,26 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + 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")); ++ ++ DWC_SPINUNLOCK(core_if->lock); + + /* + * Need to schedule a work, as there are possible DELAY function calls ++ * Release lock before scheduling workq as it holds spinlock during scheduling + */ ++ + DWC_WORKQ_SCHEDULE(core_if->wq_otg, w_conn_id_status_change, + core_if, "connection id status change"); ++ DWC_SPINLOCK(core_if->lock); + + /* 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; +} @@ -47673,7 +58287,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + */ +int32_t dwc_otg_handle_session_req_intr(dwc_otg_core_if_t * core_if) +{ -+ hprt0_data_t hprt0; + gintsts_data_t gintsts; + +#ifndef DWC_HOST_ONLY @@ -47682,23 +58295,24 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + if (dwc_otg_is_device_mode(core_if)) { + DWC_PRINTF("SRP: Device mode\n"); + } else { ++ hprt0_data_t hprt0; + DWC_PRINTF("SRP: Host mode\n"); + + /* Turn on the port power bit. */ + 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); ++ cil_hcd_session_start(core_if); + } +#endif + + /* Clear interrupt */ + 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; +} @@ -47715,22 +58329,21 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + pcgcctl_data_t pcgcctl = {.d32 = 0 }; + /* Restart the Phy Clock */ + pcgcctl.b.stoppclk = 1; -+ dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32, 0); ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); + dwc_udelay(10); -+#endif //0 ++#endif //0 + hprt0.d32 = dwc_otg_read_hprt0(core_if); + DWC_DEBUGPL(DBG_ANY, "Resume: HPRT0=%0x\n", hprt0.d32); +// dwc_mdelay(70); + hprt0.b.prtres = 0; /* Resume */ -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); ++ 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)); ++ DWC_READ_REG32(core_if->host_if->hprt0)); + -+ hcd_resume(core_if); ++ cil_hcd_resume(core_if); + + /** Change to L0 state*/ + core_if->lx_state = DWC_OTG_L0; -+ +} + +/** @@ -47752,42 +58365,43 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + 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-> ++ DWC_READ_REG32(&core_if->dev_if->dev_global_regs-> + dsts)); + if (core_if->lx_state == DWC_OTG_L2) { +#ifdef PARTIAL_POWER_DOWN + 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 */ ++ /* Clear the Remote Wakeup Signaling */ + dctl.b.rmtwkupsig = 1; -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> + dctl, dctl.d32, 0); + ++ DWC_SPINUNLOCK(core_if->lock); + if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { -+ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb-> -+ p); ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); + } ++ DWC_SPINLOCK(core_if->lock); + } else { + glpmcfg_data_t lpmcfg; + lpmcfg.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->glpmcfg); ++ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); + lpmcfg.b.hird_thres &= (~(1 << 4)); -+ dwc_write_reg32(&core_if->core_global_regs->glpmcfg, ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, + lpmcfg.d32); + } + /** Change to L0 state*/ @@ -47798,8 +58412,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + + /* Restart the Phy Clock */ + pcgcctl.b.stoppclk = 1; -+ dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32, 0); -+ ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); + DWC_TIMER_SCHEDULE(core_if->wkp_timer, 71); + } else { + /** Change to L0 state*/ @@ -47810,14 +58423,432 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + /* Clear interrupt */ + 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; +} + -+/** ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * Device disconnect. ++ */ ++static int32_t dwc_otg_handle_pwrdn_disconnect_intr(dwc_otg_core_if_t *core_if) ++{ ++ gpwrdn_data_t gpwrdn = { .d32 = 0 }; ++ gpwrdn_data_t gpwrdn_temp = { .d32 = 0 }; ++ gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ DWC_PRINTF("%s called\n", __FUNCTION__); ++ ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps*/ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ if (gpwrdn_temp.b.idsts) { ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } else { ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++ ++ return 1; ++} ++ ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * remote wakeup sequence. ++ */ ++static int32_t dwc_otg_handle_pwrdn_wakeup_detected_intr(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ DWC_DEBUGPL(DBG_ANY, ++ "++Powerdown Remote Wakeup Detected Interrupt++\n"); ++ ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (gpwrdn.b.idsts) { // Device Mode ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ dwc_otg_device_hibernation_restore(core_if, 0, 0); ++ } ++ } else { ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ dwc_otg_host_hibernation_restore(core_if, 1, 0); ++ } ++ } ++ return 1; ++} ++ ++static int32_t dwc_otg_handle_pwrdn_idsts_change(dwc_otg_device_t *otg_dev) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn_temp = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if = otg_dev->core_if; ++ ++ DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); ++ gpwrdn_temp.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (core_if->power_down == 2) { ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ DWC_DEBUGPL(DBG_ANY, "Exit from hibernation on ID sts change\n"); ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /*Indicates that we are exiting from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ gpwrdn.d32 = core_if->gr_backup->gpwrdn_local; ++ if (gpwrdn.b.dis_vbus == 1) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ } ++ ++ if (gpwrdn_temp.b.idsts) { ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } else { ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ } ++ } ++ ++ if (core_if->adp_enable) { ++ uint8_t is_host = 0; ++ DWC_SPINUNLOCK(core_if->lock); ++ /* Change the core_if's lock to hcd/pcd lock depend on mode? */ ++#ifndef DWC_HOST_ONLY ++ if (gpwrdn_temp.b.idsts) ++ core_if->lock = otg_dev->pcd->lock; ++#endif ++#ifndef DWC_DEVICE_ONLY ++ if (!gpwrdn_temp.b.idsts) { ++ core_if->lock = otg_dev->hcd->lock; ++ is_host = 1; ++ } ++#endif ++ DWC_PRINTF("RESTART ADP\n"); ++ if (core_if->adp.probe_enabled) ++ dwc_otg_adp_probe_stop(core_if); ++ if (core_if->adp.sense_enabled) ++ dwc_otg_adp_sense_stop(core_if); ++ if (core_if->adp.sense_timer_started) ++ DWC_TIMER_CANCEL(core_if->adp.sense_timer); ++ if (core_if->adp.vbuson_timer_started) ++ DWC_TIMER_CANCEL(core_if->adp.vbuson_timer); ++ core_if->adp.probe_timer_values[0] = -1; ++ core_if->adp.probe_timer_values[1] = -1; ++ core_if->adp.sense_timer_started = 0; ++ core_if->adp.vbuson_timer_started = 0; ++ core_if->adp.probe_counter = 0; ++ core_if->adp.gpwrdn = 0; ++ ++ /* Disable PMU and restart ADP */ ++ gpwrdn_temp.d32 = 0; ++ gpwrdn_temp.b.pmuactv = 1; ++ gpwrdn_temp.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ DWC_PRINTF("Check point 1\n"); ++ dwc_mdelay(110); ++ dwc_otg_adp_start(core_if, is_host); ++ DWC_SPINLOCK(core_if->lock); ++ } ++ ++ ++ return 1; ++} ++ ++static int32_t dwc_otg_handle_pwrdn_session_change(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ int32_t otg_cap_param = core_if->core_params->otg_cap; ++ DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); ++ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (core_if->power_down == 2) { ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++ ++ if ((otg_cap_param != DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE || ++ otg_cap_param != DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) && ++ gpwrdn.b.bsessvld == 0) { ++ /* Save gpwrdn register for further usage if stschng interrupt */ ++ core_if->gr_backup->gpwrdn_local = ++ DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ /*Exit from ISR and wait for stschng interrupt with bsessvld = 1 */ ++ return 1; ++ } ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /*Indicates that we are exiting from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ ++ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE || ++ otg_cap_param == DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE) { ++ /* ++ * Initiate SRP after initial ADP probe. ++ */ ++ dwc_otg_initiate_srp(core_if); ++ } ++ } ++ ++ return 1; ++} ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * status change either on IDDIG or BSessVld. ++ */ ++static uint32_t dwc_otg_handle_pwrdn_stschng_intr(dwc_otg_device_t *otg_dev) ++{ ++ int retval; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn_temp = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if = otg_dev->core_if; ++ ++ DWC_PRINTF("%s called\n", __FUNCTION__); ++ ++ if (core_if->power_down == 2) { ++ if (core_if->hibernation_suspend <= 0) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } else ++ gpwrdn_temp.d32 = core_if->gr_backup->gpwrdn_local; ++ ++ } else { ++ gpwrdn_temp.d32 = core_if->adp.gpwrdn; ++ } ++ ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ if (gpwrdn.b.idsts ^ gpwrdn_temp.b.idsts) { ++ retval = dwc_otg_handle_pwrdn_idsts_change(otg_dev); ++ } else if (gpwrdn.b.bsessvld ^ gpwrdn_temp.b.bsessvld) { ++ retval = dwc_otg_handle_pwrdn_session_change(core_if); ++ } ++ ++ return retval; ++} ++ ++/** ++ * This interrupt indicates that the Wakeup Logic has detected a ++ * SRP. ++ */ ++static int32_t dwc_otg_handle_pwrdn_srp_intr(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ ++ DWC_PRINTF("%s called\n", __FUNCTION__); ++ ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return 1; ++ } ++#ifdef DWC_DEV_SRPCAP ++ if (core_if->pwron_timer_started) { ++ core_if->pwron_timer_started = 0; ++ DWC_TIMER_CANCEL(core_if->pwron_timer); ++ } ++#endif ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Indicates that we are exiting from hibernation */ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Programm Disable VBUS to 0 */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /*Initialize the core as Host */ ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++ ++ return 1; ++} ++ ++/** This interrupt indicates that restore command after Hibernation ++ * was completed by the core. */ ++int32_t dwc_otg_handle_restore_done_intr(dwc_otg_core_if_t * core_if) ++{ ++ pcgcctl_data_t pcgcctl; ++ DWC_DEBUGPL(DBG_ANY, "++Restore Done Interrupt++\n"); ++ ++ //TODO De-assert restore signal. 8.a ++ pcgcctl.d32 = DWC_READ_REG32(core_if->pcgcctl); ++ if (pcgcctl.b.restoremode == 1) { ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ /* ++ * If restore mode is Remote Wakeup, ++ * unmask Remote Wakeup interrupt. ++ */ ++ gintmsk.b.wkupintr = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, ++ 0, gintmsk.d32); ++ } ++ ++ return 1; ++} ++ ++/** + * This interrupt indicates that a device has been disconnected from -+ * the root port. ++ * the root port. + */ +int32_t dwc_otg_handle_disconnect_intr(dwc_otg_core_if_t * core_if) +{ @@ -47832,13 +58863,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + 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); ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_hcd_disconnect(core_if); ++ cil_pcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); + 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); ++ DWC_READ_REG32(&core_if->core_global_regs->gotgctl); + if (gotgctl.b.hstsethnpen == 1) { + /* Do nothing, if HNP in process the OTG + * interrupt "Host Negotiation Detected" @@ -47847,8 +58880,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + } else if (gotgctl.b.devhnpen == 0) { + /* If in device mode Disconnect and stop the HCD, then + * start the PCD. */ -+ hcd_disconnect(core_if); -+ pcd_start(core_if); ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_hcd_disconnect(core_if); ++ cil_pcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); + core_if->op_state = B_PERIPHERAL; + } else { + DWC_DEBUGPL(DBG_ANY, "!a_peripheral && !devhnpen\n"); @@ -47856,7 +58891,26 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + } else { + if (core_if->op_state == A_HOST) { + /* A-Cable still connected but device disconnected. */ -+ hcd_disconnect(core_if); ++ cil_hcd_disconnect(core_if); ++ if (core_if->adp_enable) { ++ gpwrdn_data_t gpwrdn = { .d32 = 0 }; ++ cil_hcd_stop(core_if); ++ /* Enable Power Down Logic */ ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_otg_adp_probe_start(core_if); ++ ++ /* Power off the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32 ++ (&core_if->core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ } ++ } + } + } +#endif @@ -47865,14 +58919,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + + 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; +} + +/** + * This interrupt indicates that SUSPEND state has been detected on + * the USB. -+ * ++ * + * For HNP the USB Suspend interrupt signals the change from + * "a_peripheral" to "a_host". + * @@ -47883,6 +58937,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo +{ + dsts_data_t dsts; + gintsts_data_t gintsts; ++ dcfg_data_t dcfg; + + DWC_DEBUGPL(DBG_ANY, "USB SUSPEND\n"); + @@ -47890,7 +58945,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + /* 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); ++ 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", @@ -47904,26 +58959,161 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + 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 { + DWC_DEBUGPL(DBG_ANY, "disconnect?\n"); + } +#endif -+ /* PCD callback for suspend. */ -+ pcd_suspend(core_if); ++ /* PCD callback for suspend. Release the lock inside of callback function */ ++ cil_pcd_suspend(core_if); ++ if (core_if->power_down == 2) ++ { ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ DWC_DEBUGPL(DBG_ANY,"lx_state = %08x\n",core_if->lx_state); ++ DWC_DEBUGPL(DBG_ANY," device address = %08d\n",dcfg.b.devaddr); ++ ++ if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++ ++ /* Change to L2(suspend) state */ ++ core_if->lx_state = DWC_OTG_L2; ++ ++ /* Clear interrupt in gintsts */ ++ gintsts.d32 = 0; ++ gintsts.b.usbsuspend = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, gintsts.d32); ++ DWC_PRINTF("Start of hibernation completed\n"); ++ dwc_otg_save_global_regs(core_if); ++ dwc_otg_save_dev_regs(core_if); ++ ++ gusbcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs-> ++ gusbcfg); ++ if (gusbcfg.b.ulpi_utmi_sel == 1) { ++ /* ULPI interface */ ++ /* Suspend the Phy Clock */ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ dwc_udelay(10); ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } else { ++ /* UTMI+ Interface */ ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ dwc_udelay(10); ++ } ++ ++ /* Set flag to indicate that we are in hibernation */ ++ core_if->hibernation_suspend = 1; ++ /* Enable interrupts from wake up logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Unmask device mode interrupts in GPWRDN */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.rst_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ gpwrdn.b.sts_chngint_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Enable Power Down Clamp */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Switch off VDD */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++ /* Save gpwrdn register for further usage if stschng interrupt */ ++ core_if->gr_backup->gpwrdn_local = ++ DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ DWC_PRINTF("Hibernation completed\n"); ++ ++ return 1; ++ } ++ } else if (core_if->power_down == 3) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg); ++ DWC_DEBUGPL(DBG_ANY, "lx_state = %08x\n",core_if->lx_state); ++ DWC_DEBUGPL(DBG_ANY, " device address = %08d\n",dcfg.b.devaddr); ++ ++ if (core_if->lx_state != DWC_OTG_L3 && dcfg.b.devaddr) { ++ DWC_DEBUGPL(DBG_ANY, "Start entering to extended hibernation\n"); ++ core_if->xhib = 1; ++ ++ /* Clear interrupt in gintsts */ ++ gintsts.d32 = 0; ++ gintsts.b.usbsuspend = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, gintsts.d32); ++ ++ dwc_otg_save_global_regs(core_if); ++ dwc_otg_save_dev_regs(core_if); ++ ++ /* Wait for 10 PHY clocks */ ++ dwc_udelay(10); ++ ++ /* Program GPIO register while entering to xHib */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x1); ++ ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.extnd_hiber_pwrclmp = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.extnd_hiber_switch = 1; ++ core_if->gr_backup->xhib_gpwrdn = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ core_if->gr_backup->xhib_pcgcctl = DWC_READ_REG32(core_if->pcgcctl) | pcgcctl.d32; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ ++ DWC_DEBUGPL(DBG_ANY, "Finished entering to extended hibernation\n"); ++ ++ return 1; ++ } ++ } + } else { + 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); ++ DWC_SPINUNLOCK(core_if->lock); ++ cil_pcd_stop(core_if); ++ cil_hcd_start(core_if); ++ DWC_SPINLOCK(core_if->lock); + core_if->op_state = A_HOST; + } + } @@ -47934,7 +59124,71 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + /* Clear interrupt */ + 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; ++} ++ ++static int32_t dwc_otg_handle_xhib_exit_intr(dwc_otg_core_if_t * core_if) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gahbcfg_data_t gahbcfg = {.d32 = 0 }; ++ ++ dwc_udelay(10); ++ ++ /* Program GPIO register while entering to xHib */ ++ DWC_WRITE_REG32(&core_if->core_global_regs->ggpio, 0x0); ++ ++ pcgcctl.d32 = core_if->gr_backup->xhib_pcgcctl; ++ pcgcctl.b.extnd_hiber_pwrclmp = 0; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ dwc_udelay(10); ++ ++ gpwrdn.d32 = core_if->gr_backup->xhib_gpwrdn; ++ gpwrdn.b.restore = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ restore_lpm_i2c_regs(core_if); ++ ++ pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14); ++ pcgcctl.b.max_xcvrselect = 1; ++ pcgcctl.b.ess_reg_restored = 0; ++ pcgcctl.b.extnd_hiber_switch = 0; ++ pcgcctl.b.extnd_hiber_pwrclmp = 0; ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ ++ gahbcfg.d32 = core_if->gr_backup->gahbcfg_local; ++ gahbcfg.b.glblintrmsk = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gahbcfg, gahbcfg.d32); ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, 0xFFFFFFFF); ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, 0x1 << 16); ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, ++ core_if->gr_backup->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, ++ core_if->dr_backup->dcfg); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14); ++ pcgcctl.b.max_xcvrselect = 1; ++ pcgcctl.d32 |= 0x608; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ dwc_udelay(10); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.d32 = core_if->gr_backup->pcgcctl_local & (0x3FFFF << 14); ++ pcgcctl.b.max_xcvrselect = 1; ++ pcgcctl.b.ess_reg_restored = 1; ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ pcgcctl.b.rstpdwnmodule = 1; ++ pcgcctl.b.restoremode = 1; ++ DWC_WRITE_REG32(core_if->pcgcctl, pcgcctl.d32); ++ ++ DWC_DEBUGPL(DBG_ANY, "%s called\n", __FUNCTION__); + + return 1; +} @@ -47952,20 +59206,20 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + DWC_PRINTF("Unexpected LPM interrupt\n"); + } + -+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); + DWC_PRINTF("LPM config register = 0x%08x\n", lpmcfg.d32); + + if (dwc_otg_is_host_mode(core_if)) { -+ hcd_sleep(core_if); ++ cil_hcd_sleep(core_if); + } else { + lpmcfg.b.hird_thres |= (1 << 4); -+ dwc_write_reg32(&core_if->core_global_regs->glpmcfg, ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, + lpmcfg.d32); + } + -+ /* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */ ++ /* Examine prt_sleep_sts after TL1TokenTetry period max (10 us) */ + dwc_udelay(10); -+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); + if (lpmcfg.b.prt_sleep_sts) { + /* Save the current state */ + core_if->lx_state = DWC_OTG_L1; @@ -47974,16 +59228,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + /* Clear interrupt */ + gintsts.d32 = 0; + gintsts.b.lpmtranrcvd = 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; +} -+#endif /* CONFIG_USB_DWC_OTG_LPM */ ++#endif /* CONFIG_USB_DWC_OTG_LPM */ + +/** + * This function returns the Core Interrupt register. + */ +static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if) +{ ++ gahbcfg_data_t gahbcfg = {.d32 = 0 }; + gintsts_data_t gintsts; + gintmsk_data_t gintmsk; + gintmsk_data_t gintmsk_common = {.d32 = 0 }; @@ -47997,13 +59252,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo +#ifdef CONFIG_USB_DWC_OTG_LPM + gintmsk_common.b.lpmtranrcvd = 1; +#endif -+ /** @todo: The port interrupt occurs while in device -+ * mode. Added code to CIL to clear the interrupt for now! ++ gintmsk_common.b.restoredone = 1; ++ /** @todo: The port interrupt occurs while in device ++ * mode. Added code to CIL to clear the interrupt for now! + */ + 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); ++ gahbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gahbcfg); ++ +#ifdef DEBUG + /* if any common interrupts set */ + if (gintsts.d32 & gintmsk_common.d32) { @@ -48011,15 +59269,31 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + gintsts.d32, gintmsk.d32); + } +#endif -+ -+ return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32); ++ if (!fiq_fix_enable){ ++ if (gahbcfg.b.glblintrmsk) ++ return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32); ++ else ++ return 0; ++ } ++ else { ++ return ((gintsts.d32 & gintmsk.d32) & gintmsk_common.d32); ++ } + +} + ++/* MACRO for clearing interupt bits in GPWRDN register */ ++#define CLEAR_GPWRDN_INTR(__core_if,__intr) \ ++do { \ ++ gpwrdn_data_t gpwrdn = {.d32=0}; \ ++ gpwrdn.b.__intr = 1; \ ++ DWC_MODIFY_REG32(&__core_if->core_global_regs->gpwrdn, \ ++ 0, gpwrdn.d32); \ ++} while (0) ++ +/** + * Common interrupt handler. + * -+ * The common interrupts are those that occur in both Host and Device mode. ++ * The common interrupts are those that occur in both Host and Device mode. + * This handler handles the following interrupts: + * - Mode Mismatch Interrupt + * - Disconnect Interrupt @@ -48027,65 +59301,200 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c linux-rpi-bo + * - Connector ID Status Change Interrupt + * - Session Request Interrupt. + * - Resume / Remote Wakeup Detected Interrupt. -+ * - LPM Transaction Received Interrutp -+ * ++ * - LPM Transaction Received Interrupt ++ * - ADP Transaction Received Interrupt ++ * + */ -+int32_t dwc_otg_handle_common_intr(dwc_otg_core_if_t * core_if) ++int32_t dwc_otg_handle_common_intr(void *dev) +{ + int retval = 0; + gintsts_data_t gintsts; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ dwc_otg_device_t *otg_dev = dev; ++ dwc_otg_core_if_t *core_if = otg_dev->core_if; ++ gpwrdn.d32 = DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ if (dwc_otg_is_device_mode(core_if)) ++ core_if->frame_num = dwc_otg_get_frame_number(core_if); ++ ++ if (core_if->lock) ++ DWC_SPINLOCK(core_if->lock); + -+ gintsts.d32 = dwc_otg_read_common_intr(core_if); ++ if (core_if->power_down == 3 && core_if->xhib == 1) { ++ DWC_DEBUGPL(DBG_ANY, "Exiting from xHIB state\n"); ++ retval |= dwc_otg_handle_xhib_exit_intr(core_if); ++ core_if->xhib = 2; ++ if (core_if->lock) ++ DWC_SPINUNLOCK(core_if->lock); + -+ if (gintsts.b.modemismatch) { -+ retval |= dwc_otg_handle_mode_mismatch_intr(core_if); -+ } -+ if (gintsts.b.otgintr) { -+ retval |= dwc_otg_handle_otg_intr(core_if); -+ } -+ if (gintsts.b.conidstschng) { -+ retval |= dwc_otg_handle_conn_id_status_change_intr(core_if); -+ } -+ if (gintsts.b.disconnect) { -+ retval |= dwc_otg_handle_disconnect_intr(core_if); -+ } -+ if (gintsts.b.sessreqintr) { -+ retval |= dwc_otg_handle_session_req_intr(core_if); -+ } -+ if (gintsts.b.wkupintr) { -+ retval |= dwc_otg_handle_wakeup_detected_intr(core_if); -+ } -+ if (gintsts.b.usbsuspend) { -+ retval |= dwc_otg_handle_usb_suspend_intr(core_if); ++ return retval; + } ++ ++ if (core_if->hibernation_suspend <= 0) { ++ gintsts.d32 = dwc_otg_read_common_intr(core_if); ++ ++ if (gintsts.b.modemismatch) { ++ retval |= dwc_otg_handle_mode_mismatch_intr(core_if); ++ } ++ if (gintsts.b.otgintr) { ++ retval |= dwc_otg_handle_otg_intr(core_if); ++ } ++ if (gintsts.b.conidstschng) { ++ retval |= ++ dwc_otg_handle_conn_id_status_change_intr(core_if); ++ } ++ if (gintsts.b.disconnect) { ++ retval |= dwc_otg_handle_disconnect_intr(core_if); ++ } ++ if (gintsts.b.sessreqintr) { ++ retval |= dwc_otg_handle_session_req_intr(core_if); ++ } ++ if (gintsts.b.wkupintr) { ++ retval |= dwc_otg_handle_wakeup_detected_intr(core_if); ++ } ++ if (gintsts.b.usbsuspend) { ++ retval |= dwc_otg_handle_usb_suspend_intr(core_if); ++ } +#ifdef CONFIG_USB_DWC_OTG_LPM -+ if (gintsts.b.lpmtranrcvd) { -+ retval |= dwc_otg_handle_lpm_intr(core_if); -+ } ++ if (gintsts.b.lpmtranrcvd) { ++ retval |= dwc_otg_handle_lpm_intr(core_if); ++ } +#endif ++ if (gintsts.b.restoredone) { ++ gintsts.d32 = 0; ++ if (core_if->power_down == 2) ++ core_if->hibernation_suspend = -1; ++ else if (core_if->power_down == 3 && core_if->xhib == 2) { ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; + -+ if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) { -+ /* The port interrupt occurs while in device mode with HPRT0 -+ * Port Enable/Disable. -+ */ -+ gintsts.d32 = 0; -+ gintsts.b.portintr = 1; -+ dwc_write_reg32(&core_if->core_global_regs->gintsts, -+ gintsts.d32); -+ retval |= 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs-> ++ gintsts, 0xFFFFFFFF); + ++ DWC_DEBUGPL(DBG_ANY, ++ "RESTORE DONE generated\n"); ++ ++ gpwrdn.b.restore = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ pcgcctl.b.rstpdwnmodule = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ ++ DWC_WRITE_REG32(&core_if->core_global_regs->gusbcfg, core_if->gr_backup->gusbcfg_local); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, core_if->dr_backup->dcfg); ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, core_if->dr_backup->dctl); ++ dwc_udelay(50); ++ ++ dctl.b.pwronprgdone = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ dwc_udelay(10); ++ ++ dwc_otg_restore_global_regs(core_if); ++ dwc_otg_restore_dev_regs(core_if, 0); ++ ++ dctl.d32 = 0; ++ dctl.b.pwronprgdone = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, 0); ++ dwc_udelay(10); ++ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.enbl_extnd_hiber = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ ++ /* The core will be in ON STATE */ ++ core_if->lx_state = DWC_OTG_L0; ++ core_if->xhib = 0; ++ ++ DWC_SPINUNLOCK(core_if->lock); ++ if (core_if->pcd_cb && core_if->pcd_cb->resume_wakeup) { ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); ++ } ++ DWC_SPINLOCK(core_if->lock); ++ ++ } ++ ++ gintsts.b.restoredone = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32); ++ DWC_PRINTF(" --Restore done interrupt received-- \n"); ++ retval |= 1; ++ } ++ if (gintsts.b.portintr && dwc_otg_is_device_mode(core_if)) { ++ /* The port interrupt occurs while in device mode with HPRT0 ++ * Port Enable/Disable. ++ */ ++ gintsts.d32 = 0; ++ gintsts.b.portintr = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts,gintsts.d32); ++ retval |= 1; ++ ++ } ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "gpwrdn=%08x\n", gpwrdn.d32); ++ ++ if (gpwrdn.b.disconn_det && gpwrdn.b.disconn_det_msk) { ++ CLEAR_GPWRDN_INTR(core_if, disconn_det); ++ if (gpwrdn.b.linestate == 0) { ++ dwc_otg_handle_pwrdn_disconnect_intr(core_if); ++ } else { ++ DWC_PRINTF("Disconnect detected while linestate is not 0\n"); ++ } ++ ++ retval |= 1; ++ } ++ if (gpwrdn.b.lnstschng && gpwrdn.b.lnstchng_msk) { ++ CLEAR_GPWRDN_INTR(core_if, lnstschng); ++ /* remote wakeup from hibernation */ ++ if (gpwrdn.b.linestate == 2 || gpwrdn.b.linestate == 1) { ++ dwc_otg_handle_pwrdn_wakeup_detected_intr(core_if); ++ } else { ++ DWC_PRINTF("gpwrdn.linestate = %d\n", gpwrdn.b.linestate); ++ } ++ retval |= 1; ++ } ++ if (gpwrdn.b.rst_det && gpwrdn.b.rst_det_msk) { ++ CLEAR_GPWRDN_INTR(core_if, rst_det); ++ if (gpwrdn.b.linestate == 0) { ++ DWC_PRINTF("Reset detected\n"); ++ retval |= dwc_otg_device_hibernation_restore(core_if, 0, 1); ++ } ++ } ++ if (gpwrdn.b.srp_det && gpwrdn.b.srp_det_msk) { ++ CLEAR_GPWRDN_INTR(core_if, srp_det); ++ dwc_otg_handle_pwrdn_srp_intr(core_if); ++ retval |= 1; ++ } + } ++ /* Handle ADP interrupt here */ ++ if (gpwrdn.b.adp_int) { ++ DWC_PRINTF("ADP interrupt\n"); ++ CLEAR_GPWRDN_INTR(core_if, adp_int); ++ dwc_otg_adp_handle_intr(core_if); ++ retval |= 1; ++ } ++ if (gpwrdn.b.sts_chngint && gpwrdn.b.sts_chngint_msk) { ++ DWC_PRINTF("STS CHNG interrupt asserted\n"); ++ CLEAR_GPWRDN_INTR(core_if, sts_chngint); ++ dwc_otg_handle_pwrdn_stschng_intr(otg_dev); ++ ++ retval |= 1; ++ } ++ if (core_if->lock) ++ DWC_SPINUNLOCK(core_if->lock); ++ + return retval; +} -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_core_if.h ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_core_if.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_core_if.h 2012-07-15 20:29:19.140084674 +0200 -@@ -0,0 +1,642 @@ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_core_if.h b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h +new file mode 100644 +index 0000000..10b68c4 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_core_if.h +@@ -0,0 +1,705 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $ -+ * $Revision: #4 $ -+ * $Date: 2008/12/18 $ -+ * $Change: 1155299 $ ++ * $Revision: #13 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ + * + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless @@ -48146,7 +59555,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-rpi-boo +extern uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t * core_if); + +/** This function should be called on every hardware interrupt. */ -+extern int32_t dwc_otg_handle_common_intr(dwc_otg_core_if_t * _core_if); ++extern int32_t dwc_otg_handle_common_intr(void *otg_dev); + +/** @name OTG Core Parameters */ +/** @{ */ @@ -48351,7 +59760,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-rpi-boo + int32_t val); +extern int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t * core_if); +//#define dwc_param_host_channels_default 12 -+#define dwc_param_host_channels_default 8// Broadcom BCM2708 ++#define dwc_param_host_channels_default 8 // Broadcom BCM2708 + +/** The number of endpoints in addition to EP0 available for device + * mode operations. @@ -48380,7 +59789,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-rpi-boo +#define dwc_param_phy_type_default DWC_PHY_TYPE_PARAM_UTMI + +/** -+ * Specifies the UTMI+ Data Width. This parameter is ++ * Specifies the UTMI+ Data Width. This parameter is + * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI + * PHY_TYPE, this parameter indicates the data width between + * the MAC and the ULPI Wrapper.) Also, this parameter is @@ -48462,7 +59871,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-rpi-boo + int fifo_num, int32_t val); +extern int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t * core_if, + int fifo_num); -+#define dwc_param_dev_tx_fifo_size_default 256 ++#define dwc_param_dev_tx_fifo_size_default 768 + +/** Thresholding enable flag- + * bit 0 - enable non-ISO Tx thresholding @@ -48514,17 +59923,56 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-rpi-boo +#define dwc_param_mpi_enable_default 0 + +/** ++ * Specifies whether ADP capability is enabled ++ */ ++extern int dwc_otg_set_param_adp_enable(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_adp_enable(dwc_otg_core_if_t * core_if); ++#define dwc_param_adp_enable_default 0 ++ ++/** + * Specifies whether IC_USB capability is enabled + */ ++ +extern int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t * core_if, + int32_t val); +extern int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t * core_if); +#define dwc_param_ic_usb_cap_default 0 + -+extern int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if, int32_t val); ++extern int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if, ++ int32_t val); +extern int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t * core_if); +#define dwc_param_ahb_thr_ratio_default 0 + ++extern int dwc_otg_set_param_power_down(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_power_down(dwc_otg_core_if_t * core_if); ++#define dwc_param_power_down_default 0 ++ ++extern int dwc_otg_set_param_reload_ctl(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_reload_ctl(dwc_otg_core_if_t * core_if); ++#define dwc_param_reload_ctl_default 0 ++ ++extern int dwc_otg_set_param_dev_out_nak(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_dev_out_nak(dwc_otg_core_if_t * core_if); ++#define dwc_param_dev_out_nak_default 0 ++ ++extern int dwc_otg_set_param_cont_on_bna(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_cont_on_bna(dwc_otg_core_if_t * core_if); ++#define dwc_param_cont_on_bna_default 0 ++ ++extern int dwc_otg_set_param_ahb_single(dwc_otg_core_if_t * core_if, ++ int32_t val); ++extern int32_t dwc_otg_get_param_ahb_single(dwc_otg_core_if_t * core_if); ++#define dwc_param_ahb_single_default 0 ++ ++extern int dwc_otg_set_param_otg_ver(dwc_otg_core_if_t * core_if, int32_t val); ++extern int32_t dwc_otg_get_param_otg_ver(dwc_otg_core_if_t * core_if); ++#define dwc_param_otg_ver_default 0 ++ +/** @} */ + +/** @name Access to registers and bit-fields */ @@ -48604,6 +60052,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-rpi-boo + * Get value of prtpwr field from the HPRT0 register + */ +extern uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t * core_if); ++ ++/** ++ * Get value of flag indicating core state - hibernated or not ++ */ ++extern uint32_t dwc_otg_get_core_state(dwc_otg_core_if_t * core_if); ++ +/** + * Set value of prtpwr field from the HPRT0 register + */ @@ -48619,6 +60073,24 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-rpi-boo +extern void dwc_otg_set_prtsuspend(dwc_otg_core_if_t * core_if, uint32_t val); + +/** ++ * Get value of ModeChTimEn field from the HCFG regsiter ++ */ ++extern uint32_t dwc_otg_get_mode_ch_tim(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of ModeChTimEn field from the HCFG regsiter ++ */ ++extern void dwc_otg_set_mode_ch_tim(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** ++ * Get value of Fram Interval field from the HFIR regsiter ++ */ ++extern uint32_t dwc_otg_get_fr_interval(dwc_otg_core_if_t * core_if); ++/** ++ * Set value of Frame Interval field from the HFIR regsiter ++ */ ++extern void dwc_otg_set_fr_interval(dwc_otg_core_if_t * core_if, uint32_t val); ++ ++/** + * Set value of prtres field from the HPRT0 register + *FIXME Remove? + */ @@ -48723,10 +60195,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_core_if.h linux-rpi-boo +/** @} */ + +#endif /* __DWC_CORE_IF_H__ */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_dbg.h linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_dbg.h ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_dbg.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_dbg.h 2012-07-15 20:29:19.197085746 +0200 -@@ -0,0 +1,113 @@ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_dbg.h b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h +new file mode 100644 +index 0000000..2ff1532 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_dbg.h +@@ -0,0 +1,117 @@ +/* ========================================================================== + * + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, @@ -48778,6 +60252,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_dbg.h linux-rpi-bootc-3 + return old; +} + ++#define DBG_USER (0x1) +/** When debug level has the DBG_CIL bit set, display CIL Debug messages. */ +#define DBG_CIL (0x2) +/** When debug level has the DBG_CILV bit set, display CIL Verbose debug @@ -48797,6 +60272,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_dbg.h linux-rpi-bootc-3 +/** When debug level has the DBG_HCD_URB bit set, display enqueued URBs in host + * mode. */ +#define DBG_HCD_URB (0x800) ++/** When debug level has the DBG_HCDI bit set, display host interrupt ++ * messages. */ ++#define DBG_HCDI (0x1000) + +/** When debug level has any bit set, display debug messages */ +#define DBG_ANY (0xFF) @@ -48840,15 +60318,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_dbg.h linux-rpi-bootc-3 + +#endif /*DEBUG*/ +#endif -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c 2012-07-15 20:29:19.058083099 +0200 -@@ -0,0 +1,1726 @@ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c +new file mode 100644 +index 0000000..b618f4b +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c +@@ -0,0 +1,1727 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $ -+ * $Revision: #76 $ -+ * $Date: 2009/05/03 $ -+ * $Change: 1245589 $ ++ * $Revision: #92 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ + * + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless @@ -48894,48 +60374,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + * device. + */ + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include /* permission constants */ -+#include -+#include -+ -+#ifdef LM_INTERFACE -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+#include -+#include -+#else -+/* in 2.6.31, at least, we seem to have lost the generic LM infrastructure - -+ here we use definitions stolen from arm-integrator headers -+*/ -+#include -+#include -+#endif -+#include -+#include -+ -+#elif defined(PLATFORM_INTERFACE) -+ -+#include -+#include -+ -+#endif -+ -+# include -+ -+#ifdef SOF_FIX -+#include -+#include -+#endif -+ -+#include -+ -+ ++#include "dwc_otg_os_dep.h" +#include "dwc_os.h" +#include "dwc_otg_dbg.h" +#include "dwc_otg_driver.h" @@ -48944,49 +60383,55 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot +#include "dwc_otg_pcd_if.h" +#include "dwc_otg_hcd_if.h" + -+#define DWC_DRIVER_VERSION "2.90b 6-MAY-2010" ++#define DWC_DRIVER_VERSION "3.00a 10-AUG-2012" +#define DWC_DRIVER_DESC "HS OTG USB Controller driver" + ++bool microframe_schedule=true; ++ +static const char dwc_driver_name[] = "dwc_otg"; + ++extern void* dummy_send; ++ +extern int pcd_init( +#ifdef LM_INTERFACE -+ struct lm_device *_dev ++ struct lm_device *_dev +#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev ++ struct pci_dev *_dev +#elif defined(PLATFORM_INTERFACE) + struct platform_device *dev +#endif -+ ); ++ ); +extern int hcd_init( +#ifdef LM_INTERFACE -+ struct lm_device *_dev ++ struct lm_device *_dev +#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev ++ struct pci_dev *_dev +#elif defined(PLATFORM_INTERFACE) + struct platform_device *dev +#endif -+ ); ++ ); + +extern int pcd_remove( +#ifdef LM_INTERFACE -+ struct lm_device *_dev ++ struct lm_device *_dev +#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev ++ struct pci_dev *_dev +#elif defined(PLATFORM_INTERFACE) + struct platform_device *_dev +#endif -+ ); ++ ); + +extern void hcd_remove( +#ifdef LM_INTERFACE -+ struct lm_device *_dev ++ struct lm_device *_dev +#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev ++ struct pci_dev *_dev +#elif defined(PLATFORM_INTERFACE) + struct platform_device *_dev +#endif -+ ); ++ ); ++ ++extern void dwc_otg_adp_start(dwc_otg_core_if_t * core_if, uint8_t is_host); + +/*-------------------------------------------------------------------------*/ +/* Encapsulate the module parameter settings */ @@ -49029,8 +60474,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + int32_t lpm_enable; + int32_t ic_usb_cap; + int32_t ahb_thr_ratio; -+ int32_t sof_setting; // 0=off, 1=on -+ int32_t proc_init_done; // 0=not done, 1=done ++ int32_t power_down; ++ int32_t reload_ctl; ++ int32_t dev_out_nak; ++ int32_t cont_on_bna; ++ int32_t ahb_single; ++ int32_t otg_ver; ++ int32_t adp_enable; +}; + +static struct dwc_otg_driver_module_params dwc_otg_module_params = { @@ -49107,136 +60557,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + .lpm_enable = -1, + .ic_usb_cap = -1, + .ahb_thr_ratio = -1, -+ .sof_setting = 0, -+ .proc_init_done = 0, ++ .power_down = -1, ++ .reload_ctl = -1, ++ .dev_out_nak = -1, ++ .cont_on_bna = -1, ++ .ahb_single = -1, ++ .otg_ver = -1, ++ .adp_enable = -1, +}; + -+/** -+ * PROC_FS SUPPORT -+ * proc_fs support for setting the Start-of-Frame (SOF) interrupt processing -+ * fix (reducing SOF interrupts by an order of magnitude). When set -+ * to "on" the SOF interrupt will only be turned on once per tick, for -+ * 3 micro-frame times. When set to "off" it will not turn off the -+ * SOF interrupt, and process all 8000 per second. -+ */ -+ -+#ifdef SOF_FIX -+ -+static struct proc_dir_entry *proc_dir, *proc_file; -+ -+int sof_setting(void) -+{ -+ return dwc_otg_module_params.sof_setting; -+} -+ -+static int sof_read_data (char *page, -+ char **start, -+ off_t off, -+ int count, -+ int *eof, -+ void *data) -+{ -+ -+ if (dwc_otg_module_params.sof_setting == 1) -+ { -+ sprintf(page, "on\n"); -+ return 4; -+ } -+ else -+ { -+ sprintf(page, "off\n"); -+ return 5; -+ } -+ return 0; -+} -+ -+#define PROC_FS_MAX_SIZE 1024 -+#define PROC_FS_NAME "SOF_reduction" -+ -+static char proc_fs_buffer[PROC_FS_MAX_SIZE]; -+ -+static int sof_write_data (struct file *file, -+ const char __user *buffer, -+ unsigned long count, -+ void *data) -+{ -+ unsigned long buffer_size = count; -+ -+ if (buffer_size > PROC_FS_MAX_SIZE) -+ buffer_size = PROC_FS_MAX_SIZE; -+ -+ memset(proc_fs_buffer, 0, sizeof(proc_fs_buffer)); -+ -+ if (copy_from_user(proc_fs_buffer, buffer, buffer_size)) -+ { -+ printk(KERN_ERR "\nSOF_write_data: copy_from_user failure\n"); -+ return -EFAULT; -+ } -+ -+ if ((strnlen(proc_fs_buffer, PROC_FS_MAX_SIZE) == 3) && -+ (strncmp(proc_fs_buffer, "on", 2) == 0)) -+ { -+ printk(KERN_ERR "\n%s: Setting SOF (reduction) ON.\n", PROC_FS_NAME); -+ dwc_otg_module_params.sof_setting = 1; -+ } -+ else if ((strnlen(proc_fs_buffer, PROC_FS_MAX_SIZE) == 4) && -+ (strncmp(proc_fs_buffer, "off", 3) == 0)) -+ { -+ printk(KERN_ERR "\n%s: Setting SOF reduction OFF.\n",PROC_FS_NAME); -+ dwc_otg_module_params.sof_setting = 0; -+ } -+ else -+ printk(KERN_ERR "\n%s: input not \'on\' or \'off\', ignored.\n", PROC_FS_NAME); -+#ifdef DEBUG_SOF_FIX -+ printk(KERN_ERR "\n%s:buffer %s, len = %d.\n",__func__, -+ proc_fs_buffer, strnlen(proc_fs_buffer, PROC_FS_MAX_SIZE)); -+#endif -+ -+ return buffer_size; -+} -+ -+/** -+ * Initialize proc_fs entry for SOF setting. -+ */ -+static int init_proc_fs(void) -+{ -+ int retval = 0; -+ -+ if (dwc_otg_module_params.proc_init_done) -+ return 0; -+ -+ proc_dir = proc_mkdir_mode("dwc_sof", 0755, NULL); -+ -+ if(proc_dir == NULL) -+ { -+ retval = -ENOMEM; -+ printk("Error creating dir\n"); -+ return retval; -+ } -+ -+ proc_file = create_proc_entry(PROC_FS_NAME, 0666, proc_dir); -+ -+ if (proc_file != NULL) -+ { -+ dwc_otg_module_params.proc_init_done = 1; -+ proc_file->read_proc = sof_read_data; -+ proc_file->write_proc = sof_write_data; -+ proc_file->mode = S_IFREG | S_IRUGO; -+ proc_file->uid = 0; -+ proc_file->gid = 0; -+ proc_file->gid = PROC_FS_MAX_SIZE; -+ } -+ else -+ { -+ retval = -ENOMEM; -+ printk("Error creating file\n"); -+ remove_proc_entry(PROC_FS_NAME, NULL); -+ } -+ -+ return retval; -+} -+ -+#endif ++//Global variable to switch the fiq fix on or off ++bool fiq_fix_enable = false; + + +/** @@ -49419,7 +60750,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + } + if (dwc_otg_module_params.ulpi_fs_ls != -1) { + retval += -+ dwc_otg_set_param_ulpi_fs_ls(core_if, dwc_otg_module_params.ulpi_fs_ls); ++ dwc_otg_set_param_ulpi_fs_ls(core_if, ++ dwc_otg_module_params.ulpi_fs_ls); + } + if (dwc_otg_module_params.ts_dline != -1) { + retval += @@ -49496,9 +60828,50 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + dwc_otg_module_params. + rx_thr_length); + } -+ if(dwc_otg_module_params.ahb_thr_ratio != -1) { ++ if (dwc_otg_module_params.ahb_thr_ratio != -1) { + retval += -+ dwc_otg_set_param_ahb_thr_ratio(core_if, dwc_otg_module_params.ahb_thr_ratio); ++ dwc_otg_set_param_ahb_thr_ratio(core_if, ++ dwc_otg_module_params.ahb_thr_ratio); ++ } ++ if (dwc_otg_module_params.power_down != -1) { ++ retval += ++ dwc_otg_set_param_power_down(core_if, ++ dwc_otg_module_params.power_down); ++ } ++ if (dwc_otg_module_params.reload_ctl != -1) { ++ retval += ++ dwc_otg_set_param_reload_ctl(core_if, ++ dwc_otg_module_params.reload_ctl); ++ } ++ ++ if (dwc_otg_module_params.dev_out_nak != -1) { ++ retval += ++ dwc_otg_set_param_dev_out_nak(core_if, ++ dwc_otg_module_params.dev_out_nak); ++ } ++ ++ if (dwc_otg_module_params.cont_on_bna != -1) { ++ retval += ++ dwc_otg_set_param_cont_on_bna(core_if, ++ dwc_otg_module_params.cont_on_bna); ++ } ++ ++ if (dwc_otg_module_params.ahb_single != -1) { ++ retval += ++ dwc_otg_set_param_ahb_single(core_if, ++ dwc_otg_module_params.ahb_single); ++ } ++ ++ if (dwc_otg_module_params.otg_ver != -1) { ++ retval += ++ dwc_otg_set_param_otg_ver(core_if, ++ dwc_otg_module_params.otg_ver); ++ } ++ if (dwc_otg_module_params.adp_enable != -1) { ++ retval += ++ dwc_otg_set_param_adp_enable(core_if, ++ dwc_otg_module_params. ++ adp_enable); + } + return retval; +} @@ -49509,10 +60882,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + */ +static irqreturn_t dwc_otg_common_irq(int irq, void *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(dev); + if (retval != 0) { + S3C2410X_CLEAR_EINTPEND(); + } @@ -49529,54 +60901,41 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + * @param _dev + */ +#ifdef LM_INTERFACE -+static void dwc_otg_driver_remove( -+ struct lm_device *_dev ++#define REM_RETVAL(n) ++static void dwc_otg_driver_remove( struct lm_device *_dev ) ++{ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); +#elif defined(PCI_INTERFACE) -+static void dwc_otg_driver_remove( -+ struct pci_dev *_dev ++#define REM_RETVAL(n) ++static void dwc_otg_driver_remove( struct pci_dev *_dev ) ++{ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); +#elif defined(PLATFORM_INTERFACE) -+static int dwc_otg_driver_remove( -+ struct platform_device *_dev ++#define REM_RETVAL(n) n ++static int dwc_otg_driver_remove( struct platform_device *_dev ) ++{ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); +#endif -+) -+ -+{ -+#ifdef LM_INTERFACE -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); -+#endif -+ + + DWC_DEBUGPL(DBG_ANY, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev); + + if (!otg_dev) { + /* Memory allocation for the dwc_otg_device failed. */ + DWC_DEBUGPL(DBG_ANY, "%s: otg_dev NULL!\n", __func__); -+#ifdef PLATFORM_INTERFACE -+ return -ENOMEM; -+#else -+ return; -+#endif ++ return REM_RETVAL(-ENOMEM); + } +#ifndef DWC_DEVICE_ONLY + if (otg_dev->hcd) { + hcd_remove(_dev); + } else { + DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->hcd NULL!\n", __func__); -+#ifdef PLATFORM_INTERFACE -+ return -EINVAL; -+#else -+ return; -+#endif ++ return REM_RETVAL(-EINVAL); + } +#endif + +#ifndef DWC_HOST_ONLY + if (otg_dev->pcd) { + pcd_remove(_dev); ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->pcd NULL!\n", __func__); ++ return REM_RETVAL(-EINVAL); + } +#endif + /* @@ -49588,10 +60947,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot +#else + free_irq(_dev->irq, otg_dev); +#endif -+ } ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "%s: There is no installed irq!\n", __func__); ++ return REM_RETVAL(-ENXIO); ++ } + + if (otg_dev->core_if) { + dwc_otg_cil_remove(otg_dev->core_if); ++ } else { ++ DWC_DEBUGPL(DBG_ANY, "%s: otg_dev->core_if NULL!\n", __func__); ++ return REM_RETVAL(-ENXIO); + } + + /* @@ -49602,23 +60967,24 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + /* + * Return the memory. + */ -+ if (otg_dev->base) { -+ iounmap(otg_dev->base); ++ if (otg_dev->os_dep.base) { ++ iounmap(otg_dev->os_dep.base); + } -+ dwc_free(otg_dev); ++ DWC_FREE(otg_dev); + + /* + * Clear the drvdata pointer. + */ +#ifdef LM_INTERFACE + lm_set_drvdata(_dev, 0); -+#elif defined(PCI_INTERFACE) -+ release_mem_region(otg_dev->rsrc_start, otg_dev->rsrc_len); -+ pci_set_drvdata(_dev, 0); ++#elif defined(PCI_INTERFACE) ++ release_mem_region(otg_dev->os_dep.rsrc_start, ++ otg_dev->os_dep.rsrc_len); ++ pci_set_drvdata(_dev, 0); +#elif defined(PLATFORM_INTERFACE) + platform_set_drvdata(_dev, 0); -+ return 0; +#endif ++ return REM_RETVAL(0); +} + +/** @@ -49634,13 +61000,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + */ +static int dwc_otg_driver_probe( +#ifdef LM_INTERFACE -+struct lm_device *_dev -+#elif defined(PCI_INTERFACE) -+struct pci_dev *_dev, const struct pci_device_id *id ++ struct lm_device *_dev ++#elif defined(PCI_INTERFACE) ++ struct pci_dev *_dev, ++ const struct pci_device_id *id +#elif defined(PLATFORM_INTERFACE) -+struct platform_device *_dev ++ struct platform_device *_dev +#endif -+) ++ ) +{ + int retval = 0; + dwc_otg_device_t *dwc_otg_device; @@ -49649,9 +61016,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + dev_dbg(&_dev->dev, "dwc_otg_driver_probe(%p)\n", _dev); +#ifdef LM_INTERFACE + dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)_dev->resource.start); -+#elif defined(PCI_INTERFACE) ++#elif defined(PCI_INTERFACE) + if (!id) { -+ DWC_ERROR("Invalid pci_device_id %p", id); ++ DWC_ERROR("Invalid pci_device_id %p", id); + return -EINVAL; + } + @@ -49668,92 +61035,109 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + (unsigned)(_dev->resource->end - _dev->resource->start)); +#endif + -+ -+ dwc_otg_device = dwc_alloc(sizeof(dwc_otg_device_t)); ++ dwc_otg_device = DWC_ALLOC(sizeof(dwc_otg_device_t)); + + if (!dwc_otg_device) { + dev_err(&_dev->dev, "kmalloc of dwc_otg_device failed\n"); -+ retval = -ENOMEM; -+ goto fail; ++ return -ENOMEM; + } + + memset(dwc_otg_device, 0, sizeof(*dwc_otg_device)); -+ dwc_otg_device->reg_offset = 0xFFFFFFFF; ++ dwc_otg_device->os_dep.reg_offset = 0xFFFFFFFF; + + /* + * Map the DWC_otg Core memory into virtual address space. + */ +#ifdef LM_INTERFACE -+#if 1 -+ dwc_otg_device->base = ioremap(_dev->resource.start, SZ_256K); -+#else -+ struct map_desc desc = { -+ .virtual = IO_ADDRESS((unsigned)_dev->resource.start), -+ .pfn = __phys_to_pfn((unsigned)_dev->resource.start), -+ .length = SZ_128K, -+ .type = MT_DEVICE -+ }; -+ iotable_init(&desc, 1); -+ dwc_otg_device->base = (void *)desc.virtual; -+#endif ++ dwc_otg_device->os_dep.base = ioremap(_dev->resource.start, SZ_256K); + -+ if (!dwc_otg_device->base) { ++ if (!dwc_otg_device->os_dep.base) { + dev_err(&_dev->dev, "ioremap() failed\n"); -+ retval = -ENOMEM; -+ goto fail; ++ DWC_FREE(dwc_otg_device); ++ return -ENOMEM; + } -+ dev_dbg(&_dev->dev, "base=0x%08x\n", (unsigned)dwc_otg_device->base); -+#elif defined(PCI_INTERFACE) ++ dev_dbg(&_dev->dev, "base=0x%08x\n", ++ (unsigned)dwc_otg_device->os_dep.base); ++#elif defined(PCI_INTERFACE) + _dev->current_state = PCI_D0; + _dev->dev.power.power_state = PMSG_ON; -+ ++ + if (!_dev->irq) { -+ DWC_ERROR("Found HC with no IRQ. Check BIOS/PCI %s setup!", pci_name(_dev)); -+ retval = -ENODEV; -+ goto fail; -+ } ++ DWC_ERROR("Found HC with no IRQ. Check BIOS/PCI %s setup!", ++ pci_name(_dev)); ++ iounmap(dwc_otg_device->os_dep.base); ++ DWC_FREE(dwc_otg_device); ++ return -ENODEV; ++ } + -+ dwc_otg_device->rsrc_start = pci_resource_start(_dev,0); -+ dwc_otg_device->rsrc_len = pci_resource_len(_dev,0); -+ DWC_DEBUGPL(DBG_ANY,"PCI resource: start=%08x, len=%08x\n", -+ dwc_otg_device->rsrc_start, -+ dwc_otg_device->rsrc_len); -+ if (!request_mem_region(dwc_otg_device->rsrc_start, dwc_otg_device->rsrc_len, "dwc_otg")) { -+ dev_dbg(&_dev->dev, "error mapping memory\n"); -+ retval = -EFAULT; -+ goto fail; -+ } ++ dwc_otg_device->os_dep.rsrc_start = pci_resource_start(_dev, 0); ++ dwc_otg_device->os_dep.rsrc_len = pci_resource_len(_dev, 0); ++ DWC_DEBUGPL(DBG_ANY, "PCI resource: start=%08x, len=%08x\n", ++ (unsigned)dwc_otg_device->os_dep.rsrc_start, ++ (unsigned)dwc_otg_device->os_dep.rsrc_len); ++ if (!request_mem_region ++ (dwc_otg_device->os_dep.rsrc_start, dwc_otg_device->os_dep.rsrc_len, ++ "dwc_otg")) { ++ dev_dbg(&_dev->dev, "error requesting memory\n"); ++ iounmap(dwc_otg_device->os_dep.base); ++ DWC_FREE(dwc_otg_device); ++ return -EFAULT; ++ } + -+ dwc_otg_device->base = ioremap_nocache(dwc_otg_device->rsrc_start, dwc_otg_device->rsrc_len); -+ if (dwc_otg_device->base == NULL) { -+ dev_dbg(&_dev->dev, "error mapping memory\n"); -+ retval = -EFAULT; -+ goto fail; -+ } -+ dev_dbg(&_dev->dev, "base=0x%p (before adjust) \n", dwc_otg_device->base); -+ dwc_otg_device->base = (char *)dwc_otg_device->base; -+ dev_dbg(&_dev->dev, "base=0x%p (after adjust) \n", dwc_otg_device->base); -+ dev_dbg(&_dev->dev, "%s: mapped PA 0x%x to VA 0x%p\n", __func__, -+ (unsigned)dwc_otg_device->rsrc_start, dwc_otg_device->base); -+ // -+ pci_set_drvdata(_dev, dwc_otg_device); -+ pci_set_master(_dev); ++ dwc_otg_device->os_dep.base = ++ ioremap_nocache(dwc_otg_device->os_dep.rsrc_start, ++ dwc_otg_device->os_dep.rsrc_len); ++ if (dwc_otg_device->os_dep.base == NULL) { ++ dev_dbg(&_dev->dev, "error mapping memory\n"); ++ release_mem_region(dwc_otg_device->os_dep.rsrc_start, ++ dwc_otg_device->os_dep.rsrc_len); ++ iounmap(dwc_otg_device->os_dep.base); ++ DWC_FREE(dwc_otg_device); ++ return -EFAULT; ++ } ++ dev_dbg(&_dev->dev, "base=0x%p (before adjust) \n", ++ dwc_otg_device->os_dep.base); ++ dwc_otg_device->os_dep.base = (char *)dwc_otg_device->os_dep.base; ++ dev_dbg(&_dev->dev, "base=0x%p (after adjust) \n", ++ dwc_otg_device->os_dep.base); ++ dev_dbg(&_dev->dev, "%s: mapped PA 0x%x to VA 0x%p\n", __func__, ++ (unsigned)dwc_otg_device->os_dep.rsrc_start, ++ dwc_otg_device->os_dep.base); ++ ++ pci_set_master(_dev); ++ pci_set_drvdata(_dev, dwc_otg_device); +#elif defined(PLATFORM_INTERFACE) + DWC_DEBUGPL(DBG_ANY,"Platform resource: start=%08x, len=%08x\n", + _dev->resource->start, + _dev->resource->end - _dev->resource->start + 1); +#if 1 -+ if (!request_mem_region(_dev->resource->start, -+ _dev->resource->end - _dev->resource->start + 1, ++ if (!request_mem_region(_dev->resource[0].start, ++ _dev->resource[0].end - _dev->resource[0].start + 1, + "dwc_otg")) { + dev_dbg(&_dev->dev, "error reserving mapped memory\n"); + retval = -EFAULT; + goto fail; + } + -+ dwc_otg_device->base = ioremap_nocache(_dev->resource->start, -+ _dev->resource->end - -+ _dev->resource->start + 1); ++ dwc_otg_device->os_dep.base = ioremap_nocache(_dev->resource[0].start, ++ _dev->resource[0].end - ++ _dev->resource[0].start+1); ++ if (fiq_fix_enable) ++ { ++ if (!request_mem_region(_dev->resource[1].start, ++ _dev->resource[1].end - _dev->resource[1].start + 1, ++ "dwc_otg")) { ++ dev_dbg(&_dev->dev, "error reserving mapped memory\n"); ++ retval = -EFAULT; ++ goto fail; ++ } ++ ++ dwc_otg_device->os_dep.mphi_base = ioremap_nocache(_dev->resource[1].start, ++ _dev->resource[1].end - ++ _dev->resource[1].start + 1); ++ dummy_send = (void *) kmalloc(16, GFP_ATOMIC); ++ } ++ +#else + { + struct map_desc desc = { @@ -49763,15 +61147,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + .type = MT_DEVICE + }; + iotable_init(&desc, 1); -+ dwc_otg_device->base = (void *)desc.virtual; ++ dwc_otg_device->os_dep.base = (void *)desc.virtual; + } +#endif -+ if (!dwc_otg_device->base) { ++ if (!dwc_otg_device->os_dep.base) { + dev_err(&_dev->dev, "ioremap() failed\n"); + retval = -ENOMEM; + goto fail; + } -+ dev_dbg(&_dev->dev, "base=0x%08x\n", (unsigned)dwc_otg_device->base); ++ dev_dbg(&_dev->dev, "base=0x%08x\n", ++ (unsigned)dwc_otg_device->os_dep.base); +#endif + + /* @@ -49785,7 +61170,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot +#endif + dev_dbg(&_dev->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_device->core_if = dwc_otg_cil_init(dwc_otg_device->os_dep.base); + DWC_DEBUGPL(DBG_HCDV, "probe of device %p given core_if %p\n", + dwc_otg_device, dwc_otg_device->core_if);//GRAYG + @@ -49799,15 +61184,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + /* + * Attempt to ensure this device is really a DWC_otg Controller. + * Read and verify the SNPSID register contents. The value should be -+ * 0x45F42XXX, which corresponds to "OT2", as in "OTG version 2.XX". ++ * 0x45F42XXX or 0x45F42XXX, which corresponds to either "OT2" or "OTG3", ++ * as in "OTG version 2.XX" or "OTG version 3.XX". + */ + -+ if ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != -+ 0x4F542000) { ++ if (((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F542000) && ++ ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) { + dev_err(&_dev->dev, "Bad value for SNPSID: 0x%08x\n", + dwc_otg_get_gsnpsid(dwc_otg_device->core_if)); -+ dwc_otg_cil_remove(dwc_otg_device->core_if); -+ dwc_free(dwc_otg_device); + retval = -EINVAL; + goto fail; + } @@ -49817,7 +61201,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + */ + dev_dbg(&_dev->dev, "Calling set_parameters\n"); + if (set_parameters(dwc_otg_device->core_if)) { -+ dwc_otg_cil_remove(dwc_otg_device->core_if); + retval = -EINVAL; + goto fail; + } @@ -49828,12 +61211,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + dev_dbg(&_dev->dev, "Calling attr_create\n"); + dwc_otg_attr_create(_dev); + -+#ifdef SOF_FIX -+ retval = init_proc_fs(); -+ if (retval) -+ goto fail; -+#endif -+ + /* + * Disable the global interrupt until all the interrupt + * handlers are installed. @@ -49845,6 +61222,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + * Install the interrupt handler for the common interrupts before + * enabling common interrupts in core_init below. + */ ++ +#if defined(PLATFORM_INTERFACE) + devirq = platform_get_irq(_dev, 0); +#else @@ -49876,13 +61254,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + ); +#endif +#endif /*IRQF_TRIGGER_LOW*/ -+ ++ + /* + * Initialize the DWC_otg core. + */ + dev_dbg(&_dev->dev, "Calling dwc_otg_core_init\n"); + dwc_otg_core_init(dwc_otg_device->core_if); -+ ++ +#ifndef DWC_HOST_ONLY + /* + * Initialize the PCD @@ -49893,7 +61271,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + DWC_ERROR("pcd_init failed\n"); + dwc_otg_device->pcd = NULL; + goto fail; -+ } ++ } +#endif +#ifndef DWC_DEVICE_ONLY + /* @@ -49914,19 +61292,25 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + platform_set_drvdata(_dev, dwc_otg_device); +#elif defined(PCI_INTERFACE) + pci_set_drvdata(_dev, dwc_otg_device); ++ dwc_otg_device->os_dep.pcidev = _dev; +#endif + + /* + * Enable the global interrupt after all the interrupt -+ * handlers are installed. ++ * handlers are installed if there is no ADP support else ++ * perform initial actions required for Internal ADP logic. + */ -+ dev_dbg(&_dev->dev, "Calling enable_global_interrupts\n"); -+ dwc_otg_enable_global_interrupts(dwc_otg_device->core_if); -+ dev_dbg(&_dev->dev, "Done\n"); ++ if (!dwc_otg_get_param_adp_enable(dwc_otg_device->core_if)) { ++ dev_dbg(&_dev->dev, "Calling enable_global_interrupts\n"); ++ dwc_otg_enable_global_interrupts(dwc_otg_device->core_if); ++ dev_dbg(&_dev->dev, "Done\n"); ++ } else ++ dwc_otg_adp_start(dwc_otg_device->core_if, ++ dwc_otg_is_host_mode(dwc_otg_device->core_if)); + + return 0; + -+ fail: ++fail: + dwc_otg_driver_remove(_dev); + return retval; +} @@ -49944,32 +61328,32 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + */ +#ifdef LM_INTERFACE +static struct lm_driver dwc_otg_driver = { -+ .drv = { -+ .name = (char *)dwc_driver_name, -+ }, ++ .drv = {.name = (char *)dwc_driver_name,}, + .probe = dwc_otg_driver_probe, + .remove = dwc_otg_driver_remove, + // 'suspend' and 'resume' absent +}; +#elif defined(PCI_INTERFACE) +static const struct pci_device_id pci_ids[] = { { -+ PCI_DEVICE(0x16c3, 0xabcd), -+ .driver_data = (unsigned long) 0xdeadbeef, -+ }, { /* end: all zeroes */ } ++ PCI_DEVICE(0x16c3, 0xabcd), ++ .driver_data = ++ (unsigned long)0xdeadbeef, ++ }, { /* end: all zeroes */ } +}; ++ +MODULE_DEVICE_TABLE(pci, pci_ids); + +/* pci driver glue; this is a "new style" PCI driver module */ +static struct pci_driver dwc_otg_driver = { -+ .name = "dwc_otg", -+ .id_table = pci_ids, ++ .name = "dwc_otg", ++ .id_table = pci_ids, + -+ .probe = dwc_otg_driver_probe, -+ .remove = dwc_otg_driver_remove, ++ .probe = dwc_otg_driver_probe, ++ .remove = dwc_otg_driver_remove, + -+ .driver = { -+ .name = (char*)dwc_driver_name, -+ }, ++ .driver = { ++ .name = (char *)dwc_driver_name, ++ }, +}; +#elif defined(PLATFORM_INTERFACE) +static struct platform_device_id platform_ids[] = { @@ -49993,7 +61377,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot +}; +#endif + -+ +/** + * This function is called when the dwc_otg_driver is installed with the + * insmod command. It registers the dwc_otg_driver structure with the @@ -50004,46 +61387,36 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + * + * @return + */ -+ +static int __init dwc_otg_driver_init(void) +{ + int retval = 0; + int error; ++ struct device_driver *drv; + printk(KERN_INFO "%s: version %s (%s bus)\n", dwc_driver_name, + DWC_DRIVER_VERSION, +#ifdef LM_INTERFACE + "logicmodule"); + retval = lm_driver_register(&dwc_otg_driver); ++ drv = &dwc_otg_driver.drv; +#elif defined(PCI_INTERFACE) + "pci"); + retval = pci_register_driver(&dwc_otg_driver); ++ drv = &dwc_otg_driver.driver; +#elif defined(PLATFORM_INTERFACE) + "platform"); + retval = platform_driver_register(&dwc_otg_driver); ++ drv = &dwc_otg_driver.driver; +#endif + if (retval < 0) { + printk(KERN_ERR "%s retval=%d\n", __func__, retval); + return retval; + } -+#ifdef LM_INTERFACE -+ error = driver_create_file(&dwc_otg_driver.drv, &driver_attr_version); -+ error = driver_create_file(&dwc_otg_driver.drv, &driver_attr_debuglevel); -+#elif defined(PCI_INTERFACE) -+ error = driver_create_file(&dwc_otg_driver.driver, -+ &driver_attr_version); -+ error = driver_create_file(&dwc_otg_driver.driver, -+ &driver_attr_debuglevel); -+#elif defined(PLATFORM_INTERFACE) -+ error = driver_create_file(&dwc_otg_driver.driver, -+ &driver_attr_version); -+ error = driver_create_file(&dwc_otg_driver.driver, -+ &driver_attr_debuglevel); -+#endif ++ printk(KERN_DEBUG "dwc_otg: FIQ %s\n", fiq_fix_enable ? "enabled":"disabled"); + -+#ifdef SOF_FIX -+ retval = init_proc_fs(); ++ error = driver_create_file(drv, &driver_attr_version); ++#ifdef DEBUG ++ error = driver_create_file(drv, &driver_attr_debuglevel); +#endif -+ + return retval; +} + @@ -50075,6 +61448,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + + printk(KERN_INFO "%s module removed\n", dwc_driver_name); +} ++ +module_exit(dwc_otg_driver_cleanup); + +MODULE_DESCRIPTION(DWC_DRIVER_DESC); @@ -50298,8 +61672,29 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot +module_param_named(ic_usb_cap, dwc_otg_module_params.ic_usb_cap, int, 0444); +MODULE_PARM_DESC(ic_usb_cap, + "IC_USB Capability 0=IC_USB Disabled 1=IC_USB Enabled"); -+module_param_named(ahb_thr_ratio, dwc_otg_module_params.ahb_thr_ratio, int, 0444); ++module_param_named(ahb_thr_ratio, dwc_otg_module_params.ahb_thr_ratio, int, ++ 0444); +MODULE_PARM_DESC(ahb_thr_ratio, "AHB Threshold Ratio"); ++module_param_named(power_down, dwc_otg_module_params.power_down, int, 0444); ++MODULE_PARM_DESC(power_down, "Power Down Mode"); ++module_param_named(reload_ctl, dwc_otg_module_params.reload_ctl, int, 0444); ++MODULE_PARM_DESC(reload_ctl, "HFIR Reload Control"); ++module_param_named(dev_out_nak, dwc_otg_module_params.dev_out_nak, int, 0444); ++MODULE_PARM_DESC(dev_out_nak, "Enable Device OUT NAK"); ++module_param_named(cont_on_bna, dwc_otg_module_params.cont_on_bna, int, 0444); ++MODULE_PARM_DESC(cont_on_bna, "Enable Enable Continue on BNA"); ++module_param_named(ahb_single, dwc_otg_module_params.ahb_single, int, 0444); ++MODULE_PARM_DESC(ahb_single, "Enable AHB Single Support"); ++module_param_named(adp_enable, dwc_otg_module_params.adp_enable, int, 0444); ++MODULE_PARM_DESC(adp_enable, "ADP Enable 0=ADP Disabled 1=ADP Enabled"); ++module_param_named(otg_ver, dwc_otg_module_params.otg_ver, int, 0444); ++MODULE_PARM_DESC(otg_ver, "OTG revision supported 0=OTG 1.3 1=OTG 2.0"); ++module_param(microframe_schedule, bool, 0444); ++MODULE_PARM_DESC(microframe_schedule, "Enable the microframe scheduler"); ++ ++ ++module_param(fiq_fix_enable, bool, 0444); ++MODULE_PARM_DESC(fiq_fix_enable, "Enable the fiq fix"); + +/** @page "Module Parameters" + * @@ -50487,7 +61882,21 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + + + -+ otg_en_multiple_tx_fifo ++ ulpi_fs_ls ++ Specifies whether to use ULPI FS/LS mode only. ++ - 0: Disabled (default) ++ - 1: Enabled ++ ++ ++ ++ ts_dline ++ Specifies whether term select D-Line pulsing for all PHYs is enabled. ++ - 0: Disabled (default) ++ - 1: Enabled ++ ++ ++ ++ en_multiple_tx_fifo + Specifies whether dedicatedto tx fifos are enabled for non periodic IN EPs. + The driver will automatically detect the value for this parameter if none is + specified. @@ -50516,9 +61925,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + + + thr_ctl -+ Specifies whether to enable Thresholding for Device mode. Bits 0, 1, 2 of this -+ parmater specifies if thresholding is enabled for non-Iso Tx, Iso Tx and Rx -+ transfers accordingly. ++ Specifies whether to enable Thresholding for Device mode. Bits 0, 1, 2 of ++ this parmater specifies if thresholding is enabled for non-Iso Tx, Iso Tx and ++ Rx transfers accordingly. + The driver will automatically detect the value for this parameter if none is + specified. + - Values: 0 to 7 (default 0) @@ -50542,7 +61951,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + The driver will automatically detect the value for this parameter if none is + specified. + - 0: MPI disabled (default) -+ - 1: MPI enable ++ - 1: MPI enable + + + @@ -50551,7 +61960,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + The driver will automatically detect the value for this parameter if none is + specified. + - 0: PTI disabled (default) -+ - 1: PTI enable ++ - 1: PTI enable + + + @@ -50563,22 +61972,96 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.c linux-rpi-boot + - 1: LPM enable (default, if available) + + -+ ++ ++ ic_usb_cap ++ Specifies whether to enable IC_USB capability. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: IC_USB disabled (default, if available) ++ - 1: IC_USB enable ++ ++ ++ + ahb_thr_ratio + Specifies AHB Threshold ratio. + - Values: 0 to 3 (default 0) + + ++ ++ power_down ++ Specifies Power Down(Hibernation) Mode. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: Power Down disabled (default) ++ - 2: Power Down enabled ++ ++ ++ ++ reload_ctl ++ Specifies whether dynamic reloading of the HFIR register is allowed during ++ run time. The driver will automatically detect the value for this parameter if ++ none is specified. In case the HFIR value is reloaded when HFIR.RldCtrl == 1'b0 ++ the core might misbehave. ++ - 0: Reload Control disabled (default) ++ - 1: Reload Control enabled ++ ++ ++ ++ dev_out_nak ++ Specifies whether Device OUT NAK enhancement enabled or no. ++ The driver will automatically detect the value for this parameter if ++ none is specified. This parameter is valid only when OTG_EN_DESC_DMA == 1b1. ++ - 0: The core does not set NAK after Bulk OUT transfer complete (default) ++ - 1: The core sets NAK after Bulk OUT transfer complete ++ ++ ++ ++ cont_on_bna ++ Specifies whether Enable Continue on BNA enabled or no. ++ After receiving BNA interrupt the core disables the endpoint,when the ++ endpoint is re-enabled by the application the ++ - 0: Core starts processing from the DOEPDMA descriptor (default) ++ - 1: Core starts processing from the descriptor which received the BNA. ++ This parameter is valid only when OTG_EN_DESC_DMA == 1b1. ++ ++ ++ ++ ahb_single ++ This bit when programmed supports SINGLE transfers for remainder data ++ in a transfer for DMA mode of operation. ++ - 0: The remainder data will be sent using INCR burst size (default) ++ - 1: The remainder data will be sent using SINGLE burst size. ++ ++ ++ ++ adp_enable ++ Specifies whether ADP feature is enabled. ++ The driver will automatically detect the value for this parameter if none is ++ specified. ++ - 0: ADP feature disabled (default) ++ - 1: ADP feature enabled ++ ++ ++ ++ otg_ver ++ Specifies whether OTG is performing as USB OTG Revision 2.0 or Revision 1.3 ++ USB OTG device. ++ - 0: OTG 2.0 support disabled (default) ++ - 1: OTG 2.0 support enabled ++ ++ +*/ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.h linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.h ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.h 2012-07-15 20:29:19.139084655 +0200 -@@ -0,0 +1,101 @@ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.h b/drivers/usb/host/dwc_otg/dwc_otg_driver.h +new file mode 100644 +index 0000000..8a0e41b +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.h +@@ -0,0 +1,86 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.h $ -+ * $Revision: #16 $ -+ * $Date: 2009/04/03 $ -+ * $Change: 1225160 $ ++ * $Revision: #19 $ ++ * $Date: 2010/11/15 $ ++ * $Change: 1627671 $ + * + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless @@ -50613,41 +62096,26 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.h linux-rpi-boot +/** @file + * This file contains the interface to the Linux driver. + */ ++#include "dwc_otg_os_dep.h" +#include "dwc_otg_core_if.h" + +/* Type declarations */ +struct dwc_otg_pcd; +struct dwc_otg_hcd; + -+#ifdef PCI_INTERFACE -+#include -+#endif -+ -+ -+ +/** + * This structure is a wrapper that encapsulates the driver components used to + * manage a single DWC_otg controller. + */ +typedef struct dwc_otg_device { -+ /** Base address returned from ioremap() */ -+ void *base; -+ -+#ifdef LM_INTERFACE -+ struct lm_device *lmdev; -+#elif defined(PCI_INTERFACE) -+ int rsrc_start; -+ int rsrc_len; -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *platformdev; -+#endif ++ /** Structure containing OS-dependent stuff. KEEP THIS STRUCT AT THE ++ * VERY BEGINNING OF THE DEVICE STRUCT. OSes such as FreeBSD and NetBSD ++ * require this. */ ++ struct os_dependent os_dep; + + /** 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; + @@ -50675,16 +62143,18 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_driver.h linux-rpi-boot +#endif + +#endif -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c 2012-07-15 20:29:19.129084467 +0200 -@@ -0,0 +1,3390 @@ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +new file mode 100644 +index 0000000..20f989e +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +@@ -0,0 +1,3478 @@ + +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.c $ -+ * $Revision: #87 $ -+ * $Date: 2009/04/23 $ -+ * $Change: 1239143 $ ++ * $Revision: #104 $ ++ * $Date: 2011/10/24 $ ++ * $Change: 1871159 $ + * + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless @@ -50715,7 +62185,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 +#ifndef DWC_DEVICE_ONLY + +/** @file -+ * This file implements HCD Core. All code in this file is portable and don't ++ * This file implements HCD Core. All code in this file is portable and doesn't + * use any OS specific functions. + * Interface provided by HCD Core is defined in + * header file. @@ -50724,14 +62194,21 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 +#include "dwc_otg_hcd.h" +#include "dwc_otg_regs.h" + -+#ifdef HW2937_WORKAROUND -+//#include -+#include -+#endif -+ ++extern bool microframe_schedule; ++ ++//#define DEBUG_HOST_CHANNELS ++#ifdef DEBUG_HOST_CHANNELS ++static int last_sel_trans_num_per_scheduled = 0; ++static int last_sel_trans_num_nonper_scheduled = 0; ++static int last_sel_trans_num_avail_hc_at_start = 0; ++static int last_sel_trans_num_avail_hc_at_end = 0; ++#endif /* DEBUG_HOST_CHANNELS */ ++ ++extern int g_next_sched_frame, g_np_count, g_np_sent; ++ +dwc_otg_hcd_t *dwc_otg_hcd_alloc_hcd(void) +{ -+ return dwc_alloc(sizeof(dwc_otg_hcd_t)); ++ return DWC_ALLOC(sizeof(dwc_otg_hcd_t)); +} + +/** @@ -50745,38 +62222,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + __DWC_ERROR("Device Not Connected/Responding\n"); +} + -+/** -+ * SOF_FIX: Reduce the SOF overhead by disabling the SOF interrupt except -+ * when there are USB transfers pending. Re-enable the interrupt -+ * every tick for periodic transaction handling. MSO 5/31/12 -+ * SOF (Start of Frame) timeout function. Kick the driver by re-enabling -+ * the SOF interrupt -+ */ -+#ifdef SOF_FIX -+void dwc_otg_hcd_sof_timeout(void *ptr) -+{ -+ dwc_otg_hcd_t * hcd = (dwc_otg_hcd_t *)ptr; -+ dwc_otg_core_if_t *core_if = hcd->core_if; -+ gintmsk_data_t gintmsk = {.d32 = 0}; -+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; -+ unsigned int intmsk; -+ -+ // turn on Start-of-Frame interrupt -+ gintmsk.d32 = dwc_read_reg32(&global_regs->gintmsk); -+ intmsk = gintmsk.d32; -+ gintmsk.b.sofintr |= 1; -+ dwc_write_reg32(&global_regs->gintmsk, gintmsk.d32); -+ DWC_TIMER_SCHEDULE(hcd->sof_timer, 1); /* 1ms */ -+#ifdef DEBUG_SOF_FIX -+ if ((++sof_timeout_count % 10000) == 0) -+ printk(KERN_ERR "%s: %d timeouts handled, read 0x%x wrote 0x%x.", -+ __FUNCTION__, sof_timeout_count, intmsk, gintmsk.d32); -+#endif -+ -+} -+#endif -+ -+#ifdef DEBUG ++#if defined(DEBUG) +static void dump_channel_info(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) +{ + if (qh->channel != NULL) { @@ -50793,10 +62239,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + uint32_t hcdma; + + 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); -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ hcdma = dwc_read_reg32(&hc_regs->hcdma); ++ 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_PRINTF(" Assigned to channel %p:\n", hc); + DWC_PRINTF(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, @@ -50832,7 +62278,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + } + } +} -+#endif /* DEBUG */ ++#else ++#define dump_channel_info(hcd, qh) ++#endif /* DEBUG */ + +/** + * Work queue function for starting the HCD when A-Cable is connected. @@ -50882,8 +62330,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); + if (qtd->urb != NULL) { + hcd->fops->complete(hcd, qtd->urb->priv, -+ qtd->urb, -+ -DWC_E_TIMEOUT); ++ qtd->urb, -DWC_E_TIMEOUT); + dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); + } + @@ -50954,7 +62401,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + */ + hprt0.d32 = dwc_otg_read_hprt0(core_if); + hprt0.b.prtrst = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); + } + DWC_WORKQ_SCHEDULE_DELAYED(core_if->wq_otg, + hcd_start_func, dwc_otg_hcd, 50, @@ -50988,9 +62435,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + intr.b.nptxfempty = 1; + intr.b.ptxfempty = 1; + intr.b.hcintr = 1; -+ dwc_modify_reg32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, ++ 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, ++ DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintsts, + intr.d32, 0); + + del_timers(dwc_otg_hcd); @@ -51005,7 +62452,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + hprt0_data_t hprt0 = {.d32 = 0 }; + DWC_PRINTF("Disconnect: PortPower off\n"); + hprt0.b.prtpwr = 0; -+ dwc_write_reg32(dwc_otg_hcd->core_if->host_if->hprt0, ++ DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, + hprt0.d32); + } + @@ -51032,17 +62479,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + if (DWC_CIRCLEQ_EMPTY_ENTRY + (channel, hc_list_entry)) { + hc_regs = -+ dwc_otg_hcd->core_if->host_if-> -+ hc_regs[i]; ++ dwc_otg_hcd->core_if-> ++ host_if->hc_regs[i]; + hcchar.d32 = -+ dwc_read_reg32(&hc_regs->hcchar); ++ DWC_READ_REG32(&hc_regs->hcchar); + if (hcchar.b.chen) { + hcchar.b.chen = 0; + hcchar.b.chdis = 1; + hcchar.b.epdir = 0; -+ dwc_write_reg32(&hc_regs-> -+ hcchar, -+ hcchar.d32); ++ DWC_WRITE_REG32 ++ (&hc_regs->hcchar, ++ hcchar.d32); + } + } + } @@ -51053,25 +62500,25 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + if (DWC_CIRCLEQ_EMPTY_ENTRY(channel, hc_list_entry)) { + hc_regs = + dwc_otg_hcd->core_if->host_if->hc_regs[i]; -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + if (hcchar.b.chen) { + /* Halt the channel. */ + hcchar.b.chdis = 1; -+ dwc_write_reg32(&hc_regs->hcchar, ++ DWC_WRITE_REG32(&hc_regs->hcchar, + hcchar.d32); + } + + dwc_otg_hc_cleanup(dwc_otg_hcd->core_if, + channel); -+ DWC_CIRCLEQ_INSERT_TAIL(&dwc_otg_hcd-> -+ free_hc_list, channel, -+ hc_list_entry); -+ /* -+ * Added for Descriptor DMA to prevent channel double cleanup ++ DWC_CIRCLEQ_INSERT_TAIL ++ (&dwc_otg_hcd->free_hc_list, channel, ++ hc_list_entry); ++ /* ++ * Added for Descriptor DMA to prevent channel double cleanup + * in release_channel_ddma(). Which called from ep_disable + * when device disconnect. -+ */ -+ channel->qh = NULL; ++ */ ++ channel->qh = NULL; + } + } + } @@ -51098,7 +62545,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 +} + +#ifdef CONFIG_USB_DWC_OTG_LPM -+/** ++/** + * HCD Callback function for sleep of HCD. + * + * @param p void pointer to the struct usb_hcd @@ -51113,6 +62560,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 +} +#endif + ++ +/** + * HCD Callback function for Remote Wakeup. + * @@ -51155,44 +62603,49 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + /* Turn off the vbus power */ + DWC_PRINTF("PortPower off\n"); + hprt0.b.prtpwr = 0; -+ dwc_write_reg32(hcd->core_if->host_if->hprt0, hprt0.d32); ++ DWC_WRITE_REG32(hcd->core_if->host_if->hprt0, hprt0.d32); + dwc_mdelay(1); +} + +int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd, -+ dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle) ++ dwc_otg_hcd_urb_t * dwc_otg_urb, void **ep_handle, ++ int atomic_alloc) +{ -+ uint64_t flags; ++ dwc_irqflags_t flags; + int retval = 0; + dwc_otg_qtd_t *qtd; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; + -+ if (NULL == hcd->core_if) { //GRAYG ++#ifdef DEBUG /* integrity checks (Broadcom) */ ++ if (NULL == hcd->core_if) { + DWC_ERROR("**** DWC OTG HCD URB Enqueue - HCD has NULL core_if\n"); + /* No longer connected. */ + return -DWC_E_INVALID; + } -+ ++#endif + if (!hcd->flags.b.port_connect_status) { + /* No longer connected. */ ++ DWC_ERROR("Not connected\n"); + return -DWC_E_NO_DEVICE; + } + -+ qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb); ++ qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc); + if (qtd == NULL) { + DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n"); + return -DWC_E_NO_MEMORY; + } -+ if (qtd->urb == NULL) { //GRAYG ++#ifdef DEBUG /* integrity checks (Broadcom) */ ++ if (qtd->urb == NULL) { + DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD with no URBs\n"); + return -DWC_E_NO_MEMORY; + } -+ if (qtd->urb->priv == NULL) { //GRAYG ++ if (qtd->urb->priv == NULL) { + DWC_ERROR("**** DWC OTG HCD URB Enqueue created QTD URB with no URB handle\n"); + return -DWC_E_NO_MEMORY; + } -+ ++#endif + retval = -+ dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle); ++ dwc_otg_hcd_qtd_add(qtd, hcd, (dwc_otg_qh_t **) ep_handle, atomic_alloc); + // creates a new queue in ep_handle if it doesn't exist already + if (retval < 0) { + DWC_ERROR("DWC OTG HCD URB Enqueue failed adding QTD. " @@ -51201,11 +62654,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + } else { + qtd->qh = *ep_handle; + } -+ -+ if (hcd->core_if->dma_desc_enable && retval == 0) { -+ dwc_otg_transaction_type_e tr_type; -+ if ((qtd->qh->ep_type == UE_BULK) && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) { -+ /* Do not schedule SG transcations until qtd has URB_GIVEBACK_ASAP set */ ++ intr_mask.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->gintmsk); ++ if (!intr_mask.b.sofintr && retval == 0) { ++ dwc_otg_transaction_type_e tr_type; ++ if ((qtd->qh->ep_type == UE_BULK) ++ && !(qtd->urb->flags & URB_GIVEBACK_ASAP)) { ++ /* Do not schedule SG transactions until qtd has URB_GIVEBACK_ASAP set */ + return 0; + } + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); @@ -51222,42 +62676,43 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 +int dwc_otg_hcd_urb_dequeue(dwc_otg_hcd_t * hcd, + dwc_otg_hcd_urb_t * dwc_otg_urb) +{ -+ uint64_t flags; -+ + dwc_otg_qh_t *qh; + dwc_otg_qtd_t *urb_qtd; + -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ -+ if (hcd == NULL) { //GRAYG ++#ifdef DEBUG /* integrity checks (Broadcom) */ ++ ++ if (hcd == NULL) { + DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL HCD\n"); + return -DWC_E_INVALID; + } -+ if (dwc_otg_urb == NULL) { //GRAYG ++ if (dwc_otg_urb == NULL) { + DWC_ERROR("**** DWC OTG HCD URB Dequeue has NULL URB\n"); + return -DWC_E_INVALID; + } -+ if (dwc_otg_urb->qtd == NULL) { //GRAYG ++ if (dwc_otg_urb->qtd == NULL) { + DWC_ERROR("**** DWC OTG HCD URB Dequeue with NULL QTD\n"); + return -DWC_E_INVALID; + } + urb_qtd = dwc_otg_urb->qtd; -+ if (urb_qtd->qh == NULL) { //GRAYG ++ if (urb_qtd->qh == NULL) { + DWC_ERROR("**** DWC OTG HCD URB Dequeue with QTD with NULL Q handler\n"); + return -DWC_E_INVALID; + } ++#else ++ urb_qtd = dwc_otg_urb->qtd; ++#endif + qh = urb_qtd->qh; -+#ifdef DEBUG + if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { + if (urb_qtd->in_process) { + dump_channel_info(hcd, qh); + } + } -+#endif -+ if (hcd->core_if == NULL) { //GRAYG ++#ifdef DEBUG /* integrity checks (Broadcom) */ ++ if (hcd->core_if == NULL) { + DWC_ERROR("**** DWC OTG HCD URB Dequeue HCD has NULL core_if\n"); + return -DWC_E_INVALID; + } ++#endif + if (urb_qtd->in_process && qh->channel) { + /* The QTD is in process (it has been assigned to a channel). */ + if (hcd->flags.b.port_connect_status) { @@ -51277,12 +62732,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + * Free the QTD and clean up the associated QH. Leave the QH in the + * schedule if it has any remaining QTDs. + */ -+ ++ + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue - " + "delete %sQueue handler\n", -+ hcd->core_if->dma_desc_enable?"DMA ":""); //GRAYG ++ hcd->core_if->dma_desc_enable?"DMA ":""); + if (!hcd->core_if->dma_desc_enable) { -+ uint8_t b = urb_qtd->in_process; ++ uint8_t b = urb_qtd->in_process; + dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh); + if (b) { + dwc_otg_hcd_qh_deactivate(hcd, qh, 0); @@ -51290,13 +62745,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + } else if (DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { + dwc_otg_hcd_qh_remove(hcd, qh); + } -+ } -+ else { ++ } else { + dwc_otg_hcd_qtd_remove_and_free(hcd, urb_qtd, qh); + } -+ -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); -+ + return 0; +} + @@ -51305,7 +62756,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 +{ + dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; + int retval = 0; -+ uint64_t flags; ++ dwc_irqflags_t flags; + + if (retry < 0) { + retval = -DWC_E_INVALID; @@ -51313,11 +62764,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + } + + if (!qh) { ++ retval = -DWC_E_INVALID; + goto done; + } + + DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ ++ + while (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list) && retry) { + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); + retry--; @@ -51326,20 +62778,33 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + } + + dwc_otg_hcd_qh_remove(hcd, qh); -+ ++ + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); -+ /* -+ * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove -+ * and qh_free to prevent stack dump on dwc_dma_free() with -+ * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free() ++ /* ++ * Split dwc_otg_hcd_qh_remove_and_free() into qh_remove ++ * and qh_free to prevent stack dump on DWC_DMA_FREE() with ++ * irq_disabled (spinlock_irqsave) in dwc_otg_hcd_desc_list_free() + * and dwc_otg_hcd_frame_list_alloc(). + */ + dwc_otg_hcd_qh_free(hcd, qh); + -+ done: ++done: + return retval; +} + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle) ++{ ++ int retval = 0; ++ dwc_otg_qh_t *qh = (dwc_otg_qh_t *) ep_handle; ++ if (!qh) ++ return -DWC_E_INVALID; ++ ++ qh->data_toggle = DWC_OTG_HC_PID_DATA0; ++ return retval; ++} ++#endif ++ +/** + * HCD Callback structure for handling mode switching. + */ @@ -51368,11 +62833,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + + hprt0.d32 = dwc_otg_read_hprt0(core_if); + hprt0.b.prtrst = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); + dwc_mdelay(60); + + hprt0.b.prtrst = 0; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); + dwc_otg_hcd->flags.b.port_reset_change = 1; +} + @@ -51380,14 +62845,20 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 +{ + dwc_list_link_t *item; + dwc_otg_qh_t *qh; ++ dwc_irqflags_t flags; + + if (!qh_list->next) { + /* The list hasn't been initialized yet. */ + return; + } -+ ++ /* ++ * Hold spinlock here. Not needed in that case if bellow ++ * function is being called from ISR ++ */ ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); + /* Ensure there are no QTDs or URBs left. */ + kill_urbs_in_qh_list(hcd, qh_list); ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); + + DWC_LIST_FOREACH(item, qh_list) { + qh = DWC_LIST_ENTRY(item, dwc_otg_qh_t, qh_list_entry); @@ -51396,6 +62867,68 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 +} + +/** ++ * Exit from Hibernation if Host did not detect SRP from connected SRP capable ++ * Device during SRP time by host power up. ++ */ ++void dwc_otg_hcd_power_up(void *ptr) ++{ ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; ++ ++ DWC_PRINTF("%s called\n", __FUNCTION__); ++ ++ if (!core_if->hibernation_suspend) { ++ DWC_PRINTF("Already exited from Hibernation\n"); ++ return; ++ } ++ ++ /* Switch on the voltage to the core */ ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Reset the core */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Disable power clamps */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ /* Remove reset the core signal */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnrstn = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Disable PMU interrupt */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ core_if->hibernation_suspend = 0; ++ ++ /* Disable PMU */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ dwc_udelay(10); ++ ++ /* Enable VBUS */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, gpwrdn.d32, 0); ++ ++ core_if->op_state = A_HOST; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_hcd_start(core_if); ++} ++ ++/** + * Frees secondary storage associated with the dwc_otg_hcd structure contained + * in the struct usb_hcd field. + */ @@ -51427,25 +62960,37 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + if (hc != NULL) { + DWC_DEBUGPL(DBG_HCDV, "HCD Free channel #%i, hc=%p\n", + i, hc); -+ dwc_free(hc); ++ DWC_FREE(hc); + } + } + + if (dwc_otg_hcd->core_if->dma_enable) { + if (dwc_otg_hcd->status_buf_dma) { -+ dwc_dma_free(DWC_OTG_HCD_STATUS_BUF_SIZE, ++ DWC_DMA_FREE(DWC_OTG_HCD_STATUS_BUF_SIZE, + dwc_otg_hcd->status_buf, + dwc_otg_hcd->status_buf_dma); + } + } else if (dwc_otg_hcd->status_buf != NULL) { -+ dwc_free(dwc_otg_hcd->status_buf); ++ DWC_FREE(dwc_otg_hcd->status_buf); + } + DWC_SPINLOCK_FREE(dwc_otg_hcd->lock); ++ /* Set core_if's lock pointer to NULL */ ++ dwc_otg_hcd->core_if->lock = NULL; ++ + DWC_TIMER_FREE(dwc_otg_hcd->conn_timer); + DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet); -+ dwc_free(dwc_otg_hcd); ++ ++#ifdef DWC_DEV_SRPCAP ++ if (dwc_otg_hcd->core_if->power_down == 2 && ++ dwc_otg_hcd->core_if->pwron_timer) { ++ DWC_TIMER_FREE(dwc_otg_hcd->core_if->pwron_timer); ++ } ++#endif ++ DWC_FREE(dwc_otg_hcd); +} + ++int init_hcd_usecs(dwc_otg_hcd_t *_hcd); ++ +int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) +{ + int retval = 0; @@ -51454,11 +62999,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + dwc_hc_t *channel; + + hcd->lock = DWC_SPINLOCK_ALLOC(); -+ + DWC_DEBUGPL(DBG_HCDV, "init of HCD %p given core_if %p\n", -+ hcd, core_if);//GRAYG -+ ++ hcd, core_if); ++ if (!hcd->lock) { ++ DWC_ERROR("Could not allocate lock for pcd"); ++ DWC_FREE(hcd); ++ retval = -DWC_E_NO_MEMORY; ++ goto out; ++ } + hcd->core_if = core_if; ++ + /* Register the HCD CIL Callbacks */ + dwc_otg_cil_register_hcd_callbacks(hcd->core_if, + &hcd_cil_callbacks, hcd); @@ -51481,7 +63031,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + num_channels = hcd->core_if->core_params->host_channels; + DWC_MEMSET(hcd->hc_ptr_array, 0, sizeof(hcd->hc_ptr_array)); + for (i = 0; i < num_channels; i++) { -+ channel = dwc_alloc(sizeof(dwc_hc_t)); ++ channel = DWC_ALLOC(sizeof(dwc_hc_t)); + if (channel == NULL) { + retval = -DWC_E_NO_MEMORY; + DWC_ERROR("%s: host channel allocation failed\n", @@ -51504,15 +63054,19 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + hcd->conn_timer = DWC_TIMER_ALLOC("Connection timer", + dwc_otg_hcd_connect_timeout, 0); + -+#ifdef SOF_FIX -+ /* Initialize the Start of Frame interrupt timeout timer. */ -+ hcd->sof_timer = DWC_TIMER_ALLOC("SOF timer", -+ dwc_otg_hcd_sof_timeout, hcd); -+ DWC_TIMER_SCHEDULE(hcd->sof_timer, 1); /* 1ms */ -+#endif ++ printk(KERN_DEBUG "dwc_otg: Microframe scheduler %s\n", microframe_schedule ? "enabled":"disabled"); ++ if (microframe_schedule) ++ init_hcd_usecs(hcd); + + /* Initialize reset tasklet. */ -+ hcd->reset_tasklet = DWC_TASK_ALLOC(reset_tasklet_func, hcd); ++ hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd); ++#ifdef DWC_DEV_SRPCAP ++ if (hcd->core_if->power_down == 2) { ++ /* Initialize Power on timer for Host power up in case hibernation */ ++ hcd->core_if->pwron_timer = DWC_TIMER_ALLOC("PWRON TIMER", ++ dwc_otg_hcd_power_up, core_if); ++ } ++#endif + + /* + * Allocate space for storing data on status transactions. Normally no @@ -51522,10 +63076,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + */ + if (hcd->core_if->dma_enable) { + hcd->status_buf = -+ dwc_dma_alloc(DWC_OTG_HCD_STATUS_BUF_SIZE, ++ DWC_DMA_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE, + &hcd->status_buf_dma); + } else { -+ hcd->status_buf = dwc_alloc(DWC_OTG_HCD_STATUS_BUF_SIZE); ++ hcd->status_buf = DWC_ALLOC(DWC_OTG_HCD_STATUS_BUF_SIZE); + } + if (!hcd->status_buf) { + retval = -DWC_E_NO_MEMORY; @@ -51537,12 +63091,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + hcd->otg_port = 1; + hcd->frame_list = NULL; + hcd->frame_list_dma = 0; -+ -+#ifdef HW2937_WORKAROUND -+ hcd->hw2937_xfer_mode = HW2937_XFER_MODE_IDLE; -+ hcd->hw2937_assigned_channels = 0; -+#endif -+ ++ hcd->periodic_qh_count = 0; +out: + return retval; +} @@ -51568,9 +63117,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + hcd->flags.d32 = 0; + + hcd->non_periodic_qh_ptr = &hcd->non_periodic_sched_active; -+ hcd->non_periodic_channels = 0; -+ hcd->periodic_channels = 0; -+ ++ if (!microframe_schedule) { ++ hcd->non_periodic_channels = 0; ++ hcd->periodic_channels = 0; ++ } else { ++ hcd->available_host_channels = hcd->core_if->core_params->host_channels; ++ } + /* + * Put all channels in the free channel list and clean up channel + * states. @@ -51590,6 +63142,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + + /* Initialize the DWC core for host mode operation. */ + dwc_otg_core_host_init(hcd->core_if); ++ ++ /* Set core_if's lock pointer to the hcd->lock */ ++ hcd->core_if->lock = hcd->lock; +} + +/** @@ -51601,19 +63156,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + * @param qh Transactions from the first QTD for this QH are selected and + * assigned to a free host channel. + */ -+#ifdef HW2937_WORKAROUND -+static int assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+#else +static void assign_and_init_hc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+#endif +{ + dwc_hc_t *hc; + dwc_otg_qtd_t *qtd; + dwc_otg_hcd_urb_t *urb; + void* ptr = NULL; -+#ifdef HW2937_WORKAROUND -+ int ep_is_in; -+#endif + + qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); + @@ -51621,13 +63169,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + + DWC_DEBUGPL(DBG_HCDV, "%s(%p,%p) - urb %x, actual_length %d\n", __func__, hcd, qh, (unsigned int)urb, urb->actual_length); + -+#ifdef HW2937_WORKAROUND -+ ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0); -+ if (ep_is_in && ((hcd->hw2937_xfer_mode == HW2937_XFER_MODE_OUT) || -+ (hcd->hw2937_xfer_mode == HW2937_XFER_MODE_PAUSEIN))) -+ return 0; -+#endif -+ + if (((urb->actual_length < 0) || (urb->actual_length > urb->length)) && !dwc_otg_hcd_is_pipe_in(&urb->pipe_info)) + urb->actual_length = urb->length; + @@ -51636,8 +63177,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + + /* Remove the host channel from the free list. */ + DWC_CIRCLEQ_REMOVE_INIT(&hcd->free_hc_list, hc, hc_list_entry); ++ + qh->channel = hc; -+ ++ + qtd->in_process = 1; + + /* @@ -51662,20 +63204,23 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + * started to accommodate the max widths of the XferSize and PktCnt + * fields in the HCTSIZn register. + */ -+ hc->do_ping = qh->ping_state; -+#ifdef HW2937_WORKAROUND -+ hc->ep_is_in = ep_is_in; -+#else ++ + hc->ep_is_in = (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) != 0); -+#endif ++ if (hc->ep_is_in) { ++ hc->do_ping = 0; ++ } else { ++ hc->do_ping = qh->ping_state; ++ } ++ + hc->data_pid_start = qh->data_toggle; + hc->multi_count = 1; + + if (hcd->core_if->dma_enable) { + hc->xfer_buff = (uint8_t *) urb->dma + urb->actual_length; -+ ++ + /* For non-dword aligned case */ -+ if (((uint32_t)hc->xfer_buff & 0x3) && !hcd->core_if->dma_desc_enable) { ++ if (((unsigned long)hc->xfer_buff & 0x3) ++ && !hcd->core_if->dma_desc_enable) { + ptr = (uint8_t *) urb->buf + urb->actual_length; + } + } else { @@ -51734,7 +63279,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + if (hc->ep_is_in) { + hc->do_ping = 0; + } -+ ++ + hc->data_pid_start = DWC_OTG_HC_PID_DATA1; + + hc->xfer_len = 0; @@ -51756,16 +63301,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + case UE_ISOCHRONOUS: + { + struct dwc_otg_hcd_iso_packet_desc *frame_desc; -+ ++ + hc->ep_type = DWC_OTG_EP_TYPE_ISOC; -+ ++ + if (hcd->core_if->dma_desc_enable) + break; -+ ++ + frame_desc = &urb->iso_descs[qtd->isoc_frame_index]; -+ ++ + frame_desc->status = 0; -+ ++ + if (hcd->core_if->dma_enable) { + hc->xfer_buff = (uint8_t *) urb->dma; + } else { @@ -51777,12 +63322,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + frame_desc->length - qtd->isoc_split_offset; + + /* For non-dword aligned buffers */ -+ if (((uint32_t)hc->xfer_buff & 0x3) && hcd->core_if->dma_enable) { -+ ptr = (uint8_t *) urb->buf + frame_desc->offset + qtd->isoc_split_offset; -+ } -+ else -+ ptr = NULL; -+ ++ if (((unsigned long)hc->xfer_buff & 0x3) ++ && hcd->core_if->dma_enable) { ++ ptr = ++ (uint8_t *) urb->buf + frame_desc->offset + ++ qtd->isoc_split_offset; ++ } else ++ ptr = NULL; ++ + if (hc->xact_pos == DWC_HCSPLIT_XACTPOS_ALL) { + if (hc->xfer_len <= 188) { + hc->xact_pos = DWC_HCSPLIT_XACTPOS_ALL; @@ -51803,25 +63350,21 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + buf_size = 4096; + } + if (!qh->dw_align_buf) { -+ qh->dw_align_buf = -+ dwc_dma_alloc_atomic(buf_size, -+ &qh->dw_align_buf_dma); ++ qh->dw_align_buf = DWC_DMA_ALLOC_ATOMIC(buf_size, ++ &qh->dw_align_buf_dma); + if (!qh->dw_align_buf) { -+ DWC_ERROR("%s: Failed to allocate memory to handle " -+ "non-dword aligned buffer case\n", __func__); -+#ifdef HW2937_WORKAROUND -+ return 0; -+#else ++ DWC_ERROR ++ ("%s: Failed to allocate memory to handle " ++ "non-dword aligned buffer case\n", ++ __func__); + return; -+#endif + } + } + if (!hc->ep_is_in) { + dwc_memcpy(qh->dw_align_buf, ptr, hc->xfer_len); + } + hc->align_buff = qh->dw_align_buf_dma; -+ } -+ else { ++ } else { + hc->align_buff = 0; + } + @@ -51833,184 +63376,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + */ + hc->multi_count = dwc_hb_mult(qh->maxp); + } -+ ++ + if (hcd->core_if->dma_desc_enable) + hc->desc_list_addr = qh->desc_list_dma; -+ ++ + dwc_otg_hc_init(hcd->core_if, hc); + hc->qh = qh; -+#ifdef HW2937_WORKAROUND -+ hcd->hw2937_assigned_channels |= (1 << hc->hc_num); -+ DWC_DEBUGPL(DBG_HW2937, " assign %d -> hw2937_ac %x\n", hc->hc_num, hcd->hw2937_assigned_channels); -+ return 1; -+#endif +} + -+#ifdef HW2937_WORKAROUND -+ -+void debug_halt(void) -+{ -+ spinlock_t mr_lock = SPIN_LOCK_UNLOCKED; -+ unsigned long flags; -+ extern void v6_flush_kern_cache_all(void); -+ -+ spin_lock_irqsave(&mr_lock, flags); -+#ifdef CONFIG_MACH_BCM2708 -+ v6_flush_kern_cache_all(); -+#endif -+ while (1) continue; -+} -+ -+static -+void dwc_otg_hcd_disable_in_channels(dwc_otg_hcd_t * hcd) -+{ -+ int num_channels = hcd->core_if->core_params->host_channels; -+ static int stall_count = 0; -+ static int max_stall_count = 1; -+ static int last_stalled = 0; -+ int stalled = 0; -+ int i; -+ -+ DWC_DEBUGPL(DBG_HW2937, " Disable In Channels(%x)\n", hcd->hw2937_assigned_channels); -+ -+ for (i = 0; i < num_channels; i++) { -+ if (hcd->hw2937_assigned_channels & (1 << i)) { -+ dwc_hc_t *hc = hcd->hc_ptr_array[i]; -+ if (!hc->halt_pending) { -+ dwc_otg_hc_regs_t *hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num]; -+ hctsiz_data_t hctsiz; -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); -+ DWC_DEBUGPL(DBG_HW2937, "pktcnt %d, xfersize %x, xfer_len %x\n", hctsiz.b.pktcnt, hctsiz.b.xfersize, hc->xfer_len); -+ if (hctsiz.b.pktcnt == hc->start_pkt_count) -+ { -+ dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_PAUSE_IN); -+ } -+ else -+ { -+ /* Unless a receive is in progress */ -+ stalled |= (1< max_stall_count) -+ { -+ max_stall_count = stall_count; -+ DWC_PRINTF( "stall (%x) count -> %d\n", stalled, stall_count); -+ if (stall_count == 10) -+ { -+ debug_halt(); -+ } -+ } -+ } -+ else -+ { -+ stall_count = 0; -+ last_stalled = stalled; -+ } -+} -+ -+static -+int dwc_otg_hcd_update_transaction_mode(dwc_otg_hcd_t * hcd) -+{ -+ dwc_list_link_t *qh_ptr; -+ dwc_otg_qh_t *qh; -+ dwc_otg_qtd_t *qtd; -+ dwc_otg_hcd_urb_t *urb; -+ int found_in = 0; -+ -+ /* If there are any existing out transactions, stay in OUT mode */ -+ if (hcd->hw2937_xfer_mode == HW2937_XFER_MODE_OUT) -+ { -+ return 1; -+ } -+ -+ /* Scan entries in the periodic ready list. */ -+ qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready); -+ -+ while (qh_ptr != &hcd->periodic_sched_ready) { -+ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); -+ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); -+ urb = qtd->urb; -+ if (!dwc_otg_hcd_is_pipe_in(&urb->pipe_info)) { -+ /* Switch to OUT mode */ -+ switch (hcd->hw2937_xfer_mode) -+ { -+ case HW2937_XFER_MODE_IDLE: -+ DWC_DEBUGPL(DBG_HW2937, "utm -> OUT\n"); -+ hcd->hw2937_xfer_mode = HW2937_XFER_MODE_OUT; -+ /* Drop through... */ -+ case HW2937_XFER_MODE_OUT: -+ return 1; -+ case HW2937_XFER_MODE_IN: -+ DWC_DEBUGPL(DBG_HW2937, "utm - halting %x INs\n", hcd->hw2937_assigned_channels); -+ /* Disable the channels with outstanding INs */ -+ dwc_otg_hcd_disable_in_channels(hcd); -+ -+ DWC_DEBUGPL(DBG_HW2937, "utm -> PAUSEIN\n"); -+ hcd->hw2937_xfer_mode = HW2937_XFER_MODE_PAUSEIN; -+ /* Drop through... */ -+ case HW2937_XFER_MODE_PAUSEIN: -+ /* Delay until the halt completes */ -+ return 0; -+ } -+ } -+ found_in = 1; -+ qh_ptr = DWC_LIST_NEXT(qh_ptr); -+ } -+ -+ /* -+ * Scan entries in the inactive portion of the non-periodic -+ * schedule. -+ */ -+ qh_ptr = hcd->non_periodic_sched_inactive.next; -+ while (qh_ptr != &hcd->non_periodic_sched_inactive) { -+ qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); -+ qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list); -+ urb = qtd->urb; -+ if (!dwc_otg_hcd_is_pipe_in(&urb->pipe_info)) { -+ /* Switch to OUT mode */ -+ switch (hcd->hw2937_xfer_mode) -+ { -+ case HW2937_XFER_MODE_IDLE: -+ DWC_DEBUGPL(DBG_HW2937, "utm -> OUT\n"); -+ hcd->hw2937_xfer_mode = HW2937_XFER_MODE_OUT; -+ /* Drop through... */ -+ case HW2937_XFER_MODE_OUT: -+ return 1; -+ case HW2937_XFER_MODE_IN: -+ DWC_DEBUGPL(DBG_HW2937, "utm - halting %x INs\n", hcd->hw2937_assigned_channels); -+ /* Disable the channels with outstanding INs */ -+ dwc_otg_hcd_disable_in_channels(hcd); -+ -+ DWC_DEBUGPL(DBG_HW2937, "utm -> PAUSEIN\n"); -+ hcd->hw2937_xfer_mode = HW2937_XFER_MODE_PAUSEIN; -+ /* Drop through... */ -+ case HW2937_XFER_MODE_PAUSEIN: -+ /* Delay until the halt completes */ -+ return 0; -+ } -+ } -+ found_in = 1; -+ qh_ptr = DWC_LIST_NEXT(qh_ptr); -+ } -+ -+ if (found_in && (hcd->hw2937_xfer_mode == HW2937_XFER_MODE_IDLE)) -+ { -+ DWC_DEBUGPL(DBG_HW2937, "utm -> IN\n"); -+ hcd->hw2937_xfer_mode = HW2937_XFER_MODE_IN; -+ } -+ return 1; -+} -+ -+#endif /* HW2937_WORKAROUND */ -+ +/** + * This function selects transactions from the HCD transfer schedule and + * assigns them to available host channels. It is called from HCD interrupt @@ -52025,64 +63398,53 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + dwc_list_link_t *qh_ptr; + dwc_otg_qh_t *qh; + int num_channels; ++ dwc_irqflags_t flags; ++ dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC(); + dwc_otg_transaction_type_e ret_val = DWC_OTG_TRANSACTION_NONE; -+#ifdef SOF_FIX -+ dwc_otg_core_if_t *core_if = hcd->core_if; -+ gintmsk_data_t gintmsk = {.d32 = 0}; -+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; -+#endif + +#ifdef DEBUG_SOF + DWC_DEBUGPL(DBG_HCD, " Select Transactions\n"); +#endif + -+#ifdef HW2937_WORKAROUND -+ if (!dwc_otg_hcd_update_transaction_mode(hcd)) -+ { -+ return ret_val; -+ } -+#endif ++#ifdef DEBUG_HOST_CHANNELS ++ last_sel_trans_num_per_scheduled = 0; ++ last_sel_trans_num_nonper_scheduled = 0; ++ last_sel_trans_num_avail_hc_at_start = hcd->available_host_channels; ++#endif /* DEBUG_HOST_CHANNELS */ + + /* Process entries in the periodic ready list. */ + qh_ptr = DWC_LIST_FIRST(&hcd->periodic_sched_ready); + + while (qh_ptr != &hcd->periodic_sched_ready && + !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { ++ if (microframe_schedule) { ++ // Make sure we leave one channel for non periodic transactions. ++ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); ++ if (hcd->available_host_channels <= 1) { ++ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); ++ break; ++ } ++ hcd->available_host_channels--; ++ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); ++#ifdef DEBUG_HOST_CHANNELS ++ last_sel_trans_num_per_scheduled++; ++#endif /* DEBUG_HOST_CHANNELS */ ++ } + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); -+#ifdef HW2937_WORKAROUND -+ if (assign_and_init_hc(hcd, qh)) { -+#else + assign_and_init_hc(hcd, qh); -+#endif + + /* + * Move the QH from the periodic ready schedule to the + * periodic assigned schedule. + */ + qh_ptr = DWC_LIST_NEXT(qh_ptr); ++ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); + DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, + &qh->qh_list_entry); ++ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); + + ret_val = DWC_OTG_TRANSACTION_PERIODIC; -+#ifdef HW2937_WORKAROUND -+ } else { -+ qh_ptr = DWC_LIST_NEXT(qh_ptr); -+ } -+#endif + } -+#ifdef SOF_FIX -+ /* -+ * If there are transactions queued then enable the SOF interrupt to send them to -+ * the controller. -+ */ -+ if (ret_val != DWC_OTG_TRANSACTION_NONE) -+ { -+ // turn on Start-of-Frame interrupt -+ gintmsk.d32 = dwc_read_reg32(&global_regs->gintmsk); -+ gintmsk.b.sofintr |= 1; -+ dwc_write_reg32(&global_regs->gintmsk, gintmsk.d32); -+ } -+#endif + + /* + * Process entries in the inactive portion of the non-periodic @@ -52092,25 +63454,37 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + 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 < ++ (microframe_schedule || hcd->non_periodic_channels < + num_channels - hcd->periodic_channels) && + !DWC_CIRCLEQ_EMPTY(&hcd->free_hc_list)) { + ++ if (microframe_schedule) { ++ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); ++ if (hcd->available_host_channels < 1) { ++ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); ++ break; ++ } ++ hcd->available_host_channels--; ++ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); ++#ifdef DEBUG_HOST_CHANNELS ++ last_sel_trans_num_nonper_scheduled++; ++#endif /* DEBUG_HOST_CHANNELS */ ++ } + qh = DWC_LIST_ENTRY(qh_ptr, dwc_otg_qh_t, qh_list_entry); + -+#ifdef HW2937_WORKAROUND -+ if (assign_and_init_hc(hcd, qh)) { -+#else + assign_and_init_hc(hcd, qh); -+#endif + + /* + * Move the QH from the non-periodic inactive schedule to the + * non-periodic active schedule. + */ + qh_ptr = DWC_LIST_NEXT(qh_ptr); ++ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); + DWC_LIST_MOVE_HEAD(&hcd->non_periodic_sched_active, + &qh->qh_list_entry); ++ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); ++ ++ g_np_sent++; + + if (ret_val == DWC_OTG_TRANSACTION_NONE) { + ret_val = DWC_OTG_TRANSACTION_NON_PERIODIC; @@ -52118,16 +63492,18 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + ret_val = DWC_OTG_TRANSACTION_ALL; + } + -+ hcd->non_periodic_channels++; -+#ifdef HW2937_WORKAROUND -+ } else { -+ qh_ptr = DWC_LIST_NEXT(qh_ptr); -+ } -+#endif ++ if (!microframe_schedule) ++ hcd->non_periodic_channels++; + } + ++#ifdef DEBUG_HOST_CHANNELS ++ last_sel_trans_num_avail_hc_at_end = hcd->available_host_channels; ++#endif /* DEBUG_HOST_CHANNELS */ ++ ++ DWC_SPINLOCK_FREE(channel_lock); + return ret_val; +} ++ +/** + * Attempts to queue a single transaction request for a host channel + * associated with either a periodic or non-periodic transfer. This function @@ -52153,12 +63529,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + + if (hcd->core_if->dma_enable) { + if (hcd->core_if->dma_desc_enable) { -+ if (!hc->xfer_started || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) { ++ if (!hc->xfer_started ++ || (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)) { + dwc_otg_hcd_start_xfer_ddma(hcd, hc->qh); + hc->qh->ping_state = 0; + } -+ } -+ else if (!hc->xfer_started) { ++ } else if (!hc->xfer_started) { + dwc_otg_hc_start_transfer(hcd->core_if, hc); + hc->qh->ping_state = 0; + } @@ -52220,7 +63596,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + + DWC_DEBUGPL(DBG_HCDV, "Queue periodic transactions\n"); +#ifdef DEBUG -+ tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts); ++ tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts); + DWC_DEBUGPL(DBG_HCDV, + " P Tx Req Queue Space Avail (before queue): %d\n", + tx_status.b.ptxqspcavail); @@ -52230,7 +63606,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + + qh_ptr = hcd->periodic_sched_assigned.next; + while (qh_ptr != &hcd->periodic_sched_assigned) { -+ tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts); ++ tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts); + if (tx_status.b.ptxqspcavail == 0) { + no_queue_space = 1; + break; @@ -52283,7 +63659,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + global_regs = hcd->core_if->core_global_regs; + intr_mask.b.ptxfempty = 1; +#ifdef DEBUG -+ tx_status.d32 = dwc_read_reg32(&host_regs->hptxsts); ++ tx_status.d32 = DWC_READ_REG32(&host_regs->hptxsts); + DWC_DEBUGPL(DBG_HCDV, + " P Tx Req Queue Space Avail (after queue): %d\n", + tx_status.b.ptxqspcavail); @@ -52300,7 +63676,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + * level to ensure that new requests are loaded as + * soon as possible.) + */ -+ dwc_modify_reg32(&global_regs->gintmsk, 0, ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, + intr_mask.d32); + } else { + /* @@ -52310,7 +63686,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + * handlers to queue more transactions as transfer + * states change. + */ -+ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, + 0); + } + } @@ -52338,7 +63714,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + + DWC_DEBUGPL(DBG_HCDV, "Queue non-periodic transactions\n"); +#ifdef DEBUG -+ tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts); ++ tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts); + DWC_DEBUGPL(DBG_HCDV, + " NP Tx Req Queue Space Avail (before queue): %d\n", + tx_status.b.nptxqspcavail); @@ -52359,7 +63735,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + * available in the request queue or the Tx FIFO. + */ + do { -+ tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts); ++ tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts); + if (!hcd->core_if->dma_enable && tx_status.b.nptxqspcavail == 0) { + no_queue_space = 1; + break; @@ -52392,7 +63768,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + intr_mask.b.nptxfempty = 1; + +#ifdef DEBUG -+ tx_status.d32 = dwc_read_reg32(&global_regs->gnptxsts); ++ tx_status.d32 = DWC_READ_REG32(&global_regs->gnptxsts); + DWC_DEBUGPL(DBG_HCDV, + " NP Tx Req Queue Space Avail (after queue): %d\n", + tx_status.b.nptxqspcavail); @@ -52408,7 +63784,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + * level to ensure that new requests are loaded as + * soon as possible.) + */ -+ dwc_modify_reg32(&global_regs->gintmsk, 0, ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, + intr_mask.d32); + } else { + /* @@ -52418,7 +63794,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + * handlers to queue more transactions as transfer + * states change. + */ -+ dwc_modify_reg32(&global_regs->gintmsk, intr_mask.d32, ++ DWC_MODIFY_REG32(&global_regs->gintmsk, intr_mask.d32, + 0); + } + } @@ -52434,7 +63810,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + * periodic, or both). + */ +void dwc_otg_hcd_queue_transactions(dwc_otg_hcd_t * hcd, -+ dwc_otg_transaction_type_e tr_type) ++ dwc_otg_transaction_type_e tr_type) +{ +#ifdef DEBUG_SOF + DWC_DEBUGPL(DBG_HCD, "Queue Transactions\n"); @@ -52459,12 +63835,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + */ + gintmsk_data_t gintmsk = {.d32 = 0 }; + gintmsk.b.nptxfempty = 1; -+ dwc_modify_reg32(&hcd->core_if->core_global_regs-> -+ gintmsk, gintmsk.d32, 0); ++ DWC_MODIFY_REG32(&hcd->core_if-> ++ core_global_regs->gintmsk, gintmsk.d32, ++ 0); + } + } +} -+ ++ +#ifdef DWC_HS_ELECT_TST +/* + * Quick and dirty hack to implement the HS Electrical Test @@ -52493,70 +63870,70 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + hcint_data_t hcint; + + /* Enable HAINTs */ -+ dwc_write_reg32(&hc_global_regs->haintmsk, 0x0001); ++ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001); + + /* Enable HCINTs */ -+ dwc_write_reg32(&hc_regs->hcintmsk, 0x04a3); ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3); + + /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + + /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); + + /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); + + /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + + /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); + + /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); + + /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); + + /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + + /* + * Send Setup packet (Get Device Descriptor) + */ + + /* Make sure channel is disabled */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + if (hcchar.b.chen) { + hcchar.b.chdis = 1; +// hcchar.b.chen = 1; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); + //sleep(1); + dwc_mdelay(1000); + + /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + + /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); + + /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); + + /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + + /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); + + /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); + + /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); + -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + } + + /* Set HCTSIZ */ @@ -52564,56 +63941,55 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + hctsiz.b.xfersize = 8; + hctsiz.b.pktcnt = 1; + hctsiz.b.pid = DWC_OTG_HC_PID_SETUP; -+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); + + /* Set HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; + hcchar.b.epdir = 0; + hcchar.b.epnum = 0; + hcchar.b.mps = 8; + hcchar.b.chen = 1; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); + + /* Fill FIFO with Setup data for Get Device Descriptor */ + data_fifo = (uint32_t *) ((char *)global_regs + 0x1000); -+ dwc_write_reg32(data_fifo++, 0x01000680); -+ dwc_write_reg32(data_fifo++, 0x00080000); ++ DWC_WRITE_REG32(data_fifo++, 0x01000680); ++ DWC_WRITE_REG32(data_fifo++, 0x00080000); + -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + + /* Wait for host channel interrupt */ + do { -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + } while (gintsts.b.hcintr == 0); + -+ + /* Disable HCINTs */ -+ dwc_write_reg32(&hc_regs->hcintmsk, 0x0000); ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000); + + /* Disable HAINTs */ -+ dwc_write_reg32(&hc_global_regs->haintmsk, 0x0000); ++ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000); + + /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); + + /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); + + /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + + /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); + + /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); + + /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); + + /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); +} + +static void do_in_ack(void) @@ -52626,70 +64002,70 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + host_grxsts_data_t grxsts; + + /* Enable HAINTs */ -+ dwc_write_reg32(&hc_global_regs->haintmsk, 0x0001); ++ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0001); + + /* Enable HCINTs */ -+ dwc_write_reg32(&hc_regs->hcintmsk, 0x04a3); ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x04a3); + + /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + + /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); + + /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); + + /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + + /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); + + /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); + + /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); + + /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + + /* + * Receive Control In packet + */ + + /* Make sure channel is disabled */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + if (hcchar.b.chen) { + hcchar.b.chdis = 1; + hcchar.b.chen = 1; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); + //sleep(1); + dwc_mdelay(1000); + + /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + + /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); + + /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); + + /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + + /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); + + /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); + + /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); + -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + } + + /* Set HCTSIZ */ @@ -52697,32 +64073,31 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + hctsiz.b.xfersize = 8; + hctsiz.b.pktcnt = 1; + hctsiz.b.pid = DWC_OTG_HC_PID_DATA1; -+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); + + /* Set HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; + hcchar.b.epdir = 1; + hcchar.b.epnum = 0; + hcchar.b.mps = 8; + hcchar.b.chen = 1; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); + -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + + /* Wait for receive status queue interrupt */ + do { -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + } while (gintsts.b.rxstsqlvl == 0); + -+ + /* Read RXSTS */ -+ grxsts.d32 = dwc_read_reg32(&global_regs->grxstsp); ++ grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp); + + /* Clear RXSTSQLVL in GINTSTS */ + gintsts.d32 = 0; + gintsts.b.rxstsqlvl = 1; -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); + + switch (grxsts.b.pktsts) { + case DWC_GRXSTS_PKTSTS_IN: @@ -52734,7 +64109,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + data_fifo = (uint32_t *) ((char *)global_regs + 0x1000); + + for (i = 0; i < word_count; i++) { -+ (void)dwc_read_reg32(data_fifo++); ++ (void)DWC_READ_REG32(data_fifo++); + } + } + break; @@ -52743,21 +64118,20 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + break; + } + -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + + /* Wait for receive status queue interrupt */ + do { -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + } while (gintsts.b.rxstsqlvl == 0); + -+ + /* Read RXSTS */ -+ grxsts.d32 = dwc_read_reg32(&global_regs->grxstsp); ++ grxsts.d32 = DWC_READ_REG32(&global_regs->grxstsp); + + /* Clear RXSTSQLVL in GINTSTS */ + gintsts.d32 = 0; + gintsts.b.rxstsqlvl = 1; -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); + + switch (grxsts.b.pktsts) { + case DWC_GRXSTS_PKTSTS_IN_XFER_COMP: @@ -52767,34 +64141,33 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + break; + } + -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + + /* Wait for host channel interrupt */ + do { -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + } while (gintsts.b.hcintr == 0); + -+ + /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); + + /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); + + /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + + /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); + + /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); + + /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); + + /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + +// usleep(100000); +// mdelay(100); @@ -52805,57 +64178,57 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + */ + + /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); + + /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); + + /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + + /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); + + /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); + + /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); + + /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + + /* Make sure channel is disabled */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + if (hcchar.b.chen) { + hcchar.b.chdis = 1; + hcchar.b.chen = 1; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); + //sleep(1); + dwc_mdelay(1000); + + /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + + /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); + + /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); + + /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + + /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); + + /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); + + /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); + -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + } + + /* Set HCTSIZ */ @@ -52863,51 +64236,50 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + hctsiz.b.xfersize = 0; + hctsiz.b.pktcnt = 1; + hctsiz.b.pid = DWC_OTG_HC_PID_DATA1; -+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32); ++ DWC_WRITE_REG32(&hc_regs->hctsiz, hctsiz.d32); + + /* Set HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + hcchar.b.eptype = DWC_OTG_EP_TYPE_CONTROL; + hcchar.b.epdir = 0; + hcchar.b.epnum = 0; + hcchar.b.mps = 8; + hcchar.b.chen = 1; -+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32); ++ DWC_WRITE_REG32(&hc_regs->hcchar, hcchar.d32); + -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + + /* Wait for host channel interrupt */ + do { -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); + } while (gintsts.b.hcintr == 0); + -+ + /* Disable HCINTs */ -+ dwc_write_reg32(&hc_regs->hcintmsk, 0x0000); ++ DWC_WRITE_REG32(&hc_regs->hcintmsk, 0x0000); + + /* Disable HAINTs */ -+ dwc_write_reg32(&hc_global_regs->haintmsk, 0x0000); ++ DWC_WRITE_REG32(&hc_global_regs->haintmsk, 0x0000); + + /* Read HAINT */ -+ haint.d32 = dwc_read_reg32(&hc_global_regs->haint); ++ haint.d32 = DWC_READ_REG32(&hc_global_regs->haint); + + /* Read HCINT */ -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); + + /* Read HCCHAR */ -+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar); ++ hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar); + + /* Clear HCINT */ -+ dwc_write_reg32(&hc_regs->hcint, hcint.d32); ++ DWC_WRITE_REG32(&hc_regs->hcint, hcint.d32); + + /* Clear HAINT */ -+ dwc_write_reg32(&hc_global_regs->haint, haint.d32); ++ DWC_WRITE_REG32(&hc_global_regs->haint, haint.d32); + + /* Clear GINTSTS */ -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); + + /* Read GINTSTS */ -+ gintsts.d32 = dwc_read_reg32(&global_regs->gintsts); ++ gintsts.d32 = DWC_READ_REG32(&global_regs->gintsts); +} +#endif + @@ -52954,23 +64326,27 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + "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); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); + break; + case UHF_PORT_SUSPEND: + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "ClearPortFeature USB_PORT_FEAT_SUSPEND\n"); + -+ dwc_write_reg32(core_if->pcgcctl, 0); -+ dwc_mdelay(5); ++ if (core_if->power_down == 2) { ++ dwc_otg_host_hibernation_restore(core_if, 0, 0); ++ } else { ++ DWC_WRITE_REG32(core_if->pcgcctl, 0); ++ dwc_mdelay(5); + -+ hprt0.d32 = dwc_otg_read_hprt0(core_if); -+ hprt0.b.prtres = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ hprt0.b.prtsusp = 0; -+ /* Clear Resume bit */ -+ dwc_mdelay(100); -+ hprt0.b.prtres = 0; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtres = 1; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ hprt0.b.prtsusp = 0; ++ /* Clear Resume bit */ ++ dwc_mdelay(100); ++ hprt0.b.prtres = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ } + break; +#ifdef CONFIG_USB_DWC_OTG_LPM + case UHF_PORT_L1: @@ -52979,24 +64355,25 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + glpmcfg_data_t lpmcfg = {.d32 = 0 }; + + lpmcfg.d32 = -+ dwc_read_reg32(&core_if->core_global_regs-> -+ glpmcfg); ++ DWC_READ_REG32(&core_if-> ++ core_global_regs->glpmcfg); + lpmcfg.b.en_utmi_sleep = 0; + lpmcfg.b.hird_thres &= (~(1 << 4)); + lpmcfg.b.prt_sleep_sts = 1; -+ dwc_write_reg32(&core_if->core_global_regs-> -+ glpmcfg, lpmcfg.d32); ++ DWC_WRITE_REG32(&core_if-> ++ core_global_regs->glpmcfg, ++ lpmcfg.d32); + + /* Clear Enbl_L1Gating bit. */ + pcgcctl.b.enbl_sleep_gating = 1; -+ dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32, ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, + 0); + + dwc_mdelay(5); + + hprt0.d32 = dwc_otg_read_hprt0(core_if); + hprt0.b.prtres = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, ++ DWC_WRITE_REG32(core_if->host_if->hprt0, + hprt0.d32); + /* This bit will be cleared in wakeup interrupt handle */ + break; @@ -53007,7 +64384,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + "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); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); + break; + case UHF_PORT_INDICATOR: + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " @@ -53080,7 +64457,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + break; + case UCR_GET_PORT_STATUS: + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "GetPortStatus\n"); ++ "GetPortStatus wIndex = 0x%04x FLAGS=0x%08x\n", ++ wIndex, dwc_otg_hcd->flags.d32); + if (!wIndex || wIndex > 1) + goto error; + @@ -53103,7 +64481,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + } + + if (dwc_otg_hcd->flags.b.port_over_current_change) { -+ DWC_ERROR("Device Not Supported\n"); ++ DWC_WARN("Overcurrent change detected\n"); + port_status |= (1 << UHF_C_PORT_OVER_CURRENT); + } + @@ -53119,7 +64497,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + break; + } + -+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0); ++ hprt0.d32 = DWC_READ_REG32(core_if->host_if->hprt0); + DWC_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32); + + if (hprt0.b.prtconnsts) @@ -53150,7 +64528,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + if (dwc_otg_get_lpm_portsleepstatus(dwc_otg_hcd->core_if)) { + port_status |= (1 << UHF_PORT_L1); + } -+ ++ /* ++ For Synopsys HW emulation of Power down wkup_control asserts the ++ hreset_n and prst_n on suspned. This causes the HPRT0 to be zero. ++ We intentionally tell the software that port is in L2Suspend state. ++ Only for STE. ++ */ ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ port_status |= (1 << UHF_PORT_SUSPEND); ++ } + /* USB_PORT_FEAT_INDICATOR unsupported always 0 */ + + *((__le32 *) buf) = dwc_cpu_to_le32(&port_status); @@ -53180,19 +64567,149 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + case UHF_PORT_SUSPEND: + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " + "SetPortFeature - USB_PORT_FEAT_SUSPEND\n"); ++ if (dwc_otg_hcd_otg_port(dwc_otg_hcd) != wIndex) { ++ goto error; ++ } ++ if (core_if->power_down == 2) { ++ int timeout = 300; ++ dwc_irqflags_t flags; ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ gusbcfg_data_t gusbcfg = {.d32 = 0 }; ++#ifdef DWC_DEV_SRPCAP ++ int32_t otg_cap_param = core_if->core_params->otg_cap; ++#endif ++ DWC_PRINTF("Preparing for complete power-off\n"); ++ ++ /* Save registers before hibernation */ ++ dwc_otg_save_global_regs(core_if); ++ dwc_otg_save_host_regs(core_if); ++ ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtsusp = 1; ++ hprt0.b.prtena = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ /* Spin hprt0.b.prtsusp to became 1 */ ++ do { ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ if (hprt0.b.prtsusp) { ++ break; ++ } ++ dwc_mdelay(1); ++ } while (--timeout); ++ if (!timeout) { ++ DWC_WARN("Suspend wasn't genereted\n"); ++ } ++ dwc_udelay(10); ++ ++ /* ++ * We need to disable interrupts to prevent servicing of any IRQ ++ * during going to hibernation ++ */ ++ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); ++ core_if->lx_state = DWC_OTG_L2; ++#ifdef DWC_DEV_SRPCAP ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ hprt0.b.prtpwr = 0; ++ hprt0.b.prtena = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, ++ hprt0.d32); ++#endif ++ gusbcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs-> ++ gusbcfg); ++ if (gusbcfg.b.ulpi_utmi_sel == 1) { ++ /* ULPI interface */ ++ /* Suspend the Phy Clock */ ++ pcgcctl.d32 = 0; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, ++ pcgcctl.d32); ++ dwc_udelay(10); ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ } else { ++ /* UTMI+ Interface */ ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, pcgcctl.d32); ++ dwc_udelay(10); ++ } ++#ifdef DWC_DEV_SRPCAP ++ gpwrdn.d32 = 0; ++ gpwrdn.b.dis_vbus = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++#endif ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ gpwrdn.d32 = 0; ++#ifdef DWC_DEV_SRPCAP ++ gpwrdn.b.srp_det_msk = 1; ++#endif ++ gpwrdn.b.disconn_det_msk = 1; ++ gpwrdn.b.lnstchng_msk = 1; ++ gpwrdn.b.sts_chngint_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Enable Power Down Clamp and all interrupts in GPWRDN */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnclmp = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ dwc_udelay(10); ++ ++ /* Switch off VDD */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++#ifdef DWC_DEV_SRPCAP ++ if (otg_cap_param == DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) ++ { ++ core_if->pwron_timer_started = 1; ++ DWC_TIMER_SCHEDULE(core_if->pwron_timer, 6000 /* 6 secs */ ); ++ } ++#endif ++ /* Save gpwrdn register for further usage if stschng interrupt */ ++ core_if->gr_backup->gpwrdn_local = ++ DWC_READ_REG32(&core_if->core_global_regs->gpwrdn); ++ ++ /* Set flag to indicate that we are in hibernation */ ++ core_if->hibernation_suspend = 1; ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock,flags); ++ ++ DWC_PRINTF("Host hibernation completed\n"); ++ // Exit from case statement ++ break; ++ ++ } + if (dwc_otg_hcd_otg_port(dwc_otg_hcd) == wIndex && + dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) { + gotgctl_data_t gotgctl = {.d32 = 0 }; + gotgctl.b.hstsethnpen = 1; -+ dwc_modify_reg32(&core_if->core_global_regs-> ++ 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_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); + { -+ uint64_t flags; ++ dwc_irqflags_t flags; + /* Update lx_state */ + DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); + core_if->lx_state = DWC_OTG_L2; @@ -53202,64 +64719,111 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + { + pcgcctl_data_t pcgcctl = {.d32 = 0 }; + pcgcctl.b.stoppclk = 1; -+ dwc_modify_reg32(core_if->pcgcctl, 0, ++ DWC_MODIFY_REG32(core_if->pcgcctl, 0, + pcgcctl.d32); ++ dwc_udelay(10); + } + + /* For HNP the bus must be suspended for at least 200ms. */ + if (dwc_otg_hcd->fops->get_b_hnp_enable(dwc_otg_hcd)) { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); + dwc_mdelay(200); + } ++ ++ /** @todo - check how sw can wait for 1 sec to check asesvld??? */ ++#if 0 //vahrama !!!!!!!!!!!!!!!!!! ++ if (core_if->adp_enable) { ++ gotgctl_data_t gotgctl = {.d32 = 0 }; ++ gpwrdn_data_t gpwrdn; ++ ++ while (gotgctl.b.asesvld == 1) { ++ gotgctl.d32 = ++ DWC_READ_REG32(&core_if-> ++ core_global_regs-> ++ gotgctl); ++ dwc_mdelay(100); ++ } ++ ++ /* Enable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++ /* Unmask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs-> ++ gpwrdn, 0, gpwrdn.d32); ++ ++ dwc_otg_adp_probe_start(core_if); ++ } ++#endif + break; + case UHF_PORT_POWER: + 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); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); + break; + case UHF_PORT_RESET: -+ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " -+ "SetPortFeature - USB_PORT_FEAT_RESET\n"); -+ { -+ pcgcctl_data_t pcgcctl = {.d32 = 0 }; -+ pcgcctl.b.enbl_sleep_gating = 1; -+ pcgcctl.b.stoppclk = 1; -+ dwc_modify_reg32(core_if->pcgcctl, pcgcctl.d32, -+ 0); -+ dwc_write_reg32(core_if->pcgcctl, 0); -+ } -+#ifdef CONFIG_USB_DWC_OTG_LPM -+ { -+ glpmcfg_data_t lpmcfg; -+ lpmcfg.d32 = -+ dwc_read_reg32(&core_if->core_global_regs-> -+ glpmcfg); -+ if (lpmcfg.b.prt_sleep_sts) { -+ lpmcfg.b.en_utmi_sleep = 0; -+ lpmcfg.b.hird_thres &= (~(1 << 4)); -+ dwc_write_reg32(&core_if-> -+ core_global_regs-> -+ glpmcfg, lpmcfg.d32); -+ dwc_mdelay(1); ++ if ((core_if->power_down == 2) ++ && (core_if->hibernation_suspend == 1)) { ++ /* If we are going to exit from Hibernated ++ * state via USB RESET. ++ */ ++ dwc_otg_host_hibernation_restore(core_if, 0, 1); ++ } else { ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ ++ DWC_DEBUGPL(DBG_HCD, ++ "DWC OTG HCD HUB CONTROL - " ++ "SetPortFeature - USB_PORT_FEAT_RESET\n"); ++ { ++ pcgcctl_data_t pcgcctl = {.d32 = 0 }; ++ pcgcctl.b.enbl_sleep_gating = 1; ++ pcgcctl.b.stoppclk = 1; ++ DWC_MODIFY_REG32(core_if->pcgcctl, pcgcctl.d32, 0); ++ DWC_WRITE_REG32(core_if->pcgcctl, 0); ++ } ++#ifdef CONFIG_USB_DWC_OTG_LPM ++ { ++ glpmcfg_data_t lpmcfg; ++ lpmcfg.d32 = ++ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); ++ if (lpmcfg.b.prt_sleep_sts) { ++ lpmcfg.b.en_utmi_sleep = 0; ++ lpmcfg.b.hird_thres &= (~(1 << 4)); ++ DWC_WRITE_REG32 ++ (&core_if->core_global_regs->glpmcfg, ++ lpmcfg.d32); ++ dwc_mdelay(1); ++ } + } -+ } +#endif -+ 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 (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) { -+ hprt0.b.prtrst = 1; -+ dwc_write_reg32(core_if->host_if->hprt0, -+ hprt0.d32); ++ hprt0.d32 = dwc_otg_read_hprt0(core_if); ++ /* Clear suspend bit if resetting from suspended state. */ ++ hprt0.b.prtsusp = 0; ++ /* 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 (!dwc_otg_hcd_is_b_host(dwc_otg_hcd)) { ++ hprt0.b.prtpwr = 1; ++ hprt0.b.prtrst = 1; ++ DWC_PRINTF("Indeed it is in host mode hprt0 = %08x\n",hprt0.d32); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, ++ hprt0.d32); ++ } ++ /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */ ++ dwc_mdelay(60); ++ hprt0.b.prtrst = 0; ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); ++ core_if->lx_state = DWC_OTG_L0; /* Now back to the on state */ + } -+ /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */ -+ dwc_mdelay(60); -+ hprt0.b.prtrst = 0; -+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); -+ core_if->lx_state = DWC_OTG_L0; /* Now back to the on state */ + break; +#ifdef DWC_HS_ELECT_TST + case UHF_PORT_TEST: @@ -53276,7 +64840,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + if (t < 6) { + hprt0.d32 = dwc_otg_read_hprt0(core_if); + hprt0.b.prttstctl = t; -+ dwc_write_reg32(core_if->host_if->hprt0, ++ DWC_WRITE_REG32(core_if->host_if->hprt0, + hprt0.d32); + } else { + /* Setup global vars with reg addresses (quick and @@ -53296,14 +64860,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + if (t == 6) { /* HS_HOST_PORT_SUSPEND_RESUME */ + /* Save current interrupt mask */ + gintmsk.d32 = -+ dwc_read_reg32 ++ DWC_READ_REG32 + (&global_regs->gintmsk); + + /* Disable all interrupts while we muck with + * the hardware directly + */ -+ dwc_write_reg32(&global_regs-> -+ gintmsk, 0); ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); + + /* 15 second delay per the test spec */ + dwc_mdelay(15000); @@ -53313,9 +64876,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + dwc_otg_read_hprt0(core_if); + hprt0.b.prtsusp = 1; + hprt0.b.prtres = 0; -+ dwc_write_reg32(core_if-> -+ host_if->hprt0, -+ hprt0.d32); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); + + /* 15 second delay per the test spec */ + dwc_mdelay(15000); @@ -53325,32 +64886,25 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + dwc_otg_read_hprt0(core_if); + hprt0.b.prtsusp = 0; + hprt0.b.prtres = 1; -+ dwc_write_reg32(core_if-> -+ host_if->hprt0, -+ hprt0.d32); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); + dwc_mdelay(100); + + /* Clear the resume bit */ + hprt0.b.prtres = 0; -+ dwc_write_reg32(core_if-> -+ host_if->hprt0, -+ hprt0.d32); ++ DWC_WRITE_REG32(core_if->host_if->hprt0, hprt0.d32); + + /* Restore interrupts */ -+ dwc_write_reg32(&global_regs-> -+ gintmsk, -+ gintmsk.d32); ++ DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32); + } else if (t == 7) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */ + /* Save current interrupt mask */ + gintmsk.d32 = -+ dwc_read_reg32 ++ DWC_READ_REG32 + (&global_regs->gintmsk); + + /* Disable all interrupts while we muck with + * the hardware directly + */ -+ dwc_write_reg32(&global_regs-> -+ gintmsk, 0); ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); + + /* 15 second delay per the test spec */ + dwc_mdelay(15000); @@ -53362,20 +64916,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + dwc_mdelay(15000); + + /* Restore interrupts */ -+ dwc_write_reg32(&global_regs-> -+ gintmsk, -+ gintmsk.d32); ++ DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32); + } else if (t == 8) { /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */ + /* Save current interrupt mask */ + gintmsk.d32 = -+ dwc_read_reg32 ++ DWC_READ_REG32 + (&global_regs->gintmsk); + + /* Disable all interrupts while we muck with + * the hardware directly + */ -+ dwc_write_reg32(&global_regs-> -+ gintmsk, 0); ++ DWC_WRITE_REG32(&global_regs->gintmsk, 0); + + /* Send the Setup packet */ + do_setup(); @@ -53390,14 +64941,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + dwc_mdelay(15000); + + /* Restore interrupts */ -+ dwc_write_reg32(&global_regs-> -+ gintmsk, -+ gintmsk.d32); ++ DWC_WRITE_REG32(&global_regs->gintmsk, gintmsk.d32); + } + } + break; + } -+#endif /* DWC_HS_ELECT_TST */ ++#endif /* DWC_HS_ELECT_TST */ + + case UHF_PORT_INDICATOR: + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD HUB CONTROL - " @@ -53432,7 +64981,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + } + /* Check if the port currently is in SLEEP state */ + lpmcfg.d32 = -+ dwc_read_reg32(&core_if->core_global_regs->glpmcfg); ++ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); + if (lpmcfg.b.prt_sleep_sts) { + DWC_INFO("Port is already in sleep mode\n"); + buf[0] = 0; /* Return success */ @@ -53458,7 +65007,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + /* Disable LPM interrupt */ + gintmsk.d32 = 0; + gintmsk.b.lpmtranrcvd = 1; -+ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, + gintmsk.d32, 0); + + if (dwc_otg_hcd_send_lpm @@ -53475,8 +65024,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + */ + do { + gintsts.d32 = -+ dwc_read_reg32(&core_if->core_global_regs-> -+ gintsts); ++ DWC_READ_REG32(&core_if->core_global_regs->gintsts); + if (gintsts.b.lpmtranrcvd) { + break; + } @@ -53494,8 +65042,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + dwc_otg_hcd_free_hc_from_lpm(dwc_otg_hcd); + } else { + lpmcfg.d32 = -+ dwc_read_reg32(&core_if->core_global_regs-> -+ glpmcfg); ++ DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); + if (lpmcfg.b.lpm_resp == 0x3) { + /* ACK responce from the device */ + buf[0] = 0x00; /* Success */ @@ -53509,14 +65056,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + } + DWC_PRINTF("Device responce to LPM trans is %x\n", + lpmcfg.b.lpm_resp); -+ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, 0, ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, + gintmsk.d32); + + break; + } -+#endif /* CONFIG_USB_DWC_OTG_LPM */ ++#endif /* CONFIG_USB_DWC_OTG_LPM */ + default: -+ error: ++error: + retval = -DWC_E_INVALID; + DWC_WARN("DWC OTG HCD - " + "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n", @@ -53545,7 +65092,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + + /* Mask host channel interrupts. */ + gintmsk.b.hcintr = 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); + + /* Fill fields that core needs for LPM transaction */ + hcchar.b.devaddr = devaddr; @@ -53554,7 +65101,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + hcchar.b.mps = 64; + hcchar.b.lspddev = (hc->speed == DWC_OTG_EP_SPEED_LOW); + hcchar.b.epdir = 0; /* OUT */ -+ dwc_write_reg32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar, ++ DWC_WRITE_REG32(&core_if->host_if->hc_regs[hc->hc_num]->hcchar, + hcchar.d32); + + /* Remove the host channel from the free list. */ @@ -53572,7 +65119,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + glpmcfg_data_t lpmcfg; + uint8_t hc_num; + -+ lpmcfg.d32 = dwc_read_reg32(&hcd->core_if->core_global_regs->glpmcfg); ++ lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg); + hc_num = lpmcfg.b.lpm_chan_index; + + hc = hcd->hc_ptr_array[hc_num]; @@ -53595,10 +65142,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + } + + pcgcctl.b.enbl_sleep_gating = 1; -+ dwc_modify_reg32(hcd->core_if->pcgcctl, 0, pcgcctl.d32); ++ DWC_MODIFY_REG32(hcd->core_if->pcgcctl, 0, pcgcctl.d32); + + /* Read LPM config register */ -+ lpmcfg.d32 = dwc_read_reg32(&hcd->core_if->core_global_regs->glpmcfg); ++ lpmcfg.d32 = DWC_READ_REG32(&hcd->core_if->core_global_regs->glpmcfg); + + /* Program LPM transaction fields */ + lpmcfg.b.rem_wkup_en = bRemoteWake; @@ -53607,16 +65154,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + lpmcfg.b.lpm_chan_index = channel; + lpmcfg.b.en_utmi_sleep = 1; + /* Program LPM config register */ -+ dwc_write_reg32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32); + + /* Send LPM transaction */ + lpmcfg.b.send_lpm = 1; -+ dwc_write_reg32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++ DWC_WRITE_REG32(&hcd->core_if->core_global_regs->glpmcfg, lpmcfg.d32); + + return 0; +} + -+#endif /* CONFIG_USB_DWC_OTG_LPM */ ++#endif /* CONFIG_USB_DWC_OTG_LPM */ + +int dwc_otg_hcd_is_status_changed(dwc_otg_hcd_t * hcd, int port) +{ @@ -53653,8 +65200,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 +int dwc_otg_hcd_get_frame_number(dwc_otg_hcd_t * dwc_otg_hcd) +{ + hfnum_data_t hfnum; -+ hfnum.d32 = dwc_read_reg32(&dwc_otg_hcd->core_if-> -+ host_if->host_global_regs->hfnum); ++ hfnum.d32 = ++ DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs-> ++ hfnum); + +#ifdef DEBUG_SOF + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD GET FRAME NUMBER %d\n", @@ -53669,7 +65217,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + int retval = 0; + + hcd->fops = fops; -+ if (!dwc_otg_is_device_mode(hcd->core_if)) { ++ if (!dwc_otg_is_device_mode(hcd->core_if) && ++ (!hcd->core_if->adp_enable || hcd->core_if->adp.adp_started)) { + dwc_otg_hcd_reinit(hcd); + } else { + retval = -DWC_E_NO_DEVICE; @@ -53714,12 +65263,21 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + size = + sizeof(*dwc_otg_urb) + + iso_desc_count * sizeof(struct dwc_otg_hcd_iso_packet_desc); -+ if (atomic_alloc) { -+ dwc_otg_urb = dwc_alloc_atomic(size); -+ } else { -+ dwc_otg_urb = dwc_alloc(size); -+ } -+ dwc_otg_urb->packet_count = iso_desc_count; ++ if (atomic_alloc) ++ dwc_otg_urb = DWC_ALLOC_ATOMIC(size); ++ else ++ dwc_otg_urb = DWC_ALLOC(size); ++ ++ if (NULL != dwc_otg_urb) ++ dwc_otg_urb->packet_count = iso_desc_count; ++ else { ++ dwc_otg_urb->packet_count = 0; ++ if (size != 0) { ++ DWC_ERROR("**** DWC OTG HCD URB alloc - " ++ "%salloc of %db failed\n", ++ atomic_alloc?"atomic ":"", size); ++ } ++ } + + return dwc_otg_urb; +} @@ -53867,20 +65425,20 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + hcint_data_t hcint; + hcintmsk_data_t hcintmsk; + hfnum.d32 = -+ dwc_read_reg32(&hcd->core_if->host_if-> -+ host_global_regs->hfnum); ++ 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); ++ 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); ++ 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); ++ 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_READ_REG32(&hcd->core_if->host_if-> ++ hc_regs[i]->hcintmsk); + DWC_PRINTF(" hfnum: 0x%08x\n", hfnum.d32); + DWC_PRINTF(" hcchar: 0x%08x\n", hcchar.d32); + DWC_PRINTF(" hctsiz: 0x%08x\n", hctsiz.d32); @@ -53892,7 +65450,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + dwc_otg_hcd_urb_t *urb; + + DWC_CIRCLEQ_FOREACH(qtd, &hc->qh->qtd_list, qtd_list_entry) { -+ if(!qtd->in_process) ++ if (!qtd->in_process) + break; + + urb = qtd->urb; @@ -53916,23 +65474,23 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 + (void *)urb->dma); + DWC_PRINTF(" transfer_buffer_length: %d\n", + urb->length); -+ DWC_PRINTF(" actual_length: %d\n", -+ urb->actual_length); ++ DWC_PRINTF(" actual_length: %d\n", ++ urb->actual_length); ++ } + } + } + } -+ } + DWC_PRINTF(" non_periodic_channels: %d\n", hcd->non_periodic_channels); + DWC_PRINTF(" periodic_channels: %d\n", hcd->periodic_channels); + DWC_PRINTF(" periodic_usecs: %d\n", hcd->periodic_usecs); + np_tx_status.d32 = -+ dwc_read_reg32(&hcd->core_if->core_global_regs->gnptxsts); ++ DWC_READ_REG32(&hcd->core_if->core_global_regs->gnptxsts); + DWC_PRINTF(" NP Tx Req Queue Space Avail: %d\n", + np_tx_status.b.nptxqspcavail); + DWC_PRINTF(" 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); ++ DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hptxsts); + DWC_PRINTF(" P Tx Req Queue Space Avail: %d\n", + p_tx_status.b.ptxqspcavail); + DWC_PRINTF(" P Tx FIFO Space Avail: %d\n", p_tx_status.b.ptxfspcavail); @@ -54068,1126 +65626,18 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.c linux-rpi-bootc-3 +#endif +} + -+#endif /* DWC_DEVICE_ONLY */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c 2012-07-15 20:29:19.150084862 +0200 -@@ -0,0 +1,1106 @@ -+/*========================================================================== -+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $ -+ * $Revision: #2 $ -+ * $Date: 2009/04/21 $ -+ * $Change: 1237473 $ -+ * -+ * 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 -+ * with Synopsys or any supplement thereto. You are permitted to use and -+ * redistribute this Software in source and binary forms, with or without -+ * modification, provided that redistributions of source code must retain this -+ * notice. You may not view, use, disclose, copy or distribute this file or -+ * any information contained herein except pursuant to this license grant from -+ * Synopsys. If you do not agree with this notice, including the disclaimer -+ * below, then you are not authorized to use the Software. -+ * -+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, -+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -+ * DAMAGE. -+ * ========================================================================== */ -+#ifndef DWC_DEVICE_ONLY -+ -+/** @file -+ * This file contains Descriptor DMA support implementation for host mode. -+ */ -+ -+#include "dwc_otg_hcd.h" -+#include "dwc_otg_regs.h" -+ -+ -+static inline uint8_t frame_list_idx(uint16_t frame) -+{ -+ return (frame & (MAX_FRLIST_EN_NUM - 1)); -+} -+ -+static inline uint16_t desclist_idx_inc(uint16_t idx, uint16_t inc, uint8_t speed) -+{ -+ return (idx + inc) & -+ (((speed == DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC) - 1); -+} -+ -+static inline uint16_t desclist_idx_dec(uint16_t idx, uint16_t inc, uint8_t speed) -+{ -+ return (idx - inc) & -+ (((speed == DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC) - 1); -+} -+ -+static inline uint16_t max_desc_num(dwc_otg_qh_t * qh) -+{ -+ return (((qh->ep_type == UE_ISOCHRONOUS) && (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH)) -+ ? -+ MAX_DMA_DESC_NUM_HS_ISOC -+ : -+ MAX_DMA_DESC_NUM_GENERIC); -+} -+static inline uint16_t frame_incr_val(dwc_otg_qh_t * qh) -+{ -+ return ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) -+ ? ((qh->interval + 8 - 1) / 8) -+ : -+ qh->interval); -+} -+ -+static int desc_list_alloc(dwc_otg_qh_t * qh) -+{ -+ int retval = 0; -+ -+ qh->desc_list = (dwc_otg_host_dma_desc_t *) -+ dwc_dma_alloc(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh), -+ &qh->desc_list_dma -+ ); -+ -+ if (!qh->desc_list) { -+ retval = -DWC_E_NO_MEMORY; -+ DWC_ERROR("%s: DMA descriptor list allocation failed\n", __func__); -+ -+ } -+ -+ dwc_memset(qh->desc_list, 0x00, sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh)); -+ -+ -+ qh->n_bytes = (uint32_t *) dwc_alloc(sizeof(uint32_t) * max_desc_num(qh)); -+ -+ if (!qh->n_bytes) { -+ retval = -DWC_E_NO_MEMORY; -+ DWC_ERROR("%s: Failed to allocate array for descriptors' size actual values\n", -+ __func__); -+ -+ } -+ return retval; -+ -+} -+ -+static void desc_list_free(dwc_otg_qh_t * qh) -+{ -+ if(qh->desc_list) { -+ dwc_dma_free(max_desc_num(qh), qh->desc_list, qh->desc_list_dma); -+ qh->desc_list = NULL; -+ } -+ -+ if (qh->n_bytes) { -+ dwc_free(qh->n_bytes); -+ qh->n_bytes = NULL; -+ } -+} -+ -+static int frame_list_alloc(dwc_otg_hcd_t * hcd) -+{ -+ int retval = 0; -+ if (hcd->frame_list) -+ return 0; -+ -+ hcd->frame_list = dwc_dma_alloc(4 * MAX_FRLIST_EN_NUM, -+ &hcd->frame_list_dma -+ ); -+ if (!hcd->frame_list) { -+ retval = -DWC_E_NO_MEMORY; -+ DWC_ERROR("%s: Frame List allocation failed\n", __func__); -+ } -+ -+ dwc_memset(hcd->frame_list, 0x00, 4 * MAX_FRLIST_EN_NUM); -+ -+ return retval; -+} -+ -+static void frame_list_free(dwc_otg_hcd_t * hcd) -+{ -+ if (!hcd->frame_list) -+ return; -+ -+ dwc_dma_free(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma); -+ hcd->frame_list = NULL; -+} -+ -+static void per_sched_enable(dwc_otg_hcd_t * hcd, uint16_t fr_list_en) -+{ -+ -+ hcfg_data_t hcfg; -+ -+ hcfg.d32 = dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hcfg); -+ -+ if (hcfg.b.perschedstat) { -+ /* already enabled*/ -+ return; -+ } -+ -+ dwc_write_reg32(&hcd->core_if->host_if->host_global_regs->hflbaddr, hcd->frame_list_dma); -+ -+ switch(fr_list_en) { -+ case 64: -+ hcfg.b.frlisten = 3; -+ break; -+ case 32: -+ hcfg.b.frlisten = 2; -+ break; -+ case 16: -+ hcfg.b.frlisten = 1; -+ case 8: -+ hcfg.b.frlisten = 0; -+ default: -+ break; -+ } -+ -+ hcfg.b.perschedena = 1; -+ -+ DWC_DEBUGPL(DBG_HCD, "Enabling Periodic schedule\n"); -+ dwc_write_reg32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32); -+ -+} -+ -+static void per_sched_disable(dwc_otg_hcd_t * hcd) -+{ -+ hcfg_data_t hcfg; -+ -+ hcfg.d32 = dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hcfg); -+ -+ if (!hcfg.b.perschedstat) { -+ /* already disabled */ -+ return; -+ } -+ hcfg.b.perschedena = 0; -+ -+ DWC_DEBUGPL(DBG_HCD, "Disabling Periodic schedule\n"); -+ dwc_write_reg32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32); -+} -+ -+/* -+ * Activates/Deactivates FrameList entries for the channel -+ * based on endpoint servicing period. -+ */ -+void update_frame_list(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t enable) -+{ -+ uint16_t i, j, inc; -+ dwc_hc_t *hc = qh->channel; -+ -+ inc = frame_incr_val(qh); -+ -+ if (qh->ep_type == UE_ISOCHRONOUS) -+ i = frame_list_idx(qh->sched_frame); -+ else -+ i = 0; -+ -+ j = i; -+ do { -+ if (enable) -+ hcd->frame_list[j] |= (1 << hc->hc_num); -+ else -+ hcd->frame_list[j] &= ~(1 << hc->hc_num); -+ j = (j + inc) & (MAX_FRLIST_EN_NUM - 1); -+ } -+ while (j != i); -+ -+ if (!enable) -+ return; -+ -+ hc->schinfo = 0; -+ if (qh->channel->speed == DWC_OTG_EP_SPEED_HIGH) { -+ j = 1; -+ for (i = 0 ; i < 8 / qh->interval; i++) { -+ hc->schinfo |= j; -+ j = j << qh->interval; -+ } -+ } -+ else { -+ hc->schinfo = 0xff; -+ } -+} -+#if 1 -+void dump_frame_list(dwc_otg_hcd_t * hcd) -+{ -+ int i = 0; -+ DWC_PRINTF("--FRAME LIST (hex) --\n"); -+ for (i = 0; i < MAX_FRLIST_EN_NUM; i++) { -+ DWC_PRINTF("%x\t",hcd->frame_list[i]); -+ if (!(i % 8) && i) -+ DWC_PRINTF("\n"); -+ } -+ DWC_PRINTF("\n----\n"); -+ -+} -+#endif -+ -+static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ dwc_hc_t *hc = qh->channel; -+ if (dwc_qh_is_non_per(qh)) { -+ hcd->non_periodic_channels--; -+ } -+ else { -+ update_frame_list(hcd, qh, 0); -+ } -+ /* -+ * The condition is added to prevent double cleanup try in case of device -+ * disconnect. See channel cleanup in dwc_otg_hcd_disconnect_cb(). -+ */ -+ if (hc->qh) { -+ dwc_otg_hc_cleanup(hcd->core_if, hc); -+ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); -+ hc->qh = NULL; -+ } -+ -+ qh->channel = NULL; -+ qh->ntd = 0; -+ -+ if (qh->desc_list) { -+ dwc_memset(qh->desc_list, 0x00, -+ sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh)); -+ } -+} -+ -+/** -+ * Initializes a QH structure's Descriptor DMA related members. -+ * Allocates memory for descriptor list. -+ * On first periodic QH, allocates memory for FrameList -+ * and enables periodic scheduling. -+ * -+ * @param hcd The HCD state structure for the DWC OTG controller. -+ * @param qh The QH to init. -+ * -+ * @return 0 if successful, negative error code otherwise. -+ */ -+int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ int retval = 0; -+ -+ if (qh->do_split) { -+ DWC_ERROR("SPLIT Transfers are not supported in Descriptor DMA.\n"); -+ return -1; -+ } -+ -+ retval = desc_list_alloc(qh); -+ -+ if ((retval == 0) && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) { -+ if(!hcd->frame_list) { -+ retval = frame_list_alloc(hcd); -+ /* Enable periodic schedule on first periodic QH */ -+ if (retval == 0) -+ per_sched_enable(hcd, MAX_FRLIST_EN_NUM); -+ } -+ } -+ -+ qh->ntd = 0; -+ -+ return retval; -+} -+ -+/** -+ * Frees descriptor list memory associated with the QH. -+ * If QH is periodic and the last, frees FrameList memory -+ * and disables periodic scheduling. -+ * -+ * @param hcd The HCD state structure for the DWC OTG controller. -+ * @param qh The QH to init. -+ */ -+void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ desc_list_free(qh); -+ -+ /* -+ * Channel still assigned due to some reasons. -+ * Seen on Isoc URB dequeue. Channel halted but no subsequent -+ * ChHalted interrupt to release the channel. Afterwards -+ * when it comes here from endpoint disable routine -+ * channel remains assigned. -+ */ -+ if (qh->channel) -+ release_channel_ddma(hcd, qh); -+ -+ if ((qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT) -+ && !hcd->periodic_channels && hcd->frame_list) { -+ -+ per_sched_disable(hcd); -+ frame_list_free(hcd); -+ } -+} -+ -+static uint8_t frame_to_desc_idx(dwc_otg_qh_t * qh, uint16_t frame_idx) -+{ -+ if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) { -+ /* -+ * Descriptor set(8 descriptors) index -+ * which is 8-aligned. -+ */ -+ return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8; -+ } -+ else { -+ return (frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1)); -+ } -+} -+ -+/* -+ * Determine starting frame for Isochronous transfer. -+ * Few frames skipped to prevent race condition with HC. -+ */ -+static uint8_t calc_starting_frame(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t* skip_frames) -+{ -+ uint16_t frame = 0; -+ hcd->frame_number = dwc_otg_hcd_get_frame_number(hcd); -+ -+ /* sched_frame is always frame number(not uFrame) both in FS and HS !! */ -+ -+ /* -+ * skip_frames is used to limit activated descriptors number -+ * to avoid the situation when HC services the last activated -+ * descriptor firstly. -+ * Example for FS: -+ * Current frame is 1, scheduled frame is 3. Since HC always fetches the descriptor -+ * corresponding to curr_frame+1, the descriptor corresponding to frame 2 -+ * will be fetched. If the number of descriptors is max=64 (or greather) the list will -+ * be fully programmed with Active descriptors and it is possible case(rare) that the latest -+ * descriptor(considering rollback) corresponding to frame 2 will be serviced first. -+ * HS case is more probable because, in fact, up to 11 uframes(16 in the code) -+ * may be skipped. -+ */ -+ if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) { -+ /* -+ * Consider uframe counter also, to start xfer asap. -+ * If half of the frame elapsed skip 2 frames otherwise -+ * just 1 frame. -+ * Starting descriptor index must be 8-aligned, so -+ * if the current frame is near to complete the next one -+ * is skipped as well. -+ */ -+ -+ if (dwc_micro_frame_num(hcd->frame_number) >= 5) { -+ *skip_frames = 2 * 8; -+ frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames); -+ } -+ else { -+ *skip_frames = 1 * 8; -+ frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames); -+ } -+ -+ frame = dwc_full_frame_num(frame); -+ } else { -+ /* -+ * Two frames are skipped for FS - the current and the next. -+ * But for descriptor programming, 1 frame(descriptor) is enough, -+ * see example above. -+ */ -+ *skip_frames = 1; -+ frame = dwc_frame_num_inc(hcd->frame_number, 2); -+ } -+ -+ return frame; -+} -+/* -+ * Calculate initial descriptor index for isochronous transfer -+ * based on scheduled frame. -+ */ -+static uint8_t recalc_initial_desc_idx(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ uint16_t frame = 0, fr_idx, fr_idx_tmp; -+ uint8_t skip_frames = 0 ; -+ /* -+ * With current ISOC processing algorithm the channel is being -+ * released when no more QTDs in the list(qh->ntd == 0). -+ * Thus this function is called only when qh->ntd == 0 and qh->channel == 0. -+ * -+ * So qh->channel != NULL branch is not used and just not removed from the -+ * source file. It is required for another possible approach which is, -+ * do not disable and release the channel when ISOC session completed, -+ * just move QH to inactive schedule until new QTD arrives. -+ * On new QTD, the QH moved back to 'ready' schedule, -+ * starting frame and therefore starting desc_index are recalculated. -+ * In this case channel is released only on ep_disable. -+ */ -+ -+ /* Calculate starting descriptor index. For INTERRUPT endpoint it is always 0. */ -+ if (qh->channel) { -+ frame = calc_starting_frame(hcd, qh, &skip_frames); -+ /* -+ * Calculate initial descriptor index based on FrameList current bitmap -+ * and servicing period. -+ */ -+ fr_idx_tmp = frame_list_idx(frame); -+ fr_idx = (MAX_FRLIST_EN_NUM + frame_list_idx(qh->sched_frame) - fr_idx_tmp) -+ % frame_incr_val(qh); -+ fr_idx = (fr_idx + fr_idx_tmp) % MAX_FRLIST_EN_NUM; -+ } -+ else { -+ qh->sched_frame = calc_starting_frame(hcd, qh, &skip_frames); -+ fr_idx = frame_list_idx(qh->sched_frame); -+ } -+ -+ qh->td_first = qh->td_last = frame_to_desc_idx(qh, fr_idx); -+ -+ return skip_frames; -+} -+ -+#define ISOC_URB_GIVEBACK_ASAP -+ -+#define MAX_ISOC_XFER_SIZE_FS 1023 -+#define MAX_ISOC_XFER_SIZE_HS 3072 -+#define DESCNUM_THRESHOLD 4 -+ -+static void init_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t skip_frames) -+{ -+ struct dwc_otg_hcd_iso_packet_desc *frame_desc; -+ dwc_otg_qtd_t *qtd; -+ dwc_otg_host_dma_desc_t *dma_desc; -+ uint16_t idx, inc, n_desc, ntd_max, max_xfer_size; -+ -+ idx = qh->td_last; -+ inc = qh->interval; -+ n_desc = 0; -+ -+ ntd_max = (max_desc_num(qh) + qh->interval - 1) / qh->interval; -+ if (skip_frames && !qh->channel) -+ ntd_max = ntd_max - skip_frames / qh->interval; -+ -+ max_xfer_size = (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) ? MAX_ISOC_XFER_SIZE_HS -+ : MAX_ISOC_XFER_SIZE_FS; -+ -+ DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) { -+ while ((qh->ntd < ntd_max) && (qtd->isoc_frame_index_last < qtd->urb->packet_count)) { -+ -+ dma_desc = &qh->desc_list[idx]; -+ dwc_memset(dma_desc, 0x00, sizeof(dwc_otg_host_dma_desc_t)); -+ -+ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last]; -+ -+ if (frame_desc->length > max_xfer_size) -+ qh->n_bytes[idx] = max_xfer_size; -+ else -+ qh->n_bytes[idx] = frame_desc->length; -+ dma_desc->status.b_isoc.n_bytes = qh->n_bytes[idx]; -+ dma_desc->status.b_isoc.a = 1; -+ -+ dma_desc->buf = qtd->urb->dma + frame_desc->offset; -+ -+ qh->ntd++; -+ -+ qtd->isoc_frame_index_last++; -+ -+ #ifdef ISOC_URB_GIVEBACK_ASAP -+ /* -+ * Set IOC for each descriptor corresponding to the -+ * last frame of the URB. -+ */ -+ if (qtd->isoc_frame_index_last == qtd->urb->packet_count) -+ dma_desc->status.b_isoc.ioc = 1; -+ -+ #endif -+ idx = desclist_idx_inc(idx, inc, qh->dev_speed); -+ n_desc++; -+ -+ } -+ qtd->in_process = 1; -+ } -+ -+ qh->td_last = idx; -+ -+#ifdef ISOC_URB_GIVEBACK_ASAP -+ /* Set IOC for the last descriptor if descriptor list is full */ -+ if (qh->ntd == ntd_max) { -+ idx = desclist_idx_dec(qh->td_last, inc, qh->dev_speed); -+ qh->desc_list[idx].status.b_isoc.ioc = 1; -+ } -+#else -+ /* -+ * Set IOC bit only for one descriptor. -+ * Always try to be ahead of HW processing, -+ * i.e. on IOC generation driver activates next descriptors but -+ * core continues to process descriptors followed the one with IOC set. -+ */ -+ -+ if (n_desc > DESCNUM_THRESHOLD) { -+ /* -+ * Move IOC "up". Required even if there is only one QTD -+ * in the list, cause QTDs migth continue to be queued, -+ * but during the activation it was only one queued. -+ * Actually more than one QTD might be in the list if this function called -+ * from XferCompletion - QTDs was queued during HW processing of the previous -+ * descriptor chunk. -+ */ -+ idx = dwc_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2), qh->dev_speed); -+ } -+ else { -+ /* -+ * Set the IOC for the latest descriptor -+ * if either number of descriptor is not greather than threshold -+ * or no more new descriptors activated. -+ */ -+ idx = dwc_desclist_idx_dec(qh->td_last, inc, qh->dev_speed); -+ } -+ -+ qh->desc_list[idx].status.b_isoc.ioc = 1; -+#endif -+} -+ -+ -+static void init_non_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ -+ dwc_hc_t *hc; -+ dwc_otg_host_dma_desc_t *dma_desc; -+ dwc_otg_qtd_t *qtd; -+ int num_packets, len, n_desc = 0; -+ -+ hc = qh->channel; -+ -+ /* -+ * Start with hc->xfer_buff initialized in -+ * assign_and_init_hc(), then if SG transfer consists of multiple URBs, -+ * this pointer re-assigned to the buffer of the currently processed QTD. -+ * For non-SG request there is always one QTD active. -+ */ -+ -+ DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) { -+ -+ if (n_desc) { -+ /* SG request - more than 1 QTDs */ -+ hc->xfer_buff = (uint8_t *)qtd->urb->dma + qtd->urb->actual_length; -+ hc->xfer_len = qtd->urb->length - qtd->urb->actual_length; -+ } -+ -+ qtd->n_desc = 0; -+ -+ do { -+ dma_desc = &qh->desc_list[n_desc]; -+ len = hc->xfer_len; -+ -+ -+ if (len > MAX_DMA_DESC_SIZE) -+ len = MAX_DMA_DESC_SIZE - hc->max_packet + 1; -+ -+ if (hc->ep_is_in) { -+ if (len > 0) { -+ num_packets = (len + hc->max_packet - 1) / hc->max_packet; -+ } -+ else { -+ /* Need 1 packet for transfer length of 0. */ -+ num_packets = 1; -+ } -+ /* Always program an integral # of max packets for IN transfers. */ -+ len = num_packets * hc->max_packet; -+ } -+ -+ dma_desc->status.b.n_bytes = len; -+ -+ qh->n_bytes[n_desc] = len; -+ -+ -+ if ((qh->ep_type == UE_CONTROL) && (qtd->control_phase == DWC_OTG_CONTROL_SETUP)) -+ dma_desc->status.b.sup = 1; /* Setup Packet */ -+ -+ dma_desc->status.b.a = 1; /* Active descriptor */ -+ -+ dma_desc->buf = (uint32_t) hc->xfer_buff; -+ -+ /* -+ * Last descriptor(or single) of IN transfer -+ * with actual size less than MaxPacket. -+ */ -+ if (len > hc->xfer_len) { -+ hc->xfer_len = 0; -+ } -+ else { -+ hc->xfer_buff += len; -+ hc->xfer_len -= len; -+ } -+ -+ qtd->n_desc++; -+ n_desc++; -+ } -+ while ((hc->xfer_len > 0) && (n_desc != MAX_DMA_DESC_NUM_GENERIC)); -+ -+ -+ qtd->in_process = 1; -+ -+ if (n_desc == MAX_DMA_DESC_NUM_GENERIC) -+ break; -+ } -+ -+ if (n_desc) { -+ /* Request Transfer Complete interrupt for the last descriptor */ -+ qh->desc_list[n_desc-1].status.b.ioc = 1; -+ /* End of List indicator */ -+ qh->desc_list[n_desc-1].status.b.eol = 1; -+ -+ hc->ntd = n_desc; -+ } -+} -+ -+/** -+ * For Control and Bulk endpoints initializes descriptor list -+ * and starts the transfer. -+ * -+ * For Interrupt and Isochronous endpoints initializes descriptor list -+ * then updates FrameList, marking appropriate entries as active. -+ * In case of Isochronous, the starting descriptor index is calculated based -+ * on the scheduled frame, but only on the first transfer descriptor within a session. -+ * Then starts the transfer via enabling the channel. -+ * For Isochronous endpoint the channel is not halted on XferComplete -+ * interrupt so remains assigned to the endpoint(QH) until session is done. -+ * -+ * @param hcd The HCD state structure for the DWC OTG controller. -+ * @param qh The QH to init. -+ * -+ * @return 0 if successful, negative error code otherwise. -+ */ -+void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) -+{ -+ /* Channel is already assigned */ -+ dwc_hc_t *hc = qh->channel; -+ uint8_t skip_frames = 0; -+ -+ switch (hc->ep_type) { -+ case DWC_OTG_EP_TYPE_CONTROL: -+ case DWC_OTG_EP_TYPE_BULK: -+ init_non_isoc_dma_desc(hcd, qh); -+ -+ dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); -+ break; -+ case DWC_OTG_EP_TYPE_INTR: -+ init_non_isoc_dma_desc(hcd, qh); -+ -+ update_frame_list(hcd, qh, 1); -+ -+ dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); -+ break; -+ case DWC_OTG_EP_TYPE_ISOC: -+ -+ if(!qh->ntd) -+ skip_frames = recalc_initial_desc_idx(hcd, qh); -+ -+ init_isoc_dma_desc(hcd, qh, skip_frames); -+ -+ if (!hc->xfer_started) { -+ -+ update_frame_list(hcd, qh, 1); -+ -+ /* -+ * Always set to max, instead of actual size. -+ * Otherwise ntd will be changed with -+ * channel being enabled. Not recommended. -+ * -+ */ -+ hc->ntd = max_desc_num(qh); -+ /* Enable channel only once for ISOC */ -+ dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); -+ } -+ -+ break; -+ default: -+ -+ break; -+ } -+} -+ -+static void complete_isoc_xfer_ddma(dwc_otg_hcd_t *hcd, -+ dwc_hc_t *hc, -+ dwc_otg_hc_regs_t *hc_regs, -+ dwc_otg_halt_status_e halt_status) -+{ -+ struct dwc_otg_hcd_iso_packet_desc *frame_desc; -+ dwc_otg_qtd_t *qtd, *qtd_tmp; -+ dwc_otg_qh_t *qh; -+ dwc_otg_host_dma_desc_t *dma_desc; -+ uint16_t idx, remain; -+ uint8_t urb_compl; -+ -+ qh = hc->qh; -+ idx = qh->td_first; -+ -+ -+ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { -+ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) -+ qtd->in_process = 0; -+ return; -+ } -+ else if ((halt_status == DWC_OTG_HC_XFER_AHB_ERR) || -+ (halt_status == DWC_OTG_HC_XFER_BABBLE_ERR)) { -+ /* -+ * Channel is halted in these error cases. -+ * Considered as serious issues. -+ * Complete all URBs marking all frames as failed, -+ * irrespective whether some of the descriptors(frames) succeeded or no. -+ * Pass error code to completion routine as well, to -+ * update urb->status, some of class drivers might use it to stop -+ * queing transfer requests. -+ */ -+ int err = (halt_status == DWC_OTG_HC_XFER_AHB_ERR) -+ ? (-DWC_E_IO) -+ : (-DWC_E_OVERFLOW); -+ -+ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { -+ for(idx = 0; idx < qtd->urb->packet_count; idx++) { -+ frame_desc = &qtd->urb->iso_descs[idx]; -+ frame_desc->status = err; -+ } -+ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, err); -+ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); -+ } -+ return; -+ } -+ -+ -+ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { -+ -+ if (!qtd->in_process) -+ break; -+ -+ urb_compl = 0; -+ -+ do { -+ -+ dma_desc = &qh->desc_list[idx]; -+ -+ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; -+ remain = hc->ep_is_in ? dma_desc->status.b_isoc.n_bytes : 0; -+ -+ if (dma_desc->status.b_isoc.sts == DMA_DESC_STS_PKTERR) { -+ /* -+ * XactError or, unable to complete all the transactions -+ * in the scheduled micro-frame/frame, -+ * both indicated by DMA_DESC_STS_PKTERR. -+ */ -+ qtd->urb->error_count++; -+ frame_desc->actual_length = qh->n_bytes[idx] - remain; -+ frame_desc->status = -DWC_E_PROTOCOL; -+ } -+ else { -+ /* Success */ -+ -+ frame_desc->actual_length = qh->n_bytes[idx] - remain; -+ frame_desc->status = 0; -+ } -+ -+ if (++qtd->isoc_frame_index == qtd->urb->packet_count) { -+ /* -+ * urb->status is not used for isoc transfers here. -+ * The individual frame_desc status are used instead. -+ */ -+ -+ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); -+ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); -+ -+ /* -+ * This check is necessary because urb_dequeue can be called -+ * from urb complete callback(sound driver example). -+ * All pending URBs are dequeued there, so no need for -+ * further processing. -+ */ -+ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { -+ return; -+ } -+ -+ urb_compl = 1; -+ -+ } -+ -+ qh->ntd--; -+ -+ /* Stop if IOC requested descriptor reached */ -+ if (dma_desc->status.b_isoc.ioc) { -+ idx = desclist_idx_inc(idx, qh->interval, hc->speed); -+ goto stop_scan; -+ } -+ -+ idx = desclist_idx_inc(idx, qh->interval, hc->speed); -+ -+ if (urb_compl) -+ break; -+ } -+ while(idx != qh->td_first); -+ } -+stop_scan: -+ qh->td_first = idx; -+} -+ -+uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_qtd_t * qtd, -+ dwc_otg_host_dma_desc_t * dma_desc, -+ dwc_otg_halt_status_e halt_status, -+ uint32_t n_bytes, -+ uint8_t *xfer_done) -+{ -+ -+ uint16_t remain = hc->ep_is_in ? dma_desc->status.b.n_bytes : 0; -+ dwc_otg_hcd_urb_t *urb = qtd->urb; -+ -+ -+ if (halt_status == DWC_OTG_HC_XFER_AHB_ERR) { -+ urb->status = -DWC_E_IO; -+ return 1; -+ } -+ if (dma_desc->status.b.sts == DMA_DESC_STS_PKTERR) { -+ switch (halt_status) { -+ case DWC_OTG_HC_XFER_STALL: -+ urb->status = -DWC_E_PIPE; -+ break; -+ case DWC_OTG_HC_XFER_BABBLE_ERR: -+ urb->status = -DWC_E_OVERFLOW; -+ break; -+ case DWC_OTG_HC_XFER_XACT_ERR: -+ urb->status = -DWC_E_PROTOCOL; -+ break; -+ default: -+ DWC_ERROR("%s: Unhandled descriptor error status (%d)\n", __func__, -+ halt_status); -+ break; -+ } -+ return 1; -+ } -+ -+ if (dma_desc->status.b.a == 1) { -+ DWC_DEBUGPL(DBG_HCDV, "Active descriptor encountered on channel %d\n", hc->hc_num); -+ return 0; -+ } -+ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL) { -+ if (qtd->control_phase == DWC_OTG_CONTROL_DATA) { -+ urb->actual_length += n_bytes - remain; -+ if (remain || urb->actual_length >= urb->length) { -+ /* -+ * For Control Data stage do not set urb->status=0 to prevent -+ * URB callback. Set it when Status phase done. See below. -+ */ -+ *xfer_done = 1; -+ } -+ -+ } -+ else if (qtd->control_phase == DWC_OTG_CONTROL_STATUS) { -+ urb->status = 0; -+ *xfer_done = 1; -+ } -+ /* No handling for SETUP stage */ -+ -+ } -+ else { -+ /* BULK and INTR */ -+ urb->actual_length += n_bytes - remain; -+ if (remain || urb->actual_length >= urb->length) { -+ urb->status = 0; -+ *xfer_done = 1; -+ } -+ } -+ -+ return 0; -+} -+ -+static void complete_non_isoc_xfer_ddma(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_halt_status_e halt_status) -+{ -+ dwc_otg_hcd_urb_t *urb = NULL; -+ dwc_otg_qtd_t *qtd, *qtd_tmp; -+ dwc_otg_qh_t *qh; -+ dwc_otg_host_dma_desc_t *dma_desc; -+ uint32_t n_bytes, n_desc, i; -+ uint8_t failed = 0, xfer_done; -+ -+ n_desc = 0; -+ -+ qh = hc->qh; -+ -+ -+ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { -+ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { -+ qtd->in_process = 0; -+ } -+ return; -+ } -+ -+ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { -+ -+ urb = qtd->urb; -+ -+ n_bytes = 0; -+ xfer_done = 0; -+ -+ for (i = 0; i < qtd->n_desc; i++) { -+ dma_desc = &qh->desc_list[n_desc]; -+ -+ n_bytes = qh->n_bytes[n_desc]; -+ -+ -+ failed = update_non_isoc_urb_state_ddma(hcd, hc, qtd, dma_desc, -+ halt_status, n_bytes, &xfer_done); -+ -+ if (failed || (xfer_done && (urb->status != -DWC_E_IN_PROGRESS))) { -+ -+ hcd->fops->complete(hcd, urb->priv, urb, urb->status); -+ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); -+ -+ if (failed) -+ goto stop_scan; -+ } -+ else if (qh->ep_type == UE_CONTROL) { -+ if (qtd->control_phase == DWC_OTG_CONTROL_SETUP) { -+ if (urb->length > 0) { -+ qtd->control_phase = DWC_OTG_CONTROL_DATA; -+ } else { -+ qtd->control_phase = DWC_OTG_CONTROL_STATUS; -+ } -+ DWC_DEBUGPL(DBG_HCDV, " Control setup transaction done\n"); -+ } -+ else if(qtd->control_phase == DWC_OTG_CONTROL_DATA) { -+ if (xfer_done) { -+ qtd->control_phase = DWC_OTG_CONTROL_STATUS; -+ DWC_DEBUGPL(DBG_HCDV, " Control data transfer done\n"); -+ } else if (i+1 == qtd->n_desc){ -+ /* -+ * Last descriptor for Control data stage which is -+ * not completed yet. -+ */ -+ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); -+ } -+ } -+ } -+ -+ n_desc++; -+ } -+ -+ } -+ -+stop_scan: -+ -+ if (qh->ep_type != UE_CONTROL) { -+ /* -+ * Resetting the data toggle for bulk -+ * and interrupt endpoints in case of stall. See handle_hc_stall_intr() -+ */ -+ if (halt_status == DWC_OTG_HC_XFER_STALL) { -+ qh->data_toggle = DWC_OTG_HC_PID_DATA0; -+ } -+ else { -+ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); -+ } -+ } -+ -+ if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { -+ hcint_data_t hcint; -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); -+ if (hcint.b.nyet) { -+ /* -+ * Got a NYET on the last transaction of the transfer. It -+ * means that the endpoint should be in the PING state at the -+ * beginning of the next transfer. -+ */ -+ qh->ping_state = 1; -+ clear_hc_int(hc_regs, nyet); -+ } -+ -+ } -+ -+} -+ -+/** -+ * This function is called from interrupt handlers. -+ * Scans the descriptor list, updates URB's status and -+ * calls completion routine for the URB if it's done. -+ * Releases the channel to be used by other transfers. -+ * In case of Isochronous endpoint the channel is not halted until -+ * the end of the session, i.e. QTD list is empty. -+ * If periodic channel released the FrameList is updated accordingly. -+ * -+ * Calls transaction selection routines to activate pending transfers. -+ * -+ * @param hcd The HCD state structure for the DWC OTG controller. -+ * @param hc Host channel, the transfer is completed on. -+ * @param hc_regs Host channel registers. -+ * @param halt_status Reason the channel is being halted, -+ * or just XferComplete for isochronous transfer -+ */ -+void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t *hcd, -+ dwc_hc_t *hc, -+ dwc_otg_hc_regs_t *hc_regs, -+ dwc_otg_halt_status_e halt_status) -+{ -+ uint8_t continue_isoc_xfer = 0; -+ dwc_otg_transaction_type_e tr_type; -+ dwc_otg_qh_t *qh = hc->qh; -+ -+ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { -+ -+ complete_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status); -+ -+ /* Release the channel if halted or session completed */ -+ if (halt_status != DWC_OTG_HC_XFER_COMPLETE || -+ DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { -+ -+ /* Halt the channel if session completed */ -+ if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { -+ dwc_otg_hc_halt(hcd->core_if, hc, halt_status); -+ } -+ -+ release_channel_ddma(hcd, qh); -+ dwc_otg_hcd_qh_remove(hcd, qh); -+ } -+ else { -+ /* Keep in assigned schedule to continue transfer */ -+ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, -+ &qh->qh_list_entry); -+ continue_isoc_xfer = 1; -+ -+ } -+ /** @todo Consider the case when period exceeds FrameList size. -+ * Frame Rollover interrupt should be used. -+ */ -+ } -+ else { -+ /* Scan descriptor list to complete the URB(s), then release the channel */ -+ complete_non_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status); -+ -+ release_channel_ddma(hcd, qh); -+ -+ dwc_otg_hcd_qh_remove(hcd, qh); -+ -+ if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { -+ /* Add back to inactive non-periodic schedule on normal completion */ -+ dwc_otg_hcd_qh_add(hcd, qh); -+ } -+ -+ -+ } -+ tr_type = dwc_otg_hcd_select_transactions(hcd); -+ if (tr_type != DWC_OTG_TRANSACTION_NONE || continue_isoc_xfer) { -+ if (continue_isoc_xfer) { -+ if (tr_type == DWC_OTG_TRANSACTION_NONE) { -+ tr_type = DWC_OTG_TRANSACTION_PERIODIC; -+ } else if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC) { -+ tr_type = DWC_OTG_TRANSACTION_ALL; -+ } -+ } -+ dwc_otg_hcd_queue_transactions(hcd, tr_type); -+ } -+} -+ -+#endif /* DWC_DEVICE_ONLY */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h 2012-07-15 20:29:19.173085296 +0200 -@@ -0,0 +1,813 @@ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h +new file mode 100644 +index 0000000..dd30f47 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h +@@ -0,0 +1,824 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd.h $ -+ * $Revision: #52 $ -+ * $Date: 2009/04/21 $ -+ * $Change: 1237472 $ ++ * $Revision: #58 $ ++ * $Date: 2011/09/15 $ ++ * $Change: 1846647 $ + * + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless @@ -55219,7 +65669,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi-bootc-3 +#ifndef __DWC_HCD_H__ +#define __DWC_HCD_H__ + -+#include ++#include "dwc_otg_os_dep.h" ++#include "usb.h" +#include "dwc_otg_hcd_if.h" +#include "dwc_otg_core_if.h" +#include "dwc_list.h" @@ -55423,17 +65874,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi-bootc-3 + DWC_CIRCLEQ_ENTRY(dwc_otg_qtd) qtd_list_entry; + + /** Indicates if this QTD is currently processed by HW. */ -+ uint8_t in_process; ++ uint8_t in_process; + + /** Number of DMA descriptors for this QTD */ -+ uint8_t n_desc; -+ ++ uint8_t n_desc; ++ + /** + * Last activated frame(packet) index. + * Used in Descriptor DMA mode only. + */ + uint16_t isoc_frame_index_last; -+ ++ +} dwc_otg_qtd_t; + +DWC_CIRCLEQ_HEAD(dwc_otg_qtd_list, dwc_otg_qtd); @@ -55516,55 +65967,50 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi-bootc-3 + */ + uint8_t *dw_align_buf; + dwc_dma_t dw_align_buf_dma; -+ ++ + /** Entry for QH in either the periodic or non-periodic schedule. */ + dwc_list_link_t qh_list_entry; -+ ++ + /** @name Descriptor DMA support */ + /** @{ */ -+ ++ + /** Descriptor List. */ -+ dwc_otg_host_dma_desc_t *desc_list; -+ ++ dwc_otg_host_dma_desc_t *desc_list; ++ + /** Descriptor List physical address. */ + dwc_dma_t desc_list_dma; -+ ++ + /** + * Xfer Bytes array. + * Each element corresponds to a descriptor and indicates + * original XferSize size value for the descriptor. + */ + uint32_t *n_bytes; -+ ++ + /** Actual number of transfer descriptors in a list. */ + uint16_t ntd; -+ ++ + /** First activated isochronous transfer descriptor index. */ + uint8_t td_first; + /** Last activated isochronous transfer descriptor index. */ + uint8_t td_last; -+ ++ + /** @} */ -+ ++ ++ ++ uint16_t speed; ++ uint16_t frame_usecs[8]; +} dwc_otg_qh_t; + +DWC_CIRCLEQ_HEAD(hc_list, dwc_hc); + -+#ifdef HW2937_WORKAROUND -+ -+typedef enum { -+ HW2937_XFER_MODE_IDLE, -+ HW2937_XFER_MODE_IN, -+ HW2937_XFER_MODE_OUT, -+ HW2937_XFER_MODE_PAUSEIN /* Transitioning from IN to IDLE */ -+} hw2937_xfer_mode_t; -+#endif -+ +/** + * This structure holds the state of the HCD, including the non-periodic and + * periodic schedules. + */ +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; + @@ -55659,12 +66105,30 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi-bootc-3 + uint16_t periodic_usecs; + + /** ++ * Total bandwidth claimed so far for all periodic transfers ++ * in a frame. ++ * This will include a mixture of HS and FS transfers. ++ * Units are microseconds per (micro)frame. ++ * We have a budget per frame and have to schedule ++ * transactions accordingly. ++ * Watch out for the fact that things are actually scheduled for the ++ * "next frame". ++ */ ++ uint16_t frame_usecs[8]; ++ ++ ++ /** + * Frame number read from the core at SOF. The value ranges from 0 to + * DWC_HFNUM_MAX_FRNUM. + */ + uint16_t frame_number; + + /** ++ * Count of periodic QHs, if using several eps. For SOF enable/disable. ++ */ ++ uint16_t periodic_qh_count; ++ ++ /** + * Free host channels in the controller. This is a list of + * dwc_hc_t items. + */ @@ -55675,12 +66139,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi-bootc-3 + * transaction and at least one host channel available for + * non-periodic transactions. + */ -+ int periodic_channels; ++ int periodic_channels; /* microframe_schedule==0 */ + + /** + * Number of host channels assigned to non-periodic transfers. + */ -+ int non_periodic_channels; ++ int non_periodic_channels; /* microframe_schedule==0 */ ++ ++ /** ++ * Number of host channels assigned to non-periodic transfers. ++ */ ++ int available_host_channels; + + /** + * Array of pointers to the host channel descriptors. Allows accessing @@ -55728,14 +66197,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi-bootc-3 + /** Frame List DMA address */ + dma_addr_t frame_list_dma; + -+#ifdef HW2937_WORKAROUND -+ /** Current transfer mode (IN, OUT, or IDLE) */ -+ hw2937_xfer_mode_t hw2937_xfer_mode; -+ -+ /** Mask of channels assigned to the current mode */ -+ uint32_t hw2937_assigned_channels; -+#endif -+ +#ifdef DEBUG + uint32_t frrem_samples; + uint64_t frrem_accum; @@ -55754,15 +66215,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi-bootc-3 + uint32_t hfnum_other_samples_b; + uint64_t hfnum_other_frrem_accum_b; +#endif -+#ifdef SOF_FIX -+ /** -+ * SOF wakeup timer. We disable the SOF interrupt if there is nothing -+ * to do. However, that eventually gets us into trouble. So, re-enable -+ * the SOF interrupt every tick so we can handle any backlog that does -+ * not trigger any other interrupt. -+ */ -+ dwc_timer_t *sof_timer; -+#endif +}; + +/** @name Transaction Execution Functions */ @@ -55770,14 +66222,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi-bootc-3 +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); ++ dwc_otg_transaction_type_e tr_type); + +/** @} */ + +/** @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_sof_intr(dwc_otg_hcd_t * dwc_otg_hcd, int32_t); +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 * @@ -55803,7 +66255,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi-bootc-3 + +/* Implemented in dwc_otg_hcd_queue.c */ +extern dwc_otg_qh_t *dwc_otg_hcd_qh_create(dwc_otg_hcd_t * hcd, -+ dwc_otg_hcd_urb_t * urb); ++ dwc_otg_hcd_urb_t * urb, int atomic_alloc); +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); @@ -55814,27 +66266,37 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi-bootc-3 +static inline void dwc_otg_hcd_qh_remove_and_free(dwc_otg_hcd_t * hcd, + dwc_otg_qh_t * qh) +{ ++ dwc_irqflags_t flags; ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); + dwc_otg_hcd_qh_remove(hcd, qh); ++ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); + 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) ++static inline dwc_otg_qh_t *dwc_otg_hcd_qh_alloc(int atomic_alloc) +{ -+ return (dwc_otg_qh_t *) dwc_alloc_atomic(sizeof(dwc_otg_qh_t)); ++ if (atomic_alloc) ++ return (dwc_otg_qh_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qh_t)); ++ else ++ return (dwc_otg_qh_t *) DWC_ALLOC(sizeof(dwc_otg_qh_t)); +} + -+extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb); ++extern dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, ++ int atomic_alloc); +extern void dwc_otg_hcd_qtd_init(dwc_otg_qtd_t * qtd, dwc_otg_hcd_urb_t * urb); +extern int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, dwc_otg_hcd_t * dwc_otg_hcd, -+ dwc_otg_qh_t ** qh); ++ dwc_otg_qh_t ** qh, int atomic_alloc); + +/** 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) ++static inline dwc_otg_qtd_t *dwc_otg_hcd_qtd_alloc(int atomic_alloc) +{ -+ return (dwc_otg_qtd_t *) dwc_alloc_atomic(sizeof(dwc_otg_qtd_t)); ++ if (atomic_alloc) ++ return (dwc_otg_qtd_t *) DWC_ALLOC_ATOMIC(sizeof(dwc_otg_qtd_t)); ++ else ++ return (dwc_otg_qtd_t *) DWC_ALLOC(sizeof(dwc_otg_qtd_t)); +} + +/** Frees the memory for a QTD structure. QTD should already be removed from @@ -55842,7 +66304,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi-bootc-3 + * @param qtd QTD to free.*/ +static inline void dwc_otg_hcd_qtd_free(dwc_otg_qtd_t * qtd) +{ -+ dwc_free(qtd); ++ DWC_FREE(qtd); +} + +/** Removes a QTD from list. @@ -55854,13 +66316,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi-bootc-3 + dwc_otg_qtd_t * qtd, + dwc_otg_qh_t * qh) +{ -+ uint64_t flags; -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); + DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry); -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); +} + -+/** Remove and free a QTD */ ++/** Remove and free a QTD ++ * Need to disable IRQ and hold hcd lock while calling this function out of ++ * interrupt servicing chain */ +static inline void dwc_otg_hcd_qtd_remove_and_free(dwc_otg_hcd_t * hcd, + dwc_otg_qtd_t * qtd, + dwc_otg_qh_t * qh) @@ -55876,15 +66337,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi-bootc-3 + +extern void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); +extern void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_halt_status_e halt_status); ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_halt_status_e halt_status); + +extern int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); +extern void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh); + +/** @} */ -+ ++ +/** @name Internal Functions */ +/** @{ */ +dwc_otg_qh_t *dwc_urb_to_qh(dwc_otg_hcd_urb_t * urb); @@ -55955,8 +66416,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi-bootc-3 +} + +void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd); ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd); + +#ifdef DEBUG +/** @@ -55974,7 +66435,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi-bootc-3 + dwc_otg_qtd_t *qtd; \ + qtd = list_entry(_qh->qtd_list.next, dwc_otg_qtd_t, qtd_list_entry); \ + if (usb_pipeint(qtd->urb->pipe) && _qh->start_split_frame != 0 && !qtd->complete_split) { \ -+ 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); \ + switch (hfnum.b.frnum & 0x7) { \ + case 7: \ + _hcd->hfnum_7_samples_##_letter++; \ @@ -55995,16 +66456,1157 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd.h linux-rpi-bootc-3 +#define dwc_sample_frrem(_hcd, _qh, _letter) +#endif +#endif -+#endif /* DWC_DEVICE_ONLY */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h 2012-07-15 20:29:19.209085970 +0200 -@@ -0,0 +1,393 @@ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c +new file mode 100644 +index 0000000..d0d5fa1 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_ddma.c +@@ -0,0 +1,1133 @@ ++/*========================================================================== ++ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_ddma.c $ ++ * $Revision: #10 $ ++ * $Date: 2011/10/20 $ ++ * $Change: 1869464 $ ++ * ++ * 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 ++ * with Synopsys or any supplement thereto. You are permitted to use and ++ * redistribute this Software in source and binary forms, with or without ++ * modification, provided that redistributions of source code must retain this ++ * notice. You may not view, use, disclose, copy or distribute this file or ++ * any information contained herein except pursuant to this license grant from ++ * Synopsys. If you do not agree with this notice, including the disclaimer ++ * below, then you are not authorized to use the Software. ++ * ++ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS ++ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT, ++ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ++ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ++ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ++ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH ++ * DAMAGE. ++ * ========================================================================== */ ++#ifndef DWC_DEVICE_ONLY ++ ++/** @file ++ * This file contains Descriptor DMA support implementation for host mode. ++ */ ++ ++#include "dwc_otg_hcd.h" ++#include "dwc_otg_regs.h" ++ ++extern bool microframe_schedule; ++ ++static inline uint8_t frame_list_idx(uint16_t frame) ++{ ++ return (frame & (MAX_FRLIST_EN_NUM - 1)); ++} ++ ++static inline uint16_t desclist_idx_inc(uint16_t idx, uint16_t inc, uint8_t speed) ++{ ++ return (idx + inc) & ++ (((speed == ++ DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : ++ MAX_DMA_DESC_NUM_GENERIC) - 1); ++} ++ ++static inline uint16_t desclist_idx_dec(uint16_t idx, uint16_t inc, uint8_t speed) ++{ ++ return (idx - inc) & ++ (((speed == ++ DWC_OTG_EP_SPEED_HIGH) ? MAX_DMA_DESC_NUM_HS_ISOC : ++ MAX_DMA_DESC_NUM_GENERIC) - 1); ++} ++ ++static inline uint16_t max_desc_num(dwc_otg_qh_t * qh) ++{ ++ return (((qh->ep_type == UE_ISOCHRONOUS) ++ && (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH)) ++ ? MAX_DMA_DESC_NUM_HS_ISOC : MAX_DMA_DESC_NUM_GENERIC); ++} ++static inline uint16_t frame_incr_val(dwc_otg_qh_t * qh) ++{ ++ return ((qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) ++ ? ((qh->interval + 8 - 1) / 8) ++ : qh->interval); ++} ++ ++static int desc_list_alloc(dwc_otg_qh_t * qh) ++{ ++ int retval = 0; ++ ++ qh->desc_list = (dwc_otg_host_dma_desc_t *) ++ DWC_DMA_ALLOC(sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh), ++ &qh->desc_list_dma); ++ ++ if (!qh->desc_list) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR("%s: DMA descriptor list allocation failed\n", __func__); ++ ++ } ++ ++ dwc_memset(qh->desc_list, 0x00, ++ sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh)); ++ ++ qh->n_bytes = ++ (uint32_t *) DWC_ALLOC(sizeof(uint32_t) * max_desc_num(qh)); ++ ++ if (!qh->n_bytes) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR ++ ("%s: Failed to allocate array for descriptors' size actual values\n", ++ __func__); ++ ++ } ++ return retval; ++ ++} ++ ++static void desc_list_free(dwc_otg_qh_t * qh) ++{ ++ if (qh->desc_list) { ++ DWC_DMA_FREE(max_desc_num(qh), qh->desc_list, ++ qh->desc_list_dma); ++ qh->desc_list = NULL; ++ } ++ ++ if (qh->n_bytes) { ++ DWC_FREE(qh->n_bytes); ++ qh->n_bytes = NULL; ++ } ++} ++ ++static int frame_list_alloc(dwc_otg_hcd_t * hcd) ++{ ++ int retval = 0; ++ if (hcd->frame_list) ++ return 0; ++ ++ hcd->frame_list = DWC_DMA_ALLOC(4 * MAX_FRLIST_EN_NUM, ++ &hcd->frame_list_dma); ++ if (!hcd->frame_list) { ++ retval = -DWC_E_NO_MEMORY; ++ DWC_ERROR("%s: Frame List allocation failed\n", __func__); ++ } ++ ++ dwc_memset(hcd->frame_list, 0x00, 4 * MAX_FRLIST_EN_NUM); ++ ++ return retval; ++} ++ ++static void frame_list_free(dwc_otg_hcd_t * hcd) ++{ ++ if (!hcd->frame_list) ++ return; ++ ++ DWC_DMA_FREE(4 * MAX_FRLIST_EN_NUM, hcd->frame_list, hcd->frame_list_dma); ++ hcd->frame_list = NULL; ++} ++ ++static void per_sched_enable(dwc_otg_hcd_t * hcd, uint16_t fr_list_en) ++{ ++ ++ hcfg_data_t hcfg; ++ ++ hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg); ++ ++ if (hcfg.b.perschedena) { ++ /* already enabled */ ++ return; ++ } ++ ++ DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hflbaddr, ++ hcd->frame_list_dma); ++ ++ switch (fr_list_en) { ++ case 64: ++ hcfg.b.frlisten = 3; ++ break; ++ case 32: ++ hcfg.b.frlisten = 2; ++ break; ++ case 16: ++ hcfg.b.frlisten = 1; ++ break; ++ case 8: ++ hcfg.b.frlisten = 0; ++ break; ++ default: ++ break; ++ } ++ ++ hcfg.b.perschedena = 1; ++ ++ DWC_DEBUGPL(DBG_HCD, "Enabling Periodic schedule\n"); ++ DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++ ++} ++ ++static void per_sched_disable(dwc_otg_hcd_t * hcd) ++{ ++ hcfg_data_t hcfg; ++ ++ hcfg.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hcfg); ++ ++ if (!hcfg.b.perschedena) { ++ /* already disabled */ ++ return; ++ } ++ hcfg.b.perschedena = 0; ++ ++ DWC_DEBUGPL(DBG_HCD, "Disabling Periodic schedule\n"); ++ DWC_WRITE_REG32(&hcd->core_if->host_if->host_global_regs->hcfg, hcfg.d32); ++} ++ ++/* ++ * Activates/Deactivates FrameList entries for the channel ++ * based on endpoint servicing period. ++ */ ++void update_frame_list(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, uint8_t enable) ++{ ++ uint16_t i, j, inc; ++ dwc_hc_t *hc = NULL; ++ ++ if (!qh->channel) { ++ DWC_ERROR("qh->channel = %p", qh->channel); ++ return; ++ } ++ ++ if (!hcd) { ++ DWC_ERROR("------hcd = %p", hcd); ++ return; ++ } ++ ++ if (!hcd->frame_list) { ++ DWC_ERROR("-------hcd->frame_list = %p", hcd->frame_list); ++ return; ++ } ++ ++ hc = qh->channel; ++ inc = frame_incr_val(qh); ++ if (qh->ep_type == UE_ISOCHRONOUS) ++ i = frame_list_idx(qh->sched_frame); ++ else ++ i = 0; ++ ++ j = i; ++ do { ++ if (enable) ++ hcd->frame_list[j] |= (1 << hc->hc_num); ++ else ++ hcd->frame_list[j] &= ~(1 << hc->hc_num); ++ j = (j + inc) & (MAX_FRLIST_EN_NUM - 1); ++ } ++ while (j != i); ++ if (!enable) ++ return; ++ hc->schinfo = 0; ++ if (qh->channel->speed == DWC_OTG_EP_SPEED_HIGH) { ++ j = 1; ++ /* TODO - check this */ ++ inc = (8 + qh->interval - 1) / qh->interval; ++ for (i = 0; i < inc; i++) { ++ hc->schinfo |= j; ++ j = j << qh->interval; ++ } ++ } else { ++ hc->schinfo = 0xff; ++ } ++} ++ ++#if 1 ++void dump_frame_list(dwc_otg_hcd_t * hcd) ++{ ++ int i = 0; ++ DWC_PRINTF("--FRAME LIST (hex) --\n"); ++ for (i = 0; i < MAX_FRLIST_EN_NUM; i++) { ++ DWC_PRINTF("%x\t", hcd->frame_list[i]); ++ if (!(i % 8) && i) ++ DWC_PRINTF("\n"); ++ } ++ DWC_PRINTF("\n----\n"); ++ ++} ++#endif ++ ++static void release_channel_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ dwc_irqflags_t flags; ++ dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC(); ++ ++ dwc_hc_t *hc = qh->channel; ++ if (dwc_qh_is_non_per(qh)) { ++ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); ++ if (!microframe_schedule) ++ hcd->non_periodic_channels--; ++ else ++ hcd->available_host_channels++; ++ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); ++ } else ++ update_frame_list(hcd, qh, 0); ++ ++ /* ++ * The condition is added to prevent double cleanup try in case of device ++ * disconnect. See channel cleanup in dwc_otg_hcd_disconnect_cb(). ++ */ ++ if (hc->qh) { ++ dwc_otg_hc_cleanup(hcd->core_if, hc); ++ DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); ++ hc->qh = NULL; ++ } ++ ++ qh->channel = NULL; ++ qh->ntd = 0; ++ ++ if (qh->desc_list) { ++ dwc_memset(qh->desc_list, 0x00, ++ sizeof(dwc_otg_host_dma_desc_t) * max_desc_num(qh)); ++ } ++ DWC_SPINLOCK_FREE(channel_lock); ++} ++ ++/** ++ * Initializes a QH structure's Descriptor DMA related members. ++ * Allocates memory for descriptor list. ++ * On first periodic QH, allocates memory for FrameList ++ * and enables periodic scheduling. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh The QH to init. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++int dwc_otg_hcd_qh_init_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ int retval = 0; ++ ++ if (qh->do_split) { ++ DWC_ERROR("SPLIT Transfers are not supported in Descriptor DMA.\n"); ++ return -1; ++ } ++ ++ retval = desc_list_alloc(qh); ++ ++ if ((retval == 0) ++ && (qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT)) { ++ if (!hcd->frame_list) { ++ retval = frame_list_alloc(hcd); ++ /* Enable periodic schedule on first periodic QH */ ++ if (retval == 0) ++ per_sched_enable(hcd, MAX_FRLIST_EN_NUM); ++ } ++ } ++ ++ qh->ntd = 0; ++ ++ return retval; ++} ++ ++/** ++ * Frees descriptor list memory associated with the QH. ++ * If QH is periodic and the last, frees FrameList memory ++ * and disables periodic scheduling. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh The QH to init. ++ */ ++void dwc_otg_hcd_qh_free_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ desc_list_free(qh); ++ ++ /* ++ * Channel still assigned due to some reasons. ++ * Seen on Isoc URB dequeue. Channel halted but no subsequent ++ * ChHalted interrupt to release the channel. Afterwards ++ * when it comes here from endpoint disable routine ++ * channel remains assigned. ++ */ ++ if (qh->channel) ++ release_channel_ddma(hcd, qh); ++ ++ if ((qh->ep_type == UE_ISOCHRONOUS || qh->ep_type == UE_INTERRUPT) ++ && (microframe_schedule || !hcd->periodic_channels) && hcd->frame_list) { ++ ++ per_sched_disable(hcd); ++ frame_list_free(hcd); ++ } ++} ++ ++static uint8_t frame_to_desc_idx(dwc_otg_qh_t * qh, uint16_t frame_idx) ++{ ++ if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) { ++ /* ++ * Descriptor set(8 descriptors) index ++ * which is 8-aligned. ++ */ ++ return (frame_idx & ((MAX_DMA_DESC_NUM_HS_ISOC / 8) - 1)) * 8; ++ } else { ++ return (frame_idx & (MAX_DMA_DESC_NUM_GENERIC - 1)); ++ } ++} ++ ++/* ++ * Determine starting frame for Isochronous transfer. ++ * Few frames skipped to prevent race condition with HC. ++ */ ++static uint8_t calc_starting_frame(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, ++ uint8_t * skip_frames) ++{ ++ uint16_t frame = 0; ++ hcd->frame_number = dwc_otg_hcd_get_frame_number(hcd); ++ ++ /* sched_frame is always frame number(not uFrame) both in FS and HS !! */ ++ ++ /* ++ * skip_frames is used to limit activated descriptors number ++ * to avoid the situation when HC services the last activated ++ * descriptor firstly. ++ * Example for FS: ++ * Current frame is 1, scheduled frame is 3. Since HC always fetches the descriptor ++ * corresponding to curr_frame+1, the descriptor corresponding to frame 2 ++ * will be fetched. If the number of descriptors is max=64 (or greather) the ++ * list will be fully programmed with Active descriptors and it is possible ++ * case(rare) that the latest descriptor(considering rollback) corresponding ++ * to frame 2 will be serviced first. HS case is more probable because, in fact, ++ * up to 11 uframes(16 in the code) may be skipped. ++ */ ++ if (qh->dev_speed == DWC_OTG_EP_SPEED_HIGH) { ++ /* ++ * Consider uframe counter also, to start xfer asap. ++ * If half of the frame elapsed skip 2 frames otherwise ++ * just 1 frame. ++ * Starting descriptor index must be 8-aligned, so ++ * if the current frame is near to complete the next one ++ * is skipped as well. ++ */ ++ ++ if (dwc_micro_frame_num(hcd->frame_number) >= 5) { ++ *skip_frames = 2 * 8; ++ frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames); ++ } else { ++ *skip_frames = 1 * 8; ++ frame = dwc_frame_num_inc(hcd->frame_number, *skip_frames); ++ } ++ ++ frame = dwc_full_frame_num(frame); ++ } else { ++ /* ++ * Two frames are skipped for FS - the current and the next. ++ * But for descriptor programming, 1 frame(descriptor) is enough, ++ * see example above. ++ */ ++ *skip_frames = 1; ++ frame = dwc_frame_num_inc(hcd->frame_number, 2); ++ } ++ ++ return frame; ++} ++ ++/* ++ * Calculate initial descriptor index for isochronous transfer ++ * based on scheduled frame. ++ */ ++static uint8_t recalc_initial_desc_idx(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ uint16_t frame = 0, fr_idx, fr_idx_tmp; ++ uint8_t skip_frames = 0; ++ /* ++ * With current ISOC processing algorithm the channel is being ++ * released when no more QTDs in the list(qh->ntd == 0). ++ * Thus this function is called only when qh->ntd == 0 and qh->channel == 0. ++ * ++ * So qh->channel != NULL branch is not used and just not removed from the ++ * source file. It is required for another possible approach which is, ++ * do not disable and release the channel when ISOC session completed, ++ * just move QH to inactive schedule until new QTD arrives. ++ * On new QTD, the QH moved back to 'ready' schedule, ++ * starting frame and therefore starting desc_index are recalculated. ++ * In this case channel is released only on ep_disable. ++ */ ++ ++ /* Calculate starting descriptor index. For INTERRUPT endpoint it is always 0. */ ++ if (qh->channel) { ++ frame = calc_starting_frame(hcd, qh, &skip_frames); ++ /* ++ * Calculate initial descriptor index based on FrameList current bitmap ++ * and servicing period. ++ */ ++ fr_idx_tmp = frame_list_idx(frame); ++ fr_idx = ++ (MAX_FRLIST_EN_NUM + frame_list_idx(qh->sched_frame) - ++ fr_idx_tmp) ++ % frame_incr_val(qh); ++ fr_idx = (fr_idx + fr_idx_tmp) % MAX_FRLIST_EN_NUM; ++ } else { ++ qh->sched_frame = calc_starting_frame(hcd, qh, &skip_frames); ++ fr_idx = frame_list_idx(qh->sched_frame); ++ } ++ ++ qh->td_first = qh->td_last = frame_to_desc_idx(qh, fr_idx); ++ ++ return skip_frames; ++} ++ ++#define ISOC_URB_GIVEBACK_ASAP ++ ++#define MAX_ISOC_XFER_SIZE_FS 1023 ++#define MAX_ISOC_XFER_SIZE_HS 3072 ++#define DESCNUM_THRESHOLD 4 ++ ++static void init_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, ++ uint8_t skip_frames) ++{ ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc; ++ dwc_otg_qtd_t *qtd; ++ dwc_otg_host_dma_desc_t *dma_desc; ++ uint16_t idx, inc, n_desc, ntd_max, max_xfer_size; ++ ++ idx = qh->td_last; ++ inc = qh->interval; ++ n_desc = 0; ++ ++ ntd_max = (max_desc_num(qh) + qh->interval - 1) / qh->interval; ++ if (skip_frames && !qh->channel) ++ ntd_max = ntd_max - skip_frames / qh->interval; ++ ++ max_xfer_size = ++ (qh->dev_speed == ++ DWC_OTG_EP_SPEED_HIGH) ? MAX_ISOC_XFER_SIZE_HS : ++ MAX_ISOC_XFER_SIZE_FS; ++ ++ DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) { ++ while ((qh->ntd < ntd_max) ++ && (qtd->isoc_frame_index_last < ++ qtd->urb->packet_count)) { ++ ++ dma_desc = &qh->desc_list[idx]; ++ dwc_memset(dma_desc, 0x00, sizeof(dwc_otg_host_dma_desc_t)); ++ ++ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last]; ++ ++ if (frame_desc->length > max_xfer_size) ++ qh->n_bytes[idx] = max_xfer_size; ++ else ++ qh->n_bytes[idx] = frame_desc->length; ++ dma_desc->status.b_isoc.n_bytes = qh->n_bytes[idx]; ++ dma_desc->status.b_isoc.a = 1; ++ dma_desc->status.b_isoc.sts = 0; ++ ++ dma_desc->buf = qtd->urb->dma + frame_desc->offset; ++ ++ qh->ntd++; ++ ++ qtd->isoc_frame_index_last++; ++ ++#ifdef ISOC_URB_GIVEBACK_ASAP ++ /* ++ * Set IOC for each descriptor corresponding to the ++ * last frame of the URB. ++ */ ++ if (qtd->isoc_frame_index_last == ++ qtd->urb->packet_count) ++ dma_desc->status.b_isoc.ioc = 1; ++ ++#endif ++ idx = desclist_idx_inc(idx, inc, qh->dev_speed); ++ n_desc++; ++ ++ } ++ qtd->in_process = 1; ++ } ++ ++ qh->td_last = idx; ++ ++#ifdef ISOC_URB_GIVEBACK_ASAP ++ /* Set IOC for the last descriptor if descriptor list is full */ ++ if (qh->ntd == ntd_max) { ++ idx = desclist_idx_dec(qh->td_last, inc, qh->dev_speed); ++ qh->desc_list[idx].status.b_isoc.ioc = 1; ++ } ++#else ++ /* ++ * Set IOC bit only for one descriptor. ++ * Always try to be ahead of HW processing, ++ * i.e. on IOC generation driver activates next descriptors but ++ * core continues to process descriptors followed the one with IOC set. ++ */ ++ ++ if (n_desc > DESCNUM_THRESHOLD) { ++ /* ++ * Move IOC "up". Required even if there is only one QTD ++ * in the list, cause QTDs migth continue to be queued, ++ * but during the activation it was only one queued. ++ * Actually more than one QTD might be in the list if this function called ++ * from XferCompletion - QTDs was queued during HW processing of the previous ++ * descriptor chunk. ++ */ ++ idx = dwc_desclist_idx_dec(idx, inc * ((qh->ntd + 1) / 2), qh->dev_speed); ++ } else { ++ /* ++ * Set the IOC for the latest descriptor ++ * if either number of descriptor is not greather than threshold ++ * or no more new descriptors activated. ++ */ ++ idx = dwc_desclist_idx_dec(qh->td_last, inc, qh->dev_speed); ++ } ++ ++ qh->desc_list[idx].status.b_isoc.ioc = 1; ++#endif ++} ++ ++static void init_non_isoc_dma_desc(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ ++ dwc_hc_t *hc; ++ dwc_otg_host_dma_desc_t *dma_desc; ++ dwc_otg_qtd_t *qtd; ++ int num_packets, len, n_desc = 0; ++ ++ hc = qh->channel; ++ ++ /* ++ * Start with hc->xfer_buff initialized in ++ * assign_and_init_hc(), then if SG transfer consists of multiple URBs, ++ * this pointer re-assigned to the buffer of the currently processed QTD. ++ * For non-SG request there is always one QTD active. ++ */ ++ ++ DWC_CIRCLEQ_FOREACH(qtd, &qh->qtd_list, qtd_list_entry) { ++ ++ if (n_desc) { ++ /* SG request - more than 1 QTDs */ ++ hc->xfer_buff = (uint8_t *)qtd->urb->dma + qtd->urb->actual_length; ++ hc->xfer_len = qtd->urb->length - qtd->urb->actual_length; ++ } ++ ++ qtd->n_desc = 0; ++ ++ do { ++ dma_desc = &qh->desc_list[n_desc]; ++ len = hc->xfer_len; ++ ++ if (len > MAX_DMA_DESC_SIZE) ++ len = MAX_DMA_DESC_SIZE - hc->max_packet + 1; ++ ++ if (hc->ep_is_in) { ++ if (len > 0) { ++ num_packets = (len + hc->max_packet - 1) / hc->max_packet; ++ } else { ++ /* Need 1 packet for transfer length of 0. */ ++ num_packets = 1; ++ } ++ /* Always program an integral # of max packets for IN transfers. */ ++ len = num_packets * hc->max_packet; ++ } ++ ++ dma_desc->status.b.n_bytes = len; ++ ++ qh->n_bytes[n_desc] = len; ++ ++ if ((qh->ep_type == UE_CONTROL) ++ && (qtd->control_phase == DWC_OTG_CONTROL_SETUP)) ++ dma_desc->status.b.sup = 1; /* Setup Packet */ ++ ++ dma_desc->status.b.a = 1; /* Active descriptor */ ++ dma_desc->status.b.sts = 0; ++ ++ dma_desc->buf = ++ ((unsigned long)hc->xfer_buff & 0xffffffff); ++ ++ /* ++ * Last descriptor(or single) of IN transfer ++ * with actual size less than MaxPacket. ++ */ ++ if (len > hc->xfer_len) { ++ hc->xfer_len = 0; ++ } else { ++ hc->xfer_buff += len; ++ hc->xfer_len -= len; ++ } ++ ++ qtd->n_desc++; ++ n_desc++; ++ } ++ while ((hc->xfer_len > 0) && (n_desc != MAX_DMA_DESC_NUM_GENERIC)); ++ ++ ++ qtd->in_process = 1; ++ ++ if (qh->ep_type == UE_CONTROL) ++ break; ++ ++ if (n_desc == MAX_DMA_DESC_NUM_GENERIC) ++ break; ++ } ++ ++ if (n_desc) { ++ /* Request Transfer Complete interrupt for the last descriptor */ ++ qh->desc_list[n_desc - 1].status.b.ioc = 1; ++ /* End of List indicator */ ++ qh->desc_list[n_desc - 1].status.b.eol = 1; ++ ++ hc->ntd = n_desc; ++ } ++} ++ ++/** ++ * For Control and Bulk endpoints initializes descriptor list ++ * and starts the transfer. ++ * ++ * For Interrupt and Isochronous endpoints initializes descriptor list ++ * then updates FrameList, marking appropriate entries as active. ++ * In case of Isochronous, the starting descriptor index is calculated based ++ * on the scheduled frame, but only on the first transfer descriptor within a session. ++ * Then starts the transfer via enabling the channel. ++ * For Isochronous endpoint the channel is not halted on XferComplete ++ * interrupt so remains assigned to the endpoint(QH) until session is done. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param qh The QH to init. ++ * ++ * @return 0 if successful, negative error code otherwise. ++ */ ++void dwc_otg_hcd_start_xfer_ddma(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) ++{ ++ /* Channel is already assigned */ ++ dwc_hc_t *hc = qh->channel; ++ uint8_t skip_frames = 0; ++ ++ switch (hc->ep_type) { ++ case DWC_OTG_EP_TYPE_CONTROL: ++ case DWC_OTG_EP_TYPE_BULK: ++ init_non_isoc_dma_desc(hcd, qh); ++ ++ dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); ++ break; ++ case DWC_OTG_EP_TYPE_INTR: ++ init_non_isoc_dma_desc(hcd, qh); ++ ++ update_frame_list(hcd, qh, 1); ++ ++ dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); ++ break; ++ case DWC_OTG_EP_TYPE_ISOC: ++ ++ if (!qh->ntd) ++ skip_frames = recalc_initial_desc_idx(hcd, qh); ++ ++ init_isoc_dma_desc(hcd, qh, skip_frames); ++ ++ if (!hc->xfer_started) { ++ ++ update_frame_list(hcd, qh, 1); ++ ++ /* ++ * Always set to max, instead of actual size. ++ * Otherwise ntd will be changed with ++ * channel being enabled. Not recommended. ++ * ++ */ ++ hc->ntd = max_desc_num(qh); ++ /* Enable channel only once for ISOC */ ++ dwc_otg_hc_start_transfer_ddma(hcd->core_if, hc); ++ } ++ ++ break; ++ default: ++ ++ break; ++ } ++} ++ ++static void complete_isoc_xfer_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_halt_status_e halt_status) ++{ ++ struct dwc_otg_hcd_iso_packet_desc *frame_desc; ++ dwc_otg_qtd_t *qtd, *qtd_tmp; ++ dwc_otg_qh_t *qh; ++ dwc_otg_host_dma_desc_t *dma_desc; ++ uint16_t idx, remain; ++ uint8_t urb_compl; ++ ++ qh = hc->qh; ++ idx = qh->td_first; ++ ++ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) ++ qtd->in_process = 0; ++ return; ++ } else if ((halt_status == DWC_OTG_HC_XFER_AHB_ERR) || ++ (halt_status == DWC_OTG_HC_XFER_BABBLE_ERR)) { ++ /* ++ * Channel is halted in these error cases. ++ * Considered as serious issues. ++ * Complete all URBs marking all frames as failed, ++ * irrespective whether some of the descriptors(frames) succeeded or no. ++ * Pass error code to completion routine as well, to ++ * update urb->status, some of class drivers might use it to stop ++ * queing transfer requests. ++ */ ++ int err = (halt_status == DWC_OTG_HC_XFER_AHB_ERR) ++ ? (-DWC_E_IO) ++ : (-DWC_E_OVERFLOW); ++ ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { ++ for (idx = 0; idx < qtd->urb->packet_count; idx++) { ++ frame_desc = &qtd->urb->iso_descs[idx]; ++ frame_desc->status = err; ++ } ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, err); ++ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ } ++ return; ++ } ++ ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { ++ ++ if (!qtd->in_process) ++ break; ++ ++ urb_compl = 0; ++ ++ do { ++ ++ dma_desc = &qh->desc_list[idx]; ++ ++ frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; ++ remain = hc->ep_is_in ? dma_desc->status.b_isoc.n_bytes : 0; ++ ++ if (dma_desc->status.b_isoc.sts == DMA_DESC_STS_PKTERR) { ++ /* ++ * XactError or, unable to complete all the transactions ++ * in the scheduled micro-frame/frame, ++ * both indicated by DMA_DESC_STS_PKTERR. ++ */ ++ qtd->urb->error_count++; ++ frame_desc->actual_length = qh->n_bytes[idx] - remain; ++ frame_desc->status = -DWC_E_PROTOCOL; ++ } else { ++ /* Success */ ++ ++ frame_desc->actual_length = qh->n_bytes[idx] - remain; ++ frame_desc->status = 0; ++ } ++ ++ if (++qtd->isoc_frame_index == qtd->urb->packet_count) { ++ /* ++ * urb->status is not used for isoc transfers here. ++ * The individual frame_desc status are used instead. ++ */ ++ ++ hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); ++ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ ++ /* ++ * This check is necessary because urb_dequeue can be called ++ * from urb complete callback(sound driver example). ++ * All pending URBs are dequeued there, so no need for ++ * further processing. ++ */ ++ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { ++ return; ++ } ++ ++ urb_compl = 1; ++ ++ } ++ ++ qh->ntd--; ++ ++ /* Stop if IOC requested descriptor reached */ ++ if (dma_desc->status.b_isoc.ioc) { ++ idx = desclist_idx_inc(idx, qh->interval, hc->speed); ++ goto stop_scan; ++ } ++ ++ idx = desclist_idx_inc(idx, qh->interval, hc->speed); ++ ++ if (urb_compl) ++ break; ++ } ++ while (idx != qh->td_first); ++ } ++stop_scan: ++ qh->td_first = idx; ++} ++ ++uint8_t update_non_isoc_urb_state_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_qtd_t * qtd, ++ dwc_otg_host_dma_desc_t * dma_desc, ++ dwc_otg_halt_status_e halt_status, ++ uint32_t n_bytes, uint8_t * xfer_done) ++{ ++ ++ uint16_t remain = hc->ep_is_in ? dma_desc->status.b.n_bytes : 0; ++ dwc_otg_hcd_urb_t *urb = qtd->urb; ++ ++ if (halt_status == DWC_OTG_HC_XFER_AHB_ERR) { ++ urb->status = -DWC_E_IO; ++ return 1; ++ } ++ if (dma_desc->status.b.sts == DMA_DESC_STS_PKTERR) { ++ switch (halt_status) { ++ case DWC_OTG_HC_XFER_STALL: ++ urb->status = -DWC_E_PIPE; ++ break; ++ case DWC_OTG_HC_XFER_BABBLE_ERR: ++ urb->status = -DWC_E_OVERFLOW; ++ break; ++ case DWC_OTG_HC_XFER_XACT_ERR: ++ urb->status = -DWC_E_PROTOCOL; ++ break; ++ default: ++ DWC_ERROR("%s: Unhandled descriptor error status (%d)\n", __func__, ++ halt_status); ++ break; ++ } ++ return 1; ++ } ++ ++ if (dma_desc->status.b.a == 1) { ++ DWC_DEBUGPL(DBG_HCDV, ++ "Active descriptor encountered on channel %d\n", ++ hc->hc_num); ++ return 0; ++ } ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL) { ++ if (qtd->control_phase == DWC_OTG_CONTROL_DATA) { ++ urb->actual_length += n_bytes - remain; ++ if (remain || urb->actual_length == urb->length) { ++ /* ++ * For Control Data stage do not set urb->status=0 to prevent ++ * URB callback. Set it when Status phase done. See below. ++ */ ++ *xfer_done = 1; ++ } ++ ++ } else if (qtd->control_phase == DWC_OTG_CONTROL_STATUS) { ++ urb->status = 0; ++ *xfer_done = 1; ++ } ++ /* No handling for SETUP stage */ ++ } else { ++ /* BULK and INTR */ ++ urb->actual_length += n_bytes - remain; ++ if (remain || urb->actual_length == urb->length) { ++ urb->status = 0; ++ *xfer_done = 1; ++ } ++ } ++ ++ return 0; ++} ++ ++static void complete_non_isoc_xfer_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_halt_status_e halt_status) ++{ ++ dwc_otg_hcd_urb_t *urb = NULL; ++ dwc_otg_qtd_t *qtd, *qtd_tmp; ++ dwc_otg_qh_t *qh; ++ dwc_otg_host_dma_desc_t *dma_desc; ++ uint32_t n_bytes, n_desc, i; ++ uint8_t failed = 0, xfer_done; ++ ++ n_desc = 0; ++ ++ qh = hc->qh; ++ ++ if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) { ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &hc->qh->qtd_list, qtd_list_entry) { ++ qtd->in_process = 0; ++ } ++ return; ++ } ++ ++ DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { ++ ++ urb = qtd->urb; ++ ++ n_bytes = 0; ++ xfer_done = 0; ++ ++ for (i = 0; i < qtd->n_desc; i++) { ++ dma_desc = &qh->desc_list[n_desc]; ++ ++ n_bytes = qh->n_bytes[n_desc]; ++ ++ failed = ++ update_non_isoc_urb_state_ddma(hcd, hc, qtd, ++ dma_desc, ++ halt_status, n_bytes, ++ &xfer_done); ++ ++ if (failed ++ || (xfer_done ++ && (urb->status != -DWC_E_IN_PROGRESS))) { ++ ++ hcd->fops->complete(hcd, urb->priv, urb, ++ urb->status); ++ dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh); ++ ++ if (failed) ++ goto stop_scan; ++ } else if (qh->ep_type == UE_CONTROL) { ++ if (qtd->control_phase == DWC_OTG_CONTROL_SETUP) { ++ if (urb->length > 0) { ++ qtd->control_phase = DWC_OTG_CONTROL_DATA; ++ } else { ++ qtd->control_phase = DWC_OTG_CONTROL_STATUS; ++ } ++ DWC_DEBUGPL(DBG_HCDV, " Control setup transaction done\n"); ++ } else if (qtd->control_phase == DWC_OTG_CONTROL_DATA) { ++ if (xfer_done) { ++ qtd->control_phase = DWC_OTG_CONTROL_STATUS; ++ DWC_DEBUGPL(DBG_HCDV, " Control data transfer done\n"); ++ } else if (i + 1 == qtd->n_desc) { ++ /* ++ * Last descriptor for Control data stage which is ++ * not completed yet. ++ */ ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ } ++ } ++ } ++ ++ n_desc++; ++ } ++ ++ } ++ ++stop_scan: ++ ++ if (qh->ep_type != UE_CONTROL) { ++ /* ++ * Resetting the data toggle for bulk ++ * and interrupt endpoints in case of stall. See handle_hc_stall_intr() ++ */ ++ if (halt_status == DWC_OTG_HC_XFER_STALL) ++ qh->data_toggle = DWC_OTG_HC_PID_DATA0; ++ else ++ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); ++ } ++ ++ if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { ++ hcint_data_t hcint; ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); ++ if (hcint.b.nyet) { ++ /* ++ * Got a NYET on the last transaction of the transfer. It ++ * means that the endpoint should be in the PING state at the ++ * beginning of the next transfer. ++ */ ++ qh->ping_state = 1; ++ clear_hc_int(hc_regs, nyet); ++ } ++ ++ } ++ ++} ++ ++/** ++ * This function is called from interrupt handlers. ++ * Scans the descriptor list, updates URB's status and ++ * calls completion routine for the URB if it's done. ++ * Releases the channel to be used by other transfers. ++ * In case of Isochronous endpoint the channel is not halted until ++ * the end of the session, i.e. QTD list is empty. ++ * If periodic channel released the FrameList is updated accordingly. ++ * ++ * Calls transaction selection routines to activate pending transfers. ++ * ++ * @param hcd The HCD state structure for the DWC OTG controller. ++ * @param hc Host channel, the transfer is completed on. ++ * @param hc_regs Host channel registers. ++ * @param halt_status Reason the channel is being halted, ++ * or just XferComplete for isochronous transfer ++ */ ++void dwc_otg_hcd_complete_xfer_ddma(dwc_otg_hcd_t * hcd, ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_halt_status_e halt_status) ++{ ++ uint8_t continue_isoc_xfer = 0; ++ dwc_otg_transaction_type_e tr_type; ++ dwc_otg_qh_t *qh = hc->qh; ++ ++ if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) { ++ ++ complete_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status); ++ ++ /* Release the channel if halted or session completed */ ++ if (halt_status != DWC_OTG_HC_XFER_COMPLETE || ++ DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ ++ /* Halt the channel if session completed */ ++ if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { ++ dwc_otg_hc_halt(hcd->core_if, hc, halt_status); ++ } ++ ++ release_channel_ddma(hcd, qh); ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ } else { ++ /* Keep in assigned schedule to continue transfer */ ++ DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned, ++ &qh->qh_list_entry); ++ continue_isoc_xfer = 1; ++ ++ } ++ /** @todo Consider the case when period exceeds FrameList size. ++ * Frame Rollover interrupt should be used. ++ */ ++ } else { ++ /* Scan descriptor list to complete the URB(s), then release the channel */ ++ complete_non_isoc_xfer_ddma(hcd, hc, hc_regs, halt_status); ++ ++ release_channel_ddma(hcd, qh); ++ dwc_otg_hcd_qh_remove(hcd, qh); ++ ++ if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { ++ /* Add back to inactive non-periodic schedule on normal completion */ ++ dwc_otg_hcd_qh_add(hcd, qh); ++ } ++ ++ } ++ tr_type = dwc_otg_hcd_select_transactions(hcd); ++ if (tr_type != DWC_OTG_TRANSACTION_NONE || continue_isoc_xfer) { ++ if (continue_isoc_xfer) { ++ if (tr_type == DWC_OTG_TRANSACTION_NONE) { ++ tr_type = DWC_OTG_TRANSACTION_PERIODIC; ++ } else if (tr_type == DWC_OTG_TRANSACTION_NON_PERIODIC) { ++ tr_type = DWC_OTG_TRANSACTION_ALL; ++ } ++ } ++ dwc_otg_hcd_queue_transactions(hcd, tr_type); ++ } ++} ++ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h +new file mode 100644 +index 0000000..04ca4c2 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h +@@ -0,0 +1,417 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_if.h $ -+ * $Revision: #6 $ -+ * $Date: 2009/04/21 $ -+ * $Change: 1237474 $ ++ * $Revision: #12 $ ++ * $Date: 2011/10/26 $ ++ * $Change: 1873028 $ + * + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless @@ -56115,6 +67717,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-rpi-boot + */ +extern int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd); + ++/** This function is used to handle the fast interrupt ++ * ++ */ ++extern void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void); ++ +/** + * Returns private data set by + * dwc_otg_hcd_set_priv_data function. @@ -56177,6 +67784,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-rpi-boot +extern uint32_t dwc_otg_hcd_otg_port(dwc_otg_hcd_t * hcd); + +/** ++ * Returns OTG version - either 1.3 or 2.0. ++ * ++ * @param core_if The core_if structure pointer ++ */ ++extern uint16_t dwc_otg_get_otg_version(dwc_otg_core_if_t * core_if); ++ ++/** + * Returns 1 if currently core is acting as B host, and 0 otherwise. + * + * @param hcd The HCD @@ -56225,7 +67839,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-rpi-boot + +/** + * Allocates memory for dwc_otg_hcd_urb structure. -+ * Allocated memory should be freed by call dwc_free function. ++ * Allocated memory should be freed by call of DWC_FREE. + * + * @param hcd The HCD + * @param iso_desc_count Count of ISOC descriptors @@ -56250,7 +67864,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-rpi-boot + uint8_t ep_type, uint8_t ep_dir, + uint16_t mps); + -+/* Transfer flags */ ++/* Transfer flags */ +#define URB_GIVEBACK_ASAP 0x1 +#define URB_SEND_ZERO_PACKET 0x2 + @@ -56327,6 +67941,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-rpi-boot + * @param dwc_otg_hcd The HCD + * @param dwc_otg_urb DWC_OTG URB + * @param ep_handle Out parameter for returning endpoint handle ++ * @param atomic_alloc Flag to do atomic allocation if needed + * + * Returns -DWC_E_NO_DEVICE if no device is connected. + * Returns -DWC_E_NO_MEMORY if there is no enough memory. @@ -56334,7 +67949,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-rpi-boot + */ +extern int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * dwc_otg_hcd, + dwc_otg_hcd_urb_t * dwc_otg_urb, -+ void **ep_handle); ++ void **ep_handle, int atomic_alloc); + +/** De-queue the specified URB + * @@ -56357,6 +67972,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-rpi-boot +extern int dwc_otg_hcd_endpoint_disable(dwc_otg_hcd_t * hcd, void *ep_handle, + int retry); + ++/* Resets the data toggle in qh structure. This function can be called from ++ * usb_clear_halt routine. ++ * ++ * @param hcd The HCD ++ * @param ep_handle Endpoint handle, returned by dwc_otg_hcd_urb_enqueue function ++ * ++ * Returns -DWC_E_INVALID if invalid arguments are passed. ++ * Returns 0 on success ++ */ ++extern int dwc_otg_hcd_endpoint_reset(dwc_otg_hcd_t * hcd, void *ep_handle); ++ +/** Returns 1 if status of specified port is changed and 0 otherwise. + * + * @param hcd The HCD @@ -56391,17 +68017,19 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_if.h linux-rpi-boot + +/** @} */ + -+#endif /* __DWC_HCD_IF_H__ */ -+#endif /* DWC_DEVICE_ONLY */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c 2012-07-15 20:29:19.104083997 +0200 -@@ -0,0 +1,2158 @@ ++#endif /* __DWC_HCD_IF_H__ */ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +new file mode 100644 +index 0000000..f1658fa +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +@@ -0,0 +1,2230 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $ -+ * $Revision: #77 $ -+ * $Date: 2009/04/21 $ -+ * $Change: 1237475 $ ++ * $Revision: #89 $ ++ * $Date: 2011/10/20 $ ++ * $Change: 1869487 $ + * + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless @@ -56431,133 +68059,165 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + * ========================================================================== */ +#ifndef DWC_DEVICE_ONLY + -+#include -+#include +#include "dwc_otg_hcd.h" +#include "dwc_otg_regs.h" ++#include "dwc_otg_mphi_fix.h" ++ ++#include ++#include ++ ++ ++extern bool microframe_schedule; + +/** @file + * This file contains the implementation of the HCD Interrupt handlers. + */ + -+/** -+ * SOF_FIX: Reduce SOF interrupt handling by disabling the SOF interrupt except -+ * when there are actual USB transfers pending. MSO 5/31/12 ++/* ++ * Some globals to communicate between the FIQ and INTERRUPT + */ -+#ifdef SOF_FIX -+ extern int sof_setting(void); -+ unsigned int g_dwc_otg_hcd_handle_intr_count = 0; -+ #ifdef DEBUG_SOF_FIX -+ unsigned int g_dwc_otg_interrupt_counts[10] = {0,0,0,0,0,0,0,0,0,0}; -+ extern int g_softintr_ref_cnt; -+ #endif -+#endif ++ ++void * dummy_send; ++mphi_regs_t c_mphi_regs; ++int fiq_done, int_done; ++int g_next_sched_frame, g_np_count, g_np_sent, g_work_expected; ++static int mphi_int_count = 0 ; ++ ++extern bool fiq_fix_enable; ++ ++void __attribute__ ((naked)) dwc_otg_hcd_handle_fiq(void) ++{ ++ gintsts_data_t gintsts; ++ hfnum_data_t hfnum; ++ ++ /* entry takes care to store registers we will be treading on here */ ++ asm __volatile__ ( ++ "mov ip, sp ;" ++ /* stash FIQ and normal regs */ ++ "stmdb sp!, {r0-r12, lr};" ++ /* !! THIS SETS THE FRAME, adjust to > sizeof locals */ ++ "sub fp, ip, #256 ;" ++ ); ++ ++ fiq_done++; ++ gintsts.d32 = FIQ_READ_IO_ADDRESS(USB_BASE + 0x14) & FIQ_READ_IO_ADDRESS(USB_BASE + 0x18); ++ hfnum.d32 = FIQ_READ_IO_ADDRESS(USB_BASE + 0x408); ++ ++ if(gintsts.d32) ++ { ++ if(gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum)) ++ { ++ /* ++ * If np_count != np_sent that means we need to queue non-periodic (bulk) packets this packet ++ * g_next_sched_frame is the next frame we have periodic packets for ++ * ++ * if neither of these are required for this frame then just clear the interrupt ++ */ ++ gintsts.d32 = 0; ++ gintsts.b.sofintr = 1; ++ FIQ_WRITE_IO_ADDRESS((USB_BASE + 0x14), gintsts.d32); ++ ++ g_work_expected = 0; ++ } ++ else ++ { ++ g_work_expected = 1; ++ /* To enable the MPHI interrupt (INT 32) ++ */ ++ FIQ_WRITE( c_mphi_regs.outdda, (int) dummy_send); ++ FIQ_WRITE( c_mphi_regs.outddb, (1 << 29)); ++ ++ mphi_int_count++; ++ /* Clear the USB global interrupt so we don't just sit in the FIQ */ ++ FIQ_MODIFY_IO_ADDRESS((USB_BASE + 0x8),1,0); ++ ++ } ++ } ++ mb(); ++ ++ /* exit back to normal mode restoring everything */ ++ asm __volatile__ ( ++ /* return FIQ regs back to pristine state ++ * and get normal regs back ++ */ ++ "ldmia sp!, {r0-r12, lr};" ++ ++ /* return */ ++ "subs pc, lr, #4;" ++ ); ++} + +/** This function handles interrupts for the HCD. */ +int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) +{ + int retval = 0; ++ static int last_time; + + dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if; + gintsts_data_t gintsts; -+#ifdef SOF_FIX -+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; -+ gintmsk_data_t gintmsk; -+#endif ++ hfnum_data_t hfnum; + +#ifdef DEBUG -+ //GRAYG: debugging -+ if (NULL == global_regs) { -+ DWC_DEBUGPL(DBG_HCD, "**** NULL regs: dwc_otg_hcd=%p " -+ "core_if=%p\n", -+ dwc_otg_hcd, global_regs); -+ return retval; -+ } -+#endif -+#ifdef SOF_FIX -+ g_dwc_otg_hcd_handle_intr_count++; ++ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; ++ +#endif ++ ++ /* Exit from ISR if core is hibernated */ ++ if (core_if->hibernation_suspend == 1) { ++ goto exit_handler_routine; ++ } ++ DWC_SPINLOCK(dwc_otg_hcd->lock); + /* Check if HOST Mode */ + if (dwc_otg_is_host_mode(core_if)) { + gintsts.d32 = dwc_otg_read_core_intr(core_if); + if (!gintsts.d32) { -+ return 0; ++ goto exit_handler_routine; + } +#ifdef DEBUG + /* Don't print debug message in the interrupt handler on SOF */ +#ifndef DEBUG_SOF + if (gintsts.d32 != DWC_SOF_INTR_MASK) +#endif -+ DWC_DEBUGPL(DBG_HCD, "\n"); ++ DWC_DEBUGPL(DBG_HCDI, "\n"); +#endif + +#ifdef DEBUG +#ifndef DEBUG_SOF + if (gintsts.d32 != DWC_SOF_INTR_MASK) +#endif -+ DWC_DEBUGPL(DBG_HCD, ++ DWC_DEBUGPL(DBG_HCDI, + "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x core_if=%p\n", + gintsts.d32, core_if); +#endif -+ -+ /* -+ * If SOF handle it. If not, it probably means that there is work to do, -+ * so enable SOF for the next micro-frame. -+ */ -+ if (gintsts.b.sofintr) ++ hfnum.d32 = DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->hfnum); ++ if (gintsts.b.sofintr && g_np_count == g_np_sent && dwc_frame_num_gt(g_next_sched_frame, hfnum.b.frnum)) + { -+#ifdef DEBUG_SOF_FIX -+ g_dwc_otg_interrupt_counts[0]++; -+#endif -+ retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd); ++ /* Note, we should never get here if the FIQ is doing it's job properly*/ ++ retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd, g_work_expected); + } -+#ifdef SOF_FIX -+ else -+ { -+ // turn on Start-of-Frame interrupt -+ gintmsk.d32 = dwc_read_reg32(&global_regs->gintmsk); -+ gintmsk.b.sofintr |= 1; -+ dwc_write_reg32(&global_regs->gintmsk, gintmsk.d32); ++ else if (gintsts.b.sofintr) { ++ retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd, g_work_expected); + } -+#endif + if (gintsts.b.rxstsqlvl) { -+#ifdef DEBUG_SOF_FIX -+ g_dwc_otg_interrupt_counts[1]++; -+#endif + retval |= + dwc_otg_hcd_handle_rx_status_q_level_intr + (dwc_otg_hcd); + } + if (gintsts.b.nptxfempty) { -+#ifdef DEBUG_SOF_FIX -+ g_dwc_otg_interrupt_counts[2]++; -+#endif + retval |= + dwc_otg_hcd_handle_np_tx_fifo_empty_intr + (dwc_otg_hcd); + } + if (gintsts.b.i2cintr) { -+#ifdef DEBUG_SOF_FIX -+ g_dwc_otg_interrupt_counts[3]++; -+#endif + /** @todo Implement i2cintr handler. */ + } + if (gintsts.b.portintr) { -+#ifdef DEBUG_SOF_FIX -+ g_dwc_otg_interrupt_counts[4]++; -+#endif + retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd); + } + if (gintsts.b.hcintr) { -+#ifdef DEBUG_SOF_FIX -+ g_dwc_otg_interrupt_counts[5]++; -+#endif + retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd); + } + if (gintsts.b.ptxfempty) { -+#ifdef DEBUG_SOF_FIX -+ g_dwc_otg_interrupt_counts[6]++; -+#endif + retval |= + dwc_otg_hcd_handle_perio_tx_fifo_empty_intr + (dwc_otg_hcd); @@ -56567,12 +68227,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + if (gintsts.d32 != DWC_SOF_INTR_MASK) +#endif + { -+ DWC_DEBUGPL(DBG_HCD, ++ DWC_DEBUGPL(DBG_HCDI, + "DWC OTG HCD Finished Servicing Interrupts\n"); + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintsts=0x%08x\n", -+ dwc_read_reg32(&global_regs->gintsts)); ++ 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 + @@ -56580,29 +68240,41 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo +#ifndef DEBUG_SOF + if (gintsts.d32 != DWC_SOF_INTR_MASK) +#endif -+ DWC_DEBUGPL(DBG_HCD, "\n"); ++ DWC_DEBUGPL(DBG_HCDI, "\n"); +#endif + + } -+#if defined(SOF_FIX) && defined(DEBUG_SOF_FIX) -+ if ((g_dwc_otg_hcd_handle_intr_count % 80000) == 0) ++ ++exit_handler_routine: ++ ++ if (fiq_fix_enable) + { -+ printk(KERN_ERR "dwc_otg_hcd_handle_intr: %u handled, %u, %u, %u, %u, %u, %u, %u, %u.\n", -+ g_dwc_otg_hcd_handle_intr_count, -+ g_dwc_otg_interrupt_counts[0], -+ g_dwc_otg_interrupt_counts[1], -+ g_dwc_otg_interrupt_counts[2], -+ g_dwc_otg_interrupt_counts[3], -+ g_dwc_otg_interrupt_counts[4], -+ g_dwc_otg_interrupt_counts[5], -+ g_dwc_otg_interrupt_counts[6], -+ g_dwc_otg_interrupt_counts[7]); ++ /* Clear the MPHI interrupt */ ++ DWC_WRITE_REG32(c_mphi_regs.intstat, (1<<16)); ++ if (mphi_int_count >= 60) ++ { ++ DWC_WRITE_REG32(c_mphi_regs.ctrl, ((1<<31) + (1<<16))); ++ DWC_WRITE_REG32(c_mphi_regs.ctrl, (1<<31)); ++ mphi_int_count = 0; ++ } ++ int_done++; ++ if((jiffies / HZ) > last_time) ++ { ++ /* Once a second output the fiq and irq numbers, useful for debug */ ++ last_time = jiffies / HZ; ++ DWC_DEBUGPL(DBG_USER, "int_done = %d fiq_done = %d\n", int_done, fiq_done); ++ } ++ ++ /* Re-Enable FIQ interrupt from USB peripheral */ ++ DWC_MODIFY_REG32((uint32_t *)IO_ADDRESS(USB_BASE + 0x8), 0 , 1); + } -+#endif ++ ++ DWC_SPINUNLOCK(dwc_otg_hcd->lock); + return retval; +} + +#ifdef DWC_TRACK_MISSED_SOFS ++ +#warning Compiling code to track missed SOFs +#define FRAME_NUM_ARRAY_SIZE 1000 +/** @@ -56642,25 +68314,18 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + * (micro)frame. Periodic transactions may be queued to the controller for the + * next (micro)frame. + */ -+#ifdef SOF_FIX -+#define SOF_INTR_DELAY_COUNT 3 -+static int g_sof_intr_delay_count = SOF_INTR_DELAY_COUNT; -+#endif -+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, int32_t work_expected) +{ + hfnum_data_t hfnum; + dwc_list_link_t *qh_entry; + dwc_otg_qh_t *qh; + dwc_otg_transaction_type_e tr_type; + gintsts_data_t gintsts = {.d32 = 0 }; -+#ifdef SOF_FIX -+ dwc_otg_core_if_t *core_if = hcd->core_if; -+ gintmsk_data_t gintmsk = {.d32 = 0 }; -+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs; -+#endif ++ int did_something = 0; ++ int32_t next_sched_frame = -1; + + hfnum.d32 = -+ dwc_read_reg32(&hcd->core_if->host_if->host_global_regs->hfnum); ++ DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum); + +#ifdef DEBUG_SOF + DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n"); @@ -56687,31 +68352,34 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + */ + DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready, + &qh->qh_list_entry); ++ ++ did_something = 1; + } -+ } -+ tr_type = dwc_otg_hcd_select_transactions(hcd); -+ if (tr_type != DWC_OTG_TRANSACTION_NONE) -+ { -+ dwc_otg_hcd_queue_transactions(hcd, tr_type); -+ } -+#ifdef SOF_FIX -+ else -+ { -+ // turn off Start-of-Frame interrupt -+ if ((sof_setting()) && -+ (g_sof_intr_delay_count-- == 0)) ++ else + { -+ gintmsk.d32 = dwc_read_reg32(&global_regs->gintmsk); -+ gintmsk.b.sofintr &= 0; -+ dwc_write_reg32(&global_regs->gintmsk, gintmsk.d32); -+ g_sof_intr_delay_count = SOF_INTR_DELAY_COUNT; ++ if(next_sched_frame < 0 || dwc_frame_num_le(qh->sched_frame, next_sched_frame)) ++ { ++ next_sched_frame = qh->sched_frame; ++ } + } + } -+#endif ++ ++ g_next_sched_frame = next_sched_frame; ++ ++ tr_type = dwc_otg_hcd_select_transactions(hcd); ++ if (tr_type != DWC_OTG_TRANSACTION_NONE) { ++ dwc_otg_hcd_queue_transactions(hcd, tr_type); ++ did_something = 1; ++ } ++ if(work_expected && !did_something) ++ DWC_DEBUGPL(DBG_USER, "Nothing to do !! frame = %x, g_next_sched_frame = %x\n", (int) hfnum.b.frnum, g_next_sched_frame); ++ if(!work_expected && did_something) ++ DWC_DEBUGPL(DBG_USER, "Unexpected work done !! frame = %x, g_next_sched_frame = %x\n", (int) hfnum.b.frnum, g_next_sched_frame); ++ + + /* 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; +} @@ -56727,9 +68395,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n"); + + grxsts.d32 = -+ dwc_read_reg32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp); ++ DWC_READ_REG32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp); + + hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum]; ++ if (!hc) { ++ DWC_ERROR("Unable to get corresponding channel\n"); ++ return 0; ++ } + + /* Packet Status */ + DWC_DEBUGPL(DBG_HCDV, " Ch num = %d\n", grxsts.b.chnum); @@ -56797,8 +68469,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + hprt0_data_t hprt0; + 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 + * GINTSTS */ @@ -56810,16 +68482,41 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + + /* 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; ++ if (dwc_otg_hcd->core_if->hibernation_suspend == 1) { ++ // Dont modify port status if we are in hibernation state + hprt0_modify.b.prtconndet = 1; ++ hprt0_modify.b.prtenchng = 1; ++ DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32); ++ hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0); ++ return retval; ++ } + -+ /* B-Device has connected, Delete the connection timer. */ -+ DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer); -+ ++ if (hprt0.b.prtconndet) { ++ /** @todo - check if steps performed in 'else' block should be perfromed regardles adp */ ++ if (dwc_otg_hcd->core_if->adp_enable && ++ dwc_otg_hcd->core_if->adp.vbuson_timer_started == 1) { ++ DWC_PRINTF("PORT CONNECT DETECTED ----------------\n"); ++ DWC_TIMER_CANCEL(dwc_otg_hcd->core_if->adp.vbuson_timer); ++ dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0; ++ /* TODO - check if this is required, as ++ * host initialization was already performed ++ * after initial ADP probing ++ */ ++ /*dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0; ++ dwc_otg_core_init(dwc_otg_hcd->core_if); ++ dwc_otg_enable_global_interrupts(dwc_otg_hcd->core_if); ++ cil_hcd_start(dwc_otg_hcd->core_if);*/ ++ } else { ++ ++ 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; ++ hprt0_modify.b.prtconndet = 1; ++ ++ /* B-Device has connected, Delete the connection timer. */ ++ DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer); ++ } + /* The Hub driver asserts a reset when it sees port connect + * status change flag */ + retval |= 1; @@ -56832,6 +68529,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + "Port Enable Changed--\n", hprt0.d32); + hprt0_modify.b.prtenchng = 1; + if (hprt0.b.prtena == 1) { ++ hfir_data_t hfir; + int do_reset = 0; + dwc_otg_core_params_t *params = + dwc_otg_hcd->core_if->core_params; @@ -56839,6 +68537,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + dwc_otg_hcd->core_if->core_global_regs; + dwc_otg_host_if_t *host_if = + dwc_otg_hcd->core_if->host_if; ++ ++ /* Every time when port enables calculate ++ * HFIR.FrInterval ++ */ ++ hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir); ++ hfir.b.frint = calc_frame_interval(dwc_otg_hcd->core_if); ++ DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32); + + /* Check if we need to adjust the PHY clock speed for + * low power and adjust it */ @@ -56846,7 +68551,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + gusbcfg_data_t usbcfg; + + usbcfg.d32 = -+ dwc_read_reg32(&global_regs->gusbcfg); ++ DWC_READ_REG32(&global_regs->gusbcfg); + + if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED + || hprt0.b.prtspd == @@ -56858,20 +68563,20 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + if (usbcfg.b.phylpwrclksel == 0) { + /* Set PHY low power clock select for FS/LS devices */ + usbcfg.b.phylpwrclksel = 1; -+ dwc_write_reg32(&global_regs-> -+ gusbcfg, -+ usbcfg.d32); ++ DWC_WRITE_REG32 ++ (&global_regs->gusbcfg, ++ usbcfg.d32); + do_reset = 1; + } + + hcfg.d32 = -+ dwc_read_reg32(&host_if-> -+ host_global_regs->hcfg); ++ 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 == ++ && params->host_ls_low_power_phy_clk ++ == + DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ) + { + /* 6 MHZ */ @@ -56881,10 +68586,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + DWC_HCFG_6_MHZ) { + hcfg.b.fslspclksel = + DWC_HCFG_6_MHZ; -+ dwc_write_reg32 -+ (&host_if-> -+ host_global_regs-> -+ hcfg, hcfg.d32); ++ DWC_WRITE_REG32 ++ (&host_if->host_global_regs->hcfg, ++ hcfg.d32); + do_reset = 1; + } + } else { @@ -56895,10 +68599,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + DWC_HCFG_48_MHZ) { + hcfg.b.fslspclksel = + DWC_HCFG_48_MHZ; -+ dwc_write_reg32 -+ (&host_if-> -+ host_global_regs-> -+ hcfg, hcfg.d32); ++ DWC_WRITE_REG32 ++ (&host_if->host_global_regs->hcfg, ++ hcfg.d32); + do_reset = 1; + } + } @@ -56908,16 +68611,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + */ + if (usbcfg.b.phylpwrclksel == 1) { + usbcfg.b.phylpwrclksel = 0; -+ dwc_write_reg32(&global_regs-> -+ gusbcfg, -+ usbcfg.d32); ++ DWC_WRITE_REG32 ++ (&global_regs->gusbcfg, ++ usbcfg.d32); + do_reset = 1; + } + } + + if (do_reset) { -+ DWC_TASK_SCHEDULE(dwc_otg_hcd-> -+ reset_tasklet); ++ DWC_TASK_SCHEDULE(dwc_otg_hcd->reset_tasklet); + } + } + @@ -56941,7 +68643,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + } + + /* 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; +} @@ -56970,8 +68672,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + return retval; +} + -+ -+ +/** + * Gets the actual length of a transfer after the transfer halts. _halt_status + * holds the reason for the halt. @@ -56994,7 +68694,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + if (short_read != NULL) { + *short_read = 0; + } -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); ++ hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz); + + if (halt_status == DWC_OTG_HC_XFER_COMPLETE) { + if (hc->ep_is_in) { @@ -57043,21 +68743,23 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + + int xfer_length; + -+ xfer_length = get_actual_xfer_length(hc, hc_regs, qtd, -+ DWC_OTG_HC_XFER_COMPLETE, -+ &short_read); ++ xfer_length = get_actual_xfer_length(hc, hc_regs, qtd, ++ DWC_OTG_HC_XFER_COMPLETE, ++ &short_read); + + + /* non DWORD-aligned buffer case handling. */ + if (hc->align_buff && xfer_length && hc->ep_is_in) { -+ dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, xfer_length); ++ dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, ++ xfer_length); + } + + urb->actual_length += xfer_length; + -+ if(xfer_length && (hc->ep_type == DWC_OTG_EP_TYPE_BULK) && -+ (urb->flags & URB_SEND_ZERO_PACKET) && (urb->actual_length == urb->length) && -+ !(urb->length % hc->max_packet)) { ++ if (xfer_length && (hc->ep_type == DWC_OTG_EP_TYPE_BULK) && ++ (urb->flags & URB_SEND_ZERO_PACKET) ++ && (urb->actual_length == urb->length) ++ && !(urb->length % hc->max_packet)) { + xfer_done = 0; + } else if (short_read || urb->actual_length >= urb->length) { + xfer_done = 1; @@ -57067,7 +68769,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo +#ifdef DEBUG + { + hctsiz_data_t hctsiz; -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->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); @@ -57095,7 +68797,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + dwc_otg_hc_regs_t * hc_regs, dwc_otg_qtd_t * qtd) +{ + hctsiz_data_t hctsiz; -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->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; @@ -57138,10 +68840,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + frame_desc->status = 0; + frame_desc->actual_length = + get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL); -+ ++ + /* non DWORD-aligned buffer case handling. */ + if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) { -+ dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, ++ dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, + hc->qh->dw_align_buf, frame_desc->actual_length); + } + @@ -57165,19 +68867,19 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + frame_desc->status = -DWC_E_PROTOCOL; + frame_desc->actual_length = + get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL); -+ ++ + /* non DWORD-aligned buffer case handling. */ + if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) { -+ dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, ++ dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset, + hc->qh->dw_align_buf, frame_desc->actual_length); + } + /* Skip whole frame */ -+ if (hc->qh->do_split && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && -+ hc->ep_is_in && hcd->core_if->dma_enable) { ++ if (hc->qh->do_split && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && ++ hc->ep_is_in && hcd->core_if->dma_enable) { + qtd->complete_split = 0; + qtd->isoc_split_offset = 0; + } -+ ++ + break; + default: + DWC_ASSERT(1, "Unhandled _halt_status (%d)\n", halt_status); @@ -57246,23 +68948,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo +{ + dwc_otg_transaction_type_e tr_type; + int free_qtd; ++ dwc_irqflags_t flags; ++ dwc_spinlock_t *channel_lock = DWC_SPINLOCK_ALLOC(); + + DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d, xfer_len %d\n", + __func__, hc->hc_num, halt_status, hc->xfer_len); + -+#ifdef HW2937_WORKAROUND -+ if (hcd->hw2937_assigned_channels & (1<hc_num)) -+ { -+ if ((hcd->hw2937_assigned_channels &= ~(1<hc_num)) == 0) -+ hcd->hw2937_xfer_mode = HW2937_XFER_MODE_IDLE; -+ DWC_DEBUGPL(DBG_HW2937, " release %d, hw2937_ac -> %x\n", hc->hc_num, hcd->hw2937_assigned_channels); -+ } -+ else -+ { -+ DWC_DEBUGPL(DBG_ANY, " Unexpected release %d (hw2937_ac = %x)\n", hc->hc_num, hcd->hw2937_assigned_channels); -+ } -+#endif -+ + switch (halt_status) { + case DWC_OTG_HC_XFER_URB_COMPLETE: + free_qtd = 1; @@ -57294,6 +68985,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + case DWC_OTG_HC_XFER_NO_HALT_STATUS: + free_qtd = 0; + break; ++ case DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE: ++ DWC_DEBUGPL(DBG_HCDV, ++ " Complete URB with I/O error\n"); ++ free_qtd = 1; ++ qtd->urb->status = -DWC_E_IO; ++ hcd->fops->complete(hcd, qtd->urb->priv, ++ qtd->urb, -DWC_E_IO); ++ break; + default: + free_qtd = 0; + break; @@ -57301,7 +69000,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + + deactivate_qh(hcd, hc->qh, free_qtd); + -+ cleanup: ++cleanup: + /* + * Release the host channel for use by other transfers. The cleanup + * function clears the channel interrupt enables and conditions, so @@ -57310,19 +69009,26 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + dwc_otg_hc_cleanup(hcd->core_if, hc); + DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry); + -+ switch (hc->ep_type) { -+ case DWC_OTG_EP_TYPE_CONTROL: -+ case DWC_OTG_EP_TYPE_BULK: -+ hcd->non_periodic_channels--; -+ break; ++ if (!microframe_schedule) { ++ switch (hc->ep_type) { ++ case DWC_OTG_EP_TYPE_CONTROL: ++ case DWC_OTG_EP_TYPE_BULK: ++ hcd->non_periodic_channels--; ++ break; + -+ default: -+ /* -+ * Don't release reservations for periodic channels here. -+ * That's done when a periodic transfer is descheduled (i.e. -+ * when the QH is removed from the periodic schedule). -+ */ -+ break; ++ default: ++ /* ++ * Don't release reservations for periodic channels here. ++ * That's done when a periodic transfer is descheduled (i.e. ++ * when the QH is removed from the periodic schedule). ++ */ ++ break; ++ } ++ } else { ++ ++ DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); ++ hcd->available_host_channels++; ++ DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); + } + + /* Try to queue more transfers now that there's a free channel. */ @@ -57330,9 +69036,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + if (tr_type != DWC_OTG_TRANSACTION_NONE) { + dwc_otg_hcd_queue_transactions(hcd, tr_type); + } ++ DWC_SPINLOCK_FREE(channel_lock); +} + -+ +/** + * Halts a host channel. If the channel cannot be halted immediately because + * the request queue is full, this function ensures that the FIFO empty @@ -57368,7 +69074,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + * be processed. + */ + gintmsk.b.nptxfempty = 1; -+ dwc_modify_reg32(&global_regs->gintmsk, 0, gintmsk.d32); ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); + } else { + /* + * Move the QH from the periodic queued schedule to @@ -57385,7 +69091,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + * processed. + */ + gintmsk.b.ptxfempty = 1; -+ dwc_modify_reg32(&global_regs->gintmsk, 0, gintmsk.d32); ++ DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32); + } + } +} @@ -57405,7 +69111,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + + qtd->error_count = 0; + -+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint); ++ hcint.d32 = DWC_READ_REG32(&hc_regs->hcint); + if (hcint.b.nyet) { + /* + * Got a NYET on the last transaction of the transfer. This @@ -57456,7 +69162,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + hctsiz_data_t hctsiz; + qtd->error_count = 0; + -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz); ++ 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); @@ -57467,47 +69173,46 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo +} + +static int32_t handle_xfercomp_isoc_split_in(dwc_otg_hcd_t * hcd, -+ dwc_hc_t * hc, -+ dwc_otg_hc_regs_t * hc_regs, -+ dwc_otg_qtd_t * qtd) ++ dwc_hc_t * hc, ++ dwc_otg_hc_regs_t * hc_regs, ++ dwc_otg_qtd_t * qtd) +{ -+ uint32_t len; ++ uint32_t len; + struct dwc_otg_hcd_iso_packet_desc *frame_desc; + frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; -+ ++ + len = get_actual_xfer_length(hc, hc_regs, qtd, -+ DWC_OTG_HC_XFER_COMPLETE, -+ NULL); -+ ++ DWC_OTG_HC_XFER_COMPLETE, NULL); ++ + if (!len) { + qtd->complete_split = 0; + qtd->isoc_split_offset = 0; + return 0; + } + frame_desc->actual_length += len; -+ ++ + if (hc->align_buff && len) -+ dwc_memcpy(qtd->urb->buf + frame_desc->offset + qtd->isoc_split_offset, -+ hc->qh->dw_align_buf, -+ len); ++ dwc_memcpy(qtd->urb->buf + frame_desc->offset + ++ qtd->isoc_split_offset, hc->qh->dw_align_buf, len); + qtd->isoc_split_offset += len; -+ ++ + if (frame_desc->length == frame_desc->actual_length) { + frame_desc->status = 0; + qtd->isoc_frame_index++; + qtd->complete_split = 0; + qtd->isoc_split_offset = 0; + } -+ ++ + if (qtd->isoc_frame_index == qtd->urb->packet_count) { + hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0); + release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE); + } else { + release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS); + } -+ -+ return 1; /* Indicates that channel released */ ++ ++ return 1; /* Indicates that channel released */ +} ++ +/** + * Handles a host channel Transfer Complete interrupt. This handler may be + * called in either DMA mode or Slave mode. @@ -57522,13 +69227,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + dwc_otg_hcd_urb_t *urb = qtd->urb; + int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info); + -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " + "Transfer Complete--\n", hc->hc_num); + + if (hcd->core_if->dma_desc_enable) { + dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, halt_status); + if (pipe_type == UE_ISOCHRONOUS) { -+ /* Do not disable the interrupt, just clear it */ ++ /* Do not disable the interrupt, just clear it */ + clear_hc_int(hc_regs, xfercomp); + return 1; + } @@ -57540,13 +69245,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + */ + + if (hc->qh->do_split) { -+ if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hc->ep_is_in && hcd->core_if->dma_enable) { -+ if (qtd->complete_split && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs, qtd)) ++ if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hc->ep_is_in ++ && hcd->core_if->dma_enable) { ++ if (qtd->complete_split ++ && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs, ++ qtd)) + goto handle_xfercomp_done; ++ } else { ++ qtd->complete_split = 0; + } -+ else { -+ qtd->complete_split = 0; -+ } + } + + /* Update the QTD and URB states. */ @@ -57606,16 +69313,22 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + break; + case UE_INTERRUPT: + DWC_DEBUGPL(DBG_HCDV, " Interrupt transfer complete\n"); -+ update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); ++ urb_xfer_done = ++ update_urb_state_xfer_comp(hc, hc_regs, urb, qtd); + + /* + * Interrupt URB is done on the first transfer complete + * interrupt. + */ -+ hcd->fops->complete(hcd, urb->priv, urb, urb->status); ++ if (urb_xfer_done) { ++ hcd->fops->complete(hcd, urb->priv, urb, urb->status); ++ halt_status = DWC_OTG_HC_XFER_URB_COMPLETE; ++ } else { ++ halt_status = DWC_OTG_HC_XFER_COMPLETE; ++ } ++ + dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); -+ complete_periodic_xfer(hcd, hc, hc_regs, qtd, -+ DWC_OTG_HC_XFER_URB_COMPLETE); ++ complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status); + break; + case UE_ISOCHRONOUS: + DWC_DEBUGPL(DBG_HCDV, " Isochronous transfer complete\n"); @@ -57694,15 +69407,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + halt_status, NULL); + /* non DWORD-aligned buffer case handling. */ + if (hc->align_buff && bytes_transferred && hc->ep_is_in) { -+ dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, bytes_transferred); ++ dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf, ++ bytes_transferred); + } -+ ++ + urb->actual_length += bytes_transferred; + +#ifdef DEBUG + { + hctsiz_data_t hctsiz; -+ hctsiz.d32 = dwc_read_reg32(&hc_regs->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); @@ -57729,7 +69443,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + dwc_otg_hc_regs_t * hc_regs, + dwc_otg_qtd_t * qtd) +{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " + "NAK Received--\n", hc->hc_num); + + /* @@ -57749,11 +69463,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + case UE_CONTROL: + case UE_BULK: + if (hcd->core_if->dma_enable && hc->ep_is_in) { -+#ifdef HW2937_WORKAROUND -+ if (hc->halt_status == DWC_OTG_HC_XFER_PAUSE_IN) { -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); -+ } -+#endif + /* + * NAK interrupts are enabled on bulk/control IN + * transfers in DMA mode for the sole purpose of @@ -57779,7 +69488,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + + if (hc->speed == DWC_OTG_EP_SPEED_HIGH) + hc->qh->ping_state = 1; -+ } ++ } + + /* + * Halt the channel so the transfer can be re-started from @@ -57793,18 +69502,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); + break; + case UE_ISOCHRONOUS: -+#ifdef HW2937_WORKAROUND -+ if (hc->halt_status == DWC_OTG_HC_XFER_PAUSE_IN) { -+ halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK); -+ break; -+ } -+#endif + /* Should never get called for isochronous transfers. */ + DWC_ASSERT(1, "NACK interrupt for ISOC transfer\n"); + break; + } + -+ handle_nak_done: ++handle_nak_done: + disable_hc_int(hc_regs, nak); + + return 1; @@ -57820,7 +69523,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + dwc_otg_hc_regs_t * hc_regs, + dwc_otg_qtd_t * qtd) +{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " + "ACK Received--\n", hc->hc_num); + + if (hc->do_split) { @@ -57854,11 +69557,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + */ + { + struct dwc_otg_hcd_iso_packet_desc -+ *frame_desc; ++ *frame_desc; + + frame_desc = -+ &qtd->urb->iso_descs[qtd-> -+ isoc_frame_index]; ++ &qtd->urb-> ++ iso_descs[qtd->isoc_frame_index]; + qtd->isoc_split_offset += 188; + + if ((frame_desc->length - @@ -57890,14 +69593,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + */ + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK); + } -+#ifdef HW2937_WORKAROUND -+ else if (hc->halt_status == DWC_OTG_HC_XFER_PAUSE_IN) { -+ dwc_otg_hc_regs_t *hc_regs = hcd->core_if->host_if->hc_regs[hc->hc_num]; -+ update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd, DWC_OTG_HC_XFER_PAUSE_IN); -+ dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd); -+ release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_PAUSE_IN); -+ } -+#endif + } + + /* @@ -57922,7 +69617,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + dwc_otg_hc_regs_t * hc_regs, + dwc_otg_qtd_t * qtd) +{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " + "NYET Received--\n", hc->hc_num); + + /* @@ -57930,7 +69625,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + * re-do the CSPLIT immediately on non-periodic + */ + if (hc->do_split && hc->complete_split) { -+ if (hc->ep_is_in && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hcd->core_if->dma_enable) { ++ if (hc->ep_is_in && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) ++ && hcd->core_if->dma_enable) { + qtd->complete_split = 0; + qtd->isoc_split_offset = 0; + if (++qtd->isoc_frame_index == qtd->urb->packet_count) { @@ -57986,7 +69682,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + */ + halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET); + -+ handle_nyet_done: ++handle_nyet_done: + disable_hc_int(hc_regs, nyet); + return 1; +} @@ -58000,11 +69696,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + dwc_otg_hc_regs_t * hc_regs, + dwc_otg_qtd_t * qtd) +{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " + "Babble Error--\n", hc->hc_num); -+ ++ + if (hcd->core_if->dma_desc_enable) { -+ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_BABBLE_ERR); ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ DWC_OTG_HC_XFER_BABBLE_ERR); + goto handle_babble_done; + } + @@ -58018,7 +69715,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + DWC_OTG_HC_XFER_BABBLE_ERR); + halt_channel(hcd, hc, qtd, halt_status); + } -+ ++ +handle_babble_done: + disable_hc_int(hc_regs, bblerr); + return 1; @@ -58041,13 +69738,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + + dwc_otg_hcd_urb_t *urb = qtd->urb; + -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ DWC_DEBUGPL(DBG_HCDI, "--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); ++ 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); @@ -58058,45 +69755,44 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + DWC_ERROR(" Endpoint: %d, %s\n", + dwc_otg_hcd_get_ep_num(&urb->pipe_info), + (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT")); -+ + + switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) { -+case UE_CONTROL: -+ pipetype = "CONTROL"; -+ break; ++ case UE_CONTROL: ++ pipetype = "CONTROL"; ++ break; + case UE_BULK: -+ pipetype = "BULK"; -+ break; ++ pipetype = "BULK"; ++ break; + case UE_INTERRUPT: -+ pipetype = "INTERRUPT"; -+ break; ++ pipetype = "INTERRUPT"; ++ break; + case UE_ISOCHRONOUS: -+ pipetype = "ISOCHRONOUS"; -+ break; ++ pipetype = "ISOCHRONOUS"; ++ break; + default: -+ pipetype = "UNKNOWN"; ++ pipetype = "UNKNOWN"; + break; + } -+ ++ + DWC_ERROR(" Endpoint type: %s\n", pipetype); + + switch (hc->speed) { + case DWC_OTG_EP_SPEED_HIGH: -+ speed = "HIGH"; -+ break; -+ case DWC_OTG_EP_SPEED_FULL: -+ speed = "FULL"; -+ break; -+ case DWC_OTG_EP_SPEED_LOW: -+ speed = "LOW"; -+ break; -+ default: -+ speed = "UNKNOWN"; ++ speed = "HIGH"; + break; -+ }; ++ case DWC_OTG_EP_SPEED_FULL: ++ speed = "FULL"; ++ break; ++ case DWC_OTG_EP_SPEED_LOW: ++ speed = "LOW"; ++ break; ++ default: ++ speed = "UNKNOWN"; ++ break; ++ }; + + DWC_ERROR(" Speed: %s\n", speed); -+ ++ + DWC_ERROR(" Max packet size: %d\n", + dwc_otg_hcd_get_mps(&urb->pipe_info)); + DWC_ERROR(" Data buffer length: %d\n", urb->length); @@ -58108,7 +69804,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + + /* Core haltes the channel for Descriptor DMA mode */ + if (hcd->core_if->dma_desc_enable) { -+ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_AHB_ERR); ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ DWC_OTG_HC_XFER_AHB_ERR); + goto handle_ahberr_done; + } + @@ -58133,11 +69830,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + dwc_otg_hc_regs_t * hc_regs, + dwc_otg_qtd_t * qtd) +{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " + "Transaction Error--\n", hc->hc_num); + + if (hcd->core_if->dma_desc_enable) { -+ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_XACT_ERR); ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ DWC_OTG_HC_XFER_XACT_ERR); + goto handle_xacterr_done; + } + @@ -58195,7 +69893,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + dwc_otg_hc_regs_t * hc_regs, + dwc_otg_qtd_t * qtd) +{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " + "Frame Overrun--\n", hc->hc_num); + + switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { @@ -58231,7 +69929,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + dwc_otg_hc_regs_t * hc_regs, + dwc_otg_qtd_t * qtd) +{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " + "Data Toggle Error--\n", hc->hc_num); + + if (hc->ep_is_in) { @@ -58269,11 +69967,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + * 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); ++ 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, " + "channel %d, hcchar 0x%08x, hctsiz 0x%08x, " @@ -58294,7 +69992,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + * never be set when the halt interrupt occurs. Halt the + * 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", @@ -58334,7 +70032,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + } + + if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE || -+ (hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR && !hcd->core_if->dma_desc_enable)) { ++ (hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR ++ && !hcd->core_if->dma_desc_enable)) { + /* + * Just release the channel. A dequeue can happen on a + * transfer timeout. In the case of an AHB Error, the channel @@ -58342,15 +70041,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + * recover. + */ + if (hcd->core_if->dma_desc_enable) -+ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, hc->halt_status); ++ dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, ++ hc->halt_status); + else + 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) { + /** @todo This is here because of a possible hardware bug. Spec @@ -58383,7 +70083,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); + } else if (hcint.b.xcs_xact && hcd->core_if->dma_desc_enable) { + handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd); -+ } else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) { ++ } else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) { + handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd); + } else if (hcint.b.bblerr) { + handle_hc_babble_intr(hcd, hc, hc_regs, qtd); @@ -58435,10 +70135,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + ("%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)); ++ DWC_READ_REG32(&hcd-> ++ core_if->core_global_regs-> ++ gintsts)); + } -+ ++ + } + } else { + DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n", @@ -58462,7 +70163,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + dwc_otg_hc_regs_t * hc_regs, + dwc_otg_qtd_t * qtd) +{ -+ DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: " ++ DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: " + "Channel Halted--\n", hc->hc_num); + + if (hcd->core_if->dma_enable) { @@ -58495,8 +70196,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num]; + qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list); + -+ 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); + DWC_DEBUGPL(DBG_HCDV, + " hcint 0x%08x, hcintmsk 0x%08x, hcint&hcintmsk 0x%08x\n", + hcint.d32, hcintmsk.d32, (hcint.d32 & hcintmsk.d32)); @@ -58553,17 +70254,19 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c linux-rpi-bo + + return retval; +} ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c +new file mode 100644 +index 0000000..f91c4b1 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c +@@ -0,0 +1,938 @@ + -+#endif /* DWC_DEVICE_ONLY */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c 2012-07-15 20:29:19.190085613 +0200 -@@ -0,0 +1,890 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_linux.c $ -+ * $Revision: #11 $ -+ * $Date: 2009/04/21 $ -+ * $Change: 1237476 $ ++ * $Revision: #20 $ ++ * $Date: 2011/10/26 $ ++ * $Change: 1872981 $ + * + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless @@ -58611,27 +70314,25 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b +#include +#include +#include -+ -+#ifdef LM_INTERFACE -+//#include -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+#include -+#include -+#else -+#include -+#include -+#endif -+#elif defined(PLATFORM_INTERFACE) -+#include -+#endif -+ ++#include +#include ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) ++#include <../drivers/usb/core/hcd.h> ++#else +#include ++#endif ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) ++#define USB_URB_EP_LINKING 1 ++#else ++#define USB_URB_EP_LINKING 0 ++#endif + +#include "dwc_otg_hcd_if.h" +#include "dwc_otg_dbg.h" +#include "dwc_otg_driver.h" +#include "dwc_otg_hcd.h" ++#include "dwc_otg_mphi_fix.h" + +/** + * Gets the endpoint number from a _bEndpointAddress argument. The endpoint is @@ -58642,25 +70343,30 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + +static const char dwc_otg_hcd_name[] = "dwc_otg_hcd"; + ++extern bool fiq_fix_enable; ++ +/** @name Linux HC Driver API Functions */ +/** @{ */ +/* manage i/o requests, device state */ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+static int urb_enqueue(struct usb_hcd *hcd, ++static int dwc_otg_urb_enqueue(struct usb_hcd *hcd, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) + struct usb_host_endpoint *ep, -+ struct urb *urb, gfp_t mem_flags); -+ -+static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb); -+#else -+static int urb_enqueue(struct usb_hcd *hcd, -+ struct urb *urb, gfp_t mem_flags); -+ -+static int urb_dequeue(struct usb_hcd *hcd, -+ struct urb *urb, int status); +#endif ++ struct urb *urb, gfp_t mem_flags); ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb); ++#endif ++#else /* kernels at or post 2.6.30 */ ++static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, ++ struct urb *urb, int status); ++#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) */ + +static void endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep); -+ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep); ++#endif +static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd); +extern int hcd_start(struct usb_hcd *hcd); +extern void hcd_stop(struct usb_hcd *hcd); @@ -58692,10 +70398,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + //.resume = + .stop = hcd_stop, + -+ .urb_enqueue = urb_enqueue, -+ .urb_dequeue = urb_dequeue, ++ .urb_enqueue = dwc_otg_urb_enqueue, ++ .urb_dequeue = dwc_otg_urb_dequeue, + .endpoint_disable = endpoint_disable, -+ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++ .endpoint_reset = endpoint_reset, ++#endif + .get_frame_number = get_frame_number, + + .hub_status_data = hub_status_data, @@ -58822,21 +70530,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + * Sets the final status of an URB and returns it to the device driver. Any + * required cleanup of the URB is performed. + */ -+#ifdef DEBUG_SOF_FIX -+extern unsigned int g_dwc_otg_interrupt_counts[10]; -+#endif -+ +static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle, + dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status) +{ -+ uint64_t flags; + struct urb *urb = (struct urb *)urb_handle; + -+#ifdef DEBUG_SOF_FIX -+ g_dwc_otg_interrupt_counts[7]++; -+#endif -+ -+#ifdef DEBUG + if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { + DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n", + __func__, urb, usb_pipedevice(urb->pipe), @@ -58850,7 +70548,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + } + } + } -+#endif + + urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb); + /* Convert status value. */ @@ -58889,8 +70586,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + dwc_otg_hcd_urb_get_iso_desc_actual_length + (dwc_otg_urb, i); + urb->iso_frame_desc[i].status = -+ dwc_otg_hcd_urb_get_iso_desc_status -+ (dwc_otg_urb, i); ++ dwc_otg_hcd_urb_get_iso_desc_status(dwc_otg_urb, i); + } + } + @@ -58909,21 +70605,24 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + if (ep) { + free_bus_bandwidth(dwc_otg_hcd_to_hcd(hcd), + dwc_otg_hcd_get_ep_bandwidth(hcd, -+ ep-> -+ hcpriv), ++ ep->hcpriv), + urb); + } + } + -+ dwc_free(dwc_otg_urb); -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) ++ DWC_FREE(dwc_otg_urb); ++ ++#if USB_URB_EP_LINKING ++ usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb); ++#endif ++ DWC_SPINUNLOCK(hcd->lock); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) + usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb); +#else -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb); -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); + usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status); +#endif ++ DWC_SPINLOCK(hcd->lock); ++ + return 0; +} + @@ -58936,34 +70635,26 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + .get_b_hnp_enable = _get_b_hnp_enable, +}; + ++static struct fiq_handler fh = { ++ .name = "usb_fiq", ++}; ++static uint8_t fiqStack[1024]; ++ ++extern mphi_regs_t c_mphi_regs; +/** + * Initializes the HCD. This function allocates memory for and initializes the + * static parts of the usb_hcd and dwc_otg_hcd structures. It also registers the + * USB bus with the core and calls the hc_driver->start() function. It returns + * a negative error on failure. + */ -+int hcd_init( -+#ifdef LM_INTERFACE -+ struct lm_device *_dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *_dev -+#endif -+ ) ++int hcd_init(dwc_bus_dev_t *_dev) +{ + struct usb_hcd *hcd = NULL; + dwc_otg_hcd_t *dwc_otg_hcd = NULL; -+#ifdef LM_INTERFACE -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); -+#endif -+ ++ dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev); + int retval = 0; + u64 dmamask; ++ struct pt_regs regs; + + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD INIT otg_dev=%p\n", otg_dev); + @@ -58981,26 +70672,57 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + pci_set_consistent_dma_mask(_dev, dmamask); +#endif + ++ if (fiq_fix_enable) ++ { ++ // Set up fiq ++ claim_fiq(&fh); ++ set_fiq_handler(__FIQ_Branch, 8); ++ memset(®s,0,sizeof(regs)); ++ regs.ARM_r8 = (long)dwc_otg_hcd_handle_fiq; ++ regs.ARM_r9 = (long)0; ++ regs.ARM_sp = (long)fiqStack + sizeof(fiqStack) - 4; ++ set_fiq_regs(®s); ++ } ++ + /* + * Allocate memory for the base HCD plus the DWC OTG HCD. + * Initialize the base HCD. + */ -+ hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+ _dev->dev.bus_id); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) ++ hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, _dev->dev.bus_id); +#else -+ dev_name(&_dev->dev)); ++ hcd = usb_create_hcd(&dwc_otg_hc_driver, &_dev->dev, dev_name(&_dev->dev)); ++ hcd->has_tt = 1; ++// hcd->uses_new_polling = 1; ++// hcd->poll_rh = 0; +#endif + if (!hcd) { + retval = -ENOMEM; + goto error1; + } + -+ hcd->regs = otg_dev->base; ++ hcd->regs = otg_dev->os_dep.base; + -+ /* Integrate TT in root hub */ -+ hcd->has_tt = 1; ++ if (fiq_fix_enable) ++ { ++ //Set the mphi periph to the required registers ++ c_mphi_regs.base = otg_dev->os_dep.mphi_base; ++ c_mphi_regs.ctrl = otg_dev->os_dep.mphi_base + 0x4c; ++ c_mphi_regs.outdda = otg_dev->os_dep.mphi_base + 0x28; ++ c_mphi_regs.outddb = otg_dev->os_dep.mphi_base + 0x2c; ++ c_mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50; + ++ //Enable mphi peripheral ++ writel((1<<31),c_mphi_regs.ctrl); ++#ifdef DEBUG ++ if (readl(c_mphi_regs.ctrl) & 0x80000000) ++ DWC_DEBUGPL(DBG_USER, "MPHI periph has been enabled\n"); ++ else ++ DWC_DEBUGPL(DBG_USER, "MPHI periph has NOT been enabled\n"); ++#endif ++ // Enable FIQ interrupt from USB peripheral ++ enable_fiq(INTERRUPT_VC_USB); ++ } + /* Initialize the DWC OTG HCD. */ + dwc_otg_hcd = dwc_otg_hcd_alloc_hcd(); + if (!dwc_otg_hcd) { @@ -59014,17 +70736,24 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + goto error2; + } + ++ otg_dev->hcd->otg_dev = otg_dev; + hcd->self.otg_port = dwc_otg_hcd_otg_port(dwc_otg_hcd); -+ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33) //don't support for LM(with 2.6.20.1 kernel) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) //version field absent later ++ hcd->self.otg_version = dwc_otg_get_otg_version(otg_dev->core_if); ++#endif ++ /* Don't support SG list at this point */ ++ hcd->self.sg_tablesize = 0; ++#endif + /* + * Finish generic HCD initialization and start the HCD. This function + * allocates the DMA buffer pool, registers the USB bus, requests the + * IRQ line, and calls hcd_start method. + */ +#ifdef PLATFORM_INTERFACE -+ retval = usb_add_hcd(hcd, platform_get_irq(_dev, 0), IRQF_SHARED); ++ retval = usb_add_hcd(hcd, platform_get_irq(_dev, 0), IRQF_SHARED | IRQF_DISABLED); +#else -+ retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED); ++ retval = usb_add_hcd(hcd, _dev->irq, IRQF_SHARED | IRQF_DISABLED); +#endif + if (retval < 0) { + goto error2; @@ -59033,9 +70762,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + dwc_otg_hcd_set_priv_data(dwc_otg_hcd, hcd); + return 0; + -+ error2: ++error2: + usb_put_hcd(hcd); -+ error1: ++error1: + return retval; +} + @@ -59043,24 +70772,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + * Removes the HCD. + * Frees memory and resources associated with the HCD and deregisters the bus. + */ -+void hcd_remove( -+#ifdef LM_INTERFACE -+ struct lm_device *_dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *_dev -+#endif -+ ) ++void hcd_remove(dwc_bus_dev_t *_dev) +{ -+#ifdef LM_INTERFACE -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); -+#endif -+ ++ dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev); + dwc_otg_hcd_t *dwc_otg_hcd; + struct usb_hcd *hcd; + @@ -59186,26 +70900,25 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + } + } +} -+ +#endif + +/** Starts processing a USB transfer request specified by a USB Request Block + * (URB). mem_flags indicates the type of memory allocation to use while + * processing this URB. */ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+static int urb_enqueue(struct usb_hcd *hcd, ++static int dwc_otg_urb_enqueue(struct usb_hcd *hcd, ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) + struct usb_host_endpoint *ep, ++#endif + struct urb *urb, gfp_t mem_flags) +{ -+#else -+static int urb_enqueue(struct usb_hcd *hcd, -+ struct urb *urb, -+ gfp_t mem_flags) -+{ -+ struct usb_host_endpoint *ep = urb->ep; ++ int retval = 0; ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) ++ struct usb_host_endpoint *ep = urb->ep; ++#endif ++#if USB_URB_EP_LINKING ++ dwc_irqflags_t irqflags; +#endif + void **ref_ep_hcpriv = &ep->hcpriv; -+ int retval = 0; + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); + dwc_otg_hcd_urb_t *dwc_otg_urb; + int i; @@ -59216,7 +70929,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + +#ifdef DEBUG + if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { -+ dump_urb_info(urb, "urb_enqueue"); ++ dump_urb_info(urb, "dwc_otg_urb_enqueue"); + } +#endif + @@ -59245,9 +70958,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + ep_type = USB_ENDPOINT_XFER_INT; + break; + default: -+ DWC_WARN("Wrong ep type\n"); ++ DWC_WARN("Wrong EP type - %d\n", usb_pipetype(urb->pipe)); + } + ++ /* # of packets is often 0 - do we really need to call this then? */ + dwc_otg_urb = dwc_otg_hcd_urb_alloc(dwc_otg_hcd, + urb->number_of_packets, + mem_flags == GFP_ATOMIC ? 1 : 0); @@ -59256,6 +70970,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + return -ENOMEM; + + urb->hcpriv = dwc_otg_urb; ++ if (!dwc_otg_urb && urb->number_of_packets) ++ return -ENOMEM; + + dwc_otg_hcd_urb_set_pipeinfo(dwc_otg_urb, usb_pipedevice(urb->pipe), + usb_pipeendpoint(urb->pipe), ep_type, @@ -59275,7 +70991,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + // DMA addresses are bus addresses not physical addresses! + buf = dma_to_virt(&urb->dev->dev, urb->transfer_dma); + } -+ ++ + if (!(urb->transfer_flags & URB_NO_INTERRUPT)) + flags |= URB_GIVEBACK_ASAP; + if (urb->transfer_flags & URB_ZERO_PACKET) @@ -59284,27 +71000,28 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + dwc_otg_hcd_urb_set_params(dwc_otg_urb, urb, buf, + urb->transfer_dma, + urb->transfer_buffer_length, -+ urb->setup_packet, -+ urb->setup_dma, -+ flags, -+ urb->interval); ++ urb->setup_packet, ++ urb->setup_dma, flags, urb->interval); + + for (i = 0; i < urb->number_of_packets; ++i) { + dwc_otg_hcd_urb_set_iso_desc_params(dwc_otg_urb, i, -+ urb->iso_frame_desc[i]. -+ offset, -+ urb->iso_frame_desc[i]. -+ length); ++ urb-> ++ iso_frame_desc[i].offset, ++ urb-> ++ iso_frame_desc[i].length); + } + -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) ++#if USB_URB_EP_LINKING ++ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags); + retval = usb_hcd_link_urb_to_ep(hcd, urb); ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags); + if (0 == retval) +#endif + { + retval = dwc_otg_hcd_urb_enqueue(dwc_otg_hcd, dwc_otg_urb, + /*(dwc_otg_qh_t **)*/ -+ ref_ep_hcpriv); ++ ref_ep_hcpriv, ++ mem_flags == GFP_ATOMIC ? 1 : 0); + if (0 == retval) { + if (alloc_bandwidth) { + allocate_bus_bandwidth(hcd, @@ -59313,8 +71030,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + urb); + } + } else { -+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)) ++#if USB_URB_EP_LINKING ++ dwc_irqflags_t irqflags; ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG dwc_otg_hcd_urb_enqueue failed rc %d\n", retval); ++ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &irqflags); + usb_hcd_unlink_urb_from_ep(hcd, urb); ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, irqflags); +#endif + if (retval == -DWC_E_NO_DEVICE) { + retval = -ENODEV; @@ -59326,54 +71047,61 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + +/** Aborts/cancels a USB transfer request. Always returns 0 to indicate + * success. */ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) +#else -+static int urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ++static int dwc_otg_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) +#endif +{ -+ int rc; -+ uint64_t flags; ++ dwc_irqflags_t flags; + dwc_otg_hcd_t *dwc_otg_hcd; ++ int rc; ++ + DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue\n"); + + dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); + +#ifdef DEBUG + if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { -+ dump_urb_info(urb, "urb_dequeue"); ++ dump_urb_info(urb, "dwc_otg_urb_dequeue"); + } +#endif -+ if(urb->hcpriv != NULL) { -+ dwc_otg_hcd_urb_dequeue(dwc_otg_hcd, (dwc_otg_hcd_urb_t *)urb->hcpriv); + -+ dwc_free(urb->hcpriv); -+ urb->hcpriv = NULL; -+ } -+ -+ /* Higher layer software sets URB status. */ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+ usb_hcd_giveback_urb(hcd, urb); -+#else + DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); + rc = usb_hcd_check_unlink_urb(hcd, urb, status); -+ if(!rc) -+ { -+ usb_hcd_unlink_urb_from_ep(hcd, urb); -+ } ++ if (0 == rc) { ++ if(urb->hcpriv != NULL) { ++ dwc_otg_hcd_urb_dequeue(dwc_otg_hcd, ++ (dwc_otg_hcd_urb_t *)urb->hcpriv); + -+ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); -+ if (!rc) -+ { -+ usb_hcd_giveback_urb(hcd, urb, status); -+ } ++ DWC_FREE(urb->hcpriv); ++ urb->hcpriv = NULL; ++ } ++ } ++ ++ if (0 == rc) { ++ /* Higher layer software sets URB status. */ ++#if USB_URB_EP_LINKING ++ usb_hcd_unlink_urb_from_ep(hcd, urb); +#endif -+ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { -+ DWC_PRINTF("Called usb_hcd_giveback_urb()\n"); -+ DWC_PRINTF(" urb->status = %d\n", urb->status); -+ } -+ -+ return 0; ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ usb_hcd_giveback_urb(hcd, urb); ++#else ++ usb_hcd_giveback_urb(hcd, urb, status); ++#endif ++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) { ++ DWC_PRINTF("Called usb_hcd_giveback_urb() \n"); ++ DWC_PRINTF(" 1urb->status = %d\n", urb->status); ++ } ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue OK\n"); ++ } else { ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Dequeue failed - rc %d\n", ++ rc); ++ } ++ ++ return rc; +} + +/* Frees resources in the DWC_otg controller related to a given endpoint. Also @@ -59391,15 +71119,43 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + ep->hcpriv = NULL; +} + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) ++/* Resets endpoint specific parameter values, in current version used to reset ++ * the data toggle(as a WA). This function can be called from usb_clear_halt routine */ ++static void endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) ++{ ++ dwc_irqflags_t flags; ++ struct usb_device *udev = NULL; ++ int epnum = usb_endpoint_num(&ep->desc); ++ int is_out = usb_endpoint_dir_out(&ep->desc); ++ int is_control = usb_endpoint_xfer_control(&ep->desc); ++ dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); ++ struct device *dev = DWC_OTG_OS_GETDEV(dwc_otg_hcd->otg_dev->os_dep); ++ ++ if (dev) ++ udev = to_usb_device(dev); ++ else ++ return; ++ ++ DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD EP RESET: Endpoint Num=0x%02d\n", epnum); ++ ++ DWC_SPINLOCK_IRQSAVE(dwc_otg_hcd->lock, &flags); ++ usb_settoggle(udev, epnum, is_out, 0); ++ if (is_control) ++ usb_settoggle(udev, epnum, !is_out, 0); ++ ++ if (ep->hcpriv) { ++ dwc_otg_hcd_endpoint_reset(dwc_otg_hcd, ep->hcpriv); ++ } ++ DWC_SPINUNLOCK_IRQRESTORE(dwc_otg_hcd->lock, flags); ++} ++#endif ++ +/** Handles host mode interrupts for the DWC_otg controller. Returns IRQ_NONE if + * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid + * interrupt. + * + * This function is called by the USB core when an interrupt occurs */ -+ -+#ifdef DEBUG_SOF_FIX -+unsigned int g_dwc_otg_hcd_irq_count = 0; -+#endif +static irqreturn_t dwc_otg_hcd_irq(struct usb_hcd *hcd) +{ + dwc_otg_hcd_t *dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd); @@ -59407,12 +71163,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + if (retval != 0) { + S3C2410X_CLEAR_EINTPEND(); + } -+ -+#ifdef DEBUG_SOF_FIX -+ ++g_dwc_otg_hcd_irq_count; -+ if ((++g_dwc_otg_hcd_irq_count %10000) == 0) -+ printk(KERN_ERR "dwc_otg_hcd_irq: %u completions.\n", g_dwc_otg_hcd_irq_count); -+#endif + return IRQ_RETVAL(retval); +} + @@ -59448,16 +71198,18 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c linux-rpi-b + return retval; +} + -+#endif /* DWC_DEVICE_ONLY */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c 2012-07-15 20:29:19.192085654 +0200 -@@ -0,0 +1,732 @@ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c +new file mode 100644 +index 0000000..ac10323 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c +@@ -0,0 +1,938 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_queue.c $ -+ * $Revision: #39 $ -+ * $Date: 2009/04/21 $ -+ * $Change: 1237477 $ ++ * $Revision: #44 $ ++ * $Date: 2011/10/26 $ ++ * $Change: 1873028 $ + * + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless @@ -59497,6 +71249,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b +#include "dwc_otg_hcd.h" +#include "dwc_otg_regs.h" + ++extern bool microframe_schedule; ++ +/** + * Free each QTD in the QH's QTD-list then free the QH. QH should already be + * removed from a list. QTD list should already be empty if called from URB @@ -59508,32 +71262,28 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b +void dwc_otg_hcd_qh_free(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) +{ + dwc_otg_qtd_t *qtd, *qtd_tmp; -+ uint64_t flags; + + /* Free each QTD in the QTD list */ -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ DWC_SPINLOCK(hcd->lock); + DWC_CIRCLEQ_FOREACH_SAFE(qtd, qtd_tmp, &qh->qtd_list, qtd_list_entry) { + DWC_CIRCLEQ_REMOVE(&qh->qtd_list, qtd, qtd_list_entry); + dwc_otg_hcd_qtd_free(qtd); + } -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); + + if (hcd->core_if->dma_desc_enable) { + dwc_otg_hcd_qh_free_ddma(hcd, qh); -+ } -+ else if (qh->dw_align_buf) { ++ } else if (qh->dw_align_buf) { + uint32_t buf_size; -+ if(qh->ep_type == UE_ISOCHRONOUS) { ++ if (qh->ep_type == UE_ISOCHRONOUS) { + buf_size = 4096; + } else { + buf_size = hcd->core_if->core_params->max_transfer_size; + } -+ dwc_dma_free(buf_size, qh->dw_align_buf, qh->dw_align_buf_dma); ++ DWC_DMA_FREE(buf_size, qh->dw_align_buf, qh->dw_align_buf_dma); + } -+ -+ -+ -+ dwc_free(qh); ++ ++ DWC_FREE(qh); ++ DWC_SPINUNLOCK(hcd->lock); + return; +} + @@ -59544,8 +71294,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b +#define NS_TO_US(ns) ((ns + 500) / 1000) + /* convert & round nanoseconds to microseconds */ + -+static uint32_t calc_bus_time(int speed, int is_in, int is_isoc, -+ int bytecount) ++static uint32_t calc_bus_time(int speed, int is_in, int is_isoc, int bytecount) +{ + unsigned long retval; + @@ -59599,7 +71348,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + DWC_WARN("Unknown device speed\n"); + retval = -1; + } -+ ++ + return NS_TO_US(retval); +} + @@ -59612,18 +71361,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + * to initialize the QH. + */ +#define SCHEDULE_SLOP 10 -+void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, -+ dwc_otg_hcd_urb_t * urb) ++void qh_init(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, dwc_otg_hcd_urb_t * urb) +{ + char *speed, *type; + int dev_speed; + uint32_t hub_addr, hub_port; + + dwc_memset(qh, 0, sizeof(dwc_otg_qh_t)); -+ ++ + /* Initialize QH */ + qh->ep_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info); -+ + qh->ep_is_in = dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? 1 : 0; + + qh->data_toggle = DWC_OTG_HC_PID_DATA0; @@ -59635,17 +71382,20 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + /* FS/LS Enpoint on HS Hub + * NOT virtual root hub */ + dev_speed = hcd->fops->speed(hcd, urb->priv); ++ + hcd->fops->hub_info(hcd, urb->priv, &hub_addr, &hub_port); + qh->do_split = 0; ++ if (microframe_schedule) ++ qh->speed = dev_speed; ++ ++ + if (((dev_speed == USB_SPEED_LOW) || + (dev_speed == USB_SPEED_FULL)) && + (hub_addr != 0 && hub_addr != 1)) { -+ + DWC_DEBUGPL(DBG_HCD, + "QH init: EP %d: TT found at hub addr %d, for port %d\n", + dwc_otg_hcd_get_ep_num(&urb->pipe_info), hub_addr, + hub_port); -+ + qh->do_split = 1; + } + @@ -59657,22 +71407,22 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + int bytecount = + dwc_hb_mult(qh->maxp) * dwc_max_packet(qh->maxp); + -+ qh->usecs = calc_bus_time((qh->do_split ? USB_SPEED_HIGH : dev_speed), -+ qh->ep_is_in, -+ (qh->ep_type == UE_ISOCHRONOUS), -+ bytecount); ++ qh->usecs = ++ calc_bus_time((qh->do_split ? USB_SPEED_HIGH : dev_speed), ++ qh->ep_is_in, (qh->ep_type == UE_ISOCHRONOUS), ++ bytecount); + /* Start in a slightly future (micro)frame. */ + qh->sched_frame = dwc_frame_num_inc(hcd->frame_number, + SCHEDULE_SLOP); + qh->interval = urb->interval; -+ ++ +#if 0 + /* Increase interrupt polling rate for debugging. */ + if (qh->ep_type == UE_INTERRUPT) { + 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) && + ((dev_speed == USB_SPEED_LOW) || + (dev_speed == USB_SPEED_FULL))) { @@ -59726,7 +71476,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + type = "?"; + break; + } -+ ++ + DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD QH - Type = %s\n", type); + +#ifdef DEBUG @@ -59746,30 +71496,35 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + * @param hcd The HCD state structure for the DWC OTG controller. + * @param urb Holds the information about the device/endpoint that we need + * to initialize the QH. ++ * @param atomic_alloc Flag to do atomic allocation if needed + * + * @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, -+ dwc_otg_hcd_urb_t * urb) ++ dwc_otg_hcd_urb_t * urb, int atomic_alloc) +{ + dwc_otg_qh_t *qh; + + /* Allocate memory */ + /** @todo add memflags argument */ -+ qh = dwc_otg_hcd_qh_alloc(); ++ qh = dwc_otg_hcd_qh_alloc(atomic_alloc); + if (qh == NULL) { ++ DWC_ERROR("qh allocation failed"); + return NULL; + } + + qh_init(hcd, qh, urb); -+ -+ if (hcd->core_if->dma_desc_enable && (dwc_otg_hcd_qh_init_ddma(hcd, qh) < 0)) { -+ dwc_otg_hcd_qh_free(hcd, qh); ++ ++ if (hcd->core_if->dma_desc_enable ++ && (dwc_otg_hcd_qh_init_ddma(hcd, qh) < 0)) { ++ dwc_otg_hcd_qh_free(hcd, qh); + return NULL; + } -+ ++ + return qh; +} + ++/* microframe_schedule=0 start */ ++ +/** + * Checks that a channel is available for a periodic transfer. + * @@ -59786,8 +71541,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + 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)) { ++ if ((hcd->periodic_channels + hcd->non_periodic_channels < num_channels) ++ && (hcd->periodic_channels < num_channels - 1)) { + status = 0; + } else { + DWC_INFO("%s: Total channels: %d, Periodic: %d, Non-periodic: %d\n", @@ -59838,6 +71593,162 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + return status; +} + ++/* microframe_schedule=0 end */ ++ ++/** ++ * Microframe scheduler ++ * track the total use in hcd->frame_usecs ++ * keep each qh use in qh->frame_usecs ++ * when surrendering the qh then donate the time back ++ */ ++const unsigned short max_uframe_usecs[]={ 100, 100, 100, 100, 100, 100, 30, 0 }; ++ ++/* ++ * called from dwc_otg_hcd.c:dwc_otg_hcd_init ++ */ ++int init_hcd_usecs(dwc_otg_hcd_t *_hcd) ++{ ++ int i; ++ for (i=0; i<8; i++) { ++ _hcd->frame_usecs[i] = max_uframe_usecs[i]; ++ } ++ return 0; ++} ++ ++static int find_single_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh) ++{ ++ int i; ++ unsigned short utime; ++ int t_left; ++ int ret; ++ int done; ++ ++ ret = -1; ++ utime = _qh->usecs; ++ t_left = utime; ++ i = 0; ++ done = 0; ++ while (done == 0) { ++ /* At the start _hcd->frame_usecs[i] = max_uframe_usecs[i]; */ ++ if (utime <= _hcd->frame_usecs[i]) { ++ _hcd->frame_usecs[i] -= utime; ++ _qh->frame_usecs[i] += utime; ++ t_left -= utime; ++ ret = i; ++ done = 1; ++ return ret; ++ } else { ++ i++; ++ if (i == 8) { ++ done = 1; ++ ret = -1; ++ } ++ } ++ } ++ return ret; ++ } ++ ++/* ++ * use this for FS apps that can span multiple uframes ++ */ ++static int find_multi_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh) ++{ ++ int i; ++ int j; ++ unsigned short utime; ++ int t_left; ++ int ret; ++ int done; ++ unsigned short xtime; ++ ++ ret = -1; ++ utime = _qh->usecs; ++ t_left = utime; ++ i = 0; ++ done = 0; ++loop: ++ while (done == 0) { ++ if(_hcd->frame_usecs[i] <= 0) { ++ i++; ++ if (i == 8) { ++ done = 1; ++ ret = -1; ++ } ++ goto loop; ++ } ++ ++ /* ++ * we need n consecutive slots ++ * so use j as a start slot j plus j+1 must be enough time (for now) ++ */ ++ xtime= _hcd->frame_usecs[i]; ++ for (j = i+1 ; j < 8 ; j++ ) { ++ /* ++ * if we add this frame remaining time to xtime we may ++ * be OK, if not we need to test j for a complete frame ++ */ ++ if ((xtime+_hcd->frame_usecs[j]) < utime) { ++ if (_hcd->frame_usecs[j] < max_uframe_usecs[j]) { ++ j = 8; ++ ret = -1; ++ continue; ++ } ++ } ++ if (xtime >= utime) { ++ ret = i; ++ j = 8; /* stop loop with a good value ret */ ++ continue; ++ } ++ /* add the frame time to x time */ ++ xtime += _hcd->frame_usecs[j]; ++ /* we must have a fully available next frame or break */ ++ if ((xtime < utime) ++ && (_hcd->frame_usecs[j] == max_uframe_usecs[j])) { ++ ret = -1; ++ j = 8; /* stop loop with a bad value ret */ ++ continue; ++ } ++ } ++ if (ret >= 0) { ++ t_left = utime; ++ for (j = i; (t_left>0) && (j < 8); j++ ) { ++ t_left -= _hcd->frame_usecs[j]; ++ if ( t_left <= 0 ) { ++ _qh->frame_usecs[j] += _hcd->frame_usecs[j] + t_left; ++ _hcd->frame_usecs[j]= -t_left; ++ ret = i; ++ done = 1; ++ } else { ++ _qh->frame_usecs[j] += _hcd->frame_usecs[j]; ++ _hcd->frame_usecs[j] = 0; ++ } ++ } ++ } else { ++ i++; ++ if (i == 8) { ++ done = 1; ++ ret = -1; ++ } ++ } ++ } ++ return ret; ++} ++ ++static int find_uframe(dwc_otg_hcd_t * _hcd, dwc_otg_qh_t * _qh) ++{ ++ int ret; ++ ret = -1; ++ ++ if (_qh->speed == USB_SPEED_HIGH) { ++ /* if this is a hs transaction we need a full frame */ ++ ret = find_single_uframe(_hcd, _qh); ++ } else { ++ /* if this is a fs transaction we may need a sequence of frames */ ++ ret = find_multi_uframe(_hcd, _qh); ++ } ++ return ret; ++} ++ +/** + * Checks that the max transfer size allowed in a host channel is large enough + * to handle the maximum data transfer in a single (micro)frame for a periodic @@ -59868,6 +71779,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + return status; +} + ++ ++extern int g_next_sched_frame, g_np_count, g_np_sent; ++ +/** + * Schedules an interrupt or isochronous transfer in the periodic schedule. + * @@ -59881,21 +71795,43 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b +{ + int status = 0; + -+ status = periodic_channel_available(hcd); ++ if (microframe_schedule) { ++ int frame; ++ status = find_uframe(hcd, qh); ++ frame = -1; ++ if (status == 0) { ++ frame = 7; ++ } else { ++ if (status > 0 ) ++ frame = status-1; ++ } ++ ++ /* Set the new frame up */ ++ if (frame > -1) { ++ qh->sched_frame &= ~0x7; ++ qh->sched_frame |= (frame & 7); ++ } ++ ++ if (status != -1) ++ status = 0; ++ } else { ++ status = periodic_channel_available(hcd); ++ if (status) { ++ DWC_INFO("%s: No host channel available for periodic " "transfer.\n", __func__); //NOTICE ++ return status; ++ } ++ ++ status = check_periodic_bandwidth(hcd, qh); ++ } + if (status) { -+ DWC_INFO("%s: No host channel available for periodic " "transfer.\n", __func__); //NOTICE ++ DWC_INFO("%s: Insufficient periodic bandwidth for " ++ "periodic transfer.\n", __func__); + return status; + } -+ -+ status = check_periodic_bandwidth(hcd, qh); -+ if (status) { -+ DWC_INFO("%s: Insufficient periodic bandwidth for " "periodic transfer.\n", __func__); //NOTICE -+ return status; -+ } -+ + status = check_max_xfer_size(hcd, qh); + if (status) { -+ DWC_INFO("%s: Channel max transfer size too small " "for periodic transfer.\n", __func__); //NOTICE ++ DWC_INFO("%s: Channel max transfer size too small " ++ "for periodic transfer.\n", __func__); + return status; + } + @@ -59904,12 +71840,19 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_ready, &qh->qh_list_entry); + } + else { -+ /* Always start in the inactive schedule. */ -+ DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry); ++ if(DWC_LIST_EMPTY(&hcd->periodic_sched_inactive) || dwc_frame_num_le(qh->sched_frame, g_next_sched_frame)) ++ { ++ g_next_sched_frame = qh->sched_frame; ++ ++ } ++ /* Always start in the inactive schedule. */ ++ DWC_LIST_INSERT_TAIL(&hcd->periodic_sched_inactive, &qh->qh_list_entry); + } + -+ /* Reserve the periodic channel. */ -+ hcd->periodic_channels++; ++ if (!microframe_schedule) { ++ /* Reserve the periodic channel. */ ++ hcd->periodic_channels++; ++ } + + /* Update claimed usecs per (micro)frame. */ + hcd->periodic_usecs += qh->usecs; @@ -59917,6 +71860,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + return status; +} + ++ +/** + * This function adds a QH to either the non periodic or periodic schedule if + * it is not already in the schedule. If the QH is already in the schedule, no @@ -59927,13 +71871,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b +int dwc_otg_hcd_qh_add(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) +{ + int status = 0; -+ uint64_t flags; -+ -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ gintmsk_data_t intr_mask = {.d32 = 0 }; + + if (!DWC_LIST_EMPTY(&qh->qh_list_entry)) { + /* QH already in a schedule. */ -+ goto done; ++ return status; + } + + /* Add the new QH to the appropriate schedule */ @@ -59941,13 +71883,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + /* Always start in the inactive schedule. */ + DWC_LIST_INSERT_TAIL(&hcd->non_periodic_sched_inactive, + &qh->qh_list_entry); ++ g_np_count++; + } else { + status = schedule_periodic(hcd, qh); ++ if ( !hcd->periodic_qh_count ) { ++ intr_mask.b.sofintr = 1; ++ DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, ++ intr_mask.d32, intr_mask.d32); ++ } ++ hcd->periodic_qh_count++; + } + -+ done: -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); -+ + return status; +} + @@ -59959,13 +71905,21 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + */ +static void deschedule_periodic(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) +{ ++ int i; + DWC_LIST_REMOVE_INIT(&qh->qh_list_entry); + -+ /* Release the periodic channel reservation. */ -+ hcd->periodic_channels--; -+ + /* Update claimed usecs per (micro)frame. */ + hcd->periodic_usecs -= qh->usecs; ++ ++ if (!microframe_schedule) { ++ /* Release the periodic channel reservation. */ ++ hcd->periodic_channels--; ++ } else { ++ for (i = 0; i < 8; i++) { ++ hcd->frame_usecs[i] += qh->frame_usecs[i]; ++ qh->frame_usecs[i] = 0; ++ } ++ } +} + +/** @@ -59976,12 +71930,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + * @param qh QH to remove from schedule. */ +void dwc_otg_hcd_qh_remove(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh) +{ -+ uint64_t flags; -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); ++ gintmsk_data_t intr_mask = {.d32 = 0 }; + + if (DWC_LIST_EMPTY(&qh->qh_list_entry)) { + /* QH is not in a schedule. */ -+ goto done; ++ return; + } + + if (dwc_qh_is_non_per(qh)) { @@ -59992,10 +71945,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + DWC_LIST_REMOVE_INIT(&qh->qh_list_entry); + } else { + deschedule_periodic(hcd, qh); ++ hcd->periodic_qh_count--; ++ if( !hcd->periodic_qh_count ) { ++ intr_mask.b.sofintr = 1; ++ DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, ++ intr_mask.d32, 0); ++ } + } -+ -+ done: -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); +} + +/** @@ -60013,10 +71969,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + */ +void dwc_otg_hcd_qh_deactivate(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, + int sched_next_periodic_split) -+{ -+ uint64_t flags; -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ ++{ + if (dwc_qh_is_non_per(qh)) { + dwc_otg_hcd_qh_remove(hcd, qh); + if (!DWC_CIRCLEQ_EMPTY(&qh->qtd_list)) { @@ -60031,10 +71984,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + if (sched_next_periodic_split) { + + 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 + * split microframe before scheduling @@ -60074,18 +72028,22 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + * Remove from periodic_sched_queued and move to + * appropriate queue. + */ -+ if (qh->sched_frame == frame_number) { ++ if ((microframe_schedule && dwc_frame_num_le(qh->sched_frame, frame_number)) || ++ (!microframe_schedule && qh->sched_frame == frame_number)) { + DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready, + &qh->qh_list_entry); + } else { -+ DWC_LIST_MOVE_HEAD(&hcd-> -+ periodic_sched_inactive, -+ &qh->qh_list_entry); ++ if(!dwc_frame_num_le(g_next_sched_frame, qh->sched_frame)) ++ { ++ g_next_sched_frame = qh->sched_frame; ++ } ++ ++ DWC_LIST_MOVE_HEAD ++ (&hcd->periodic_sched_inactive, ++ &qh->qh_list_entry); + } + } + } -+ -+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); +} + +/** @@ -60093,13 +72051,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + * + * @param 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. ++ * @param atomic_alloc Flag to do atomic alloc if needed + * + * @return Returns pointer to the newly allocated QTD, or NULL on error. */ -+dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb) ++dwc_otg_qtd_t *dwc_otg_hcd_qtd_create(dwc_otg_hcd_urb_t * urb, int atomic_alloc) +{ + dwc_otg_qtd_t *qtd; + -+ qtd = dwc_otg_hcd_qtd_alloc(); ++ qtd = dwc_otg_hcd_qtd_alloc(atomic_alloc); + if (qtd == NULL) { + return NULL; + } @@ -60147,53 +72106,409 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_hcd_queue.c linux-rpi-b + * @param[in] qtd The QTD to add + * @param[in] hcd The DWC HCD structure + * @param[out] qh out parameter to return queue head ++ * @param atomic_alloc Flag to do atomic alloc if needed + * + * @return 0 if successful, negative error code otherwise. + */ +int dwc_otg_hcd_qtd_add(dwc_otg_qtd_t * qtd, -+ dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh) ++ dwc_otg_hcd_t * hcd, dwc_otg_qh_t ** qh, int atomic_alloc) +{ + int retval = 0; -+ uint64_t flags; ++ dwc_irqflags_t flags; + + dwc_otg_hcd_urb_t *urb = qtd->urb; + -+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); -+ + /* + * Get the QH which holds the QTD-list to insert to. Create QH if it + * doesn't exist. + */ + if (*qh == NULL) { -+ *qh = dwc_otg_hcd_qh_create(hcd, urb); ++ *qh = dwc_otg_hcd_qh_create(hcd, urb, atomic_alloc); + if (*qh == NULL) { + retval = -1; + goto done; + } + } -+ ++ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); + retval = dwc_otg_hcd_qh_add(hcd, *qh); + if (retval == 0) { + DWC_CIRCLEQ_INSERT_TAIL(&((*qh)->qtd_list), qtd, + qtd_list_entry); + } -+ -+ done: + DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); + ++done: ++ + return retval; +} + -+#endif /* DWC_DEVICE_ONLY */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c 2012-07-15 20:29:19.076083471 +0200 -@@ -0,0 +1,2067 @@ ++#endif /* DWC_DEVICE_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c +new file mode 100755 +index 0000000..b70ca68 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.c +@@ -0,0 +1,113 @@ ++#include "dwc_otg_regs.h" ++#include "dwc_otg_dbg.h" ++ ++void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name) ++{ ++ DWC_DEBUGPL(DBG_USER, "*** Debugging from within the %s function: ***\n" ++ "curmode: %1i Modemismatch: %1i otgintr: %1i sofintr: %1i\n" ++ "rxstsqlvl: %1i nptxfempty : %1i ginnakeff: %1i goutnakeff: %1i\n" ++ "ulpickint: %1i i2cintr: %1i erlysuspend:%1i usbsuspend: %1i\n" ++ "usbreset: %1i enumdone: %1i isooutdrop: %1i eopframe: %1i\n" ++ "restoredone: %1i epmismatch: %1i inepint: %1i outepintr: %1i\n" ++ "incomplisoin:%1i incomplisoout:%1i fetsusp: %1i resetdet: %1i\n" ++ "portintr: %1i hcintr: %1i ptxfempty: %1i lpmtranrcvd:%1i\n" ++ "conidstschng:%1i disconnect: %1i sessreqintr:%1i wkupintr: %1i\n", ++ function_name, ++ gintsts.b.curmode, ++ gintsts.b.modemismatch, ++ gintsts.b.otgintr, ++ gintsts.b.sofintr, ++ gintsts.b.rxstsqlvl, ++ gintsts.b.nptxfempty, ++ gintsts.b.ginnakeff, ++ gintsts.b.goutnakeff, ++ gintsts.b.ulpickint, ++ gintsts.b.i2cintr, ++ gintsts.b.erlysuspend, ++ gintsts.b.usbsuspend, ++ gintsts.b.usbreset, ++ gintsts.b.enumdone, ++ gintsts.b.isooutdrop, ++ gintsts.b.eopframe, ++ gintsts.b.restoredone, ++ gintsts.b.epmismatch, ++ gintsts.b.inepint, ++ gintsts.b.outepintr, ++ gintsts.b.incomplisoin, ++ gintsts.b.incomplisoout, ++ gintsts.b.fetsusp, ++ gintsts.b.resetdet, ++ gintsts.b.portintr, ++ gintsts.b.hcintr, ++ gintsts.b.ptxfempty, ++ gintsts.b.lpmtranrcvd, ++ gintsts.b.conidstschng, ++ gintsts.b.disconnect, ++ gintsts.b.sessreqintr, ++ gintsts.b.wkupintr); ++ return; ++} ++ ++void dwc_debug_core_int_mask(gintmsk_data_t gintmsk, const char* function_name) ++{ ++ DWC_DEBUGPL(DBG_USER, "Interrupt Mask status (called from %s) :\n" ++ "modemismatch: %1i otgintr: %1i sofintr: %1i rxstsqlvl: %1i\n" ++ "nptxfempty: %1i ginnakeff: %1i goutnakeff: %1i ulpickint: %1i\n" ++ "i2cintr: %1i erlysuspend:%1i usbsuspend: %1i usbreset: %1i\n" ++ "enumdone: %1i isooutdrop: %1i eopframe: %1i restoredone: %1i\n" ++ "epmismatch: %1i inepintr: %1i outepintr: %1i incomplisoin:%1i\n" ++ "incomplisoout:%1i fetsusp: %1i resetdet: %1i portintr: %1i\n" ++ "hcintr: %1i ptxfempty: %1i lpmtranrcvd:%1i conidstschng:%1i\n" ++ "disconnect: %1i sessreqintr:%1i wkupintr: %1i\n", ++ function_name, ++ gintmsk.b.modemismatch, ++ gintmsk.b.otgintr, ++ gintmsk.b.sofintr, ++ gintmsk.b.rxstsqlvl, ++ gintmsk.b.nptxfempty, ++ gintmsk.b.ginnakeff, ++ gintmsk.b.goutnakeff, ++ gintmsk.b.ulpickint, ++ gintmsk.b.i2cintr, ++ gintmsk.b.erlysuspend, ++ gintmsk.b.usbsuspend, ++ gintmsk.b.usbreset, ++ gintmsk.b.enumdone, ++ gintmsk.b.isooutdrop, ++ gintmsk.b.eopframe, ++ gintmsk.b.restoredone, ++ gintmsk.b.epmismatch, ++ gintmsk.b.inepintr, ++ gintmsk.b.outepintr, ++ gintmsk.b.incomplisoin, ++ gintmsk.b.incomplisoout, ++ gintmsk.b.fetsusp, ++ gintmsk.b.resetdet, ++ gintmsk.b.portintr, ++ gintmsk.b.hcintr, ++ gintmsk.b.ptxfempty, ++ gintmsk.b.lpmtranrcvd, ++ gintmsk.b.conidstschng, ++ gintmsk.b.disconnect, ++ gintmsk.b.sessreqintr, ++ gintmsk.b.wkupintr); ++ return; ++} ++ ++void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name) ++{ ++ DWC_DEBUGPL(DBG_USER, "otg int register (from %s function):\n" ++ "sesenddet:%1i sesreqsucstschung:%2i hstnegsucstschng:%1i\n" ++ "hstnegdet:%1i adevtoutchng: %2i debdone: %1i\n" ++ "mvic: %1i\n", ++ function_name, ++ gotgint.b.sesenddet, ++ gotgint.b.sesreqsucstschng, ++ gotgint.b.hstnegsucstschng, ++ gotgint.b.hstnegdet, ++ gotgint.b.adevtoutchng, ++ gotgint.b.debdone, ++ gotgint.b.mvic); ++ ++ return; ++} +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h +new file mode 100755 +index 0000000..22f28e1 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h +@@ -0,0 +1,36 @@ ++#ifndef __DWC_OTG_MPHI_FIX_H__ ++#define __DWC_OTG_MPHI_FIX_H__ ++ ++#define FIQ_WRITE_IO_ADDRESS(_addr_,_data_) *(volatile uint32_t *) IO_ADDRESS(_addr_) = _data_ ++#define FIQ_READ_IO_ADDRESS(_addr_) *(volatile uint32_t *) IO_ADDRESS(_addr_) ++#define FIQ_MODIFY_IO_ADDRESS(_addr_,_clear_,_set_) FIQ_WRITE_IO_ADDRESS(_addr_ , (FIQ_READ_IO_ADDRESS(_addr_)&~_clear_)|_set_) ++#define FIQ_WRITE(_addr_,_data_) *(volatile uint32_t *) _addr_ = _data_ ++ ++typedef struct { ++ volatile void* base; ++ volatile void* ctrl; ++ volatile void* outdda; ++ volatile void* outddb; ++ volatile void* intstat; ++} mphi_regs_t; ++ ++void dwc_debug_print_core_int_reg(gintsts_data_t gintsts, const char* function_name); ++void dwc_debug_core_int_mask(gintsts_data_t gintmsk, const char* function_name); ++void dwc_debug_otg_int(gotgint_data_t gotgint, const char* function_name); ++ ++ ++ ++#ifdef DEBUG ++#define DWC_DBG_PRINT_CORE_INT(_arg_) dwc_debug_print_core_int_reg(_arg_,__func__) ++#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_) dwc_debug_core_int_mask(_arg_,__func__) ++#define DWC_DBG_PRINT_OTG_INT(_arg_) dwc_debug_otg_int(_arg_,__func__) ++ ++#else ++#define DWC_DBG_PRINT_CORE_INT(_arg_) ++#define DWC_DBG_PRINT_CORE_INT_MASK(_arg_) ++#define DWC_DBG_PRINT_OTG_INT(_arg_) ++ ++ ++#endif ++ ++#endif +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h +new file mode 100644 +index 0000000..bb1c42d +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h +@@ -0,0 +1,188 @@ ++#ifndef _DWC_OS_DEP_H_ ++#define _DWC_OS_DEP_H_ ++ ++/** ++ * @file ++ * ++ * This file contains OS dependent structures. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ++# include ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) ++# include ++#else ++# include ++#endif ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) ++# include ++#else ++# include ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ++# include ++#endif ++ ++#ifdef PCI_INTERFACE ++# include ++#endif ++ ++#ifdef LM_INTERFACE ++# include ++# include ++# include ++# include ++# if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) ++# include ++# include ++# include ++# include ++# else ++/* in 2.6.31, at least, we seem to have lost the generic LM infrastructure - ++ here we assume that the machine architecture provides definitions ++ in its own header ++*/ ++# include ++# include ++# endif ++#endif ++ ++#ifdef PLATFORM_INTERFACE ++#include ++#include ++#endif ++ ++/** The OS page size */ ++#define DWC_OS_PAGE_SIZE PAGE_SIZE ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) ++typedef int gfp_t; ++#endif ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) ++# define IRQF_SHARED SA_SHIRQ ++#endif ++ ++typedef struct os_dependent { ++ /** Base address returned from ioremap() */ ++ void *base; ++ ++ /** Register offset for Diagnostic API */ ++ uint32_t reg_offset; ++ ++ /** Base address for MPHI peripheral */ ++ void *mphi_base; ++ ++#ifdef LM_INTERFACE ++ struct lm_device *lmdev; ++#elif defined(PCI_INTERFACE) ++ struct pci_dev *pcidev; ++ ++ /** Start address of a PCI region */ ++ resource_size_t rsrc_start; ++ ++ /** Length address of a PCI region */ ++ resource_size_t rsrc_len; ++#elif defined(PLATFORM_INTERFACE) ++ struct platform_device *platformdev; ++#endif ++ ++} os_dependent_t; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++ ++ ++/* Type for the our device on the chosen bus */ ++#if defined(LM_INTERFACE) ++typedef struct lm_device dwc_bus_dev_t; ++#elif defined(PCI_INTERFACE) ++typedef struct pci_dev dwc_bus_dev_t; ++#elif defined(PLATFORM_INTERFACE) ++typedef struct platform_device dwc_bus_dev_t; ++#endif ++ ++/* Helper macro to retrieve drvdata from the device on the chosen bus */ ++#if defined(LM_INTERFACE) ++#define DWC_OTG_BUSDRVDATA(_dev) lm_get_drvdata(_dev) ++#elif defined(PCI_INTERFACE) ++#define DWC_OTG_BUSDRVDATA(_dev) pci_get_drvdata(_dev) ++#elif defined(PLATFORM_INTERFACE) ++#define DWC_OTG_BUSDRVDATA(_dev) platform_get_drvdata(_dev) ++#endif ++ ++/** ++ * Helper macro returning the otg_device structure of a given struct device ++ * ++ * c.f. static dwc_otg_device_t *dwc_otg_drvdev(struct device *_dev) ++ */ ++#ifdef LM_INTERFACE ++#define DWC_OTG_GETDRVDEV(_var, _dev) do { \ ++ struct lm_device *lm_dev = \ ++ container_of(_dev, struct lm_device, dev); \ ++ _var = lm_get_drvdata(lm_dev); \ ++ } while (0) ++ ++#elif defined(PCI_INTERFACE) ++#define DWC_OTG_GETDRVDEV(_var, _dev) do { \ ++ _var = dev_get_drvdata(_dev); \ ++ } while (0) ++ ++#elif defined(PLATFORM_INTERFACE) ++#define DWC_OTG_GETDRVDEV(_var, _dev) do { \ ++ struct platform_device *platform_dev = \ ++ container_of(_dev, struct platform_device, dev); \ ++ _var = platform_get_drvdata(platform_dev); \ ++ } while (0) ++#endif ++ ++ ++/** ++ * Helper macro returning the struct dev of the given struct os_dependent ++ * ++ * c.f. static struct device *dwc_otg_getdev(struct os_dependent *osdep) ++ */ ++#ifdef LM_INTERFACE ++#define DWC_OTG_OS_GETDEV(_osdep) \ ++ ((_osdep).lmdev == NULL? NULL: &(_osdep).lmdev->dev) ++#elif defined(PCI_INTERFACE) ++#define DWC_OTG_OS_GETDEV(_osdep) \ ++ ((_osdep).pci_dev == NULL? NULL: &(_osdep).pci_dev->dev) ++#elif defined(PLATFORM_INTERFACE) ++#define DWC_OTG_OS_GETDEV(_osdep) \ ++ ((_osdep).platformdev == NULL? NULL: &(_osdep).platformdev->dev) ++#endif ++ ++ ++ ++ ++#endif /* _DWC_OS_DEP_H_ */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c +new file mode 100644 +index 0000000..c97d65c +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.c +@@ -0,0 +1,2708 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.c $ -+ * $Revision: #79 $ -+ * $Date: 2009/04/10 $ -+ * $Change: 1230501 $ ++ * $Revision: #101 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ + * + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless @@ -60224,7 +72539,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 +#ifndef DWC_HOST_ONLY + +/** @file -+ * This file implements PCD Core. All code in this file is portable and don't ++ * This file implements PCD Core. All code in this file is portable and doesn't + * use any OS specific functions. + * PCD Core provides Interface, defined in + * header file, which can be used to implement OS specific PCD interface. @@ -60247,6 +72562,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 +extern int init_cfi(cfiobject_t * cfiobj); +#endif + ++/** ++ * Choose endpoint from ep arrays using usb_ep structure. ++ */ +static dwc_otg_pcd_ep_t *get_ep_from_handle(dwc_otg_pcd_t * pcd, void *handle) +{ + int i; @@ -60270,23 +72588,22 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + int32_t status) +{ + unsigned stopped = ep->stopped; -+ -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, ep); ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(ep %p req %p)\n", __func__, ep, req); + DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry); + + /* don't modify queue heads during completion callback */ + ep->stopped = 1; -+ DWC_SPINUNLOCK(ep->pcd->lock); ++ /* spin_unlock/spin_lock now done in fops->complete() */ + ep->pcd->fops->complete(ep->pcd, ep->priv, req->priv, status, + req->actual); -+ DWC_SPINLOCK(ep->pcd->lock); + + if (ep->pcd->request_pending > 0) { + --ep->pcd->request_pending; + } + + ep->stopped = stopped; -+ dwc_free(req); ++ DWC_FREE(req); +} + +/** @@ -60320,12 +72637,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 +static int32_t dwc_otg_pcd_start_cb(void *p) +{ + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); + + /* + * 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(core_if)) { ++ dwc_otg_core_dev_init(core_if); ++ /* Set core_if's lock pointer to the pcd->lock */ ++ core_if->lock = pcd->lock; + } + return 1; +} @@ -60337,6 +72657,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 +{ + dwc_otg_pcd_ep_t *ep; + ep = get_ep_from_handle(pcd, pep); ++ if (!ep) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ + return pcd->cfi->ops.ep_alloc_buf(pcd->cfi, pcd, ep, addr, buflen, + flags); +} @@ -60364,7 +72689,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + || (!GET_CORE_IF(pcd)->core_params->i2c_enable)) { + if (GET_CORE_IF(pcd)->srp_timer_started) { + GET_CORE_IF(pcd)->srp_timer_started = 0; -+ DWC_TIMER_CANCEL(pcd->srp_timer); ++ DWC_TIMER_CANCEL(GET_CORE_IF(pcd)->srp_timer); + } + } + return 1; @@ -60380,7 +72705,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + dwc_otg_pcd_t *pcd = (dwc_otg_pcd_t *) p; + + if (pcd->fops->suspend) { ++ DWC_SPINUNLOCK(pcd->lock); + pcd->fops->suspend(pcd); ++ DWC_SPINLOCK(pcd->lock); + } + + return 1; @@ -60413,14 +72740,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 +}; + +/** -+ * This function allocates a DMA Descriptor chain for the Endpoint ++ * This function allocates a DMA Descriptor chain for the Endpoint + * buffer to be used for a transfer to/from the specified endpoint. + */ -+dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(uint32_t * dma_desc_addr, -+ uint32_t count) ++dwc_otg_dev_dma_desc_t *dwc_otg_ep_alloc_desc_chain(dwc_dma_t * dma_desc_addr, ++ uint32_t count) +{ -+ -+ return dwc_dma_alloc(count * sizeof(dwc_otg_dev_dma_desc_t), dma_desc_addr); ++ return DWC_DMA_ALLOC_ATOMIC(count * sizeof(dwc_otg_dev_dma_desc_t), ++ dma_desc_addr); +} + +/** @@ -60429,7 +72756,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 +void dwc_otg_ep_free_desc_chain(dwc_otg_dev_dma_desc_t * desc_addr, + uint32_t dma_desc_addr, uint32_t count) +{ -+ dwc_dma_free(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr, ++ DWC_DMA_FREE(count * sizeof(dwc_otg_dev_dma_desc_t), desc_addr, + dma_desc_addr); +} + @@ -60450,6 +72777,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + depctl_data_t depctl = {.d32 = 0 }; + volatile uint32_t *addr; + int i, j; ++ uint32_t len; + + if (dwc_ep->is_in) + dwc_ep->desc_cnt = dwc_ep->buf_proc_intrvl / dwc_ep->bInterval; @@ -60467,7 +72795,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + return; + } + -+ 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); + + /** ISO OUT EP */ + if (dwc_ep->is_in == 0) { @@ -60480,7 +72808,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + 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)); ++ dma_ad = (dma_addr_t) DWC_READ_REG32(&(out_regs->doepdma)); + + /** Buffer 0 descriptors setup */ + dma_ad = dwc_ep->dma_addr0; @@ -60498,16 +72826,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + 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; ++ uint32_t len = (j + 1) * dwc_ep->maxpacket; ++ if (len > dwc_ep->data_per_frame) ++ data_per_desc = ++ dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket; ++ else ++ data_per_desc = dwc_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; + -+ data_per_desc += -+ (data_per_desc % 4) ? (4 - -+ data_per_desc % -+ 4) : 0; + sts.b_iso_out.rxbytes = data_per_desc; + dma_desc->buf = dma_ad; + dma_desc->status.d32 = sts.d32; @@ -60519,12 +72848,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + } + + 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; ++ uint32_t len = (j + 1) * dwc_ep->maxpacket; ++ if (len > dwc_ep->data_per_frame) ++ data_per_desc = ++ dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket; ++ else ++ data_per_desc = dwc_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; + sts.b_iso_out.rxbytes = data_per_desc; + dma_desc->buf = dma_ad; + dma_desc->status.d32 = sts.d32; @@ -60535,12 +72868,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + } + + 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; ++ len = (j + 1) * dwc_ep->maxpacket; ++ if (len > dwc_ep->data_per_frame) ++ data_per_desc = ++ dwc_ep->data_per_frame - j * dwc_ep->maxpacket; ++ else ++ data_per_desc = dwc_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; + sts.b_iso_out.rxbytes = data_per_desc; + + dma_desc->buf = dma_ad; @@ -60555,16 +72891,19 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + 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) { ++ uint32_t len = (j + 1) * dwc_ep->maxpacket; ++ if (len > dwc_ep->data_per_frame) ++ data_per_desc = ++ dwc_ep->data_per_frame - ++ j * dwc_ep->maxpacket; ++ else ++ data_per_desc = dwc_ep->maxpacket; ++ len = data_per_desc % 4; ++ if (len) ++ data_per_desc += 4 - len; ++ + 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; ++ sts.b_iso_out.rxbytes = data_per_desc; + dma_desc->buf = dma_ad; + dma_desc->status.d32 = sts.d32; + @@ -60605,7 +72944,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + dwc_ep->next_frame = 0; + + /** Write dma_ad into DOEPDMA register */ -+ dwc_write_reg32(&(out_regs->doepdma), ++ DWC_WRITE_REG32(&(out_regs->doepdma), + (uint32_t) dwc_ep->iso_dma_desc_addr); + + } @@ -60620,17 +72959,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + fifosize_data_t txfifosize, rxfifosize; + + txfifosize.d32 = -+ dwc_read_reg32(&core_if->dev_if->in_ep_regs[dwc_ep->num]-> ++ 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); ++ 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); ++ 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; @@ -60684,7 +73023,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + dwc_ep->next_frame = sts.b_iso_in.framenum + dwc_ep->bInterval; + + /** Write dma_ad into diepdma register */ -+ dwc_write_reg32(&(in_regs->diepdma), ++ DWC_WRITE_REG32(&(in_regs->diepdma), + (uint32_t) dwc_ep->iso_dma_desc_addr); + } + /** Enable endpoint, clear nak */ @@ -60693,8 +73032,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + depctl.b.usbactep = 1; + depctl.b.cnak = 1; + -+ dwc_modify_reg32(addr, depctl.d32, depctl.d32); -+ depctl.d32 = dwc_read_reg32(addr); ++ DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32); ++ depctl.d32 = DWC_READ_REG32(addr); +} + +/** @@ -60704,7 +73043,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + * @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) +{ @@ -60736,17 +73074,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + /* Program the transfer size and packet count + * as follows: xfersize = N * maxpacket + + * short_packet pktcnt = N + (short_packet -+ * exist ? 1 : 0) ++ * 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]-> ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[ep->num]-> + dieptsiz, deptsiz.d32); + + /* Write the DMA register */ -+ dwc_write_reg32(& ++ DWC_WRITE_REG32(& + (core_if->dev_if->in_ep_regs[ep->num]-> + diepdma), (uint32_t) ep->dma_addr); + @@ -60756,31 +73094,29 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + ep->maxpacket; + deptsiz.b.xfersize = deptsiz.b.pktcnt * ep->maxpacket; + -+ dwc_write_reg32(&core_if->dev_if->out_ep_regs[ep->num]-> ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[ep->num]-> + doeptsiz, deptsiz.d32); + + /* Write the DMA register */ -+ dwc_write_reg32(& ++ 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); ++ 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 ++ * 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. ++ * the packets are unloaded from the Rx FIFO in the ISR. + * + * @param core_if Programming view of DWC_otg controller. + * @param ep The EP to start the transfer on. @@ -60820,10 +73156,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 +} + +/** -+ * 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. ++ * This function stops transfer for an EP and ++ * resets the ep's variables. + * + * @param core_if Programming view of DWC_otg controller. + * @param ep The EP to start the transfer on. @@ -60841,12 +73175,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + } + + /* disable the ep */ -+ depctl.d32 = dwc_read_reg32(addr); ++ depctl.d32 = DWC_READ_REG32(addr); + + depctl.b.epdis = 1; + depctl.b.snak = 1; + -+ dwc_write_reg32(addr, depctl.d32); ++ DWC_WRITE_REG32(addr, depctl.d32); + + if (core_if->dma_desc_enable && + ep->iso_desc_addr && ep->iso_dma_desc_addr) { @@ -60881,7 +73215,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + int atomic_alloc) +{ + dwc_otg_pcd_ep_t *ep; -+ uint64_t flags = 0; ++ dwc_irqflags_t flags = 0; + dwc_ep_t *dwc_ep; + int32_t frm_data; + dsts_data_t dsts; @@ -60889,7 +73223,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + + ep = get_ep_from_handle(pcd, ep_handle); + -+ if (!ep->desc || ep->dwc_ep.num == 0) { ++ if (!ep || !ep->desc || ep->dwc_ep.num == 0) { + DWC_WARN("bad ep\n"); + return -DWC_E_INVALID; + } @@ -60927,7 +73261,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + frm_data -= ep->dwc_ep.maxpacket; + } + -+ 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); + + if (start_frame == -1) { + dwc_ep->next_frame = dsts.b.soffn + 1; @@ -60960,10 +73294,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + + if (atomic_alloc) { + dwc_ep->pkt_info = -+ dwc_alloc_atomic(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); ++ DWC_ALLOC_ATOMIC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); + } else { + dwc_ep->pkt_info = -+ dwc_alloc(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); ++ DWC_ALLOC(sizeof(iso_pkt_info_t) * dwc_ep->pkt_cnt); + } + if (!dwc_ep->pkt_info) { + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); @@ -60985,7 +73319,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 +int dwc_otg_pcd_iso_ep_stop(dwc_otg_pcd_t * pcd, void *ep_handle, + void *req_handle) +{ -+ uint64_t flags = 0; ++ dwc_irqflags_t flags = 0; + dwc_otg_pcd_ep_t *ep; + dwc_ep_t *dwc_ep; + @@ -60998,7 +73332,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + + dwc_otg_iso_ep_stop_transfer(GET_CORE_IF(pcd), dwc_ep); + -+ dwc_free(dwc_ep->pkt_info); ++ DWC_FREE(dwc_ep->pkt_info); + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); + if (ep->iso_req_handle != req_handle) { + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); @@ -61015,7 +73349,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + * 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 ++ * - 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_t * pcd, dwc_otg_pcd_ep_t * ep, @@ -61045,6 +73379,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + dwc_ep_t *dwc_ep; + + ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep->desc || ep->dwc_ep.num == 0) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } + dwc_ep = &ep->dwc_ep; + + return dwc_ep->pkt_cnt; @@ -61058,6 +73396,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + dwc_ep_t *dwc_ep; + + ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep) ++ DWC_WARN("bad ep\n"); ++ + dwc_ep = &ep->dwc_ep; + + *status = dwc_ep->pkt_info[packet].status; @@ -61065,7 +73406,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + *offset = dwc_ep->pkt_info[packet].offset; +} + -+#endif /* DWC_EN_ISOC */ ++#endif /* DWC_EN_ISOC */ + +static void dwc_otg_pcd_init_ep(dwc_otg_pcd_t * pcd, dwc_otg_pcd_ep_t * pcd_ep, + uint32_t is_in, uint32_t ep_num) @@ -61097,7 +73438,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 +} + +/** -+ * Initialise ep's ++ * Initialize ep's + */ +static void dwc_otg_pcd_reinit(dwc_otg_pcd_t * pcd) +{ @@ -61155,7 +73496,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 +} + +/** -+ * This function is called when the SRP timer expires. The SRP should ++ * This function is called when the SRP timer expires. The SRP should + * complete within 6 seconds. + */ +static void srp_timeout(void *ptr) @@ -61164,9 +73505,36 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + dwc_otg_core_if_t *core_if = (dwc_otg_core_if_t *) ptr; + volatile uint32_t *addr = &core_if->core_global_regs->gotgctl; + -+ gotgctl.d32 = dwc_read_reg32(addr); ++ gotgctl.d32 = DWC_READ_REG32(addr); + + core_if->srp_timer_started = 0; ++ ++ if (core_if->adp_enable) { ++ if (gotgctl.b.bsesvld == 0) { ++ gpwrdn_data_t gpwrdn = {.d32 = 0 }; ++ DWC_PRINTF("SRP Timeout BSESSVLD = 0\n"); ++ /* Power off the core */ ++ if (core_if->power_down == 2) { ++ gpwrdn.b.pwrdnswtch = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ } ++ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuintsel = 1; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gpwrdn, 0, ++ gpwrdn.d32); ++ dwc_otg_adp_probe_start(core_if); ++ } else { ++ DWC_PRINTF("SRP Timeout BSESSVLD = 1\n"); ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ } ++ } + + if ((core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS) && + (core_if->core_params->i2c_enable)) { @@ -61174,28 +73542,27 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + + if ((core_if->srp_success) && (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); ++ core_if->pcd_cb->resume_wakeup(core_if->pcd_cb->p); + } + + /* Clear Session Request */ + 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"); + gotgctl.b.sesreq = 0; -+ dwc_write_reg32(addr, gotgctl.d32); ++ DWC_WRITE_REG32(addr, gotgctl.d32); + } + } else if (gotgctl.b.sesreq) { + DWC_PRINTF("SRP Timeout\n"); + + __DWC_ERROR("Device not connected/responding\n"); + gotgctl.b.sesreq = 0; -+ dwc_write_reg32(addr, gotgctl.d32); ++ DWC_WRITE_REG32(addr, gotgctl.d32); + } else { + DWC_PRINTF(" SRP GOTGCTL=%0x\n", gotgctl.d32); + } @@ -61217,7 +73584,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + + DWC_DEBUGPL(DBG_PCDV, "Start xfer tasklet\n"); + -+ diepctl.d32 = dwc_read_reg32(&core_if->dev_if->in_ep_regs[0]->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; @@ -61228,7 +73595,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + for (i = 0; i < core_if->dev_if->num_in_eps; i++) { + depctl_data_t diepctl; + diepctl.d32 = -+ dwc_read_reg32(&core_if->dev_if->in_ep_regs[i]->diepctl); ++ 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; @@ -61246,28 +73613,33 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + */ +dwc_otg_pcd_t *dwc_otg_pcd_init(dwc_otg_core_if_t * core_if) +{ -+ dwc_otg_pcd_t *pcd = 0; ++ dwc_otg_pcd_t *pcd = NULL; + dwc_otg_dev_if_t *dev_if; ++ int i; + + /* + * Allocate PCD structure + */ -+ pcd = dwc_alloc(sizeof(dwc_otg_pcd_t)); ++ pcd = DWC_ALLOC(sizeof(dwc_otg_pcd_t)); + -+ if (pcd == 0) { ++ if (pcd == NULL) { + return NULL; + } + + pcd->lock = DWC_SPINLOCK_ALLOC(); + DWC_DEBUGPL(DBG_HCDV, "Init of PCD %p given core_if %p\n", + pcd, core_if);//GRAYG -+ pcd->core_if = core_if; + if (!pcd->lock) { + DWC_ERROR("Could not allocate lock for pcd"); -+ dwc_free(pcd); ++ DWC_FREE(pcd); + return NULL; + } ++ /* Set core_if's lock pointer to hcd->lock */ ++ core_if->lock = pcd->lock; ++ pcd->core_if = core_if; ++ + dev_if = core_if->dev_if; ++ dev_if->isoc_ep = NULL; + + if (core_if->hwcfg4.b.ded_fifo_en) { + DWC_PRINTF("Dedicated Tx FIFOs mode\n"); @@ -61276,9 +73648,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + } + + /* -+ * Initialized the Core for Device mode. -+ */ -+ if (dwc_otg_is_device_mode(core_if)) { ++ * Initialized the Core for Device mode here if there is nod ADP support. ++ * Otherwise it will be done later in dwc_otg_adp_start routine. ++ */ ++ if (dwc_otg_is_device_mode(core_if) /*&& !core_if->adp_enable*/) { + dwc_otg_core_dev_init(core_if); + } + @@ -61292,38 +73665,37 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + */ + if (GET_CORE_IF(pcd)->dma_enable) { + pcd->setup_pkt = -+ dwc_dma_alloc(sizeof(*pcd->setup_pkt) * 5, ++ DWC_DMA_ALLOC(sizeof(*pcd->setup_pkt) * 5, + &pcd->setup_pkt_dma_handle); -+ if (pcd->setup_pkt == 0) { -+ dwc_free(pcd); ++ if (pcd->setup_pkt == NULL) { ++ DWC_FREE(pcd); + return NULL; + } + + pcd->status_buf = -+ dwc_dma_alloc(sizeof(uint16_t), ++ DWC_DMA_ALLOC(sizeof(uint16_t), + &pcd->status_buf_dma_handle); -+ if (pcd->status_buf == 0) { -+ dwc_dma_free(sizeof(*pcd->setup_pkt) * 5, ++ if (pcd->status_buf == NULL) { ++ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, + pcd->setup_pkt, pcd->setup_pkt_dma_handle); -+ dwc_free(pcd); ++ DWC_FREE(pcd); + return NULL; + } + + if (GET_CORE_IF(pcd)->dma_desc_enable) { + dev_if->setup_desc_addr[0] = -+ dwc_otg_ep_alloc_desc_chain(&dev_if-> -+ dma_setup_desc_addr[0], -+ 1); ++ dwc_otg_ep_alloc_desc_chain ++ (&dev_if->dma_setup_desc_addr[0], 1); + dev_if->setup_desc_addr[1] = -+ dwc_otg_ep_alloc_desc_chain(&dev_if-> -+ dma_setup_desc_addr[1], -+ 1); ++ dwc_otg_ep_alloc_desc_chain ++ (&dev_if->dma_setup_desc_addr[1], 1); + dev_if->in_desc_addr = -+ dwc_otg_ep_alloc_desc_chain(&dev_if-> -+ dma_in_desc_addr, 1); ++ dwc_otg_ep_alloc_desc_chain ++ (&dev_if->dma_in_desc_addr, 1); + dev_if->out_desc_addr = -+ dwc_otg_ep_alloc_desc_chain(&dev_if-> -+ dma_out_desc_addr, 1); ++ dwc_otg_ep_alloc_desc_chain ++ (&dev_if->dma_out_desc_addr, 1); ++ pcd->data_terminated = 0; + + if (dev_if->setup_desc_addr[0] == 0 + || dev_if->setup_desc_addr[1] == 0 @@ -61331,55 +73703,45 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + || dev_if->out_desc_addr == 0) { + + if (dev_if->out_desc_addr) -+ dwc_otg_ep_free_desc_chain(dev_if-> -+ out_desc_addr, -+ dev_if-> -+ dma_out_desc_addr, -+ 1); ++ dwc_otg_ep_free_desc_chain ++ (dev_if->out_desc_addr, ++ dev_if->dma_out_desc_addr, 1); + if (dev_if->in_desc_addr) -+ dwc_otg_ep_free_desc_chain(dev_if-> -+ in_desc_addr, -+ dev_if-> -+ dma_in_desc_addr, -+ 1); ++ dwc_otg_ep_free_desc_chain ++ (dev_if->in_desc_addr, ++ dev_if->dma_in_desc_addr, 1); + if (dev_if->setup_desc_addr[1]) -+ dwc_otg_ep_free_desc_chain(dev_if-> -+ setup_desc_addr -+ [1], -+ dev_if-> -+ dma_setup_desc_addr -+ [1], 1); ++ dwc_otg_ep_free_desc_chain ++ (dev_if->setup_desc_addr[1], ++ dev_if->dma_setup_desc_addr[1], 1); + if (dev_if->setup_desc_addr[0]) -+ dwc_otg_ep_free_desc_chain(dev_if-> -+ setup_desc_addr -+ [0], -+ dev_if-> -+ dma_setup_desc_addr -+ [0], 1); ++ dwc_otg_ep_free_desc_chain ++ (dev_if->setup_desc_addr[0], ++ dev_if->dma_setup_desc_addr[0], 1); + -+ dwc_dma_free(sizeof(*pcd->setup_pkt) * 5, ++ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, + pcd->setup_pkt, + pcd->setup_pkt_dma_handle); -+ dwc_dma_free(sizeof(*pcd->status_buf), ++ DWC_DMA_FREE(sizeof(*pcd->status_buf), + pcd->status_buf, + pcd->status_buf_dma_handle); + -+ dwc_free(pcd); ++ DWC_FREE(pcd); + + return NULL; + } + } + } else { -+ pcd->setup_pkt = dwc_alloc(sizeof(*pcd->setup_pkt) * 5); -+ if (pcd->setup_pkt == 0) { -+ dwc_free(pcd); ++ pcd->setup_pkt = DWC_ALLOC(sizeof(*pcd->setup_pkt) * 5); ++ if (pcd->setup_pkt == NULL) { ++ DWC_FREE(pcd); + return NULL; + } + -+ pcd->status_buf = dwc_alloc(sizeof(uint16_t)); -+ if (pcd->status_buf == 0) { -+ dwc_free(pcd->setup_pkt); -+ dwc_free(pcd); ++ pcd->status_buf = DWC_ALLOC(sizeof(uint16_t)); ++ if (pcd->status_buf == NULL) { ++ DWC_FREE(pcd->setup_pkt); ++ DWC_FREE(pcd); + return NULL; + } + } @@ -61388,39 +73750,80 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + + /* Allocate the cfi object for the PCD */ +#ifdef DWC_UTE_CFI -+ pcd->cfi = dwc_alloc(sizeof(cfiobject_t)); ++ pcd->cfi = DWC_ALLOC(sizeof(cfiobject_t)); + if (NULL == pcd->cfi) -+ return NULL; ++ goto fail; + if (init_cfi(pcd->cfi)) { + CFI_INFO("%s: Failed to init the CFI object\n", __func__); -+ return NULL; ++ goto fail; + } +#endif + + /* Initialize tasklets */ -+ pcd->start_xfer_tasklet = DWC_TASK_ALLOC(start_xfer_tasklet_func, pcd); -+ pcd->test_mode_tasklet = DWC_TASK_ALLOC(do_test_mode, pcd); -+ /* Initialize timer */ -+ pcd->srp_timer = DWC_TIMER_ALLOC("SRP TIMER", srp_timeout, core_if); ++ pcd->start_xfer_tasklet = DWC_TASK_ALLOC("xfer_tasklet", ++ start_xfer_tasklet_func, pcd); ++ pcd->test_mode_tasklet = DWC_TASK_ALLOC("test_mode_tasklet", ++ do_test_mode, pcd); ++ ++ /* Initialize SRP timer */ ++ core_if->srp_timer = DWC_TIMER_ALLOC("SRP TIMER", srp_timeout, core_if); ++ ++ if (core_if->core_params->dev_out_nak) { ++ /** ++ * Initialize xfer timeout timer. Implemented for ++ * 2.93a feature "Device DDMA OUT NAK Enhancement" ++ */ ++ for(i = 0; i < MAX_EPS_CHANNELS; i++) { ++ pcd->core_if->ep_xfer_timer[i] = ++ DWC_TIMER_ALLOC("ep timer", ep_xfer_timeout, ++ &pcd->core_if->ep_xfer_info[i]); ++ } ++ } ++ + return pcd; ++#ifdef DWC_UTE_CFI ++fail: ++#endif ++ if (pcd->setup_pkt) ++ DWC_FREE(pcd->setup_pkt); ++ if (pcd->status_buf) ++ DWC_FREE(pcd->status_buf); ++#ifdef DWC_UTE_CFI ++ if (pcd->cfi) ++ DWC_FREE(pcd->cfi); ++#endif ++ if (pcd) ++ DWC_FREE(pcd); ++ return NULL; ++ +} + ++/** ++ * Remove PCD specific data ++ */ +void dwc_otg_pcd_remove(dwc_otg_pcd_t * pcd) +{ + dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; ++ int i; ++ if (pcd->core_if->core_params->dev_out_nak) { ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[i]); ++ pcd->core_if->ep_xfer_info[i].state = 0; ++ } ++ } + + if (GET_CORE_IF(pcd)->dma_enable) { -+ dwc_dma_free(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt, ++ DWC_DMA_FREE(sizeof(*pcd->setup_pkt) * 5, pcd->setup_pkt, + pcd->setup_pkt_dma_handle); -+ dwc_dma_free(sizeof(uint16_t), pcd->status_buf, ++ DWC_DMA_FREE(sizeof(uint16_t), pcd->status_buf, + pcd->status_buf_dma_handle); + if (GET_CORE_IF(pcd)->dma_desc_enable) { + dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[0], -+ dev_if-> -+ dma_setup_desc_addr[0], 1); ++ dev_if->dma_setup_desc_addr ++ [0], 1); + dwc_otg_ep_free_desc_chain(dev_if->setup_desc_addr[1], -+ dev_if-> -+ dma_setup_desc_addr[1], 1); ++ dev_if->dma_setup_desc_addr ++ [1], 1); + dwc_otg_ep_free_desc_chain(dev_if->in_desc_addr, + dev_if->dma_in_desc_addr, 1); + dwc_otg_ep_free_desc_chain(dev_if->out_desc_addr, @@ -61428,13 +73831,22 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + 1); + } + } else { -+ dwc_free(pcd->setup_pkt); -+ dwc_free(pcd->status_buf); ++ DWC_FREE(pcd->setup_pkt); ++ DWC_FREE(pcd->status_buf); + } + DWC_SPINLOCK_FREE(pcd->lock); ++ /* Set core_if's lock pointer to NULL */ ++ pcd->core_if->lock = NULL; ++ + DWC_TASK_FREE(pcd->start_xfer_tasklet); + DWC_TASK_FREE(pcd->test_mode_tasklet); -+ DWC_TIMER_FREE(pcd->srp_timer); ++ if (pcd->core_if->core_params->dev_out_nak) { ++ for (i = 0; i < MAX_EPS_CHANNELS; i++) { ++ if (pcd->core_if->ep_xfer_timer[i]) { ++ DWC_TIMER_FREE(pcd->core_if->ep_xfer_timer[i]); ++ } ++ } ++ } + +/* Release the CFI object's dynamic memory */ +#ifdef DWC_UTE_CFI @@ -61443,9 +73855,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + } +#endif + -+ dwc_free(pcd); ++ DWC_FREE(pcd); +} + ++/** ++ * Returns whether registered pcd is dual speed or not ++ */ +uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); @@ -61460,12 +73875,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + return 1; +} + ++/** ++ * Returns whether registered pcd is OTG capable or not ++ */ +uint32_t dwc_otg_pcd_is_otg(dwc_otg_pcd_t * pcd) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); + gusbcfg_data_t usbcfg = {.d32 = 0 }; + -+ usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg); ++ usbcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->gusbcfg); + if (!usbcfg.b.srpcap || !usbcfg.b.hnpcap) { + return 0; + } @@ -61531,14 +73949,22 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + (core_if->tx_msk & (1 << (fifo_num - 1))) ^ core_if->tx_msk; +} + ++/** ++ * This function is being called from gadget ++ * to enable PCD endpoint. ++ */ +int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, + const uint8_t * ep_desc, void *usb_ep) +{ + int num, dir; -+ dwc_otg_pcd_ep_t *ep = 0; ++ dwc_otg_pcd_ep_t *ep = NULL; + const usb_endpoint_descriptor_t *desc; -+ uint64_t flags; ++ dwc_irqflags_t flags; ++ fifosize_data_t dptxfsiz = {.d32 = 0 }; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; + int retval = 0; ++ int i, epcount; + + desc = (const usb_endpoint_descriptor_t *)ep_desc; + @@ -61559,9 +73985,27 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + } + + if (dir == UE_DIR_IN) { -+ ep = &pcd->in_ep[num - 1]; ++ epcount = pcd->core_if->dev_if->num_in_eps; ++ for (i = 0; i < epcount; i++) { ++ if (num == pcd->in_ep[i].dwc_ep.num) { ++ ep = &pcd->in_ep[i]; ++ break; ++ } ++ } + } else { -+ ep = &pcd->out_ep[num - 1]; ++ epcount = pcd->core_if->dev_if->num_out_eps; ++ for (i = 0; i < epcount; i++) { ++ if (num == pcd->out_ep[i].dwc_ep.num) { ++ ep = &pcd->out_ep[i]; ++ break; ++ } ++ } ++ } ++ ++ if (!ep) { ++ DWC_WARN("bad address\n"); ++ retval = -DWC_E_INVALID; ++ goto out; + } + + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); @@ -61596,7 +74040,26 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + */ + ep->dwc_ep.tx_fifo_num = + assign_tx_fifo(GET_CORE_IF(pcd)); ++ } + ++ /* Calculating EP info controller base address */ ++ if (ep->dwc_ep.tx_fifo_num ++ && GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ gdfifocfg.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)-> ++ core_global_regs->gdfifocfg); ++ gdfifocfgbase.d32 = gdfifocfg.d32 >> 16; ++ dptxfsiz.d32 = ++ (DWC_READ_REG32 ++ (&GET_CORE_IF(pcd)->core_global_regs-> ++ dtxfsiz[ep->dwc_ep.tx_fifo_num - 1]) >> 16); ++ gdfifocfg.b.epinfobase = ++ gdfifocfgbase.d32 + dptxfsiz.d32; ++ if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) { ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)-> ++ core_global_regs->gdfifocfg, ++ gdfifocfg.d32); ++ } + } + } + /* Set initial data PID. */ @@ -61606,10 +74069,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + + /* Alloc DMA Descriptors */ + if (GET_CORE_IF(pcd)->dma_desc_enable) { ++#ifndef DWC_UTE_PER_IO + if (ep->dwc_ep.type != UE_ISOCHRONOUS) { ++#endif + ep->dwc_ep.desc_addr = -+ dwc_otg_ep_alloc_desc_chain(&ep->dwc_ep. -+ dma_desc_addr, ++ dwc_otg_ep_alloc_desc_chain(&ep-> ++ dwc_ep.dma_desc_addr, + MAX_DMA_DESC_CNT); + if (!ep->dwc_ep.desc_addr) { + DWC_WARN("%s, can't allocate DMA descriptor\n", @@ -61618,12 +74083,21 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); + goto out; + } ++#ifndef DWC_UTE_PER_IO + } ++#endif + } + + DWC_DEBUGPL(DBG_PCD, "Activate %s: type=%d, mps=%d desc=%p\n", + (ep->dwc_ep.is_in ? "IN" : "OUT"), + ep->dwc_ep.type, ep->dwc_ep.maxpacket, ep->desc); ++#ifdef DWC_UTE_PER_IO ++ ep->dwc_ep.xiso_bInterval = 1 << (ep->desc->bInterval - 1); ++#endif ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ ep->dwc_ep.bInterval = 1 << (ep->desc->bInterval - 1); ++ ep->dwc_ep.frame_num = 0xFFFFFFFF; ++ } + + dwc_otg_ep_activate(GET_CORE_IF(pcd), &ep->dwc_ep); + @@ -61635,22 +74109,28 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); + -+ out: ++out: + return retval; +} + ++/** ++ * This function is being called from gadget ++ * to disable PCD endpoint. ++ */ +int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle) +{ + dwc_otg_pcd_ep_t *ep; -+ uint64_t flags; ++ dwc_irqflags_t flags; + dwc_otg_dev_dma_desc_t *desc_addr; + dwc_dma_t dma_desc_addr; ++ gdfifocfg_data_t gdfifocfgbase = {.d32 = 0 }; ++ gdfifocfg_data_t gdfifocfg = {.d32 = 0 }; ++ fifosize_data_t dptxfsiz = {.d32 = 0 }; + + ep = get_ep_from_handle(pcd, ep_handle); + + if (!ep || !ep->desc) { -+ DWC_DEBUGPL(DBG_PCD, "%s, %d %s not enabled\n", __func__, -+ ep->dwc_ep.num, ep->dwc_ep.is_in ? "IN" : "OUT"); ++ DWC_DEBUGPL(DBG_PCD, "bad ep address\n"); + return -DWC_E_INVALID; + } + @@ -61659,13 +74139,37 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + dwc_otg_request_nuke(ep); + + dwc_otg_ep_deactivate(GET_CORE_IF(pcd), &ep->dwc_ep); -+ ep->desc = 0; ++ if (pcd->core_if->core_params->dev_out_nak) { ++ DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[ep->dwc_ep.num]); ++ pcd->core_if->ep_xfer_info[ep->dwc_ep.num].state = 0; ++ } ++ ep->desc = NULL; + ep->stopped = 1; + ++ gdfifocfg.d32 = ++ DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg); ++ gdfifocfgbase.d32 = gdfifocfg.d32 >> 16; ++ + if (ep->dwc_ep.is_in) { -+ dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); ++ if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ /* Flush the Tx FIFO */ ++ dwc_otg_flush_tx_fifo(GET_CORE_IF(pcd), ++ ep->dwc_ep.tx_fifo_num); ++ } + release_perio_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); + release_tx_fifo(GET_CORE_IF(pcd), ep->dwc_ep.tx_fifo_num); ++ if (GET_CORE_IF(pcd)->en_multiple_tx_fifo) { ++ /* Decreasing EPinfo Base Addr */ ++ dptxfsiz.d32 = ++ (DWC_READ_REG32 ++ (&GET_CORE_IF(pcd)-> ++ core_global_regs->dtxfsiz[ep->dwc_ep.tx_fifo_num-1]) >> 16); ++ gdfifocfg.b.epinfobase = gdfifocfgbase.d32 - dptxfsiz.d32; ++ if (GET_CORE_IF(pcd)->snpsid <= OTG_CORE_REV_2_94a) { ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gdfifocfg, ++ gdfifocfg.d32); ++ } ++ } + } + + /* Free DMA Descriptors */ @@ -61682,36 +74186,416 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + goto out_unlocked; + } + } -+ + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); + -+ out_unlocked: ++out_unlocked: + DWC_DEBUGPL(DBG_PCD, "%d %s disabled\n", ep->dwc_ep.num, + ep->dwc_ep.is_in ? "IN" : "OUT"); + return 0; + +} + ++/******************************************************************************/ ++#ifdef DWC_UTE_PER_IO ++ ++/** ++ * Free the request and its extended parts ++ * ++ */ ++void dwc_pcd_xiso_ereq_free(dwc_otg_pcd_ep_t * ep, dwc_otg_pcd_request_t * req) ++{ ++ DWC_FREE(req->ext_req.per_io_frame_descs); ++ DWC_FREE(req); ++} ++ ++/** ++ * Start the next request in the endpoint's queue. ++ * ++ */ ++int dwc_otg_pcd_xiso_start_next_request(dwc_otg_pcd_t * pcd, ++ dwc_otg_pcd_ep_t * ep) ++{ ++ int i; ++ dwc_otg_pcd_request_t *req = NULL; ++ dwc_ep_t *dwcep = NULL; ++ struct dwc_iso_xreq_port *ereq = NULL; ++ struct dwc_iso_pkt_desc_port *ddesc_iso; ++ uint16_t nat; ++ depctl_data_t diepctl; ++ ++ dwcep = &ep->dwc_ep; ++ ++ if (dwcep->xiso_active_xfers > 0) { ++#if 0 //Disable this to decrease s/w overhead that is crucial for Isoc transfers ++ DWC_WARN("There are currently active transfers for EP%d \ ++ (active=%d; queued=%d)", dwcep->num, dwcep->xiso_active_xfers, ++ dwcep->xiso_queued_xfers); ++#endif ++ return 0; ++ } ++ ++ nat = UGETW(ep->desc->wMaxPacketSize); ++ nat = (nat >> 11) & 0x03; ++ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ ereq = &req->ext_req; ++ ep->stopped = 0; ++ ++ /* Get the frame number */ ++ dwcep->xiso_frame_num = ++ dwc_otg_get_frame_number(GET_CORE_IF(pcd)); ++ DWC_DEBUG("FRM_NUM=%d", dwcep->xiso_frame_num); ++ ++ ddesc_iso = ereq->per_io_frame_descs; ++ ++ if (dwcep->is_in) { ++ /* Setup DMA Descriptor chain for IN Isoc request */ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ //if ((i % (nat + 1)) == 0) ++ if ( i > 0 ) ++ dwcep->xiso_frame_num = ++ (dwcep->xiso_bInterval + ++ dwcep->xiso_frame_num) & 0x3FFF; ++ dwcep->desc_addr[i].buf = ++ req->dma + ddesc_iso[i].offset; ++ dwcep->desc_addr[i].status.b_iso_in.txbytes = ++ ddesc_iso[i].length; ++ dwcep->desc_addr[i].status.b_iso_in.framenum = ++ dwcep->xiso_frame_num; ++ dwcep->desc_addr[i].status.b_iso_in.bs = ++ BS_HOST_READY; ++ dwcep->desc_addr[i].status.b_iso_in.txsts = 0; ++ dwcep->desc_addr[i].status.b_iso_in.sp = ++ (ddesc_iso[i].length % ++ dwcep->maxpacket) ? 1 : 0; ++ dwcep->desc_addr[i].status.b_iso_in.ioc = 0; ++ dwcep->desc_addr[i].status.b_iso_in.pid = nat + 1; ++ dwcep->desc_addr[i].status.b_iso_in.l = 0; ++ ++ /* Process the last descriptor */ ++ if (i == ereq->pio_pkt_count - 1) { ++ dwcep->desc_addr[i].status.b_iso_in.ioc = 1; ++ dwcep->desc_addr[i].status.b_iso_in.l = 1; ++ } ++ } ++ ++ /* Setup and start the transfer for this endpoint */ ++ dwcep->xiso_active_xfers++; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ in_ep_regs[dwcep->num]->diepdma, ++ dwcep->dma_desc_addr); ++ diepctl.d32 = 0; ++ diepctl.b.epena = 1; ++ diepctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)->dev_if-> ++ in_ep_regs[dwcep->num]->diepctl, 0, ++ diepctl.d32); ++ } else { ++ /* Setup DMA Descriptor chain for OUT Isoc request */ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ //if ((i % (nat + 1)) == 0) ++ dwcep->xiso_frame_num = (dwcep->xiso_bInterval + ++ dwcep->xiso_frame_num) & 0x3FFF; ++ dwcep->desc_addr[i].buf = ++ req->dma + ddesc_iso[i].offset; ++ dwcep->desc_addr[i].status.b_iso_out.rxbytes = ++ ddesc_iso[i].length; ++ dwcep->desc_addr[i].status.b_iso_out.framenum = ++ dwcep->xiso_frame_num; ++ dwcep->desc_addr[i].status.b_iso_out.bs = ++ BS_HOST_READY; ++ dwcep->desc_addr[i].status.b_iso_out.rxsts = 0; ++ dwcep->desc_addr[i].status.b_iso_out.sp = ++ (ddesc_iso[i].length % ++ dwcep->maxpacket) ? 1 : 0; ++ dwcep->desc_addr[i].status.b_iso_out.ioc = 0; ++ dwcep->desc_addr[i].status.b_iso_out.pid = nat + 1; ++ dwcep->desc_addr[i].status.b_iso_out.l = 0; ++ ++ /* Process the last descriptor */ ++ if (i == ereq->pio_pkt_count - 1) { ++ dwcep->desc_addr[i].status.b_iso_out.ioc = 1; ++ dwcep->desc_addr[i].status.b_iso_out.l = 1; ++ } ++ } ++ ++ /* Setup and start the transfer for this endpoint */ ++ dwcep->xiso_active_xfers++; ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->out_ep_regs[dwcep->num]-> ++ doepdma, dwcep->dma_desc_addr); ++ diepctl.d32 = 0; ++ diepctl.b.epena = 1; ++ diepctl.b.cnak = 1; ++ DWC_MODIFY_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->out_ep_regs[dwcep->num]-> ++ doepctl, 0, diepctl.d32); ++ } ++ ++ } else { ++ ep->stopped = 1; ++ } ++ ++ return 0; ++} ++ ++/** ++ * - Remove the request from the queue ++ */ ++void complete_xiso_ep(dwc_otg_pcd_ep_t * ep) ++{ ++ dwc_otg_pcd_request_t *req = NULL; ++ struct dwc_iso_xreq_port *ereq = NULL; ++ struct dwc_iso_pkt_desc_port *ddesc_iso = NULL; ++ dwc_ep_t *dwcep = NULL; ++ int i; ++ ++ //DWC_DEBUG(); ++ dwcep = &ep->dwc_ep; ++ ++ /* Get the first pending request from the queue */ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); ++ return; ++ } ++ dwcep->xiso_active_xfers--; ++ dwcep->xiso_queued_xfers--; ++ /* Remove this request from the queue */ ++ DWC_CIRCLEQ_REMOVE_INIT(&ep->queue, req, queue_entry); ++ } else { ++ DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); ++ return; ++ } ++ ++ ep->stopped = 1; ++ ereq = &req->ext_req; ++ ddesc_iso = ereq->per_io_frame_descs; ++ ++ if (dwcep->xiso_active_xfers < 0) { ++ DWC_WARN("EP#%d (xiso_active_xfers=%d)", dwcep->num, ++ dwcep->xiso_active_xfers); ++ } ++ ++ /* Fill the Isoc descs of portable extended req from dma descriptors */ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ if (dwcep->is_in) { /* IN endpoints */ ++ ddesc_iso[i].actual_length = ddesc_iso[i].length - ++ dwcep->desc_addr[i].status.b_iso_in.txbytes; ++ ddesc_iso[i].status = ++ dwcep->desc_addr[i].status.b_iso_in.txsts; ++ } else { /* OUT endpoints */ ++ ddesc_iso[i].actual_length = ddesc_iso[i].length - ++ dwcep->desc_addr[i].status.b_iso_out.rxbytes; ++ ddesc_iso[i].status = ++ dwcep->desc_addr[i].status.b_iso_out.rxsts; ++ } ++ } ++ ++ DWC_SPINUNLOCK(ep->pcd->lock); ++ ++ /* Call the completion function in the non-portable logic */ ++ ep->pcd->fops->xisoc_complete(ep->pcd, ep->priv, req->priv, 0, ++ &req->ext_req); ++ ++ DWC_SPINLOCK(ep->pcd->lock); ++ ++ /* Free the request - specific freeing needed for extended request object */ ++ dwc_pcd_xiso_ereq_free(ep, req); ++ ++ /* Start the next request */ ++ dwc_otg_pcd_xiso_start_next_request(ep->pcd, ep); ++ ++ return; ++} ++ ++/** ++ * Create and initialize the Isoc pkt descriptors of the extended request. ++ * ++ */ ++static int dwc_otg_pcd_xiso_create_pkt_descs(dwc_otg_pcd_request_t * req, ++ void *ereq_nonport, ++ int atomic_alloc) ++{ ++ struct dwc_iso_xreq_port *ereq = NULL; ++ struct dwc_iso_xreq_port *req_mapped = NULL; ++ struct dwc_iso_pkt_desc_port *ipds = NULL; /* To be created in this function */ ++ uint32_t pkt_count; ++ int i; ++ ++ ereq = &req->ext_req; ++ req_mapped = (struct dwc_iso_xreq_port *)ereq_nonport; ++ pkt_count = req_mapped->pio_pkt_count; ++ ++ /* Create the isoc descs */ ++ if (atomic_alloc) { ++ ipds = DWC_ALLOC_ATOMIC(sizeof(*ipds) * pkt_count); ++ } else { ++ ipds = DWC_ALLOC(sizeof(*ipds) * pkt_count); ++ } ++ ++ if (!ipds) { ++ DWC_ERROR("Failed to allocate isoc descriptors"); ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ /* Initialize the extended request fields */ ++ ereq->per_io_frame_descs = ipds; ++ ereq->error_count = 0; ++ ereq->pio_alloc_pkt_count = pkt_count; ++ ereq->pio_pkt_count = pkt_count; ++ ereq->tr_sub_flags = req_mapped->tr_sub_flags; ++ ++ /* Init the Isoc descriptors */ ++ for (i = 0; i < pkt_count; i++) { ++ ipds[i].length = req_mapped->per_io_frame_descs[i].length; ++ ipds[i].offset = req_mapped->per_io_frame_descs[i].offset; ++ ipds[i].status = req_mapped->per_io_frame_descs[i].status; /* 0 */ ++ ipds[i].actual_length = ++ req_mapped->per_io_frame_descs[i].actual_length; ++ } ++ ++ return 0; ++} ++ ++static void prn_ext_request(struct dwc_iso_xreq_port *ereq) ++{ ++ struct dwc_iso_pkt_desc_port *xfd = NULL; ++ int i; ++ ++ DWC_DEBUG("per_io_frame_descs=%p", ereq->per_io_frame_descs); ++ DWC_DEBUG("tr_sub_flags=%d", ereq->tr_sub_flags); ++ DWC_DEBUG("error_count=%d", ereq->error_count); ++ DWC_DEBUG("pio_alloc_pkt_count=%d", ereq->pio_alloc_pkt_count); ++ DWC_DEBUG("pio_pkt_count=%d", ereq->pio_pkt_count); ++ DWC_DEBUG("res=%d", ereq->res); ++ ++ for (i = 0; i < ereq->pio_pkt_count; i++) { ++ xfd = &ereq->per_io_frame_descs[0]; ++ DWC_DEBUG("FD #%d", i); ++ ++ DWC_DEBUG("xfd->actual_length=%d", xfd->actual_length); ++ DWC_DEBUG("xfd->length=%d", xfd->length); ++ DWC_DEBUG("xfd->offset=%d", xfd->offset); ++ DWC_DEBUG("xfd->status=%d", xfd->status); ++ } ++} ++ ++/** ++ * ++ */ ++int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen, ++ int zero, void *req_handle, int atomic_alloc, ++ void *ereq_nonport) ++{ ++ dwc_otg_pcd_request_t *req = NULL; ++ dwc_otg_pcd_ep_t *ep; ++ dwc_irqflags_t flags; ++ int res; ++ ++ ep = get_ep_from_handle(pcd, ep_handle); ++ if (!ep) { ++ DWC_WARN("bad ep\n"); ++ return -DWC_E_INVALID; ++ } ++ ++ /* We support this extension only for DDMA mode */ ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ++ if (!GET_CORE_IF(pcd)->dma_desc_enable) ++ return -DWC_E_INVALID; ++ ++ /* Create a dwc_otg_pcd_request_t object */ ++ if (atomic_alloc) { ++ req = DWC_ALLOC_ATOMIC(sizeof(*req)); ++ } else { ++ req = DWC_ALLOC(sizeof(*req)); ++ } ++ ++ if (!req) { ++ return -DWC_E_NO_MEMORY; ++ } ++ ++ /* Create the Isoc descs for this request which shall be the exact match ++ * of the structure sent to us from the non-portable logic */ ++ res = ++ dwc_otg_pcd_xiso_create_pkt_descs(req, ereq_nonport, atomic_alloc); ++ if (res) { ++ DWC_WARN("Failed to init the Isoc descriptors"); ++ DWC_FREE(req); ++ return res; ++ } ++ ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ++ DWC_CIRCLEQ_INIT_ENTRY(req, queue_entry); ++ req->buf = buf; ++ req->dma = dma_buf; ++ req->length = buflen; ++ req->sent_zlp = zero; ++ req->priv = req_handle; ++ ++ //DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ ep->dwc_ep.dma_addr = dma_buf; ++ ep->dwc_ep.start_xfer_buff = buf; ++ ep->dwc_ep.xfer_buff = buf; ++ ep->dwc_ep.xfer_len = 0; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = buflen; ++ ++ /* Add this request to the tail */ ++ DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); ++ ep->dwc_ep.xiso_queued_xfers++; ++ ++//DWC_DEBUG("CP_0"); ++//DWC_DEBUG("req->ext_req.tr_sub_flags=%d", req->ext_req.tr_sub_flags); ++//prn_ext_request((struct dwc_iso_xreq_port *) ereq_nonport); ++//prn_ext_request(&req->ext_req); ++ ++ //DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ ++ /* If the req->status == ASAP then check if there is any active transfer ++ * for this endpoint. If no active transfers, then get the first entry ++ * from the queue and start that transfer ++ */ ++ if (req->ext_req.tr_sub_flags == DWC_EREQ_TF_ASAP) { ++ res = dwc_otg_pcd_xiso_start_next_request(pcd, ep); ++ if (res) { ++ DWC_WARN("Failed to start the next Isoc transfer"); ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ DWC_FREE(req); ++ return res; ++ } ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ return 0; ++} ++ ++#endif ++/* END ifdef DWC_UTE_PER_IO ***************************************************/ +int dwc_otg_pcd_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, + uint8_t * buf, dwc_dma_t dma_buf, uint32_t buflen, + int zero, void *req_handle, int atomic_alloc) +{ -+ int prevented = 0; -+ uint64_t flags; ++ dwc_irqflags_t flags; + dwc_otg_pcd_request_t *req; + dwc_otg_pcd_ep_t *ep; + uint32_t max_transfer; + + ep = get_ep_from_handle(pcd, ep_handle); -+ if ((!ep->desc && ep->dwc_ep.num != 0)) { ++ if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) { + DWC_WARN("bad ep\n"); + return -DWC_E_INVALID; + } + + if (atomic_alloc) { -+ req = dwc_alloc_atomic(sizeof(*req)); ++ req = DWC_ALLOC_ATOMIC(sizeof(*req)); + } else { -+ req = dwc_alloc(sizeof(*req)); ++ req = DWC_ALLOC(sizeof(*req)); + } + + if (!req) { @@ -61730,10 +74614,41 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + req->length = buflen; + req->sent_zlp = zero; + req->priv = req_handle; -+ ++ req->dw_align_buf = NULL; ++ if ((dma_buf & 0x3) && GET_CORE_IF(pcd)->dma_enable ++ && !GET_CORE_IF(pcd)->dma_desc_enable) ++ req->dw_align_buf = DWC_DMA_ALLOC(buflen, ++ &req->dw_align_buf_dma); + DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); + + /* ++ * After adding request to the queue for IN ISOC wait for In Token Received ++ * when TX FIFO is empty interrupt and for OUT ISOC wait for OUT Token ++ * Received when EP is disabled interrupt to obtain starting microframe ++ * (odd/even) start transfer ++ */ ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ if (req != 0) { ++ depctl_data_t depctl = {.d32 = ++ DWC_READ_REG32(&pcd->core_if->dev_if-> ++ in_ep_regs[ep->dwc_ep.num]-> ++ diepctl) }; ++ ++pcd->request_pending; ++ ++ DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); ++ if (ep->dwc_ep.is_in) { ++ depctl.b.cnak = 1; ++ DWC_WRITE_REG32(&pcd->core_if->dev_if-> ++ in_ep_regs[ep->dwc_ep.num]-> ++ diepctl, depctl.d32); ++ } ++ ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); ++ } ++ return 0; ++ } ++ ++ /* + * For EP0 IN without premature status, zlp is required? + */ + if (ep->dwc_ep.num == 0 && ep->dwc_ep.is_in) { @@ -61803,53 +74718,65 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + ep->dwc_ep.cfi_req_len = buflen; + pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, + ep, req); -+ } else { ++ } else { +#endif + max_transfer = + GET_CORE_IF(ep->pcd)->core_params-> + max_transfer_size; + -+ /* Setup and start the Transfer */ -+ ep->dwc_ep.dma_addr = dma_buf; -+ ep->dwc_ep.start_xfer_buff = buf; -+ ep->dwc_ep.xfer_buff = buf; -+ ep->dwc_ep.xfer_len = 0; -+ ep->dwc_ep.xfer_count = 0; -+ ep->dwc_ep.sent_zlp = 0; -+ ep->dwc_ep.total_len = buflen; ++ /* Setup and start the Transfer */ ++ if (req->dw_align_buf){ ++ if (ep->dwc_ep.is_in) ++ dwc_memcpy(req->dw_align_buf, ++ buf, buflen); ++ ep->dwc_ep.dma_addr = ++ req->dw_align_buf_dma; ++ ep->dwc_ep.start_xfer_buff = ++ req->dw_align_buf; ++ ep->dwc_ep.xfer_buff = ++ req->dw_align_buf; ++ } else { ++ ep->dwc_ep.dma_addr = dma_buf; ++ ep->dwc_ep.start_xfer_buff = buf; ++ ep->dwc_ep.xfer_buff = buf; ++ } ++ ep->dwc_ep.xfer_len = 0; ++ ep->dwc_ep.xfer_count = 0; ++ ep->dwc_ep.sent_zlp = 0; ++ ep->dwc_ep.total_len = buflen; + -+ ep->dwc_ep.maxxfer = max_transfer; -+ if (GET_CORE_IF(pcd)->dma_desc_enable) { ++ ep->dwc_ep.maxxfer = max_transfer; ++ if (GET_CORE_IF(pcd)->dma_desc_enable) { + uint32_t out_max_xfer = + DDMA_MAX_TRANSFER_SIZE - + (DDMA_MAX_TRANSFER_SIZE % 4); -+ if (ep->dwc_ep.is_in) { -+ if (ep->dwc_ep.maxxfer > -+ DDMA_MAX_TRANSFER_SIZE) { -+ ep->dwc_ep.maxxfer = -+ DDMA_MAX_TRANSFER_SIZE; -+ } -+ } else { ++ if (ep->dwc_ep.is_in) { ++ if (ep->dwc_ep.maxxfer > ++ DDMA_MAX_TRANSFER_SIZE) { ++ ep->dwc_ep.maxxfer = ++ DDMA_MAX_TRANSFER_SIZE; ++ } ++ } else { + if (ep->dwc_ep.maxxfer > + out_max_xfer) { -+ ep->dwc_ep.maxxfer = -+ out_max_xfer; ++ ep->dwc_ep.maxxfer = ++ out_max_xfer; ++ } + } + } -+ } -+ if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) { -+ ep->dwc_ep.maxxfer -= ++ if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) { ++ ep->dwc_ep.maxxfer -= + (ep->dwc_ep.maxxfer % + ep->dwc_ep.maxpacket); -+ } ++ } + -+ if (zero) { -+ if ((ep->dwc_ep.total_len % ++ if (zero) { ++ if ((ep->dwc_ep.total_len % + ep->dwc_ep.maxpacket == 0) + && (ep->dwc_ep.total_len != 0)) { -+ ep->dwc_ep.sent_zlp = 1; ++ ep->dwc_ep.sent_zlp = 1; ++ } + } -+ } +#ifdef DWC_UTE_CFI + } +#endif @@ -61858,7 +74785,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + } + } + -+ if ((req != 0) || prevented) { ++ if (req != 0) { + ++pcd->request_pending; + DWC_CIRCLEQ_INSERT_TAIL(&ep->queue, req, queue_entry); + if (ep->dwc_ep.is_in && ep->stopped @@ -61867,32 +74794,32 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + diepmsk_data_t diepmsk = {.d32 = 0 }; + diepmsk.b.intktxfemp = 1; + 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, ++ 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); + } + + } + } -+ + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); + + return 0; +} ++ +int dwc_otg_pcd_ep_dequeue(dwc_otg_pcd_t * pcd, void *ep_handle, + void *req_handle) +{ -+ uint64_t flags; ++ dwc_irqflags_t flags; + dwc_otg_pcd_request_t *req; + dwc_otg_pcd_ep_t *ep; + + ep = get_ep_from_handle(pcd, ep_handle); -+ if (!ep->desc && ep->dwc_ep.num != 0) { ++ if (!ep || (!ep->desc && ep->dwc_ep.num != 0)) { + DWC_WARN("bad argument\n"); + return -DWC_E_INVALID; + } @@ -61914,7 +74841,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + if (!DWC_CIRCLEQ_EMPTY_ENTRY(req, queue_entry)) { + dwc_otg_request_done(ep, req, -DWC_E_RESTART); + } else { -+ req = 0; ++ req = NULL; + } + + DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); @@ -61935,7 +74862,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 +int dwc_otg_pcd_ep_wedge(dwc_otg_pcd_t * pcd, void *ep_handle) +{ + dwc_otg_pcd_ep_t *ep; -+ uint64_t flags; ++ dwc_irqflags_t flags; + int retval = 0; + + ep = get_ep_from_handle(pcd, ep_handle); @@ -61958,12 +74885,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + fifosize_data_t txfifosize; + + txfifosize.d32 = -+ dwc_read_reg32(&GET_CORE_IF(pcd)->core_global_regs-> -+ dptxfsiz_dieptxf[ep->dwc_ep. -+ tx_fifo_num]); ++ DWC_READ_REG32(&GET_CORE_IF(pcd)-> ++ core_global_regs->dtxfsiz[ep->dwc_ep. ++ tx_fifo_num]); + txstatus.d32 = -+ dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if-> -+ in_ep_regs[ep->dwc_ep.num]->dtxfsts); ++ DWC_READ_REG32(&GET_CORE_IF(pcd)-> ++ dev_if->in_ep_regs[ep->dwc_ep.num]-> ++ dtxfsts); + + if (txstatus.b.txfspcavail < txfifosize.b.depth) { + DWC_WARN("%s() Data In Tx Fifo\n", __func__); @@ -61995,12 +74923,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 +int dwc_otg_pcd_ep_halt(dwc_otg_pcd_t * pcd, void *ep_handle, int value) +{ + dwc_otg_pcd_ep_t *ep; -+ uint64_t flags; ++ dwc_irqflags_t flags; + int retval = 0; + + ep = get_ep_from_handle(pcd, ep_handle); + -+ if ((!ep->desc && ep != &pcd->ep0) || ++ if (!ep || (!ep->desc && ep != &pcd->ep0) || + (ep->desc && (ep->desc->bmAttributes == UE_ISOCHRONOUS))) { + DWC_WARN("%s, bad ep\n", __func__); + return -DWC_E_INVALID; @@ -62019,11 +74947,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + fifosize_data_t txfifosize; + + txfifosize.d32 = -+ dwc_read_reg32(&GET_CORE_IF(pcd)->core_global_regs-> -+ dptxfsiz_dieptxf[ep->dwc_ep. -+ tx_fifo_num]); ++ DWC_READ_REG32(&GET_CORE_IF(pcd)->core_global_regs-> ++ dtxfsiz[ep->dwc_ep.tx_fifo_num]); + txstatus.d32 = -+ dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if-> ++ DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if-> + in_ep_regs[ep->dwc_ep.num]->dtxfsts); + + if (txstatus.b.txfspcavail < txfifosize.b.depth) { @@ -62066,19 +74993,51 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); + dsts_data_t dsts; + -+ 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); + if (!dsts.b.suspsts) { + DWC_WARN("Remote wakeup while is not in suspend state\n"); + } + /* Check if DEVICE_REMOTE_WAKEUP feature enabled */ + if (pcd->remote_wakeup_enable) { + if (set) { ++ ++ if (core_if->adp_enable) { ++ gpwrdn_data_t gpwrdn; ++ ++ dwc_otg_adp_probe_stop(core_if); ++ ++ /* Mask SRP detected interrupt from Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.srp_det_msk = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ ++ /* Disable Power Down Logic */ ++ gpwrdn.d32 = 0; ++ gpwrdn.b.pmuactv = 1; ++ DWC_MODIFY_REG32(&core_if-> ++ core_global_regs->gpwrdn, ++ gpwrdn.d32, 0); ++ ++ /* ++ * Initialize the Core for Device mode. ++ */ ++ core_if->op_state = B_PERIPHERAL; ++ dwc_otg_core_init(core_if); ++ dwc_otg_enable_global_interrupts(core_if); ++ cil_pcd_start(core_if); ++ ++ dwc_otg_initiate_srp(core_if); ++ } ++ + dctl.b.rmtwkupsig = 1; -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> + dctl, 0, dctl.d32); + DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n"); ++ + dwc_mdelay(2); -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs-> + dctl, dctl.d32, 0); + DWC_DEBUGPL(DBG_PCD, "Clear Remote Wakeup\n"); + } @@ -62096,7 +75055,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + glpmcfg_data_t lpmcfg; + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); + -+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); + + /* Check if we are in L1 state */ + if (!lpmcfg.b.prt_sleep_sts) { @@ -62116,10 +75075,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + return; + } + -+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg); ++ lpmcfg.d32 = DWC_READ_REG32(&core_if->core_global_regs->glpmcfg); + lpmcfg.b.en_utmi_sleep = 0; + lpmcfg.b.hird_thres &= (~(1 << 4)); -+ dwc_write_reg32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); ++ DWC_WRITE_REG32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32); + + if (set) { + dctl_data_t dctl = {.d32 = 0 }; @@ -62127,7 +75086,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + /* Set RmtWkUpSig bit to start remote wakup signaling. + * Hardware will automatically clear this bit. + */ -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs->dctl, ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, + 0, dctl.d32); + DWC_DEBUGPL(DBG_PCD, "Set Remote Wakeup\n"); + } @@ -62141,7 +75100,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 +void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set) +{ + dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dwc_irqflags_t flags; + if (dwc_otg_is_device_mode(core_if)) { ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); +#ifdef CONFIG_USB_DWC_OTG_LPM + if (core_if->lx_state == DWC_OTG_L1) { + dwc_otg_pcd_rem_wkup_from_sleep(pcd, set); @@ -62151,17 +75112,34 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 +#ifdef CONFIG_USB_DWC_OTG_LPM + } +#endif ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); + } + return; +} + ++void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs) ++{ ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dctl_data_t dctl = { 0 }; ++ ++ if (dwc_otg_is_device_mode(core_if)) { ++ dctl.b.sftdiscon = 1; ++ DWC_PRINTF("Soft disconnect for %d useconds\n",no_of_usecs); ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, 0, dctl.d32); ++ dwc_udelay(no_of_usecs); ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32,0); ++ ++ } else{ ++ DWC_PRINTF("NOT SUPPORTED IN HOST MODE\n"); ++ } ++ return; ++ ++} ++ +int dwc_otg_pcd_wakeup(dwc_otg_pcd_t * pcd) +{ + dsts_data_t dsts; + gotgctl_data_t gotgctl; -+ uint64_t flags; -+ -+ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); + + /* + * This function starts the Protocol if no session is in progress. If @@ -62171,13 +75149,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + + /* Check if valid session */ + gotgctl.d32 = -+ dwc_read_reg32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl)); ++ DWC_READ_REG32(&(GET_CORE_IF(pcd)->core_global_regs->gotgctl)); + if (gotgctl.b.bsesvld) { + /* Check if suspend state */ + dsts.d32 = -+ dwc_read_reg32(& -+ (GET_CORE_IF(pcd)->dev_if->dev_global_regs-> -+ dsts)); ++ DWC_READ_REG32(& ++ (GET_CORE_IF(pcd)->dev_if-> ++ dev_global_regs->dsts)); + if (dsts.b.suspsts) { + dwc_otg_pcd_remote_wakeup(pcd, 1); + } @@ -62185,7 +75163,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + dwc_otg_pcd_initiate_srp(pcd); + } + -+ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); + return 0; + +} @@ -62196,33 +75173,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + * + * @param pcd the pcd structure. + */ -+void dwc_otg_pcd_start_srp_timer(dwc_otg_pcd_t * pcd) -+{ -+ GET_CORE_IF(pcd)->srp_timer_started = 1; -+ DWC_TIMER_SCHEDULE(pcd->srp_timer, 6000 /* 6 secs */ ); -+} -+ +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) { -+ DWC_ERROR("Session Request Already active!\n"); -+ return; -+ } -+ -+ DWC_INFO("Session Request Initated\n"); //NOTICE -+ mem.d32 = dwc_read_reg32(addr); -+ mem.b.sesreq = 1; -+ dwc_write_reg32(addr, mem.d32); -+ -+ /* Start the SRP timer */ -+ dwc_otg_pcd_start_srp_timer(pcd); -+ return; ++ dwc_irqflags_t flags; ++ DWC_SPINLOCK_IRQSAVE(pcd->lock, &flags); ++ dwc_otg_initiate_srp(GET_CORE_IF(pcd)); ++ DWC_SPINUNLOCK_IRQRESTORE(pcd->lock, flags); +} + +int dwc_otg_pcd_get_frame_number(dwc_otg_pcd_t * pcd) @@ -62255,16 +75211,18 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.c linux-rpi-bootc-3 + return pcd->remote_wakeup_enable; +} + -+#endif /* DWC_HOST_ONLY */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.h ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.h 2012-07-15 20:29:19.046082944 +0200 -@@ -0,0 +1,216 @@ ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h +new file mode 100644 +index 0000000..8ef7ba6 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd.h +@@ -0,0 +1,266 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd.h $ -+ * $Revision: #39 $ -+ * $Date: 2008/12/16 $ -+ * $Change: 1153731 $ ++ * $Revision: #48 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ + * + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless @@ -62296,6 +75254,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-rpi-bootc-3 +#if !defined(__DWC_PCD_H__) +#define __DWC_PCD_H__ + ++#include "dwc_otg_os_dep.h" +#include "usb.h" +#include "dwc_otg_cil.h" +#include "dwc_otg_pcd_if.h" @@ -62308,7 +75267,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-rpi-bootc-3 + * the Perpherial Contoller Driver (PCD). + * + * The Peripheral Controller Driver (PCD) for Linux will implement the -+ * Gadget API, so that the existing Gadget drivers can be used. For ++ * Gadget API, so that the existing Gadget drivers can be used. For + * the Mass Storage Function driver the File-backed USB Storage Gadget + * (FBS) driver will be used. The FBS driver supports the + * Control-Bulk (CB), Control-Bulk-Interrupt (CBI), and Bulk-Only @@ -62316,12 +75275,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-rpi-bootc-3 + * + */ + ++/** Invalid DMA Address */ ++#define DWC_DMA_ADDR_INVALID (~(dwc_dma_t)0) ++ +/** Max Transfer size for any EP */ +#define DDMA_MAX_TRANSFER_SIZE 65535 + -+/** Max DMA Descriptor count for any EP */ -+#define MAX_DMA_DESC_CNT 64 -+ +/** + * Get the pointer to the core_if from the pcd pointer. + */ @@ -62348,6 +75307,42 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-rpi-bootc-3 + */ +typedef struct usb_iso_request dwc_otg_pcd_iso_request_t; + ++#ifdef DWC_UTE_PER_IO ++ ++/** ++ * This shall be the exact analogy of the same type structure defined in the ++ * usb_gadget.h. Each descriptor contains ++ */ ++struct dwc_iso_pkt_desc_port { ++ uint32_t offset; ++ uint32_t length; /* expected length */ ++ uint32_t actual_length; ++ uint32_t status; ++}; ++ ++struct dwc_iso_xreq_port { ++ /** transfer/submission flag */ ++ uint32_t tr_sub_flags; ++ /** Start the request ASAP */ ++#define DWC_EREQ_TF_ASAP 0x00000002 ++ /** Just enqueue the request w/o initiating a transfer */ ++#define DWC_EREQ_TF_ENQUEUE 0x00000004 ++ ++ /** ++ * count of ISO packets attached to this request - shall ++ * not exceed the pio_alloc_pkt_count ++ */ ++ uint32_t pio_pkt_count; ++ /** count of ISO packets allocated for this request */ ++ uint32_t pio_alloc_pkt_count; ++ /** number of ISO packet errors */ ++ uint32_t error_count; ++ /** reserved for future extension */ ++ uint32_t res; ++ /** Will be allocated and freed in the UTE gadget and based on the CFC value */ ++ struct dwc_iso_pkt_desc_port *per_io_frame_descs; ++}; ++#endif +/** DWC_otg request structure. + * This structure is a list of requests. + */ @@ -62358,8 +75353,18 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-rpi-bootc-3 + uint32_t length; + uint32_t actual; + unsigned sent_zlp:1; ++ /** ++ * Used instead of original buffer if ++ * it(physical address) is not dword-aligned. ++ **/ ++ uint8_t *dw_align_buf; ++ dwc_dma_t dw_align_buf_dma; + + DWC_CIRCLEQ_ENTRY(dwc_otg_pcd_request) queue_entry; ++#ifdef DWC_UTE_PER_IO ++ struct dwc_iso_xreq_port ext_req; ++ //void *priv_ereq_nport; /* */ ++#endif +} dwc_otg_pcd_request_t; + +DWC_CIRCLEQ_HEAD(req_list, dwc_otg_pcd_request); @@ -62398,6 +75403,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-rpi-bootc-3 + */ +struct dwc_otg_pcd { + const struct dwc_otg_pcd_function_ops *fops; ++ /** The DWC otg device pointer */ ++ struct dwc_otg_device *otg_dev; + /** Core Interface */ + dwc_otg_core_if_t *core_if; + /** State of EP0 */ @@ -62428,6 +75435,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-rpi-bootc-3 + + dwc_dma_t setup_pkt_dma_handle; + ++ /* Additional buffer and flag for CTRL_WR premature case */ ++ uint8_t *backup_buf; ++ unsigned data_terminated; ++ + /** 2-byte dma buffer used to return status from GET_STATUS */ + uint16_t *status_buf; + dwc_dma_t status_buf_dma_handle; @@ -62442,9 +75453,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-rpi-bootc-3 + /** number of valid EPs in the above array. */ +// unsigned num_eps : 4; + dwc_spinlock_t *lock; -+ /** Timer for SRP. If it expires before SRP is successful -+ * clear the SRP. */ -+ dwc_timer_t *srp_timer; + + /** Tasklet to defer starting of TEST mode transmissions until + * Status Phase has been completed. @@ -62457,7 +75465,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-rpi-bootc-3 + /** The test mode to enter when the tasklet is executed. */ + unsigned test_mode; + /** The cfi_api structure that implements most of the CFI API -+ * and OTG specific core configuration functionality ++ * and OTG specific core configuration functionality + */ +#ifdef DWC_UTE_CFI + struct cfiobject *cfi; @@ -62475,16 +75483,18 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd.h linux-rpi-bootc-3 + +extern void do_test_mode(void *data); +#endif -+#endif /* DWC_HOST_ONLY */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h 2012-07-15 20:29:19.179085409 +0200 -@@ -0,0 +1,333 @@ ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h +new file mode 100644 +index 0000000..c8d2e0e +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h +@@ -0,0 +1,360 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_if.h $ -+ * $Revision: #6 $ -+ * $Date: 2009/04/03 $ -+ * $Change: 1225059 $ ++ * $Revision: #11 $ ++ * $Date: 2011/10/26 $ ++ * $Change: 1873028 $ + * + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless @@ -62517,10 +75527,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-rpi-boot +#if !defined(__DWC_PCD_IF_H__) +#define __DWC_PCD_IF_H__ + -+#include "dwc_os.h" ++//#include "dwc_os.h" +#include "dwc_otg_core_if.h" + -+/** @file ++/** @file + * This file defines DWC_OTG PCD Core API. + */ + @@ -62585,6 +75595,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-rpi-boot + +typedef int (*cfi_setup_cb_t) (dwc_otg_pcd_t * pcd, void *ctrl_req_bytes); + ++/** ++ * ++ * @param ep_handle Void pointer to the usb_ep structure ++ * @param ereq_port Pointer to the extended request structure created in the ++ * portable part. ++ */ ++typedef int (*xiso_completion_cb_t) (dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int32_t status, ++ void *ereq_port); +/** Function Driver Ops Data Structure */ +struct dwc_otg_pcd_function_ops { + dwc_connect_cb_t connect; @@ -62598,6 +75617,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-rpi-boot + dwc_reset_cb_t reset; + dwc_hnp_params_changed_cb_t hnp_changed; + cfi_setup_cb_t cfi_setup; ++#ifdef DWC_UTE_PER_IO ++ xiso_completion_cb_t xisoc_complete; ++#endif +}; +/** @} */ + @@ -62638,15 +75660,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-rpi-boot + * + * @param pcd The PCD + * @param ep_desc Endpoint descriptor -+ * @param ep_handle Handle on endpoint, that will be used to identify endpoint. ++ * @param usb_ep Handle on endpoint, that will be used to identify endpoint. + */ +extern int dwc_otg_pcd_ep_enable(dwc_otg_pcd_t * pcd, -+ const uint8_t * ep_desc, void *ep_handle); ++ const uint8_t * ep_desc, void *usb_ep); + +/** Disable the endpoint referenced by ep_handle. + * + * Returns -DWC_E_INVALID if invalid parameters were passed. -+ * Returns -DWC_E_SHUTDOWN if any other error ocurred. ++ * Returns -DWC_E_SHUTDOWN if any other error occurred. + * Returns 0 on success. */ +extern int dwc_otg_pcd_ep_disable(dwc_otg_pcd_t * pcd, void *ep_handle); + @@ -62672,6 +75694,19 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-rpi-boot + uint8_t * buf, dwc_dma_t dma_buf, + uint32_t buflen, int zero, void *req_handle, + int atomic_alloc); ++#ifdef DWC_UTE_PER_IO ++/** ++ * ++ * @param ereq_nonport Pointer to the extended request part of the ++ * usb_request structure defined in usb_gadget.h file. ++ */ ++extern int dwc_otg_pcd_xiso_ep_queue(dwc_otg_pcd_t * pcd, void *ep_handle, ++ uint8_t * buf, dwc_dma_t dma_buf, ++ uint32_t buflen, int zero, ++ void *req_handle, int atomic_alloc, ++ void *ereq_nonport); ++ ++#endif + +/** De-queue the specified data transfer that has not yet completed. + * @@ -62789,6 +75824,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-rpi-boot +/** Starts remote wakeup signaling. */ +extern void dwc_otg_pcd_remote_wakeup(dwc_otg_pcd_t * pcd, int set); + ++/** Starts micorsecond soft disconnect. */ ++extern void dwc_otg_pcd_disconnect_us(dwc_otg_pcd_t * pcd, int no_of_usecs); +/** This function returns whether device is dualspeed.*/ +extern uint32_t dwc_otg_pcd_is_dualspeed(dwc_otg_pcd_t * pcd); + @@ -62813,15 +75850,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_if.h linux-rpi-boot +#endif /* __DWC_PCD_IF_H__ */ + +#endif /* DWC_HOST_ONLY */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c 2012-07-15 20:29:19.078083509 +0200 -@@ -0,0 +1,4077 @@ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c +new file mode 100644 +index 0000000..27061d3 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c +@@ -0,0 +1,5147 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_intr.c $ -+ * $Revision: #93 $ -+ * $Date: 2009/04/02 $ -+ * $Change: 1224216 $ ++ * $Revision: #116 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ + * + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless @@ -62857,6 +75896,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo +#include "dwc_otg_cfi.h" +#endif + ++#ifdef DWC_UTE_PER_IO ++extern void complete_xiso_ep(dwc_otg_pcd_ep_t * ep); ++#endif +//#define PRINT_CFI_DMA_DESCS + +#define DEBUG_EP0 @@ -62927,6 +75969,40 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo +#endif +} + ++/** ++ * This function calculate the size of the payload in the memory ++ * for out endpoints and prints size for debug purposes(used in ++ * 2.93a DevOutNak feature). ++ */ ++static inline void print_memory_payload(dwc_otg_pcd_t * pcd, dwc_ep_t * ep) ++{ ++#ifdef DEBUG ++ deptsiz_data_t deptsiz_init = {.d32 = 0 }; ++ deptsiz_data_t deptsiz_updt = {.d32 = 0 }; ++ int pack_num; ++ unsigned payload; ++ ++ deptsiz_init.d32 = pcd->core_if->start_doeptsiz_val[ep->num]; ++ deptsiz_updt.d32 = ++ DWC_READ_REG32(&pcd->core_if->dev_if-> ++ out_ep_regs[ep->num]->doeptsiz); ++ /* Payload will be */ ++ payload = deptsiz_init.b.xfersize - deptsiz_updt.b.xfersize; ++ /* Packet count is decremented every time a packet ++ * is written to the RxFIFO not in to the external memory ++ * So, if payload == 0, then it means no packet was sent to ext memory*/ ++ pack_num = (!payload) ? 0 : (deptsiz_init.b.pktcnt - deptsiz_updt.b.pktcnt); ++ DWC_DEBUGPL(DBG_PCDV, ++ "Payload for EP%d-%s\n", ++ ep->num, (ep->is_in ? "IN" : "OUT")); ++ DWC_DEBUGPL(DBG_PCDV, ++ "Number of transfered bytes = 0x%08x\n", payload); ++ DWC_DEBUGPL(DBG_PCDV, ++ "Number of transfered packets = %d\n", pack_num); ++#endif ++} ++ ++ +#ifdef DWC_UTE_CFI +static inline void print_desc(struct dwc_otg_dma_desc *ddesc, + const uint8_t * epname, int descnum) @@ -63019,48 +76095,57 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + pcd->cfi->ops.build_descriptors(pcd->cfi, pcd, ep, req); + } else { +#endif -+ /* 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.sent_zlp = 0; -+ ep->dwc_ep.total_len = req->length; -+ ep->dwc_ep.xfer_len = 0; -+ ep->dwc_ep.xfer_count = 0; ++ /* Setup and start the Transfer */ ++ if (req->dw_align_buf) { ++ ep->dwc_ep.dma_addr = req->dw_align_buf_dma; ++ ep->dwc_ep.start_xfer_buff = req->dw_align_buf; ++ ep->dwc_ep.xfer_buff = req->dw_align_buf; ++ } else { ++ 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.sent_zlp = 0; ++ ep->dwc_ep.total_len = req->length; ++ ep->dwc_ep.xfer_len = 0; ++ ep->dwc_ep.xfer_count = 0; + -+ ep->dwc_ep.maxxfer = max_transfer; -+ if (GET_CORE_IF(ep->pcd)->dma_desc_enable) { -+ uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE -+ - (DDMA_MAX_TRANSFER_SIZE % 4); -+ if (ep->dwc_ep.is_in) { ++ ep->dwc_ep.maxxfer = max_transfer; ++ if (GET_CORE_IF(ep->pcd)->dma_desc_enable) { ++ uint32_t out_max_xfer = DDMA_MAX_TRANSFER_SIZE ++ - (DDMA_MAX_TRANSFER_SIZE % 4); ++ if (ep->dwc_ep.is_in) { + if (ep->dwc_ep.maxxfer > + DDMA_MAX_TRANSFER_SIZE) { -+ ep->dwc_ep.maxxfer = -+ DDMA_MAX_TRANSFER_SIZE; -+ } -+ } else { -+ if (ep->dwc_ep.maxxfer > out_max_xfer) { ++ ep->dwc_ep.maxxfer = ++ DDMA_MAX_TRANSFER_SIZE; ++ } ++ } else { ++ if (ep->dwc_ep.maxxfer > out_max_xfer) { + ep->dwc_ep.maxxfer = + out_max_xfer; ++ } + } + } -+ } -+ if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) { -+ ep->dwc_ep.maxxfer -= -+ (ep->dwc_ep.maxxfer % ep->dwc_ep.maxpacket); -+ } -+ if (req->sent_zlp) { ++ if (ep->dwc_ep.maxxfer < ep->dwc_ep.total_len) { ++ ep->dwc_ep.maxxfer -= ++ (ep->dwc_ep.maxxfer % ep->dwc_ep.maxpacket); ++ } ++ if (req->sent_zlp) { + if ((ep->dwc_ep.total_len % + ep->dwc_ep.maxpacket == 0) + && (ep->dwc_ep.total_len != 0)) { -+ ep->dwc_ep.sent_zlp = 1; -+ } ++ ep->dwc_ep.sent_zlp = 1; ++ } + -+ } ++ } +#ifdef DWC_UTE_CFI + } +#endif + dwc_otg_ep_start_transfer(GET_CORE_IF(ep->pcd), &ep->dwc_ep); ++ } else if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ DWC_PRINTF("There are no more ISOC requests \n"); ++ ep->dwc_ep.frame_num = 0xFFFFFFFF; + } +} + @@ -63079,7 +76164,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + /* Clear interrupt */ + gintsts.d32 = 0; + gintsts.b.sofintr = 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; +} @@ -63116,10 +76201,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + //DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, _pcd); + /* 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 " + "pktsts:%x Frame:%d(0x%0x)\n", @@ -63172,11 +76257,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + } + + /* 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; + gintsts.b.rxstsqlvl = 1; -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); + + //DWC_DEBUGPL(DBG_PCDV, "EXIT: %s\n", __func__); + return 1; @@ -63212,7 +76297,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + + /* Read the DTKNQ Registers */ + for (i = 0; i < DTKNQ_REG_CNT; i++) { -+ in_tkn_epnums[i] = dwc_read_reg32(addr); ++ 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) { @@ -63296,7 +76381,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + + /* 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 && @@ -63311,17 +76396,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + } + + dwords = (len + 3) / 4; -+ txstatus.d32 = dwc_read_reg32(&global_regs->gnptxsts); ++ txstatus.d32 = DWC_READ_REG32(&global_regs->gnptxsts); + DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", txstatus.d32); + } + + DWC_DEBUGPL(DBG_PCDV, "GNPTXSTS=0x%08x\n", -+ dwc_read_reg32(&global_regs->gnptxsts)); ++ DWC_READ_REG32(&global_regs->gnptxsts)); + + /* Clear interrupt */ + gintsts.d32 = 0; + gintsts.b.nptxfempty = 1; -+ dwc_write_reg32(&global_regs->gintsts, gintsts.d32); ++ DWC_WRITE_REG32(&global_regs->gintsts, gintsts.d32); + + return 1; +} @@ -63357,7 +76442,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + + /* 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 && @@ -63373,13 +76458,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + + dwords = (len + 3) / 4; + txstatus.d32 = -+ dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dtxfsts); ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts); + DWC_DEBUGPL(DBG_PCDV, "dtxfsts[%d]=0x%08x\n", epnum, + txstatus.d32); + } + + DWC_DEBUGPL(DBG_PCDV, "b4 dtxfsts[%d]=0x%08x\n", epnum, -+ dwc_read_reg32(&dev_if->in_ep_regs[epnum]->dtxfsts)); ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dtxfsts)); + + return 1; +} @@ -63405,6 +76490,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + /* don't disconnect drivers more than once */ + if (pcd->ep0state == EP0_DISCONNECT) { + DWC_DEBUGPL(DBG_ANY, "%s() Already Disconnected\n", __func__); ++ DWC_SPINUNLOCK(pcd->lock); + return; + } + pcd->ep0state = EP0_DISCONNECT; @@ -63414,7 +76500,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + + /* 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 */ @@ -63455,13 +76541,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + + DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "i2cintr"); + intr_mask.b.i2cintr = 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); + + /* 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; +} @@ -63475,10 +76561,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo +#if defined(VERBOSE) + DWC_PRINTF("Early Suspend Detected\n"); +#endif ++ + /* Clear interrupt */ + gintsts.d32 = 0; + gintsts.b.erlysuspend = 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; +} @@ -63510,8 +76597,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + +#ifdef VERBOSE + DWC_DEBUGPL(DBG_PCDV, "%s() doepctl0=%0x\n", __func__, -+ dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl)); ++ DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl)); +#endif ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doepctl); ++ if (doepctl.b.epena) { ++ return; ++ } ++ } + + doeptsize0.b.supcnt = 3; + doeptsize0.b.pktcnt = 1; @@ -63520,11 +76613,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + 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, ++ 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, ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepdma, + pcd->setup_pkt_dma_handle); + } else { + dev_if->setup_desc_index = @@ -63534,39 +76627,49 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + + /** DMA Descriptor Setup */ + dma_desc->status.b.bs = BS_HOST_BUSY; ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ dma_desc->status.b.sr = 0; ++ dma_desc->status.b.mtrf = 0; ++ } + 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.sts = 0; + 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]); ++ 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, ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doeptsiz, + doeptsize0.d32); + } + -+ /** DOEPCTL0 Register write */ ++ /** DOEPCTL0 Register write cnak will be set after setup interrupt */ ++ doepctl.d32 = 0; + doepctl.b.epena = 1; ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) { + doepctl.b.cnak = 1; -+ dwc_write_reg32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[0]->doepctl, doepctl.d32); ++ } else { ++ DWC_MODIFY_REG32(&dev_if->out_ep_regs[0]->doepctl, 0, doepctl.d32); ++ } + +#ifdef VERBOSE + DWC_DEBUGPL(DBG_PCDV, "doepctl0=%0x\n", -+ dwc_read_reg32(&dev_if->out_ep_regs[0]->doepctl)); ++ 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_READ_REG32(&dev_if->in_ep_regs[0]->diepctl)); +#endif +} + +/** -+ * This interrupt occurs when a USB Reset is detected. When the USB ++ * This interrupt occurs when a USB Reset is detected. When the USB + * Reset Interrupt occurs the device state is set to DEFAULT and the + * EP0 state is set to IDLE. + * -# Set the NAK bit for all OUT endpoints (DOEPCTLn.SNAK = 1) @@ -63593,6 +76696,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + 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 }; ++ depctl_data_t diepctl = {.d32 = 0 }; + daint_data_t daintmsk = {.d32 = 0 }; + doepmsk_data_t doepmsk = {.d32 = 0 }; + diepmsk_data_t diepmsk = {.d32 = 0 }; @@ -63603,17 +76707,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + gintsts_data_t gintsts; + pcgcctl_data_t power = {.d32 = 0 }; + -+ power.d32 = dwc_read_reg32(core_if->pcgcctl); ++ power.d32 = DWC_READ_REG32(core_if->pcgcctl); + if (power.b.stoppclk) { + power.d32 = 0; + power.b.stoppclk = 1; -+ dwc_modify_reg32(core_if->pcgcctl, power.d32, 0); ++ DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0); + + power.b.pwrclmp = 1; -+ dwc_modify_reg32(core_if->pcgcctl, power.d32, 0); ++ DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0); + + power.b.rstpdwnmodule = 1; -+ dwc_modify_reg32(core_if->pcgcctl, power.d32, 0); ++ DWC_MODIFY_REG32(core_if->pcgcctl, power.d32, 0); + } + + core_if->lx_state = DWC_OTG_L0; @@ -63629,31 +76733,55 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + dwc_ep->next_frame = 0xffffffff; + } + } -+#endif /* DWC_EN_ISOC */ ++#endif /* DWC_EN_ISOC */ + + /* reset the HNP settings */ + 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 */ + doepctl.b.snak = 1; + 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, 0x10); + /* Flush the Learning Queue */ + resetctl.b.intknqflsh = 1; -+ dwc_write_reg32(&core_if->core_global_regs->grstctl, resetctl.d32); ++ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); ++ ++ if (!core_if->core_params->en_multiple_tx_fifo && core_if->dma_enable) { ++ core_if->start_predict = 0; ++ for (i = 0; i<= core_if->dev_if->num_in_eps; ++i) { ++ core_if->nextep_seq[i] = 0xff; // 0xff - EP not active ++ } ++ core_if->nextep_seq[0] = 0; ++ core_if->first_in_nextep_seq = 0; ++ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[0]->diepctl); ++ diepctl.b.nextep = 0; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[0]->diepctl, diepctl.d32); ++ ++ /* Update IN Endpoint Mismatch Count by active IN NP EP count + 1 */ ++ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg); ++ dcfg.b.epmscnt = 2; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32); ++ ++ DWC_DEBUGPL(DBG_PCDV, ++ "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_PCDV, "%2d\n", core_if->nextep_seq[i]); ++ } ++ } + + if (core_if->multiproc_int_enable) { + daintmsk.b.inep0 = 1; + daintmsk.b.outep0 = 1; -+ dwc_write_reg32(&dev_if->dev_global_regs->deachintmsk, ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->deachintmsk, + daintmsk.d32); + + doepmsk.b.setup = 1; @@ -63661,41 +76789,47 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + doepmsk.b.ahberr = 1; + doepmsk.b.epdisabled = 1; + -+ if (core_if->dma_desc_enable) { ++ if ((core_if->dma_desc_enable) || ++ (core_if->dma_enable ++ && core_if->snpsid >= OTG_CORE_REV_3_00a)) { + doepmsk.b.stsphsercvd = 1; -+ doepmsk.b.bna = 1; + } ++ if (core_if->dma_desc_enable) ++ doepmsk.b.bna = 1; +/* + doepmsk.b.babble = 1; + doepmsk.b.nyet = 1; + -+ if(core_if->dma_enable) { ++ if (core_if->dma_enable) { + doepmsk.b.nak = 1; + } +*/ -+ dwc_write_reg32(&dev_if->dev_global_regs->doepeachintmsk[0], ++ 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; ++ diepmsk.b.intknepmis = 1; ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) ++ diepmsk.b.intknepmis = 0; + -+ if (core_if->dma_desc_enable) { ++/* if (core_if->dma_desc_enable) { + diepmsk.b.bna = 1; + } ++*/ +/* -+ if(core_if->dma_enable) { ++ if (core_if->dma_enable) { + diepmsk.b.nak = 1; + } +*/ -+ dwc_write_reg32(&dev_if->dev_global_regs->diepeachintmsk[0], ++ 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, ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, + daintmsk.d32); + + doepmsk.b.setup = 1; @@ -63703,37 +76837,43 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + doepmsk.b.ahberr = 1; + doepmsk.b.epdisabled = 1; + -+ if (core_if->dma_desc_enable) { ++ if ((core_if->dma_desc_enable) || ++ (core_if->dma_enable ++ && core_if->snpsid >= OTG_CORE_REV_3_00a)) { + doepmsk.b.stsphsercvd = 1; -+ doepmsk.b.bna = 1; + } -+ dwc_write_reg32(&dev_if->dev_global_regs->doepmsk, doepmsk.d32); ++ if (core_if->dma_desc_enable) ++ doepmsk.b.bna = 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->en_multiple_tx_fifo && core_if->dma_enable) ++ diepmsk.b.intknepmis = 0; ++/* + if (core_if->dma_desc_enable) { + diepmsk.b.bna = 1; + } ++*/ + -+ dwc_write_reg32(&dev_if->dev_global_regs->diepmsk, diepmsk.d32); ++ 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); ++ if (core_if->snpsid <= OTG_CORE_REV_2_94a) ++ ep0_out_start(core_if, pcd); + + /* Clear interrupt */ + gintsts.d32 = 0; + gintsts.b.usbreset = 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; +} @@ -63748,7 +76888,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo +{ + dsts_data_t dsts; + int speed = 0; -+ 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); + + switch (dsts.b.enumspd) { + case DWC_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ: @@ -63784,13 +76924,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + DWC_DEBUGPL(DBG_PCD, "SPEED ENUM\n"); + + if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_2_60a) { -+ utmi16b = 6; ++ utmi16b = 6; //vahrama old value was 6; + utmi8b = 9; + } else { + utmi16b = 4; + utmi8b = 8; + } + dwc_otg_ep0_activate(GET_CORE_IF(pcd), &ep0->dwc_ep); ++ if (GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) { ++ ep0_out_start(GET_CORE_IF(pcd), pcd); ++ } + +#ifdef DEBUG_EP0 + print_ep0_state(pcd); @@ -63810,7 +76953,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + pcd->fops->connect(pcd, speed); + + /* Set USB turnaround time based on device speed and PHY interface. */ -+ gusbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg); ++ gusbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg); + if (speed == USB_SPEED_HIGH) { + if (GET_CORE_IF(pcd)->hwcfg2.b.hs_phy_type == + DWC_HWCFG2_HS_PHY_TYPE_ULPI) { @@ -63822,11 +76965,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + /* UTMI+ interface */ + 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 { + gusbcfg.b.usbtrdtim = utmi16b; @@ -63840,8 +76983,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + gusbcfg.b.usbtrdtim = 9; + } 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 { + gusbcfg.b.usbtrdtim = utmi8b; @@ -63852,12 +76995,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + /* Full or low speed */ + gusbcfg.b.usbtrdtim = 9; + } -+ dwc_write_reg32(&global_regs->gusbcfg, gusbcfg.d32); ++ DWC_WRITE_REG32(&global_regs->gusbcfg, gusbcfg.d32); + + /* Clear interrupt */ + gintsts.d32 = 0; + gintsts.b.enumdone = 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; +} @@ -63872,17 +77015,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + gintmsk_data_t intr_mask = {.d32 = 0 }; + gintsts_data_t gintsts; + -+ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", -+ "ISOC Out Dropped"); ++ DWC_WARN("INTERRUPT Handler not implemented for %s\n", ++ "ISOC Out Dropped"); + + intr_mask.b.isooutdrop = 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); + + /* Clear interrupt */ + gintsts.d32 = 0; + gintsts.b.isooutdrop = 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; @@ -63900,13 +77043,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "EOP"); + + intr_mask.b.eopframe = 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); + + /* Clear interrupt */ + gintsts.d32 = 0; + gintsts.b.eopframe = 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; @@ -63917,24 +77060,84 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + * non-periodic Tx FIFO does not match EP of the IN Token received. + * + * The "Device IN Token Queue" Registers are read to determine the -+ * order the IN Tokens have been received. The non-periodic Tx FIFO ++ * order the IN Tokens have been received. The non-periodic Tx FIFO + * is flushed, so it can be reloaded in the order seen in the IN Token + * 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_pcd_t * pcd) +{ + gintsts_data_t gintsts; -+ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if); ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ dctl_data_t dctl; ++ gintmsk_data_t intr_mask = {.d32 = 0 }; + ++ if (!core_if->en_multiple_tx_fifo && core_if->dma_enable) { ++ core_if->start_predict = 1; ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if); ++ ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ if (!gintsts.b.ginnakeff) { ++ /* Disable EP Mismatch interrupt */ ++ intr_mask.d32 = 0; ++ intr_mask.b.epmismatch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32, 0); ++ /* Enable the Global IN NAK Effective Interrupt */ ++ intr_mask.d32 = 0; ++ intr_mask.b.ginnakeff = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32); ++ /* Set the global non-periodic IN NAK handshake */ ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ dctl.b.sgnpinnak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++ } else { ++ DWC_PRINTF("gintsts.b.ginnakeff = 1! dctl.b.sgnpinnak not set\n"); ++ } ++ /* Disabling of all EP's will be done in dwc_otg_pcd_handle_in_nak_effective() ++ * handler after Global IN NAK Effective interrupt will be asserted */ ++ } + /* 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; +} + +/** ++ * This interrupt is valid only in DMA mode. This interrupt indicates that the ++ * core has stopped fetching data for IN endpoints due to the unavailability of ++ * TxFIFO space or Request Queue space. This interrupt is used by the ++ * application for an endpoint mismatch algorithm. ++ * ++ * @param pcd The PCD ++ */ ++int32_t dwc_otg_pcd_handle_ep_fetsusp_intr(dwc_otg_pcd_t * pcd) ++{ ++ gintsts_data_t gintsts; ++ gintmsk_data_t gintmsk_data; ++ dctl_data_t dctl; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); ++ DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, core_if); ++ ++ /* Clear the global non-periodic IN NAK handshake */ ++ dctl.d32 = 0; ++ dctl.b.cgnpinnak = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ ++ /* Mask GINTSTS.FETSUSP interrupt */ ++ gintmsk_data.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); ++ gintmsk_data.b.fetsusp = 0; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, gintmsk_data.d32); ++ ++ /* Clear interrupt */ ++ gintsts.d32 = 0; ++ gintsts.b.fetsusp = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintsts, gintsts.d32); ++ ++ return 1; ++} ++/** + * This funcion stalls EP0. + */ +static inline void ep0_do_stall(dwc_otg_pcd_t * pcd, const int err_val) @@ -63968,12 +77171,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + /** @todo This is a g_file_storage gadget driver specific + * workaround: a DELAYED_STATUS result from the fsg_setup + * routine will result in the gadget queueing a EP0 IN status -+ * phase for a two-stage control transfer. Exactly the same as ++ * phase for a two-stage control transfer. Exactly the same as + * a SET_CONFIGURATION/SET_INTERFACE except that this is a class + * specific request. Need a generic way to know when the gadget -+ * driver will queue the status phase. Can we assume when we ++ * driver will queue the status phase. Can we assume when we + * call the gadget driver setup() function that it will always -+ * queue and require the following flag? Need to look into ++ * queue and require the following flag? Need to look into + * this. + */ + @@ -64021,6 +77224,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + + /* Prepare for more SETUP Packets */ + DWC_DEBUGPL(DBG_PCD, "EP0 IN ZLP\n"); ++ if ((GET_CORE_IF(pcd)->snpsid >= OTG_CORE_REV_3_00a) ++ && (pcd->core_if->dma_desc_enable) ++ && (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len)) { ++ DWC_DEBUGPL(DBG_PCDV, ++ "Data terminated wait next packet in out_desc_addr\n"); ++ pcd->backup_buf = phys_to_virt(ep0->dwc_ep.dma_addr); ++ pcd->data_terminated = 1; ++ } + ep0->dwc_ep.xfer_len = 0; + ep0->dwc_ep.xfer_count = 0; + ep0->dwc_ep.is_in = 1; @@ -64109,7 +77320,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + +// DWC_WARN("%s() has not been tested since being rewritten!\n", __func__); + -+ dctl.d32 = dwc_read_reg32(&core_if->dev_if->dev_global_regs->dctl); ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); + switch (test_mode) { + case 1: // TEST_J + dctl.b.tstctl = 1; @@ -64131,7 +77342,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + dctl.b.tstctl = 5; + 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); +} + +/** @@ -64143,6 +77354,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + dwc_otg_pcd_ep_t *ep; + dwc_otg_pcd_ep_t *ep0 = &pcd->ep0; + uint16_t *status = pcd->status_buf; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); + +#ifdef DEBUG_EP0 + DWC_DEBUGPL(DBG_PCD, @@ -64154,10 +77366,39 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + + switch (UT_GET_RECIPIENT(ctrl.bmRequestType)) { + case UT_DEVICE: -+ *status = 0x1; /* Self powered */ -+ *status |= pcd->remote_wakeup_enable << 1; -+ break; -+ ++ if(UGETW(ctrl.wIndex) == 0xF000) { /* OTG Status selector */ ++ DWC_PRINTF("wIndex - %d\n", UGETW(ctrl.wIndex)); ++ DWC_PRINTF("OTG VERSION - %d\n", core_if->otg_ver); ++ DWC_PRINTF("OTG CAP - %d, %d\n", ++ core_if->core_params->otg_cap, ++ DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE); ++ if (core_if->otg_ver == 1 ++ && core_if->core_params->otg_cap == ++ DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE) { ++ uint8_t *otgsts = (uint8_t*)pcd->status_buf; ++ *otgsts = (core_if->otg_sts & 0x1); ++ pcd->ep0_pending = 1; ++ ep0->dwc_ep.start_xfer_buff = ++ (uint8_t *) otgsts; ++ ep0->dwc_ep.xfer_buff = (uint8_t *) otgsts; ++ ep0->dwc_ep.dma_addr = ++ pcd->status_buf_dma_handle; ++ ep0->dwc_ep.xfer_len = 1; ++ 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); ++ return; ++ } else { ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ } ++ break; ++ } else { ++ *status = 0x1; /* Self powered */ ++ *status |= pcd->remote_wakeup_enable << 1; ++ break; ++ } + case UT_INTERFACE: + *status = 0; + break; @@ -64232,10 +77473,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + * by a USB Reset? */ + gotgctl.b.devhnpen = 1; + gotgctl.b.hnpreq = 1; -+ dwc_write_reg32(&global_regs->gotgctl, ++ DWC_WRITE_REG32(&global_regs->gotgctl, + gotgctl.d32); + } else { + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; + } + break; + @@ -64248,6 +77490,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + dwc_otg_pcd_update_otg(pcd, 0); + } else { + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; + } + break; + @@ -64260,8 +77503,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + dwc_otg_pcd_update_otg(pcd, 0); + } else { + ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; + } + break; ++ ++ default: ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; ++ + } + do_setup_in_status_phase(pcd); + break; @@ -64309,6 +77558,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + case UF_TEST_MODE: + /** @todo Add CLEAR_FEATURE for TEST modes. */ + break; ++ ++ default: ++ ep0_do_stall(pcd, -DWC_E_NOT_SUPPORTED); ++ return; + } + do_setup_in_status_phase(pcd); + break; @@ -64341,13 +77594,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo +// DWC_DEBUGPL(DBG_PCDV, "SET_ADDRESS:%d\n", ctrl.wValue); +#endif + dcfg.b.devaddr = UGETW(ctrl.wValue); -+ dwc_modify_reg32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32); ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dcfg, 0, dcfg.d32); + do_setup_in_status_phase(pcd); + } +} + +/** -+ * This function processes SETUP commands. In Linux, the USB Command ++ * This function processes SETUP commands. In Linux, the USB Command + * processing is done in two places - the first being the PCD and the + * second in the Gadget Driver (for example, the File-Backed Storage + * Gadget Driver). @@ -64410,6 +77663,22 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + struct cfi_usb_ctrlrequest cfi_req; +#endif + ++ doeptsize0.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[0]->doeptsiz); ++ ++ /** In BDMA more then 1 setup packet is not supported till 3.00a */ ++ if (core_if->dma_enable && core_if->dma_desc_enable == 0 ++ && (doeptsize0.b.supcnt < 2) ++ && (core_if->snpsid < OTG_CORE_REV_2_94a)) { ++ DWC_ERROR ++ ("\n\n----------- CANNOT handle > 1 setup packet in DMA mode\n\n"); ++ } ++ if ((core_if->snpsid >= OTG_CORE_REV_3_00a) ++ && (core_if->dma_enable == 1) && (core_if->dma_desc_enable == 0)) { ++ ctrl = ++ (pcd->setup_pkt + ++ (3 - doeptsize0.b.supcnt - 1 + ++ ep0->dwc_ep.stp_rollover))->req; ++ } +#ifdef DEBUG_EP0 + DWC_DEBUGPL(DBG_PCD, "SETUP %02x.%02x v%04x i%04x l%04x\n", + ctrl.bmRequestType, ctrl.bRequest, @@ -64417,16 +77686,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + UGETW(ctrl.wLength)); +#endif + -+ 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 && 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 */ + dwc_otg_request_nuke(ep0); + ep0->stopped = 0; @@ -64449,7 +77708,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo +#ifdef DWC_UTE_CFI + DWC_MEMCPY(&cfi_req, &ctrl, sizeof(usb_device_request_t)); + -+ //printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n", ctrl.bRequestType, ctrl.bRequest); ++ //printk(KERN_ALERT "CFI: req_type=0x%02x; req=0x%02x\n", ++ ctrl.bRequestType, ctrl.bRequest); + if (UT_GET_TYPE(cfi_req.bRequestType) == UT_VENDOR) { + if (cfi_req.bRequest > 0xB0 && cfi_req.bRequest < 0xBF) { + retval = cfi_setup(pcd, &cfi_req); @@ -64463,8 +77723,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + if (pcd->cfi->need_gadget_att) { + retval = + cfi_gadget_setup(pcd, -+ &pcd->cfi-> -+ ctrl_req); ++ &pcd-> ++ cfi->ctrl_req); + if (retval < 0) { + pcd->ep0_pending = 0; + return; @@ -64547,6 +77807,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + int retval = -DWC_E_NOT_SUPPORTED; +#endif + ++ desc_sts.b.bytes = 0; ++ + if (pcd->ep0_pending && DWC_CIRCLEQ_EMPTY(&ep->queue)) { + if (ep->dwc_ep.is_in) { +#ifdef DEBUG_EP0 @@ -64628,7 +77890,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + || pcd->ep0state == EP0_IN_STATUS_PHASE) { + is_last = 1; + } else if (ep->dwc_ep.is_in) { -+ deptsiz.d32 = dwc_read_reg32(&in_ep_regs->dieptsiz); ++ deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz); + if (core_if->dma_desc_enable != 0) + desc_sts = dev_if->in_desc_addr->status; +#ifdef DEBUG_EP0 @@ -64654,7 +77916,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + } 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, "%d len=%d xsize=%d pktcnt=%d\n", + ep->dwc_ep.num, ep->dwc_ep.xfer_len, + deptsiz.b.xfersize, deptsiz.b.pktcnt); @@ -64668,8 +77930,18 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo +#endif + req->sent_zlp = 0; + } -+ if (core_if->dma_desc_enable == 0) ++ /* For older cores do setup in status phase in Slave/BDMA modes, ++ * starting from 3.00 do that only in slave, and for DMA modes ++ * just re-enable ep 0 OUT here*/ ++ if (core_if->dma_enable == 0 ++ || (core_if->dma_desc_enable == 0 ++ && core_if->snpsid <= OTG_CORE_REV_2_94a)) { + do_setup_in_status_phase(pcd); ++ } else if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ DWC_DEBUGPL(DBG_PCDV, ++ "Enable out ep before in status phase\n"); ++ ep0_out_start(core_if, pcd); ++ } + } + + /* Complete the request */ @@ -64724,7 +77996,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo +#endif + +/** -+ * This function completes the request for the EP. If there are ++ * This function completes the request for the EP. If there are + * additional requests for the EP in the queue they will be started. + */ +static void complete_ep(dwc_otg_pcd_ep_t * ep) @@ -64759,7 +78031,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + 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); ++ deptsiz.d32 = DWC_READ_REG32(&in_ep_regs->dieptsiz); + + if (core_if->dma_enable) { + if (core_if->dma_desc_enable == 0) { @@ -64787,20 +78059,20 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + 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. ++ /* ++ * This fragment of code should initiate 0 ++ * length transfer in case if it is queued ++ * a transfer 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 Descriptor ++ * DMA mode SW is able to initiate a transfer, ++ * which will handle all the packets including ++ * the last 0 length. + */ + ep->dwc_ep.sent_zlp = 0; + dwc_otg_ep_start_zl_transfer @@ -64809,12 +78081,24 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + is_last = 1; + } + } else { -+ DWC_WARN -+ ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n", -+ ep->dwc_ep.num, -+ (ep->dwc_ep.is_in ? "IN" : "OUT"), -+ deptsiz.b.xfersize, -+ deptsiz.b.pktcnt); ++ if (ep->dwc_ep.type == ++ DWC_OTG_EP_TYPE_ISOC) { ++ req->actual = 0; ++ 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); ++ } else ++ DWC_WARN ++ ("Incomplete transfer (%d - %s [siz=%d pkt=%d])\n", ++ ep->dwc_ep.num, ++ (ep->dwc_ep.is_in ? "IN" : "OUT"), ++ deptsiz.b.xfersize, ++ deptsiz.b.pktcnt); + } + } else { + dma_desc = ep->dwc_ep.desc_addr; @@ -64861,32 +78145,31 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + deptsiz.b.xfersize, + deptsiz.b.pktcnt); + -+ /* Check if the whole transfer was completed, ++ /* 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 ++ /* ++ * 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 ++ * 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); ++ &ep->dwc_ep); + } else { + is_last = 1; + } @@ -64922,22 +78205,53 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + + for (i = 0; i < ep->dwc_ep.desc_cnt; + ++i) { -+ desc_sts = dma_desc->status; -+ byte_count += desc_sts.b.bytes; -+ dma_desc++; -+ } ++ desc_sts = dma_desc->status; ++ byte_count += desc_sts.b.bytes; ++ dma_desc++; ++ } + +#ifdef DWC_UTE_CFI + } +#endif -+ ep->dwc_ep.xfer_count = ep->dwc_ep.total_len -+ - byte_count + -+ ((4 - (ep->dwc_ep.total_len & 0x3)) & 0x3); -+ is_last = 1; ++ /* Checking for interrupt Out transfers with not ++ * dword aligned mps sizes ++ */ ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_INTR && ++ (ep->dwc_ep.maxpacket%4)) { ++ ep->dwc_ep.xfer_count = ++ ep->dwc_ep.total_len - byte_count; ++ if ((ep->dwc_ep.xfer_len % ++ ep->dwc_ep.maxpacket) ++ && (ep->dwc_ep.xfer_len / ++ ep->dwc_ep.maxpacket < ++ MAX_DMA_DESC_CNT)) ++ ep->dwc_ep.xfer_len -= ++ (ep->dwc_ep.desc_cnt - ++ 1) * ep->dwc_ep.maxpacket + ++ ep->dwc_ep.xfer_len % ++ ep->dwc_ep.maxpacket; ++ else ++ ep->dwc_ep.xfer_len -= ++ ep->dwc_ep.desc_cnt * ++ ep->dwc_ep.maxpacket; ++ if (ep->dwc_ep.xfer_len > 0) { ++ dwc_otg_ep_start_transfer ++ (core_if, &ep->dwc_ep); ++ } else { ++ is_last = 1; ++ } ++ } else { ++ 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); ++ DWC_READ_REG32(&out_ep_regs->doeptsiz); + + byte_count = (ep->dwc_ep.xfer_len - + ep->dwc_ep.xfer_count - @@ -64946,57 +78260,56 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + ep->dwc_ep.dma_addr += byte_count; + ep->dwc_ep.xfer_count += byte_count; + -+ /* Check if the whole transfer was completed, ++ /* 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 ++ /* ++ * 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 ++ * 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); ++ &ep->dwc_ep); + } else { + is_last = 1; + } + } + } else { -+ /* Check if the whole transfer was completed, ++ /* 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. ++ /* ++ * This fragment of code should initiate 0 ++ * length transfer in case if it is queued ++ * a transfer 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 Descriptor ++ * DMA mode SW is able to initiate a transfer, ++ * which will handle all the packets including ++ * the last 0 length. + */ + ep->dwc_ep.sent_zlp = 0; + dwc_otg_ep_start_zl_transfer(core_if, @@ -65021,10 +78334,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + req->actual = ep->dwc_ep.cfi_req_len - byte_count; + } else { +#endif -+ req->actual = ep->dwc_ep.xfer_count; ++ req->actual = ep->dwc_ep.xfer_count; +#ifdef DWC_UTE_CFI + } +#endif ++ if (req->dw_align_buf) { ++ if (!ep->dwc_ep.is_in) { ++ dwc_memcpy(req->buf, req->dw_align_buf, req->length); ++ } ++ DWC_DMA_FREE(req->length, req->dw_align_buf, ++ req->dw_align_buf_dma); ++ } + + dwc_otg_request_done(ep, req, 0); + @@ -65073,14 +78393,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + + if (dwc_ep->is_in == 0) { + addr = -+ &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]-> -+ doepctl; ++ &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); ++ DWC_MODIFY_REG32(addr, depctl.d32, depctl.d32); +} + +/** @@ -65103,13 +78423,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + + if (ep->is_in) { + deptsiz.d32 = -+ dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]-> -+ dieptsiz); ++ 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); ++ 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))); @@ -65163,8 +78483,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + 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 - ++ 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 - @@ -65190,8 +78510,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + iso_packet->length = + data_per_desc - + sts.b_iso_out.rxbytes + (4 - -+ dwc_ep-> -+ data_per_frame ++ dwc_ep->data_per_frame + % 4); + } + @@ -65345,8 +78664,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + 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 - ++ 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 - @@ -65447,8 +78766,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + int i; + + deptsiz.d32 = -+ dwc_read_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]-> -+ doeptsiz); ++ 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); @@ -65469,7 +78788,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + deptsiz.b.pktcnt = 0; + } + -+ dwc_write_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz, ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz, + deptsiz.d32); + + if (deptsiz.b.pktcnt > 0) { @@ -65483,16 +78802,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + deptsiz.b.xfersize;; + } + -+ dwc_write_reg32(&core_if->dev_if->out_ep_regs[dwc_ep->num]-> -+ doepdma, dma_addr); ++ 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); ++ DWC_MODIFY_REG32(&core_if->dev_if-> ++ out_ep_regs[dwc_ep->num]->doepctl, depctl.d32, ++ depctl.d32); + return 0; + } else { + return 1; @@ -65525,11 +78845,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + + if (ep->is_in) { + deptsiz.d32 = -+ dwc_read_reg32(&core_if->dev_if->in_ep_regs[ep->num]-> ++ 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]-> ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[ep->num]-> + doeptsiz); + } + @@ -65539,8 +78859,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + 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 ++ /* 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 */ @@ -65558,11 +78878,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + } + 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 ++ /* 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 ++ * 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. @@ -65588,7 +78908,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + dwc_ep_t *dwc_ep = &ep->dwc_ep; + uint8_t is_last = 0; + -+ if(ep->dwc_ep.next_frame == 0xffffffff) { ++ if (ep->dwc_ep.next_frame == 0xffffffff) { + DWC_WARN("Next frame is not set!\n"); + return; + } @@ -65651,12 +78971,64 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + if (is_last) + dwc_otg_iso_buffer_done(pcd, ep, ep->iso_req_handle); +} -+#endif /* DWC_EN_ISOC */ ++#endif /* DWC_EN_ISOC */ ++ ++/** ++ * This function handle BNA interrupt for Non Isochronous EPs ++ * ++ */ ++static void dwc_otg_pcd_handle_noniso_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_dev_dma_desc_t *dma_desc; ++ dev_dma_desc_sts_t sts = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if = ep->pcd->core_if; ++ int i, start; ++ ++ if (!dwc_ep->desc_cnt) ++ DWC_WARN("Ep%d %s Descriptor count = %d \n", dwc_ep->num, ++ (dwc_ep->is_in ? "IN" : "OUT"), dwc_ep->desc_cnt); ++ ++ if (core_if->core_params->cont_on_bna && !dwc_ep->is_in ++ && dwc_ep->type != DWC_OTG_EP_TYPE_CONTROL) { ++ uint32_t doepdma; ++ dwc_otg_dev_out_ep_regs_t *out_regs = ++ core_if->dev_if->out_ep_regs[dwc_ep->num]; ++ doepdma = DWC_READ_REG32(&(out_regs->doepdma)); ++ start = (doepdma - dwc_ep->dma_desc_addr)/sizeof(dwc_otg_dev_dma_desc_t); ++ dma_desc = &(dwc_ep->desc_addr[start]); ++ } else { ++ start = 0; ++ dma_desc = dwc_ep->desc_addr; ++ } ++ ++ ++ for (i = start; i < dwc_ep->desc_cnt; ++i, ++dma_desc) { ++ sts.d32 = dma_desc->status.d32; ++ sts.b.bs = BS_HOST_READY; ++ dma_desc->status.d32 = sts.d32; ++ } ++ ++ 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; ++ depctl.b.cnak = 1; ++ DWC_MODIFY_REG32(addr, 0, depctl.d32); ++} + +/** + * This function handles EP0 Control transfers. + * -+ * The state of the control tranfers are tracked in ++ * The state of the control transfers are tracked in + * ep0state. + */ +static void handle_ep0(dwc_otg_pcd_t * pcd) @@ -65701,8 +79073,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + */ + if (core_if->dma_desc_enable == 0) { + deptsiz.d32 = -+ dwc_read_reg32(&core_if->dev_if-> -+ in_ep_regs[0]->dieptsiz); ++ DWC_READ_REG32(&core_if-> ++ dev_if->in_ep_regs[0]-> ++ dieptsiz); + byte_count = + ep0->dwc_ep.xfer_len - deptsiz.b.xfersize; + } else { @@ -65723,7 +79096,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + 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"); ++ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n"); + } else { + ep0_complete_request(ep0); + DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); @@ -65738,8 +79111,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + 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); ++ DWC_READ_REG32(&core_if-> ++ dev_if->out_ep_regs[0]-> ++ doeptsiz); + byte_count = + ep0->dwc_ep.maxpacket - deptsiz.b.xfersize; + } else { @@ -65760,7 +79134,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + 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"); ++ DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER sent zlp\n"); + } else { + ep0_complete_request(ep0); + DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); @@ -65806,12 +79180,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { + return; + } -+#endif /* DWC_EN_ISOC */ ++#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); ++ 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, @@ -65845,6 +79219,177 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + } +} + ++/* ++ * This function create new nextep sequnce based on Learn Queue. ++ * ++ * @param core_if Programming view of DWC_otg controller ++ */ ++void predict_nextep_seq( 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; ++ /* Number of Token Queue Registers */ ++ const int DTKNQ_REG_CNT = (TOKEN_Q_DEPTH + 7) / 8; ++ dtknq1_data_t dtknqr1; ++ uint32_t in_tkn_epnums[4]; ++ uint8_t seqnum[MAX_EPS_CHANNELS]; ++ uint8_t intkn_seq[TOKEN_Q_DEPTH]; ++ grstctl_t resetctl = {.d32 = 0 }; ++ uint8_t temp; ++ int ndx = 0; ++ int start = 0; ++ int end = 0; ++ int sort_done = 0; ++ int i = 0; ++ volatile uint32_t *addr = &dev_global_regs->dtknqr1; ++ ++ ++ DWC_DEBUGPL(DBG_PCD,"dev_token_q_depth=%d\n",TOKEN_Q_DEPTH); ++ ++ /* Read the DTKNQ Registers */ ++ for (i = 0; i < DTKNQ_REG_CNT; i++) { ++ 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) { ++ addr = &dev_global_regs->dtknqr3_dthrctl; ++ } else { ++ ++addr; ++ } ++ ++ } ++ ++ /* Copy the DTKNQR1 data to the bit field. */ ++ dtknqr1.d32 = in_tkn_epnums[0]; ++ if (dtknqr1.b.wrap_bit) { ++ ndx = dtknqr1.b.intknwptr; ++ end = ndx -1; ++ if (end < 0) ++ end = TOKEN_Q_DEPTH -1; ++ } else { ++ ndx = 0; ++ end = dtknqr1.b.intknwptr -1; ++ if (end < 0) ++ end = 0; ++ } ++ start = ndx; ++ ++ /* Fill seqnum[] by initial values: EP number + 31 */ ++ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { ++ seqnum[i] = i +31; ++ } ++ ++ /* Fill intkn_seq[] from in_tkn_epnums[0] */ ++ for (i=0; i < 6; i++) ++ intkn_seq[i] = (in_tkn_epnums[0] >> ((7-i) * 4)) & 0xf; ++ ++ if (TOKEN_Q_DEPTH > 6) { ++ /* Fill intkn_seq[] from in_tkn_epnums[1] */ ++ for (i=6; i < 14; i++) ++ intkn_seq[i] = ++ (in_tkn_epnums[1] >> ((7 - (i - 6)) * 4)) & 0xf; ++ } ++ ++ if (TOKEN_Q_DEPTH > 14) { ++ /* Fill intkn_seq[] from in_tkn_epnums[1] */ ++ for (i=14; i < 22; i++) ++ intkn_seq[i] = ++ (in_tkn_epnums[2] >> ((7 - (i - 14)) * 4)) & 0xf; ++ } ++ ++ if (TOKEN_Q_DEPTH > 22) { ++ /* Fill intkn_seq[] from in_tkn_epnums[1] */ ++ for (i=22; i < 30; i++) ++ intkn_seq[i] = ++ (in_tkn_epnums[3] >> ((7 - (i - 22)) * 4)) & 0xf; ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s start=%d end=%d intkn_seq[]:\n", __func__, ++ start, end); ++ for (i=0; idev_if->num_in_eps; i++) { ++ if (core_if->nextep_seq[i] == 0xff ) ++ seqnum[i] = 0xff; ++ } ++ ++ /* Sort seqnum[] */ ++ sort_done = 0; ++ while (!sort_done) { ++ sort_done = 1; ++ for (i=0; idev_if->num_in_eps; i++) { ++ if (seqnum[i] > seqnum[i+1]) { ++ temp = seqnum[i]; ++ seqnum[i] = seqnum[i+1]; ++ seqnum[i+1] = temp; ++ sort_done = 0; ++ } ++ } ++ } ++ ++ ndx = start + seqnum[0]; ++ if (ndx >= TOKEN_Q_DEPTH) ++ ndx = ndx % TOKEN_Q_DEPTH; ++ core_if->first_in_nextep_seq = intkn_seq[ndx]; ++ ++ /* Update seqnum[] by EP numbers */ ++ for (i=0; i<=core_if->dev_if->num_in_eps; i++) { ++ ndx = start + i; ++ if (seqnum[i] < 31) { ++ ndx = start + seqnum[i]; ++ if (ndx >= TOKEN_Q_DEPTH) ++ ndx = ndx % TOKEN_Q_DEPTH; ++ seqnum[i] = intkn_seq[ndx]; ++ } else { ++ if (seqnum[i] < 0xff) { ++ seqnum[i] = seqnum[i] - 31; ++ } else { ++ break; ++ } ++ } ++ } ++ ++ /* Update nextep_seq[] based on seqnum[] */ ++ for (i=0; idev_if->num_in_eps; i++) { ++ if (seqnum[i] != 0xff) { ++ if (seqnum[i+1] != 0xff) { ++ core_if->nextep_seq[seqnum[i]] = seqnum[i+1]; ++ } else { ++ core_if->nextep_seq[seqnum[i]] = core_if->first_in_nextep_seq; ++ break; ++ } ++ } else { ++ break; ++ } ++ } ++ ++ DWC_DEBUGPL(DBG_PCDV, "%s first_in_nextep_seq= %2d; nextep_seq[]:\n", ++ __func__, core_if->first_in_nextep_seq); ++ for (i=0; i <= core_if->dev_if->num_in_eps; i++) { ++ DWC_DEBUGPL(DBG_PCDV,"%2d\n", core_if->nextep_seq[i]); ++ } ++ ++ /* Flush the Learning Queue */ ++ resetctl.d32 = DWC_READ_REG32(&core_if->core_global_regs->grstctl); ++ resetctl.b.intknqflsh = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32); ++ ++ ++} ++ +/** + * handle the IN EP disable interrupt. + */ @@ -65857,40 +79402,136 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + dctl_data_t dctl = {.d32 = 0 }; + dwc_otg_pcd_ep_t *ep; + dwc_ep_t *dwc_ep; -+ ++ gintmsk_data_t gintmsk_data; ++ depctl_data_t depctl; ++ uint32_t diepdma; ++ uint32_t remain_to_transfer = 0; ++ uint8_t i; ++ uint32_t xfer_size; ++ + ep = get_in_ep(pcd, epnum); + dwc_ep = &ep->dwc_ep; + + if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { + dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num); ++ complete_ep(ep); + 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_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl)); ++ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->dieptsiz); ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); + + DWC_DEBUGPL(DBG_ANY, "pktcnt=%d size=%d\n", + dieptsiz.b.pktcnt, dieptsiz.b.xfersize); ++ ++ if ((core_if->start_predict == 0) || (depctl.b.eptype & 1)) { ++ if (ep->stopped) { ++ if (core_if->en_multiple_tx_fifo) ++ /* Flush the Tx FIFO */ ++ 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, dctl.d32); ++ /* Restart the transaction */ ++ if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { ++ restart_transfer(pcd, epnum); ++ } ++ } else { ++ /* Restart the transaction */ ++ if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { ++ restart_transfer(pcd, epnum); ++ } ++ DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n"); ++ } ++ return; ++ } + -+ if (ep->stopped) { -+ /* Flush the Tx FIFO */ -+ dwc_otg_flush_tx_fifo(core_if, dwc_ep->tx_fifo_num); -+ /* Clear the Global IN NP NAK */ ++ if (core_if->start_predict > 2) { // NP IN EP ++ core_if->start_predict--; ++ return; ++ } ++ ++ core_if->start_predict--; ++ ++ if (core_if->start_predict == 1) { // All NP IN Ep's disabled now ++ ++ predict_nextep_seq(core_if); ++ ++ /* Update all active IN EP's NextEP field based of nextep_seq[] */ ++ for ( i = 0; i <= core_if->dev_if->num_in_eps; i++) { ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (core_if->nextep_seq[i] != 0xff) { // Active NP IN EP ++ depctl.b.nextep = core_if->nextep_seq[i]; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); ++ } ++ } ++ /* Flush Shared NP TxFIFO */ ++ dwc_otg_flush_tx_fifo(core_if, 0); ++ /* Rewind buffers */ ++ if (!core_if->dma_desc_enable) { ++ i = core_if->first_in_nextep_seq; ++ do { ++ ep = get_in_ep(pcd, i); ++ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz); ++ xfer_size = ep->dwc_ep.total_len - ep->dwc_ep.xfer_count; ++ if (xfer_size > ep->dwc_ep.maxxfer) ++ xfer_size = ep->dwc_ep.maxxfer; ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (dieptsiz.b.pktcnt != 0) { ++ if (xfer_size == 0) { ++ remain_to_transfer = 0; ++ } else { ++ if ((xfer_size % ep->dwc_ep.maxpacket) == 0) { ++ remain_to_transfer = ++ dieptsiz.b.pktcnt * ep->dwc_ep.maxpacket; ++ } else { ++ remain_to_transfer = ((dieptsiz.b.pktcnt -1) * ep->dwc_ep.maxpacket) ++ + (xfer_size % ep->dwc_ep.maxpacket); ++ } ++ } ++ diepdma = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepdma); ++ dieptsiz.b.xfersize = remain_to_transfer; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, dieptsiz.d32); ++ diepdma = ep->dwc_ep.dma_addr + (xfer_size - remain_to_transfer); ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, diepdma); ++ } ++ i = core_if->nextep_seq[i]; ++ } while (i != core_if->first_in_nextep_seq); ++ } else { // dma_desc_enable ++ DWC_PRINTF("%s Learning Queue not supported in DDMA\n", __func__); ++ } ++ ++ /* Restart transfers in predicted sequences */ ++ i = core_if->first_in_nextep_seq; ++ do { ++ dieptsiz.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz); ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (dieptsiz.b.pktcnt != 0) { ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ depctl.b.epena = 1; ++ depctl.b.cnak = 1; ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32); ++ } ++ i = core_if->nextep_seq[i]; ++ } while (i != core_if->first_in_nextep_seq); ++ ++ /* Clear the global non-periodic IN NAK handshake */ + dctl.d32 = 0; + dctl.b.cgnpinnak = 1; -+ dwc_modify_reg32(&dev_if->dev_global_regs->dctl, dctl.d32, 0); -+ /* Restart the transaction */ -+ if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { -+ restart_transfer(pcd, epnum); -+ } -+ } else { -+ /* Restart the transaction */ -+ if (dieptsiz.b.pktcnt != 0 || dieptsiz.b.xfersize != 0) { -+ restart_transfer(pcd, epnum); -+ } -+ DWC_DEBUGPL(DBG_ANY, "STOPPED!!!\n"); -+ } ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ ++ /* Unmask EP Mismatch interrupt */ ++ gintmsk_data.d32 = 0; ++ gintmsk_data.b.epmismatch = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk_data.d32); ++ ++ core_if->start_predict = 0; ++ ++ } +} + +/** @@ -65916,7 +79557,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + /* Disable the NP Tx Fifo Empty Interrrupt */ + if (!core_if->dma_enable) { + intr_mask.b.nptxfempty = 1; -+ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, + intr_mask.d32, 0); + } + /** @todo NGS Check EP type. @@ -65926,16 +79567,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + */ + /* Enable the Global IN NAK Effective Interrupt */ + intr_mask.b.ginnakeff = 1; -+ dwc_modify_reg32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32); ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, intr_mask.d32); + + /* Set Global IN NAK */ + dctl.b.sgnpinnak = 1; -+ dwc_modify_reg32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); ++ DWC_MODIFY_REG32(&dev_if->dev_global_regs->dctl, dctl.d32, dctl.d32); + + ep->stopped = 1; + +#ifdef DEBUG -+ dieptsiz.d32 = dwc_read_reg32(&dev_if->in_ep_regs[num]->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); +#endif @@ -65947,7 +79588,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + */ + diepctl.d32 = 0; + diepctl.b.snak = 1; -+ dwc_modify_reg32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32, ++ DWC_MODIFY_REG32(&dev_if->in_ep_regs[num]->diepctl, diepctl.d32, + diepctl.d32); + ep->disabling = 1; + ep->stopped = 1; @@ -65955,7 +79596,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo +} + +/** -+ * Handler for the IN EP NAK interrupt. ++ * 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) @@ -65969,10 +79610,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + intr_mask.b.nak = 1; + + if (core_if->multiproc_int_enable) { -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> ++ 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, ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->diepmsk, + intr_mask.d32, 0); + } + @@ -65980,7 +79621,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo +} + +/** -+ * Handler for the OUT EP Babble interrupt. ++ * 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) @@ -65995,10 +79636,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + intr_mask.b.babble = 1; + + if (core_if->multiproc_int_enable) { -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> ++ 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, ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, + intr_mask.d32, 0); + } + @@ -66006,7 +79647,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo +} + +/** -+ * Handler for the OUT EP NAK interrupt. ++ * 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) @@ -66015,15 +79656,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + dwc_otg_core_if_t *core_if; + doepmsk_data_t intr_mask = {.d32 = 0 }; + -+ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", "OUT EP NAK"); ++ DWC_DEBUGPL(DBG_ANY, "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-> ++ 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, ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, + intr_mask.d32, 0); + } + @@ -66031,7 +79672,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo +} + +/** -+ * Handler for the OUT EP NYET interrupt. ++ * 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) @@ -66045,10 +79686,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + intr_mask.b.nyet = 1; + + if (core_if->multiproc_int_enable) { -+ dwc_modify_reg32(&core_if->dev_if->dev_global_regs-> ++ 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, ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, + intr_mask.d32, 0); + } + @@ -66077,14 +79718,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo +do { \ + diepint_data_t diepint = {.d32=0}; \ + diepint.b.__intr = 1; \ -+ dwc_write_reg32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \ ++ DWC_WRITE_REG32(&__core_if->dev_if->in_ep_regs[__epnum]->diepint, \ + diepint.d32); \ +} while (0) + + 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 }; -+ dctl_data_t dctl = {.d32 = 0 }; + depctl_data_t depctl = {.d32 = 0 }; + uint32_t ep_intr; + uint32_t epnum = 0; @@ -66106,10 +79746,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + dwc_ep = &ep->dwc_ep; + + depctl.d32 = -+ dwc_read_reg32(&dev_if->in_ep_regs[epnum]->diepctl); ++ DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); + empty_msk = -+ dwc_read_reg32(&dev_if->dev_global_regs-> -+ dtknqr4_fifoemptymsk); ++ DWC_READ_REG32(&dev_if-> ++ dev_global_regs->dtknqr4_fifoemptymsk); + + DWC_DEBUGPL(DBG_PCDV, + "IN EP INTERRUPT - %d\nepmty_msk - %8x diepctl - %8x\n", @@ -66129,20 +79769,18 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + /* Transfer complete */ + if (diepint.b.xfercompl) { + /* Disable the NP Tx FIFO Empty -+ * Interrrupt */ ++ * Interrupt */ + 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 { + /* Disable the Tx FIFO Empty Interrupt for this EP */ + uint32_t fifoemptymsk = + 0x1 << dwc_ep->num; -+ dwc_modify_reg32(&core_if->dev_if-> -+ dev_global_regs-> -+ dtknqr4_fifoemptymsk, ++ DWC_MODIFY_REG32(&core_if-> ++ dev_if->dev_global_regs->dtknqr4_fifoemptymsk, + fifoemptymsk, 0); + } + /* Clear the bit in DIEPINTn for this interrupt */ @@ -66157,10 +79795,27 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + if (!ep->stopped) + complete_iso_ep(pcd, ep); + } -+#endif /* DWC_EN_ISOC */ ++#endif /* DWC_EN_ISOC */ ++#ifdef DWC_UTE_PER_IO ++ else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (!ep->stopped) ++ complete_xiso_ep(ep); ++ } ++#endif /* DWC_UTE_PER_IO */ + else { -+ ++ if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC && ++ dwc_ep->bInterval > 1) { ++ dwc_ep->frame_num += dwc_ep->bInterval; ++ if (dwc_ep->frame_num > 0x3FFF) ++ { ++ dwc_ep->frm_overrun = 1; ++ dwc_ep->frame_num &= 0x3FFF; ++ } else ++ dwc_ep->frm_overrun = 0; ++ } + complete_ep(ep); ++ if(diepint.b.nak) ++ CLEAR_IN_EP_INTR(core_if, epnum, nak); + } + } + /* Endpoint disable */ @@ -66174,15 +79829,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + } + /* AHB Error */ + if (diepint.b.ahberr) { -+ DWC_DEBUGPL(DBG_ANY, "EP%d IN AHB Error\n", -+ epnum); ++ DWC_ERROR("EP%d IN AHB Error\n", epnum); + /* Clear the bit in DIEPINTn for this interrupt */ + CLEAR_IN_EP_INTR(core_if, epnum, ahberr); + } + /* TimeOUT Handshake (non-ISOC IN EPs) */ + if (diepint.b.timeout) { -+ DWC_DEBUGPL(DBG_ANY, "EP%d IN Time-out\n", -+ epnum); ++ DWC_ERROR("EP%d IN Time-out\n", epnum); + handle_in_ep_timeout_intr(pcd, epnum); + + CLEAR_IN_EP_INTR(core_if, epnum, timeout); @@ -66198,18 +79851,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + diepmsk.b.intktxfemp = 1; + + if (core_if->multiproc_int_enable) { -+ dwc_modify_reg32(&dev_if-> -+ dev_global_regs-> -+ diepeachintmsk -+ [epnum], -+ diepmsk.d32, -+ 0); ++ 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); ++ DWC_MODIFY_REG32 ++ (&dev_if->dev_global_regs->diepmsk, ++ diepmsk.d32, 0); + } + } else if (core_if->dma_desc_enable + && epnum == 0 @@ -66217,18 +79865,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + EP0_OUT_STATUS_PHASE) { + // EP0 IN set STALL + depctl.d32 = -+ dwc_read_reg32(&dev_if-> -+ in_ep_regs[epnum]-> -+ diepctl); ++ 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); ++ DWC_WRITE_REG32(&dev_if->in_ep_regs ++ [epnum]->diepctl, ++ depctl.d32); + } + CLEAR_IN_EP_INTR(core_if, epnum, intktxfemp); + } @@ -66236,7 +79883,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + if (diepint.b.intknepmis) { + DWC_DEBUGPL(DBG_ANY, + "EP%d IN TKN EP Mismatch\n", epnum); -+ CLEAR_IN_EP_INTR(core_if, epnum, intknepmis); ++ CLEAR_IN_EP_INTR(core_if, epnum, intknepmis); + } + /** IN Endpoint NAK Effective */ + if (diepint.b.inepnakeff) { @@ -66248,9 +79895,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + depctl.d32 = 0; + depctl.b.snak = 1; + depctl.b.epdis = 1; -+ dwc_modify_reg32(&dev_if-> -+ in_ep_regs[epnum]-> -+ diepctl, depctl.d32, ++ DWC_MODIFY_REG32(&dev_if->in_ep_regs ++ [epnum]->diepctl, ++ depctl.d32, + depctl.d32); + } + CLEAR_IN_EP_INTR(core_if, epnum, inepnakeff); @@ -66276,35 +79923,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + if (dwc_ep->type == + DWC_OTG_EP_TYPE_ISOC) { + /* -+ * This checking is performed to prevent first "false" BNA -+ * handling occuring right after reconnect ++ * 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); ++ 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); -+ } ++ dwc_otg_pcd_handle_noniso_bna(ep); + } + } + } @@ -66312,7 +79940,31 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + if (diepint.b.nak) { + DWC_DEBUGPL(DBG_ANY, "EP%d IN NAK Interrupt\n", + epnum); -+ handle_in_ep_nak_intr(pcd, epnum); ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ depctl_data_t depctl; ++ if (ep->dwc_ep.frame_num == 0xFFFFFFFF) { ++ ep->dwc_ep.frame_num = core_if->frame_num; ++ if (ep->dwc_ep.bInterval > 1) { ++ depctl.d32 = 0; ++ depctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[epnum]->diepctl); ++ if (ep->dwc_ep.frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ depctl.b.setd0pid = 0; ++ } else { ++ depctl.b.setd0pid = 1; ++ depctl.b.setd1pid = 0; ++ } ++ DWC_WRITE_REG32(&dev_if->in_ep_regs[epnum]->diepctl, depctl.d32); ++ } ++ start_next_request(ep); ++ } ++ ep->dwc_ep.frame_num += ep->dwc_ep.bInterval; ++ if (dwc_ep->frame_num > 0x3FFF) { ++ dwc_ep->frm_overrun = 1; ++ dwc_ep->frame_num &= 0x3FFF; ++ } else ++ dwc_ep->frm_overrun = 0; ++ } + + CLEAR_IN_EP_INTR(core_if, epnum, nak); + } @@ -66344,19 +79996,19 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo +do { \ + doepint_data_t doepint = {.d32=0}; \ + doepint.b.__intr = 1; \ -+ dwc_write_reg32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \ ++ DWC_WRITE_REG32(&__core_if->dev_if->out_ep_regs[__epnum]->doepint, \ + doepint.d32); \ +} while (0) + + 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; ++ dctl_data_t dctl = {.d32 = 0 }; ++ gintmsk_data_t gintmsk = {.d32 = 0 }; ++ + + DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__); + @@ -66377,17 +80029,290 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo +#endif + doepint.d32 = + dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep); -+ ++ /* Moved this interrupt upper due to core deffect of asserting ++ * OUT EP 0 xfercompl along with stsphsrcvd in BDMA */ ++ if (doepint.b.stsphsercvd) { ++ deptsiz0_data_t deptsiz; ++ CLEAR_OUT_EP_INTR(core_if, epnum, stsphsercvd); ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doeptsiz); ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a ++ && core_if->dma_enable ++ && core_if->dma_desc_enable == 0 ++ && doepint.b.xfercompl ++ && deptsiz.b.xfersize == 24) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, ++ xfercompl); ++ doepint.b.xfercompl = 0; ++ ep0_out_start(core_if, pcd); ++ } ++ if ((core_if->dma_desc_enable) || ++ (core_if->dma_enable ++ && core_if->snpsid >= ++ OTG_CORE_REV_3_00a)) { ++ do_setup_in_status_phase(pcd); ++ } ++ } + /* Transfer complete */ + if (doepint.b.xfercompl) { + + if (epnum == 0) { + /* Clear the bit in DOEPINTn for this interrupt */ -+ CLEAR_OUT_EP_INTR(core_if, epnum, -+ xfercompl); ++ CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl); ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a) { ++ DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n", ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepint), ++ doepint.d32); ++ DWC_DEBUGPL(DBG_PCDV, "DOEPCTL=%x \n", ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[0]->doepctl)); ++ ++ if (core_if->snpsid >= OTG_CORE_REV_3_00a ++ && core_if->dma_enable == 0) { ++ doepint_data_t doepint; ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepint); ++ if (pcd->ep0state == EP0_IDLE && doepint.b.sr) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, sr); ++ goto exit_xfercompl; ++ } ++ } ++ /* In case of DDMA look at SR bit to go to the Data Stage */ ++ if (core_if->dma_desc_enable) { ++ dev_dma_desc_sts_t status = {.d32 = 0}; ++ if (pcd->ep0state == EP0_IDLE) { ++ status.d32 = core_if->dev_if->setup_desc_addr[core_if-> ++ dev_if->setup_desc_index]->status.d32; ++ if(pcd->data_terminated) { ++ pcd->data_terminated = 0; ++ status.d32 = core_if->dev_if->out_desc_addr->status.d32; ++ dwc_memcpy(&pcd->setup_pkt->req, pcd->backup_buf, 8); ++ } ++ if (status.b.sr) { ++ if (doepint.b.setup) { ++ DWC_DEBUGPL(DBG_PCDV, "DMA DESC EP0_IDLE SR=1 setup=1\n"); ++ /* Already started data stage, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ /* Prepare for more setup packets */ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE || ++ pcd->ep0state == EP0_IN_DATA_PHASE) { ++ ep0_out_start(core_if, pcd); ++ } ++ ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ DWC_DEBUGPL(DBG_PCDV, ++ "EP0_IDLE SR=1 setup=0 new setup comes\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ } else { ++ dwc_otg_pcd_request_t *req; ++ dev_dma_desc_sts_t status = {.d32 = 0}; ++ diepint_data_t diepint0; ++ diepint0.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ ++ if (pcd->ep0state == EP0_STALL || pcd->ep0state == EP0_DISCONNECT) { ++ DWC_ERROR("EP0 is stalled/disconnected\n"); ++ } ++ ++ /* Clear IN xfercompl if set */ ++ if (diepint0.b.xfercompl && (pcd->ep0state == EP0_IN_STATUS_PHASE ++ || pcd->ep0state == EP0_IN_DATA_PHASE)) { ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint, diepint0.d32); ++ } ++ ++ status.d32 = core_if->dev_if->setup_desc_addr[core_if-> ++ dev_if->setup_desc_index]->status.d32; ++ ++ if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len ++ && (pcd->ep0state == EP0_OUT_DATA_PHASE)) ++ status.d32 = core_if->dev_if->out_desc_addr->status.d32; ++ if (pcd->ep0state == EP0_OUT_STATUS_PHASE) ++ status.d32 = status.d32 = core_if->dev_if-> ++ out_desc_addr->status.d32; ++ ++ if (status.b.sr) { ++ if (DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n"); ++ } else { ++ DWC_DEBUGPL(DBG_PCDV, "complete req!!\n"); ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len && ++ pcd->ep0state == EP0_OUT_DATA_PHASE) { ++ /* Read arrived setup packet from req->buf */ ++ dwc_memcpy(&pcd->setup_pkt->req, ++ req->buf + ep->dwc_ep.xfer_count, 8); ++ } ++ req->actual = ep->dwc_ep.xfer_count; ++ dwc_otg_request_done(ep, req, -ECONNRESET); ++ ep->dwc_ep.start_xfer_buff = 0; ++ ep->dwc_ep.xfer_buff = 0; ++ ep->dwc_ep.xfer_len = 0; ++ } ++ pcd->ep0state = EP0_IDLE; ++ if (doepint.b.setup) { ++ DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n"); ++ /* Data stage started, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ /* Prepare for setup packets if ep0in was enabled*/ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ ep0_out_start(core_if, pcd); ++ } ++ ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ DWC_DEBUGPL(DBG_PCDV, ++ "EP0_IDLE SR=1 setup=0 new setup comes 2\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ } ++ } ++ if (core_if->snpsid >= OTG_CORE_REV_2_94a && core_if->dma_enable ++ && core_if->dma_desc_enable == 0) { ++ doepint_data_t doepint_temp = {.d32 = 0}; ++ deptsiz0_data_t doeptsize0 = {.d32 = 0 }; ++ doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->dwc_ep.num]->doepint); ++ doeptsize0.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->dwc_ep.num]->doeptsiz); ++ if (pcd->ep0state == EP0_IDLE) { ++ if (doepint_temp.b.sr) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, sr); ++ } ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepint); ++ if (doeptsize0.b.supcnt == 3) { ++ DWC_DEBUGPL(DBG_ANY, "Rolling over!!!!!!!\n"); ++ ep->dwc_ep.stp_rollover = 1; ++ } ++ if (doepint.b.setup) { ++retry: ++ /* Already started data stage, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ ep->dwc_ep.stp_rollover = 0; ++ /* Prepare for more setup packets */ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE || ++ pcd->ep0state == EP0_IN_DATA_PHASE) { ++ ep0_out_start(core_if, pcd); ++ } ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ DWC_DEBUGPL(DBG_ANY, ++ "EP0_IDLE SR=1 setup=0 new setup comes\n"); ++ doepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[0]->doepint); ++ if(doepint.b.setup) ++ goto retry; ++ ep0_out_start(core_if, pcd); ++ } ++ } else { ++ dwc_otg_pcd_request_t *req; ++ diepint_data_t diepint0 = {.d32 = 0}; ++ doepint_data_t doepint_temp = {.d32 = 0}; ++ depctl_data_t diepctl0; ++ diepint0.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ diepctl0.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepctl); ++ ++ if (pcd->ep0state == EP0_IN_DATA_PHASE ++ || pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ if (diepint0.b.xfercompl) { ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint, diepint0.d32); ++ } ++ if (diepctl0.b.epena) { ++ diepint_data_t diepint = {.d32 = 0}; ++ diepctl0.b.snak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepctl, diepctl0.d32); ++ do { ++ dwc_udelay(10); ++ diepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ } while (!diepint.b.inepnakeff); ++ diepint.b.inepnakeff = 1; ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint, diepint.d32); ++ diepctl0.d32 = 0; ++ diepctl0.b.epdis = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepctl, ++ diepctl0.d32); ++ do { ++ dwc_udelay(10); ++ diepint.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ in_ep_regs[0]->diepint); ++ } while (!diepint.b.epdisabled); ++ diepint.b.epdisabled = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->in_ep_regs[0]->diepint, ++ diepint.d32); ++ } ++ } ++ doepint_temp.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[ep->dwc_ep.num]->doepint); ++ if (doepint_temp.b.sr) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, sr); ++ if (DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ DWC_DEBUGPL(DBG_PCDV, "Request queue empty!!\n"); ++ } else { ++ DWC_DEBUGPL(DBG_PCDV, "complete req!!\n"); ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (ep->dwc_ep.xfer_count != ep->dwc_ep.total_len && ++ pcd->ep0state == EP0_OUT_DATA_PHASE) { ++ /* Read arrived setup packet from req->buf */ ++ dwc_memcpy(&pcd->setup_pkt->req, ++ req->buf + ep->dwc_ep.xfer_count, 8); ++ } ++ req->actual = ep->dwc_ep.xfer_count; ++ dwc_otg_request_done(ep, req, -ECONNRESET); ++ ep->dwc_ep.start_xfer_buff = 0; ++ ep->dwc_ep.xfer_buff = 0; ++ ep->dwc_ep.xfer_len = 0; ++ } ++ pcd->ep0state = EP0_IDLE; ++ if (doepint.b.setup) { ++ DWC_DEBUGPL(DBG_PCDV, "EP0_IDLE SR=1 setup=1\n"); ++ /* Data stage started, clear setup */ ++ CLEAR_OUT_EP_INTR(core_if, epnum, setup); ++ doepint.b.setup = 0; ++ handle_ep0(pcd); ++ /* Prepare for setup packets if ep0in was enabled*/ ++ if (pcd->ep0state == EP0_IN_STATUS_PHASE) { ++ ep0_out_start(core_if, pcd); ++ } ++ goto exit_xfercompl; ++ } else { ++ /* Prepare for more setup packets */ ++ DWC_DEBUGPL(DBG_PCDV, ++ "EP0_IDLE SR=1 setup=0 new setup comes 2\n"); ++ ep0_out_start(core_if, pcd); ++ } ++ } ++ } ++ } ++ if (core_if->dma_enable == 0 || pcd->ep0state != EP0_IDLE) ++ handle_ep0(pcd); ++exit_xfercompl: ++ DWC_DEBUGPL(DBG_PCDV, "DOEPINT=%x doepint=%x\n", ++ dwc_otg_read_dev_out_ep_intr(core_if, dwc_ep), doepint.d32); ++ } else { + 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) { @@ -66398,28 +80323,39 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + complete_iso_ep(pcd, ep); + } else { + -+ doepint_data_t doepint = {.d32 = -+ 0 }; ++ 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); ++ 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(pcd, + ep); + } + } -+#endif /* DWC_EN_ISOC */ ++#endif /* DWC_EN_ISOC */ ++#ifdef DWC_UTE_PER_IO ++ } else if (dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ CLEAR_OUT_EP_INTR(core_if, epnum, xfercompl); ++ if (!ep->stopped) ++ complete_xiso_ep(ep); ++#endif /* DWC_UTE_PER_IO */ + } else { + /* Clear the bit in DOEPINTn for this interrupt */ + CLEAR_OUT_EP_INTR(core_if, epnum, + xfercompl); -+ complete_ep(ep); ++ ++ if (core_if->core_params->dev_out_nak) { ++ DWC_TIMER_CANCEL(pcd->core_if->ep_xfer_timer[epnum]); ++ pcd->core_if->ep_xfer_info[epnum].state = 0; ++#ifdef DEBUG ++ print_memory_payload(pcd, dwc_ep); ++#endif ++ } ++ complete_ep(ep); + } + + } @@ -66429,21 +80365,66 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + + /* Clear the bit in DOEPINTn for this interrupt */ + CLEAR_OUT_EP_INTR(core_if, epnum, epdisabled); ++ if (core_if->core_params->dev_out_nak) { ++#ifdef DEBUG ++ print_memory_payload(pcd, dwc_ep); ++#endif ++ /* In case of timeout condition */ ++ if (core_if->ep_xfer_info[epnum].state == 2) { ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dctl); ++ dctl.b.cgoutnak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ /* Unmask goutnakeff interrupt which was masked ++ * during handle nak out interrupt */ ++ gintmsk.b.goutnakeff = 1; ++ DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, ++ 0, gintmsk.d32); ++ ++ complete_ep(ep); ++ } ++ } ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ++ { ++ dctl_data_t dctl; ++ gintmsk_data_t intr_mask = {.d32 = 0}; ++ dwc_otg_pcd_request_t *req = 0; ++ ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ dev_global_regs->dctl); ++ dctl.b.cgoutnak = 1; ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ ++ intr_mask.d32 = 0; ++ intr_mask.b.incomplisoout = 1; ++ ++ /* Get any pending requests */ ++ if (!DWC_CIRCLEQ_EMPTY(&ep->queue)) { ++ req = DWC_CIRCLEQ_FIRST(&ep->queue); ++ if (!req) { ++ DWC_PRINTF("complete_ep 0x%p, req = NULL!\n", ep); ++ } else { ++ dwc_otg_request_done(ep, req, 0); ++ start_next_request(ep); ++ } ++ } else { ++ DWC_PRINTF("complete_ep 0x%p, ep->queue empty!\n", ep); ++ } ++ } + } + /* AHB Error */ + 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); ++ DWC_ERROR("EP%d OUT AHB Error\n", epnum); ++ DWC_ERROR("EP%d DEPDMA=0x%08x \n", ++ epnum, core_if->dev_if->out_ep_regs[epnum]->doepdma); + CLEAR_OUT_EP_INTR(core_if, epnum, ahberr); + } + /* Setup Phase Done (contorl EPs) */ + if (doepint.b.setup) { +#ifdef DEBUG_EP0 -+ DWC_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n", -+ epnum); ++ DWC_DEBUGPL(DBG_PCD, "EP%d SETUP Done\n", epnum); +#endif + CLEAR_OUT_EP_INTR(core_if, epnum, setup); + @@ -66458,45 +80439,20 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + if (dwc_ep->type == + DWC_OTG_EP_TYPE_ISOC) { + /* -+ * This checking is performed to prevent first "false" BNA -+ * handling occuring right after reconnect ++ * 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); ++ 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); -+ } ++ dwc_otg_pcd_handle_noniso_bna(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 */ ++ /* Babble Interrupt */ + if (doepint.b.babble) { + DWC_DEBUGPL(DBG_ANY, "EP%d OUT Babble\n", + epnum); @@ -66504,6 +80460,34 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + + CLEAR_OUT_EP_INTR(core_if, epnum, babble); + } ++ if (doepint.b.outtknepdis) { ++ DWC_DEBUGPL(DBG_ANY, "EP%d OUT Token received when EP is \ ++ disabled\n",epnum); ++ if (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { ++ doepmsk_data_t doepmsk = {.d32 = 0}; ++ ep->dwc_ep.frame_num = core_if->frame_num; ++ if (ep->dwc_ep.bInterval > 1) { ++ depctl_data_t depctl; ++ depctl.d32 = DWC_READ_REG32(&core_if->dev_if-> ++ out_ep_regs[epnum]->doepctl); ++ if (ep->dwc_ep.frame_num & 0x1) { ++ depctl.b.setd1pid = 1; ++ depctl.b.setd0pid = 0; ++ } else { ++ depctl.b.setd0pid = 1; ++ depctl.b.setd1pid = 0; ++ } ++ DWC_WRITE_REG32(&core_if->dev_if-> ++ out_ep_regs[epnum]->doepctl, depctl.d32); ++ } ++ start_next_request(ep); ++ doepmsk.b.outtknepdis = 1; ++ DWC_MODIFY_REG32(&core_if->dev_if->dev_global_regs->doepmsk, ++ doepmsk.d32, 0); ++ } ++ CLEAR_OUT_EP_INTR(core_if, epnum, outtknepdis); ++ } ++ + /* NAK Interrutp */ + if (doepint.b.nak) { + DWC_DEBUGPL(DBG_ANY, "EP%d OUT NAK\n", epnum); @@ -66528,7 +80512,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + +#undef CLEAR_OUT_EP_INTR +} -+ ++static int drop_transfer(uint32_t trgt_fr, uint32_t curr_fr, uint8_t frm_overrun) ++{ ++ int retval = 0; ++ if(!frm_overrun && curr_fr >= trgt_fr) ++ retval = 1; ++ else if (frm_overrun ++ && (curr_fr >= trgt_fr && ((curr_fr - trgt_fr) < 0x3FFF / 2))) ++ retval = 1; ++ return retval; ++} +/** + * Incomplete ISO IN Transfer Interrupt. + * This interrupt indicates one of the following conditions occurred @@ -66559,9 +80552,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + dwc_ep = &pcd->in_ep[i].dwc_ep; + if (dwc_ep->active && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { + deptsiz.d32 = -+ dwc_read_reg32(&dev_if->in_ep_regs[i]->dieptsiz); ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->dieptsiz); + depctl.d32 = -+ dwc_read_reg32(&dev_if->in_ep_regs[i]->diepctl); ++ 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); @@ -66585,7 +80578,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + } + + dsts.d32 = -+ dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if-> ++ DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if-> + dev_global_regs->dsts); + dwc_ep->next_frame = dsts.b.soffn; + @@ -66597,19 +80590,40 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + } + +#else -+ gintmsk_data_t intr_mask = {.d32 = 0 }; -+ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", -+ "IN ISOC Incomplete"); ++ depctl_data_t depctl = {.d32 = 0 }; ++ dwc_ep_t *dwc_ep; ++ dwc_otg_dev_if_t *dev_if; ++ int i; ++ dev_if = GET_CORE_IF(pcd)->dev_if; + -+ intr_mask.b.incomplisoin = 1; -+ dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -+ intr_mask.d32, 0); ++ DWC_DEBUGPL(DBG_PCD,"Incomplete ISO IN \n"); ++ ++ for (i = 1; i <= dev_if->num_in_eps; ++i) { ++ dwc_ep = &pcd->in_ep[i-1].dwc_ep; ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (depctl.b.epena && dwc_ep->type == DWC_OTG_EP_TYPE_ISOC) { ++ if (drop_transfer(dwc_ep->frame_num, GET_CORE_IF(pcd)->frame_num, ++ dwc_ep->frm_overrun)) ++ { ++ depctl.d32 = ++ DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ depctl.b.snak = 1; ++ depctl.b.epdis = 1; ++ DWC_MODIFY_REG32(&dev_if->in_ep_regs[i]->diepctl, depctl.d32, depctl.d32); ++ } ++ } ++ } ++ ++ /*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, ++ DWC_WRITE_REG32(&GET_CORE_IF(pcd)->core_global_regs->gintsts, + gintsts.d32); + + return 1; @@ -66619,7 +80633,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + * Incomplete ISO OUT Transfer Interrupt. + * + * This interrupt indicates that the core has dropped an ISO OUT -+ * packet. The following conditions can be the cause: ++ * packet. The following conditions can be the cause: + * - FIFO Full, the entire packet would not fit in the FIFO. + * - CRC Error + * - Corrupted Token @@ -66627,7 +80641,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + * -# Determine the EP + * -# Set incomplete flag in dwc_ep structure + * -# Read any data from the FIFO -+ * -# Disable EP. when "Endpoint Disabled" interrupt is received ++ * -# Disable EP. When "Endpoint Disabled" interrupt is received + * re-enable EP. + */ +int32_t dwc_otg_pcd_handle_incomplete_isoc_out_intr(dwc_otg_pcd_t * pcd) @@ -66650,9 +80664,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + if (pcd->out_ep[i].dwc_ep.active && + pcd->out_ep[i].dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) { + deptsiz.d32 = -+ dwc_read_reg32(&dev_if->out_ep_regs[i]->doeptsiz); ++ DWC_READ_REG32(&dev_if->out_ep_regs[i]->doeptsiz); + depctl.d32 = -+ dwc_read_reg32(&dev_if->out_ep_regs[i]->doepctl); ++ DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); + + if (depctl.b.epdis && deptsiz.d32) { + set_current_pkt_info(GET_CORE_IF(pcd), @@ -66677,7 +80691,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + } + + dsts.d32 = -+ dwc_read_reg32(&GET_CORE_IF(pcd)->dev_if-> ++ DWC_READ_REG32(&GET_CORE_IF(pcd)->dev_if-> + dev_global_regs->dsts); + dwc_ep->next_frame = dsts.b.soffn; + @@ -66690,20 +80704,55 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo +#else + /** @todo implement ISR */ + gintmsk_data_t intr_mask = {.d32 = 0 }; ++ dwc_otg_core_if_t *core_if; ++ deptsiz_data_t deptsiz = {.d32 = 0 }; ++ depctl_data_t depctl = {.d32 = 0 }; ++ dctl_data_t dctl = {.d32 = 0 }; ++ dwc_ep_t *dwc_ep = NULL; ++ int i; ++ core_if = GET_CORE_IF(pcd); + -+ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", -+ "OUT ISOC Incomplete"); ++ for (i = 0; i < core_if->dev_if->num_out_eps; ++i) { ++ dwc_ep = &pcd->out_ep[i].dwc_ep; ++ depctl.d32 = ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl); ++ if (depctl.b.epena && depctl.b.dpid == (core_if->frame_num & 0x1)) { ++ core_if->dev_if->isoc_ep = dwc_ep; ++ deptsiz.d32 = ++ DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doeptsiz); ++ break; ++ } ++ } ++ dctl.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dctl); ++ gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts); ++ intr_mask.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk); + ++ if (!intr_mask.b.goutnakeff) { ++ /* Unmask it */ ++ intr_mask.b.goutnakeff = 1; ++ DWC_WRITE_REG32(&core_if->core_global_regs->gintmsk, intr_mask.d32); ++ } ++ if (!gintsts.b.goutnakeff) { ++ dctl.b.sgoutnak = 1; ++ } ++ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dctl, dctl.d32); ++ ++ depctl.d32 = DWC_READ_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl); ++ if (depctl.b.epena) { ++ depctl.b.epdis = 1; ++ depctl.b.snak = 1; ++ } ++ DWC_WRITE_REG32(&core_if->dev_if->out_ep_regs[dwc_ep->num]->doepctl, depctl.d32); ++ ++ intr_mask.d32 = 0; + intr_mask.b.incomplisoout = 1; -+ dwc_modify_reg32(&GET_CORE_IF(pcd)->core_global_regs->gintmsk, -+ intr_mask.d32, 0); -+ -+#endif /* DWC_EN_ISOC */ ++ ++#endif /* DWC_EN_ISOC */ + + /* Clear interrupt */ + gintsts.d32 = 0; + gintsts.b.incomplisoout = 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; @@ -66717,34 +80766,35 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo +{ + 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 }; + gintmsk_data_t intr_mask = {.d32 = 0 }; + gintsts_data_t gintsts; ++ dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd); + int i; + + DWC_DEBUGPL(DBG_PCD, "Global IN NAK Effective\n"); + + /* Disable all active IN EPs */ -+ diepctl.b.epdis = 1; -+ diepctl.b.snak = 1; -+ + for (i = 0; i <= dev_if->num_in_eps; i++) { -+ 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); -+ } ++ diepctl.d32 = DWC_READ_REG32(&dev_if->in_ep_regs[i]->diepctl); ++ if (!(diepctl.b.eptype & 1) && diepctl.b.epena) { ++ if (core_if->start_predict > 0) ++ core_if->start_predict++; ++ diepctl.b.epdis = 1; ++ diepctl.b.snak = 1; ++ 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); + + /* Clear interrupt */ + 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); + + return 1; @@ -66756,20 +80806,72 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + */ +int32_t dwc_otg_pcd_handle_out_nak_effective(dwc_otg_pcd_t * pcd) +{ ++ dwc_otg_dev_if_t *dev_if = GET_CORE_IF(pcd)->dev_if; + gintmsk_data_t intr_mask = {.d32 = 0 }; + gintsts_data_t gintsts; ++ depctl_data_t doepctl; ++ int i; + -+ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", -+ "Global IN NAK Effective\n"); -+ /* Disable the Global IN NAK Effective Interrupt */ ++ /* Disable the Global OUT NAK Effective Interrupt */ + intr_mask.b.goutnakeff = 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); ++ ++ /* If DEV OUT NAK enabled*/ ++ if (pcd->core_if->core_params->dev_out_nak) { ++ /* Run over all out endpoints to determine the ep number on ++ * which the timeout has happened ++ */ ++ for (i = 0; i <= dev_if->num_out_eps; i++) { ++ if ( pcd->core_if->ep_xfer_info[i].state == 2 ) ++ break; ++ } ++ if (i > dev_if->num_out_eps) { ++ dctl_data_t dctl; ++ dctl.d32 = ++ DWC_READ_REG32(&dev_if->dev_global_regs->dctl); ++ dctl.b.cgoutnak = 1; ++ DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, ++ dctl.d32); ++ goto out; ++ } + ++ /* Disable the endpoint */ ++ doepctl.d32 = DWC_READ_REG32(&dev_if->out_ep_regs[i]->doepctl); ++ if (doepctl.b.epena) { ++ doepctl.b.epdis = 1; ++ doepctl.b.snak = 1; ++ } ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl, doepctl.d32); ++ return 1; ++ } ++ /* We come here from Incomplete ISO OUT handler */ ++ if (dev_if->isoc_ep) { ++ dwc_ep_t *dwc_ep = (dwc_ep_t *)dev_if->isoc_ep; ++ uint32_t epnum = dwc_ep->num; ++ doepint_data_t doepint; ++ doepint.d32 = ++ DWC_READ_REG32(&dev_if->out_ep_regs[dwc_ep->num]->doepint); ++ dev_if->isoc_ep = NULL; ++ doepctl.d32 = ++ DWC_READ_REG32(&dev_if->out_ep_regs[epnum]->doepctl); ++ DWC_PRINTF("Before disable DOEPCTL = %08x\n", doepctl.d32); ++ if (doepctl.b.epena) { ++ doepctl.b.epdis = 1; ++ doepctl.b.snak = 1; ++ } ++ DWC_WRITE_REG32(&dev_if->out_ep_regs[epnum]->doepctl, ++ doepctl.d32); ++ return 1; ++ } else ++ DWC_PRINTF("INTERRUPT Handler not implemented for %s\n", ++ "Global OUT NAK Effective\n"); ++ ++out: + /* Clear interrupt */ + 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); + + return 1; @@ -66796,11 +80898,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + gintsts_data_t gintr_status; + int32_t retval = 0; + ++ /* Exit from ISR if core is hibernated */ ++ if (core_if->hibernation_suspend == 1) { ++ return retval; ++ } +#ifdef VERBOSE + 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)) { @@ -66808,8 +80914,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo +#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); @@ -66827,9 +80933,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + 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); + } @@ -66854,9 +80957,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + 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); @@ -66867,6 +80967,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + retval |= dwc_otg_pcd_handle_out_ep_intr(pcd); + } + } ++ if (gintr_status.b.epmismatch) { ++ retval |= dwc_otg_pcd_handle_ep_mismatch_intr(pcd); ++ } ++ if (gintr_status.b.fetsusp) { ++ retval |= dwc_otg_pcd_handle_ep_fetsusp_intr(pcd); ++ } ++ if (gintr_status.b.ginnakeff) { ++ retval |= dwc_otg_pcd_handle_in_nak_effective(pcd); ++ } + if (gintr_status.b.incomplisoin) { + retval |= + dwc_otg_pcd_handle_incomplete_isoc_in_intr(pcd); @@ -66876,7 +80985,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + dwc_otg_pcd_handle_incomplete_isoc_out_intr(pcd); + } + -+ /* In MPI mode De vice Endpoints intterrupts are asserted ++ /* In MPI mode Device Endpoints interrupts are asserted + * without setting outepintr and inepint bits set, so these + * Interrupt handlers are called without checking these bit-fields + */ @@ -66886,23 +80995,25 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_intr.c linux-rpi-bo + } +#ifdef VERBOSE + DWC_DEBUGPL(DBG_PCDV, "%s() gintsts=%0x\n", __func__, -+ dwc_read_reg32(&global_regs->gintsts)); ++ DWC_READ_REG32(&global_regs->gintsts)); +#endif + DWC_SPINUNLOCK(pcd->lock); + } + return retval; +} + -+#endif /* DWC_HOST_ONLY */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c 2012-07-15 20:29:19.092083771 +0200 -@@ -0,0 +1,1288 @@ ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c +new file mode 100644 +index 0000000..9289fc0 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c +@@ -0,0 +1,1374 @@ + /* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_pcd_linux.c $ -+ * $Revision: #7 $ -+ * $Date: 2009/04/03 $ -+ * $Change: 1225160 $ ++ * $Revision: #21 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ + * + * Synopsys HS OTG Linux Software Driver and documentation (hereinafter, + * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless @@ -66953,47 +81064,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + * + */ + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#if defined(LM_INTERFACE) -+//# include -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+#include -+#else -+/* by 2.6.31, at least, the location of some headers has changed -+*/ -+#include -+#endif -+ -+#elif defined(PLATFORM_INTERFACE) -+#include -+#endif -+ -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) -+#include -+#include -+#include -+#else -+/* by 2.6.31, at least, the location of some headers has changed -+*/ -+#include -+#include -+#include -+#endif -+ -+#include -+ ++#include "dwc_otg_os_dep.h" +#include "dwc_otg_pcd_if.h" ++#include "dwc_otg_pcd.h" +#include "dwc_otg_driver.h" +#include "dwc_otg_dbg.h" + @@ -67011,6 +81084,26 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + +/* Display the contents of the buffer */ +extern void dump_msg(const u8 * buf, unsigned int length); ++/** ++ * Get the dwc_otg_pcd_ep_t* from usb_ep* pointer - NULL in case ++ * if the endpoint is not found ++ */ ++static struct dwc_otg_pcd_ep *ep_from_handle(dwc_otg_pcd_t * pcd, void *handle) ++{ ++ int i; ++ if (pcd->ep0.priv == handle) { ++ return &pcd->ep0; ++ } ++ ++ for (i = 0; i < MAX_EPS_CHANNELS - 1; i++) { ++ if (pcd->in_ep[i].priv == handle) ++ return &pcd->in_ep[i]; ++ if (pcd->out_ep[i].priv == handle) ++ return &pcd->out_ep[i]; ++ } ++ ++ return NULL; ++} + +/* USB Endpoint Operations */ +/* @@ -67064,6 +81157,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + return -ESHUTDOWN; + } + ++ /* Delete after check - MAS */ ++#if 0 ++ nat = (uint32_t) ep_desc->wMaxPacketSize; ++ printk(KERN_ALERT "%s: nat (before) =%d\n", __func__, nat); ++ nat = (nat >> 11) & 0x03; ++ printk(KERN_ALERT "%s: nat (after) =%d\n", __func__, nat); ++#endif + retval = dwc_otg_pcd_ep_enable(gadget_wrapper->pcd, + (const uint8_t *)ep_desc, + (void *)usb_ep); @@ -67127,7 +81227,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + return 0; + } + memset(usb_req, 0, sizeof(*usb_req)); -+ usb_req->dma = DWC_INVALID_DMA_ADDR; ++ usb_req->dma = DWC_DMA_ADDR_INVALID; + + return usb_req; +} @@ -67151,7 +81251,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + kfree(req); +} + -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) +/** + * This function allocates an I/O buffer to be used for a transfer + * to/from the specified endpoint. @@ -67229,7 +81329,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + gfp_t gfp_flags) +{ + dwc_otg_pcd_t *pcd; -+ int retval; ++ struct dwc_otg_pcd_ep *ep = NULL; ++ int retval = 0, is_isoc_ep = 0; ++ dma_addr_t dma_addr = DWC_DMA_ADDR_INVALID; + + DWC_DEBUGPL(DBG_PCDV, "%s(%p,%p,%d)\n", + __func__, usb_ep, usb_req, gfp_flags); @@ -67259,7 +81361,44 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + usb_req->status = -EINPROGRESS; + usb_req->actual = 0; + -+ retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, usb_req->dma, ++ ep = ep_from_handle(pcd, usb_ep); ++ if (ep == NULL) ++ is_isoc_ep = 0; ++ else ++ is_isoc_ep = (ep->dwc_ep.type == DWC_OTG_EP_TYPE_ISOC) ? 1 : 0; ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) ++ dma_addr = usb_req->dma; ++#else ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev; ++ struct device *dev = NULL; ++ ++ if (otg_dev != NULL) ++ dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep); ++ ++ if (usb_req->length != 0 && ++ usb_req->dma == DWC_DMA_ADDR_INVALID) { ++ dma_addr = dma_map_single(dev, usb_req->buf, ++ usb_req->length, ++ ep->dwc_ep.is_in ? ++ DMA_TO_DEVICE: ++ DMA_FROM_DEVICE); ++ } ++ } ++#endif ++ ++#ifdef DWC_UTE_PER_IO ++ if (is_isoc_ep == 1) { ++ retval = dwc_otg_pcd_xiso_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr, ++ usb_req->length, usb_req->zero, usb_req, ++ gfp_flags == GFP_ATOMIC ? 1 : 0, &usb_req->ext_req); ++ if (retval) ++ return -EINVAL; ++ ++ return 0; ++ } ++#endif ++ retval = dwc_otg_pcd_ep_queue(pcd, usb_ep, usb_req->buf, dma_addr, + usb_req->length, usb_req->zero, usb_req, + gfp_flags == GFP_ATOMIC ? 1 : 0); + if (retval) { @@ -67397,9 +81536,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + req->buf1, req->dma0, req->dma1, + req->sync_frame, req->data_pattern_frame, + req->data_per_frame, -+ req->flags & USB_REQ_ISO_ASAP ? -1 : req-> -+ start_frame, req->buf_proc_intrvl, req, -+ gfp_flags == GFP_ATOMIC ? 1 : 0); ++ req-> ++ flags & USB_REQ_ISO_ASAP ? -1 : ++ req->start_frame, req->buf_proc_intrvl, ++ req, gfp_flags == GFP_ATOMIC ? 1 : 0); + + if (retval) { + return -EINVAL; @@ -67468,8 +81608,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + .alloc_request = dwc_otg_pcd_alloc_request, + .free_request = dwc_otg_pcd_free_request, + ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) + .alloc_buffer = dwc_otg_pcd_alloc_buffer, + .free_buffer = dwc_otg_pcd_free_buffer, ++#endif + + .queue = ep_queue, + .dequeue = ep_dequeue, @@ -67510,7 +81652,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + .alloc_request = dwc_otg_pcd_alloc_request, + .free_request = dwc_otg_pcd_free_request, + -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28) + .alloc_buffer = dwc_otg_pcd_alloc_buffer, + .free_buffer = dwc_otg_pcd_free_buffer, +#else @@ -67527,7 +81669,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + +}; + -+#endif /* _EN_ISOC_ */ ++#endif /* _EN_ISOC_ */ +/* Gadget Operations */ +/** + * The following gadget operations will be implemented in the DWC_otg @@ -67661,12 +81803,78 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + + return 0; +} -+#endif /* DWC_EN_ISOC */ ++#endif /* DWC_EN_ISOC */ ++ ++#ifdef DWC_UTE_PER_IO ++/** ++ * Copy the contents of the extended request to the Linux usb_request's ++ * extended part and call the gadget's completion. ++ * ++ * @param pcd Pointer to the pcd structure ++ * @param ep_handle Void pointer to the usb_ep structure ++ * @param req_handle Void pointer to the usb_request structure ++ * @param status Request status returned from the portable logic ++ * @param ereq_port Void pointer to the extended request structure ++ * created in the the portable part that contains the ++ * results of the processed iso packets. ++ */ ++static int _xisoc_complete(dwc_otg_pcd_t * pcd, void *ep_handle, ++ void *req_handle, int32_t status, void *ereq_port) ++{ ++ struct dwc_ute_iso_req_ext *ereqorg = NULL; ++ struct dwc_iso_xreq_port *ereqport = NULL; ++ struct dwc_ute_iso_packet_descriptor *desc_org = NULL; ++ int i; ++ struct usb_request *req; ++ //struct dwc_ute_iso_packet_descriptor * ++ //int status = 0; ++ ++ req = (struct usb_request *)req_handle; ++ ereqorg = &req->ext_req; ++ ereqport = (struct dwc_iso_xreq_port *)ereq_port; ++ desc_org = ereqorg->per_io_frame_descs; ++ ++ if (req && req->complete) { ++ /* Copy the request data from the portable logic to our request */ ++ for (i = 0; i < ereqport->pio_pkt_count; i++) { ++ desc_org[i].actual_length = ++ ereqport->per_io_frame_descs[i].actual_length; ++ desc_org[i].status = ++ ereqport->per_io_frame_descs[i].status; ++ } ++ ++ switch (status) { ++ case -DWC_E_SHUTDOWN: ++ req->status = -ESHUTDOWN; ++ break; ++ case -DWC_E_RESTART: ++ req->status = -ECONNRESET; ++ break; ++ case -DWC_E_INVALID: ++ req->status = -EINVAL; ++ break; ++ case -DWC_E_TIMEOUT: ++ req->status = -ETIMEDOUT; ++ break; ++ default: ++ req->status = status; ++ } ++ ++ /* And call the gadget's completion */ ++ req->complete(ep_handle, req); ++ } ++ ++ return 0; ++} ++#endif /* DWC_UTE_PER_IO */ + +static int _complete(dwc_otg_pcd_t * pcd, void *ep_handle, + void *req_handle, int32_t status, uint32_t actual) +{ + struct usb_request *req = (struct usb_request *)req_handle; ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27) ++ struct dwc_otg_pcd_ep *ep = NULL; ++#endif + + if (req && req->complete) { + switch (status) { @@ -67686,9 +81894,28 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + req->status = status; + + } ++ + req->actual = actual; ++ DWC_SPINUNLOCK(pcd->lock); + req->complete(ep_handle, req); ++ DWC_SPINLOCK(pcd->lock); + } ++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27) ++ ep = ep_from_handle(pcd, ep_handle); ++ if (GET_CORE_IF(pcd)->dma_enable) { ++ if (req->length != 0) { ++ dwc_otg_device_t *otg_dev = gadget_wrapper->pcd->otg_dev; ++ struct device *dev = NULL; ++ ++ if (otg_dev != NULL) ++ dev = DWC_OTG_OS_GETDEV(otg_dev->os_dep); ++ ++ dma_unmap_single(dev, req->dma, req->length, ++ ep->dwc_ep.is_in ? ++ DMA_TO_DEVICE: DMA_FROM_DEVICE); ++ } ++ } ++#endif + + return 0; +} @@ -67750,11 +81977,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + int retval = -DWC_E_INVALID; + if (gadget_wrapper->driver->cfi_feature_setup) { + retval = -+ gadget_wrapper->driver->cfi_feature_setup(&gadget_wrapper-> -+ gadget, -+ (struct -+ cfi_usb_ctrlrequest -+ *)cfi_req); ++ gadget_wrapper->driver-> ++ cfi_feature_setup(&gadget_wrapper->gadget, ++ (struct cfi_usb_ctrlrequest *)cfi_req); + } + + return retval; @@ -67776,6 +82001,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b +#ifdef DWC_UTE_CFI + .cfi_setup = _cfi_setup, +#endif ++#ifdef DWC_UTE_PER_IO ++ .xisoc_complete = _xisoc_complete, ++#endif +}; + +/** @@ -67838,6 +82066,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + + int i; + struct usb_ep *ep; ++ int8_t dev_endpoints; + + DWC_DEBUGPL(DBG_PCDV, "%s\n", __func__); + @@ -67868,12 +82097,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + /** + * Initialize the EP structures. + */ ++ dev_endpoints = d->pcd->core_if->dev_if->num_in_eps; + -+ for (i = 0; i < 15; i++) { ++ for (i = 0; i < dev_endpoints; i++) { + ep = &d->in_ep[i]; + + /* Init the usb_ep structure. */ -+ ep->name = names[i + 1]; ++ ep->name = names[d->pcd->in_ep[i].dwc_ep.num]; + ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; + + /** @@ -67884,11 +82114,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + list_add_tail(&ep->ep_list, &d->gadget.ep_list); + } + -+ for (i = 0; i < 15; i++) { ++ dev_endpoints = d->pcd->core_if->dev_if->num_out_eps; ++ ++ for (i = 0; i < dev_endpoints; i++) { + ep = &d->out_ep[i]; + + /* Init the usb_ep structure. */ -+ ep->name = names[15 + i + 1]; ++ ep->name = names[15 + d->pcd->out_ep[i].dwc_ep.num]; + ep->ops = (struct usb_ep_ops *)&dwc_otg_pcd_ep_ops; + + /** @@ -67917,29 +82149,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + DWC_DEBUGPL(DBG_PCDV, "%s(%p)\n", __func__, dev); +} + -+static struct gadget_wrapper *alloc_wrapper( -+#ifdef LM_INTERFACE -+ struct lm_device *_dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *_dev -+#endif -+ ) ++static struct gadget_wrapper *alloc_wrapper(dwc_bus_dev_t *_dev) +{ -+#ifdef LM_INTERFACE -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); -+#endif + static char pcd_name[] = "dwc_otg_pcd"; -+ ++ dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev); + struct gadget_wrapper *d; + int retval; + -+ d = dwc_alloc(sizeof(*d)); ++ d = DWC_ALLOC(sizeof(*d)); + if (d == NULL) { + return NULL; + } @@ -67948,12 +82165,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + + d->gadget.name = pcd_name; + d->pcd = otg_dev->pcd; -+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)) ++ ++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) + strcpy(d->gadget.dev.bus_id, "gadget"); +#else -+ /*d->gadget.dev.bus = NULL;*/ -+ d->gadget.dev.init_name = "gadget"; ++ dev_set_name(&d->gadget.dev, "%s", "gadget"); +#endif ++ + d->gadget.dev.parent = &_dev->dev; + d->gadget.dev.release = dwc_otg_pcd_gadget_release; + d->gadget.ops = &dwc_otg_pcd_ops; @@ -67965,7 +82183,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + retval = device_register(&d->gadget.dev); + if (retval != 0) { + DWC_ERROR("device_register failed\n"); -+ dwc_free(d); ++ DWC_FREE(d); + return NULL; + } + @@ -67982,33 +82200,16 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + } + + device_unregister(&d->gadget.dev); -+ dwc_free(d); ++ DWC_FREE(d); +} + +/** + * This function initialized the PCD portion of the driver. + * + */ -+int pcd_init( -+#ifdef LM_INTERFACE -+ struct lm_device *_dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *_dev -+#endif -+ ) -+ ++int pcd_init(dwc_bus_dev_t *_dev) +{ -+#ifdef LM_INTERFACE -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); -+#endif -+ int devirq; -+ ++ dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev); + int retval = 0; + + DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev=%p\n", __func__, _dev, otg_dev); @@ -68020,30 +82221,40 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + return -ENOMEM; + } + ++ otg_dev->pcd->otg_dev = otg_dev; + gadget_wrapper = alloc_wrapper(_dev); + + /* + * Initialize EP structures + */ + gadget_add_eps(gadget_wrapper); -+ + /* + * Setup interupt handler + */ +#ifdef PLATFORM_INTERFACE -+ devirq = platform_get_irq(_dev, 0); -+#else -+ devirq = _dev->irq; -+#endif -+ DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n", devirq); -+ retval = request_irq(devirq, dwc_otg_pcd_irq, ++ DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n", ++ platform_get_irq(_dev, 0)); ++ retval = request_irq(platform_get_irq(_dev, 0), dwc_otg_pcd_irq, + IRQF_SHARED, gadget_wrapper->gadget.name, + otg_dev->pcd); + if (retval != 0) { -+ DWC_ERROR("request of irq%d failed\n", devirq); ++ DWC_ERROR("request of irq%d failed\n", ++ platform_get_irq(_dev, 0)); + free_wrapper(gadget_wrapper); + return -EBUSY; + } ++#else ++ DWC_DEBUGPL(DBG_ANY, "registering handler for irq%d\n", ++ _dev->irq); ++ retval = request_irq(_dev->irq, dwc_otg_pcd_irq, ++ IRQF_SHARED | IRQF_DISABLED, ++ gadget_wrapper->gadget.name, otg_dev->pcd); ++ if (retval != 0) { ++ DWC_ERROR("request of irq%d failed\n", _dev->irq); ++ free_wrapper(gadget_wrapper); ++ return -EBUSY; ++ } ++#endif + + dwc_otg_pcd_start(gadget_wrapper->pcd, &fops); + @@ -68053,23 +82264,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b +/** + * Cleanup the PCD. + */ -+void pcd_remove( -+#ifdef LM_INTERFACE -+ struct lm_device *_dev -+#elif defined(PCI_INTERFACE) -+ struct pci_dev *_dev -+#elif defined(PLATFORM_INTERFACE) -+ struct platform_device *_dev -+#endif -+ ) ++void pcd_remove(dwc_bus_dev_t *_dev) +{ -+#ifdef LM_INTERFACE -+ dwc_otg_device_t *otg_dev = lm_get_drvdata(_dev); -+#elif defined(PCI_INTERFACE) -+ dwc_otg_device_t *otg_dev = pci_get_drvdata(_dev); -+#elif defined(PLATFORM_INTERFACE) -+ dwc_otg_device_t *otg_dev = platform_get_drvdata(_dev); -+#endif ++ dwc_otg_device_t *otg_dev = DWC_OTG_BUSDRVDATA(_dev); + dwc_otg_pcd_t *pcd = otg_dev->pcd; + + DWC_DEBUGPL(DBG_PCDV, "%s(%p) otg_dev %p\n", __func__, _dev, otg_dev); @@ -68096,6 +82293,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + * then a host may connect again, or the driver might get unbound. + * + * @param driver The driver being registered ++ * @param bind The bind function of gadget driver + */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) +int usb_gadget_register_driver(struct usb_gadget_driver *driver) @@ -68113,7 +82311,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) + !driver->bind || +#else -+ !bind || ++ !bind || +#endif + !driver->unbind || !driver->disconnect || !driver->setup) { + DWC_DEBUGPL(DBG_PCDV, "EINVAL\n"); @@ -68149,7 +82347,6 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + driver->driver.name); + return 0; +} -+ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) +EXPORT_SYMBOL(usb_gadget_register_driver); +#else @@ -68185,21 +82382,23 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c linux-rpi-b + +EXPORT_SYMBOL(usb_gadget_unregister_driver); + -+#endif /* DWC_HOST_ONLY */ -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h ---- linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h 2012-07-15 20:29:19.077083490 +0200 -@@ -0,0 +1,2237 @@ ++#endif /* DWC_HOST_ONLY */ +diff --git a/drivers/usb/host/dwc_otg/dwc_otg_regs.h b/drivers/usb/host/dwc_otg/dwc_otg_regs.h +new file mode 100644 +index 0000000..0572642 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/dwc_otg_regs.h +@@ -0,0 +1,2550 @@ +/* ========================================================================== + * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $ -+ * $Revision: #76 $ -+ * $Date: 2009/04/02 $ -+ * $Change: 1224216 $ ++ * $Revision: #98 $ ++ * $Date: 2012/08/10 $ ++ * $Change: 2047372 $ + * + * 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 + * with Synopsys or any supplement thereto. You are permitted to use and @@ -68209,7 +82408,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + * any information contained herein except pursuant to this license grant from + * Synopsys. If you do not agree with this notice, including the disclaimer + * below, then you are not authorized to use the Software. -+ * ++ * + * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -68256,7 +82455,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + */ + +/****************************************************************************/ -+/** DWC_otg Core registers . ++/** DWC_otg Core registers . + * The dwc_otg_core_global_regs structure defines the size + * and relative field offsets for the Core Global registers. + */ @@ -68324,21 +82523,27 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + volatile uint32_t ghwcfg3; + /**User HW Config4 Register (Read Only). Offset: 050h*/ + volatile uint32_t ghwcfg4; -+ /** Core LPM Configuration register */ ++ /** Core LPM Configuration register Offset: 054h*/ + volatile uint32_t glpmcfg; -+ /** Reserved Offset: 058h-0FFh */ -+ volatile uint32_t reserved[42]; ++ /** Global PowerDn Register Offset: 058h */ ++ volatile uint32_t gpwrdn; ++ /** Global DFIFO SW Config Register Offset: 05Ch */ ++ volatile uint32_t gdfifocfg; ++ /** ADP Control Register Offset: 060h */ ++ volatile uint32_t adpctl; ++ /** Reserved Offset: 064h-0FFh */ ++ volatile uint32_t reserved39[39]; + /** Host Periodic Transmit FIFO Size Register. Offset: 100h */ + volatile uint32_t hptxfsiz; -+ /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled, -+ otherwise Device Transmit FIFO#n Register. ++ /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled, ++ otherwise Device Transmit FIFO#n Register. + * Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15). */ -+ volatile uint32_t dptxfsiz_dieptxf[15]; ++ volatile uint32_t dtxfsiz[15]; +} dwc_otg_core_global_regs_t; + +/** + * This union represents the bit fields of the Core OTG Control -+ * and Status Register (GOTGCTL). Set the bits using the bit ++ * and Status Register (GOTGCTL). Set the bits using the bit + * fields then write the d32 value to the register. + */ +typedef union gotgctl_data { @@ -68348,18 +82553,26 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + struct { + unsigned sesreqscs:1; + unsigned sesreq:1; -+ unsigned reserved2_7:6; ++ unsigned vbvalidoven:1; ++ unsigned vbvalidovval:1; ++ unsigned avalidoven:1; ++ unsigned avalidovval:1; ++ unsigned bvalidoven:1; ++ unsigned bvalidovval:1; + unsigned hstnegscs:1; + unsigned hnpreq:1; + unsigned hstsethnpen:1; + unsigned devhnpen:1; + unsigned reserved12_15:4; + unsigned conidsts:1; -+ unsigned reserved17:1; ++ unsigned dbnctime:1; + unsigned asesvld:1; + unsigned bsesvld:1; -+ unsigned currmod:1; -+ unsigned reserved21_31:11; ++ unsigned otgver:1; ++ unsigned reserved1:1; ++ unsigned multvalidbc:5; ++ unsigned chirpen:1; ++ unsigned reserved28_31:4; + } b; +} gotgctl_data_t; + @@ -68386,7 +82599,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + /** Host Negotiation Success Status Change */ + unsigned hstnegsucstschng:1; + -+ unsigned reserver10_16:7; ++ unsigned reserved10_16:7; + + /** Host Negotiation Detected */ + unsigned hstnegdet:1; @@ -68394,15 +82607,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned adevtoutchng:1; + /** Debounce Done */ + unsigned debdone:1; ++ /** Multi-Valued input changed */ ++ unsigned mvic:1; + -+ unsigned reserved31_20:12; ++ unsigned reserved31_21:11; + + } b; +} gotgint_data_t; + +/** + * This union represents the bit fields of the Core AHB Configuration -+ * Register (GAHBCFG). Set/clear the bits using the bit fields then ++ * Register (GAHBCFG). Set/clear the bits using the bit fields then + * write the d32 value to the register. + */ +typedef union gahbcfg_data { @@ -68427,13 +82642,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned ptxfemplvl:1; +#define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY 1 +#define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0 -+ unsigned reserved9_31:23; ++ unsigned reserved9_20:12; ++ unsigned remmemsupp:1; ++ unsigned notialldmawrit:1; ++ unsigned ahbsingle:1; ++ unsigned reserved24_31:8; + } b; +} gahbcfg_data_t; + +/** + * This union represents the bit fields of the Core USB Configuration -+ * Register (GUSBCFG). Set the bits using the bit fields then write ++ * Register (GUSBCFG). Set the bits using the bit fields then write + * the d32 value to the register. + */ +typedef union gusbcfg_data { @@ -68450,7 +82669,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned srpcap:1; + unsigned hnpcap:1; + unsigned usbtrdtim:4; -+ unsigned nptxfrwnden:1; ++ unsigned reserved1:1; + unsigned phylpwrclksel:1; + unsigned otgutmifssel:1; + unsigned ulpi_fsls:1; @@ -68459,120 +82678,19 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned ulpi_ext_vbus_drv:1; + unsigned ulpi_int_vbus_indicator:1; + unsigned term_sel_dl_pulse:1; -+ unsigned reserved23_25:3; ++ unsigned indicator_complement:1; ++ unsigned indicator_pass_through:1; ++ unsigned ulpi_int_prot_dis:1; + unsigned ic_usb_cap:1; + unsigned ic_traffic_pull_remove:1; + unsigned tx_end_delay:1; -+ unsigned reserved29_31:3; ++ unsigned force_host_mode:1; ++ unsigned force_dev_mode:1; ++ unsigned reserved31:1; + } b; +} gusbcfg_data_t; + +/** -+ * This union represents the bit fields of the Core LPM Configuration -+ * Register (GLPMCFG). Set the bits using bit fields then write -+ * the d32 value to the register. -+ */ -+typedef union glpmctl_data { -+ /** raw register data */ -+ uint32_t d32; -+ /** register bits */ -+ struct { -+ /** LPM-Capable (LPMCap) (Device and Host) -+ * The application uses this bit to control -+ * the DWC_otg core LPM capabilities. -+ */ -+ unsigned lpm_cap_en:1; -+ /** LPM response programmed by application (AppL1Res) (Device) -+ * Handshake response to LPM token pre-programmed -+ * by device application software. -+ */ -+ unsigned appl_resp:1; -+ /** Host Initiated Resume Duration (HIRD) (Device and Host) -+ * In Host mode this field indicates the value of HIRD -+ * to be sent in an LPM transaction. -+ * In Device mode this field is updated with the -+ * Received LPM Token HIRD bmAttribute -+ * when an ACK/NYET/STALL response is sent -+ * to an LPM transaction. -+ */ -+ unsigned hird:4; -+ /** RemoteWakeEnable (bRemoteWake) (Device and Host) -+ * In Host mode this bit indicates the value of remote -+ * wake up to be sent in wIndex field of LPM transaction. -+ * In Device mode this field is updated with the -+ * Received LPM Token bRemoteWake bmAttribute -+ * when an ACK/NYET/STALL response is sent -+ * to an LPM transaction. -+ */ -+ unsigned rem_wkup_en:1; -+ /** Enable utmi_sleep_n (EnblSlpM) (Device and Host) -+ * The application uses this bit to control -+ * the utmi_sleep_n assertion to the PHY when in L1 state. -+ */ -+ unsigned en_utmi_sleep:1; -+ /** HIRD Threshold (HIRD_Thres) (Device and Host) -+ */ -+ unsigned hird_thres:5; -+ /** LPM Response (CoreL1Res) (Device and Host) -+ * In Host mode this bit contains handsake response to -+ * LPM transaction. -+ * In Device mode the response of the core to -+ * LPM transaction received is reflected in these two bits. -+ - 0x0 : ERROR (No handshake response) -+ - 0x1 : STALL -+ - 0x2 : NYET -+ - 0x3 : ACK -+ */ -+ unsigned lpm_resp:2; -+ /** Port Sleep Status (SlpSts) (Device and Host) -+ * This bit is set as long as a Sleep condition -+ * is present on the USB bus. -+ */ -+ unsigned prt_sleep_sts:1; -+ /** Sleep State Resume OK (L1ResumeOK) (Device and Host) -+ * Indicates that the application or host -+ * can start resume from Sleep state. -+ */ -+ unsigned sleep_state_resumeok:1; -+ /** LPM channel Index (LPM_Chnl_Indx) (Host) -+ * The channel number on which the LPM transaction -+ * has to be applied while sending -+ * an LPM transaction to the local device. -+ */ -+ unsigned lpm_chan_index:4; -+ /** LPM Retry Count (LPM_Retry_Cnt) (Host) -+ * Number host retries that would be performed -+ * if the device response was not valid response. -+ */ -+ unsigned retry_count:3; -+ /** Send LPM Transaction (SndLPM) (Host) -+ * When set by application software, -+ * an LPM transaction containing two tokens -+ * is sent. -+ */ -+ unsigned send_lpm:1; -+ /** LPM Retry status (LPM_RetryCnt_Sts) (Host) -+ * Number of LPM Host Retries still remaining -+ * to be transmitted for the current LPM sequence -+ */ -+ unsigned retry_count_sts:3; -+ unsigned reserved28_29:2; -+ /** In host mode once this bit is set, the host -+ * configures to drive the HSIC Idle state on the bus. -+ * It then waits for the device to initiate the Connect sequence. -+ * In device mode once this bit is set, the device waits for -+ * the HSIC Idle line state on the bus. Upon receving the Idle -+ * line state, it initiates the HSIC Connect sequence. -+ */ -+ unsigned hsic_connect:1; -+ /** This bit overrides and functionally inverts -+ * the if_select_hsic input port signal. -+ */ -+ unsigned inv_sel_hsic:1; -+ } b; -+} glpmcfg_data_t; -+ -+/** + * This union represents the bit fields of the Core Reset Register + * (GRSTCTL). Set/clear the bits using the bit fields then write the + * d32 value to the register. @@ -68626,7 +82744,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + */ + unsigned hsftrst:1; + /** Host Frame Counter Reset (Host Only)
-+ * ++ * + * The application can reset the (micro)frame number + * counter inside the core, using this bit. When the + * (micro)frame counter is reset, the subsequent SOF @@ -68641,27 +82759,27 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + /** RxFIFO Flush (RxFFlsh) (Device and Host) + * + * The application can flush the entire Receive FIFO -+ * using this bit.

The application must first ++ * using this bit. The application must first + * ensure that the core is not in the middle of a -+ * transaction.

The application should write into ++ * transaction. The application should write into + * this bit, only after making sure that neither the + * DMA engine is reading from the RxFIFO nor the MAC -+ * is writing the data in to the FIFO.

The ++ * is writing the data in to the FIFO. The + * application should wait until the bit is cleared + * before performing any other operations. This bit + * will takes 8 clocks (slowest of PHY or AHB clock) + * to clear. + */ + unsigned rxfflsh:1; -+ /** TxFIFO Flush (TxFFlsh) (Device and Host). ++ /** TxFIFO Flush (TxFFlsh) (Device and Host). + * + * This bit is used to selectively flush a single or -+ * all transmit FIFOs. The application must first ++ * all transmit FIFOs. The application must first + * ensure that the core is not in the middle of a -+ * transaction.

The application should write into ++ * transaction. The application should write into + * this bit, only after making sure that neither the + * DMA engine is writing into the TxFIFO nor the MAC -+ * is reading the data out of the FIFO.

The ++ * is reading the data out of the FIFO. The + * application should wait until the core clears this + * bit, before performing any operations. This bit + * will takes 8 clocks (slowest of PHY or AHB clock) @@ -68670,7 +82788,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned txfflsh:1; + + /** TxFIFO Number (TxFNum) (Device and Host). -+ * ++ * + * This is the FIFO number which needs to be flushed, + * using the TxFIFO Flush bit. This field should not + * be changed until the TxFIFO Flush bit is cleared by @@ -68688,7 +82806,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + /** Reserved */ + unsigned reserved11_29:19; + /** DMA Request Signal. Indicated DMA request is in -+ * probress. Used for debug purpose. */ ++ * probress. Used for debug purpose. */ + unsigned dmareq:1; + /** AHB Master Idle. Indicates the AHB Master State + * Machine is in IDLE condition. */ @@ -68698,7 +82816,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + +/** + * This union represents the bit fields of the Core Interrupt Mask -+ * Register (GINTMSK). Set/clear the bits using the bit fields then ++ * Register (GINTMSK). Set/clear the bits using the bit fields then + * write the d32 value to the register. + */ +typedef union gintmsk_data { @@ -68714,7 +82832,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned nptxfempty:1; + unsigned ginnakeff:1; + unsigned goutnakeff:1; -+ unsigned reserved8:1; ++ unsigned ulpickint:1; + unsigned i2cintr:1; + unsigned erlysuspend:1; + unsigned usbsuspend:1; @@ -68722,13 +82840,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned enumdone:1; + unsigned isooutdrop:1; + unsigned eopframe:1; -+ unsigned reserved16:1; ++ unsigned restoredone:1; + unsigned epmismatch:1; + unsigned inepintr:1; + unsigned outepintr:1; + unsigned incomplisoin:1; + unsigned incomplisoout:1; -+ unsigned reserved22_23:2; ++ unsigned fetsusp:1; ++ unsigned resetdet:1; + unsigned portintr:1; + unsigned hcintr:1; + unsigned ptxfempty:1; @@ -68759,7 +82878,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned nptxfempty:1; + unsigned ginnakeff:1; + unsigned goutnakeff:1; -+ unsigned reserved8:1; ++ unsigned ulpickint:1; + unsigned i2cintr:1; + unsigned erlysuspend:1; + unsigned usbsuspend:1; @@ -68767,13 +82886,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned enumdone:1; + unsigned isooutdrop:1; + unsigned eopframe:1; -+ unsigned intokenrx:1; ++ unsigned restoredone:1; + unsigned epmismatch:1; + unsigned inepint:1; + unsigned outepintr:1; + unsigned incomplisoin:1; + unsigned incomplisoout:1; -+ unsigned reserved22_23:2; ++ unsigned fetsusp:1; ++ unsigned resetdet:1; + unsigned portintr:1; + unsigned hcintr:1; + unsigned ptxfempty:1; @@ -68786,8 +82906,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- +} gintsts_data_t; + +/** -+ * This union represents the bit fields in the Device Receive Status Read and -+ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the d32 ++ * This union represents the bit fields in the Device Receive Status Read and ++ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the d32 + * element then read out the bits using the bit elements. + */ +typedef union device_grxsts_data { @@ -68807,13 +82927,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- +#define DWC_DSTS_SETUP_UPDT 0x6 // SETUP Packet + unsigned pktsts:4; + unsigned fn:4; -+ unsigned reserved:7; ++ unsigned reserved25_31:7; + } b; +} device_grxsts_data_t; + +/** -+ * This union represents the bit fields in the Host Receive Status Read and -+ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the d32 ++ * This union represents the bit fields in the Host Receive Status Read and ++ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the d32 + * element then read out the bits using the bit elements. + */ +typedef union host_grxsts_data { @@ -68831,14 +82951,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- +#define DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5 +#define DWC_GRXSTS_PKTSTS_CH_HALTED 0x7 + -+ unsigned reserved:11; ++ unsigned reserved21_31:11; + } b; +} host_grxsts_data_t; + +/** + * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ, -+ * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the d32 element then -+ * read out the bits using the bit elements. ++ * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the d32 element ++ * then read out the bits using the bit elements. + */ +typedef union fifosize_data { + /** raw register data */ @@ -68863,10 +82983,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + struct { + unsigned nptxfspcavail:16; + unsigned nptxqspcavail:8; -+ /** Top of the Non-Periodic Transmit Request Queue ++ /** Top of the Non-Periodic Transmit Request Queue + * - bit 24 - Terminate (Last entry for the selected + * channel/EP) -+ * - bits 26:25 - Token Type ++ * - bits 26:25 - Token Type + * - 2'b00 - IN/OUT + * - 2'b01 - Zero Length OUT + * - 2'b10 - PING/Complete Split @@ -68913,13 +83033,81 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned ack:1; + unsigned i2csuspctl:1; + unsigned i2cdevaddr:2; -+ unsigned reserved:2; ++ unsigned i2cdatse0:1; ++ unsigned reserved:1; + unsigned rw:1; + unsigned bsydne:1; + } b; +} gi2cctl_data_t; + +/** ++ * This union represents the bit fields in the PHY Vendor Control Register ++ * (GPVNDCTL). Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++typedef union gpvndctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned regdata:8; ++ unsigned vctrl:8; ++ unsigned regaddr16_21:6; ++ unsigned regwr:1; ++ unsigned reserved23_24:2; ++ unsigned newregreq:1; ++ unsigned vstsbsy:1; ++ unsigned vstsdone:1; ++ unsigned reserved28_30:3; ++ unsigned disulpidrvr:1; ++ } b; ++} gpvndctl_data_t; ++ ++/** ++ * This union represents the bit fields in the General Purpose ++ * Input/Output Register (GGPIO). ++ * Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++typedef union ggpio_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned gpi:16; ++ unsigned gpo:16; ++ } b; ++} ggpio_data_t; ++ ++/** ++ * This union represents the bit fields in the User ID Register ++ * (GUID). Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++typedef union guid_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned rwdata:32; ++ } b; ++} guid_data_t; ++ ++/** ++ * This union represents the bit fields in the Synopsys ID Register ++ * (GSNPSID). Read the register into the d32 element then read out the ++ * bits using the bit elements. ++ */ ++typedef union gsnpsid_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ unsigned rwdata:32; ++ } b; ++} gsnpsid_data_t; ++ ++/** + * This union represents the bit fields in the User HW Config1 + * Register. Read the register into the d32 element then read + * out the bits using the bit elements. @@ -68986,7 +83174,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned nonperio_tx_q_depth:2; + unsigned host_perio_tx_q_depth:2; + unsigned dev_token_q_depth:5; -+ unsigned reserved31:1; ++ unsigned otg_enable_ic_usb:1; + } b; +} hwcfg2_data_t; + @@ -69008,9 +83196,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned vendor_ctrl_if:1; + unsigned optional_features:1; + unsigned synch_reset_type:1; -+ unsigned otg_enable_ic_usb:1; ++ unsigned adp_supp:1; + unsigned otg_enable_hsic:1; -+ unsigned reserved14:1; ++ unsigned bc_support:1; + unsigned otg_lpm_en:1; + unsigned dfifo_depth:16; + } b; @@ -69028,7 +83216,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + struct { + unsigned num_dev_perio_in_ep:4; + unsigned power_optimiz:1; -+ unsigned min_ahb_freq:9; ++ unsigned min_ahb_freq:1; ++ unsigned hiber:1; ++ unsigned xhiber:1; ++ unsigned reserved:6; + unsigned utmi_phy_data_width:2; + unsigned num_dev_mode_ctrl_ep:4; + unsigned iddig_filt_en:1; @@ -69043,6 +83234,229 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + } b; +} hwcfg4_data_t; + ++/** ++ * This union represents the bit fields of the Core LPM Configuration ++ * Register (GLPMCFG). Set the bits using bit fields then write ++ * the d32 value to the register. ++ */ ++typedef union glpmctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** LPM-Capable (LPMCap) (Device and Host) ++ * The application uses this bit to control ++ * the DWC_otg core LPM capabilities. ++ */ ++ unsigned lpm_cap_en:1; ++ /** LPM response programmed by application (AppL1Res) (Device) ++ * Handshake response to LPM token pre-programmed ++ * by device application software. ++ */ ++ unsigned appl_resp:1; ++ /** Host Initiated Resume Duration (HIRD) (Device and Host) ++ * In Host mode this field indicates the value of HIRD ++ * to be sent in an LPM transaction. ++ * In Device mode this field is updated with the ++ * Received LPM Token HIRD bmAttribute ++ * when an ACK/NYET/STALL response is sent ++ * to an LPM transaction. ++ */ ++ unsigned hird:4; ++ /** RemoteWakeEnable (bRemoteWake) (Device and Host) ++ * In Host mode this bit indicates the value of remote ++ * wake up to be sent in wIndex field of LPM transaction. ++ * In Device mode this field is updated with the ++ * Received LPM Token bRemoteWake bmAttribute ++ * when an ACK/NYET/STALL response is sent ++ * to an LPM transaction. ++ */ ++ unsigned rem_wkup_en:1; ++ /** Enable utmi_sleep_n (EnblSlpM) (Device and Host) ++ * The application uses this bit to control ++ * the utmi_sleep_n assertion to the PHY when in L1 state. ++ */ ++ unsigned en_utmi_sleep:1; ++ /** HIRD Threshold (HIRD_Thres) (Device and Host) ++ */ ++ unsigned hird_thres:5; ++ /** LPM Response (CoreL1Res) (Device and Host) ++ * In Host mode this bit contains handsake response to ++ * LPM transaction. ++ * In Device mode the response of the core to ++ * LPM transaction received is reflected in these two bits. ++ - 0x0 : ERROR (No handshake response) ++ - 0x1 : STALL ++ - 0x2 : NYET ++ - 0x3 : ACK ++ */ ++ unsigned lpm_resp:2; ++ /** Port Sleep Status (SlpSts) (Device and Host) ++ * This bit is set as long as a Sleep condition ++ * is present on the USB bus. ++ */ ++ unsigned prt_sleep_sts:1; ++ /** Sleep State Resume OK (L1ResumeOK) (Device and Host) ++ * Indicates that the application or host ++ * can start resume from Sleep state. ++ */ ++ unsigned sleep_state_resumeok:1; ++ /** LPM channel Index (LPM_Chnl_Indx) (Host) ++ * The channel number on which the LPM transaction ++ * has to be applied while sending ++ * an LPM transaction to the local device. ++ */ ++ unsigned lpm_chan_index:4; ++ /** LPM Retry Count (LPM_Retry_Cnt) (Host) ++ * Number host retries that would be performed ++ * if the device response was not valid response. ++ */ ++ unsigned retry_count:3; ++ /** Send LPM Transaction (SndLPM) (Host) ++ * When set by application software, ++ * an LPM transaction containing two tokens ++ * is sent. ++ */ ++ unsigned send_lpm:1; ++ /** LPM Retry status (LPM_RetryCnt_Sts) (Host) ++ * Number of LPM Host Retries still remaining ++ * to be transmitted for the current LPM sequence ++ */ ++ unsigned retry_count_sts:3; ++ unsigned reserved28_29:2; ++ /** In host mode once this bit is set, the host ++ * configures to drive the HSIC Idle state on the bus. ++ * It then waits for the device to initiate the Connect sequence. ++ * In device mode once this bit is set, the device waits for ++ * the HSIC Idle line state on the bus. Upon receving the Idle ++ * line state, it initiates the HSIC Connect sequence. ++ */ ++ unsigned hsic_connect:1; ++ /** This bit overrides and functionally inverts ++ * the if_select_hsic input port signal. ++ */ ++ unsigned inv_sel_hsic:1; ++ } b; ++} glpmcfg_data_t; ++ ++/** ++ * This union represents the bit fields of the Core ADP Timer, Control and ++ * Status Register (ADPTIMCTLSTS). Set the bits using bit fields then write ++ * the d32 value to the register. ++ */ ++typedef union adpctl_data { ++ /** raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** Probe Discharge (PRB_DSCHG) ++ * These bits set the times for TADP_DSCHG. ++ * These bits are defined as follows: ++ * 2'b00 - 4 msec ++ * 2'b01 - 8 msec ++ * 2'b10 - 16 msec ++ * 2'b11 - 32 msec ++ */ ++ unsigned prb_dschg:2; ++ /** Probe Delta (PRB_DELTA) ++ * These bits set the resolution for RTIM value. ++ * The bits are defined in units of 32 kHz clock cycles as follows: ++ * 2'b00 - 1 cycles ++ * 2'b01 - 2 cycles ++ * 2'b10 - 3 cycles ++ * 2'b11 - 4 cycles ++ * For example if this value is chosen to 2'b01, it means that RTIM ++ * increments for every 3(three) 32Khz clock cycles. ++ */ ++ unsigned prb_delta:2; ++ /** Probe Period (PRB_PER) ++ * These bits sets the TADP_PRD as shown in Figure 4 as follows: ++ * 2'b00 - 0.625 to 0.925 sec (typical 0.775 sec) ++ * 2'b01 - 1.25 to 1.85 sec (typical 1.55 sec) ++ * 2'b10 - 1.9 to 2.6 sec (typical 2.275 sec) ++ * 2'b11 - Reserved ++ */ ++ unsigned prb_per:2; ++ /** These bits capture the latest time it took for VBUS to ramp from ++ * VADP_SINK to VADP_PRB. ++ * 0x000 - 1 cycles ++ * 0x001 - 2 cycles ++ * 0x002 - 3 cycles ++ * etc ++ * 0x7FF - 2048 cycles ++ * A time of 1024 cycles at 32 kHz corresponds to a time of 32 msec. ++ */ ++ unsigned rtim:11; ++ /** Enable Probe (EnaPrb) ++ * When programmed to 1'b1, the core performs a probe operation. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned enaprb:1; ++ /** Enable Sense (EnaSns) ++ * When programmed to 1'b1, the core performs a Sense operation. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned enasns:1; ++ /** ADP Reset (ADPRes) ++ * When set, ADP controller is reset. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adpres:1; ++ /** ADP Enable (ADPEn) ++ * When set, the core performs either ADP probing or sensing ++ * based on EnaPrb or EnaSns. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adpen:1; ++ /** ADP Probe Interrupt (ADP_PRB_INT) ++ * When this bit is set, it means that the VBUS ++ * voltage is greater than VADP_PRB or VADP_PRB is reached. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_prb_int:1; ++ /** ++ * ADP Sense Interrupt (ADP_SNS_INT) ++ * When this bit is set, it means that the VBUS voltage is greater than ++ * VADP_SNS value or VADP_SNS is reached. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_sns_int:1; ++ /** ADP Tomeout Interrupt (ADP_TMOUT_INT) ++ * This bit is relevant only for an ADP probe. ++ * When this bit is set, it means that the ramp time has ++ * completed ie ADPCTL.RTIM has reached its terminal value ++ * of 0x7FF. This is a debug feature that allows software ++ * to read the ramp time after each cycle. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_tmout_int:1; ++ /** ADP Probe Interrupt Mask (ADP_PRB_INT_MSK) ++ * When this bit is set, it unmasks the interrupt due to ADP_PRB_INT. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_prb_int_msk:1; ++ /** ADP Sense Interrupt Mask (ADP_SNS_INT_MSK) ++ * When this bit is set, it unmasks the interrupt due to ADP_SNS_INT. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_sns_int_msk:1; ++ /** ADP Timoeout Interrupt Mask (ADP_TMOUT_MSK) ++ * When this bit is set, it unmasks the interrupt due to ADP_TMOUT_INT. ++ * This bit is valid only if OTG_Ver = 1'b1. ++ */ ++ unsigned adp_tmout_int_msk:1; ++ /** Access Request ++ * 2'b00 - Read/Write Valid (updated by the core) ++ * 2'b01 - Read ++ * 2'b00 - Write ++ * 2'b00 - Reserved ++ */ ++ unsigned ar:2; ++ /** Reserved */ ++ unsigned reserved29_31:3; ++ } b; ++} adpctl_data_t; ++ +//////////////////////////////////////////// +// Device Registers +/** @@ -69123,7 +83537,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned nzstsouthshk:1; +#define DWC_DCFG_SEND_STALL 1 + -+ unsigned reserved3:1; ++ unsigned ena32khzs:1; + /** Device Addresses */ + unsigned devaddr:7; + /** Periodic Frame Interval */ @@ -69132,12 +83546,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- +#define DWC_DCFG_FRAME_INTERVAL_85 1 +#define DWC_DCFG_FRAME_INTERVAL_90 2 +#define DWC_DCFG_FRAME_INTERVAL_95 3 ++ ++ /** Enable Device OUT NAK for bulk in DDMA mode */ ++ unsigned endevoutnak:1; + -+ unsigned reserved13_17:5; ++ unsigned reserved14_17:4; + /** In Endpoint Mis-match count */ + unsigned epmscnt:5; + /** Enable Descriptor DMA in Device mode */ + unsigned descdma:1; ++ unsigned perschintvl:2; ++ unsigned resvalid:6; + } b; +} dcfg_data_t; + @@ -69169,19 +83588,20 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned sgoutnak:1; + /** Clear Global OUT NAK */ + unsigned cgoutnak:1; -+ + /** Power-On Programming Done */ + unsigned pwronprgdone:1; -+ /** Global Continue on BNA */ -+ unsigned gcontbna:1; ++ /** Reserved */ ++ unsigned reserved:1; + /** Global Multi Count */ + unsigned gmc:2; + /** Ignore Frame Number for ISOC EPs */ + unsigned ifrmnum:1; + /** NAK on Babble */ + unsigned nakonbble:1; ++ /** Enable Continue on BNA */ ++ unsigned encontonbna:1; + -+ unsigned reserved17_31:15; ++ unsigned reserved18_31:14; + } b; +} dctl_data_t; + @@ -69236,9 +83656,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned intktxfemp:1; + /** IN Token Received with EP mismatch mask */ + unsigned intknepmis:1; -+ /** IN Endpoint HAK Effective mask */ ++ /** IN Endpoint NAK Effective mask */ + unsigned inepnakeff:1; -+ /** IN Endpoint HAK Effective mask */ ++ /** Reserved */ + unsigned emptyintr:1; + + unsigned txfifoundrn:1; @@ -69255,7 +83675,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- +} diepint_data_t; + +/** -+ * This union represents the bit fields in the Device IN EP ++ * This union represents the bit fields in the Device IN EP + * Common/Dedicated Interrupt Mask Register. + */ +typedef union diepint_data diepmsk_data_t; @@ -69302,13 +83722,15 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned nak:1; + /** NYET Interrupt */ + unsigned nyet:1; ++ /** Bit indicating setup packet received */ ++ unsigned sr:1; + -+ unsigned reserved15_31:17; ++ unsigned reserved16_31:16; + } b; +} doepint_data_t; + +/** -+ * This union represents the bit fields in the Device OUT EP ++ * This union represents the bit fields in the Device OUT EP + * Common/Dedicated Interrupt Mask Register. + */ +typedef union doepint_data doepmsk_data_t; @@ -69413,8 +83835,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned rx_thr_en:1; + /** Rx Thr. Length */ + unsigned rx_thr_len:9; ++ unsigned reserved26:1; ++ /** Arbiter Parking Enable*/ ++ unsigned arbprken:1; + /** Reserved */ -+ unsigned reserved26_31:6; ++ unsigned reserved28_31:4; + } b; +} dthrctl_data_t; + @@ -69467,9 +83892,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + /** Device OUT Endpoint Control Register. Offset:B00h + + * (ep_num * 20h) + 00h */ + volatile uint32_t doepctl; -+ /** Device OUT Endpoint Frame number Register. Offset: -+ * B00h + (ep_num * 20h) + 04h */ -+ volatile uint32_t doepfn; ++ /** Reserved. Offset:B00h + (ep_num * 20h) + 04h */ ++ uint32_t reserved04; + /** Device OUT Endpoint Interrupt Register. Offset:B00h + + * (ep_num * 20h) + 08h */ + volatile uint32_t doepint; @@ -69498,7 +83922,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + uint32_t d32; + /** register bits */ + struct { -+ /** Maximum Packet Size ++ /** Maximum Packet Size + * IN/OUT EPn + * IN/OUT EP0 - 2 bits + * 2'b00: 64 Bytes @@ -69511,8 +83935,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- +#define DWC_DEP0CTL_MPS_16 2 +#define DWC_DEP0CTL_MPS_8 3 + -+ /** Next Endpoint -+ * IN EPn/IN EP0 ++ /** Next Endpoint ++ * IN EPn/IN EP0 + * OUT EPn/OUT EP0 - reserved */ + unsigned nextep:4; + @@ -69528,7 +83952,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + * activated. Application use the SetD1PID and + * SetD0PID fields of this register to program either + * D0 or D1 PID. -+ * ++ * + * The encoding for this field is + * - 0: D0 + * - 1: D1 @@ -69538,14 +83962,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + /** NAK Status */ + unsigned naksts:1; + -+ /** Endpoint Type ++ /** Endpoint Type + * 2'b00: Control + * 2'b01: Isochronous + * 2'b10: Bulk + * 2'b11: Interrupt */ + unsigned eptype:2; + -+ /** Snoop Mode ++ /** Snoop Mode + * OUT EPn/OUT EP0 + * IN EPn/IN EP0 - reserved */ + unsigned snp:1; @@ -69553,7 +83977,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + /** Stall Handshake */ + unsigned stall:1; + -+ /** Tx Fifo Number ++ /** Tx Fifo Number + * IN EPn/IN EP0 + * OUT EPn/OUT EP0 - reserved */ + unsigned txfnum:4; @@ -69599,6 +84023,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + struct { + /** Transfer size */ + unsigned xfersize:19; ++/** Max packet count for EP (pow(2,10)-1) */ ++#define MAX_PKT_CNT 1023 + /** Packet Count */ + unsigned pktcnt:10; + /** Multi Count - Periodic IN endpoints */ @@ -69622,9 +84048,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + /** Reserved */ + unsigned reserved7_18:12; + /** Packet Count */ -+ unsigned pktcnt:1; ++ unsigned pktcnt:2; + /** Reserved */ -+ unsigned reserved20_28:9; ++ unsigned reserved21_28:8; + /**Setup Packet Count (DOEPTSIZ0 Only) */ + unsigned supcnt:2; + unsigned reserved31; @@ -69652,7 +84078,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- +/** + * 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 ++ * set/clear the bits using the bit, b_iso_out and + * b_iso_in elements. + */ +typedef union dev_dma_desc_sts { @@ -69662,8 +84088,9 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + struct { + /** Received number of bytes */ + unsigned bytes:16; -+ -+ unsigned reserved16_22:7; ++ /** NAK bit - only for OUT EPs */ ++ unsigned nak:1; ++ unsigned reserved17_22:6; + /** Multiple Transfer - only for OUT EPs */ + unsigned mtrf:1; + /** Setup Packet received - only for OUT EPs */ @@ -69680,7 +84107,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned bs:2; + } b; + -+#ifdef DWC_EN_ISOC ++//#ifdef DWC_EN_ISOC + /** iso out quadlet bits */ + struct { + /** Received number of bytes */ @@ -69722,11 +84149,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + /** Buffer Status */ + unsigned bs:2; + } b_iso_in; -+#endif /* DWC_EN_ISOC */ ++//#endif /* DWC_EN_ISOC */ +} dev_dma_desc_sts_t; + -+/** -+ * DMA Descriptor structure ++/** ++ * DMA Descriptor structure + * + * DMA Descriptor structure contains two quadlets: + * Status quadlet and Data buffer pointer. @@ -69750,8 +84177,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + dwc_otg_device_global_regs_t *dev_global_regs; +#define DWC_DEV_GLOBAL_REG_OFFSET 0x800 + -+ /** -+ * Device Logical IN Endpoint-Specific Registers 900h-AFCh ++ /** ++ * Device Logical IN Endpoint-Specific Registers 900h-AFCh + */ + dwc_otg_dev_in_ep_regs_t *in_ep_regs[MAX_EPS_CHANNELS]; +#define DWC_DEV_IN_EP_REG_OFFSET 0x900 @@ -69805,6 +84232,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + + /** Setup Packet Detected - if set clear NAK when queueing */ + uint32_t spd; ++ /** Isoc ep pointer on which incomplete happens */ ++ void *isoc_ep; + +} dwc_otg_dev_if_t; + @@ -69835,20 +84264,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + volatile uint32_t hflbaddr; +} dwc_otg_host_global_regs_t; + -+ +/** + * This union represents the bit fields in the Host Configuration Register. + * Read the register into the d32 member then set/clear the bits using + * the bit elements. Write the d32 member to the hcfg register. + */ -+typedef union hcfg_data -+{ ++typedef union hcfg_data { + /** raw register data */ + uint32_t d32; + + /** register bits */ -+ struct -+ { ++ struct { + /** FS/LS Phy Clock Select */ + unsigned fslspclksel:2; +#define DWC_HCFG_30_60_MHZ 0 @@ -69857,21 +84283,26 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + + /** FS/LS Only Support */ + unsigned fslssupp:1; -+ unsigned reserved3_22 : 20; ++ unsigned reserved3_6:4; ++ /** Enable 32-KHz Suspend Mode */ ++ unsigned ena32khzs:1; ++ /** Resume Validation Periiod */ ++ unsigned resvalid:8; ++ unsigned reserved16_22:7; + /** Enable Scatter/gather DMA in Host mode */ -+ unsigned descdma : 1; ++ unsigned descdma:1; + /** Frame List Entries */ -+ unsigned frlisten: 2; ++ unsigned frlisten:2; + /** Enable Periodic Scheduling */ -+ unsigned perschedena: 1; -+ /** Periodic Scheduling Enabled Status */ -+ unsigned perschedstat: 1; ++ unsigned perschedena:1; ++ unsigned reserved27_30:4; ++ unsigned modechtimen:1; + } b; +} hcfg_data_t; + +/** + * This union represents the bit fields in the Host Frame Remaing/Number -+ * Register. ++ * Register. + */ +typedef union hfir_data { + /** raw register data */ @@ -69880,13 +84311,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + /** register bits */ + struct { + unsigned frint:16; -+ unsigned reserved:16; ++ unsigned hfirrldctrl:1; ++ unsigned reserved:15; + } b; +} hfir_data_t; + +/** + * This union represents the bit fields in the Host Frame Remaing/Number -+ * Register. ++ * Register. + */ +typedef union hfnum_data { + /** raw register data */ @@ -69957,8 +84389,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- +} hprt0_data_t; + +/** -+ * This union represents the bit fields in the Host All Interrupt -+ * Register. ++ * This union represents the bit fields in the Host All Interrupt ++ * Register. + */ +typedef union haint_data { + /** raw register data */ @@ -69991,8 +84423,8 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- +} haint_data_t; + +/** -+ * This union represents the bit fields in the Host All Interrupt -+ * Register. ++ * This union represents the bit fields in the Host All Interrupt ++ * Register. + */ +typedef union haintmsk_data { + /** raw register data */ @@ -70024,11 +84456,10 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + } b2; +} haintmsk_data_t; + -+/** ++/** + * Host Channel Specific Registers. 500h-5FCh + */ -+typedef struct dwc_otg_hc_regs -+{ ++typedef struct dwc_otg_hc_regs { + /** Host Channel 0 Characteristic Register. Offset: 500h + (chan_num * 20h) + 00h */ + volatile uint32_t hcchar; + /** Host Channel 0 Split Control Register. Offset: 500h + (chan_num * 20h) + 04h */ @@ -70126,16 +84557,14 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- +} hcsplt_data_t; + +/** -+ * This union represents the bit fields in the Host All Interrupt -+ * Register. ++ * This union represents the bit fields in the Host All Interrupt ++ * Register. + */ -+typedef union hcint_data -+{ ++typedef union hcint_data { + /** raw register data */ + uint32_t d32; + /** register bits */ -+ struct -+ { ++ struct { + /** Transfer Complete */ + unsigned xfercomp:1; + /** Channel Halted */ @@ -70159,13 +84588,13 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + /** Data Toggle Error */ + unsigned datatglerr:1; + /** Buffer Not Available (only for DDMA mode) */ -+ unsigned bna : 1; ++ unsigned bna:1; + /** Exessive transaction error (only for DDMA mode) */ -+ unsigned xcs_xact : 1; ++ unsigned xcs_xact:1; + /** Frame List Rollover interrupt */ -+ unsigned frm_list_roll : 1; ++ unsigned frm_list_roll:1; + /** Reserved */ -+ unsigned reserved14_31 : 18; ++ unsigned reserved14_31:18; + } b; +} hcint_data_t; + @@ -70175,29 +84604,27 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + * bits using the bit elements. Write the d32 member to the + * hcintmsk register. + */ -+typedef union hcintmsk_data -+{ ++typedef union hcintmsk_data { + /** raw register data */ + uint32_t d32; + + /** register bits */ -+ struct -+ { -+ unsigned xfercompl : 1; -+ unsigned chhltd : 1; -+ unsigned ahberr : 1; -+ unsigned stall : 1; -+ unsigned nak : 1; -+ unsigned ack : 1; -+ unsigned nyet : 1; -+ unsigned xacterr : 1; -+ unsigned bblerr : 1; -+ unsigned frmovrun : 1; -+ unsigned datatglerr : 1; -+ unsigned bna : 1; -+ unsigned xcs_xact : 1; -+ unsigned frm_list_roll : 1; -+ unsigned reserved14_31 : 18; ++ struct { ++ unsigned xfercompl:1; ++ unsigned chhltd:1; ++ unsigned ahberr:1; ++ unsigned stall:1; ++ unsigned nak:1; ++ unsigned ack:1; ++ unsigned nyet:1; ++ unsigned xacterr:1; ++ unsigned bblerr:1; ++ unsigned frmovrun:1; ++ unsigned datatglerr:1; ++ unsigned bna:1; ++ unsigned xcs_xact:1; ++ unsigned frm_list_roll:1; ++ unsigned reserved14_31:18; + } b; +} hcintmsk_data_t; + @@ -70208,14 +84635,12 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + * hcchar register. + */ + -+typedef union hctsiz_data -+{ ++typedef union hctsiz_data { + /** raw register data */ + uint32_t d32; + + /** register bits */ -+ struct -+ { ++ struct { + /** Total transfer size in bytes */ + unsigned xfersize:19; + @@ -70239,22 +84664,21 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + /** Do PING protocol when 1 */ + unsigned dopng:1; + } b; -+ ++ + /** register bits */ -+ struct -+ { ++ struct { + /** Scheduling information */ -+ unsigned schinfo : 8; -+ -+ /** Number of transfer descriptors. ++ unsigned schinfo:8; ++ ++ /** Number of transfer descriptors. + * Max value: -+ * 64 in general, ++ * 64 in general, + * 256 only for HS isochronous endpoint. + */ -+ unsigned ntd : 8; ++ unsigned ntd:8; + + /** Data packets to transfer */ -+ unsigned reserved16_28 : 13; ++ unsigned reserved16_28:13; + + /** + * Packet ID for next data packet @@ -70263,30 +84687,27 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + * 2: DATA1 + * 3: MDATA (non-Control) + */ -+ unsigned pid : 2; ++ unsigned pid:2; + + /** Do PING protocol when 1 */ -+ unsigned dopng : 1; ++ unsigned dopng:1; + } b_ddma; +} hctsiz_data_t; + -+ +/** -+ * This union represents the bit fields in the Host DMA Address ++ * This union represents the bit fields in the Host DMA Address + * Register used in Descriptor DMA mode. + */ -+typedef union hcdma_data -+{ ++typedef union hcdma_data { + /** raw register data */ + uint32_t d32; + /** register bits */ -+ struct -+ { -+ unsigned reserved0_2 : 3; ++ struct { ++ unsigned reserved0_2:3; + /** Current Transfer Descriptor. Not used for ISOC */ -+ unsigned ctd : 8; ++ unsigned ctd:8; + /** Start Address of Descriptor List */ -+ unsigned dma_addr : 21; ++ unsigned dma_addr:21; + } b; +} hcdma_data_t; + @@ -70295,8 +84716,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + * status quadlet for host mode. Read the quadlet into the d32 member then + * set/clear the bits using the bit elements. + */ -+typedef union host_dma_desc_sts -+{ ++typedef union host_dma_desc_sts { + /** raw register data */ + uint32_t d32; + /** quadlet bits */ @@ -70304,44 +84724,44 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + /* for non-isochronous */ + struct { + /** Number of bytes */ -+ unsigned n_bytes : 17; ++ unsigned n_bytes:17; + /** QTD offset to jump when Short Packet received - only for IN EPs */ -+ unsigned qtd_offset : 6; -+ /** -+ * Set to request the core to jump to alternate QTD if -+ * Short Packet received - only for IN EPs ++ unsigned qtd_offset:6; ++ /** ++ * Set to request the core to jump to alternate QTD if ++ * Short Packet received - only for IN EPs + */ -+ unsigned a_qtd : 1; -+ /** ++ unsigned a_qtd:1; ++ /** + * Setup Packet bit. When set indicates that buffer contains -+ * setup packet. ++ * setup packet. + */ -+ unsigned sup : 1; ++ unsigned sup:1; + /** Interrupt On Complete */ -+ unsigned ioc : 1; ++ unsigned ioc:1; + /** End of List */ -+ unsigned eol : 1; -+ unsigned reserved27 : 1; ++ unsigned eol:1; ++ unsigned reserved27:1; + /** Rx/Tx Status */ -+ unsigned sts : 2; -+ #define DMA_DESC_STS_PKTERR 1 -+ unsigned reserved30 : 1; ++ unsigned sts:2; ++#define DMA_DESC_STS_PKTERR 1 ++ unsigned reserved30:1; + /** Active Bit */ -+ unsigned a : 1; ++ unsigned a:1; + } b; + /* for isochronous */ + struct { + /** Number of bytes */ -+ unsigned n_bytes : 12; -+ unsigned reserved12_24 : 13; ++ unsigned n_bytes:12; ++ unsigned reserved12_24:13; + /** Interrupt On Complete */ -+ unsigned ioc : 1; -+ unsigned reserved26_27 : 2; ++ unsigned ioc:1; ++ unsigned reserved26_27:2; + /** Rx/Tx Status */ -+ unsigned sts : 2; -+ unsigned reserved30 : 1; ++ unsigned sts:2; ++ unsigned reserved30:1; + /** Active Bit */ -+ unsigned a : 1; ++ unsigned a:1; + } b_isoc; +} host_dma_desc_sts_t; + @@ -70349,18 +84769,17 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- +#define MAX_DMA_DESC_NUM_GENERIC 64 +#define MAX_DMA_DESC_NUM_HS_ISOC 256 +#define MAX_FRLIST_EN_NUM 64 -+/** -+ * Host-mode DMA Descriptor structure ++/** ++ * Host-mode DMA Descriptor structure + * + * DMA Descriptor structure contains two quadlets: + * Status quadlet and Data buffer pointer. + */ -+typedef struct dwc_otg_host_dma_desc -+{ ++typedef struct dwc_otg_host_dma_desc { + /** DMA Descriptor status quadlet */ -+ host_dma_desc_sts_t status; ++ host_dma_desc_sts_t status; + /** DMA Descriptor data buffer pointer */ -+ uint32_t buf; ++ uint32_t buf; +} dwc_otg_host_dma_desc_t; + +/** OTG Host Interface Structure. @@ -70397,7 +84816,7 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- +/** + * This union represents the bit fields in the Power and Clock Gating Control + * Register. Read the register into the d32 member then set/clear the -+ * bits using the bit elements. ++ * bits using the bit elements. + */ +typedef union pcgcctl_data { + /** raw register data */ @@ -70413,112 +84832,140 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/dwc_otg_regs.h linux-rpi-bootc- + unsigned pwrclmp:1; + /** Reset Power Down Modules */ + unsigned rstpdwnmodule:1; -+ /** PHY Suspended */ -+ unsigned physuspended:1; ++ /** Reserved */ ++ unsigned reserved:1; + /** Enable Sleep Clock Gating (Enbl_L1Gating) */ + unsigned enbl_sleep_gating:1; + /** PHY In Sleep (PhySleep) */ + unsigned phy_in_sleep:1; + /** Deep Sleep*/ + unsigned deep_sleep:1; -+ -+ unsigned reserved31_8:24; ++ unsigned resetaftsusp:1; ++ unsigned restoremode:1; ++ unsigned enbl_extnd_hiber:1; ++ unsigned extnd_hiber_pwrclmp:1; ++ unsigned extnd_hiber_switch:1; ++ unsigned ess_reg_restored:1; ++ unsigned prt_clk_sel:2; ++ unsigned port_power:1; ++ unsigned max_xcvrselect:2; ++ unsigned max_termsel:1; ++ unsigned mac_dev_addr:7; ++ unsigned p2hd_dev_enum_spd:2; ++ unsigned p2hd_prt_spd:2; ++ unsigned if_dev_mode:1; + } b; +} pcgcctl_data_t; + ++/** ++ * This union represents the bit fields in the Global Data FIFO Software ++ * Configuration Register. Read the register into the d32 member then ++ * set/clear the bits using the bit elements. ++ */ ++typedef union gdfifocfg_data { ++ /* raw register data */ ++ uint32_t d32; ++ /** register bits */ ++ struct { ++ /** OTG Data FIFO depth */ ++ unsigned gdfifocfg:16; ++ /** Start address of EP info controller */ ++ unsigned epinfobase:16; ++ } b; ++} gdfifocfg_data_t; ++ ++/** ++ * This union represents the bit fields in the Global Power Down Register ++ * Register. Read the register into the d32 member then set/clear the ++ * bits using the bit elements. ++ */ ++typedef union gpwrdn_data { ++ /* raw register data */ ++ uint32_t d32; ++ ++ /** register bits */ ++ struct { ++ /** PMU Interrupt Select */ ++ unsigned pmuintsel:1; ++ /** PMU Active */ ++ unsigned pmuactv:1; ++ /** Restore */ ++ unsigned restore:1; ++ /** Power Down Clamp */ ++ unsigned pwrdnclmp:1; ++ /** Power Down Reset */ ++ unsigned pwrdnrstn:1; ++ /** Power Down Switch */ ++ unsigned pwrdnswtch:1; ++ /** Disable VBUS */ ++ unsigned dis_vbus:1; ++ /** Line State Change */ ++ unsigned lnstschng:1; ++ /** Line state change mask */ ++ unsigned lnstchng_msk:1; ++ /** Reset Detected */ ++ unsigned rst_det:1; ++ /** Reset Detect mask */ ++ unsigned rst_det_msk:1; ++ /** Disconnect Detected */ ++ unsigned disconn_det:1; ++ /** Disconnect Detect mask */ ++ unsigned disconn_det_msk:1; ++ /** Connect Detected*/ ++ unsigned connect_det:1; ++ /** Connect Detected Mask*/ ++ unsigned connect_det_msk:1; ++ /** SRP Detected */ ++ unsigned srp_det:1; ++ /** SRP Detect mask */ ++ unsigned srp_det_msk:1; ++ /** Status Change Interrupt */ ++ unsigned sts_chngint:1; ++ /** Status Change Interrupt Mask */ ++ unsigned sts_chngint_msk:1; ++ /** Line State */ ++ unsigned linestate:2; ++ /** Indicates current mode(status of IDDIG signal) */ ++ unsigned idsts:1; ++ /** B Session Valid signal status*/ ++ unsigned bsessvld:1; ++ /** ADP Event Detected */ ++ unsigned adp_int:1; ++ /** Multi Valued ID pin */ ++ unsigned mult_val_id_bc:5; ++ /** Reserved 24_31 */ ++ unsigned reserved29_31:3; ++ } b; ++} gpwrdn_data_t; ++ +#endif -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/Makefile linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/Makefile ---- linux-3.2.23/drivers/usb/host/dwc_otg/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/Makefile 2012-07-15 20:29:19.058083099 +0200 -@@ -0,0 +1,85 @@ -+# -+# Makefile for DWC_otg Highspeed USB controller driver -+# +diff --git a/drivers/usb/host/dwc_otg/test/Makefile b/drivers/usb/host/dwc_otg/test/Makefile +new file mode 100644 +index 0000000..fc45375 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/test/Makefile +@@ -0,0 +1,16 @@ + -+ifneq ($(KERNELRELEASE),) ++PERL=/usr/bin/perl ++PL_TESTS=test_sysfs.pl test_mod_param.pl + -+ifeq ($(BUS_INTERFACE),) -+ # BUS_INTERFACE = -DLM_INTERFACE -+ BUS_INTERFACE = -DPLATFORM_INTERFACE=1 -+endif ++.PHONY : test ++test : perl_tests + -+ifeq ($(CONFIG_USB_DEBUG),y) -+CPPFLAGS += -DDEBUG -+endif -+ -+# Use one of the following flags to compile the software in host-only or -+# device-only mode. -+ifeq ($(CONFIG_USB_GADGET_DWCOTG),) -+CPPFLAGS += -DDWC_HOST_ONLY -+endif -+#CPPFLAGS += -DDWC_DEVICE_ONLY -+ -+# Use this flag to reduce SOF interrupt service overhead -+CPPFLAGS += -DSOF_FIX -+ -+CPPFLAGS += -Dlinux -DDWC_HS_ELECT_TST -+#CGG: CPPFLAGS += -DDWC_EN_ISOC -+CPPFLAGS += -I$(obj)/../dwc_common_port -+#CPPFLAGS += -I$(PORTLIB) -+CPPFLAGS += -DDWC_LINUX -+CPPFLAGS += $(CFI) -+CPPFLAGS += $(BUS_INTERFACE) -+ -+obj-$(CONFIG_USB_DWCOTG) += dwc_otg.o -+ -+dwc_otg-objs := dwc_otg_driver.o dwc_otg_attr.o -+dwc_otg-objs += dwc_otg_cil.o dwc_otg_cil_intr.o -+dwc_otg-objs += dwc_otg_pcd_linux.o dwc_otg_pcd.o dwc_otg_pcd_intr.o -+dwc_otg-objs += dwc_otg_hcd.o dwc_otg_hcd_linux.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o dwc_otg_hcd_ddma.o -+ifneq ($(CFI),) -+dwc_otg-objs += dwc_otg_cfi.o -+endif -+ -+kernrelwd := $(subst ., ,$(KERNELRELEASE)) -+kernrel3 := $(word 1,$(kernrelwd)).$(word 2,$(kernrelwd)).$(word 3,$(kernrelwd)) -+ -+ifneq ($(kernrel3),2.6.20) -+EXTRA_CFLAGS += $(CPPFLAGS) -+endif -+ -+else -+ -+PWD := $(shell pwd) -+PORTLIB := $(PWD)/../dwc_common_port -+ -+# Command paths -+CTAGS := $(CTAGS) -+DOXYGEN := $(DOXYGEN) -+ -+default: portlib -+ $(MAKE) -C$(KDIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules -+ -+install: default -+ifneq ($(INSTALL_MOD_PATH),) -+ $(MAKE) -C$(KDIR) M=$(PORTLIB) modules_install -+ $(MAKE) -C$(KDIR) M=$(PWD) modules_install -+else -+ @echo "No install path defined" -+endif -+ -+portlib: -+ $(MAKE) -C$(KDIR) M=$(PORTLIB) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules -+ cp $(PORTLIB)/Module.symvers $(PWD)/ -+ -+docs: $(wildcard *.[hc]) doc/doxygen.cfg -+ $(DOXYGEN) doc/doxygen.cfg -+ -+tags: $(wildcard *.[hc]) -+ $(CTAGS) -e $(wildcard *.[hc]) $(wildcard linux/*.[hc]) $(wildcard $(KDIR)/include/linux/usb*.h) -+ -+ -+clean: -+ rm -rf *.o *.ko .*cmd *.mod.c .tmp_versions -+ -+endif -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm ---- linux-3.2.23/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm 2012-07-15 20:29:19.079083527 +0200 ++perl_tests : ++ @echo ++ @echo Running perl tests ++ @for test in $(PL_TESTS); do \ ++ if $(PERL) ./$$test ; then \ ++ echo "=======> $$test, PASSED" ; \ ++ else echo "=======> $$test, FAILED" ; \ ++ fi \ ++ done +diff --git a/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm b/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm +new file mode 100644 +index 0000000..233b04a +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm @@ -0,0 +1,337 @@ +package dwc_otg_test; + @@ -70857,29 +85304,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/test/dwc_otg_test.pm linux-rpi- +); + +1; -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/test/Makefile linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/test/Makefile ---- linux-3.2.23/drivers/usb/host/dwc_otg/test/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/test/Makefile 2012-07-15 20:29:19.079083527 +0200 -@@ -0,0 +1,16 @@ -+ -+PERL=/usr/bin/perl -+PL_TESTS=test_sysfs.pl test_mod_param.pl -+ -+.PHONY : test -+test : perl_tests -+ -+perl_tests : -+ @echo -+ @echo Running perl tests -+ @for test in $(PL_TESTS); do \ -+ if $(PERL) ./$$test ; then \ -+ echo "=======> $$test, PASSED" ; \ -+ else echo "=======> $$test, FAILED" ; \ -+ fi \ -+ done -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/test/test_mod_param.pl linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/test/test_mod_param.pl ---- linux-3.2.23/drivers/usb/host/dwc_otg/test/test_mod_param.pl 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/test/test_mod_param.pl 2012-07-15 20:29:19.079083527 +0200 +diff --git a/drivers/usb/host/dwc_otg/test/test_mod_param.pl b/drivers/usb/host/dwc_otg/test/test_mod_param.pl +new file mode 100644 +index 0000000..e887dce +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/test/test_mod_param.pl @@ -0,0 +1,133 @@ +#!/usr/bin/perl -w +# @@ -71014,9 +85443,11 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/test/test_mod_param.pl linux-rp + +test_main(); +0; -diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/test/test_sysfs.pl linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/test/test_sysfs.pl ---- linux-3.2.23/drivers/usb/host/dwc_otg/test/test_sysfs.pl 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/dwc_otg/test/test_sysfs.pl 2012-07-15 20:29:19.079083527 +0200 +diff --git a/drivers/usb/host/dwc_otg/test/test_sysfs.pl b/drivers/usb/host/dwc_otg/test/test_sysfs.pl +new file mode 100644 +index 0000000..abcf284 +--- /dev/null ++++ b/drivers/usb/host/dwc_otg/test/test_sysfs.pl @@ -0,0 +1,193 @@ +#!/usr/bin/perl -w +# @@ -71211,55 +85642,48 @@ diff -Naur linux-3.2.23/drivers/usb/host/dwc_otg/test/test_sysfs.pl linux-rpi-bo + +test_main(); +0; -diff -Naur linux-3.2.23/drivers/usb/host/Kconfig linux-rpi-bootc-3.2.23/drivers/usb/host/Kconfig ---- linux-3.2.23/drivers/usb/host/Kconfig 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/Kconfig 2012-07-15 20:29:18.995081945 +0200 -@@ -556,6 +556,19 @@ - To compile this driver a module, choose M here: the module - will be called "hwa-hc". +diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig +index d83e967..a488cd7 100644 +--- a/drivers/video/Kconfig ++++ b/drivers/video/Kconfig +@@ -312,6 +312,20 @@ config FB_PM2_FIFO_DISCONNECT + help + Support the Permedia2 FIFO disconnect feature. -+config USB_DWCOTG -+ tristate "Synopsis DWC host support" -+ depends on USB ++config FB_BCM2708 ++ tristate "BCM2708 framebuffer support" ++ depends on FB && ARM ++ select FB_CFB_FILLRECT ++ select FB_CFB_COPYAREA ++ select FB_CFB_IMAGEBLIT + help -+ The Synopsis DWC controller is a dual-role -+ host/peripheral/OTG ("On The Go") USB controllers. ++ This framebuffer device driver is for the BCM2708 framebuffer. + -+ Enable this option to support this IP in host controller mode. -+ If unsure, say N. ++ If you want to compile this as a module (=code which can be ++ inserted into and removed from the running kernel), say M ++ here and read . The module ++ will be called bcm2708_fb. + -+ To compile this driver as a module, choose M here: the -+ modules built will be called dwc_otg and dwc_common_port. -+ - config USB_IMX21_HCD - tristate "i.MX21 HCD support" - depends on USB && ARM && ARCH_MXC -diff -Naur linux-3.2.23/drivers/usb/host/Makefile linux-rpi-bootc-3.2.23/drivers/usb/host/Makefile ---- linux-3.2.23/drivers/usb/host/Makefile 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/usb/host/Makefile 2012-07-15 20:29:18.988081815 +0200 -@@ -33,6 +33,8 @@ - obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o - obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o - obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o -+ -+obj-$(CONFIG_USB_DWCOTG) += dwc_otg/ dwc_common_port/ - obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o - obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o - obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o -diff -Naur linux-3.2.23/drivers/usb/Makefile linux-rpi-bootc-3.2.23/drivers/usb/Makefile ---- linux-3.2.23/drivers/usb/Makefile 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/usb/Makefile 2012-07-15 20:29:18.536073310 +0200 -@@ -23,6 +23,7 @@ - obj-$(CONFIG_USB_R8A66597_HCD) += host/ - obj-$(CONFIG_USB_HWA_HCD) += host/ - obj-$(CONFIG_USB_ISP1760_HCD) += host/ -+obj-$(CONFIG_USB_DWCOTG) += host/ - obj-$(CONFIG_USB_IMX21_HCD) += host/ - obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/ - -diff -Naur linux-3.2.23/drivers/video/bcm2708_fb.c linux-rpi-bootc-3.2.23/drivers/video/bcm2708_fb.c ---- linux-3.2.23/drivers/video/bcm2708_fb.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/video/bcm2708_fb.c 2012-07-15 20:29:07.886872929 +0200 + config FB_ARMCLCD + tristate "ARM PrimeCell PL110 support" + depends on FB && ARM && ARM_AMBA +diff --git a/drivers/video/Makefile b/drivers/video/Makefile +index 9b9d8ff..6e9e8e9 100644 +--- a/drivers/video/Makefile ++++ b/drivers/video/Makefile +@@ -96,6 +96,7 @@ obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o + obj-$(CONFIG_FB_PVR2) += pvr2fb.o + obj-$(CONFIG_FB_VOODOO1) += sstfb.o + obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o ++obj-$(CONFIG_FB_BCM2708) += bcm2708_fb.o + obj-$(CONFIG_FB_68328) += 68328fb.o + obj-$(CONFIG_FB_GBE) += gbefb.o + obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o +diff --git a/drivers/video/bcm2708_fb.c b/drivers/video/bcm2708_fb.c +new file mode 100644 +index 0000000..5ca8aca +--- /dev/null ++++ b/drivers/video/bcm2708_fb.c @@ -0,0 +1,487 @@ +/* + * linux/drivers/video/bcm2708_fb.c @@ -71637,8 +86061,8 @@ diff -Naur linux-3.2.23/drivers/video/bcm2708_fb.c linux-rpi-bootc-3.2.23/driver + fb->fb.var.vmode = FB_VMODE_NONINTERLACED; + fb->fb.var.activate = FB_ACTIVATE_NOW; + fb->fb.var.nonstd = 0; -+ fb->fb.var.height = fbwidth; -+ fb->fb.var.width = fbheight; ++ fb->fb.var.height = -1; /* height of picture in mm */ ++ fb->fb.var.width = -1; /* width of picture in mm */ + fb->fb.var.accel_flags = 0; + + fb->fb.monspecs.hfmin = 0; @@ -71748,33 +86172,10 @@ diff -Naur linux-3.2.23/drivers/video/bcm2708_fb.c linux-rpi-bootc-3.2.23/driver +MODULE_PARM_DESC(fbwidth, "Width of ARM Framebuffer"); +MODULE_PARM_DESC(fbheight, "Height of ARM Framebuffer"); +MODULE_PARM_DESC(fbdepth, "Bit depth of ARM Framebuffer"); -diff -Naur linux-3.2.23/drivers/video/Kconfig linux-rpi-bootc-3.2.23/drivers/video/Kconfig ---- linux-3.2.23/drivers/video/Kconfig 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/video/Kconfig 2012-07-15 20:29:07.824871765 +0200 -@@ -312,6 +312,20 @@ - help - Support the Permedia2 FIFO disconnect feature. - -+config FB_BCM2708 -+ tristate "BCM2708 framebuffer support" -+ depends on FB && ARM -+ select FB_CFB_FILLRECT -+ select FB_CFB_COPYAREA -+ select FB_CFB_IMAGEBLIT -+ help -+ This framebuffer device driver is for the BCM2708 framebuffer. -+ -+ If you want to compile this as a module (=code which can be -+ inserted into and removed from the running kernel), say M -+ here and read . The module -+ will be called bcm2708_fb. -+ - config FB_ARMCLCD - tristate "ARM PrimeCell PL110 support" - depends on FB && ARM && ARM_AMBA -diff -Naur linux-3.2.23/drivers/video/logo/logo_linux_clut224.ppm linux-rpi-bootc-3.2.23/drivers/video/logo/logo_linux_clut224.ppm ---- linux-3.2.23/drivers/video/logo/logo_linux_clut224.ppm 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/video/logo/logo_linux_clut224.ppm 2012-07-15 20:29:05.160821635 +0200 +diff --git a/drivers/video/logo/logo_linux_clut224.ppm b/drivers/video/logo/logo_linux_clut224.ppm +index 3c14e43..7626beb 100644 +--- a/drivers/video/logo/logo_linux_clut224.ppm ++++ b/drivers/video/logo/logo_linux_clut224.ppm @@ -1,1604 +1,883 @@ P3 -# Standard 224-color Linux logo @@ -74261,20 +88662,40 @@ diff -Naur linux-3.2.23/drivers/video/logo/logo_linux_clut224.ppm linux-rpi-boot +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 -diff -Naur linux-3.2.23/drivers/video/Makefile linux-rpi-bootc-3.2.23/drivers/video/Makefile ---- linux-3.2.23/drivers/video/Makefile 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/video/Makefile 2012-07-15 20:29:03.534791038 +0200 -@@ -96,6 +96,7 @@ - obj-$(CONFIG_FB_PVR2) += pvr2fb.o - obj-$(CONFIG_FB_VOODOO1) += sstfb.o - obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o -+obj-$(CONFIG_FB_BCM2708) += bcm2708_fb.o - obj-$(CONFIG_FB_68328) += 68328fb.o - obj-$(CONFIG_FB_GBE) += gbefb.o - obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o -diff -Naur linux-3.2.23/drivers/watchdog/bcm2708_wdog.c linux-rpi-bootc-3.2.23/drivers/watchdog/bcm2708_wdog.c ---- linux-3.2.23/drivers/watchdog/bcm2708_wdog.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/drivers/watchdog/bcm2708_wdog.c 2012-07-15 20:29:50.389672677 +0200 +diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig +index 79fd606..bd76a65 100644 +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -343,6 +343,12 @@ config IMX2_WDT + To compile this driver as a module, choose M here: the + module will be called imx2_wdt. + ++config BCM2708_WDT ++ tristate "BCM2708 Watchdog" ++ depends on ARCH_BCM2708 ++ help ++ Enables BCM2708 watchdog support. ++ + # AVR32 Architecture + + config AT32AP700X_WDT +diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile +index fe893e9..897ab01 100644 +--- a/drivers/watchdog/Makefile ++++ b/drivers/watchdog/Makefile +@@ -53,6 +53,7 @@ obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o + obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o + obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o + obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o ++obj-$(CONFIG_BCM2708_WDT) += bcm2708_wdog.o + + # AVR32 Architecture + obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o +diff --git a/drivers/watchdog/bcm2708_wdog.c b/drivers/watchdog/bcm2708_wdog.c +new file mode 100644 +index 0000000..dd33c35 +--- /dev/null ++++ b/drivers/watchdog/bcm2708_wdog.c @@ -0,0 +1,385 @@ +/* + * Broadcom BCM2708 watchdog driver. @@ -74661,37 +89082,31 @@ diff -Naur linux-3.2.23/drivers/watchdog/bcm2708_wdog.c linux-rpi-bootc-3.2.23/d +MODULE_ALIAS_MISCDEV(TEMP_MINOR); +MODULE_LICENSE("GPL"); + -diff -Naur linux-3.2.23/drivers/watchdog/Kconfig linux-rpi-bootc-3.2.23/drivers/watchdog/Kconfig ---- linux-3.2.23/drivers/watchdog/Kconfig 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/watchdog/Kconfig 2012-07-15 20:29:50.364672206 +0200 -@@ -343,6 +343,12 @@ - To compile this driver as a module, choose M here: the - module will be called imx2_wdt. +diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h +index deb6282..e97b341 100644 +--- a/include/linux/mmc/host.h ++++ b/include/linux/mmc/host.h +@@ -242,6 +242,7 @@ struct mmc_host { + #define MMC_CAP2_CACHE_CTRL (1 << 1) /* Allow cache control */ + #define MMC_CAP2_POWEROFF_NOTIFY (1 << 2) /* Notify poweroff supported */ + #define MMC_CAP2_NO_MULTI_READ (1 << 3) /* Multiblock reads don't work */ ++#define MMC_CAP2_FORCE_MULTIBLOCK (1 << 4) /* Always use multiblock transfers */ -+config BCM2708_WDT -+ tristate "BCM2708 Watchdog" -+ depends on ARCH_BCM2708 -+ help -+ Enables BCM2708 watchdog support. -+ - # AVR32 Architecture + mmc_pm_flag_t pm_caps; /* supported pm features */ + unsigned int power_notify_type; +diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h +index e4b6935..d307033 100644 +--- a/include/linux/mmc/sdhci.h ++++ b/include/linux/mmc/sdhci.h +@@ -93,6 +93,7 @@ struct sdhci_host { + #define SDHCI_QUIRK2_OWN_CARD_DETECTION (1<<0) - config AT32AP700X_WDT -diff -Naur linux-3.2.23/drivers/watchdog/Makefile linux-rpi-bootc-3.2.23/drivers/watchdog/Makefile ---- linux-3.2.23/drivers/watchdog/Makefile 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/drivers/watchdog/Makefile 2012-07-15 20:29:50.262670287 +0200 -@@ -53,6 +53,7 @@ - obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o - obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o - obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o -+obj-$(CONFIG_BCM2708_WDT) += bcm2708_wdog.o + int irq; /* Device IRQ */ ++ int second_irq; /* Additional IRQ to disable/enable in low-latency mode */ + void __iomem *ioaddr; /* Mapped address */ - # AVR32 Architecture - obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o -diff -Naur linux-3.2.23/include/linux/mmc/sdhci.h linux-rpi-bootc-3.2.23/include/linux/mmc/sdhci.h ---- linux-3.2.23/include/linux/mmc/sdhci.h 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/include/linux/mmc/sdhci.h 2012-07-15 20:28:57.500677501 +0200 -@@ -121,6 +121,7 @@ + const struct sdhci_ops *ops; /* Low level hw interface */ +@@ -121,6 +122,7 @@ struct sdhci_host { #define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */ #define SDHCI_PV_ENABLED (1<<8) /* Preset value enabled */ #define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ @@ -74699,7 +89114,7 @@ diff -Naur linux-3.2.23/include/linux/mmc/sdhci.h linux-rpi-bootc-3.2.23/include unsigned int version; /* SDHCI spec. version */ -@@ -135,6 +136,7 @@ +@@ -135,6 +137,7 @@ struct sdhci_host { struct mmc_request *mrq; /* Current request */ struct mmc_command *cmd; /* Current command */ @@ -74707,9 +89122,1543 @@ diff -Naur linux-3.2.23/include/linux/mmc/sdhci.h linux-rpi-bootc-3.2.23/include struct mmc_data *data; /* Current data request */ unsigned int data_early:1; /* Data finished before cmd */ -diff -Naur linux-3.2.23/sound/arm/bcm2835.c linux-rpi-bootc-3.2.23/sound/arm/bcm2835.c ---- linux-3.2.23/sound/arm/bcm2835.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/sound/arm/bcm2835.c 2012-07-15 20:28:25.381073128 +0200 +diff --git a/kernel/module.c b/kernel/module.c +index 6969ef0..0a64968 100644 +--- a/kernel/module.c ++++ b/kernel/module.c +@@ -2604,20 +2604,23 @@ static int move_module(struct module *mod, struct load_info *info) + memset(ptr, 0, mod->core_size); + mod->module_core = ptr; + +- ptr = module_alloc_update_bounds(mod->init_size); +- /* +- * The pointer to this block is stored in the module structure +- * which is inside the block. This block doesn't need to be +- * scanned as it contains data and code that will be freed +- * after the module is initialized. +- */ +- kmemleak_ignore(ptr); +- if (!ptr && mod->init_size) { +- module_free(mod, mod->module_core); +- return -ENOMEM; ++ if (mod->init_size) { ++ ptr = module_alloc_update_bounds(mod->init_size); ++ /* ++ * The pointer to this block is stored in the module structure ++ * which is inside the block. This block doesn't need to be ++ * scanned as it contains data and code that will be freed ++ * after the module is initialized. ++ */ ++ kmemleak_ignore(ptr); ++ if (!ptr && mod->init_size) { ++ module_free(mod, mod->module_core); ++ return -ENOMEM; ++ } ++ memset(ptr, 0, mod->init_size); ++ mod->module_init = ptr; + } +- memset(ptr, 0, mod->init_size); +- mod->module_init = ptr; ++ else mod->module_init = NULL; + + /* Transfer each section which specifies SHF_ALLOC */ + DEBUGP("final section addresses:\n"); +diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig +index 885683a..3577572 100644 +--- a/sound/arm/Kconfig ++++ b/sound/arm/Kconfig +@@ -39,5 +39,12 @@ config SND_PXA2XX_AC97 + Say Y or M if you want to support any AC97 codec attached to + the PXA2xx AC97 interface. + ++config SND_BCM2835 ++ tristate "BCM2835 ALSA driver" ++ depends on ARCH_BCM2708 && SND ++ select SND_PCM ++ help ++ Say Y or M if you want to support BCM2835 Alsa pcm card driver ++ + endif # SND_ARM + +diff --git a/sound/arm/Makefile b/sound/arm/Makefile +index 8c0c851..181cb57 100644 +--- a/sound/arm/Makefile ++++ b/sound/arm/Makefile +@@ -14,3 +14,9 @@ snd-pxa2xx-lib-$(CONFIG_SND_PXA2XX_LIB_AC97) += pxa2xx-ac97-lib.o + + obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o + snd-pxa2xx-ac97-objs := pxa2xx-ac97.o ++ ++obj-$(CONFIG_SND_BCM2835) += snd-bcm2835.o ++snd-bcm2835-objs := bcm2835.o bcm2835-ctl.o bcm2835-pcm.o bcm2835-vchiq.o ++ ++EXTRA_CFLAGS += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000 ++ +diff --git a/sound/arm/bcm2835-ctl.c b/sound/arm/bcm2835-ctl.c +new file mode 100755 +index 0000000..0c1b80a +--- /dev/null ++++ b/sound/arm/bcm2835-ctl.c +@@ -0,0 +1,200 @@ ++/***************************************************************************** ++* Copyright 2011 Broadcom Corporation. All rights reserved. ++* ++* Unless you and Broadcom execute a separate written software license ++* agreement governing use of this software, this software is licensed to you ++* under the terms of the GNU General Public License version 2, available at ++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). ++* ++* Notwithstanding the above, under no circumstances may you combine this ++* software in any way with any other Broadcom software provided under a ++* license other than the GPL, without Broadcom's express prior written ++* consent. ++*****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "bcm2835.h" ++ ++/* volume maximum and minimum in terms of 0.01dB */ ++#define CTRL_VOL_MAX 400 ++#define CTRL_VOL_MIN -10239 /* originally -10240 */ ++ ++ ++static int snd_bcm2835_ctl_info(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_info *uinfo) ++{ ++ audio_info(" ... IN "); ++ if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) { ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; ++ uinfo->count = 1; ++ uinfo->value.integer.min = CTRL_VOL_MIN; ++ uinfo->value.integer.max = CTRL_VOL_MAX; /* 2303 */ ++ } else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) { ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; ++ uinfo->count = 1; ++ uinfo->value.integer.min = 0; ++ uinfo->value.integer.max = 1; ++ } else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) { ++ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; ++ uinfo->count = 1; ++ uinfo->value.integer.min = 0; ++ uinfo->value.integer.max = AUDIO_DEST_MAX-1; ++ } ++ audio_info(" ... OUT "); ++ return 0; ++} ++ ++/* toggles mute on or off depending on the value of nmute, and returns ++ * 1 if the mute value was changed, otherwise 0 ++ */ ++static int toggle_mute(struct bcm2835_chip *chip, int nmute) ++{ ++ /* if settings are ok, just return 0 */ ++ if(chip->mute == nmute) ++ return 0; ++ ++ /* if the sound is muted then we need to unmute */ ++ if(chip->mute == CTRL_VOL_MUTE) ++ { ++ chip->volume = chip->old_volume; /* copy the old volume back */ ++ audio_info("Unmuting, old_volume = %d, volume = %d ...", chip->old_volume, chip->volume); ++ } ++ else /* otherwise we mute */ ++ { ++ chip->old_volume = chip->volume; ++ chip->volume = 26214; /* set volume to minimum level AKA mute */ ++ audio_info("Muting, old_volume = %d, volume = %d ...", chip->old_volume, chip->volume); ++ } ++ ++ chip->mute = nmute; ++ return 1; ++} ++ ++static int snd_bcm2835_ctl_get(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol); ++ ++ BUG_ON(!chip && !(chip->avail_substreams & AVAIL_SUBSTREAMS_MASK)); ++ ++ if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) ++ ucontrol->value.integer.value[0] = chip2alsa(chip->volume); ++ else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) ++ ucontrol->value.integer.value[0] = chip->mute; ++ else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) ++ ucontrol->value.integer.value[0] = chip->dest; ++ ++ return 0; ++} ++ ++static int snd_bcm2835_ctl_put(struct snd_kcontrol *kcontrol, ++ struct snd_ctl_elem_value *ucontrol) ++{ ++ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol); ++ int changed = 0; ++ ++ if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) { ++ audio_info("Volume change attempted.. volume = %d new_volume = %d", chip->volume, (int)ucontrol->value.integer.value[0]); ++ if (chip->mute == CTRL_VOL_MUTE) { ++ /* changed = toggle_mute(chip, CTRL_VOL_UNMUTE); */ ++ return 1; /* should return 0 to signify no change but the mixer takes this as the opposite sign (no idea why) */ ++ } ++ if (changed ++ || (ucontrol->value.integer.value[0] != chip2alsa(chip->volume))) { ++ ++ chip->volume = alsa2chip(ucontrol->value.integer.value[0]); ++ changed = 1; ++ } ++ ++ } else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) { ++ /* Now implemented */ ++ audio_info(" Mute attempted"); ++ changed = toggle_mute(chip, ucontrol->value.integer.value[0]); ++ ++ } else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) { ++ if (ucontrol->value.integer.value[0] != chip->dest) { ++ chip->dest = ucontrol->value.integer.value[0]; ++ changed = 1; ++ } ++ } ++ ++ if (changed) { ++ if (bcm2835_audio_set_ctls(chip)) ++ printk(KERN_ERR "Failed to set ALSA controls..\n"); ++ } ++ ++ return changed; ++} ++ ++static DECLARE_TLV_DB_SCALE(snd_bcm2835_db_scale, CTRL_VOL_MIN, 1, 1); ++ ++static struct snd_kcontrol_new snd_bcm2835_ctl[] __devinitdata = { ++ { ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = "PCM Playback Volume", ++ .index = 0, ++ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, ++ .private_value = PCM_PLAYBACK_VOLUME, ++ .info = snd_bcm2835_ctl_info, ++ .get = snd_bcm2835_ctl_get, ++ .put = snd_bcm2835_ctl_put, ++ .count = 1, ++ .tlv = {.p = snd_bcm2835_db_scale} ++ }, ++ { ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = "PCM Playback Switch", ++ .index = 0, ++ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, ++ .private_value = PCM_PLAYBACK_MUTE, ++ .info = snd_bcm2835_ctl_info, ++ .get = snd_bcm2835_ctl_get, ++ .put = snd_bcm2835_ctl_put, ++ .count = 1, ++ }, ++ { ++ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, ++ .name = "PCM Playback Route", ++ .index = 0, ++ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, ++ .private_value = PCM_PLAYBACK_DEVICE, ++ .info = snd_bcm2835_ctl_info, ++ .get = snd_bcm2835_ctl_get, ++ .put = snd_bcm2835_ctl_put, ++ .count = 1, ++ }, ++}; ++ ++int __devinit snd_bcm2835_new_ctl(bcm2835_chip_t * chip) ++{ ++ int err; ++ unsigned int idx; ++ ++ strcpy(chip->card->mixername, "Broadcom Mixer"); ++ for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_ctl); idx++) { ++ err = ++ snd_ctl_add(chip->card, ++ snd_ctl_new1(&snd_bcm2835_ctl[idx], chip)); ++ if (err < 0) ++ return err; ++ } ++ return 0; ++} +diff --git a/sound/arm/bcm2835-pcm.c b/sound/arm/bcm2835-pcm.c +new file mode 100755 +index 0000000..bc146a2 +--- /dev/null ++++ b/sound/arm/bcm2835-pcm.c +@@ -0,0 +1,408 @@ ++/***************************************************************************** ++* Copyright 2011 Broadcom Corporation. All rights reserved. ++* ++* Unless you and Broadcom execute a separate written software license ++* agreement governing use of this software, this software is licensed to you ++* under the terms of the GNU General Public License version 2, available at ++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). ++* ++* Notwithstanding the above, under no circumstances may you combine this ++* software in any way with any other Broadcom software provided under a ++* license other than the GPL, without Broadcom's express prior written ++* consent. ++*****************************************************************************/ ++ ++#include ++#include ++ ++#include "bcm2835.h" ++ ++/* hardware definition */ ++static struct snd_pcm_hardware snd_bcm2835_playback_hw = { ++ .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER), ++ .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, ++ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, ++ .rate_min = 8000, ++ .rate_max = 48000, ++ .channels_min = 1, ++ .channels_max = 2, ++ .buffer_bytes_max = 32 * 1024, /* Needs to be less than audioplay buffer size */ ++ .period_bytes_min = 1 * 1024, ++ .period_bytes_max = 32 * 1024, ++ .periods_min = 1, ++ .periods_max = 32, ++}; ++ ++static void snd_bcm2835_playback_free(struct snd_pcm_runtime *runtime) ++{ ++ audio_info("Freeing up alsa stream here ..\n"); ++ if (runtime->private_data) ++ kfree(runtime->private_data); ++ runtime->private_data = NULL; ++} ++ ++static irqreturn_t bcm2835_playback_fifo_irq(int irq, void *dev_id) ++{ ++ bcm2835_alsa_stream_t *alsa_stream = (bcm2835_alsa_stream_t *) dev_id; ++ uint32_t consumed = 0; ++ int new_period = 0; ++ ++ audio_info(" .. IN\n"); ++ ++ audio_info("alsa_stream=%p substream=%p\n", alsa_stream, ++ alsa_stream ? alsa_stream->substream : 0); ++ ++ if (alsa_stream->open) ++ consumed = bcm2835_audio_retrieve_buffers(alsa_stream); ++ ++ /* We get called only if playback was triggered, So, the number of buffers we retrieve in ++ * each iteration are the buffers that have been played out already ++ */ ++ ++ if (alsa_stream->period_size) { ++ if ((alsa_stream->pos / alsa_stream->period_size) != ++ ((alsa_stream->pos + consumed) / alsa_stream->period_size)) ++ new_period = 1; ++ } ++ audio_debug("updating pos cur: %d + %d max:%d period_bytes:%d, hw_ptr: %d new_period:%d\n", ++ alsa_stream->pos, ++ consumed, ++ alsa_stream->buffer_size, ++ (int)(alsa_stream->period_size*alsa_stream->substream->runtime->periods), ++ frames_to_bytes(alsa_stream->substream->runtime, alsa_stream->substream->runtime->status->hw_ptr), ++ new_period); ++ if (alsa_stream->buffer_size) { ++ alsa_stream->pos += consumed &~ (1<<30); ++ alsa_stream->pos %= alsa_stream->buffer_size; ++ } ++ ++ if (alsa_stream->substream) { ++ if (new_period) ++ snd_pcm_period_elapsed(alsa_stream->substream); ++ } else { ++ audio_warning(" unexpected NULL substream\n"); ++ } ++ audio_info(" .. OUT\n"); ++ ++ return IRQ_HANDLED; ++} ++ ++/* open callback */ ++static int snd_bcm2835_playback_open(struct snd_pcm_substream *substream) ++{ ++ bcm2835_chip_t *chip = snd_pcm_substream_chip(substream); ++ struct snd_pcm_runtime *runtime = substream->runtime; ++ bcm2835_alsa_stream_t *alsa_stream; ++ int idx; ++ int err; ++ ++ audio_info(" .. IN (%d)\n", substream->number); ++ ++ audio_warning("Alsa open (%d)\n", substream->number); ++ idx = substream->number; ++ ++ if (idx > MAX_SUBSTREAMS) { ++ audio_error ++ ("substream(%d) device doesn't exist max(%d) substreams allowed\n", ++ idx, MAX_SUBSTREAMS); ++ err = -ENODEV; ++ goto out; ++ } ++ ++ /* Check if we are ready */ ++ if (!(chip->avail_substreams & (1 << idx))) { ++ /* We are not ready yet */ ++ audio_error("substream(%d) device is not ready yet\n", idx); ++ err = -EAGAIN; ++ goto out; ++ } ++ ++ alsa_stream = kzalloc(sizeof(bcm2835_alsa_stream_t), GFP_KERNEL); ++ if (alsa_stream == NULL) { ++ return -ENOMEM; ++ } ++ ++ /* Initialise alsa_stream */ ++ alsa_stream->chip = chip; ++ alsa_stream->substream = substream; ++ alsa_stream->idx = idx; ++ chip->alsa_stream[idx] = alsa_stream; ++ ++ sema_init(&alsa_stream->buffers_update_sem, 0); ++ sema_init(&alsa_stream->control_sem, 0); ++ spin_lock_init(&alsa_stream->lock); ++ ++ /* Enabled in start trigger, called on each "fifo irq" after that */ ++ alsa_stream->enable_fifo_irq = 0; ++ alsa_stream->fifo_irq_handler = bcm2835_playback_fifo_irq; ++ ++ runtime->private_data = alsa_stream; ++ runtime->private_free = snd_bcm2835_playback_free; ++ runtime->hw = snd_bcm2835_playback_hw; ++ /* minimum 16 bytes alignment (for vchiq bulk transfers) */ ++ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, ++ 16); ++ ++ err = bcm2835_audio_open(alsa_stream); ++ if (err != 0) { ++ kfree(alsa_stream); ++ return err; ++ } ++ ++ alsa_stream->open = 1; ++ alsa_stream->draining = 1; ++ ++out: ++ audio_info(" .. OUT =%d\n", err); ++ ++ return err; ++} ++ ++/* close callback */ ++static int snd_bcm2835_playback_close(struct snd_pcm_substream *substream) ++{ ++ /* the hardware-specific codes will be here */ ++ ++ struct snd_pcm_runtime *runtime = substream->runtime; ++ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; ++ ++ audio_info(" .. IN\n"); ++ audio_warning("Alsa close\n"); ++ ++ /* ++ * Call stop if it's still running. This happens when app ++ * is force killed and we don't get a stop trigger. ++ */ ++ if (alsa_stream->running) { ++ int err; ++ err = bcm2835_audio_stop(alsa_stream); ++ alsa_stream->running = 0; ++ if (err != 0) ++ audio_error(" Failed to STOP alsa device\n"); ++ } ++ ++ alsa_stream->period_size = 0; ++ alsa_stream->buffer_size = 0; ++ ++ if (alsa_stream->open) { ++ alsa_stream->open = 0; ++ bcm2835_audio_close(alsa_stream); ++ } ++ if (alsa_stream->chip) ++ alsa_stream->chip->alsa_stream[alsa_stream->idx] = NULL; ++ /* ++ * Do not free up alsa_stream here, it will be freed up by ++ * runtime->private_free callback we registered in *_open above ++ */ ++ ++ audio_info(" .. OUT\n"); ++ ++ return 0; ++} ++ ++/* hw_params callback */ ++static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ int err; ++ struct snd_pcm_runtime *runtime = substream->runtime; ++ bcm2835_alsa_stream_t *alsa_stream = ++ (bcm2835_alsa_stream_t *) runtime->private_data; ++ ++ audio_info(" .. IN\n"); ++ ++ err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); ++ if (err < 0) { ++ audio_error ++ (" pcm_lib_malloc failed to allocated pages for buffers\n"); ++ return err; ++ } ++ ++ err = bcm2835_audio_set_params(alsa_stream, params_channels(params), ++ params_rate(params), ++ snd_pcm_format_width(params_format ++ (params))); ++ if (err < 0) { ++ audio_error(" error setting hw params\n"); ++ } ++ ++ bcm2835_audio_setup(alsa_stream); ++ ++ /* in preparation of the stream, set the controls (volume level) of the stream */ ++ bcm2835_audio_set_ctls(alsa_stream->chip); ++ ++ audio_info(" .. OUT\n"); ++ ++ return err; ++} ++ ++/* hw_free callback */ ++static int snd_bcm2835_pcm_hw_free(struct snd_pcm_substream *substream) ++{ ++ audio_info(" .. IN\n"); ++ return snd_pcm_lib_free_pages(substream); ++} ++ ++/* prepare callback */ ++static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream) ++{ ++ struct snd_pcm_runtime *runtime = substream->runtime; ++ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; ++ ++ audio_info(" .. IN\n"); ++ ++ alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream); ++ alsa_stream->period_size = snd_pcm_lib_period_bytes(substream); ++ alsa_stream->pos = 0; ++ ++ audio_debug("buffer_size=%d, period_size=%d pos=%d frame_bits=%d\n", ++ alsa_stream->buffer_size, alsa_stream->period_size, ++ alsa_stream->pos, runtime->frame_bits); ++ ++ audio_info(" .. OUT\n"); ++ return 0; ++} ++ ++/* trigger callback */ ++static int snd_bcm2835_pcm_trigger(struct snd_pcm_substream *substream, int cmd) ++{ ++ struct snd_pcm_runtime *runtime = substream->runtime; ++ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; ++ int err = 0; ++ ++ audio_info(" .. IN\n"); ++ ++ switch (cmd) { ++ case SNDRV_PCM_TRIGGER_START: ++ audio_debug("bcm2835_AUDIO_TRIGGER_START running=%d\n", ++ alsa_stream->running); ++ if (!alsa_stream->running) { ++ err = bcm2835_audio_start(alsa_stream); ++ if (err == 0) { ++ alsa_stream->running = 1; ++ alsa_stream->draining = 1; ++ } ++ } ++ break; ++ case SNDRV_PCM_TRIGGER_STOP: ++ audio_debug ++ ("bcm2835_AUDIO_TRIGGER_STOP running=%d draining=%d\n", ++ runtime->status->state == SNDRV_PCM_STATE_DRAINING, ++ alsa_stream->running); ++ if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { ++ audio_info("DRAINING\n"); ++ alsa_stream->draining = 1; ++ } else { ++ audio_info("DROPPING\n"); ++ alsa_stream->draining = 0; ++ } ++ if (alsa_stream->running) { ++ err = bcm2835_audio_stop(alsa_stream); ++ if (err != 0) ++ audio_error(" Failed to STOP alsa device\n"); ++ alsa_stream->running = 0; ++ } ++ break; ++ default: ++ err = -EINVAL; ++ } ++ ++ audio_info(" .. OUT\n"); ++ return err; ++} ++ ++/* pointer callback */ ++static snd_pcm_uframes_t ++snd_bcm2835_pcm_pointer(struct snd_pcm_substream *substream) ++{ ++ struct snd_pcm_runtime *runtime = substream->runtime; ++ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; ++ ++ audio_info(" .. IN\n"); ++ ++ audio_debug("pcm_pointer... (%d) hwptr=%d appl=%d pos=%d\n", 0, ++ frames_to_bytes(runtime, runtime->status->hw_ptr), ++ frames_to_bytes(runtime, runtime->control->appl_ptr), ++ alsa_stream->pos); ++ ++ audio_info(" .. OUT\n"); ++ return bytes_to_frames(runtime, alsa_stream->pos); ++} ++ ++static int snd_bcm2835_pcm_copy(struct snd_pcm_substream *substream, ++ int channel, snd_pcm_uframes_t pos, void *src, ++ snd_pcm_uframes_t count) ++{ ++ int ret; ++ struct snd_pcm_runtime *runtime = substream->runtime; ++ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; ++ ++ audio_info(" .. IN\n"); ++ audio_debug("copy.......... (%d) hwptr=%d appl=%d pos=%d\n", ++ frames_to_bytes(runtime, count), frames_to_bytes(runtime, ++ runtime-> ++ status-> ++ hw_ptr), ++ frames_to_bytes(runtime, runtime->control->appl_ptr), ++ alsa_stream->pos); ++ ret = ++ bcm2835_audio_write(alsa_stream, frames_to_bytes(runtime, count), ++ src); ++ audio_info(" .. OUT\n"); ++ return ret; ++} ++ ++static int snd_bcm2835_pcm_lib_ioctl(struct snd_pcm_substream *substream, ++ unsigned int cmd, void *arg) ++{ ++ int ret = snd_pcm_lib_ioctl(substream, cmd, arg); ++ audio_info(" .. substream=%p, cmd=%d, arg=%p (%x) ret=%d\n", substream, ++ cmd, arg, arg ? *(unsigned *)arg : 0, ret); ++ return ret; ++} ++ ++/* operators */ ++static struct snd_pcm_ops snd_bcm2835_playback_ops = { ++ .open = snd_bcm2835_playback_open, ++ .close = snd_bcm2835_playback_close, ++ .ioctl = snd_bcm2835_pcm_lib_ioctl, ++ .hw_params = snd_bcm2835_pcm_hw_params, ++ .hw_free = snd_bcm2835_pcm_hw_free, ++ .prepare = snd_bcm2835_pcm_prepare, ++ .trigger = snd_bcm2835_pcm_trigger, ++ .pointer = snd_bcm2835_pcm_pointer, ++ .copy = snd_bcm2835_pcm_copy, ++}; ++ ++/* create a pcm device */ ++int __devinit snd_bcm2835_new_pcm(bcm2835_chip_t * chip) ++{ ++ struct snd_pcm *pcm; ++ int err; ++ ++ audio_info(" .. IN\n"); ++ err = ++ snd_pcm_new(chip->card, "bcm2835 ALSA", 0, MAX_SUBSTREAMS, 0, &pcm); ++ if (err < 0) ++ return err; ++ pcm->private_data = chip; ++ strcpy(pcm->name, "bcm2835 ALSA"); ++ chip->pcm = pcm; ++ chip->dest = AUDIO_DEST_AUTO; ++ chip->volume = alsa2chip(0); ++ chip->mute = CTRL_VOL_UNMUTE; /*disable mute on startup */ ++ /* set operators */ ++ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, ++ &snd_bcm2835_playback_ops); ++ ++ /* pre-allocation of buffers */ ++ /* NOTE: this may fail */ ++ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, ++ snd_dma_continuous_data ++ (GFP_KERNEL), 64 * 1024, ++ 64 * 1024); ++ ++ audio_info(" .. OUT\n"); ++ ++ return 0; ++} +diff --git a/sound/arm/bcm2835-vchiq.c b/sound/arm/bcm2835-vchiq.c +new file mode 100755 +index 0000000..68d838d +--- /dev/null ++++ b/sound/arm/bcm2835-vchiq.c +@@ -0,0 +1,834 @@ ++/***************************************************************************** ++* Copyright 2011 Broadcom Corporation. All rights reserved. ++* ++* Unless you and Broadcom execute a separate written software license ++* agreement governing use of this software, this software is licensed to you ++* under the terms of the GNU General Public License version 2, available at ++* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). ++* ++* Notwithstanding the above, under no circumstances may you combine this ++* software in any way with any other Broadcom software provided under a ++* license other than the GPL, without Broadcom's express prior written ++* consent. ++*****************************************************************************/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "bcm2835.h" ++ ++/* ---- Include Files -------------------------------------------------------- */ ++ ++#include "interface/vchi/vchi.h" ++#include "interface/vcos/vcos.h" ++#include "interface/vcos/vcos_logging.h" ++#include "vc_vchi_audioserv_defs.h" ++ ++/* ---- Private Constants and Types ------------------------------------------ */ ++ ++/* VCOS logging category for this service */ ++#define VCOS_LOG_CATEGORY (&audio_log_category) ++ ++/* Default VCOS logging level */ ++#define LOG_LEVEL VCOS_LOG_WARN ++/* Logging macros (for remapping to other logging mechanisms, i.e., printf) */ ++#ifdef AUDIO_DEBUG_ENABLE ++ #define LOG_ERR( fmt, arg... ) pr_err( "%s:%d " fmt, __func__, __LINE__, ##arg) ++ #define LOG_WARN( fmt, arg... ) pr_info( "%s:%d " fmt, __func__, __LINE__, ##arg) ++ #define LOG_INFO( fmt, arg... ) pr_info( "%s:%d " fmt, __func__, __LINE__, ##arg) ++ #define LOG_DBG( fmt, arg... ) pr_info( "%s:%d " fmt, __func__, __LINE__, ##arg) ++#else ++ #define LOG_ERR( fmt, arg... ) vcos_log_error( "%s:%d " fmt, __func__, __LINE__, ##arg) ++ #define LOG_WARN( fmt, arg... ) vcos_log_warn( "%s:%d " fmt, __func__, __LINE__, ##arg) ++ #define LOG_INFO( fmt, arg... ) vcos_log_info( "%s:%d " fmt, __func__, __LINE__, ##arg) ++ #define LOG_DBG( fmt, arg... ) vcos_log_info( "%s:%d " fmt, __func__, __LINE__, ##arg) ++#endif ++ ++typedef struct opaque_AUDIO_INSTANCE_T { ++ uint32_t num_connections; ++ VCHI_SERVICE_HANDLE_T vchi_handle[VCHI_MAX_NUM_CONNECTIONS]; ++ VCOS_EVENT_T msg_avail_event; ++ VCOS_MUTEX_T vchi_mutex; ++ bcm2835_alsa_stream_t *alsa_stream; ++ int32_t result, got_result; ++} AUDIO_INSTANCE_T; ++ ++/* ---- Private Variables ---------------------------------------------------- */ ++ ++/* VCOS logging category for this service */ ++static VCOS_LOG_CAT_T audio_log_category; ++ ++/* ---- Private Function Prototypes ------------------------------------------ */ ++ ++/* ---- Private Functions ---------------------------------------------------- */ ++ ++static int bcm2835_audio_stop_worker(bcm2835_alsa_stream_t * alsa_stream); ++static int bcm2835_audio_start_worker(bcm2835_alsa_stream_t * alsa_stream); ++ ++typedef struct { ++ struct work_struct my_work; ++ bcm2835_alsa_stream_t *alsa_stream; ++ int x; ++} my_work_t; ++ ++static void my_wq_function(struct work_struct *work) ++{ ++ my_work_t *w = (my_work_t *) work; ++ int ret = -9; ++ LOG_DBG(" .. IN %p:%d\n", w->alsa_stream, w->x); ++ switch (w->x) { ++ case 1: ++ ret = bcm2835_audio_start_worker(w->alsa_stream); ++ break; ++ case 2: ++ ret = bcm2835_audio_stop_worker(w->alsa_stream); ++ break; ++ default: ++ LOG_ERR(" Unexpected work: %p:%d\n", w->alsa_stream, w->x); ++ break; ++ } ++ kfree((void *)work); ++ LOG_DBG(" .. OUT %d\n", ret); ++} ++ ++int bcm2835_audio_start(bcm2835_alsa_stream_t * alsa_stream) ++{ ++ int ret = -1; ++ LOG_DBG(" .. IN\n"); ++ if (alsa_stream->my_wq) { ++ my_work_t *work = kmalloc(sizeof(my_work_t), GFP_ATOMIC); ++ /*--- Queue some work (item 1) ---*/ ++ if (work) { ++ INIT_WORK((struct work_struct *)work, my_wq_function); ++ work->alsa_stream = alsa_stream; ++ work->x = 1; ++ if (queue_work ++ (alsa_stream->my_wq, (struct work_struct *)work)) ++ ret = 0; ++ } else ++ LOG_ERR(" .. Error: NULL work kmalloc\n"); ++ } ++ LOG_DBG(" .. OUT %d\n", ret); ++ return ret; ++} ++ ++int bcm2835_audio_stop(bcm2835_alsa_stream_t * alsa_stream) ++{ ++ int ret = -1; ++ LOG_DBG(" .. IN\n"); ++ if (alsa_stream->my_wq) { ++ my_work_t *work = kmalloc(sizeof(my_work_t), GFP_ATOMIC); ++ /*--- Queue some work (item 1) ---*/ ++ if (work) { ++ INIT_WORK((struct work_struct *)work, my_wq_function); ++ work->alsa_stream = alsa_stream; ++ work->x = 2; ++ if (queue_work ++ (alsa_stream->my_wq, (struct work_struct *)work)) ++ ret = 0; ++ } else ++ LOG_ERR(" .. Error: NULL work kmalloc\n"); ++ } ++ LOG_DBG(" .. OUT %d\n", ret); ++ return ret; ++} ++ ++void my_workqueue_init(bcm2835_alsa_stream_t * alsa_stream) ++{ ++ alsa_stream->my_wq = create_workqueue("my_queue"); ++ return; ++} ++ ++void my_workqueue_quit(bcm2835_alsa_stream_t * alsa_stream) ++{ ++ if (alsa_stream->my_wq) { ++ flush_workqueue(alsa_stream->my_wq); ++ destroy_workqueue(alsa_stream->my_wq); ++ alsa_stream->my_wq = NULL; ++ } ++ return; ++} ++ ++static void audio_vchi_callback(void *param, ++ const VCHI_CALLBACK_REASON_T reason, ++ void *msg_handle) ++{ ++ AUDIO_INSTANCE_T *instance = (AUDIO_INSTANCE_T *) param; ++ int32_t status; ++ int32_t msg_len; ++ VC_AUDIO_MSG_T m; ++ bcm2835_alsa_stream_t *alsa_stream = 0; ++ LOG_DBG(" .. IN instance=%p, param=%p, reason=%d, handle=%p\n", ++ instance, param, reason, msg_handle); ++ ++ if (!instance || reason != VCHI_CALLBACK_MSG_AVAILABLE) { ++ return; ++ } ++ alsa_stream = instance->alsa_stream; ++ status = vchi_msg_dequeue(instance->vchi_handle[0], ++ &m, sizeof m, &msg_len, VCHI_FLAGS_NONE); ++ if (m.type == VC_AUDIO_MSG_TYPE_RESULT) { ++ LOG_DBG ++ (" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_RESULT, success=%d\n", ++ instance, m.u.result.success); ++ BUG_ON(instance->got_result); ++ instance->result = m.u.result.success; ++ instance->got_result = 1; ++ vcos_event_signal(&instance->msg_avail_event); ++ } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) { ++ irq_handler_t callback = (irq_handler_t) m.u.complete.callback; ++ LOG_DBG ++ (" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_COMPLETE, complete=%d\n", ++ instance, m.u.complete.count); ++ if (alsa_stream && callback) { ++ atomic_add(m.u.complete.count, &alsa_stream->retrieved); ++ callback(0, alsa_stream); ++ } else { ++ LOG_DBG(" .. unexpected alsa_stream=%p, callback=%p\n", ++ alsa_stream, callback); ++ } ++ vcos_event_signal(&instance->msg_avail_event); ++ } else { ++ LOG_DBG(" .. unexpected m.type=%d\n", m.type); ++ } ++} ++ ++static AUDIO_INSTANCE_T *vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance, ++ VCHI_CONNECTION_T ** ++ vchi_connections, ++ uint32_t num_connections) ++{ ++ uint32_t i; ++ AUDIO_INSTANCE_T *instance; ++ VCOS_STATUS_T status; ++ ++ LOG_DBG("%s: start", __func__); ++ ++ if (num_connections > VCHI_MAX_NUM_CONNECTIONS) { ++ LOG_ERR("%s: unsupported number of connections %u (max=%u)", ++ __func__, num_connections, VCHI_MAX_NUM_CONNECTIONS); ++ ++ return NULL; ++ } ++ /* Allocate memory for this instance */ ++ instance = vcos_malloc(sizeof(*instance), "audio_instance"); ++ memset(instance, 0, sizeof(*instance)); ++ ++ instance->num_connections = num_connections; ++ /* Create the message available event */ ++ status = ++ vcos_event_create(&instance->msg_avail_event, "audio_msg_avail"); ++ if (status != VCOS_SUCCESS) { ++ LOG_ERR("%s: failed to create event (status=%d)", __func__, ++ status); ++ ++ goto err_free_mem; ++ } ++ /* Create a lock for exclusive, serialized VCHI connection access */ ++ status = vcos_mutex_create(&instance->vchi_mutex, "audio_vchi_mutex"); ++ if (status != VCOS_SUCCESS) { ++ LOG_ERR("%s: failed to create event (status=%d)", __func__, ++ status); ++ ++ goto err_delete_event; ++ } ++ /* Open the VCHI service connections */ ++ for (i = 0; i < num_connections; i++) { ++ SERVICE_CREATION_T params = { ++ VC_AUDIO_SERVER_NAME, // 4cc service code ++ vchi_connections[i], // passed in fn pointers ++ 0, // rx fifo size (unused) ++ 0, // tx fifo size (unused) ++ audio_vchi_callback, // service callback ++ instance, // service callback parameter ++ VCOS_TRUE, //TODO: remove VCOS_FALSE, // unaligned bulk recieves ++ VCOS_TRUE, //TODO: remove VCOS_FALSE, // unaligned bulk transmits ++ VCOS_FALSE // want crc check on bulk transfers ++ }; ++ ++ status = vchi_service_open(vchi_instance, ¶ms, ++ &instance->vchi_handle[i]); ++ if (status != VCOS_SUCCESS) { ++ LOG_ERR ++ ("%s: failed to open VCHI service connection (status=%d)", ++ __func__, status); ++ ++ goto err_close_services; ++ } ++ /* Finished with the service for now */ ++ vchi_service_release(instance->vchi_handle[i]); ++ } ++ ++ return instance; ++ ++err_close_services: ++ for (i = 0; i < instance->num_connections; i++) { ++ vchi_service_close(instance->vchi_handle[i]); ++ } ++ ++ vcos_mutex_delete(&instance->vchi_mutex); ++ ++err_delete_event: ++ vcos_event_delete(&instance->msg_avail_event); ++ ++err_free_mem: ++ vcos_free(instance); ++ ++ return NULL; ++} ++ ++static int32_t vc_vchi_audio_deinit(AUDIO_INSTANCE_T * instance) ++{ ++ uint32_t i; ++ ++ LOG_DBG(" .. IN\n"); ++ ++ if (instance == NULL) { ++ LOG_ERR("%s: invalid handle %p", __func__, instance); ++ ++ return -1; ++ } ++ ++ LOG_DBG(" .. about to lock (%d)\n", instance->num_connections); ++ vcos_mutex_lock(&instance->vchi_mutex); ++ ++ /* Close all VCHI service connections */ ++ for (i = 0; i < instance->num_connections; i++) { ++ int32_t success; ++ LOG_DBG(" .. %i:closing %p\n", i, instance->vchi_handle[i]); ++ vchi_service_use(instance->vchi_handle[i]); ++ ++ success = vchi_service_close(instance->vchi_handle[i]); ++ if (success != 0) { ++ LOG_ERR ++ ("%s: failed to close VCHI service connection (status=%d)", ++ __func__, success); ++ } ++ } ++ ++ vcos_mutex_unlock(&instance->vchi_mutex); ++ ++ vcos_mutex_delete(&instance->vchi_mutex); ++ ++ vcos_event_delete(&instance->msg_avail_event); ++ ++ vcos_free(instance); ++ ++ /* Unregister the log category so we can add it back next time */ ++ vcos_log_unregister(&audio_log_category); ++ ++ LOG_DBG(" .. OUT\n"); ++ ++ return 0; ++} ++ ++static int bcm2835_audio_open_connection(bcm2835_alsa_stream_t * alsa_stream) ++{ ++ static VCHI_INSTANCE_T vchi_instance; ++ static VCHI_CONNECTION_T *vchi_connection; ++ AUDIO_INSTANCE_T *instance = alsa_stream->instance; ++ int ret; ++ LOG_DBG(" .. IN\n"); ++ ++ LOG_INFO("%s: start", __func__); ++ //BUG_ON(instance); ++ if (instance) { ++ LOG_ERR("%s: VCHI instance already open (%p)", ++ __func__, instance); ++ instance->alsa_stream = alsa_stream; ++ alsa_stream->instance = instance; ++ ret = 0; // xxx todo -1; ++ goto err_free_mem; ++ } ++ ++ /* Initialize and create a VCHI connection */ ++ ret = vchi_initialise(&vchi_instance); ++ if (ret != 0) { ++ LOG_ERR("%s: failed to initialise VCHI instance (ret=%d)", ++ __func__, ret); ++ ++ ret = -EIO; ++ goto err_free_mem; ++ } ++ ret = vchi_connect(NULL, 0, vchi_instance); ++ if (ret != 0) { ++ LOG_ERR("%s: failed to connect VCHI instance (ret=%d)", ++ __func__, ret); ++ ++ ret = -EIO; ++ goto err_free_mem; ++ } ++ ++ /* Set up the VCOS logging */ ++ vcos_log_set_level(VCOS_LOG_CATEGORY, LOG_LEVEL); ++ vcos_log_register("audio", VCOS_LOG_CATEGORY); ++ ++ /* Initialize an instance of the audio service */ ++ instance = vc_vchi_audio_init(vchi_instance, &vchi_connection, 1); ++ ++ if (instance == NULL /*|| audio_handle != instance */ ) { ++ LOG_ERR("%s: failed to initialize audio service", __func__); ++ ++ ret = -EPERM; ++ goto err_free_mem; ++ } ++ ++ instance->alsa_stream = alsa_stream; ++ alsa_stream->instance = instance; ++ ++ LOG_DBG(" success !\n"); ++err_free_mem: ++ LOG_DBG(" .. OUT\n"); ++ ++ return ret; ++} ++ ++int bcm2835_audio_open(bcm2835_alsa_stream_t * alsa_stream) ++{ ++ AUDIO_INSTANCE_T *instance; ++ VC_AUDIO_MSG_T m; ++ int32_t success; ++ int ret; ++ LOG_DBG(" .. IN\n"); ++ ++ my_workqueue_init(alsa_stream); ++ ++ ret = bcm2835_audio_open_connection(alsa_stream); ++ if (ret != 0) { ++ ret = -1; ++ goto exit; ++ } ++ instance = alsa_stream->instance; ++ ++ vcos_mutex_lock(&instance->vchi_mutex); ++ vchi_service_use(instance->vchi_handle[0]); ++ ++ m.type = VC_AUDIO_MSG_TYPE_OPEN; ++ ++ /* Send the message to the videocore */ ++ success = vchi_msg_queue(instance->vchi_handle[0], ++ &m, sizeof m, ++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); ++ ++ if (success != 0) { ++ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)", ++ __func__, success); ++ ++ ret = -1; ++ goto unlock; ++ } ++ ++ ret = 0; ++ ++unlock: ++ vchi_service_release(instance->vchi_handle[0]); ++ vcos_mutex_unlock(&instance->vchi_mutex); ++exit: ++ LOG_DBG(" .. OUT\n"); ++ return ret; ++} ++ ++static int bcm2835_audio_set_ctls_chan(bcm2835_alsa_stream_t * alsa_stream, ++ bcm2835_chip_t * chip) ++{ ++ VC_AUDIO_MSG_T m; ++ AUDIO_INSTANCE_T *instance = alsa_stream->instance; ++ int32_t success; ++ int ret; ++ LOG_DBG(" .. IN\n"); ++ ++ LOG_INFO ++ (" Setting ALSA dest(%d), volume(%d)\n", chip->dest, chip->volume); ++ ++ vcos_mutex_lock(&instance->vchi_mutex); ++ vchi_service_use(instance->vchi_handle[0]); ++ ++ instance->got_result = 0; ++ instance->result = -1; ++ ++ m.type = VC_AUDIO_MSG_TYPE_CONTROL; ++ m.u.control.dest = chip->dest; ++ m.u.control.volume = chip->volume; ++ ++ /* Send the message to the videocore */ ++ success = vchi_msg_queue(instance->vchi_handle[0], ++ &m, sizeof m, ++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); ++ ++ if (success != 0) { ++ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)", ++ __func__, success); ++ ++ ret = -1; ++ goto unlock; ++ } ++ ++ /* We are expecting a reply from the videocore */ ++ while (!instance->got_result) { ++ success = vcos_event_wait(&instance->msg_avail_event); ++ if (success != VCOS_SUCCESS) { ++ LOG_ERR("%s: failed on waiting for event (status=%d)", ++ __func__, success); ++ ++ ret = -1; ++ goto unlock; ++ } ++ } ++ ++ if (instance->result != 0) { ++ LOG_ERR("%s: result=%d", __func__, instance->result); ++ ++ ret = -1; ++ goto unlock; ++ } ++ ++ ret = 0; ++ ++unlock: ++ vchi_service_release(instance->vchi_handle[0]); ++ vcos_mutex_unlock(&instance->vchi_mutex); ++ ++ LOG_DBG(" .. OUT\n"); ++ return ret; ++} ++ ++int bcm2835_audio_set_ctls(bcm2835_chip_t * chip) ++{ ++ int i; ++ int ret = 0; ++ LOG_DBG(" .. IN\n"); ++ ++ /* change ctls for all substreams */ ++ for (i = 0; i < MAX_SUBSTREAMS; i++) { ++ if (chip->avail_substreams & (1 << i)) { ++ if (!chip->alsa_stream[i]) ++ { ++ LOG_DBG(" No ALSA stream available?! "); ++ ret = 0; ++ } ++ else if (bcm2835_audio_set_ctls_chan /* returns 0 on success */ ++ (chip->alsa_stream[i], chip) != 0) ++ { ++ LOG_DBG("Couldn't set the controls for stream %d", i); ++ ret = -1; ++ } ++ LOG_DBG(" Controls set for stream %d", i); ++ } ++ } ++ LOG_DBG(" .. OUT ret=%d\n", ret); ++ return ret; ++} ++ ++int bcm2835_audio_set_params(bcm2835_alsa_stream_t * alsa_stream, ++ uint32_t channels, uint32_t samplerate, ++ uint32_t bps) ++{ ++ VC_AUDIO_MSG_T m; ++ AUDIO_INSTANCE_T *instance = alsa_stream->instance; ++ int32_t success; ++ int ret; ++ LOG_DBG(" .. IN\n"); ++ ++ LOG_INFO ++ (" Setting ALSA channels(%d), samplerate(%d), bits-per-sample(%d)\n", ++ channels, samplerate, bps); ++ ++ /* resend ctls - alsa_stream may not have been open when first send */ ++ ret = bcm2835_audio_set_ctls_chan(alsa_stream, alsa_stream->chip); ++ if (ret != 0) { ++ LOG_ERR(" Alsa controls not supported\n"); ++ return -EINVAL; ++ } ++ ++ vcos_mutex_lock(&instance->vchi_mutex); ++ vchi_service_use(instance->vchi_handle[0]); ++ ++ instance->got_result = 0; ++ instance->result = -1; ++ ++ m.type = VC_AUDIO_MSG_TYPE_CONFIG; ++ m.u.config.channels = channels; ++ m.u.config.samplerate = samplerate; ++ m.u.config.bps = bps; ++ ++ /* Send the message to the videocore */ ++ success = vchi_msg_queue(instance->vchi_handle[0], ++ &m, sizeof m, ++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); ++ ++ if (success != 0) { ++ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)", ++ __func__, success); ++ ++ ret = -1; ++ goto unlock; ++ } ++ ++ /* We are expecting a reply from the videocore */ ++ while (!instance->got_result) { ++ success = vcos_event_wait(&instance->msg_avail_event); ++ if (success != VCOS_SUCCESS) { ++ LOG_ERR("%s: failed on waiting for event (status=%d)", ++ __func__, success); ++ ++ ret = -1; ++ goto unlock; ++ } ++ } ++ ++ if (instance->result != 0) { ++ LOG_ERR("%s: result=%d", __func__, instance->result); ++ ++ ret = -1; ++ goto unlock; ++ } ++ ++ ret = 0; ++ ++unlock: ++ vchi_service_release(instance->vchi_handle[0]); ++ vcos_mutex_unlock(&instance->vchi_mutex); ++ ++ LOG_DBG(" .. OUT\n"); ++ return ret; ++} ++ ++int bcm2835_audio_setup(bcm2835_alsa_stream_t * alsa_stream) ++{ ++ LOG_DBG(" .. IN\n"); ++ ++ LOG_DBG(" .. OUT\n"); ++ ++ return 0; ++} ++ ++static int bcm2835_audio_start_worker(bcm2835_alsa_stream_t * alsa_stream) ++{ ++ VC_AUDIO_MSG_T m; ++ AUDIO_INSTANCE_T *instance = alsa_stream->instance; ++ int32_t success; ++ int ret; ++ LOG_DBG(" .. IN\n"); ++ ++ vcos_mutex_lock(&instance->vchi_mutex); ++ vchi_service_use(instance->vchi_handle[0]); ++ ++ m.type = VC_AUDIO_MSG_TYPE_START; ++ ++ /* Send the message to the videocore */ ++ success = vchi_msg_queue(instance->vchi_handle[0], ++ &m, sizeof m, ++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); ++ ++ if (success != 0) { ++ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)", ++ __func__, success); ++ ++ ret = -1; ++ goto unlock; ++ } ++ ++ ret = 0; ++ ++unlock: ++ vchi_service_release(instance->vchi_handle[0]); ++ vcos_mutex_unlock(&instance->vchi_mutex); ++ LOG_DBG(" .. OUT\n"); ++ return ret; ++} ++ ++static int bcm2835_audio_stop_worker(bcm2835_alsa_stream_t * alsa_stream) ++{ ++ VC_AUDIO_MSG_T m; ++ AUDIO_INSTANCE_T *instance = alsa_stream->instance; ++ int32_t success; ++ int ret; ++ LOG_DBG(" .. IN\n"); ++ ++ vcos_mutex_lock(&instance->vchi_mutex); ++ vchi_service_use(instance->vchi_handle[0]); ++ ++ m.type = VC_AUDIO_MSG_TYPE_STOP; ++ m.u.stop.draining = alsa_stream->draining; ++ ++ /* Send the message to the videocore */ ++ success = vchi_msg_queue(instance->vchi_handle[0], ++ &m, sizeof m, ++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); ++ ++ if (success != 0) { ++ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)", ++ __func__, success); ++ ++ ret = -1; ++ goto unlock; ++ } ++ ++ ret = 0; ++ ++unlock: ++ vchi_service_release(instance->vchi_handle[0]); ++ vcos_mutex_unlock(&instance->vchi_mutex); ++ LOG_DBG(" .. OUT\n"); ++ return ret; ++} ++ ++int bcm2835_audio_close(bcm2835_alsa_stream_t * alsa_stream) ++{ ++ VC_AUDIO_MSG_T m; ++ AUDIO_INSTANCE_T *instance = alsa_stream->instance; ++ int32_t success; ++ int ret; ++ LOG_DBG(" .. IN\n"); ++ ++ my_workqueue_quit(alsa_stream); ++ ++ vcos_mutex_lock(&instance->vchi_mutex); ++ vchi_service_use(instance->vchi_handle[0]); ++ ++ m.type = VC_AUDIO_MSG_TYPE_CLOSE; ++ instance->got_result = 0; ++ /* Send the message to the videocore */ ++ success = vchi_msg_queue(instance->vchi_handle[0], ++ &m, sizeof m, ++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); ++ ++ if (success != 0) { ++ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)", ++ __func__, success); ++ ret = -1; ++ goto unlock; ++ } ++ while (!instance->got_result) { ++ success = vcos_event_wait(&instance->msg_avail_event); ++ if (success != VCOS_SUCCESS) { ++ LOG_ERR("%s: failed on waiting for event (status=%d)", ++ __func__, success); ++ ++ ret = -1; ++ goto unlock; ++ } ++ } ++ if (instance->result != 0) { ++ LOG_ERR("%s: failed result (status=%d)", ++ __func__, instance->result); ++ ++ ret = -1; ++ goto unlock; ++ } ++ ++ ret = 0; ++ ++unlock: ++ vchi_service_release(instance->vchi_handle[0]); ++ vcos_mutex_unlock(&instance->vchi_mutex); ++ ++ /* Stop the audio service */ ++ if (instance) { ++ vc_vchi_audio_deinit(instance); ++ alsa_stream->instance = NULL; ++ } ++ LOG_DBG(" .. OUT\n"); ++ return ret; ++} ++ ++int bcm2835_audio_write(bcm2835_alsa_stream_t * alsa_stream, uint32_t count, ++ void *src) ++{ ++ VC_AUDIO_MSG_T m; ++ AUDIO_INSTANCE_T *instance = alsa_stream->instance; ++ int32_t success; ++ int ret; ++ ++ LOG_DBG(" .. IN\n"); ++ ++ LOG_INFO(" Writing %d bytes from %p\n", count, src); ++ ++ vcos_mutex_lock(&instance->vchi_mutex); ++ vchi_service_use(instance->vchi_handle[0]); ++ ++ m.type = VC_AUDIO_MSG_TYPE_WRITE; ++ m.u.write.count = count; ++ m.u.write.callback = alsa_stream->fifo_irq_handler; ++ m.u.write.cookie = alsa_stream; ++ m.u.write.silence = src == NULL; ++ ++ /* Send the message to the videocore */ ++ success = vchi_msg_queue(instance->vchi_handle[0], ++ &m, sizeof m, ++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); ++ ++ if (success != 0) { ++ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)", ++ __func__, success); ++ ++ ret = -1; ++ goto unlock; ++ } ++ LOG_DBG(" ... sent header\n"); ++ if (!m.u.write.silence) { ++ /* Send the message to the videocore */ ++ success = vchi_bulk_queue_transmit(instance->vchi_handle[0], ++ src, count, ++ 0 * ++ VCHI_FLAGS_BLOCK_UNTIL_QUEUED ++ + ++ 1 * ++ VCHI_FLAGS_BLOCK_UNTIL_DATA_READ, ++ NULL); ++ if (success != 0) { ++ LOG_ERR ++ ("%s: failed on vchi_bulk_queue_transmit (status=%d)", ++ __func__, success); ++ ++ ret = -1; ++ goto unlock; ++ } ++ } ++ ret = 0; ++ ++unlock: ++ vchi_service_release(instance->vchi_handle[0]); ++ vcos_mutex_unlock(&instance->vchi_mutex); ++ LOG_DBG(" .. OUT\n"); ++ return ret; ++} ++ ++/** ++ * Returns all buffers from arm->vc ++ */ ++void bcm2835_audio_flush_buffers(bcm2835_alsa_stream_t * alsa_stream) ++{ ++ LOG_DBG(" .. IN\n"); ++ LOG_DBG(" .. OUT\n"); ++ return; ++} ++ ++/** ++ * Forces VC to flush(drop) its filled playback buffers and ++ * return them the us. (VC->ARM) ++ */ ++void bcm2835_audio_flush_playback_buffers(bcm2835_alsa_stream_t * alsa_stream) ++{ ++ LOG_DBG(" .. IN\n"); ++ LOG_DBG(" .. OUT\n"); ++} ++ ++uint32_t bcm2835_audio_retrieve_buffers(bcm2835_alsa_stream_t * alsa_stream) ++{ ++ uint32_t count = atomic_read(&alsa_stream->retrieved); ++ atomic_sub(count, &alsa_stream->retrieved); ++ return count; ++} +diff --git a/sound/arm/bcm2835.c b/sound/arm/bcm2835.c +new file mode 100755 +index 0000000..3f6b0ea +--- /dev/null ++++ b/sound/arm/bcm2835.c @@ -0,0 +1,424 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. @@ -75135,186 +91084,12 @@ diff -Naur linux-3.2.23/sound/arm/bcm2835.c linux-rpi-bootc-3.2.23/sound/arm/bcm +MODULE_DESCRIPTION("Alsa driver for BCM2835 chip"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:bcm2835_alsa"); -diff -Naur linux-3.2.23/sound/arm/bcm2835-ctl.c linux-rpi-bootc-3.2.23/sound/arm/bcm2835-ctl.c ---- linux-3.2.23/sound/arm/bcm2835-ctl.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/sound/arm/bcm2835-ctl.c 2012-07-15 20:28:25.380073109 +0200 -@@ -0,0 +1,172 @@ -+/***************************************************************************** -+* Copyright 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "bcm2835.h" -+ -+static int snd_bcm2835_ctl_info(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_info *uinfo) -+{ -+ if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) { -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; -+ uinfo->count = 1; -+ uinfo->value.integer.min = -10240; -+ uinfo->value.integer.max = 2303; -+ } else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) { -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; -+ uinfo->count = 1; -+ uinfo->value.integer.min = 0; -+ uinfo->value.integer.max = 1; -+ } else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) { -+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; -+ uinfo->count = 1; -+ uinfo->value.integer.min = 0; -+ uinfo->value.integer.max = AUDIO_DEST_MAX-0; -+ } -+ -+ return 0; -+} -+ -+static int snd_bcm2835_ctl_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol); -+ -+ BUG_ON(!chip && !(chip->avail_substreams & AVAIL_SUBSTREAMS_MASK)); -+ -+ if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) -+ ucontrol->value.integer.value[0] = chip->volume; -+ else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) -+ ucontrol->value.integer.value[0] = chip->mute; -+ else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) -+ ucontrol->value.integer.value[0] = chip->dest; -+ -+ return 0; -+} -+ -+static int snd_bcm2835_ctl_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct bcm2835_chip *chip = snd_kcontrol_chip(kcontrol); -+ int changed = 0; -+ -+ if (kcontrol->private_value == PCM_PLAYBACK_VOLUME) { -+ if (chip->mute) { -+ chip->mute = 0; -+ changed = 1; -+ } -+ if (changed -+ || (ucontrol->value.integer.value[0] != chip->volume)) { -+ int atten; -+ -+ chip->volume = ucontrol->value.integer.value[0]; -+ changed = 1; -+ atten = -((chip->volume << 8) / 100); -+ chip->volume = atten; -+ } -+ -+ } else if (kcontrol->private_value == PCM_PLAYBACK_MUTE) { -+ /* Not implemented */ -+ if (ucontrol->value.integer.value[0] != chip->mute) { -+ chip->mute = ucontrol->value.integer.value[0]; -+ changed = 0; -+ } -+ } else if (kcontrol->private_value == PCM_PLAYBACK_DEVICE) { -+ if (ucontrol->value.integer.value[0] != chip->dest) { -+ chip->dest = ucontrol->value.integer.value[0]; -+ changed = 1; -+ } -+ } -+ -+ if (changed) { -+ if (bcm2835_audio_set_ctls(chip)) -+ printk(KERN_ERR "Failed to set ALSA controls..\n"); -+ } -+ -+ return changed; -+} -+ -+static DECLARE_TLV_DB_SCALE(snd_bcm2835_db_scale, -10240, 1, 1); -+ -+static struct snd_kcontrol_new snd_bcm2835_ctl[] __devinitdata = { -+ { -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = "PCM Playback Volume", -+ .index = 0, -+ .access = -+ SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE, -+ .private_value = PCM_PLAYBACK_VOLUME, -+ .info = snd_bcm2835_ctl_info, -+ .get = snd_bcm2835_ctl_get, -+ .put = snd_bcm2835_ctl_put, -+ .count = 1, -+ .tlv = {.p = snd_bcm2835_db_scale} -+ }, -+ { -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = "PCM Playback Switch", -+ .index = 0, -+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, -+ .private_value = PCM_PLAYBACK_MUTE, -+ .info = snd_bcm2835_ctl_info, -+ .get = snd_bcm2835_ctl_get, -+ .put = snd_bcm2835_ctl_put, -+ .count = 1, -+ }, -+ { -+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, -+ .name = "PCM Playback Route", -+ .index = 0, -+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, -+ .private_value = PCM_PLAYBACK_DEVICE, -+ .info = snd_bcm2835_ctl_info, -+ .get = snd_bcm2835_ctl_get, -+ .put = snd_bcm2835_ctl_put, -+ .count = 1, -+ }, -+}; -+ -+int __devinit snd_bcm2835_new_ctl(bcm2835_chip_t * chip) -+{ -+ int err; -+ unsigned int idx; -+ -+ strcpy(chip->card->mixername, "Broadcom Mixer"); -+ for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_ctl); idx++) { -+ err = -+ snd_ctl_add(chip->card, -+ snd_ctl_new1(&snd_bcm2835_ctl[idx], chip)); -+ if (err < 0) -+ return err; -+ } -+ return 0; -+} -diff -Naur linux-3.2.23/sound/arm/bcm2835.h linux-rpi-bootc-3.2.23/sound/arm/bcm2835.h ---- linux-3.2.23/sound/arm/bcm2835.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/sound/arm/bcm2835.h 2012-07-15 20:28:25.381073128 +0200 -@@ -0,0 +1,242 @@ +diff --git a/sound/arm/bcm2835.h b/sound/arm/bcm2835.h +new file mode 100755 +index 0000000..b966e28 +--- /dev/null ++++ b/sound/arm/bcm2835.h +@@ -0,0 +1,155 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved. +* @@ -75332,8 +91107,6 @@ diff -Naur linux-3.2.23/sound/arm/bcm2835.h linux-rpi-bootc-3.2.23/sound/arm/bcm +#ifndef __SOUND_ARM_BCM2835_H +#define __SOUND_ARM_BCM2835_H + -+#define SUBSTREAM_NUM 1 -+ +#include +#include +#include @@ -75344,13 +91117,14 @@ diff -Naur linux-3.2.23/sound/arm/bcm2835.h linux-rpi-bootc-3.2.23/sound/arm/bcm +#include +#include + -+/* #define DUMP_RAW_DATA */ -+//#define AUDIO_DEBUG_ENABLE -+//#define AUDIO_VERBOSE_DEBUG_ENABLE ++/* ++#define AUDIO_DEBUG_ENABLE ++#define AUDIO_VERBOSE_DEBUG_ENABLE ++*/ + +/* Debug macros */ -+#ifdef AUDIO_DEBUG_ENABLE + ++#ifdef AUDIO_DEBUG_ENABLE +#ifdef AUDIO_VERBOSE_DEBUG_ENABLE + +#define audio_debug(fmt, arg...) \ @@ -75361,17 +91135,17 @@ diff -Naur linux-3.2.23/sound/arm/bcm2835.h linux-rpi-bootc-3.2.23/sound/arm/bcm + +#else + -+#define audio_debug(fmt, arg...) do {} while (0) ++#define audio_debug(fmt, arg...) + -+#define audio_info(fmt, arg...) do {} while (0) ++#define audio_info(fmt, arg...) + +#endif /* AUDIO_VERBOSE_DEBUG_ENABLE */ + +#else + -+#define audio_debug(fmt, arg...) do {} while (0) ++#define audio_debug(fmt, arg...) + -+#define audio_info(fmt, arg...) do {} while (0) ++#define audio_info(fmt, arg...) + +#endif /* AUDIO_DEBUG_ENABLE */ + @@ -75386,75 +91160,15 @@ diff -Naur linux-3.2.23/sound/arm/bcm2835.h linux-rpi-bootc-3.2.23/sound/arm/bcm + +#define MAX_SUBSTREAMS (8) +#define AVAIL_SUBSTREAMS_MASK (0xff) ++enum { ++ CTRL_VOL_MUTE, ++ CTRL_VOL_UNMUTE ++}; + -+#define AUDIO_IPC_BLOCK_NUM_BUFFERS (8) -+#define AUDIO_IPC_BLOCK_BUFFER_SIZE (1024*8) ++/* macros for alsa2chip and chip2alsa, instead of functions */ + -+#define AUDIO_CONTROL_OFFSET (0x00) -+#define CTRL_EN_SHIFT (0) -+#define CTRL_EN_MASK (0x00000001) -+#define CTRL_PLAY_SHIFT (1) -+#define CTRL_PLAY_MASK (0x00000002) -+#define CTRL_MUTE_SHIFT (2) -+#define CTRL_MUTE_MASK (0x00000004) -+#define CTRL_SETUP_SHIFT (3) -+#define CTRL_SETUP_MASK (0x00000008) -+#define CTRL_FLUSH_SHIFT (4) -+#define CTRL_FLUSH_MASK (0x00000010) -+#define CTRL_STOPMODE_SHIFT (5) -+#define CTRL_STOPMODE_MASK (0x00000020) -+ -+#define AUDIO_STATUS_OFFSET (0x04) -+#define STAT_EN_SHIFT (0) -+#define STAT_EN_MASK (0x00000001) -+#define STAT_PLAY_SHIFT (1) -+#define STAT_PLAY_MASK (0x00000002) -+#define STAT_MUTE_SHIFT (2) -+#define STAT_MUTE_MASK (0x00000004) -+#define STAT_SETUP_SHIFT (3) -+#define STAT_SETUP_MASK (0x00000008) -+#define STAT_FLUSH_SHIFT (4) -+#define STAT_FLUSH_MASK (0x00000010) -+#define STAT_STOPMODE_SHIFT (5) -+#define STAT_STOPMODE_MASK (0x00000020) -+ -+/* Interrupt status */ -+#define AUDIO_INTSTAT_OFFSET (0x08) -+#define INTSTAT_CONTROL_SHIFT (0) -+#define INTSTAT_CONTROL_MASK (0x0000000f) -+#define INTSTAT_FIFO_SHIFT (4) -+#define INTSTAT_FIFO_MASK (0x000000f0) -+ -+/* Configuration */ -+#define AUDIO_DESTINATION_OFFSET (0x0C) -+#define AUDIO_SAMPLE_RATE_OFFSET (0x10) -+#define AUDIO_BIT_RATE_OFFSET (0x14) -+#define AUDIO_VOLUME_OFFSET (0x18) -+#define AUDIO_CHANNELS_OFFSET (0x1C) -+ -+/* Implemention of peterson's algorithm for shared memory semaphores */ -+#define AUDIO_FLAG0_OFFSET (0x20) -+#define AUDIO_FLAG1_OFFSET (0x24) -+#define AUDIO_TURN_OFFSET (0x28) -+ -+/* Fifo registers */ -+#define AUDIO_IN_WRITE_PTR_OFFSET (0x30) -+#define AUDIO_IN_READ_PTR_OFFSET (0x34) -+#define AUDIO_IN_FIFO_SIZE_OFFSET (0x38) -+#define AUDIO_IN_FIFO_ENTRY_OFFSET (0x3C) -+#define AUDIO_IN_FIFO_START_OFFSET (0x40) -+ -+/* 8 entries here of 4 words each = 0x80 gap from 0x50 */ -+#define AUDIO_IN_FIFO_OFFSET (0x50) -+ -+#define AUDIO_OUT_WRITE_PTR_OFFSET (0xD0) -+#define AUDIO_OUT_READ_PTR_OFFSET (0xD4) -+#define AUDIO_OUT_FIFO_SIZE_OFFSET (0xD8) -+#define AUDIO_OUT_FIFO_ENTRY_OFFSET (0xDC) -+#define AUDIO_OUT_FIFO_START_OFFSET (0xE0) -+ -+/* 8 entries here of 4 words each = 0x80 gap from 0xF0 */ -+#define AUDIO_OUT_FIFO_OFFSET (0xF0) ++#define alsa2chip(vol) (uint)(-((vol << 8) / 100)) /* convert alsa to chip volume (defined as macro rather than function call) */ ++#define chip2alsa(vol) -((vol * 100) >> 8) /* convert chip to alsa volume */ + +/* Some constants for values .. */ +typedef enum { @@ -75470,15 +91184,6 @@ diff -Naur linux-3.2.23/sound/arm/bcm2835.h linux-rpi-bootc-3.2.23/sound/arm/bcm + PCM_PLAYBACK_DEVICE, +} SND_BCM2835_CTRL_T; + -+/* this struct is tightly packed - its size is 16bytes */ -+typedef struct { -+ uint32_t buffer_id; -+ uint32_t buffer_size; -+ uint32_t buffer_ptr; -+ uint32_t spare; -+ -+} AUDIO_FIFO_ENTRY_T; -+ +/* definition of the chip-specific record */ +typedef struct bcm2835_chip { + struct snd_card *card; @@ -75489,20 +91194,11 @@ diff -Naur linux-3.2.23/sound/arm/bcm2835.h linux-rpi-bootc-3.2.23/sound/arm/bcm + struct bcm2835_alsa_stream *alsa_stream[MAX_SUBSTREAMS]; + + int volume; ++ int old_volume; /* stores the volume value whist muted */ + int dest; + int mute; +} bcm2835_chip_t; + -+typedef struct bcm2835_audio_buffer { -+ uint32_t buffer_id; -+ phys_addr_t bus_addr; -+ uint8_t __iomem *start; -+ uint32_t size; -+ uint32_t data_left; -+ struct list_head link; -+ -+} bcm2835_audio_buffer_t; -+ +typedef struct bcm2835_alsa_stream { + bcm2835_chip_t *chip; + struct snd_pcm_substream *substream; @@ -75517,10 +91213,6 @@ diff -Naur linux-3.2.23/sound/arm/bcm2835.h linux-rpi-bootc-3.2.23/sound/arm/bcm + int running; + int draining; + -+#ifdef DUMP_RAW_DATA -+ /* for debug */ -+ int file; -+#endif + unsigned int pos; + unsigned int buffer_size; + unsigned int period_size; @@ -75537,9 +91229,6 @@ diff -Naur linux-3.2.23/sound/arm/bcm2835.h linux-rpi-bootc-3.2.23/sound/arm/bcm +int snd_bcm2835_new_ctl(bcm2835_chip_t * chip); +int snd_bcm2835_new_pcm(bcm2835_chip_t * chip); + -+void bcm2835_audio_fifo_get_lock(bcm2835_alsa_stream_t * alsa_stream); -+void bcm2835_audio_fifo_put_lock(bcm2835_alsa_stream_t * alsa_stream); -+ +int bcm2835_audio_open(bcm2835_alsa_stream_t * alsa_stream); +int bcm2835_audio_close(bcm2835_alsa_stream_t * alsa_stream); +int bcm2835_audio_set_params(bcm2835_alsa_stream_t * alsa_stream, @@ -75551,1270 +91240,16 @@ diff -Naur linux-3.2.23/sound/arm/bcm2835.h linux-rpi-bootc-3.2.23/sound/arm/bcm +int bcm2835_audio_set_ctls(bcm2835_chip_t * chip); +int bcm2835_audio_write(bcm2835_alsa_stream_t * alsa_stream, uint32_t count, + void *src); -+//uint32_t bcm2835_audio_buffers_consumed_bytes(bcm2835_alsa_stream_t *alsa_stream); +uint32_t bcm2835_audio_retrieve_buffers(bcm2835_alsa_stream_t * alsa_stream); +void bcm2835_audio_flush_buffers(bcm2835_alsa_stream_t * alsa_stream); +void bcm2835_audio_flush_playback_buffers(bcm2835_alsa_stream_t * alsa_stream); + +#endif /* __SOUND_ARM_BCM2835_H */ -diff -Naur linux-3.2.23/sound/arm/bcm2835-pcm.c linux-rpi-bootc-3.2.23/sound/arm/bcm2835-pcm.c ---- linux-3.2.23/sound/arm/bcm2835-pcm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/sound/arm/bcm2835-pcm.c 2012-07-15 20:28:25.380073109 +0200 -@@ -0,0 +1,400 @@ -+/***************************************************************************** -+* Copyright 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#include -+#include -+ -+#include "bcm2835.h" -+ -+/* hardware definition */ -+static struct snd_pcm_hardware snd_bcm2835_playback_hw = { -+ .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER), -+ .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, -+ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, -+ .rate_min = 8000, -+ .rate_max = 48000, -+ .channels_min = 1, -+ .channels_max = 2, -+ .buffer_bytes_max = (4 * 8 - 1) * 1024, /* Needs to be less than audioplay buffer size */ -+ .period_bytes_min = 1 * 1024, -+ .period_bytes_max = (4 * 8 - 1) * 1024, -+ .periods_min = 1, -+ .periods_max = 4 * 8 - 1, -+}; -+ -+static void snd_bcm2835_playback_free(struct snd_pcm_runtime *runtime) -+{ -+ audio_info("Freeing up alsa stream here ..\n"); -+ if (runtime->private_data) -+ kfree(runtime->private_data); -+ runtime->private_data = NULL; -+} -+ -+static irqreturn_t bcm2835_playback_fifo_irq(int irq, void *dev_id) -+{ -+ bcm2835_alsa_stream_t *alsa_stream = (bcm2835_alsa_stream_t *) dev_id; -+ uint32_t consumed = 0; -+ int new_period = 0; -+ -+ audio_info(" .. IN\n"); -+ -+ audio_info("alsa_stream=%p substream=%p\n", alsa_stream, -+ alsa_stream ? alsa_stream->substream : 0); -+ -+ if (alsa_stream->open) -+ consumed = bcm2835_audio_retrieve_buffers(alsa_stream); -+ -+ /* We get called only if playback was triggered, So, the number of buffers we retrieve in -+ * each iteration are the buffers that have been played out already -+ */ -+ -+ if (alsa_stream->period_size) { -+ if ((alsa_stream->pos / alsa_stream->period_size) != -+ ((alsa_stream->pos + consumed) / alsa_stream->period_size)) -+ new_period = 1; -+ } -+ audio_debug("updating pos cur: %d + %d max:%d new_period:%d\n", -+ alsa_stream->pos, -+ (consumed /** AUDIO_IPC_BLOCK_BUFFER_SIZE*/ ), -+ alsa_stream->buffer_size, new_period); -+ if (alsa_stream->buffer_size) { -+ alsa_stream->pos += consumed; -+ alsa_stream->pos %= alsa_stream->buffer_size; -+ } -+ if (alsa_stream->substream) { -+ if (new_period) -+ snd_pcm_period_elapsed(alsa_stream->substream); -+ } else { -+ audio_warning(" unexpected NULL substream\n"); -+ } -+ audio_info(" .. OUT\n"); -+ -+ return IRQ_HANDLED; -+} -+ -+/* open callback */ -+static int snd_bcm2835_playback_open(struct snd_pcm_substream *substream) -+{ -+ bcm2835_chip_t *chip = snd_pcm_substream_chip(substream); -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ bcm2835_alsa_stream_t *alsa_stream; -+ int idx; -+ int err; -+ -+ audio_info(" .. IN (%d)\n", substream->number); -+ -+ audio_warning("Alsa open (%d)\n", substream->number); -+ idx = substream->number; -+ -+ if (idx > MAX_SUBSTREAMS) { -+ audio_error -+ ("substream(%d) device doesn't exist max(%d) substreams allowed\n", -+ idx, MAX_SUBSTREAMS); -+ err = -ENODEV; -+ goto out; -+ } -+ -+ /* Check if we are ready */ -+ if (!(chip->avail_substreams & (1 << idx))) { -+ /* We are not ready yet */ -+ audio_error("substream(%d) device is not ready yet\n", idx); -+ err = -EAGAIN; -+ goto out; -+ } -+ -+ alsa_stream = kzalloc(sizeof(bcm2835_alsa_stream_t), GFP_KERNEL); -+ if (alsa_stream == NULL) { -+ return -ENOMEM; -+ } -+ -+ /* Initialise alsa_stream */ -+ alsa_stream->chip = chip; -+ alsa_stream->substream = substream; -+ alsa_stream->idx = idx; -+ chip->alsa_stream[idx] = alsa_stream; -+ -+ sema_init(&alsa_stream->buffers_update_sem, 0); -+ sema_init(&alsa_stream->control_sem, 0); -+ spin_lock_init(&alsa_stream->lock); -+ -+ /* Enabled in start trigger, called on each "fifo irq" after that */ -+ alsa_stream->enable_fifo_irq = 0; -+ alsa_stream->fifo_irq_handler = bcm2835_playback_fifo_irq; -+ -+ runtime->private_data = alsa_stream; -+ runtime->private_free = snd_bcm2835_playback_free; -+ runtime->hw = snd_bcm2835_playback_hw; -+ -+ /* minimum 16 bytes alignment (for vchiq bulk transfers) */ -+ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, -+ 16); -+ -+ err = bcm2835_audio_open(alsa_stream); -+ if (err != 0) { -+ kfree(alsa_stream); -+ return err; -+ } -+ -+ alsa_stream->open = 1; -+ alsa_stream->draining = 1; -+ -+out: -+ audio_info(" .. OUT =%d\n", err); -+ -+ return err; -+} -+ -+/* close callback */ -+static int snd_bcm2835_playback_close(struct snd_pcm_substream *substream) -+{ -+ /* the hardware-specific codes will be here */ -+ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; -+ -+ audio_info(" .. IN\n"); -+ audio_warning("Alsa close\n"); -+ -+ /* -+ * Call stop if it's still running. This happens when app -+ * is force killed and we don't get a stop trigger. -+ */ -+ if (alsa_stream->running) { -+ int err; -+ err = bcm2835_audio_stop(alsa_stream); -+ alsa_stream->running = 0; -+ if (err != 0) -+ audio_error(" Failed to STOP alsa device\n"); -+ } -+ -+ alsa_stream->period_size = 0; -+ alsa_stream->buffer_size = 0; -+ -+ if (alsa_stream->open) { -+ alsa_stream->open = 0; -+ bcm2835_audio_close(alsa_stream); -+ } -+ if (alsa_stream->chip) -+ alsa_stream->chip->alsa_stream[alsa_stream->idx] = NULL; -+ /* -+ * Do not free up alsa_stream here, it will be freed up by -+ * runtime->private_free callback we registered in *_open above -+ */ -+ -+ audio_info(" .. OUT\n"); -+ -+ return 0; -+} -+ -+/* hw_params callback */ -+static int snd_bcm2835_pcm_hw_params(struct snd_pcm_substream *substream, -+ struct snd_pcm_hw_params *params) -+{ -+ int err; -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ bcm2835_alsa_stream_t *alsa_stream = -+ (bcm2835_alsa_stream_t *) runtime->private_data; -+ -+ audio_info(" .. IN\n"); -+ -+ err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); -+ if (err < 0) { -+ audio_error -+ (" pcm_lib_malloc failed to allocated pages for buffers\n"); -+ return err; -+ } -+ -+ err = bcm2835_audio_set_params(alsa_stream, params_channels(params), -+ params_rate(params), -+ snd_pcm_format_width(params_format -+ (params))); -+ if (err < 0) { -+ audio_error(" error setting hw params\n"); -+ } -+ -+ bcm2835_audio_setup(alsa_stream); -+ audio_info(" .. OUT\n"); -+ -+ return err; -+} -+ -+/* hw_free callback */ -+static int snd_bcm2835_pcm_hw_free(struct snd_pcm_substream *substream) -+{ -+ audio_info(" .. IN\n"); -+ return snd_pcm_lib_free_pages(substream); -+} -+ -+/* prepare callback */ -+static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; -+ -+ audio_info(" .. IN\n"); -+ -+ alsa_stream->buffer_size = snd_pcm_lib_buffer_bytes(substream); -+ alsa_stream->period_size = snd_pcm_lib_period_bytes(substream); -+ alsa_stream->pos = 0; -+ -+ audio_debug("buffer_size=%d, period_size=%d pos=%d frame_bits=%d\n", -+ alsa_stream->buffer_size, alsa_stream->period_size, -+ alsa_stream->pos, runtime->frame_bits); -+ -+ audio_info(" .. OUT\n"); -+ return 0; -+} -+ -+/* trigger callback */ -+static int snd_bcm2835_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; -+ int err = 0; -+ -+ audio_info(" .. IN\n"); -+ -+ switch (cmd) { -+ case SNDRV_PCM_TRIGGER_START: -+ audio_debug("bcm2835_AUDIO_TRIGGER_START running=%d\n", -+ alsa_stream->running); -+ if (!alsa_stream->running) { -+ err = bcm2835_audio_start(alsa_stream); -+ if (err == 0) { -+ alsa_stream->running = 1; -+ alsa_stream->draining = 1; -+ } -+ } -+ break; -+ case SNDRV_PCM_TRIGGER_STOP: -+ audio_debug -+ ("bcm2835_AUDIO_TRIGGER_STOP running=%d draining=%d\n", -+ runtime->status->state == SNDRV_PCM_STATE_DRAINING, -+ alsa_stream->running); -+ if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { -+ audio_info("DRAINING\n"); -+ alsa_stream->draining = 1; -+ } else { -+ audio_info("DROPPING\n"); -+ alsa_stream->draining = 0; -+ } -+ if (alsa_stream->running) { -+ err = bcm2835_audio_stop(alsa_stream); -+ if (err != 0) -+ audio_error(" Failed to STOP alsa device\n"); -+ alsa_stream->running = 0; -+ } -+ break; -+ default: -+ err = -EINVAL; -+ } -+ -+ audio_info(" .. OUT\n"); -+ return err; -+} -+ -+/* pointer callback */ -+static snd_pcm_uframes_t -+snd_bcm2835_pcm_pointer(struct snd_pcm_substream *substream) -+{ -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; -+ -+ audio_info(" .. IN\n"); -+ -+ audio_debug("pcm_pointer... (%d) hwptr=%d appl=%d pos=%d\n", 0, -+ frames_to_bytes(runtime, runtime->status->hw_ptr), -+ frames_to_bytes(runtime, runtime->control->appl_ptr), -+ alsa_stream->pos); -+ -+ audio_info(" .. OUT\n"); -+ return bytes_to_frames(runtime, alsa_stream->pos); -+} -+ -+static int snd_bcm2835_pcm_copy(struct snd_pcm_substream *substream, -+ int channel, snd_pcm_uframes_t pos, void *src, -+ snd_pcm_uframes_t count) -+{ -+ int ret; -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; -+ -+ audio_info(" .. IN\n"); -+ audio_debug("copy.......... (%d) hwptr=%d appl=%d pos=%d\n", -+ frames_to_bytes(runtime, count), frames_to_bytes(runtime, -+ runtime-> -+ status-> -+ hw_ptr), -+ frames_to_bytes(runtime, runtime->control->appl_ptr), -+ alsa_stream->pos); -+ ret = -+ bcm2835_audio_write(alsa_stream, frames_to_bytes(runtime, count), -+ src); -+ audio_info(" .. OUT\n"); -+ return ret; -+} -+ -+static int snd_bcm2835_pcm_lib_ioctl(struct snd_pcm_substream *substream, -+ unsigned int cmd, void *arg) -+{ -+ int ret = snd_pcm_lib_ioctl(substream, cmd, arg); -+ audio_info(" .. substream=%p, cmd=%d, arg=%p (%x) ret=%d\n", substream, -+ cmd, arg, arg ? *(unsigned *)arg : 0, ret); -+ return ret; -+} -+ -+/* operators */ -+static struct snd_pcm_ops snd_bcm2835_playback_ops = { -+ .open = snd_bcm2835_playback_open, -+ .close = snd_bcm2835_playback_close, -+ .ioctl = snd_bcm2835_pcm_lib_ioctl, -+ .hw_params = snd_bcm2835_pcm_hw_params, -+ .hw_free = snd_bcm2835_pcm_hw_free, -+ .prepare = snd_bcm2835_pcm_prepare, -+ .trigger = snd_bcm2835_pcm_trigger, -+ .pointer = snd_bcm2835_pcm_pointer, -+ .copy = snd_bcm2835_pcm_copy, -+}; -+ -+/* create a pcm device */ -+int __devinit snd_bcm2835_new_pcm(bcm2835_chip_t * chip) -+{ -+ struct snd_pcm *pcm; -+ int err; -+ -+ audio_info(" .. IN\n"); -+ err = -+ snd_pcm_new(chip->card, "bcm2835 ALSA", 0, MAX_SUBSTREAMS, 0, &pcm); -+ if (err < 0) -+ return err; -+ pcm->private_data = chip; -+ strcpy(pcm->name, "bcm2835 ALSA"); -+ chip->pcm = pcm; -+ chip->dest = AUDIO_DEST_AUTO; -+ chip->volume = 100; -+ /* set operators */ -+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, -+ &snd_bcm2835_playback_ops); -+ -+ /* pre-allocation of buffers */ -+ /* NOTE: this may fail */ -+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, -+ snd_dma_continuous_data -+ (GFP_KERNEL), 64 * 1024, -+ 64 * 1024); -+ -+ audio_info(" .. OUT\n"); -+ -+ return 0; -+} -diff -Naur linux-3.2.23/sound/arm/bcm2835-vchiq.c linux-rpi-bootc-3.2.23/sound/arm/bcm2835-vchiq.c ---- linux-3.2.23/sound/arm/bcm2835-vchiq.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/sound/arm/bcm2835-vchiq.c 2012-07-15 20:28:25.381073128 +0200 -@@ -0,0 +1,818 @@ -+/***************************************************************************** -+* Copyright 2011 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "bcm2835.h" -+ -+/* ---- Include Files -------------------------------------------------------- */ -+ -+#include "interface/vchi/vchi.h" -+#include "interface/vcos/vcos.h" -+#include "interface/vcos/vcos_logging.h" -+#include "vc_vchi_audioserv_defs.h" -+ -+/* ---- Private Constants and Types ------------------------------------------ */ -+ -+/* VCOS logging category for this service */ -+#define VCOS_LOG_CATEGORY (&audio_log_category) -+ -+/* Default VCOS logging level */ -+#define LOG_LEVEL VCOS_LOG_WARN -+ -+/* Logging macros (for remapping to other logging mechanisms, i.e., printf) */ -+#define LOG_ERR( fmt, arg... ) vcos_log_error( "%s:%d " fmt, __func__, __LINE__, ##arg) -+#define LOG_WARN( fmt, arg... ) vcos_log_warn( "%s:%d " fmt, __func__, __LINE__, ##arg) -+#define LOG_INFO( fmt, arg... ) vcos_log_info( "%s:%d " fmt, __func__, __LINE__, ##arg) -+#define LOG_DBG( fmt, arg... ) vcos_log_info( "%s:%d " fmt, __func__, __LINE__, ##arg) -+ -+typedef struct opaque_AUDIO_INSTANCE_T { -+ uint32_t num_connections; -+ VCHI_SERVICE_HANDLE_T vchi_handle[VCHI_MAX_NUM_CONNECTIONS]; -+ VCOS_EVENT_T msg_avail_event; -+ VCOS_MUTEX_T vchi_mutex; -+ bcm2835_alsa_stream_t *alsa_stream; -+ int32_t result, got_result; -+} AUDIO_INSTANCE_T; -+ -+/* ---- Private Variables ---------------------------------------------------- */ -+ -+/* VCOS logging category for this service */ -+static VCOS_LOG_CAT_T audio_log_category; -+ -+/* ---- Private Function Prototypes ------------------------------------------ */ -+ -+/* ---- Private Functions ---------------------------------------------------- */ -+ -+static int bcm2835_audio_stop_worker(bcm2835_alsa_stream_t * alsa_stream); -+static int bcm2835_audio_start_worker(bcm2835_alsa_stream_t * alsa_stream); -+ -+typedef struct { -+ struct work_struct my_work; -+ bcm2835_alsa_stream_t *alsa_stream; -+ int x; -+} my_work_t; -+ -+static void my_wq_function(struct work_struct *work) -+{ -+ my_work_t *w = (my_work_t *) work; -+ int ret = -9; -+ LOG_DBG(" .. IN %p:%d\n", w->alsa_stream, w->x); -+ switch (w->x) { -+ case 1: -+ ret = bcm2835_audio_start_worker(w->alsa_stream); -+ break; -+ case 2: -+ ret = bcm2835_audio_stop_worker(w->alsa_stream); -+ break; -+ default: -+ LOG_ERR(" Unexpected work: %p:%d\n", w->alsa_stream, w->x); -+ break; -+ } -+ kfree((void *)work); -+ LOG_DBG(" .. OUT %d\n", ret); -+} -+ -+int bcm2835_audio_start(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ int ret = -1; -+ LOG_DBG(" .. IN\n"); -+ if (alsa_stream->my_wq) { -+ my_work_t *work = kmalloc(sizeof(my_work_t), GFP_ATOMIC); -+ /* Queue some work (item 1) */ -+ if (work) { -+ INIT_WORK((struct work_struct *)work, my_wq_function); -+ work->alsa_stream = alsa_stream; -+ work->x = 1; -+ if (queue_work -+ (alsa_stream->my_wq, (struct work_struct *)work)) -+ ret = 0; -+ } else -+ LOG_ERR(" .. Error: NULL work kmalloc\n"); -+ } -+ LOG_DBG(" .. OUT %d\n", ret); -+ return ret; -+} -+ -+int bcm2835_audio_stop(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ int ret = -1; -+ LOG_DBG(" .. IN\n"); -+ if (alsa_stream->my_wq) { -+ my_work_t *work = kmalloc(sizeof(my_work_t), GFP_ATOMIC); -+ /* Queue some work (item 1) */ -+ if (work) { -+ INIT_WORK((struct work_struct *)work, my_wq_function); -+ work->alsa_stream = alsa_stream; -+ work->x = 2; -+ if (queue_work -+ (alsa_stream->my_wq, (struct work_struct *)work)) -+ ret = 0; -+ } else -+ LOG_ERR(" .. Error: NULL work kmalloc\n"); -+ } -+ LOG_DBG(" .. OUT %d\n", ret); -+ return ret; -+} -+ -+void my_workqueue_init(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ alsa_stream->my_wq = create_workqueue("my_queue"); -+} -+ -+void my_workqueue_quit(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ if (alsa_stream->my_wq) { -+ flush_workqueue(alsa_stream->my_wq); -+ destroy_workqueue(alsa_stream->my_wq); -+ alsa_stream->my_wq = NULL; -+ } -+} -+ -+static void audio_vchi_callback(void *param, -+ const VCHI_CALLBACK_REASON_T reason, -+ void *msg_handle) -+{ -+ AUDIO_INSTANCE_T *instance = (AUDIO_INSTANCE_T *) param; -+ int32_t status; -+ int32_t msg_len; -+ VC_AUDIO_MSG_T m; -+ bcm2835_alsa_stream_t *alsa_stream = 0; -+ LOG_DBG(" .. IN instance=%p, param=%p, reason=%d, handle=%p\n", -+ instance, param, reason, msg_handle); -+ -+ if (!instance || reason != VCHI_CALLBACK_MSG_AVAILABLE) { -+ return; -+ } -+ alsa_stream = instance->alsa_stream; -+ status = vchi_msg_dequeue(instance->vchi_handle[0], -+ &m, sizeof m, &msg_len, VCHI_FLAGS_NONE); -+ if (m.type == VC_AUDIO_MSG_TYPE_RESULT) { -+ LOG_DBG -+ (" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_RESULT, success=%d\n", -+ instance, m.u.result.success); -+ BUG_ON(instance->got_result); -+ instance->result = m.u.result.success; -+ instance->got_result = 1; -+ vcos_event_signal(&instance->msg_avail_event); -+ } else if (m.type == VC_AUDIO_MSG_TYPE_COMPLETE) { -+ irq_handler_t callback = (irq_handler_t) m.u.complete.callback; -+ LOG_DBG -+ (" .. instance=%p, m.type=VC_AUDIO_MSG_TYPE_COMPLETE, complete=%d\n", -+ instance, m.u.complete.count); -+ if (alsa_stream && callback) { -+ atomic_add(m.u.complete.count, &alsa_stream->retrieved); -+ callback(0, alsa_stream); -+ } else { -+ LOG_DBG(" .. unexpected alsa_stream=%p, callback=%p\n", -+ alsa_stream, callback); -+ } -+ vcos_event_signal(&instance->msg_avail_event); -+ } else { -+ LOG_DBG(" .. unexpected m.type=%d\n", m.type); -+ } -+} -+ -+static AUDIO_INSTANCE_T *vc_vchi_audio_init(VCHI_INSTANCE_T vchi_instance, -+ VCHI_CONNECTION_T ** -+ vchi_connections, -+ uint32_t num_connections) -+{ -+ uint32_t i; -+ AUDIO_INSTANCE_T *instance; -+ VCOS_STATUS_T status; -+ -+ LOG_DBG("%s: start", __func__); -+ -+ if (num_connections > VCHI_MAX_NUM_CONNECTIONS) { -+ LOG_ERR("%s: unsupported number of connections %u (max=%u)", -+ __func__, num_connections, VCHI_MAX_NUM_CONNECTIONS); -+ -+ return NULL; -+ } -+ /* Allocate memory for this instance */ -+ instance = vcos_malloc(sizeof(*instance), "audio_instance"); -+ memset(instance, 0, sizeof(*instance)); -+ -+ instance->num_connections = num_connections; -+ /* Create the message available event */ -+ status = -+ vcos_event_create(&instance->msg_avail_event, "audio_msg_avail"); -+ if (status != VCOS_SUCCESS) { -+ LOG_ERR("%s: failed to create event (status=%d)", __func__, -+ status); -+ -+ goto err_free_mem; -+ } -+ /* Create a lock for exclusive, serialized VCHI connection access */ -+ status = vcos_mutex_create(&instance->vchi_mutex, "audio_vchi_mutex"); -+ if (status != VCOS_SUCCESS) { -+ LOG_ERR("%s: failed to create event (status=%d)", __func__, -+ status); -+ -+ goto err_delete_event; -+ } -+ /* Open the VCHI service connections */ -+ for (i = 0; i < num_connections; i++) { -+ SERVICE_CREATION_T params = { -+ VC_AUDIO_SERVER_NAME, // 4cc service code -+ vchi_connections[i], // passed in fn pointers -+ 0, // rx fifo size (unused) -+ 0, // tx fifo size (unused) -+ audio_vchi_callback, // service callback -+ instance, // service callback parameter -+ VCOS_TRUE, //TODO: remove VCOS_FALSE, // unaligned bulk recieves -+ VCOS_TRUE, //TODO: remove VCOS_FALSE, // unaligned bulk transmits -+ VCOS_FALSE // want crc check on bulk transfers -+ }; -+ -+ status = vchi_service_open(vchi_instance, ¶ms, -+ &instance->vchi_handle[i]); -+ if (status != VCOS_SUCCESS) { -+ LOG_ERR -+ ("%s: failed to open VCHI service connection (status=%d)", -+ __func__, status); -+ -+ goto err_close_services; -+ } -+ /* Finished with the service for now */ -+ vchi_service_release(instance->vchi_handle[i]); -+ } -+ -+ return instance; -+ -+err_close_services: -+ for (i = 0; i < instance->num_connections; i++) { -+ vchi_service_close(instance->vchi_handle[i]); -+ } -+ -+ vcos_mutex_delete(&instance->vchi_mutex); -+ -+err_delete_event: -+ vcos_event_delete(&instance->msg_avail_event); -+ -+err_free_mem: -+ vcos_free(instance); -+ -+ return NULL; -+} -+ -+static int32_t vc_vchi_audio_deinit(AUDIO_INSTANCE_T * instance) -+{ -+ uint32_t i; -+ -+ LOG_DBG(" .. IN\n"); -+ -+ if (instance == NULL) { -+ LOG_ERR("%s: invalid handle %p", __func__, instance); -+ -+ return -1; -+ } -+ -+ LOG_DBG(" .. about to lock (%d)\n", instance->num_connections); -+ vcos_mutex_lock(&instance->vchi_mutex); -+ -+ /* Close all VCHI service connections */ -+ for (i = 0; i < instance->num_connections; i++) { -+ int32_t success; -+ LOG_DBG(" .. %i:closing %p\n", i, instance->vchi_handle[i]); -+ vchi_service_use(instance->vchi_handle[i]); -+ -+ success = vchi_service_close(instance->vchi_handle[i]); -+ if (success != 0) { -+ LOG_ERR -+ ("%s: failed to close VCHI service connection (status=%d)", -+ __func__, success); -+ } -+ } -+ -+ vcos_mutex_unlock(&instance->vchi_mutex); -+ -+ vcos_mutex_delete(&instance->vchi_mutex); -+ -+ vcos_event_delete(&instance->msg_avail_event); -+ -+ vcos_free(instance); -+ -+ /* Unregister the log category so we can add it back next time */ -+ vcos_log_unregister(&audio_log_category); -+ -+ LOG_DBG(" .. OUT\n"); -+ -+ return 0; -+} -+ -+static int bcm2835_audio_open_connection(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ static VCHI_INSTANCE_T vchi_instance; -+ static VCHI_CONNECTION_T *vchi_connection; -+ AUDIO_INSTANCE_T *instance = alsa_stream->instance; -+ int ret; -+ LOG_DBG(" .. IN\n"); -+ -+ LOG_INFO("%s: start", __func__); -+ //BUG_ON(instance); -+ if (instance) { -+ LOG_ERR("%s: VCHI instance already open (%p)", -+ __func__, instance); -+ instance->alsa_stream = alsa_stream; -+ alsa_stream->instance = instance; -+ ret = 0; // xxx todo -1; -+ goto err_free_mem; -+ } -+ -+ /* Initialize and create a VCHI connection */ -+ ret = vchi_initialise(&vchi_instance); -+ if (ret != 0) { -+ LOG_ERR("%s: failed to initialise VCHI instance (ret=%d)", -+ __func__, ret); -+ -+ ret = -EIO; -+ goto err_free_mem; -+ } -+ ret = vchi_connect(NULL, 0, vchi_instance); -+ if (ret != 0) { -+ LOG_ERR("%s: failed to connect VCHI instance (ret=%d)", -+ __func__, ret); -+ -+ ret = -EIO; -+ goto err_free_mem; -+ } -+ -+ /* Set up the VCOS logging */ -+ vcos_log_set_level(VCOS_LOG_CATEGORY, LOG_LEVEL); -+ vcos_log_register("audio", VCOS_LOG_CATEGORY); -+ -+ /* Initialize an instance of the audio service */ -+ instance = vc_vchi_audio_init(vchi_instance, &vchi_connection, 1); -+ -+ if (instance == NULL /*|| audio_handle != instance */ ) { -+ LOG_ERR("%s: failed to initialize audio service", __func__); -+ -+ ret = -EPERM; -+ goto err_free_mem; -+ } -+ -+ instance->alsa_stream = alsa_stream; -+ alsa_stream->instance = instance; -+ -+ LOG_DBG(" success !\n"); -+err_free_mem: -+ LOG_DBG(" .. OUT\n"); -+ -+ return ret; -+} -+ -+int bcm2835_audio_open(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ AUDIO_INSTANCE_T *instance; -+ VC_AUDIO_MSG_T m; -+ int32_t success; -+ int ret; -+ LOG_DBG(" .. IN\n"); -+ -+ my_workqueue_init(alsa_stream); -+ -+ ret = bcm2835_audio_open_connection(alsa_stream); -+ if (ret != 0) { -+ ret = -1; -+ goto exit; -+ } -+ instance = alsa_stream->instance; -+ -+ vcos_mutex_lock(&instance->vchi_mutex); -+ vchi_service_use(instance->vchi_handle[0]); -+ -+ m.type = VC_AUDIO_MSG_TYPE_OPEN; -+ -+ /* Send the message to the videocore */ -+ success = vchi_msg_queue(instance->vchi_handle[0], -+ &m, sizeof m, -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); -+ -+ if (success != 0) { -+ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)", -+ __func__, success); -+ -+ ret = -1; -+ goto unlock; -+ } -+ -+ ret = 0; -+ -+unlock: -+ vchi_service_release(instance->vchi_handle[0]); -+ vcos_mutex_unlock(&instance->vchi_mutex); -+exit: -+ LOG_DBG(" .. OUT\n"); -+ return ret; -+} -+ -+static int bcm2835_audio_set_ctls_chan(bcm2835_alsa_stream_t * alsa_stream, -+ bcm2835_chip_t * chip) -+{ -+ VC_AUDIO_MSG_T m; -+ AUDIO_INSTANCE_T *instance = alsa_stream->instance; -+ int32_t success; -+ int ret; -+ LOG_DBG(" .. IN\n"); -+ -+ LOG_INFO -+ (" Setting ALSA dest(%d), volume(%d)\n", chip->dest, chip->volume); -+ -+ vcos_mutex_lock(&instance->vchi_mutex); -+ vchi_service_use(instance->vchi_handle[0]); -+ -+ instance->got_result = 0; -+ instance->result = -1; -+ -+ m.type = VC_AUDIO_MSG_TYPE_CONTROL; -+ m.u.control.dest = chip->dest; -+ m.u.control.volume = chip->volume; -+ -+ /* Send the message to the videocore */ -+ success = vchi_msg_queue(instance->vchi_handle[0], -+ &m, sizeof m, -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); -+ -+ if (success != 0) { -+ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)", -+ __func__, success); -+ -+ ret = -1; -+ goto unlock; -+ } -+ -+ /* We are expecting a reply from the videocore */ -+ while (!instance->got_result) { -+ success = vcos_event_wait(&instance->msg_avail_event); -+ if (success != VCOS_SUCCESS) { -+ LOG_ERR("%s: failed on waiting for event (status=%d)", -+ __func__, success); -+ -+ ret = -1; -+ goto unlock; -+ } -+ } -+ -+ if (instance->result != 0) { -+ LOG_ERR("%s: result=%d", __func__, instance->result); -+ -+ ret = -1; -+ goto unlock; -+ } -+ -+ ret = 0; -+ -+unlock: -+ vchi_service_release(instance->vchi_handle[0]); -+ vcos_mutex_unlock(&instance->vchi_mutex); -+ -+ LOG_DBG(" .. OUT\n"); -+ return ret; -+} -+ -+int bcm2835_audio_set_ctls(bcm2835_chip_t * chip) -+{ -+ int i; -+ int ret = 0; -+ LOG_DBG(" .. IN\n"); -+ /* change ctls for all substreams */ -+ for (i = 0; i < MAX_SUBSTREAMS; i++) { -+ if (chip->avail_substreams & (1 << i)) { -+ if (!chip->alsa_stream[i]) -+ ret = 0; -+ else if (bcm2835_audio_set_ctls_chan -+ (chip->alsa_stream[i], chip) != 0) -+ ret = -1; -+ } -+ } -+ LOG_DBG(" .. OUT ret=%d\n", ret); -+ return ret; -+} -+ -+int bcm2835_audio_set_params(bcm2835_alsa_stream_t * alsa_stream, -+ uint32_t channels, uint32_t samplerate, -+ uint32_t bps) -+{ -+ VC_AUDIO_MSG_T m; -+ AUDIO_INSTANCE_T *instance = alsa_stream->instance; -+ int32_t success; -+ int ret; -+ LOG_DBG(" .. IN\n"); -+ -+ LOG_INFO -+ (" Setting ALSA channels(%d), samplerate(%d), bits-per-sample(%d)\n", -+ channels, samplerate, bps); -+ -+ /* resend ctls - alsa_stream may not have been open when first send */ -+ ret = bcm2835_audio_set_ctls_chan(alsa_stream, alsa_stream->chip); -+ if (ret != 0) { -+ LOG_ERR(" Alsa controls not supported\n"); -+ return -EINVAL; -+ } -+ -+ vcos_mutex_lock(&instance->vchi_mutex); -+ vchi_service_use(instance->vchi_handle[0]); -+ -+ instance->got_result = 0; -+ instance->result = -1; -+ -+ m.type = VC_AUDIO_MSG_TYPE_CONFIG; -+ m.u.config.channels = channels; -+ m.u.config.samplerate = samplerate; -+ m.u.config.bps = bps; -+ -+ /* Send the message to the videocore */ -+ success = vchi_msg_queue(instance->vchi_handle[0], -+ &m, sizeof m, -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); -+ -+ if (success != 0) { -+ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)", -+ __func__, success); -+ -+ ret = -1; -+ goto unlock; -+ } -+ -+ /* We are expecting a reply from the videocore */ -+ while (!instance->got_result) { -+ success = vcos_event_wait(&instance->msg_avail_event); -+ if (success != VCOS_SUCCESS) { -+ LOG_ERR("%s: failed on waiting for event (status=%d)", -+ __func__, success); -+ -+ ret = -1; -+ goto unlock; -+ } -+ } -+ -+ if (instance->result != 0) { -+ LOG_ERR("%s: result=%d", __func__, instance->result); -+ -+ ret = -1; -+ goto unlock; -+ } -+ -+ ret = 0; -+ -+unlock: -+ vchi_service_release(instance->vchi_handle[0]); -+ vcos_mutex_unlock(&instance->vchi_mutex); -+ -+ LOG_DBG(" .. OUT\n"); -+ return ret; -+} -+ -+int bcm2835_audio_setup(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ LOG_DBG(" .. IN\n"); -+ -+ LOG_DBG(" .. OUT\n"); -+ -+ return 0; -+} -+ -+static int bcm2835_audio_start_worker(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ VC_AUDIO_MSG_T m; -+ AUDIO_INSTANCE_T *instance = alsa_stream->instance; -+ int32_t success; -+ int ret; -+ LOG_DBG(" .. IN\n"); -+ -+ vcos_mutex_lock(&instance->vchi_mutex); -+ vchi_service_use(instance->vchi_handle[0]); -+ -+ m.type = VC_AUDIO_MSG_TYPE_START; -+ -+ /* Send the message to the videocore */ -+ success = vchi_msg_queue(instance->vchi_handle[0], -+ &m, sizeof m, -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); -+ -+ if (success != 0) { -+ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)", -+ __func__, success); -+ -+ ret = -1; -+ goto unlock; -+ } -+ -+ ret = 0; -+ -+unlock: -+ vchi_service_release(instance->vchi_handle[0]); -+ vcos_mutex_unlock(&instance->vchi_mutex); -+ LOG_DBG(" .. OUT\n"); -+ return ret; -+} -+ -+static int bcm2835_audio_stop_worker(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ VC_AUDIO_MSG_T m; -+ AUDIO_INSTANCE_T *instance = alsa_stream->instance; -+ int32_t success; -+ int ret; -+ LOG_DBG(" .. IN\n"); -+ -+ vcos_mutex_lock(&instance->vchi_mutex); -+ vchi_service_use(instance->vchi_handle[0]); -+ -+ m.type = VC_AUDIO_MSG_TYPE_STOP; -+ m.u.stop.draining = alsa_stream->draining; -+ -+ /* Send the message to the videocore */ -+ success = vchi_msg_queue(instance->vchi_handle[0], -+ &m, sizeof m, -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); -+ -+ if (success != 0) { -+ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)", -+ __func__, success); -+ -+ ret = -1; -+ goto unlock; -+ } -+ -+ ret = 0; -+ -+unlock: -+ vchi_service_release(instance->vchi_handle[0]); -+ vcos_mutex_unlock(&instance->vchi_mutex); -+ LOG_DBG(" .. OUT\n"); -+ return ret; -+} -+ -+int bcm2835_audio_close(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ VC_AUDIO_MSG_T m; -+ AUDIO_INSTANCE_T *instance = alsa_stream->instance; -+ int32_t success; -+ int ret; -+ LOG_DBG(" .. IN\n"); -+ -+ my_workqueue_quit(alsa_stream); -+ -+ vcos_mutex_lock(&instance->vchi_mutex); -+ vchi_service_use(instance->vchi_handle[0]); -+ -+ m.type = VC_AUDIO_MSG_TYPE_CLOSE; -+ instance->got_result = 0; -+ /* Send the message to the videocore */ -+ success = vchi_msg_queue(instance->vchi_handle[0], -+ &m, sizeof m, -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); -+ -+ if (success != 0) { -+ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)", -+ __func__, success); -+ ret = -1; -+ goto unlock; -+ } -+ while (!instance->got_result) { -+ success = vcos_event_wait(&instance->msg_avail_event); -+ if (success != VCOS_SUCCESS) { -+ LOG_ERR("%s: failed on waiting for event (status=%d)", -+ __func__, success); -+ -+ ret = -1; -+ goto unlock; -+ } -+ } -+ if (instance->result != 0) { -+ LOG_ERR("%s: failed result (status=%d)", -+ __func__, instance->result); -+ -+ ret = -1; -+ goto unlock; -+ } -+ -+ ret = 0; -+ -+unlock: -+ vchi_service_release(instance->vchi_handle[0]); -+ vcos_mutex_unlock(&instance->vchi_mutex); -+ -+ /* Stop the audio service */ -+ if (instance) { -+ vc_vchi_audio_deinit(instance); -+ alsa_stream->instance = NULL; -+ } -+ LOG_DBG(" .. OUT\n"); -+ return ret; -+} -+ -+int bcm2835_audio_write(bcm2835_alsa_stream_t * alsa_stream, uint32_t count, -+ void *src) -+{ -+ VC_AUDIO_MSG_T m; -+ AUDIO_INSTANCE_T *instance = alsa_stream->instance; -+ int32_t success; -+ int ret; -+ -+ LOG_DBG(" .. IN\n"); -+ -+ LOG_INFO(" Writing %d bytes from %p\n", count, src); -+ -+ vcos_mutex_lock(&instance->vchi_mutex); -+ vchi_service_use(instance->vchi_handle[0]); -+ -+ m.type = VC_AUDIO_MSG_TYPE_WRITE; -+ m.u.write.count = count; -+ m.u.write.callback = alsa_stream->fifo_irq_handler; -+ m.u.write.cookie = alsa_stream; -+ m.u.write.silence = src == NULL; -+ -+ /* Send the message to the videocore */ -+ success = vchi_msg_queue(instance->vchi_handle[0], -+ &m, sizeof m, -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED, NULL); -+ -+ if (success != 0) { -+ LOG_ERR("%s: failed on vchi_msg_queue (status=%d)", -+ __func__, success); -+ -+ ret = -1; -+ goto unlock; -+ } -+ LOG_DBG(" ... sent header\n"); -+ if (!m.u.write.silence) { -+ /* Send the message to the videocore */ -+ success = vchi_bulk_queue_transmit(instance->vchi_handle[0], -+ src, count, -+ 0 * -+ VCHI_FLAGS_BLOCK_UNTIL_QUEUED -+ + -+ 1 * -+ VCHI_FLAGS_BLOCK_UNTIL_DATA_READ, -+ NULL); -+ if (success != 0) { -+ LOG_ERR -+ ("%s: failed on vchi_bulk_queue_transmit (status=%d)", -+ __func__, success); -+ -+ ret = -1; -+ goto unlock; -+ } -+ } -+ ret = 0; -+ -+unlock: -+ vchi_service_release(instance->vchi_handle[0]); -+ vcos_mutex_unlock(&instance->vchi_mutex); -+ LOG_DBG(" .. OUT\n"); -+ return ret; -+} -+ -+/** -+ * Returns all buffers from arm->vc -+ */ -+void bcm2835_audio_flush_buffers(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ LOG_DBG(" .. IN\n"); -+ LOG_DBG(" .. OUT\n"); -+ return; -+} -+ -+/** -+ * Forces VC to flush(drop) its filled playback buffers and -+ * return them the us. (VC->ARM) -+ */ -+void bcm2835_audio_flush_playback_buffers(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ LOG_DBG(" .. IN\n"); -+ LOG_DBG(" .. OUT\n"); -+} -+ -+uint32_t bcm2835_audio_retrieve_buffers(bcm2835_alsa_stream_t * alsa_stream) -+{ -+ uint32_t count = atomic_read(&alsa_stream->retrieved); -+ atomic_sub(count, &alsa_stream->retrieved); -+ return count; -+} -diff -Naur linux-3.2.23/sound/arm/Kconfig linux-rpi-bootc-3.2.23/sound/arm/Kconfig ---- linux-3.2.23/sound/arm/Kconfig 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/sound/arm/Kconfig 2012-07-15 20:28:25.381073128 +0200 -@@ -39,5 +39,12 @@ - Say Y or M if you want to support any AC97 codec attached to - the PXA2xx AC97 interface. - -+config SND_BCM2835 -+ tristate "BCM2835 ALSA driver" -+ depends on ARCH_BCM2708 && SND -+ select SND_PCM -+ help -+ Say Y or M if you want to support BCM2835 Alsa pcm card driver -+ - endif # SND_ARM - -diff -Naur linux-3.2.23/sound/arm/Makefile linux-rpi-bootc-3.2.23/sound/arm/Makefile ---- linux-3.2.23/sound/arm/Makefile 2012-07-12 05:32:21.000000000 +0200 -+++ linux-rpi-bootc-3.2.23/sound/arm/Makefile 2012-07-15 20:28:25.380073109 +0200 -@@ -14,3 +14,9 @@ - - obj-$(CONFIG_SND_PXA2XX_AC97) += snd-pxa2xx-ac97.o - snd-pxa2xx-ac97-objs := pxa2xx-ac97.o -+ -+obj-$(CONFIG_SND_BCM2835) += snd-bcm2835.o -+snd-bcm2835-objs := bcm2835.o bcm2835-ctl.o bcm2835-pcm.o bcm2835-vchiq.o -+ -+EXTRA_CFLAGS += -Idrivers/misc/vc04_services -Idrivers/misc/vc04_services/interface/vcos/linuxkernel -D__VCCOREVER__=0x04000000 -+ -diff -Naur linux-3.2.23/sound/arm/vc_vchi_audioserv_defs.h linux-rpi-bootc-3.2.23/sound/arm/vc_vchi_audioserv_defs.h ---- linux-3.2.23/sound/arm/vc_vchi_audioserv_defs.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-rpi-bootc-3.2.23/sound/arm/vc_vchi_audioserv_defs.h 2012-07-15 20:28:25.381073128 +0200 +diff --git a/sound/arm/vc_vchi_audioserv_defs.h b/sound/arm/vc_vchi_audioserv_defs.h +new file mode 100644 +index 0000000..d610734 +--- /dev/null ++++ b/sound/arm/vc_vchi_audioserv_defs.h @@ -0,0 +1,112 @@ +/***************************************************************************** +* Copyright 2011 Broadcom Corporation. All rights reserved.