diff for duplicates of <20060109180356.GA8855@cosmic.amd.com> diff --git a/a/1.txt b/N1/1.txt index f9ceed1..8b13789 100644 --- a/a/1.txt +++ b/N1/1.txt @@ -1,10 +1 @@ -From the "two-birds-one-stone" department, I am pleased to present USB UDC -support for both the MIPS Au1200 SoC and the Geode CS5535 south bridge. -Also, coming soon (in the next few days), OTG, which has been removed from -the usb_host patch, and put into its own patch (as per David's comments). -This patch is against current linux-mips git, but it should apply for Linus's -tree as well. - -Regards, -Jordan diff --git a/a/2.hdr b/a/2.hdr deleted file mode 100644 index 476b07e..0000000 --- a/a/2.hdr +++ /dev/null @@ -1,5 +0,0 @@ -Content-Type: text/plain; - charset=us-ascii -Content-Disposition: inline; - filename=udc.patch -Content-Transfer-Encoding: 7bit diff --git a/a/2.txt b/a/2.txt deleted file mode 100644 index 932616d..0000000 --- a/a/2.txt +++ /dev/null @@ -1,9931 +0,0 @@ -PATCH: Add UDC support for MIPS/AU1200 and Geode/CS5536 - -This patch adds UDC support for the AU1200 processor and the Geode CS5536 -southbridge. - -Signed-off-by: Jordan Crouse <jordan.crouse@amd.com> ---- - - Documentation/usb/au1200udc.txt | 185 + - drivers/usb/gadget/Kconfig | 86 + - drivers/usb/gadget/Makefile | 9 - drivers/usb/gadget/au1200otg.h | 147 + - drivers/usb/gadget/au1200udc.c | 4880 +++++++++++++++++++++++++++++++++++++ - drivers/usb/gadget/au1200udc.h | 936 +++++++ - drivers/usb/gadget/au1200uoc.c | 2015 +++++++++++++++ - drivers/usb/gadget/au1200uoc.h | 1338 ++++++++++ - drivers/usb/gadget/ether.c | 65 - drivers/usb/gadget/file_storage.c | 8 - drivers/usb/gadget/gadget_chips.h | 8 - drivers/usb/gadget/zero.c | 10 - 12 files changed, 9684 insertions(+), 3 deletions(-) - -diff --git a/Documentation/usb/au1200udc.txt b/Documentation/usb/au1200udc.txt -new file mode 100644 -index 0000000..20f4d58 ---- /dev/null -+++ b/Documentation/usb/au1200udc.txt -@@ -0,0 +1,185 @@ -+------------------------------------------------------------------------------- -+Howto for Linux device driver for the AU1200 USB Device Controller (UDC) -+for gadget driver stack -+------------------------------------------------------------------------------- -+ -+Author: Thomas Dahlmann -+ -+INTRODUCTION: -+ -+The AU1200 UDC is part of AMD MIPS CPU Au1200 and AMD5536 chip (south- -+bridge of AMD Geode LX Processor). -+It is a DMA capable usb device controller. The usb port is shared -+between host and UDC. The Au1200 on-chip OTG controller is used to switch the -+usb port between host, UDC and neutral. So au1200otg driver is needed -+to get the UDC operating. -+ -+Current gadget support: file_storage, ether, zero -+ -+------------------------------------------------------------------------------- -+WHAT YOU NEED: -+------------------------------------------------------------------------------- -+ -+copy/replace following files to /usr/src/linux/drivers/usb/gadget -+ au1200udc.c -+ au1200udc.h -+ au1200otg.h -+ au1200uoc.c -+ au1200uoc.h -+ ether.c -+ file_storage.c -+ zero.c -+ gadget_chips.h -+ Makefile -+ Kconfig -+ -+------------------------------------------------------------------------------- -+HOW TO INSTALL IT: -+------------------------------------------------------------------------------- -+ -+change to directory /usr/src/linux -+ -+configure gadget as module: -+ "make menuconfig" -+ under "Code maturity level options" choose "Prompt for development ..." -+ goto "Device Drivers" -+ goto "USB support" -> "USB Gadget support" -+ choose "Support for USB Gadgets" as module -+ under choice "USB Peripheral Controller" choose "AU1200UDC" -+ under "USB Gadget Drivers" -+ choose "Gadget Zero" as module or -+ choose "Ethernet Gagdet" as module or -+ choose "File-backed Storage Gadget" as module -+ choose "AU1200 USB portmux control (On-The-Go support)" -+ under choice "OTG port functionality" choose "Gadget only" -+ exit and save config -+ -+compile and install modules: -+ "make modules modules_install" -+ -+------------------------------------------------------------------------------- -+HOW TO USE IT: -+------------------------------------------------------------------------------- -+ -+*** How to load FILE-BACKED STORAGE gadget driver - mass storage *** -+enable USB mass storage support for linux host: -+ change to directory /usr/src/linux -+ "make menuconfig" -+ under "File systems" choose "DOS/FAT/NT filesystems" -+ choose "MSDOS fs support" -+ under "Device Drivers" under "SCSI device support" -+ choose "SCSI device support" -+ choose "SCSI generic support" -+ under "Device Drivers" under "USB support" in section -+ "USB Device Class drivers" choose -+ "USB Mass Storage support" -+ compile new kernel -+create disk file: -+ "dd bs=1M count=128 if=/dev/zero of=/tmp/disk" -+ => creates a 128Mbyte image file /tmp/disk -+load modules: -+ "modprobe au1200udc" -+ "modprobe g_file_storage file=/tmp/disk" -+ "modprobe au1200otg" -+create a primary FAT16 disk partition via linux host site: -+ "fdisk /dev/sda", make FAT16 prim. partition -+ => "n", "p", "1", "<RETURN>", "<RETURN>", "t", "6", "w", -+ "mkdosfs /dev/sda1" -+ "sync" -+create primary disk partition via Windows XP host site: -+ right click on "My Computer" -+ choose "Manage" => "Disk Management" -+ choose usb disk and follow instructions of partition menu -+mount usb mass storage device on linux host: -+ make directory "/mnt/gadget/" -+ "mount -t msdos /dev/sda1 /mnt/gadget" -+ -+*** How to access files of disk image on UDC side *** -+When files were copied from host to UDC mass storage device then files -+are inside the monolitic disk image (see above) on UDC side. This -+disk image can be mounted via the loopback device driver to a -+directory on UDC side to access these files. -+Steps on UDC side: -+ enable kernel support for loopback device -+ change to directory /usr/src/linux -+ "make menuconfig" -+ under "Block devices" choose "Loopback device support" -+ and recompile the kernel -+ determine offset inside disk image: -+ "fdisk -l -u disk_image", output is like: -+>> You must set cylinders. -+>> You can do this from the extra functions menu. -+>> -+>> Disk /tmp/disk128: 5 heads, 52 sectors, 0 cylinders -+>> Units = sectors of 1 * 512 bytes -+>> -+>> Device Boot Start End Blocks Id System -+>> /tmp/disk128p1 52 262079 131014 6 FAT16 -+ -+ get offset my multiplying start value by sector size: -+ 52 * 512 = 26624 -+ mount disk image: -+ "mount -o loop,offset=26624 -t msdos disk_image /mnt" -+ -+ -+*** How to load ZERO gadget driver - simple BULK loop back *** -+load modules: -+UDC driver: -+ (a) Slave/Fifo mode: "modprobe au1200udc use_dma=0" -+ (b) DMA Buffer Fill mode: "modprobe au1200udc use_dma=1" -+ default: -+ (c) DMA PPBNDU mode: "modprobe au1200udc" -+ (d) DMA PPBDU mode: "modprobe au1200udc use_dma=1 use_dma_ppb=1 use_dma_ppb_du=1" -+ (e) fullspeed mode: "modprobe au1200udc use_fullspeed=1", can be combined -+ with all dma modes -+ (f) special higspeed -+ tx buffer size: "modprobe au1200udc hs_tx_buf=<buf_size in dwords>" -+ example: "modprobe au1200udc use_dma=1 hs_tx_buf=128" -+ => buffer size = 512 bytes (=bulk max packet) -+Gadget Zero driver: -+ (a) Bulk loop: "modprobe g_zero" -+ (b) Int loop: "modprobe g_zero use_interrupt_traffic=1" -+ (c) Source/Sink "modprobe g_zero loopdefault=0" -+ OUT data must all be zero's -+ (d) Source/Sink count "modprobe g_zero loopdefault=0 pattern=1" -+ each OUT packet must count modulo63 (0,1,..,62,0,1,..) -+OTG driver: "modprobe au1200otg" -+example: -+ "modprobe au1200udc" -+ "modprobe g_zero" -+ "modprobe au1200otg" -+ => loads driver for DMA PPBNDU mode and Bulk loop -+ -+ -+*** How to use ETHERNET gadget driver (CDC protocol) *** -+ with Linux Host -+UDC side bringup: -+ load gadget modules -+ "modprobe au1200udc" -+ "modprobe g_ether" -+ "modprobe au1200otg" -+ "ifconfig usb0 192.168.0.2" -+Host side bringup: -+ install support for CDC Ethernet: -+ change to directory /usr/src/linux -+ "make menuconfig" -+ under "Device Drivers" under "USB support" under -+ "USB Network adapters" choose -+ "Multi-purpose USB Networking Framework" -+ choose "CDC Ethernet support" -+ compile mew kernel -+ "modprobe CDCEther" -+ "ifconfig eth1 192.168.0.1" -+ note: assuming there is one network card assigned to eth0, -+ otherwise kernel messages of CDC Ethernet module show -+ which interface (ethX) is used -+Use network connection: -+ after bringup of host and UDC side it behaves like a normal -+ ethernet connection between host and UDC -+ test the connection: -+ host side: "ping -I eth1 192.168.0.2" -+ UDC side : "ping -I usb0 192.168.0.1" -+ note: the "-I" option assures that the USB cable is used, the -+ option can be omitted when the routing table is setup to avoid -+ using other network interfaces as eth0 -+ -diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig -index ff075a5..2a3b652 100644 ---- a/drivers/usb/gadget/Kconfig -+++ b/drivers/usb/gadget/Kconfig -@@ -89,7 +89,27 @@ config USB_NET2280 - depends on USB_GADGET_NET2280 - default USB_GADGET - select USB_GADGET_SELECTED -+config USB_GADGET_AU1200UDC -+ boolean "AU1200UDC" -+ depends on PCI || SOC_AU1200 -+ select USB_GADGET_DUALSPEED -+ help -+ AU1200 UDC is a PCI based USB peripheral controller which -+ supports both full and high speed USB 2.0 data transfers. -+ -+ It has four configurable endpoints, as well as endpoint zero -+ (for control transfers). -+ -+ Say "y" to link the driver statically, or "m" to build a -+ dynamically linked module called "au1200udc" and force all -+ gadget drivers to also be dynamically linked. - -+config USB_AU1200UDC -+ tristate -+ depends on USB_GADGET_AU1200UDC -+ default USB_GADGET -+ select USB_GADGET_SELECTED -+ select USB_PORT_AU1200OTG - config USB_GADGET_PXA2XX - boolean "PXA 25x or IXP 4xx" - depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX -@@ -322,7 +342,7 @@ config USB_ETH - - config USB_ETH_RNDIS - bool "RNDIS support (EXPERIMENTAL)" -- depends on USB_ETH && EXPERIMENTAL -+ depends on USB_ETH && EXPERIMENTAL && !(USB_GADGET_AU1200UDC) - default y - help - Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol, -@@ -395,4 +415,68 @@ config USB_G_SERIAL - - endchoice - -+# -+# AU1200 USB OTG options -+# -+config USB_PORT_AU1200OTG -+ boolean "AU1200 USB portmux control (On-The-Go support)" -+ depends on USB_GADGET_AU1200UDC || USB_EHCI_HCD || USB_OHCI_HCD -+ default n -+ help -+ The AU1200 and Au1200 USB device port can be used as -+ either a host port or a device port. -+ Say "y" here if you want to use both or if you want to -+ setup this port to fit into your board configuration. -+ -+ If the AU1200UDC driver is configured to be statically -+ linked this module will be linked into the kernel image -+ as well otherwise an additional module called -+ "au1200otg" will be built. -+ -+config USB_AU1200OTG -+ tristate -+ depends on USB_PORT_AU1200OTG -+ default USB_AU1200UDC -+ -+choice -+ prompt "OTG port functionality" -+ depends on USB_PORT_AU1200OTG -+ default USB_OTGMUX_GADGET -+ -+config USB_OTGMUX_HOST -+ boolean "Host only" -+ depends on !USB_GADGET_AU1200UDC && (USB_EHCI_HCD || USB_OHCI_HCD) -+ help -+ Select this if your device port is connected to a -+ Standard-A or a Mini-A connector. -+ It is possible to choose this with a Mini-AB connector -+ if the device controller is not to be used. -+ -+config USB_OTGMUX_GADGET -+ boolean "Gadget only" -+ depends on USB_GADGET_AU1200UDC -+ help -+ Select this if your device port is connected to a -+ Standard-B or a Mini-B connector. -+ It is possible to choose this with a Mini-AB connector -+ if the host controller is not to be used at this port. -+ -+config USB_OTGMUX_IDPIN -+ boolean "Cable select" -+ depends on USB_GADGET_AU1200UDC && (USB_EHCI_HCD || USB_OHCI_HCD) -+ help -+ Choose this if you want to use both host and device at -+ this port. The port multiplexer is controlled by the -+ connectors ID pin. If an A-plug is connected the port -+ it is routed to the host otherwise it's routed to the -+ device controller. -+ -+ This is useful for validation platforms which use AB -+ receptacle in order to share one port between host and device. -+ It is not a USB compliant option. -+ -+ Select this only if your device port is connected to -+ a Mini-AB connector. -+ -+endchoice - endmenu -diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile -index d5fd04d..0298250 100644 ---- a/drivers/usb/gadget/Makefile -+++ b/drivers/usb/gadget/Makefile -@@ -3,6 +3,7 @@ - # - obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o - obj-$(CONFIG_USB_NET2280) += net2280.o -+obj-$(CONFIG_USB_AU1200UDC) += au1200udc.o - obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o - obj-$(CONFIG_USB_GOKU) += goku_udc.o - obj-$(CONFIG_USB_OMAP) += omap_udc.o -@@ -28,3 +29,11 @@ obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o - obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o - obj-$(CONFIG_USB_G_SERIAL) += g_serial.o - -+# -+# AU1200 USB OTG options -+# -+ifeq ($(CONFIG_USB_PORT_AU1200OTG),y) -+obj-$(CONFIG_USB_AU1200OTG) += au1200otg.o -+ -+au1200otg-objs := au1200uoc.o -+endif -diff --git a/drivers/usb/gadget/au1200otg.h b/drivers/usb/gadget/au1200otg.h -new file mode 100644 -index 0000000..2b05703 ---- /dev/null -+++ b/drivers/usb/gadget/au1200otg.h -@@ -0,0 +1,147 @@ -+/* -+ * AMD Au1200 USB OTG driver -+ */ -+ -+/* -+ * Copyright (C) 2005 AMD (http://www.amd.com) -+ * Author: Karsten Boge -+ * -+ * 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 AU1200OTG_H -+#define AU1200OTG_H -+ -+/* log Bug 5395 */ -+#define OTG_HNP_ERR_LOG -+ -+/***************************************************************************** -+* Constants -+*****************************************************************************/ -+ -+ -+/********************************** -+ * OTG sub-state definitions -+***********************************/ -+ -+#define OTG_STATE_MASK 0x0F -+ -+#define OTG_STATE_B_HOST_WT (0x10 | OTG_STATE_B_HOST) -+#define OTG_STATE_B_PERIPHERAL_WT (0x10 | OTG_STATE_B_PERIPHERAL) -+#define OTG_STATE_B_PERIPHERAL_DC (0x20 | OTG_STATE_B_PERIPHERAL) -+#define OTG_STATE_B_SRP_WAIT_SE0 (0x10 | OTG_STATE_B_SRP_INIT) -+#define OTG_STATE_B_SRP_D_PULSE (0x20 | OTG_STATE_B_SRP_INIT) -+#define OTG_STATE_B_SRP_V_PULSE (0x30 | OTG_STATE_B_SRP_INIT) -+#define OTG_STATE_B_SRP_V_DCHRG (0x40 | OTG_STATE_B_SRP_INIT) -+#define OTG_STATE_B_SRP_WAIT_VBUS (0x50 | OTG_STATE_B_SRP_INIT) -+ -+#define OTG_STATE_A_IDLE_WAIT_DP (0x10 | OTG_STATE_A_IDLE) -+#define OTG_STATE_A_IDLE_WAIT_VP (0x20 | OTG_STATE_A_IDLE) -+#define OTG_STATE_A_IDLE_WAIT_MP (0x30 | OTG_STATE_A_IDLE) -+#define OTG_STATE_A_IDLE_WAIT_DV (0x40 | OTG_STATE_A_IDLE) -+#define OTG_STATE_A_WAIT_BCON_VB (0x10 | OTG_STATE_A_WAIT_BCON) -+#define OTG_STATE_A_WAIT_VFALL_DN (0x10 | OTG_STATE_A_WAIT_VFALL) -+ -+ -+/********************************** -+* typical timer values -+**********************************/ -+ -+#define OTG_TMR_WAIT_VFALL 10 /* ( ) A waits for VBus */ -+#define OTG_TMR_A_WAIT_VRISE 100 /* ( ) A waits for VBus */ -+#define OTG_TMR_A_WAIT_BCON 200 /* ( ) A waits for B-connect (1.. s) */ -+#define OTG_TMR_A_IDLE_BDIS 250 /* (ms) A waits for B-disc (200.. ms) */ -+#define OTG_TMR_B_WAIT_ADISCON 600 /* (us) B waits for A to disconnect <1ms */ -+#define OTG_TMR_B_ACON_BRST 200 /* (us) B waits before starting reset */ -+#define OTG_TMR_B_ASE0_BRST 5 /* (ms) B waits for A-conn (3.125.. ms) */ -+#define OTG_TMR_B_AIDL_BDIS 50 /* (ms) B waits before dc (5..150ms) */ -+#define OTG_TMR_SRP_WAIT_SE0 2 /* ( ) B SRP idle wait */ -+#define OTG_TMR_SRP_WAIT_DP 7 /* (ms) B SRP D_PULSE (5..10ms) */ -+#define OTG_TMR_SRP_WAIT_VP 80 /* (ms) B SRP V_PULSE (5..100ms) */ -+#define OTG_TMR_SRP_DCHRG_V 30 /* ( ) B SRP VBus discharge */ -+#define OTG_TMR_SRP_WAIT_VRS 5800 /* (ms) B SRP waits for VBus (5..6s) */ -+#define OTG_TMR_ASRP_WAIT_MP 4 /* ( ) A SRP min. pulse */ -+#define OTG_TMR_ASRP_WAIT_DP 10 /* (ms) A SRP D_PULSE TO */ -+#define OTG_TMR_ASRP_WAIT_VP 200 /* (ms) A SRP V_PULSE TO */ -+#define OTG_TMR_ASRP_WAIT_DV 200 /* ( ) A SRP waits for V_PULSE */ -+#define OTG_TMR_A_BCON_VB 50 /* ( ) A waits for VBus after connect */ -+ -+#define OTG_TMR_IDSNS_WAIT 10 /* (ms) ID sense wait */ -+ -+/*********************************/ -+ -+#define TIMER_PERIOD 1000 /* 10 ms, if longer than 10ms */ -+ -+/********************************** -+ * OTG state parameters -+ **********************************/ -+ -+#define OTG_HOST_READY (1<<20) /* indicates a USB host driver is */ -+ /* running */ -+#define OTG_GADGET_READY (1<<21) /* indicates a USB gadget driver is */ -+ /* running */ -+#define OTG_A_BUS_REQ (1<<22) /* used by appl-SW to request a */ -+ /* VBus rise, auto-reset by driver */ -+#define OTG_A_BUS_DROP (1<<23) /* used by appl-SW to request a */ -+ /* VBus drop, auto-reset by driver */ -+#define OTG_A_CLR_ERR (1<<24) /* used by appl-SW to request VBerr */ -+ /* clean-up, auto-reset by driver */ -+#define OTG_AB_HNP_REQ (1<<25) /* used by appl-SW to initiate */ -+ /* HNP, auto-reset by driver */ -+#define OTG_B_BUS_REQ (1<<26) /* used by appl-SW to request */ -+ /* B-device functionality, ... */ -+#define OTG_B_BUS_DIS (1<<27) /* used by appl-SW to request */ -+ /* disable B-device functionality */ -+#define OTG_B_aSSN_REQ (1<<28) /* used by appl-SW to initiate SRP, */ -+ /* auto-reset by the driver */ -+#define OTG_B_SRP_ERROR (1<<29) /* indicates invalid HW conditions */ -+ /* during SRP, reset by writing "1" */ -+#define OTG_A_VBUS_FAILED (1<<30) /* indicates a VBus error, reset by */ -+ /* writing "1", when setting */ -+ /* CLR_ERR or when leaving A-states */ -+#define OTG_UDC_RWK_REQ (1<<31) /* call UDC function to force a */ -+ /* remote wake-up */ -+ -+#define SW_REQUEST_MASK (OTG_A_BUS_REQ | OTG_A_BUS_DROP | \ -+ OTG_A_CLR_ERR | OTG_B_aSSN_REQ | \ -+ OTG_B_BUS_REQ | OTG_B_BUS_DIS | \ -+ OTG_UDC_RWK_REQ) -+ -+/*********************************************************************/ -+ -+/* -+ * gadget events for notify function -+ */ -+#define OTG_GADGET_EVT_SVDROP (1<<0) /* Session valid drop */ -+#define OTG_GADGET_EVT_SVALID (1<<1) /* Session valid */ -+#define OTG_GADGET_REQ_WAKE (1<<2) /* Request remote wake-up */ -+ -+/*** HS-A0 WA: gadget phy suspend issue ***/ -+#define OTG_FLAGS_UDC_SUSP (1<<17) /* gadget phy suspended */ -+ -+#ifdef OTG_HNP_ERR_LOG -+#define OTG_FLAGS_HNP_ERR (1<<18) /* HNP error bug 5395 occured */ -+#endif -+ -+/***************************************************************************** -+* Data -+*****************************************************************************/ -+ -+struct usb_otg_gadget_extension { -+ int (*request) (u32); /* function call for state change requests */ -+ u32 (*query) (int); /* function call to query state */ -+ void (*notify) (u32); /* filled in by gadget for notification */ -+}; -+ -+#endif /* AU1200OTG_H */ -diff --git a/drivers/usb/gadget/au1200udc.c b/drivers/usb/gadget/au1200udc.c -new file mode 100644 -index 0000000..7153902 ---- /dev/null -+++ b/drivers/usb/gadget/au1200udc.c -@@ -0,0 +1,4880 @@ -+/* -+ * AMD Au1200 UDC high/full speed USB device controller driver. -+ * -+ * Note: Driver also works with AMD Geode LX southbridge AMD5536 -+ */ -+ -+/* -+ * Copyright (C) 2005 AMD (http://www.amd.com) -+ * Author: Thomas Dahlmann -+ * -+ * 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 -+ */ -+ -+/***************************************************************************** -+ * Defines -+ *****************************************************************************/ -+ -+/* debug control */ -+#undef UDC_DEBUG -+/* #define UDC_DEBUG 1 */ -+#undef UDC_VERBOSE -+/* #define UDC_VERBOSE */ -+/* #define UDC_REGISTER_DUMP */ -+ -+/* Driver strings */ -+#define UDC_MOD_DESCRIPTION "AMD Au1200 UDC - USB Device Controller" -+#define UDC_DRIVER_VERSION_STRING "01.00.0204 - $Revision: #4 $" -+ -+/***************************************************************************** -+ * Includes -+ *****************************************************************************/ -+ -+/* system */ -+#include <linux/config.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/kernel.h> -+#include <linux/version.h> -+#include <linux/delay.h> -+#include <linux/ioport.h> -+#include <linux/sched.h> -+#include <linux/slab.h> -+#include <linux/smp_lock.h> -+#include <linux/errno.h> -+#include <linux/init.h> -+#include <linux/timer.h> -+#include <linux/list.h> -+#include <linux/interrupt.h> -+#include <linux/ioctl.h> -+#include <linux/fs.h> -+#include <linux/dmapool.h> -+#include <linux/moduleparam.h> -+#include <linux/device.h> -+#include <asm/byteorder.h> -+#include <asm/io.h> -+#include <asm/irq.h> -+#include <asm/system.h> -+#include <asm/unaligned.h> -+ -+/* MIPS config */ -+#ifdef CONFIG_SOC_AU1200 -+#include <asm/mach-au1x00/au1000.h> -+#include <linux/platform_device.h> -+#endif -+ -+/* gadget stack */ -+#include <linux/usb_ch9.h> -+#include <linux/usb_gadget.h> -+#include <linux/usb_otg.h> -+ -+/* udc/uoc specific */ -+#include "au1200udc.h" -+#include "au1200uoc.h" -+ -+ -+/* use RDE timer for new kernel only */ -+#define UDC_USE_TIMER -+/***************************************************************************** -+ * Static Function Declarations -+ *****************************************************************************/ -+ -+void udc_tasklet_disconnect(unsigned long); -+#ifdef UDC_USE_TIMER -+void udc_timer_function(unsigned long v); -+void udc_pollstall_timer_function(unsigned long v); -+#endif -+static int udc_rxfifo_read_dwords(struct udc* dev, u32* buf, int dwords); -+static void empty_req_queue (struct udc_ep *); -+static int udc_probe (struct udc* dev); -+static void udc_basic_init (struct udc *dev); -+static void udc_setup_endpoints (struct udc *dev); -+static void udc_soft_reset(struct udc* dev); -+#ifdef UDC_DEBUG -+static void dump_buffer(u8* buf, u32 bytes); -+static int udc_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -+static int udc_open (struct inode *inode, struct file *file); -+static int udc_release (struct inode *inode, struct file *file); -+#endif -+static struct udc_data_dma* udc_get_last_dma_desc(struct udc_request* req); -+static u32 udc_get_ppbdu_rxbytes(struct udc_request* req); -+static int udc_free_dma_chain(struct udc* dev, struct udc_request* req); -+static int udc_create_dma_chain(struct udc_ep* ep, struct udc_request* req, unsigned long buf_len, int gfp_flags); -+static inline int startup_registers(struct udc* dev); -+#ifdef CONFIG_SOC_AU1200 -+void au1200_sync(void); -+#endif -+static int udc_remote_wakeup(struct udc* dev); -+#if defined(CONFIG_SOC_AU1200) -+static int udc_suspend(struct udc* dev); -+static int udc_resume(struct udc* dev); -+#else -+static int udc_pci_probe (struct pci_dev *pdev, const struct pci_device_id *id); -+static void udc_pci_remove (struct pci_dev *pdev); -+#endif -+ -+/***************************************************************************** -+ * Data -+ *****************************************************************************/ -+ -+/* description */ -+static const char mod_desc [] = UDC_MOD_DESCRIPTION; -+static const char name [] = DRIVER_NAME_FOR_PRINT; -+ -+/* structure to hold endpoint function pointers */ -+static struct usb_ep_ops udc_ep_ops; -+ -+/* received setup data */ -+static union udc_setup_data setup_data; -+ -+/* pointer to device object */ -+static struct udc *udc; -+ -+/* irq spin lock for soft reset */ -+spinlock_t udc_irq_spinlock; -+/* stall spin lock */ -+spinlock_t udc_stall_spinlock; -+ -+/* this is used for dma chaining */ -+static int udc_gfp_flags = 0; -+ -+/* slave mode: pending bytes in rx fifo after nyet, -+used if EPIN irq came but no req was available */ -+static unsigned int udc_rxfifo_pending = 0; -+ -+/* count soft resets after suspend to avoid loop */ -+static int soft_reset_occured = 0; -+#ifdef UDC_IPBUG_3958_WORKAROUND -+static int soft_reset_after_usbreset_occured = 0; -+#endif -+ -+#ifdef UDC_USE_TIMER -+/* timer */ -+static struct timer_list udc_timer; -+static int stop_timer = 0; -+int set_rde = -1; -+DECLARE_COMPLETION(on_exit); -+static struct timer_list udc_pollstall_timer; -+static int stop_pollstall_timer = 0; -+DECLARE_COMPLETION(on_pollstall_exit); -+#endif -+ -+/* tasklet for usb disconnect */ -+DECLARE_TASKLET(disconnect_tasklet, udc_tasklet_disconnect, (unsigned long) &udc); -+ -+#ifdef USE_AU1200_PCI_DUMMY -+static struct pci_dev pdev_dummy; -+static struct pci_dev* pdev = &pdev_dummy; -+#endif -+ -+#ifdef UDC_IPBUG_3958_WORKAROUND -+/* CNAK pending field: bit0 = ep0in, bit16 = ep0out */ -+static u32 cnak_pending = 0; -+#define UDC_QUEUE_CNAK(ep, num) \ -+ if (readl(&((ep)->regs->ctl)) & AMD_BIT(UDC_EPCTL_NAK)) { \ -+ DBG("NAK could not be cleared for ep%d\n", num); \ -+ cnak_pending |= 1 << (num); \ -+ (ep)->naking = 1; \ -+ } \ -+ else \ -+ cnak_pending = cnak_pending & (~(1<<(num))); -+#else -+#define UDC_QUEUE_CNAK(ep, num) {} -+#endif -+ -+#ifdef UDC_IPBUG_3943_WORKAROUND -+/* otg registering count */ -+static u32 otg_reg_count = 0; -+#endif -+/* gadget registering count */ -+static u32 gadget_bind_count = 0; -+ -+/* endpoint names used for print */ -+static const char ep0_string[] = "ep0in"; -+static const char *ep_string[] = { -+ ep0_string, -+ "ep1in-int", "ep2in-bulk", "ep3in-bulk", "ep4in-bulk", "ep5in-bulk", "ep6in-bulk", "ep7in-bulk", "ep8in-bulk", -+ "ep9in-bulk", "ep10in-bulk", "ep11in-bulk", "ep12in-bulk", "ep13in-bulk", "ep14in-bulk", "ep15in-bulk", "ep0out", -+ "ep1out-bulk", "ep2out-bulk", "ep3out-bulk", "ep4out-bulk", "ep5out-bulk", "ep6out-bulk", "ep7out-bulk", "ep8out-bulk", -+ "ep9out-bulk", "ep10out-bulk", "ep11out-bulk", "ep12out-bulk", "ep13out-bulk", "ep14out-bulk", "ep15out-bulk" -+}; -+ -+#ifdef UDC_DEBUG -+/* driver callback functions */ -+static struct file_operations udc_fops = { -+ owner: THIS_MODULE, -+ -+ read: NULL, -+ write: NULL, -+ ioctl: udc_ioctl, -+ open: udc_open, -+ release: udc_release, -+}; -+#endif -+ -+/* PCI device parameters */ -+static struct pci_device_id pci_id[] = {{ -+ .vendor = UDC_PCI_VENID, -+ .device = UDC_PCI_DEVID, -+ .class = UDC_PCI_CLASS, -+ .class_mask = UDC_PCI_CLASS_MASK, -+ .subvendor = PCI_ANY_ID, -+ .subdevice = PCI_ANY_ID, -+}, -+{} -+}; -+ -+#if !defined(CONFIG_SOC_AU1200) -+/* PCI functions */ -+static struct pci_driver udc_pci_driver = { -+ .name = (char *) name, -+ .id_table = pci_id, -+ .probe = udc_pci_probe, -+ .remove = udc_pci_remove, -+}; -+#endif -+ -+#ifdef UDC_DEBUG -+/* data for debuging only */ -+static unsigned long no_pref_req = 0; -+static unsigned long no_req = 0; -+static u32 same_cfg = 0; -+static u32 num_enums = 0; -+#endif -+ -+/****** following flags can be set by module parameters */ -+/* DMA usage flag */ -+static int use_dma = 1; -+/* packet per buffer dma */ -+static int use_dma_ppb = 1; -+/* with per descr. update */ -+static int use_dma_ppb_du = 0; -+/* buffer fill mode */ -+static int use_dma_bufferfill_mode = 0; -+/* full speed only mode */ -+static int use_fullspeed = 0; -+/* tx buffer size for high speed */ -+static unsigned long hs_tx_buf = UDC_EPIN_BUFF_SIZE; -+ -+/* module parameters */ -+MODULE_PARM (use_dma, "i"); -+MODULE_PARM_DESC (use_dma, "true for DMA"); -+MODULE_PARM (use_dma_ppb, "i"); -+MODULE_PARM_DESC (use_dma_ppb, "true for DMA in packet per buffer mode"); -+MODULE_PARM (use_dma_ppb_du, "i"); -+MODULE_PARM_DESC (use_dma_ppb_du, "true for DMA in packet per buffer mode with descriptor update"); -+MODULE_PARM (use_fullspeed, "i"); -+MODULE_PARM_DESC (use_fullspeed, "true for fullspeed only"); -+MODULE_PARM (hs_tx_buf, "l"); -+MODULE_PARM_DESC (hs_tx_buf, "high speed tx buffer size for data endpoints in dwords"); -+ -+MODULE_DESCRIPTION (UDC_MOD_DESCRIPTION); -+MODULE_AUTHOR ("Thomas Dahlmann"); -+MODULE_LICENSE("GPL"); -+ -+#ifndef USE_AU1200_PCI_DUMMY -+MODULE_DEVICE_TABLE (pci, pci_id); -+#endif -+ -+/***************************************************************************** -+ * Function Definitions -+ *****************************************************************************/ -+ -+/* AU specific */ -+#ifdef CONFIG_SOC_AU1200 -+void au1200_sync(void) -+{ -+ au1200_sync_delay(); -+} -+#endif -+ -+#ifdef UDC_DEBUG -+/** -+ * Dumps byte read access -+ * -+ * \param a address pointer -+ * \return read byte -+ */ -+static void print_td(struct udc_data_dma *p) -+{ -+ INFO("td = %08lx: status=%08lx bufptr=%08lx next=%08lx\n", -+ (unsigned long) p, -+ (unsigned long) p->status, -+ (unsigned long) p->bufptr, -+ (unsigned long) p->next); -+} -+#endif -+ -+/* printing registers --------------------------------------------------------*/ -+/** -+ * Prints UDC device registers and endpoint irq registers -+ * -+ * \param dev pointer to device struct -+ */ -+static void print_regs(struct udc* dev) -+{ -+#ifndef UDC_IPBUG_3943_WORKAROUND -+ DBG( "------- Device registers -------\n"); -+ DBG( "dev config = %08lx\n", (unsigned long) dev->regs->cfg); -+ DBG( "dev control = %08lx\n", (unsigned long) dev->regs->ctl); -+ DBG( "dev status = %08lx\n", (unsigned long) dev->regs->sts); -+ DBG( "\n"); -+ DBG( "dev int's = %08lx\n", (unsigned long) dev->regs->irqsts); -+ DBG( "dev intmask = %08lx\n", (unsigned long) dev->regs->irqmsk); -+ DBG( "\n"); -+ DBG( "dev ep int's = %08lx\n", (unsigned long) dev->regs->ep_irqsts); -+ DBG( "dev ep intmask = %08lx\n", (unsigned long) dev->regs->ep_irqmsk); -+ DBG( "\n"); -+#endif -+ DBG( "USE DMA = %d\n", use_dma); -+ if (use_dma && use_dma_ppb && !use_dma_ppb_du) { -+ DBG( "DMA mode = PPBNDU (packet per buffer WITHOUT desc. update)\n"); -+#ifndef UDC_DEBUG -+ INFO( "DMA mode (PPBNDU)\n"); -+#endif -+ } -+ else if (use_dma && use_dma_ppb_du && use_dma_ppb_du) { -+ DBG( "DMA mode = PPBDU (packet per buffer WITH desc. update)\n"); -+#ifndef UDC_DEBUG -+ INFO( "DMA mode (PPBDU)\n"); -+#endif -+ } -+ if (use_dma && use_dma_bufferfill_mode) { -+ DBG( "DMA mode = BF (buffer fill mode)\n"); -+#ifndef UDC_DEBUG -+ INFO( "DMA mode (BF)\n"); -+#endif -+ } -+#ifndef UDC_DEBUG -+ if (!use_dma) { -+ INFO( "FIFO mode\n"); -+ } -+#endif -+#ifdef UDC_USE_TIMER -+ INFO("RDE timer is used\n"); -+#endif -+ DBG("-------------------------------------------------------\n"); -+} -+ -+/** -+ * Prints snapshot of ep registers -+ * -+ * \param dev pointer to device struct -+ */ -+#ifdef UDC_DEBUG -+static void print_ep_regs(struct udc* dev, struct udc_ep_regs* ep_regs) -+{ -+ INFO( "ep control = %08lx\n", (unsigned long) ep_regs->ctl); -+ INFO( "ep status = %08lx\n", (unsigned long) ep_regs->sts); -+ INFO( "--------------------------------\n"); -+} -+ -+/** -+ * Prints misc information, to be removed -+ * -+ * \param dev pointer to device struct -+ */ -+static void print_misc(struct udc* dev) -+{ -+ print_regs(dev); -+ -+ if (use_dma) { -+ -+ INFO("no_req=%ld no_pref_req=%ld\n", no_req, no_pref_req); -+ } -+} -+#endif -+ -+/* driver functions ----------------------------------------------------------*/ -+/** -+ * Called by OS for insmod -+ * -+ * \param inode file node -+ * \param file struct -+ * \return read byte -+ */ -+#ifdef UDC_DEBUG -+static int udc_open (struct inode *inode, struct file *file) -+{ -+ int retval = 0; -+ return retval; -+} -+ -+/** -+ * Called by OS for rmmod -+ * -+ * \param inode file node -+ * \param file file struct -+ * \return read byte -+ */ -+static int udc_release (struct inode *inode, struct file *file) -+{ -+ int retval = 0; -+ return retval; -+} -+ -+/** -+ * Called by OS for ioctl() from user space -+ * -+ * \param inode file node -+ * \param file file struct -+ * \param command ioctl command code -+ * \param argument ioctl argument -+ * \return 0 if success -+ */ -+static int udc_ioctl (struct inode *inode, -+ struct file *file, -+ unsigned int command, -+ unsigned long argument) -+{ -+ struct udc* dev = udc; -+ -+ if (!dev) -+ return -EINVAL; -+ -+ /* for testing PM */ -+ switch (command) -+ { -+ case 1: -+ udc_remote_wakeup(udc); -+ break; -+ case 5: -+ udc_suspend(udc); -+ break; -+ case 6: -+ udc_resume(udc); -+ break; -+ } -+ -+ INFO( "ioctl called\n"); -+ -+ return 0; -+} -+ -+/** -+ * Prints a buffers contents -+ * \param buf pointer to buffer -+ * \param bytes number bytes to print -+ */ -+static void dump_buffer(u8* buf, u32 bytes) -+{ -+ int i; -+ -+ printk("\nbuffer %lx = %d bytes:\n", (unsigned long) buf, bytes); -+ for (i = 0; i < bytes; i++) { -+ printk("%02x", *(buf + i)); -+ if ((i+1)%16 == 0) -+ printk("\n"); -+ } -+ printk("\n"); -+} -+#endif -+ -+/** -+ * Masks unused interrupts -+ * -+ * \param dev pointer to device struct -+ * \return 0 if success -+ */ -+static int udc_mask_unused_interrupts(struct udc* dev) -+{ -+ u32 tmp; -+ -+ /* mask all dev interrupts */ -+ tmp = AMD_BIT(UDC_DEVINT_SVC) | -+ AMD_BIT(UDC_DEVINT_ENUM) | -+ AMD_BIT(UDC_DEVINT_US) | -+ AMD_BIT(UDC_DEVINT_UR) | -+ AMD_BIT(UDC_DEVINT_ES) | -+ AMD_BIT(UDC_DEVINT_SI) | -+ AMD_BIT(UDC_DEVINT_SOF)| -+ AMD_BIT(UDC_DEVINT_SC); -+ writel(tmp, &dev->regs->irqmsk); -+ -+ /* mask all ep interrupts */ -+ writel(UDC_EPINT_MSK_DISABLE_ALL, &dev->regs->ep_irqmsk); -+ -+ return 0; -+} -+ -+/** -+ * Enables endpoint 0 interrupts -+ * -+ * \param dev pointer to device struct -+ * \return 0 if success -+ */ -+static int udc_enable_ep0_interrupts(struct udc* dev) -+{ -+ u32 tmp; -+ -+ DBG("udc_enable_ep0_interrupts()\n"); -+ -+ /* read irq mask */ -+ tmp = readl(&dev->regs->ep_irqmsk); -+ /* enable ep0 irq's */ -+ tmp &= AMD_UNMASK_BIT(UDC_EPINT_IN_EP0) -+ & AMD_UNMASK_BIT(UDC_EPINT_OUT_EP0); -+ writel(tmp, &dev->regs->ep_irqmsk); -+ -+ return 0; -+} -+ -+/** -+ * Enables device interrupts for SET_INTF and SET_CONFIG -+ * -+ * \param dev pointer to device struct -+ * \return 0 if success -+ */ -+static int udc_enable_dev_setup_interrupts(struct udc* dev) -+{ -+ u32 tmp; -+ -+ DBG("enable device interrupts for setup data\n"); -+ -+ /* read irq mask */ -+ tmp = readl(&dev->regs->irqmsk); -+ -+ /* enable SET_INTERFACE, SET_CONFIG and other needed irq's */ -+ tmp &= AMD_UNMASK_BIT(UDC_DEVINT_SI) -+ & AMD_UNMASK_BIT(UDC_DEVINT_SC) -+ & AMD_UNMASK_BIT(UDC_DEVINT_UR) -+#ifndef UDC_IPBUG_3943_WORKAROUND -+ & AMD_UNMASK_BIT(UDC_DEVINT_US) -+#endif -+#ifndef UDC_IPBUG_3950_WORKAROUND -+ & AMD_UNMASK_BIT(UDC_DEVINT_SVC) -+#endif -+ & AMD_UNMASK_BIT(UDC_DEVINT_ENUM); -+ writel(tmp, &dev->regs->irqmsk); -+ -+ return 0; -+} -+ -+/** -+ * Calculates fifo start of endpoint based on preceeding endpoints -+ * -+ * \param ep pointer to ep struct -+ * \return 0 if success -+ */ -+static int udc_set_txfifo_addr(struct udc_ep *ep) -+{ -+ struct udc *dev; -+ u32 tmp; -+ int i; -+ -+ if (!ep || !(ep->in)) -+ return -EINVAL; -+ -+ dev = ep->dev; -+ ep->txfifo = dev->txfifo; -+ -+ /* traverse ep's */ -+ for (i = 0; i < ep->num; i++) { -+ if (dev->ep[i].regs) { -+ /* read fifo size */ -+ tmp = readl(&dev->ep[i].regs->bufin_framenum); -+ tmp = AMD_GETBITS(tmp, UDC_EPIN_BUFF_SIZE); -+ ep->txfifo+= tmp; -+ } -+ } -+ return 0; -+} -+ -+/** -+ * Enables endpoint, is called by gadget driver -+ * -+ * \param usbep pointer to ep struct -+ * \param desc pointer to endpoint descriptor -+ * \return 0 if success -+ */ -+static int -+udc_enable (struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc) -+{ -+ struct udc_ep *ep; -+ struct udc *dev; -+ u32 tmp; -+ unsigned long iflags; -+ u8 udc_csr_epix; -+ -+ VDBG("udc_enable()\n"); -+ -+ ep = container_of (usbep, struct udc_ep, ep); -+ if (!usbep -+ || usbep->name == ep0_string -+ || !desc -+ || desc->bDescriptorType != USB_DT_ENDPOINT) { -+ ERR("udc_enable: !usbep=%d !desc=%d ep->desc!=NULL=%d usbep->name==ep0_string=%d desc->bDescriptorType!=USB_DT_ENDPOINT=%d\n", -+ !usbep, !desc, ep->desc != NULL, usbep->name == ep0_string, desc->bDescriptorType != USB_DT_ENDPOINT); -+ return -EINVAL; -+ } -+ -+ DBG("udc_enable() ep %d\n", ep->num); -+ -+ dev = ep->dev; -+ -+ /* exit on suspend */ -+ if (dev->sys_suspended) -+ return -ESHUTDOWN; -+ -+ if (!dev->driver -+ || dev->gadget.speed == USB_SPEED_UNKNOWN) -+ return -ESHUTDOWN; -+ -+ spin_lock_irqsave (&dev->lock, iflags); -+ ep->desc = desc; -+ -+ ep->halted = 0; -+ -+ /* set traffic type */ -+ tmp = readl(&dev->ep[ep->num].regs->ctl); -+ tmp = AMD_ADDBITS(tmp, desc->bmAttributes, UDC_EPCTL_ET); -+ writel(tmp, &dev->ep[ep->num].regs->ctl); -+ -+ /* set max packet size */ -+ tmp = readl(&dev->ep[ep->num].regs->bufout_maxpkt); -+ tmp = AMD_ADDBITS(tmp, desc->wMaxPacketSize, UDC_EP_MAX_PKT_SIZE); -+ ep->ep.maxpacket = desc->wMaxPacketSize; -+ writel(tmp, &dev->ep[ep->num].regs->bufout_maxpkt); -+ -+ /* IN ep */ -+ if (ep->in) { -+ -+ /* ep ix in UDC CSR register space */ -+ udc_csr_epix = ep->num; -+ -+ /* set buffer size (tx fifo entries) */ -+ tmp = readl(&dev->ep[ep->num].regs->bufin_framenum); -+ /* double buffering: fifo size = 2 x max packet size */ -+ tmp = AMD_ADDBITS( -+ tmp, -+ desc->wMaxPacketSize * UDC_EPIN_BUFF_SIZE_MULT / -+ UDC_DWORD_BYTES, -+ UDC_EPIN_BUFF_SIZE); -+ writel(tmp, &dev->ep[ep->num].regs->bufin_framenum); -+ -+ /* calc. tx fifo base addr */ -+ udc_set_txfifo_addr(ep); -+ -+ /* flush fifo */ -+ tmp = readl(&ep->regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_F); -+ writel(tmp, &ep->regs->ctl); -+ -+ } /* OUT ep */ -+ else { -+ /* ep ix in UDC CSR register space */ -+ udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS; -+ -+ /* set max packet size UDC CSR */ -+ tmp = readl(&dev->csr->ne[ep->num - UDC_CSR_EP_OUT_IX_OFS]); -+ tmp = AMD_ADDBITS(tmp, desc->wMaxPacketSize, UDC_CSR_NE_MAX_PKT); -+ writel(tmp, &dev->csr->ne[ep->num - UDC_CSR_EP_OUT_IX_OFS]); -+ -+ if (ep->num != UDC_EP0OUT_IX) -+ dev->data_ep_enabled = 1; -+ } -+ -+ /***** UDC CSR reg ****************************/ -+ /* set ep values */ -+ tmp = readl(&dev->csr->ne[udc_csr_epix]); -+ /* max packet */ -+ tmp = AMD_ADDBITS(tmp, desc->wMaxPacketSize, UDC_CSR_NE_MAX_PKT); -+ /* ep number */ -+ tmp = AMD_ADDBITS(tmp, desc->bEndpointAddress, UDC_CSR_NE_NUM); -+ /* ep direction */ -+ tmp = AMD_ADDBITS(tmp, ep->in, UDC_CSR_NE_DIR); -+ /* ep type */ -+ tmp = AMD_ADDBITS(tmp, desc->bmAttributes, UDC_CSR_NE_TYPE); -+ /* ep config */ -+ tmp = AMD_ADDBITS(tmp, ep->dev->cur_config, UDC_CSR_NE_CFG); -+ /* ep interface */ -+ tmp = AMD_ADDBITS(tmp, ep->dev->cur_intf, UDC_CSR_NE_INTF); -+ /* ep alt */ -+ tmp = AMD_ADDBITS(tmp, ep->dev->cur_alt, UDC_CSR_NE_ALT); -+ /* write reg */ -+ writel(tmp, &dev->csr->ne[udc_csr_epix]); -+ -+ /* enable ep irq */ -+ tmp = readl(&dev->regs->ep_irqmsk); -+ tmp &= AMD_UNMASK_BIT(ep->num); -+ writel(tmp, &dev->regs->ep_irqmsk); -+ -+ /* clear NAK by writing CNAK */ -+ /* avoid BNA for DMA, dont clear NAK until DMA desc. written */ -+ if (!use_dma) { -+ tmp = readl(&ep->regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); -+ writel(tmp, &ep->regs->ctl); -+ ep->naking = 0; -+ UDC_QUEUE_CNAK(ep, ep->num); -+ } -+ tmp = desc->bEndpointAddress; -+ DBG( "%s enabled\n", -+ usbep->name); -+ -+ spin_unlock_irqrestore (&dev->lock, iflags); -+ return 0; -+} -+/** -+ * Resets endpoint -+ * -+ * \param regs pointer to device register struct -+ * \param ep pointer to endpoint -+ */ -+static void ep_init (struct udc_regs *regs, struct udc_ep *ep) -+{ -+ u32 tmp; -+ -+ VDBG("ep-%d reset\n", ep->num); -+ ep->desc = 0; -+ ep->ep.ops = &udc_ep_ops; -+ INIT_LIST_HEAD (&ep->queue); -+ -+ ep->ep.maxpacket = (u16) ~0; -+ if (!(ep->dev->sys_suspended)) { -+ /* set NAK */ -+ tmp = readl(&ep->regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_SNAK); -+ writel(tmp, &ep->regs->ctl); -+ ep->naking = 1; -+ -+ /* disable interrupt */ -+ tmp = readl(®s->ep_irqmsk); -+ tmp |= AMD_BIT(ep->num); -+ writel(tmp, ®s->ep_irqmsk); -+ -+ if (ep->in) { -+ /* unset P and IN bit of potential former DMA */ -+ tmp = readl(&ep->regs->ctl); -+ tmp &= AMD_UNMASK_BIT(UDC_EPCTL_P); -+ writel(tmp, &ep->regs->ctl); -+ -+ tmp = readl(&ep->regs->sts); -+ tmp |= AMD_BIT(UDC_EPSTS_IN); -+ writel(tmp, &ep->regs->sts); -+ -+ /* flush the fifo */ -+ tmp = readl(&ep->regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_F); -+ writel(tmp, &ep->regs->ctl); -+ -+ } -+ /* reset desc pointer */ -+ writel(0, &ep->regs->desptr); -+ } -+ -+ -+} -+ -+/** -+ * Disables endpoint, is called by gadget driver -+ * -+ * \param usbep pointer to ep struct -+ * \return 0 if success -+ */ -+static int udc_disable (struct usb_ep *usbep) -+{ -+ struct udc_ep *ep = NULL; -+ unsigned long iflags; -+ -+ if (!usbep) -+ return -EINVAL; -+ -+ ep = container_of (usbep, struct udc_ep, ep); -+ if (usbep->name == ep0_string -+ || !ep->desc) -+ return -EINVAL; -+ -+ DBG("Disable ep-%d\n", ep->num); -+ -+ spin_lock_irqsave(&ep->dev->lock, iflags); -+ empty_req_queue(ep); -+ ep_init(ep->dev->regs, ep); -+ spin_unlock_irqrestore(&ep->dev->lock, iflags); -+ -+ return 0; -+} -+ -+/** -+ * Allocates request packet, called by gadget driver -+ * -+ * \param _ep pointer to usb ep struct -+ * \param gfp_flags flags for kmalloc -+ * \return allocated request packet, 0 if error -+ */ -+static struct usb_request * -+udc_alloc_request (struct usb_ep *usbep, gfp_t gfp) -+{ -+ struct udc_request *req; -+ struct udc_data_dma *dma_desc; -+ struct udc_ep *ep; -+ -+ VDBG("udc_alloc_req()\n"); -+ if (!usbep) -+ return 0; -+ -+ ep = container_of (usbep, struct udc_ep, ep); -+ udc_gfp_flags = gfp; -+ -+ VDBG("udc_alloc_req(): ep%d\n", ep->num); -+ req = kmalloc (sizeof (struct udc_request), gfp); -+ if (!req) -+ return 0; -+ -+ memset (req, 0, sizeof *req); -+ req->req.dma = DMA_DONT_USE; -+ INIT_LIST_HEAD (&req->queue); -+ -+ if (ep->dma) { -+ -+#if defined(CONFIG_SOC_AU1200) -+ gfp = GFP_ATOMIC | GFP_DMA; -+#endif -+ /* ep0 in requests are allocated from data pool here */ -+ dma_desc = dma_pool_alloc (ep->dev->data_requests, gfp, -+ &req->td_phys); -+ if (!dma_desc) { -+ kfree (req); -+ return 0; -+ } -+ -+ VDBG("udc_alloc_req: req = %lx dma_desc = %lx, req->td_phys = %lx\n", -+ (unsigned long) req, (unsigned long) dma_desc, (unsigned long)req->td_phys); -+ /* prevent from using desc. - set HOST BUSY */ -+ dma_desc->status = AMD_ADDBITS(dma_desc->status, -+ UDC_DMA_STP_STS_BS_HOST_BUSY, -+ UDC_DMA_STP_STS_BS); -+ dma_desc->bufptr = __constant_cpu_to_le32 (DMA_DONT_USE); -+ req->td_data = dma_desc; -+ req->td_data_last = NULL; -+ req->chain_len = 1; -+ } -+ -+ return &req->req; -+} -+ -+/** -+ * Frees request packet, called by gadget driver -+ * -+ * \param usbep pointer to usb ep struct -+ * \param usbreq pointer to request packet to be freed -+ */ -+static void -+udc_free_request (struct usb_ep *usbep, struct usb_request *usbreq) -+{ -+ struct udc_ep *ep; -+ struct udc_request *req; -+ -+ if (!usbep || !usbreq) -+ return; -+ -+ ep = container_of (usbep, struct udc_ep, ep); -+ req = container_of (usbreq, struct udc_request, req); -+ VDBG("free_req req=%lx\n", (unsigned long) req); -+ WARN_ON(!list_empty (&req->queue)); -+ if (req->td_data) { -+ VDBG("req->td_data=%lx\n", (unsigned long) req->td_data); -+ -+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND -+ /* re-link broken chain */ -+ if (req->td_data_last) { -+ req->td_data_last->next = req->td_data_last_next; -+ } -+#endif -+ /* free dma chain if created */ -+ if (req->chain_len > 1) { -+ udc_free_dma_chain(ep->dev, req); -+ } -+ -+ dma_pool_free (ep->dev->data_requests, req->td_data, req->td_phys); -+ } -+ kfree (req); -+} -+ -+/* choose dma buffer allocation method */ -+#undef USE_KMALLOC -+#if defined(CONFIG_X86) -+#define USE_KMALLOC -+#elif defined(CONFIG_SOC_AU1200) -+#ifdef CONFIG_DMA_COHERENT -+#define USE_KMALLOC -+#endif /* CONFIG_DMA_COHERENT */ -+#endif -+ -+/** -+ * Allocates data buffer for request packet, called by gadget driver -+ * -+ * \param usbep pointer to usb ep struct -+ * \param bytes number bytes to allocate -+ * \param dma pointer to dma struct -+ * \param gfp_flags flags for allocate -+ * \return pointer to allocated buffer, 0 if error -+ */ -+static void * -+udc_alloc_buffer ( -+ struct usb_ep *usbep, -+ unsigned len, -+ dma_addr_t *dma, -+ gfp_t gfp -+) -+{ -+ void *ptr; -+ struct udc_ep *ep; -+ VDBG("alloc_buffer(): %s\n", usbep->name); -+ -+ ep = container_of (usbep, struct udc_ep, ep); -+ *dma = DMA_DONT_USE; -+ -+ if (!usbep) -+ return 0; -+ -+ if (ep->dma) { -+#if defined(USE_KMALLOC) -+ -+#if defined(CONFIG_SOC_AU1200) -+ gfp = GFP_ATOMIC | GFP_DMA; -+#endif -+ ptr = kmalloc(len, gfp); -+ -+ if (ptr) -+ *dma = virt_to_phys(ptr); -+ -+#else -+ ptr = dma_alloc_coherent (&ep->dev->pdev->dev, len, dma, gfp); -+#endif -+ } else -+ ptr = kmalloc(len, gfp); -+ -+ VDBG("alloc_buffer() ptr = %lx dma=%lx\n", (unsigned long) ptr, (unsigned long) *dma); -+ return ptr; -+} -+ -+ -+/** -+ * Free data buffer for request packet, called by gadget driver -+ * -+ * \param usbep pointer to usb ep struct -+ * \param buf pointer to buffer to be freed -+ * \param dma pointer to dma struct -+ * \param len number bytes to be freed -+ * \return pointer to allocated buffer, 0 if error -+ */ -+static void -+udc_free_buffer ( -+ struct usb_ep *usbep, -+ void *buf, -+ dma_addr_t dma, -+ unsigned len -+) { -+ struct udc_ep *ep; -+ -+ VDBG ("ep %s - free buffer %lx\n", usbep->name, (unsigned long) buf); -+ -+ /* null pointer ? */ -+ if (!buf) { -+ return; -+ } -+ -+ ep = container_of(usbep, struct udc_ep, ep); -+ if (!ep) -+ return; -+ -+#ifndef USE_KMALLOC -+ if (dma != DMA_DONT_USE) { -+ dma_free_coherent (&ep->dev->pdev->dev, len, buf, dma); -+ } else -+#endif -+ { -+ if (!(ep->dma)) -+ kfree (buf); -+ } -+ -+} -+ -+/** -+ * Write data to TX fifo for IN packets -+ * -+ * \param ep pointer to ep struct -+ * \param req pointer to request packet -+ * \return allocated request packet, 0 if error -+ */ -+static void -+udc_txfifo_write (struct udc_ep *ep, struct usb_request *req) -+{ -+ u8 *req_buf; -+ u32 *buf; -+ int i,j; -+ unsigned bytes = 0; -+ unsigned remaining = 0; -+ -+ VDBG("udc_txfifo_write()\n"); -+ -+ if (!req || !ep) -+ return; -+ -+ req_buf = req->buf + req->actual; -+ prefetch (req_buf); -+ remaining = req->length - req->actual; -+ -+ buf = (u32*) req_buf; -+ -+ bytes = ep->ep.maxpacket; -+ if (bytes > remaining) -+ bytes = remaining; -+ -+ /* dwords first */ -+ for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) { -+ writel(*(buf + i), ep->txfifo); -+ } -+ -+ /* remaining bytes must be written by byte access */ -+ for (j = 0; j < bytes % UDC_DWORD_BYTES; j++) { -+ writeb((u8) (*(buf + i) >> (j << UDC_BITS_PER_BYTE_SHIFT)), -+ ep->txfifo); -+ } -+ -+#ifdef UDC_IPBUG_2253_WORKAROUND -+ { -+ u32 tmp; -+ -+ /* NAK if small packet until write confirm completed */ -+ if (bytes < UDC_SMALL_PACKET) { -+ /* set NAK */ -+ tmp = readl(&ep->regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_SNAK); -+ writel(tmp, &ep->regs->ctl); -+ ep->naking = 1; -+ wb_flush(); -+ } -+ -+ /* dummy write confirm */ -+ writel(0, &ep->regs->confirm); -+ -+ /* stop NAKing after small packet DMA */ -+ if (ep->naking) { -+ /* clear NAK by writing CNAK */ -+ tmp = readl(&ep->regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); -+ writel(tmp, &ep->regs->ctl); -+ ep->naking = 0; -+ UDC_QUEUE_CNAK(ep, ep->num); -+ } -+ } -+#else -+ /* dummy write confirm */ -+ writel(0, &ep->regs->confirm); -+#endif -+} -+ -+/** -+ * Read dwords from RX fifo for OUT transfers -+ * -+ * \param dev pointer to device struct -+ * \param buf pointer to buffer to be filled -+ * \param dwords number of dwords to be read -+ * \return allocated request packet, 0 if error -+ */ -+static int udc_rxfifo_read_dwords(struct udc* dev, u32* buf, int dwords) -+{ -+ int i; -+ -+ VDBG("udc_read_dwords(): %d dwords\n", dwords); -+ -+ for (i = 0; i < dwords; i++) -+ { -+ *(buf + i) = readl(dev->rxfifo); -+ } -+ return 0; -+} -+ -+/** -+ * Read bytes from RX fifo for OUT transfers -+ * -+ * \param dev pointer to device struct -+ * \param buf pointer to buffer to be filled -+ * \param bytes number of bytes to be read -+ * \return allocated request packet, 0 if error -+ */ -+static int udc_rxfifo_read_bytes(struct udc* dev, u8* buf, int bytes) -+{ -+ int i,j; -+ u32 tmp; -+ -+ VDBG("udc_read_bytes(): %d bytes\n", bytes); -+ -+ /* dwords first */ -+ for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) { -+ *((u32*) (buf + (i<<2))) = readl(dev->rxfifo); -+ } -+ -+ /* remaining bytes must be read by byte access */ -+ if (bytes % UDC_DWORD_BYTES) { -+ tmp = readl(dev->rxfifo); -+ for (j = 0; j < bytes % UDC_DWORD_BYTES; j++) { -+ *(buf + (i<<2) + j) = (u8) (tmp & UDC_BYTE_MASK); -+ tmp = tmp >> UDC_BITS_PER_BYTE; -+ } -+ } -+ -+ return 0; -+} -+ -+/** -+ * Read data from RX fifo for OUT transfers -+ * -+ * \param ep pointer to ep struct -+ * \param req pointer to request packet -+ * \return true if request completes for short or max packet, false otherwise -+ */ -+static int -+udc_rxfifo_read(struct udc_ep *ep, struct udc_request *req) -+{ -+ u8 *buf; -+ unsigned buf_space; -+ unsigned bytes = 0; -+ unsigned finished = 0; -+ -+ /* received number bytes */ -+ bytes = readl(&ep->regs->sts); -+ bytes = AMD_GETBITS(bytes, UDC_EPSTS_RX_PKT_SIZE); -+ -+ buf_space = req->req.length - req->req.actual; -+ buf = req->req.buf + req->req.actual; -+ if (bytes > buf_space) { -+ if ((buf_space % ep->ep.maxpacket) != 0) { -+ ERR( "%s: received %d bytes, rx-buffer space = %d bytes => buffer overrun\n", -+ ep->ep.name, bytes, buf_space); -+ req->req.status = -EOVERFLOW; -+ } -+ bytes = buf_space; -+ } -+ req->req.actual += bytes; -+ -+ /* last packet ? */ -+ if (((bytes % ep->ep.maxpacket) != 0) -+ || (!bytes) -+ || ((req->req.actual == req->req.length) && !req->req.zero)) -+ finished = 1; -+ -+ /* read rx fifo bytes */ -+ VDBG("ep %s: rxfifo read %d bytes\n", ep->ep.name, bytes); -+ udc_rxfifo_read_bytes(ep->dev, buf, bytes); -+ -+ return finished; -+} -+ -+/** -+ * create/re-init a DMA descriptor or a DMA descriptor chain -+ * -+ * \param ep pointer to endpoint struct -+ * \param req pointer to request packet -+ */ -+static int prep_dma (struct udc_ep *ep, struct udc_request *req) -+{ -+ int retval = 0; -+ u32 tmp; -+ VDBG("prep_dma\n"); -+ VDBG("prep_dma ep%d req->td_data=%lx\n", -+ ep->num, (unsigned long) req->td_data); -+ -+ /* set buffer pointer */ -+ req->td_data->bufptr = req->req.dma; -+ -+ /* set last bit */ -+ req->td_data->status |= AMD_BIT(UDC_DMA_IN_STS_L); -+ -+ /* build/re-init dma chain if maxpkt scatter mode, not for EP0 */ -+ if (use_dma_ppb && ep->num != UDC_EP0OUT_IX && ep->num != UDC_EP0IN_IX) { -+ -+ retval = udc_create_dma_chain(ep, req, ep->ep.maxpacket, udc_gfp_flags); -+ if (retval != 0) -+ { -+ if (retval == -ENOMEM) -+ INFO("Out of DMA memory (allocation failed)\n"); -+ return retval; -+ } -+ if (ep->in) { -+ if (req->req.length == ep->ep.maxpacket) { -+ /* write tx bytes */ -+ req->td_data->status = AMD_ADDBITS(req->td_data->status, -+ ep->ep.maxpacket, -+ UDC_DMA_IN_STS_TXBYTES); -+ -+ } -+ } -+ -+ } -+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND -+ else { /* EP0 */ -+ /* point to itself */ -+ req->td_data->next = req->td_phys; -+ } -+#endif -+ -+ if (ep->in) { -+ VDBG("IN: use_dma_ppb=%d req->req.length=%d ep->ep.maxpacket=%d ep%d\n", -+ use_dma_ppb, req->req.length, ep->ep.maxpacket, ep->num); -+ /* if bytes < max packet then tx bytes must */ -+ /* be written in packet per buffer mode */ -+ if (!use_dma_ppb || req->req.length < ep->ep.maxpacket -+ || ep->num == UDC_EP0OUT_IX || ep->num == UDC_EP0IN_IX) { -+ /* write tx bytes */ -+ req->td_data->status = AMD_ADDBITS(req->td_data->status, -+ req->req.length, -+ UDC_DMA_IN_STS_TXBYTES); -+ /* reset frame num */ -+ req->td_data->status = AMD_ADDBITS(req->td_data->status, -+ 0, -+ UDC_DMA_IN_STS_FRAMENUM); -+ } -+ /* set HOST BUSY */ -+ req->td_data->status -+ = AMD_ADDBITS(req->td_data->status, -+ UDC_DMA_STP_STS_BS_HOST_BUSY, -+ UDC_DMA_STP_STS_BS); -+ } -+ else { -+ VDBG("OUT set host ready\n"); -+ /* set HOST READY */ -+ req->td_data->status -+ = AMD_ADDBITS(req->td_data->status, -+ UDC_DMA_STP_STS_BS_HOST_READY, -+ UDC_DMA_STP_STS_BS); -+ -+ -+ /* clear NAK by writing CNAK */ -+ if (ep->naking) { -+ tmp = readl(&ep->regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); -+ writel(tmp, &ep->regs->ctl); -+ ep->naking = 0; -+ UDC_QUEUE_CNAK(ep, ep->num); -+ } -+ -+ } -+ -+ return retval; -+} -+ -+/** -+ * Completes request packet -+ * -+ * \param ep pointer to ep struct -+ * \param req pointer to request packet -+ * \param sts status of request -+ */ -+static void -+complete_req(struct udc_ep *ep, struct udc_request *req, int sts) -+{ -+ struct udc *dev; -+ unsigned halted; -+ -+ VDBG("complete_req(): ep%d\n", ep->num); -+ -+ dev = ep->dev; -+ /* unmap DMA */ -+ if (req->dma_mapping) { -+#if defined(CONFIG_SOC_AU1200) -+ if (ep->in) -+ dma_unmap_single(0, -+ req->req.dma, -+ req->req.length, -+ PCI_DMA_TODEVICE); -+ else -+ dma_unmap_single(0, -+ req->req.dma, -+ req->req.length, -+ PCI_DMA_FROMDEVICE); -+#else -+ if (ep->in) -+ pci_unmap_single(dev->pdev, -+ req->req.dma, -+ req->req.length, -+ PCI_DMA_TODEVICE); -+ else -+ pci_unmap_single(dev->pdev, -+ req->req.dma, -+ req->req.length, -+ PCI_DMA_FROMDEVICE); -+#endif -+ req->dma_mapping = 0; -+ req->req.dma = DMA_DONT_USE; -+ } -+ -+ halted = ep->halted; -+ ep->halted = 1; -+ -+ /* set new status if pending */ -+ if (req->req.status == -EINPROGRESS) -+ req->req.status = sts; -+ -+ /* remove from ep queue */ -+ list_del_init (&req->queue); -+ -+ VDBG( "req %p => complete %d bytes at %s with sts %d\n", -+ &req->req, req->req.length, ep->ep.name, sts); -+ if (spin_is_locked(&dev->lock)) { -+ spin_unlock (&dev->lock); -+ req->req.complete (&ep->ep, &req->req); -+ spin_lock (&dev->lock); -+ } -+ else { -+ req->req.complete (&ep->ep, &req->req); -+ } -+ ep->halted = halted; -+} -+ -+/** -+ * frees pci pool descriptors of a DMA chain -+ * -+ * \param dev pointer to device struct -+ * \param req pointer to request packet -+ * \return 0 if success -+ */ -+static int udc_free_dma_chain(struct udc* dev, struct udc_request* req) -+{ -+ -+ int ret_val = 0; -+ struct udc_data_dma *td; -+ struct udc_data_dma *td_last = NULL; -+ unsigned int i; -+ -+ DBG("free chain req = %lx\n", (unsigned long) req); -+ -+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND -+ /* re-link broken chain */ -+ if (req->td_data_last) { -+ req->td_data_last->next = req->td_data_last_next; -+ } -+#endif -+ /* do not free first desc., will be done by free for request */ -+ td_last = req->td_data; -+#if defined (CONFIG_SOC_AU1200) && !defined(CONFIG_DMA_COHERENT) -+ td = UNCAC_ADDR(phys_to_virt(td_last->next)); -+#else -+ td = phys_to_virt(td_last->next); -+#endif -+ -+ for (i = 1; i < req->chain_len; i++) { -+ -+ dma_pool_free (dev->data_requests, td, -+ (dma_addr_t) td_last->next); -+ td_last = td; -+#if defined (CONFIG_SOC_AU1200) && !defined(CONFIG_DMA_COHERENT) -+ td = UNCAC_ADDR(phys_to_virt(td_last->next)); -+#else -+ td = phys_to_virt(td_last->next); -+#endif -+ } -+ -+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND -+ req->td_data_last = NULL; -+#endif -+ return ret_val; -+} -+ -+/** -+ * Iterates to the end of a DMA chain and returns last descriptor -+ * -+ * \param req pointer to request packet -+ * \return pointer to last descriptori of chain -+ */ -+static struct udc_data_dma* udc_get_last_dma_desc(struct udc_request* req) -+{ -+ struct udc_data_dma *td; -+ -+ td = req->td_data; -+ while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L))) { -+#if defined (CONFIG_SOC_AU1200) && !defined(CONFIG_DMA_COHERENT) -+ td = UNCAC_ADDR(phys_to_virt(td->next)); -+#else -+ td = phys_to_virt(td->next); -+#endif -+ } -+ -+ return td; -+ -+} -+ -+/** -+ * Iterates to the end of a DMA chain and counts bytes received -+ * -+ * \param req pointer to request packet -+ * \return number of received bytes -+ */ -+static u32 udc_get_ppbdu_rxbytes(struct udc_request* req) -+{ -+ struct udc_data_dma *td; -+ u32 count; -+ -+ td = req->td_data; -+ /* received number bytes */ -+ count = AMD_GETBITS(td->status, UDC_DMA_OUT_STS_RXBYTES); -+ -+ while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L))) { -+#if defined (CONFIG_SOC_AU1200) && !defined(CONFIG_DMA_COHERENT) -+ td = UNCAC_ADDR(phys_to_virt(td->next)); -+#else -+ td = phys_to_virt(td->next); -+#endif -+ /* received number bytes */ -+ if (td) { -+ count += AMD_GETBITS(td->status, UDC_DMA_OUT_STS_RXBYTES); -+ } -+ } -+ -+ return count; -+ -+} -+ -+/** -+ * Creates or re-inits a DMA chain -+ * -+ * \param ep pointer to endpoint struct -+ * \param req pointer to request packet -+ * \param buf_len number of buffer bytes per descriptor (except last short) -+ */ -+static int udc_create_dma_chain(struct udc_ep* ep, struct udc_request* req, unsigned long buf_len, int gfp_flags) -+{ -+ unsigned long bytes = req->req.length; -+ unsigned int i; -+ dma_addr_t dma_addr; -+ struct udc_data_dma *td = NULL; -+ struct udc_data_dma *last = NULL; -+ unsigned long txbytes; -+ unsigned create_new_chain = 0; -+ unsigned len; -+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND -+ dma_addr_t last_next = DMA_DONT_USE; -+#endif -+ -+ VDBG("udc_create_dma_chain: bytes=%ld buf_len=%ld\n", bytes, buf_len); -+ dma_addr = DMA_DONT_USE; -+ -+ /* unset L bit in first desc for OUT */ -+ if (!ep->in) { -+ req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L); -+ } -+ -+ /* alloc only new desc's if not already available */ -+ len = req->req.length / ep->ep.maxpacket; -+ if (req->req.length % ep->ep.maxpacket) { -+ len++; -+ } -+ -+ if (len > req->chain_len) { -+ /* shorter chain already allocated before */ -+ if (req->chain_len > 1) { -+ udc_free_dma_chain(ep->dev, req); -+ } -+ req->chain_len = len; -+ create_new_chain = 1; -+ } -+ -+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND -+ /* re-link broken chain */ -+ if (req->td_data_last) { -+ req->td_data_last->next = req->td_data_last_next; -+ } -+ /* if only one td then last_next is root td */ -+ last_next = req->td_phys; -+#endif -+ -+ td = req->td_data; -+ /* gen. required number of descriptors and buffers */ -+ for (i = buf_len; i < bytes; i += buf_len) -+ { -+ /* create or determine next desc. */ -+ if (create_new_chain) { -+ -+#if defined(CONFIG_SOC_AU1200) -+ gfp_flags = GFP_ATOMIC | GFP_DMA; -+#endif -+ td = dma_pool_alloc (ep->dev->data_requests, gfp_flags, -+ &dma_addr); -+ if (!td) -+ return -ENOMEM; -+ -+ td->status = 0; -+ } -+ else if (i == buf_len) -+ { -+ /* first td */ -+#if defined (CONFIG_SOC_AU1200) && !defined(CONFIG_DMA_COHERENT) -+ td = (struct udc_data_dma*) UNCAC_ADDR(phys_to_virt(req->td_data->next)); -+#else -+ td = (struct udc_data_dma*) phys_to_virt(req->td_data->next); -+#endif -+ td->status = 0; -+ } -+ else { -+#if defined (CONFIG_SOC_AU1200) && !defined(CONFIG_DMA_COHERENT) -+ td = (struct udc_data_dma*) UNCAC_ADDR(phys_to_virt(last->next)); -+#else -+ td = (struct udc_data_dma*) phys_to_virt(last->next); -+#endif -+ td->status = 0; -+ } -+ -+ -+ if (td) { -+ /* assign buffer */ -+ td->bufptr = req->req.dma + i; -+ } -+ else { -+ break; -+ } -+ -+ /* short packet ? */ -+ if ((bytes - i) >= buf_len) { -+ txbytes = buf_len; -+ } -+ else { -+ /* short packet */ -+ txbytes = bytes - i; -+ } -+ -+ /* link td and assign tx bytes */ -+ if (i == buf_len) { -+ if (create_new_chain) { -+ req->td_data->next = dma_addr; -+ } -+ else { -+ /* req->td_data->next = virt_to_phys(td); */ -+ } -+ /* write tx bytes */ -+ if (ep->in) { -+ /* first desc */ -+ req->td_data->status = AMD_ADDBITS(req->td_data->status, -+ ep->ep.maxpacket, -+ UDC_DMA_IN_STS_TXBYTES); -+ /* second desc */ -+ td->status = AMD_ADDBITS(td->status, -+ txbytes, -+ UDC_DMA_IN_STS_TXBYTES); -+ } -+ -+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND -+ last_next = req->td_data->next; -+#endif -+ } -+ else { -+ if (create_new_chain) { -+ last->next = dma_addr; -+ } -+ else { -+ /* last->next = virt_to_phys(td); */ -+ } -+ if (ep->in) { -+ /* write tx bytes */ -+ td->status = AMD_ADDBITS(td->status, -+ txbytes, -+ UDC_DMA_IN_STS_TXBYTES); -+ } -+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND -+ last_next = last->next; -+#endif -+ } -+ last = td; -+ } -+ /* set last bit */ -+ if (td) { -+ td->status |= AMD_BIT(UDC_DMA_IN_STS_L); -+ /* last desc. points to itself */ -+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND -+ /* remember broken chain next pointer */ -+ req->td_data_last_next = td->next; -+ /* point to itself */ -+ td->next = last_next; -+#endif -+ req->td_data_last = td; -+ } -+ -+ return 0; -+} -+ -+/** -+ * Enabling RX DMA -+ * -+ * \param dev pointer to UDC device object -+ */ -+static inline void udc_set_rde(struct udc* dev) -+{ -+ u32 tmp; -+ -+ VDBG("udc_set_rde()\n"); -+#ifdef UDC_USE_TIMER -+ /* stop RDE timer */ -+ if (timer_pending(&udc_timer)) { -+ set_rde = 0; -+ mod_timer(&udc_timer, jiffies - 1); -+ } -+#endif -+ /* set RDE */ -+ tmp = readl(&dev->regs->ctl); -+ tmp |= AMD_BIT(UDC_DEVCTL_RDE); -+ writel(tmp, &dev->regs->ctl); -+} -+ -+/** -+ * Queues a request packet, called by gadget driver -+ * -+ * \param usbep pointer to usb ep struct -+ * \param usbreq pointer to request packet to be freed -+ * \param gfp flags for alloc -+ * \return 0 if success -+ */ -+static int -+udc_queue (struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp) -+{ -+ int retval = 0; -+ unsigned long iflags; -+ struct udc_ep *ep; -+ struct udc_request *req; -+ struct udc *dev; -+ u32 tmp; -+ -+ VDBG ("udc_queue()\n"); -+ -+ /* check the inputs */ -+ req = container_of (usbreq, struct udc_request, req); -+ VDBG("!usbep=%d !req=%d !buf=%d !compl=%d !empty_list=%d \n", -+ !usbep, !usbreq, !usbreq->buf, !usbreq->complete, -+ !list_empty(&req->queue)); -+ -+ if (!usbep || !usbreq || !usbreq->complete || !usbreq->buf -+ || !list_empty (&req->queue)) -+ return -EINVAL; -+ -+ ep = container_of (usbep, struct udc_ep, ep); -+ if (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX)) -+ return -EINVAL; -+ -+ VDBG("udc_queue(): ep%d-in=%d\n", ep->num, ep->in); -+ dev = ep->dev; -+ -+ /* exit on suspend */ -+ if (dev->sys_suspended) -+ return -ESHUTDOWN; -+ -+ if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) -+ return -ESHUTDOWN; -+ -+ /* map dma (usally done before) */ -+ if (ep->dma && usbreq->length != 0 && usbreq->dma == DMA_DONT_USE) { -+ VDBG("DMA map req %lx\n", (unsigned long) req); -+#if defined(CONFIG_SOC_AU1200) -+ if (ep->in) -+ usbreq->dma = dma_map_single(dev->pdev, -+ usbreq->buf, -+ usbreq->length, -+ PCI_DMA_TODEVICE); -+ else -+ usbreq->dma = dma_map_single(dev->pdev, -+ usbreq->buf, -+ usbreq->length, -+ PCI_DMA_FROMDEVICE); -+#else -+ if (ep->in) -+ usbreq->dma = pci_map_single(dev->pdev, -+ usbreq->buf, -+ usbreq->length, -+ PCI_DMA_TODEVICE); -+ else -+ usbreq->dma = pci_map_single(dev->pdev, -+ usbreq->buf, -+ usbreq->length, -+ PCI_DMA_FROMDEVICE); -+#endif -+ req->dma_mapping = 1; -+ } -+ -+ VDBG( "%s queue req %p, len %d req->td_data=%lx buf %p\n", -+ usbep->name, usbreq, usbreq->length, (unsigned long) req->td_data, usbreq->buf); -+ -+ spin_lock_irqsave (&dev->lock, iflags); -+ usbreq->actual = 0; -+ usbreq->status = -EINPROGRESS; -+ req->dma_done = 0; -+ -+ /* on empty queue just do first transfer */ -+ if (list_empty (&ep->queue)) { -+ /* zlp */ -+ if (ep->in && usbreq->length == 0) { -+ /* IN zlp's are handled by hardware */ -+ complete_req(ep, req, 0); -+ VDBG( "%s: zlp\n", ep->ep.name); -+ /* if set_config or set_intf is waiting for ack by zlp -+ then set CSR_DONE */ -+ if (dev->set_cfg_not_acked) { -+ tmp = readl(&dev->regs->ctl); -+ tmp |= AMD_BIT(UDC_DEVCTL_CSR_DONE); -+ writel(tmp, &dev->regs->ctl); -+ dev->set_cfg_not_acked = 0; -+ } -+ /* setup command is ACK'ed now by zlp */ -+ if (dev->waiting_zlp_ack_ep0in) { -+ /* clear NAK by writing CNAK in EP0_IN */ -+ tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); -+ writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl); -+ dev->ep[UDC_EP0IN_IX].naking = 0; -+ UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX], UDC_EP0IN_IX); -+ dev->waiting_zlp_ack_ep0in = 0; -+ } -+ goto finished; -+ } -+ if (ep->dma) { -+ retval = prep_dma(ep, req); -+ if (retval != 0) -+ goto finished; -+ /* write desc pointer to enable DMA */ -+ if (ep->in) { -+ /* set HOST READY */ -+ req->td_data->status -+ = AMD_ADDBITS(req->td_data->status, -+ UDC_DMA_IN_STS_BS_HOST_READY, -+ UDC_DMA_IN_STS_BS); -+ } -+ -+ /* write desc pointer */ -+ writel(req->td_phys, &ep->regs->desptr); -+ /* clear NAK by writing CNAK */ -+ if (ep->naking) { -+ tmp = readl(&ep->regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); -+ writel(tmp, &ep->regs->ctl); -+ ep->naking = 0; -+ UDC_QUEUE_CNAK(ep, ep->num); -+ } -+ -+ if (!ep->in) { -+ /* enable DMA */ -+ udc_set_rde(dev); -+ if (ep->num != UDC_EP0OUT_IX) -+ dev->data_ep_queued = 1; -+ } -+#ifdef UDC_DISABLE_IRQ_IF_EMPTY_IN_QUEUE -+ else { -+ /* enable ep irq */ -+ tmp = readl(&dev->regs->ep_irqmsk); -+ tmp &= AMD_UNMASK_BIT(ep->num); -+ writel(tmp, &dev->regs->ep_irqmsk); -+ } -+#endif -+ } -+ -+ } else if (ep->dma) { -+ -+ /* prep_dma not used for OUT ep's, this is not possible -+ for PPB modes, because of chain creation reasons */ -+ if (ep->in) { -+ retval = prep_dma(ep, req); -+ if (retval != 0) -+ goto finished; -+ } -+ -+ } -+ VDBG("list_add\n"); -+ /* add request to ep queue */ -+ if (req) { -+ -+ list_add_tail (&req->queue, &ep->queue); -+ -+ /* stop OUT naking */ -+ if (!ep->in) { -+ if (!use_dma && udc_rxfifo_pending) { -+ DBG("udc_queue(): pending bytes in rxfifo after nyet\n"); -+ /* read pending bytes afer nyet: referring to isr */ -+ if (udc_rxfifo_read(ep, req)) { -+ /* finish */ -+ complete_req(ep, req, 0); -+ } -+ udc_rxfifo_pending = 0; -+ -+ } -+ } -+ -+ } -+ -+finished: -+ spin_unlock_irqrestore (&dev->lock, iflags); -+ return retval; -+} -+ -+/** -+ * Empty request queue of an endpoint -+ * -+ * \param ep pointer to ep struct -+ */ -+static void empty_req_queue(struct udc_ep *ep) -+{ -+ struct udc_request *req; -+ -+ ep->halted = 1; -+ while (!list_empty (&ep->queue)) { -+ req = list_entry(ep->queue.next, -+ struct udc_request, -+ queue); -+ complete_req(ep, req, -ESHUTDOWN); -+ } -+} -+ -+/** -+ * Dequeues a request packet, called by gadget driver -+ * -+ * \param usbep pointer to usb ep struct -+ * \param usbreq pointer to request packet to be freed -+ * \return 0 if success -+ */ -+static int udc_dequeue (struct usb_ep *usbep, struct usb_request *usbreq) -+{ -+ struct udc_ep *ep; -+ struct udc_request *req; -+ unsigned req_may_used = 0; -+ unsigned halted; -+ unsigned long iflags; -+ -+ ep = container_of (usbep, struct udc_ep, ep); -+ if (!usbep -+ || !usbreq -+ || (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))) -+ return -EINVAL; -+ -+ req = container_of (usbreq, struct udc_request, req); -+ -+ spin_lock_irqsave (&ep->dev->lock, iflags); -+ halted = ep->halted; -+ ep->halted = 1; -+ /* request in processing or next one */ -+ if (ep->queue.next == &req->queue) { -+ req_may_used = 1; -+ } -+ complete_req(ep, req, -ECONNRESET); -+ ep->halted = halted; -+ -+ spin_unlock_irqrestore (&ep->dev->lock, iflags); -+ if (req_may_used) -+ return -EOPNOTSUPP; -+ else -+ return 0; -+} -+ -+/** -+ * Halt or clear halt of endpoint -+ * -+ * \param usbe pointer to ep struct -+ * \param halt 1 - halt, 0 - clear halt -+ * \return 0 if success -+ */ -+static int -+udc_set_halt (struct usb_ep *usbep, int halt) -+{ -+ struct udc_ep *ep; -+ u32 tmp; -+ unsigned long iflags; -+ int retval = 0; -+ -+ if (!usbep) -+ return -EINVAL; -+ -+ DBG("set_halt %s: halt=%d\n", usbep->name, halt); -+ -+ ep = container_of (usbep, struct udc_ep, ep); -+ if (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX)) -+ return -EINVAL; -+ if (!ep->dev->driver -+ || ep->dev->gadget.speed == USB_SPEED_UNKNOWN) -+ return -ESHUTDOWN; -+ -+ /* exit on suspend */ -+ if (ep->dev->sys_suspended) -+ return -ESHUTDOWN; -+ -+ spin_lock_irqsave (&udc_stall_spinlock, iflags); -+ /* halt or clear halt */ -+ if (halt) { -+ if (ep->num == 0) -+ ep->dev->stall_ep0in = 1; -+ else { -+ /* set STALL */ -+ /* rxfifo empty not taken into acount */ -+ tmp = readl(&ep->regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_S); -+ writel(tmp, &ep->regs->ctl); -+ ep->halted = 1; -+ -+#ifdef UDC_USE_TIMER -+ /* setup poll timer */ -+ if (!timer_pending(&udc_pollstall_timer)) { -+ udc_pollstall_timer.expires = jiffies + HZ -+ * UDC_POLLSTALL_TIMER_USECONDS -+ / (1000 * 1000); -+ if (!stop_pollstall_timer) { -+ DBG("start polltimer\n"); -+ add_timer(&udc_pollstall_timer); -+ } -+ } -+#endif -+ } -+ } else { -+ /* ep is halted by set_halt() before */ -+ if (ep->halted) { -+ tmp = readl(&ep->regs->ctl); -+ /* clear stall bit */ -+ tmp = tmp & AMD_CLEAR_BIT(UDC_EPCTL_S); -+ /* clear NAK by writing CNAK */ -+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); -+ writel(tmp, &ep->regs->ctl); -+ ep->halted = 0; -+ UDC_QUEUE_CNAK(ep, ep->num); -+ } -+ } -+ spin_unlock_irqrestore (&udc_stall_spinlock, iflags); -+ return retval; -+} -+ -+/** -+ * Return fifo fill state (not used, not implemented) -+ * -+ * \param usbep pointer to usb ep struct -+ * \return available bytes in fifo -+ */ -+static int -+udc_fifo_status (struct usb_ep *usbep) -+{ -+ return 0; -+} -+ -+/** -+ * Flush the endpoint fifo (not implemented) -+ * -+ * \param usbep pointer to usb ep struct -+ */ -+static void -+udc_fifo_flush (struct usb_ep *usbep) -+{ -+ return; -+} -+ -+/* gadget interface */ -+static struct usb_ep_ops udc_ep_ops = { -+ .enable = udc_enable, -+ .disable = udc_disable, -+ -+ .queue = udc_queue, -+ .dequeue = udc_dequeue, -+ -+ .alloc_request = udc_alloc_request, -+ .free_request = udc_free_request, -+ -+ .alloc_buffer = udc_alloc_buffer, -+ .free_buffer = udc_free_buffer, -+ -+ .set_halt = udc_set_halt, -+ .fifo_status = udc_fifo_status, -+ .fifo_flush = udc_fifo_flush, -+}; -+ -+/*-------------------------------------------------------------------------*/ -+ -+/** -+ * Get frame count fifo (not implemented) -+ * -+ * \param gadget pointer to gadget struct -+ * \return frame count -+ */ -+static int udc_get_frame (struct usb_gadget *gadget) -+{ -+ return 0; -+} -+ -+/** -+ * Remote wakeup gadget interface -+ * -+ * \param gadget pointer to gadget struct -+ * \return 0 if success -+ */ -+static int udc_wakeup (struct usb_gadget *gadget) -+{ -+ struct udc *dev; -+ -+ if (!gadget) -+ return -EINVAL; -+ dev = container_of (gadget, struct udc, gadget); -+ udc_remote_wakeup(dev); -+ -+ return 0; -+} -+ -+/** -+ * gadget ioctl, used for OTG support notification -+ * -+ * \param gadget pointer to gadget struct -+ * \param cmd command -+ * \param par parmater -+ * \return 1 if OTG supported, else 0 -+ */ -+static int udc_gadget_ioctl (struct usb_gadget *gadget, unsigned cmd, unsigned long par) -+{ -+ struct udc *dev; -+ int retval = 0; -+ unsigned long iflags; -+ u32 tmp; -+ -+ if (!gadget) -+ return -ENODEV; -+ dev = container_of (gadget, struct udc, gadget); -+ spin_lock_irqsave (&dev->lock, iflags); -+ tmp = readl(&dev->regs->cfg); -+ -+ if (tmp & AMD_BIT(UDC_DEVCFG_HNPSFEN)) -+ retval = 1; -+ else -+ retval = 0; -+ spin_unlock_irqrestore (&dev->lock, iflags); -+ return retval; -+} -+ -+/* gadget operations */ -+static const struct usb_gadget_ops udc_ops = { -+ .wakeup = udc_wakeup, -+ .get_frame = udc_get_frame, -+ .ioctl = udc_gadget_ioctl, -+}; -+ -+/** -+ * Setups endpoint parameters, adds endpoints to linked list -+ * -+ * \param dev pointer to dev struct -+ */ -+static void make_ep_lists(struct udc *dev) -+{ -+ /* make gadget ep lists */ -+ INIT_LIST_HEAD (&dev->gadget.ep_list); -+ list_add_tail (&dev->ep [UDC_EPIN_STATUS_IX].ep.ep_list, &dev->gadget.ep_list); -+ list_add_tail (&dev->ep [UDC_EPIN_IX].ep.ep_list, &dev->gadget.ep_list); -+ list_add_tail (&dev->ep [UDC_EPOUT_IX].ep.ep_list, &dev->gadget.ep_list); -+ -+ /* fifo config */ -+ dev->ep [UDC_EPIN_STATUS_IX].fifo_depth = UDC_EPIN_SMALLINT_BUFF_SIZE; -+ if (dev->gadget.speed == USB_SPEED_FULL) -+ dev->ep [UDC_EPIN_IX].fifo_depth = UDC_FS_EPIN_BUFF_SIZE; -+ else if (dev->gadget.speed == USB_SPEED_HIGH) -+ dev->ep [UDC_EPIN_IX].fifo_depth = hs_tx_buf; -+ dev->ep [UDC_EPOUT_IX].fifo_depth = UDC_RXFIFO_SIZE; -+} -+ -+/** -+ * Sets fifo mode, called by gadget driver -+ * -+ * \param gadget pointer to gadget struct -+ * \param md not used -+ * \return 0 if success -+ */ -+int au1200udc_set_fifo_mode (struct usb_gadget *gadget, int md) -+{ -+ struct udc *dev; -+ unsigned long iflags; -+ -+ if (!gadget) -+ return -ENODEV; -+ -+ dev = container_of (gadget, struct udc, gadget); -+ -+ spin_lock_irqsave (&dev->lock, iflags); -+ make_ep_lists(dev); -+ spin_unlock_irqrestore (&dev->lock, iflags); -+ -+ return 0; -+} -+EXPORT_SYMBOL (au1200udc_set_fifo_mode); -+ -+/** -+ * \brief -+ * init registers at driver load time -+ * -+ * \param dev pointer to device struc -+ * \return 0 if success -+ */ -+static int startup_registers(struct udc* dev) -+{ -+ u32 tmp; -+ -+ /* init controller by soft reset */ -+ udc_soft_reset(dev); -+ -+ /* mask not needed interrupts */ -+ udc_mask_unused_interrupts(dev); -+ -+ /* put into initial config */ -+ udc_basic_init (dev); -+ /* link up all endpoints */ -+ udc_setup_endpoints (dev); -+ -+ /* program speed */ -+ tmp = readl(&dev->regs->cfg); -+ if (use_fullspeed) { -+ tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD); -+ } -+ else { -+ tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_HS, UDC_DEVCFG_SPD); -+ } -+ writel(tmp, &dev->regs->cfg); -+ -+ return 0; -+} -+ -+/** -+ * Inits UDC context -+ * -+ * \param dev pointer to device struct -+ */ -+static void udc_basic_init (struct udc *dev) -+{ -+ u32 tmp; -+ -+ DBG("udc_basic_init()\n"); -+ -+ dev->gadget.speed = USB_SPEED_UNKNOWN; -+ -+#ifdef UDC_USE_TIMER -+ /* stop RDE timer */ -+ if (timer_pending(&udc_timer)) { -+ set_rde = 0; -+ mod_timer(&udc_timer, jiffies - 1); -+ } -+ /* stop poll stall timer */ -+ if (timer_pending(&udc_pollstall_timer)) { -+ mod_timer(&udc_pollstall_timer, jiffies - 1); -+ } -+#endif -+ /* disable DMA */ -+ tmp = readl(&dev->regs->ctl); -+ tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_RDE); -+ tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_TDE); -+ writel(tmp, &dev->regs->ctl); -+ -+ /* enable dynamic CSR programming */ -+ tmp = readl(&dev->regs->cfg); -+ tmp |= AMD_BIT(UDC_DEVCFG_CSR_PRG); -+ /* set self powered */ -+ tmp |= AMD_BIT(UDC_DEVCFG_SP); -+ /* set remote wakeupable */ -+ tmp |= AMD_BIT(UDC_DEVCFG_RWKP); -+ writel(tmp, &dev->regs->cfg); -+ -+ make_ep_lists(dev); -+ -+ dev->data_ep_enabled = 0; -+ dev->data_ep_queued = 0; -+} -+ -+/** -+ * Sets initial endpoint parameters -+ * -+ * \param dev pointer to device struct -+ */ -+static void udc_setup_endpoints(struct udc *dev) -+{ -+ struct udc_ep *ep; -+ u32 tmp; -+ u32 reg; -+ -+ DBG("udc_setup_endpoints()\n"); -+ -+ /* read enum speed */ -+ tmp = readl(&dev->regs->sts); -+ tmp = AMD_GETBITS(tmp, UDC_DEVSTS_ENUM_SPEED); -+ if (tmp == UDC_DEVSTS_ENUM_SPEED_HIGH) { -+ dev->gadget.speed = USB_SPEED_HIGH; -+ } -+ else if (tmp == UDC_DEVSTS_ENUM_SPEED_FULL) { -+ dev->gadget.speed = USB_SPEED_FULL; -+ } -+ -+ /* set basic ep parameters */ -+ for (tmp = 0; tmp < UDC_EP_NUM; tmp++) { -+ ep = &dev->ep[tmp]; -+ ep->dev = dev; -+ ep->ep.name = ep_string [tmp]; -+ ep->num = tmp; -+ /* txfifo size is calculated at enable time */ -+ ep->txfifo = dev->txfifo; -+ -+ /* fifo size */ -+ if (tmp < UDC_EPIN_NUM) { -+ ep->fifo_depth = UDC_TXFIFO_SIZE; -+ ep->in = 1; -+ } -+ else { -+ ep->fifo_depth = UDC_RXFIFO_SIZE; -+ ep->in = 0; -+ -+ } -+ ep->regs = &dev->ep_regs[tmp]; -+ /* ep will be reset only if ep was not enabled before to avoid -+ disabling ep interrupts when ENUM interrupt occurs but ep is -+ not enabled by gadget driver */ -+ if (!ep->desc) { -+ ep_init (dev->regs, ep); -+ } -+ -+ if (use_dma) { -+ /* ep->dma is not really used, just to indicate that */ -+ /* DMA is active: remove this */ -+ /* dma regs = dev control regs */ -+ ep->dma = (u32*) &dev->regs->ctl; -+ -+ /* nak OUT endpoints until enable - not for ep0*/ -+ if (tmp != UDC_EP0IN_IX -+ && tmp != UDC_EP0OUT_IX -+ && tmp > UDC_EPIN_NUM) { -+ /* set NAK */ -+ reg = readl(&dev->ep[tmp].regs->ctl); -+ reg |= AMD_BIT(UDC_EPCTL_SNAK); -+ writel(reg, &dev->ep[tmp].regs->ctl); -+ dev->ep[tmp].naking = 1; -+ -+ } -+ } -+ } -+ /* EP0 max packet */ -+ if (dev->gadget.speed == USB_SPEED_FULL) { -+ dev->ep [UDC_EP0IN_IX].ep.maxpacket = UDC_FS_EP0IN_MAX_PKT_SIZE; -+ dev->ep [UDC_EP0OUT_IX].ep.maxpacket = UDC_FS_EP0OUT_MAX_PKT_SIZE; -+ } -+ else if (dev->gadget.speed == USB_SPEED_HIGH) { -+ dev->ep [UDC_EP0IN_IX].ep.maxpacket = UDC_EP0IN_MAX_PKT_SIZE; -+ dev->ep [UDC_EP0OUT_IX].ep.maxpacket = UDC_EP0OUT_MAX_PKT_SIZE; -+ } -+ -+ /* with suspend bug workaround, ep0 params for gadget driver -+ are set at gadget driver bind() call */ -+ dev->gadget.ep0 = &dev->ep [UDC_EP0IN_IX].ep; -+ dev->ep [UDC_EP0IN_IX].halted = 0; -+ INIT_LIST_HEAD (&dev->gadget.ep0->ep_list); -+ -+ /* init cfg/alt/int */ -+ dev->cur_config = 0; -+ dev->cur_intf = 0; -+ dev->cur_alt = 0; -+} -+ -+/** -+ * Bringup after Connect event, -+ * initial bringup to be ready for ep0 events -+ * -+ * \param dev pointer to device struct -+ */ -+static void usb_connect (struct udc *dev) { -+ -+ INFO("USB Connect\n"); -+ -+ dev->connected = 1; -+ -+ /* put into initial config */ -+ udc_basic_init (dev); -+ -+ /* enable device setup interrupts */ -+ udc_enable_dev_setup_interrupts(dev); -+} -+ -+/** -+ * Calls gadget with disconnect event and resets the UDC and makes -+ * initial bringup to be ready for ep0 events -+ * -+ * \param dev pointer to device struct -+ */ -+static void usb_disconnect (struct udc *dev) { -+ -+ INFO("USB Disconnect\n"); -+ -+ dev->connected = 0; -+ -+ /* mask interrupts */ -+ udc_mask_unused_interrupts(dev); -+ -+ tasklet_schedule(&disconnect_tasklet); -+} -+ -+/** -+ * Tasklet for disconnect to be outside of interrupt -+ * context -+ * -+ * \param par pointer to device struct pointer -+ */ -+void udc_tasklet_disconnect(unsigned long par) -+{ -+ struct udc* dev = (struct udc*) (*((struct udc**) par)); -+ u32 tmp; -+ -+ DBG("Tasklet disconnect\n"); -+ -+ if (dev->driver) { -+ /* call gadget to reset configs etc. */ -+ if (spin_is_locked(&dev->lock)) { -+ spin_unlock(&dev->lock); -+ dev->driver->disconnect (&dev->gadget); -+ spin_lock(&dev->lock); -+ } -+ else -+ dev->driver->disconnect (&dev->gadget); -+ -+ /* empty queues */ -+ for (tmp = 0; tmp < UDC_EP_NUM; tmp++) { -+ empty_req_queue (&dev->ep [tmp]); -+ } -+ } -+ -+ /* disable ep0 */ -+ ep_init (dev->regs, -+ &dev->ep [UDC_EP0IN_IX]); -+ -+ -+ if (!soft_reset_occured) { -+ /* init controller by soft reset */ -+#ifdef UDC_IPCASE_8000018724_WORKAROUND -+ udc_soft_reset(dev); -+#endif -+ soft_reset_occured++; -+ } -+#ifndef UDC_IPBUG_3950_WORKAROUND -+ /* re-enable dev interrupts */ -+ udc_enable_dev_setup_interrupts(dev); -+#endif -+ /* back to full speed ? */ -+ if (use_fullspeed) { -+ tmp = readl(&dev->regs->cfg); -+ tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD); -+ writel(tmp, &dev->regs->cfg); -+ } -+} -+ -+/** -+ * Reset the UDC core -+ * -+ * \param dev pointer to device struct -+ */ -+static void udc_soft_reset(struct udc* dev) -+{ -+ DBG("Soft reset\n"); -+ /* reset possible waiting interrupts, because int. -+ status is lost after soft reset */ -+ /* ep int. status reset */ -+ writel(UDC_EPINT_MSK_DISABLE_ALL, &dev->regs->ep_irqsts); -+ /* device int. status reset */ -+ writel(UDC_DEV_MSK_DISABLE, &dev->regs->irqsts); -+ -+ spin_lock_irq(&udc_irq_spinlock); -+ writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg); -+ readl(&dev->regs->cfg); -+ spin_unlock_irq(&udc_irq_spinlock); -+ -+} -+ -+#ifdef UDC_USE_TIMER -+/** -+ * RDE timer callback to set RDE bit -+ * -+ * \param v timer callback argument -+ */ -+void udc_timer_function(unsigned long v) -+{ -+ u32 tmp; -+ unsigned int i; -+ unsigned int bulk_data_arrived; -+ spin_lock_irq(&udc_irq_spinlock); -+ if (set_rde) { -+ /* open the fifo if fifo was filled on last timer call */ -+ if (set_rde > 1) { -+ bulk_data_arrived = 0; -+ /* check wether OUT bulk data is arrived */ -+ for (i = UDC_EPIN_NUM + 1; i < UDC_EP_NUM; i++) { -+ tmp = readl(&udc->ep [i].regs->sts); -+ if (AMD_GETBITS(tmp, UDC_EPSTS_OUT) -+ == UDC_EPSTS_OUT_DATA) { -+ bulk_data_arrived = 1; -+ break; -+ } -+ } -+ /* if OUT bulk data in fifo wait for queueing which -+ sets RDE, if not open fifo for setup packet */ -+ if (!bulk_data_arrived) { -+ /* set RDE */ -+ tmp = readl(&udc->regs->ctl); -+ tmp |= AMD_BIT(UDC_DEVCTL_RDE); -+ writel(tmp, &udc->regs->ctl); -+ } -+ else -+ INFO("ep%d - queueing delay longer than %d second(s)\n", -+ i, UDC_RDE_TIMER_SECONDS); -+ set_rde = -1; -+ } -+ else if (readl(&udc->regs->sts) & -+ AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) { -+ /* if fifo empty setup polling, do not just -+ open the fifo */ -+ udc_timer.expires = jiffies + HZ/UDC_RDE_TIMER_DIV; -+ if (!stop_timer) { -+ add_timer(&udc_timer); -+ } -+ } -+ else { -+ /* fifo contains data now, setup timer for opening -+ the fifo when timer expires to be able to receive -+ setup packets, when data packets gets queued by -+ gadget layer then timer will forced to expire with -+ set_rde=0 (RDE is set in udc_queue()) */ -+ set_rde++; -+ /* debug: lhadmot_timer_start = 221070 */ -+ udc_timer.expires = jiffies + HZ*UDC_RDE_TIMER_SECONDS; -+ if (!stop_timer) { -+ add_timer(&udc_timer); -+ } -+ } -+ -+ } -+ else -+ set_rde = -1; /* RDE was set by udc_queue() */ -+ spin_unlock_irq(&udc_irq_spinlock); -+ if (stop_timer) -+ complete(&on_exit); -+ -+} -+ -+/** -+ * Handle halt state, used in stall poll timer -+ * -+ * \param ep pointer to endpoint struct -+ */ -+static inline void udc_handle_halt_state(struct udc_ep* ep) -+{ -+ u32 tmp; -+ /* set stall as long not halted */ -+ if (ep->halted == 1) { -+ tmp = readl(&ep->regs->ctl); -+ /* STALL cleared ? */ -+ if (!(tmp & AMD_BIT(UDC_EPCTL_S))) { -+ DBG("ep %d: set STALL again\n", ep->num); -+ /* set STALL again */ -+ tmp |= AMD_BIT(UDC_EPCTL_S); -+ writel(tmp, &ep->regs->ctl); -+ } -+ } -+} -+ -+/** -+ * Stall timer callback to poll S bit and set it again after -+ * CLEAR_FEATURE -+ * -+ * \param v timer callback argument -+ */ -+void udc_pollstall_timer_function(unsigned long v) -+{ -+ struct udc_ep *ep; -+ int halted = 0; -+ unsigned long iflags; -+ -+ spin_lock_irqsave (&udc_stall_spinlock, iflags); -+ /* only one IN and OUT endpoints are handled */ -+ /* IN poll stall */ -+ ep = &udc->ep [UDC_EPIN_IX]; -+ udc_handle_halt_state(ep); -+ if (ep->halted) -+ halted = 1; -+ /* OUT poll stall */ -+ ep = &udc->ep [UDC_EPOUT_IX]; -+ udc_handle_halt_state(ep); -+ if (ep->halted) -+ halted = 1; -+ -+ /* setup timer again when still halted */ -+ if (!stop_pollstall_timer && halted) { -+ udc_pollstall_timer.expires = jiffies + HZ -+ * UDC_POLLSTALL_TIMER_USECONDS -+ / (1000 * 1000); -+ add_timer(&udc_pollstall_timer); -+ } -+ spin_unlock_irqrestore (&udc_stall_spinlock, iflags); -+ -+ if (stop_pollstall_timer) -+ complete(&on_pollstall_exit); -+} -+#endif -+ -+#if defined(UDC_IPBUG_3950_WORKAROUND) \ -+ || defined(UDC_IPCASE_8000018724_WORKAROUND) \ -+ && !defined(UDC_HSB1) -+/** -+ * Called by OTG driver to notify us regarding an OTG event -+ * -+ * \param code notify code -+ */ -+void otg_notify(unsigned int code) { -+ VDBG("OTG notify code=%d\n", code); -+ switch (code) { -+ case OTG_GADGET_EVT_SVDROP: -+ /* disconnect event */ -+ usb_disconnect(udc); -+ break; -+ case OTG_GADGET_EVT_SVALID: -+ /* connect event */ -+ usb_connect(udc); -+ break; -+ case OTG_GADGET_REQ_WAKE: -+ /* remote wakeup event */ -+ udc_remote_wakeup(udc); -+ break; -+ } -+} -+#endif -+ -+/** -+ * Inits endpoint 0 so that SETUP packets are processed -+ * -+ * \param dev pointer to device struct -+ */ -+static void activate_control_endpoints (struct udc *dev) -+{ -+ u32 tmp; -+ -+ DBG("activate_control_endpoints\n"); -+ -+ /* flush fifo */ -+ tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_F); -+ writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl); -+ -+ /* set ep0 directions */ -+ dev->ep[UDC_EP0IN_IX].in = 1; -+ dev->ep[UDC_EP0OUT_IX].in = 0; -+ -+ /* set buffer size (tx fifo entries) of EP0_IN */ -+ tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->bufin_framenum); -+ if (dev->gadget.speed == USB_SPEED_FULL) -+ tmp = AMD_ADDBITS(tmp, UDC_FS_EPIN0_BUFF_SIZE, UDC_EPIN_BUFF_SIZE); -+ else if (dev->gadget.speed == USB_SPEED_HIGH) -+ tmp = AMD_ADDBITS(tmp, UDC_EPIN0_BUFF_SIZE, UDC_EPIN_BUFF_SIZE); -+ writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->bufin_framenum); -+ -+ /* set max packet size of EP0_IN */ -+ tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->bufout_maxpkt); -+ if (dev->gadget.speed == USB_SPEED_FULL) -+ tmp = AMD_ADDBITS(tmp, UDC_FS_EP0IN_MAX_PKT_SIZE, UDC_EP_MAX_PKT_SIZE); -+ else if (dev->gadget.speed == USB_SPEED_HIGH) -+ tmp = AMD_ADDBITS(tmp, UDC_EP0IN_MAX_PKT_SIZE, UDC_EP_MAX_PKT_SIZE); -+ writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->bufout_maxpkt); -+ -+ /* set max packet size of EP0_OUT */ -+ tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->bufout_maxpkt); -+ if (dev->gadget.speed == USB_SPEED_FULL) -+ tmp = AMD_ADDBITS(tmp, UDC_FS_EP0OUT_MAX_PKT_SIZE, UDC_EP_MAX_PKT_SIZE); -+ else if (dev->gadget.speed == USB_SPEED_HIGH) -+ tmp = AMD_ADDBITS(tmp, UDC_EP0OUT_MAX_PKT_SIZE, UDC_EP_MAX_PKT_SIZE); -+ writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->bufout_maxpkt); -+ -+ /* set max packet size of EP0 in UDC CSR */ -+ tmp = readl(&dev->csr->ne[0]); -+ if (dev->gadget.speed == USB_SPEED_FULL) -+ tmp = AMD_ADDBITS(tmp, UDC_FS_EP0OUT_MAX_PKT_SIZE, UDC_CSR_NE_MAX_PKT); -+ else if (dev->gadget.speed == USB_SPEED_HIGH) -+ tmp = AMD_ADDBITS(tmp, UDC_EP0OUT_MAX_PKT_SIZE, UDC_CSR_NE_MAX_PKT); -+ writel(tmp, &dev->csr->ne[0]); -+ -+ if (use_dma) { -+ dev->ep [UDC_EP0OUT_IX].td->status |= AMD_BIT(UDC_DMA_OUT_STS_L); -+ /* write dma desc address */ -+ writel(dev->ep [UDC_EP0OUT_IX].td_stp_dma, &dev->ep[UDC_EP0OUT_IX].regs->subptr); -+ writel(dev->ep [UDC_EP0OUT_IX].td_phys, &dev->ep[UDC_EP0OUT_IX].regs->desptr); -+#ifdef UDC_USE_TIMER -+ /* stop RDE timer */ -+ if (timer_pending(&udc_timer)) { -+ set_rde = 0; -+ mod_timer(&udc_timer, jiffies - 1); -+ } -+ /* stop pollstall timer */ -+ if (timer_pending(&udc_pollstall_timer)) { -+ mod_timer(&udc_pollstall_timer, jiffies - 1); -+ } -+#endif -+ /* enable DMA */ -+ tmp = readl(&dev->regs->ctl); -+ tmp |= AMD_BIT(UDC_DEVCTL_MODE) -+ | AMD_BIT(UDC_DEVCTL_RDE) -+ | AMD_BIT(UDC_DEVCTL_TDE); -+ if (use_dma_bufferfill_mode) { -+ tmp |= AMD_BIT(UDC_DEVCTL_BF); -+ } -+ else if (use_dma_ppb_du) { -+ tmp |= AMD_BIT(UDC_DEVCTL_DU); -+ } -+ writel(tmp, &dev->regs->ctl); -+ } -+ -+ /* clear NAK by writing CNAK for EP0IN */ -+ tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); -+ writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl); -+ dev->ep[UDC_EP0IN_IX].naking = 0; -+ UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX], UDC_EP0IN_IX); -+ -+ /* clear NAK by writing CNAK for EP0OUT */ -+ tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); -+ writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->ctl); -+ dev->ep[UDC_EP0OUT_IX].naking = 0; -+ UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX], UDC_EP0OUT_IX); -+} -+ -+/** -+ * \brief -+ * Make endpoint 0 ready for control traffic -+ * -+ * \param dev pointer to device struc -+ * \return 0 if success -+ */ -+static int setup_ep0(struct udc *dev) -+{ -+ activate_control_endpoints (dev); -+ /* enable ep0 interrupts */ -+ udc_enable_ep0_interrupts(dev); -+ /* enable device setup interrupts */ -+ udc_enable_dev_setup_interrupts(dev); -+ -+ return 0; -+} -+ -+/** -+ * \brief -+ * Called by gadget driver to register itself -+ * -+ * \param driver pointer to gadget driver struct -+ * \return 0 if success -+ */ -+int usb_gadget_register_driver (struct usb_gadget_driver *driver) -+{ -+ struct udc *dev = udc; -+ int retval; -+ u32 tmp; -+ -+ if (!driver || !driver->bind -+ || !driver->unbind -+ || !driver->setup -+ || driver->speed != USB_SPEED_HIGH) -+ return -EINVAL; -+ if (!dev) -+ return -ENODEV; -+ if (dev->driver) -+ return -EBUSY; -+ -+ driver->driver.bus = 0; -+ dev->driver = driver; -+ dev->gadget.dev.driver = &driver->driver; -+ -+#ifndef CONFIG_SOC_AU1200 -+ /*device_create_file (&dev->pdev->dev, &dev_attr_function); -+ device_create_file (&dev->pdev->dev, &dev_attr_queues);*/ -+#endif -+ -+#ifdef CONFIG_USB_OTG -+ dev->gadget.is_otg = 1; -+#endif -+ retval = driver->bind (&dev->gadget); -+ /* e.g. ether gadget needs driver_data on both ep0 endpoints */ -+ dev->ep[UDC_EP0OUT_IX].ep.driver_data = -+ dev->ep [UDC_EP0IN_IX].ep.driver_data; -+ -+ gadget_bind_count++; -+ if (retval) { -+ DBG( "binding to %s returning %d\n", -+ driver->driver.name, retval); -+ dev->driver = 0; -+ dev->gadget.dev.driver = 0; -+ return retval; -+ } -+ -+ /* if otg driver already registered */ -+ /* call otg bind() to mux udc to phy */ -+ if (dev->otg_transceiver) { -+ dev->otg_transceiver->set_peripheral( -+ dev->otg_transceiver, &dev->gadget); -+ /* clear SD */ -+ tmp = readl(&dev->regs->ctl); -+ tmp = tmp & AMD_CLEAR_BIT(UDC_DEVCTL_SD); -+ writel(tmp, &dev->regs->ctl); -+ } -+#ifndef UDC_IPBUG_3950_WORKAROUND -+ usb_connect(dev); -+#endif -+ -+ return 0; -+} -+EXPORT_SYMBOL (usb_gadget_register_driver); -+ -+/** -+ * Called by OTG driver to register itself -+ * -+ * -+ * \param get_transceiver function pointer to get OTG info -+ * \return 0 if success -+ */ -+int usb_gadget_register_otg (struct otg_transceiver * (*get_transceiver)(void)) -+{ -+ struct udc *dev = udc; -+ int retval; -+ u32 tmp; -+ -+ if (!get_transceiver) -+ return -EINVAL; -+ if (!dev) -+ return -ENODEV; -+ if (dev->otg_transceiver) -+ return -EBUSY; -+ -+ dev->otg_transceiver = get_transceiver (); -+ -+#if !defined(UDC_HSB1) -+ if (!(transceiver_to_otg(dev->otg_transceiver)->otg_priv)) -+ return -EINVAL; -+ dev->otg_driver = (struct usb_otg_gadget_extension *) -+ transceiver_to_otg(dev->otg_transceiver)->otg_priv; -+#endif -+ -+#ifdef UDC_IPBUG_3943_WORKAROUND -+ /* init registers here first with suspend bug */ -+ if (!otg_reg_count) { -+ startup_registers(dev); -+ otg_reg_count++; -+ } -+#endif -+ -+#ifdef UDC_IPBUG_3950_WORKAROUND -+ /* set notify function */ -+ dev->otg_driver->notify = otg_notify; -+#endif -+ /* if gadget driver already registered */ -+ /* call gadget bind() to switch to mux udc to phy */ -+ if (dev->driver) { -+ -+ /* otg driver bind() */ -+ retval = dev->otg_transceiver->set_peripheral( -+ dev->otg_transceiver, &dev->gadget); -+ if (retval) { -+ DBG( "error bind to uoc driver\n"); -+#if !defined(UDC_HSB1) -+ dev->otg_driver = NULL; -+#endif -+ dev->otg_transceiver = NULL; -+ return retval; -+ } -+ /* get ready for ep0 traffic */ -+ setup_ep0(dev); -+ -+ /* clear SD */ -+ tmp = readl(&dev->regs->ctl); -+ tmp = tmp & AMD_CLEAR_BIT(UDC_DEVCTL_SD); -+ writel(tmp, &dev->regs->ctl); -+ } -+ -+ INFO( "registered uoc driver\n"); -+ -+ return 0; -+} -+EXPORT_SYMBOL (usb_gadget_register_otg); -+ -+/** -+ * Called by OTG driver to unregister itself -+ * -+ * -+ * \return 0 if success -+ */ -+int usb_gadget_unregister_otg (void) -+{ -+ struct udc *dev = udc; -+ unsigned long flags; -+ u32 tmp; -+ -+ if (!dev) -+ return -ENODEV; -+ -+ spin_lock_irqsave (&dev->lock, flags); -+ -+ /* mask not needed interrupts */ -+ udc_mask_unused_interrupts(dev); -+ -+ spin_unlock_irqrestore (&dev->lock, flags); -+ -+ dev->otg_supported = 0; -+ if (dev->otg_transceiver) { -+ dev->otg_transceiver->set_peripheral(dev->otg_transceiver, NULL); -+ dev->otg_transceiver = NULL; -+ } -+#if !defined(UDC_HSB1) -+ if (dev->otg_driver) { -+#ifdef UDC_IPBUG_3950_WORKAROUND -+ dev->otg_driver->notify = NULL; -+#endif -+ dev->otg_driver = NULL; -+ } -+#endif -+ -+ /* set SD */ -+ tmp = readl(&dev->regs->ctl); -+ tmp |= AMD_BIT(UDC_DEVCTL_SD); -+ writel(tmp, &dev->regs->ctl); -+ -+ DBG( "unregistered uoc driver\n"); -+ return 0; -+} -+EXPORT_SYMBOL (usb_gadget_unregister_otg); -+ -+/** -+ * shutdown requests and disconnect from gadget -+ */ -+static void -+shutdown(struct udc *dev, struct usb_gadget_driver *driver) -+{ -+ int tmp; -+ -+ /* empty queues and init hardware */ -+ udc_basic_init(dev); -+ for (tmp = 0; tmp < UDC_EP_NUM; tmp++) { -+ empty_req_queue (&dev->ep [tmp]); -+ } -+ -+ if (dev->gadget.speed != USB_SPEED_UNKNOWN) { -+ spin_unlock (&dev->lock); -+ driver->disconnect (&dev->gadget); -+ spin_lock (&dev->lock); -+ } -+ /* init */ -+ udc_setup_endpoints (dev); -+} -+ -+/** -+ * Called by gadget driver to unregister itself -+ * -+ * \param driver pointer to gadget driver struct -+ * \return 0 if success -+ */ -+int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) -+{ -+ struct udc *dev = udc; -+ unsigned long iflags; -+ u32 tmp; -+ -+ if (!dev) -+ return -ENODEV; -+ if (!driver || driver != dev->driver) -+ return -EINVAL; -+ if (gadget_bind_count) { -+ spin_lock_irqsave (&dev->lock, iflags); -+ shutdown(dev, driver); -+ spin_unlock_irqrestore (&dev->lock, iflags); -+ } -+ -+ /* unbind from otg driver first */ -+ if (dev->otg_transceiver) { -+ dev->otg_transceiver->set_peripheral( -+ dev->otg_transceiver, NULL); -+ } -+ -+ if (gadget_bind_count) { -+ driver->unbind (&dev->gadget); -+ } -+ gadget_bind_count = 0; -+ dev->driver = 0; -+ -+ /* set SD */ -+ tmp = readl(&dev->regs->ctl); -+ tmp |= AMD_BIT(UDC_DEVCTL_SD); -+ writel(tmp, &dev->regs->ctl); -+ -+ -+ DBG( "%s: unregistered\n", driver->driver.name); -+ -+ return 0; -+} -+EXPORT_SYMBOL (usb_gadget_unregister_driver); -+ -+ -+#ifdef UDC_IPBUG_3958_WORKAROUND -+/** -+ * Clear pending NAK bits -+ * -+ * \param dev pointer to UDC device object -+ * \return 0 if success -+ */ -+static void udc_process_cnak_queue(struct udc* dev) -+{ -+ u32 tmp; -+ u32 reg; -+ /* check epin's */ -+ DBG("CNAK pending queue processing\n"); -+ for (tmp = 0; tmp < UDC_EPIN_NUM_USED; tmp++) { -+ if (cnak_pending & (1 << tmp)) { -+ DBG("CNAK pending for ep%d\n", tmp); -+ /* clear NAK by writing CNAK */ -+ reg = readl(&dev->ep[tmp].regs->ctl); -+ reg |= AMD_BIT(UDC_EPCTL_CNAK); -+ writel(reg, &dev->ep[tmp].regs->ctl); -+ dev->ep[tmp].naking = 0; -+ UDC_QUEUE_CNAK(&dev->ep[tmp], dev->ep[tmp].num); -+ } -+ } -+ /* ... and ep0out */ -+ if (cnak_pending & (1 << UDC_EP0OUT_IX)) { -+ DBG("CNAK pending for ep%d\n", UDC_EP0OUT_IX); -+ /* clear NAK by writing CNAK */ -+ reg = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl); -+ reg |= AMD_BIT(UDC_EPCTL_CNAK); -+ writel(reg, &dev->ep[UDC_EP0OUT_IX].regs->ctl); -+ dev->ep[UDC_EP0OUT_IX].naking = 0; -+ UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX], -+ dev->ep[UDC_EP0OUT_IX].num); -+ } -+} -+#endif -+ -+/** -+ * Enabling RX DMA after setup packet -+ * -+ * \param dev pointer to UDC device object -+ */ -+static inline void udc_ep0_set_rde(struct udc* dev) -+{ -+ if (use_dma) { -+#ifndef UDC_USE_TIMER -+ udc_set_rde(dev); -+#else -+ /* only enable RXDMA when no data endpoint enabled -+ or data is queued */ -+ if (!dev->data_ep_enabled || dev->data_ep_queued) { -+ udc_set_rde(dev); -+ } -+ else { -+ /* setup timer for enabling RDE (to not enable -+ RXFIFO DMA for data endpoints to early) */ -+ if (set_rde != 0 && !timer_pending(&udc_timer)) { -+ udc_timer.expires = jiffies + HZ/UDC_RDE_TIMER_DIV; -+ set_rde = 1; -+ if (!stop_timer) { -+ add_timer(&udc_timer); -+ } -+ } -+ } -+#endif -+ } -+} -+ -+ -+/** -+ * Interrupt handler for data OUT traffic -+ * -+ * \param dev pointer to UDC device object -+ * \param ep_ix endpoint index -+ * \return 0 if success -+ */ -+static inline int udc_data_out_isr(struct udc* dev, int ep_ix) -+{ -+ int ret_val = 0; -+ u32 tmp; -+ struct udc_ep *ep; -+ struct udc_request *req; -+ unsigned int count; -+ struct udc_data_dma *td = NULL; -+ unsigned dma_done; -+ -+ VDBG("ep%d irq\n", ep_ix); -+ ep = &dev->ep [ep_ix]; -+ -+ tmp = readl(&ep->regs->sts); -+ if (use_dma) { -+ /* BNA event ? */ -+ if (tmp & AMD_BIT(UDC_EPSTS_BNA)) { -+ ERR("BNA ep%dout occured - DESPTR = %lx \n", ep->num, (unsigned long) readl(&ep->regs->desptr)); -+ -+ /* clear BNA */ -+ writel(tmp | AMD_BIT(UDC_EPSTS_BNA), &ep->regs->sts); -+ return 1; -+ } -+ } -+ /* HE event ? */ -+ if (tmp & AMD_BIT(UDC_EPSTS_HE)) { -+ ERR("HE ep%dout occured\n", ep->num); -+ -+ /* clear HE */ -+ writel(tmp | AMD_BIT(UDC_EPSTS_HE), &ep->regs->sts); -+ return 1; -+ } -+ -+ if (!list_empty (&ep->queue)) { -+ -+ /* next request */ -+ req = list_entry (ep->queue.next, -+ struct udc_request, queue); -+ } -+ else -+ { -+ req = 0; -+#ifdef UDC_DEBUG -+ no_req++; -+#endif -+ udc_rxfifo_pending = 1; -+ } -+ VDBG("req = %lx\n", (unsigned long) req); -+ /* fifo mode ****************/ -+ if (!use_dma) { -+ -+ /* read fifo */ -+ if (req && udc_rxfifo_read(ep, req)) { -+ /* finish */ -+ complete_req (ep, req, 0); -+ /* next request */ -+ if (!list_empty (&ep->queue) && !ep->halted) { -+ req = list_entry (ep->queue.next, -+ struct udc_request, queue); -+ } -+ else -+ req = 0; -+ } -+ -+ } /* DMA ********************/ -+ else if (req) { -+ -+ /* check for DMA done */ -+ if (!use_dma_ppb) { -+ dma_done = AMD_GETBITS(req->td_data->status, UDC_DMA_OUT_STS_BS); -+ } /* packet per buffer mode - rx bytes */ -+ else { -+ td = udc_get_last_dma_desc(req); -+ dma_done = AMD_GETBITS(td->status, UDC_DMA_OUT_STS_BS); -+ } -+ if (dma_done == UDC_DMA_OUT_STS_BS_DMA_DONE) { -+ /* buffer fill mode - rx bytes */ -+ if (!use_dma_ppb) { -+ /* received number bytes */ -+ count = AMD_GETBITS(req->td_data->status, UDC_DMA_OUT_STS_RXBYTES); -+ VDBG("rx bytes=%lx\n", (unsigned long) count); -+ } /* packet per buffer mode - rx bytes */ -+ else { -+ VDBG("req->td_data=%lx\n", (unsigned long) req->td_data); -+ VDBG("last desc = %lx\n", (unsigned long) td); -+ /* received number bytes */ -+ if (use_dma_ppb_du) { -+ /* every desc. counts bytes */ -+ count = udc_get_ppbdu_rxbytes(req); -+ } -+ else { -+ /* last desc. counts bytes */ -+ count = AMD_GETBITS(td->status, UDC_DMA_OUT_STS_RXBYTES); -+ if (!count) { -+ /* on 64k packets the RXBYTES field is zero */ -+ if (req->req.length == UDC_DMA_MAXPACKET) -+ count = UDC_DMA_MAXPACKET; -+ } -+ } -+ VDBG("last desc rx bytes=%lx\n", (unsigned long) count); -+ } -+ -+ tmp = req->req.length - req->req.actual; -+ if (count > tmp) { -+ if ((tmp % ep->ep.maxpacket) != 0) { -+ ERR( "%s: received %d bytes, rx-buffer space = %d bytes => buffer overrun\n", -+ ep->ep.name, count, tmp); -+ req->req.status = -EOVERFLOW; -+ } -+ count = tmp; -+ } -+ req->req.actual += count; -+ -+ /* complete request */ -+ complete_req(ep, req, 0); -+ -+ /* next request */ -+ if (!list_empty (&ep->queue) && !ep->halted) { -+ req = list_entry(ep->queue.next, -+ struct udc_request, -+ queue); -+ -+ /* next dma */ -+ ret_val = prep_dma(ep, req); -+ if (ret_val != 0) -+ goto finished; -+ /* write desc pointer */ -+ writel(req->td_phys, &ep->regs->desptr); -+ -+ /* enable DMA */ -+ udc_set_rde(dev); -+ } -+ else { -+#ifdef UDC_DEBUG -+ no_pref_req++; -+ VDBG("OUT queue empty\n"); -+#endif -+ /* schedule timer for setting RDE if queue remains empty -+ * to allow ep0 packets pass through */ -+#ifdef UDC_USE_TIMER -+ if (set_rde != 0 && !timer_pending(&udc_timer)) { -+ udc_timer.expires = jiffies + HZ*UDC_RDE_TIMER_SECONDS; -+ set_rde = 1; -+ if (!stop_timer) { -+ add_timer(&udc_timer); -+ } -+ } -+#endif -+ if (ep->num != UDC_EP0OUT_IX) -+ dev->data_ep_queued = 0; -+ } -+ -+ } -+ else { -+ /* RX DMA must be reenabled for each desc in PPBDU mode */ -+ if (use_dma_ppb_du) { -+ udc_set_rde(dev); -+ } -+ } -+ -+ } -+ -+#ifdef UDC_IPBUG_3958_WORKAROUND -+ /* check pending CNAKS */ -+ if (cnak_pending) { -+ /* CNAk processing when rxfifo empty only */ -+ if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) { -+ udc_process_cnak_queue(dev); -+ } -+ } -+#endif -+ -+ /* clear OUT bits in ep status */ -+ writel(UDC_EPSTS_OUT_DATA_CLEAR, &ep->regs->sts); -+finished: -+ return ret_val; -+} -+ -+/** -+ * Interrupt handler for data IN traffic -+ * -+ * \param dev pointer to UDC device object -+ * \param ep_ix endpoint index -+ * \return 0 if success -+ */ -+static inline int udc_data_in_isr(struct udc* dev, int ep_ix) -+{ -+ int ret_val = 0; -+ u32 tmp; -+ u32 epsts; -+ struct udc_ep *ep; -+ struct udc_request *req; -+ struct udc_data_dma *td; -+ unsigned dma_done; -+ unsigned len; -+ -+ ep = &dev->ep[ep_ix]; -+ -+ epsts = readl(&ep->regs->sts); -+ if (use_dma) { -+ /* BNA ? */ -+ if (epsts & AMD_BIT(UDC_EPSTS_BNA)) { -+ ERR("BNA ep%din occured - DESPTR = %08lx \n", -+ ep->num, (unsigned long) readl(&ep->regs->desptr)); -+ -+ /* clear BNA */ -+ writel(epsts, &ep->regs->sts); -+ -+ return 1; -+ } -+ } -+ /* HE event ? */ -+ if (epsts & AMD_BIT(UDC_EPSTS_HE)) { -+ ERR("HE ep%dn occured - DESPTR = %08lx \n", -+ ep->num, (unsigned long) readl(&ep->regs->desptr)); -+ -+ /* clear HE */ -+ writel(epsts | AMD_BIT(UDC_EPSTS_HE), &ep->regs->sts); -+ return 1; -+ } -+ -+ /* DMA completion */ -+ if (epsts & AMD_BIT(UDC_EPSTS_TDC)) { -+ VDBG("TDC set- completion\n"); -+ if (!list_empty (&ep->queue)) { -+ req = list_entry (ep->queue.next, -+ struct udc_request, queue); -+ if (req) { -+ /* lengh bytes transfered */ -+ /* check dma done of last desc. in PPBDU mode */ -+ if (use_dma_ppb_du) { -+ td = udc_get_last_dma_desc(req); -+ if (td) { -+ dma_done = -+ AMD_GETBITS(td->status, UDC_DMA_IN_STS_BS); -+ /* don't care DMA done */ -+ /* if (dma_done == UDC_DMA_IN_STS_BS_DMA_DONE) */ -+ req->req.actual = req->req.length; -+ } -+ } -+ else { -+ /* assume all bytes transferred */ -+ /* TODO check error status */ -+ req->req.actual = req->req.length; -+ } -+ -+ if (req->req.actual == req->req.length) { -+#ifdef UDC_IPBUG_2253_WORKAROUND -+ /* stop NAKing after small packet DMA */ -+ if (ep->naking) { -+ /* clear NAK by writing CNAK */ -+ tmp = readl(&ep->regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); -+ writel(tmp, &ep->regs->ctl); -+ ep->naking = 0; -+ UDC_QUEUE_CNAK(ep, ep->num); -+ } -+#endif -+ /* complete req */ -+ complete_req(ep, req, 0); -+ req->dma_going = 0; -+#ifdef UDC_DISABLE_IRQ_IF_EMPTY_IN_QUEUE -+ /* further request available ? */ -+ if (list_empty (&ep->queue)) { -+ /* disable interrupt */ -+ tmp = readl(&dev->regs->ep_irqmsk); -+ tmp |= AMD_BIT(ep->num); -+ writel(tmp, &dev->regs->ep_irqmsk); -+ } -+#endif -+ -+ } -+ } -+ } -+ -+ } /* status reg has IN bit set and TDC not set (if TDC was handled, -+ IN must not be handled (UDC defect) ? */ -+ if ((epsts & AMD_BIT(UDC_EPSTS_IN)) && !(epsts & AMD_BIT(UDC_EPSTS_TDC))) { -+ if (!list_empty (&ep->queue)) -+ { -+ /* next request */ -+ req = list_entry (ep->queue.next, -+ struct udc_request, queue); -+ /* FIFO mode ********/ -+ if (!use_dma) { -+ /* write fifo */ -+ udc_txfifo_write(ep, &(req->req)); -+ len = req->req.length - req->req.actual; -+ if (len > ep->ep.maxpacket) -+ len = ep->ep.maxpacket; -+ req->req.actual += len; -+ if (req->req.actual == req->req.length -+ || (len != ep->ep.maxpacket)) { -+ /* && (!req->req.zero || len != ep->ep.maxpacket)) { */ -+ /* complete req */ -+ complete_req (ep, req, 0); -+ } -+ } /* DMA *****************/ -+ else if (req && !req->dma_going) { -+ VDBG("IN DMA : req=%lx req->td_data=%lx\n", -+ (unsigned long) req, (unsigned long) req->td_data); -+ if (req->td_data) { -+ -+ req->dma_going = 1; -+ -+ /* unset L bit of first desc. for chain */ -+ if (use_dma_ppb && req->req.length > ep->ep.maxpacket) { -+ req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L); -+ } -+ -+ /* write desc pointer */ -+ writel(req->td_phys, &ep->regs->desptr); -+ -+ wb_flush(); -+ /* set HOST READY */ -+ req->td_data->status -+ = AMD_ADDBITS(req->td_data->status, -+ UDC_DMA_IN_STS_BS_HOST_READY, -+ UDC_DMA_IN_STS_BS); -+ -+ wb_flush(); -+ -+#ifdef UDC_IPBUG_2253_WORKAROUND -+ /* NAK if small packet until TDC interrupt */ -+ if (req->req.length < UDC_SMALL_PACKET) { -+ /* set NAK */ -+ tmp = readl(&ep->regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_SNAK); -+ writel(tmp, &ep->regs->ctl); -+ ep->naking = 1; -+ wb_flush(); -+ } -+#endif -+ /* set poll demand bit */ -+ tmp = readl(&ep->regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_P); -+ writel(tmp, &ep->regs->ctl); -+ } -+ } -+ -+ } -+ } -+ /* clear status bits */ -+ writel(epsts, &ep->regs->sts); -+ -+ return ret_val; -+ -+} -+ -+/** -+ * Interrupt handler for Control OUT traffic -+ * -+ * \param dev pointer to UDC device object -+ * \return 0 if success -+ */ -+static inline int udc_control_out_isr(struct udc* dev) -+{ -+ int ret_val = 0; -+ u32 tmp; -+ int setup_supported; -+ u32 count; -+ int set = 0; -+ struct udc_ep *ep; -+ struct udc_ep *ep_tmp; -+ -+ ep = &dev->ep[UDC_EP0OUT_IX]; -+ -+ /* clear irq */ -+ writel(AMD_BIT(UDC_EPINT_OUT_EP0), &dev->regs->ep_irqsts); -+ -+ tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->sts); -+ /* check BNA and clear if set */ -+ if (tmp & AMD_BIT(UDC_EPSTS_BNA)) { -+ VDBG("BNA set\n"); -+ writel(AMD_BIT(UDC_EPSTS_BNA), &dev->ep[UDC_EP0OUT_IX].regs->sts); -+ } -+ -+ /* type of data: SETUP or DATA 0 bytes */ -+ tmp = AMD_GETBITS(tmp, UDC_EPSTS_OUT); -+ VDBG( "data_typ = %lx\n", (unsigned long) tmp); -+ /* setup data */ -+ if (tmp == UDC_EPSTS_OUT_SETUP) { -+ -+ ep->dev->stall_ep0in = 0; -+ dev->waiting_zlp_ack_ep0in = 0; -+ -+ /* set NAK for EP0_IN */ -+ tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_SNAK); -+ writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl); -+ dev->ep[UDC_EP0IN_IX].naking = 1; -+ /* get setup data */ -+ if (use_dma) { -+ -+ /* clear OUT bits in ep status */ -+ writel(UDC_EPSTS_OUT_SETUP_CLEAR, &dev->ep[UDC_EP0OUT_IX].regs->sts); -+ -+ setup_data.data[0] = dev->ep[UDC_EP0OUT_IX].td_stp->data12; -+ setup_data.data[1] = dev->ep[UDC_EP0OUT_IX].td_stp->data34; -+ /* set HOST READY */ -+ writel(UDC_DMA_STP_STS_BS_HOST_READY, -+ &dev->ep[UDC_EP0OUT_IX].td_stp->status); -+ } -+ else { -+ /* read fifo */ -+ udc_rxfifo_read_dwords(dev, setup_data.data, 2); -+ } -+ -+ /* determine direction of control data */ -+ if ((setup_data.request.bRequestType & USB_DIR_IN) != 0) { -+ dev->gadget.ep0 = &dev->ep [UDC_EP0IN_IX].ep; -+ /* enable RDE */ -+ udc_ep0_set_rde(dev); -+ set = 0; -+ } -+ else { -+ dev->gadget.ep0 = &dev->ep [UDC_EP0OUT_IX].ep; -+#ifdef UDC_USE_TIMER -+ set = 1; -+ dev->ep[UDC_EP0OUT_IX].naking = 1; -+ /* setup timer for enabling RDE (to not enable -+ RXFIFO DMA for data to early) */ -+ set_rde = 1; -+ if (!timer_pending(&udc_timer)) { -+ udc_timer.expires = jiffies + HZ/UDC_RDE_TIMER_DIV; -+ if (!stop_timer) { -+ add_timer(&udc_timer); -+ } -+ } -+#endif -+ } -+ /* mass storage reset must be processed here because -+ next packet may be a CLEAR_FEATURE HALT which would not -+ clear the stall bit when no STALL handshale was received before -+ (autostall can cause this) */ -+ if (setup_data.data[0] == UDC_MSCRES_DWORD0 && -+ setup_data.data[1] == UDC_MSCRES_DWORD1) { -+ DBG("MSC Reset\n"); -+ /* clear stall bits */ -+ /* only one IN and OUT endpoints are handled */ -+ ep_tmp = &udc->ep [UDC_EPIN_IX]; -+ udc_set_halt (&ep_tmp->ep, 0); -+ ep_tmp = &udc->ep [UDC_EPOUT_IX]; -+ udc_set_halt (&ep_tmp->ep, 0); -+ } -+ -+ /* call gadget with setup data received */ -+ spin_unlock (&dev->lock); -+ setup_supported = dev->driver->setup (&dev->gadget, -+ &setup_data.request); -+ spin_lock (&dev->lock); -+ -+ tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl); -+ /* ep0 in returns data (not zlp) on IN phase */ -+ if (setup_supported >= 0 && setup_supported < UDC_EP0IN_MAXPACKET) { -+ /* clear NAK by writing CNAK in EP0_IN */ -+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); -+ writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl); -+ dev->ep[UDC_EP0IN_IX].naking = 0; -+ UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX], UDC_EP0IN_IX); -+ } -+ else if (setup_supported < 0) { -+ /* if unsupported request then stall */ -+ tmp |= AMD_BIT(UDC_EPCTL_S); -+ writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl); -+ } -+ else -+ dev->waiting_zlp_ack_ep0in = 1; -+ -+ -+ /* clear NAK by writing CNAK in EP0_OUT */ -+ if (!set) { -+ tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); -+ writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->ctl); -+ dev->ep[UDC_EP0OUT_IX].naking = 0; -+ UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX], UDC_EP0OUT_IX); -+ } -+ -+ if (!use_dma) { -+ /* clear OUT bits in ep status */ -+ writel(UDC_EPSTS_OUT_SETUP_CLEAR, &dev->ep[UDC_EP0OUT_IX].regs->sts); -+ } -+ -+ } /* data packet 0 bytes */ -+ else if (tmp == UDC_EPSTS_OUT_DATA) { -+ /* clear OUT bits in ep status */ -+ writel(UDC_EPSTS_OUT_DATA_CLEAR, &dev->ep[UDC_EP0OUT_IX].regs->sts); -+ -+ /* get setup data: only 0 packet */ -+ if (use_dma) { -+ /* no req if 0 packet, just reactivate */ -+ if (list_empty (&dev->ep[UDC_EP0OUT_IX].queue)) { -+ VDBG("ZLP\n"); -+ -+ /* set HOST READY */ -+ dev->ep[UDC_EP0OUT_IX].td->status = -+ AMD_ADDBITS(dev->ep[UDC_EP0OUT_IX].td->status, -+ UDC_DMA_OUT_STS_BS_HOST_READY, -+ UDC_DMA_OUT_STS_BS); -+ /* enable RDE */ -+ udc_ep0_set_rde(dev); -+ } -+ else { -+ /* control write */ -+ udc_data_out_isr(dev, UDC_EP0OUT_IX); -+ /* re-program desc. pointer for possible ZLPs */ -+ writel(dev->ep [UDC_EP0OUT_IX].td_phys, -+ &dev->ep[UDC_EP0OUT_IX].regs->desptr); -+ /* enable RDE */ -+ udc_ep0_set_rde(dev); -+ } -+ } -+ else { -+ -+ /* received number bytes */ -+ count = readl(&dev->ep[UDC_EP0OUT_IX].regs->sts); -+ count = AMD_GETBITS(count, UDC_EPSTS_RX_PKT_SIZE); -+ /* out data for fifo mode not working */ -+ count = 0; -+ -+ /* 0 packet or real data ? */ -+ if (count != 0) { -+ udc_data_out_isr(dev, UDC_EP0OUT_IX); -+ } -+ else { -+ /* dummy read confirm */ -+ readl(&dev->ep[UDC_EP0OUT_IX].regs->confirm); -+ } -+ } -+ } -+ -+#ifdef UDC_IPBUG_3958_WORKAROUND -+ /* check pending CNAKS */ -+ if (cnak_pending) { -+ /* CNAk processing when rxfifo empty only */ -+ if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) { -+ udc_process_cnak_queue(dev); -+ } -+ } -+#endif -+ -+ return ret_val; -+} -+ -+/** -+ * Interrupt handler for Control IN traffic -+ * -+ * \param dev pointer to UDC device object -+ * \return 0 if success -+ */ -+static inline int udc_control_in_isr(struct udc* dev) -+{ -+ int ret_val = 0; -+ u32 tmp; -+ struct udc_ep *ep; -+ struct udc_request *req; -+ unsigned len; -+ -+ ep = &dev->ep [UDC_EP0IN_IX]; -+ -+ /* clear irq */ -+ writel(AMD_BIT(UDC_EPINT_IN_EP0), &dev->regs->ep_irqsts); -+ -+ tmp= readl(&dev->ep[UDC_EP0IN_IX].regs->sts); -+ /* DMA completion */ -+ if (tmp & AMD_BIT(UDC_EPSTS_TDC)) { -+ VDBG("isr: TDC clear \n"); -+#ifdef UDC_IPBUG_2253_WORKAROUND -+ /* stop NAKing after small packet DMA */ -+ if (ep->naking) { -+ /* clear NAK by writing CNAK */ -+ tmp = readl(&ep->regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); -+ writel(tmp, &ep->regs->ctl); -+ ep->naking = 0; -+ UDC_QUEUE_CNAK(ep, ep->num); -+ } -+#endif -+ /* clear TDC bit */ -+ writel(AMD_BIT(UDC_EPSTS_TDC),&dev->ep[UDC_EP0IN_IX].regs->sts); -+ } /* status reg has IN bit set ? */ -+ else if (tmp & AMD_BIT(UDC_EPSTS_IN)) { -+ if (ep->dma) { -+ /* clear IN bit */ -+ writel(AMD_BIT(UDC_EPSTS_IN),&dev->ep[UDC_EP0IN_IX].regs->sts); -+ } -+ if (dev->stall_ep0in) { -+ DBG("stall ep0in\n"); -+ /* halt ep0in */ -+ tmp = readl(&ep->regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_S); -+ writel(tmp, &ep->regs->ctl); -+ } -+ else { -+ if (!list_empty (&ep->queue)) -+ { -+ /* next request */ -+ req = list_entry (ep->queue.next, -+ struct udc_request, queue); -+ -+ if (ep->dma) { -+ /* write desc pointer */ -+ writel(req->td_phys, &ep->regs->desptr); -+ /* set HOST READY */ -+ req->td_data->status -+ = AMD_ADDBITS(req->td_data->status, -+ UDC_DMA_STP_STS_BS_HOST_READY, -+ UDC_DMA_STP_STS_BS); -+ wb_flush(); -+ -+#ifdef UDC_IPBUG_2253_WORKAROUND -+ /* NAK if small packet until TDC interrupt */ -+ if (req->req.length < UDC_SMALL_PACKET) { -+ /* set NAK */ -+ tmp = readl(&ep->regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_SNAK); -+ writel(tmp, &ep->regs->ctl); -+ ep->naking = 1; -+ wb_flush(); -+ } -+#endif -+ /* set poll demand bit */ -+ tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl); -+ tmp |= AMD_BIT(UDC_EPCTL_P); -+ writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl); -+ -+ /* all bytes will be transferred */ -+ req->req.actual = req->req.length; -+ -+ /* complete req */ -+ complete_req(ep, req, 0); -+ -+ } -+ else { -+ /* write fifo */ -+ udc_txfifo_write(ep, &(req->req)); -+ -+ /* lengh bytes transfered */ -+ len = req->req.length - req->req.actual; -+ if (len > ep->ep.maxpacket) -+ len = ep->ep.maxpacket; -+ -+ req->req.actual += len; -+ if (req->req.actual == req->req.length -+ || (len != ep->ep.maxpacket)) { -+ /* && (!req->req.zero || len != ep->ep.maxpacket)) { */ -+ /* complete req */ -+ complete_req(ep, req, 0); -+ } -+ } -+ -+ } -+ } -+ ep->halted = 0; -+ dev->stall_ep0in = 0; -+ if (!ep->dma) { -+ /* clear IN bit */ -+ writel(AMD_BIT(UDC_EPSTS_IN),&dev->ep[UDC_EP0IN_IX].regs->sts); -+ } -+ } -+ -+ return ret_val; -+} -+ -+ -+/** -+ * Interrupt handler for global device events -+ * -+ * \param dev pointer to UDC device object -+ * \param dev_irq device interrupt bit of DEVINT register -+ * \return 0 if success -+ */ -+static inline int udc_dev_isr(struct udc* dev, u32 dev_irq) -+{ -+ int ret_val = 0; -+ u32 tmp; -+ u32 cfg; -+ struct udc_ep *ep; -+ u16 i; -+ u8 udc_csr_epix; -+ -+ /* SET_CONFIG irq ? */ -+ if (dev_irq & AMD_BIT(UDC_DEVINT_SC)) { -+ -+ /* read config value */ -+ tmp = readl(&dev->regs->sts); -+ cfg = AMD_GETBITS(tmp, UDC_DEVSTS_CFG); -+#ifdef UDC_DEBUG -+ /* this is needed for debug only */ -+ if (cfg == dev->cur_config) { -+ same_cfg = 1; -+ } -+ else { -+ same_cfg = 0; -+ } -+ VDBG("same_cfg=%d\n", same_cfg); -+#endif -+ DBG("SET_CONFIG interrupt: config=%d\n", cfg); -+ dev->cur_config = cfg; -+ dev->set_cfg_not_acked = 1; -+ -+ /* make usb request for gadget driver */ -+ memset(&setup_data, 0 , sizeof(union udc_setup_data)); -+ setup_data.request.bRequest = USB_REQ_SET_CONFIGURATION; -+ setup_data.request.wValue = dev->cur_config; -+ -+ /* programm the NE registers */ -+ /* TODO - put this to extra function or use udc_setup_endpoints() or udc_enable() */ -+ for (i = 0; i < UDC_EP_NUM; i++) { -+ ep = &dev->ep[i]; -+ if (ep->in) { -+ -+ /* ep ix in UDC CSR register space */ -+ udc_csr_epix = ep->num; -+ -+ -+ } /* OUT ep */ -+ else { -+ /* ep ix in UDC CSR register space */ -+ udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS; -+ } -+ -+ tmp = readl(&dev->csr->ne[udc_csr_epix]); -+ /* ep cfg */ -+ tmp = AMD_ADDBITS(tmp, ep->dev->cur_config, UDC_CSR_NE_CFG); -+ /* write reg */ -+ writel(tmp, &dev->csr->ne[udc_csr_epix]); -+ -+ /* clear stall bits */ -+ ep->halted = 0; -+ tmp = readl(&ep->regs->ctl); -+ tmp = tmp & AMD_CLEAR_BIT(UDC_EPCTL_S); -+ writel(tmp, &ep->regs->ctl); -+ } -+ /* call gadget zero with setup data received */ -+ spin_unlock (&dev->lock); -+ tmp = dev->driver->setup (&dev->gadget, &setup_data.request); -+ spin_lock (&dev->lock); -+ -+ } /* SET_INTERFACE ? */ -+ if (dev_irq & AMD_BIT(UDC_DEVINT_SI)) { -+ dev->set_cfg_not_acked = 1; -+ /* read interface and alt setting values */ -+ tmp = readl(&dev->regs->sts); -+ dev->cur_alt = AMD_GETBITS(tmp, UDC_DEVSTS_ALT); -+ dev->cur_intf = AMD_GETBITS(tmp, UDC_DEVSTS_INTF); -+ -+ /* make usb request for gadget driver */ -+ memset(&setup_data, 0 , sizeof(union udc_setup_data)); -+ setup_data.request.bRequest = USB_REQ_SET_INTERFACE; -+ setup_data.request.bRequestType = USB_RECIP_INTERFACE; -+ setup_data.request.wValue = dev->cur_alt; -+ setup_data.request.wIndex = dev->cur_intf; -+ -+ DBG("SET_INTERFACE interrupt: alt=%d intf=%d\n", dev->cur_alt, dev->cur_intf); -+ -+ /* programm the NE registers */ -+ /* TODO - put this to extra function or use udc_setup_endpoints() or udc_enable() */ -+ for (i = 0; i < UDC_EP_NUM; i++) { -+ ep = &dev->ep[i]; -+ if (ep->in) { -+ -+ /* ep ix in UDC CSR register space */ -+ udc_csr_epix = ep->num; -+ -+ -+ } /* OUT ep */ -+ else { -+ /* ep ix in UDC CSR register space */ -+ udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS; -+ } -+ -+ /***** UDC CSR reg ****************************/ -+ /* set ep values */ -+ tmp = readl(&dev->csr->ne[udc_csr_epix]); -+ /* ep interface */ -+ tmp = AMD_ADDBITS(tmp, ep->dev->cur_intf, UDC_CSR_NE_INTF); -+ /* tmp = AMD_ADDBITS(tmp, 2, UDC_CSR_NE_INTF); */ -+ /* ep alt */ -+ tmp = AMD_ADDBITS(tmp, ep->dev->cur_alt, UDC_CSR_NE_ALT); -+ /* tmp = AMD_ADDBITS(tmp, 1, UDC_CSR_NE_ALT); */ -+ /* write reg */ -+ writel(tmp, &dev->csr->ne[udc_csr_epix]); -+ -+ /* clear stall bits */ -+ ep->halted = 0; -+ tmp = readl(&ep->regs->ctl); -+ tmp = tmp & AMD_CLEAR_BIT(UDC_EPCTL_S); -+ writel(tmp, &ep->regs->ctl); -+ } -+ -+ /* call gadget zero with setup data received */ -+ spin_unlock (&dev->lock); -+ tmp = dev->driver->setup (&dev->gadget, &setup_data.request); -+ spin_lock (&dev->lock); -+ -+ } /* USB reset */ -+ if (dev_irq & AMD_BIT(UDC_DEVINT_UR)) { -+ DBG("USB Reset interrupt\n"); -+ -+ /* allow soft reset when suspend occurs */ -+ soft_reset_occured = 0; -+ -+ dev->waiting_zlp_ack_ep0in = 0; -+ dev->set_cfg_not_acked = 0; -+ -+ /* mask not needed interrupts */ -+ udc_mask_unused_interrupts(dev); -+ -+ /* call gadget to reset configs etc. */ -+ spin_unlock(&dev->lock); -+ dev->driver->disconnect(&dev->gadget); -+ spin_lock(&dev->lock); -+ -+ /* disable ep0 to empty req queue */ -+ empty_req_queue (&dev->ep [UDC_EP0IN_IX]); -+ ep_init(dev->regs, -+ &dev->ep [UDC_EP0IN_IX]); -+ -+#ifdef UDC_IPBUG_3958_WORKAROUND_SOFT_RESET_ON_USBRESET -+ /* soft reset when rxfifo not empty */ -+ tmp = readl(&dev->regs->sts); -+ if (!(tmp & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) && -+ !soft_reset_after_usbreset_occured) { -+ udc_soft_reset(dev); -+ soft_reset_after_usbreset_occured++; -+ } -+#endif -+ -+ /* DMA reset to kill potential old DMA hw hang, */ -+ /* POLL bit is already reset by ep_init() through */ -+ /* disconnect() */ -+ UDC_DMARST(tmp,dev); -+ -+ /* put into initial config */ -+ udc_basic_init (dev); -+ -+ /* enable device setup interrupts */ -+ udc_enable_dev_setup_interrupts(dev); -+ -+ } /* USB suspend */ -+#ifndef UDC_IPBUG_3943_WORKAROUND -+ if (dev_irq & AMD_BIT(UDC_DEVINT_US)) { -+ DBG("USB Suspend interrupt\n"); -+ -+ } /* new speed ? */ -+#endif -+ if (dev_irq & AMD_BIT(UDC_DEVINT_ENUM)) { -+ DBG("ENUM interrupt\n"); -+#ifdef UDC_DEBUG -+ num_enums++; -+ DBG("%d enumerations !\n", num_enums); -+#endif -+ soft_reset_after_usbreset_occured = 0; -+ -+ /* disable ep0 to empty req queue */ -+ empty_req_queue (&dev->ep [UDC_EP0IN_IX]); -+ ep_init (dev->regs, -+ &dev->ep [UDC_EP0IN_IX]); -+ -+ /* link up all endpoints */ -+ udc_setup_endpoints (dev); -+ if (dev->gadget.speed == USB_SPEED_HIGH) { -+ INFO("Connect: Speed = HIGH_SPEED\n"); -+ } -+ else if (dev->gadget.speed == USB_SPEED_FULL) { -+ INFO("Connect: Speed = FULL_SPEED\n"); -+ } -+ -+ /* init ep 0 */ -+ activate_control_endpoints(dev); -+ -+ /* enable ep0 interrupts */ -+ udc_enable_ep0_interrupts(dev); -+ } -+#ifndef UDC_IPBUG_3950_WORKAROUND -+ /* session valid change interrupt */ -+ if (dev_irq & AMD_BIT(UDC_DEVINT_SVC)) { -+ DBG("USB SVC interrupt\n"); -+ -+ /* check that session is not valid to detect disconnect */ -+ tmp = readl(&dev->regs->sts); -+ if (!(tmp & AMD_BIT(UDC_DEVSTS_SESSVLD))) { -+ DBG("USB Disconnect (session valid low)\n"); -+ /* cleanup on disconnect */ -+ usb_disconnect(udc); -+ } -+ -+ } -+#endif -+ -+ return ret_val; -+} -+ -+/** -+ * Interrupt Service Routine, see Linux Kernel Doc for parameters -+ * -+ * \param irq irq number -+ * \param pdev pointer to device object -+ * \param ptregs don't used -+ */ -+static irqreturn_t udc_irq (int irq, void *pdev, struct pt_regs * ptregs) -+{ -+ struct udc *dev = pdev; -+ u32 reg; -+ u16 i; -+ u32 ep_irq; -+ -+ -+#ifdef UDC_IPBUG_3943_WORKAROUND -+ /* If UDC is suspended, then don't touch any register, otherwise -+ system hangs in endless retry => possibly hang !!! */ -+ if (dev->otg_driver && dev->otg_driver->query) { -+ if (dev->otg_driver->query(0) & OTG_FLAGS_UDC_SUSP) { -+ return IRQ_HANDLED; -+ } -+ } -+ else -+ return IRQ_HANDLED; -+#endif -+ -+ if (dev->sys_suspended) -+ return IRQ_HANDLED; -+ -+ spin_lock (&dev->lock); -+ -+ -+ /* check for ep irq */ -+ reg = readl(&dev->regs->ep_irqsts); -+ if (reg) -+ { -+ /* EP0 OUT */ -+ if (reg & AMD_BIT(UDC_EPINT_OUT_EP0)) -+ { -+ udc_control_out_isr(dev); -+ } /* EP0 IN */ -+ if (reg & AMD_BIT(UDC_EPINT_IN_EP0)) { -+ udc_control_in_isr(dev); -+ -+ } -+ -+ /* data endpoint */ -+ /* iterate ep's */ -+ for (i = 1; i < UDC_EP_NUM; i++) { -+ ep_irq = 1 << i; -+ /* irq for out ep ? */ -+ if ((reg & ep_irq) && i > UDC_EPIN_NUM) { -+ /* clear irq */ -+ writel(ep_irq, &dev->regs->ep_irqsts); -+ udc_data_out_isr(dev,i); -+ } /* irq for in ep ? */ -+ if ((reg & ep_irq) && i < UDC_EPIN_NUM && i > 0) { -+ /* clear irq */ -+ writel(ep_irq, &dev->regs->ep_irqsts); -+ udc_data_in_isr(dev,i); -+ } -+ -+ } -+ -+ } -+ -+ -+ /* check for dev irq */ -+ reg = readl(&dev->regs->irqsts); -+ if (reg) { -+ /* clear irq */ -+ writel(reg, &dev->regs->irqsts); -+ udc_dev_isr(dev, reg); -+ } -+ -+ -+ spin_unlock (&dev->lock); -+ return IRQ_HANDLED; -+} -+ -+/** -+ * Tears down device -+ * -+ * \param pdev pointer to device struct -+ */ -+static void gadget_release (struct device *pdev) -+{ -+ struct au1200udc *dev = dev_get_drvdata(pdev); -+ kfree (dev); -+} -+ -+/** -+ * Cleanup on device remove -+ * -+ * \param dev pointer to udc struct -+ */ -+static void udc_remove(struct udc* dev) -+{ -+#ifdef CONFIG_SOC_AU1200 -+ { -+ u32 tmp; -+ /* disable UDC memory, DMA and clock */ -+ tmp = readl((u32*) (USB_MSR_BASE + USB_MSR_MCFG)); -+ tmp &= AMD_CLEAR_BIT(USBMSRMCFG_DMEMEN) -+ & AMD_CLEAR_BIT(USBMSRMCFG_DBMEN) -+ & AMD_CLEAR_BIT(USBMSRMCFG_UDCCLKEN); -+ writel(tmp, USB_MSR_BASE + USB_MSR_MCFG); -+ } -+#endif -+ -+#if defined(CONFIG_SOC_AU1200) -+ /* done by gadget.dev.release() in kernel 2.6.x -+ * TMP26: device registration currently disabled for Au1200 */ -+ kfree (dev); -+#endif -+#ifdef UDC_USE_TIMER -+ /* remove timer */ -+ stop_timer++; -+ if (timer_pending(&udc_timer)) -+ wait_for_completion(&on_exit); -+ if (udc_timer.data) -+ del_timer_sync(&udc_timer); -+ /* remove pollstall timer */ -+ stop_pollstall_timer++; -+ if (timer_pending(&udc_pollstall_timer)) -+ wait_for_completion(&on_pollstall_exit); -+ if (udc_pollstall_timer.data) -+ del_timer_sync(&udc_pollstall_timer); -+#endif -+ udc = 0; -+} -+ -+#if defined(CONFIG_SOC_AU1200) -+/** -+ * Reset all context -+ * -+ * \param pdev pointer to device struct -+ */ -+static void udc_drv_remove (struct device *_dev) -+{ -+ struct platform_device *pdev = to_platform_device(_dev); -+ struct udc *dev = dev_get_drvdata (_dev); -+ -+#ifdef UDC_DEBUG -+ /* debug */ -+ print_misc(dev); -+#endif -+ /* gadget driver registered ? */ -+ if (dev->driver) { -+ WARN( "unregistering %s on driver remove\n", dev->driver->driver.name); -+ usb_gadget_unregister_driver (dev->driver); -+ } -+ /* otg driver registered ? */ -+ if (dev->otg_transceiver) { -+ /* should have been done already by driver model core */ -+ WARN( "uoc driver is still registered\n"); -+ } -+ /* dma pool cleanup */ -+ if (dev->data_requests) { -+ dma_pool_destroy (dev->data_requests); -+ } -+ if (dev->stp_requests) { -+ /* cleanup DMA desc's for ep0in */ -+ dma_pool_free (dev->stp_requests, -+ dev->ep [UDC_EP0OUT_IX].td_stp, -+ dev->ep [UDC_EP0OUT_IX].td_stp_dma); -+ dma_pool_free (dev->stp_requests, -+ dev->ep [UDC_EP0OUT_IX].td, -+ dev->ep [UDC_EP0OUT_IX].td_phys); -+ -+ dma_pool_destroy (dev->stp_requests); -+ } -+ -+ /* init controller by soft reset */ -+ writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg); -+ -+ if (dev->irq_registered) -+ free_irq (pdev->resource[1].start, dev); -+ if (dev->regs) -+ iounmap (dev->regs); -+ if (dev->mem_region) -+ release_mem_region (pdev->resource[0].start, -+ pdev->resource[0].end + 1 -+ - pdev->resource[0].start); -+ -+ device_unregister (&dev->gadget.dev); -+ /* device_remove_file (&pdev->dev, &dev_attr_registers); */ -+ dev_set_drvdata (_dev, 0); -+ -+ udc_remove(dev); -+} -+#endif -+ -+#if !defined(CONFIG_SOC_AU1200) -+/** -+ * Reset all pci context -+ * -+ * \param pdev pointer to pci device struct -+ */ -+static void udc_pci_remove (struct pci_dev *pdev) -+{ -+ struct udc *dev; -+ -+ dev = pci_get_drvdata(pdev); -+#ifdef UDC_DEBUG -+ /* debug */ -+ print_misc(dev); -+#endif -+ /* gadget driver registered ? */ -+ if (dev->driver) { -+ WARN( "unregistering %s on pci remove\n", dev->driver->driver.name); -+ usb_gadget_unregister_driver (dev->driver); -+ } -+ /* otg driver registered ? */ -+ if (dev->otg_transceiver) { -+ /* should have been done already by driver model core */ -+ WARN( "uoc driver is still registered\n"); -+ } -+ /* dma pool cleanup */ -+ if (dev->data_requests) { -+ dma_pool_destroy (dev->data_requests); -+ } -+ if (dev->stp_requests) { -+ /* cleanup DMA desc's for ep0in */ -+ dma_pool_free (dev->stp_requests, -+ dev->ep [UDC_EP0OUT_IX].td_stp, -+ dev->ep [UDC_EP0OUT_IX].td_stp_dma); -+ dma_pool_free (dev->stp_requests, -+ dev->ep [UDC_EP0OUT_IX].td, -+ dev->ep [UDC_EP0OUT_IX].td_phys); -+ -+ dma_pool_destroy (dev->stp_requests); -+ } -+ -+ /* init controller by soft reset */ -+ writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg); -+ if (dev->irq_registered) -+ free_irq (pdev->irq, dev); -+ if (dev->regs) -+ iounmap (dev->regs); -+ if (dev->mem_region) -+ release_mem_region (pci_resource_start (pdev, 0), -+ pci_resource_len (pdev, 0)); -+#ifndef USE_AU1200_PCI_DUMMY -+ if (dev->active) -+ pci_disable_device (pdev); -+#endif -+ -+ /* device file system not working for Au1200 */ -+ device_unregister (&dev->gadget.dev); -+ /* device_remove_file (&pdev->dev, &dev_attr_registers); */ -+ pci_set_drvdata (pdev,0); -+ -+ udc_remove(dev); -+} -+#endif -+ -+/** -+ * create dma pools on init -+ * -+ * \param dev pointer to udc device struct -+ * \return 0 if success -+ */ -+__init static int init_dma_pools(struct udc* dev) -+{ -+ struct udc_stp_dma *td_stp; -+ struct udc_data_dma *td_data; -+ int retval; -+ -+ /* consistent DMA mode setting ? */ -+ if (use_dma_ppb) { -+ use_dma_bufferfill_mode = 0; -+ } -+ else { -+ use_dma_ppb_du = 0; -+ use_dma_bufferfill_mode = 1; -+ } -+ -+ /* DMA setup */ -+ dev->data_requests = dma_pool_create ("data_requests", NULL, -+ sizeof (struct udc_data_dma), -+ UDC_PCIPOOL_ALIGN, -+ UDC_PCIPOOL_CROSS); -+ if (!dev->data_requests) { -+ DBG( "can't get request data pool\n"); -+ retval = -ENOMEM; -+ goto finished; -+ } -+ -+ /* EP0 in dma regs = dev control regs */ -+ dev->ep[UDC_EP0IN_IX].dma = &dev->regs->ctl; -+ -+ /* dma desc for setup data */ -+ dev->stp_requests = dma_pool_create ("setup requests", NULL, -+ sizeof (struct udc_stp_dma), -+ UDC_PCIPOOL_ALIGN, -+ UDC_PCIPOOL_CROSS); -+ if (!dev->stp_requests) { -+ DBG( "can't get stp request pool\n"); -+ retval = -ENOMEM; -+ goto finished; -+ } -+ /* setup */ -+ td_stp = dma_pool_alloc (dev->stp_requests, UDC_PCIPOOL_GFP_STP, -+ &dev->ep [UDC_EP0OUT_IX].td_stp_dma); -+ if (td_stp == NULL){ -+ retval = -ENOMEM; -+ goto finished; -+ } -+ dev->ep [UDC_EP0OUT_IX].td_stp = td_stp; -+ /* data: 0 packets !? */ -+ td_data = dma_pool_alloc (dev->stp_requests, UDC_PCIPOOL_GFP_STP, -+ &dev->ep [UDC_EP0OUT_IX].td_phys); -+ if (td_data == NULL){ -+ retval = -ENOMEM; -+ goto finished; -+ } -+ dev->ep [UDC_EP0OUT_IX].td = td_data; -+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND -+ /* point to itself */ -+ dev->ep [UDC_EP0OUT_IX].td->next = dev->ep [UDC_EP0OUT_IX].td_phys; -+#endif -+ return 0; -+ -+finished: -+ return retval; -+} -+ -+#if defined(CONFIG_SOC_AU1200) -+/** -+ * Called by kernel init device context -+ * -+ * \param dev pointer to device struct -+ * \return 0 if success -+ */ -+static int udc_drv_probe (struct device* _dev) -+{ -+ char tmp[8]; -+ struct udc *dev; -+ struct platform_device *pdev = to_platform_device(_dev); -+ u32 resource; -+ u32 len; -+ u32 irq; -+ int retval = 0; -+#ifdef CONFIG_SOC_AU1200 -+ u32 reg; -+ -+ /* basic init */ -+ reg = readl((u32*) (USB_MSR_BASE + USB_MSR_MCFG)); -+ if (reg == 0) { -+ /* default value */ -+ reg = USBMSRMCFG_DEFAULT; -+ writel(reg, USB_MSR_BASE + USB_MSR_MCFG); -+ readl((u32*) USB_MSR_BASE + USB_MSR_MCFG); -+ udelay(1000); -+ } -+ /* enable UDC memory, DMA, clock, cacheable memory, -+ * read combining and prefetch enable */ -+ reg |= AMD_BIT(USBMSRMCFG_DMEMEN) | AMD_BIT(USBMSRMCFG_DBMEN) -+ | AMD_BIT(USBMSRMCFG_UDCCLKEN) -+ | AMD_BIT(USBMSRMCFG_PHYPLLEN) -+#ifdef CONFIG_DMA_COHERENT -+ | AMD_BIT(USBMSRMCFG_UCAM) -+#endif -+ | AMD_BIT(USBMSRMCFG_RDCOMB) -+ | AMD_BIT(USBMSRMCFG_PFEN); -+ writel(reg, USB_MSR_BASE + USB_MSR_MCFG); -+#endif -+ -+ /* one udc only */ -+ if (udc) { -+ WARN("already probed: %04x/%04x\n", UDC_PCI_VENID, UDC_PCI_DEVID); -+ return -EBUSY; -+ } -+ -+ /* init */ -+ dev = kmalloc (sizeof (struct udc), SLAB_KERNEL); -+ if (!dev) { -+ retval = -ENOMEM; -+ goto finished; -+ } -+ memset (dev, 0, sizeof(struct udc)); -+ -+ dev->pdev = _dev; -+ -+ /* check platform resources */ -+ if (pdev->resource[0].flags != IORESOURCE_MEM) { -+ ERR ("resource[0] must be IORESOURCE_MEM\n"); -+ retval = -ENOMEM; -+ goto finished; -+ } -+ resource = pdev->resource[0].start; -+ len = pdev->resource[0].end + 1 - pdev->resource[0].start; -+ if (pdev->resource[1].flags != IORESOURCE_IRQ) { -+ ERR ("resource[1] must be IORESOURCE_IRQ\n"); -+ retval = -ENOMEM; -+ goto finished; -+ } -+ irq = pdev->resource[1].start; -+ -+ /* platform device resource allocation */ -+ /* mem */ -+ if (!request_mem_region (resource, len, name)) { -+ ERR ("controller already in use\n"); -+ retval = -EBUSY; -+ goto finished; -+ } -+ dev->mem_region = 1; -+ -+ dev->virt_addr = ioremap_nocache(resource, len); -+ if (dev->virt_addr == NULL) { -+ DBG( "start address cannot be mapped\n"); -+ retval = -EFAULT; -+ goto finished; -+ } -+ -+ /* irq */ -+ if (!irq) { -+ ERR( "irq not set\n"); -+ retval = -ENODEV; -+ goto finished; -+ } -+ snprintf (tmp, sizeof tmp, "%d", irq); -+ if (request_irq (irq, udc_irq, SA_SHIRQ, name, dev) != 0) { -+ ERR( "error on request_irq() with %s\n", tmp); -+ retval = -EBUSY; -+ goto finished; -+ } -+ dev->irq_registered = 1; -+ -+ dev_set_drvdata (_dev, dev); -+ -+ /* chip revision */ -+ dev->chiprev = 0; -+ -+ /* chip rev for Au1200 */ -+ dev->chiprev = (u16) read_c0_prid() & 0xff; -+ -+ /* init dma pools */ -+ if (use_dma) { -+ retval = init_dma_pools(dev); -+ if (retval != 0) -+ goto finished; -+ } -+ -+ dev->phys_addr = resource; -+ dev->irq = irq; -+ dev->gadget.dev.parent = _dev; -+ dev->gadget.dev.dma_mask = _dev->dma_mask; -+ /* general probing */ -+ if (udc_probe(dev) != 0) -+ goto finished; -+ return retval; -+ -+finished: -+ if (dev) -+ udc_drv_remove (_dev); -+ return retval; -+} -+#endif -+ -+#if !defined(CONFIG_SOC_AU1200) -+/** -+ * Called by pci bus driver to init pci context -+ * -+ * \param pdev pointer to pci device struct -+ * \param id pointer to pci device id -+ * \return 0 if success -+ */ -+static int udc_pci_probe (struct pci_dev *pdev, const struct pci_device_id *id) -+{ -+ char tmp[8]; -+ struct udc *dev; -+ unsigned long resource; -+ unsigned long len; -+ int retval = 0;; -+ -+ VDBG("udc_pci_probe()\n"); -+ -+#ifdef CONFIG_SOC_AU1200 -+ { -+ u32 tmp; -+ /* -+ * Fill in the dummy pci_dev -+ */ -+ memset(pdev, 0, sizeof(struct pci_dev)); -+ pdev->resource[0].name = "UDC Registers"; -+ pdev->resource[0].start = USB_UDC_BASE; -+ pdev->resource[0].end = USB_UDC_BASE + USB_UDC_LEN - 1; -+ pdev->resource[0].flags = 0; -+ pdev->irq = AU1200_USB_INT; -+ -+ tmp = readl((u32*) (USB_MSR_BASE + USB_MSR_MCFG)); -+ if (tmp == 0) { -+ /* default value */ -+ tmp = USBMSRMCFG_DEFAULT; -+ writel(tmp, USB_MSR_BASE + USB_MSR_MCFG); -+ readl((u32*) USB_MSR_BASE + USB_MSR_MCFG); -+ udelay(1000); -+ } -+ /* enable UDC memory, DMA, clock, cacheable memory, -+ * read combining and prefetch enable */ -+ tmp |= AMD_BIT(USBMSRMCFG_DMEMEN) | AMD_BIT(USBMSRMCFG_DBMEN) -+ | AMD_BIT(USBMSRMCFG_UDCCLKEN) -+ | AMD_BIT(USBMSRMCFG_PHYPLLEN) -+#ifdef CONFIG_DMA_COHERENT -+ | AMD_BIT(USBMSRMCFG_UCAM) -+#endif -+ | AMD_BIT(USBMSRMCFG_RDCOMB) -+ | AMD_BIT(USBMSRMCFG_PFEN); -+ writel(tmp, USB_MSR_BASE + USB_MSR_MCFG); -+ } -+#endif -+ /* one udc only */ -+ if (udc) { -+ WARN("already probed: %04x/%04x\n", UDC_PCI_VENID, UDC_PCI_DEVID); -+ return -EBUSY; -+ } -+ -+ /* init */ -+ dev = kmalloc (sizeof (struct udc), SLAB_KERNEL); -+ if (!dev) { -+ retval = -ENOMEM; -+ goto finished; -+ } -+ memset (dev, 0, sizeof(struct udc)); -+ -+ /* pci setup */ -+#ifndef USE_AU1200_PCI_DUMMY -+ if (pci_enable_device (pdev) < 0) { -+ retval = -ENODEV; -+ goto finished; -+ } -+#endif -+ dev->active = 1; -+ -+ /* PCI resource allocation */ -+ resource = pci_resource_start(pdev, 0); -+ len = pci_resource_len (pdev, 0); -+ -+ if (!request_mem_region (resource, len, name)) { -+ DBG( "pci device used already\n"); -+ retval = -EBUSY; -+ goto finished; -+ } -+ dev->mem_region = 1; -+ -+ dev->virt_addr = ioremap_nocache(resource, len); -+ if (dev->virt_addr == NULL) { -+ DBG( "start address cannot be mapped\n"); -+ retval = -EFAULT; -+ goto finished; -+ } -+ -+ if (!pdev->irq) { -+ ERR( "pdev->irq not set\n"); -+ retval = -ENODEV; -+ goto finished; -+ } -+ -+ snprintf (tmp, sizeof tmp, "%d", pdev->irq); -+ -+ if (request_irq (pdev->irq, udc_irq, SA_SHIRQ, name, dev) != 0) { -+ ERR( "error on request_irq() with %s\n", tmp); -+ retval = -EBUSY; -+ goto finished; -+ } -+ dev->irq_registered = 1; -+ -+ pci_set_drvdata (pdev, dev); -+ -+ /* chip revision */ -+ dev->chiprev = 0; -+ -+#ifndef CONFIG_SOC_AU1200 -+ pci_set_master (pdev); -+#ifdef HAVE_PCI_SET_MWI -+ pci_set_mwi (pdev); -+#endif -+ /* chip rev for Hs AU1200 */ -+ pci_read_config_byte(pdev, PCI_REVISION_ID, (u8*) &dev->chiprev); -+#else -+ /* chip rev for Au1200 */ -+ dev->chiprev = (u16) read_c0_prid() & 0xff; -+#endif -+ /* init dma pools */ -+ if (use_dma) { -+ retval = init_dma_pools(dev); -+ if (retval != 0) -+ goto finished; -+ } -+ -+ dev->phys_addr = resource; -+ dev->irq = pdev->irq; -+ dev->pdev = pdev; -+ dev->gadget.dev.parent = &pdev->dev; -+ dev->gadget.dev.dma_mask = pdev->dev.dma_mask; -+ -+ /* general probing */ -+ if (udc_probe(dev) != 0) -+ goto finished; -+ return retval; -+ -+finished: -+ if (dev) -+ udc_pci_remove (pdev); -+ return retval; -+} -+#endif -+ -+/** -+ * general probe -+ * -+ * \param dev pointer to udc device struct -+ * \return 0 if success -+ */ -+__init int udc_probe(struct udc* dev) -+{ -+ char tmp[128]; -+ u32 reg; -+ int retval; -+ -+ /* mark timer as not initialized */ -+ udc_timer.data = 0; -+ udc_pollstall_timer.data = 0; -+ -+ /* device struct setup */ -+ spin_lock_init(&dev->lock); -+ spin_lock_init(&udc_irq_spinlock); -+ spin_lock_init(&udc_stall_spinlock); -+ dev->gadget.ops = &udc_ops; -+ -+ strcpy(dev->gadget.dev.bus_id, "gadget"); -+ dev->gadget.dev.release = gadget_release; -+ dev->gadget.name = name; -+ dev->gadget.is_dualspeed = 1; -+ -+ /* udc csr registers base */ -+ dev->csr = (struct udc_csrs*) (dev->virt_addr + UDC_CSR_ADDR); -+ /* dev registers base */ -+ dev->regs = (struct udc_regs *) (dev->virt_addr + UDC_DEVCFG_ADDR); -+ /* ep registers base */ -+ dev->ep_regs = (struct udc_ep_regs *) (dev->virt_addr + UDC_EPREGS_ADDR); -+ /* fifo's base */ -+ dev->rxfifo = (u32*) (dev->virt_addr + UDC_RXFIFO_ADDR); -+ dev->txfifo = (u32*) (dev->virt_addr + UDC_TXFIFO_ADDR); -+ -+ /* init registers, interrupts, ... */ -+#ifndef UDC_IPBUG_3943_WORKAROUND -+ startup_registers(dev); -+#else -+ { -+ u32 tmp; -+ -+ /* TODO put this to extra function, -+ * this all is extracted from usb_init() and -+ * udc_basic_init() but without register access */ -+ dev->gadget.ep0 = &dev->ep [UDC_EP0IN_IX].ep; -+ dev->ep [UDC_EP0IN_IX].halted = 0; -+ INIT_LIST_HEAD (&dev->gadget.ep0->ep_list); -+ dev->gadget.speed = USB_SPEED_HIGH; -+ make_ep_lists(dev); -+ /* basic endpoint init */ -+ for (tmp = 0; tmp < UDC_EP_NUM; tmp++) { -+ struct udc_ep *ep = &dev->ep[tmp]; -+ -+ ep->ep.name = ep_string[tmp]; -+ ep->dev = dev; -+ ep->num = tmp; -+ /* txfifo size is calculated at enable time */ -+ ep->txfifo = dev->txfifo; -+ -+ /* fifo size */ -+ if (tmp < UDC_EPIN_NUM) { -+ ep->fifo_depth = UDC_TXFIFO_SIZE; -+ ep->in = 1; -+ } -+ else { -+ ep->fifo_depth = UDC_RXFIFO_SIZE; -+ ep->in = 0; -+ -+ } -+ -+ ep->regs = &dev->ep_regs [tmp]; -+ if (!ep->desc) { -+ ep->desc = 0; -+ INIT_LIST_HEAD (&ep->queue); -+ -+ ep->ep.maxpacket = ~0; -+ ep->ep.ops = &udc_ep_ops; -+ } -+ if (use_dma) { -+ /* ep->dma is not really used, just to indicate that */ -+ /* DMA is active */ -+ /* dma regs = dev control regs */ -+ ep->dma = (u32*) &dev->regs->ctl; -+ } -+ } -+ dev->ep [UDC_EP0IN_IX].ep.maxpacket = UDC_EP0IN_MAX_PKT_SIZE; -+ dev->ep [UDC_EP0OUT_IX].ep.maxpacket = UDC_EP0OUT_MAX_PKT_SIZE; -+ } -+#endif -+ -+ -+ INFO( "%s\n", mod_desc); -+ -+ snprintf (tmp, sizeof tmp, "%d", dev->irq); -+#ifdef CONFIG_SOC_AU1200 -+ INFO( "irq %s, mem %08lx, chip rev %02x (Au1200 %s)\n", -+ tmp, dev->phys_addr, dev->chiprev, (dev->chiprev == 0) ? "AB" : "AC"); -+ strcpy(tmp, UDC_DRIVER_VERSION_STRING); -+#ifdef CONFIG_DMA_COHERENT -+ /* coherent DMA not possible with AB silicon */ -+ if (dev->chiprev == UDC_AUAB_REV) { -+ ERR("Your chip revision is %s, it must be at least %s to use coherent DMA. \nPlease change DMA_COHERENT to DMA_NONCOHERENT in arch/mips/Kconfig and re-compile .\n", -+ "AB", "AC"); -+ retval = -ENODEV; -+ goto finished; -+ } -+#endif -+ -+#ifdef UDC_AUA1 -+ if (dev->chiprev < UDC_AUA1) { -+ ERR("Your chip revision is %s, it must be at least %s\n", -+ "AB", "AC"); -+ retval = -ENODEV; -+ goto finished; -+ } -+ INFO("driver version: %s (for Au1200 AC)\n", tmp); -+#else -+ INFO("driver version: %s (for Au1200 AB)\n", tmp); -+#endif -+#ifdef CONFIG_DMA_COHERENT -+ INFO("Compiled for coherent memory.\n"); -+#endif -+#ifdef CONFIG_DMA_NONCOHERENT -+ INFO("Compiled for non-coherent memory.\n"); -+#endif -+#else -+ INFO("irq %s, pci mem %08lx, chip rev %02x (Geode5536 %s)\n", -+ tmp, dev->phys_addr, dev->chiprev, (dev->chiprev == UDC_HSA0_REV) ? "A0" : "B1"); -+ strcpy(tmp, UDC_DRIVER_VERSION_STRING); -+#ifdef UDC_HSB1 -+ if (dev->chiprev == UDC_HSA0_REV) { -+ ERR("Your chip revision is %s, it must be at least %s\n", -+ "A0", "B1"); -+ retval = -ENODEV; -+ goto finished; -+ } -+ INFO("driver version: %s (for Geode5536 B1)\n", tmp); -+#else -+ INFO("driver version: %s (for Geode5536 A0)\n", tmp); -+#endif -+#endif -+ udc = dev; -+ -+ device_register (&dev->gadget.dev); -+ /* device_create_file (&pdev->dev, &dev_attr_registers); */ -+ -+#ifdef UDC_USE_TIMER -+ /* timer init */ -+ init_timer(&udc_timer); -+ udc_timer.function = udc_timer_function; -+ udc_timer.data = 1; -+ /* timer pollstall init */ -+ init_timer(&udc_pollstall_timer); -+ udc_pollstall_timer.function = udc_pollstall_timer_function; -+ udc_pollstall_timer.data = 1; -+#endif -+ -+ /* set SD */ -+ reg = readl(&dev->regs->ctl); -+ reg |= AMD_BIT(UDC_DEVCTL_SD); -+ writel(reg, &dev->regs->ctl); -+ -+ /* print dev register info */ -+ print_regs(dev); -+ -+ return 0; -+ -+finished: -+ return retval; -+} -+ -+ -+/** -+ * Initiates a remote wakeup -+ * -+ * \return 0 if success -+ */ -+/* initiate remote wakeup */ -+static int udc_remote_wakeup(struct udc* dev) -+{ -+ u32 tmp; -+ -+ INFO("UDC initiates remote wakeup\n"); -+ -+ tmp = readl(&dev->regs->ctl); -+ tmp |= AMD_BIT(UDC_DEVCTL_RES); -+ writel(tmp, &dev->regs->ctl); -+ /* wait 1ms before clear resume bit */ -+ /* udelay(1000); */ -+ tmp &= AMD_CLEAR_BIT(UDC_DEVCTL_RES); -+ writel(tmp, &dev->regs->ctl); -+ -+ return 0; -+} -+ -+#if defined(CONFIG_SOC_AU1200) -+/** -+ * Suspends UDC -+ * -+ * \return 0 if success -+ */ -+static int udc_suspend(struct udc* dev) -+{ -+ int retval = 0; -+ -+ INFO("UDC suspend\n"); -+#ifdef CONFIG_SOC_AU1200 -+ u32 tmp; -+ /* mask interrupts */ -+ udc_mask_unused_interrupts(dev); -+ -+ if (dev->driver && dev->driver->disconnect) { -+ /* call gadget to reset context */ -+ if (spin_is_locked(&dev->lock)) { -+ spin_unlock(&dev->lock); -+ dev->driver->disconnect (&dev->gadget); -+ spin_lock(&dev->lock); -+ } -+ else -+ dev->driver->disconnect (&dev->gadget); -+ -+ /* disable ep0 to empty req queue */ -+ empty_req_queue (&dev->ep [UDC_EP0IN_IX]); -+ ep_init (dev->regs, -+ &dev->ep [UDC_EP0IN_IX]); -+ -+ /* init controller by soft reset */ -+ udc_soft_reset(dev); -+ -+ } -+ if (dev->otg_driver && dev->otg_transceiver -+ && dev->otg_transceiver->set_peripheral) { -+ /* if UDC is supended by Host or already disconnected then -+ don't force disconnect by unbind() */ -+ if (dev->otg_driver->query) { -+ if (!(dev->otg_driver->query(0) & OTG_FLAGS_UDC_SUSP)) { -+ /* unbind from otg driver -> host disconnect */ -+ dev->otg_transceiver->set_peripheral(dev->otg_transceiver, NULL); -+ dev->connected = 0; -+ } -+ } -+ else -+ { -+ /* unbind from otg driver -> host disconnect */ -+ dev->otg_transceiver->set_peripheral (dev->otg_transceiver, NULL); -+ dev->connected = 0; -+ } -+ } -+ -+ dev->sys_suspended = 1; -+ -+ /* switch off UDC clock */ -+ tmp = readl((u32*) (USB_MSR_BASE + USB_MSR_MCFG)); -+ tmp &= AMD_CLEAR_BIT(USBMSRMCFG_UDCCLKEN); -+ writel(tmp, USB_MSR_BASE + USB_MSR_MCFG); -+ -+#endif -+ -+ return retval; -+} -+ -+/** -+ * Resumes UDC -+ * -+ * \return 0 if success -+ */ -+static int udc_resume(struct udc* dev) -+{ -+ int retval = 0; -+ -+ INFO("UDC resume\n"); -+#ifdef CONFIG_SOC_AU1200 -+ u32 tmp; -+ /* switch on UDC clock */ -+ tmp = readl((u32*) (USB_MSR_BASE + USB_MSR_MCFG)); -+ tmp |= AMD_BIT(USBMSRMCFG_UDCCLKEN); -+ writel(tmp, USB_MSR_BASE + USB_MSR_MCFG); -+ -+ dev->sys_suspended = 0; -+ -+ usb_connect(dev); -+ if (dev->otg_transceiver && dev->otg_transceiver->set_peripheral) { -+ /* bind to otg driver */ -+ dev->otg_transceiver->set_peripheral(dev->otg_transceiver, &dev->gadget); -+ } -+ -+#endif -+ -+ return retval; -+} -+ -+static int udc_au1xxx_drv_probe(struct device *dev) -+{ -+ int retval; -+ -+ DBG("udc_au1xxx_drv_probe()\n"); -+ retval = udc_drv_probe(dev); -+ return retval; -+} -+ -+static int udc_au1xxx_drv_remove(struct device *dev) -+{ -+ DBG("udc_au1xxx_drv_remove()\n"); -+ udc_drv_remove(dev); -+ return 0; -+} -+ -+static int udc_au1xxx_drv_suspend(struct device *dev, pm_message_t state) -+{ -+ struct udc *udc_dev = dev_get_drvdata(dev); -+ return udc_suspend(udc_dev); -+} -+ -+static int udc_au1xxx_drv_resume(struct device *dev) -+{ -+ struct udc *udc_dev = dev_get_drvdata(dev); -+ return udc_resume(udc_dev); -+} -+ -+static struct device_driver udc_au1xxx_driver = { -+ .name = "au1xxx-udc", -+ .bus = &platform_bus_type, -+ .probe = udc_au1xxx_drv_probe, -+ .remove = udc_au1xxx_drv_remove, -+ .suspend = udc_au1xxx_drv_suspend, -+ .resume = udc_au1xxx_drv_resume, -+}; -+#endif -+ -+ -+/** -+ * Inits driver -+ * -+ * \return 0 if success -+ */ -+static int __init init(void) -+{ -+ int rc; -+ -+#ifdef UDC_DEBUG -+ /* register char device */ -+ rc = register_chrdev(UDC_MAJOR_NUM, UDC_DEVICE_NAME, &udc_fops); -+ if (rc < 0) -+ { -+ printk("Error registering udc char device"); -+ } -+#endif -+ -+#ifdef CONFIG_SOC_AU1200 -+ /* probe by device system */ -+ rc = driver_register(&udc_au1xxx_driver); -+#else -+ /* probe by PCI bus driver */ -+ rc = pci_module_init (&udc_pci_driver); -+#endif -+ -+ return rc; -+} -+module_init (init); -+ -+/** -+ * Cleans driver -+ */ -+static void __exit cleanup(void) -+{ -+#ifdef UDC_DEBUG -+ /* unregister char device */ -+ unregister_chrdev(UDC_MAJOR_NUM, UDC_DEVICE_NAME); -+#endif -+ -+#ifdef CONFIG_SOC_AU1200 -+ /* unregister at device system */ -+ driver_unregister(&udc_au1xxx_driver); -+#else -+ /* unregister at PCI bus driver */ -+ pci_unregister_driver (&udc_pci_driver); -+#endif -+ -+} -+module_exit (cleanup); -+ -diff --git a/drivers/usb/gadget/au1200udc.h b/drivers/usb/gadget/au1200udc.h -new file mode 100644 -index 0000000..d7d8491 ---- /dev/null -+++ b/drivers/usb/gadget/au1200udc.h -@@ -0,0 +1,936 @@ -+/* -+ * Header for driver for AMD Au1200 UDC high/full speed USB device controller -+ */ -+ -+/* -+ * Copyright (C) 2005 AMD (http://www.amd.com) -+ * Author: Thomas Dahlmann -+ * -+ * 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 AU1200UDC_H -+#define AU1200UDC_H -+ -+/***************************************************************************** -+* Constants -+*****************************************************************************/ -+ -+/* Driver constants -------------------------------------------------------*/ -+#define DRIVER_NAME_FOR_PRINT "au1200udc" -+ -+/* PCI constants -----------------------------------------------------------*/ -+#define UDC_PCI_VENID 0x1022 -+#define UDC_PCI_DEVID 0x2096 -+#define UDC_PCI_CLASS ((PCI_CLASS_SERIAL_USB << 8) | 0xfe) -+#define UDC_PCI_CLASS_MASK 0xffffffff -+ -+/* Platform specific -------------------------------------------------------*/ -+#if defined(CONFIG_SOC_AU1200) -+#define UDC_PCIPOOL_ALIGN 32 -+#define UDC_PCIPOOL_CROSS 4096 -+#define UDC_PCIPOOL_GFP_STP (GFP_ATOMIC | GFP_DMA) -+#else -+#define UDC_PCIPOOL_ALIGN 0 -+#define UDC_PCIPOOL_CROSS 0 -+#define UDC_PCIPOOL_GFP_STP (GFP_KERNEL) -+#endif -+ -+/* temp define for AU1200, will live in au1000.h normally */ -+#ifndef USB_UDC_BASE -+#define USB_UDC_BASE 0x14022000 -+#define USB_UDC_LEN 0x2000 -+#define USB_MSR_BASE 0xB4020000 -+#define USB_MSR_MCFG 4 -+#define USBMSRMCFG_DMEMEN 4 -+#define USBMSRMCFG_DBMEN 5 -+#define USBMSRMCFG_UDCCLKEN 18 -+#define USBMSRMCFG_PHYPLLEN 19 -+#define USBMSRMCFG_RDCOMB 30 -+#define USBMSRMCFG_PFEN 31 -+#define AU1200_USB_INT 29 -+#endif -+#ifndef USBMSRMCFG_UCAM -+#define USBMSRMCFG_UCAM 7 -+#endif -+#define USBMSRMCFG_DEFAULT 0x00d02000 -+ -+/* other constants */ -+#define UDC_RDE_TIMER_SECONDS 1 -+#define UDC_RDE_TIMER_DIV 10 -+#define UDC_POLLSTALL_TIMER_USECONDS 500 -+ -+/* Special optimization for certain gadgets ------------------------------- */ -+/* use hardware NAK if IN queue empty, this can be used to -+* avoid interrupt flood as for the ethernet gadget where host side -+* sends IN tokens permamently */ -+#define UDC_DISABLE_IRQ_IF_EMPTY_IN_QUEUE -+/*#undef UDC_DISABLE_IRQ_IF_EMPTY_IN_QUEUE*/ -+ -+/* IP core defect/bug/case workarounds ---------------------------------------- */ -+/* Hs AU1200 A0 workarounds */ -+/* Description: "Last descriptor loop */ -+#define UDC_IPDEFECT_9000004946_WORKAROUND -+/* Description: "DMA machine not restartable" */ -+#define UDC_IPCASE_8000018724_WORKAROUND -+/* Description: "UDC not accessible when phy is suspended */ -+#define UDC_IPBUG_3943_WORKAROUND -+/* Description: "USB device needs session-valid status information */ -+#define UDC_IPBUG_3950_WORKAROUND -+/* Description: "Clearing endpoint NAK bits not possible if RxFIFO -+ not empty (PCS#1503) */ -+#define UDC_IPBUG_3958_WORKAROUND -+/* UDC data errors during loop test (DMA) -+ - found only with Au1200 but used for Hs too, bug entry -+ is in Au1200 bugzilla -+ - the workaround applies only for small packets */ -+#define UDC_IPBUG_2253_WORKAROUND -+#define UDC_SMALL_PACKET 32 -+ -+/* Disable workarounds which don't apply to Hs AU1200 B1/ Au1200 A1 */ -+/* And enable new features */ -+ -+/* Hs AU1200 A0 flag */ -+/* #define UDC_HSA0 */ -+/* Hs AU1200 B1 flag */ -+#define UDC_HSB1 -+ -+/* Hs AU1200 chip rev. */ -+#define UDC_HSA0_REV 1 -+#define UDC_HSB1_REV 2 -+ -+/* consistency */ -+#ifdef UDC_HSB1 -+#undef UDC_HSA0 -+#endif -+ -+/* Au1200 rev. */ -+#if defined(CONFIG_SOC_AU1200) -+#undef UDC_HSB1 -+#undef UDC_HSA0 -+/* revision value */ -+#define UDC_AUAB_REV 0 -+#define UDC_AUAC_REV 1 -+#define UDC_AUA0 0 -+/* Au1200 AC flag */ -+/* #define UDC_AUA1 1 */ -+#endif -+ -+/* disable workarounds for newer chip revisions */ -+#ifdef UDC_HSB1 -+#undef UDC_IPBUG_3943_WORKAROUND -+#undef UDC_IPBUG_3950_WORKAROUND -+#define UDC_DMARST_AVAIL -+#endif -+#ifdef UDC_AUA1 -+#undef UDC_IPBUG_3943_WORKAROUND -+#endif -+ -+/* SETUP usb commands -+* needed, because some SETUP's are handled in hw, but must be passed to -+* gadget driver above -----------------------------------------------------*/ -+/* SET_CONFIG */ -+#define UDC_SETCONFIG_DWORD0 0x00000900 -+#define UDC_SETCONFIG_DWORD0_VALUE_MASK 0xffff0000 -+#define UDC_SETCONFIG_DWORD0_VALUE_OFS 16 -+ -+#define UDC_SETCONFIG_DWORD1 0x00000000 -+ -+/* SET_INTERFACE */ -+#define UDC_SETINTF_DWORD0 0x00000b00 -+#define UDC_SETINTF_DWORD0_ALT_MASK 0xffff0000 -+#define UDC_SETINTF_DWORD0_ALT_OFS 16 -+ -+#define UDC_SETINTF_DWORD1 0x00000000 -+#define UDC_SETINTF_DWORD1_INTF_MASK 0x0000ffff -+#define UDC_SETINTF_DWORD1_INTF_OFS 0 -+ -+/* Mass storage reset */ -+#define UDC_MSCRES_DWORD0 0x0000ff21 -+#define UDC_MSCRES_DWORD1 0x00000000 -+ -+/* Global CSR's -------------------------------------------------------------*/ -+/* UDC CSR's */ -+#define UDC_CSR_ADDR 0x500 -+ -+/* EP NE bits */ -+/* EP number */ -+#define UDC_CSR_NE_NUM_MASK 0x0000000f -+#define UDC_CSR_NE_NUM_OFS 0 -+/* EP direction */ -+#define UDC_CSR_NE_DIR_MASK 0x00000010 -+#define UDC_CSR_NE_DIR_OFS 4 -+/* EP type */ -+#define UDC_CSR_NE_TYPE_MASK 0x00000060 -+#define UDC_CSR_NE_TYPE_OFS 5 -+/* EP config number */ -+#define UDC_CSR_NE_CFG_MASK 0x00000780 -+#define UDC_CSR_NE_CFG_OFS 7 -+/* EP interface number */ -+#define UDC_CSR_NE_INTF_MASK 0x00007800 -+#define UDC_CSR_NE_INTF_OFS 11 -+/* EP alt setting */ -+#define UDC_CSR_NE_ALT_MASK 0x00078000 -+#define UDC_CSR_NE_ALT_OFS 15 -+ -+/* max pkt */ -+#define UDC_CSR_NE_MAX_PKT_MASK 0x3ff80000 -+#define UDC_CSR_NE_MAX_PKT_OFS 19 -+ -+/* Device Config Register ---------------------------------------------------*/ -+#define UDC_DEVCFG_ADDR 0x400 -+ -+#define UDC_DEVCFG_SOFTRESET 31 -+#define UDC_DEVCFG_HNPSFEN 30 -+#define UDC_DEVCFG_DMARST 29 -+#define UDC_DEVCFG_SET_DESC 18 -+#define UDC_DEVCFG_CSR_PRG 17 -+#define UDC_DEVCFG_STATUS 7 -+#define UDC_DEVCFG_DIR 6 -+#define UDC_DEVCFG_PI 5 -+#define UDC_DEVCFG_SS 4 -+#define UDC_DEVCFG_SP 3 -+#define UDC_DEVCFG_RWKP 2 -+ -+#define UDC_DEVCFG_SPD_MASK 0x3 -+#define UDC_DEVCFG_SPD_OFS 0 -+#define UDC_DEVCFG_SPD_HS 0x0 -+#define UDC_DEVCFG_SPD_FS 0x1 -+#define UDC_DEVCFG_SPD_LS 0x2 -+/*#define UDC_DEVCFG_SPD_FS 0x3*/ -+ -+ -+/* Device Control Register --------------------------------------------------*/ -+#define UDC_DEVCTL_ADDR 0x404 -+ -+#define UDC_DEVCTL_THLEN_MASK 0xff000000 -+#define UDC_DEVCTL_THLEN_OFS 24 -+ -+#define UDC_DEVCTL_BRLEN_MASK 0x00ff0000 -+#define UDC_DEVCTL_BRLEN_OFS 16 -+ -+#define UDC_DEVCTL_CSR_DONE 13 -+#define UDC_DEVCTL_DEVNAK 12 -+#define UDC_DEVCTL_SD 10 -+#define UDC_DEVCTL_MODE 9 -+#define UDC_DEVCTL_BREN 8 -+#define UDC_DEVCTL_THE 7 -+#define UDC_DEVCTL_BF 6 -+#define UDC_DEVCTL_BE 5 -+#define UDC_DEVCTL_DU 4 -+#define UDC_DEVCTL_TDE 3 -+#define UDC_DEVCTL_RDE 2 -+#define UDC_DEVCTL_RES 0 -+ -+ -+/* Device Status Register ---------------------------------------------------*/ -+#define UDC_DEVSTS_ADDR 0x408 -+ -+#define UDC_DEVSTS_TS_MASK 0xfffc0000 -+#define UDC_DEVSTS_TS_OFS 18 -+ -+#define UDC_DEVSTS_SESSVLD 17 -+#define UDC_DEVSTS_PHY_ERROR 16 -+#define UDC_DEVSTS_RXFIFO_EMPTY 15 -+ -+#define UDC_DEVSTS_ENUM_SPEED_MASK 0x00006000 -+#define UDC_DEVSTS_ENUM_SPEED_OFS 13 -+#define UDC_DEVSTS_ENUM_SPEED_FULL 1 -+#define UDC_DEVSTS_ENUM_SPEED_HIGH 0 -+ -+#define UDC_DEVSTS_SUSP 12 -+ -+#define UDC_DEVSTS_ALT_MASK 0x00000f00 -+#define UDC_DEVSTS_ALT_OFS 8 -+ -+#define UDC_DEVSTS_INTF_MASK 0x000000f0 -+#define UDC_DEVSTS_INTF_OFS 4 -+ -+#define UDC_DEVSTS_CFG_MASK 0x0000000f -+#define UDC_DEVSTS_CFG_OFS 0 -+ -+ -+/* Device Interrupt Register ------------------------------------------------*/ -+#define UDC_DEVINT_ADDR 0x40c -+ -+#define UDC_DEVINT_SVC 7 -+#define UDC_DEVINT_ENUM 6 -+#define UDC_DEVINT_SOF 5 -+#define UDC_DEVINT_US 4 -+#define UDC_DEVINT_UR 3 -+#define UDC_DEVINT_ES 2 -+#define UDC_DEVINT_SI 1 -+#define UDC_DEVINT_SC 0 -+ -+/* Device Interrupt Mask Register -------------------------------------------*/ -+#define UDC_DEVINT_MSK_ADDR 0x410 -+ -+#define UDC_DEVINT_MSK 0x7f -+ -+/* Endpoint Interrupt Register ----------------------------------------------*/ -+#define UDC_EPINT_ADDR 0x414 -+ -+#define UDC_EPINT_OUT_MASK 0xffff0000 -+#define UDC_EPINT_OUT_OFS 16 -+#define UDC_EPINT_IN_MASK 0x0000ffff -+#define UDC_EPINT_IN_OFS 0 -+ -+#define UDC_EPINT_IN_EP0 0 -+#define UDC_EPINT_IN_EP1 1 -+#define UDC_EPINT_IN_EP2 2 -+#define UDC_EPINT_IN_EP3 3 -+#define UDC_EPINT_OUT_EP0 16 -+#define UDC_EPINT_OUT_EP1 17 -+#define UDC_EPINT_OUT_EP2 18 -+#define UDC_EPINT_OUT_EP3 19 -+ -+#define UDC_EPINT_EP0_ENABLE_MSK 0x001e001e -+ -+/* Endpoint Interrupt Mask Register -----------------------------------------*/ -+#define UDC_EPINT_MSK_ADDR 0x418 -+ -+#define UDC_EPINT_OUT_MSK_MASK 0xffff0000 -+#define UDC_EPINT_OUT_MSK_OFS 16 -+#define UDC_EPINT_IN_MSK_MASK 0x0000ffff -+#define UDC_EPINT_IN_MSK_OFS 0 -+ -+#define UDC_EPINT_MSK_DISABLE_ALL 0xffffffff -+/* mask non-EP0 endpoints */ -+#define UDC_EPDATAINT_MSK_DISABLE 0xfffefffe -+/* mask all dev interrupts */ -+#define UDC_DEV_MSK_DISABLE 0x7f -+ -+/* Endpoint-specific CSR's --------------------------------------------------*/ -+/* Endpoint Control Registers -----------------------------------------------*/ -+#define UDC_EPREGS_ADDR 0x0 -+#define UDC_EPIN_REGS_ADDR 0x0 -+#define UDC_EPOUT_REGS_ADDR 0x200 -+ -+#define UDC_EPCTL_ADDR 0x0 -+ -+#define UDC_EPCTL_RRDY 9 -+#define UDC_EPCTL_CNAK 8 -+#define UDC_EPCTL_SNAK 7 -+#define UDC_EPCTL_NAK 6 -+ -+#define UDC_EPCTL_ET_MASK 0x00000030 -+#define UDC_EPCTL_ET_OFS 4 -+#define UDC_EPCTL_ET_CONTROL 0 -+#define UDC_EPCTL_ET_ISO 1 -+#define UDC_EPCTL_ET_BULK 2 -+#define UDC_EPCTL_ET_INTERRUPT 3 -+ -+#define UDC_EPCTL_P 3 -+#define UDC_EPCTL_SN 2 -+#define UDC_EPCTL_F 1 -+#define UDC_EPCTL_S 0 -+ -+/* Endpoint Status Registers ------------------------------------------------*/ -+#define UDC_EPSTS_ADDR 0x4 -+ -+#define UDC_EPSTS_RX_PKT_SIZE_MASK 0x007ff800 -+#define UDC_EPSTS_RX_PKT_SIZE_OFS 11 -+ -+#define UDC_EPSTS_TDC 10 -+#define UDC_EPSTS_HE 9 -+#define UDC_EPSTS_BNA 7 -+#define UDC_EPSTS_IN 6 -+ -+#define UDC_EPSTS_OUT_MASK 0x00000030 -+#define UDC_EPSTS_OUT_OFS 4 -+#define UDC_EPSTS_OUT_DATA 1 -+#define UDC_EPSTS_OUT_DATA_CLEAR 0x10 -+#define UDC_EPSTS_OUT_SETUP 2 -+#define UDC_EPSTS_OUT_SETUP_CLEAR 0x20 -+ -+/* Endpoint Buffer Size IN/ Receive Packet Frame Number OUT Registers ------*/ -+#define UDC_EPIN_BUFF_SIZE_ADDR 0x8 -+#define UDC_EPOUT_FRAME_NUMBER_ADDR 0x8 -+ -+#define UDC_EPIN_BUFF_SIZE_MASK 0x0000ffff -+#define UDC_EPIN_BUFF_SIZE_OFS 0 -+/* EP0in txfifo = 128 bytes*/ -+#define UDC_EPIN0_BUFF_SIZE 32 -+/* EP0in fullspeed txfifo = 128 bytes*/ -+#define UDC_FS_EPIN0_BUFF_SIZE 32 -+ -+/* fifo size mult = fifo size / max packet */ -+#define UDC_EPIN_BUFF_SIZE_MULT 2 -+ -+/* EPin data fifo size = 1024 bytes DOUBLE BUFFERING */ -+#define UDC_EPIN_BUFF_SIZE 256 -+/* EPin small INT data fifo size = 128 bytes */ -+#define UDC_EPIN_SMALLINT_BUFF_SIZE 32 -+ -+/* EPin fullspeed data fifo size = 128 bytes DOUBLE BUFFERING */ -+#define UDC_FS_EPIN_BUFF_SIZE 32 -+ -+#define UDC_EPOUT_FRAME_NUMBER_MASK 0x0000ffff -+#define UDC_EPOUT_FRAME_NUMBER_OFS 0 -+ -+/* Endpoint Buffer Size OUT/Max Packet Size Registers -----------------------*/ -+#define UDC_EPOUT_BUFF_SIZE_ADDR 0x0c -+#define UDC_EP_MAX_PKT_SIZE_ADDR 0x0c -+ -+#define UDC_EPOUT_BUFF_SIZE_MASK 0xffff0000 -+#define UDC_EPOUT_BUFF_SIZE_OFS 16 -+#define UDC_EP_MAX_PKT_SIZE_MASK 0x0000ffff -+#define UDC_EP_MAX_PKT_SIZE_OFS 0 -+/* EP0in max packet size = 64 bytes */ -+#define UDC_EP0IN_MAX_PKT_SIZE 64 -+/* EP0out max packet size = 64 bytes */ -+#define UDC_EP0OUT_MAX_PKT_SIZE 64 -+/* EP0in fullspeed max packet size = 64 bytes */ -+#define UDC_FS_EP0IN_MAX_PKT_SIZE 64 -+/* EP0out fullspeed max packet size = 64 bytes */ -+#define UDC_FS_EP0OUT_MAX_PKT_SIZE 64 -+ -+/* Endpoint dma descriptors ------------------------------------------------*/ -+/* Setup data */ -+/* Status dword */ -+#define UDC_DMA_STP_STS_CFG_MASK 0x0fff0000 -+#define UDC_DMA_STP_STS_CFG_OFS 16 -+#define UDC_DMA_STP_STS_CFG_ALT_MASK 0x000f0000 -+#define UDC_DMA_STP_STS_CFG_ALT_OFS 16 -+#define UDC_DMA_STP_STS_CFG_INTF_MASK 0x00f00000 -+#define UDC_DMA_STP_STS_CFG_INTF_OFS 20 -+#define UDC_DMA_STP_STS_CFG_NUM_MASK 0x0f000000 -+#define UDC_DMA_STP_STS_CFG_NUM_OFS 24 -+#define UDC_DMA_STP_STS_RX_MASK 0x30000000 -+#define UDC_DMA_STP_STS_RX_OFS 28 -+#define UDC_DMA_STP_STS_BS_MASK 0xc0000000 -+#define UDC_DMA_STP_STS_BS_OFS 30 -+#define UDC_DMA_STP_STS_BS_HOST_READY 0 -+#define UDC_DMA_STP_STS_BS_DMA_BUSY 1 -+#define UDC_DMA_STP_STS_BS_DMA_DONE 2 -+#define UDC_DMA_STP_STS_BS_HOST_BUSY 3 -+/* IN data */ -+/* Status dword */ -+#define UDC_DMA_IN_STS_TXBYTES_MASK 0x0000ffff -+#define UDC_DMA_IN_STS_TXBYTES_OFS 0 -+#define UDC_DMA_IN_STS_FRAMENUM_MASK 0x07ff0000 -+#define UDC_DMA_IN_STS_FRAMENUM_OFS 0 -+#define UDC_DMA_IN_STS_L 27 -+#define UDC_DMA_IN_STS_TX_MASK 0x30000000 -+#define UDC_DMA_IN_STS_TX_OFS 28 -+#define UDC_DMA_IN_STS_BS_MASK 0xc0000000 -+#define UDC_DMA_IN_STS_BS_OFS 30 -+#define UDC_DMA_IN_STS_BS_HOST_READY 0 -+#define UDC_DMA_IN_STS_BS_DMA_BUSY 1 -+#define UDC_DMA_IN_STS_BS_DMA_DONE 2 -+#define UDC_DMA_IN_STS_BS_HOST_BUSY 3 -+/* OUT data */ -+/* Status dword */ -+#define UDC_DMA_OUT_STS_RXBYTES_MASK 0x0000ffff -+#define UDC_DMA_OUT_STS_RXBYTES_OFS 0 -+#define UDC_DMA_OUT_STS_FRAMENUM_MASK 0x07ff0000 -+#define UDC_DMA_OUT_STS_FRAMENUM_OFS 0 -+#define UDC_DMA_OUT_STS_L 27 -+#define UDC_DMA_OUT_STS_RX_MASK 0x30000000 -+#define UDC_DMA_OUT_STS_RX_OFS 28 -+#define UDC_DMA_OUT_STS_BS_MASK 0xc0000000 -+#define UDC_DMA_OUT_STS_BS_OFS 30 -+#define UDC_DMA_OUT_STS_BS_HOST_READY 0 -+#define UDC_DMA_OUT_STS_BS_DMA_BUSY 1 -+#define UDC_DMA_OUT_STS_BS_DMA_DONE 2 -+#define UDC_DMA_OUT_STS_BS_HOST_BUSY 3 -+/* other constants */ -+/* max ep0in packet */ -+#define UDC_EP0IN_MAXPACKET 1000 -+/* max dma packet */ -+#define UDC_DMA_MAXPACKET 65536 -+/* DMA buffer len for temp request, should be the same as the upper -+layer gadget is using */ -+#define UDC_DMA_TEMP_BUFFER_LEN 4096 -+/* un-usable DMA address */ -+#define DMA_DONT_USE (~(dma_addr_t) 0 ) -+ -+/* other Endpoint register addresses and values-----------------------------*/ -+#define UDC_EP_SUBPTR_ADDR 0x10 -+#define UDC_EP_DESPTR_ADDR 0x14 -+#define UDC_EP_WRITE_CONFIRM_ADDR 0x1c -+ -+/* EP number as layouted in AHB space */ -+#define UDC_EP_NUM 32 -+#define UDC_EPIN_NUM 16 -+#define UDC_EPIN_NUM_USED 5 -+#define UDC_EPOUT_NUM 16 -+/* EP number of EP's really used = EP0 + 8 data EP's */ -+#define UDC_USED_EP_NUM 9 -+/* UDC CSR regs are aligned but AHB regs not - offset for OUT EP's */ -+#define UDC_CSR_EP_OUT_IX_OFS 12 -+ -+#define UDC_EP0OUT_IX 16 -+#define UDC_EP0IN_IX 0 -+ -+/* max packet */ -+#define UDC_HS_BULK_MAXPKT 512 -+ -+/* Rx fifo address and size = 1k -------------------------------------------*/ -+#define UDC_RXFIFO_ADDR 0x800 -+#define UDC_RXFIFO_SIZE 0x400 -+ -+/* Tx fifo address and size = 1.5k -----------------------------------------*/ -+#define UDC_TXFIFO_ADDR 0xc00 -+#define UDC_TXFIFO_SIZE 0x600 -+ -+/* default data endpoints --------------------------------------------------*/ -+#define UDC_EPIN_STATUS_IX 1 -+#define UDC_EPIN_IX 2 -+#define UDC_EPOUT_IX 18 -+ -+/* general constants -------------------------------------------------------*/ -+#define UDC_DWORD_BYTES 4 -+#define UDC_BITS_PER_BYTE_SHIFT 3 -+#define UDC_BYTE_MASK 0xff -+#define UDC_BITS_PER_BYTE 8 -+ -+/* char device constants ---------------------------------------------------*/ -+/* names */ -+#ifdef UDC_DEBUG -+#ifdef UDC_DRIVER_NAME -+#define UDC_DEVICE_NAME UDC_DRIVER_NAME -+#else -+#define UDC_DEVICE_NAME "au1200udc" -+#endif -+#define UDC_DEVICE_FILE_NAME "au1200udc_dev" -+#define UDC_DEVICE_FILE_INODE "/dev/au1200udc_dev" -+/* major number */ -+#define UDC_MAJOR_NUM 240 -+#endif -+ -+#ifdef __KERNEL__ -+/* kernel wrappers */ -+#define device_create_file(x,y) do {} while (0) -+#define device_remove_file device_create_file -+ -+#ifndef WARN_ON -+#define WARN_ON(a) do {} while (0) -+#endif -+ -+#ifndef BUG_ON -+#define BUG_ON(cond)do {if (unlikely((cond) != 0)) BUG();} while(0) -+#endif -+ -+#ifndef likely -+#define likely(a) (a) -+#define unlikely(a) (a) -+#endif -+ -+#ifndef container_of -+#define container_of list_entry -+#endif -+ -+#ifndef IRQ_NONE -+typedef void irqreturn_t; -+#define IRQ_HANDLED -+#define IRQ_NONE -+#define IRQ_RETVAL(a) -+#endif -+#endif -+ -+/* MIPS specific -----------------------------------------------------------*/ -+#if defined(CONFIG_SOC_AU1200) -+/* sync does it without refilling the pipe, -+ so read after write can bypass write */ -+#define au1200_sync_delay() {\ -+ asm(".set noreorder"); \ -+ asm("b l1");\ -+ asm("l1:");\ -+ asm("sync");\ -+ asm("nop");\ -+ asm("nop");\ -+ asm("nop");\ -+ asm("nop");\ -+ asm("b l2");\ -+ asm("l2:");\ -+ asm("nop");\ -+ asm("nop");\ -+ asm(".set reorder");\ -+} -+ -+/* #define wb_flush() au1200_sync() */ -+#define wb_flush() __asm__ volatile ("sync") -+ -+/* special write functions for MIPS (with write buffer flush) */ -+#undef writel -+#undef writeb -+#define writel(d,a) {((*(volatile unsigned int *)(a))=(d));wb_flush();} -+#define writeb(d,a) {((*(volatile unsigned char *)(a))=(d));wb_flush();} -+#else -+#define wb_flush() {} -+#endif -+ -+/***************************************************************************** -+* Includes -+*****************************************************************************/ -+ -+#if !defined(UDC_HSB1) -+#include "au1200otg.h" -+#endif -+ -+/***************************************************************************** -+* Types -+*****************************************************************************/ -+ -+/* UDC CSR's */ -+struct udc_csrs { -+ -+ /* sca - setup command address */ -+ u32 sca; -+ -+ /* ep ne's */ -+ u32 ne[UDC_USED_EP_NUM]; -+} __attribute__ ((packed)); -+ -+/* AHB subsystem CSR registers */ -+struct udc_regs { -+ -+ /* device configuration */ -+ u32 cfg; -+ -+ /* device control */ -+ u32 ctl; -+ -+ /* device status */ -+ u32 sts; -+ -+ /* device interrupt */ -+ u32 irqsts; -+ -+ /* device interrupt mask */ -+ u32 irqmsk; -+ -+ /* endpoint interrupt */ -+ u32 ep_irqsts; -+ -+ /* endpoint interrupt mask */ -+ u32 ep_irqmsk; -+} __attribute__ ((packed)); -+ -+/* endpoint specific registers */ -+struct udc_ep_regs { -+ -+ /* endpoint control */ -+ u32 ctl; -+ -+ /* endpoint status */ -+ u32 sts; -+ -+ /* endpoint buffer size in/ receive packet frame number out */ -+ u32 bufin_framenum; -+ -+ /* endpoint buffer size out/max packet size */ -+ u32 bufout_maxpkt; -+ -+ /* endpoint setup buffer pointer */ -+ u32 subptr; -+ -+ /* endpoint data descriptor pointer */ -+ u32 desptr; -+ -+ /* reserverd */ -+ u32 reserved; -+ -+ /* write/read confirmation */ -+ u32 confirm; -+ -+} __attribute__ ((packed)); -+ -+#ifdef __KERNEL__ -+/* control data DMA desc */ -+struct udc_stp_dma { -+ /* status quadlet */ -+ u32 status; -+ /* reserved */ -+ u32 _reserved; -+ /* first setup word */ -+ u32 data12; -+ /* second setup word */ -+ u32 data34; -+} __attribute__ ((aligned (16))); -+ -+/* normal data DMA desc */ -+struct udc_data_dma { -+ /* status quadlet */ -+ u32 status; -+ /* reserved */ -+ u32 _reserved; -+ /* buffer pointer */ -+ u32 bufptr; -+ /* next descriptor pointer */ -+ u32 next; -+} __attribute__ ((aligned (16))); -+ -+/* request packet */ -+struct udc_request { -+ /* embedded gadget ep */ -+ struct usb_request req; -+ -+ /* flags */ -+ unsigned dma_going : 1, -+ dma_mapping : 1, -+ dma_done : 1; -+ /* phys. address */ -+ dma_addr_t td_phys; -+ /* first dma desc. of chain */ -+ struct udc_data_dma *td_data; -+ /* last dma desc. of chain */ -+ struct udc_data_dma *td_data_last; -+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND -+ /* next pointer of broken chain */ -+ dma_addr_t td_data_last_next; -+#endif -+ -+ struct list_head queue; -+ -+ /* chain length */ -+ unsigned chain_len; -+ -+}; -+ -+/* UDC specific endpoint parameters */ -+struct udc_ep { -+ struct usb_ep ep; -+ struct udc_ep_regs *regs; -+ u32 *txfifo; -+ u32* dma; -+ dma_addr_t td_phys; -+ dma_addr_t td_stp_dma; -+ struct udc_stp_dma *td_stp; -+ struct udc_data_dma *td; -+ /* temp request */ -+ struct udc_request *req; -+ unsigned req_used; -+ unsigned req_completed; -+ /* NAK state */ -+ unsigned naking; -+ -+ struct udc *dev; -+ -+ /* queue for requests */ -+ struct list_head queue; -+ const struct usb_endpoint_descriptor *desc; -+ unsigned halted; -+ unsigned num : 5, -+ fifo_depth : 14, -+ in : 1; -+}; -+ -+/* device struct */ -+struct udc { -+ struct usb_gadget gadget; -+ spinlock_t lock; -+ /* all endpoints */ -+ struct udc_ep ep[UDC_EP_NUM]; -+ struct usb_gadget_driver *driver; -+ struct otg_transceiver *otg_transceiver; -+#if !defined(UDC_HSB1) -+ struct usb_otg_gadget_extension *otg_driver; -+#endif -+ /* operational flags */ -+ unsigned active : 1, -+ stall_ep0in : 1, -+ waiting_zlp_ack_ep0in : 1, -+ set_cfg_not_acked : 1, -+ irq_registered : 1, -+ otg_supported : 1, -+ data_ep_enabled : 1, -+ data_ep_queued : 1, -+ mem_region : 1, -+ selfpowered : 1, -+ sys_suspended : 1, -+ connected; -+ -+ u16 chiprev; -+ -+ /* registers */ -+#if defined(CONFIG_SOC_AU1200) && !defined(USE_AU1200_PCI_DUMMY) -+ struct device *pdev; -+#else -+ struct pci_dev *pdev; -+#endif -+ struct udc_csrs *csr; -+ struct udc_regs *regs; -+ struct udc_ep_regs *ep_regs; -+ u32* rxfifo; -+ u32* txfifo; -+ -+ /* DMA desc pools */ -+#if defined(CONFIG_SOC_AU1200) -+ struct dma_pool *data_requests; -+ struct dma_pool *stp_requests; -+#else -+ struct pci_pool *data_requests; -+ struct pci_pool *stp_requests; -+#endif -+ -+ /* device data */ -+ unsigned long phys_addr; -+ void* virt_addr; -+ unsigned irq; -+ -+ /* states */ -+ u16 cur_config; -+ u16 cur_intf; -+ u16 cur_alt; -+}; -+ -+/* setup request data */ -+union udc_setup_data { -+ u32 data[2]; -+ struct usb_ctrlrequest request; -+}; -+#endif /*__KERNEL__*/ -+ -+/***************************************************************************** -+* Macros -+*****************************************************************************/ -+ -+/*************************************** -+* SET and GET bitfields in u32 values -+* via constants for mask/offset: -+* <bit_field_stub_name> is the text between -+* UDC_ and _MASK|_OFS of appropiate -+* constant -+****************************************/ -+/* set bitfield value in u32 u32Val */ -+#define AMD_ADDBITS(u32Val, bitfield_val, bitfield_stub_name)\ -+ (((u32Val) & (((u32) ~((u32) bitfield_stub_name##_MASK))))\ -+ |(((bitfield_val) << ((u32) bitfield_stub_name##_OFS))\ -+ & ((u32) bitfield_stub_name##_MASK))) -+ -+/* set bitfield value in zero-initialized u32 u32Val */ -+/* => bitfield bits in u32Val are all zero */ -+#define AMD_INIT_SETBITS(u32Val, bitfield_val, bitfield_stub_name)\ -+ ((u32Val)\ -+ |(((bitfield_val) << ((u32) bitfield_stub_name##_OFS))\ -+ &((u32) bitfield_stub_name##_MASK))) -+ -+/* get bitfield value from u32 u32Val */ -+#define AMD_GETBITS(u32Val, bitfield_stub_name)\ -+ ((u32Val & ((u32) bitfield_stub_name##_MASK))\ -+ >> ((u32) bitfield_stub_name##_OFS)) -+ -+/* SET and GET bits in u32 values ------------------------------------------*/ -+#define AMD_BIT(bit_stub_name) (1 << bit_stub_name) -+#define AMD_UNMASK_BIT(bit_stub_name) (~AMD_BIT(bit_stub_name)) -+#define AMD_CLEAR_BIT(bit_stub_name) (~AMD_BIT(bit_stub_name)) -+ -+/* misc --------------------------------------------------------------------*/ -+#define DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out") -+ -+/* UDC specific macros -----------------------------------------------------*/ -+#ifdef UDC_DMARST_AVAIL -+#define UDC_DMARST(tmp, dev) \ -+ DBG("DMA machine reset\n"); \ -+ tmp = readl(&dev->regs->cfg); \ -+ writel(tmp | AMD_BIT(UDC_DEVCFG_DMARST), &dev->regs->cfg); \ -+ writel(tmp, &dev->regs->cfg); -+#else -+#define UDC_DMARST(tmp, dev) {} -+#endif -+ -+/* print macros ------------------------------------------------------------*/ -+ -+#ifdef UDC_VERBOSE -+#ifndef UDC_DEBUG -+#define UDC_DEBUG -+#endif -+#endif -+ -+/** -+ * \brief -+ * Macro for printing information in drivers -+ * -+ * This macro is used for printing kernel messages in driver source code. -+ * It should be used for printing useful information about states and called -+ * functions for normal operation (not for errors and warnings). -+ * -+ * \param fmt is format string for printk -+ * \param args... are arguments given to printk (number depends on <fmt>) -+ * \return code from printk -+ */ -+#define INFO(args...) \ -+ printk(KERN_INFO DRIVER_NAME_FOR_PRINT ": " args) -+ -+/** -+ * \brief -+ * Macro for printing warnings in drivers -+ * -+ * This macro is used for printing kernel messages in driver source code. -+ * It should be used for printing warnings. -+ * -+ * \param fmt is format string for printk -+ * \param args... are arguments given to printk (number depends on <fmt>) -+ * \return code from printk -+ */ -+#define WARN(args...) \ -+ printk(KERN_WARNING DRIVER_NAME_FOR_PRINT " warning: " args) -+ -+/** -+ * \brief -+ * Macro for printing errors in drivers -+ * -+ * This macro is used for printing kernel messages in driver source code. -+ * It should be used for printing errors. -+ * -+ * \param fmt is format string for printk -+ * \param args... are arguments given to printk (number depends on <fmt>) -+ * \return code from printk -+ */ -+#define ERR(args...) \ -+ printk(KERN_ERR DRIVER_NAME_FOR_PRINT " error: " args) -+ -+/** -+ * \brief -+ * Macro for printing debug messages in drivers -+ * -+ * This macro is used for printing kernel messages in driver source code -+ * when UDC_DEBUG is defined -+ * It should be used for printing debug messages. -+ * -+ * \param fmt is format string for printk -+ * \param args... are arguments given to printk (number depends on <fmt>) -+ * \return code from printk -+ */ -+#ifdef UDC_DEBUG -+#define DBG(args...) \ -+ printk(KERN_DEBUG DRIVER_NAME_FOR_PRINT " debug: " args) -+#else -+ -+#define DBG(args...) \ -+ do {} while (0) -+#endif -+ -+/** -+ * \brief -+ * Macro for printing verbose debug messages in drivers -+ * -+ * This macro is used for printing kernel messages in driver source code -+ * when UDC_DEBUG and UDC_VERBOSE is defined -+ * It should be used for printing debug messages. -+ * -+ * \param fmt is format string for printk -+ * \param args... are arguments given to printk (number depends on <fmt>) -+ * \return code from printk -+ */ -+#ifdef UDC_VERBOSE -+#define VDBG DBG -+#else -+#define VDBG(args...) \ -+ do {} while (0) -+#endif -+#endif /* #ifdef AU1200UDC_H */ -diff --git a/drivers/usb/gadget/au1200uoc.c b/drivers/usb/gadget/au1200uoc.c -new file mode 100644 -index 0000000..5297eee ---- /dev/null -+++ b/drivers/usb/gadget/au1200uoc.c -@@ -0,0 +1,2015 @@ -+/* -+ * AMD Au1200 USB OTG controller driver -+ */ -+ -+/* -+ * Copyright (C) 2005 AMD (http://www.amd.com) -+ * Author: Karsten Boge -+ * -+ * 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 -+ */ -+ -+ -+/***************************************************************************** -+ * Includes -+ *****************************************************************************/ -+ -+#include <linux/config.h> -+#include <linux/module.h> -+#include <linux/pci.h> -+#include <linux/kernel.h> -+#include <linux/version.h> -+#include <linux/delay.h> -+#include <linux/ioport.h> -+#include <linux/sched.h> -+#include <linux/slab.h> -+#include <linux/smp_lock.h> -+#include <linux/errno.h> -+#include <linux/init.h> -+#include <linux/timer.h> -+#include <linux/list.h> -+#include <linux/interrupt.h> -+ -+#include <asm/byteorder.h> -+#include <asm/io.h> -+#include <asm/irq.h> -+#include <asm/system.h> -+#include <asm/unaligned.h> -+ -+#ifdef CONFIG_USB_OTG_TEST_INTERFACE -+#ifndef CONFIG_USB_OTG -+#define CONFIG_USB_OTG -+#endif -+#endif -+ -+/* #define DEBUG */ -+/* #define VERBOSE */ -+ -+#ifdef CONFIG_SOC_AU1200 -+#include <asm/mach-au1x00/au1000.h> -+#include <asm/mach-au1x00/au1000_gpio.h> -+#include <linux/platform_device.h> -+#endif -+ -+#include <linux/usb.h> -+#include <linux/usb_gadget.h> -+#include <linux/usb_otg.h> -+ -+#define DRIVER_DESC "AMD Au1200 USB OTG Controller" -+#define DRIVER_VERSION "01.00.0201 - $Revision: #3 $" -+#define DRIVER_NAME_FOR_PRINT OTG_DRIVER_NAME -+ -+#include "au1200otg.h" -+#include "au1200uoc.h" -+ -+ -+/***************************************************************************** -+ * Function Declarations -+ *****************************************************************************/ -+ -+#ifdef CONFIG_USB_OTG_TEST_INTERFACE -+static int otg_test_bind(struct otg **); -+static int otg_test_unbind(struct otg **); -+#endif -+#ifdef CONFIG_USB_OTG -+static int otg_app_request(u32); -+static int otg1200_set_host (struct otg_transceiver *, struct usb_bus *); -+static int otg1200_set_power (struct otg_transceiver *, unsigned); -+static int otg1200_start_srp (struct otg_transceiver *); -+static int otg1200_start_hnp (struct otg_transceiver *); -+#endif -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+static u32 otg_app_query(int); -+static int otg1200_set_peripheral (struct otg_transceiver *, -+ struct usb_gadget *); -+#endif -+ -+ -+/***************************************************************************** -+ * Data -+ *****************************************************************************/ -+ -+static const char driver_name [] = OTG_DRIVER_NAME; -+static const char driver_desc [] = DRIVER_DESC; -+ -+static struct otg *the_controller; -+static const char *transceiver_label = "au1200_otg"; -+ -+static u32 init_state = 0; -+#ifdef OTG_HNP_ERR_LOG -+int hnp_err = 0; -+#endif -+ -+#ifdef CONFIG_USB_OTG_TEST_INTERFACE -+static struct usb_otg_test_extension otg_test_extension = { -+ .bind = otg_test_bind, -+ .unbind = otg_test_unbind, -+ .request = otg_app_request, -+ .query = otg_app_query -+}; -+#endif -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+struct usb_otg_gadget_extension otg_gadget_extension = { -+#ifdef CONFIG_USB_OTG -+ .request = otg_app_request, -+#else -+ .request = NULL, -+#endif -+ .query = otg_app_query, -+ .notify = NULL -+}; -+ -+static u32 state_mask; -+u32 otg_tmr_high_count = 0; -+#endif -+ -+#ifdef CONFIG_SOC_AU1200 -+#ifdef USE_AU1200_PCI_DUMMY -+static struct pci_dev pdev_dummy; -+#endif -+#endif -+ -+ -+/***************************************************************************** -+ * Function Definitions -+ *****************************************************************************/ -+ -+/** -+ * \brief -+ * fill OTG transceiver struct -+ * -+ * \param transceiver OTG transceiver -+ * -+ * \return void -+ */ -+static inline void otg_init_transceiver (struct otg_transceiver *transceiver) -+{ -+ transceiver_to_otg(transceiver)->prv_state = OTG_STATE_UNDEFINED; -+ transceiver_to_otg(transceiver)->params = 0; -+ transceiver_to_otg(transceiver)->hostcount = 0; -+ transceiver_to_otg(transceiver)->otg_priv = (void *) &otg_gadget_extension; -+ -+ transceiver->dev = NULL; -+ transceiver->label = transceiver_label; -+ transceiver->default_a = 0; -+ transceiver->state = OTG_STATE_UNDEFINED; -+ transceiver->host = NULL; -+#ifdef CONFIG_USB_OTG_HIGHSPEED -+ transceiver->companion = NULL; -+#endif -+ transceiver->gadget = NULL; -+ transceiver->port_status = 0; -+ transceiver->port_change = 0; -+#ifdef CONFIG_USB_OTG -+ transceiver->set_host = otg1200_set_host; -+ transceiver->set_peripheral = otg1200_set_peripheral; -+ transceiver->set_power = otg1200_set_power; -+ transceiver->start_srp = otg1200_start_srp; -+ transceiver->start_hnp = otg1200_start_hnp; -+#else -+ transceiver->set_host = NULL; -+ transceiver->set_peripheral = otg1200_set_peripheral; -+ transceiver->set_power = NULL; -+ transceiver->start_srp = NULL; -+ transceiver->start_hnp = NULL; -+#endif -+} -+ -+#ifdef CONFIG_USB_OTGMUX_GADGET -+/** -+ * \brief -+ * OTG state change -+ * -+ * subset of OTG states to support the gadget only or -+ * ID pin configuration -+ * -+ * \param otg OTG controller info -+ * \param event_code event that requested a state change -+ * \param pEvt_mask -+ * -+ * \return events that were not handled here -+ */ -+u32 otg_change_state (struct otg *otg, u32 _event, u32 *pEvt_mask) -+{ -+ u32 event_code = _event; -+ u32 uoc_status = get_status (otg); -+ -+ if (GOT_EVENT (OTG_GADGET_READY, event_code) -+ -+#ifdef CONFIG_USB_OTGMUX_IDPIN -+ -+ || GOT_EVENT (OTG_HOST_READY, event_code) -+#endif -+ ) { -+ -+ if (((IS_FLAG_RES (otg, OTG_GADGET_READY)) -+ -+#ifdef CONFIG_USB_OTGMUX_IDPIN -+ -+ || (IS_FLAG_RES (otg, OTG_HOST_READY)) -+#endif -+ ) -+ -+ && ((otg->transceiver.state & OTG_STATE_MASK) != -+ OTG_STATE_UNDEFINED)) { -+ -+ /* driver unload, back to "not ready" state */ -+ -+ CHANGE_STATE (otg, OTG_STATE_UNDEFINED, pEvt_mask); -+ RES_EVENT ((OTG_GADGET_READY | OTG_HOST_READY), -+ event_code); -+ } -+ } -+ if ((OTG_INT_TMX & event_code) && otg_tmr_high_count) { -+ -+ /* a long timer is running : decrement the high part */ -+ -+ restart_timer (otg); -+ otg_tmr_high_count--; -+ RES_EVENT (OTG_INT_TMX, event_code); -+ } -+ -+ do switch (otg->transceiver.state & OTG_STATE_MASK) { -+ -+ /* NOT_ASSIGNED (yet): init state, 1st time after loading */ -+ /* ====================================================== */ -+ -+ case OTG_STATE_UNDEFINED : -+ -+ CHECK_STATE (otg, OTG_STATE_UNDEFINED, pEvt_mask); -+ -+ if (IS_FLAG_RES (otg, OTG_FLAGS_ACTIV)) { -+ -+ /* seems to be the first time: let it run ! */ -+ -+ SET_FLAG (otg, OTG_FLAGS_ACTIV); -+ } -+ -+ /* muxer is still neutral */ -+ -+ RES_EVENT ((OTG_GADGET_READY | OTG_HOST_READY | -+ OTG_INT_IDC | OTG_INT_TMX), event_code); -+ -+ if ((IS_FLAG_SET (otg, OTG_GADGET_READY)) -+ -+#ifdef CONFIG_USB_OTGMUX_IDPIN -+ -+ || (IS_FLAG_SET (otg, OTG_HOST_READY)) -+#endif -+ ) { -+ -+ /* NOT_READY (substate): drivers now ready */ -+ /* ======================================= */ -+ -+#ifdef CONFIG_USB_OTGMUX_IDPIN -+ -+ if (IS_BIT_RES (OTG_STS_ID, uoc_status)) { -+ -+ /* ID pin connected: A-device (host) */ -+ -+ CHANGE_STATE (otg, OTG_STATE_A_HOST, -+ pEvt_mask); -+ } -+ else { -+ /* ID pin not connected: disable (neutral) */ -+#endif -+ CHANGE_STATE (otg, OTG_STATE_B_IDLE, -+ pEvt_mask); -+ -+#ifdef CONFIG_USB_OTGMUX_IDPIN -+ } -+#endif -+ } -+ break; -+ -+#ifdef CONFIG_USB_OTGMUX_IDPIN -+ -+ /* A: ID pin is connected, A-device drives VBus */ -+ /* ============================================ */ -+ -+ case OTG_STATE_A_HOST : -+ -+ CHECK_STATE (otg, OTG_STATE_A_HOST, pEvt_mask); -+ -+ if (IS_BIT_SET (OTG_STS_ID, uoc_status)) { -+ -+ /* ID change => B_IDLE */ -+ -+ RES_EVENT ((OTG_INT_IDC | OTG_INT_PCC), event_code); -+ CHANGE_STATE (otg, OTG_STATE_B_IDLE, pEvt_mask); -+ } -+ break; -+ -+ /* B: ID pin is not connected */ -+ /* ========================== */ -+#endif -+ -+ case OTG_STATE_B_IDLE : -+ -+ /* B_IDLE: init state for B-devices */ -+ /* monitor VBus, no connection, no activity */ -+ -+ CHECK_STATE (otg, OTG_STATE_B_IDLE, pEvt_mask); -+ -+#ifdef CONFIG_USB_OTGMUX_IDPIN -+ -+ if (IS_BIT_RES (OTG_STS_ID, uoc_status)) { -+ -+ /* ID pin changed => A_HOST */ -+ -+ RES_EVENT (OTG_INT_IDC, event_code); -+ CHANGE_STATE (otg, OTG_STATE_A_HOST, pEvt_mask); -+ } -+ else if (IS_BIT_SET (OTG_STS_SESSVLD, uoc_status)) -+#else -+ if (IS_BIT_SET (OTG_STS_SESSVLD, uoc_status)) -+#endif -+ { -+ /* Session valid => B_PERIPHERAL */ -+ -+ RES_EVENT (OTG_INT_SVC, event_code); -+ CHANGE_STATE (otg, OTG_STATE_B_PERIPHERAL, pEvt_mask); -+#ifndef CONFIG_TEST_MODE_ONLY -+ if (otg_gadget_extension.notify) { -+ otg_gadget_extension.notify ( -+ OTG_GADGET_EVT_SVALID); -+ } -+#endif -+ } -+ break; -+ -+ case OTG_STATE_B_PERIPHERAL : -+ -+ /* B_PERIPHERAL: connected to A-host, responding */ -+ /* VBus driven by A, remote activity */ -+ -+ CHECK_STATE (otg, OTG_STATE_B_PERIPHERAL, pEvt_mask); -+ -+#ifdef CONFIG_USB_OTGMUX_IDPIN -+ -+ if (IS_BIT_RES (OTG_STS_ID, uoc_status) || -+ IS_BIT_RES (OTG_STS_SESSVLD, uoc_status)) -+#else -+ if (IS_BIT_RES (OTG_STS_SESSVLD, uoc_status)) -+#endif -+ { -+ /* ID pin changed | ~Session valid => B_IDLE */ -+ -+ RES_EVENT ((OTG_INT_IDC | OTG_INT_SVC), event_code); -+ CHANGE_STATE (otg, OTG_STATE_B_IDLE, pEvt_mask); -+#ifndef CONFIG_TEST_MODE_ONLY -+ if (otg_gadget_extension.notify) { -+ otg_gadget_extension.notify ( -+ OTG_GADGET_EVT_SVDROP); -+ } -+#endif -+ } -+ break; -+ -+ /* unlikely */ default : -+ -+ /* something went wrong */ -+ -+ BUG (); -+ break; -+ } -+ while ((otg->transceiver.state ^ otg->prv_state) & -+ OTG_STATE_MASK); -+ -+ DBG ("OTG-state change done\n"); -+ -+ return event_code; -+} -+#endif /* CONFIG_USB_OTGMUX_GADGET */ -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+/** -+ * \brief -+ * OTG state change request -+ * -+ * \param dev OTG device info -+ * \param params -+ * -+ * \return void -+ */ -+static inline void otg_req_state_chg (struct otg *otg, u32 params) -+{ -+ u32 temp, tmp2, flags; -+ -+ local_irq_save (flags); -+ -+ /* disable global OTG interrupt, clear int status: */ -+ temp = ~((u32) OTG_INT_GLOBAL) & readl (&otg->regs->inten); -+ writel (temp, &otg->regs->inten); -+ tmp2 = readl (&otg->regs->intr); -+ writel (tmp2, &otg->regs->intr); -+ temp &= tmp2; -+ -+ /* update OTG state: */ -+ otg_change_state (otg, (params | temp), &temp); -+ -+ /* enable global OTG interrupt: */ -+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/ -+/*** HS-A0 WA: BUG-3950: gadget needs disconnect notification ***/ -+#ifdef UDC_HSA0_WORKAROUNDS -+ state_mask = ~temp & OTG_INT_ADDS; -+ writel ((OTG_INT_ADDS | temp | OTG_INT_GLOBAL), &otg->regs->inten); -+#else -+ writel ((temp | OTG_INT_GLOBAL), &otg->regs->inten); -+#endif -+ local_irq_restore (flags); -+} -+#endif /* CONFIG_USB_OTG || CONFIG_USB_OTGMUX_GADGET */ -+ -+#ifdef CONFIG_USB_OTG_TEST_INTERFACE -+ -+/** -+ * \brief -+ * Bind the OTG controller to the test driver -+ * -+ * \param dev otg controller info -+ * -+ * \return error code -+ */ -+static int otg_test_bind (struct otg **otg) -+{ -+ *otg = the_controller; -+ if (!*otg) -+ return -EINVAL; -+#ifdef CONFIG_TEST_MODE_ONLY -+ INFO ("bind OTG driver to the test driver, enable device\n"); -+ SET_FLAG (*otg, OTG_HOST_READY | OTG_GADGET_READY); -+ if (IS_FLAG_SET (*otg, OTG_FLAGS_ACTIV)) { -+ otg_req_state_chg (*otg, OTG_HOST_READY | OTG_GADGET_READY); -+ } -+ (*otg)->transceiver.gadget = (struct usb_gadget *) 1; -+#else -+ INFO ("bind OTG driver to the test interface\n"); -+#endif -+ return 0; -+} -+ -+/** -+ * \brief -+ * Unbind the OTG controller from the test driver -+ * -+ * \param dev otg controller info -+ * -+ * \return error code -+ */ -+static int otg_test_unbind (struct otg **otg) -+{ -+#ifdef CONFIG_TEST_MODE_ONLY -+ INFO ("unbind OTG driver from the test driver, disable device\n"); -+ (*otg)->transceiver.gadget = NULL; -+ RES_FLAG (*otg, OTG_HOST_READY | OTG_GADGET_READY); -+ if (IS_FLAG_SET (*otg, OTG_FLAGS_ACTIV)) { -+ otg_req_state_chg (*otg, OTG_HOST_READY | OTG_GADGET_READY); -+ } -+ *otg = NULL; -+ return otg_unbind_gadget (); -+#else -+ INFO ("unbind OTG driver from the test interface\n"); -+ *otg = NULL; -+ return 0; -+#endif -+} -+#endif /* CONFIG_USB_OTG_TEST_INTERFACE */ -+ -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+/** -+ * \brief -+ * OTG set transceiver: -+ * -+ * \param pointer to transceiver struct -+ * -+ * \return void -+ */ -+int otg_set_transceiver (struct otg_transceiver *transceiver) -+{ -+ struct otg *otg = the_controller; -+ -+ if (unlikely (transceiver != otg_to_transceiver (otg))) { -+ ERR ("USB OTG: unknown transceiver\n"); -+ return -EINVAL; -+ } -+ else { -+ return 0; -+ } -+} -+ -+/** -+ * \brief -+ * OTG get transceiver: provide info to others -+ * -+ * \param void -+ * -+ * \return pointer to transceiver struct -+ */ -+struct otg_transceiver * otg_get_transceiver (void) -+{ -+ return otg_to_transceiver (the_controller); -+} -+#endif -+ -+#ifdef CONFIG_USB_OTG -+ -+/** -+ * \brief -+ * Bind/unbind the OTG controller to/from usbcore -+ * -+ * \param transceiver this transceiver -+ * \param bus usb bus the host is assigned to -+ * -+ * \return error code -+ */ -+static int otg1200_set_host (struct otg_transceiver *transceiver, -+ struct usb_bus *bus) -+{ -+ struct otg *otg = the_controller; -+ int flag, count = 0; -+ -+ if (unlikely (transceiver != otg_to_transceiver (otg))) { -+ ERR ("USB OTG: unknown transceiver\n"); -+ return -EINVAL; -+ } -+ if (bus) { -+ -+ /* This bus supports OTG */ -+ -+ if (transceiver->host) { -+ count++; -+ } -+#ifdef CONFIG_USB_OTG_HIGHSPEED -+ if (transceiver->companion) { -+ count++; -+ } -+ /* Now checking consistence ... */ -+ /* Depending on the driver loading sequence is possible */ -+ /* that the "Load state defaults" function was already */ -+ /* called so the state could be inconsistent. */ -+ if (transceiver->host && transceiver->companion) { -+ flag = (transceiver->host->is_b_host | -+ transceiver->companion->is_b_host); -+ if (transceiver->gadget && -+ !transceiver->gadget->is_a_peripheral) { -+ flag |= 1; -+ } -+ transceiver->host->is_b_host = flag; -+ transceiver->companion->is_b_host = flag; -+ } -+#endif -+ DBG ("USB OTG: bind host: bus %d, port %d (OTG host #%d)\n", -+ bus->busnum, bus->otg_port, count); -+ if (IS_FLAG_RES (otg, OTG_HOST_READY)) { -+ RES_FLAG (otg, OTG_A_BUS_DROP); -+ SET_FLAG (otg, OTG_HOST_READY | OTG_A_BUS_REQ); -+ if (IS_FLAG_SET (otg, OTG_FLAGS_ACTIV)) { -+ otg_req_state_chg (otg, OTG_HOST_READY); -+ } -+ } -+ } -+ else { -+#ifdef CONFIG_USB_OTG_HIGHSPEED -+ if (transceiver->companion) { -+ count++; -+ } -+#endif -+ if (transceiver->host) { -+ count++; -+ } -+ DBG ("USB OTG: unbind host (actual OTG hosts: %d)\n", count); -+ if (!count) { -+ RES_FLAG (otg, OTG_HOST_READY | OTG_A_BUS_REQ); -+ SET_FLAG (otg, OTG_A_BUS_DROP); -+ if (IS_FLAG_SET (otg, OTG_FLAGS_ACTIV)) { -+ otg_req_state_chg (otg, OTG_HOST_READY); -+ } -+ } -+ } -+ return 0; -+} -+#endif /* CONFIG_USB_OTG */ -+ -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+/** -+ * \brief -+ * Bind/unbind the OTG controller to/from usb gadget -+ * -+ * \param transceiver this transceiver -+ * \param gadget usb gadget info -+ * -+ * \return error code -+ */ -+static int otg1200_set_peripheral (struct otg_transceiver *transceiver, -+ struct usb_gadget *gadget) -+{ -+ struct otg *otg = the_controller; -+ int flag = 0; -+ -+ if (unlikely (transceiver != otg_to_transceiver (otg))) { -+ ERR ("USB OTG: unknown transceiver\n"); -+ return -EINVAL; -+ } -+ if (gadget) { -+ if (transceiver->gadget) { -+ ERR ("USB gadget: OTG driver already registered\n"); -+ return -EBUSY; -+ } -+ DBG ("bind OTG driver to USB gadget\n"); -+ transceiver->gadget = gadget; -+ SET_FLAG (otg, OTG_GADGET_READY | OTG_B_BUS_REQ); -+ -+ /* Now checking consistence ... */ -+ /* Depending on the driver loading sequence is possible */ -+ /* that the "Load state defaults" function was already */ -+ /* called so the state could be inconsistent. */ -+#ifdef CONFIG_USB_OTG_HIGHSPEED -+ if (transceiver->companion && -+ !transceiver->companion->is_b_host) { -+ flag |= 1; -+ } -+#endif -+ if (transceiver->host && !transceiver->host->is_b_host) { -+ flag |= 1; -+ } -+ transceiver->gadget->is_a_peripheral = flag; -+ -+ if (IS_FLAG_SET (otg, OTG_FLAGS_ACTIV)) { -+ otg_req_state_chg (otg, OTG_GADGET_READY); -+ } -+ if (IS_BIT_SET (OTG_STS_SESSVLD, readl (&otg->regs->sts)) && -+ (otg->transceiver.state & OTG_STATE_MASK) -+ == OTG_STATE_B_PERIPHERAL) { -+ VDBG ("calling gadget: connect\n"); -+ if (otg_gadget_extension.notify) { -+ otg_gadget_extension.notify ( -+ OTG_GADGET_EVT_SVALID); -+ } -+ } -+ return 0; -+ } -+ else { -+ DBG ("unbind OTG driver from USB gadget\n"); -+ RES_FLAG (otg, OTG_GADGET_READY | OTG_B_BUS_REQ); -+ if (IS_FLAG_SET (otg, OTG_FLAGS_ACTIV)) { -+ otg_req_state_chg (otg, OTG_GADGET_READY); -+ } -+ transceiver->gadget = NULL; -+ return 0; -+ } -+} -+#endif /* CONFIG_USB_OTGMUX || CONFIG_USB_OTGMUX_GADGET */ -+ -+#ifdef CONFIG_USB_OTG -+ -+/** -+ * \brief -+ * Set host controllers power budget -+ * -+ * \param transceiver this transceiver -+ * \param mA value to fill in -+ * -+ * \return error code -+ */ -+static int otg1200_set_power (struct otg_transceiver *transceiver, -+ unsigned mA) -+{ -+ struct otg *otg = the_controller; -+ -+ if (unlikely (transceiver != otg_to_transceiver (otg))) { -+ ERR ("USB OTG: unknown transceiver\n"); -+ return -EINVAL; -+ } -+ /* TODO kboge: do we need to support this ? */ -+ -+ DBG ("USB OTG: power budget change not supported\n"); -+ return 0; -+} -+ -+/** -+ * \brief -+ * Start a HNP request -+ * -+ * \param transceiver this transceiver -+ * -+ * \return error code -+ */ -+static int otg1200_start_hnp (struct otg_transceiver *transceiver) -+{ -+ struct otg *otg = the_controller; -+ -+ if (unlikely (transceiver != otg_to_transceiver (otg))) { -+ ERR ("USB OTG: unknown transceiver\n"); -+ return -ENODEV; -+ } -+ if (transceiver->default_a -+ && (!transceiver->host || !transceiver->host->b_hnp_enable) -+#ifdef CONFIG_USB_OTG_HIGHSPEED -+ && (!transceiver->companion || !transceiver->companion->b_hnp_enable) -+#endif -+ ) -+ return -ENOTCONN; -+ if (!transceiver->default_a && -+ (!transceiver->gadget || !transceiver->gadget->b_hnp_enable)) -+ return -ENOTCONN; -+ -+ switch (transceiver->state & OTG_STATE_MASK) { -+ case OTG_STATE_B_HOST: -+ case OTG_STATE_A_HOST: -+ case OTG_STATE_A_PERIPHERAL: -+ break; -+ default: -+ ERR ("USB OTG: wrong OTG state for role swap\n"); -+ return -EILSEQ; -+ } -+ return 0; -+} -+ -+/** -+ * \brief -+ * Start a SRP request -+ * -+ * \param transceiver this transceiver -+ * -+ * \return error code -+ */ -+static int otg1200_start_srp (struct otg_transceiver *transceiver) -+{ -+ struct otg *otg = the_controller; -+ -+ if (unlikely (transceiver != otg_to_transceiver (otg))) { -+ ERR ("USB OTG: unknown transceiver\n"); -+ return -EINVAL; -+ } -+ if ((transceiver->state & OTG_STATE_MASK) != OTG_STATE_B_IDLE) { -+ RES_FLAG (otg, OTG_B_aSSN_REQ); -+ ERR ("USB OTG: wrong OTG state for SRP\n"); -+ return -EBUSY; -+ } -+ SET_FLAG (otg, OTG_B_aSSN_REQ); -+ otg_req_state_chg (otg, OTG_B_aSSN_REQ); -+ return 0; -+} -+ -+/** -+ * \brief -+ * Start a USB host enumeration -+ * -+ * \param transceiver this transceiver -+ * -+ * \return error code -+ */ -+int otg_hnp_start_enum (struct otg_transceiver *transceiver) -+{ -+ struct otg *otg = the_controller; -+ struct usb_bus *bus; -+ int status = 0; -+ -+ if (unlikely (transceiver != otg_to_transceiver (otg))) { -+ ERR ("USB OTG: unknown transceiver\n"); -+ return -EINVAL; -+ } -+ if (otg->transceiver.state == OTG_STATE_B_HOST) { -+ -+ bus = otg->transceiver.host; -+ -+#ifdef CONFIG_USB_OTG_HIGHSPEED -+ -+ if (!bus || !bus->is_b_host) { -+ bus = otg->transceiver.companion; -+ } -+#endif -+ if (bus && bus->is_b_host) { -+ DBG ("USB OTG: in HNP, start enumeration ...\n"); -+ status = usb_bus_start_enum (bus, bus->otg_port); -+ } -+ else { -+ DBG ("USB OTG: no device to enumerate\n"); -+ } -+ } -+ else { -+ DBG ("USB OTG: in HNP: wrong state %02x\n", -+ otg->transceiver.state); -+ } -+ return status; -+} -+ -+/** -+ * \brief -+ * OTG application request -+ * -+ * \param params -+ * -+ * \return OTG_APP_REQ_ACK -+ */ -+static int otg_app_request (u32 params) -+{ -+ struct otg *otg = the_controller; -+ u32 flags = params; -+ struct usb_bus *bus; -+ -+ if (OTG_UDC_RWK_REQ & flags) { -+ -+ if (otg_gadget_extension.notify) { -+ otg_gadget_extension.notify (OTG_GADGET_REQ_WAKE); -+ } -+ flags &= ~((u32) OTG_UDC_RWK_REQ); -+ } -+ -+ if (OTG_AB_HNP_REQ & flags) { -+ -+ /* request HNP */ -+ -+ bus = otg->transceiver.host; -+ if (!bus->b_hnp_enable) { -+ -+#ifdef CONFIG_USB_OTG_HIGHSPEED -+ bus = otg->transceiver.companion; -+ } -+ if (!bus->b_hnp_enable) { -+#endif -+ INFO ("HNP not enabled, ignoring request\n"); -+ } -+ else { -+ if (!otg1200_start_hnp (&otg->transceiver) && -+ bus->root_hub->children [bus->otg_port - 1]) { -+ usb_suspend_device (bus->root_hub->children [bus->otg_port - 1], -+ PM_SUSPEND_MEM); -+ } -+ else { -+ ERR ("no device found for HNP\n"); -+ } -+ } -+ flags &= ~((u32) OTG_AB_HNP_REQ); -+ } -+ -+ if (OTG_A_CLR_ERR & flags) { -+ -+ /* request to clear error flags */ -+ -+ flags |= OTG_A_VBUS_FAILED; -+ } -+ -+ /* create mask of flags to clear */ -+ -+ flags &= (OTG_B_SRP_ERROR | OTG_A_VBUS_FAILED); -+ -+ if (flags) { -+ -+ /* reset error flags if requested */ -+ -+ RES_FLAG (otg, (flags)); -+ } -+ -+ /* prepare for pending requests (no more actions on OTG_A_bHNP_EN) */ -+ -+ flags = params & SW_REQUEST_MASK; -+ SET_FLAG (otg, (flags)); -+ -+ if (OTG_A_BUS_DROP & flags) { -+ -+ /* request to drop A-VBus: reset "rise" request if pending */ -+ -+ flags &= ~OTG_A_BUS_REQ; -+ RES_FLAG (otg, OTG_A_BUS_REQ); -+ } -+ if (OTG_A_BUS_REQ & flags) { -+ -+ /* request to rise A-VBus: reset "drop" request if pending */ -+ -+ RES_FLAG (otg, OTG_A_BUS_DROP); -+ } -+ if (OTG_B_BUS_DIS & flags) { -+ -+ /* request to disable B-dev: reset "ena" request if pending */ -+ -+ flags &= ~OTG_B_BUS_REQ; -+ RES_FLAG (otg, OTG_B_BUS_REQ); -+ } -+ if (OTG_B_BUS_REQ & flags) { -+ -+ /* request to enable B-dev: reset "disa" request if pending */ -+ -+ RES_FLAG (otg, OTG_B_BUS_DIS); -+ } -+ if (flags) { -+ -+ /* request still pending may force a state change */ -+ -+ otg_req_state_chg (otg, flags); -+ } -+ return OTG_APP_REQ_ACK; -+} -+#endif /* CONFIG_USB_OTG */ -+ -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+/** -+ * \brief -+ * OTG application query -+ * -+ * \param index select status info data -+ * -+ * \return status -+ */ -+static u32 otg_app_query (int index) -+{ -+ struct otg *otg = the_controller; -+ u32 temp = 0; -+ -+ if (index == 0) { -+ temp = otg->params | -+ readl (&otg->regs->sts); -+ -+/*** HS-A0 WA: BUG-3943: gadget phy suspend issue ***/ -+#ifdef UDC_HSA0_WORKAROUNDS -+ if (((readl (&otg->regs->ctl) & OTG_CTL_MUX_MASK) == -+ OTG_CTL_ENABLE_UDC) && -+ ((temp & OTG_STS_PSUS) || (~temp & OTG_STS_VBUSVLD))) { -+ temp |= OTG_FLAGS_UDC_SUSP; -+ } -+#endif -+ } -+ else if (index == 1) { -+ temp = otg->transceiver.state; -+ } -+#ifdef OTG_HNP_ERR_LOG -+ if (hnp_err) { -+ temp |= OTG_FLAGS_HNP_ERR; -+ } -+#endif -+ return temp; -+} -+ -+/** -+ * \brief -+ * OTG ISR calling the main state machine -+ * -+ * \param irq IRQ number -+ * \param _dev -+ * \param r -+ * -+ * \return IRQ_HANDLED (system code) -+ */ -+static irqreturn_t otg_isr (int irq, void *dev, struct pt_regs *r) -+{ -+ struct otg *otg = (struct otg *) dev; -+ u32 interrupts, int_mask, temp; -+ -+ int_mask = readl (&otg->regs->inten); -+ if ((OTG_INT_GLOBAL & int_mask) && -+ (int_mask &= ~((u32) OTG_INT_GLOBAL)) && -+ (interrupts = int_mask & -+ (temp = readl (&otg->regs->intr)))) { -+ -+ writel (int_mask, &otg->regs->inten); -+ /* clear interrupt status */ -+ writel (temp, &otg->regs->intr); -+/* -+#ifdef CONFIG_USB_OTG -+ -+ if (GOT_EVENT (OTG_INT_PCC, interrupts) && -+ IS_BIT_SET (OTG_STS_PCON, readl (&otg->regs->sts))) { -+ otg_hnp_start_enum (&otg->transceiver); -+ } -+#endif */ -+ /* filter out additional WA interrupts, they're done */ -+ /* don't want to see them in the state machine */ -+ -+ if (interrupts & ~state_mask) { -+ -+ /* events pending for the state machine */ -+ -+ otg_change_state (otg, (interrupts & ~state_mask), -+ &int_mask); -+ } -+ -+ /* enable interrupts and keep information about WA ints: */ -+ -+ state_mask = OTG_INT_ADDS & ~int_mask; -+ writel ((OTG_INT_ADDS | int_mask | OTG_INT_GLOBAL), -+ &otg->regs->inten); -+ } -+ return IRQ_HANDLED; -+} -+#endif /* CONFIG_USB_OTG || CONFIG_USB_OTGMUX_GADGET */ -+ -+/** -+ * \brief -+ * OTG probe: init hardware, register the driver -+ * -+ * \param otg otg controller info -+ * -+ * \return success -+ */ -+static inline int __init otg_probe (struct otg *otg) -+{ -+ int retval; -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ u32 temp; -+ int i; -+#endif -+ -+ /* initialize the OTG controller */ -+ -+ VDBG ("OTG init ...\n"); -+ -+#ifdef VERBOSE -+ /* print regs */ -+ print_regs (otg); -+#endif -+ /* Make sure we'll remember the initial state */ -+ init_state = readl (&otg->regs->ctl); -+ VDBG (" OTG init state was %08x\n", init_state); -+ -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+ /* turn on the OTG controller */ -+ -+ writel ((init_state | OTG_CTL_PADEN), &otg->regs->ctl); -+ -+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/ -+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/ -+#ifndef UDC_HSA0_WORKAROUNDS -+ -+ /* Enable OTG hardware (incl. auto pull-up enable) */ -+ -+ writel ((readl (&dev->regs->cap) | OTG_CAP_APU), &otg->regs->cap); -+#endif -+ -+ /* initialize flags */ -+ otg->params = 0; -+#endif -+ -+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/ -+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/ -+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/ -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+ /* make sure all interrupts are disabled */ -+ -+ writel (OTG_INT_DISALL, &otg->regs->inten); -+ writel (OTG_INT_ENALL, &otg->regs->intr); -+ -+ /* Set multiplexer to neutral, get power control, drop VBus */ -+ -+ if (((init_state & OTG_CTL_MUX_MASK) == OTG_CTL_ENABLE_UHC) && -+ ((((init_state & OTG_CTL_PPO) && (init_state & OTG_CTL_PPWR))) || -+ ((~init_state & OTG_CTL_PPO) && -+ (readl (&otg->regs->sts) & OTG_STS_SESSVLD)))) { -+ -+ /* VBus still powered try to discharge VBus and set timer */ -+ -+ DBG ("Setting init state, trying to discharge VBus ...\n"); -+ -+ for (i = 0; i < 4; i++) { -+ writel (TIMER_PERIOD, &otg->regs->tmr); -+ writel ((OTG_CTL_PADEN | OTG_CTL_IDSNSEN | -+ OTG_CTL_PPO | OTG_CTL_DISCHRG | -+ OTG_CTL_TMR_UNCOND), &otg->regs->ctl); -+ do { } -+ while (!(readl (&otg->regs->sts) & OTG_STS_TMH)); -+ } -+ writel ((OTG_CTL_PADEN | OTG_CTL_IDSNSEN | OTG_CTL_PPO), -+ &otg->regs->ctl); -+ writel (OTG_INT_ENALL, &otg->regs->intr); -+#ifdef DEBUG -+ if (readl (&otg->regs->sts) & OTG_STS_SESSVLD) { -+ -+ DBG (" VBus still high, external host connected\n"); -+ } -+ else { -+ -+ DBG (" VBus discharged\n"); -+ } -+#endif -+ } -+ else { -+ DBG ("Setting init state\n"); -+ -+ writel ((OTG_CTL_PADEN | OTG_CTL_IDSNSEN | OTG_CTL_PPO), -+ &otg->regs->ctl); -+ } -+#endif /* CONFIG_USB_OTG || CONFIG_USB_OTGMUX_GADGET */ -+ -+#ifdef CONFIG_USB_OTGMUX_HOST -+ -+ /* Set multiplexer to host */ -+ writel ((readl (&otg->regs->cap) & ~((u32) OTG_CAP_APU)), -+ &otg->regs->cap); -+ -+#ifdef CONFIG_SOC_AU1200 -+ -+ writel ((OTG_CTL_ENABLE_UHC | OTG_CTL_PPO | OTG_CTL_PPWR), -+ &otg->regs->ctl); -+ -+ /* Turn on VBus */ -+ AU1000GPIO_CLR_BIT (USB_VBUS_GPIO); -+#else -+ writel (OTG_CTL_ENABLE_UHC, &otg->regs->ctl); -+#endif -+ -+ INFO ("OTG functionality is disabled, port is assigned to host\n"); -+#endif -+ VDBG ("OTG init done\n"); -+ -+#ifdef CONFIG_USB_OTG_TEST_INTERFACE -+ -+ /* registering to the test driver */ -+ usb_otg_test_register_driver (&otg_test_extension); -+#endif -+#ifndef CONFIG_TEST_MODE_ONLY -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+ /* registering to the device driver */ -+ if (usb_gadget_register_otg (otg_get_transceiver)) { -+ ERR ("gadget driver registration failed\n"); -+ retval = -ENODEV; -+ goto err1; -+ } -+#endif -+#ifdef CONFIG_USB_OTG -+ -+ /* registering to the usbcore */ -+ if (usb_host_register_otg (otg_get_transceiver)) { -+ ERR ("usbcore registration failed\n"); -+ retval = -ENODEV; -+ goto err2; -+ } -+#endif -+#endif -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+ /* finally activate OTG functionality */ -+ /* Enable timer interrupt, start timer, set state */ -+ -+ SET_OTG_TIMER (otg, IDSNS_WAIT); -+ CHANGE_STATE (otg, OTG_STATE_UNDEFINED, &temp); -+ CHECK_STATE (otg, OTG_STATE_UNDEFINED, &temp); -+ -+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/ -+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/ -+/*** HS-A0 WA: BUG-3950: gadget needs disconnect notification ***/ -+ -+ /* clear all interrupts before enable */ -+ writel (readl (&otg->regs->intr), &otg->regs->intr); -+ -+ state_mask = ~temp & OTG_INT_ADDS; -+ writel ((OTG_INT_ADDS | temp | OTG_INT_GLOBAL), &otg->regs->inten); -+ -+ DBG ("OTG-HW initialized, now checking ID ...\n"); -+#endif -+ -+ return 0; -+ -+#ifndef CONFIG_TEST_MODE_ONLY -+#ifdef CONFIG_USB_OTG -+ -+err2: -+ -+#endif -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+ usb_gadget_unregister_otg (); -+err1: -+ -+#endif -+#endif -+#ifdef CONFIG_USB_OTG_TEST_INTERFACE -+ -+ usb_otg_test_unregister_driver (); -+#endif -+ return retval; -+} -+ -+/** -+ * \brief -+ * OTG remove: deregister the driver, clean-up hardware -+ * -+ * \param otg otg controller info -+ * -+ * \return void -+ */ -+static inline void __exit otg_remove (struct otg *otg) -+{ -+ int muxer; -+ -+#ifndef CONFIG_TEST_MODE_ONLY -+#ifdef CONFIG_USB_OTG -+ -+ /* unregistering from the usb core */ -+ usb_host_deregister_otg (); -+#endif -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+ /* unregistering from the usb gadget */ -+ usb_gadget_unregister_otg (); -+ -+#endif -+#endif -+#ifdef CONFIG_USB_OTG_TEST_INTERFACE -+ -+ /* unregistering from the test driver */ -+ usb_otg_test_unregister_driver (); -+#endif -+ -+ /* clean up the OTG controller */ -+ -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+ /* Disable all interrupts */ -+ writel (OTG_INT_DISALL, &otg->regs->inten); -+ writel (OTG_INT_ENALL, &otg->regs->intr); -+ -+ /* reset state, terminate all connections */ -+ CHANGE_STATE (otg, OTG_STATE_UNDEFINED, &state_mask); -+ CHECK_STATE (otg, OTG_STATE_UNDEFINED, &state_mask); -+ otg->params = 0; -+#endif -+ -+ muxer = init_state & (OTG_CTL_ENABLE_UHC | OTG_CTL_ENABLE_UDC); -+ -+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/ -+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/ -+#ifdef UDC_HSA0_WORKAROUNDS -+ -+ /* Don't assign the port to the device controller */ -+ -+ if (!(muxer ^ OTG_CTL_ENABLE_UDC)) { -+ -+ init_state &= ~((u32) (OTG_CTL_MUX_MASK | OTG_CTL_PUEN)); -+ muxer = OTG_CTL_DISABLE_ALL; -+ } -+ VDBG ("OTG writing back corrected init state: %08x\n", init_state); -+#else -+ /* Reset APU */ -+ -+ writel ((readl (&otg->regs->cap) & ~((u32) OTG_CAP_APU)), -+ &otg->regs->cap); -+ -+ VDBG ("OTG writing back init state: %08x\n", init_state); -+#endif -+ /* Now, that's the moment to remember */ -+ /* Set dev muxer and pull up bits, turn off the OTG controller */ -+ -+#ifdef CONFIG_SOC_AU1200 -+ -+ /* Turn off VBus */ -+ AU1000GPIO_SET_BIT (USB_VBUS_GPIO); -+#endif -+ writel (init_state, &otg->regs->ctl); -+ -+ if (!(muxer ^ OTG_CTL_ENABLE_UHC)) { -+ INFO ("disabling OTG-HW, port is assigned to host\n"); -+ } -+ else if (!(muxer ^ OTG_CTL_ENABLE_UDC)) { -+ INFO ("disabling OTG-HW, port is assigned to device\n"); -+ } -+ else { -+ INFO ("disabling OTG-HW, port is not assigned\n"); -+ } -+ -+ VDBG ("OTG exit: OTG-HW disabled\n"); -+ -+ if (!muxer) { -+ INFO ("OTG HW disabled, port is not assigned\n"); -+ } -+} -+ -+#ifdef CONFIG_SOC_AU1200 -+#ifdef USE_AU1200_PCI_DUMMY -+ -+/** -+ * \brief -+ * OTG dev probe: enable, init controller hardware -+ * -+ * \param pdev dummy pci device pointer -+ * -+ * \return success -+ */ -+static int __init otg_pci_probe (struct pci_dev *pdev) -+{ -+ struct otg *otg; -+ void *base; -+ int retval; -+ char buf [8] = {0,0,0,0,0,0,0,0}, *bufp; -+ -+ /* alloc, and start init */ -+ otg = (struct otg *) kmalloc (sizeof(struct otg), SLAB_KERNEL); -+ if (!otg) { -+ ERR ("couldn't allocate memory for OTG driver\n"); -+ retval = -ENOMEM; -+ goto err1; -+ } -+ DBG ( "kmalloc: OTG driver: %p\n", otg); -+ -+ /* hold global device pointer */ -+ the_controller = otg; -+ -+ memset (otg, 0, sizeof(struct otg)); -+ spin_lock_init (&otg->lock); -+ -+ /* -+ * Fill in the dummy pci_dev. Only those members actually -+ * dereferenced in this driver are initialized. -+ */ -+ memset(pdev, 0, sizeof(struct pci_dev)); -+ pdev->resource[0].name = "UOC Registers"; -+ pdev->resource[0].start = USB_UOC_BASE; -+ pdev->resource[0].end = USB_UOC_BASE + USB_UOC_LEN - 1; -+ pdev->resource[0].flags = 0; -+ pdev->irq = AU1200_USB_INT; -+ -+ otg->pdev = pdev; -+ -+ au_writel ((au_readl (USB_MSR_BASE + USB_MSR_MCFG) | -+ (1 << USBMSRMCFG_GMEMEN)), (USB_MSR_BASE + USB_MSR_MCFG)); -+ au_readl (USB_MSR_BASE + USB_MSR_MCFG); -+ /* au_sync (); */ -+ udelay (1000); -+ if (AU1000GPIO_INIT_BIT (USB_VBUS_GPIO)) -+ WARN ("Couldn't initialize power switch GPIO\n"); -+ otg->enabled = 1; -+ -+ if (!request_mem_region (pdev->resource[0].start, -+ pdev->resource[0].end + 1 -+ - pdev->resource[0].start, -+ driver_name)) { -+ ERR ("controller already in use\n"); -+ retval = -EBUSY; -+ goto err3; -+ } -+ otg->region = 1; -+ -+ base = ioremap_nocache (pdev->resource[0].start, -+ pdev->resource[0].end + 1 -+ - pdev->resource[0].start); -+ if (!base) { -+ ERR ("couldn't map memory\n"); -+ retval = -EFAULT; -+ goto err4; -+ } -+ otg->regs = (struct otg_regs *) base; -+ bufp = buf; -+ -+ otg->chiprev = (u16) read_c0_prid() & 0xff; -+ -+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/ -+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/ -+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/ -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+ /* OTG transceiver info */ -+ otg->transceiver.dev = &pdev->dev; -+ otg_init_transceiver (otg_to_transceiver (otg)); -+ -+ /* make sure all interrupts are disabled */ -+ writel (OTG_INT_DISALL, &otg->regs->inten); -+ writel (OTG_INT_ENALL, &otg->regs->intr); -+ readl (&otg->regs->inten); -+ -+ /* irq setup after old hardware is cleaned up */ -+ if (!pdev->irq) { -+ ERR ("No IRQ. Check system setup!\n"); -+ retval = -ENODEV; -+ goto err5; -+ } -+ snprintf (buf, sizeof buf, "%d", pdev->irq); -+ bufp = buf; -+ if (request_irq (pdev->irq, otg_isr, SA_INTERRUPT | SA_SHIRQ, -+ driver_name, otg) != 0) { -+ ERR ("request interrupt %s failed\n", bufp); -+ retval = -EBUSY; -+ goto err5; -+ } -+ otg->got_irq = 1; -+ -+ /* done */ -+ INFO ("%s\n", driver_desc); -+ INFO ("irq %s, mem %08lx, chip rev %02x (Au1200 %s)\n", -+ bufp, pdev->resource[0].start, otg->chiprev, -+ (otg->chiprev ? "AC" : "AB")); -+ -+#else /* CONFIG_USB_OTG || CONFIG_USB_OTGMUX_GADGET */ -+ -+ INFO ("%s\n", driver_desc); -+ INFO ("mem %08lx, chip rev %02x (Au1200 %s)\n", -+ pdev->resource[0].start, otg->chiprev, -+ (otg->chiprev ? "AC" : "AB")); -+#endif -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_IDPIN) || defined(CONFIG_USB_OTGMUX_HOST) -+ -+ INFO ("using GPIO_%d for VBus control\n", USB_VBUS_GPIO); -+#endif -+ bufp = DRIVER_VERSION; -+ INFO ("driver version: %s\n", bufp); -+ -+ if ((retval = otg_probe (otg)) == 0) { -+ pci_set_drvdata (pdev, otg); -+ return 0; -+ } -+ -+ /* something went wrong */ -+ -+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/ -+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/ -+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/ -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+ otg->got_irq = 0; -+ free_irq (pdev->irq, otg); -+err5: -+ -+#endif -+ otg->regs = NULL; -+ iounmap (base); -+err4: -+ otg->region = 0; -+ release_mem_region (pdev->resource[0].start, -+ pdev->resource[0].end + 1 -+ - pdev->resource[0].start); -+err3: -+ otg->enabled = 0; -+ AU1000GPIO_TERM_BIT (USB_VBUS_GPIO); -+ au_writel ((au_readl (USB_MSR_BASE + USB_MSR_MCFG) & -+ ~((u32) (1 << USBMSRMCFG_GMEMEN))), -+ (USB_MSR_BASE + USB_MSR_MCFG)); -+ au_readl (USB_MSR_BASE + USB_MSR_MCFG); -+ /* au_sync (); */ -+ udelay (1000); -+ -+ otg->pdev = NULL; -+ the_controller = NULL; -+ DBG ( "kfree: OTG driver: %p\n", otg); -+ kfree (otg); -+err1: -+ otg = NULL; -+ return retval; -+} -+ -+/** -+ * \brief -+ * OTG dev remove: clean-up, disable controller hardware -+ * -+ * \param pdev dummy pci device info -+ * -+ * \return void -+ */ -+static void __exit otg_pci_remove (struct pci_dev *pdev) -+{ -+ struct otg *otg = pci_get_drvdata (pdev); -+ -+ otg_remove (otg); -+ -+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/ -+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/ -+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/ -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+ otg->got_irq = 0; -+ free_irq (pdev->irq, otg); -+#endif -+ iounmap (otg->regs); -+ otg->regs = NULL; -+ otg->region = 0; -+ release_mem_region (pdev->resource[0].start, -+ pdev->resource[0].end + 1 -+ - pdev->resource[0].start); -+ otg->enabled = 0; -+ AU1000GPIO_TERM_BIT (USB_VBUS_GPIO); -+/* au_writel ((au_readl (USB_MSR_BASE + USB_MSR_MCFG) & -+ ~((u32) (1 << USBMSRMCFG_GMEMEN))), -+ (USB_MSR_BASE + USB_MSR_MCFG)); */ -+ au_readl (USB_MSR_BASE + USB_MSR_MCFG); -+ /* au_sync (); */ -+ udelay (1000); -+ otg->pdev = NULL; -+ the_controller = NULL; -+ DBG ( "kfree: OTG driver: %p\n", otg); -+ kfree (otg); -+ otg = NULL; -+ pci_set_drvdata(pdev, NULL); -+} -+#else -+ -+/** -+ * \brief -+ * OTG dev probe: enable, init controller hardware -+ * -+ * \param dev platform device info -+ * -+ * \return success -+ */ -+static int __init otg_drv_probe (struct device *dev) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct otg *otg; -+ u32 resource, len, irq; -+ void *base; -+ int retval; -+ char buf [8] = {0,0,0,0,0,0,0,0}, *bufp; -+ -+ /* alloc, and start init */ -+ otg = (struct otg *) kmalloc (sizeof(struct otg), SLAB_KERNEL); -+ if (!otg) { -+ ERR ("couldn't allocate memory for OTG driver\n"); -+ retval = -ENOMEM; -+ goto err1; -+ } -+ DBG ( "kmalloc: OTG driver: %p\n", otg); -+ -+ /* hold global device pointer */ -+ the_controller = otg; -+ -+ memset (otg, 0, sizeof(struct otg)); -+ spin_lock_init (&otg->lock); -+ -+ if (pdev->resource[0].flags != IORESOURCE_MEM) { -+ ERR ("resource is not IORESOURCE_MEM\n"); -+ retval = -ENOMEM; -+ goto err2; -+ } -+ resource = pdev->resource[0].start; -+ len = pdev->resource[0].end + 1 - pdev->resource[0].start; -+ if (pdev->resource[1].flags != IORESOURCE_IRQ) { -+ ERR ("resource is not IORESOURCE_IRQ\n"); -+ retval = -ENOMEM; -+ goto err2; -+ } -+ irq = pdev->resource[1].start; -+ -+ otg->pdev = pdev; -+ -+ au_writel ((au_readl (USB_MSR_BASE + USB_MSR_MCFG) | -+ (1 << USBMSRMCFG_GMEMEN)), (USB_MSR_BASE + USB_MSR_MCFG)); -+ au_readl (USB_MSR_BASE + USB_MSR_MCFG); -+ /* au_sync (); */ -+ udelay (1000); -+ if (AU1000GPIO_INIT_BIT (USB_VBUS_GPIO)) -+ WARN ("Couldn't initialize power switch GPIO\n"); -+ otg->enabled = 1; -+ -+ if (!request_mem_region (resource, len, driver_name)) { -+ ERR ("controller already in use\n"); -+ retval = -EBUSY; -+ goto err3; -+ } -+ otg->region = 1; -+ -+ base = ioremap_nocache (resource, len); -+ if (!base) { -+ ERR ("couldn't map memory\n"); -+ retval = -EFAULT; -+ goto err4; -+ } -+ otg->regs = (struct otg_regs *) base; -+ bufp = buf; -+ -+ otg->chiprev = (u16) read_c0_prid() & 0xff; -+ -+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/ -+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/ -+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/ -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+ /* OTG transceiver info */ -+ otg->transceiver.dev = dev; -+ otg_init_transceiver (otg_to_transceiver (otg)); -+ -+ /* make sure all interrupts are disabled */ -+ writel (OTG_INT_DISALL, &otg->regs->inten); -+ writel (OTG_INT_ENALL, &otg->regs->intr); -+ readl (&otg->regs->inten); -+ -+ /* irq setup after old hardware is cleaned up */ -+ if (!irq) { -+ ERR ("No IRQ. Check system setup!\n"); -+ retval = -ENODEV; -+ goto err5; -+ } -+ snprintf (buf, sizeof buf, "%d", irq); -+ bufp = buf; -+ if (request_irq (irq, otg_isr, SA_INTERRUPT | SA_SHIRQ, -+ driver_name, otg) != 0) { -+ ERR ("request interrupt %s failed\n", bufp); -+ retval = -EBUSY; -+ goto err5; -+ } -+ otg->got_irq = 1; -+ -+ /* done */ -+ INFO ("%s\n", driver_desc); -+ INFO ("irq %s, mem %08x, chip rev %02x (Au1200 %s)\n", -+ bufp, resource, otg->chiprev, (otg->chiprev ? "AC" : "AB")); -+ -+#else /* CONFIG_USB_OTG || CONFIG_USB_OTGMUX_GADGET */ -+ -+ INFO ("%s\n", driver_desc); -+ INFO ("mem %08x, chip rev %02x (Au1200 %s)\n", -+ resource, otg->chiprev, (otg->chiprev ? "AC" : "AB")); -+#endif -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_IDPIN) || defined(CONFIG_USB_OTGMUX_HOST) -+ -+ INFO ("using GPIO_%d for VBus control\n", USB_VBUS_GPIO); -+#endif -+ bufp = DRIVER_VERSION; -+ INFO ("driver version: %s\n", bufp); -+ -+ if ((retval = otg_probe (otg)) == 0) { -+ dev_set_drvdata (dev, otg); -+ return 0; -+ } -+ -+ /* something went wrong */ -+ -+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/ -+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/ -+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/ -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+ otg->got_irq = 0; -+ free_irq (irq, otg); -+err5: -+ -+#endif -+ otg->regs = NULL; -+ iounmap (base); -+err4: -+ otg->region = 0; -+ release_mem_region (resource, len); -+err3: -+ otg->enabled = 0; -+ AU1000GPIO_TERM_BIT (USB_VBUS_GPIO); -+ au_writel ((au_readl (USB_MSR_BASE + USB_MSR_MCFG) & -+ ~((u32) (1 << USBMSRMCFG_GMEMEN))), -+ (USB_MSR_BASE + USB_MSR_MCFG)); -+ au_readl (USB_MSR_BASE + USB_MSR_MCFG); -+ /* au_sync (); */ -+ udelay (1000); -+err2: -+ otg->pdev = NULL; -+ the_controller = NULL; -+ DBG ( "kfree: OTG driver: %p\n", otg); -+ kfree (otg); -+err1: -+ otg = NULL; -+ -+ return retval; -+} -+ -+/** -+ * \brief -+ * OTG dev remove: clean-up, disable controller hardware -+ * -+ * \param dev platform device info -+ * -+ * \return void -+ */ -+static int __exit otg_drv_remove (struct device *dev) -+{ -+ struct platform_device *pdev = to_platform_device(dev); -+ struct otg *otg = dev_get_drvdata (dev); -+ -+ otg_remove (otg); -+ -+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/ -+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/ -+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/ -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+ otg->got_irq = 0; -+ free_irq (pdev->resource[1].start, otg); -+#endif -+ iounmap (otg->regs); -+ otg->regs = NULL; -+ otg->region = 0; -+ release_mem_region (pdev->resource[0].start, -+ pdev->resource[0].end + 1 -+ - pdev->resource[0].start); -+ otg->enabled = 0; -+ AU1000GPIO_TERM_BIT (USB_VBUS_GPIO); -+/* au_writel ((au_readl (USB_MSR_BASE + USB_MSR_MCFG) & -+ ~((u32) (1 << USBMSRMCFG_GMEMEN))), -+ (USB_MSR_BASE + USB_MSR_MCFG)); */ -+ au_readl (USB_MSR_BASE + USB_MSR_MCFG); -+ /* au_sync (); */ -+ udelay (1000); -+ otg->pdev = NULL; -+ the_controller = NULL; -+ DBG ( "kfree: OTG driver: %p\n", otg); -+ kfree (otg); -+ otg = NULL; -+ dev_set_drvdata(dev, NULL); -+ return 0; -+} -+#endif -+#else -+#ifdef CONFIG_PCI -+ -+/** -+ * \brief -+ * OTG PCI probe: enable, init controller hardware -+ * -+ * \param pdev pci device info -+ * \param id pci ids -+ * -+ * \return success -+ */ -+static int __init otg_pci_probe (struct pci_dev *pdev, -+ const struct pci_device_id *id) -+{ -+ struct otg *otg; -+ u32 resource, len; -+ void *base; -+ int retval; -+ char buf [8] = {0,0,0,0,0,0,0,0}, *bufp; -+ -+ /* alloc, and start init */ -+ otg = (struct otg *) kmalloc (sizeof(struct otg), SLAB_KERNEL); -+ if (!otg) { -+ ERR ("couldn't allocate memory for OTG driver\n"); -+ retval = -ENOMEM; -+ goto err1; -+ } -+ DBG ( "kmalloc: OTG driver: %p\n", otg); -+ -+ /* hold global device pointer */ -+ the_controller = otg; -+ -+ memset (otg, 0, sizeof(struct otg)); -+ spin_lock_init (&otg->lock); -+ -+ otg->pdev = pdev; -+ -+ /* now all the pci goodies ... */ -+ if (pci_enable_device (pdev) < 0) { -+ ERR ("couldn't enable PCI device\n"); -+ retval = -ENODEV; -+ goto err2; -+ } -+ otg->enabled = 1; -+ -+ resource = pci_resource_start (pdev, 0); -+ len = pci_resource_len (pdev, 0); -+ -+ if (!request_mem_region (resource, len, driver_name)) { -+ ERR ("controller already in use\n"); -+ retval = -EBUSY; -+ goto err3; -+ } -+ otg->region = 1; -+ -+ base = ioremap_nocache (resource, len); -+ if (!base) { -+ ERR ("couldn't map memory\n"); -+ retval = -EFAULT; -+ goto err4; -+ } -+ otg->regs = (struct otg_regs *) base; -+ bufp = buf; -+ -+ pci_read_config_byte (pdev, PCI_REVISION_ID, (u8*) &otg->chiprev); -+ -+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/ -+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/ -+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/ -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+ /* OTG transceiver info */ -+ -+ otg->transceiver.dev = &pdev->dev; -+ otg_init_transceiver (otg_to_transceiver (otg)); -+ -+ /* make sure all interrupts are disabled */ -+ writel (OTG_INT_DISALL, &otg->regs->inten); -+ writel (OTG_INT_ENALL, &otg->regs->intr); -+ readl (&otg->regs->inten); -+ -+ /* irq setup after old hardware is cleaned up */ -+ if (!pdev->irq) { -+ ERR ("No IRQ. Check PCI setup!\n"); -+ retval = -ENODEV; -+ goto err5; -+ } -+#ifndef __sparc__ -+ snprintf (buf, sizeof buf, "%d", pdev->irq); -+ bufp = buf; -+#else -+ bufp = __irq_itoa(pdev->irq); -+#endif -+ if (request_irq (pdev->irq, otg_isr, SA_INTERRUPT | SA_SHIRQ, -+ driver_name, otg) != 0) { -+ ERR ("request interrupt %s failed\n", bufp); -+ retval = -EBUSY; -+ goto err5; -+ } -+ otg->got_irq = 1; -+ -+ /* done */ -+ INFO ("%s\n", driver_desc); -+ INFO ("irq %s, pci mem %08x, chip rev %02x (Geode5536 %s)\n", -+ bufp, resource, otg->chiprev, (otg->chiprev - 1 ? "B1" : "A0")); -+ -+#else /* CONFIG_USB_OTG || CONFIG_USB_OTGMUX_GADGET */ -+ -+ INFO ("%s\n", driver_desc); -+ INFO ("pci mem %08x, chip rev %02x (Geode5536 %s)\n", -+ resource, otg->chiprev, (otg->chiprev - 1 ? "B1" : "A0")); -+#endif -+ bufp = DRIVER_VERSION; -+ INFO ("driver version: %s\n", bufp); -+ -+ if ((retval = otg_probe (otg)) == 0) { -+ pci_set_drvdata (pdev, otg); -+ return 0; -+ } -+ -+ /* something went wrong */ -+ -+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/ -+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/ -+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/ -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+ otg->got_irq = 0; -+ free_irq (pdev->irq, otg); -+err5: -+ -+#endif -+ otg->regs = NULL; -+ iounmap (base); -+err4: -+ otg->region = 0; -+ release_mem_region (resource, len); -+err3: -+ otg->enabled = 0; -+ pci_disable_device (pdev); -+err2: -+ otg->pdev = NULL; -+ the_controller = NULL; -+ DBG ( "kfree: OTG driver: %p\n", otg); -+ kfree (otg); -+err1: -+ otg = NULL; -+ return retval; -+} -+ -+/** -+ * \brief -+ * OTG PCI remove: clean-up, disable controller hardware -+ * -+ * \param pdev pci device info -+ * -+ * \return void -+ */ -+static void __exit otg_pci_remove (struct pci_dev *pdev) -+{ -+ struct otg *otg = pci_get_drvdata (pdev); -+ -+ otg_remove (otg); -+ -+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/ -+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/ -+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/ -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+ otg->got_irq = 0; -+ free_irq (pdev->irq, otg); -+#endif -+ iounmap (otg->regs); -+ otg->regs = NULL; -+ otg->region = 0; -+ release_mem_region (pci_resource_start(pdev, 0), -+ pci_resource_len(pdev, 0)); -+ otg->enabled = 0; -+ pci_disable_device (pdev); -+ otg->pdev = NULL; -+ the_controller = NULL; -+ DBG ( "kfree: OTG driver: %p\n", otg); -+ kfree (otg); -+ otg = NULL; -+ pci_set_drvdata(pdev, NULL); -+} -+#endif -+#endif -+ -+ -+/***************************************************************************** -+ * More data -+ *****************************************************************************/ -+ -+#ifdef CONFIG_SOC_AU1200 -+#ifndef USE_AU1200_PCI_DUMMY -+/** -+ * \brief -+ * driver struct to be used for driver registration -+ * -+ */ -+static struct device_driver otg_device_driver = { -+ .name = "au1xxx-uoc", -+ .bus = &platform_bus_type, -+ .probe = otg_drv_probe, -+ .remove = otg_drv_remove, -+/* .suspend = otg_drv_suspend, */ -+/* .resume = otg_drv_resume, */ -+}; -+#endif -+#else -+#ifdef CONFIG_PCI -+/** -+ * \brief -+ * PCI ID table -+ * -+ */ -+static struct pci_device_id pci_ids [] = { { -+ .vendor = PCI_VENDOR_ID_AMD, -+ .device = PCI_DEVICE_ID_AMD_CS5536_UOC, -+ .subvendor = PCI_ANY_ID, -+ .subdevice = PCI_ANY_ID, -+ .class = 0, -+ .class_mask = 0, -+ -+}, { /* end: all zeroes */ } -+}; -+ -+/** -+ * \brief -+ * PCI driver struct to be used for driver registration -+ * ( this is a "new style" PCI driver module ) -+ * -+ */ -+static struct pci_driver otg_pci_driver = { -+ .name = (char *) driver_name, -+ .id_table = pci_ids, -+ .probe = otg_pci_probe, -+ .remove = otg_pci_remove, -+/* .suspend = otg_pci_suspend, */ -+/* .resume = otg_pci_resume, */ -+}; -+MODULE_DEVICE_TABLE (pci, pci_ids); -+#endif -+#endif -+ -+/* This comment closes the module definition from above. There can be multiple -+ definitions of this kind in a file. See the doxygen documentation for more -+ information. */ -+/** \}*/ -+ -+MODULE_DESCRIPTION (DRIVER_DESC); -+MODULE_AUTHOR ("Karsten Boge"); -+MODULE_LICENSE ("GPL"); -+ -+#ifdef CONFIG_SOC_AU1200 -+#ifdef USE_AU1200_PCI_DUMMY -+ -+static int __init init (void) -+{ -+ return otg_pci_probe (&pdev_dummy); -+} -+static void __exit cleanup (void) -+{ -+ otg_pci_remove (&pdev_dummy); -+} -+#else -+ -+static int __init init (void) -+{ -+ return driver_register (&otg_device_driver); -+} -+static void __exit cleanup (void) -+{ -+ driver_unregister (&otg_device_driver); -+} -+#endif -+#else -+#ifdef CONFIG_PCI -+ -+static int __init init (void) -+{ -+ return pci_module_init (&otg_pci_driver); -+} -+static void __exit cleanup (void) -+{ -+ pci_unregister_driver (&otg_pci_driver); -+} -+#endif -+#endif -+ -+module_init (init); -+module_exit (cleanup); -diff --git a/drivers/usb/gadget/au1200uoc.h b/drivers/usb/gadget/au1200uoc.h -new file mode 100644 -index 0000000..9b4503e ---- /dev/null -+++ b/drivers/usb/gadget/au1200uoc.h -@@ -0,0 +1,1338 @@ -+/* -+ * AMD Au1200 USB OTG controller driver -+ */ -+ -+/* -+ * Copyright (C) 2005 AMD (http://www.amd.com) -+ * Author: Karsten Boge -+ * -+ * 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 AU1200UOC_H -+#define AU1200UOC_H -+ -+ -+/***************************************************************************** -+* Config options -+*****************************************************************************/ -+ -+#ifndef UDC_HSA0_WORKAROUNDS -+#define UDC_HSA0_WORKAROUNDS -+#endif -+ -+/* #define USE_AU1200_PCI_DUMMY */ -+#undef USE_AU1200_PCI_DUMMY -+ -+#ifdef CONFIG_USB_OTG -+#undef CONFIG_USB_OTGMUX_HOST -+#undef CONFIG_USB_OTGMUX_GADGET -+#undef CONFIG_USB_OTGMUX_IDPIN -+#endif -+ -+#ifdef CONFIG_USB_OTGMUX_IDPIN -+#undef CONFIG_USB_OTGMUX_HOST -+#ifndef CONFIG_USB_OTGMUX_GADGET -+#define CONFIG_USB_OTGMUX_GADGET -+#endif -+#endif -+ -+#ifndef OTG_HSA0_HNP_WA -+#define OTG_HSA0_HNP_WA -+#endif -+ -+#ifdef VERBOSE -+#ifndef DEBUG -+#define DEBUG -+#endif -+#endif -+ -+ -+/***************************************************************************** -+* Constants -+*****************************************************************************/ -+ -+#define OTG_DRIVER_NAME "au1200otg" -+ -+#define OTG_CHIPREV 0 -+ -+#define OTG_FLAGS_ACTIV (1<<19) /* full OTG functionality is activ */ -+ -+#ifndef CONFIG_SOC_AU1200 -+#ifdef CONFIG_PCI -+#ifndef PCI_VENDOR_ID_AMD -+#define PCI_VENDOR_ID_AMD 0x1022 -+#endif -+#ifndef PCI_DEVICE_ID_AMD_CS5536_UOC -+#define PCI_DEVICE_ID_AMD_CS5536_UOC 0x2097 -+#endif -+#else -+#error "!!! UNKNOWN SYSTEM BUS TYPE !!!" -+#endif -+#endif -+ -+#ifdef CONFIG_SOC_AU1200 -+#define GPIO_2_BASE 200 -+#define GPIO_215 215 -+#define SYS_PINFUNC_P0A_GPIO (2<<17) -+#ifdef CONFIG_MIPS_PB1200 -+#define USB_VBUS_GPIO 3 /* AU1000_GPIO_3 */ -+#endif -+#ifdef CONFIG_MIPS_DB1200 -+#define USB_VBUS_GPIO GPIO_215 -+#endif -+#if !(defined(CONFIG_MIPS_PB1200) || defined(CONFIG_MIPS_DB1200)) -+#error "!!! UNKNOWN AU1200 BOARD !!!" -+#endif -+#endif -+ -+ -+/********************************** -+* UOC Register definitions -+**********************************/ -+ -+/* capabilities */ -+#define OTG_CAP_APU (1<<15) /* automatic pull-up enable */ -+ -+/* multiplexer */ -+#define OTG_MUX_DISABLE_ALL 0 /* not assigned */ -+#define OTG_MUX_ENABLE_UHC (2<<0) /* assigned to host */ -+#define OTG_MUX_ENABLE_UDC (3<<0) /* assigned to device */ -+#define OTG_MUX_PUEN (1<<2) /* pull-up enable */ -+#define OTG_MUX_VBUSVLD (1<<8) /* VBus valid */ -+ -+/* status */ -+#define OTG_STS_ID (1<<0) /* ID pin status */ -+#define OTG_STS_VBUSVLD (1<<1) /* VBus valid */ -+#define OTG_STS_SESSVLD (1<<2) /* Session valid */ -+#define OTG_STS_SESSEND (1<<3) /* Session end */ -+#define OTG_STS_LST (3<<4) /* Line state */ -+#define OTG_STS_LST_J (1<<4) /* Line state */ -+#define OTG_STS_LST_K (2<<4) /* Line state */ -+#define OTG_STS_PSPD (3<<6) /* Port speed */ -+#define OTG_STS_PSPD_LS (2<<6) /* Port speed */ -+#define OTG_STS_PSPD_FS (1<<6) /* Port speed */ -+#define OTG_STS_FSOE (1<<8) /* FS output enable (OHC) */ -+#define OTG_STS_PCON (1<<9) /* Port connected */ -+#define OTG_STS_PSUS (1<<10) /* Port suspended */ -+#define OTG_STS_TMH (1<<11) /* Timer halted */ -+#define OTG_STS_HNP_EN (1<<12) /* HNP enabled for B-dev */ -+#define OTG_STS_HNP_SUPP (1<<13) /* A-host supports HNP */ -+#define OTG_STS_HNP_ALTSUPP (1<<14) /* A-host supports alt. HNP */ -+#define OTG_STS_HNPSTS (OTG_STS_HNP_EN | OTG_STS_HNP_SUPP | \ -+ OTG_STS_HNP_ALTSUPP) -+#define OTG_STS_OC (1<<15) /* over-current */ -+#define OTG_STS_DPR (1<<16) /* Downstream port reset */ -+ -+/* control */ -+#define OTG_CTL_DISABLE_ALL 0 /* not assigned */ -+#define OTG_CTL_ENABLE_UHC (2<<0) /* assigned to host */ -+#define OTG_CTL_ENABLE_UDC (3<<0) /* assigned to device */ -+#define OTG_CTL_MUX_MASK (3<<0) /* port mux mask */ -+#define OTG_CTL_PPWR (1<<2) /* port power switch */ -+#define OTG_CTL_PPO (1<<3) /* port power override */ -+#define OTG_CTL_CHRG (1<<4) /* charge VBus */ -+#define OTG_CTL_DISCHRG (1<<5) /* discharge VBus */ -+#define OTG_CTL_IDSNSEN (1<<6) /* ID sense enable, ID-PU */ -+#define OTG_CTL_PADEN (1<<7) -+#define OTG_CTL_PUEN (1<<8) /* pull-up enable */ -+#define OTG_CTL_DMPDEN (1<<9) /* pull-down enable */ -+#define OTG_CTL_HNPSFEN (1<<10) /* HNP SET_FEATURE enable */ -+#define OTG_CTL_WPCS_DEAS (2<<16) /* deassert port connect */ -+#define OTG_CTL_WPCS_ASRT (3<<16) /* assert port connect */ -+#define OTG_CTL_WPSS_DEAS (2<<18) /* deassert port suspend */ -+#define OTG_CTL_WPSS_ASRT (3<<18) /* assert port suspend */ -+/* timer conditions */ -+#define OTG_CTL_TMR_RLP (1<<28) /* timer reload policy */ -+#define OTG_CTL_TMR_ALL (0xf<<24) /* stop timer */ -+#define OTG_CTL_TMR_STOP 0 /* timer disabled */ -+#define OTG_CTL_TMR_UNCOND (1<<24) /* count unconditionally */ -+#define OTG_CTL_TMR_SE0 (2<<24) /* count if LSt = FS-SE0 */ -+#define OTG_CTL_TMR_FSJ (3<<24) /* count if LSt = FS-J */ -+#define OTG_CTL_TMR_FSK (4<<24) /* count if LSt = FS-K */ -+#define OTG_CTL_TMR_NOSE0 (5<<24) /* count if LSt <> FS-SE0 */ -+#define OTG_CTL_TMR_NORX (6<<24) /* count if Rx inactiv */ -+#define OTG_CTL_TMR_ID (7<<24) /* count if ID = 0 */ -+ -+/* interrupts */ -+#define OTG_INT_GLOBAL (1<<31) /* global interrupt enable */ -+#define OTG_INT_ENALL 0x7fff /* enable all */ -+#define OTG_INT_DISALL 0 /* disable all */ -+#define OTG_INT_IDC (1<<0) /* ID pin change */ -+#define OTG_INT_VBVC (1<<1) /* VBUS valid change */ -+#define OTG_INT_SVC (1<<2) /* Session valid change */ -+#define OTG_INT_SEC (1<<3) /* Session end change */ -+#define OTG_INT_LSTC (1<<4) /* Line state change */ -+#define OTG_INT_PSPDC (1<<5) /* Port speed change */ -+#define OTG_INT_FSOEC (1<<6) /* FS/LS OE change */ -+#define OTG_INT_HSDD (1<<7) /* HS disconnect detected */ -+#define OTG_INT_RXACT (1<<8) /* Rx activity detected */ -+#define OTG_INT_PCC (1<<9) /* Port connect change */ -+#define OTG_INT_PSC (1<<10) /* Port suspend change */ -+#define OTG_INT_TMX (1<<11) /* Timer expired */ -+#define OTG_INT_HNPFC (1<<12) /* HNP feature change */ -+#define OTG_INT_OCD (1<<13) /* over current detected */ -+#define OTG_INT_DPRC (1<<14) /* Downstream port reset change */ -+ -+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/ -+/*** HS-A0 WA: BUG-3950: gadget SV notification ***/ -+#ifdef UDC_HSA0_WORKAROUNDS -+#define OTG_INT_ADDS OTG_INT_SVC -+#endif -+ -+ -+/********************************** -+* OTG state dependend data -+**********************************/ -+ -+/* -+ * generic -+ */ -+#define OTG_CTL_DEFAULT (OTG_CTL_PADEN | \ -+ OTG_CTL_IDSNSEN) -+#define OTG_CTL_HOST_DEFAULT (OTG_CTL_DEFAULT | \ -+ OTG_CTL_ENABLE_UHC) -+#ifdef UDC_HSA0_WORKAROUNDS -+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/ -+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/ -+#ifdef CONFIG_USB_OTG -+#define OTG_CTL_PERIPHERAL_DEFAULT (OTG_CTL_DEFAULT | \ -+ OTG_CTL_HNPSFEN | \ -+ OTG_CTL_ENABLE_UDC | \ -+ OTG_CTL_PPO | OTG_CTL_PUEN) -+#else -+#define OTG_CTL_PERIPHERAL_DEFAULT (OTG_CTL_DEFAULT | \ -+ OTG_CTL_ENABLE_UDC | \ -+ OTG_CTL_PPO | OTG_CTL_PUEN) -+#endif -+#else -+#ifdef CONFIG_USB_OTG -+#define OTG_CTL_PERIPHERAL_DEFAULT (OTG_CTL_DEFAULT | \ -+ OTG_CTL_HNPSFEN | \ -+ OTG_CTL_ENABLE_UDC | OTG_CTL_PPO) -+#else -+#define OTG_CTL_PERIPHERAL_DEFAULT (OTG_CTL_DEFAULT | \ -+ OTG_CTL_ENABLE_UDC | OTG_CTL_PPO) -+#endif -+#endif -+ -+#define OTG_INT_DEFAULT OTG_INT_IDC -+ -+/* -+ * OTG_STATE_UNDEFINED -+ */ -+#define OTG_STATE_UNDEFINED_CONTROL (OTG_CTL_DEFAULT | OTG_CTL_PPO | \ -+ OTG_CTL_TMR_UNCOND) -+#define OTG_STATE_UNDEFINED_STATUS 0 -+#define OTG_STATE_UNDEFINED_STATUS_MASK 0 -+#define OTG_STATE_UNDEFINED_INTERRUPTS OTG_INT_TMX -+ -+/* -+ * OTG_STATE_A_IDLE -+ */ -+#define OTG_STATE_A_IDLE_CONTROL (OTG_CTL_DEFAULT | OTG_CTL_PPO) -+#define OTG_STATE_A_IDLE_STATUS 0 -+#define OTG_STATE_A_IDLE_STATUS_MASK 0 -+#define OTG_STATE_A_IDLE_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SVC | \ -+ OTG_INT_LSTC) -+ -+/* -+ * OTG_STATE_A_IDLE_WAIT_DP -+ */ -+#define OTG_STATE_A_IDLE_WAIT_DP_CONTROL (OTG_STATE_A_IDLE_CONTROL | \ -+ OTG_CTL_TMR_UNCOND) -+#define OTG_STATE_A_IDLE_WAIT_DP_STATUS 0 -+#define OTG_STATE_A_IDLE_WAIT_DP_STATUS_MASK 0 -+#define OTG_STATE_A_IDLE_WAIT_DP_INTERRUPTS (OTG_STATE_A_IDLE_INTERRUPTS | \ -+ OTG_INT_TMX) -+ -+/* -+ * OTG_STATE_A_IDLE_WAIT_VP -+ */ -+#define OTG_STATE_A_IDLE_WAIT_VP_CONTROL (OTG_STATE_A_IDLE_CONTROL | \ -+ OTG_CTL_TMR_UNCOND) -+#define OTG_STATE_A_IDLE_WAIT_VP_STATUS 0 -+#define OTG_STATE_A_IDLE_WAIT_VP_STATUS_MASK 0 -+#define OTG_STATE_A_IDLE_WAIT_VP_INTERRUPTS (OTG_STATE_A_IDLE_INTERRUPTS | \ -+ OTG_INT_TMX) -+ -+/* -+ * OTG_STATE_A_IDLE_WAIT_MP -+ */ -+#define OTG_STATE_A_IDLE_WAIT_MP_CONTROL (OTG_STATE_A_IDLE_CONTROL | \ -+ OTG_CTL_TMR_UNCOND) -+#define OTG_STATE_A_IDLE_WAIT_MP_STATUS 0 -+#define OTG_STATE_A_IDLE_WAIT_MP_STATUS_MASK 0 -+#define OTG_STATE_A_IDLE_WAIT_MP_INTERRUPTS (OTG_STATE_A_IDLE_INTERRUPTS | \ -+ OTG_INT_TMX) -+ -+/* -+ * OTG_STATE_A_IDLE_WAIT_DV -+ */ -+#define OTG_STATE_A_IDLE_WAIT_DV_CONTROL (OTG_STATE_A_IDLE_CONTROL | \ -+ OTG_CTL_TMR_UNCOND) -+#define OTG_STATE_A_IDLE_WAIT_DV_STATUS 0 -+#define OTG_STATE_A_IDLE_WAIT_DV_STATUS_MASK 0 -+#define OTG_STATE_A_IDLE_WAIT_DV_INTERRUPTS (OTG_STATE_A_IDLE_INTERRUPTS | \ -+ OTG_INT_TMX) -+ -+/* -+ * OTG_STATE_A_WAIT_VRISE -+ */ -+#define OTG_STATE_A_WAIT_VRISE_CONTROL (OTG_CTL_HOST_DEFAULT | \ -+ OTG_CTL_TMR_UNCOND) -+#define OTG_STATE_A_WAIT_VRISE_STATUS 0 -+#define OTG_STATE_A_WAIT_VRISE_STATUS_MASK 0 -+#define OTG_STATE_A_WAIT_VRISE_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_TMX | \ -+ OTG_INT_VBVC) -+ -+/* -+ * OTG_STATE_A_WAIT_BCON -+ */ -+#define OTG_STATE_A_WAIT_BCON_CONTROL OTG_CTL_HOST_DEFAULT -+#define OTG_STATE_A_WAIT_BCON_STATUS 0 -+#define OTG_STATE_A_WAIT_BCON_STATUS_MASK 0 -+#define OTG_STATE_A_WAIT_BCON_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_TMX | \ -+ OTG_INT_VBVC | OTG_INT_PCC) -+ -+/* -+ * OTG_STATE_A_WAIT_BCON_VB -+ */ -+#define OTG_STATE_A_WAIT_BCON_VB_CONTROL (OTG_STATE_A_WAIT_BCON_CONTROL | \ -+ OTG_CTL_TMR_UNCOND) -+#define OTG_STATE_A_WAIT_BCON_VB_STATUS 0 -+#define OTG_STATE_A_WAIT_BCON_VB_STATUS_MASK 0 -+#define OTG_STATE_A_WAIT_BCON_VB_INTERRUPTS OTG_STATE_A_WAIT_BCON_INTERRUPTS -+ -+/* -+ * OTG_STATE_A_HOST -+ */ -+#define OTG_STATE_A_HOST_CONTROL OTG_CTL_HOST_DEFAULT -+#define OTG_STATE_A_HOST_STATUS 0 -+#define OTG_STATE_A_HOST_STATUS_MASK 0 -+#ifdef CONFIG_USB_OTG -+#ifndef VERBOSE -+#define OTG_STATE_A_HOST_INTERRUPTS (OTG_INT_DEFAULT | \ -+ OTG_INT_VBVC | OTG_INT_DPRC | \ -+ OTG_INT_PCC | OTG_INT_PSC) -+#else -+#define OTG_STATE_A_HOST_INTERRUPTS (OTG_INT_DEFAULT | \ -+ OTG_INT_VBVC | OTG_INT_DPRC | \ -+ OTG_INT_PCC | OTG_INT_PSC | \ -+ OTG_INT_PSPDC) -+ /* OTG_INT_LSTC */ -+#endif -+#else -+ /* IDPIN mode only */ -+#define OTG_STATE_A_HOST_INTERRUPTS OTG_INT_IDC -+#endif -+ -+/* -+ * OTG_STATE_A_SUSPEND -+ */ -+#define OTG_STATE_A_SUSPEND_CONTROL (OTG_CTL_HOST_DEFAULT | \ -+ OTG_CTL_TMR_UNCOND) -+#define OTG_STATE_A_SUSPEND_STATUS 0 -+#define OTG_STATE_A_SUSPEND_STATUS_MASK 0 -+#define OTG_STATE_A_SUSPEND_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_TMX | \ -+ OTG_INT_VBVC | OTG_INT_DPRC | \ -+ OTG_INT_PCC | OTG_INT_PSC) -+ -+/* -+ * OTG_STATE_A_PERIPHERAL -+ */ -+#define OTG_STATE_A_PERIPHERAL_CONTROL (OTG_CTL_PERIPHERAL_DEFAULT | \ -+ OTG_CTL_PPWR | OTG_CTL_DMPDEN) -+#define OTG_STATE_A_PERIPHERAL_STATUS 0 -+#define OTG_STATE_A_PERIPHERAL_STATUS_MASK 0 -+#ifndef VERBOSE -+#define OTG_STATE_A_PERIPHERAL_INTERRUPTS (OTG_INT_DEFAULT | \ -+ OTG_INT_VBVC | OTG_INT_OCD | \ -+ OTG_INT_PCC | OTG_INT_PSC) -+#else -+#define OTG_STATE_A_PERIPHERAL_INTERRUPTS (OTG_INT_DEFAULT | \ -+ OTG_INT_VBVC | OTG_INT_OCD | \ -+ OTG_INT_PCC | OTG_INT_PSC | \ -+ OTG_INT_PSPDC) -+ /* OTG_INT_LSTC */ -+#endif -+ -+/* -+ * OTG_STATE_A_VBUS_ERR -+ */ -+#define OTG_STATE_A_VBUS_ERR_CONTROL (OTG_CTL_HOST_DEFAULT | \ -+ OTG_CTL_PPO | OTG_CTL_DISCHRG) -+#define OTG_STATE_A_VBUS_ERR_STATUS 0 -+#define OTG_STATE_A_VBUS_ERR_STATUS_MASK 0 -+#define OTG_STATE_A_VBUS_ERR_INTERRUPTS OTG_INT_DEFAULT -+ -+/* -+ * OTG_STATE_A_WAIT_VFALL -+ */ -+#define OTG_STATE_A_WAIT_VFALL_CONTROL (OTG_CTL_HOST_DEFAULT | \ -+ OTG_CTL_PPO) -+#define OTG_STATE_A_WAIT_VFALL_STATUS 0 -+#define OTG_STATE_A_WAIT_VFALL_STATUS_MASK 0 -+#define OTG_STATE_A_WAIT_VFALL_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SEC) -+ -+/* -+ * OTG_STATE_A_WAIT_VFALL_DN -+ */ -+#define OTG_STATE_A_WAIT_VFALL_DN_CONTROL (OTG_STATE_A_WAIT_VFALL_CONTROL | \ -+ OTG_CTL_DISCHRG) -+#define OTG_STATE_A_WAIT_VFALL_DN_STATUS 0 -+#define OTG_STATE_A_WAIT_VFALL_DN_STATUS_MASK 0 -+#define OTG_STATE_A_WAIT_VFALL_DN_INTERRUPTS OTG_STATE_A_WAIT_VFALL_INTERRUPTS -+ -+/* -+ * OTG_STATE_A_WAIT_BDISCON -+ */ -+#define OTG_STATE_A_WAIT_BDISCON_CONTROL (OTG_CTL_DEFAULT | \ -+ OTG_CTL_PPO | OTG_CTL_PPWR | \ -+ OTG_CTL_TMR_UNCOND) -+#define OTG_STATE_A_WAIT_BDISCON_STATUS 0 -+#define OTG_STATE_A_WAIT_BDISCON_STATUS_MASK 0 -+#define OTG_STATE_A_WAIT_BDISCON_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_TMX | \ -+ OTG_INT_VBVC | OTG_INT_OCD | \ -+ OTG_INT_PSPDC | OTG_INT_LSTC) -+ -+/* -+ * OTG_STATE_B_IDLE -+ */ -+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/ -+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/ -+#ifdef UDC_HSA0_WORKAROUNDS -+#define OTG_STATE_B_IDLE_CONTROL (OTG_CTL_PERIPHERAL_DEFAULT & \ -+ ~((u32) (OTG_CTL_PUEN | \ -+ OTG_CTL_ENABLE_UDC))) -+#else -+#define OTG_STATE_B_IDLE_CONTROL OTG_CTL_PERIPHERAL_DEFAULT -+#endif -+#define OTG_STATE_B_IDLE_STATUS 0 -+#define OTG_STATE_B_IDLE_STATUS_MASK 0 -+#ifdef CONFIG_USB_OTG -+#define OTG_STATE_B_IDLE_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SVC) -+#else -+#ifdef CONFIG_USB_OTGMUX_IDPIN -+ /* IDPIN mode */ -+#define OTG_STATE_B_IDLE_INTERRUPTS (OTG_INT_IDC | OTG_INT_SVC) -+#else -+ /* gadget mode */ -+#define OTG_STATE_B_IDLE_INTERRUPTS OTG_INT_SVC -+#endif -+#endif -+ -+/* -+ * OTG_STATE_B_PERIPHERAL -+ */ -+#define OTG_STATE_B_PERIPHERAL_CONTROL (OTG_CTL_PERIPHERAL_DEFAULT | \ -+ OTG_CTL_DMPDEN) -+#define OTG_STATE_B_PERIPHERAL_STATUS 0 -+#define OTG_STATE_B_PERIPHERAL_STATUS_MASK 0 -+#ifdef CONFIG_USB_OTG -+#ifndef VERBOSE -+#define OTG_STATE_B_PERIPHERAL_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SVC | \ -+ OTG_INT_PCC | OTG_INT_PSC | \ -+ OTG_INT_HNPFC) -+#else -+#define OTG_STATE_B_PERIPHERAL_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SVC | \ -+ OTG_INT_PCC | OTG_INT_PSC | \ -+ OTG_INT_HNPFC | OTG_INT_PSPDC) -+ /* OTG_INT_LSTC */ -+#endif -+#else -+#ifdef CONFIG_USB_OTGMUX_IDPIN -+ /* IDPIN mode */ -+#define OTG_STATE_B_PERIPHERAL_INTERRUPTS (OTG_INT_IDC | OTG_INT_SVC) -+#else -+ /* gadget mode */ -+#define OTG_STATE_B_PERIPHERAL_INTERRUPTS OTG_INT_SVC -+#endif -+#endif -+ -+/* -+ * OTG_STATE_B_PERIPHERAL_WT -+ */ -+#define OTG_STATE_B_PERIPHERAL_WT_CONTROL (OTG_STATE_B_PERIPHERAL_CONTROL | \ -+ OTG_CTL_PPO | OTG_CTL_TMR_UNCOND) -+#define OTG_STATE_B_PERIPHERAL_WT_STATUS 0 -+#define OTG_STATE_B_PERIPHERAL_WT_STATUS_MASK 0 -+#define OTG_STATE_B_PERIPHERAL_WT_INTERRUPTS (OTG_STATE_B_PERIPHERAL_INTERRUPTS \ -+ | OTG_INT_TMX) -+ -+/* -+ * OTG_STATE_B_PERIPHERAL_DC -+ */ -+#define OTG_STATE_B_PERIPHERAL_DC_CONTROL (OTG_CTL_HOST_DEFAULT | \ -+ OTG_CTL_PPO | OTG_CTL_DMPDEN | \ -+ OTG_CTL_TMR_UNCOND) -+#define OTG_STATE_B_PERIPHERAL_DC_STATUS 0 -+#define OTG_STATE_B_PERIPHERAL_DC_STATUS_MASK 0 -+#define OTG_STATE_B_PERIPHERAL_DC_INTERRUPTS (OTG_STATE_B_PERIPHERAL_INTERRUPTS \ -+ | OTG_INT_TMX | OTG_INT_LSTC) -+ -+/* -+ * OTG_STATE_B_WAIT_ACON -+ */ -+#define OTG_STATE_B_WAIT_ACON_CONTROL (OTG_CTL_HOST_DEFAULT | \ -+ OTG_CTL_PPO | OTG_CTL_TMR_UNCOND) -+#define OTG_STATE_B_WAIT_ACON_STATUS 0 -+#define OTG_STATE_B_WAIT_ACON_STATUS_MASK 0 -+#define OTG_STATE_B_WAIT_ACON_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SVC | \ -+ OTG_INT_PCC | OTG_INT_PSC | \ -+ OTG_INT_HNPFC | OTG_INT_TMX) -+ -+/* -+ * OTG_STATE_B_HOST -+ */ -+#define OTG_STATE_B_HOST_CONTROL (OTG_CTL_HOST_DEFAULT | \ -+ OTG_CTL_PPO) -+#define OTG_STATE_B_HOST_STATUS 0 -+#define OTG_STATE_B_HOST_STATUS_MASK 0 -+#ifndef VERBOSE -+#define OTG_STATE_B_HOST_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SVC | \ -+ OTG_INT_PCC) -+#else -+#define OTG_STATE_B_HOST_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SVC | \ -+ OTG_INT_PCC | OTG_INT_SVC | \ -+ OTG_INT_PSPDC) -+ /* OTG_INT_LSTC */ -+#endif -+ -+/* -+ * OTG_STATE_B_HOST_WT -+ */ -+#define OTG_STATE_B_HOST_WT_CONTROL (OTG_STATE_B_HOST_CONTROL | \ -+ OTG_CTL_TMR_UNCOND) -+#define OTG_STATE_B_HOST_WT_STATUS 0 -+#define OTG_STATE_B_HOST_WT_STATUS_MASK 0 -+#ifndef VERBOSE -+#define OTG_STATE_B_HOST_WT_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SVC | \ -+ OTG_INT_PCC | OTG_INT_TMX) -+#else -+#define OTG_STATE_B_HOST_WT_INTERRUPTS (OTG_STATE_B_HOST_INTERRUPTS | \ -+ OTG_INT_TMX) -+/* -+#define OTG_STATE_B_HOST_WT_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SVC | \ -+ OTG_INT_PCC | OTG_INT_DPRC | \ -+ OTG_INT_TMX | OTG_INT_PSPDC) */ -+ /* OTG_INT_LSTC */ -+#endif -+ -+/* -+ * OTG_STATE_B_SRP_INIT -+ */ -+#define OTG_STATE_B_SRP_INIT_CONTROL OTG_STATE_B_IDLE_CONTROL -+#define OTG_STATE_B_SRP_INIT_STATUS 0 -+#define OTG_STATE_B_SRP_INIT_STATUS_MASK 0 -+#define OTG_STATE_B_SRP_INIT_INTERRUPTS OTG_INT_DEFAULT -+ -+/* -+ * OTG_STATE_B_SRP_WTSE0 -+ */ -+#define OTG_STATE_B_SRP_WAIT_SE0_CONTROL (OTG_STATE_B_SRP_INIT_CONTROL | \ -+ OTG_CTL_TMR_UNCOND) -+#define OTG_STATE_B_SRP_WAIT_SE0_STATUS 0 -+#define OTG_STATE_B_SRP_WAIT_SE0_STATUS_MASK 0 -+#define OTG_STATE_B_SRP_WAIT_SE0_INTERRUPTS (OTG_STATE_B_SRP_INIT_INTERRUPTS \ -+ | OTG_INT_TMX | OTG_INT_LSTC) -+ -+/* -+ * OTG_STATE_B_SRP_D_PLS -+ * -+ * note: changing to this state requires an additional call: -+ * set_srp_conditions (dev); -+ * reset_srp_conditions (dev) is required for the next state -+ */ -+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/ -+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/ -+/* note: set_/reset_srp_conditions is not needed if HS-A0 WAs are active -+ */ -+#ifdef UDC_HSA0_WORKAROUNDS -+#define OTG_STATE_B_SRP_D_PULSE_CONTROL (OTG_CTL_PERIPHERAL_DEFAULT | \ -+ OTG_CTL_PUEN | \ -+ OTG_CTL_TMR_UNCOND) -+#else -+#define OTG_STATE_B_SRP_D_PULSE_CONTROL (OTG_STATE_B_SRP_INIT_CONTROL | \ -+ OTG_CTL_PUEN | \ -+ OTG_CTL_TMR_UNCOND) -+#endif -+#define OTG_STATE_B_SRP_D_PULSE_STATUS 0 -+#define OTG_STATE_B_SRP_D_PULSE_STATUS_MASK 0 -+#define OTG_STATE_B_SRP_D_PULSE_INTERRUPTS (OTG_STATE_B_SRP_INIT_INTERRUPTS \ -+ | OTG_INT_SEC | OTG_INT_TMX) -+ -+/* -+ * OTG_STATE_B_SRP_V_PLS -+ */ -+#define OTG_STATE_B_SRP_V_PULSE_CONTROL (OTG_STATE_B_SRP_INIT_CONTROL | \ -+ OTG_CTL_CHRG | \ -+ OTG_CTL_TMR_UNCOND) -+#define OTG_STATE_B_SRP_V_PULSE_STATUS 0 -+#define OTG_STATE_B_SRP_V_PULSE_STATUS_MASK 0 -+#define OTG_STATE_B_SRP_V_PULSE_INTERRUPTS (OTG_STATE_B_SRP_INIT_INTERRUPTS \ -+ | OTG_INT_TMX) -+ -+/* -+ * OTG_STATE_B_SRP_V_DCG -+ */ -+#define OTG_STATE_B_SRP_V_DCHRG_CONTROL (OTG_STATE_B_SRP_INIT_CONTROL | \ -+ OTG_CTL_DISCHRG | \ -+ OTG_CTL_TMR_UNCOND) -+#define OTG_STATE_B_SRP_V_DCHRG_STATUS 0 -+#define OTG_STATE_B_SRP_V_DCHRG_STATUS_MASK 0 -+#define OTG_STATE_B_SRP_V_DCHRG_INTERRUPTS (OTG_STATE_B_SRP_INIT_INTERRUPTS \ -+ | OTG_INT_TMX) -+ -+/* -+ * OTG_STATE_B_SRP_WTVB -+ */ -+#define OTG_STATE_B_SRP_WAIT_VBUS_CONTROL (OTG_STATE_B_SRP_INIT_CONTROL | \ -+ OTG_CTL_TMR_UNCOND) -+#define OTG_STATE_B_SRP_WAIT_VBUS_STATUS 0 -+#define OTG_STATE_B_SRP_WAIT_VBUS_STATUS_MASK 0 -+#define OTG_STATE_B_SRP_WAIT_VBUS_INTERRUPTS (OTG_STATE_B_SRP_INIT_INTERRUPTS \ -+ | OTG_INT_SVC | OTG_INT_TMX) -+ -+/*********************************/ -+ -+/* other */ -+ -+#define OTG_APP_REQ_ACK 0 -+ -+ -+/***************************************************************************** -+* Types -+*****************************************************************************/ -+ -+ -+/***************************************************************************** -+* Macros -+*****************************************************************************/ -+ -+/* printing messages */ -+#ifndef INFO -+#define INFO(args...) \ -+ printk(KERN_INFO DRIVER_NAME_FOR_PRINT ": " args) -+#endif -+ -+#ifndef WARN -+#define WARN(args...) \ -+ printk(KERN_WARNING DRIVER_NAME_FOR_PRINT " warning: " args) -+#endif -+ -+#ifndef ERR -+#define ERR(args...) \ -+ printk(KERN_ERR DRIVER_NAME_FOR_PRINT " error: " args) -+#endif -+ -+#ifndef DBG -+#ifdef DEBUG -+#define DBG(args...) \ -+ printk(KERN_DEBUG DRIVER_NAME_FOR_PRINT " debug: " args) -+#else -+#define DBG(args...) \ -+ do {} while (0) -+#endif -+#endif -+ -+#ifndef VDBG -+#ifdef VERBOSE -+#define VDBG DBG -+#else -+#define VDBG(args...) \ -+ do { } while (0) -+#endif -+#endif -+ -+/****************************************************************************/ -+ -+/* this should always return "1" and print something in verbose mode */ -+#ifdef VERBOSE -+#define VDBG_SPC(fmt,args...) \ -+ (VDBG (fmt, args) ? 1 : 1) -+#else -+#define VDBG_SPC(fmt,args...) 1 -+#endif -+ -+/* query bit(s) (long: 32-bit access) */ -+#define IS_BIT_RES(data, code) \ -+ (!((data) & (code)) ? \ -+ (VDBG_SPC (" OTG HW status: %s is reset\n", #data)) : 0) -+ -+#define IS_BIT_SET(data, code) \ -+ (((data) & (code)) ? \ -+ (VDBG_SPC (" OTG HW status: %s is set\n", #data)) : 0) -+ -+/* query SW flag(s) */ -+#define IS_FLAG_RES(dev, data) \ -+ (!((data) & (dev)->params) ? \ -+ (VDBG_SPC (" OTG SW status: %s is reset\n", #data)) : 0) -+ -+#define IS_FLAG_SET(dev, data) \ -+ (((data) & (dev)->params) ? \ -+ (VDBG_SPC (" OTG SW status: %s is set\n", #data)) : 0) -+ -+/* query event bit(s) */ -+#define GOT_EVENT(data, code) \ -+ (((data) & (code)) ? \ -+ (VDBG_SPC (" OTG event: %s\n", #data)) : 0) -+ -+/* set SW flag */ -+#ifdef VERBOSE -+#define SET_FLAG(dev, data) \ -+ if (!((data) & (dev)->params)) \ -+ DBG (" OTG SW status change: set flag %s\n", #data); \ -+ (dev)->params |= (data) -+#else -+#define SET_FLAG(dev, data) \ -+ (dev)->params |= (data) -+#endif -+ -+/* reset SW flag */ -+#ifdef VERBOSE -+#define RES_FLAG(dev, data) \ -+ if ((data) & (dev)->params) \ -+ DBG (" OTG SW status change: reset flag %s\n", #data); \ -+ (dev)->params &= ~((u32) (data)) -+#else -+#define RES_FLAG(dev, data) \ -+ (dev)->params &= ~((u32) (data)) -+#endif -+ -+/* reset event bit */ -+#define RES_EVENT(data, code) \ -+ (code) &= ~((u32) (data)) -+/* NOTE: this is not really needed so far, might be replaced with */ -+/* #define RES_EVENT(data, code) \ */ -+/* do {} while (0) */ -+ -+/* change OTG state */ -+#ifdef CONFIG_USB_OTG -+#define PREPARE_STATE_CHANGE_1ST(dev, new_state) \ -+ switch ((new_state) & OTG_STATE_MASK) { \ -+ case OTG_STATE_UNDEFINED: \ -+ set_undef_state_defaults((dev)); \ -+ break; \ -+ case OTG_STATE_A_IDLE: \ -+ set_a_state_defaults((dev)); \ -+ break; \ -+ case OTG_STATE_B_IDLE: \ -+ set_b_state_defaults((dev)); \ -+ break; \ -+ default: \ -+ break; \ -+ } \ -+ do {} while (0) -+#else -+#define PREPARE_STATE_CHANGE_1ST(dev, new_state) \ -+ do {} while (0) -+#endif -+ -+#ifdef CONFIG_SOC_AU1200 -+ -+#if (USB_VBUS_GPIO < GPIO_2_BASE) -+#define AU1000GPIO_SET_BIT(data) \ -+ au1000gpio_bit_set (data) -+#define AU1000GPIO_CLR_BIT(data) \ -+ au1000gpio_bit_clear (data) -+#define AU1000GPIO_INIT_BIT(data) \ -+ au1000gpio_bit_init (data) -+#define AU1000GPIO_TERM_BIT(data) \ -+ au1000gpio_bit_term (data) -+#else -+#define AU1000GPIO_SET_BIT(data) \ -+ au1000gpio2_bit_set (data) -+#define AU1000GPIO_CLR_BIT(data) \ -+ au1000gpio2_bit_clear (data) -+#define AU1000GPIO_INIT_BIT(data) \ -+ au1000gpio2_bit_init (data) -+#define AU1000GPIO_TERM_BIT(data) \ -+ au1000gpio2_bit_term (data) -+#endif -+ -+#define PREPARE_STATE_CHANGE_2ND(new_state_control) \ -+ if (((new_state_control) & OTG_CTL_PPO) && \ -+ (~(new_state_control) & OTG_CTL_PPWR)) \ -+ AU1000GPIO_SET_BIT(USB_VBUS_GPIO); \ -+ else \ -+ AU1000GPIO_CLR_BIT(USB_VBUS_GPIO) -+#else -+#define PREPARE_STATE_CHANGE_2ND(new_state_control) \ -+ do {} while (0) -+#endif -+ -+#define CHANGE_STATE(dev, new_state, pMask) \ -+ PREPARE_STATE_CHANGE_1ST(dev, new_state); \ -+ PREPARE_STATE_CHANGE_2ND(new_state##_CONTROL); \ -+ writel ((new_state##_CONTROL), &(dev)->regs->ctl); \ -+ *(pMask) = (new_state##_INTERRUPTS); \ -+ (dev)->transceiver.state = (new_state); \ -+ DBG ("OTG new state: %s\n", #new_state) -+ -+/* verify OTG state */ -+#ifndef CONFIG_OTG_TEST_MODE -+ -+#define CHECK_STATE(dev, act_state, pMask) \ -+ *(pMask) = (act_state##_INTERRUPTS); \ -+ (dev)->prv_state = (act_state); \ -+ VDBG ("OTG state: %s\n", #act_state) -+#else -+#define CHECK_STATE(dev, act_state, pMask) \ -+ *(pMask) = (act_state##_INTERRUPTS); \ -+ (dev)->prv_state = (act_state); \ -+ if (((readl (&(dev)->regs->sts) ^ (act_state##_STATUS))) & \ -+ act_state##_STATUS_MASK) \ -+ WARN ("OTG warning: incorrect status\n"); \ -+ VDBG ("OTG state: %s\n", #act_state) -+#endif -+ -+/* set timer */ -+#define SET_OTG_TIMER(dev, val) \ -+ set_timer ((dev), ((OTG_TMR_##val) * 100)) -+ -+/* set timer ( <1ms ) */ -+#define SET_OTG_TIMER_SHORT(dev, val) \ -+ set_timer ((dev), ((OTG_TMR_##val) / 10)) -+ -+/* set timer ( >10ms ) */ -+#define SET_OTG_TIMER_LONG(dev, val) \ -+ set_timer_long ((dev), ((OTG_TMR_##val) / 10)) -+ -+#ifdef VERBOSE -+#define HS_DISCON_WARNING() \ -+ if (!(OTG_CTL_ENABLE_UHC ^ \ -+ (OTG_CTL_MUX_MASK & readl (&dev->regs->ctl))) && \ -+ !(OTG_STS_PSPD & readl (&dev->regs->sts))) \ -+ DBG (" OTG warning: disable UHC from HS-mode\n") -+#else -+#define HS_DISCON_WARNING() \ -+ do { } while (0) -+#endif -+ -+ -+/***************************************************************************** -+* Data -+*****************************************************************************/ -+struct otg_regs { -+ u32 cap; /* capabilities */ -+ u32 mux; /* mux */ -+ u32 sts; /* status */ -+ u32 ctl; /* control */ -+ u32 tmr; /* timer */ -+ u32 intr; /* interrupt request */ -+ u32 inten; /* interrupt enable */ -+} __attribute__ ((packed)); -+ -+struct otg { -+ spinlock_t lock; -+ unsigned enabled : 1, -+ got_irq : 1, -+ region : 1; -+ u16 chiprev; -+ -+ /* state variables */ -+ u8 prv_state; -+ u32 params; -+ void *otg_priv; -+ u8 hostcount; -+ -+#ifdef CONFIG_SOC_AU1200 -+#ifdef USE_AU1200_PCI_DUMMY -+ -+ struct pci_dev *pdev; -+#else -+ struct platform_device *pdev; -+#endif -+#else -+ struct pci_dev *pdev; -+#endif -+ struct otg_regs *regs; -+ struct otg_transceiver transceiver; -+}; -+#define transceiver_to_otg(pTransceiver) \ -+ container_of (pTransceiver, struct otg, transceiver) -+#define otg_to_transceiver(pOtg) \ -+ &pOtg->transceiver -+ -+#ifdef CONFIG_USB_OTG_TEST_INTERFACE -+struct usb_otg_test_extension { -+ int (*bind) (struct otg **); -+ int (*unbind) (struct otg **); -+ int (*request) (u32); /* function call for state change requests */ -+ u32 (*query) (int); /* function call to query state */ -+}; -+#endif -+ -+#ifdef __KERNEL__ -+ -+/* 2.5 and 2.4.older portability changes ... */ -+ -+#ifndef container_of -+#define container_of list_entry -+#endif -+ -+#ifndef likely -+#define likely(x) (x) -+#define unlikely(x) (x) -+#endif -+ -+#ifndef BUG_ON -+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0) -+#endif -+ -+#ifndef WARN_ON -+#define WARN_ON(x) do { } while (0) -+#endif -+ -+#endif /* __KERNEL__ */ -+ -+/***************************************************************************** -+* Functions -+*****************************************************************************/ -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+extern int usb_gadget_register_otg (struct otg_transceiver * ( -+ *get_transceiver)(void)); -+extern int usb_gadget_unregister_otg (void); -+ -+#endif -+#ifdef CONFIG_USB_OTG -+u32 otg_change_state (struct otg *, u32, u32 *); -+int otg_hnp_start_enum (struct otg_transceiver *); -+#endif -+ -+void otg_init_state (struct otg *); -+int otg_exit_state (struct otg *); -+ -+#ifdef DEBUG -+static void print_regs (struct otg *); -+#endif /* DEBUG */ -+ -+#ifdef CONFIG_USB_OTG_TEST_INTERFACE -+int usb_otg_test_register_driver (struct usb_otg_test_extension *); -+int usb_otg_test_unregister_driver (void); -+#endif -+ -+/***************************************************************************** -+* Inline Functions -+*****************************************************************************/ -+ -+extern u32 otg_tmr_high_count; -+extern struct otg_ctl *otg_ctl; -+ -+#ifdef CONFIG_USB_OTG -+/** -+ * \brief -+ * set neutral state information -+ * -+ * \param dev OTG controller info -+ * -+ * \return void -+ */ -+static inline void set_undef_state_defaults (struct otg *dev) -+{ -+ dev->transceiver.default_a = 0; -+ if (dev->transceiver.host) { -+ dev->transceiver.host->is_b_host = 0; -+ } -+#ifdef CONFIG_USB_OTG_HIGHSPEED -+ if (dev->transceiver.companion) { -+ dev->transceiver.companion->is_b_host = 0; -+ } -+#endif -+ if (dev->transceiver.gadget) { -+ dev->transceiver.gadget->is_a_peripheral = 0; -+ } -+} -+ -+/** -+ * \brief -+ * set A state information -+ * -+ * \param dev OTG controller info -+ * -+ * \return void -+ */ -+static inline void set_a_state_defaults (struct otg *dev) -+{ -+ dev->transceiver.default_a = 1; -+ if (dev->transceiver.host) { -+ dev->transceiver.host->is_b_host = 0; -+ } -+#ifdef CONFIG_USB_OTG_HIGHSPEED -+ if (dev->transceiver.companion) { -+ dev->transceiver.companion->is_b_host = 0; -+ } -+#endif -+ if (dev->transceiver.gadget) { -+ dev->transceiver.gadget->is_a_peripheral = 1; -+ } -+} -+ -+/** -+ * \brief -+ * set B state information -+ * -+ * \param dev OTG controller info -+ * -+ * \return void -+ */ -+static inline void set_b_state_defaults (struct otg *dev) -+{ -+ dev->transceiver.default_a = 0; -+ if (dev->transceiver.host) { -+ dev->transceiver.host->is_b_host = 1; -+ } -+#ifdef CONFIG_USB_OTG_HIGHSPEED -+ if (dev->transceiver.companion) { -+ dev->transceiver.companion->is_b_host = 1; -+ } -+#endif -+ if (dev->transceiver.gadget) { -+ dev->transceiver.gadget->is_a_peripheral = 0; -+ } -+} -+ -+/** -+ * \brief -+ * set B state information -+ * -+ * \param dev OTG controller info -+ * -+ * \return void -+ */ -+static inline void reset_b_hnp_enable (struct otg *dev) -+{ -+ if (dev->transceiver.host) { -+ dev->transceiver.host->b_hnp_enable = 0; -+ } -+#ifdef CONFIG_USB_OTG_HIGHSPEED -+ if (dev->transceiver.companion) { -+ dev->transceiver.companion->b_hnp_enable = 0; -+ } -+#endif -+ VDBG (" OTG action: HNP disabled in B-device\n"); -+} -+ -+/** -+ * \brief -+ * set B state information -+ * -+ * \param dev OTG controller info -+ * -+ * \return void -+ */ -+static inline int is_b_hnp_enabled (struct otg *dev) -+{ -+ int retVal = 0; -+ -+ if (dev->transceiver.host && -+ dev->transceiver.host->b_hnp_enable) { -+ VDBG (" OTG status: HNP is enabled in HS-B-device\n"); -+ retVal = 1; -+ } -+#ifdef CONFIG_USB_OTG_HIGHSPEED -+ else if (dev->transceiver.companion && -+ dev->transceiver.companion->b_hnp_enable) { -+ VDBG (" OTG status: HNP is enabled in FS-B-device\n"); -+ retVal = 1; -+ } -+#endif -+#ifdef VERBOSE -+ else { -+ DBG (" OTG status: HNP is disabled in B-device\n"); -+ } -+#endif -+ return retVal; -+} -+#endif -+ -+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET) -+ -+/** -+ * \brief -+ * Read the status register -+ * -+ * \param dev OTG controller info -+ * -+ * \return status -+ */ -+static inline u32 get_status (struct otg *dev) -+{ -+ return (readl (&dev->regs->sts)); -+} -+ -+/** -+ * \brief -+ * Load and start the timer for an unconditional run -+ * -+ * \param dev OTG controller info -+ * \param val Value to load -+ * -+ * \return void -+ */ -+static inline void set_timer (struct otg *dev, u32 val) -+{ -+ otg_tmr_high_count = 0; -+ -+ writel ((val), &dev->regs->tmr); -+ VDBG (" OTG action: start timer: %d0 us\n", val); -+} -+ -+/** -+ * \brief -+ * Load and start the timer for an unconditional run -+ * -+ * \param dev OTG controller info -+ * \param val Value to load -+ * -+ * \return void -+ */ -+static inline void set_timer_long (struct otg *dev, u32 val) -+{ -+ otg_tmr_high_count = val - 1; -+ -+ writel (TIMER_PERIOD, &dev->regs->tmr); -+ VDBG (" OTG action: start timer: %d0 ms\n", val); -+} -+ -+/** -+ * \brief -+ * Re-start the timer (value already loaded) -+ * -+ * \param dev OTG controller info -+ * -+ * \return void -+ */ -+static inline void restart_timer (struct otg *dev) -+{ -+ writel ((readl (&dev->regs->ctl) | OTG_CTL_TMR_UNCOND), -+ &dev->regs->ctl); -+} -+ -+/** -+ * \brief -+ * Reset the timer while running (value already loaded) -+ * -+ * \param dev OTG controller info -+ * -+ * \return void -+ */ -+static inline void reset_timer (struct otg *dev) -+{ -+ u32 temp; -+ -+ temp = readl (&dev->regs->ctl); -+ writel ((temp & ~((u32) OTG_CTL_TMR_ALL)), &dev->regs->ctl); -+ writel (temp, &dev->regs->ctl); -+ VDBG (" OTG action: re-start timer\n"); -+} -+ -+/** -+ * \brief -+ * Prepare the D-pulse -+ * -+ * \param dev OTG controller info -+ * -+ * \return void -+ */ -+static inline void set_srp_conditions (struct otg *dev) -+{ -+#ifdef UDC_HSA0_WORKAROUNDS -+ VDBG (" OTG action: SRP init: no action needed due to A0 WAs\n"); -+#else -+ writel ((readl (&dev->regs->cap) & ~((u32) OTG_CAP_APU)), -+ &dev->regs->cap); -+ VDBG (" OTG action: set SRP conditions: disable APU\n"); -+#endif -+} -+ -+/** -+ * \brief -+ * Reset conditions after SRP -+ * -+ * activates the auto-pull-up feature so after SRP the host -+ * will detect a device connect after calling this function -+ * -+ * \param dev OTG controller info -+ * -+ * \return void -+ */ -+static inline void reset_srp_conditions (struct otg *dev) -+{ -+#ifdef UDC_HSA0_WORKAROUNDS -+ VDBG (" OTG action: SRP done: no action needed due to A0 WAs\n"); -+#else -+ writel ((readl (&dev->regs->cap) | OTG_CAP_APU), -+ &dev->regs->cap); -+ VDBG (" OTG action: reset SRP conditions: enable APU\n"); -+#endif -+} -+ -+/** -+ * \brief -+ * enable HNP for both devices -+ * -+ * \param dev OTG controller info -+ * -+ * \return success -+ */ -+static inline int otg_enable_hnp (struct otg *dev) -+{ -+ int retVal = 0; -+ -+/* if (!dev->device) { -+ ERR ("Tried to send OTG request, device pointer not valid\n"); -+ retVal = -ENODEV; -+ } -+ else { -+ retVal = usb_otg_enable_b_hnp (dev->device); -+ DBG (" OTG action: enabled HNP in B-device\n"); -+ } -+ if (retVal < 0) { -+ RES_FLAG (OTG_A_bHNP_EN); -+ } -+ else { -+ SET_FLAG (OTG_A_bHNP_EN); -+ }*/ -+ return retVal; -+} -+ -+#endif /* CONFIG_USB_OTG || CONFIG_USB_OTGMUX_GADGET */ -+#ifdef DEBUG -+/** -+ * \brief -+ * Print OTG controller registers (debug mode only) -+ * -+ * \param dev OTG controller info -+ * -+ * \return void -+ */ -+static inline void print_regs (struct otg *dev) -+{ -+ DBG( "-- UOC registers ---\n"); -+ DBG( "otg cap = %08x\n", readl (&dev->regs->cap)); -+ DBG( "otg mux = %08x\n", readl (&dev->regs->mux)); -+ DBG( "otg sts = %08x\n", readl (&dev->regs->sts)); -+ DBG( "otg ctl = %08x\n", readl (&dev->regs->ctl)); -+ DBG( "otg tmr = %08x\n", readl (&dev->regs->tmr)); -+ DBG( "otg intr = %08x\n", readl (&dev->regs->intr)); -+ DBG( "otg inten = %08x\n", readl (&dev->regs->inten)); -+ DBG( "--------------------\n"); -+} -+#endif /* DEBUG */ -+ -+#ifdef CONFIG_SOC_AU1200 -+ -+/** -+ * \brief -+ * GPIO functions (Au1200 only) -+ * -+ * \param data pin info -+ * -+ * \return success -+ */ -+static inline int au1000gpio_bit_get (u32 data) -+{ -+ return (au_readl ((SYS_PINSTATERD & (1 << data)) ? 1 : 0)); -+} -+ -+#ifdef CONFIG_AU1X00_GPIO -+ -+ /* GPIO functions are defined in drivers/char/au1000_gpio.c */ -+ -+#else -+ -+static inline int au1000gpio_bit_tristate (u32 data) -+{ -+ au_writel ((1 << data), SYS_TRIOUTCLR); -+ return 0; -+} -+ -+static inline int au1000gpio_bit_set (u32 data) -+{ -+ au_writel ((1 << data), SYS_OUTPUTSET); -+ return 0; -+} -+ -+static inline int au1000gpio_bit_clear (u32 data) -+{ -+ au_writel ((1 << data), SYS_OUTPUTCLR); -+ return 0; -+} -+ -+static inline int au1000gpio_bit_init (u32 data) -+{ -+ return au1000gpio_bit_set (data); -+} -+ -+static inline int au1000gpio_bit_term (u32 data) -+{ -+ return au1000gpio_bit_set (data); -+} -+ -+static inline int au1000gpio2_bit_set (u32 data) -+{ -+ au_writel (((1 << (data - GPIO_2_BASE)) | -+ (1 << (data - GPIO_2_BASE + 0x10))), GPIO2_OUTPUT); -+ au_sync(); -+ return 0; -+} -+ -+static inline int au1000gpio2_bit_clear (u32 data) -+{ -+ au_writel ((1 << (data - GPIO_2_BASE + 0x10)), GPIO2_OUTPUT); -+ au_sync(); -+ return 0; -+} -+ -+static inline int au1000gpio2_bit_init (u32 data) -+{ -+ u32 temp = au_readl (GPIO2_ENABLE); -+ -+ if (!(temp | 1)) { -+ au_writel (temp | 1, GPIO2_ENABLE); -+ au_readl (GPIO2_ENABLE); -+ udelay (20); -+ } -+ if (temp | 2) { -+ au_writel (((temp & 0xfffffffd) | 1), GPIO2_ENABLE); -+ au_readl (GPIO2_ENABLE); -+ } -+ -+ /* FIXME: check the system impact of the P0A setting */ -+ /* DbAu1200 pin (GPIO_215) pin is shared w/ PSC0 functions */ -+ /* setting this field to GPIO affects also GPIO_16, GPIO_31 */ -+ -+ if (data == GPIO_215) { -+ au_writel (((au_readl (SYS_PINFUNC) & -+ ~((u32) SYS_PINFUNC_P0A)) | SYS_PINFUNC_P0A_GPIO), -+ SYS_PINFUNC); -+ } -+ au_writel (au_readl (GPIO2_INTENABLE) & ~(1 << (data - GPIO_2_BASE)), -+ GPIO2_INTENABLE); -+ au_writel (au_readl (GPIO2_DIR) | (1 << (data - GPIO_2_BASE)), -+ GPIO2_DIR); -+ au_sync(); -+ return 0; -+} -+ -+static inline int au1000gpio2_bit_term (u32 data) -+{ -+ return au1000gpio2_bit_set (data); -+} -+#endif -+#endif /* CONFIG_SOC_AU1200 */ -+ -+#endif /* AU1200UOC_H */ -diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c -index 8f402f8..e147883 100644 ---- a/drivers/usb/gadget/ether.c -+++ b/drivers/usb/gadget/ether.c -@@ -91,6 +91,13 @@ static const char driver_desc [] = DRIVE - - #define RX_EXTRA 20 /* guard against rx overflows */ - -+#ifdef CONFIG_USB_GADGET_AU1200UDC -+/* -+ * AMD UDC supports dword aligned DMA buffers only, so skbuf buffers -+ * from network layer must be copied -+ */ -+#define UDC_MAX_BUFLEN 2048 /* size of dword aligned buffer */ -+#endif - #include "rndis.h" - - #ifndef CONFIG_USB_ETH_RNDIS -@@ -151,8 +158,13 @@ struct eth_dev { - /* Thanks to NetChip Technologies for donating this product ID. - * It's for devices with only CDC Ethernet configurations. - */ -+#ifdef CONFIG_USB_GADGET_AU1200UDC -+#define CDC_VENDOR_NUM 0x0438 /* AMD */ -+#define CDC_PRODUCT_NUM 0xdc01 /* AMD Linux-USB Ethernet Gadget (temporary) */ -+#else - #define CDC_VENDOR_NUM 0x0525 /* NetChip */ - #define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */ -+#endif - - /* For hardware that can't talk CDC, we use the same vendor ID that - * ARM Linux has used for ethernet-over-usb, both with sa1100 and -@@ -253,6 +265,10 @@ MODULE_PARM_DESC(host_addr, "Host Ethern - #define DEV_CONFIG_CDC - #endif - -+#ifdef CONFIG_USB_GADGET_AU1200UDC -+#define DEV_CONFIG_CDC -+#endif -+ - - /* For CDC-incapable hardware, choose the simple cdc subset. - * Anything that talks bulk (without notable bugs) can do this. -@@ -1056,6 +1072,10 @@ static void eth_reset_config (struct eth - req = container_of (dev->tx_reqs.next, - struct usb_request, list); - list_del (&req->list); -+#ifdef CONFIG_USB_GADGET_AU1200UDC -+ if (req->buf) -+ usb_ep_free_buffer (dev->in_ep, req->buf, req->dma, UDC_MAX_BUFLEN); -+#endif - usb_ep_free_request (dev->in_ep, req); - } - } -@@ -1065,6 +1085,10 @@ static void eth_reset_config (struct eth - req = container_of (dev->rx_reqs.next, - struct usb_request, list); - list_del (&req->list); -+#ifdef CONFIG_USB_GADGET_AU1200UDC -+ if (req->buf) -+ usb_ep_free_buffer (dev->out_ep, req->buf, req->dma, UDC_MAX_BUFLEN); -+#endif - usb_ep_free_request (dev->out_ep, req); - } - } -@@ -1632,7 +1656,9 @@ rx_submit (struct eth_dev *dev, struct u - */ - skb_reserve(skb, NET_IP_ALIGN); - -+#ifndef CONFIG_USB_GADGET_AU1200UDC - req->buf = skb->data; -+#endif - req->length = size; - req->complete = rx_complete; - req->context = skb; -@@ -1674,6 +1700,16 @@ static void rx_complete (struct usb_ep * - break; - } - -+#ifdef CONFIG_USB_GADGET_AU1200UDC -+ /* we need to copy here because AMD UDC needs dword aligned buffers */ -+ VDEBUG(dev, "memcpy( skb->data %lx,req->buf %lx,req->actual %d)\n", skb->data,req->buf,req->actual); -+ if (req->actual <= UDC_MAX_BUFLEN) { -+ memcpy(skb->data, req->buf, req->actual); -+ } -+ else { -+ ERROR(dev, "memcpy of %d bytes bigger than max %d\n", req->actual, UDC_MAX_BUFLEN); -+ } -+#endif - skb->dev = dev->net; - skb->protocol = eth_type_trans (skb, dev->net); - dev->stats.rx_packets++; -@@ -1742,6 +1778,15 @@ static int prealloc (struct list_head *l - req = usb_ep_alloc_request (ep, gfp_flags); - if (!req) - return list_empty (list) ? -ENOMEM : 0; -+ -+ -+#ifdef CONFIG_USB_GADGET_AU1200UDC -+ /* allocate buffer which must be dword aligned for AMD UDC */ -+ req->buf = usb_ep_alloc_buffer (ep, UDC_MAX_BUFLEN, -+ &req->dma, GFP_ATOMIC); -+#endif -+ -+ - list_add (&req->list, list); - } - return 0; -@@ -1753,6 +1798,10 @@ extra: - - next = req->list.next; - list_del (&req->list); -+#ifdef CONFIG_USB_GADGET_AU1200UDC -+ if (req->buf) -+ usb_ep_free_buffer (ep, req->buf, req->dma, UDC_MAX_BUFLEN); -+#endif - usb_ep_free_request (ep, req); - - if (next == list) -@@ -1905,7 +1954,19 @@ static int eth_start_xmit (struct sk_buf - rndis_add_hdr (skb); - length = skb->len; - } -- req->buf = skb->data; -+#ifdef CONFIG_USB_GADGET_AU1200UDC -+ /* we need to copy here because AMD UDC needs dword aligned buffers */ -+ VDEBUG(dev, "memcpy(req->buf %lx, skb->data %lx, length %d)", req->buf, skb->data, length); -+ if (length <= UDC_MAX_BUFLEN) { -+ memcpy(req->buf, skb->data, length); -+ } -+ else { -+ ERROR(dev, "memcpy of %d bytes bigger than max %d\n", length, UDC_MAX_BUFLEN); -+ } -+ VDEBUG(dev, "past memcpy(req->buf %lx, skb->data %lx, length %d)", req->buf, skb->data, length); -+#else -+ req->buf = skb->data; -+#endif - req->context = skb; - req->complete = tx_complete; - -@@ -2202,6 +2263,8 @@ eth_bind (struct usb_gadget *gadget) - /* sh doesn't support multiple interfaces or configs */ - cdc = 0; - rndis = 0; -+ } else if (gadget_is_au1200udc(gadget)) { -+ rndis = 0; - } else if (gadget_is_sa1100 (gadget)) { - /* hardware can't write zlps */ - zlp = 0; -diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c -index ea09aaa..ae800e6 100644 ---- a/drivers/usb/gadget/file_storage.c -+++ b/drivers/usb/gadget/file_storage.c -@@ -263,8 +263,14 @@ MODULE_LICENSE("Dual BSD/GPL"); - * - * DO NOT REUSE THESE IDs with any other driver!! Ever!! - * Instead: allocate your own, using normal USB-IF procedures. */ -+ -+#ifdef CONFIG_USB_GADGET_AU1200UDC -+#define DRIVER_VENDOR_ID 0x0438 // AMD -+#define DRIVER_PRODUCT_ID 0xdc02 // AMD Linux-USB File-backed Storage Gadget (temporary) -+#else - #define DRIVER_VENDOR_ID 0x0525 // NetChip - #define DRIVER_PRODUCT_ID 0xa4a5 // Linux-USB File-backed Storage Gadget -+#endif - - - /* -@@ -3717,6 +3723,8 @@ static int __init check_parameters(struc - mod_data.can_stall = 0; - - if (mod_data.release == 0xffff) { // Parameter wasn't set -+ if (gadget_is_au1200udc(fsg->gadget)) -+ mod_data.can_stall = 0; - /* The sa1100 controller is not supported */ - if (gadget_is_sa1100(fsg->gadget)) - gcnum = -1; -diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h -index 8cbae21..541fbd0 100644 ---- a/drivers/usb/gadget/gadget_chips.h -+++ b/drivers/usb/gadget/gadget_chips.h -@@ -15,6 +15,12 @@ - #define gadget_is_net2280(g) 0 - #endif - -+#ifdef CONFIG_USB_GADGET_AU1200UDC -+#define gadget_is_au1200udc(g) !strcmp("au1200udc", (g)->name) -+#else -+#define gadget_is_au1200udc(g) 0 -+#endif -+ - #ifdef CONFIG_USB_GADGET_DUMMY_HCD - #define gadget_is_dummy(g) !strcmp("dummy_udc", (g)->name) - #else -@@ -143,5 +149,7 @@ static inline int usb_gadget_controller_ - return 0x13; - else if (gadget_is_imx(gadget)) - return 0x14; -+ else if (gadget_is_au1200udc(gadget)) -+ return 0x15; - return -ENOENT; - } -diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c -index 6c58636..4ec28bb 100644 ---- a/drivers/usb/gadget/zero.c -+++ b/drivers/usb/gadget/zero.c -@@ -193,6 +193,10 @@ module_param (loopdefault, bool, S_IRUGO - * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! - * Instead: allocate your own, using normal USB-IF procedures. - */ -+#ifdef CONFIG_USB_GADGET_AU1200UDC -+#define DRIVER_VENDOR_NUM 0x0438 /* AMD */ -+#define DRIVER_PRODUCT_NUM 0xdc00 /* AMD Linux-USB "Gadget Zero" (temporary) */ -+#else - #ifndef CONFIG_USB_ZERO_HNPTEST - #define DRIVER_VENDOR_NUM 0x0525 /* NetChip */ - #define DRIVER_PRODUCT_NUM 0xa4a0 /* Linux-USB "Gadget Zero" */ -@@ -200,6 +204,7 @@ module_param (loopdefault, bool, S_IRUGO - #define DRIVER_VENDOR_NUM 0x1a0a /* OTG test device IDs */ - #define DRIVER_PRODUCT_NUM 0xbadd - #endif -+#endif - - /*-------------------------------------------------------------------------*/ - -@@ -1127,8 +1132,11 @@ zero_unbind (struct usb_gadget *gadget) - DBG (dev, "unbind\n"); - - /* we've already been disconnected ... no i/o is active */ -- if (dev->req) -+ if (dev->req) { -+ /* free with original length */ -+ dev->req->length = USB_BUFSIZ; - free_ep_req (gadget->ep0, dev->req); -+ } - del_timer_sync (&dev->resume); - kfree (dev); - set_gadget_data (gadget, NULL); diff --git a/a/content_digest b/N1/content_digest index 96e8d5c..0e3ef66 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -8,9949 +8,5 @@ " thomas.dahlmann@amd.com\0" "\01:1\0" "b\0" - "From the \"two-birds-one-stone\" department, I am pleased to present USB UDC\n" - "support for both the MIPS Au1200 SoC and the Geode CS5535 south bridge. \n" - "Also, coming soon (in the next few days), OTG, which has been removed from\n" - "the usb_host patch, and put into its own patch (as per David's comments).\n" - "\n" - "This patch is against current linux-mips git, but it should apply for Linus's\n" - "tree as well.\n" - "\n" - "Regards,\n" - Jordan - "\01:2\0" - "fn\0udc.patch\0" - "b\0" - "PATCH: Add UDC support for MIPS/AU1200 and Geode/CS5536\n" - "\n" - "This patch adds UDC support for the AU1200 processor and the Geode CS5536\n" - "southbridge. \n" - "\n" - "Signed-off-by: Jordan Crouse <jordan.crouse@amd.com>\n" - "---\n" - "\n" - " Documentation/usb/au1200udc.txt | 185 +\n" - " drivers/usb/gadget/Kconfig | 86 +\n" - " drivers/usb/gadget/Makefile | 9 \n" - " drivers/usb/gadget/au1200otg.h | 147 +\n" - " drivers/usb/gadget/au1200udc.c | 4880 +++++++++++++++++++++++++++++++++++++\n" - " drivers/usb/gadget/au1200udc.h | 936 +++++++\n" - " drivers/usb/gadget/au1200uoc.c | 2015 +++++++++++++++\n" - " drivers/usb/gadget/au1200uoc.h | 1338 ++++++++++\n" - " drivers/usb/gadget/ether.c | 65 \n" - " drivers/usb/gadget/file_storage.c | 8 \n" - " drivers/usb/gadget/gadget_chips.h | 8 \n" - " drivers/usb/gadget/zero.c | 10 \n" - " 12 files changed, 9684 insertions(+), 3 deletions(-)\n" - "\n" - "diff --git a/Documentation/usb/au1200udc.txt b/Documentation/usb/au1200udc.txt\n" - "new file mode 100644\n" - "index 0000000..20f4d58\n" - "--- /dev/null\n" - "+++ b/Documentation/usb/au1200udc.txt\n" - "@@ -0,0 +1,185 @@\n" - "+-------------------------------------------------------------------------------\n" - "+Howto for Linux device driver for the AU1200 USB Device Controller (UDC)\n" - "+for gadget driver stack\n" - "+-------------------------------------------------------------------------------\n" - "+\n" - "+Author: Thomas Dahlmann\n" - "+\n" - "+INTRODUCTION:\n" - "+\n" - "+The AU1200 UDC is part of AMD MIPS CPU Au1200 and AMD5536 chip (south-\n" - "+bridge of AMD Geode LX Processor).\n" - "+It is a DMA capable usb device controller. The usb port is shared\n" - "+between host and UDC. The Au1200 on-chip OTG controller is used to switch the\n" - "+usb port between host, UDC and neutral. So au1200otg driver is needed\n" - "+to get the UDC operating.\n" - "+\n" - "+Current gadget support: file_storage, ether, zero\n" - "+\n" - "+-------------------------------------------------------------------------------\n" - "+WHAT YOU NEED:\n" - "+-------------------------------------------------------------------------------\n" - "+\n" - "+copy/replace following files to /usr/src/linux/drivers/usb/gadget\n" - "+ au1200udc.c\n" - "+ au1200udc.h\n" - "+ au1200otg.h\n" - "+ au1200uoc.c\n" - "+ au1200uoc.h\n" - "+ ether.c\n" - "+ file_storage.c\n" - "+ zero.c\n" - "+ gadget_chips.h\n" - "+ Makefile\n" - "+ Kconfig \n" - "+\n" - "+-------------------------------------------------------------------------------\n" - "+HOW TO INSTALL IT:\n" - "+-------------------------------------------------------------------------------\n" - "+\n" - "+change to directory /usr/src/linux\n" - "+\n" - "+configure gadget as module:\n" - "+ \"make menuconfig\"\n" - "+ under \"Code maturity level options\" choose \"Prompt for development ...\"\n" - "+ goto \"Device Drivers\"\n" - "+ goto \"USB support\" -> \"USB Gadget support\"\n" - "+ choose \"Support for USB Gadgets\" as module\n" - "+ under choice \"USB Peripheral Controller\" choose \"AU1200UDC\"\n" - "+ under \"USB Gadget Drivers\"\n" - "+ choose \"Gadget Zero\" as module or\n" - "+ choose \"Ethernet Gagdet\" as module or\n" - "+ choose \"File-backed Storage Gadget\" as module\n" - "+ choose \"AU1200 USB portmux control (On-The-Go support)\"\n" - "+ under choice \"OTG port functionality\" choose \"Gadget only\"\n" - "+ exit and save config\n" - "+\n" - "+compile and install modules:\n" - "+ \"make modules modules_install\"\n" - "+\n" - "+-------------------------------------------------------------------------------\n" - "+HOW TO USE IT:\n" - "+-------------------------------------------------------------------------------\n" - "+\n" - "+*** How to load FILE-BACKED STORAGE gadget driver - mass storage ***\n" - "+enable USB mass storage support for linux host:\n" - "+ change to directory /usr/src/linux\n" - "+ \"make menuconfig\"\n" - "+ under \"File systems\" choose \"DOS/FAT/NT filesystems\"\n" - "+ choose \"MSDOS fs support\"\n" - "+ under \"Device Drivers\" under \"SCSI device support\"\n" - "+ choose \"SCSI device support\"\n" - "+ choose \"SCSI generic support\"\n" - "+ under \"Device Drivers\" under \"USB support\" in section \n" - "+ \"USB Device Class drivers\" choose\n" - "+ \"USB Mass Storage support\"\n" - "+ compile new kernel\n" - "+create disk file:\n" - "+ \"dd bs=1M count=128 if=/dev/zero of=/tmp/disk\"\n" - "+ => creates a 128Mbyte image file /tmp/disk\n" - "+load modules:\n" - "+ \"modprobe au1200udc\" \n" - "+ \"modprobe g_file_storage file=/tmp/disk\"\n" - "+ \"modprobe au1200otg\"\n" - "+create a primary FAT16 disk partition via linux host site:\n" - "+ \"fdisk /dev/sda\", make FAT16 prim. partition\n" - "+ => \"n\", \"p\", \"1\", \"<RETURN>\", \"<RETURN>\", \"t\", \"6\", \"w\",\n" - "+ \"mkdosfs /dev/sda1\"\n" - "+ \"sync\"\n" - "+create primary disk partition via Windows XP host site:\n" - "+ right click on \"My Computer\"\n" - "+ choose \"Manage\" => \"Disk Management\"\n" - "+ choose usb disk and follow instructions of partition menu\n" - "+mount usb mass storage device on linux host:\n" - "+ make directory \"/mnt/gadget/\"\n" - "+ \"mount -t msdos /dev/sda1 /mnt/gadget\"\n" - "+\n" - "+*** How to access files of disk image on UDC side ***\n" - "+When files were copied from host to UDC mass storage device then files\n" - "+are inside the monolitic disk image (see above) on UDC side. This\n" - "+disk image can be mounted via the loopback device driver to a \n" - "+directory on UDC side to access these files.\n" - "+Steps on UDC side:\n" - "+ enable kernel support for loopback device\n" - "+ change to directory /usr/src/linux\n" - "+ \"make menuconfig\"\n" - "+ under \"Block devices\" choose \"Loopback device support\"\n" - "+ and recompile the kernel\n" - "+ determine offset inside disk image:\n" - "+ \"fdisk -l -u disk_image\", output is like:\n" - "+>> You must set cylinders.\n" - "+>> You can do this from the extra functions menu.\n" - "+>>\n" - "+>> Disk /tmp/disk128: 5 heads, 52 sectors, 0 cylinders\n" - "+>> Units = sectors of 1 * 512 bytes\n" - "+>>\n" - "+>> Device Boot Start End Blocks Id System\n" - "+>> /tmp/disk128p1 52 262079 131014 6 FAT16\n" - "+\n" - "+ get offset my multiplying start value by sector size:\n" - "+ 52 * 512 = 26624\n" - "+ mount disk image:\n" - "+ \"mount -o loop,offset=26624 -t msdos disk_image /mnt\"\n" - "+\n" - "+\n" - "+*** How to load ZERO gadget driver - simple BULK loop back ***\n" - "+load modules:\n" - "+UDC driver:\n" - "+ (a) Slave/Fifo mode: \"modprobe au1200udc use_dma=0\"\n" - "+ (b) DMA Buffer Fill mode: \"modprobe au1200udc use_dma=1\" \n" - "+ default:\n" - "+ (c) DMA PPBNDU mode: \"modprobe au1200udc\" \n" - "+ (d) DMA PPBDU mode: \"modprobe au1200udc use_dma=1 use_dma_ppb=1 use_dma_ppb_du=1\" \n" - "+ (e) fullspeed mode: \"modprobe au1200udc use_fullspeed=1\", can be combined\n" - "+ with all dma modes \n" - "+ (f) special higspeed\n" - "+ tx buffer size: \"modprobe au1200udc hs_tx_buf=<buf_size in dwords>\"\n" - "+ example: \"modprobe au1200udc use_dma=1 hs_tx_buf=128\"\n" - "+ => buffer size = 512 bytes (=bulk max packet)\n" - "+Gadget Zero driver:\n" - "+ (a) Bulk loop: \"modprobe g_zero\"\n" - "+ (b) Int loop: \"modprobe g_zero use_interrupt_traffic=1\"\n" - "+ (c) Source/Sink \"modprobe g_zero loopdefault=0\"\n" - "+ OUT data must all be zero's\n" - "+ (d) Source/Sink count \"modprobe g_zero loopdefault=0 pattern=1\"\n" - "+ each OUT packet must count modulo63 (0,1,..,62,0,1,..) \n" - "+OTG driver: \"modprobe au1200otg\"\n" - "+example:\n" - "+ \"modprobe au1200udc\"\n" - "+ \"modprobe g_zero\"\n" - "+ \"modprobe au1200otg\"\n" - "+ => loads driver for DMA PPBNDU mode and Bulk loop \n" - "+\n" - "+\n" - "+*** How to use ETHERNET gadget driver (CDC protocol) ***\n" - "+ with Linux Host\n" - "+UDC side bringup: \n" - "+ load gadget modules\n" - "+ \"modprobe au1200udc\" \n" - "+ \"modprobe g_ether\"\n" - "+ \"modprobe au1200otg\"\n" - "+ \"ifconfig usb0 192.168.0.2\" \n" - "+Host side bringup: \n" - "+ install support for CDC Ethernet:\n" - "+ change to directory /usr/src/linux\n" - "+ \"make menuconfig\"\n" - "+ under \"Device Drivers\" under \"USB support\" under\n" - "+ \"USB Network adapters\" choose\n" - "+ \"Multi-purpose USB Networking Framework\"\n" - "+ choose \"CDC Ethernet support\"\n" - "+ compile mew kernel\n" - "+ \"modprobe CDCEther\"\n" - "+ \"ifconfig eth1 192.168.0.1\"\n" - "+ note: assuming there is one network card assigned to eth0,\n" - "+ otherwise kernel messages of CDC Ethernet module show\n" - "+ which interface (ethX) is used \n" - "+Use network connection: \n" - "+ after bringup of host and UDC side it behaves like a normal\n" - "+ ethernet connection between host and UDC\n" - "+ test the connection:\n" - "+ host side: \"ping -I eth1 192.168.0.2\"\n" - "+ UDC side : \"ping -I usb0 192.168.0.1\"\n" - "+ note: the \"-I\" option assures that the USB cable is used, the\n" - "+ option can be omitted when the routing table is setup to avoid\n" - "+ using other network interfaces as eth0\n" - "+\n" - "diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig\n" - "index ff075a5..2a3b652 100644\n" - "--- a/drivers/usb/gadget/Kconfig\n" - "+++ b/drivers/usb/gadget/Kconfig\n" - "@@ -89,7 +89,27 @@ config USB_NET2280\n" - " \tdepends on USB_GADGET_NET2280\n" - " \tdefault USB_GADGET\n" - " \tselect USB_GADGET_SELECTED\n" - "+config USB_GADGET_AU1200UDC\n" - "+\tboolean \"AU1200UDC\"\n" - "+\tdepends on PCI || SOC_AU1200\n" - "+\tselect USB_GADGET_DUALSPEED\n" - "+\thelp\n" - "+\t AU1200 UDC is a PCI based USB peripheral controller which\n" - "+\t supports both full and high speed USB 2.0 data transfers. \n" - "+\t \n" - "+\t It has four configurable endpoints, as well as endpoint zero\n" - "+\t (for control transfers).\n" - "+\n" - "+\t Say \"y\" to link the driver statically, or \"m\" to build a\n" - "+\t dynamically linked module called \"au1200udc\" and force all\n" - "+\t gadget drivers to also be dynamically linked.\n" - " \n" - "+config USB_AU1200UDC\n" - "+\ttristate\n" - "+\tdepends on USB_GADGET_AU1200UDC\n" - "+\tdefault USB_GADGET\n" - "+\tselect USB_GADGET_SELECTED\n" - "+ select USB_PORT_AU1200OTG\n" - " config USB_GADGET_PXA2XX\n" - " \tboolean \"PXA 25x or IXP 4xx\"\n" - " \tdepends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX\n" - "@@ -322,7 +342,7 @@ config USB_ETH\n" - " \n" - " config USB_ETH_RNDIS\n" - " \tbool \"RNDIS support (EXPERIMENTAL)\"\n" - "-\tdepends on USB_ETH && EXPERIMENTAL\n" - "+\tdepends on USB_ETH && EXPERIMENTAL && !(USB_GADGET_AU1200UDC)\n" - " \tdefault y\n" - " \thelp\n" - " \t Microsoft Windows XP bundles the \"Remote NDIS\" (RNDIS) protocol,\n" - "@@ -395,4 +415,68 @@ config USB_G_SERIAL\n" - " \n" - " endchoice\n" - " \n" - "+#\n" - "+# AU1200 USB OTG options\n" - "+#\n" - "+config USB_PORT_AU1200OTG\n" - "+\tboolean \"AU1200 USB portmux control (On-The-Go support)\"\n" - "+\tdepends on USB_GADGET_AU1200UDC || USB_EHCI_HCD || USB_OHCI_HCD\n" - "+\tdefault n\n" - "+\thelp\n" - "+\t The AU1200 and Au1200 USB device port can be used as\n" - "+\t either a host port or a device port.\n" - "+\t Say \"y\" here if you want to use both or if you want to\n" - "+\t setup this port to fit into your board configuration.\n" - "+\n" - "+\t If the AU1200UDC driver is configured to be statically\n" - "+\t linked this module will be linked into the kernel image\n" - "+\t as well otherwise an additional module called\n" - "+\t \"au1200otg\" will be built.\n" - "+\n" - "+config USB_AU1200OTG\n" - "+\ttristate\n" - "+\tdepends on USB_PORT_AU1200OTG\n" - "+\tdefault USB_AU1200UDC\n" - "+\n" - "+choice\n" - "+\tprompt \"OTG port functionality\"\n" - "+\tdepends on USB_PORT_AU1200OTG\n" - "+\tdefault USB_OTGMUX_GADGET\n" - "+\n" - "+config USB_OTGMUX_HOST\n" - "+\tboolean \"Host only\"\n" - "+\tdepends on !USB_GADGET_AU1200UDC && (USB_EHCI_HCD || USB_OHCI_HCD)\n" - "+\thelp\n" - "+\t Select this if your device port is connected to a\n" - "+\t Standard-A or a Mini-A connector.\n" - "+\t It is possible to choose this with a Mini-AB connector\n" - "+\t if the device controller is not to be used.\n" - "+\n" - "+config USB_OTGMUX_GADGET\n" - "+\tboolean \"Gadget only\"\n" - "+\tdepends on USB_GADGET_AU1200UDC\n" - "+\thelp\n" - "+\t Select this if your device port is connected to a\n" - "+\t Standard-B or a Mini-B connector.\n" - "+\t It is possible to choose this with a Mini-AB connector\n" - "+\t if the host controller is not to be used at this port.\n" - "+\n" - "+config USB_OTGMUX_IDPIN\n" - "+\tboolean \"Cable select\"\n" - "+\tdepends on USB_GADGET_AU1200UDC && (USB_EHCI_HCD || USB_OHCI_HCD)\n" - "+\thelp\n" - "+\t Choose this if you want to use both host and device at\n" - "+\t this port. The port multiplexer is controlled by the\n" - "+\t connectors ID pin. If an A-plug is connected the port\n" - "+\t it is routed to the host otherwise it's routed to the\n" - "+\t device controller. \n" - "+\n" - "+ This is useful for validation platforms which use AB\n" - "+ receptacle in order to share one port between host and device.\n" - "+ It is not a USB compliant option.\n" - "+\n" - "+\t Select this only if your device port is connected to\n" - "+\t a Mini-AB connector.\n" - "+\n" - "+endchoice\n" - " endmenu\n" - "diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile\n" - "index d5fd04d..0298250 100644\n" - "--- a/drivers/usb/gadget/Makefile\n" - "+++ b/drivers/usb/gadget/Makefile\n" - "@@ -3,6 +3,7 @@\n" - " #\n" - " obj-$(CONFIG_USB_DUMMY_HCD)\t+= dummy_hcd.o\n" - " obj-$(CONFIG_USB_NET2280)\t+= net2280.o\n" - "+obj-$(CONFIG_USB_AU1200UDC)\t+= au1200udc.o\n" - " obj-$(CONFIG_USB_PXA2XX)\t+= pxa2xx_udc.o\n" - " obj-$(CONFIG_USB_GOKU)\t\t+= goku_udc.o\n" - " obj-$(CONFIG_USB_OMAP)\t\t+= omap_udc.o\n" - "@@ -28,3 +29,11 @@ obj-$(CONFIG_USB_GADGETFS)\t+= gadgetfs.o\n" - " obj-$(CONFIG_USB_FILE_STORAGE)\t+= g_file_storage.o\n" - " obj-$(CONFIG_USB_G_SERIAL)\t+= g_serial.o\n" - " \n" - "+#\n" - "+# AU1200 USB OTG options\n" - "+#\n" - "+ifeq ($(CONFIG_USB_PORT_AU1200OTG),y)\n" - "+obj-$(CONFIG_USB_AU1200OTG)\t+= au1200otg.o\n" - "+\n" - "+au1200otg-objs\t\t\t:= au1200uoc.o\n" - "+endif\n" - "diff --git a/drivers/usb/gadget/au1200otg.h b/drivers/usb/gadget/au1200otg.h\n" - "new file mode 100644\n" - "index 0000000..2b05703\n" - "--- /dev/null\n" - "+++ b/drivers/usb/gadget/au1200otg.h\n" - "@@ -0,0 +1,147 @@\n" - "+/*\n" - "+ * AMD Au1200 USB OTG driver\n" - "+ */\n" - "+\n" - "+/*\n" - "+ * Copyright (C) 2005 AMD (http://www.amd.com)\n" - "+ * Author: Karsten Boge \n" - "+ *\n" - "+ * This program is free software; you can redistribute it and/or modify\n" - "+ * it under the terms of the GNU General Public License as published by\n" - "+ * the Free Software Foundation; either version 2 of the License, or\n" - "+ * (at your option) any later version.\n" - "+ *\n" - "+ * This program is distributed in the hope that it will be useful,\n" - "+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - "+ * GNU General Public License for more details.\n" - "+ *\n" - "+ * You should have received a copy of the GNU General Public License\n" - "+ * along with this program; if not, write to the Free Software\n" - "+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n" - "+ */\n" - "+#ifndef AU1200OTG_H\n" - "+#define AU1200OTG_H\n" - "+\n" - "+/* log Bug 5395 */\n" - "+#define OTG_HNP_ERR_LOG\n" - "+\n" - "+/*****************************************************************************\n" - "+* Constants\n" - "+*****************************************************************************/\n" - "+\n" - "+\n" - "+/**********************************\n" - "+ * OTG sub-state definitions\n" - "+***********************************/\n" - "+\n" - "+#define OTG_STATE_MASK 0x0F\n" - "+\n" - "+#define OTG_STATE_B_HOST_WT (0x10 | OTG_STATE_B_HOST)\n" - "+#define OTG_STATE_B_PERIPHERAL_WT (0x10 | OTG_STATE_B_PERIPHERAL)\n" - "+#define OTG_STATE_B_PERIPHERAL_DC (0x20 | OTG_STATE_B_PERIPHERAL)\n" - "+#define OTG_STATE_B_SRP_WAIT_SE0 (0x10 | OTG_STATE_B_SRP_INIT)\n" - "+#define OTG_STATE_B_SRP_D_PULSE (0x20 | OTG_STATE_B_SRP_INIT)\n" - "+#define OTG_STATE_B_SRP_V_PULSE (0x30 | OTG_STATE_B_SRP_INIT)\n" - "+#define OTG_STATE_B_SRP_V_DCHRG (0x40 | OTG_STATE_B_SRP_INIT)\n" - "+#define OTG_STATE_B_SRP_WAIT_VBUS (0x50 | OTG_STATE_B_SRP_INIT)\n" - "+\n" - "+#define OTG_STATE_A_IDLE_WAIT_DP (0x10 | OTG_STATE_A_IDLE)\n" - "+#define OTG_STATE_A_IDLE_WAIT_VP (0x20 | OTG_STATE_A_IDLE)\n" - "+#define OTG_STATE_A_IDLE_WAIT_MP (0x30 | OTG_STATE_A_IDLE)\n" - "+#define OTG_STATE_A_IDLE_WAIT_DV (0x40 | OTG_STATE_A_IDLE)\n" - "+#define OTG_STATE_A_WAIT_BCON_VB (0x10 | OTG_STATE_A_WAIT_BCON)\n" - "+#define OTG_STATE_A_WAIT_VFALL_DN (0x10 | OTG_STATE_A_WAIT_VFALL)\n" - "+\n" - "+\n" - "+/**********************************\n" - "+* typical timer values\n" - "+**********************************/\n" - "+\n" - "+#define OTG_TMR_WAIT_VFALL 10 /* ( ) A waits for VBus */\n" - "+#define OTG_TMR_A_WAIT_VRISE 100 /* ( ) A waits for VBus */\n" - "+#define OTG_TMR_A_WAIT_BCON 200 /* ( ) A waits for B-connect (1.. s) */\n" - "+#define OTG_TMR_A_IDLE_BDIS 250 /* (ms) A waits for B-disc (200.. ms) */\n" - "+#define OTG_TMR_B_WAIT_ADISCON 600 /* (us) B waits for A to disconnect <1ms */\n" - "+#define OTG_TMR_B_ACON_BRST 200 /* (us) B waits before starting reset */\n" - "+#define OTG_TMR_B_ASE0_BRST 5 /* (ms) B waits for A-conn (3.125.. ms) */\n" - "+#define OTG_TMR_B_AIDL_BDIS 50 /* (ms) B waits before dc (5..150ms) */\n" - "+#define OTG_TMR_SRP_WAIT_SE0 2 /* ( ) B SRP idle wait */\n" - "+#define OTG_TMR_SRP_WAIT_DP 7 /* (ms) B SRP D_PULSE (5..10ms) */\n" - "+#define OTG_TMR_SRP_WAIT_VP 80 /* (ms) B SRP V_PULSE (5..100ms) */\n" - "+#define OTG_TMR_SRP_DCHRG_V 30 /* ( ) B SRP VBus discharge */\n" - "+#define OTG_TMR_SRP_WAIT_VRS 5800 /* (ms) B SRP waits for VBus (5..6s) */\n" - "+#define OTG_TMR_ASRP_WAIT_MP 4 /* ( ) A SRP min. pulse */\n" - "+#define OTG_TMR_ASRP_WAIT_DP 10 /* (ms) A SRP D_PULSE TO */\n" - "+#define OTG_TMR_ASRP_WAIT_VP 200 /* (ms) A SRP V_PULSE TO */\n" - "+#define OTG_TMR_ASRP_WAIT_DV 200 /* ( ) A SRP waits for V_PULSE */\n" - "+#define OTG_TMR_A_BCON_VB 50 /* ( ) A waits for VBus after connect */\n" - "+\n" - "+#define OTG_TMR_IDSNS_WAIT 10 /* (ms) ID sense wait */\n" - "+\n" - "+/*********************************/\n" - "+\n" - "+#define TIMER_PERIOD 1000 /* 10 ms, if longer than 10ms */\n" - "+\n" - "+/**********************************\n" - "+ * OTG state parameters\n" - "+ **********************************/\n" - "+\n" - "+#define OTG_HOST_READY (1<<20) /* indicates a USB host driver is */\n" - "+ /* running */\n" - "+#define OTG_GADGET_READY (1<<21) /* indicates a USB gadget driver is */\n" - "+ /* running */\n" - "+#define OTG_A_BUS_REQ (1<<22) /* used by appl-SW to request a */\n" - "+ /* VBus rise, auto-reset by driver */\n" - "+#define OTG_A_BUS_DROP (1<<23) /* used by appl-SW to request a */\n" - "+ /* VBus drop, auto-reset by driver */\n" - "+#define OTG_A_CLR_ERR (1<<24) /* used by appl-SW to request VBerr */\n" - "+ /* clean-up, auto-reset by driver */\n" - "+#define OTG_AB_HNP_REQ (1<<25) /* used by appl-SW to initiate */\n" - "+ /* HNP, auto-reset by driver */\n" - "+#define OTG_B_BUS_REQ (1<<26) /* used by appl-SW to request */\n" - "+ /* B-device functionality, ... */\n" - "+#define OTG_B_BUS_DIS (1<<27) /* used by appl-SW to request */\n" - "+ /* disable B-device functionality */\n" - "+#define OTG_B_aSSN_REQ (1<<28) /* used by appl-SW to initiate SRP, */\n" - "+ /* auto-reset by the driver */\n" - "+#define OTG_B_SRP_ERROR (1<<29) /* indicates invalid HW conditions */\n" - "+ /* during SRP, reset by writing \"1\" */\n" - "+#define OTG_A_VBUS_FAILED (1<<30) /* indicates a VBus error, reset by */\n" - "+ /* writing \"1\", when setting */\n" - "+ /* CLR_ERR or when leaving A-states */\n" - "+#define OTG_UDC_RWK_REQ (1<<31) /* call UDC function to force a */\n" - "+ /* remote wake-up */\n" - "+\n" - "+#define SW_REQUEST_MASK (OTG_A_BUS_REQ | OTG_A_BUS_DROP | \\\n" - "+ OTG_A_CLR_ERR | OTG_B_aSSN_REQ | \\\n" - "+ OTG_B_BUS_REQ | OTG_B_BUS_DIS | \\\n" - "+ OTG_UDC_RWK_REQ)\n" - "+\n" - "+/*********************************************************************/\n" - "+\n" - "+/*\n" - "+ * gadget events for notify function\n" - "+ */\n" - "+#define OTG_GADGET_EVT_SVDROP (1<<0) /* Session valid drop */\n" - "+#define OTG_GADGET_EVT_SVALID (1<<1) /* Session valid */\n" - "+#define OTG_GADGET_REQ_WAKE (1<<2) /* Request remote wake-up */\n" - "+\n" - "+/*** HS-A0 WA: gadget phy suspend issue ***/\n" - "+#define OTG_FLAGS_UDC_SUSP (1<<17) /* gadget phy suspended */\n" - "+\n" - "+#ifdef OTG_HNP_ERR_LOG\n" - "+#define OTG_FLAGS_HNP_ERR (1<<18) /* HNP error bug 5395 occured */\n" - "+#endif\n" - "+\n" - "+/*****************************************************************************\n" - "+* Data\n" - "+*****************************************************************************/\n" - "+\n" - "+struct usb_otg_gadget_extension {\n" - "+\tint (*request) (u32);\t/* function call for state change requests */\n" - "+\tu32 (*query) (int);\t/* function call to query state */\n" - "+\tvoid (*notify) (u32); /* filled in by gadget for notification */\n" - "+};\n" - "+\n" - "+#endif /* AU1200OTG_H */\n" - "diff --git a/drivers/usb/gadget/au1200udc.c b/drivers/usb/gadget/au1200udc.c\n" - "new file mode 100644\n" - "index 0000000..7153902\n" - "--- /dev/null\n" - "+++ b/drivers/usb/gadget/au1200udc.c\n" - "@@ -0,0 +1,4880 @@\n" - "+/*\n" - "+ * AMD Au1200 UDC high/full speed USB device controller driver.\n" - "+ *\n" - "+ * Note: Driver also works with AMD Geode LX southbridge AMD5536 \n" - "+ */\n" - "+\n" - "+/*\n" - "+ * Copyright (C) 2005 AMD (http://www.amd.com)\n" - "+ * Author: Thomas Dahlmann \n" - "+ *\n" - "+ * This program is free software; you can redistribute it and/or modify\n" - "+ * it under the terms of the GNU General Public License as published by\n" - "+ * the Free Software Foundation; either version 2 of the License, or\n" - "+ * (at your option) any later version.\n" - "+ *\n" - "+ * This program is distributed in the hope that it will be useful,\n" - "+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - "+ * GNU General Public License for more details.\n" - "+ *\n" - "+ * You should have received a copy of the GNU General Public License\n" - "+ * along with this program; if not, write to the Free Software\n" - "+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n" - "+ */\n" - "+\n" - "+/*****************************************************************************\n" - "+ * Defines\n" - "+ *****************************************************************************/\n" - "+\n" - "+/* debug control */\n" - "+#undef UDC_DEBUG\n" - "+/* #define UDC_DEBUG 1 */\n" - "+#undef UDC_VERBOSE\n" - "+/* #define UDC_VERBOSE */ \n" - "+/* #define UDC_REGISTER_DUMP */\n" - "+\n" - "+/* Driver strings */\n" - "+#define UDC_MOD_DESCRIPTION \"AMD Au1200 UDC - USB Device Controller\"\n" - "+#define UDC_DRIVER_VERSION_STRING \"01.00.0204 - $Revision: #4 $\"\n" - "+\n" - "+/*****************************************************************************\n" - "+ * Includes\n" - "+ *****************************************************************************/\n" - "+\n" - "+/* system */\n" - "+#include <linux/config.h>\n" - "+#include <linux/module.h>\n" - "+#include <linux/pci.h>\n" - "+#include <linux/kernel.h>\n" - "+#include <linux/version.h>\n" - "+#include <linux/delay.h>\n" - "+#include <linux/ioport.h>\n" - "+#include <linux/sched.h>\n" - "+#include <linux/slab.h>\n" - "+#include <linux/smp_lock.h>\n" - "+#include <linux/errno.h>\n" - "+#include <linux/init.h>\n" - "+#include <linux/timer.h>\n" - "+#include <linux/list.h>\n" - "+#include <linux/interrupt.h>\n" - "+#include <linux/ioctl.h>\n" - "+#include <linux/fs.h>\n" - "+#include <linux/dmapool.h>\n" - "+#include <linux/moduleparam.h>\n" - "+#include <linux/device.h>\n" - "+#include <asm/byteorder.h>\n" - "+#include <asm/io.h>\n" - "+#include <asm/irq.h>\n" - "+#include <asm/system.h>\n" - "+#include <asm/unaligned.h>\n" - "+\n" - "+/* MIPS config */\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+#include <asm/mach-au1x00/au1000.h>\n" - "+#include <linux/platform_device.h>\n" - "+#endif\n" - "+\n" - "+/* gadget stack */\n" - "+#include <linux/usb_ch9.h>\n" - "+#include <linux/usb_gadget.h>\n" - "+#include <linux/usb_otg.h>\n" - "+\n" - "+/* udc/uoc specific */\n" - "+#include \"au1200udc.h\"\n" - "+#include \"au1200uoc.h\"\n" - "+\n" - "+\n" - "+/* use RDE timer for new kernel only */\n" - "+#define UDC_USE_TIMER\n" - "+/*****************************************************************************\n" - "+ * Static Function Declarations\n" - "+ *****************************************************************************/\n" - "+\n" - "+void udc_tasklet_disconnect(unsigned long);\n" - "+#ifdef UDC_USE_TIMER\n" - "+void udc_timer_function(unsigned long v);\n" - "+void udc_pollstall_timer_function(unsigned long v);\n" - "+#endif\n" - "+static int udc_rxfifo_read_dwords(struct udc* dev, u32* buf, int dwords);\n" - "+static void empty_req_queue (struct udc_ep *);\n" - "+static int udc_probe (struct udc* dev);\n" - "+static void udc_basic_init (struct udc *dev);\n" - "+static void udc_setup_endpoints (struct udc *dev);\n" - "+static void udc_soft_reset(struct udc* dev);\n" - "+#ifdef UDC_DEBUG\n" - "+static void dump_buffer(u8* buf, u32 bytes);\n" - "+static int udc_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);\n" - "+static int udc_open (struct inode *inode, struct file *file);\n" - "+static int udc_release (struct inode *inode, struct file *file);\n" - "+#endif\n" - "+static struct udc_data_dma* udc_get_last_dma_desc(struct udc_request* req);\n" - "+static u32 udc_get_ppbdu_rxbytes(struct udc_request* req);\n" - "+static int udc_free_dma_chain(struct udc* dev, struct udc_request* req);\n" - "+static int udc_create_dma_chain(struct udc_ep* ep, struct udc_request* req, unsigned long buf_len, int gfp_flags);\n" - "+static inline int startup_registers(struct udc* dev);\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+void au1200_sync(void);\n" - "+#endif\n" - "+static int udc_remote_wakeup(struct udc* dev);\n" - "+#if defined(CONFIG_SOC_AU1200)\n" - "+static int udc_suspend(struct udc* dev);\n" - "+static int udc_resume(struct udc* dev);\n" - "+#else\n" - "+static int udc_pci_probe (struct pci_dev *pdev, const struct pci_device_id *id);\n" - "+static void udc_pci_remove (struct pci_dev *pdev);\n" - "+#endif\n" - "+\n" - "+/*****************************************************************************\n" - "+ * Data\n" - "+ *****************************************************************************/\n" - "+\n" - "+/* description */\n" - "+static const char mod_desc [] = UDC_MOD_DESCRIPTION;\n" - "+static const char name [] = DRIVER_NAME_FOR_PRINT; \n" - "+\n" - "+/* structure to hold endpoint function pointers */\n" - "+static struct usb_ep_ops udc_ep_ops;\n" - "+\n" - "+/* received setup data */\n" - "+static union udc_setup_data setup_data;\n" - "+\n" - "+/* pointer to device object */ \n" - "+static struct udc *udc;\n" - "+\n" - "+/* irq spin lock for soft reset */\n" - "+spinlock_t udc_irq_spinlock;\n" - "+/* stall spin lock */\n" - "+spinlock_t udc_stall_spinlock;\n" - "+\n" - "+/* this is used for dma chaining */\n" - "+static int udc_gfp_flags = 0;\n" - "+ \n" - "+/* slave mode: pending bytes in rx fifo after nyet,\n" - "+used if EPIN irq came but no req was available */\n" - "+static unsigned int udc_rxfifo_pending = 0;\n" - "+\n" - "+/* count soft resets after suspend to avoid loop */\n" - "+static int soft_reset_occured = 0;\n" - "+#ifdef UDC_IPBUG_3958_WORKAROUND\n" - "+static int soft_reset_after_usbreset_occured = 0;\n" - "+#endif\n" - "+\n" - "+#ifdef UDC_USE_TIMER\n" - "+/* timer */\n" - "+static struct timer_list udc_timer;\n" - "+static int stop_timer = 0;\n" - "+int set_rde = -1;\n" - "+DECLARE_COMPLETION(on_exit);\n" - "+static struct timer_list udc_pollstall_timer;\n" - "+static int stop_pollstall_timer = 0;\n" - "+DECLARE_COMPLETION(on_pollstall_exit);\n" - "+#endif\n" - "+\n" - "+/* tasklet for usb disconnect */\n" - "+DECLARE_TASKLET(disconnect_tasklet, udc_tasklet_disconnect, (unsigned long) &udc);\n" - "+\n" - "+#ifdef USE_AU1200_PCI_DUMMY\n" - "+static struct pci_dev pdev_dummy;\n" - "+static struct pci_dev* pdev = &pdev_dummy;\n" - "+#endif\n" - "+\n" - "+#ifdef UDC_IPBUG_3958_WORKAROUND\n" - "+/* CNAK pending field: bit0 = ep0in, bit16 = ep0out */\n" - "+static u32 cnak_pending = 0;\n" - "+#define UDC_QUEUE_CNAK(ep, num) \\\n" - "+ if (readl(&((ep)->regs->ctl)) & AMD_BIT(UDC_EPCTL_NAK)) { \\\n" - "+ DBG(\"NAK could not be cleared for ep%d\\n\", num); \\\n" - "+ cnak_pending |= 1 << (num); \\\n" - "+ (ep)->naking = 1; \\\n" - "+ } \\\n" - "+ else \\\n" - "+ cnak_pending = cnak_pending & (~(1<<(num))); \n" - "+#else\n" - "+#define UDC_QUEUE_CNAK(ep, num) {} \n" - "+#endif\n" - "+\n" - "+#ifdef UDC_IPBUG_3943_WORKAROUND\n" - "+/* otg registering count */\n" - "+static u32 otg_reg_count = 0;\n" - "+#endif\n" - "+/* gadget registering count */\n" - "+static u32 gadget_bind_count = 0;\n" - "+\n" - "+/* endpoint names used for print */\n" - "+static const char ep0_string[] = \"ep0in\";\n" - "+static const char *ep_string[] = {\n" - "+ ep0_string,\n" - "+ \"ep1in-int\", \"ep2in-bulk\", \"ep3in-bulk\", \"ep4in-bulk\", \"ep5in-bulk\", \"ep6in-bulk\", \"ep7in-bulk\", \"ep8in-bulk\",\n" - "+ \"ep9in-bulk\", \"ep10in-bulk\", \"ep11in-bulk\", \"ep12in-bulk\", \"ep13in-bulk\", \"ep14in-bulk\", \"ep15in-bulk\", \"ep0out\",\n" - "+ \"ep1out-bulk\", \"ep2out-bulk\", \"ep3out-bulk\", \"ep4out-bulk\", \"ep5out-bulk\", \"ep6out-bulk\", \"ep7out-bulk\", \"ep8out-bulk\",\n" - "+ \"ep9out-bulk\", \"ep10out-bulk\", \"ep11out-bulk\", \"ep12out-bulk\", \"ep13out-bulk\", \"ep14out-bulk\", \"ep15out-bulk\" \n" - "+};\n" - "+\n" - "+#ifdef UDC_DEBUG\n" - "+/* driver callback functions */\n" - "+static struct file_operations udc_fops = {\n" - "+ owner: THIS_MODULE,\n" - "+\n" - "+ read: NULL,\n" - "+ write: NULL,\n" - "+ ioctl: udc_ioctl,\n" - "+ open: udc_open,\n" - "+ release: udc_release,\n" - "+};\n" - "+#endif\n" - "+\n" - "+/* PCI device parameters */\n" - "+static struct pci_device_id pci_id[] = {{\n" - "+ .vendor = UDC_PCI_VENID,\n" - "+ .device = UDC_PCI_DEVID,\n" - "+ .class = UDC_PCI_CLASS,\n" - "+ .class_mask = UDC_PCI_CLASS_MASK,\n" - "+ .subvendor = PCI_ANY_ID,\n" - "+ .subdevice = PCI_ANY_ID,\n" - "+},\n" - "+{}\n" - "+};\n" - "+\n" - "+#if !defined(CONFIG_SOC_AU1200)\n" - "+/* PCI functions */\n" - "+static struct pci_driver udc_pci_driver = {\n" - "+ .name = (char *) name,\n" - "+ .id_table = pci_id,\n" - "+ .probe = udc_pci_probe,\n" - "+ .remove = udc_pci_remove,\n" - "+};\n" - "+#endif\n" - "+\n" - "+#ifdef UDC_DEBUG\n" - "+/* data for debuging only */\n" - "+static unsigned long no_pref_req = 0;\n" - "+static unsigned long no_req = 0;\n" - "+static u32 same_cfg = 0;\n" - "+static u32 num_enums = 0;\n" - "+#endif\n" - "+\n" - "+/****** following flags can be set by module parameters */\n" - "+/* DMA usage flag */\n" - "+static int use_dma = 1;\n" - "+/* packet per buffer dma */\n" - "+static int use_dma_ppb = 1;\n" - "+/* with per descr. update */\n" - "+static int use_dma_ppb_du = 0;\n" - "+/* buffer fill mode */\n" - "+static int use_dma_bufferfill_mode = 0;\n" - "+/* full speed only mode */\n" - "+static int use_fullspeed = 0;\n" - "+/* tx buffer size for high speed */\n" - "+static unsigned long hs_tx_buf = UDC_EPIN_BUFF_SIZE;\n" - "+\n" - "+/* module parameters */\n" - "+MODULE_PARM (use_dma, \"i\");\n" - "+MODULE_PARM_DESC (use_dma, \"true for DMA\");\n" - "+MODULE_PARM (use_dma_ppb, \"i\");\n" - "+MODULE_PARM_DESC (use_dma_ppb, \"true for DMA in packet per buffer mode\");\n" - "+MODULE_PARM (use_dma_ppb_du, \"i\");\n" - "+MODULE_PARM_DESC (use_dma_ppb_du, \"true for DMA in packet per buffer mode with descriptor update\");\n" - "+MODULE_PARM (use_fullspeed, \"i\");\n" - "+MODULE_PARM_DESC (use_fullspeed, \"true for fullspeed only\");\n" - "+MODULE_PARM (hs_tx_buf, \"l\");\n" - "+MODULE_PARM_DESC (hs_tx_buf, \"high speed tx buffer size for data endpoints in dwords\");\n" - "+\n" - "+MODULE_DESCRIPTION (UDC_MOD_DESCRIPTION);\n" - "+MODULE_AUTHOR (\"Thomas Dahlmann\");\n" - "+MODULE_LICENSE(\"GPL\");\n" - "+\n" - "+#ifndef USE_AU1200_PCI_DUMMY\n" - "+MODULE_DEVICE_TABLE (pci, pci_id);\n" - "+#endif\n" - "+\n" - "+/*****************************************************************************\n" - "+ * Function Definitions\n" - "+ *****************************************************************************/\n" - "+\n" - "+/* AU specific */\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+void au1200_sync(void)\n" - "+{\n" - "+ au1200_sync_delay();\n" - "+}\n" - "+#endif\n" - "+\n" - "+#ifdef UDC_DEBUG\n" - "+/**\n" - "+ * Dumps byte read access\n" - "+ * \n" - "+ * \\param a address pointer\n" - "+ * \\return read byte\n" - "+ */\n" - "+static void print_td(struct udc_data_dma *p)\n" - "+{\n" - "+ INFO(\"td = %08lx: status=%08lx bufptr=%08lx next=%08lx\\n\", \n" - "+ (unsigned long) p,\n" - "+ (unsigned long) p->status,\n" - "+ (unsigned long) p->bufptr,\n" - "+ (unsigned long) p->next);\n" - "+}\n" - "+#endif\n" - "+\n" - "+/* printing registers --------------------------------------------------------*/\n" - "+/**\n" - "+ * Prints UDC device registers and endpoint irq registers\n" - "+ * \n" - "+ * \\param dev pointer to device struct \n" - "+ */\n" - "+static void print_regs(struct udc* dev)\n" - "+{\n" - "+#ifndef UDC_IPBUG_3943_WORKAROUND\n" - "+ DBG( \"------- Device registers -------\\n\");\n" - "+ DBG( \"dev config = %08lx\\n\", (unsigned long) dev->regs->cfg);\n" - "+ DBG( \"dev control = %08lx\\n\", (unsigned long) dev->regs->ctl);\n" - "+ DBG( \"dev status = %08lx\\n\", (unsigned long) dev->regs->sts);\n" - "+ DBG( \"\\n\");\n" - "+ DBG( \"dev int's = %08lx\\n\", (unsigned long) dev->regs->irqsts);\n" - "+ DBG( \"dev intmask = %08lx\\n\", (unsigned long) dev->regs->irqmsk);\n" - "+ DBG( \"\\n\");\n" - "+ DBG( \"dev ep int's = %08lx\\n\", (unsigned long) dev->regs->ep_irqsts);\n" - "+ DBG( \"dev ep intmask = %08lx\\n\", (unsigned long) dev->regs->ep_irqmsk);\n" - "+ DBG( \"\\n\");\n" - "+#endif\n" - "+ DBG( \"USE DMA = %d\\n\", use_dma);\n" - "+ if (use_dma && use_dma_ppb && !use_dma_ppb_du) {\n" - "+ DBG( \"DMA mode = PPBNDU (packet per buffer WITHOUT desc. update)\\n\");\n" - "+#ifndef UDC_DEBUG\n" - "+ INFO( \"DMA mode (PPBNDU)\\n\");\n" - "+#endif\n" - "+ } \n" - "+ else if (use_dma && use_dma_ppb_du && use_dma_ppb_du) {\n" - "+ DBG( \"DMA mode = PPBDU (packet per buffer WITH desc. update)\\n\");\n" - "+#ifndef UDC_DEBUG\n" - "+ INFO( \"DMA mode (PPBDU)\\n\");\n" - "+#endif\n" - "+ } \n" - "+ if (use_dma && use_dma_bufferfill_mode) {\n" - "+ DBG( \"DMA mode = BF (buffer fill mode)\\n\");\n" - "+#ifndef UDC_DEBUG\n" - "+ INFO( \"DMA mode (BF)\\n\");\n" - "+#endif\n" - "+ } \n" - "+#ifndef UDC_DEBUG\n" - "+ if (!use_dma) {\n" - "+ INFO( \"FIFO mode\\n\");\n" - "+ } \n" - "+#endif\n" - "+#ifdef UDC_USE_TIMER\n" - "+ INFO(\"RDE timer is used\\n\");\n" - "+#endif\n" - "+ DBG(\"-------------------------------------------------------\\n\"); \n" - "+}\n" - "+\n" - "+/**\n" - "+ * Prints snapshot of ep registers\n" - "+ * \n" - "+ * \\param dev pointer to device struct\n" - "+ */\n" - "+#ifdef UDC_DEBUG\n" - "+static void print_ep_regs(struct udc* dev, struct udc_ep_regs* ep_regs)\n" - "+{\n" - "+ INFO( \"ep control = %08lx\\n\", (unsigned long) ep_regs->ctl);\n" - "+ INFO( \"ep status = %08lx\\n\", (unsigned long) ep_regs->sts);\n" - "+ INFO( \"--------------------------------\\n\");\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Prints misc information, to be removed\n" - "+ * \n" - "+ * \\param dev pointer to device struct\n" - "+ */\n" - "+static void print_misc(struct udc* dev)\n" - "+{\n" - "+ print_regs(dev);\n" - "+ \n" - "+ if (use_dma) {\n" - "+\n" - "+ INFO(\"no_req=%ld no_pref_req=%ld\\n\", no_req, no_pref_req);\n" - "+ }\n" - "+}\n" - "+#endif\n" - "+\n" - "+/* driver functions ----------------------------------------------------------*/\n" - "+/**\n" - "+ * Called by OS for insmod \n" - "+ * \n" - "+ * \\param inode file node\n" - "+ * \\param file struct\n" - "+ * \\return read byte\n" - "+ */\n" - "+#ifdef UDC_DEBUG\n" - "+static int udc_open (struct inode *inode, struct file *file)\n" - "+{\n" - "+ int retval = 0;\n" - "+ return retval;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Called by OS for rmmod \n" - "+ * \n" - "+ * \\param inode file node\n" - "+ * \\param file file struct\n" - "+ * \\return read byte\n" - "+ */\n" - "+static int udc_release (struct inode *inode, struct file *file)\n" - "+{\n" - "+ int retval = 0;\n" - "+ return retval;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Called by OS for ioctl() from user space\n" - "+ * \n" - "+ * \\param inode file node\n" - "+ * \\param file file struct\n" - "+ * \\param command ioctl command code\n" - "+ * \\param argument ioctl argument\n" - "+ * \\return 0 if success \n" - "+ */\n" - "+static int udc_ioctl (struct inode *inode, \n" - "+ struct file *file, \n" - "+ unsigned int command,\n" - "+ unsigned long argument)\n" - "+{\n" - "+ struct udc* dev = udc;\n" - "+ \n" - "+ if (!dev)\n" - "+ return -EINVAL;\n" - "+ \n" - "+ /* for testing PM */ \n" - "+ switch (command)\n" - "+ {\n" - "+ case 1:\n" - "+ udc_remote_wakeup(udc);\n" - "+ break;\n" - "+ case 5:\n" - "+ udc_suspend(udc);\n" - "+ break;\n" - "+ case 6:\n" - "+ udc_resume(udc);\n" - "+ break;\n" - "+ }\n" - "+ \n" - "+ INFO( \"ioctl called\\n\");\n" - "+\n" - "+ return 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Prints a buffers contents \n" - "+ * \\param buf pointer to buffer\n" - "+ * \\param bytes number bytes to print\n" - "+ */\n" - "+static void dump_buffer(u8* buf, u32 bytes)\n" - "+{\n" - "+ int i;\n" - "+\n" - "+ printk(\"\\nbuffer %lx = %d bytes:\\n\", (unsigned long) buf, bytes);\n" - "+ for (i = 0; i < bytes; i++) {\n" - "+ printk(\"%02x\", *(buf + i));\n" - "+ if ((i+1)%16 == 0)\n" - "+ printk(\"\\n\");\n" - "+ }\n" - "+ printk(\"\\n\");\n" - "+}\n" - "+#endif\n" - "+\n" - "+/**\n" - "+ * Masks unused interrupts \n" - "+ * \n" - "+ * \\param dev pointer to device struct\n" - "+ * \\return 0 if success \n" - "+ */\n" - "+static int udc_mask_unused_interrupts(struct udc* dev)\n" - "+{\n" - "+ u32 tmp;\n" - "+\n" - "+ /* mask all dev interrupts */\n" - "+ tmp = AMD_BIT(UDC_DEVINT_SVC) |\n" - "+ AMD_BIT(UDC_DEVINT_ENUM) |\n" - "+ AMD_BIT(UDC_DEVINT_US) |\n" - "+ AMD_BIT(UDC_DEVINT_UR) |\n" - "+ AMD_BIT(UDC_DEVINT_ES) |\n" - "+ AMD_BIT(UDC_DEVINT_SI) |\n" - "+ AMD_BIT(UDC_DEVINT_SOF)|\n" - "+ AMD_BIT(UDC_DEVINT_SC);\n" - "+ writel(tmp, &dev->regs->irqmsk); \n" - "+ \n" - "+ /* mask all ep interrupts */\n" - "+ writel(UDC_EPINT_MSK_DISABLE_ALL, &dev->regs->ep_irqmsk); \n" - "+\n" - "+ return 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Enables endpoint 0 interrupts \n" - "+ * \n" - "+ * \\param dev pointer to device struct\n" - "+ * \\return 0 if success \n" - "+ */\n" - "+static int udc_enable_ep0_interrupts(struct udc* dev)\n" - "+{\n" - "+ u32 tmp;\n" - "+\n" - "+ DBG(\"udc_enable_ep0_interrupts()\\n\");\n" - "+\n" - "+ /* read irq mask */\n" - "+ tmp = readl(&dev->regs->ep_irqmsk);\n" - "+ /* enable ep0 irq's */\n" - "+ tmp &= AMD_UNMASK_BIT(UDC_EPINT_IN_EP0)\n" - "+ & AMD_UNMASK_BIT(UDC_EPINT_OUT_EP0); \n" - "+ writel(tmp, &dev->regs->ep_irqmsk); \n" - "+\n" - "+ return 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Enables device interrupts for SET_INTF and SET_CONFIG\n" - "+ * \n" - "+ * \\param dev pointer to device struct\n" - "+ * \\return 0 if success \n" - "+ */\n" - "+static int udc_enable_dev_setup_interrupts(struct udc* dev)\n" - "+{\n" - "+ u32 tmp;\n" - "+\n" - "+ DBG(\"enable device interrupts for setup data\\n\");\n" - "+\n" - "+ /* read irq mask */\n" - "+ tmp = readl(&dev->regs->irqmsk);\n" - "+ \n" - "+ /* enable SET_INTERFACE, SET_CONFIG and other needed irq's */\n" - "+ tmp &= AMD_UNMASK_BIT(UDC_DEVINT_SI)\n" - "+ & AMD_UNMASK_BIT(UDC_DEVINT_SC) \n" - "+ & AMD_UNMASK_BIT(UDC_DEVINT_UR) \n" - "+#ifndef UDC_IPBUG_3943_WORKAROUND\n" - "+ & AMD_UNMASK_BIT(UDC_DEVINT_US) \n" - "+#endif\n" - "+#ifndef UDC_IPBUG_3950_WORKAROUND\n" - "+ & AMD_UNMASK_BIT(UDC_DEVINT_SVC)\n" - "+#endif\n" - "+ & AMD_UNMASK_BIT(UDC_DEVINT_ENUM);\n" - "+ writel(tmp, &dev->regs->irqmsk); \n" - "+\n" - "+ return 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Calculates fifo start of endpoint based on preceeding endpoints\n" - "+ * \n" - "+ * \\param ep pointer to ep struct\n" - "+ * \\return 0 if success \n" - "+ */\n" - "+static int udc_set_txfifo_addr(struct udc_ep *ep)\n" - "+{\n" - "+ struct udc *dev;\n" - "+ u32 tmp;\n" - "+ int i;\n" - "+\n" - "+ if (!ep || !(ep->in))\n" - "+ return -EINVAL;\n" - "+ \n" - "+ dev = ep->dev;\n" - "+ ep->txfifo = dev->txfifo;\n" - "+\n" - "+ /* traverse ep's */\n" - "+ for (i = 0; i < ep->num; i++) {\n" - "+ if (dev->ep[i].regs) {\n" - "+ /* read fifo size */\n" - "+ tmp = readl(&dev->ep[i].regs->bufin_framenum);\n" - "+ tmp = AMD_GETBITS(tmp, UDC_EPIN_BUFF_SIZE);\n" - "+ ep->txfifo+= tmp;\n" - "+ }\n" - "+ }\n" - "+ return 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Enables endpoint, is called by gadget driver\n" - "+ * \n" - "+ * \\param usbep pointer to ep struct\n" - "+ * \\param desc pointer to endpoint descriptor\n" - "+ * \\return 0 if success \n" - "+ */\n" - "+static int\n" - "+udc_enable (struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc)\n" - "+{\n" - "+ struct udc_ep *ep;\n" - "+ struct udc *dev;\n" - "+ u32 tmp;\n" - "+ unsigned long iflags;\n" - "+ u8 udc_csr_epix;\n" - "+\n" - "+ VDBG(\"udc_enable()\\n\"); \n" - "+ \n" - "+ ep = container_of (usbep, struct udc_ep, ep);\n" - "+ if (!usbep \n" - "+ || usbep->name == ep0_string\n" - "+ || !desc \n" - "+ || desc->bDescriptorType != USB_DT_ENDPOINT) {\n" - "+ ERR(\"udc_enable: !usbep=%d !desc=%d ep->desc!=NULL=%d usbep->name==ep0_string=%d desc->bDescriptorType!=USB_DT_ENDPOINT=%d\\n\",\n" - "+ !usbep, !desc, ep->desc != NULL, usbep->name == ep0_string, desc->bDescriptorType != USB_DT_ENDPOINT);\n" - "+ return -EINVAL;\n" - "+ }\n" - "+ \n" - "+ DBG(\"udc_enable() ep %d\\n\", ep->num);\n" - "+\n" - "+ dev = ep->dev;\n" - "+\n" - "+ /* exit on suspend */\n" - "+ if (dev->sys_suspended) \n" - "+ return -ESHUTDOWN;\n" - "+\n" - "+ if (!dev->driver\n" - "+ || dev->gadget.speed == USB_SPEED_UNKNOWN)\n" - "+ return -ESHUTDOWN;\n" - "+\n" - "+ spin_lock_irqsave (&dev->lock, iflags);\n" - "+ ep->desc = desc;\n" - "+\n" - "+ ep->halted = 0;\n" - "+\n" - "+ /* set traffic type */\n" - "+ tmp = readl(&dev->ep[ep->num].regs->ctl);\n" - "+ tmp = AMD_ADDBITS(tmp, desc->bmAttributes, UDC_EPCTL_ET);\n" - "+ writel(tmp, &dev->ep[ep->num].regs->ctl);\n" - "+\n" - "+ /* set max packet size */\n" - "+ tmp = readl(&dev->ep[ep->num].regs->bufout_maxpkt);\n" - "+ tmp = AMD_ADDBITS(tmp, desc->wMaxPacketSize, UDC_EP_MAX_PKT_SIZE);\n" - "+ ep->ep.maxpacket = desc->wMaxPacketSize;\n" - "+ writel(tmp, &dev->ep[ep->num].regs->bufout_maxpkt);\n" - "+\n" - "+ /* IN ep */\n" - "+ if (ep->in) {\n" - "+ \n" - "+ /* ep ix in UDC CSR register space */\n" - "+ udc_csr_epix = ep->num;\n" - "+ \n" - "+ /* set buffer size (tx fifo entries) */\n" - "+ tmp = readl(&dev->ep[ep->num].regs->bufin_framenum);\n" - "+ /* double buffering: fifo size = 2 x max packet size */\n" - "+ tmp = AMD_ADDBITS(\n" - "+ tmp,\n" - "+ desc->wMaxPacketSize * UDC_EPIN_BUFF_SIZE_MULT /\n" - "+ UDC_DWORD_BYTES,\n" - "+ UDC_EPIN_BUFF_SIZE); \n" - "+ writel(tmp, &dev->ep[ep->num].regs->bufin_framenum);\n" - "+\n" - "+ /* calc. tx fifo base addr */\n" - "+ udc_set_txfifo_addr(ep); \n" - "+\n" - "+ /* flush fifo */\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_F); \n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+ \n" - "+ } /* OUT ep */\n" - "+ else {\n" - "+ /* ep ix in UDC CSR register space */\n" - "+ udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS;\n" - "+\n" - "+ /* set max packet size UDC CSR */\n" - "+ tmp = readl(&dev->csr->ne[ep->num - UDC_CSR_EP_OUT_IX_OFS]);\n" - "+ tmp = AMD_ADDBITS(tmp, desc->wMaxPacketSize, UDC_CSR_NE_MAX_PKT);\n" - "+ writel(tmp, &dev->csr->ne[ep->num - UDC_CSR_EP_OUT_IX_OFS]);\n" - "+\n" - "+ if (ep->num != UDC_EP0OUT_IX) \n" - "+ dev->data_ep_enabled = 1;\n" - "+ }\n" - "+\n" - "+ /***** UDC CSR reg ****************************/\n" - "+ /* set ep values */\n" - "+ tmp = readl(&dev->csr->ne[udc_csr_epix]);\n" - "+ /* max packet */\n" - "+ tmp = AMD_ADDBITS(tmp, desc->wMaxPacketSize, UDC_CSR_NE_MAX_PKT);\n" - "+ /* ep number */\n" - "+ tmp = AMD_ADDBITS(tmp, desc->bEndpointAddress, UDC_CSR_NE_NUM);\n" - "+ /* ep direction */\n" - "+ tmp = AMD_ADDBITS(tmp, ep->in, UDC_CSR_NE_DIR);\n" - "+ /* ep type */\n" - "+ tmp = AMD_ADDBITS(tmp, desc->bmAttributes, UDC_CSR_NE_TYPE);\n" - "+ /* ep config */\n" - "+ tmp = AMD_ADDBITS(tmp, ep->dev->cur_config, UDC_CSR_NE_CFG);\n" - "+ /* ep interface */\n" - "+ tmp = AMD_ADDBITS(tmp, ep->dev->cur_intf, UDC_CSR_NE_INTF);\n" - "+ /* ep alt */\n" - "+ tmp = AMD_ADDBITS(tmp, ep->dev->cur_alt, UDC_CSR_NE_ALT);\n" - "+ /* write reg */\n" - "+ writel(tmp, &dev->csr->ne[udc_csr_epix]);\n" - "+ \n" - "+ /* enable ep irq */\n" - "+ tmp = readl(&dev->regs->ep_irqmsk);\n" - "+ tmp &= AMD_UNMASK_BIT(ep->num);\n" - "+ writel(tmp, &dev->regs->ep_irqmsk); \n" - "+\n" - "+ /* clear NAK by writing CNAK */\n" - "+ /* avoid BNA for DMA, dont clear NAK until DMA desc. written */\n" - "+ if (!use_dma) {\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); \n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+ ep->naking = 0;\n" - "+ UDC_QUEUE_CNAK(ep, ep->num);\n" - "+ }\n" - "+ tmp = desc->bEndpointAddress;\n" - "+ DBG( \"%s enabled\\n\",\n" - "+ usbep->name);\n" - "+\n" - "+ spin_unlock_irqrestore (&dev->lock, iflags);\n" - "+ return 0;\n" - "+}\n" - "+/**\n" - "+ * Resets endpoint\n" - "+ * \n" - "+ * \\param regs pointer to device register struct\n" - "+ * \\param ep pointer to endpoint\n" - "+ */\n" - "+static void ep_init (struct udc_regs *regs, struct udc_ep *ep)\n" - "+{\n" - "+ u32 tmp;\n" - "+\n" - "+ VDBG(\"ep-%d reset\\n\", ep->num);\n" - "+ ep->desc = 0;\n" - "+ ep->ep.ops = &udc_ep_ops;\n" - "+ INIT_LIST_HEAD (&ep->queue);\n" - "+\n" - "+ ep->ep.maxpacket = (u16) ~0;\n" - "+ if (!(ep->dev->sys_suspended)) {\n" - "+ /* set NAK */\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_SNAK); \n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+ ep->naking = 1;\n" - "+ \n" - "+ /* disable interrupt */\n" - "+ tmp = readl(®s->ep_irqmsk);\n" - "+ tmp |= AMD_BIT(ep->num);\n" - "+ writel(tmp, ®s->ep_irqmsk); \n" - "+\n" - "+ if (ep->in) {\n" - "+ /* unset P and IN bit of potential former DMA */\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ tmp &= AMD_UNMASK_BIT(UDC_EPCTL_P);\n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+\n" - "+ tmp = readl(&ep->regs->sts);\n" - "+ tmp |= AMD_BIT(UDC_EPSTS_IN);\n" - "+ writel(tmp, &ep->regs->sts);\n" - "+\n" - "+ /* flush the fifo */\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_F); \n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+\n" - "+ }\n" - "+ /* reset desc pointer */\n" - "+ writel(0, &ep->regs->desptr);\n" - "+ }\n" - "+\n" - "+\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Disables endpoint, is called by gadget driver\n" - "+ * \n" - "+ * \\param usbep pointer to ep struct\n" - "+ * \\return 0 if success \n" - "+ */\n" - "+static int udc_disable (struct usb_ep *usbep)\n" - "+{\n" - "+ struct udc_ep *ep = NULL;\n" - "+ unsigned long iflags;\n" - "+\n" - "+ if (!usbep)\n" - "+ return -EINVAL;\n" - "+ \n" - "+ ep = container_of (usbep, struct udc_ep, ep);\n" - "+ if (usbep->name == ep0_string\n" - "+ || !ep->desc)\n" - "+ return -EINVAL;\n" - "+\n" - "+ DBG(\"Disable ep-%d\\n\", ep->num);\n" - "+\n" - "+ spin_lock_irqsave(&ep->dev->lock, iflags);\n" - "+ empty_req_queue(ep);\n" - "+ ep_init(ep->dev->regs, ep);\n" - "+ spin_unlock_irqrestore(&ep->dev->lock, iflags);\n" - "+\n" - "+ return 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Allocates request packet, called by gadget driver\n" - "+ * \n" - "+ * \\param _ep pointer to usb ep struct\n" - "+ * \\param gfp_flags flags for kmalloc\n" - "+ * \\return allocated request packet, 0 if error\n" - "+ */\n" - "+static struct usb_request *\n" - "+udc_alloc_request (struct usb_ep *usbep, gfp_t gfp)\n" - "+{\n" - "+ struct udc_request *req;\n" - "+ struct udc_data_dma *dma_desc;\n" - "+ struct udc_ep *ep;\n" - "+\n" - "+ VDBG(\"udc_alloc_req()\\n\");\n" - "+ if (!usbep)\n" - "+ return 0;\n" - "+\n" - "+ ep = container_of (usbep, struct udc_ep, ep);\n" - "+ udc_gfp_flags = gfp;\n" - "+\n" - "+ VDBG(\"udc_alloc_req(): ep%d\\n\", ep->num);\n" - "+ req = kmalloc (sizeof (struct udc_request), gfp);\n" - "+ if (!req)\n" - "+ return 0;\n" - "+\n" - "+ memset (req, 0, sizeof *req);\n" - "+ req->req.dma = DMA_DONT_USE;\n" - "+ INIT_LIST_HEAD (&req->queue);\n" - "+\n" - "+ if (ep->dma) {\n" - "+\n" - "+#if defined(CONFIG_SOC_AU1200)\n" - "+ gfp = GFP_ATOMIC | GFP_DMA;\n" - "+#endif\n" - "+ /* ep0 in requests are allocated from data pool here */\n" - "+ dma_desc = dma_pool_alloc (ep->dev->data_requests, gfp,\n" - "+ &req->td_phys);\n" - "+ if (!dma_desc) {\n" - "+ kfree (req);\n" - "+ return 0;\n" - "+ }\n" - "+\n" - "+ VDBG(\"udc_alloc_req: req = %lx dma_desc = %lx, req->td_phys = %lx\\n\",\n" - "+ (unsigned long) req, (unsigned long) dma_desc, (unsigned long)req->td_phys);\n" - "+ /* prevent from using desc. - set HOST BUSY */\n" - "+ dma_desc->status = AMD_ADDBITS(dma_desc->status,\n" - "+ UDC_DMA_STP_STS_BS_HOST_BUSY,\n" - "+ UDC_DMA_STP_STS_BS); \n" - "+ dma_desc->bufptr = __constant_cpu_to_le32 (DMA_DONT_USE);\n" - "+ req->td_data = dma_desc;\n" - "+ req->td_data_last = NULL;\n" - "+ req->chain_len = 1;\n" - "+ }\n" - "+\n" - "+ return &req->req;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Frees request packet, called by gadget driver\n" - "+ * \n" - "+ * \\param usbep pointer to usb ep struct\n" - "+ * \\param usbreq pointer to request packet to be freed\n" - "+ */\n" - "+static void\n" - "+udc_free_request (struct usb_ep *usbep, struct usb_request *usbreq)\n" - "+{\n" - "+ struct udc_ep *ep;\n" - "+ struct udc_request *req;\n" - "+\n" - "+ if (!usbep || !usbreq)\n" - "+ return;\n" - "+\n" - "+ ep = container_of (usbep, struct udc_ep, ep);\n" - "+ req = container_of (usbreq, struct udc_request, req);\n" - "+ VDBG(\"free_req req=%lx\\n\", (unsigned long) req);\n" - "+ WARN_ON(!list_empty (&req->queue));\n" - "+ if (req->td_data) {\n" - "+ VDBG(\"req->td_data=%lx\\n\", (unsigned long) req->td_data);\n" - "+\n" - "+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND\n" - "+ /* re-link broken chain */\n" - "+ if (req->td_data_last) {\n" - "+ req->td_data_last->next = req->td_data_last_next;\n" - "+ }\n" - "+#endif\n" - "+ /* free dma chain if created */\n" - "+ if (req->chain_len > 1) {\n" - "+ udc_free_dma_chain(ep->dev, req);\n" - "+ }\n" - "+\n" - "+ dma_pool_free (ep->dev->data_requests, req->td_data, req->td_phys);\n" - "+ }\n" - "+ kfree (req);\n" - "+}\n" - "+\n" - "+/* choose dma buffer allocation method */\n" - "+#undef USE_KMALLOC\n" - "+#if defined(CONFIG_X86)\n" - "+#define USE_KMALLOC\n" - "+#elif defined(CONFIG_SOC_AU1200)\n" - "+#ifdef CONFIG_DMA_COHERENT\n" - "+#define USE_KMALLOC\n" - "+#endif /* CONFIG_DMA_COHERENT */\n" - "+#endif\n" - "+\n" - "+/**\n" - "+ * Allocates data buffer for request packet, called by gadget driver\n" - "+ * \n" - "+ * \\param usbep pointer to usb ep struct\n" - "+ * \\param bytes number bytes to allocate\n" - "+ * \\param dma pointer to dma struct\n" - "+ * \\param gfp_flags flags for allocate \n" - "+ * \\return pointer to allocated buffer, 0 if error\n" - "+ */\n" - "+static void *\n" - "+udc_alloc_buffer (\n" - "+ struct usb_ep *usbep,\n" - "+ unsigned len,\n" - "+ dma_addr_t *dma,\n" - "+ gfp_t gfp\n" - "+)\n" - "+{\n" - "+ void *ptr;\n" - "+ struct udc_ep *ep;\n" - "+ VDBG(\"alloc_buffer(): %s\\n\", usbep->name);\n" - "+\n" - "+ ep = container_of (usbep, struct udc_ep, ep);\n" - "+ *dma = DMA_DONT_USE;\n" - "+\n" - "+ if (!usbep)\n" - "+ return 0;\n" - "+\n" - "+ if (ep->dma) {\n" - "+#if defined(USE_KMALLOC)\n" - "+\n" - "+#if defined(CONFIG_SOC_AU1200)\n" - "+ gfp = GFP_ATOMIC | GFP_DMA;\n" - "+#endif\n" - "+ ptr = kmalloc(len, gfp);\n" - "+\n" - "+ if (ptr)\n" - "+ *dma = virt_to_phys(ptr);\n" - "+\n" - "+#else\n" - "+ ptr = dma_alloc_coherent (&ep->dev->pdev->dev, len, dma, gfp);\n" - "+#endif\n" - "+ } else\n" - "+ ptr = kmalloc(len, gfp);\n" - "+\n" - "+ VDBG(\"alloc_buffer() ptr = %lx dma=%lx\\n\", (unsigned long) ptr, (unsigned long) *dma);\n" - "+ return ptr;\n" - "+}\n" - "+\n" - "+\n" - "+/**\n" - "+ * Free data buffer for request packet, called by gadget driver\n" - "+ * \n" - "+ * \\param usbep pointer to usb ep struct\n" - "+ * \\param buf pointer to buffer to be freed\n" - "+ * \\param dma pointer to dma struct\n" - "+ * \\param len number bytes to be freed \n" - "+ * \\return pointer to allocated buffer, 0 if error\n" - "+ */\n" - "+static void\n" - "+udc_free_buffer (\n" - "+ struct usb_ep *usbep,\n" - "+ void *buf,\n" - "+ dma_addr_t dma,\n" - "+ unsigned len\n" - "+) {\n" - "+ struct udc_ep *ep;\n" - "+\n" - "+ VDBG (\"ep %s - free buffer %lx\\n\", usbep->name, (unsigned long) buf);\n" - "+\n" - "+ /* null pointer ? */\n" - "+ if (!buf) {\n" - "+ return;\n" - "+ }\n" - "+\n" - "+ ep = container_of(usbep, struct udc_ep, ep);\n" - "+ if (!ep)\n" - "+ return;\n" - "+\n" - "+#ifndef USE_KMALLOC\n" - "+ if (dma != DMA_DONT_USE) {\n" - "+ dma_free_coherent (&ep->dev->pdev->dev, len, buf, dma);\n" - "+ } else\n" - "+#endif\n" - "+ {\n" - "+ if (!(ep->dma))\n" - "+ kfree (buf);\n" - "+ }\n" - "+\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Write data to TX fifo for IN packets \n" - "+ * \n" - "+ * \\param ep pointer to ep struct\n" - "+ * \\param req pointer to request packet\n" - "+ * \\return allocated request packet, 0 if error\n" - "+ */\n" - "+static void\n" - "+udc_txfifo_write (struct udc_ep *ep, struct usb_request *req)\n" - "+{\n" - "+ u8 *req_buf;\n" - "+ u32 *buf;\n" - "+ int i,j;\n" - "+ unsigned bytes = 0;\n" - "+ unsigned remaining = 0;\n" - "+\n" - "+ VDBG(\"udc_txfifo_write()\\n\");\n" - "+\n" - "+ if (!req || !ep)\n" - "+ return;\n" - "+\n" - "+ req_buf = req->buf + req->actual;\n" - "+ prefetch (req_buf);\n" - "+ remaining = req->length - req->actual;\n" - "+ \n" - "+ buf = (u32*) req_buf; \n" - "+ \n" - "+ bytes = ep->ep.maxpacket;\n" - "+ if (bytes > remaining)\n" - "+ bytes = remaining;\n" - "+\t\n" - "+ /* dwords first */\n" - "+ for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) {\n" - "+ writel(*(buf + i), ep->txfifo);\n" - "+ }\n" - "+\n" - "+ /* remaining bytes must be written by byte access */\n" - "+ for (j = 0; j < bytes % UDC_DWORD_BYTES; j++) {\n" - "+ writeb((u8) (*(buf + i) >> (j << UDC_BITS_PER_BYTE_SHIFT)),\n" - "+ ep->txfifo);\n" - "+ }\n" - "+\n" - "+#ifdef UDC_IPBUG_2253_WORKAROUND\n" - "+ {\n" - "+ u32 tmp;\n" - "+\n" - "+ /* NAK if small packet until write confirm completed */\n" - "+ if (bytes < UDC_SMALL_PACKET) {\n" - "+ /* set NAK */\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_SNAK); \n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+ ep->naking = 1;\n" - "+ wb_flush();\n" - "+ }\n" - "+\n" - "+ /* dummy write confirm */\n" - "+ writel(0, &ep->regs->confirm); \n" - "+\n" - "+ /* stop NAKing after small packet DMA */\n" - "+ if (ep->naking) {\n" - "+ /* clear NAK by writing CNAK */\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); \n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+ ep->naking = 0;\n" - "+ UDC_QUEUE_CNAK(ep, ep->num);\n" - "+ }\n" - "+ }\n" - "+#else\n" - "+ /* dummy write confirm */\n" - "+ writel(0, &ep->regs->confirm); \n" - "+#endif\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Read dwords from RX fifo for OUT transfers\n" - "+ * \n" - "+ * \\param dev pointer to device struct\n" - "+ * \\param buf pointer to buffer to be filled\n" - "+ * \\param dwords number of dwords to be read\n" - "+ * \\return allocated request packet, 0 if error\n" - "+ */\n" - "+static int udc_rxfifo_read_dwords(struct udc* dev, u32* buf, int dwords)\n" - "+{\n" - "+ int i;\n" - "+ \n" - "+ VDBG(\"udc_read_dwords(): %d dwords\\n\", dwords);\n" - "+\n" - "+ for (i = 0; i < dwords; i++)\n" - "+ {\n" - "+ *(buf + i) = readl(dev->rxfifo);\n" - "+ } \n" - "+ return 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Read bytes from RX fifo for OUT transfers\n" - "+ * \n" - "+ * \\param dev pointer to device struct\n" - "+ * \\param buf pointer to buffer to be filled\n" - "+ * \\param bytes number of bytes to be read\n" - "+ * \\return allocated request packet, 0 if error\n" - "+ */\n" - "+static int udc_rxfifo_read_bytes(struct udc* dev, u8* buf, int bytes)\n" - "+{\n" - "+ int i,j;\n" - "+ u32 tmp;\n" - "+ \n" - "+ VDBG(\"udc_read_bytes(): %d bytes\\n\", bytes);\n" - "+\n" - "+ /* dwords first */\n" - "+ for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) {\n" - "+ *((u32*) (buf + (i<<2))) = readl(dev->rxfifo); \n" - "+ }\n" - "+\n" - "+ /* remaining bytes must be read by byte access */\n" - "+ if (bytes % UDC_DWORD_BYTES) {\n" - "+ tmp = readl(dev->rxfifo);\n" - "+ for (j = 0; j < bytes % UDC_DWORD_BYTES; j++) {\n" - "+ *(buf + (i<<2) + j) = (u8) (tmp & UDC_BYTE_MASK);\n" - "+ tmp = tmp >> UDC_BITS_PER_BYTE;\n" - "+ }\n" - "+ }\n" - "+ \n" - "+ return 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Read data from RX fifo for OUT transfers\n" - "+ * \n" - "+ * \\param ep pointer to ep struct\n" - "+ * \\param req pointer to request packet\n" - "+ * \\return true if request completes for short or max packet, false otherwise \n" - "+ */\n" - "+static int\n" - "+udc_rxfifo_read(struct udc_ep *ep, struct udc_request *req)\n" - "+{\n" - "+ u8 *buf;\n" - "+ unsigned buf_space;\n" - "+ unsigned bytes = 0; \n" - "+ unsigned finished = 0;\n" - "+\n" - "+ /* received number bytes */\n" - "+ bytes = readl(&ep->regs->sts);\n" - "+ bytes = AMD_GETBITS(bytes, UDC_EPSTS_RX_PKT_SIZE);\n" - "+ \n" - "+ buf_space = req->req.length - req->req.actual;\n" - "+ buf = req->req.buf + req->req.actual;\n" - "+ if (bytes > buf_space) {\n" - "+ if ((buf_space % ep->ep.maxpacket) != 0) {\n" - "+ ERR( \"%s: received %d bytes, rx-buffer space = %d bytes => buffer overrun\\n\",\n" - "+ ep->ep.name, bytes, buf_space);\n" - "+ req->req.status = -EOVERFLOW;\n" - "+ }\n" - "+ bytes = buf_space;\n" - "+ }\n" - "+ req->req.actual += bytes;\n" - "+\n" - "+ /* last packet ? */\n" - "+ if (((bytes % ep->ep.maxpacket) != 0)\n" - "+ || (!bytes)\n" - "+ || ((req->req.actual == req->req.length) && !req->req.zero))\n" - "+ finished = 1;\n" - "+\n" - "+ /* read rx fifo bytes */\n" - "+ VDBG(\"ep %s: rxfifo read %d bytes\\n\", ep->ep.name, bytes);\n" - "+ udc_rxfifo_read_bytes(ep->dev, buf, bytes); \n" - "+ \n" - "+ return finished;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * create/re-init a DMA descriptor or a DMA descriptor chain\n" - "+ *\n" - "+ * \\param ep pointer to endpoint struct \n" - "+ * \\param req pointer to request packet\n" - "+ */\n" - "+static int prep_dma (struct udc_ep *ep, struct udc_request *req)\n" - "+{\n" - "+ int retval = 0;\n" - "+ u32 tmp;\n" - "+ VDBG(\"prep_dma\\n\");\n" - "+ VDBG(\"prep_dma ep%d req->td_data=%lx\\n\",\n" - "+ ep->num, (unsigned long) req->td_data);\n" - "+\n" - "+ /* set buffer pointer */\n" - "+ req->td_data->bufptr = req->req.dma;\n" - "+\n" - "+ /* set last bit */\n" - "+ req->td_data->status |= AMD_BIT(UDC_DMA_IN_STS_L);\n" - "+ \n" - "+ /* build/re-init dma chain if maxpkt scatter mode, not for EP0 */\n" - "+ if (use_dma_ppb && ep->num != UDC_EP0OUT_IX && ep->num != UDC_EP0IN_IX) {\n" - "+\n" - "+ retval = udc_create_dma_chain(ep, req, ep->ep.maxpacket, udc_gfp_flags);\n" - "+ if (retval != 0)\n" - "+ {\n" - "+ if (retval == -ENOMEM)\n" - "+ INFO(\"Out of DMA memory (allocation failed)\\n\"); \n" - "+ return retval;\n" - "+ }\n" - "+ if (ep->in) {\n" - "+ if (req->req.length == ep->ep.maxpacket) {\n" - "+ /* write tx bytes */\n" - "+ req->td_data->status = AMD_ADDBITS(req->td_data->status,\n" - "+ ep->ep.maxpacket,\n" - "+ UDC_DMA_IN_STS_TXBYTES); \n" - "+\n" - "+ }\n" - "+ }\n" - "+ \n" - "+ }\n" - "+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND\n" - "+ else { /* EP0 */\n" - "+ /* point to itself */\n" - "+ req->td_data->next = req->td_phys;\n" - "+ }\n" - "+#endif\n" - "+ \n" - "+ if (ep->in) {\n" - "+ VDBG(\"IN: use_dma_ppb=%d req->req.length=%d ep->ep.maxpacket=%d ep%d\\n\",\n" - "+ use_dma_ppb, req->req.length, ep->ep.maxpacket, ep->num);\n" - "+ /* if bytes < max packet then tx bytes must */\n" - "+ /* be written in packet per buffer mode */\n" - "+ if (!use_dma_ppb || req->req.length < ep->ep.maxpacket\n" - "+ || ep->num == UDC_EP0OUT_IX || ep->num == UDC_EP0IN_IX) {\n" - "+ /* write tx bytes */\n" - "+ req->td_data->status = AMD_ADDBITS(req->td_data->status,\n" - "+ req->req.length,\n" - "+ UDC_DMA_IN_STS_TXBYTES); \n" - "+ /* reset frame num */\n" - "+ req->td_data->status = AMD_ADDBITS(req->td_data->status,\n" - "+ 0,\n" - "+ UDC_DMA_IN_STS_FRAMENUM); \n" - "+ }\n" - "+ /* set HOST BUSY */\n" - "+ req->td_data->status \n" - "+ = AMD_ADDBITS(req->td_data->status,\n" - "+ UDC_DMA_STP_STS_BS_HOST_BUSY,\n" - "+ UDC_DMA_STP_STS_BS);\n" - "+ }\n" - "+ else {\n" - "+ VDBG(\"OUT set host ready\\n\");\n" - "+ /* set HOST READY */\n" - "+ req->td_data->status \n" - "+ = AMD_ADDBITS(req->td_data->status,\n" - "+ UDC_DMA_STP_STS_BS_HOST_READY,\n" - "+ UDC_DMA_STP_STS_BS);\n" - "+\n" - "+ \n" - "+ /* clear NAK by writing CNAK */\n" - "+ if (ep->naking) {\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); \n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+ ep->naking = 0;\n" - "+ UDC_QUEUE_CNAK(ep, ep->num);\n" - "+ }\n" - "+\n" - "+ }\n" - "+\n" - "+ return retval;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Completes request packet \n" - "+ * \n" - "+ * \\param ep pointer to ep struct\n" - "+ * \\param req pointer to request packet\n" - "+ * \\param sts status of request\n" - "+ */\n" - "+static void\n" - "+complete_req(struct udc_ep *ep, struct udc_request *req, int sts)\n" - "+{\n" - "+ struct udc *dev;\n" - "+ unsigned halted;\n" - "+\n" - "+ VDBG(\"complete_req(): ep%d\\n\", ep->num);\n" - "+\n" - "+ dev = ep->dev;\n" - "+ /* unmap DMA */\n" - "+ if (req->dma_mapping) {\n" - "+#if defined(CONFIG_SOC_AU1200)\n" - "+ if (ep->in)\n" - "+ dma_unmap_single(0,\n" - "+ req->req.dma,\n" - "+ req->req.length,\n" - "+ PCI_DMA_TODEVICE);\n" - "+ else\n" - "+ dma_unmap_single(0,\n" - "+ req->req.dma,\n" - "+ req->req.length,\n" - "+ PCI_DMA_FROMDEVICE);\n" - "+#else\n" - "+ if (ep->in)\n" - "+ pci_unmap_single(dev->pdev,\n" - "+ req->req.dma,\n" - "+ req->req.length,\n" - "+ PCI_DMA_TODEVICE);\n" - "+ else\n" - "+ pci_unmap_single(dev->pdev,\n" - "+ req->req.dma,\n" - "+ req->req.length,\n" - "+ PCI_DMA_FROMDEVICE);\n" - "+#endif\n" - "+ req->dma_mapping = 0;\n" - "+ req->req.dma = DMA_DONT_USE;\n" - "+ }\n" - "+\n" - "+ halted = ep->halted;\n" - "+ ep->halted = 1;\n" - "+\n" - "+ /* set new status if pending */\n" - "+ if (req->req.status == -EINPROGRESS)\n" - "+ req->req.status = sts;\n" - "+\n" - "+ /* remove from ep queue */\n" - "+ list_del_init (&req->queue);\n" - "+\n" - "+ VDBG( \"req %p => complete %d bytes at %s with sts %d\\n\",\n" - "+ &req->req, req->req.length, ep->ep.name, sts);\n" - "+ if (spin_is_locked(&dev->lock)) {\n" - "+ spin_unlock (&dev->lock);\n" - "+ req->req.complete (&ep->ep, &req->req);\n" - "+ spin_lock (&dev->lock);\n" - "+ }\n" - "+ else {\n" - "+ req->req.complete (&ep->ep, &req->req);\n" - "+ }\n" - "+ ep->halted = halted;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * frees pci pool descriptors of a DMA chain \n" - "+ * \n" - "+ * \\param dev pointer to device struct\n" - "+ * \\param req pointer to request packet\n" - "+ * \\return 0 if success\n" - "+ */\n" - "+static int udc_free_dma_chain(struct udc* dev, struct udc_request* req)\n" - "+{\n" - "+\n" - "+ int ret_val = 0;\n" - "+ struct udc_data_dma *td;\n" - "+ struct udc_data_dma *td_last = NULL;\n" - "+ unsigned int i;\n" - "+\n" - "+ DBG(\"free chain req = %lx\\n\", (unsigned long) req);\n" - "+\n" - "+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND\n" - "+ /* re-link broken chain */\n" - "+ if (req->td_data_last) {\n" - "+ req->td_data_last->next = req->td_data_last_next;\n" - "+ }\n" - "+#endif\n" - "+ /* do not free first desc., will be done by free for request */\n" - "+ td_last = req->td_data;\n" - "+#if defined (CONFIG_SOC_AU1200) && !defined(CONFIG_DMA_COHERENT)\n" - "+ td = UNCAC_ADDR(phys_to_virt(td_last->next));\n" - "+#else\n" - "+ td = phys_to_virt(td_last->next);\n" - "+#endif\n" - "+\n" - "+ for (i = 1; i < req->chain_len; i++) {\n" - "+\n" - "+ dma_pool_free (dev->data_requests, td,\n" - "+ (dma_addr_t) td_last->next);\n" - "+ td_last = td;\n" - "+#if defined (CONFIG_SOC_AU1200) && !defined(CONFIG_DMA_COHERENT)\n" - "+ td = UNCAC_ADDR(phys_to_virt(td_last->next));\n" - "+#else\n" - "+ td = phys_to_virt(td_last->next);\n" - "+#endif\n" - "+ }\n" - "+\n" - "+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND\n" - "+ req->td_data_last = NULL;\n" - "+#endif\n" - "+ return ret_val; \n" - "+}\n" - "+\n" - "+/**\n" - "+ * Iterates to the end of a DMA chain and returns last descriptor \n" - "+ * \n" - "+ * \\param req pointer to request packet\n" - "+ * \\return pointer to last descriptori of chain\n" - "+ */\n" - "+static struct udc_data_dma* udc_get_last_dma_desc(struct udc_request* req)\n" - "+{\n" - "+ struct udc_data_dma *td;\n" - "+\n" - "+ td = req->td_data;\n" - "+ while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L))) {\n" - "+#if defined (CONFIG_SOC_AU1200) && !defined(CONFIG_DMA_COHERENT)\n" - "+ td = UNCAC_ADDR(phys_to_virt(td->next));\n" - "+#else\n" - "+ td = phys_to_virt(td->next);\n" - "+#endif\n" - "+ }\n" - "+\n" - "+ return td;\n" - "+\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Iterates to the end of a DMA chain and counts bytes received \n" - "+ * \n" - "+ * \\param req pointer to request packet\n" - "+ * \\return number of received bytes\n" - "+ */\n" - "+static u32 udc_get_ppbdu_rxbytes(struct udc_request* req)\n" - "+{\n" - "+ struct udc_data_dma *td;\n" - "+ u32 count;\n" - "+\n" - "+ td = req->td_data;\n" - "+ /* received number bytes */\n" - "+ count = AMD_GETBITS(td->status, UDC_DMA_OUT_STS_RXBYTES); \n" - "+ \n" - "+ while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L))) {\n" - "+#if defined (CONFIG_SOC_AU1200) && !defined(CONFIG_DMA_COHERENT)\n" - "+ td = UNCAC_ADDR(phys_to_virt(td->next));\n" - "+#else\n" - "+ td = phys_to_virt(td->next);\n" - "+#endif\n" - "+ /* received number bytes */\n" - "+ if (td) {\n" - "+ count += AMD_GETBITS(td->status, UDC_DMA_OUT_STS_RXBYTES);\n" - "+ }\n" - "+ }\n" - "+\n" - "+ return count;\n" - "+\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Creates or re-inits a DMA chain \n" - "+ *\n" - "+ * \\param ep pointer to endpoint struct \n" - "+ * \\param req pointer to request packet\n" - "+ * \\param buf_len number of buffer bytes per descriptor (except last short)\n" - "+ */\n" - "+static int udc_create_dma_chain(struct udc_ep* ep, struct udc_request* req, unsigned long buf_len, int gfp_flags)\n" - "+{\n" - "+ unsigned long bytes = req->req.length;\n" - "+ unsigned int i;\n" - "+ dma_addr_t dma_addr;\n" - "+ struct udc_data_dma *td = NULL;\n" - "+ struct udc_data_dma *last = NULL;\n" - "+ unsigned long txbytes;\n" - "+ unsigned create_new_chain = 0;\n" - "+ unsigned len;\n" - "+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND\n" - "+ dma_addr_t last_next = DMA_DONT_USE;\n" - "+#endif\n" - "+\n" - "+ VDBG(\"udc_create_dma_chain: bytes=%ld buf_len=%ld\\n\", bytes, buf_len);\n" - "+ dma_addr = DMA_DONT_USE;\n" - "+\n" - "+ /* unset L bit in first desc for OUT */\n" - "+ if (!ep->in) {\n" - "+ req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L);\n" - "+ }\n" - "+ \n" - "+ /* alloc only new desc's if not already available */\n" - "+ len = req->req.length / ep->ep.maxpacket;\n" - "+ if (req->req.length % ep->ep.maxpacket) {\n" - "+ len++;\n" - "+ }\n" - "+\n" - "+ if (len > req->chain_len) {\n" - "+ /* shorter chain already allocated before */\n" - "+ if (req->chain_len > 1) {\n" - "+ udc_free_dma_chain(ep->dev, req);\n" - "+ }\n" - "+ req->chain_len = len;\n" - "+ create_new_chain = 1;\n" - "+ }\n" - "+\n" - "+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND\n" - "+ /* re-link broken chain */\n" - "+ if (req->td_data_last) {\n" - "+ req->td_data_last->next = req->td_data_last_next;\n" - "+ }\n" - "+ /* if only one td then last_next is root td */\n" - "+ last_next = req->td_phys;\n" - "+#endif\n" - "+\n" - "+ td = req->td_data; \n" - "+ /* gen. required number of descriptors and buffers */\n" - "+ for (i = buf_len; i < bytes; i += buf_len)\n" - "+ {\n" - "+ /* create or determine next desc. */\n" - "+ if (create_new_chain) {\n" - "+\n" - "+#if defined(CONFIG_SOC_AU1200)\n" - "+ gfp_flags = GFP_ATOMIC | GFP_DMA;\n" - "+#endif\n" - "+ td = dma_pool_alloc (ep->dev->data_requests, gfp_flags,\n" - "+ &dma_addr);\n" - "+ if (!td) \n" - "+ return -ENOMEM;\n" - "+\n" - "+ td->status = 0;\n" - "+ }\n" - "+ else if (i == buf_len)\n" - "+ {\n" - "+ /* first td */\n" - "+#if defined (CONFIG_SOC_AU1200) && !defined(CONFIG_DMA_COHERENT)\n" - "+ td = (struct udc_data_dma*) UNCAC_ADDR(phys_to_virt(req->td_data->next));\n" - "+#else\n" - "+ td = (struct udc_data_dma*) phys_to_virt(req->td_data->next);\n" - "+#endif\n" - "+ td->status = 0;\n" - "+ }\n" - "+ else {\n" - "+#if defined (CONFIG_SOC_AU1200) && !defined(CONFIG_DMA_COHERENT)\n" - "+ td = (struct udc_data_dma*) UNCAC_ADDR(phys_to_virt(last->next));\n" - "+#else\n" - "+ td = (struct udc_data_dma*) phys_to_virt(last->next);\n" - "+#endif\n" - "+ td->status = 0;\n" - "+ }\n" - "+ \n" - "+\n" - "+ if (td) {\n" - "+ /* assign buffer */\n" - "+ td->bufptr = req->req.dma + i; \n" - "+ }\n" - "+ else {\n" - "+ break;\n" - "+ }\n" - "+\n" - "+ /* short packet ? */\n" - "+ if ((bytes - i) >= buf_len) {\n" - "+ txbytes = buf_len;\n" - "+ }\n" - "+ else {\n" - "+ /* short packet */\n" - "+ txbytes = bytes - i;\n" - "+ }\n" - "+ \n" - "+ /* link td and assign tx bytes */\n" - "+ if (i == buf_len) {\n" - "+ if (create_new_chain) {\n" - "+ req->td_data->next = dma_addr;\n" - "+ }\n" - "+ else {\n" - "+ /* req->td_data->next = virt_to_phys(td); */\n" - "+ }\n" - "+ /* write tx bytes */\n" - "+ if (ep->in) {\n" - "+ /* first desc */\n" - "+ req->td_data->status = AMD_ADDBITS(req->td_data->status,\n" - "+ ep->ep.maxpacket,\n" - "+ UDC_DMA_IN_STS_TXBYTES);\n" - "+ /* second desc */\n" - "+ td->status = AMD_ADDBITS(td->status,\n" - "+ txbytes,\n" - "+ UDC_DMA_IN_STS_TXBYTES); \n" - "+ } \n" - "+\n" - "+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND\n" - "+ last_next = req->td_data->next;\n" - "+#endif\n" - "+ }\n" - "+ else {\n" - "+ if (create_new_chain) {\n" - "+ last->next = dma_addr;\n" - "+ }\n" - "+ else { \n" - "+ /* last->next = virt_to_phys(td); */\n" - "+ }\n" - "+ if (ep->in) {\n" - "+ /* write tx bytes */\n" - "+ td->status = AMD_ADDBITS(td->status,\n" - "+ txbytes,\n" - "+ UDC_DMA_IN_STS_TXBYTES); \n" - "+ }\n" - "+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND\n" - "+ last_next = last->next;\n" - "+#endif\n" - "+ }\n" - "+ last = td;\n" - "+ }\n" - "+ /* set last bit */\n" - "+ if (td) {\n" - "+ td->status |= AMD_BIT(UDC_DMA_IN_STS_L);\n" - "+ /* last desc. points to itself */\n" - "+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND\n" - "+ /* remember broken chain next pointer */\n" - "+ req->td_data_last_next = td->next;\n" - "+ /* point to itself */\n" - "+ td->next = last_next;\n" - "+#endif\n" - "+ req->td_data_last = td;\n" - "+ }\n" - "+\n" - "+ return 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Enabling RX DMA \n" - "+ *\n" - "+ * \\param dev pointer to UDC device object \n" - "+ */\n" - "+static inline void udc_set_rde(struct udc* dev)\n" - "+{\n" - "+ u32 tmp;\n" - "+\n" - "+ VDBG(\"udc_set_rde()\\n\");\n" - "+#ifdef UDC_USE_TIMER\n" - "+ /* stop RDE timer */ \n" - "+ if (timer_pending(&udc_timer)) {\n" - "+ set_rde = 0;\n" - "+ mod_timer(&udc_timer, jiffies - 1);\n" - "+ }\n" - "+#endif\n" - "+ /* set RDE */\n" - "+ tmp = readl(&dev->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_DEVCTL_RDE);\n" - "+ writel(tmp, &dev->regs->ctl); \n" - "+}\n" - "+\n" - "+/**\n" - "+ * Queues a request packet, called by gadget driver\n" - "+ * \n" - "+ * \\param usbep pointer to usb ep struct\n" - "+ * \\param usbreq pointer to request packet to be freed\n" - "+ * \\param gfp flags for alloc\n" - "+ * \\return 0 if success\n" - "+ */\n" - "+static int\n" - "+udc_queue (struct usb_ep *usbep, struct usb_request *usbreq, gfp_t gfp)\n" - "+{\n" - "+ int retval = 0;\n" - "+ unsigned long iflags;\n" - "+ struct udc_ep *ep;\n" - "+ struct udc_request *req;\n" - "+ struct udc *dev;\n" - "+ u32 tmp;\n" - "+ \n" - "+ VDBG (\"udc_queue()\\n\");\n" - "+\n" - "+ /* check the inputs */\n" - "+ req = container_of (usbreq, struct udc_request, req);\n" - "+ VDBG(\"!usbep=%d !req=%d !buf=%d !compl=%d !empty_list=%d \\n\",\n" - "+ !usbep, !usbreq, !usbreq->buf, !usbreq->complete,\n" - "+ !list_empty(&req->queue));\n" - "+\n" - "+ if (!usbep || !usbreq || !usbreq->complete || !usbreq->buf\n" - "+ || !list_empty (&req->queue))\n" - "+ return -EINVAL;\n" - "+\n" - "+ ep = container_of (usbep, struct udc_ep, ep);\n" - "+ if (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))\n" - "+ return -EINVAL;\n" - "+\n" - "+ VDBG(\"udc_queue(): ep%d-in=%d\\n\", ep->num, ep->in);\n" - "+ dev = ep->dev;\n" - "+\n" - "+ /* exit on suspend */\n" - "+ if (dev->sys_suspended) \n" - "+ return -ESHUTDOWN;\n" - "+\n" - "+ if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)\n" - "+ return -ESHUTDOWN;\n" - "+\n" - "+ /* map dma (usally done before) */\n" - "+ if (ep->dma && usbreq->length != 0 && usbreq->dma == DMA_DONT_USE) {\n" - "+ VDBG(\"DMA map req %lx\\n\", (unsigned long) req);\n" - "+#if defined(CONFIG_SOC_AU1200)\n" - "+ if (ep->in)\n" - "+ usbreq->dma = dma_map_single(dev->pdev,\n" - "+ usbreq->buf,\n" - "+ usbreq->length,\n" - "+ PCI_DMA_TODEVICE);\n" - "+ else\n" - "+ usbreq->dma = dma_map_single(dev->pdev,\n" - "+ usbreq->buf,\n" - "+ usbreq->length,\n" - "+ PCI_DMA_FROMDEVICE);\n" - "+#else\n" - "+ if (ep->in)\n" - "+ usbreq->dma = pci_map_single(dev->pdev,\n" - "+ usbreq->buf,\n" - "+ usbreq->length,\n" - "+ PCI_DMA_TODEVICE);\n" - "+ else\n" - "+ usbreq->dma = pci_map_single(dev->pdev,\n" - "+ usbreq->buf,\n" - "+ usbreq->length,\n" - "+ PCI_DMA_FROMDEVICE);\n" - "+#endif\n" - "+ req->dma_mapping = 1;\n" - "+ }\n" - "+\n" - "+ VDBG( \"%s queue req %p, len %d req->td_data=%lx buf %p\\n\",\n" - "+ usbep->name, usbreq, usbreq->length, (unsigned long) req->td_data, usbreq->buf);\n" - "+\n" - "+ spin_lock_irqsave (&dev->lock, iflags);\n" - "+ usbreq->actual = 0;\n" - "+ usbreq->status = -EINPROGRESS;\n" - "+ req->dma_done = 0;\n" - "+ \n" - "+ /* on empty queue just do first transfer */\n" - "+ if (list_empty (&ep->queue)) {\n" - "+ /* zlp */\n" - "+ if (ep->in && usbreq->length == 0) {\n" - "+ /* IN zlp's are handled by hardware */\n" - "+ complete_req(ep, req, 0);\n" - "+ VDBG( \"%s: zlp\\n\", ep->ep.name);\n" - "+ /* if set_config or set_intf is waiting for ack by zlp\n" - "+ then set CSR_DONE */\n" - "+ if (dev->set_cfg_not_acked) {\n" - "+ tmp = readl(&dev->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_DEVCTL_CSR_DONE);\n" - "+ writel(tmp, &dev->regs->ctl);\n" - "+ dev->set_cfg_not_acked = 0;\n" - "+ }\n" - "+ /* setup command is ACK'ed now by zlp */\n" - "+ if (dev->waiting_zlp_ack_ep0in) {\n" - "+ /* clear NAK by writing CNAK in EP0_IN */\n" - "+ tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); \n" - "+ writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);\n" - "+ dev->ep[UDC_EP0IN_IX].naking = 0;\n" - "+ UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX], UDC_EP0IN_IX);\n" - "+ dev->waiting_zlp_ack_ep0in = 0;\n" - "+ }\n" - "+ goto finished;\n" - "+ }\n" - "+ if (ep->dma) {\n" - "+ retval = prep_dma(ep, req);\n" - "+ if (retval != 0)\n" - "+ goto finished;\n" - "+ /* write desc pointer to enable DMA */\n" - "+ if (ep->in) {\n" - "+ /* set HOST READY */\n" - "+ req->td_data->status \n" - "+ = AMD_ADDBITS(req->td_data->status,\n" - "+ UDC_DMA_IN_STS_BS_HOST_READY, \n" - "+ UDC_DMA_IN_STS_BS);\n" - "+ }\n" - "+\n" - "+ /* write desc pointer */\n" - "+ writel(req->td_phys, &ep->regs->desptr);\n" - "+ /* clear NAK by writing CNAK */\n" - "+ if (ep->naking) {\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); \n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+ ep->naking = 0;\n" - "+ UDC_QUEUE_CNAK(ep, ep->num);\n" - "+ }\n" - "+ \n" - "+ if (!ep->in) {\n" - "+ /* enable DMA */\n" - "+ udc_set_rde(dev);\n" - "+ if (ep->num != UDC_EP0OUT_IX) \n" - "+ dev->data_ep_queued = 1;\n" - "+ }\n" - "+#ifdef UDC_DISABLE_IRQ_IF_EMPTY_IN_QUEUE\n" - "+ else {\n" - "+ /* enable ep irq */\n" - "+ tmp = readl(&dev->regs->ep_irqmsk);\n" - "+ tmp &= AMD_UNMASK_BIT(ep->num);\n" - "+ writel(tmp, &dev->regs->ep_irqmsk); \n" - "+ }\n" - "+#endif\n" - "+ }\n" - "+\n" - "+ } else if (ep->dma) {\n" - "+\n" - "+ /* prep_dma not used for OUT ep's, this is not possible\n" - "+ for PPB modes, because of chain creation reasons */\n" - "+ if (ep->in) {\n" - "+ retval = prep_dma(ep, req);\n" - "+ if (retval != 0)\n" - "+ goto finished;\n" - "+ }\n" - "+\n" - "+ }\n" - "+ VDBG(\"list_add\\n\");\n" - "+ /* add request to ep queue */\n" - "+ if (req) {\n" - "+ \n" - "+ list_add_tail (&req->queue, &ep->queue);\n" - "+\n" - "+ /* stop OUT naking */\n" - "+ if (!ep->in) {\n" - "+ if (!use_dma && udc_rxfifo_pending) {\n" - "+ DBG(\"udc_queue(): pending bytes in rxfifo after nyet\\n\");\n" - "+ /* read pending bytes afer nyet: referring to isr */\n" - "+ if (udc_rxfifo_read(ep, req)) {\n" - "+ /* finish */\n" - "+ complete_req(ep, req, 0);\n" - "+ }\n" - "+ udc_rxfifo_pending = 0;\n" - "+\n" - "+ }\n" - "+ }\n" - "+\n" - "+ }\n" - "+\n" - "+finished:\n" - "+ spin_unlock_irqrestore (&dev->lock, iflags);\n" - "+ return retval;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Empty request queue of an endpoint \n" - "+ * \n" - "+ * \\param ep pointer to ep struct\n" - "+ */\n" - "+static void empty_req_queue(struct udc_ep *ep)\n" - "+{\n" - "+ struct udc_request *req;\n" - "+\n" - "+ ep->halted = 1;\n" - "+ while (!list_empty (&ep->queue)) {\n" - "+ req = list_entry(ep->queue.next,\n" - "+ struct udc_request,\n" - "+ queue);\n" - "+ complete_req(ep, req, -ESHUTDOWN);\n" - "+ }\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Dequeues a request packet, called by gadget driver\n" - "+ * \n" - "+ * \\param usbep pointer to usb ep struct\n" - "+ * \\param usbreq pointer to request packet to be freed\n" - "+ * \\return 0 if success\n" - "+ */\n" - "+static int udc_dequeue (struct usb_ep *usbep, struct usb_request *usbreq)\n" - "+{\n" - "+ struct udc_ep *ep;\n" - "+ struct udc_request *req;\n" - "+ unsigned req_may_used = 0;\n" - "+ unsigned halted;\n" - "+ unsigned long iflags;\n" - "+\n" - "+ ep = container_of (usbep, struct udc_ep, ep);\n" - "+ if (!usbep\n" - "+ || !usbreq\n" - "+ || (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX)))\n" - "+ return -EINVAL;\n" - "+\n" - "+ req = container_of (usbreq, struct udc_request, req);\n" - "+\n" - "+ spin_lock_irqsave (&ep->dev->lock, iflags);\n" - "+ halted = ep->halted;\n" - "+ ep->halted = 1;\n" - "+ /* request in processing or next one */\n" - "+ if (ep->queue.next == &req->queue) {\n" - "+ req_may_used = 1;\n" - "+ }\n" - "+ complete_req(ep, req, -ECONNRESET);\n" - "+ ep->halted = halted;\n" - "+\n" - "+ spin_unlock_irqrestore (&ep->dev->lock, iflags);\n" - "+ if (req_may_used)\n" - "+ return -EOPNOTSUPP;\n" - "+ else\n" - "+ return 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Halt or clear halt of endpoint \n" - "+ * \n" - "+ * \\param usbe pointer to ep struct\n" - "+ * \\param halt 1 - halt, 0 - clear halt\n" - "+ * \\return 0 if success \n" - "+ */\n" - "+static int\n" - "+udc_set_halt (struct usb_ep *usbep, int halt)\n" - "+{\n" - "+ struct udc_ep *ep;\n" - "+ u32 tmp;\n" - "+ unsigned long iflags;\n" - "+ int retval = 0;\n" - "+\n" - "+ if (!usbep)\n" - "+ return -EINVAL;\n" - "+\n" - "+ DBG(\"set_halt %s: halt=%d\\n\", usbep->name, halt);\n" - "+\n" - "+ ep = container_of (usbep, struct udc_ep, ep);\n" - "+ if (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))\n" - "+ return -EINVAL;\n" - "+ if (!ep->dev->driver\n" - "+ || ep->dev->gadget.speed == USB_SPEED_UNKNOWN)\n" - "+ return -ESHUTDOWN;\n" - "+\n" - "+ /* exit on suspend */\n" - "+ if (ep->dev->sys_suspended) \n" - "+ return -ESHUTDOWN;\n" - "+\n" - "+ spin_lock_irqsave (&udc_stall_spinlock, iflags);\n" - "+ /* halt or clear halt */\n" - "+ if (halt) {\n" - "+ if (ep->num == 0)\n" - "+ ep->dev->stall_ep0in = 1;\n" - "+ else {\n" - "+ /* set STALL */\n" - "+ /* rxfifo empty not taken into acount */\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_S);\n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+ ep->halted = 1;\n" - "+\n" - "+#ifdef UDC_USE_TIMER\n" - "+ /* setup poll timer */\n" - "+ if (!timer_pending(&udc_pollstall_timer)) {\n" - "+ udc_pollstall_timer.expires = jiffies + HZ \n" - "+ * UDC_POLLSTALL_TIMER_USECONDS\n" - "+ / (1000 * 1000);\n" - "+ if (!stop_pollstall_timer) {\n" - "+ DBG(\"start polltimer\\n\");\n" - "+ add_timer(&udc_pollstall_timer);\n" - "+ }\n" - "+ }\n" - "+#endif\n" - "+ }\n" - "+ } else {\n" - "+ /* ep is halted by set_halt() before */\n" - "+ if (ep->halted) {\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ /* clear stall bit */\n" - "+ tmp = tmp & AMD_CLEAR_BIT(UDC_EPCTL_S);\n" - "+ /* clear NAK by writing CNAK */\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); \n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+ ep->halted = 0;\n" - "+ UDC_QUEUE_CNAK(ep, ep->num);\n" - "+ }\n" - "+ }\n" - "+ spin_unlock_irqrestore (&udc_stall_spinlock, iflags);\n" - "+ return retval;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Return fifo fill state (not used, not implemented)\n" - "+ * \n" - "+ * \\param usbep pointer to usb ep struct\n" - "+ * \\return available bytes in fifo \n" - "+ */\n" - "+static int\n" - "+udc_fifo_status (struct usb_ep *usbep)\n" - "+{\n" - "+ return 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Flush the endpoint fifo (not implemented)\n" - "+ * \n" - "+ * \\param usbep pointer to usb ep struct\n" - "+ */\n" - "+static void\n" - "+udc_fifo_flush (struct usb_ep *usbep)\n" - "+{\n" - "+ return;\n" - "+}\n" - "+\n" - "+/* gadget interface */\n" - "+static struct usb_ep_ops udc_ep_ops = {\n" - "+ .enable = udc_enable,\n" - "+ .disable = udc_disable,\n" - "+\n" - "+ .queue = udc_queue,\n" - "+ .dequeue = udc_dequeue,\n" - "+\n" - "+ .alloc_request = udc_alloc_request,\n" - "+ .free_request = udc_free_request,\n" - "+\n" - "+ .alloc_buffer = udc_alloc_buffer,\n" - "+ .free_buffer = udc_free_buffer,\n" - "+\n" - "+ .set_halt = udc_set_halt,\n" - "+ .fifo_status = udc_fifo_status,\n" - "+ .fifo_flush = udc_fifo_flush,\n" - "+};\n" - "+\n" - "+/*-------------------------------------------------------------------------*/\n" - "+\n" - "+/**\n" - "+ * Get frame count fifo (not implemented)\n" - "+ * \n" - "+ * \\param gadget pointer to gadget struct\n" - "+ * \\return frame count\n" - "+ */\n" - "+static int udc_get_frame (struct usb_gadget *gadget)\n" - "+{\n" - "+ return 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Remote wakeup gadget interface\n" - "+ * \n" - "+ * \\param gadget pointer to gadget struct\n" - "+ * \\return 0 if success\n" - "+ */\n" - "+static int udc_wakeup (struct usb_gadget *gadget)\n" - "+{\n" - "+ struct udc *dev;\n" - "+\n" - "+ if (!gadget)\n" - "+ return -EINVAL;\n" - "+ dev = container_of (gadget, struct udc, gadget);\n" - "+ udc_remote_wakeup(dev);\n" - "+\n" - "+ return 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * gadget ioctl, used for OTG support notification\n" - "+ * \n" - "+ * \\param gadget pointer to gadget struct\n" - "+ * \\param cmd command\n" - "+ * \\param par parmater\n" - "+ * \\return 1 if OTG supported, else 0\n" - "+ */\n" - "+static int udc_gadget_ioctl (struct usb_gadget *gadget, unsigned cmd, unsigned long par)\n" - "+{\n" - "+ struct udc *dev;\n" - "+ int retval = 0;\n" - "+ unsigned long iflags;\n" - "+ u32 tmp;\n" - "+\n" - "+ if (!gadget)\n" - "+ return -ENODEV;\n" - "+ dev = container_of (gadget, struct udc, gadget);\n" - "+ spin_lock_irqsave (&dev->lock, iflags);\n" - "+ tmp = readl(&dev->regs->cfg);\n" - "+ \n" - "+ if (tmp & AMD_BIT(UDC_DEVCFG_HNPSFEN))\n" - "+ retval = 1;\n" - "+ else\n" - "+ retval = 0;\n" - "+ spin_unlock_irqrestore (&dev->lock, iflags);\n" - "+ return retval;\n" - "+}\n" - "+\n" - "+/* gadget operations */\n" - "+static const struct usb_gadget_ops udc_ops = {\n" - "+ .wakeup = udc_wakeup,\n" - "+ .get_frame = udc_get_frame,\n" - "+ .ioctl = udc_gadget_ioctl, \n" - "+};\n" - "+\n" - "+/**\n" - "+ * Setups endpoint parameters, adds endpoints to linked list\n" - "+ * \n" - "+ * \\param dev pointer to dev struct\n" - "+ */\n" - "+static void make_ep_lists(struct udc *dev)\n" - "+{\n" - "+ /* make gadget ep lists */\n" - "+ INIT_LIST_HEAD (&dev->gadget.ep_list);\n" - "+ list_add_tail (&dev->ep [UDC_EPIN_STATUS_IX].ep.ep_list, &dev->gadget.ep_list);\n" - "+ list_add_tail (&dev->ep [UDC_EPIN_IX].ep.ep_list, &dev->gadget.ep_list);\n" - "+ list_add_tail (&dev->ep [UDC_EPOUT_IX].ep.ep_list, &dev->gadget.ep_list);\n" - "+ \n" - "+ /* fifo config */\n" - "+ dev->ep [UDC_EPIN_STATUS_IX].fifo_depth = UDC_EPIN_SMALLINT_BUFF_SIZE;\n" - "+ if (dev->gadget.speed == USB_SPEED_FULL)\n" - "+ dev->ep [UDC_EPIN_IX].fifo_depth = UDC_FS_EPIN_BUFF_SIZE; \n" - "+ else if (dev->gadget.speed == USB_SPEED_HIGH)\n" - "+ dev->ep [UDC_EPIN_IX].fifo_depth = hs_tx_buf; \n" - "+ dev->ep [UDC_EPOUT_IX].fifo_depth = UDC_RXFIFO_SIZE;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Sets fifo mode, called by gadget driver\n" - "+ * \n" - "+ * \\param gadget pointer to gadget struct\n" - "+ * \\param md not used\n" - "+ * \\return 0 if success \n" - "+ */\n" - "+int au1200udc_set_fifo_mode (struct usb_gadget *gadget, int md)\n" - "+{\n" - "+ struct udc *dev;\n" - "+ unsigned long iflags;\n" - "+\n" - "+ if (!gadget)\n" - "+ return -ENODEV;\n" - "+\n" - "+ dev = container_of (gadget, struct udc, gadget);\n" - "+\n" - "+ spin_lock_irqsave (&dev->lock, iflags);\n" - "+ make_ep_lists(dev);\n" - "+ spin_unlock_irqrestore (&dev->lock, iflags);\n" - "+\n" - "+ return 0;\n" - "+}\n" - "+EXPORT_SYMBOL (au1200udc_set_fifo_mode);\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * init registers at driver load time \n" - "+ *\n" - "+ * \\param dev pointer to device struc\n" - "+ * \\return 0 if success\n" - "+ */\n" - "+static int startup_registers(struct udc* dev)\n" - "+{\n" - "+ u32 tmp;\n" - "+\n" - "+ /* init controller by soft reset */\n" - "+ udc_soft_reset(dev);\n" - "+\n" - "+ /* mask not needed interrupts */\n" - "+ udc_mask_unused_interrupts(dev);\n" - "+\n" - "+ /* put into initial config */\n" - "+ udc_basic_init (dev);\n" - "+ /* link up all endpoints */\n" - "+ udc_setup_endpoints (dev);\n" - "+ \n" - "+ /* program speed */\n" - "+ tmp = readl(&dev->regs->cfg);\n" - "+ if (use_fullspeed) {\n" - "+ tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);\n" - "+ }\n" - "+ else {\n" - "+ tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_HS, UDC_DEVCFG_SPD);\n" - "+ }\n" - "+ writel(tmp, &dev->regs->cfg);\n" - "+\n" - "+ return 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Inits UDC context \n" - "+ * \n" - "+ * \\param dev pointer to device struct\n" - "+ */\n" - "+static void udc_basic_init (struct udc *dev)\n" - "+{\n" - "+ u32 tmp;\n" - "+\n" - "+ DBG(\"udc_basic_init()\\n\"); \n" - "+ \n" - "+ dev->gadget.speed = USB_SPEED_UNKNOWN;\n" - "+\n" - "+#ifdef UDC_USE_TIMER\n" - "+ /* stop RDE timer */ \n" - "+ if (timer_pending(&udc_timer)) {\n" - "+ set_rde = 0;\n" - "+ mod_timer(&udc_timer, jiffies - 1);\n" - "+ }\n" - "+ /* stop poll stall timer */ \n" - "+ if (timer_pending(&udc_pollstall_timer)) {\n" - "+ mod_timer(&udc_pollstall_timer, jiffies - 1);\n" - "+ }\n" - "+#endif\n" - "+ /* disable DMA */\n" - "+ tmp = readl(&dev->regs->ctl);\n" - "+ tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_RDE);\n" - "+ tmp &= AMD_UNMASK_BIT(UDC_DEVCTL_TDE);\n" - "+ writel(tmp, &dev->regs->ctl); \n" - "+\n" - "+ /* enable dynamic CSR programming */\n" - "+ tmp = readl(&dev->regs->cfg);\n" - "+ tmp |= AMD_BIT(UDC_DEVCFG_CSR_PRG);\n" - "+ /* set self powered */\n" - "+ tmp |= AMD_BIT(UDC_DEVCFG_SP);\n" - "+ /* set remote wakeupable */\n" - "+ tmp |= AMD_BIT(UDC_DEVCFG_RWKP);\n" - "+ writel(tmp, &dev->regs->cfg); \n" - "+\n" - "+ make_ep_lists(dev);\n" - "+\n" - "+ dev->data_ep_enabled = 0;\n" - "+ dev->data_ep_queued = 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Sets initial endpoint parameters\n" - "+ * \n" - "+ * \\param dev pointer to device struct\n" - "+ */\n" - "+static void udc_setup_endpoints(struct udc *dev)\n" - "+{\n" - "+ struct udc_ep *ep;\n" - "+ u32 tmp;\n" - "+ u32 reg;\n" - "+\n" - "+ DBG(\"udc_setup_endpoints()\\n\");\n" - "+\n" - "+ /* read enum speed */\n" - "+ tmp = readl(&dev->regs->sts);\n" - "+ tmp = AMD_GETBITS(tmp, UDC_DEVSTS_ENUM_SPEED); \n" - "+ if (tmp == UDC_DEVSTS_ENUM_SPEED_HIGH) {\n" - "+ dev->gadget.speed = USB_SPEED_HIGH;\n" - "+ }\n" - "+ else if (tmp == UDC_DEVSTS_ENUM_SPEED_FULL) {\n" - "+ dev->gadget.speed = USB_SPEED_FULL;\n" - "+ }\n" - "+ \n" - "+ /* set basic ep parameters */\n" - "+ for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {\n" - "+ ep = &dev->ep[tmp];\n" - "+ ep->dev = dev;\n" - "+ ep->ep.name = ep_string [tmp];\n" - "+ ep->num = tmp;\n" - "+ /* txfifo size is calculated at enable time */\n" - "+ ep->txfifo = dev->txfifo;\n" - "+\n" - "+ /* fifo size */\n" - "+ if (tmp < UDC_EPIN_NUM) {\n" - "+ ep->fifo_depth = UDC_TXFIFO_SIZE;\n" - "+ ep->in = 1;\n" - "+ }\n" - "+ else {\n" - "+ ep->fifo_depth = UDC_RXFIFO_SIZE;\n" - "+ ep->in = 0;\n" - "+\n" - "+ }\n" - "+ ep->regs = &dev->ep_regs[tmp];\n" - "+ /* ep will be reset only if ep was not enabled before to avoid\n" - "+ disabling ep interrupts when ENUM interrupt occurs but ep is\n" - "+ not enabled by gadget driver */\n" - "+ if (!ep->desc) {\n" - "+ ep_init (dev->regs, ep);\n" - "+ }\n" - "+\n" - "+ if (use_dma) {\n" - "+ /* ep->dma is not really used, just to indicate that */\n" - "+ /* DMA is active: remove this */\n" - "+ /* dma regs = dev control regs */ \n" - "+ ep->dma = (u32*) &dev->regs->ctl; \n" - "+\n" - "+ /* nak OUT endpoints until enable - not for ep0*/\n" - "+ if (tmp != UDC_EP0IN_IX\n" - "+ && tmp != UDC_EP0OUT_IX\n" - "+ && tmp > UDC_EPIN_NUM) {\n" - "+ /* set NAK */\n" - "+ reg = readl(&dev->ep[tmp].regs->ctl);\n" - "+ reg |= AMD_BIT(UDC_EPCTL_SNAK); \n" - "+ writel(reg, &dev->ep[tmp].regs->ctl);\n" - "+ dev->ep[tmp].naking = 1;\n" - "+ \n" - "+ }\n" - "+ }\n" - "+ }\n" - "+ /* EP0 max packet */\n" - "+ if (dev->gadget.speed == USB_SPEED_FULL) {\n" - "+ dev->ep [UDC_EP0IN_IX].ep.maxpacket = UDC_FS_EP0IN_MAX_PKT_SIZE;\n" - "+ dev->ep [UDC_EP0OUT_IX].ep.maxpacket = UDC_FS_EP0OUT_MAX_PKT_SIZE;\n" - "+ }\n" - "+ else if (dev->gadget.speed == USB_SPEED_HIGH) {\n" - "+ dev->ep [UDC_EP0IN_IX].ep.maxpacket = UDC_EP0IN_MAX_PKT_SIZE;\n" - "+ dev->ep [UDC_EP0OUT_IX].ep.maxpacket = UDC_EP0OUT_MAX_PKT_SIZE;\n" - "+ }\n" - "+\n" - "+ /* with suspend bug workaround, ep0 params for gadget driver\n" - "+ are set at gadget driver bind() call */\n" - "+ dev->gadget.ep0 = &dev->ep [UDC_EP0IN_IX].ep;\n" - "+ dev->ep [UDC_EP0IN_IX].halted = 0;\n" - "+ INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);\n" - "+\n" - "+ /* init cfg/alt/int */\n" - "+ dev->cur_config = 0;\n" - "+ dev->cur_intf = 0;\n" - "+ dev->cur_alt = 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Bringup after Connect event,\n" - "+ * initial bringup to be ready for ep0 events \n" - "+ * \n" - "+ * \\param dev pointer to device struct\n" - "+ */\n" - "+static void usb_connect (struct udc *dev) {\n" - "+\n" - "+ INFO(\"USB Connect\\n\");\n" - "+\n" - "+ dev->connected = 1;\n" - "+\n" - "+ /* put into initial config */\n" - "+ udc_basic_init (dev);\n" - "+\n" - "+ /* enable device setup interrupts */\n" - "+ udc_enable_dev_setup_interrupts(dev);\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Calls gadget with disconnect event and resets the UDC and makes\n" - "+ * initial bringup to be ready for ep0 events \n" - "+ * \n" - "+ * \\param dev pointer to device struct\n" - "+ */\n" - "+static void usb_disconnect (struct udc *dev) {\n" - "+\n" - "+ INFO(\"USB Disconnect\\n\");\n" - "+\n" - "+ dev->connected = 0;\n" - "+\n" - "+ /* mask interrupts */\n" - "+ udc_mask_unused_interrupts(dev);\n" - "+\n" - "+ tasklet_schedule(&disconnect_tasklet);\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Tasklet for disconnect to be outside of interrupt \n" - "+ * context \n" - "+ * \n" - "+ * \\param par pointer to device struct pointer\n" - "+ */\n" - "+void udc_tasklet_disconnect(unsigned long par)\n" - "+{\n" - "+ struct udc* dev = (struct udc*) (*((struct udc**) par));\n" - "+ u32 tmp;\n" - "+\n" - "+ DBG(\"Tasklet disconnect\\n\");\n" - "+\n" - "+ if (dev->driver) {\n" - "+ /* call gadget to reset configs etc. */\n" - "+ if (spin_is_locked(&dev->lock)) {\n" - "+ spin_unlock(&dev->lock);\n" - "+ dev->driver->disconnect (&dev->gadget);\n" - "+ spin_lock(&dev->lock);\n" - "+ }\n" - "+ else\n" - "+ dev->driver->disconnect (&dev->gadget);\n" - "+\n" - "+ /* empty queues */\n" - "+ for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {\n" - "+ empty_req_queue (&dev->ep [tmp]);\n" - "+ }\n" - "+ }\t\n" - "+\n" - "+ /* disable ep0 */\n" - "+ ep_init (dev->regs,\n" - "+ &dev->ep [UDC_EP0IN_IX]);\n" - "+ \n" - "+\n" - "+ if (!soft_reset_occured) {\n" - "+ /* init controller by soft reset */\n" - "+#ifdef UDC_IPCASE_8000018724_WORKAROUND\n" - "+ udc_soft_reset(dev);\n" - "+#endif\n" - "+ soft_reset_occured++;\n" - "+ }\n" - "+#ifndef UDC_IPBUG_3950_WORKAROUND\n" - "+ /* re-enable dev interrupts */\n" - "+ udc_enable_dev_setup_interrupts(dev);\n" - "+#endif\n" - "+ /* back to full speed ? */\n" - "+ if (use_fullspeed) {\n" - "+ tmp = readl(&dev->regs->cfg);\n" - "+ tmp = AMD_ADDBITS(tmp, UDC_DEVCFG_SPD_FS, UDC_DEVCFG_SPD);\n" - "+ writel(tmp, &dev->regs->cfg);\n" - "+ }\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Reset the UDC core \n" - "+ * \n" - "+ * \\param dev pointer to device struct\n" - "+ */\n" - "+static void udc_soft_reset(struct udc* dev)\n" - "+{\n" - "+ DBG(\"Soft reset\\n\");\n" - "+ /* reset possible waiting interrupts, because int.\n" - "+ status is lost after soft reset */\n" - "+ /* ep int. status reset */ \n" - "+ writel(UDC_EPINT_MSK_DISABLE_ALL, &dev->regs->ep_irqsts);\n" - "+ /* device int. status reset */ \n" - "+ writel(UDC_DEV_MSK_DISABLE, &dev->regs->irqsts);\n" - "+\n" - "+ spin_lock_irq(&udc_irq_spinlock);\n" - "+ writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);\n" - "+ readl(&dev->regs->cfg);\n" - "+ spin_unlock_irq(&udc_irq_spinlock);\n" - "+ \n" - "+}\n" - "+\n" - "+#ifdef UDC_USE_TIMER\n" - "+/**\n" - "+ * RDE timer callback to set RDE bit \n" - "+ * \n" - "+ * \\param v timer callback argument\n" - "+ */\n" - "+void udc_timer_function(unsigned long v)\n" - "+{\n" - "+ u32 tmp;\n" - "+ unsigned int i;\n" - "+ unsigned int bulk_data_arrived;\n" - "+ spin_lock_irq(&udc_irq_spinlock);\n" - "+ if (set_rde) {\n" - "+ /* open the fifo if fifo was filled on last timer call */\n" - "+ if (set_rde > 1) {\n" - "+ bulk_data_arrived = 0;\n" - "+ /* check wether OUT bulk data is arrived */\n" - "+ for (i = UDC_EPIN_NUM + 1; i < UDC_EP_NUM; i++) {\n" - "+ tmp = readl(&udc->ep [i].regs->sts);\n" - "+ if (AMD_GETBITS(tmp, UDC_EPSTS_OUT)\n" - "+ == UDC_EPSTS_OUT_DATA) {\n" - "+ bulk_data_arrived = 1;\n" - "+ break;\n" - "+ }\n" - "+ }\n" - "+ /* if OUT bulk data in fifo wait for queueing which\n" - "+ sets RDE, if not open fifo for setup packet */\n" - "+ if (!bulk_data_arrived) {\n" - "+ /* set RDE */\n" - "+ tmp = readl(&udc->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_DEVCTL_RDE);\n" - "+ writel(tmp, &udc->regs->ctl); \n" - "+ }\n" - "+ else \n" - "+ INFO(\"ep%d - queueing delay longer than %d second(s)\\n\",\n" - "+ i, UDC_RDE_TIMER_SECONDS);\n" - "+ set_rde = -1;\n" - "+ }\n" - "+ else if (readl(&udc->regs->sts) & \n" - "+ AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) {\n" - "+ /* if fifo empty setup polling, do not just\n" - "+ open the fifo */\n" - "+ udc_timer.expires = jiffies + HZ/UDC_RDE_TIMER_DIV;\n" - "+ if (!stop_timer) {\n" - "+ add_timer(&udc_timer);\n" - "+ }\n" - "+ }\n" - "+ else {\n" - "+ /* fifo contains data now, setup timer for opening\n" - "+ the fifo when timer expires to be able to receive\n" - "+ setup packets, when data packets gets queued by\n" - "+ gadget layer then timer will forced to expire with\n" - "+ set_rde=0 (RDE is set in udc_queue()) */\n" - "+ set_rde++;\n" - "+ /* debug: lhadmot_timer_start = 221070 */\n" - "+ udc_timer.expires = jiffies + HZ*UDC_RDE_TIMER_SECONDS;\n" - "+ if (!stop_timer) {\n" - "+ add_timer(&udc_timer);\n" - "+ }\n" - "+ }\n" - "+ \n" - "+ }\n" - "+ else\n" - "+ set_rde = -1; /* RDE was set by udc_queue() */\n" - "+ spin_unlock_irq(&udc_irq_spinlock);\n" - "+ if (stop_timer)\n" - "+ complete(&on_exit);\n" - "+ \n" - "+}\n" - "+\n" - "+/**\n" - "+ * Handle halt state, used in stall poll timer \n" - "+ * \n" - "+ * \\param ep pointer to endpoint struct \n" - "+ */\n" - "+static inline void udc_handle_halt_state(struct udc_ep* ep)\n" - "+{\n" - "+ u32 tmp;\n" - "+ /* set stall as long not halted */\n" - "+ if (ep->halted == 1) {\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ /* STALL cleared ? */\n" - "+ if (!(tmp & AMD_BIT(UDC_EPCTL_S))) {\n" - "+ DBG(\"ep %d: set STALL again\\n\", ep->num);\n" - "+ /* set STALL again */\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_S);\n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+ }\n" - "+ } \n" - "+}\n" - "+\n" - "+/**\n" - "+ * Stall timer callback to poll S bit and set it again after\n" - "+ * CLEAR_FEATURE \n" - "+ * \n" - "+ * \\param v timer callback argument\n" - "+ */\n" - "+void udc_pollstall_timer_function(unsigned long v)\n" - "+{\n" - "+ struct udc_ep *ep;\n" - "+ int halted = 0;\n" - "+ unsigned long iflags;\n" - "+\n" - "+ spin_lock_irqsave (&udc_stall_spinlock, iflags);\n" - "+ /* only one IN and OUT endpoints are handled */\n" - "+ /* IN poll stall */ \n" - "+ ep = &udc->ep [UDC_EPIN_IX];\n" - "+ udc_handle_halt_state(ep); \n" - "+ if (ep->halted)\n" - "+ halted = 1;\n" - "+ /* OUT poll stall */ \n" - "+ ep = &udc->ep [UDC_EPOUT_IX];\n" - "+ udc_handle_halt_state(ep); \n" - "+ if (ep->halted)\n" - "+ halted = 1;\n" - "+\n" - "+ /* setup timer again when still halted */\n" - "+ if (!stop_pollstall_timer && halted) {\n" - "+ udc_pollstall_timer.expires = jiffies + HZ \n" - "+ * UDC_POLLSTALL_TIMER_USECONDS\n" - "+ / (1000 * 1000);\n" - "+ add_timer(&udc_pollstall_timer);\n" - "+ }\n" - "+ spin_unlock_irqrestore (&udc_stall_spinlock, iflags);\n" - "+\n" - "+ if (stop_pollstall_timer)\n" - "+ complete(&on_pollstall_exit);\n" - "+}\n" - "+#endif\n" - "+\n" - "+#if defined(UDC_IPBUG_3950_WORKAROUND) \\\n" - "+ || defined(UDC_IPCASE_8000018724_WORKAROUND) \\\n" - "+ && !defined(UDC_HSB1)\n" - "+/**\n" - "+ * Called by OTG driver to notify us regarding an OTG event\n" - "+ * \n" - "+ * \\param code notify code\n" - "+ */\n" - "+void otg_notify(unsigned int code) {\n" - "+ VDBG(\"OTG notify code=%d\\n\", code);\n" - "+ switch (code) {\n" - "+ case OTG_GADGET_EVT_SVDROP:\n" - "+ /* disconnect event */\n" - "+ usb_disconnect(udc);\n" - "+ break;\n" - "+ case OTG_GADGET_EVT_SVALID:\n" - "+ /* connect event */\n" - "+ usb_connect(udc);\n" - "+ break;\n" - "+ case OTG_GADGET_REQ_WAKE:\n" - "+ /* remote wakeup event */\n" - "+ udc_remote_wakeup(udc);\n" - "+ break;\n" - "+ } \n" - "+}\n" - "+#endif\n" - "+\n" - "+/**\n" - "+ * Inits endpoint 0 so that SETUP packets are processed\n" - "+ * \n" - "+ * \\param dev pointer to device struct\n" - "+ */\n" - "+static void activate_control_endpoints (struct udc *dev)\n" - "+{\n" - "+ u32 tmp;\n" - "+\n" - "+ DBG(\"activate_control_endpoints\\n\");\n" - "+\n" - "+ /* flush fifo */\n" - "+ tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_F); \n" - "+ writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);\n" - "+\n" - "+ /* set ep0 directions */\n" - "+ dev->ep[UDC_EP0IN_IX].in = 1;\n" - "+ dev->ep[UDC_EP0OUT_IX].in = 0;\n" - "+\n" - "+ /* set buffer size (tx fifo entries) of EP0_IN */\n" - "+ tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->bufin_framenum);\n" - "+ if (dev->gadget.speed == USB_SPEED_FULL)\n" - "+ tmp = AMD_ADDBITS(tmp, UDC_FS_EPIN0_BUFF_SIZE, UDC_EPIN_BUFF_SIZE);\n" - "+ else if (dev->gadget.speed == USB_SPEED_HIGH)\n" - "+ tmp = AMD_ADDBITS(tmp, UDC_EPIN0_BUFF_SIZE, UDC_EPIN_BUFF_SIZE);\n" - "+ writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->bufin_framenum);\n" - "+ \n" - "+ /* set max packet size of EP0_IN */\n" - "+ tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->bufout_maxpkt);\n" - "+ if (dev->gadget.speed == USB_SPEED_FULL)\n" - "+ tmp = AMD_ADDBITS(tmp, UDC_FS_EP0IN_MAX_PKT_SIZE, UDC_EP_MAX_PKT_SIZE);\n" - "+ else if (dev->gadget.speed == USB_SPEED_HIGH)\n" - "+ tmp = AMD_ADDBITS(tmp, UDC_EP0IN_MAX_PKT_SIZE, UDC_EP_MAX_PKT_SIZE);\n" - "+ writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->bufout_maxpkt);\n" - "+\n" - "+ /* set max packet size of EP0_OUT */\n" - "+ tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->bufout_maxpkt);\n" - "+ if (dev->gadget.speed == USB_SPEED_FULL)\n" - "+ tmp = AMD_ADDBITS(tmp, UDC_FS_EP0OUT_MAX_PKT_SIZE, UDC_EP_MAX_PKT_SIZE);\n" - "+ else if (dev->gadget.speed == USB_SPEED_HIGH)\n" - "+ tmp = AMD_ADDBITS(tmp, UDC_EP0OUT_MAX_PKT_SIZE, UDC_EP_MAX_PKT_SIZE);\n" - "+ writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->bufout_maxpkt);\n" - "+\n" - "+ /* set max packet size of EP0 in UDC CSR */\n" - "+ tmp = readl(&dev->csr->ne[0]);\n" - "+ if (dev->gadget.speed == USB_SPEED_FULL)\n" - "+ tmp = AMD_ADDBITS(tmp, UDC_FS_EP0OUT_MAX_PKT_SIZE, UDC_CSR_NE_MAX_PKT);\n" - "+ else if (dev->gadget.speed == USB_SPEED_HIGH)\n" - "+ tmp = AMD_ADDBITS(tmp, UDC_EP0OUT_MAX_PKT_SIZE, UDC_CSR_NE_MAX_PKT);\n" - "+ writel(tmp, &dev->csr->ne[0]);\n" - "+\n" - "+ if (use_dma) {\n" - "+ dev->ep [UDC_EP0OUT_IX].td->status |= AMD_BIT(UDC_DMA_OUT_STS_L);\n" - "+ /* write dma desc address */\n" - "+ writel(dev->ep [UDC_EP0OUT_IX].td_stp_dma, &dev->ep[UDC_EP0OUT_IX].regs->subptr);\n" - "+ writel(dev->ep [UDC_EP0OUT_IX].td_phys, &dev->ep[UDC_EP0OUT_IX].regs->desptr);\n" - "+#ifdef UDC_USE_TIMER\n" - "+ /* stop RDE timer */ \n" - "+ if (timer_pending(&udc_timer)) {\n" - "+ set_rde = 0;\n" - "+ mod_timer(&udc_timer, jiffies - 1);\n" - "+ }\n" - "+ /* stop pollstall timer */ \n" - "+ if (timer_pending(&udc_pollstall_timer)) {\n" - "+ mod_timer(&udc_pollstall_timer, jiffies - 1);\n" - "+ }\n" - "+#endif\n" - "+ /* enable DMA */\n" - "+ tmp = readl(&dev->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_DEVCTL_MODE)\n" - "+ | AMD_BIT(UDC_DEVCTL_RDE)\n" - "+ | AMD_BIT(UDC_DEVCTL_TDE);\n" - "+ if (use_dma_bufferfill_mode) {\n" - "+ tmp |= AMD_BIT(UDC_DEVCTL_BF);\n" - "+ } \n" - "+ else if (use_dma_ppb_du) {\n" - "+ tmp |= AMD_BIT(UDC_DEVCTL_DU);\n" - "+ }\n" - "+ writel(tmp, &dev->regs->ctl); \n" - "+ }\n" - "+\n" - "+ /* clear NAK by writing CNAK for EP0IN */\n" - "+ tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); \n" - "+ writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);\n" - "+ dev->ep[UDC_EP0IN_IX].naking = 0;\n" - "+ UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX], UDC_EP0IN_IX);\n" - "+ \n" - "+ /* clear NAK by writing CNAK for EP0OUT */\n" - "+ tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); \n" - "+ writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->ctl);\n" - "+ dev->ep[UDC_EP0OUT_IX].naking = 0;\n" - "+ UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX], UDC_EP0OUT_IX);\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Make endpoint 0 ready for control traffic\n" - "+ *\n" - "+ * \\param dev pointer to device struc\n" - "+ * \\return 0 if success\n" - "+ */\n" - "+static int setup_ep0(struct udc *dev)\n" - "+{\n" - "+ activate_control_endpoints (dev);\n" - "+ /* enable ep0 interrupts */\n" - "+ udc_enable_ep0_interrupts(dev);\n" - "+ /* enable device setup interrupts */\n" - "+ udc_enable_dev_setup_interrupts(dev);\n" - "+\n" - "+ return 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Called by gadget driver to register itself\n" - "+ *\n" - "+ * \\param driver pointer to gadget driver struct\n" - "+ * \\return 0 if success\n" - "+ */\n" - "+int usb_gadget_register_driver (struct usb_gadget_driver *driver)\n" - "+{\n" - "+ struct udc *dev = udc;\n" - "+ int retval;\n" - "+\tu32 tmp;\n" - "+\n" - "+ if (!driver || !driver->bind\n" - "+ || !driver->unbind\n" - "+ || !driver->setup\n" - "+ || driver->speed != USB_SPEED_HIGH)\n" - "+ return -EINVAL;\n" - "+ if (!dev)\n" - "+ return -ENODEV;\n" - "+ if (dev->driver)\n" - "+ return -EBUSY;\n" - "+\n" - "+ driver->driver.bus = 0;\n" - "+ dev->driver = driver;\n" - "+ dev->gadget.dev.driver = &driver->driver;\n" - "+\n" - "+#ifndef CONFIG_SOC_AU1200\n" - "+ /*device_create_file (&dev->pdev->dev, &dev_attr_function);\n" - "+ device_create_file (&dev->pdev->dev, &dev_attr_queues);*/\n" - "+#endif\n" - "+\n" - "+#ifdef CONFIG_USB_OTG\n" - "+\tdev->gadget.is_otg = 1;\n" - "+#endif\n" - "+ retval = driver->bind (&dev->gadget);\n" - "+ /* e.g. ether gadget needs driver_data on both ep0 endpoints */\n" - "+ dev->ep[UDC_EP0OUT_IX].ep.driver_data =\n" - "+ dev->ep [UDC_EP0IN_IX].ep.driver_data;\n" - "+ \n" - "+ gadget_bind_count++;\n" - "+ if (retval) {\n" - "+ DBG( \"binding to %s returning %d\\n\",\n" - "+ driver->driver.name, retval);\n" - "+ dev->driver = 0;\n" - "+ dev->gadget.dev.driver = 0;\n" - "+ return retval;\n" - "+ }\n" - "+\n" - "+ /* if otg driver already registered */\n" - "+ /* call otg bind() to mux udc to phy */\n" - "+ if (dev->otg_transceiver) {\n" - "+ dev->otg_transceiver->set_peripheral(\n" - "+ dev->otg_transceiver, &dev->gadget);\n" - "+\t\t/* clear SD */\n" - "+\t\ttmp = readl(&dev->regs->ctl);\n" - "+\t\ttmp = tmp & AMD_CLEAR_BIT(UDC_DEVCTL_SD);\n" - "+\t\twritel(tmp, &dev->regs->ctl);\n" - "+ }\n" - "+#ifndef UDC_IPBUG_3950_WORKAROUND\n" - "+ usb_connect(dev);\n" - "+#endif\n" - "+\n" - "+ return 0;\n" - "+}\n" - "+EXPORT_SYMBOL (usb_gadget_register_driver);\n" - "+\n" - "+/**\n" - "+ * Called by OTG driver to register itself\n" - "+ * \n" - "+ *\n" - "+ * \\param get_transceiver function pointer to get OTG info\n" - "+ * \\return 0 if success\n" - "+ */\n" - "+int usb_gadget_register_otg (struct otg_transceiver * (*get_transceiver)(void))\n" - "+{\n" - "+ struct udc *dev = udc;\n" - "+ int retval;\n" - "+\tu32 tmp;\n" - "+ \n" - "+ if (!get_transceiver)\n" - "+ return -EINVAL;\n" - "+ if (!dev)\n" - "+ return -ENODEV;\n" - "+ if (dev->otg_transceiver)\n" - "+ return -EBUSY;\n" - "+\n" - "+ dev->otg_transceiver = get_transceiver ();\n" - "+\n" - "+#if !defined(UDC_HSB1)\t\n" - "+ if (!(transceiver_to_otg(dev->otg_transceiver)->otg_priv))\n" - "+ return -EINVAL;\n" - "+ dev->otg_driver = (struct usb_otg_gadget_extension *)\n" - "+ transceiver_to_otg(dev->otg_transceiver)->otg_priv;\n" - "+#endif\t\n" - "+\n" - "+#ifdef UDC_IPBUG_3943_WORKAROUND\n" - "+ /* init registers here first with suspend bug */\n" - "+ if (!otg_reg_count) {\n" - "+ startup_registers(dev);\n" - "+ otg_reg_count++; \n" - "+ }\n" - "+#endif\n" - "+\n" - "+#ifdef UDC_IPBUG_3950_WORKAROUND\n" - "+ /* set notify function */\n" - "+ dev->otg_driver->notify = otg_notify;\n" - "+#endif\n" - "+ /* if gadget driver already registered */\n" - "+ /* call gadget bind() to switch to mux udc to phy */\n" - "+ if (dev->driver) {\n" - "+\n" - "+ /* otg driver bind() */\n" - "+ retval = dev->otg_transceiver->set_peripheral(\n" - "+ dev->otg_transceiver, &dev->gadget);\n" - "+ if (retval) {\n" - "+ DBG( \"error bind to uoc driver\\n\");\n" - "+#if !defined(UDC_HSB1)\t\n" - "+ dev->otg_driver = NULL;\n" - "+#endif\t\t\t\n" - "+ dev->otg_transceiver = NULL;\n" - "+ return retval;\n" - "+ }\n" - "+ /* get ready for ep0 traffic */\n" - "+ setup_ep0(dev);\n" - "+\n" - "+\t\t/* clear SD */\n" - "+\t\ttmp = readl(&dev->regs->ctl);\n" - "+\t\ttmp = tmp & AMD_CLEAR_BIT(UDC_DEVCTL_SD);\n" - "+\t\twritel(tmp, &dev->regs->ctl);\n" - "+ }\n" - "+\n" - "+ INFO( \"registered uoc driver\\n\");\n" - "+\n" - "+ return 0;\n" - "+}\n" - "+EXPORT_SYMBOL (usb_gadget_register_otg);\n" - "+\n" - "+/**\n" - "+ * Called by OTG driver to unregister itself\n" - "+ * \n" - "+ *\n" - "+ * \\return 0 if success\n" - "+ */\n" - "+int usb_gadget_unregister_otg (void)\n" - "+{\n" - "+ struct udc *dev = udc;\n" - "+ unsigned long flags;\n" - "+ u32 tmp;\n" - "+\n" - "+ if (!dev)\n" - "+ return -ENODEV;\n" - "+\n" - "+ spin_lock_irqsave (&dev->lock, flags);\n" - "+\n" - "+ /* mask not needed interrupts */\n" - "+ udc_mask_unused_interrupts(dev);\n" - "+\n" - "+ spin_unlock_irqrestore (&dev->lock, flags);\n" - "+\n" - "+ dev->otg_supported = 0;\n" - "+ if (dev->otg_transceiver) {\n" - "+ dev->otg_transceiver->set_peripheral(dev->otg_transceiver, NULL);\n" - "+ dev->otg_transceiver = NULL;\n" - "+ }\n" - "+#if !defined(UDC_HSB1)\t\n" - "+ if (dev->otg_driver) {\n" - "+#ifdef UDC_IPBUG_3950_WORKAROUND\n" - "+ dev->otg_driver->notify = NULL;\n" - "+#endif\n" - "+\t\tdev->otg_driver = NULL;\n" - "+ }\n" - "+#endif\t\n" - "+\n" - "+ /* set SD */\n" - "+ tmp = readl(&dev->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_DEVCTL_SD);\n" - "+ writel(tmp, &dev->regs->ctl);\n" - "+\n" - "+ DBG( \"unregistered uoc driver\\n\");\n" - "+ return 0;\n" - "+}\n" - "+EXPORT_SYMBOL (usb_gadget_unregister_otg);\n" - "+\n" - "+/**\n" - "+ * shutdown requests and disconnect from gadget \n" - "+ */\n" - "+static void\n" - "+shutdown(struct udc *dev, struct usb_gadget_driver *driver)\n" - "+{\n" - "+ int tmp;\n" - "+\n" - "+ /* empty queues and init hardware */\n" - "+ udc_basic_init(dev);\n" - "+ for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {\n" - "+ empty_req_queue (&dev->ep [tmp]);\n" - "+ }\n" - "+\n" - "+ if (dev->gadget.speed != USB_SPEED_UNKNOWN) {\n" - "+ spin_unlock (&dev->lock);\n" - "+ driver->disconnect (&dev->gadget);\n" - "+ spin_lock (&dev->lock);\n" - "+ }\n" - "+ /* init */\n" - "+ udc_setup_endpoints (dev);\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Called by gadget driver to unregister itself\n" - "+ *\n" - "+ * \\param driver pointer to gadget driver struct\n" - "+ * \\return 0 if success\n" - "+ */\n" - "+int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)\n" - "+{\n" - "+ struct udc *dev = udc;\n" - "+ unsigned long iflags;\n" - "+ u32 tmp;\n" - "+\n" - "+ if (!dev)\n" - "+ return -ENODEV;\n" - "+ if (!driver || driver != dev->driver)\n" - "+ return -EINVAL;\n" - "+ if (gadget_bind_count) {\n" - "+ spin_lock_irqsave (&dev->lock, iflags);\n" - "+ shutdown(dev, driver);\n" - "+ spin_unlock_irqrestore (&dev->lock, iflags);\n" - "+ }\n" - "+\n" - "+ /* unbind from otg driver first */\n" - "+ if (dev->otg_transceiver) {\n" - "+ dev->otg_transceiver->set_peripheral(\n" - "+ dev->otg_transceiver, NULL);\n" - "+ }\n" - "+\n" - "+ if (gadget_bind_count) {\n" - "+ driver->unbind (&dev->gadget);\n" - "+ }\n" - "+ gadget_bind_count = 0;\n" - "+ dev->driver = 0;\n" - "+\n" - "+ /* set SD */\n" - "+ tmp = readl(&dev->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_DEVCTL_SD);\n" - "+ writel(tmp, &dev->regs->ctl);\n" - "+\n" - "+\n" - "+ DBG( \"%s: unregistered\\n\", driver->driver.name);\n" - "+\n" - "+ return 0;\n" - "+}\n" - "+EXPORT_SYMBOL (usb_gadget_unregister_driver);\n" - "+\n" - "+\n" - "+#ifdef UDC_IPBUG_3958_WORKAROUND\n" - "+/**\n" - "+ * Clear pending NAK bits \n" - "+ *\n" - "+ * \\param dev pointer to UDC device object \n" - "+ * \\return 0 if success\n" - "+ */\n" - "+static void udc_process_cnak_queue(struct udc* dev)\n" - "+{\n" - "+ u32 tmp;\n" - "+ u32 reg;\n" - "+ /* check epin's */\n" - "+ DBG(\"CNAK pending queue processing\\n\");\n" - "+ for (tmp = 0; tmp < UDC_EPIN_NUM_USED; tmp++) {\n" - "+ if (cnak_pending & (1 << tmp)) {\n" - "+ DBG(\"CNAK pending for ep%d\\n\", tmp);\n" - "+ /* clear NAK by writing CNAK */\n" - "+ reg = readl(&dev->ep[tmp].regs->ctl);\n" - "+ reg |= AMD_BIT(UDC_EPCTL_CNAK); \n" - "+ writel(reg, &dev->ep[tmp].regs->ctl);\n" - "+ dev->ep[tmp].naking = 0;\n" - "+ UDC_QUEUE_CNAK(&dev->ep[tmp], dev->ep[tmp].num);\n" - "+ } \n" - "+ }\n" - "+ /* ... and ep0out */\n" - "+ if (cnak_pending & (1 << UDC_EP0OUT_IX)) {\n" - "+ DBG(\"CNAK pending for ep%d\\n\", UDC_EP0OUT_IX);\n" - "+ /* clear NAK by writing CNAK */\n" - "+ reg = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl);\n" - "+ reg |= AMD_BIT(UDC_EPCTL_CNAK); \n" - "+ writel(reg, &dev->ep[UDC_EP0OUT_IX].regs->ctl);\n" - "+ dev->ep[UDC_EP0OUT_IX].naking = 0;\n" - "+ UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX], \n" - "+ dev->ep[UDC_EP0OUT_IX].num);\n" - "+ }\n" - "+}\n" - "+#endif\n" - "+\n" - "+/**\n" - "+ * Enabling RX DMA after setup packet \n" - "+ *\n" - "+ * \\param dev pointer to UDC device object \n" - "+ */\n" - "+static inline void udc_ep0_set_rde(struct udc* dev)\n" - "+{\n" - "+ if (use_dma) {\n" - "+#ifndef UDC_USE_TIMER\n" - "+ udc_set_rde(dev);\n" - "+#else\n" - "+ /* only enable RXDMA when no data endpoint enabled\t\n" - "+ or data is queued */\n" - "+ if (!dev->data_ep_enabled || dev->data_ep_queued) {\n" - "+ udc_set_rde(dev);\n" - "+ }\n" - "+ else {\n" - "+ /* setup timer for enabling RDE (to not enable\n" - "+ RXFIFO DMA for data endpoints to early) */\n" - "+ if (set_rde != 0 && !timer_pending(&udc_timer)) {\n" - "+ udc_timer.expires = jiffies + HZ/UDC_RDE_TIMER_DIV;\n" - "+ set_rde = 1;\n" - "+ if (!stop_timer) {\n" - "+ add_timer(&udc_timer);\n" - "+ }\n" - "+ }\n" - "+ }\n" - "+#endif\n" - "+ }\n" - "+}\n" - "+\n" - "+\n" - "+/**\n" - "+ * Interrupt handler for data OUT traffic \n" - "+ *\n" - "+ * \\param dev pointer to UDC device object \n" - "+ * \\param ep_ix endpoint index \n" - "+ * \\return 0 if success\n" - "+ */\n" - "+static inline int udc_data_out_isr(struct udc* dev, int ep_ix)\n" - "+{\n" - "+ int ret_val = 0;\n" - "+ u32 tmp;\n" - "+ struct udc_ep *ep;\n" - "+ struct udc_request *req;\n" - "+ unsigned int count;\n" - "+ struct udc_data_dma *td = NULL;\n" - "+ unsigned dma_done;\n" - "+\n" - "+ VDBG(\"ep%d irq\\n\", ep_ix); \n" - "+ ep = &dev->ep [ep_ix];\n" - "+\n" - "+ tmp = readl(&ep->regs->sts);\n" - "+ if (use_dma) {\n" - "+ /* BNA event ? */\n" - "+ if (tmp & AMD_BIT(UDC_EPSTS_BNA)) {\n" - "+ ERR(\"BNA ep%dout occured - DESPTR = %lx \\n\", ep->num, (unsigned long) readl(&ep->regs->desptr));\n" - "+ \n" - "+ /* clear BNA */\n" - "+ writel(tmp | AMD_BIT(UDC_EPSTS_BNA), &ep->regs->sts); \n" - "+ return 1; \n" - "+ } \n" - "+ }\n" - "+ /* HE event ? */\n" - "+ if (tmp & AMD_BIT(UDC_EPSTS_HE)) {\n" - "+ ERR(\"HE ep%dout occured\\n\", ep->num);\n" - "+ \n" - "+ /* clear HE */\n" - "+ writel(tmp | AMD_BIT(UDC_EPSTS_HE), &ep->regs->sts); \n" - "+ return 1; \n" - "+ } \n" - "+\n" - "+ if (!list_empty (&ep->queue)) {\n" - "+\n" - "+ /* next request */ \n" - "+ req = list_entry (ep->queue.next,\n" - "+ struct udc_request, queue);\n" - "+ }\n" - "+ else\n" - "+ {\n" - "+ req = 0;\n" - "+#ifdef UDC_DEBUG\n" - "+ no_req++;\n" - "+#endif\n" - "+ udc_rxfifo_pending = 1;\n" - "+ }\n" - "+ VDBG(\"req = %lx\\n\", (unsigned long) req);\n" - "+ /* fifo mode ****************/\n" - "+ if (!use_dma) {\n" - "+\n" - "+ /* read fifo */\n" - "+ if (req && udc_rxfifo_read(ep, req)) {\n" - "+ /* finish */\n" - "+ complete_req (ep, req, 0);\n" - "+ /* next request */\n" - "+ if (!list_empty (&ep->queue) && !ep->halted) {\n" - "+ req = list_entry (ep->queue.next,\n" - "+ struct udc_request, queue);\n" - "+ } \n" - "+ else\n" - "+ req = 0;\n" - "+ }\n" - "+\n" - "+ } /* DMA ********************/\n" - "+ else if (req) {\n" - "+\n" - "+ /* check for DMA done */\n" - "+ if (!use_dma_ppb) {\n" - "+ dma_done = AMD_GETBITS(req->td_data->status, UDC_DMA_OUT_STS_BS); \n" - "+ } /* packet per buffer mode - rx bytes */\n" - "+ else {\n" - "+ td = udc_get_last_dma_desc(req);\n" - "+ dma_done = AMD_GETBITS(td->status, UDC_DMA_OUT_STS_BS); \n" - "+ }\n" - "+ if (dma_done == UDC_DMA_OUT_STS_BS_DMA_DONE) {\n" - "+ /* buffer fill mode - rx bytes */\n" - "+ if (!use_dma_ppb) {\n" - "+ /* received number bytes */\n" - "+ count = AMD_GETBITS(req->td_data->status, UDC_DMA_OUT_STS_RXBYTES); \n" - "+ VDBG(\"rx bytes=%lx\\n\", (unsigned long) count);\n" - "+ } /* packet per buffer mode - rx bytes */\n" - "+ else {\n" - "+ VDBG(\"req->td_data=%lx\\n\", (unsigned long) req->td_data);\n" - "+ VDBG(\"last desc = %lx\\n\", (unsigned long) td);\n" - "+ /* received number bytes */\n" - "+ if (use_dma_ppb_du) {\n" - "+ /* every desc. counts bytes */\n" - "+ count = udc_get_ppbdu_rxbytes(req);\n" - "+ }\n" - "+ else {\n" - "+ /* last desc. counts bytes */\n" - "+ count = AMD_GETBITS(td->status, UDC_DMA_OUT_STS_RXBYTES);\n" - "+ if (!count) {\n" - "+ /* on 64k packets the RXBYTES field is zero */\n" - "+ if (req->req.length == UDC_DMA_MAXPACKET)\n" - "+ count = UDC_DMA_MAXPACKET; \n" - "+ }\n" - "+ }\n" - "+ VDBG(\"last desc rx bytes=%lx\\n\", (unsigned long) count);\n" - "+ }\n" - "+\n" - "+ tmp = req->req.length - req->req.actual;\n" - "+ if (count > tmp) {\n" - "+ if ((tmp % ep->ep.maxpacket) != 0) {\n" - "+ ERR( \"%s: received %d bytes, rx-buffer space = %d bytes => buffer overrun\\n\",\n" - "+ ep->ep.name, count, tmp);\n" - "+ req->req.status = -EOVERFLOW;\n" - "+ }\n" - "+ count = tmp;\n" - "+ }\n" - "+ req->req.actual += count;\n" - "+\n" - "+ /* complete request */ \n" - "+ complete_req(ep, req, 0);\n" - "+ \n" - "+ /* next request */\n" - "+ if (!list_empty (&ep->queue) && !ep->halted) {\n" - "+ req = list_entry(ep->queue.next,\n" - "+ struct udc_request,\n" - "+ queue);\n" - "+\n" - "+ /* next dma */\n" - "+ ret_val = prep_dma(ep, req);\n" - "+ if (ret_val != 0)\n" - "+ goto finished;\n" - "+ /* write desc pointer */\n" - "+ writel(req->td_phys, &ep->regs->desptr);\n" - "+\n" - "+ /* enable DMA */\n" - "+ udc_set_rde(dev);\n" - "+ } \n" - "+ else {\n" - "+#ifdef UDC_DEBUG\n" - "+ no_pref_req++;\n" - "+ VDBG(\"OUT queue empty\\n\");\n" - "+#endif\n" - "+ /* schedule timer for setting RDE if queue remains empty\n" - "+ * to allow ep0 packets pass through */\n" - "+#ifdef UDC_USE_TIMER\n" - "+ if (set_rde != 0 && !timer_pending(&udc_timer)) {\n" - "+ udc_timer.expires = jiffies + HZ*UDC_RDE_TIMER_SECONDS;\n" - "+ set_rde = 1;\n" - "+ if (!stop_timer) {\n" - "+ add_timer(&udc_timer);\n" - "+ }\n" - "+ }\n" - "+#endif\n" - "+ if (ep->num != UDC_EP0OUT_IX) \n" - "+ dev->data_ep_queued = 0;\n" - "+ }\n" - "+\n" - "+ } \n" - "+ else {\n" - "+ /* RX DMA must be reenabled for each desc in PPBDU mode */\n" - "+ if (use_dma_ppb_du) {\n" - "+ udc_set_rde(dev);\n" - "+ }\n" - "+ } \n" - "+ \n" - "+ }\n" - "+\n" - "+#ifdef UDC_IPBUG_3958_WORKAROUND\n" - "+ /* check pending CNAKS */\n" - "+ if (cnak_pending) {\n" - "+ /* CNAk processing when rxfifo empty only */\n" - "+ if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) {\n" - "+ udc_process_cnak_queue(dev);\n" - "+ }\n" - "+ }\n" - "+#endif \n" - "+\n" - "+ /* clear OUT bits in ep status */\n" - "+ writel(UDC_EPSTS_OUT_DATA_CLEAR, &ep->regs->sts);\n" - "+finished:\n" - "+ return ret_val;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Interrupt handler for data IN traffic \n" - "+ *\n" - "+ * \\param dev pointer to UDC device object \n" - "+ * \\param ep_ix endpoint index \n" - "+ * \\return 0 if success\n" - "+ */\n" - "+static inline int udc_data_in_isr(struct udc* dev, int ep_ix)\n" - "+{\n" - "+ int ret_val = 0;\n" - "+ u32 tmp;\n" - "+ u32 epsts;\n" - "+ struct udc_ep *ep;\n" - "+ struct udc_request *req;\n" - "+ struct udc_data_dma *td;\n" - "+ unsigned dma_done;\n" - "+ unsigned len;\n" - "+\n" - "+ ep = &dev->ep[ep_ix];\n" - "+ \n" - "+ epsts = readl(&ep->regs->sts);\n" - "+ if (use_dma) {\n" - "+ /* BNA ? */\n" - "+ if (epsts & AMD_BIT(UDC_EPSTS_BNA)) {\n" - "+ ERR(\"BNA ep%din occured - DESPTR = %08lx \\n\",\n" - "+ ep->num, (unsigned long) readl(&ep->regs->desptr));\n" - "+ \n" - "+ /* clear BNA */\n" - "+ writel(epsts, &ep->regs->sts); \n" - "+\n" - "+ return 1; \n" - "+ } \n" - "+ }\n" - "+ /* HE event ? */\n" - "+ if (epsts & AMD_BIT(UDC_EPSTS_HE)) {\n" - "+ ERR(\"HE ep%dn occured - DESPTR = %08lx \\n\",\n" - "+ ep->num, (unsigned long) readl(&ep->regs->desptr));\n" - "+ \n" - "+ /* clear HE */\n" - "+ writel(epsts | AMD_BIT(UDC_EPSTS_HE), &ep->regs->sts); \n" - "+ return 1; \n" - "+ } \n" - "+\n" - "+ /* DMA completion */\n" - "+ if (epsts & AMD_BIT(UDC_EPSTS_TDC)) {\n" - "+ VDBG(\"TDC set- completion\\n\");\n" - "+ if (!list_empty (&ep->queue)) {\n" - "+ req = list_entry (ep->queue.next,\n" - "+ struct udc_request, queue);\n" - "+ if (req) { \n" - "+ /* lengh bytes transfered */\n" - "+ /* check dma done of last desc. in PPBDU mode */\n" - "+ if (use_dma_ppb_du) {\n" - "+ td = udc_get_last_dma_desc(req);\n" - "+ if (td) {\n" - "+ dma_done = \n" - "+ AMD_GETBITS(td->status, UDC_DMA_IN_STS_BS); \n" - "+ /* don't care DMA done */\n" - "+ /* if (dma_done == UDC_DMA_IN_STS_BS_DMA_DONE) */\n" - "+ req->req.actual = req->req.length;\n" - "+ }\n" - "+ }\n" - "+ else {\n" - "+ /* assume all bytes transferred */\n" - "+ /* TODO check error status */\n" - "+ req->req.actual = req->req.length;\n" - "+ }\n" - "+\n" - "+ if (req->req.actual == req->req.length) { \n" - "+#ifdef UDC_IPBUG_2253_WORKAROUND\n" - "+ /* stop NAKing after small packet DMA */\n" - "+ if (ep->naking) {\n" - "+ /* clear NAK by writing CNAK */\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); \n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+ ep->naking = 0;\n" - "+ UDC_QUEUE_CNAK(ep, ep->num);\n" - "+ }\n" - "+#endif\n" - "+ /* complete req */\n" - "+ complete_req(ep, req, 0);\n" - "+ req->dma_going = 0;\n" - "+#ifdef UDC_DISABLE_IRQ_IF_EMPTY_IN_QUEUE\n" - "+ /* further request available ? */\n" - "+ if (list_empty (&ep->queue)) {\n" - "+ /* disable interrupt */\n" - "+ tmp = readl(&dev->regs->ep_irqmsk);\n" - "+ tmp |= AMD_BIT(ep->num);\n" - "+ writel(tmp, &dev->regs->ep_irqmsk); \n" - "+ } \n" - "+#endif\n" - "+\n" - "+ }\n" - "+ }\n" - "+ }\n" - "+ \n" - "+ } /* status reg has IN bit set and TDC not set (if TDC was handled,\n" - "+ IN must not be handled (UDC defect) ? */\n" - "+ if ((epsts & AMD_BIT(UDC_EPSTS_IN)) && !(epsts & AMD_BIT(UDC_EPSTS_TDC))) {\n" - "+ if (!list_empty (&ep->queue))\n" - "+ {\n" - "+ /* next request */\n" - "+ req = list_entry (ep->queue.next,\n" - "+ struct udc_request, queue);\n" - "+ /* FIFO mode ********/ \n" - "+ if (!use_dma) {\n" - "+ /* write fifo */\n" - "+ udc_txfifo_write(ep, &(req->req));\n" - "+ len = req->req.length - req->req.actual;\n" - "+\t\t\t\tif (len > ep->ep.maxpacket)\n" - "+\t\t\t\t\tlen = ep->ep.maxpacket;\n" - "+\t\t\t\treq->req.actual += len;\n" - "+ if (req->req.actual == req->req.length \n" - "+ || (len != ep->ep.maxpacket)) {\n" - "+ /* && (!req->req.zero || len != ep->ep.maxpacket)) { */\n" - "+ /* complete req */\n" - "+ complete_req (ep, req, 0);\n" - "+ }\n" - "+ } /* DMA *****************/\n" - "+ else if (req && !req->dma_going) { \n" - "+ VDBG(\"IN DMA : req=%lx req->td_data=%lx\\n\",\n" - "+ (unsigned long) req, (unsigned long) req->td_data);\n" - "+ if (req->td_data) {\n" - "+\n" - "+ req->dma_going = 1;\n" - "+\n" - "+ /* unset L bit of first desc. for chain */\n" - "+ if (use_dma_ppb && req->req.length > ep->ep.maxpacket) {\n" - "+ req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L);\n" - "+ }\n" - "+\n" - "+ /* write desc pointer */\n" - "+ writel(req->td_phys, &ep->regs->desptr);\n" - "+\n" - "+ wb_flush(); \n" - "+ /* set HOST READY */\n" - "+ req->td_data->status \n" - "+ = AMD_ADDBITS(req->td_data->status,\n" - "+ UDC_DMA_IN_STS_BS_HOST_READY,\n" - "+ UDC_DMA_IN_STS_BS);\n" - "+\n" - "+ wb_flush();\n" - "+\n" - "+#ifdef UDC_IPBUG_2253_WORKAROUND\n" - "+ /* NAK if small packet until TDC interrupt */\n" - "+ if (req->req.length < UDC_SMALL_PACKET) {\n" - "+ /* set NAK */\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_SNAK); \n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+ ep->naking = 1;\n" - "+ wb_flush();\n" - "+ }\n" - "+#endif\n" - "+ /* set poll demand bit */\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_P);\n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+ }\n" - "+ }\n" - "+\n" - "+ } \n" - "+ }\n" - "+ /* clear status bits */\n" - "+ writel(epsts, &ep->regs->sts);\n" - "+ \n" - "+ return ret_val;\n" - "+ \n" - "+}\n" - "+\n" - "+/**\n" - "+ * Interrupt handler for Control OUT traffic \n" - "+ *\n" - "+ * \\param dev pointer to UDC device object \n" - "+ * \\return 0 if success\n" - "+ */\n" - "+static inline int udc_control_out_isr(struct udc* dev)\n" - "+{\n" - "+ int ret_val = 0;\n" - "+ u32 tmp;\n" - "+ int setup_supported;\n" - "+ u32 count;\n" - "+ int set = 0; \n" - "+ struct udc_ep *ep;\n" - "+ struct udc_ep *ep_tmp;\n" - "+\n" - "+ ep = &dev->ep[UDC_EP0OUT_IX];\n" - "+ \n" - "+ /* clear irq */\n" - "+ writel(AMD_BIT(UDC_EPINT_OUT_EP0), &dev->regs->ep_irqsts);\n" - "+\n" - "+ tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->sts);\n" - "+ /* check BNA and clear if set */\n" - "+ if (tmp & AMD_BIT(UDC_EPSTS_BNA)) {\n" - "+ VDBG(\"BNA set\\n\"); \n" - "+ writel(AMD_BIT(UDC_EPSTS_BNA), &dev->ep[UDC_EP0OUT_IX].regs->sts);\n" - "+ }\n" - "+ \n" - "+ /* type of data: SETUP or DATA 0 bytes */\n" - "+ tmp = AMD_GETBITS(tmp, UDC_EPSTS_OUT);\n" - "+ VDBG( \"data_typ = %lx\\n\", (unsigned long) tmp);\n" - "+ /* setup data */\n" - "+ if (tmp == UDC_EPSTS_OUT_SETUP) {\n" - "+\n" - "+ ep->dev->stall_ep0in = 0;\n" - "+ dev->waiting_zlp_ack_ep0in = 0;\n" - "+\n" - "+ /* set NAK for EP0_IN */\n" - "+ tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_SNAK); \n" - "+ writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);\n" - "+ dev->ep[UDC_EP0IN_IX].naking = 1;\n" - "+ /* get setup data */\n" - "+ if (use_dma) {\n" - "+\n" - "+ /* clear OUT bits in ep status */\n" - "+ writel(UDC_EPSTS_OUT_SETUP_CLEAR, &dev->ep[UDC_EP0OUT_IX].regs->sts);\n" - "+\n" - "+ setup_data.data[0] = dev->ep[UDC_EP0OUT_IX].td_stp->data12;\n" - "+ setup_data.data[1] = dev->ep[UDC_EP0OUT_IX].td_stp->data34;\n" - "+ /* set HOST READY */\n" - "+ writel(UDC_DMA_STP_STS_BS_HOST_READY,\n" - "+ &dev->ep[UDC_EP0OUT_IX].td_stp->status);\n" - "+ }\n" - "+ else {\n" - "+ /* read fifo */\n" - "+ udc_rxfifo_read_dwords(dev, setup_data.data, 2);\n" - "+ }\n" - "+\n" - "+ /* determine direction of control data */\n" - "+ if ((setup_data.request.bRequestType & USB_DIR_IN) != 0) {\n" - "+\t dev->gadget.ep0 = &dev->ep [UDC_EP0IN_IX].ep;\n" - "+ /* enable RDE */\n" - "+ udc_ep0_set_rde(dev);\n" - "+ set = 0;\n" - "+ }\n" - "+ else {\n" - "+\t dev->gadget.ep0 = &dev->ep [UDC_EP0OUT_IX].ep;\n" - "+#ifdef UDC_USE_TIMER\n" - "+ set = 1;\n" - "+ dev->ep[UDC_EP0OUT_IX].naking = 1;\n" - "+ /* setup timer for enabling RDE (to not enable\n" - "+ RXFIFO DMA for data to early) */\n" - "+ set_rde = 1;\n" - "+ if (!timer_pending(&udc_timer)) {\n" - "+ udc_timer.expires = jiffies + HZ/UDC_RDE_TIMER_DIV;\n" - "+ if (!stop_timer) {\n" - "+ add_timer(&udc_timer);\n" - "+ }\n" - "+ }\n" - "+#endif\n" - "+ }\n" - "+ /* mass storage reset must be processed here because\n" - "+ next packet may be a CLEAR_FEATURE HALT which would not\n" - "+ clear the stall bit when no STALL handshale was received before\n" - "+ (autostall can cause this) */\n" - "+ if (setup_data.data[0] == UDC_MSCRES_DWORD0 &&\n" - "+ setup_data.data[1] == UDC_MSCRES_DWORD1) {\n" - "+ DBG(\"MSC Reset\\n\");\n" - "+ /* clear stall bits */\n" - "+ /* only one IN and OUT endpoints are handled */\n" - "+ ep_tmp = &udc->ep [UDC_EPIN_IX];\n" - "+ udc_set_halt (&ep_tmp->ep, 0);\n" - "+ ep_tmp = &udc->ep [UDC_EPOUT_IX];\n" - "+ udc_set_halt (&ep_tmp->ep, 0);\n" - "+ }\n" - "+\n" - "+ /* call gadget with setup data received */\n" - "+ spin_unlock (&dev->lock);\n" - "+ setup_supported = dev->driver->setup (&dev->gadget,\n" - "+ &setup_data.request);\n" - "+ spin_lock (&dev->lock);\n" - "+\n" - "+ tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);\n" - "+ /* ep0 in returns data (not zlp) on IN phase */\n" - "+ if (setup_supported >= 0 && setup_supported < UDC_EP0IN_MAXPACKET) {\n" - "+ /* clear NAK by writing CNAK in EP0_IN */\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); \n" - "+ writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);\n" - "+ dev->ep[UDC_EP0IN_IX].naking = 0;\n" - "+ UDC_QUEUE_CNAK(&dev->ep[UDC_EP0IN_IX], UDC_EP0IN_IX);\n" - "+ }\n" - "+ else if (setup_supported < 0) {\n" - "+ /* if unsupported request then stall */\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_S);\n" - "+ writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);\n" - "+ }\n" - "+ else\n" - "+ dev->waiting_zlp_ack_ep0in = 1;\n" - "+\n" - "+\n" - "+ /* clear NAK by writing CNAK in EP0_OUT */\n" - "+ if (!set) {\n" - "+ tmp = readl(&dev->ep[UDC_EP0OUT_IX].regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); \n" - "+ writel(tmp, &dev->ep[UDC_EP0OUT_IX].regs->ctl);\n" - "+ dev->ep[UDC_EP0OUT_IX].naking = 0;\n" - "+ UDC_QUEUE_CNAK(&dev->ep[UDC_EP0OUT_IX], UDC_EP0OUT_IX);\n" - "+ }\n" - "+ \n" - "+ if (!use_dma) { \n" - "+ /* clear OUT bits in ep status */\n" - "+ writel(UDC_EPSTS_OUT_SETUP_CLEAR, &dev->ep[UDC_EP0OUT_IX].regs->sts);\n" - "+ }\n" - "+\n" - "+ } /* data packet 0 bytes */\n" - "+ else if (tmp == UDC_EPSTS_OUT_DATA) {\n" - "+ /* clear OUT bits in ep status */\n" - "+ writel(UDC_EPSTS_OUT_DATA_CLEAR, &dev->ep[UDC_EP0OUT_IX].regs->sts);\n" - "+ \n" - "+ /* get setup data: only 0 packet */\n" - "+ if (use_dma) {\n" - "+ /* no req if 0 packet, just reactivate */\n" - "+ if (list_empty (&dev->ep[UDC_EP0OUT_IX].queue)) {\n" - "+ VDBG(\"ZLP\\n\");\n" - "+\n" - "+ /* set HOST READY */\n" - "+ dev->ep[UDC_EP0OUT_IX].td->status =\n" - "+ AMD_ADDBITS(dev->ep[UDC_EP0OUT_IX].td->status,\n" - "+ UDC_DMA_OUT_STS_BS_HOST_READY,\n" - "+ UDC_DMA_OUT_STS_BS);\n" - "+ /* enable RDE */\n" - "+ udc_ep0_set_rde(dev);\n" - "+ }\n" - "+ else {\n" - "+ /* control write */\n" - "+ udc_data_out_isr(dev, UDC_EP0OUT_IX);\n" - "+ /* re-program desc. pointer for possible ZLPs */\n" - "+ writel(dev->ep [UDC_EP0OUT_IX].td_phys,\n" - "+ &dev->ep[UDC_EP0OUT_IX].regs->desptr);\n" - "+ /* enable RDE */\n" - "+ udc_ep0_set_rde(dev);\n" - "+ }\n" - "+ }\n" - "+ else {\n" - "+\n" - "+ /* received number bytes */\n" - "+ count = readl(&dev->ep[UDC_EP0OUT_IX].regs->sts);\n" - "+ count = AMD_GETBITS(count, UDC_EPSTS_RX_PKT_SIZE);\n" - "+ /* out data for fifo mode not working */\n" - "+ count = 0;\n" - "+\n" - "+ /* 0 packet or real data ? */\n" - "+ if (count != 0) {\n" - "+ udc_data_out_isr(dev, UDC_EP0OUT_IX);\n" - "+ }\n" - "+ else {\n" - "+ /* dummy read confirm */\n" - "+ readl(&dev->ep[UDC_EP0OUT_IX].regs->confirm);\n" - "+ }\n" - "+ }\n" - "+ }\n" - "+\n" - "+#ifdef UDC_IPBUG_3958_WORKAROUND\n" - "+ /* check pending CNAKS */\n" - "+ if (cnak_pending) {\n" - "+ /* CNAk processing when rxfifo empty only */\n" - "+ if (readl(&dev->regs->sts) & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) {\n" - "+ udc_process_cnak_queue(dev);\n" - "+ }\n" - "+ }\n" - "+#endif \n" - "+ \n" - "+ return ret_val; \n" - "+}\n" - "+\n" - "+/**\n" - "+ * Interrupt handler for Control IN traffic \n" - "+ *\n" - "+ * \\param dev pointer to UDC device object \n" - "+ * \\return 0 if success\n" - "+ */\n" - "+static inline int udc_control_in_isr(struct udc* dev)\n" - "+{\n" - "+ int ret_val = 0;\n" - "+ u32 tmp;\n" - "+ struct udc_ep *ep;\n" - "+ struct udc_request *req;\n" - "+ unsigned len;\n" - "+\n" - "+ ep = &dev->ep [UDC_EP0IN_IX];\n" - "+\n" - "+ /* clear irq */\n" - "+ writel(AMD_BIT(UDC_EPINT_IN_EP0), &dev->regs->ep_irqsts);\n" - "+ \n" - "+ tmp= readl(&dev->ep[UDC_EP0IN_IX].regs->sts);\n" - "+ /* DMA completion */\n" - "+ if (tmp & AMD_BIT(UDC_EPSTS_TDC)) {\n" - "+ VDBG(\"isr: TDC clear \\n\");\n" - "+#ifdef UDC_IPBUG_2253_WORKAROUND\n" - "+ /* stop NAKing after small packet DMA */\n" - "+ if (ep->naking) {\n" - "+ /* clear NAK by writing CNAK */\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_CNAK); \n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+ ep->naking = 0;\n" - "+ UDC_QUEUE_CNAK(ep, ep->num);\n" - "+ }\n" - "+#endif\n" - "+ /* clear TDC bit */\n" - "+ writel(AMD_BIT(UDC_EPSTS_TDC),&dev->ep[UDC_EP0IN_IX].regs->sts);\n" - "+ } /* status reg has IN bit set ? */\n" - "+ else if (tmp & AMD_BIT(UDC_EPSTS_IN)) {\n" - "+ if (ep->dma) {\n" - "+ /* clear IN bit */\n" - "+ writel(AMD_BIT(UDC_EPSTS_IN),&dev->ep[UDC_EP0IN_IX].regs->sts);\n" - "+ }\n" - "+ if (dev->stall_ep0in) {\n" - "+ DBG(\"stall ep0in\\n\");\n" - "+ /* halt ep0in */ \n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_S);\n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+ }\n" - "+ else {\n" - "+ if (!list_empty (&ep->queue))\n" - "+ {\n" - "+ /* next request */\n" - "+ req = list_entry (ep->queue.next,\n" - "+ struct udc_request, queue);\n" - "+\n" - "+ if (ep->dma) {\n" - "+ /* write desc pointer */\n" - "+ writel(req->td_phys, &ep->regs->desptr);\n" - "+ /* set HOST READY */\n" - "+ req->td_data->status \n" - "+ = AMD_ADDBITS(req->td_data->status,\n" - "+ UDC_DMA_STP_STS_BS_HOST_READY,\n" - "+ UDC_DMA_STP_STS_BS);\n" - "+ wb_flush();\n" - "+\n" - "+#ifdef UDC_IPBUG_2253_WORKAROUND\n" - "+ /* NAK if small packet until TDC interrupt */\n" - "+ if (req->req.length < UDC_SMALL_PACKET) {\n" - "+ /* set NAK */\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_SNAK); \n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+ ep->naking = 1;\n" - "+ wb_flush();\n" - "+ }\n" - "+#endif\n" - "+ /* set poll demand bit */\n" - "+ tmp = readl(&dev->ep[UDC_EP0IN_IX].regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_EPCTL_P);\n" - "+ writel(tmp, &dev->ep[UDC_EP0IN_IX].regs->ctl);\n" - "+\n" - "+ /* all bytes will be transferred */\n" - "+ req->req.actual = req->req.length;\n" - "+\n" - "+ /* complete req */\n" - "+ complete_req(ep, req, 0);\n" - "+\n" - "+ }\n" - "+ else {\n" - "+ /* write fifo */\n" - "+ udc_txfifo_write(ep, &(req->req));\n" - "+\n" - "+ /* lengh bytes transfered */\n" - "+ len = req->req.length - req->req.actual;\n" - "+ if (len > ep->ep.maxpacket)\n" - "+ len = ep->ep.maxpacket;\n" - "+\n" - "+ req->req.actual += len;\n" - "+ if (req->req.actual == req->req.length\n" - "+ || (len != ep->ep.maxpacket)) {\n" - "+ /* && (!req->req.zero || len != ep->ep.maxpacket)) { */\n" - "+ /* complete req */\n" - "+ complete_req(ep, req, 0);\n" - "+ }\n" - "+ }\n" - "+\n" - "+ }\n" - "+ } \n" - "+ ep->halted = 0;\n" - "+ dev->stall_ep0in = 0;\n" - "+ if (!ep->dma) {\n" - "+ /* clear IN bit */\n" - "+ writel(AMD_BIT(UDC_EPSTS_IN),&dev->ep[UDC_EP0IN_IX].regs->sts);\n" - "+ }\n" - "+ }\n" - "+\n" - "+ return ret_val;\n" - "+}\n" - "+\n" - "+\n" - "+/**\n" - "+ * Interrupt handler for global device events \n" - "+ *\n" - "+ * \\param dev pointer to UDC device object \n" - "+ * \\param dev_irq device interrupt bit of DEVINT register \n" - "+ * \\return 0 if success\n" - "+ */\n" - "+static inline int udc_dev_isr(struct udc* dev, u32 dev_irq)\n" - "+{\n" - "+ int ret_val = 0;\n" - "+ u32 tmp;\n" - "+ u32 cfg;\n" - "+ struct udc_ep *ep;\n" - "+ u16 i;\n" - "+ u8 udc_csr_epix;\n" - "+\n" - "+ /* SET_CONFIG irq ? */\n" - "+ if (dev_irq & AMD_BIT(UDC_DEVINT_SC)) {\n" - "+\n" - "+ /* read config value */\n" - "+ tmp = readl(&dev->regs->sts);\n" - "+ cfg = AMD_GETBITS(tmp, UDC_DEVSTS_CFG);\n" - "+#ifdef UDC_DEBUG\n" - "+ /* this is needed for debug only */\n" - "+ if (cfg == dev->cur_config) {\n" - "+ same_cfg = 1;\n" - "+ }\n" - "+ else {\n" - "+ same_cfg = 0;\n" - "+ }\n" - "+ VDBG(\"same_cfg=%d\\n\", same_cfg);\n" - "+#endif\n" - "+ DBG(\"SET_CONFIG interrupt: config=%d\\n\", cfg);\n" - "+ dev->cur_config = cfg;\n" - "+ dev->set_cfg_not_acked = 1;\n" - "+\n" - "+ /* make usb request for gadget driver */\n" - "+ memset(&setup_data, 0 , sizeof(union udc_setup_data));\n" - "+ setup_data.request.bRequest = USB_REQ_SET_CONFIGURATION;\n" - "+ setup_data.request.wValue = dev->cur_config;\n" - "+\n" - "+ /* programm the NE registers */\n" - "+ /* TODO - put this to extra function or use udc_setup_endpoints() or udc_enable() */\n" - "+ for (i = 0; i < UDC_EP_NUM; i++) {\n" - "+ ep = &dev->ep[i];\n" - "+ if (ep->in) {\n" - "+ \n" - "+ /* ep ix in UDC CSR register space */\n" - "+ udc_csr_epix = ep->num;\n" - "+\n" - "+ \n" - "+ } /* OUT ep */\n" - "+ else {\n" - "+ /* ep ix in UDC CSR register space */\n" - "+ udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS;\n" - "+ }\n" - "+\n" - "+ tmp = readl(&dev->csr->ne[udc_csr_epix]);\n" - "+ /* ep cfg */\n" - "+ tmp = AMD_ADDBITS(tmp, ep->dev->cur_config, UDC_CSR_NE_CFG);\n" - "+ /* write reg */\n" - "+ writel(tmp, &dev->csr->ne[udc_csr_epix]);\n" - "+\n" - "+ /* clear stall bits */\n" - "+ ep->halted = 0;\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ tmp = tmp & AMD_CLEAR_BIT(UDC_EPCTL_S);\n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+ }\n" - "+ /* call gadget zero with setup data received */\n" - "+ spin_unlock (&dev->lock);\n" - "+ tmp = dev->driver->setup (&dev->gadget, &setup_data.request);\n" - "+ spin_lock (&dev->lock);\n" - "+\n" - "+ } /* SET_INTERFACE ? */\n" - "+ if (dev_irq & AMD_BIT(UDC_DEVINT_SI)) {\n" - "+ dev->set_cfg_not_acked = 1;\n" - "+ /* read interface and alt setting values */\n" - "+ tmp = readl(&dev->regs->sts);\n" - "+ dev->cur_alt = AMD_GETBITS(tmp, UDC_DEVSTS_ALT);\n" - "+ dev->cur_intf = AMD_GETBITS(tmp, UDC_DEVSTS_INTF);\n" - "+ \n" - "+ /* make usb request for gadget driver */\n" - "+ memset(&setup_data, 0 , sizeof(union udc_setup_data));\n" - "+ setup_data.request.bRequest = USB_REQ_SET_INTERFACE;\n" - "+ setup_data.request.bRequestType = USB_RECIP_INTERFACE;\n" - "+ setup_data.request.wValue = dev->cur_alt;\n" - "+ setup_data.request.wIndex = dev->cur_intf;\n" - "+ \n" - "+ DBG(\"SET_INTERFACE interrupt: alt=%d intf=%d\\n\", dev->cur_alt, dev->cur_intf);\n" - "+\n" - "+ /* programm the NE registers */\n" - "+ /* TODO - put this to extra function or use udc_setup_endpoints() or udc_enable() */\n" - "+ for (i = 0; i < UDC_EP_NUM; i++) {\n" - "+ ep = &dev->ep[i];\n" - "+ if (ep->in) {\n" - "+ \n" - "+ /* ep ix in UDC CSR register space */\n" - "+ udc_csr_epix = ep->num;\n" - "+\n" - "+ \n" - "+ } /* OUT ep */\n" - "+ else {\n" - "+ /* ep ix in UDC CSR register space */\n" - "+ udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS;\n" - "+ }\n" - "+\n" - "+ /***** UDC CSR reg ****************************/\n" - "+ /* set ep values */\n" - "+ tmp = readl(&dev->csr->ne[udc_csr_epix]);\n" - "+ /* ep interface */\n" - "+ tmp = AMD_ADDBITS(tmp, ep->dev->cur_intf, UDC_CSR_NE_INTF);\n" - "+ /* tmp = AMD_ADDBITS(tmp, 2, UDC_CSR_NE_INTF); */\n" - "+ /* ep alt */\n" - "+ tmp = AMD_ADDBITS(tmp, ep->dev->cur_alt, UDC_CSR_NE_ALT);\n" - "+ /* tmp = AMD_ADDBITS(tmp, 1, UDC_CSR_NE_ALT); */\n" - "+ /* write reg */\n" - "+ writel(tmp, &dev->csr->ne[udc_csr_epix]);\n" - "+\n" - "+ /* clear stall bits */\n" - "+ ep->halted = 0;\n" - "+ tmp = readl(&ep->regs->ctl);\n" - "+ tmp = tmp & AMD_CLEAR_BIT(UDC_EPCTL_S);\n" - "+ writel(tmp, &ep->regs->ctl);\n" - "+ }\n" - "+\n" - "+ /* call gadget zero with setup data received */\n" - "+ spin_unlock (&dev->lock);\n" - "+ tmp = dev->driver->setup (&dev->gadget, &setup_data.request);\n" - "+ spin_lock (&dev->lock);\n" - "+\n" - "+ } /* USB reset */\n" - "+ if (dev_irq & AMD_BIT(UDC_DEVINT_UR)) {\n" - "+ DBG(\"USB Reset interrupt\\n\");\n" - "+\n" - "+ /* allow soft reset when suspend occurs */\n" - "+ soft_reset_occured = 0;\n" - "+\n" - "+ dev->waiting_zlp_ack_ep0in = 0;\n" - "+ dev->set_cfg_not_acked = 0;\n" - "+\n" - "+ /* mask not needed interrupts */\n" - "+ udc_mask_unused_interrupts(dev);\n" - "+\n" - "+ /* call gadget to reset configs etc. */\n" - "+ spin_unlock(&dev->lock);\n" - "+ dev->driver->disconnect(&dev->gadget);\n" - "+ spin_lock(&dev->lock);\n" - "+\n" - "+ /* disable ep0 to empty req queue */\n" - "+ empty_req_queue (&dev->ep [UDC_EP0IN_IX]);\n" - "+ ep_init(dev->regs,\n" - "+ &dev->ep [UDC_EP0IN_IX]);\n" - "+\n" - "+#ifdef UDC_IPBUG_3958_WORKAROUND_SOFT_RESET_ON_USBRESET\n" - "+ /* soft reset when rxfifo not empty */\n" - "+ tmp = readl(&dev->regs->sts);\n" - "+ if (!(tmp & AMD_BIT(UDC_DEVSTS_RXFIFO_EMPTY)) && \n" - "+ !soft_reset_after_usbreset_occured) {\n" - "+ udc_soft_reset(dev);\n" - "+ soft_reset_after_usbreset_occured++;\n" - "+ } \n" - "+#endif\n" - "+\n" - "+ /* DMA reset to kill potential old DMA hw hang, */\n" - "+ /* POLL bit is already reset by ep_init() through */\n" - "+ /* disconnect() */\n" - "+ UDC_DMARST(tmp,dev);\n" - "+ \n" - "+ /* put into initial config */\n" - "+ udc_basic_init (dev);\n" - "+\n" - "+ /* enable device setup interrupts */\n" - "+ udc_enable_dev_setup_interrupts(dev);\n" - "+\n" - "+ } /* USB suspend */\n" - "+#ifndef UDC_IPBUG_3943_WORKAROUND\n" - "+ if (dev_irq & AMD_BIT(UDC_DEVINT_US)) {\n" - "+ DBG(\"USB Suspend interrupt\\n\");\n" - "+\n" - "+ } /* new speed ? */\n" - "+#endif\n" - "+ if (dev_irq & AMD_BIT(UDC_DEVINT_ENUM)) {\n" - "+ DBG(\"ENUM interrupt\\n\");\n" - "+#ifdef UDC_DEBUG\n" - "+ num_enums++;\n" - "+ DBG(\"%d enumerations !\\n\", num_enums);\n" - "+#endif\n" - "+ soft_reset_after_usbreset_occured = 0;\n" - "+\n" - "+ /* disable ep0 to empty req queue */\n" - "+ empty_req_queue (&dev->ep [UDC_EP0IN_IX]);\n" - "+ ep_init (dev->regs,\n" - "+ &dev->ep [UDC_EP0IN_IX]);\n" - "+\n" - "+ /* link up all endpoints */\n" - "+ udc_setup_endpoints (dev);\n" - "+ if (dev->gadget.speed == USB_SPEED_HIGH) {\n" - "+ INFO(\"Connect: Speed = HIGH_SPEED\\n\");\n" - "+ }\n" - "+ else if (dev->gadget.speed == USB_SPEED_FULL) {\n" - "+ INFO(\"Connect: Speed = FULL_SPEED\\n\");\n" - "+ }\n" - "+\n" - "+ /* init ep 0 */\n" - "+ activate_control_endpoints(dev);\n" - "+\n" - "+ /* enable ep0 interrupts */\n" - "+ udc_enable_ep0_interrupts(dev);\n" - "+ }\n" - "+#ifndef UDC_IPBUG_3950_WORKAROUND \n" - "+ /* session valid change interrupt */\n" - "+ if (dev_irq & AMD_BIT(UDC_DEVINT_SVC)) {\n" - "+ DBG(\"USB SVC interrupt\\n\");\n" - "+\n" - "+ /* check that session is not valid to detect disconnect */\n" - "+ tmp = readl(&dev->regs->sts);\n" - "+ if (!(tmp & AMD_BIT(UDC_DEVSTS_SESSVLD))) {\n" - "+ DBG(\"USB Disconnect (session valid low)\\n\");\n" - "+ /* cleanup on disconnect */\n" - "+ usb_disconnect(udc);\n" - "+ }\n" - "+\n" - "+ }\n" - "+#endif\n" - "+\n" - "+ return ret_val;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Interrupt Service Routine, see Linux Kernel Doc for parameters \n" - "+ *\n" - "+ * \\param irq irq number\n" - "+ * \\param pdev pointer to device object\n" - "+ * \\param ptregs don't used\n" - "+ */\n" - "+static irqreturn_t udc_irq (int irq, void *pdev, struct pt_regs * ptregs)\n" - "+{\n" - "+ struct udc *dev = pdev;\n" - "+ u32 reg;\n" - "+ u16 i;\n" - "+ u32 ep_irq;\n" - "+\n" - "+\n" - "+#ifdef UDC_IPBUG_3943_WORKAROUND\n" - "+ /* If UDC is suspended, then don't touch any register, otherwise\n" - "+ system hangs in endless retry => possibly hang !!! */\n" - "+ if (dev->otg_driver && dev->otg_driver->query) {\n" - "+ if (dev->otg_driver->query(0) & OTG_FLAGS_UDC_SUSP) {\n" - "+ return IRQ_HANDLED;\n" - "+ } \n" - "+ }\n" - "+ else\n" - "+ return IRQ_HANDLED;\n" - "+#endif \n" - "+ \n" - "+ if (dev->sys_suspended)\n" - "+ return IRQ_HANDLED;\n" - "+\n" - "+ spin_lock (&dev->lock);\n" - "+\n" - "+\n" - "+ /* check for ep irq */\n" - "+ reg = readl(&dev->regs->ep_irqsts);\n" - "+ if (reg)\n" - "+ {\n" - "+ /* EP0 OUT */\n" - "+ if (reg & AMD_BIT(UDC_EPINT_OUT_EP0))\n" - "+ {\n" - "+ udc_control_out_isr(dev);\n" - "+ } /* EP0 IN */\n" - "+ if (reg & AMD_BIT(UDC_EPINT_IN_EP0)) {\n" - "+ udc_control_in_isr(dev);\n" - "+ \n" - "+ } \n" - "+\n" - "+ /* data endpoint */\n" - "+ /* iterate ep's */\n" - "+ for (i = 1; i < UDC_EP_NUM; i++) {\n" - "+ ep_irq = 1 << i;\n" - "+ /* irq for out ep ? */\n" - "+ if ((reg & ep_irq) && i > UDC_EPIN_NUM) { \n" - "+ /* clear irq */\n" - "+ writel(ep_irq, &dev->regs->ep_irqsts);\n" - "+ udc_data_out_isr(dev,i);\n" - "+ } /* irq for in ep ? */\n" - "+ if ((reg & ep_irq) && i < UDC_EPIN_NUM && i > 0) { \n" - "+ /* clear irq */\n" - "+ writel(ep_irq, &dev->regs->ep_irqsts);\n" - "+ udc_data_in_isr(dev,i);\n" - "+ }\n" - "+ \n" - "+ }\n" - "+ \n" - "+ }\n" - "+\n" - "+\n" - "+ /* check for dev irq */\n" - "+ reg = readl(&dev->regs->irqsts);\n" - "+ if (reg) {\n" - "+ /* clear irq */\n" - "+ writel(reg, &dev->regs->irqsts);\n" - "+ udc_dev_isr(dev, reg);\n" - "+ }\n" - "+ \n" - "+\n" - "+ spin_unlock (&dev->lock);\n" - "+ return IRQ_HANDLED;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Tears down device \n" - "+ *\n" - "+ * \\param pdev pointer to device struct\n" - "+ */\n" - "+static void gadget_release (struct device *pdev)\n" - "+{\n" - "+ struct au1200udc *dev = dev_get_drvdata(pdev);\n" - "+ kfree (dev);\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Cleanup on device remove\n" - "+ *\n" - "+ * \\param dev pointer to udc struct\n" - "+ */\n" - "+static void udc_remove(struct udc* dev)\n" - "+{\n" - "+#ifdef CONFIG_SOC_AU1200 \n" - "+ {\n" - "+ u32 tmp;\n" - "+ /* disable UDC memory, DMA and clock */\n" - "+ tmp = readl((u32*) (USB_MSR_BASE + USB_MSR_MCFG));\n" - "+ tmp &= AMD_CLEAR_BIT(USBMSRMCFG_DMEMEN)\n" - "+ & AMD_CLEAR_BIT(USBMSRMCFG_DBMEN) \n" - "+ & AMD_CLEAR_BIT(USBMSRMCFG_UDCCLKEN);\n" - "+ writel(tmp, USB_MSR_BASE + USB_MSR_MCFG); \n" - "+ }\n" - "+#endif\n" - "+\n" - "+#if defined(CONFIG_SOC_AU1200)\n" - "+ /* done by gadget.dev.release() in kernel 2.6.x \n" - "+ * TMP26: device registration currently disabled for Au1200 */\n" - "+ kfree (dev);\n" - "+#endif\n" - "+#ifdef UDC_USE_TIMER\n" - "+ /* remove timer */\n" - "+ stop_timer++;\n" - "+ if (timer_pending(&udc_timer))\n" - "+ wait_for_completion(&on_exit);\n" - "+\tif (udc_timer.data)\n" - "+\t\tdel_timer_sync(&udc_timer);\n" - "+ /* remove pollstall timer */\n" - "+ stop_pollstall_timer++;\n" - "+ if (timer_pending(&udc_pollstall_timer))\n" - "+ wait_for_completion(&on_pollstall_exit);\n" - "+\tif (udc_pollstall_timer.data)\n" - "+\t\tdel_timer_sync(&udc_pollstall_timer);\n" - "+#endif\n" - "+ udc = 0;\n" - "+}\n" - "+\n" - "+#if defined(CONFIG_SOC_AU1200)\n" - "+/**\n" - "+ * Reset all context\n" - "+ *\n" - "+ * \\param pdev pointer to device struct\n" - "+ */\n" - "+static void udc_drv_remove (struct device *_dev)\n" - "+{\n" - "+\tstruct platform_device *pdev = to_platform_device(_dev);\n" - "+\tstruct udc *dev = dev_get_drvdata (_dev);\n" - "+\n" - "+#ifdef UDC_DEBUG\n" - "+ /* debug */\n" - "+ print_misc(dev);\n" - "+#endif\n" - "+ /* gadget driver registered ? */\n" - "+ if (dev->driver) {\n" - "+ WARN( \"unregistering %s on driver remove\\n\", dev->driver->driver.name);\n" - "+ usb_gadget_unregister_driver (dev->driver);\n" - "+ }\n" - "+ /* otg driver registered ? */\n" - "+ if (dev->otg_transceiver) {\n" - "+ /* should have been done already by driver model core */\n" - "+ WARN( \"uoc driver is still registered\\n\");\n" - "+ }\n" - "+ /* dma pool cleanup */\n" - "+ if (dev->data_requests) {\n" - "+ dma_pool_destroy (dev->data_requests);\n" - "+ }\n" - "+ if (dev->stp_requests) {\n" - "+ /* cleanup DMA desc's for ep0in */\n" - "+ dma_pool_free (dev->stp_requests,\n" - "+ dev->ep [UDC_EP0OUT_IX].td_stp,\n" - "+ dev->ep [UDC_EP0OUT_IX].td_stp_dma);\n" - "+ dma_pool_free (dev->stp_requests,\n" - "+ dev->ep [UDC_EP0OUT_IX].td,\n" - "+ dev->ep [UDC_EP0OUT_IX].td_phys);\n" - "+\n" - "+ dma_pool_destroy (dev->stp_requests);\n" - "+ }\n" - "+\n" - "+ /* init controller by soft reset */\n" - "+ writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);\n" - "+\n" - "+ if (dev->irq_registered)\n" - "+ free_irq (pdev->resource[1].start, dev);\n" - "+ if (dev->regs)\n" - "+ iounmap (dev->regs);\n" - "+ if (dev->mem_region)\n" - "+ release_mem_region (pdev->resource[0].start,\n" - "+ pdev->resource[0].end + 1\n" - "+ - pdev->resource[0].start);\n" - "+\n" - "+ device_unregister (&dev->gadget.dev);\n" - "+ /* device_remove_file (&pdev->dev, &dev_attr_registers); */\n" - "+ dev_set_drvdata (_dev, 0);\n" - "+\n" - "+ udc_remove(dev);\n" - "+}\n" - "+#endif\n" - "+\n" - "+#if !defined(CONFIG_SOC_AU1200)\n" - "+/**\n" - "+ * Reset all pci context\n" - "+ *\n" - "+ * \\param pdev pointer to pci device struct\n" - "+ */\n" - "+static void udc_pci_remove (struct pci_dev *pdev)\n" - "+{\n" - "+ struct udc *dev;\n" - "+\n" - "+ dev = pci_get_drvdata(pdev);\n" - "+#ifdef UDC_DEBUG\n" - "+ /* debug */\n" - "+ print_misc(dev);\n" - "+#endif\n" - "+ /* gadget driver registered ? */\n" - "+ if (dev->driver) {\n" - "+ WARN( \"unregistering %s on pci remove\\n\", dev->driver->driver.name);\n" - "+ usb_gadget_unregister_driver (dev->driver);\n" - "+ }\n" - "+ /* otg driver registered ? */\n" - "+ if (dev->otg_transceiver) {\n" - "+ /* should have been done already by driver model core */\n" - "+ WARN( \"uoc driver is still registered\\n\");\n" - "+ }\n" - "+ /* dma pool cleanup */\n" - "+ if (dev->data_requests) {\n" - "+ dma_pool_destroy (dev->data_requests);\n" - "+ }\n" - "+ if (dev->stp_requests) {\n" - "+ /* cleanup DMA desc's for ep0in */\n" - "+ dma_pool_free (dev->stp_requests,\n" - "+ dev->ep [UDC_EP0OUT_IX].td_stp,\n" - "+ dev->ep [UDC_EP0OUT_IX].td_stp_dma);\n" - "+ dma_pool_free (dev->stp_requests,\n" - "+ dev->ep [UDC_EP0OUT_IX].td,\n" - "+ dev->ep [UDC_EP0OUT_IX].td_phys);\n" - "+\n" - "+ dma_pool_destroy (dev->stp_requests);\n" - "+ }\n" - "+\n" - "+ /* init controller by soft reset */\n" - "+ writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);\n" - "+ if (dev->irq_registered)\n" - "+ free_irq (pdev->irq, dev);\n" - "+ if (dev->regs)\n" - "+ iounmap (dev->regs);\n" - "+ if (dev->mem_region)\n" - "+ release_mem_region (pci_resource_start (pdev, 0),\n" - "+ pci_resource_len (pdev, 0));\n" - "+#ifndef USE_AU1200_PCI_DUMMY\n" - "+ if (dev->active)\n" - "+ pci_disable_device (pdev);\n" - "+#endif\n" - "+\n" - "+ /* device file system not working for Au1200 */\n" - "+ device_unregister (&dev->gadget.dev);\n" - "+ /* device_remove_file (&pdev->dev, &dev_attr_registers); */\n" - "+ pci_set_drvdata (pdev,0);\n" - "+\n" - "+ udc_remove(dev);\n" - "+}\n" - "+#endif\n" - "+\n" - "+/**\n" - "+ * create dma pools on init \n" - "+ *\n" - "+ * \\param dev pointer to udc device struct\n" - "+ * \\return 0 if success\n" - "+ */\n" - "+__init static int init_dma_pools(struct udc* dev)\n" - "+{\n" - "+ struct udc_stp_dma *td_stp;\n" - "+ struct udc_data_dma *td_data;\n" - "+ int retval;\n" - "+\n" - "+ /* consistent DMA mode setting ? */\n" - "+ if (use_dma_ppb) {\n" - "+ use_dma_bufferfill_mode = 0;\n" - "+ }\n" - "+ else {\n" - "+ use_dma_ppb_du = 0;\n" - "+ use_dma_bufferfill_mode = 1;\n" - "+ }\n" - "+\n" - "+ /* DMA setup */\n" - "+ dev->data_requests = dma_pool_create (\"data_requests\", NULL,\n" - "+ sizeof (struct udc_data_dma),\n" - "+ UDC_PCIPOOL_ALIGN,\n" - "+ UDC_PCIPOOL_CROSS);\n" - "+ if (!dev->data_requests) {\n" - "+ DBG( \"can't get request data pool\\n\");\n" - "+ retval = -ENOMEM;\n" - "+ goto finished;\n" - "+ }\n" - "+\n" - "+ /* EP0 in dma regs = dev control regs */ \n" - "+ dev->ep[UDC_EP0IN_IX].dma = &dev->regs->ctl; \n" - "+\n" - "+ /* dma desc for setup data */\n" - "+ dev->stp_requests = dma_pool_create (\"setup requests\", NULL,\n" - "+ sizeof (struct udc_stp_dma),\n" - "+ UDC_PCIPOOL_ALIGN,\n" - "+ UDC_PCIPOOL_CROSS);\n" - "+ if (!dev->stp_requests) {\n" - "+ DBG( \"can't get stp request pool\\n\");\n" - "+ retval = -ENOMEM;\n" - "+ goto finished;\n" - "+ }\n" - "+ /* setup */\n" - "+ td_stp = dma_pool_alloc (dev->stp_requests, UDC_PCIPOOL_GFP_STP,\n" - "+ &dev->ep [UDC_EP0OUT_IX].td_stp_dma);\n" - "+ if (td_stp == NULL){\n" - "+ retval = -ENOMEM;\n" - "+ goto finished;\n" - "+ }\n" - "+ dev->ep [UDC_EP0OUT_IX].td_stp = td_stp;\n" - "+ /* data: 0 packets !? */\n" - "+ td_data = dma_pool_alloc (dev->stp_requests, UDC_PCIPOOL_GFP_STP,\n" - "+ &dev->ep [UDC_EP0OUT_IX].td_phys);\n" - "+ if (td_data == NULL){\n" - "+ retval = -ENOMEM;\n" - "+ goto finished;\n" - "+ }\n" - "+ dev->ep [UDC_EP0OUT_IX].td = td_data;\n" - "+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND\n" - "+ /* point to itself */\n" - "+ dev->ep [UDC_EP0OUT_IX].td->next = dev->ep [UDC_EP0OUT_IX].td_phys;\n" - "+#endif\n" - "+ return 0;\n" - "+\n" - "+finished:\n" - "+ return retval;\n" - "+}\n" - "+\n" - "+#if defined(CONFIG_SOC_AU1200)\n" - "+/**\n" - "+ * Called by kernel init device context\n" - "+ *\n" - "+ * \\param dev pointer to device struct\n" - "+ * \\return 0 if success\n" - "+ */\n" - "+static int udc_drv_probe (struct device* _dev)\n" - "+{\n" - "+ char tmp[8];\n" - "+ struct udc *dev;\n" - "+\tstruct platform_device *pdev = to_platform_device(_dev);\n" - "+\tu32 resource;\n" - "+ u32 len;\n" - "+ u32 irq;\n" - "+ int retval = 0;\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+ u32 reg;\n" - "+\n" - "+ /* basic init */\n" - "+ reg = readl((u32*) (USB_MSR_BASE + USB_MSR_MCFG));\n" - "+ if (reg == 0) {\n" - "+ /* default value */\n" - "+ reg = USBMSRMCFG_DEFAULT; \n" - "+ writel(reg, USB_MSR_BASE + USB_MSR_MCFG); \n" - "+ readl((u32*) USB_MSR_BASE + USB_MSR_MCFG); \n" - "+ udelay(1000);\n" - "+ }\n" - "+ /* enable UDC memory, DMA, clock, cacheable memory,\n" - "+ * read combining and prefetch enable */\n" - "+ reg |= AMD_BIT(USBMSRMCFG_DMEMEN) | AMD_BIT(USBMSRMCFG_DBMEN)\n" - "+ | AMD_BIT(USBMSRMCFG_UDCCLKEN)\n" - "+ | AMD_BIT(USBMSRMCFG_PHYPLLEN)\n" - "+#ifdef CONFIG_DMA_COHERENT\n" - "+ | AMD_BIT(USBMSRMCFG_UCAM)\n" - "+#endif\n" - "+ | AMD_BIT(USBMSRMCFG_RDCOMB)\n" - "+ | AMD_BIT(USBMSRMCFG_PFEN);\n" - "+ writel(reg, USB_MSR_BASE + USB_MSR_MCFG); \n" - "+#endif\n" - "+\n" - "+ /* one udc only */\n" - "+ if (udc) {\n" - "+ WARN(\"already probed: %04x/%04x\\n\", UDC_PCI_VENID, UDC_PCI_DEVID);\n" - "+ return -EBUSY;\n" - "+ }\n" - "+\n" - "+ /* init */\n" - "+ dev = kmalloc (sizeof (struct udc), SLAB_KERNEL);\n" - "+ if (!dev) {\n" - "+ retval = -ENOMEM;\n" - "+ goto finished;\n" - "+ }\n" - "+ memset (dev, 0, sizeof(struct udc));\n" - "+\n" - "+\tdev->pdev = _dev;\n" - "+\n" - "+ /* check platform resources */\n" - "+\tif (pdev->resource[0].flags != IORESOURCE_MEM) {\n" - "+\t\tERR (\"resource[0] must be IORESOURCE_MEM\\n\");\n" - "+\t\tretval = -ENOMEM;\n" - "+\t\tgoto finished;\n" - "+\t}\n" - "+\tresource = pdev->resource[0].start;\n" - "+\tlen = pdev->resource[0].end + 1 - pdev->resource[0].start;\n" - "+\tif (pdev->resource[1].flags != IORESOURCE_IRQ) {\n" - "+\t\tERR (\"resource[1] must be IORESOURCE_IRQ\\n\");\n" - "+\t\tretval = -ENOMEM;\n" - "+\t\tgoto finished;\n" - "+\t}\n" - "+\tirq = pdev->resource[1].start;\n" - "+\n" - "+ /* platform device resource allocation */\n" - "+ /* mem */\n" - "+\tif (!request_mem_region (resource, len, name)) {\n" - "+\t\tERR (\"controller already in use\\n\");\n" - "+\t\tretval = -EBUSY;\n" - "+\t\tgoto finished;\n" - "+\t}\n" - "+\tdev->mem_region = 1;\n" - "+\n" - "+ dev->virt_addr = ioremap_nocache(resource, len);\n" - "+ if (dev->virt_addr == NULL) {\n" - "+ DBG( \"start address cannot be mapped\\n\");\n" - "+ retval = -EFAULT;\n" - "+ goto finished;\n" - "+ }\n" - "+\n" - "+ /* irq */\n" - "+ if (!irq) {\n" - "+ ERR( \"irq not set\\n\");\n" - "+ retval = -ENODEV;\n" - "+ goto finished;\n" - "+ }\n" - "+ snprintf (tmp, sizeof tmp, \"%d\", irq);\n" - "+ if (request_irq (irq, udc_irq, SA_SHIRQ, name, dev) != 0) {\n" - "+ ERR( \"error on request_irq() with %s\\n\", tmp);\n" - "+ retval = -EBUSY;\n" - "+ goto finished;\n" - "+ }\n" - "+ dev->irq_registered = 1;\n" - "+\n" - "+ dev_set_drvdata (_dev, dev);\n" - "+\n" - "+ /* chip revision */\n" - "+ dev->chiprev = 0;\n" - "+\n" - "+ /* chip rev for Au1200 */\n" - "+ dev->chiprev = (u16) read_c0_prid() & 0xff;\n" - "+\n" - "+ /* init dma pools */\n" - "+ if (use_dma) {\n" - "+ retval = init_dma_pools(dev);\n" - "+ if (retval != 0)\n" - "+ goto finished; \n" - "+ }\n" - "+\n" - "+ dev->phys_addr = resource;\n" - "+ dev->irq = irq;\n" - "+ dev->gadget.dev.parent = _dev;\n" - "+ dev->gadget.dev.dma_mask = _dev->dma_mask;\n" - "+ /* general probing */\n" - "+ if (udc_probe(dev) != 0)\n" - "+ goto finished;\n" - "+ return retval; \n" - "+\n" - "+finished:\n" - "+ if (dev)\n" - "+ udc_drv_remove (_dev);\n" - "+ return retval;\n" - "+}\n" - "+#endif\n" - "+\n" - "+#if !defined(CONFIG_SOC_AU1200)\n" - "+/**\n" - "+ * Called by pci bus driver to init pci context\n" - "+ *\n" - "+ * \\param pdev pointer to pci device struct\n" - "+ * \\param id pointer to pci device id\n" - "+ * \\return 0 if success\n" - "+ */\n" - "+static int udc_pci_probe (struct pci_dev *pdev, const struct pci_device_id *id)\n" - "+{\n" - "+ char tmp[8];\n" - "+ struct udc *dev;\n" - "+ unsigned long resource;\n" - "+ unsigned long len;\n" - "+ int retval = 0;;\n" - "+\n" - "+ VDBG(\"udc_pci_probe()\\n\");\n" - "+\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+ {\n" - "+ u32 tmp;\n" - "+ /*\n" - "+ * Fill in the dummy pci_dev\n" - "+ */\n" - "+ memset(pdev, 0, sizeof(struct pci_dev));\n" - "+ pdev->resource[0].name = \"UDC Registers\";\n" - "+ pdev->resource[0].start = USB_UDC_BASE;\n" - "+ pdev->resource[0].end = USB_UDC_BASE + USB_UDC_LEN - 1;\n" - "+ pdev->resource[0].flags = 0;\n" - "+ pdev->irq = AU1200_USB_INT;\n" - "+\n" - "+ tmp = readl((u32*) (USB_MSR_BASE + USB_MSR_MCFG));\n" - "+ if (tmp == 0) {\n" - "+ /* default value */\n" - "+ tmp = USBMSRMCFG_DEFAULT; \n" - "+ writel(tmp, USB_MSR_BASE + USB_MSR_MCFG); \n" - "+ readl((u32*) USB_MSR_BASE + USB_MSR_MCFG); \n" - "+ udelay(1000);\n" - "+ }\n" - "+ /* enable UDC memory, DMA, clock, cacheable memory,\n" - "+ * read combining and prefetch enable */\n" - "+ tmp |= AMD_BIT(USBMSRMCFG_DMEMEN) | AMD_BIT(USBMSRMCFG_DBMEN)\n" - "+ | AMD_BIT(USBMSRMCFG_UDCCLKEN)\n" - "+ | AMD_BIT(USBMSRMCFG_PHYPLLEN)\n" - "+#ifdef CONFIG_DMA_COHERENT\n" - "+ | AMD_BIT(USBMSRMCFG_UCAM)\n" - "+#endif\n" - "+ | AMD_BIT(USBMSRMCFG_RDCOMB)\n" - "+ | AMD_BIT(USBMSRMCFG_PFEN);\n" - "+ writel(tmp, USB_MSR_BASE + USB_MSR_MCFG); \n" - "+ }\n" - "+#endif\n" - "+ /* one udc only */\n" - "+ if (udc) {\n" - "+ WARN(\"already probed: %04x/%04x\\n\", UDC_PCI_VENID, UDC_PCI_DEVID);\n" - "+ return -EBUSY;\n" - "+ }\n" - "+\n" - "+ /* init */\n" - "+ dev = kmalloc (sizeof (struct udc), SLAB_KERNEL);\n" - "+ if (!dev) {\n" - "+ retval = -ENOMEM;\n" - "+ goto finished;\n" - "+ }\n" - "+ memset (dev, 0, sizeof(struct udc));\n" - "+\n" - "+ /* pci setup */\n" - "+#ifndef USE_AU1200_PCI_DUMMY\n" - "+ if (pci_enable_device (pdev) < 0) {\n" - "+ retval = -ENODEV;\n" - "+ goto finished;\n" - "+ }\n" - "+#endif\n" - "+ dev->active = 1;\n" - "+\n" - "+ /* PCI resource allocation */\n" - "+ resource = pci_resource_start(pdev, 0);\n" - "+ len = pci_resource_len (pdev, 0);\n" - "+\n" - "+ if (!request_mem_region (resource, len, name)) {\n" - "+ DBG( \"pci device used already\\n\");\n" - "+ retval = -EBUSY;\n" - "+ goto finished;\n" - "+ }\n" - "+ dev->mem_region = 1;\n" - "+\n" - "+ dev->virt_addr = ioremap_nocache(resource, len);\n" - "+ if (dev->virt_addr == NULL) {\n" - "+ DBG( \"start address cannot be mapped\\n\");\n" - "+ retval = -EFAULT;\n" - "+ goto finished;\n" - "+ }\n" - "+\n" - "+ if (!pdev->irq) {\n" - "+ ERR( \"pdev->irq not set\\n\");\n" - "+ retval = -ENODEV;\n" - "+ goto finished;\n" - "+ }\n" - "+\n" - "+ snprintf (tmp, sizeof tmp, \"%d\", pdev->irq);\n" - "+\n" - "+ if (request_irq (pdev->irq, udc_irq, SA_SHIRQ, name, dev) != 0) {\n" - "+ ERR( \"error on request_irq() with %s\\n\", tmp);\n" - "+ retval = -EBUSY;\n" - "+ goto finished;\n" - "+ }\n" - "+ dev->irq_registered = 1;\n" - "+\n" - "+ pci_set_drvdata (pdev, dev);\n" - "+\n" - "+ /* chip revision */\n" - "+ dev->chiprev = 0;\n" - "+\n" - "+#ifndef CONFIG_SOC_AU1200 \n" - "+ pci_set_master (pdev);\n" - "+#ifdef HAVE_PCI_SET_MWI\n" - "+ pci_set_mwi (pdev);\n" - "+#endif\n" - "+ /* chip rev for Hs AU1200 */\n" - "+ pci_read_config_byte(pdev, PCI_REVISION_ID, (u8*) &dev->chiprev);\n" - "+#else\n" - "+ /* chip rev for Au1200 */\n" - "+ dev->chiprev = (u16) read_c0_prid() & 0xff;\n" - "+#endif\n" - "+ /* init dma pools */\n" - "+ if (use_dma) {\n" - "+ retval = init_dma_pools(dev);\n" - "+ if (retval != 0)\n" - "+ goto finished; \n" - "+ }\n" - "+\n" - "+ dev->phys_addr = resource;\n" - "+ dev->irq = pdev->irq;\n" - "+ dev->pdev = pdev;\n" - "+ dev->gadget.dev.parent = &pdev->dev;\n" - "+ dev->gadget.dev.dma_mask = pdev->dev.dma_mask;\n" - "+\n" - "+ /* general probing */\n" - "+ if (udc_probe(dev) != 0)\n" - "+ goto finished;\n" - "+ return retval; \n" - "+\n" - "+finished:\n" - "+ if (dev)\n" - "+ udc_pci_remove (pdev);\n" - "+ return retval;\n" - "+}\n" - "+#endif\n" - "+\n" - "+/**\n" - "+ * general probe\n" - "+ *\n" - "+ * \\param dev pointer to udc device struct\n" - "+ * \\return 0 if success\n" - "+ */\n" - "+__init int udc_probe(struct udc* dev)\n" - "+{\n" - "+ char tmp[128];\n" - "+\tu32 reg;\n" - "+ int retval;\n" - "+\n" - "+\t/* mark timer as not initialized */\n" - "+ udc_timer.data = 0;\n" - "+ udc_pollstall_timer.data = 0;\n" - "+\t\n" - "+ /* device struct setup */\n" - "+ spin_lock_init(&dev->lock);\n" - "+ spin_lock_init(&udc_irq_spinlock);\n" - "+ spin_lock_init(&udc_stall_spinlock);\n" - "+ dev->gadget.ops = &udc_ops;\n" - "+\n" - "+ strcpy(dev->gadget.dev.bus_id, \"gadget\");\n" - "+ dev->gadget.dev.release = gadget_release;\n" - "+ dev->gadget.name = name;\n" - "+\tdev->gadget.is_dualspeed = 1;\n" - "+\n" - "+ /* udc csr registers base */\n" - "+ dev->csr = (struct udc_csrs*) (dev->virt_addr + UDC_CSR_ADDR);\n" - "+ /* dev registers base */\n" - "+ dev->regs = (struct udc_regs *) (dev->virt_addr + UDC_DEVCFG_ADDR); \n" - "+ /* ep registers base */\n" - "+ dev->ep_regs = (struct udc_ep_regs *) (dev->virt_addr + UDC_EPREGS_ADDR); \n" - "+ /* fifo's base */\n" - "+ dev->rxfifo = (u32*) (dev->virt_addr + UDC_RXFIFO_ADDR); \n" - "+ dev->txfifo = (u32*) (dev->virt_addr + UDC_TXFIFO_ADDR); \n" - "+\n" - "+ /* init registers, interrupts, ... */\n" - "+#ifndef UDC_IPBUG_3943_WORKAROUND\n" - "+ startup_registers(dev);\n" - "+#else\n" - "+ {\n" - "+ u32 tmp;\n" - "+\n" - "+ /* TODO put this to extra function,\n" - "+ * this all is extracted from usb_init() and\n" - "+ * udc_basic_init() but without register access */\n" - "+ dev->gadget.ep0 = &dev->ep [UDC_EP0IN_IX].ep;\n" - "+ dev->ep [UDC_EP0IN_IX].halted = 0;\n" - "+ INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);\n" - "+ dev->gadget.speed = USB_SPEED_HIGH;\n" - "+ make_ep_lists(dev);\n" - "+ /* basic endpoint init */\n" - "+ for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {\n" - "+ struct udc_ep *ep = &dev->ep[tmp];\n" - "+\n" - "+ ep->ep.name = ep_string[tmp];\n" - "+ ep->dev = dev;\n" - "+ ep->num = tmp;\n" - "+ /* txfifo size is calculated at enable time */\n" - "+ ep->txfifo = dev->txfifo;\n" - "+\n" - "+ /* fifo size */\n" - "+ if (tmp < UDC_EPIN_NUM) {\n" - "+ ep->fifo_depth = UDC_TXFIFO_SIZE;\n" - "+ ep->in = 1;\n" - "+ }\n" - "+ else {\n" - "+ ep->fifo_depth = UDC_RXFIFO_SIZE;\n" - "+ ep->in = 0;\n" - "+\n" - "+ }\n" - "+\n" - "+ ep->regs = &dev->ep_regs [tmp];\n" - "+ if (!ep->desc) {\n" - "+ ep->desc = 0;\n" - "+ INIT_LIST_HEAD (&ep->queue);\n" - "+\n" - "+ ep->ep.maxpacket = ~0;\n" - "+ ep->ep.ops = &udc_ep_ops;\n" - "+ }\n" - "+ if (use_dma) {\n" - "+ /* ep->dma is not really used, just to indicate that */\n" - "+ /* DMA is active */\n" - "+ /* dma regs = dev control regs */ \n" - "+ ep->dma = (u32*) &dev->regs->ctl; \n" - "+ }\n" - "+ }\n" - "+ dev->ep [UDC_EP0IN_IX].ep.maxpacket = UDC_EP0IN_MAX_PKT_SIZE;\n" - "+ dev->ep [UDC_EP0OUT_IX].ep.maxpacket = UDC_EP0OUT_MAX_PKT_SIZE;\n" - "+ }\n" - "+#endif\n" - "+\n" - "+\n" - "+ INFO( \"%s\\n\", mod_desc);\n" - "+\n" - "+ snprintf (tmp, sizeof tmp, \"%d\", dev->irq);\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+ INFO( \"irq %s, mem %08lx, chip rev %02x (Au1200 %s)\\n\",\n" - "+ tmp, dev->phys_addr, dev->chiprev, (dev->chiprev == 0) ? \"AB\" : \"AC\");\n" - "+ strcpy(tmp, UDC_DRIVER_VERSION_STRING);\n" - "+#ifdef CONFIG_DMA_COHERENT\n" - "+ /* coherent DMA not possible with AB silicon */\n" - "+ if (dev->chiprev == UDC_AUAB_REV) {\n" - "+ ERR(\"Your chip revision is %s, it must be at least %s to use coherent DMA. \\nPlease change DMA_COHERENT to DMA_NONCOHERENT in arch/mips/Kconfig and re-compile .\\n\",\n" - "+ \"AB\", \"AC\");\n" - "+ retval = -ENODEV;\n" - "+ goto finished;\n" - "+ }\n" - "+#endif\n" - "+ \n" - "+#ifdef UDC_AUA1\n" - "+ if (dev->chiprev < UDC_AUA1) {\n" - "+ ERR(\"Your chip revision is %s, it must be at least %s\\n\",\n" - "+ \"AB\", \"AC\");\n" - "+ retval = -ENODEV;\n" - "+ goto finished;\n" - "+ }\n" - "+ INFO(\"driver version: %s (for Au1200 AC)\\n\", tmp);\n" - "+#else\n" - "+ INFO(\"driver version: %s (for Au1200 AB)\\n\", tmp);\n" - "+#endif\n" - "+#ifdef CONFIG_DMA_COHERENT\n" - "+ INFO(\"Compiled for coherent memory.\\n\");\n" - "+#endif\n" - "+#ifdef CONFIG_DMA_NONCOHERENT\n" - "+ INFO(\"Compiled for non-coherent memory.\\n\");\n" - "+#endif\n" - "+#else\n" - "+ INFO(\"irq %s, pci mem %08lx, chip rev %02x (Geode5536 %s)\\n\",\n" - "+ tmp, dev->phys_addr, dev->chiprev, (dev->chiprev == UDC_HSA0_REV) ? \"A0\" : \"B1\");\n" - "+ strcpy(tmp, UDC_DRIVER_VERSION_STRING);\n" - "+#ifdef UDC_HSB1\n" - "+ if (dev->chiprev == UDC_HSA0_REV) {\n" - "+ ERR(\"Your chip revision is %s, it must be at least %s\\n\",\n" - "+ \"A0\", \"B1\");\n" - "+ retval = -ENODEV;\n" - "+ goto finished;\n" - "+ }\n" - "+ INFO(\"driver version: %s (for Geode5536 B1)\\n\", tmp);\n" - "+#else\n" - "+ INFO(\"driver version: %s (for Geode5536 A0)\\n\", tmp);\n" - "+#endif\n" - "+#endif\n" - "+ udc = dev;\n" - "+\n" - "+ device_register (&dev->gadget.dev);\n" - "+ /* device_create_file (&pdev->dev, &dev_attr_registers); */\n" - "+\n" - "+#ifdef UDC_USE_TIMER\n" - "+ /* timer init */\n" - "+ init_timer(&udc_timer);\n" - "+ udc_timer.function = udc_timer_function;\n" - "+ udc_timer.data = 1;\n" - "+ /* timer pollstall init */\n" - "+ init_timer(&udc_pollstall_timer);\n" - "+ udc_pollstall_timer.function = udc_pollstall_timer_function;\n" - "+ udc_pollstall_timer.data = 1;\n" - "+#endif\n" - "+\n" - "+ /* set SD */\n" - "+ reg = readl(&dev->regs->ctl);\n" - "+ reg |= AMD_BIT(UDC_DEVCTL_SD);\n" - "+ writel(reg, &dev->regs->ctl);\n" - "+\n" - "+ /* print dev register info */\n" - "+ print_regs(dev);\n" - "+\n" - "+ return 0;\n" - "+\n" - "+finished:\n" - "+ return retval;\n" - "+}\n" - "+\n" - "+\n" - "+/**\n" - "+ * Initiates a remote wakeup \n" - "+ *\n" - "+ * \\return 0 if success\n" - "+ */\n" - "+/* initiate remote wakeup */\n" - "+static int udc_remote_wakeup(struct udc* dev)\n" - "+{\n" - "+ u32 tmp;\n" - "+\n" - "+ INFO(\"UDC initiates remote wakeup\\n\");\n" - "+ \n" - "+ tmp = readl(&dev->regs->ctl);\n" - "+ tmp |= AMD_BIT(UDC_DEVCTL_RES);\n" - "+ writel(tmp, &dev->regs->ctl); \n" - "+ /* wait 1ms before clear resume bit */\n" - "+ /* udelay(1000); */\n" - "+ tmp &= AMD_CLEAR_BIT(UDC_DEVCTL_RES);\n" - "+ writel(tmp, &dev->regs->ctl); \n" - "+\n" - "+ return 0;\n" - "+}\n" - "+\n" - "+#if defined(CONFIG_SOC_AU1200)\n" - "+/**\n" - "+ * Suspends UDC \n" - "+ *\n" - "+ * \\return 0 if success\n" - "+ */\n" - "+static int udc_suspend(struct udc* dev)\n" - "+{\n" - "+ int retval = 0;\n" - "+\n" - "+ INFO(\"UDC suspend\\n\");\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+ u32 tmp;\n" - "+ /* mask interrupts */\n" - "+ udc_mask_unused_interrupts(dev);\n" - "+\n" - "+ if (dev->driver && dev->driver->disconnect) {\n" - "+ /* call gadget to reset context */\n" - "+ if (spin_is_locked(&dev->lock)) {\n" - "+ spin_unlock(&dev->lock);\n" - "+ dev->driver->disconnect (&dev->gadget);\n" - "+ spin_lock(&dev->lock);\n" - "+ }\n" - "+ else\n" - "+ dev->driver->disconnect (&dev->gadget);\n" - "+\n" - "+ /* disable ep0 to empty req queue */\n" - "+ empty_req_queue (&dev->ep [UDC_EP0IN_IX]);\n" - "+ ep_init (dev->regs,\n" - "+ &dev->ep [UDC_EP0IN_IX]);\n" - "+\n" - "+ /* init controller by soft reset */\n" - "+ udc_soft_reset(dev);\n" - "+\n" - "+ }\n" - "+ if (dev->otg_driver && dev->otg_transceiver \n" - "+ && dev->otg_transceiver->set_peripheral) {\n" - "+ /* if UDC is supended by Host or already disconnected then\n" - "+ don't force disconnect by unbind() */\n" - "+ if (dev->otg_driver->query) {\n" - "+ if (!(dev->otg_driver->query(0) & OTG_FLAGS_UDC_SUSP)) {\n" - "+ /* unbind from otg driver -> host disconnect */\n" - "+ dev->otg_transceiver->set_peripheral(dev->otg_transceiver, NULL);\n" - "+ dev->connected = 0;\n" - "+ }\n" - "+ }\n" - "+ else\n" - "+ {\n" - "+ /* unbind from otg driver -> host disconnect */\n" - "+ dev->otg_transceiver->set_peripheral (dev->otg_transceiver, NULL);\n" - "+ dev->connected = 0;\n" - "+ }\n" - "+ }\n" - "+ \n" - "+ dev->sys_suspended = 1;\n" - "+\n" - "+ /* switch off UDC clock */\n" - "+ tmp = readl((u32*) (USB_MSR_BASE + USB_MSR_MCFG));\n" - "+ tmp &= AMD_CLEAR_BIT(USBMSRMCFG_UDCCLKEN);\n" - "+ writel(tmp, USB_MSR_BASE + USB_MSR_MCFG); \n" - "+\n" - "+#endif \n" - "+\n" - "+ return retval;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * Resumes UDC \n" - "+ *\n" - "+ * \\return 0 if success\n" - "+ */\n" - "+static int udc_resume(struct udc* dev)\n" - "+{\n" - "+ int retval = 0;\n" - "+\n" - "+ INFO(\"UDC resume\\n\");\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+ u32 tmp;\n" - "+ /* switch on UDC clock */\n" - "+ tmp = readl((u32*) (USB_MSR_BASE + USB_MSR_MCFG));\n" - "+ tmp |= AMD_BIT(USBMSRMCFG_UDCCLKEN);\n" - "+ writel(tmp, USB_MSR_BASE + USB_MSR_MCFG); \n" - "+\n" - "+ dev->sys_suspended = 0;\n" - "+\n" - "+ usb_connect(dev);\n" - "+ if (dev->otg_transceiver && dev->otg_transceiver->set_peripheral) {\n" - "+ /* bind to otg driver */\n" - "+ dev->otg_transceiver->set_peripheral(dev->otg_transceiver, &dev->gadget);\n" - "+ }\n" - "+ \n" - "+#endif\n" - "+\n" - "+ return retval;\n" - "+}\n" - "+\n" - "+static int udc_au1xxx_drv_probe(struct device *dev)\n" - "+{\n" - "+\tint retval;\n" - "+\n" - "+\tDBG(\"udc_au1xxx_drv_probe()\\n\");\n" - "+ retval = udc_drv_probe(dev);\n" - "+\treturn retval;\n" - "+}\n" - "+\n" - "+static int udc_au1xxx_drv_remove(struct device *dev)\n" - "+{\n" - "+\tDBG(\"udc_au1xxx_drv_remove()\\n\");\n" - "+ udc_drv_remove(dev);\n" - "+\treturn 0;\n" - "+}\n" - "+\n" - "+static int udc_au1xxx_drv_suspend(struct device *dev, pm_message_t state)\n" - "+{\n" - "+\tstruct udc *udc_dev = dev_get_drvdata(dev);\n" - "+ return udc_suspend(udc_dev);\n" - "+}\n" - "+\n" - "+static int udc_au1xxx_drv_resume(struct device *dev)\n" - "+{\n" - "+\tstruct udc *udc_dev = dev_get_drvdata(dev);\n" - "+ return udc_resume(udc_dev);\n" - "+}\n" - "+\n" - "+static struct device_driver udc_au1xxx_driver = {\n" - "+\t.name\t\t= \"au1xxx-udc\",\n" - "+\t.bus\t\t= &platform_bus_type,\n" - "+\t.probe\t\t= udc_au1xxx_drv_probe,\n" - "+\t.remove\t\t= udc_au1xxx_drv_remove,\n" - "+\t.suspend\t= udc_au1xxx_drv_suspend,\n" - "+\t.resume\t = udc_au1xxx_drv_resume,\n" - "+};\n" - "+#endif\n" - "+\n" - "+\n" - "+/**\n" - "+ * Inits driver\n" - "+ *\n" - "+ * \\return 0 if success\n" - "+ */\n" - "+static int __init init(void)\n" - "+{\n" - "+ int rc;\n" - "+\n" - "+#ifdef UDC_DEBUG\n" - "+ /* register char device */\n" - "+ rc = register_chrdev(UDC_MAJOR_NUM, UDC_DEVICE_NAME, &udc_fops);\n" - "+ if (rc < 0)\n" - "+ {\n" - "+ printk(\"Error registering udc char device\");\n" - "+ }\n" - "+#endif \n" - "+\n" - "+#ifdef CONFIG_SOC_AU1200 \n" - "+ /* probe by device system */\n" - "+ rc = driver_register(&udc_au1xxx_driver); \n" - "+#else\n" - "+ /* probe by PCI bus driver */\n" - "+ rc = pci_module_init (&udc_pci_driver);\n" - "+#endif\n" - "+\n" - "+ return rc;\n" - "+}\n" - "+module_init (init);\n" - "+\n" - "+/**\n" - "+ * Cleans driver\n" - "+ */\n" - "+static void __exit cleanup(void)\n" - "+{\n" - "+#ifdef UDC_DEBUG\n" - "+ /* unregister char device */\n" - "+ unregister_chrdev(UDC_MAJOR_NUM, UDC_DEVICE_NAME);\n" - "+#endif\n" - "+\n" - "+#ifdef CONFIG_SOC_AU1200 \n" - "+ /* unregister at device system */\n" - "+ driver_unregister(&udc_au1xxx_driver); \n" - "+#else\n" - "+ /* unregister at PCI bus driver */\n" - "+ pci_unregister_driver (&udc_pci_driver);\n" - "+#endif\n" - "+\n" - "+}\n" - "+module_exit (cleanup);\n" - "+\n" - "diff --git a/drivers/usb/gadget/au1200udc.h b/drivers/usb/gadget/au1200udc.h\n" - "new file mode 100644\n" - "index 0000000..d7d8491\n" - "--- /dev/null\n" - "+++ b/drivers/usb/gadget/au1200udc.h\n" - "@@ -0,0 +1,936 @@\n" - "+/*\n" - "+ * Header for driver for AMD Au1200 UDC high/full speed USB device controller\n" - "+ */\n" - "+\n" - "+/*\n" - "+ * Copyright (C) 2005 AMD (http://www.amd.com)\n" - "+ * Author: Thomas Dahlmann \n" - "+ *\n" - "+ * This program is free software; you can redistribute it and/or modify\n" - "+ * it under the terms of the GNU General Public License as published by\n" - "+ * the Free Software Foundation; either version 2 of the License, or\n" - "+ * (at your option) any later version.\n" - "+ *\n" - "+ * This program is distributed in the hope that it will be useful,\n" - "+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - "+ * GNU General Public License for more details.\n" - "+ *\n" - "+ * You should have received a copy of the GNU General Public License\n" - "+ * along with this program; if not, write to the Free Software\n" - "+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n" - "+ */\n" - "+\n" - "+#ifndef AU1200UDC_H\n" - "+#define AU1200UDC_H\n" - "+\n" - "+/*****************************************************************************\n" - "+* Constants\n" - "+*****************************************************************************/\n" - "+\n" - "+/* Driver constants -------------------------------------------------------*/\n" - "+#define DRIVER_NAME_FOR_PRINT \"au1200udc\"\n" - "+\n" - "+/* PCI constants -----------------------------------------------------------*/\n" - "+#define UDC_PCI_VENID 0x1022\n" - "+#define UDC_PCI_DEVID 0x2096\n" - "+#define UDC_PCI_CLASS ((PCI_CLASS_SERIAL_USB << 8) | 0xfe)\n" - "+#define UDC_PCI_CLASS_MASK 0xffffffff\n" - "+\n" - "+/* Platform specific -------------------------------------------------------*/\n" - "+#if defined(CONFIG_SOC_AU1200)\n" - "+#define UDC_PCIPOOL_ALIGN 32 \n" - "+#define UDC_PCIPOOL_CROSS 4096\n" - "+#define UDC_PCIPOOL_GFP_STP (GFP_ATOMIC | GFP_DMA)\n" - "+#else\n" - "+#define UDC_PCIPOOL_ALIGN 0 \n" - "+#define UDC_PCIPOOL_CROSS 0 \n" - "+#define UDC_PCIPOOL_GFP_STP (GFP_KERNEL)\n" - "+#endif\n" - "+\n" - "+/* temp define for AU1200, will live in au1000.h normally */\n" - "+#ifndef USB_UDC_BASE\n" - "+#define USB_UDC_BASE 0x14022000\n" - "+#define USB_UDC_LEN 0x2000\n" - "+#define USB_MSR_BASE 0xB4020000\n" - "+#define USB_MSR_MCFG 4\n" - "+#define USBMSRMCFG_DMEMEN 4\n" - "+#define USBMSRMCFG_DBMEN 5\n" - "+#define USBMSRMCFG_UDCCLKEN 18\n" - "+#define USBMSRMCFG_PHYPLLEN 19\n" - "+#define USBMSRMCFG_RDCOMB 30\n" - "+#define USBMSRMCFG_PFEN 31\n" - "+#define AU1200_USB_INT 29\n" - "+#endif\n" - "+#ifndef USBMSRMCFG_UCAM \n" - "+#define USBMSRMCFG_UCAM 7\n" - "+#endif\n" - "+#define USBMSRMCFG_DEFAULT 0x00d02000\n" - "+\n" - "+/* other constants */\n" - "+#define UDC_RDE_TIMER_SECONDS 1\n" - "+#define UDC_RDE_TIMER_DIV 10\n" - "+#define UDC_POLLSTALL_TIMER_USECONDS 500\n" - "+\n" - "+/* Special optimization for certain gadgets ------------------------------- */ \n" - "+/* use hardware NAK if IN queue empty, this can be used to \n" - "+* avoid interrupt flood as for the ethernet gadget where host side\n" - "+* sends IN tokens permamently */\n" - "+#define UDC_DISABLE_IRQ_IF_EMPTY_IN_QUEUE\n" - "+/*#undef UDC_DISABLE_IRQ_IF_EMPTY_IN_QUEUE*/ \n" - "+\n" - "+/* IP core defect/bug/case workarounds ---------------------------------------- */\n" - "+/* Hs AU1200 A0 workarounds */\n" - "+/* Description: \"Last descriptor loop */\n" - "+#define UDC_IPDEFECT_9000004946_WORKAROUND\n" - "+/* Description: \"DMA machine not restartable\" */\n" - "+#define UDC_IPCASE_8000018724_WORKAROUND\n" - "+/* Description: \"UDC not accessible when phy is suspended */\n" - "+#define UDC_IPBUG_3943_WORKAROUND\n" - "+/* Description: \"USB device needs session-valid status information */\n" - "+#define UDC_IPBUG_3950_WORKAROUND\n" - "+/* Description: \"Clearing endpoint NAK bits not possible if RxFIFO\n" - "+ not empty (PCS#1503) */\n" - "+#define UDC_IPBUG_3958_WORKAROUND\n" - "+/* UDC data errors during loop test (DMA) \n" - "+ - found only with Au1200 but used for Hs too, bug entry\n" - "+ is in Au1200 bugzilla\n" - "+ - the workaround applies only for small packets */\n" - "+#define UDC_IPBUG_2253_WORKAROUND\n" - "+#define UDC_SMALL_PACKET 32\n" - "+\n" - "+/* Disable workarounds which don't apply to Hs AU1200 B1/ Au1200 A1 */\n" - "+/* And enable new features */\n" - "+ \n" - "+/* Hs AU1200 A0 flag */\n" - "+/* #define UDC_HSA0 */\n" - "+/* Hs AU1200 B1 flag */\n" - "+#define UDC_HSB1\n" - "+\n" - "+/* Hs AU1200 chip rev. */\n" - "+#define UDC_HSA0_REV 1\n" - "+#define UDC_HSB1_REV 2\n" - "+\n" - "+/* consistency */\n" - "+#ifdef UDC_HSB1\n" - "+#undef UDC_HSA0\n" - "+#endif\n" - "+\n" - "+/* Au1200 rev. */\n" - "+#if defined(CONFIG_SOC_AU1200)\n" - "+#undef UDC_HSB1\n" - "+#undef UDC_HSA0\n" - "+/* revision value */\n" - "+#define UDC_AUAB_REV 0\n" - "+#define UDC_AUAC_REV 1\n" - "+#define UDC_AUA0 0\n" - "+/* Au1200 AC flag */\n" - "+/* #define UDC_AUA1 1 */\n" - "+#endif\n" - "+\n" - "+/* disable workarounds for newer chip revisions */\n" - "+#ifdef UDC_HSB1\n" - "+#undef UDC_IPBUG_3943_WORKAROUND\n" - "+#undef UDC_IPBUG_3950_WORKAROUND\n" - "+#define UDC_DMARST_AVAIL\n" - "+#endif\n" - "+#ifdef UDC_AUA1\n" - "+#undef UDC_IPBUG_3943_WORKAROUND\n" - "+#endif\n" - "+\n" - "+/* SETUP usb commands \n" - "+* needed, because some SETUP's are handled in hw, but must be passed to \n" - "+* gadget driver above -----------------------------------------------------*/\n" - "+/* SET_CONFIG */\n" - "+#define UDC_SETCONFIG_DWORD0 0x00000900\n" - "+#define UDC_SETCONFIG_DWORD0_VALUE_MASK 0xffff0000 \n" - "+#define UDC_SETCONFIG_DWORD0_VALUE_OFS 16 \n" - "+\n" - "+#define UDC_SETCONFIG_DWORD1 0x00000000\n" - "+\n" - "+/* SET_INTERFACE */\n" - "+#define UDC_SETINTF_DWORD0 0x00000b00\n" - "+#define UDC_SETINTF_DWORD0_ALT_MASK 0xffff0000 \n" - "+#define UDC_SETINTF_DWORD0_ALT_OFS 16\n" - "+\n" - "+#define UDC_SETINTF_DWORD1 0x00000000\n" - "+#define UDC_SETINTF_DWORD1_INTF_MASK 0x0000ffff \n" - "+#define UDC_SETINTF_DWORD1_INTF_OFS 0 \n" - "+\n" - "+/* Mass storage reset */\n" - "+#define UDC_MSCRES_DWORD0 0x0000ff21\n" - "+#define UDC_MSCRES_DWORD1 0x00000000\n" - "+\n" - "+/* Global CSR's -------------------------------------------------------------*/\n" - "+/* UDC CSR's */\n" - "+#define UDC_CSR_ADDR 0x500 \n" - "+\n" - "+/* EP NE bits */\n" - "+/* EP number */\n" - "+#define UDC_CSR_NE_NUM_MASK 0x0000000f \n" - "+#define UDC_CSR_NE_NUM_OFS 0 \n" - "+/* EP direction */\n" - "+#define UDC_CSR_NE_DIR_MASK 0x00000010 \n" - "+#define UDC_CSR_NE_DIR_OFS 4 \n" - "+/* EP type */\n" - "+#define UDC_CSR_NE_TYPE_MASK 0x00000060\n" - "+#define UDC_CSR_NE_TYPE_OFS 5\n" - "+/* EP config number */\n" - "+#define UDC_CSR_NE_CFG_MASK 0x00000780\n" - "+#define UDC_CSR_NE_CFG_OFS 7\n" - "+/* EP interface number */\n" - "+#define UDC_CSR_NE_INTF_MASK 0x00007800\n" - "+#define UDC_CSR_NE_INTF_OFS 11 \n" - "+/* EP alt setting */\n" - "+#define UDC_CSR_NE_ALT_MASK 0x00078000\n" - "+#define UDC_CSR_NE_ALT_OFS 15\n" - "+ \n" - "+/* max pkt */\n" - "+#define UDC_CSR_NE_MAX_PKT_MASK 0x3ff80000 \n" - "+#define UDC_CSR_NE_MAX_PKT_OFS 19 \n" - "+\n" - "+/* Device Config Register ---------------------------------------------------*/\n" - "+#define UDC_DEVCFG_ADDR 0x400 \n" - "+\n" - "+#define UDC_DEVCFG_SOFTRESET 31\n" - "+#define UDC_DEVCFG_HNPSFEN 30\n" - "+#define UDC_DEVCFG_DMARST 29\n" - "+#define UDC_DEVCFG_SET_DESC 18\n" - "+#define UDC_DEVCFG_CSR_PRG 17\n" - "+#define UDC_DEVCFG_STATUS 7\n" - "+#define UDC_DEVCFG_DIR 6\n" - "+#define UDC_DEVCFG_PI 5\n" - "+#define UDC_DEVCFG_SS 4\n" - "+#define UDC_DEVCFG_SP 3\n" - "+#define UDC_DEVCFG_RWKP 2\n" - "+\n" - "+#define UDC_DEVCFG_SPD_MASK 0x3\n" - "+#define UDC_DEVCFG_SPD_OFS 0\n" - "+#define UDC_DEVCFG_SPD_HS 0x0\n" - "+#define UDC_DEVCFG_SPD_FS 0x1\n" - "+#define UDC_DEVCFG_SPD_LS 0x2\n" - "+/*#define UDC_DEVCFG_SPD_FS 0x3*/\n" - "+\n" - "+\n" - "+/* Device Control Register --------------------------------------------------*/\n" - "+#define UDC_DEVCTL_ADDR 0x404 \n" - "+\n" - "+#define UDC_DEVCTL_THLEN_MASK 0xff000000 \n" - "+#define UDC_DEVCTL_THLEN_OFS 24 \n" - "+\n" - "+#define UDC_DEVCTL_BRLEN_MASK 0x00ff0000 \n" - "+#define UDC_DEVCTL_BRLEN_OFS 16 \n" - "+\n" - "+#define UDC_DEVCTL_CSR_DONE 13\n" - "+#define UDC_DEVCTL_DEVNAK 12\n" - "+#define UDC_DEVCTL_SD 10\n" - "+#define UDC_DEVCTL_MODE 9 \n" - "+#define UDC_DEVCTL_BREN 8\n" - "+#define UDC_DEVCTL_THE 7\n" - "+#define UDC_DEVCTL_BF 6\n" - "+#define UDC_DEVCTL_BE 5\n" - "+#define UDC_DEVCTL_DU 4\n" - "+#define UDC_DEVCTL_TDE 3\n" - "+#define UDC_DEVCTL_RDE 2\n" - "+#define UDC_DEVCTL_RES 0\n" - "+\n" - "+\n" - "+/* Device Status Register ---------------------------------------------------*/\n" - "+#define UDC_DEVSTS_ADDR 0x408\n" - "+\n" - "+#define UDC_DEVSTS_TS_MASK 0xfffc0000\n" - "+#define UDC_DEVSTS_TS_OFS 18\n" - "+\n" - "+#define UDC_DEVSTS_SESSVLD 17\n" - "+#define UDC_DEVSTS_PHY_ERROR 16\n" - "+#define UDC_DEVSTS_RXFIFO_EMPTY 15\n" - "+\n" - "+#define UDC_DEVSTS_ENUM_SPEED_MASK 0x00006000\n" - "+#define UDC_DEVSTS_ENUM_SPEED_OFS 13\n" - "+#define UDC_DEVSTS_ENUM_SPEED_FULL 1\n" - "+#define UDC_DEVSTS_ENUM_SPEED_HIGH 0\n" - "+\n" - "+#define UDC_DEVSTS_SUSP 12\n" - "+\n" - "+#define UDC_DEVSTS_ALT_MASK 0x00000f00\n" - "+#define UDC_DEVSTS_ALT_OFS 8\n" - "+\n" - "+#define UDC_DEVSTS_INTF_MASK 0x000000f0\n" - "+#define UDC_DEVSTS_INTF_OFS 4\n" - "+\n" - "+#define UDC_DEVSTS_CFG_MASK 0x0000000f\n" - "+#define UDC_DEVSTS_CFG_OFS 0\n" - "+\n" - "+\n" - "+/* Device Interrupt Register ------------------------------------------------*/\n" - "+#define UDC_DEVINT_ADDR 0x40c\n" - "+\n" - "+#define UDC_DEVINT_SVC 7\n" - "+#define UDC_DEVINT_ENUM 6\n" - "+#define UDC_DEVINT_SOF 5\n" - "+#define UDC_DEVINT_US 4\n" - "+#define UDC_DEVINT_UR 3\n" - "+#define UDC_DEVINT_ES 2\n" - "+#define UDC_DEVINT_SI 1\n" - "+#define UDC_DEVINT_SC 0\n" - "+\n" - "+/* Device Interrupt Mask Register -------------------------------------------*/\n" - "+#define UDC_DEVINT_MSK_ADDR 0x410\n" - "+\n" - "+#define UDC_DEVINT_MSK 0x7f\n" - "+\n" - "+/* Endpoint Interrupt Register ----------------------------------------------*/\n" - "+#define UDC_EPINT_ADDR 0x414 \n" - "+\n" - "+#define UDC_EPINT_OUT_MASK 0xffff0000 \n" - "+#define UDC_EPINT_OUT_OFS 16 \n" - "+#define UDC_EPINT_IN_MASK 0x0000ffff \n" - "+#define UDC_EPINT_IN_OFS 0 \n" - "+\n" - "+#define UDC_EPINT_IN_EP0 0 \n" - "+#define UDC_EPINT_IN_EP1 1 \n" - "+#define UDC_EPINT_IN_EP2 2 \n" - "+#define UDC_EPINT_IN_EP3 3 \n" - "+#define UDC_EPINT_OUT_EP0 16 \n" - "+#define UDC_EPINT_OUT_EP1 17\n" - "+#define UDC_EPINT_OUT_EP2 18 \n" - "+#define UDC_EPINT_OUT_EP3 19 \n" - "+\n" - "+#define UDC_EPINT_EP0_ENABLE_MSK 0x001e001e \n" - "+\n" - "+/* Endpoint Interrupt Mask Register -----------------------------------------*/\n" - "+#define UDC_EPINT_MSK_ADDR 0x418 \n" - "+\n" - "+#define UDC_EPINT_OUT_MSK_MASK 0xffff0000 \n" - "+#define UDC_EPINT_OUT_MSK_OFS 16 \n" - "+#define UDC_EPINT_IN_MSK_MASK 0x0000ffff \n" - "+#define UDC_EPINT_IN_MSK_OFS 0 \n" - "+\n" - "+#define UDC_EPINT_MSK_DISABLE_ALL 0xffffffff\n" - "+/* mask non-EP0 endpoints */\n" - "+#define UDC_EPDATAINT_MSK_DISABLE 0xfffefffe\n" - "+/* mask all dev interrupts */\n" - "+#define UDC_DEV_MSK_DISABLE 0x7f\n" - "+\n" - "+/* Endpoint-specific CSR's --------------------------------------------------*/\n" - "+/* Endpoint Control Registers -----------------------------------------------*/\n" - "+#define UDC_EPREGS_ADDR 0x0\n" - "+#define UDC_EPIN_REGS_ADDR 0x0\n" - "+#define UDC_EPOUT_REGS_ADDR 0x200\n" - "+\n" - "+#define UDC_EPCTL_ADDR 0x0\n" - "+\n" - "+#define UDC_EPCTL_RRDY 9\n" - "+#define UDC_EPCTL_CNAK 8\n" - "+#define UDC_EPCTL_SNAK 7\n" - "+#define UDC_EPCTL_NAK 6\n" - "+\n" - "+#define UDC_EPCTL_ET_MASK 0x00000030\n" - "+#define UDC_EPCTL_ET_OFS 4\n" - "+#define UDC_EPCTL_ET_CONTROL 0\n" - "+#define UDC_EPCTL_ET_ISO 1 \n" - "+#define UDC_EPCTL_ET_BULK 2\n" - "+#define UDC_EPCTL_ET_INTERRUPT 3\n" - "+\n" - "+#define UDC_EPCTL_P 3\n" - "+#define UDC_EPCTL_SN 2\n" - "+#define UDC_EPCTL_F 1\n" - "+#define UDC_EPCTL_S 0\n" - "+\n" - "+/* Endpoint Status Registers ------------------------------------------------*/\n" - "+#define UDC_EPSTS_ADDR 0x4\n" - "+\n" - "+#define UDC_EPSTS_RX_PKT_SIZE_MASK 0x007ff800\n" - "+#define UDC_EPSTS_RX_PKT_SIZE_OFS 11\n" - "+\n" - "+#define UDC_EPSTS_TDC 10\n" - "+#define UDC_EPSTS_HE 9\n" - "+#define UDC_EPSTS_BNA 7\n" - "+#define UDC_EPSTS_IN 6\n" - "+\n" - "+#define UDC_EPSTS_OUT_MASK 0x00000030\n" - "+#define UDC_EPSTS_OUT_OFS 4 \n" - "+#define UDC_EPSTS_OUT_DATA 1\n" - "+#define UDC_EPSTS_OUT_DATA_CLEAR 0x10\n" - "+#define UDC_EPSTS_OUT_SETUP 2\n" - "+#define UDC_EPSTS_OUT_SETUP_CLEAR 0x20\n" - "+\n" - "+/* Endpoint Buffer Size IN/ Receive Packet Frame Number OUT Registers ------*/\n" - "+#define UDC_EPIN_BUFF_SIZE_ADDR 0x8\n" - "+#define UDC_EPOUT_FRAME_NUMBER_ADDR 0x8\n" - "+\n" - "+#define UDC_EPIN_BUFF_SIZE_MASK 0x0000ffff\n" - "+#define UDC_EPIN_BUFF_SIZE_OFS 0\n" - "+/* EP0in txfifo = 128 bytes*/ \n" - "+#define UDC_EPIN0_BUFF_SIZE 32\n" - "+/* EP0in fullspeed txfifo = 128 bytes*/ \n" - "+#define UDC_FS_EPIN0_BUFF_SIZE 32\n" - "+\n" - "+/* fifo size mult = fifo size / max packet */\n" - "+#define UDC_EPIN_BUFF_SIZE_MULT 2\n" - "+\n" - "+/* EPin data fifo size = 1024 bytes DOUBLE BUFFERING */\n" - "+#define UDC_EPIN_BUFF_SIZE 256 \n" - "+/* EPin small INT data fifo size = 128 bytes */\n" - "+#define UDC_EPIN_SMALLINT_BUFF_SIZE 32 \n" - "+\n" - "+/* EPin fullspeed data fifo size = 128 bytes DOUBLE BUFFERING */\n" - "+#define UDC_FS_EPIN_BUFF_SIZE 32 \n" - "+\n" - "+#define UDC_EPOUT_FRAME_NUMBER_MASK 0x0000ffff\n" - "+#define UDC_EPOUT_FRAME_NUMBER_OFS 0 \n" - "+\n" - "+/* Endpoint Buffer Size OUT/Max Packet Size Registers -----------------------*/\n" - "+#define UDC_EPOUT_BUFF_SIZE_ADDR 0x0c\n" - "+#define UDC_EP_MAX_PKT_SIZE_ADDR 0x0c\n" - "+\n" - "+#define UDC_EPOUT_BUFF_SIZE_MASK 0xffff0000\n" - "+#define UDC_EPOUT_BUFF_SIZE_OFS 16 \n" - "+#define UDC_EP_MAX_PKT_SIZE_MASK 0x0000ffff\n" - "+#define UDC_EP_MAX_PKT_SIZE_OFS 0\n" - "+/* EP0in max packet size = 64 bytes */\n" - "+#define UDC_EP0IN_MAX_PKT_SIZE 64\n" - "+/* EP0out max packet size = 64 bytes */\n" - "+#define UDC_EP0OUT_MAX_PKT_SIZE 64\n" - "+/* EP0in fullspeed max packet size = 64 bytes */\n" - "+#define UDC_FS_EP0IN_MAX_PKT_SIZE 64 \n" - "+/* EP0out fullspeed max packet size = 64 bytes */\n" - "+#define UDC_FS_EP0OUT_MAX_PKT_SIZE 64\n" - "+\n" - "+/* Endpoint dma descriptors ------------------------------------------------*/\n" - "+/* Setup data */\n" - "+/* Status dword */\n" - "+#define UDC_DMA_STP_STS_CFG_MASK 0x0fff0000\n" - "+#define UDC_DMA_STP_STS_CFG_OFS 16\n" - "+#define UDC_DMA_STP_STS_CFG_ALT_MASK 0x000f0000 \n" - "+#define UDC_DMA_STP_STS_CFG_ALT_OFS 16 \n" - "+#define UDC_DMA_STP_STS_CFG_INTF_MASK 0x00f00000 \n" - "+#define UDC_DMA_STP_STS_CFG_INTF_OFS 20 \n" - "+#define UDC_DMA_STP_STS_CFG_NUM_MASK 0x0f000000 \n" - "+#define UDC_DMA_STP_STS_CFG_NUM_OFS 24 \n" - "+#define UDC_DMA_STP_STS_RX_MASK 0x30000000\n" - "+#define UDC_DMA_STP_STS_RX_OFS 28 \n" - "+#define UDC_DMA_STP_STS_BS_MASK 0xc0000000\n" - "+#define UDC_DMA_STP_STS_BS_OFS 30 \n" - "+#define UDC_DMA_STP_STS_BS_HOST_READY 0 \n" - "+#define UDC_DMA_STP_STS_BS_DMA_BUSY 1 \n" - "+#define UDC_DMA_STP_STS_BS_DMA_DONE 2 \n" - "+#define UDC_DMA_STP_STS_BS_HOST_BUSY 3 \n" - "+/* IN data */\n" - "+/* Status dword */\n" - "+#define UDC_DMA_IN_STS_TXBYTES_MASK 0x0000ffff\n" - "+#define UDC_DMA_IN_STS_TXBYTES_OFS 0\n" - "+#define UDC_DMA_IN_STS_FRAMENUM_MASK 0x07ff0000\n" - "+#define UDC_DMA_IN_STS_FRAMENUM_OFS 0\n" - "+#define UDC_DMA_IN_STS_L 27\n" - "+#define UDC_DMA_IN_STS_TX_MASK 0x30000000\n" - "+#define UDC_DMA_IN_STS_TX_OFS 28 \n" - "+#define UDC_DMA_IN_STS_BS_MASK 0xc0000000\n" - "+#define UDC_DMA_IN_STS_BS_OFS 30 \n" - "+#define UDC_DMA_IN_STS_BS_HOST_READY 0 \n" - "+#define UDC_DMA_IN_STS_BS_DMA_BUSY 1 \n" - "+#define UDC_DMA_IN_STS_BS_DMA_DONE 2 \n" - "+#define UDC_DMA_IN_STS_BS_HOST_BUSY 3 \n" - "+/* OUT data */\n" - "+/* Status dword */\n" - "+#define UDC_DMA_OUT_STS_RXBYTES_MASK 0x0000ffff\n" - "+#define UDC_DMA_OUT_STS_RXBYTES_OFS 0\n" - "+#define UDC_DMA_OUT_STS_FRAMENUM_MASK 0x07ff0000\n" - "+#define UDC_DMA_OUT_STS_FRAMENUM_OFS 0\n" - "+#define UDC_DMA_OUT_STS_L 27\n" - "+#define UDC_DMA_OUT_STS_RX_MASK 0x30000000\n" - "+#define UDC_DMA_OUT_STS_RX_OFS 28 \n" - "+#define UDC_DMA_OUT_STS_BS_MASK 0xc0000000\n" - "+#define UDC_DMA_OUT_STS_BS_OFS 30 \n" - "+#define UDC_DMA_OUT_STS_BS_HOST_READY 0 \n" - "+#define UDC_DMA_OUT_STS_BS_DMA_BUSY 1 \n" - "+#define UDC_DMA_OUT_STS_BS_DMA_DONE 2 \n" - "+#define UDC_DMA_OUT_STS_BS_HOST_BUSY 3 \n" - "+/* other constants */\n" - "+/* max ep0in packet */\n" - "+#define UDC_EP0IN_MAXPACKET 1000\n" - "+/* max dma packet */\n" - "+#define UDC_DMA_MAXPACKET 65536 \n" - "+/* DMA buffer len for temp request, should be the same as the upper\n" - "+layer gadget is using */\n" - "+#define UDC_DMA_TEMP_BUFFER_LEN 4096 \n" - "+/* un-usable DMA address */\n" - "+#define DMA_DONT_USE (~(dma_addr_t) 0 )\n" - "+\n" - "+/* other Endpoint register addresses and values-----------------------------*/\n" - "+#define UDC_EP_SUBPTR_ADDR 0x10\n" - "+#define UDC_EP_DESPTR_ADDR 0x14\n" - "+#define UDC_EP_WRITE_CONFIRM_ADDR 0x1c\n" - "+\n" - "+/* EP number as layouted in AHB space */\n" - "+#define UDC_EP_NUM 32\n" - "+#define UDC_EPIN_NUM 16\n" - "+#define UDC_EPIN_NUM_USED 5\n" - "+#define UDC_EPOUT_NUM 16\n" - "+/* EP number of EP's really used = EP0 + 8 data EP's */\n" - "+#define UDC_USED_EP_NUM 9\n" - "+/* UDC CSR regs are aligned but AHB regs not - offset for OUT EP's */\n" - "+#define UDC_CSR_EP_OUT_IX_OFS 12\n" - "+\n" - "+#define UDC_EP0OUT_IX 16\n" - "+#define UDC_EP0IN_IX 0\n" - "+\n" - "+/* max packet */\n" - "+#define UDC_HS_BULK_MAXPKT 512\n" - "+\n" - "+/* Rx fifo address and size = 1k -------------------------------------------*/\n" - "+#define UDC_RXFIFO_ADDR 0x800\n" - "+#define UDC_RXFIFO_SIZE 0x400\n" - "+\n" - "+/* Tx fifo address and size = 1.5k -----------------------------------------*/\n" - "+#define UDC_TXFIFO_ADDR 0xc00\n" - "+#define UDC_TXFIFO_SIZE 0x600\n" - "+\n" - "+/* default data endpoints --------------------------------------------------*/\n" - "+#define UDC_EPIN_STATUS_IX 1 \n" - "+#define UDC_EPIN_IX 2 \n" - "+#define UDC_EPOUT_IX 18 \n" - "+\n" - "+/* general constants -------------------------------------------------------*/ \n" - "+#define UDC_DWORD_BYTES 4\n" - "+#define UDC_BITS_PER_BYTE_SHIFT 3\n" - "+#define UDC_BYTE_MASK 0xff\n" - "+#define UDC_BITS_PER_BYTE 8\n" - "+\n" - "+/* char device constants ---------------------------------------------------*/\n" - "+/* names */\n" - "+#ifdef UDC_DEBUG\n" - "+#ifdef UDC_DRIVER_NAME\n" - "+#define UDC_DEVICE_NAME UDC_DRIVER_NAME\n" - "+#else\n" - "+#define UDC_DEVICE_NAME \"au1200udc\"\n" - "+#endif\n" - "+#define UDC_DEVICE_FILE_NAME \"au1200udc_dev\"\n" - "+#define UDC_DEVICE_FILE_INODE \"/dev/au1200udc_dev\"\n" - "+/* major number */\n" - "+#define UDC_MAJOR_NUM 240\n" - "+#endif\n" - "+\n" - "+#ifdef __KERNEL__\n" - "+/* kernel wrappers */\n" - "+#define device_create_file(x,y) do {} while (0)\n" - "+#define device_remove_file device_create_file\n" - "+\n" - "+#ifndef WARN_ON\n" - "+#define WARN_ON(a) do {} while (0)\n" - "+#endif\n" - "+\n" - "+#ifndef BUG_ON\n" - "+#define BUG_ON(cond)do {if (unlikely((cond) != 0)) BUG();} while(0)\n" - "+#endif\n" - "+\n" - "+#ifndef likely\n" - "+#define likely(a) (a)\n" - "+#define unlikely(a) (a)\n" - "+#endif\n" - "+\n" - "+#ifndef container_of\n" - "+#define container_of list_entry\n" - "+#endif\n" - "+\n" - "+#ifndef IRQ_NONE\n" - "+typedef void irqreturn_t;\n" - "+#define IRQ_HANDLED\n" - "+#define IRQ_NONE\n" - "+#define IRQ_RETVAL(a)\n" - "+#endif\n" - "+#endif \n" - "+\n" - "+/* MIPS specific -----------------------------------------------------------*/\n" - "+#if defined(CONFIG_SOC_AU1200)\n" - "+/* sync does it without refilling the pipe,\n" - "+ so read after write can bypass write */\n" - "+#define au1200_sync_delay() {\\\n" - "+ asm(\".set noreorder\"); \\\n" - "+ asm(\"b l1\");\\\n" - "+ asm(\"l1:\");\\\n" - "+ asm(\"sync\");\\\n" - "+ asm(\"nop\");\\\n" - "+ asm(\"nop\");\\\n" - "+ asm(\"nop\");\\\n" - "+ asm(\"nop\");\\\n" - "+ asm(\"b l2\");\\\n" - "+ asm(\"l2:\");\\\n" - "+ asm(\"nop\");\\\n" - "+ asm(\"nop\");\\\n" - "+ asm(\".set reorder\");\\\n" - "+}\n" - "+\n" - "+/* #define wb_flush() au1200_sync() */\n" - "+#define wb_flush() __asm__ volatile (\"sync\")\n" - "+\n" - "+/* special write functions for MIPS (with write buffer flush) */\n" - "+#undef writel\n" - "+#undef writeb\n" - "+#define writel(d,a) {((*(volatile unsigned int *)(a))=(d));wb_flush();}\n" - "+#define writeb(d,a) {((*(volatile unsigned char *)(a))=(d));wb_flush();}\n" - "+#else\n" - "+#define wb_flush() {}\n" - "+#endif\n" - "+\n" - "+/*****************************************************************************\n" - "+* Includes \n" - "+*****************************************************************************/\n" - "+\n" - "+#if !defined(UDC_HSB1)\t\n" - "+#include \"au1200otg.h\"\n" - "+#endif\n" - "+\n" - "+/*****************************************************************************\n" - "+* Types\n" - "+*****************************************************************************/\n" - "+\n" - "+/* UDC CSR's */\n" - "+struct udc_csrs {\n" - "+ \n" - "+ /* sca - setup command address */\n" - "+ u32 sca;\n" - "+\n" - "+ /* ep ne's */\n" - "+ u32 ne[UDC_USED_EP_NUM];\n" - "+} __attribute__ ((packed));\n" - "+\n" - "+/* AHB subsystem CSR registers */\n" - "+struct udc_regs {\n" - "+\n" - "+ /* device configuration */\n" - "+ u32 cfg;\n" - "+\n" - "+ /* device control */\n" - "+ u32 ctl;\n" - "+\n" - "+ /* device status */\n" - "+ u32 sts;\n" - "+\n" - "+ /* device interrupt */\n" - "+ u32 irqsts;\n" - "+\n" - "+ /* device interrupt mask */\n" - "+ u32 irqmsk;\n" - "+ \n" - "+ /* endpoint interrupt */\n" - "+ u32 ep_irqsts;\n" - "+\n" - "+ /* endpoint interrupt mask */\n" - "+ u32 ep_irqmsk;\n" - "+} __attribute__ ((packed));\n" - "+\n" - "+/* endpoint specific registers */\n" - "+struct udc_ep_regs {\n" - "+\n" - "+ /* endpoint control */\n" - "+ u32 ctl;\n" - "+\n" - "+ /* endpoint status */\n" - "+ u32 sts;\n" - "+\n" - "+ /* endpoint buffer size in/ receive packet frame number out */\n" - "+ u32 bufin_framenum;\n" - "+\n" - "+ /* endpoint buffer size out/max packet size */\n" - "+ u32 bufout_maxpkt; \n" - "+\n" - "+ /* endpoint setup buffer pointer */\n" - "+ u32 subptr; \n" - "+ \n" - "+ /* endpoint data descriptor pointer */\n" - "+ u32 desptr;\n" - "+\n" - "+ /* reserverd */\n" - "+ u32 reserved;\n" - "+\n" - "+ /* write/read confirmation */\n" - "+ u32 confirm;\n" - "+\n" - "+} __attribute__ ((packed));\n" - "+\n" - "+#ifdef __KERNEL__\n" - "+/* control data DMA desc */\n" - "+struct udc_stp_dma {\n" - "+ /* status quadlet */\n" - "+ u32 status;\n" - "+ /* reserved */\n" - "+ u32 _reserved;\n" - "+ /* first setup word */\n" - "+ u32 data12;\n" - "+ /* second setup word */\n" - "+ u32 data34;\n" - "+} __attribute__ ((aligned (16)));\n" - "+\n" - "+/* normal data DMA desc */\n" - "+struct udc_data_dma {\n" - "+ /* status quadlet */\n" - "+ u32 status;\n" - "+ /* reserved */\n" - "+ u32 _reserved;\n" - "+ /* buffer pointer */\n" - "+ u32 bufptr;\n" - "+ /* next descriptor pointer */\n" - "+ u32 next;\n" - "+} __attribute__ ((aligned (16)));\n" - "+\n" - "+/* request packet */\n" - "+struct udc_request {\n" - "+ /* embedded gadget ep */\n" - "+ struct usb_request req;\n" - "+\n" - "+ /* flags */\n" - "+ unsigned dma_going : 1,\n" - "+ dma_mapping : 1,\n" - "+ dma_done : 1;\n" - "+ /* phys. address */\n" - "+ dma_addr_t td_phys;\n" - "+ /* first dma desc. of chain */\n" - "+ struct udc_data_dma *td_data;\n" - "+ /* last dma desc. of chain */\n" - "+ struct udc_data_dma *td_data_last;\n" - "+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND\n" - "+ /* next pointer of broken chain */\n" - "+ dma_addr_t td_data_last_next; \n" - "+#endif\n" - "+\n" - "+ struct list_head queue;\n" - "+\n" - "+ /* chain length */\n" - "+ unsigned chain_len;\n" - "+\n" - "+};\n" - "+\n" - "+/* UDC specific endpoint parameters */\n" - "+struct udc_ep {\n" - "+ struct usb_ep ep;\n" - "+ struct udc_ep_regs *regs;\n" - "+ u32 *txfifo;\n" - "+ u32* dma;\n" - "+ dma_addr_t td_phys;\n" - "+ dma_addr_t td_stp_dma; \n" - "+ struct udc_stp_dma *td_stp;\n" - "+ struct udc_data_dma *td;\n" - "+ /* temp request */\n" - "+ struct udc_request *req;\n" - "+ unsigned req_used; \n" - "+ unsigned req_completed; \n" - "+ /* NAK state */\n" - "+ unsigned naking; \n" - "+\n" - "+ struct udc *dev;\n" - "+\n" - "+ /* queue for requests */\n" - "+ struct list_head queue;\n" - "+ const struct usb_endpoint_descriptor *desc;\n" - "+ unsigned halted;\n" - "+ unsigned num : 5,\n" - "+ fifo_depth : 14,\n" - "+ in : 1;\n" - "+};\n" - "+\n" - "+/* device struct */\n" - "+struct udc {\n" - "+ struct usb_gadget gadget;\n" - "+ spinlock_t lock;\n" - "+ /* all endpoints */\n" - "+ struct udc_ep ep[UDC_EP_NUM];\n" - "+ struct usb_gadget_driver *driver;\n" - "+ struct otg_transceiver *otg_transceiver;\n" - "+#if !defined(UDC_HSB1)\t\n" - "+ struct usb_otg_gadget_extension *otg_driver;\n" - "+#endif\n" - "+ /* operational flags */\n" - "+ unsigned active : 1,\n" - "+ stall_ep0in : 1,\n" - "+ waiting_zlp_ack_ep0in : 1,\n" - "+ set_cfg_not_acked : 1,\n" - "+ irq_registered : 1,\n" - "+ otg_supported : 1,\n" - "+ data_ep_enabled : 1,\n" - "+ data_ep_queued : 1,\n" - "+ mem_region : 1,\n" - "+ selfpowered : 1,\n" - "+ sys_suspended : 1,\n" - "+ connected;\n" - "+\n" - "+ u16 chiprev;\n" - "+\n" - "+ /* registers */\n" - "+#if defined(CONFIG_SOC_AU1200) && !defined(USE_AU1200_PCI_DUMMY)\n" - "+ struct device *pdev;\n" - "+#else\n" - "+ struct pci_dev *pdev;\n" - "+#endif\n" - "+ struct udc_csrs *csr;\n" - "+ struct udc_regs *regs;\n" - "+ struct udc_ep_regs *ep_regs;\n" - "+ u32* rxfifo;\n" - "+ u32* txfifo;\n" - "+\n" - "+ /* DMA desc pools */\n" - "+#if defined(CONFIG_SOC_AU1200)\n" - "+ struct dma_pool *data_requests;\n" - "+ struct dma_pool *stp_requests;\n" - "+#else\n" - "+ struct pci_pool *data_requests;\n" - "+ struct pci_pool *stp_requests;\n" - "+#endif\n" - "+\n" - "+ /* device data */\n" - "+ unsigned long phys_addr;\n" - "+ void* virt_addr; \n" - "+ unsigned irq;\n" - "+\n" - "+ /* states */\n" - "+ u16 cur_config;\n" - "+ u16 cur_intf;\n" - "+ u16 cur_alt;\n" - "+};\n" - "+\n" - "+/* setup request data */\n" - "+union udc_setup_data {\n" - "+ u32 data[2];\n" - "+ struct usb_ctrlrequest request;\n" - "+};\n" - "+#endif /*__KERNEL__*/\n" - "+\n" - "+/*****************************************************************************\n" - "+* Macros\n" - "+*****************************************************************************/\n" - "+\n" - "+/***************************************\n" - "+* SET and GET bitfields in u32 values\n" - "+* via constants for mask/offset:\n" - "+* <bit_field_stub_name> is the text between\n" - "+* UDC_ and _MASK|_OFS of appropiate\n" - "+* constant\n" - "+****************************************/\n" - "+/* set bitfield value in u32 u32Val */\n" - "+#define AMD_ADDBITS(u32Val, bitfield_val, bitfield_stub_name)\\\n" - "+ (((u32Val) & (((u32) ~((u32) bitfield_stub_name##_MASK))))\\\n" - "+ |(((bitfield_val) << ((u32) bitfield_stub_name##_OFS))\\\n" - "+ & ((u32) bitfield_stub_name##_MASK)))\n" - "+\n" - "+/* set bitfield value in zero-initialized u32 u32Val */\n" - "+/* => bitfield bits in u32Val are all zero */\n" - "+#define AMD_INIT_SETBITS(u32Val, bitfield_val, bitfield_stub_name)\\\n" - "+ ((u32Val)\\\n" - "+ |(((bitfield_val) << ((u32) bitfield_stub_name##_OFS))\\\n" - "+ &((u32) bitfield_stub_name##_MASK)))\n" - "+\n" - "+/* get bitfield value from u32 u32Val */\n" - "+#define AMD_GETBITS(u32Val, bitfield_stub_name)\\\n" - "+ ((u32Val & ((u32) bitfield_stub_name##_MASK))\\\n" - "+ >> ((u32) bitfield_stub_name##_OFS))\n" - "+\n" - "+/* SET and GET bits in u32 values ------------------------------------------*/\n" - "+#define AMD_BIT(bit_stub_name) (1 << bit_stub_name)\n" - "+#define AMD_UNMASK_BIT(bit_stub_name) (~AMD_BIT(bit_stub_name))\n" - "+#define AMD_CLEAR_BIT(bit_stub_name) (~AMD_BIT(bit_stub_name))\n" - "+\n" - "+/* misc --------------------------------------------------------------------*/\n" - "+#define DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? \"in\" : \"out\")\n" - "+\n" - "+/* UDC specific macros -----------------------------------------------------*/\n" - "+#ifdef UDC_DMARST_AVAIL\n" - "+#define UDC_DMARST(tmp, dev) \\\n" - "+ DBG(\"DMA machine reset\\n\"); \\\n" - "+ tmp = readl(&dev->regs->cfg); \\\n" - "+ writel(tmp | AMD_BIT(UDC_DEVCFG_DMARST), &dev->regs->cfg); \\\n" - "+ writel(tmp, &dev->regs->cfg);\n" - "+#else\n" - "+#define UDC_DMARST(tmp, dev) {} \n" - "+#endif\n" - "+\n" - "+/* print macros ------------------------------------------------------------*/\n" - "+\n" - "+#ifdef UDC_VERBOSE\n" - "+#ifndef UDC_DEBUG\n" - "+#define UDC_DEBUG\n" - "+#endif\n" - "+#endif\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Macro for printing information in drivers\n" - "+ * \n" - "+ * This macro is used for printing kernel messages in driver source code.\n" - "+ * It should be used for printing useful information about states and called\n" - "+ * functions for normal operation (not for errors and warnings).\n" - "+ * \n" - "+ * \\param fmt is format string for printk\n" - "+ * \\param args... are arguments given to printk (number depends on <fmt>)\n" - "+ * \\return code from printk\n" - "+ */\n" - "+#define INFO(args...) \\\n" - "+ printk(KERN_INFO DRIVER_NAME_FOR_PRINT \": \" args)\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Macro for printing warnings in drivers\n" - "+ * \n" - "+ * This macro is used for printing kernel messages in driver source code.\n" - "+ * It should be used for printing warnings.\n" - "+ * \n" - "+ * \\param fmt is format string for printk\n" - "+ * \\param args... are arguments given to printk (number depends on <fmt>)\n" - "+ * \\return code from printk\n" - "+ */\n" - "+#define WARN(args...) \\\n" - "+ printk(KERN_WARNING DRIVER_NAME_FOR_PRINT \" warning: \" args)\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Macro for printing errors in drivers\n" - "+ * \n" - "+ * This macro is used for printing kernel messages in driver source code.\n" - "+ * It should be used for printing errors.\n" - "+ * \n" - "+ * \\param fmt is format string for printk\n" - "+ * \\param args... are arguments given to printk (number depends on <fmt>)\n" - "+ * \\return code from printk\n" - "+ */\n" - "+#define ERR(args...) \\\n" - "+ printk(KERN_ERR DRIVER_NAME_FOR_PRINT \" error: \" args)\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Macro for printing debug messages in drivers\n" - "+ * \n" - "+ * This macro is used for printing kernel messages in driver source code\n" - "+ * when UDC_DEBUG is defined \n" - "+ * It should be used for printing debug messages.\n" - "+ * \n" - "+ * \\param fmt is format string for printk\n" - "+ * \\param args... are arguments given to printk (number depends on <fmt>)\n" - "+ * \\return code from printk\n" - "+ */\n" - "+#ifdef UDC_DEBUG\n" - "+#define DBG(args...) \\\n" - "+ printk(KERN_DEBUG DRIVER_NAME_FOR_PRINT \" debug: \" args)\n" - "+#else\n" - "+\n" - "+#define DBG(args...) \\\n" - "+ do {} while (0)\n" - "+#endif\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Macro for printing verbose debug messages in drivers\n" - "+ * \n" - "+ * This macro is used for printing kernel messages in driver source code\n" - "+ * when UDC_DEBUG and UDC_VERBOSE is defined\n" - "+ * It should be used for printing debug messages.\n" - "+ * \n" - "+ * \\param fmt is format string for printk\n" - "+ * \\param args... are arguments given to printk (number depends on <fmt>)\n" - "+ * \\return code from printk\n" - "+ */\n" - "+#ifdef UDC_VERBOSE\n" - "+#define VDBG DBG\n" - "+#else\n" - "+#define VDBG(args...) \\\n" - "+\tdo {} while (0)\n" - "+#endif\n" - "+#endif /* #ifdef AU1200UDC_H */\n" - "diff --git a/drivers/usb/gadget/au1200uoc.c b/drivers/usb/gadget/au1200uoc.c\n" - "new file mode 100644\n" - "index 0000000..5297eee\n" - "--- /dev/null\n" - "+++ b/drivers/usb/gadget/au1200uoc.c\n" - "@@ -0,0 +1,2015 @@\n" - "+/*\n" - "+ * AMD Au1200 USB OTG controller driver\n" - "+ */\n" - "+\n" - "+/*\n" - "+ * Copyright (C) 2005 AMD (http://www.amd.com)\n" - "+ * Author: Karsten Boge \n" - "+ *\n" - "+ * This program is free software; you can redistribute it and/or modify\n" - "+ * it under the terms of the GNU General Public License as published by\n" - "+ * the Free Software Foundation; either version 2 of the License, or\n" - "+ * (at your option) any later version.\n" - "+ *\n" - "+ * This program is distributed in the hope that it will be useful,\n" - "+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - "+ * GNU General Public License for more details.\n" - "+ *\n" - "+ * You should have received a copy of the GNU General Public License\n" - "+ * along with this program; if not, write to the Free Software\n" - "+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n" - "+ */\n" - "+\n" - "+\n" - "+/*****************************************************************************\n" - "+ * Includes\n" - "+ *****************************************************************************/\n" - "+\n" - "+#include <linux/config.h>\n" - "+#include <linux/module.h>\n" - "+#include <linux/pci.h>\n" - "+#include <linux/kernel.h>\n" - "+#include <linux/version.h>\n" - "+#include <linux/delay.h>\n" - "+#include <linux/ioport.h>\n" - "+#include <linux/sched.h>\n" - "+#include <linux/slab.h>\n" - "+#include <linux/smp_lock.h>\n" - "+#include <linux/errno.h>\n" - "+#include <linux/init.h>\n" - "+#include <linux/timer.h>\n" - "+#include <linux/list.h>\n" - "+#include <linux/interrupt.h>\n" - "+\n" - "+#include <asm/byteorder.h>\n" - "+#include <asm/io.h>\n" - "+#include <asm/irq.h>\n" - "+#include <asm/system.h>\n" - "+#include <asm/unaligned.h>\n" - "+\n" - "+#ifdef CONFIG_USB_OTG_TEST_INTERFACE\n" - "+#ifndef CONFIG_USB_OTG\n" - "+#define CONFIG_USB_OTG\n" - "+#endif\n" - "+#endif\n" - "+\n" - "+/* #define DEBUG */\n" - "+/* #define VERBOSE */\n" - "+\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+#include <asm/mach-au1x00/au1000.h>\n" - "+#include <asm/mach-au1x00/au1000_gpio.h>\n" - "+#include <linux/platform_device.h>\n" - "+#endif\n" - "+\n" - "+#include <linux/usb.h>\n" - "+#include <linux/usb_gadget.h>\n" - "+#include <linux/usb_otg.h>\n" - "+\n" - "+#define\tDRIVER_DESC\t\t\"AMD Au1200 USB OTG Controller\"\n" - "+#define\tDRIVER_VERSION\t\t\"01.00.0201 - $Revision: #3 $\"\n" - "+#define DRIVER_NAME_FOR_PRINT OTG_DRIVER_NAME\n" - "+\n" - "+#include \"au1200otg.h\"\n" - "+#include \"au1200uoc.h\"\n" - "+\n" - "+\n" - "+/*****************************************************************************\n" - "+ * Function Declarations\n" - "+ *****************************************************************************/\n" - "+\n" - "+#ifdef CONFIG_USB_OTG_TEST_INTERFACE\n" - "+static int otg_test_bind(struct otg **);\n" - "+static int otg_test_unbind(struct otg **);\n" - "+#endif\n" - "+#ifdef CONFIG_USB_OTG\n" - "+static int otg_app_request(u32);\n" - "+static int otg1200_set_host (struct otg_transceiver *, struct usb_bus *);\n" - "+static int otg1200_set_power (struct otg_transceiver *, unsigned);\n" - "+static int otg1200_start_srp (struct otg_transceiver *);\n" - "+static int otg1200_start_hnp (struct otg_transceiver *);\n" - "+#endif\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+static u32 otg_app_query(int);\n" - "+static int otg1200_set_peripheral (struct otg_transceiver *,\n" - "+ struct usb_gadget *);\n" - "+#endif\n" - "+\n" - "+\n" - "+/*****************************************************************************\n" - "+ * Data\n" - "+ *****************************************************************************/\n" - "+\n" - "+static const char driver_name [] = OTG_DRIVER_NAME;\n" - "+static const char driver_desc [] = DRIVER_DESC;\n" - "+\n" - "+static struct otg *the_controller;\n" - "+static const char *transceiver_label = \"au1200_otg\";\n" - "+\n" - "+static u32 init_state = 0;\n" - "+#ifdef OTG_HNP_ERR_LOG\n" - "+int hnp_err = 0;\n" - "+#endif\n" - "+\n" - "+#ifdef CONFIG_USB_OTG_TEST_INTERFACE\n" - "+static struct usb_otg_test_extension otg_test_extension = {\n" - "+\t.bind = otg_test_bind,\n" - "+\t.unbind = otg_test_unbind,\n" - "+\t.request = otg_app_request,\n" - "+\t.query = otg_app_query\n" - "+};\n" - "+#endif\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+struct usb_otg_gadget_extension otg_gadget_extension = {\n" - "+#ifdef CONFIG_USB_OTG\n" - "+\t.request = otg_app_request,\n" - "+#else\n" - "+\t.request = NULL,\n" - "+#endif\n" - "+\t.query = otg_app_query,\n" - "+\t.notify = NULL\n" - "+};\n" - "+\n" - "+static u32 state_mask;\n" - "+u32 otg_tmr_high_count = 0;\n" - "+#endif\n" - "+\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+#ifdef USE_AU1200_PCI_DUMMY\n" - "+static struct pci_dev pdev_dummy;\n" - "+#endif\n" - "+#endif\n" - "+\n" - "+\n" - "+/*****************************************************************************\n" - "+ * Function Definitions\n" - "+ *****************************************************************************/\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * fill OTG transceiver struct\n" - "+ *\n" - "+ * \\param transceiver OTG transceiver\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+static inline void otg_init_transceiver (struct otg_transceiver *transceiver)\n" - "+{\n" - "+ transceiver_to_otg(transceiver)->prv_state = OTG_STATE_UNDEFINED;\n" - "+\ttransceiver_to_otg(transceiver)->params = 0;\n" - "+\ttransceiver_to_otg(transceiver)->hostcount = 0;\n" - "+\ttransceiver_to_otg(transceiver)->otg_priv = (void *) &otg_gadget_extension;\n" - "+\n" - "+\ttransceiver->dev = NULL;\n" - "+\ttransceiver->label = transceiver_label;\n" - "+\ttransceiver->default_a = 0;\n" - "+\ttransceiver->state = OTG_STATE_UNDEFINED;\n" - "+\ttransceiver->host = NULL;\n" - "+#ifdef CONFIG_USB_OTG_HIGHSPEED\n" - "+\ttransceiver->companion = NULL;\n" - "+#endif\n" - "+\ttransceiver->gadget = NULL;\n" - "+\ttransceiver->port_status = 0;\n" - "+\ttransceiver->port_change = 0;\n" - "+#ifdef CONFIG_USB_OTG\n" - "+\ttransceiver->set_host = otg1200_set_host;\n" - "+\ttransceiver->set_peripheral = otg1200_set_peripheral;\n" - "+\ttransceiver->set_power = otg1200_set_power;\n" - "+\ttransceiver->start_srp = otg1200_start_srp;\n" - "+\ttransceiver->start_hnp = otg1200_start_hnp;\n" - "+#else\n" - "+\ttransceiver->set_host = NULL;\n" - "+\ttransceiver->set_peripheral = otg1200_set_peripheral;\n" - "+\ttransceiver->set_power = NULL;\n" - "+\ttransceiver->start_srp = NULL;\n" - "+\ttransceiver->start_hnp = NULL;\n" - "+#endif\n" - "+}\n" - "+\n" - "+#ifdef CONFIG_USB_OTGMUX_GADGET\n" - "+/**\n" - "+ * \\brief\n" - "+ * OTG state change\n" - "+ *\n" - "+ * subset of OTG states to support the gadget only or\n" - "+ * ID pin configuration\n" - "+ *\n" - "+ * \\param otg OTG controller info\n" - "+ * \\param event_code event that requested a state change\n" - "+ * \\param pEvt_mask\n" - "+ *\n" - "+ * \\return events that were not handled here\n" - "+ */\n" - "+u32 otg_change_state (struct otg *otg, u32 _event, u32 *pEvt_mask)\n" - "+{\n" - "+\tu32 event_code = _event;\n" - "+\tu32 uoc_status = get_status (otg);\n" - "+\n" - "+\tif (GOT_EVENT (OTG_GADGET_READY, event_code)\n" - "+\n" - "+#ifdef CONFIG_USB_OTGMUX_IDPIN\n" - "+\n" - "+\t || GOT_EVENT (OTG_HOST_READY, event_code)\n" - "+#endif\n" - "+\t ) {\n" - "+\n" - "+\t\tif (((IS_FLAG_RES (otg, OTG_GADGET_READY))\n" - "+\n" - "+#ifdef CONFIG_USB_OTGMUX_IDPIN\n" - "+\n" - "+\t\t || (IS_FLAG_RES (otg, OTG_HOST_READY))\n" - "+#endif\n" - "+ )\n" - "+\n" - "+\t\t && ((otg->transceiver.state & OTG_STATE_MASK) !=\n" - "+\t\t OTG_STATE_UNDEFINED)) {\n" - "+\n" - "+\t\t\t/* driver unload, back to \"not ready\" state */\n" - "+\n" - "+\t\t\tCHANGE_STATE (otg, OTG_STATE_UNDEFINED, pEvt_mask);\n" - "+\t\t\tRES_EVENT ((OTG_GADGET_READY | OTG_HOST_READY),\n" - "+\t\t\t event_code);\n" - "+\t\t}\n" - "+\t}\n" - "+\tif ((OTG_INT_TMX & event_code) && otg_tmr_high_count) {\n" - "+\n" - "+\t\t/* a long timer is running : decrement the high part */\n" - "+\n" - "+\t\trestart_timer (otg);\n" - "+\t\totg_tmr_high_count--;\n" - "+\t\tRES_EVENT (OTG_INT_TMX, event_code);\n" - "+\t}\n" - "+\n" - "+\tdo switch (otg->transceiver.state & OTG_STATE_MASK) {\n" - "+\n" - "+\t/* NOT_ASSIGNED (yet): init state, 1st time after loading */\n" - "+\t/* ====================================================== */\n" - "+\n" - "+\tcase OTG_STATE_UNDEFINED :\n" - "+\n" - "+\t\tCHECK_STATE (otg, OTG_STATE_UNDEFINED, pEvt_mask);\n" - "+\n" - "+\t\tif (IS_FLAG_RES (otg, OTG_FLAGS_ACTIV)) {\n" - "+\n" - "+\t\t\t/* seems to be the first time: let it run ! */\n" - "+\n" - "+\t\t\tSET_FLAG (otg, OTG_FLAGS_ACTIV);\n" - "+\t\t}\n" - "+\n" - "+\t\t/* muxer is still neutral */\n" - "+\n" - "+\t\tRES_EVENT ((OTG_GADGET_READY | OTG_HOST_READY |\n" - "+\t\t OTG_INT_IDC | OTG_INT_TMX), event_code);\n" - "+\n" - "+\t\tif ((IS_FLAG_SET (otg, OTG_GADGET_READY))\n" - "+\n" - "+#ifdef CONFIG_USB_OTGMUX_IDPIN\n" - "+\n" - "+\t\t || (IS_FLAG_SET (otg, OTG_HOST_READY))\n" - "+#endif\n" - "+\t\t ) {\n" - "+\n" - "+\t\t\t/* NOT_READY (substate): drivers now ready */\n" - "+\t\t\t/* ======================================= */\n" - "+\n" - "+#ifdef CONFIG_USB_OTGMUX_IDPIN\n" - "+\n" - "+\t\t\tif (IS_BIT_RES (OTG_STS_ID, uoc_status)) {\n" - "+\n" - "+\t\t\t\t/* ID pin connected: A-device (host) */\n" - "+\n" - "+\t\t\t\tCHANGE_STATE (otg, OTG_STATE_A_HOST,\n" - "+\t\t\t\t\t pEvt_mask);\n" - "+\t\t\t}\n" - "+\t\t\telse {\n" - "+\t\t\t\t/* ID pin not connected: disable (neutral) */\n" - "+#endif\n" - "+\t\t\t\tCHANGE_STATE (otg, OTG_STATE_B_IDLE,\n" - "+\t\t\t\t\t pEvt_mask);\n" - "+\n" - "+#ifdef CONFIG_USB_OTGMUX_IDPIN\n" - "+\t\t\t}\n" - "+#endif\n" - "+\t\t}\n" - "+\t\tbreak;\n" - "+\n" - "+#ifdef CONFIG_USB_OTGMUX_IDPIN\n" - "+\n" - "+\t/* A: ID pin is connected, A-device drives VBus */\n" - "+\t/* ============================================ */\n" - "+\n" - "+\tcase OTG_STATE_A_HOST :\n" - "+\n" - "+\t\tCHECK_STATE (otg, OTG_STATE_A_HOST, pEvt_mask);\n" - "+\n" - "+\t\tif (IS_BIT_SET (OTG_STS_ID, uoc_status)) {\n" - "+\n" - "+\t\t\t/* ID change => B_IDLE */\n" - "+\n" - "+\t\t\tRES_EVENT ((OTG_INT_IDC | OTG_INT_PCC), event_code);\n" - "+\t\t\tCHANGE_STATE (otg, OTG_STATE_B_IDLE, pEvt_mask);\n" - "+\t\t}\n" - "+\t\tbreak;\n" - "+\n" - "+\t/* B: ID pin is not connected */\n" - "+\t/* ========================== */\n" - "+#endif\n" - "+\n" - "+\tcase OTG_STATE_B_IDLE :\n" - "+\n" - "+\t\t/* B_IDLE: init state for B-devices */\n" - "+\t\t/* monitor VBus, no connection, no activity */\n" - "+\n" - "+\t\tCHECK_STATE (otg, OTG_STATE_B_IDLE, pEvt_mask);\n" - "+\n" - "+#ifdef CONFIG_USB_OTGMUX_IDPIN\n" - "+\n" - "+\t\tif (IS_BIT_RES (OTG_STS_ID, uoc_status)) {\n" - "+\n" - "+\t\t\t/* ID pin changed => A_HOST */\n" - "+\n" - "+\t\t\tRES_EVENT (OTG_INT_IDC, event_code);\n" - "+\t\t\tCHANGE_STATE (otg, OTG_STATE_A_HOST, pEvt_mask);\n" - "+\t\t}\n" - "+\t\telse if (IS_BIT_SET (OTG_STS_SESSVLD, uoc_status))\n" - "+#else\n" - "+\t\tif (IS_BIT_SET (OTG_STS_SESSVLD, uoc_status))\n" - "+#endif\n" - "+\t\t{\n" - "+\t\t\t/* Session valid => B_PERIPHERAL */\n" - "+\n" - "+\t\t\tRES_EVENT (OTG_INT_SVC, event_code);\n" - "+\t\t\tCHANGE_STATE (otg, OTG_STATE_B_PERIPHERAL, pEvt_mask);\n" - "+#ifndef CONFIG_TEST_MODE_ONLY\n" - "+\t\t\tif (otg_gadget_extension.notify) {\n" - "+\t\t\t\totg_gadget_extension.notify (\n" - "+\t\t\t\t\tOTG_GADGET_EVT_SVALID);\n" - "+\t\t\t}\n" - "+#endif\n" - "+\t\t}\n" - "+\t\tbreak;\n" - "+\n" - "+\tcase OTG_STATE_B_PERIPHERAL :\n" - "+\n" - "+\t\t/* B_PERIPHERAL: connected to A-host, responding */\n" - "+\t\t/* VBus driven by A, remote activity */\n" - "+\n" - "+\t\tCHECK_STATE (otg, OTG_STATE_B_PERIPHERAL, pEvt_mask);\n" - "+\n" - "+#ifdef CONFIG_USB_OTGMUX_IDPIN\n" - "+\n" - "+\t\tif (IS_BIT_RES (OTG_STS_ID, uoc_status) ||\n" - "+\t\t IS_BIT_RES (OTG_STS_SESSVLD, uoc_status))\n" - "+#else\n" - "+\t\tif (IS_BIT_RES (OTG_STS_SESSVLD, uoc_status))\n" - "+#endif\n" - "+\t\t{\n" - "+\t\t\t/* ID pin changed | ~Session valid => B_IDLE */\n" - "+\n" - "+\t\t\tRES_EVENT ((OTG_INT_IDC | OTG_INT_SVC), event_code);\n" - "+\t\t\tCHANGE_STATE (otg, OTG_STATE_B_IDLE, pEvt_mask);\n" - "+#ifndef CONFIG_TEST_MODE_ONLY\n" - "+\t\t\tif (otg_gadget_extension.notify) {\n" - "+\t\t\t\totg_gadget_extension.notify (\n" - "+\t\t\t\t\tOTG_GADGET_EVT_SVDROP);\n" - "+\t\t\t}\n" - "+#endif\n" - "+\t\t}\n" - "+\t\tbreak;\n" - "+\n" - "+\t/* unlikely */ default :\n" - "+\n" - "+\t\t/* something went wrong */\n" - "+\n" - "+\t\tBUG ();\n" - "+\t\tbreak;\n" - "+\t}\n" - "+\twhile ((otg->transceiver.state ^ otg->prv_state) &\n" - "+\t OTG_STATE_MASK);\n" - "+\n" - "+\tDBG (\"OTG-state change done\\n\");\n" - "+\n" - "+\treturn event_code;\n" - "+}\n" - "+#endif /* CONFIG_USB_OTGMUX_GADGET */\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * OTG state change request\n" - "+ *\n" - "+ * \\param dev OTG device info\n" - "+ * \\param params\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+static inline void otg_req_state_chg (struct otg *otg, u32 params)\n" - "+{\n" - "+\tu32 temp, tmp2, flags;\n" - "+\n" - "+\tlocal_irq_save (flags);\n" - "+\n" - "+\t/* disable global OTG interrupt, clear int status: */\n" - "+\ttemp = ~((u32) OTG_INT_GLOBAL) & readl (&otg->regs->inten);\n" - "+\twritel (temp, &otg->regs->inten);\n" - "+\ttmp2 = readl (&otg->regs->intr);\n" - "+\twritel (tmp2, &otg->regs->intr);\n" - "+\ttemp &= tmp2;\n" - "+\n" - "+\t/* update OTG state: */\n" - "+\totg_change_state (otg, (params | temp), &temp);\n" - "+\n" - "+\t/* enable global OTG interrupt: */\n" - "+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/\n" - "+/*** HS-A0 WA: BUG-3950: gadget needs disconnect notification ***/\n" - "+#ifdef UDC_HSA0_WORKAROUNDS\n" - "+\tstate_mask = ~temp & OTG_INT_ADDS;\n" - "+\twritel ((OTG_INT_ADDS | temp | OTG_INT_GLOBAL), &otg->regs->inten);\n" - "+#else\n" - "+\twritel ((temp | OTG_INT_GLOBAL), &otg->regs->inten);\n" - "+#endif\n" - "+\tlocal_irq_restore (flags);\n" - "+}\n" - "+#endif /* CONFIG_USB_OTG || CONFIG_USB_OTGMUX_GADGET */\n" - "+\n" - "+#ifdef CONFIG_USB_OTG_TEST_INTERFACE\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Bind the OTG controller to the test driver\n" - "+ *\n" - "+ * \\param dev otg controller info\n" - "+ *\n" - "+ * \\return error code\n" - "+ */\n" - "+static int otg_test_bind (struct otg **otg)\n" - "+{\n" - "+\t*otg = the_controller;\n" - "+\tif (!*otg)\n" - "+\t\treturn -EINVAL;\n" - "+#ifdef CONFIG_TEST_MODE_ONLY\n" - "+\tINFO (\"bind OTG driver to the test driver, enable device\\n\");\n" - "+\tSET_FLAG (*otg, OTG_HOST_READY | OTG_GADGET_READY);\n" - "+\tif (IS_FLAG_SET (*otg, OTG_FLAGS_ACTIV)) {\n" - "+\t\totg_req_state_chg (*otg, OTG_HOST_READY | OTG_GADGET_READY);\n" - "+\t}\n" - "+\t(*otg)->transceiver.gadget = (struct usb_gadget *) 1;\n" - "+#else\n" - "+\tINFO (\"bind OTG driver to the test interface\\n\");\n" - "+#endif\n" - "+\treturn 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Unbind the OTG controller from the test driver\n" - "+ *\n" - "+ * \\param dev otg controller info\n" - "+ *\n" - "+ * \\return error code\n" - "+ */\n" - "+static int otg_test_unbind (struct otg **otg)\n" - "+{\n" - "+#ifdef CONFIG_TEST_MODE_ONLY\n" - "+\tINFO (\"unbind OTG driver from the test driver, disable device\\n\");\n" - "+\t(*otg)->transceiver.gadget = NULL;\n" - "+\tRES_FLAG (*otg, OTG_HOST_READY | OTG_GADGET_READY);\n" - "+\tif (IS_FLAG_SET (*otg, OTG_FLAGS_ACTIV)) {\n" - "+\t\totg_req_state_chg (*otg, OTG_HOST_READY | OTG_GADGET_READY);\n" - "+\t}\n" - "+\t*otg = NULL;\n" - "+\treturn otg_unbind_gadget ();\n" - "+#else\n" - "+\tINFO (\"unbind OTG driver from the test interface\\n\");\n" - "+\t*otg = NULL;\n" - "+\treturn 0;\n" - "+#endif\n" - "+}\n" - "+#endif /* CONFIG_USB_OTG_TEST_INTERFACE */\n" - "+\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * OTG set transceiver:\n" - "+ *\n" - "+ * \\param pointer to transceiver struct\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+int otg_set_transceiver (struct otg_transceiver *transceiver)\n" - "+{\n" - "+\tstruct otg *otg = the_controller;\n" - "+\n" - "+\tif (unlikely (transceiver != otg_to_transceiver (otg))) {\n" - "+\t\tERR (\"USB OTG: unknown transceiver\\n\");\n" - "+\t\treturn -EINVAL;\n" - "+\t}\n" - "+\telse {\n" - "+\t\treturn 0;\n" - "+\t}\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * OTG get transceiver: provide info to others\n" - "+ *\n" - "+ * \\param void\n" - "+ *\n" - "+ * \\return pointer to transceiver struct\n" - "+ */\n" - "+struct otg_transceiver * otg_get_transceiver (void)\n" - "+{\n" - "+\treturn otg_to_transceiver (the_controller);\n" - "+}\n" - "+#endif\n" - "+\n" - "+#ifdef CONFIG_USB_OTG\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Bind/unbind the OTG controller to/from usbcore\n" - "+ *\n" - "+ * \\param transceiver this transceiver\n" - "+ * \\param bus usb bus the host is assigned to\n" - "+ *\n" - "+ * \\return error code\n" - "+ */\n" - "+static int otg1200_set_host (struct otg_transceiver *transceiver,\n" - "+ struct usb_bus *bus)\n" - "+{\n" - "+\tstruct otg *otg = the_controller;\n" - "+\tint flag, count = 0;\n" - "+\n" - "+\tif (unlikely (transceiver != otg_to_transceiver (otg))) {\n" - "+\t\tERR (\"USB OTG: unknown transceiver\\n\");\n" - "+\t\treturn -EINVAL;\n" - "+\t}\n" - "+\tif (bus) {\n" - "+\n" - "+\t\t/* This bus supports OTG */\n" - "+\n" - "+\t\tif (transceiver->host) {\n" - "+\t\t\tcount++;\n" - "+\t\t}\n" - "+#ifdef CONFIG_USB_OTG_HIGHSPEED\n" - "+\t\tif (transceiver->companion) {\n" - "+\t\t\tcount++;\n" - "+\t\t}\n" - "+\t\t/* Now checking consistence ... */\n" - "+\t\t/* Depending on the driver loading sequence is possible */\n" - "+\t\t/* that the \"Load state defaults\" function was already */\n" - "+\t\t/* called so the state could be inconsistent. */\n" - "+\t\tif (transceiver->host && transceiver->companion) {\n" - "+\t\t\tflag = (transceiver->host->is_b_host |\n" - "+\t\t\t transceiver->companion->is_b_host);\n" - "+\t\t\tif (transceiver->gadget &&\n" - "+\t\t\t !transceiver->gadget->is_a_peripheral) {\n" - "+\t\t\t\tflag |= 1;\n" - "+\t\t\t}\n" - "+\t\t\ttransceiver->host->is_b_host = flag;\n" - "+\t\t\ttransceiver->companion->is_b_host = flag;\n" - "+\t\t}\n" - "+#endif\n" - "+\t\tDBG (\"USB OTG: bind host: bus %d, port %d (OTG host #%d)\\n\",\n" - "+\t\t bus->busnum, bus->otg_port, count);\n" - "+\t\tif (IS_FLAG_RES (otg, OTG_HOST_READY)) {\n" - "+\t\t\tRES_FLAG (otg, OTG_A_BUS_DROP);\n" - "+\t\t\tSET_FLAG (otg, OTG_HOST_READY | OTG_A_BUS_REQ);\n" - "+\t\t\tif (IS_FLAG_SET (otg, OTG_FLAGS_ACTIV)) {\n" - "+\t\t\t\totg_req_state_chg (otg, OTG_HOST_READY);\n" - "+\t\t\t}\n" - "+\t\t}\n" - "+\t}\n" - "+\telse {\n" - "+#ifdef CONFIG_USB_OTG_HIGHSPEED\n" - "+\t\tif (transceiver->companion) {\n" - "+\t\t\tcount++;\n" - "+\t\t}\n" - "+#endif\n" - "+\t\tif (transceiver->host) {\n" - "+\t\t\tcount++;\n" - "+\t\t}\n" - "+\t\tDBG (\"USB OTG: unbind host (actual OTG hosts: %d)\\n\", count);\n" - "+\t\tif (!count) {\n" - "+\t\t\tRES_FLAG (otg, OTG_HOST_READY | OTG_A_BUS_REQ);\n" - "+\t\t\tSET_FLAG (otg, OTG_A_BUS_DROP);\n" - "+\t\t\tif (IS_FLAG_SET (otg, OTG_FLAGS_ACTIV)) {\n" - "+\t\t\t\totg_req_state_chg (otg, OTG_HOST_READY);\n" - "+\t\t\t}\n" - "+\t\t}\n" - "+\t}\n" - "+\treturn 0;\n" - "+}\n" - "+#endif /* CONFIG_USB_OTG */\n" - "+\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Bind/unbind the OTG controller to/from usb gadget\n" - "+ *\n" - "+ * \\param transceiver this transceiver\n" - "+ * \\param gadget usb gadget info\n" - "+ *\n" - "+ * \\return error code\n" - "+ */\n" - "+static int otg1200_set_peripheral (struct otg_transceiver *transceiver,\n" - "+ struct usb_gadget *gadget)\n" - "+{\n" - "+\tstruct otg *otg = the_controller;\n" - "+\tint flag = 0;\n" - "+\n" - "+\tif (unlikely (transceiver != otg_to_transceiver (otg))) {\n" - "+\t\tERR (\"USB OTG: unknown transceiver\\n\");\n" - "+\t\treturn -EINVAL;\n" - "+\t}\n" - "+\tif (gadget) {\n" - "+\t\tif (transceiver->gadget) {\n" - "+\t\t\tERR (\"USB gadget: OTG driver already registered\\n\");\n" - "+\t\t\treturn -EBUSY;\n" - "+\t\t}\n" - "+\t\tDBG (\"bind OTG driver to USB gadget\\n\");\n" - "+\t\ttransceiver->gadget = gadget;\n" - "+\t\tSET_FLAG (otg, OTG_GADGET_READY | OTG_B_BUS_REQ);\n" - "+\n" - "+\t\t/* Now checking consistence ... */\n" - "+\t\t/* Depending on the driver loading sequence is possible */\n" - "+\t\t/* that the \"Load state defaults\" function was already */\n" - "+\t\t/* called so the state could be inconsistent. */\n" - "+#ifdef CONFIG_USB_OTG_HIGHSPEED\n" - "+\t\tif (transceiver->companion &&\n" - "+\t\t !transceiver->companion->is_b_host) {\n" - "+\t\t\tflag |= 1;\n" - "+\t\t}\n" - "+#endif\n" - "+\t\tif (transceiver->host && !transceiver->host->is_b_host) {\n" - "+\t\t\tflag |= 1;\n" - "+\t\t}\n" - "+\t\ttransceiver->gadget->is_a_peripheral = flag;\n" - "+\n" - "+\t\tif (IS_FLAG_SET (otg, OTG_FLAGS_ACTIV)) {\n" - "+\t\t\totg_req_state_chg (otg, OTG_GADGET_READY);\n" - "+\t\t}\n" - "+\t\tif (IS_BIT_SET (OTG_STS_SESSVLD, readl (&otg->regs->sts)) &&\n" - "+\t\t (otg->transceiver.state & OTG_STATE_MASK)\n" - "+\t\t == OTG_STATE_B_PERIPHERAL) {\n" - "+\t\t\tVDBG (\"calling gadget: connect\\n\");\n" - "+\t\t\tif (otg_gadget_extension.notify) {\n" - "+\t\t\t\totg_gadget_extension.notify (\n" - "+\t\t\t\tOTG_GADGET_EVT_SVALID);\n" - "+\t\t\t}\n" - "+\t\t}\n" - "+\t\treturn 0;\n" - "+\t}\n" - "+\telse {\n" - "+\t\tDBG (\"unbind OTG driver from USB gadget\\n\");\n" - "+\t\tRES_FLAG (otg, OTG_GADGET_READY | OTG_B_BUS_REQ);\n" - "+\t\tif (IS_FLAG_SET (otg, OTG_FLAGS_ACTIV)) {\n" - "+\t\t\totg_req_state_chg (otg, OTG_GADGET_READY);\n" - "+\t\t}\n" - "+\t\ttransceiver->gadget = NULL;\n" - "+\t\treturn 0;\n" - "+\t}\n" - "+}\n" - "+#endif /* CONFIG_USB_OTGMUX || CONFIG_USB_OTGMUX_GADGET */\n" - "+\n" - "+#ifdef CONFIG_USB_OTG\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Set host controllers power budget\n" - "+ *\n" - "+ * \\param transceiver this transceiver\n" - "+ * \\param mA value to fill in\n" - "+ *\n" - "+ * \\return error code\n" - "+ */\n" - "+static int otg1200_set_power (struct otg_transceiver *transceiver,\n" - "+ unsigned mA)\n" - "+{\n" - "+\tstruct otg *otg = the_controller;\n" - "+\n" - "+\tif (unlikely (transceiver != otg_to_transceiver (otg))) {\n" - "+\t\tERR (\"USB OTG: unknown transceiver\\n\");\n" - "+\t\treturn -EINVAL;\n" - "+\t}\n" - "+\t/* TODO kboge: do we need to support this ? */\n" - "+\n" - "+\tDBG (\"USB OTG: power budget change not supported\\n\");\n" - "+\treturn 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Start a HNP request\n" - "+ *\n" - "+ * \\param transceiver this transceiver\n" - "+ *\n" - "+ * \\return error code\n" - "+ */\n" - "+static int otg1200_start_hnp (struct otg_transceiver *transceiver)\n" - "+{\n" - "+\tstruct otg *otg = the_controller;\n" - "+\n" - "+\tif (unlikely (transceiver != otg_to_transceiver (otg))) {\n" - "+\t\tERR (\"USB OTG: unknown transceiver\\n\");\n" - "+\t\treturn -ENODEV;\n" - "+\t}\n" - "+\tif (transceiver->default_a\n" - "+\t && (!transceiver->host || !transceiver->host->b_hnp_enable)\n" - "+#ifdef CONFIG_USB_OTG_HIGHSPEED\n" - "+\t && (!transceiver->companion || !transceiver->companion->b_hnp_enable)\n" - "+#endif\n" - "+\t )\n" - "+\t\treturn -ENOTCONN;\n" - "+\tif (!transceiver->default_a &&\n" - "+\t (!transceiver->gadget || !transceiver->gadget->b_hnp_enable))\n" - "+\t\treturn -ENOTCONN;\n" - "+\n" - "+\tswitch (transceiver->state & OTG_STATE_MASK) {\n" - "+\tcase OTG_STATE_B_HOST:\n" - "+\tcase OTG_STATE_A_HOST:\n" - "+\tcase OTG_STATE_A_PERIPHERAL:\n" - "+\t\tbreak;\n" - "+\tdefault:\n" - "+\t\tERR (\"USB OTG: wrong OTG state for role swap\\n\");\n" - "+\t\treturn -EILSEQ;\n" - "+\t}\n" - "+\treturn 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Start a SRP request\n" - "+ *\n" - "+ * \\param transceiver this transceiver\n" - "+ *\n" - "+ * \\return error code\n" - "+ */\n" - "+static int otg1200_start_srp (struct otg_transceiver *transceiver)\n" - "+{\n" - "+\tstruct otg *otg = the_controller;\n" - "+\n" - "+\tif (unlikely (transceiver != otg_to_transceiver (otg))) {\n" - "+\t\tERR (\"USB OTG: unknown transceiver\\n\");\n" - "+\t\treturn -EINVAL;\n" - "+\t}\n" - "+\tif ((transceiver->state & OTG_STATE_MASK) != OTG_STATE_B_IDLE) {\n" - "+\t\tRES_FLAG (otg, OTG_B_aSSN_REQ);\n" - "+\t\tERR (\"USB OTG: wrong OTG state for SRP\\n\");\n" - "+\t\treturn -EBUSY;\n" - "+\t}\n" - "+\tSET_FLAG (otg, OTG_B_aSSN_REQ);\n" - "+\totg_req_state_chg (otg, OTG_B_aSSN_REQ);\n" - "+\treturn 0;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Start a USB host enumeration\n" - "+ *\n" - "+ * \\param transceiver this transceiver\n" - "+ *\n" - "+ * \\return error code\n" - "+ */\n" - "+int otg_hnp_start_enum (struct otg_transceiver *transceiver)\n" - "+{\n" - "+\tstruct otg *otg = the_controller;\n" - "+\tstruct usb_bus *bus;\n" - "+\tint status = 0;\n" - "+\n" - "+\tif (unlikely (transceiver != otg_to_transceiver (otg))) {\n" - "+\t\tERR (\"USB OTG: unknown transceiver\\n\");\n" - "+\t\treturn -EINVAL;\n" - "+\t}\n" - "+\tif (otg->transceiver.state == OTG_STATE_B_HOST) {\n" - "+\n" - "+\t\tbus = otg->transceiver.host;\n" - "+\n" - "+#ifdef CONFIG_USB_OTG_HIGHSPEED\n" - "+\n" - "+\t\tif (!bus || !bus->is_b_host) {\n" - "+\t\t\tbus = otg->transceiver.companion;\n" - "+\t\t}\n" - "+#endif\n" - "+\t\tif (bus && bus->is_b_host) {\n" - "+\t\t\tDBG (\"USB OTG: in HNP, start enumeration ...\\n\");\n" - "+\t\t\tstatus = usb_bus_start_enum (bus, bus->otg_port);\n" - "+\t\t}\n" - "+\t\telse {\n" - "+\t\t\tDBG (\"USB OTG: no device to enumerate\\n\");\n" - "+\t\t}\n" - "+\t}\n" - "+\telse {\n" - "+\t\tDBG (\"USB OTG: in HNP: wrong state %02x\\n\",\n" - "+\t\t otg->transceiver.state);\n" - "+\t}\n" - "+\treturn status;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * OTG application request\n" - "+ *\n" - "+ * \\param params\n" - "+ *\n" - "+ * \\return OTG_APP_REQ_ACK\n" - "+ */\n" - "+static int otg_app_request (u32 params)\n" - "+{\n" - "+\tstruct otg *otg = the_controller;\n" - "+\tu32 flags = params;\n" - "+\tstruct usb_bus *bus;\n" - "+\n" - "+\tif (OTG_UDC_RWK_REQ & flags) {\n" - "+\n" - "+\t\tif (otg_gadget_extension.notify) {\n" - "+\t\t\totg_gadget_extension.notify (OTG_GADGET_REQ_WAKE);\n" - "+\t\t}\n" - "+\t\tflags &= ~((u32) OTG_UDC_RWK_REQ);\n" - "+\t}\n" - "+\n" - "+\tif (OTG_AB_HNP_REQ & flags) {\n" - "+\n" - "+\t\t/* request HNP */\n" - "+\n" - "+\t\tbus = otg->transceiver.host;\n" - "+\t\tif (!bus->b_hnp_enable) {\n" - "+\n" - "+#ifdef CONFIG_USB_OTG_HIGHSPEED\n" - "+\t\t\tbus = otg->transceiver.companion;\n" - "+\t\t}\n" - "+\t\tif (!bus->b_hnp_enable) {\n" - "+#endif\n" - "+\t\t\tINFO (\"HNP not enabled, ignoring request\\n\");\n" - "+\t\t}\n" - "+\t\telse {\n" - "+\t\t\tif (!otg1200_start_hnp (&otg->transceiver) &&\n" - "+\t\t\t bus->root_hub->children [bus->otg_port - 1]) {\n" - "+\t\t\t\tusb_suspend_device (bus->root_hub->children [bus->otg_port - 1],\n" - "+\t\t\t\t PM_SUSPEND_MEM);\n" - "+\t\t\t}\n" - "+\t\t\telse {\n" - "+\t\t\t\tERR (\"no device found for HNP\\n\");\n" - "+\t\t\t}\n" - "+\t\t}\n" - "+\t\tflags &= ~((u32) OTG_AB_HNP_REQ);\n" - "+\t}\n" - "+\n" - "+\tif (OTG_A_CLR_ERR & flags) {\n" - "+\n" - "+\t\t/* request to clear error flags */\n" - "+\n" - "+\t\tflags |= OTG_A_VBUS_FAILED;\n" - "+\t}\n" - "+\n" - "+\t/* create mask of flags to clear */\n" - "+\n" - "+\tflags &= (OTG_B_SRP_ERROR | OTG_A_VBUS_FAILED);\n" - "+\n" - "+\tif (flags) {\n" - "+\n" - "+\t\t/* reset error flags if requested */\n" - "+\n" - "+\t\tRES_FLAG (otg, (flags));\n" - "+\t}\n" - "+\n" - "+\t/* prepare for pending requests (no more actions on OTG_A_bHNP_EN) */\n" - "+\n" - "+\tflags = params & SW_REQUEST_MASK;\n" - "+\tSET_FLAG (otg, (flags));\n" - "+\n" - "+\tif (OTG_A_BUS_DROP & flags) {\n" - "+\n" - "+\t\t/* request to drop A-VBus: reset \"rise\" request if pending */\n" - "+\n" - "+\t\tflags &= ~OTG_A_BUS_REQ;\n" - "+\t\tRES_FLAG (otg, OTG_A_BUS_REQ);\n" - "+\t}\n" - "+\tif (OTG_A_BUS_REQ & flags) {\n" - "+\n" - "+\t\t/* request to rise A-VBus: reset \"drop\" request if pending */\n" - "+\n" - "+\t\tRES_FLAG (otg, OTG_A_BUS_DROP);\n" - "+\t}\n" - "+\tif (OTG_B_BUS_DIS & flags) {\n" - "+\n" - "+\t\t/* request to disable B-dev: reset \"ena\" request if pending */\n" - "+\n" - "+\t\tflags &= ~OTG_B_BUS_REQ;\n" - "+\t\tRES_FLAG (otg, OTG_B_BUS_REQ);\n" - "+\t}\n" - "+\tif (OTG_B_BUS_REQ & flags) {\n" - "+\n" - "+\t\t/* request to enable B-dev: reset \"disa\" request if pending */\n" - "+\n" - "+\t\tRES_FLAG (otg, OTG_B_BUS_DIS);\n" - "+\t}\n" - "+\tif (flags) {\n" - "+\n" - "+\t\t/* request still pending may force a state change */\n" - "+\n" - "+\t\totg_req_state_chg (otg, flags);\n" - "+\t}\n" - "+\treturn OTG_APP_REQ_ACK;\n" - "+}\n" - "+#endif /* CONFIG_USB_OTG */\n" - "+\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * OTG application query\n" - "+ *\n" - "+ * \\param index select status info data\n" - "+ *\n" - "+ * \\return status\n" - "+ */\n" - "+static u32 otg_app_query (int index)\n" - "+{\n" - "+\tstruct otg *otg = the_controller;\n" - "+\tu32 temp = 0;\n" - "+\n" - "+\tif (index == 0) {\n" - "+\t\ttemp = otg->params |\n" - "+\t\t readl (&otg->regs->sts);\n" - "+\n" - "+/*** HS-A0 WA: BUG-3943: gadget phy suspend issue ***/\n" - "+#ifdef UDC_HSA0_WORKAROUNDS\n" - "+\t\tif (((readl (&otg->regs->ctl) & OTG_CTL_MUX_MASK) ==\n" - "+\t\t OTG_CTL_ENABLE_UDC) &&\n" - "+\t\t ((temp & OTG_STS_PSUS) || (~temp & OTG_STS_VBUSVLD))) {\n" - "+\t\t\ttemp |= OTG_FLAGS_UDC_SUSP;\n" - "+\t\t}\n" - "+#endif\n" - "+\t}\n" - "+\telse if (index == 1) {\n" - "+\t\ttemp = otg->transceiver.state;\n" - "+\t}\n" - "+#ifdef OTG_HNP_ERR_LOG\n" - "+ if (hnp_err) {\n" - "+ temp |= OTG_FLAGS_HNP_ERR;\n" - "+ }\n" - "+#endif\n" - "+\treturn temp;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * OTG ISR calling the main state machine\n" - "+ *\n" - "+ * \\param irq IRQ number\n" - "+ * \\param _dev \n" - "+ * \\param r \n" - "+ *\n" - "+ * \\return IRQ_HANDLED (system code)\n" - "+ */\n" - "+static irqreturn_t otg_isr (int irq, void *dev, struct pt_regs *r)\n" - "+{\n" - "+\tstruct otg *otg = (struct otg *) dev;\n" - "+\tu32 interrupts, int_mask, temp;\n" - "+\n" - "+\tint_mask = readl (&otg->regs->inten);\n" - "+\tif ((OTG_INT_GLOBAL & int_mask) &&\n" - "+\t (int_mask &= ~((u32) OTG_INT_GLOBAL)) &&\n" - "+\t (interrupts = int_mask &\n" - "+\t\t (temp = readl (&otg->regs->intr)))) {\n" - "+\n" - "+\t\twritel (int_mask, &otg->regs->inten);\n" - "+\t\t/* clear interrupt status */\n" - "+\t\twritel (temp, &otg->regs->intr);\n" - "+/*\n" - "+#ifdef CONFIG_USB_OTG\n" - "+\n" - "+\t\tif (GOT_EVENT (OTG_INT_PCC, interrupts) &&\n" - "+\t\t IS_BIT_SET (OTG_STS_PCON, readl (&otg->regs->sts))) {\n" - "+\t\t\totg_hnp_start_enum (&otg->transceiver);\n" - "+\t\t}\n" - "+#endif */\n" - "+\t\t/* filter out additional WA interrupts, they're done */\n" - "+\t\t/* don't want to see them in the state machine */\n" - "+\n" - "+\t\tif (interrupts & ~state_mask) {\n" - "+\n" - "+\t\t\t/* events pending for the state machine */\n" - "+\n" - "+\t\t\totg_change_state (otg, (interrupts & ~state_mask),\n" - "+\t\t\t &int_mask);\n" - "+\t\t}\n" - "+\n" - "+\t\t/* enable interrupts and keep information about WA ints: */\n" - "+\n" - "+\t\tstate_mask = OTG_INT_ADDS & ~int_mask;\n" - "+\t\twritel ((OTG_INT_ADDS | int_mask | OTG_INT_GLOBAL),\n" - "+\t\t &otg->regs->inten);\n" - "+\t}\n" - "+\treturn IRQ_HANDLED;\n" - "+}\n" - "+#endif /* CONFIG_USB_OTG || CONFIG_USB_OTGMUX_GADGET */\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * OTG probe: init hardware, register the driver\n" - "+ *\n" - "+ * \\param otg otg controller info\n" - "+ *\n" - "+ * \\return success\n" - "+ */\n" - "+static inline int __init otg_probe (struct otg *otg)\n" - "+{\n" - "+\tint retval;\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\tu32 temp;\n" - "+\tint i;\n" - "+#endif\n" - "+\n" - "+\t/* initialize the OTG controller */\n" - "+\n" - "+\tVDBG (\"OTG init ...\\n\");\n" - "+\n" - "+#ifdef VERBOSE\n" - "+\t/* print regs */\n" - "+\tprint_regs (otg);\n" - "+#endif\n" - "+\t/* Make sure we'll remember the initial state */\n" - "+\tinit_state = readl (&otg->regs->ctl);\n" - "+\tVDBG (\" OTG init state was %08x\\n\", init_state);\n" - "+\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+\t/* turn on the OTG controller */\n" - "+\n" - "+\twritel ((init_state | OTG_CTL_PADEN), &otg->regs->ctl);\n" - "+\n" - "+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/\n" - "+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/\n" - "+#ifndef UDC_HSA0_WORKAROUNDS\n" - "+\n" - "+\t/* Enable OTG hardware (incl. auto pull-up enable) */\n" - "+\n" - "+\twritel ((readl (&dev->regs->cap) | OTG_CAP_APU), &otg->regs->cap);\n" - "+#endif\n" - "+\n" - "+\t/* initialize flags */\n" - "+\totg->params = 0;\n" - "+#endif\n" - "+\n" - "+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/\n" - "+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/\n" - "+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+\t/* make sure all interrupts are disabled */\n" - "+\n" - "+\twritel (OTG_INT_DISALL, &otg->regs->inten);\n" - "+\twritel (OTG_INT_ENALL, &otg->regs->intr);\n" - "+\n" - "+\t/* Set multiplexer to neutral, get power control, drop VBus */\n" - "+\n" - "+\tif (((init_state & OTG_CTL_MUX_MASK) == OTG_CTL_ENABLE_UHC) &&\n" - "+\t ((((init_state & OTG_CTL_PPO) && (init_state & OTG_CTL_PPWR))) ||\n" - "+\t ((~init_state & OTG_CTL_PPO) &&\n" - "+\t (readl (&otg->regs->sts) & OTG_STS_SESSVLD)))) {\n" - "+\n" - "+\t\t/* VBus still powered try to discharge VBus and set timer */\n" - "+\n" - "+\t\tDBG (\"Setting init state, trying to discharge VBus ...\\n\");\n" - "+\n" - "+\t\tfor (i = 0; i < 4; i++) {\n" - "+\t\t\twritel (TIMER_PERIOD, &otg->regs->tmr);\n" - "+\t\t\twritel ((OTG_CTL_PADEN | OTG_CTL_IDSNSEN |\n" - "+\t\t\t OTG_CTL_PPO | OTG_CTL_DISCHRG |\n" - "+\t\t\t OTG_CTL_TMR_UNCOND), &otg->regs->ctl);\n" - "+\t\t\tdo { }\n" - "+\t\t\twhile (!(readl (&otg->regs->sts) & OTG_STS_TMH));\n" - "+\t\t}\n" - "+\t\twritel ((OTG_CTL_PADEN | OTG_CTL_IDSNSEN | OTG_CTL_PPO),\n" - "+\t\t &otg->regs->ctl);\n" - "+\t\twritel (OTG_INT_ENALL, &otg->regs->intr);\n" - "+#ifdef DEBUG\n" - "+\t\tif (readl (&otg->regs->sts) & OTG_STS_SESSVLD) {\n" - "+\n" - "+\t\t\tDBG (\" VBus still high, external host connected\\n\");\n" - "+\t\t}\n" - "+\t\telse {\n" - "+\n" - "+\t\t\tDBG (\" VBus discharged\\n\");\n" - "+\t\t}\n" - "+#endif\n" - "+\t}\n" - "+\telse {\n" - "+\t\tDBG (\"Setting init state\\n\");\n" - "+\n" - "+\t\twritel ((OTG_CTL_PADEN | OTG_CTL_IDSNSEN | OTG_CTL_PPO),\n" - "+\t\t &otg->regs->ctl);\n" - "+\t}\n" - "+#endif /* CONFIG_USB_OTG || CONFIG_USB_OTGMUX_GADGET */\n" - "+\n" - "+#ifdef CONFIG_USB_OTGMUX_HOST\n" - "+\n" - "+\t/* Set multiplexer to host */\n" - "+\twritel ((readl (&otg->regs->cap) & ~((u32) OTG_CAP_APU)),\n" - "+\t &otg->regs->cap);\n" - "+\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+\n" - "+\twritel ((OTG_CTL_ENABLE_UHC | OTG_CTL_PPO | OTG_CTL_PPWR),\n" - "+\t &otg->regs->ctl);\n" - "+\n" - "+\t/* Turn on VBus */\n" - "+\tAU1000GPIO_CLR_BIT (USB_VBUS_GPIO);\n" - "+#else\n" - "+\twritel (OTG_CTL_ENABLE_UHC, &otg->regs->ctl);\n" - "+#endif\n" - "+\n" - "+\tINFO (\"OTG functionality is disabled, port is assigned to host\\n\");\n" - "+#endif\n" - "+\tVDBG (\"OTG init done\\n\");\n" - "+\n" - "+#ifdef CONFIG_USB_OTG_TEST_INTERFACE\n" - "+\n" - "+\t/* registering to the test driver */\n" - "+\tusb_otg_test_register_driver (&otg_test_extension);\n" - "+#endif\n" - "+#ifndef CONFIG_TEST_MODE_ONLY\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+\t/* registering to the device driver */\n" - "+\tif (usb_gadget_register_otg (otg_get_transceiver)) {\n" - "+\t\tERR (\"gadget driver registration failed\\n\");\n" - "+\t\tretval = -ENODEV;\n" - "+\t\tgoto err1;\n" - "+\t}\n" - "+#endif\n" - "+#ifdef CONFIG_USB_OTG\n" - "+\n" - "+\t/* registering to the usbcore */\n" - "+\tif (usb_host_register_otg (otg_get_transceiver)) {\n" - "+\t\tERR (\"usbcore registration failed\\n\");\n" - "+\t\tretval = -ENODEV;\n" - "+\t\tgoto err2;\n" - "+\t}\n" - "+#endif\n" - "+#endif\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+\t/* finally activate OTG functionality */\n" - "+\t/* Enable timer interrupt, start timer, set state */\n" - "+\n" - "+\tSET_OTG_TIMER (otg, IDSNS_WAIT);\n" - "+\tCHANGE_STATE (otg, OTG_STATE_UNDEFINED, &temp);\n" - "+\tCHECK_STATE (otg, OTG_STATE_UNDEFINED, &temp);\n" - "+\n" - "+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/\n" - "+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/\n" - "+/*** HS-A0 WA: BUG-3950: gadget needs disconnect notification ***/\n" - "+\n" - "+\t/* clear all interrupts before enable */\n" - "+\twritel (readl (&otg->regs->intr), &otg->regs->intr);\n" - "+\n" - "+\tstate_mask = ~temp & OTG_INT_ADDS;\n" - "+\twritel ((OTG_INT_ADDS | temp | OTG_INT_GLOBAL), &otg->regs->inten);\n" - "+\n" - "+\tDBG (\"OTG-HW initialized, now checking ID ...\\n\");\n" - "+#endif\n" - "+\n" - "+\treturn 0;\n" - "+\n" - "+#ifndef CONFIG_TEST_MODE_ONLY\n" - "+#ifdef CONFIG_USB_OTG\n" - "+\n" - "+err2:\n" - "+\n" - "+#endif\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+\tusb_gadget_unregister_otg ();\n" - "+err1:\n" - "+\n" - "+#endif\n" - "+#endif\n" - "+#ifdef CONFIG_USB_OTG_TEST_INTERFACE\n" - "+\n" - "+\tusb_otg_test_unregister_driver ();\n" - "+#endif\n" - "+\treturn retval;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * OTG remove: deregister the driver, clean-up hardware\n" - "+ *\n" - "+ * \\param otg otg controller info\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+static inline void __exit otg_remove (struct otg *otg)\n" - "+{\n" - "+\tint muxer;\n" - "+\n" - "+#ifndef CONFIG_TEST_MODE_ONLY\n" - "+#ifdef CONFIG_USB_OTG\n" - "+\n" - "+\t/* unregistering from the usb core */\n" - "+\tusb_host_deregister_otg ();\n" - "+#endif\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+\t/* unregistering from the usb gadget */\n" - "+\tusb_gadget_unregister_otg ();\n" - "+\n" - "+#endif\n" - "+#endif\n" - "+#ifdef CONFIG_USB_OTG_TEST_INTERFACE\n" - "+\n" - "+\t/* unregistering from the test driver */\n" - "+\tusb_otg_test_unregister_driver ();\n" - "+#endif\n" - "+\n" - "+\t/* clean up the OTG controller */\n" - "+\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+\t/* Disable all interrupts */\n" - "+\twritel (OTG_INT_DISALL, &otg->regs->inten);\n" - "+\twritel (OTG_INT_ENALL, &otg->regs->intr);\n" - "+\n" - "+\t/* reset state, terminate all connections */\n" - "+\tCHANGE_STATE (otg, OTG_STATE_UNDEFINED, &state_mask);\n" - "+\tCHECK_STATE (otg, OTG_STATE_UNDEFINED, &state_mask);\n" - "+\totg->params = 0;\n" - "+#endif\n" - "+\n" - "+\tmuxer = init_state & (OTG_CTL_ENABLE_UHC | OTG_CTL_ENABLE_UDC);\n" - "+\n" - "+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/\n" - "+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/\n" - "+#ifdef UDC_HSA0_WORKAROUNDS\n" - "+\n" - "+\t/* Don't assign the port to the device controller */\n" - "+\n" - "+\tif (!(muxer ^ OTG_CTL_ENABLE_UDC)) {\n" - "+\n" - "+\t\tinit_state &= ~((u32) (OTG_CTL_MUX_MASK | OTG_CTL_PUEN));\n" - "+\t\tmuxer = OTG_CTL_DISABLE_ALL;\n" - "+\t}\n" - "+\tVDBG (\"OTG writing back corrected init state: %08x\\n\", init_state);\n" - "+#else\n" - "+\t/* Reset APU */\n" - "+\n" - "+\twritel ((readl (&otg->regs->cap) & ~((u32) OTG_CAP_APU)),\n" - "+\t &otg->regs->cap);\n" - "+\n" - "+\tVDBG (\"OTG writing back init state: %08x\\n\", init_state);\n" - "+#endif\n" - "+\t/* Now, that's the moment to remember */\n" - "+\t/* Set dev muxer and pull up bits, turn off the OTG controller */\n" - "+\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+\n" - "+\t/* Turn off VBus */\n" - "+\tAU1000GPIO_SET_BIT (USB_VBUS_GPIO);\n" - "+#endif\n" - "+\twritel (init_state, &otg->regs->ctl);\n" - "+\n" - "+\tif (!(muxer ^ OTG_CTL_ENABLE_UHC)) {\n" - "+\t\tINFO (\"disabling OTG-HW, port is assigned to host\\n\");\n" - "+\t}\n" - "+\telse if (!(muxer ^ OTG_CTL_ENABLE_UDC)) {\n" - "+\t\tINFO (\"disabling OTG-HW, port is assigned to device\\n\");\n" - "+\t}\n" - "+\telse {\n" - "+\t\tINFO (\"disabling OTG-HW, port is not assigned\\n\");\n" - "+\t}\n" - "+\n" - "+\tVDBG (\"OTG exit: OTG-HW disabled\\n\");\n" - "+\n" - "+\tif (!muxer) {\n" - "+\t\tINFO (\"OTG HW disabled, port is not assigned\\n\");\n" - "+\t}\n" - "+}\n" - "+\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+#ifdef USE_AU1200_PCI_DUMMY\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * OTG dev probe: enable, init controller hardware\n" - "+ *\n" - "+ * \\param pdev dummy pci device pointer\n" - "+ *\n" - "+ * \\return success\n" - "+ */\n" - "+static int __init otg_pci_probe (struct pci_dev *pdev)\n" - "+{\n" - "+\tstruct otg *otg;\n" - "+\tvoid *base;\n" - "+\tint retval;\n" - "+\tchar buf [8] = {0,0,0,0,0,0,0,0}, *bufp;\n" - "+\n" - "+\t/* alloc, and start init */\n" - "+\totg = (struct otg *) kmalloc (sizeof(struct otg), SLAB_KERNEL);\n" - "+\tif (!otg) {\n" - "+\t\tERR (\"couldn't allocate memory for OTG driver\\n\");\n" - "+\t\tretval = -ENOMEM;\n" - "+\t\tgoto err1;\n" - "+\t}\n" - "+\tDBG ( \"kmalloc: OTG driver: %p\\n\", otg);\n" - "+\n" - "+\t/* hold global device pointer */\n" - "+\tthe_controller = otg;\n" - "+\n" - "+\tmemset (otg, 0, sizeof(struct otg));\n" - "+\tspin_lock_init (&otg->lock);\n" - "+\n" - "+\t/*\n" - "+\t* Fill in the dummy pci_dev. Only those members actually\n" - "+\t* dereferenced in this driver are initialized.\n" - "+\t*/\n" - "+\tmemset(pdev, 0, sizeof(struct pci_dev));\n" - "+\tpdev->resource[0].name = \"UOC Registers\";\n" - "+\tpdev->resource[0].start = USB_UOC_BASE;\n" - "+\tpdev->resource[0].end = USB_UOC_BASE + USB_UOC_LEN - 1;\n" - "+\tpdev->resource[0].flags = 0;\n" - "+\tpdev->irq = AU1200_USB_INT;\n" - "+\n" - "+\totg->pdev = pdev;\n" - "+\n" - "+\tau_writel ((au_readl (USB_MSR_BASE + USB_MSR_MCFG) |\n" - "+\t (1 << USBMSRMCFG_GMEMEN)), (USB_MSR_BASE + USB_MSR_MCFG));\n" - "+\tau_readl (USB_MSR_BASE + USB_MSR_MCFG);\n" - "+\t/* au_sync (); */\n" - "+\tudelay (1000);\n" - "+\tif (AU1000GPIO_INIT_BIT (USB_VBUS_GPIO))\n" - "+\t\tWARN (\"Couldn't initialize power switch GPIO\\n\");\n" - "+\totg->enabled = 1;\n" - "+\n" - "+\tif (!request_mem_region (pdev->resource[0].start,\n" - "+\t pdev->resource[0].end + 1\n" - "+\t - pdev->resource[0].start,\n" - "+\t driver_name)) {\n" - "+\t\tERR (\"controller already in use\\n\");\n" - "+\t\tretval = -EBUSY;\n" - "+\t\tgoto err3;\n" - "+\t}\n" - "+\totg->region = 1;\n" - "+\n" - "+\tbase = ioremap_nocache (pdev->resource[0].start,\n" - "+\t pdev->resource[0].end + 1\n" - "+\t - pdev->resource[0].start);\n" - "+\tif (!base) {\n" - "+\t\tERR (\"couldn't map memory\\n\");\n" - "+\t\tretval = -EFAULT;\n" - "+\t\tgoto err4;\n" - "+\t}\n" - "+\totg->regs = (struct otg_regs *) base;\n" - "+\tbufp = buf;\n" - "+\n" - "+\totg->chiprev = (u16) read_c0_prid() & 0xff;\n" - "+\n" - "+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/\n" - "+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/\n" - "+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+\t/* OTG transceiver info */\n" - "+\totg->transceiver.dev = &pdev->dev;\n" - "+\totg_init_transceiver (otg_to_transceiver (otg));\n" - "+\n" - "+\t/* make sure all interrupts are disabled */\n" - "+\twritel (OTG_INT_DISALL, &otg->regs->inten);\n" - "+\twritel (OTG_INT_ENALL, &otg->regs->intr);\n" - "+\treadl (&otg->regs->inten);\n" - "+\n" - "+\t/* irq setup after old hardware is cleaned up */\n" - "+\tif (!pdev->irq) {\n" - "+\t\tERR (\"No IRQ. Check system setup!\\n\");\n" - "+\t\tretval = -ENODEV;\n" - "+\t\tgoto err5;\n" - "+\t}\n" - "+\tsnprintf (buf, sizeof buf, \"%d\", pdev->irq);\n" - "+\tbufp = buf;\n" - "+\tif (request_irq (pdev->irq, otg_isr, SA_INTERRUPT | SA_SHIRQ,\n" - "+\t driver_name, otg) != 0) {\n" - "+\t\tERR (\"request interrupt %s failed\\n\", bufp);\n" - "+\t\tretval = -EBUSY;\n" - "+\t\tgoto err5;\n" - "+\t}\n" - "+\totg->got_irq = 1;\n" - "+\n" - "+\t/* done */\n" - "+\tINFO (\"%s\\n\", driver_desc);\n" - "+\tINFO (\"irq %s, mem %08lx, chip rev %02x (Au1200 %s)\\n\",\n" - "+\t bufp, pdev->resource[0].start, otg->chiprev,\n" - "+\t (otg->chiprev ? \"AC\" : \"AB\"));\n" - "+\n" - "+#else /* CONFIG_USB_OTG || CONFIG_USB_OTGMUX_GADGET */\n" - "+\n" - "+\tINFO (\"%s\\n\", driver_desc);\n" - "+\tINFO (\"mem %08lx, chip rev %02x (Au1200 %s)\\n\",\n" - "+\t pdev->resource[0].start, otg->chiprev,\n" - "+\t (otg->chiprev ? \"AC\" : \"AB\"));\n" - "+#endif\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_IDPIN) || defined(CONFIG_USB_OTGMUX_HOST)\n" - "+\n" - "+\tINFO (\"using GPIO_%d for VBus control\\n\", USB_VBUS_GPIO);\n" - "+#endif\n" - "+\tbufp = DRIVER_VERSION;\n" - "+\tINFO (\"driver version: %s\\n\", bufp);\n" - "+\n" - "+\tif ((retval = otg_probe (otg)) == 0) {\n" - "+\t\tpci_set_drvdata (pdev, otg);\n" - "+\t\treturn 0;\n" - "+\t}\n" - "+\n" - "+\t/* something went wrong */\n" - "+\n" - "+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/\n" - "+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/\n" - "+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+\totg->got_irq = 0;\n" - "+\tfree_irq (pdev->irq, otg);\n" - "+err5:\n" - "+\n" - "+#endif\n" - "+\totg->regs = NULL;\n" - "+\tiounmap (base);\n" - "+err4:\n" - "+\totg->region = 0;\n" - "+\trelease_mem_region (pdev->resource[0].start,\n" - "+\t pdev->resource[0].end + 1\n" - "+\t - pdev->resource[0].start);\n" - "+err3:\n" - "+\totg->enabled = 0;\n" - "+\tAU1000GPIO_TERM_BIT (USB_VBUS_GPIO);\n" - "+\tau_writel ((au_readl (USB_MSR_BASE + USB_MSR_MCFG) &\n" - "+\t ~((u32) (1 << USBMSRMCFG_GMEMEN))),\n" - "+\t (USB_MSR_BASE + USB_MSR_MCFG));\n" - "+\tau_readl (USB_MSR_BASE + USB_MSR_MCFG);\n" - "+\t/* au_sync (); */\n" - "+\tudelay (1000);\n" - "+\n" - "+\totg->pdev = NULL;\n" - "+\tthe_controller = NULL;\n" - "+\tDBG ( \"kfree: OTG driver: %p\\n\", otg);\n" - "+\tkfree (otg);\n" - "+err1:\n" - "+\totg = NULL;\n" - "+\treturn retval;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * OTG dev remove: clean-up, disable controller hardware\n" - "+ *\n" - "+ * \\param pdev dummy pci device info\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+static void __exit otg_pci_remove (struct pci_dev *pdev)\n" - "+{\n" - "+\tstruct otg *otg = pci_get_drvdata (pdev);\n" - "+\n" - "+\totg_remove (otg);\n" - "+\n" - "+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/\n" - "+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/\n" - "+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+\totg->got_irq = 0;\n" - "+\tfree_irq (pdev->irq, otg);\n" - "+#endif\n" - "+\tiounmap (otg->regs);\n" - "+\totg->regs = NULL;\n" - "+\totg->region = 0;\n" - "+\trelease_mem_region (pdev->resource[0].start,\n" - "+\t pdev->resource[0].end + 1\n" - "+\t - pdev->resource[0].start);\n" - "+\totg->enabled = 0;\n" - "+\tAU1000GPIO_TERM_BIT (USB_VBUS_GPIO);\n" - "+/*\tau_writel ((au_readl (USB_MSR_BASE + USB_MSR_MCFG) &\n" - "+\t ~((u32) (1 << USBMSRMCFG_GMEMEN))),\n" - "+\t (USB_MSR_BASE + USB_MSR_MCFG)); */\n" - "+\tau_readl (USB_MSR_BASE + USB_MSR_MCFG);\n" - "+\t/* au_sync (); */\n" - "+\tudelay (1000);\n" - "+\totg->pdev = NULL;\n" - "+\tthe_controller = NULL;\n" - "+\tDBG ( \"kfree: OTG driver: %p\\n\", otg);\n" - "+\tkfree (otg);\n" - "+\totg = NULL;\n" - "+\tpci_set_drvdata(pdev, NULL);\n" - "+}\n" - "+#else\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * OTG dev probe: enable, init controller hardware\n" - "+ *\n" - "+ * \\param dev platform device info\n" - "+ *\n" - "+ * \\return success\n" - "+ */\n" - "+static int __init otg_drv_probe (struct device *dev)\n" - "+{\n" - "+\tstruct platform_device *pdev = to_platform_device(dev);\n" - "+\tstruct otg *otg;\n" - "+\tu32 resource, len, irq;\n" - "+\tvoid *base;\n" - "+\tint retval;\n" - "+\tchar buf [8] = {0,0,0,0,0,0,0,0}, *bufp;\n" - "+\n" - "+\t/* alloc, and start init */\n" - "+\totg = (struct otg *) kmalloc (sizeof(struct otg), SLAB_KERNEL);\n" - "+\tif (!otg) {\n" - "+\t\tERR (\"couldn't allocate memory for OTG driver\\n\");\n" - "+\t\tretval = -ENOMEM;\n" - "+\t\tgoto err1;\n" - "+\t}\n" - "+\tDBG ( \"kmalloc: OTG driver: %p\\n\", otg);\n" - "+\n" - "+\t/* hold global device pointer */\n" - "+\tthe_controller = otg;\n" - "+\n" - "+\tmemset (otg, 0, sizeof(struct otg));\n" - "+\tspin_lock_init (&otg->lock);\n" - "+\n" - "+\tif (pdev->resource[0].flags != IORESOURCE_MEM) {\n" - "+\t\tERR (\"resource is not IORESOURCE_MEM\\n\");\n" - "+\t\tretval = -ENOMEM;\n" - "+\t\tgoto err2;\n" - "+\t}\n" - "+\tresource = pdev->resource[0].start;\n" - "+\tlen = pdev->resource[0].end + 1 - pdev->resource[0].start;\n" - "+\tif (pdev->resource[1].flags != IORESOURCE_IRQ) {\n" - "+\t\tERR (\"resource is not IORESOURCE_IRQ\\n\");\n" - "+\t\tretval = -ENOMEM;\n" - "+\t\tgoto err2;\n" - "+\t}\n" - "+\tirq = pdev->resource[1].start;\n" - "+\n" - "+\totg->pdev = pdev;\n" - "+\n" - "+\tau_writel ((au_readl (USB_MSR_BASE + USB_MSR_MCFG) |\n" - "+\t (1 << USBMSRMCFG_GMEMEN)), (USB_MSR_BASE + USB_MSR_MCFG));\n" - "+\tau_readl (USB_MSR_BASE + USB_MSR_MCFG);\n" - "+\t/* au_sync (); */\n" - "+\tudelay (1000);\n" - "+\tif (AU1000GPIO_INIT_BIT (USB_VBUS_GPIO))\n" - "+\t\tWARN (\"Couldn't initialize power switch GPIO\\n\");\n" - "+\totg->enabled = 1;\n" - "+\n" - "+\tif (!request_mem_region (resource, len, driver_name)) {\n" - "+\t\tERR (\"controller already in use\\n\");\n" - "+\t\tretval = -EBUSY;\n" - "+\t\tgoto err3;\n" - "+\t}\n" - "+\totg->region = 1;\n" - "+\n" - "+\tbase = ioremap_nocache (resource, len);\n" - "+\tif (!base) {\n" - "+\t\tERR (\"couldn't map memory\\n\");\n" - "+\t\tretval = -EFAULT;\n" - "+\t\tgoto err4;\n" - "+\t}\n" - "+\totg->regs = (struct otg_regs *) base;\n" - "+\tbufp = buf;\n" - "+\n" - "+\totg->chiprev = (u16) read_c0_prid() & 0xff;\n" - "+\n" - "+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/\n" - "+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/\n" - "+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+\t/* OTG transceiver info */\n" - "+\totg->transceiver.dev = dev;\n" - "+\totg_init_transceiver (otg_to_transceiver (otg));\n" - "+\n" - "+\t/* make sure all interrupts are disabled */\n" - "+\twritel (OTG_INT_DISALL, &otg->regs->inten);\n" - "+\twritel (OTG_INT_ENALL, &otg->regs->intr);\n" - "+\treadl (&otg->regs->inten);\n" - "+\n" - "+\t/* irq setup after old hardware is cleaned up */\n" - "+\tif (!irq) {\n" - "+\t\tERR (\"No IRQ. Check system setup!\\n\");\n" - "+\t\tretval = -ENODEV;\n" - "+\t\tgoto err5;\n" - "+\t}\n" - "+\tsnprintf (buf, sizeof buf, \"%d\", irq);\n" - "+\tbufp = buf;\n" - "+\tif (request_irq (irq, otg_isr, SA_INTERRUPT | SA_SHIRQ,\n" - "+\t driver_name, otg) != 0) {\n" - "+\t\tERR (\"request interrupt %s failed\\n\", bufp);\n" - "+\t\tretval = -EBUSY;\n" - "+\t\tgoto err5;\n" - "+\t}\n" - "+\totg->got_irq = 1;\n" - "+\n" - "+\t/* done */\n" - "+\tINFO (\"%s\\n\", driver_desc);\n" - "+\tINFO (\"irq %s, mem %08x, chip rev %02x (Au1200 %s)\\n\",\n" - "+\t bufp, resource, otg->chiprev, (otg->chiprev ? \"AC\" : \"AB\"));\n" - "+\n" - "+#else /* CONFIG_USB_OTG || CONFIG_USB_OTGMUX_GADGET */\n" - "+\n" - "+\tINFO (\"%s\\n\", driver_desc);\n" - "+\tINFO (\"mem %08x, chip rev %02x (Au1200 %s)\\n\",\n" - "+\t resource, otg->chiprev, (otg->chiprev ? \"AC\" : \"AB\"));\n" - "+#endif\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_IDPIN) || defined(CONFIG_USB_OTGMUX_HOST)\n" - "+\n" - "+\tINFO (\"using GPIO_%d for VBus control\\n\", USB_VBUS_GPIO);\n" - "+#endif\n" - "+\tbufp = DRIVER_VERSION;\n" - "+\tINFO (\"driver version: %s\\n\", bufp);\n" - "+\n" - "+\tif ((retval = otg_probe (otg)) == 0) {\n" - "+\t\tdev_set_drvdata (dev, otg);\n" - "+\t\treturn 0;\n" - "+\t}\n" - "+\n" - "+\t/* something went wrong */\n" - "+\n" - "+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/\n" - "+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/\n" - "+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+\totg->got_irq = 0;\n" - "+\tfree_irq (irq, otg);\n" - "+err5:\n" - "+\n" - "+#endif\n" - "+\totg->regs = NULL;\n" - "+\tiounmap (base);\n" - "+err4:\n" - "+\totg->region = 0;\n" - "+\trelease_mem_region (resource, len);\n" - "+err3:\n" - "+\totg->enabled = 0;\n" - "+\tAU1000GPIO_TERM_BIT (USB_VBUS_GPIO);\n" - "+\tau_writel ((au_readl (USB_MSR_BASE + USB_MSR_MCFG) &\n" - "+\t ~((u32) (1 << USBMSRMCFG_GMEMEN))),\n" - "+\t (USB_MSR_BASE + USB_MSR_MCFG));\n" - "+\tau_readl (USB_MSR_BASE + USB_MSR_MCFG);\n" - "+\t/* au_sync (); */\n" - "+\tudelay (1000);\n" - "+err2:\n" - "+\totg->pdev = NULL;\n" - "+\tthe_controller = NULL;\n" - "+\tDBG ( \"kfree: OTG driver: %p\\n\", otg);\n" - "+\tkfree (otg);\n" - "+err1:\n" - "+\totg = NULL;\n" - "+\n" - "+\treturn retval;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * OTG dev remove: clean-up, disable controller hardware\n" - "+ *\n" - "+ * \\param dev platform device info\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+static int __exit otg_drv_remove (struct device *dev)\n" - "+{\n" - "+\tstruct platform_device *pdev = to_platform_device(dev);\n" - "+\tstruct otg *otg = dev_get_drvdata (dev);\n" - "+\n" - "+\totg_remove (otg);\n" - "+\n" - "+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/\n" - "+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/\n" - "+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+\totg->got_irq = 0;\n" - "+\tfree_irq (pdev->resource[1].start, otg);\n" - "+#endif\n" - "+\tiounmap (otg->regs);\n" - "+\totg->regs = NULL;\n" - "+\totg->region = 0;\n" - "+\trelease_mem_region (pdev->resource[0].start,\n" - "+\t pdev->resource[0].end + 1\n" - "+\t - pdev->resource[0].start);\n" - "+\totg->enabled = 0;\n" - "+\tAU1000GPIO_TERM_BIT (USB_VBUS_GPIO);\n" - "+/*\tau_writel ((au_readl (USB_MSR_BASE + USB_MSR_MCFG) &\n" - "+\t ~((u32) (1 << USBMSRMCFG_GMEMEN))),\n" - "+\t (USB_MSR_BASE + USB_MSR_MCFG)); */\n" - "+\tau_readl (USB_MSR_BASE + USB_MSR_MCFG);\n" - "+\t/* au_sync (); */\n" - "+\tudelay (1000);\n" - "+\totg->pdev = NULL;\n" - "+\tthe_controller = NULL;\n" - "+\tDBG ( \"kfree: OTG driver: %p\\n\", otg);\n" - "+\tkfree (otg);\n" - "+\totg = NULL;\n" - "+\tdev_set_drvdata(dev, NULL);\n" - "+\treturn 0;\n" - "+}\n" - "+#endif\n" - "+#else\n" - "+#ifdef CONFIG_PCI\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * OTG PCI probe: enable, init controller hardware\n" - "+ *\n" - "+ * \\param pdev pci device info\n" - "+ * \\param id pci ids\n" - "+ *\n" - "+ * \\return success\n" - "+ */\n" - "+static int __init otg_pci_probe (struct pci_dev *pdev,\n" - "+ const struct pci_device_id *id)\n" - "+{\n" - "+\tstruct otg *otg;\n" - "+\tu32 resource, len;\n" - "+\tvoid *base;\n" - "+\tint retval;\n" - "+\tchar buf [8] = {0,0,0,0,0,0,0,0}, *bufp;\n" - "+\n" - "+\t/* alloc, and start init */\n" - "+\totg = (struct otg *) kmalloc (sizeof(struct otg), SLAB_KERNEL);\n" - "+\tif (!otg) {\n" - "+\t\tERR (\"couldn't allocate memory for OTG driver\\n\");\n" - "+\t\tretval = -ENOMEM;\n" - "+\t\tgoto err1;\n" - "+\t}\n" - "+\tDBG ( \"kmalloc: OTG driver: %p\\n\", otg);\n" - "+\n" - "+\t/* hold global device pointer */\n" - "+\tthe_controller = otg;\n" - "+\n" - "+\tmemset (otg, 0, sizeof(struct otg));\n" - "+\tspin_lock_init (&otg->lock);\n" - "+\n" - "+\totg->pdev = pdev;\n" - "+\n" - "+\t/* now all the pci goodies ... */\n" - "+\tif (pci_enable_device (pdev) < 0) {\n" - "+\t\tERR (\"couldn't enable PCI device\\n\");\n" - "+\t\tretval = -ENODEV;\n" - "+\t\tgoto err2;\n" - "+\t}\n" - "+\totg->enabled = 1;\n" - "+\n" - "+\tresource = pci_resource_start (pdev, 0);\n" - "+\tlen = pci_resource_len (pdev, 0);\n" - "+\n" - "+\tif (!request_mem_region (resource, len, driver_name)) {\n" - "+\t\tERR (\"controller already in use\\n\");\n" - "+\t\tretval = -EBUSY;\n" - "+\t\tgoto err3;\n" - "+\t}\n" - "+\totg->region = 1;\n" - "+\n" - "+\tbase = ioremap_nocache (resource, len);\n" - "+\tif (!base) {\n" - "+\t\tERR (\"couldn't map memory\\n\");\n" - "+\t\tretval = -EFAULT;\n" - "+\t\tgoto err4;\n" - "+\t}\n" - "+\totg->regs = (struct otg_regs *) base;\n" - "+\tbufp = buf;\n" - "+\n" - "+\tpci_read_config_byte (pdev, PCI_REVISION_ID, (u8*) &otg->chiprev);\n" - "+\n" - "+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/\n" - "+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/\n" - "+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+\t/* OTG transceiver info */\n" - "+\n" - "+\totg->transceiver.dev = &pdev->dev;\n" - "+\totg_init_transceiver (otg_to_transceiver (otg));\n" - "+\n" - "+\t/* make sure all interrupts are disabled */\n" - "+\twritel (OTG_INT_DISALL, &otg->regs->inten);\n" - "+\twritel (OTG_INT_ENALL, &otg->regs->intr);\n" - "+\treadl (&otg->regs->inten);\n" - "+\n" - "+\t/* irq setup after old hardware is cleaned up */\n" - "+\tif (!pdev->irq) {\n" - "+\t\tERR (\"No IRQ. Check PCI setup!\\n\");\n" - "+\t\tretval = -ENODEV;\n" - "+\t\tgoto err5;\n" - "+\t}\n" - "+#ifndef __sparc__\n" - "+\tsnprintf (buf, sizeof buf, \"%d\", pdev->irq);\n" - "+\tbufp = buf;\n" - "+#else\n" - "+\tbufp = __irq_itoa(pdev->irq);\n" - "+#endif\n" - "+\tif (request_irq (pdev->irq, otg_isr, SA_INTERRUPT | SA_SHIRQ,\n" - "+\t driver_name, otg) != 0) {\n" - "+\t\tERR (\"request interrupt %s failed\\n\", bufp);\n" - "+\t\tretval = -EBUSY;\n" - "+\t\tgoto err5;\n" - "+\t}\n" - "+\totg->got_irq = 1;\n" - "+\n" - "+\t/* done */\n" - "+\tINFO (\"%s\\n\", driver_desc);\n" - "+\tINFO (\"irq %s, pci mem %08x, chip rev %02x (Geode5536 %s)\\n\",\n" - "+\t bufp, resource, otg->chiprev, (otg->chiprev - 1 ? \"B1\" : \"A0\"));\n" - "+\n" - "+#else /* CONFIG_USB_OTG || CONFIG_USB_OTGMUX_GADGET */\n" - "+\n" - "+\tINFO (\"%s\\n\", driver_desc);\n" - "+\tINFO (\"pci mem %08x, chip rev %02x (Geode5536 %s)\\n\",\n" - "+\t resource, otg->chiprev, (otg->chiprev - 1 ? \"B1\" : \"A0\"));\n" - "+#endif\n" - "+\tbufp = DRIVER_VERSION;\n" - "+\tINFO (\"driver version: %s\\n\", bufp);\n" - "+\n" - "+\tif ((retval = otg_probe (otg)) == 0) {\n" - "+\t\tpci_set_drvdata (pdev, otg);\n" - "+\t\treturn 0;\n" - "+\t}\n" - "+\n" - "+\t/* something went wrong */\n" - "+\n" - "+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/\n" - "+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/\n" - "+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+\totg->got_irq = 0;\n" - "+\tfree_irq (pdev->irq, otg);\n" - "+err5:\n" - "+\n" - "+#endif\n" - "+\totg->regs = NULL;\n" - "+\tiounmap (base);\n" - "+err4:\n" - "+\totg->region = 0;\n" - "+\trelease_mem_region (resource, len);\n" - "+err3:\n" - "+\totg->enabled = 0;\n" - "+\tpci_disable_device (pdev);\n" - "+err2:\n" - "+\totg->pdev = NULL;\n" - "+\tthe_controller = NULL;\n" - "+\tDBG ( \"kfree: OTG driver: %p\\n\", otg);\n" - "+\tkfree (otg);\n" - "+err1:\n" - "+\totg = NULL;\n" - "+\treturn retval;\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * OTG PCI remove: clean-up, disable controller hardware\n" - "+ *\n" - "+ * \\param pdev pci device info\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+static void __exit otg_pci_remove (struct pci_dev *pdev)\n" - "+{\n" - "+\tstruct otg *otg = pci_get_drvdata (pdev);\n" - "+\n" - "+\totg_remove (otg);\n" - "+\n" - "+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/\n" - "+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/\n" - "+/*** HS-A0 WA: BUG-3950: gadget disconnect notification ***/\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+\totg->got_irq = 0;\n" - "+\tfree_irq (pdev->irq, otg);\n" - "+#endif\n" - "+\tiounmap (otg->regs);\n" - "+\totg->regs = NULL;\n" - "+\totg->region = 0;\n" - "+\trelease_mem_region (pci_resource_start(pdev, 0),\n" - "+\t pci_resource_len(pdev, 0));\n" - "+\totg->enabled = 0;\n" - "+\tpci_disable_device (pdev);\n" - "+\totg->pdev = NULL;\n" - "+\tthe_controller = NULL;\n" - "+\tDBG ( \"kfree: OTG driver: %p\\n\", otg);\n" - "+\tkfree (otg);\n" - "+\totg = NULL;\n" - "+\tpci_set_drvdata(pdev, NULL);\n" - "+}\n" - "+#endif\n" - "+#endif\n" - "+\n" - "+\n" - "+/*****************************************************************************\n" - "+ * More data\n" - "+ *****************************************************************************/\n" - "+\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+#ifndef USE_AU1200_PCI_DUMMY\n" - "+/**\n" - "+ * \\brief\n" - "+ * driver struct to be used for driver registration\n" - "+ *\n" - "+ */\n" - "+static struct device_driver otg_device_driver = {\n" - "+\t.name =\t\t\"au1xxx-uoc\",\n" - "+\t.bus =\t\t&platform_bus_type,\n" - "+\t.probe =\totg_drv_probe,\n" - "+\t.remove =\totg_drv_remove,\n" - "+/* \t.suspend =\totg_drv_suspend, */\n" - "+/* \t.resume =\totg_drv_resume, */\n" - "+};\n" - "+#endif\n" - "+#else\n" - "+#ifdef CONFIG_PCI\n" - "+/**\n" - "+ * \\brief\n" - "+ * PCI ID table\n" - "+ *\n" - "+ */\n" - "+static struct pci_device_id pci_ids [] = { {\n" - "+\t.vendor =\tPCI_VENDOR_ID_AMD,\n" - "+\t.device =\tPCI_DEVICE_ID_AMD_CS5536_UOC,\n" - "+\t.subvendor =\tPCI_ANY_ID,\n" - "+\t.subdevice =\tPCI_ANY_ID,\n" - "+\t.class = \t0,\n" - "+\t.class_mask = \t0,\n" - "+\n" - "+}, { /* end: all zeroes */ }\n" - "+};\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * PCI driver struct to be used for driver registration\n" - "+ * ( this is a \"new style\" PCI driver module )\n" - "+ *\n" - "+ */\n" - "+static struct pci_driver otg_pci_driver = {\n" - "+\t.name =\t\t(char *) driver_name,\n" - "+\t.id_table =\tpci_ids,\n" - "+\t.probe =\totg_pci_probe,\n" - "+\t.remove =\totg_pci_remove,\n" - "+/* \t.suspend =\totg_pci_suspend, */\n" - "+/* \t.resume =\totg_pci_resume, */\n" - "+};\n" - "+MODULE_DEVICE_TABLE (pci, pci_ids);\n" - "+#endif\n" - "+#endif\n" - "+\n" - "+/* This comment closes the module definition from above. There can be multiple \n" - "+ definitions of this kind in a file. See the doxygen documentation for more\n" - "+ information. */\n" - "+/** \\}*/\n" - "+\n" - "+MODULE_DESCRIPTION (DRIVER_DESC);\n" - "+MODULE_AUTHOR (\"Karsten Boge\");\n" - "+MODULE_LICENSE (\"GPL\");\n" - "+\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+#ifdef USE_AU1200_PCI_DUMMY\n" - "+\n" - "+static int __init init (void)\n" - "+{\n" - "+\treturn otg_pci_probe (&pdev_dummy);\n" - "+}\n" - "+static void __exit cleanup (void)\n" - "+{\n" - "+\totg_pci_remove (&pdev_dummy);\n" - "+}\n" - "+#else\n" - "+\n" - "+static int __init init (void)\n" - "+{\n" - "+ return driver_register (&otg_device_driver);\n" - "+}\n" - "+static void __exit cleanup (void)\n" - "+{\n" - "+\tdriver_unregister (&otg_device_driver);\n" - "+}\n" - "+#endif\n" - "+#else\n" - "+#ifdef CONFIG_PCI\n" - "+\n" - "+static int __init init (void)\n" - "+{\n" - "+ return pci_module_init (&otg_pci_driver);\n" - "+}\n" - "+static void __exit cleanup (void)\n" - "+{\n" - "+\tpci_unregister_driver (&otg_pci_driver);\n" - "+}\n" - "+#endif\n" - "+#endif\n" - "+\n" - "+module_init (init);\n" - "+module_exit (cleanup);\n" - "diff --git a/drivers/usb/gadget/au1200uoc.h b/drivers/usb/gadget/au1200uoc.h\n" - "new file mode 100644\n" - "index 0000000..9b4503e\n" - "--- /dev/null\n" - "+++ b/drivers/usb/gadget/au1200uoc.h\n" - "@@ -0,0 +1,1338 @@\n" - "+/*\n" - "+ * AMD Au1200 USB OTG controller driver\n" - "+ */\n" - "+\n" - "+/*\n" - "+ * Copyright (C) 2005 AMD (http://www.amd.com)\n" - "+ * Author: Karsten Boge \n" - "+ *\n" - "+ * This program is free software; you can redistribute it and/or modify\n" - "+ * it under the terms of the GNU General Public License as published by\n" - "+ * the Free Software Foundation; either version 2 of the License, or\n" - "+ * (at your option) any later version.\n" - "+ *\n" - "+ * This program is distributed in the hope that it will be useful,\n" - "+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - "+ * GNU General Public License for more details.\n" - "+ *\n" - "+ * You should have received a copy of the GNU General Public License\n" - "+ * along with this program; if not, write to the Free Software\n" - "+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n" - "+ */\n" - "+#ifndef AU1200UOC_H\n" - "+#define AU1200UOC_H\n" - "+\n" - "+\n" - "+/*****************************************************************************\n" - "+* Config options\n" - "+*****************************************************************************/\n" - "+\n" - "+#ifndef UDC_HSA0_WORKAROUNDS\n" - "+#define UDC_HSA0_WORKAROUNDS\n" - "+#endif\n" - "+\n" - "+/* #define USE_AU1200_PCI_DUMMY */\n" - "+#undef USE_AU1200_PCI_DUMMY\n" - "+\n" - "+#ifdef CONFIG_USB_OTG\n" - "+#undef CONFIG_USB_OTGMUX_HOST\n" - "+#undef CONFIG_USB_OTGMUX_GADGET\n" - "+#undef CONFIG_USB_OTGMUX_IDPIN\n" - "+#endif\n" - "+\n" - "+#ifdef CONFIG_USB_OTGMUX_IDPIN\n" - "+#undef CONFIG_USB_OTGMUX_HOST\n" - "+#ifndef CONFIG_USB_OTGMUX_GADGET\n" - "+#define CONFIG_USB_OTGMUX_GADGET\n" - "+#endif\n" - "+#endif\n" - "+\n" - "+#ifndef OTG_HSA0_HNP_WA\n" - "+#define OTG_HSA0_HNP_WA\n" - "+#endif\n" - "+\n" - "+#ifdef VERBOSE\n" - "+#ifndef DEBUG\n" - "+#define DEBUG\n" - "+#endif\n" - "+#endif\n" - "+\n" - "+\n" - "+/*****************************************************************************\n" - "+* Constants\n" - "+*****************************************************************************/\n" - "+\n" - "+#define OTG_DRIVER_NAME \"au1200otg\"\n" - "+\n" - "+#define OTG_CHIPREV 0\n" - "+\n" - "+#define OTG_FLAGS_ACTIV (1<<19) /* full OTG functionality is activ */\n" - "+\n" - "+#ifndef CONFIG_SOC_AU1200\n" - "+#ifdef CONFIG_PCI\n" - "+#ifndef PCI_VENDOR_ID_AMD\n" - "+#define PCI_VENDOR_ID_AMD 0x1022\n" - "+#endif\n" - "+#ifndef PCI_DEVICE_ID_AMD_CS5536_UOC\n" - "+#define PCI_DEVICE_ID_AMD_CS5536_UOC 0x2097\n" - "+#endif\n" - "+#else\n" - "+#error \"!!! UNKNOWN SYSTEM BUS TYPE !!!\"\n" - "+#endif\n" - "+#endif\n" - "+\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+#define GPIO_2_BASE 200\n" - "+#define GPIO_215 215\n" - "+#define SYS_PINFUNC_P0A_GPIO (2<<17)\n" - "+#ifdef CONFIG_MIPS_PB1200\n" - "+#define USB_VBUS_GPIO 3 /* AU1000_GPIO_3 */\n" - "+#endif\n" - "+#ifdef CONFIG_MIPS_DB1200\n" - "+#define USB_VBUS_GPIO GPIO_215\n" - "+#endif\n" - "+#if !(defined(CONFIG_MIPS_PB1200) || defined(CONFIG_MIPS_DB1200))\n" - "+#error \"!!! UNKNOWN AU1200 BOARD !!!\"\n" - "+#endif\n" - "+#endif\n" - "+\n" - "+\n" - "+/**********************************\n" - "+* UOC Register definitions\n" - "+**********************************/\n" - "+\n" - "+/* capabilities */\n" - "+#define OTG_CAP_APU (1<<15) /* automatic pull-up enable */\n" - "+\n" - "+/* multiplexer */\n" - "+#define OTG_MUX_DISABLE_ALL 0 /* not assigned */\n" - "+#define OTG_MUX_ENABLE_UHC (2<<0) /* assigned to host */\n" - "+#define OTG_MUX_ENABLE_UDC (3<<0) /* assigned to device */\n" - "+#define OTG_MUX_PUEN (1<<2) /* pull-up enable */\n" - "+#define OTG_MUX_VBUSVLD (1<<8) /* VBus valid */\n" - "+\n" - "+/* status */\n" - "+#define OTG_STS_ID (1<<0) /* ID pin status */\n" - "+#define OTG_STS_VBUSVLD (1<<1) /* VBus valid */\n" - "+#define OTG_STS_SESSVLD (1<<2) /* Session valid */\n" - "+#define OTG_STS_SESSEND (1<<3) /* Session end */\n" - "+#define OTG_STS_LST (3<<4) /* Line state */\n" - "+#define OTG_STS_LST_J (1<<4) /* Line state */\n" - "+#define OTG_STS_LST_K (2<<4) /* Line state */\n" - "+#define OTG_STS_PSPD (3<<6) /* Port speed */\n" - "+#define OTG_STS_PSPD_LS (2<<6) /* Port speed */\n" - "+#define OTG_STS_PSPD_FS (1<<6) /* Port speed */\n" - "+#define OTG_STS_FSOE (1<<8) /* FS output enable (OHC) */\n" - "+#define OTG_STS_PCON (1<<9) /* Port connected */\n" - "+#define OTG_STS_PSUS (1<<10) /* Port suspended */\n" - "+#define OTG_STS_TMH (1<<11) /* Timer halted */\n" - "+#define OTG_STS_HNP_EN (1<<12) /* HNP enabled for B-dev */\n" - "+#define OTG_STS_HNP_SUPP (1<<13) /* A-host supports HNP */\n" - "+#define OTG_STS_HNP_ALTSUPP (1<<14) /* A-host supports alt. HNP */\n" - "+#define OTG_STS_HNPSTS (OTG_STS_HNP_EN | OTG_STS_HNP_SUPP | \\\n" - "+ OTG_STS_HNP_ALTSUPP)\n" - "+#define OTG_STS_OC (1<<15) /* over-current */\n" - "+#define OTG_STS_DPR (1<<16) /* Downstream port reset */\n" - "+\n" - "+/* control */\n" - "+#define OTG_CTL_DISABLE_ALL 0 /* not assigned */\n" - "+#define OTG_CTL_ENABLE_UHC (2<<0) /* assigned to host */\n" - "+#define OTG_CTL_ENABLE_UDC (3<<0) /* assigned to device */\n" - "+#define OTG_CTL_MUX_MASK (3<<0) /* port mux mask */\n" - "+#define OTG_CTL_PPWR (1<<2) /* port power switch */\n" - "+#define OTG_CTL_PPO (1<<3) /* port power override */\n" - "+#define OTG_CTL_CHRG (1<<4) /* charge VBus */\n" - "+#define OTG_CTL_DISCHRG (1<<5) /* discharge VBus */\n" - "+#define OTG_CTL_IDSNSEN (1<<6) /* ID sense enable, ID-PU */\n" - "+#define OTG_CTL_PADEN (1<<7)\n" - "+#define OTG_CTL_PUEN (1<<8) /* pull-up enable */\n" - "+#define OTG_CTL_DMPDEN (1<<9) /* pull-down enable */\n" - "+#define OTG_CTL_HNPSFEN (1<<10) /* HNP SET_FEATURE enable */\n" - "+#define OTG_CTL_WPCS_DEAS (2<<16) /* deassert port connect */\n" - "+#define OTG_CTL_WPCS_ASRT (3<<16) /* assert port connect */\n" - "+#define OTG_CTL_WPSS_DEAS (2<<18) /* deassert port suspend */\n" - "+#define OTG_CTL_WPSS_ASRT (3<<18) /* assert port suspend */\n" - "+/* timer conditions */\n" - "+#define OTG_CTL_TMR_RLP (1<<28) /* timer reload policy */\n" - "+#define OTG_CTL_TMR_ALL (0xf<<24) /* stop timer */\n" - "+#define OTG_CTL_TMR_STOP 0 /* timer disabled */\n" - "+#define OTG_CTL_TMR_UNCOND (1<<24) /* count unconditionally */\n" - "+#define OTG_CTL_TMR_SE0 (2<<24) /* count if LSt = FS-SE0 */\n" - "+#define OTG_CTL_TMR_FSJ (3<<24) /* count if LSt = FS-J */\n" - "+#define OTG_CTL_TMR_FSK (4<<24) /* count if LSt = FS-K */\n" - "+#define OTG_CTL_TMR_NOSE0 (5<<24) /* count if LSt <> FS-SE0 */\n" - "+#define OTG_CTL_TMR_NORX (6<<24) /* count if Rx inactiv */\n" - "+#define OTG_CTL_TMR_ID (7<<24) /* count if ID = 0 */\n" - "+\n" - "+/* interrupts */\n" - "+#define OTG_INT_GLOBAL (1<<31) /* global interrupt enable */\n" - "+#define OTG_INT_ENALL 0x7fff /* enable all */\n" - "+#define OTG_INT_DISALL 0 /* disable all */\n" - "+#define OTG_INT_IDC (1<<0) /* ID pin change */\n" - "+#define OTG_INT_VBVC (1<<1) /* VBUS valid change */\n" - "+#define OTG_INT_SVC (1<<2) /* Session valid change */\n" - "+#define OTG_INT_SEC (1<<3) /* Session end change */\n" - "+#define OTG_INT_LSTC (1<<4) /* Line state change */\n" - "+#define OTG_INT_PSPDC (1<<5) /* Port speed change */\n" - "+#define OTG_INT_FSOEC (1<<6) /* FS/LS OE change */\n" - "+#define OTG_INT_HSDD (1<<7) /* HS disconnect detected */\n" - "+#define OTG_INT_RXACT (1<<8) /* Rx activity detected */\n" - "+#define OTG_INT_PCC (1<<9) /* Port connect change */\n" - "+#define OTG_INT_PSC (1<<10) /* Port suspend change */\n" - "+#define OTG_INT_TMX (1<<11) /* Timer expired */\n" - "+#define OTG_INT_HNPFC (1<<12) /* HNP feature change */\n" - "+#define OTG_INT_OCD (1<<13) /* over current detected */\n" - "+#define OTG_INT_DPRC (1<<14) /* Downstream port reset change */\n" - "+\n" - "+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/\n" - "+/*** HS-A0 WA: BUG-3950: gadget SV notification ***/\n" - "+#ifdef UDC_HSA0_WORKAROUNDS\n" - "+#define OTG_INT_ADDS OTG_INT_SVC\n" - "+#endif\n" - "+\n" - "+\n" - "+/**********************************\n" - "+* OTG state dependend data\n" - "+**********************************/\n" - "+\n" - "+/*\n" - "+ * generic\n" - "+ */\n" - "+#define OTG_CTL_DEFAULT (OTG_CTL_PADEN | \\\n" - "+ OTG_CTL_IDSNSEN)\n" - "+#define OTG_CTL_HOST_DEFAULT (OTG_CTL_DEFAULT | \\\n" - "+ OTG_CTL_ENABLE_UHC)\n" - "+#ifdef UDC_HSA0_WORKAROUNDS\n" - "+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/\n" - "+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/\n" - "+#ifdef CONFIG_USB_OTG\n" - "+#define OTG_CTL_PERIPHERAL_DEFAULT (OTG_CTL_DEFAULT | \\\n" - "+ OTG_CTL_HNPSFEN | \\\n" - "+ OTG_CTL_ENABLE_UDC | \\\n" - "+ OTG_CTL_PPO | OTG_CTL_PUEN)\n" - "+#else\n" - "+#define OTG_CTL_PERIPHERAL_DEFAULT (OTG_CTL_DEFAULT | \\\n" - "+ OTG_CTL_ENABLE_UDC | \\\n" - "+ OTG_CTL_PPO | OTG_CTL_PUEN)\n" - "+#endif\n" - "+#else\n" - "+#ifdef CONFIG_USB_OTG\n" - "+#define OTG_CTL_PERIPHERAL_DEFAULT (OTG_CTL_DEFAULT | \\\n" - "+ OTG_CTL_HNPSFEN | \\\n" - "+ OTG_CTL_ENABLE_UDC | OTG_CTL_PPO)\n" - "+#else\n" - "+#define OTG_CTL_PERIPHERAL_DEFAULT (OTG_CTL_DEFAULT | \\\n" - "+ OTG_CTL_ENABLE_UDC | OTG_CTL_PPO)\n" - "+#endif\n" - "+#endif\n" - "+\n" - "+#define OTG_INT_DEFAULT OTG_INT_IDC\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_UNDEFINED\n" - "+ */\n" - "+#define OTG_STATE_UNDEFINED_CONTROL (OTG_CTL_DEFAULT | OTG_CTL_PPO | \\\n" - "+ OTG_CTL_TMR_UNCOND)\n" - "+#define OTG_STATE_UNDEFINED_STATUS 0\n" - "+#define OTG_STATE_UNDEFINED_STATUS_MASK 0\n" - "+#define OTG_STATE_UNDEFINED_INTERRUPTS OTG_INT_TMX\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_A_IDLE\n" - "+ */\n" - "+#define OTG_STATE_A_IDLE_CONTROL (OTG_CTL_DEFAULT | OTG_CTL_PPO)\n" - "+#define OTG_STATE_A_IDLE_STATUS 0\n" - "+#define OTG_STATE_A_IDLE_STATUS_MASK 0\n" - "+#define OTG_STATE_A_IDLE_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SVC | \\\n" - "+ OTG_INT_LSTC)\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_A_IDLE_WAIT_DP\n" - "+ */\n" - "+#define OTG_STATE_A_IDLE_WAIT_DP_CONTROL (OTG_STATE_A_IDLE_CONTROL | \\\n" - "+ OTG_CTL_TMR_UNCOND)\n" - "+#define OTG_STATE_A_IDLE_WAIT_DP_STATUS 0\n" - "+#define OTG_STATE_A_IDLE_WAIT_DP_STATUS_MASK 0\n" - "+#define OTG_STATE_A_IDLE_WAIT_DP_INTERRUPTS (OTG_STATE_A_IDLE_INTERRUPTS | \\\n" - "+ OTG_INT_TMX)\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_A_IDLE_WAIT_VP\n" - "+ */\n" - "+#define OTG_STATE_A_IDLE_WAIT_VP_CONTROL (OTG_STATE_A_IDLE_CONTROL | \\\n" - "+ OTG_CTL_TMR_UNCOND)\n" - "+#define OTG_STATE_A_IDLE_WAIT_VP_STATUS 0\n" - "+#define OTG_STATE_A_IDLE_WAIT_VP_STATUS_MASK 0\n" - "+#define OTG_STATE_A_IDLE_WAIT_VP_INTERRUPTS (OTG_STATE_A_IDLE_INTERRUPTS | \\\n" - "+ OTG_INT_TMX)\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_A_IDLE_WAIT_MP\n" - "+ */\n" - "+#define OTG_STATE_A_IDLE_WAIT_MP_CONTROL (OTG_STATE_A_IDLE_CONTROL | \\\n" - "+ OTG_CTL_TMR_UNCOND)\n" - "+#define OTG_STATE_A_IDLE_WAIT_MP_STATUS 0\n" - "+#define OTG_STATE_A_IDLE_WAIT_MP_STATUS_MASK 0\n" - "+#define OTG_STATE_A_IDLE_WAIT_MP_INTERRUPTS (OTG_STATE_A_IDLE_INTERRUPTS | \\\n" - "+ OTG_INT_TMX)\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_A_IDLE_WAIT_DV\n" - "+ */\n" - "+#define OTG_STATE_A_IDLE_WAIT_DV_CONTROL (OTG_STATE_A_IDLE_CONTROL | \\\n" - "+ OTG_CTL_TMR_UNCOND)\n" - "+#define OTG_STATE_A_IDLE_WAIT_DV_STATUS 0\n" - "+#define OTG_STATE_A_IDLE_WAIT_DV_STATUS_MASK 0\n" - "+#define OTG_STATE_A_IDLE_WAIT_DV_INTERRUPTS (OTG_STATE_A_IDLE_INTERRUPTS | \\\n" - "+ OTG_INT_TMX)\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_A_WAIT_VRISE\n" - "+ */\n" - "+#define OTG_STATE_A_WAIT_VRISE_CONTROL (OTG_CTL_HOST_DEFAULT | \\\n" - "+ OTG_CTL_TMR_UNCOND)\n" - "+#define OTG_STATE_A_WAIT_VRISE_STATUS 0\n" - "+#define OTG_STATE_A_WAIT_VRISE_STATUS_MASK 0\n" - "+#define OTG_STATE_A_WAIT_VRISE_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_TMX | \\\n" - "+ OTG_INT_VBVC)\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_A_WAIT_BCON\n" - "+ */\n" - "+#define OTG_STATE_A_WAIT_BCON_CONTROL OTG_CTL_HOST_DEFAULT\n" - "+#define OTG_STATE_A_WAIT_BCON_STATUS 0\n" - "+#define OTG_STATE_A_WAIT_BCON_STATUS_MASK 0\n" - "+#define OTG_STATE_A_WAIT_BCON_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_TMX | \\\n" - "+ OTG_INT_VBVC | OTG_INT_PCC)\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_A_WAIT_BCON_VB\n" - "+ */\n" - "+#define OTG_STATE_A_WAIT_BCON_VB_CONTROL (OTG_STATE_A_WAIT_BCON_CONTROL | \\\n" - "+ OTG_CTL_TMR_UNCOND)\n" - "+#define OTG_STATE_A_WAIT_BCON_VB_STATUS 0\n" - "+#define OTG_STATE_A_WAIT_BCON_VB_STATUS_MASK 0\n" - "+#define OTG_STATE_A_WAIT_BCON_VB_INTERRUPTS OTG_STATE_A_WAIT_BCON_INTERRUPTS\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_A_HOST\n" - "+ */\n" - "+#define OTG_STATE_A_HOST_CONTROL OTG_CTL_HOST_DEFAULT\n" - "+#define OTG_STATE_A_HOST_STATUS 0\n" - "+#define OTG_STATE_A_HOST_STATUS_MASK 0\n" - "+#ifdef CONFIG_USB_OTG\n" - "+#ifndef VERBOSE\n" - "+#define OTG_STATE_A_HOST_INTERRUPTS (OTG_INT_DEFAULT | \\\n" - "+ OTG_INT_VBVC | OTG_INT_DPRC | \\\n" - "+ OTG_INT_PCC | OTG_INT_PSC)\n" - "+#else\n" - "+#define OTG_STATE_A_HOST_INTERRUPTS (OTG_INT_DEFAULT | \\\n" - "+ OTG_INT_VBVC | OTG_INT_DPRC | \\\n" - "+ OTG_INT_PCC | OTG_INT_PSC | \\\n" - "+ OTG_INT_PSPDC)\n" - "+ /* OTG_INT_LSTC */\n" - "+#endif\n" - "+#else\n" - "+ /* IDPIN mode only */\n" - "+#define OTG_STATE_A_HOST_INTERRUPTS OTG_INT_IDC\n" - "+#endif\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_A_SUSPEND\n" - "+ */\n" - "+#define OTG_STATE_A_SUSPEND_CONTROL (OTG_CTL_HOST_DEFAULT | \\\n" - "+ OTG_CTL_TMR_UNCOND)\n" - "+#define OTG_STATE_A_SUSPEND_STATUS 0\n" - "+#define OTG_STATE_A_SUSPEND_STATUS_MASK 0\n" - "+#define OTG_STATE_A_SUSPEND_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_TMX | \\\n" - "+ OTG_INT_VBVC | OTG_INT_DPRC | \\\n" - "+ OTG_INT_PCC | OTG_INT_PSC)\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_A_PERIPHERAL\n" - "+ */\n" - "+#define OTG_STATE_A_PERIPHERAL_CONTROL (OTG_CTL_PERIPHERAL_DEFAULT | \\\n" - "+ OTG_CTL_PPWR | OTG_CTL_DMPDEN)\n" - "+#define OTG_STATE_A_PERIPHERAL_STATUS 0\n" - "+#define OTG_STATE_A_PERIPHERAL_STATUS_MASK 0\n" - "+#ifndef VERBOSE\n" - "+#define OTG_STATE_A_PERIPHERAL_INTERRUPTS (OTG_INT_DEFAULT | \\\n" - "+ OTG_INT_VBVC | OTG_INT_OCD | \\\n" - "+ OTG_INT_PCC | OTG_INT_PSC)\n" - "+#else\n" - "+#define OTG_STATE_A_PERIPHERAL_INTERRUPTS (OTG_INT_DEFAULT | \\\n" - "+ OTG_INT_VBVC | OTG_INT_OCD | \\\n" - "+ OTG_INT_PCC | OTG_INT_PSC | \\\n" - "+ OTG_INT_PSPDC)\n" - "+ /* OTG_INT_LSTC */\n" - "+#endif\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_A_VBUS_ERR\n" - "+ */\n" - "+#define OTG_STATE_A_VBUS_ERR_CONTROL (OTG_CTL_HOST_DEFAULT | \\\n" - "+ OTG_CTL_PPO | OTG_CTL_DISCHRG)\n" - "+#define OTG_STATE_A_VBUS_ERR_STATUS 0\n" - "+#define OTG_STATE_A_VBUS_ERR_STATUS_MASK 0\n" - "+#define OTG_STATE_A_VBUS_ERR_INTERRUPTS OTG_INT_DEFAULT\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_A_WAIT_VFALL\n" - "+ */\n" - "+#define OTG_STATE_A_WAIT_VFALL_CONTROL (OTG_CTL_HOST_DEFAULT | \\\n" - "+ OTG_CTL_PPO)\n" - "+#define OTG_STATE_A_WAIT_VFALL_STATUS 0\n" - "+#define OTG_STATE_A_WAIT_VFALL_STATUS_MASK 0\n" - "+#define OTG_STATE_A_WAIT_VFALL_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SEC)\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_A_WAIT_VFALL_DN\n" - "+ */\n" - "+#define OTG_STATE_A_WAIT_VFALL_DN_CONTROL (OTG_STATE_A_WAIT_VFALL_CONTROL | \\\n" - "+ OTG_CTL_DISCHRG)\n" - "+#define OTG_STATE_A_WAIT_VFALL_DN_STATUS 0\n" - "+#define OTG_STATE_A_WAIT_VFALL_DN_STATUS_MASK 0\n" - "+#define OTG_STATE_A_WAIT_VFALL_DN_INTERRUPTS OTG_STATE_A_WAIT_VFALL_INTERRUPTS\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_A_WAIT_BDISCON\n" - "+ */\n" - "+#define OTG_STATE_A_WAIT_BDISCON_CONTROL (OTG_CTL_DEFAULT | \\\n" - "+ OTG_CTL_PPO | OTG_CTL_PPWR | \\\n" - "+ OTG_CTL_TMR_UNCOND)\n" - "+#define OTG_STATE_A_WAIT_BDISCON_STATUS 0\n" - "+#define OTG_STATE_A_WAIT_BDISCON_STATUS_MASK 0\n" - "+#define OTG_STATE_A_WAIT_BDISCON_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_TMX | \\\n" - "+ OTG_INT_VBVC | OTG_INT_OCD | \\\n" - "+ OTG_INT_PSPDC | OTG_INT_LSTC)\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_B_IDLE\n" - "+ */\n" - "+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/\n" - "+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/\n" - "+#ifdef UDC_HSA0_WORKAROUNDS\n" - "+#define OTG_STATE_B_IDLE_CONTROL (OTG_CTL_PERIPHERAL_DEFAULT & \\\n" - "+ ~((u32) (OTG_CTL_PUEN | \\\n" - "+ OTG_CTL_ENABLE_UDC)))\n" - "+#else\n" - "+#define OTG_STATE_B_IDLE_CONTROL OTG_CTL_PERIPHERAL_DEFAULT\n" - "+#endif\n" - "+#define OTG_STATE_B_IDLE_STATUS 0\n" - "+#define OTG_STATE_B_IDLE_STATUS_MASK 0\n" - "+#ifdef CONFIG_USB_OTG\n" - "+#define OTG_STATE_B_IDLE_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SVC)\n" - "+#else\n" - "+#ifdef CONFIG_USB_OTGMUX_IDPIN\n" - "+ /* IDPIN mode */\n" - "+#define OTG_STATE_B_IDLE_INTERRUPTS (OTG_INT_IDC | OTG_INT_SVC)\n" - "+#else\n" - "+ /* gadget mode */\n" - "+#define OTG_STATE_B_IDLE_INTERRUPTS OTG_INT_SVC\n" - "+#endif\n" - "+#endif\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_B_PERIPHERAL\n" - "+ */\n" - "+#define OTG_STATE_B_PERIPHERAL_CONTROL (OTG_CTL_PERIPHERAL_DEFAULT | \\\n" - "+ OTG_CTL_DMPDEN)\n" - "+#define OTG_STATE_B_PERIPHERAL_STATUS 0\n" - "+#define OTG_STATE_B_PERIPHERAL_STATUS_MASK 0\n" - "+#ifdef CONFIG_USB_OTG\n" - "+#ifndef VERBOSE\n" - "+#define OTG_STATE_B_PERIPHERAL_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SVC | \\\n" - "+ OTG_INT_PCC | OTG_INT_PSC | \\\n" - "+ OTG_INT_HNPFC)\n" - "+#else\n" - "+#define OTG_STATE_B_PERIPHERAL_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SVC | \\\n" - "+ OTG_INT_PCC | OTG_INT_PSC | \\\n" - "+ OTG_INT_HNPFC | OTG_INT_PSPDC)\n" - "+ /* OTG_INT_LSTC */\n" - "+#endif\n" - "+#else\n" - "+#ifdef CONFIG_USB_OTGMUX_IDPIN\n" - "+ /* IDPIN mode */\n" - "+#define OTG_STATE_B_PERIPHERAL_INTERRUPTS (OTG_INT_IDC | OTG_INT_SVC)\n" - "+#else\n" - "+ /* gadget mode */\n" - "+#define OTG_STATE_B_PERIPHERAL_INTERRUPTS OTG_INT_SVC\n" - "+#endif\n" - "+#endif\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_B_PERIPHERAL_WT\n" - "+ */\n" - "+#define OTG_STATE_B_PERIPHERAL_WT_CONTROL (OTG_STATE_B_PERIPHERAL_CONTROL | \\\n" - "+ OTG_CTL_PPO | OTG_CTL_TMR_UNCOND)\n" - "+#define OTG_STATE_B_PERIPHERAL_WT_STATUS 0\n" - "+#define OTG_STATE_B_PERIPHERAL_WT_STATUS_MASK 0\n" - "+#define OTG_STATE_B_PERIPHERAL_WT_INTERRUPTS (OTG_STATE_B_PERIPHERAL_INTERRUPTS \\\n" - "+ | OTG_INT_TMX)\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_B_PERIPHERAL_DC\n" - "+ */\n" - "+#define OTG_STATE_B_PERIPHERAL_DC_CONTROL (OTG_CTL_HOST_DEFAULT | \\\n" - "+ OTG_CTL_PPO | OTG_CTL_DMPDEN | \\\n" - "+ OTG_CTL_TMR_UNCOND)\n" - "+#define OTG_STATE_B_PERIPHERAL_DC_STATUS 0\n" - "+#define OTG_STATE_B_PERIPHERAL_DC_STATUS_MASK 0\n" - "+#define OTG_STATE_B_PERIPHERAL_DC_INTERRUPTS (OTG_STATE_B_PERIPHERAL_INTERRUPTS \\\n" - "+ | OTG_INT_TMX | OTG_INT_LSTC)\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_B_WAIT_ACON\n" - "+ */\n" - "+#define OTG_STATE_B_WAIT_ACON_CONTROL (OTG_CTL_HOST_DEFAULT | \\\n" - "+ OTG_CTL_PPO | OTG_CTL_TMR_UNCOND)\n" - "+#define OTG_STATE_B_WAIT_ACON_STATUS 0\n" - "+#define OTG_STATE_B_WAIT_ACON_STATUS_MASK 0\n" - "+#define OTG_STATE_B_WAIT_ACON_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SVC | \\\n" - "+ OTG_INT_PCC | OTG_INT_PSC | \\\n" - "+ OTG_INT_HNPFC | OTG_INT_TMX)\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_B_HOST\n" - "+ */\n" - "+#define OTG_STATE_B_HOST_CONTROL (OTG_CTL_HOST_DEFAULT | \\\n" - "+ OTG_CTL_PPO)\n" - "+#define OTG_STATE_B_HOST_STATUS 0\n" - "+#define OTG_STATE_B_HOST_STATUS_MASK 0\n" - "+#ifndef VERBOSE\n" - "+#define OTG_STATE_B_HOST_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SVC | \\\n" - "+ OTG_INT_PCC)\n" - "+#else\n" - "+#define OTG_STATE_B_HOST_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SVC | \\\n" - "+ OTG_INT_PCC | OTG_INT_SVC | \\\n" - "+ OTG_INT_PSPDC)\n" - "+ /* OTG_INT_LSTC */\n" - "+#endif\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_B_HOST_WT\n" - "+ */\n" - "+#define OTG_STATE_B_HOST_WT_CONTROL (OTG_STATE_B_HOST_CONTROL | \\\n" - "+ OTG_CTL_TMR_UNCOND)\n" - "+#define OTG_STATE_B_HOST_WT_STATUS 0\n" - "+#define OTG_STATE_B_HOST_WT_STATUS_MASK 0\n" - "+#ifndef VERBOSE\n" - "+#define OTG_STATE_B_HOST_WT_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SVC | \\\n" - "+ OTG_INT_PCC | OTG_INT_TMX)\n" - "+#else\n" - "+#define OTG_STATE_B_HOST_WT_INTERRUPTS (OTG_STATE_B_HOST_INTERRUPTS | \\\n" - "+ OTG_INT_TMX)\n" - "+/*\n" - "+#define OTG_STATE_B_HOST_WT_INTERRUPTS (OTG_INT_DEFAULT | OTG_INT_SVC | \\\n" - "+ OTG_INT_PCC | OTG_INT_DPRC | \\\n" - "+ OTG_INT_TMX | OTG_INT_PSPDC) */\n" - "+ /* OTG_INT_LSTC */\n" - "+#endif\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_B_SRP_INIT\n" - "+ */\n" - "+#define OTG_STATE_B_SRP_INIT_CONTROL OTG_STATE_B_IDLE_CONTROL\n" - "+#define OTG_STATE_B_SRP_INIT_STATUS 0\n" - "+#define OTG_STATE_B_SRP_INIT_STATUS_MASK 0\n" - "+#define OTG_STATE_B_SRP_INIT_INTERRUPTS OTG_INT_DEFAULT \n" - "+\n" - "+/*\n" - "+ * OTG_STATE_B_SRP_WTSE0\n" - "+ */\n" - "+#define OTG_STATE_B_SRP_WAIT_SE0_CONTROL (OTG_STATE_B_SRP_INIT_CONTROL | \\\n" - "+ OTG_CTL_TMR_UNCOND)\n" - "+#define OTG_STATE_B_SRP_WAIT_SE0_STATUS 0\n" - "+#define OTG_STATE_B_SRP_WAIT_SE0_STATUS_MASK 0\n" - "+#define OTG_STATE_B_SRP_WAIT_SE0_INTERRUPTS (OTG_STATE_B_SRP_INIT_INTERRUPTS \\\n" - "+ | OTG_INT_TMX | OTG_INT_LSTC)\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_B_SRP_D_PLS\n" - "+ *\n" - "+ * note: changing to this state requires an additional call:\n" - "+ * set_srp_conditions (dev);\n" - "+ * reset_srp_conditions (dev) is required for the next state\n" - "+ */\n" - "+/*** HS-A0 WA: BUG-3885: VB_SESS_VLD value too high ***/\n" - "+/*** HS-A0 WA: BUG-3943: gadget suspend issue ***/\n" - "+/* note: set_/reset_srp_conditions is not needed if HS-A0 WAs are active\n" - "+ */\n" - "+#ifdef UDC_HSA0_WORKAROUNDS\n" - "+#define OTG_STATE_B_SRP_D_PULSE_CONTROL (OTG_CTL_PERIPHERAL_DEFAULT | \\\n" - "+ OTG_CTL_PUEN | \\\n" - "+ OTG_CTL_TMR_UNCOND)\n" - "+#else\n" - "+#define OTG_STATE_B_SRP_D_PULSE_CONTROL (OTG_STATE_B_SRP_INIT_CONTROL | \\\n" - "+ OTG_CTL_PUEN | \\\n" - "+ OTG_CTL_TMR_UNCOND)\n" - "+#endif\n" - "+#define OTG_STATE_B_SRP_D_PULSE_STATUS 0\n" - "+#define OTG_STATE_B_SRP_D_PULSE_STATUS_MASK 0\n" - "+#define OTG_STATE_B_SRP_D_PULSE_INTERRUPTS (OTG_STATE_B_SRP_INIT_INTERRUPTS \\\n" - "+ | OTG_INT_SEC | OTG_INT_TMX)\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_B_SRP_V_PLS\n" - "+ */\n" - "+#define OTG_STATE_B_SRP_V_PULSE_CONTROL (OTG_STATE_B_SRP_INIT_CONTROL | \\\n" - "+ OTG_CTL_CHRG | \\\n" - "+ OTG_CTL_TMR_UNCOND)\n" - "+#define OTG_STATE_B_SRP_V_PULSE_STATUS 0\n" - "+#define OTG_STATE_B_SRP_V_PULSE_STATUS_MASK 0\n" - "+#define OTG_STATE_B_SRP_V_PULSE_INTERRUPTS (OTG_STATE_B_SRP_INIT_INTERRUPTS \\\n" - "+ | OTG_INT_TMX)\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_B_SRP_V_DCG\n" - "+ */\n" - "+#define OTG_STATE_B_SRP_V_DCHRG_CONTROL (OTG_STATE_B_SRP_INIT_CONTROL | \\\n" - "+ OTG_CTL_DISCHRG | \\\n" - "+ OTG_CTL_TMR_UNCOND)\n" - "+#define OTG_STATE_B_SRP_V_DCHRG_STATUS 0\n" - "+#define OTG_STATE_B_SRP_V_DCHRG_STATUS_MASK 0\n" - "+#define OTG_STATE_B_SRP_V_DCHRG_INTERRUPTS (OTG_STATE_B_SRP_INIT_INTERRUPTS \\\n" - "+ | OTG_INT_TMX)\n" - "+\n" - "+/*\n" - "+ * OTG_STATE_B_SRP_WTVB\n" - "+ */\n" - "+#define OTG_STATE_B_SRP_WAIT_VBUS_CONTROL (OTG_STATE_B_SRP_INIT_CONTROL | \\\n" - "+ OTG_CTL_TMR_UNCOND)\n" - "+#define OTG_STATE_B_SRP_WAIT_VBUS_STATUS 0\n" - "+#define OTG_STATE_B_SRP_WAIT_VBUS_STATUS_MASK 0\n" - "+#define OTG_STATE_B_SRP_WAIT_VBUS_INTERRUPTS (OTG_STATE_B_SRP_INIT_INTERRUPTS \\\n" - "+ | OTG_INT_SVC | OTG_INT_TMX)\n" - "+\n" - "+/*********************************/\n" - "+\n" - "+/* other */\n" - "+\n" - "+#define OTG_APP_REQ_ACK 0\n" - "+\n" - "+\n" - "+/*****************************************************************************\n" - "+* Types\n" - "+*****************************************************************************/\n" - "+\n" - "+\n" - "+/*****************************************************************************\n" - "+* Macros\n" - "+*****************************************************************************/\n" - "+\n" - "+/* printing messages */\n" - "+#ifndef INFO\n" - "+#define INFO(args...) \\\n" - "+ printk(KERN_INFO DRIVER_NAME_FOR_PRINT \": \" args)\n" - "+#endif\n" - "+\n" - "+#ifndef WARN\n" - "+#define WARN(args...) \\\n" - "+ printk(KERN_WARNING DRIVER_NAME_FOR_PRINT \" warning: \" args)\n" - "+#endif\n" - "+\n" - "+#ifndef ERR\n" - "+#define ERR(args...) \\\n" - "+ printk(KERN_ERR DRIVER_NAME_FOR_PRINT \" error: \" args)\n" - "+#endif\n" - "+\n" - "+#ifndef DBG \n" - "+#ifdef DEBUG\n" - "+#define DBG(args...) \\\n" - "+ printk(KERN_DEBUG DRIVER_NAME_FOR_PRINT \" debug: \" args)\n" - "+#else\n" - "+#define DBG(args...) \\\n" - "+ do {} while (0)\n" - "+#endif\n" - "+#endif\n" - "+\n" - "+#ifndef VDBG \n" - "+#ifdef VERBOSE\n" - "+#define VDBG DBG\n" - "+#else\n" - "+#define VDBG(args...) \\\n" - "+\tdo { } while (0)\n" - "+#endif\n" - "+#endif\n" - "+\n" - "+/****************************************************************************/\n" - "+\n" - "+/* this should always return \"1\" and print something in verbose mode */\n" - "+#ifdef VERBOSE\n" - "+#define VDBG_SPC(fmt,args...) \\\n" - "+\t(VDBG (fmt, args) ? 1 : 1)\n" - "+#else\n" - "+#define VDBG_SPC(fmt,args...) 1\n" - "+#endif\n" - "+\n" - "+/* query bit(s) (long: 32-bit access) */\n" - "+#define IS_BIT_RES(data, code) \\\n" - "+\t(!((data) & (code)) ? \\\n" - "+\t (VDBG_SPC (\" OTG HW status: %s is reset\\n\", #data)) : 0)\n" - "+\n" - "+#define IS_BIT_SET(data, code) \\\n" - "+\t(((data) & (code)) ? \\\n" - "+\t (VDBG_SPC (\" OTG HW status: %s is set\\n\", #data)) : 0)\n" - "+\n" - "+/* query SW flag(s) */\n" - "+#define IS_FLAG_RES(dev, data) \\\n" - "+\t(!((data) & (dev)->params) ? \\\n" - "+\t (VDBG_SPC (\" OTG SW status: %s is reset\\n\", #data)) : 0)\n" - "+\n" - "+#define IS_FLAG_SET(dev, data) \\\n" - "+\t(((data) & (dev)->params) ? \\\n" - "+\t (VDBG_SPC (\" OTG SW status: %s is set\\n\", #data)) : 0)\n" - "+\n" - "+/* query event bit(s) */\n" - "+#define GOT_EVENT(data, code) \\\n" - "+\t(((data) & (code)) ? \\\n" - "+\t (VDBG_SPC (\" OTG event: %s\\n\", #data)) : 0)\n" - "+\n" - "+/* set SW flag */\n" - "+#ifdef VERBOSE\n" - "+#define SET_FLAG(dev, data) \\\n" - "+\tif (!((data) & (dev)->params)) \\\n" - "+\t\tDBG (\" OTG SW status change: set flag %s\\n\", #data); \\\n" - "+\t(dev)->params |= (data)\n" - "+#else\n" - "+#define SET_FLAG(dev, data) \\\n" - "+\t(dev)->params |= (data)\n" - "+#endif\n" - "+\n" - "+/* reset SW flag */\n" - "+#ifdef VERBOSE\n" - "+#define RES_FLAG(dev, data) \\\n" - "+\tif ((data) & (dev)->params) \\\n" - "+\t\tDBG (\" OTG SW status change: reset flag %s\\n\", #data); \\\n" - "+\t(dev)->params &= ~((u32) (data))\n" - "+#else\n" - "+#define RES_FLAG(dev, data) \\\n" - "+\t(dev)->params &= ~((u32) (data))\n" - "+#endif\n" - "+\n" - "+/* reset event bit */\n" - "+#define RES_EVENT(data, code) \\\n" - "+\t(code) &= ~((u32) (data))\n" - "+/* NOTE: this is not really needed so far, might be replaced with */\n" - "+/* #define RES_EVENT(data, code) \\ */\n" - "+/* \tdo {} while (0) */\n" - "+\n" - "+/* change OTG state */\n" - "+#ifdef CONFIG_USB_OTG\n" - "+#define PREPARE_STATE_CHANGE_1ST(dev, new_state) \\\n" - "+\tswitch ((new_state) & OTG_STATE_MASK) { \\\n" - "+\tcase OTG_STATE_UNDEFINED: \\\n" - "+\t\tset_undef_state_defaults((dev)); \\\n" - "+\t\tbreak; \\\n" - "+\tcase OTG_STATE_A_IDLE: \\\n" - "+\t\tset_a_state_defaults((dev)); \\\n" - "+\t\tbreak; \\\n" - "+\tcase OTG_STATE_B_IDLE: \\\n" - "+\t\tset_b_state_defaults((dev)); \\\n" - "+\t\tbreak; \\\n" - "+\tdefault: \\\n" - "+\t\tbreak; \\\n" - "+\t} \\\n" - "+\tdo {} while (0)\n" - "+#else\n" - "+#define PREPARE_STATE_CHANGE_1ST(dev, new_state) \\\n" - "+\tdo {} while (0)\n" - "+#endif\n" - "+\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+\n" - "+#if (USB_VBUS_GPIO < GPIO_2_BASE)\n" - "+#define AU1000GPIO_SET_BIT(data) \\\n" - "+\tau1000gpio_bit_set (data)\n" - "+#define AU1000GPIO_CLR_BIT(data) \\\n" - "+\tau1000gpio_bit_clear (data)\n" - "+#define AU1000GPIO_INIT_BIT(data) \\\n" - "+\tau1000gpio_bit_init (data)\n" - "+#define AU1000GPIO_TERM_BIT(data) \\\n" - "+\tau1000gpio_bit_term (data)\n" - "+#else\n" - "+#define AU1000GPIO_SET_BIT(data) \\\n" - "+\tau1000gpio2_bit_set (data)\n" - "+#define AU1000GPIO_CLR_BIT(data) \\\n" - "+\tau1000gpio2_bit_clear (data)\n" - "+#define AU1000GPIO_INIT_BIT(data) \\\n" - "+\tau1000gpio2_bit_init (data)\n" - "+#define AU1000GPIO_TERM_BIT(data) \\\n" - "+\tau1000gpio2_bit_term (data)\n" - "+#endif\n" - "+\n" - "+#define PREPARE_STATE_CHANGE_2ND(new_state_control) \\\n" - "+\tif (((new_state_control) & OTG_CTL_PPO) && \\\n" - "+\t (~(new_state_control) & OTG_CTL_PPWR)) \\\n" - "+\t\tAU1000GPIO_SET_BIT(USB_VBUS_GPIO); \\\n" - "+\telse \\\n" - "+\t\tAU1000GPIO_CLR_BIT(USB_VBUS_GPIO)\n" - "+#else\n" - "+#define PREPARE_STATE_CHANGE_2ND(new_state_control) \\\n" - "+\tdo {} while (0)\n" - "+#endif\n" - "+\n" - "+#define CHANGE_STATE(dev, new_state, pMask) \\\n" - "+\tPREPARE_STATE_CHANGE_1ST(dev, new_state); \\\n" - "+\tPREPARE_STATE_CHANGE_2ND(new_state##_CONTROL); \\\n" - "+\twritel ((new_state##_CONTROL), &(dev)->regs->ctl); \\\n" - "+\t*(pMask) = (new_state##_INTERRUPTS); \\\n" - "+\t(dev)->transceiver.state = (new_state); \\\n" - "+\tDBG (\"OTG new state: %s\\n\", #new_state)\n" - "+\n" - "+/* verify OTG state */\n" - "+#ifndef CONFIG_OTG_TEST_MODE\n" - "+\n" - "+#define CHECK_STATE(dev, act_state, pMask) \\\n" - "+\t*(pMask) = (act_state##_INTERRUPTS); \\\n" - "+\t(dev)->prv_state = (act_state); \\\n" - "+\tVDBG (\"OTG state: %s\\n\", #act_state)\n" - "+#else\n" - "+#define CHECK_STATE(dev, act_state, pMask) \\\n" - "+\t*(pMask) = (act_state##_INTERRUPTS); \\\n" - "+\t(dev)->prv_state = (act_state); \\\n" - "+\tif (((readl (&(dev)->regs->sts) ^ (act_state##_STATUS))) & \\\n" - "+\t act_state##_STATUS_MASK) \\\n" - "+\t\tWARN (\"OTG warning: incorrect status\\n\"); \\\n" - "+\tVDBG (\"OTG state: %s\\n\", #act_state)\n" - "+#endif\n" - "+\n" - "+/* set timer */\n" - "+#define SET_OTG_TIMER(dev, val) \\\n" - "+\tset_timer ((dev), ((OTG_TMR_##val) * 100))\n" - "+\n" - "+/* set timer ( <1ms ) */\n" - "+#define SET_OTG_TIMER_SHORT(dev, val) \\\n" - "+\tset_timer ((dev), ((OTG_TMR_##val) / 10))\n" - "+\n" - "+/* set timer ( >10ms ) */\n" - "+#define SET_OTG_TIMER_LONG(dev, val) \\\n" - "+\tset_timer_long ((dev), ((OTG_TMR_##val) / 10))\n" - "+\n" - "+#ifdef VERBOSE\n" - "+#define HS_DISCON_WARNING() \\\n" - "+\tif (!(OTG_CTL_ENABLE_UHC ^ \\\n" - "+\t (OTG_CTL_MUX_MASK & readl (&dev->regs->ctl))) && \\\n" - "+\t !(OTG_STS_PSPD & readl (&dev->regs->sts))) \\\n" - "+\t\tDBG (\" OTG warning: disable UHC from HS-mode\\n\")\n" - "+#else\n" - "+#define HS_DISCON_WARNING() \\\n" - "+\tdo { } while (0)\n" - "+#endif\n" - "+\n" - "+\n" - "+/*****************************************************************************\n" - "+* Data\n" - "+*****************************************************************************/\n" - "+struct otg_regs {\n" - "+\tu32 cap; /* capabilities */\n" - "+\tu32 mux; /* mux */\n" - "+\tu32 sts; /* status */\n" - "+\tu32 ctl; /* control */\n" - "+\tu32 tmr; /* timer */\n" - "+\tu32 intr; /* interrupt request */\n" - "+\tu32 inten; /* interrupt enable */\n" - "+} __attribute__ ((packed));\n" - "+\n" - "+struct otg {\n" - "+\tspinlock_t lock;\n" - "+\tunsigned enabled : 1,\n" - "+\t got_irq : 1,\n" - "+\t region : 1;\n" - "+\tu16 chiprev;\n" - "+\n" - "+ /* state variables */\n" - "+ u8 prv_state;\n" - "+ u32 params;\n" - "+ void *otg_priv;\n" - "+ u8 hostcount;\n" - "+\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+#ifdef USE_AU1200_PCI_DUMMY\n" - "+\n" - "+\tstruct pci_dev *pdev;\n" - "+#else\n" - "+\tstruct platform_device *pdev;\n" - "+#endif\n" - "+#else\n" - "+\tstruct pci_dev *pdev;\n" - "+#endif\n" - "+\tstruct otg_regs *regs;\n" - "+\tstruct otg_transceiver transceiver;\n" - "+};\n" - "+#define transceiver_to_otg(pTransceiver) \\\n" - "+\tcontainer_of (pTransceiver, struct otg, transceiver)\n" - "+#define otg_to_transceiver(pOtg) \\\n" - "+\t&pOtg->transceiver\n" - "+\n" - "+#ifdef CONFIG_USB_OTG_TEST_INTERFACE\n" - "+struct usb_otg_test_extension {\n" - "+\tint (*bind) (struct otg **);\n" - "+\tint (*unbind) (struct otg **);\n" - "+\tint (*request) (u32);\t/* function call for state change requests */\n" - "+\tu32 (*query) (int);\t/* function call to query state */\n" - "+};\n" - "+#endif\n" - "+\n" - "+#ifdef\t__KERNEL__\n" - "+\n" - "+/* 2.5 and 2.4.older portability changes ... */\n" - "+\n" - "+#ifndef container_of\n" - "+#define\tcontainer_of\tlist_entry\n" - "+#endif\n" - "+\n" - "+#ifndef likely\n" - "+#define likely(x) (x)\n" - "+#define unlikely(x) (x)\n" - "+#endif\n" - "+\n" - "+#ifndef BUG_ON\n" - "+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)\n" - "+#endif\n" - "+\n" - "+#ifndef WARN_ON\n" - "+#define\tWARN_ON(x)\tdo { } while (0)\n" - "+#endif\n" - "+\n" - "+#endif\t/* __KERNEL__ */\n" - "+\n" - "+/*****************************************************************************\n" - "+* Functions\n" - "+*****************************************************************************/\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+extern int usb_gadget_register_otg (struct otg_transceiver * (\n" - "+ *get_transceiver)(void));\n" - "+extern int usb_gadget_unregister_otg (void);\n" - "+\n" - "+#endif\n" - "+#ifdef CONFIG_USB_OTG\n" - "+u32 otg_change_state (struct otg *, u32, u32 *);\n" - "+int otg_hnp_start_enum (struct otg_transceiver *);\n" - "+#endif\n" - "+\n" - "+void otg_init_state (struct otg *);\n" - "+int otg_exit_state (struct otg *);\n" - "+\n" - "+#ifdef DEBUG\n" - "+static void print_regs (struct otg *);\n" - "+#endif /* DEBUG */\n" - "+\n" - "+#ifdef CONFIG_USB_OTG_TEST_INTERFACE\n" - "+int usb_otg_test_register_driver (struct usb_otg_test_extension *);\n" - "+int usb_otg_test_unregister_driver (void);\n" - "+#endif\n" - "+\n" - "+/*****************************************************************************\n" - "+* Inline Functions\n" - "+*****************************************************************************/\n" - "+\n" - "+extern u32 otg_tmr_high_count;\n" - "+extern struct otg_ctl *otg_ctl;\n" - "+\n" - "+#ifdef CONFIG_USB_OTG\n" - "+/**\n" - "+ * \\brief\n" - "+ * set neutral state information\n" - "+ *\n" - "+ * \\param dev OTG controller info\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+static inline void set_undef_state_defaults (struct otg *dev)\n" - "+{\n" - "+\tdev->transceiver.default_a = 0;\n" - "+\tif (dev->transceiver.host) {\n" - "+\t\tdev->transceiver.host->is_b_host = 0;\n" - "+\t}\n" - "+#ifdef CONFIG_USB_OTG_HIGHSPEED\n" - "+\tif (dev->transceiver.companion) {\n" - "+\t\tdev->transceiver.companion->is_b_host = 0;\n" - "+\t}\n" - "+#endif\n" - "+\tif (dev->transceiver.gadget) {\n" - "+\t\tdev->transceiver.gadget->is_a_peripheral = 0;\n" - "+\t}\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * set A state information\n" - "+ *\n" - "+ * \\param dev OTG controller info\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+static inline void set_a_state_defaults (struct otg *dev)\n" - "+{\n" - "+\tdev->transceiver.default_a = 1;\n" - "+\tif (dev->transceiver.host) {\n" - "+\t\tdev->transceiver.host->is_b_host = 0;\n" - "+\t}\n" - "+#ifdef CONFIG_USB_OTG_HIGHSPEED\n" - "+\tif (dev->transceiver.companion) {\n" - "+\t\tdev->transceiver.companion->is_b_host = 0;\n" - "+\t}\n" - "+#endif\n" - "+\tif (dev->transceiver.gadget) {\n" - "+\t\tdev->transceiver.gadget->is_a_peripheral = 1;\n" - "+\t}\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * set B state information\n" - "+ *\n" - "+ * \\param dev OTG controller info\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+static inline void set_b_state_defaults (struct otg *dev)\n" - "+{\n" - "+\tdev->transceiver.default_a = 0;\n" - "+\tif (dev->transceiver.host) {\n" - "+\t\tdev->transceiver.host->is_b_host = 1;\n" - "+\t}\n" - "+#ifdef CONFIG_USB_OTG_HIGHSPEED\n" - "+\tif (dev->transceiver.companion) {\n" - "+\t\tdev->transceiver.companion->is_b_host = 1;\n" - "+\t}\n" - "+#endif\n" - "+\tif (dev->transceiver.gadget) {\n" - "+\t\tdev->transceiver.gadget->is_a_peripheral = 0;\n" - "+\t}\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * set B state information\n" - "+ *\n" - "+ * \\param dev OTG controller info\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+static inline void reset_b_hnp_enable (struct otg *dev)\n" - "+{\n" - "+\tif (dev->transceiver.host) {\n" - "+\t\tdev->transceiver.host->b_hnp_enable = 0;\n" - "+\t}\n" - "+#ifdef CONFIG_USB_OTG_HIGHSPEED\n" - "+\tif (dev->transceiver.companion) {\n" - "+\t\tdev->transceiver.companion->b_hnp_enable = 0;\n" - "+\t}\n" - "+#endif\n" - "+\tVDBG (\" OTG action: HNP disabled in B-device\\n\");\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * set B state information\n" - "+ *\n" - "+ * \\param dev OTG controller info\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+static inline int is_b_hnp_enabled (struct otg *dev)\n" - "+{\n" - "+\tint retVal = 0;\n" - "+\n" - "+\tif (dev->transceiver.host &&\n" - "+\t\tdev->transceiver.host->b_hnp_enable) {\n" - "+\t\tVDBG (\" OTG status: HNP is enabled in HS-B-device\\n\");\n" - "+\t\tretVal = 1;\n" - "+\t}\n" - "+#ifdef CONFIG_USB_OTG_HIGHSPEED\n" - "+\telse if (dev->transceiver.companion &&\n" - "+\t\tdev->transceiver.companion->b_hnp_enable) {\n" - "+\t\tVDBG (\" OTG status: HNP is enabled in FS-B-device\\n\");\n" - "+\t\tretVal = 1;\n" - "+\t}\n" - "+#endif\n" - "+#ifdef VERBOSE\n" - "+\telse {\n" - "+\t\tDBG (\" OTG status: HNP is disabled in B-device\\n\");\n" - "+\t}\n" - "+#endif\n" - "+\treturn retVal;\n" - "+}\n" - "+#endif\n" - "+\n" - "+#if defined(CONFIG_USB_OTG) || defined(CONFIG_USB_OTGMUX_GADGET)\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Read the status register\n" - "+ *\n" - "+ * \\param dev OTG controller info\n" - "+ *\n" - "+ * \\return status\n" - "+ */\n" - "+static inline u32 get_status (struct otg *dev)\n" - "+{\n" - "+\treturn (readl (&dev->regs->sts));\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Load and start the timer for an unconditional run\n" - "+ *\n" - "+ * \\param dev OTG controller info\n" - "+ * \\param val Value to load\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+static inline void set_timer (struct otg *dev, u32 val)\n" - "+{\n" - "+\totg_tmr_high_count = 0;\n" - "+\n" - "+\twritel ((val), &dev->regs->tmr);\n" - "+\tVDBG (\" OTG action: start timer: %d0 us\\n\", val);\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Load and start the timer for an unconditional run\n" - "+ *\n" - "+ * \\param dev OTG controller info\n" - "+ * \\param val Value to load\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+static inline void set_timer_long (struct otg *dev, u32 val)\n" - "+{\n" - "+\totg_tmr_high_count = val - 1;\n" - "+\n" - "+\twritel (TIMER_PERIOD, &dev->regs->tmr);\n" - "+\tVDBG (\" OTG action: start timer: %d0 ms\\n\", val);\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Re-start the timer (value already loaded)\n" - "+ *\n" - "+ * \\param dev OTG controller info\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+static inline void restart_timer (struct otg *dev)\n" - "+{\n" - "+\twritel ((readl (&dev->regs->ctl) | OTG_CTL_TMR_UNCOND),\n" - "+\t &dev->regs->ctl);\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Reset the timer while running (value already loaded)\n" - "+ *\n" - "+ * \\param dev OTG controller info\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+static inline void reset_timer (struct otg *dev)\n" - "+{\n" - "+\tu32 temp;\n" - "+\n" - "+\ttemp = readl (&dev->regs->ctl);\n" - "+\twritel ((temp & ~((u32) OTG_CTL_TMR_ALL)), &dev->regs->ctl);\n" - "+\twritel (temp, &dev->regs->ctl);\n" - "+\tVDBG (\" OTG action: re-start timer\\n\");\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Prepare the D-pulse\n" - "+ *\n" - "+ * \\param dev OTG controller info\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+static inline void set_srp_conditions (struct otg *dev)\n" - "+{\n" - "+#ifdef UDC_HSA0_WORKAROUNDS\n" - "+\tVDBG (\" OTG action: SRP init: no action needed due to A0 WAs\\n\");\n" - "+#else\n" - "+\twritel ((readl (&dev->regs->cap) & ~((u32) OTG_CAP_APU)),\n" - "+\t &dev->regs->cap);\n" - "+\tVDBG (\" OTG action: set SRP conditions: disable APU\\n\");\n" - "+#endif\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * Reset conditions after SRP\n" - "+ *\n" - "+ * activates the auto-pull-up feature so after SRP the host\n" - "+ * will detect a device connect after calling this function\n" - "+ *\n" - "+ * \\param dev OTG controller info\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+static inline void reset_srp_conditions (struct otg *dev)\n" - "+{\n" - "+#ifdef UDC_HSA0_WORKAROUNDS\n" - "+\tVDBG (\" OTG action: SRP done: no action needed due to A0 WAs\\n\");\n" - "+#else\n" - "+\twritel ((readl (&dev->regs->cap) | OTG_CAP_APU),\n" - "+\t &dev->regs->cap);\n" - "+\tVDBG (\" OTG action: reset SRP conditions: enable APU\\n\");\n" - "+#endif\n" - "+}\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * enable HNP for both devices\n" - "+ *\n" - "+ * \\param dev OTG controller info\n" - "+ *\n" - "+ * \\return success\n" - "+ */\n" - "+static inline int otg_enable_hnp (struct otg *dev)\n" - "+{\n" - "+\tint retVal = 0;\n" - "+\n" - "+/*\tif (!dev->device) {\n" - "+\t\tERR (\"Tried to send OTG request, device pointer not valid\\n\");\n" - "+\t\tretVal = -ENODEV;\n" - "+\t}\n" - "+\telse {\n" - "+\t\tretVal = usb_otg_enable_b_hnp (dev->device);\n" - "+\t\tDBG (\" OTG action: enabled HNP in B-device\\n\");\n" - "+\t}\n" - "+\tif (retVal < 0) {\n" - "+\t\tRES_FLAG (OTG_A_bHNP_EN);\n" - "+\t}\n" - "+\telse {\n" - "+\t\tSET_FLAG (OTG_A_bHNP_EN);\n" - "+\t}*/\n" - "+\treturn retVal;\n" - "+}\n" - "+\n" - "+#endif /* CONFIG_USB_OTG || CONFIG_USB_OTGMUX_GADGET */\n" - "+#ifdef DEBUG\n" - "+/**\n" - "+ * \\brief\n" - "+ * Print OTG controller registers (debug mode only)\n" - "+ *\n" - "+ * \\param dev OTG controller info\n" - "+ *\n" - "+ * \\return void\n" - "+ */\n" - "+static inline void print_regs (struct otg *dev)\n" - "+{\n" - "+\tDBG( \"-- UOC registers ---\\n\");\n" - "+\tDBG( \"otg cap = %08x\\n\", readl (&dev->regs->cap));\n" - "+\tDBG( \"otg mux = %08x\\n\", readl (&dev->regs->mux));\n" - "+\tDBG( \"otg sts = %08x\\n\", readl (&dev->regs->sts));\n" - "+\tDBG( \"otg ctl = %08x\\n\", readl (&dev->regs->ctl));\n" - "+\tDBG( \"otg tmr = %08x\\n\", readl (&dev->regs->tmr));\n" - "+\tDBG( \"otg intr = %08x\\n\", readl (&dev->regs->intr));\n" - "+\tDBG( \"otg inten = %08x\\n\", readl (&dev->regs->inten));\n" - "+\tDBG( \"--------------------\\n\");\n" - "+}\n" - "+#endif /* DEBUG */\n" - "+\n" - "+#ifdef CONFIG_SOC_AU1200\n" - "+\n" - "+/**\n" - "+ * \\brief\n" - "+ * GPIO functions (Au1200 only)\n" - "+ *\n" - "+ * \\param data pin info\n" - "+ *\n" - "+ * \\return success\n" - "+ */\n" - "+static inline int au1000gpio_bit_get (u32 data)\n" - "+{\n" - "+\treturn (au_readl ((SYS_PINSTATERD & (1 << data)) ? 1 : 0));\n" - "+}\n" - "+\n" - "+#ifdef CONFIG_AU1X00_GPIO\n" - "+\n" - "+\t/* GPIO functions are defined in drivers/char/au1000_gpio.c */\n" - "+\n" - "+#else\n" - "+\n" - "+static inline int au1000gpio_bit_tristate (u32 data)\n" - "+{\n" - "+\tau_writel ((1 << data), SYS_TRIOUTCLR);\n" - "+\treturn 0;\n" - "+}\n" - "+\n" - "+static inline int au1000gpio_bit_set (u32 data)\n" - "+{\n" - "+\tau_writel ((1 << data), SYS_OUTPUTSET);\n" - "+\treturn 0;\n" - "+}\n" - "+\n" - "+static inline int au1000gpio_bit_clear (u32 data)\n" - "+{\n" - "+\tau_writel ((1 << data), SYS_OUTPUTCLR);\n" - "+\treturn 0;\n" - "+}\n" - "+\n" - "+static inline int au1000gpio_bit_init (u32 data)\n" - "+{\n" - "+\treturn au1000gpio_bit_set (data);\n" - "+}\n" - "+\n" - "+static inline int au1000gpio_bit_term (u32 data)\n" - "+{\n" - "+\treturn au1000gpio_bit_set (data);\n" - "+}\n" - "+\n" - "+static inline int au1000gpio2_bit_set (u32 data)\n" - "+{\n" - "+\tau_writel (((1 << (data - GPIO_2_BASE)) |\n" - "+\t (1 << (data - GPIO_2_BASE + 0x10))), GPIO2_OUTPUT);\n" - "+\tau_sync();\n" - "+\treturn 0;\n" - "+}\n" - "+\n" - "+static inline int au1000gpio2_bit_clear (u32 data)\n" - "+{\n" - "+\tau_writel ((1 << (data - GPIO_2_BASE + 0x10)), GPIO2_OUTPUT);\n" - "+\tau_sync();\n" - "+\treturn 0;\n" - "+}\n" - "+\n" - "+static inline int au1000gpio2_bit_init (u32 data)\n" - "+{\n" - "+\tu32 temp = au_readl (GPIO2_ENABLE);\n" - "+\n" - "+\tif (!(temp | 1)) {\n" - "+\t\tau_writel (temp | 1, GPIO2_ENABLE);\n" - "+\t\tau_readl (GPIO2_ENABLE);\n" - "+\t\tudelay (20);\n" - "+\t}\n" - "+\tif (temp | 2) {\n" - "+\t\tau_writel (((temp & 0xfffffffd) | 1), GPIO2_ENABLE);\n" - "+\t\tau_readl (GPIO2_ENABLE);\n" - "+\t}\n" - "+\n" - "+\t/* FIXME: check the system impact of the P0A setting */\n" - "+\t/* DbAu1200 pin (GPIO_215) pin is shared w/ PSC0 functions */\n" - "+\t/* setting this field to GPIO affects also GPIO_16, GPIO_31 */\n" - "+\n" - "+\tif (data == GPIO_215) {\n" - "+\t\tau_writel (((au_readl (SYS_PINFUNC) &\n" - "+\t\t ~((u32) SYS_PINFUNC_P0A)) | SYS_PINFUNC_P0A_GPIO),\n" - "+\t\t\t SYS_PINFUNC);\n" - "+\t}\n" - "+\tau_writel (au_readl (GPIO2_INTENABLE) & ~(1 << (data - GPIO_2_BASE)),\n" - "+\t GPIO2_INTENABLE);\n" - "+\tau_writel (au_readl (GPIO2_DIR) | (1 << (data - GPIO_2_BASE)),\n" - "+\t GPIO2_DIR);\n" - "+\tau_sync();\n" - "+\treturn 0;\n" - "+}\n" - "+\n" - "+static inline int au1000gpio2_bit_term (u32 data)\n" - "+{\n" - "+\treturn au1000gpio2_bit_set (data);\n" - "+}\n" - "+#endif\n" - "+#endif /* CONFIG_SOC_AU1200 */\n" - "+\n" - "+#endif /* AU1200UOC_H */\n" - "diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c\n" - "index 8f402f8..e147883 100644\n" - "--- a/drivers/usb/gadget/ether.c\n" - "+++ b/drivers/usb/gadget/ether.c\n" - "@@ -91,6 +91,13 @@ static const char driver_desc [] = DRIVE\n" - " \n" - " #define RX_EXTRA\t20\t\t/* guard against rx overflows */\n" - " \n" - "+#ifdef CONFIG_USB_GADGET_AU1200UDC\n" - "+/*\n" - "+ * AMD UDC supports dword aligned DMA buffers only, so skbuf buffers\n" - "+ * from network layer must be copied\n" - "+ */\n" - "+#define UDC_MAX_BUFLEN 2048 /* size of dword aligned buffer */\n" - "+#endif\n" - " #include \"rndis.h\"\n" - " \n" - " #ifndef\tCONFIG_USB_ETH_RNDIS\n" - "@@ -151,8 +158,13 @@ struct eth_dev {\n" - " /* Thanks to NetChip Technologies for donating this product ID.\n" - " * It's for devices with only CDC Ethernet configurations.\n" - " */\n" - "+#ifdef CONFIG_USB_GADGET_AU1200UDC\n" - "+#define CDC_VENDOR_NUM\t0x0438\t\t/* AMD */\n" - "+#define CDC_PRODUCT_NUM\t0xdc01\t\t/* AMD Linux-USB Ethernet Gadget (temporary) */\n" - "+#else\n" - " #define CDC_VENDOR_NUM\t0x0525\t\t/* NetChip */\n" - " #define CDC_PRODUCT_NUM\t0xa4a1\t\t/* Linux-USB Ethernet Gadget */\n" - "+#endif\n" - " \n" - " /* For hardware that can't talk CDC, we use the same vendor ID that\n" - " * ARM Linux has used for ethernet-over-usb, both with sa1100 and\n" - "@@ -253,6 +265,10 @@ MODULE_PARM_DESC(host_addr, \"Host Ethern\n" - " #define DEV_CONFIG_CDC\n" - " #endif\n" - " \n" - "+#ifdef CONFIG_USB_GADGET_AU1200UDC\n" - "+#define\tDEV_CONFIG_CDC\n" - "+#endif\n" - "+\n" - " \n" - " /* For CDC-incapable hardware, choose the simple cdc subset.\n" - " * Anything that talks bulk (without notable bugs) can do this.\n" - "@@ -1056,6 +1072,10 @@ static void eth_reset_config (struct eth\n" - " \t\t\treq = container_of (dev->tx_reqs.next,\n" - " \t\t\t\t\t\tstruct usb_request, list);\n" - " \t\t\tlist_del (&req->list);\n" - "+#ifdef CONFIG_USB_GADGET_AU1200UDC\n" - "+ if (req->buf)\n" - "+ usb_ep_free_buffer (dev->in_ep, req->buf, req->dma, UDC_MAX_BUFLEN);\n" - "+#endif\n" - " \t\t\tusb_ep_free_request (dev->in_ep, req);\n" - " \t\t}\n" - " \t}\n" - "@@ -1065,6 +1085,10 @@ static void eth_reset_config (struct eth\n" - " \t\t\treq = container_of (dev->rx_reqs.next,\n" - " \t\t\t\t\t\tstruct usb_request, list);\n" - " \t\t\tlist_del (&req->list);\n" - "+#ifdef CONFIG_USB_GADGET_AU1200UDC\n" - "+ if (req->buf)\n" - "+ usb_ep_free_buffer (dev->out_ep, req->buf, req->dma, UDC_MAX_BUFLEN);\n" - "+#endif\n" - " \t\t\tusb_ep_free_request (dev->out_ep, req);\n" - " \t\t}\n" - " \t}\n" - "@@ -1632,7 +1656,9 @@ rx_submit (struct eth_dev *dev, struct u\n" - " \t */\n" - " \tskb_reserve(skb, NET_IP_ALIGN);\n" - " \n" - "+#ifndef CONFIG_USB_GADGET_AU1200UDC\n" - " \treq->buf = skb->data;\n" - "+#endif\n" - " \treq->length = size;\n" - " \treq->complete = rx_complete;\n" - " \treq->context = skb;\n" - "@@ -1674,6 +1700,16 @@ static void rx_complete (struct usb_ep *\n" - " \t\t\tbreak;\n" - " \t\t}\n" - " \n" - "+#ifdef CONFIG_USB_GADGET_AU1200UDC\n" - "+ /* we need to copy here because AMD UDC needs dword aligned buffers */\n" - "+ VDEBUG(dev, \"memcpy( skb->data %lx,req->buf %lx,req->actual %d)\\n\", skb->data,req->buf,req->actual);\n" - "+ if (req->actual <= UDC_MAX_BUFLEN) {\n" - "+ memcpy(skb->data, req->buf, req->actual);\n" - "+ }\n" - "+ else {\n" - "+ ERROR(dev, \"memcpy of %d bytes bigger than max %d\\n\", req->actual, UDC_MAX_BUFLEN);\n" - "+ }\n" - "+#endif\n" - " \t\tskb->dev = dev->net;\n" - " \t\tskb->protocol = eth_type_trans (skb, dev->net);\n" - " \t\tdev->stats.rx_packets++;\n" - "@@ -1742,6 +1778,15 @@ static int prealloc (struct list_head *l\n" - " \t\treq = usb_ep_alloc_request (ep, gfp_flags);\n" - " \t\tif (!req)\n" - " \t\t\treturn list_empty (list) ? -ENOMEM : 0;\n" - "+\n" - "+\n" - "+#ifdef CONFIG_USB_GADGET_AU1200UDC\n" - "+ /* allocate buffer which must be dword aligned for AMD UDC */\n" - "+ req->buf = usb_ep_alloc_buffer (ep, UDC_MAX_BUFLEN, \n" - "+ &req->dma, GFP_ATOMIC);\n" - "+#endif\n" - "+\n" - "+\n" - " \t\tlist_add (&req->list, list);\n" - " \t}\n" - " \treturn 0;\n" - "@@ -1753,6 +1798,10 @@ extra:\n" - " \n" - " \t\tnext = req->list.next;\n" - " \t\tlist_del (&req->list);\n" - "+#ifdef CONFIG_USB_GADGET_AU1200UDC\n" - "+ if (req->buf)\n" - "+ usb_ep_free_buffer (ep, req->buf, req->dma, UDC_MAX_BUFLEN);\n" - "+#endif\n" - " \t\tusb_ep_free_request (ep, req);\n" - " \n" - " \t\tif (next == list)\n" - "@@ -1905,7 +1954,19 @@ static int eth_start_xmit (struct sk_buf\n" - " \t\trndis_add_hdr (skb);\n" - " \t\tlength = skb->len;\n" - " \t}\n" - "-\treq->buf = skb->data;\n" - "+#ifdef CONFIG_USB_GADGET_AU1200UDC\n" - "+ /* we need to copy here because AMD UDC needs dword aligned buffers */\n" - "+ VDEBUG(dev, \"memcpy(req->buf %lx, skb->data %lx, length %d)\", req->buf, skb->data, length);\n" - "+ if (length <= UDC_MAX_BUFLEN) {\n" - "+ memcpy(req->buf, skb->data, length);\n" - "+ }\n" - "+ else {\n" - "+ ERROR(dev, \"memcpy of %d bytes bigger than max %d\\n\", length, UDC_MAX_BUFLEN);\n" - "+ }\n" - "+ VDEBUG(dev, \"past memcpy(req->buf %lx, skb->data %lx, length %d)\", req->buf, skb->data, length);\n" - "+#else\n" - "+ req->buf = skb->data;\n" - "+#endif\n" - " \treq->context = skb;\n" - " \treq->complete = tx_complete;\n" - " \n" - "@@ -2202,6 +2263,8 @@ eth_bind (struct usb_gadget *gadget)\n" - " \t\t/* sh doesn't support multiple interfaces or configs */\n" - " \t\tcdc = 0;\n" - " \t\trndis = 0;\n" - "+\t} else if (gadget_is_au1200udc(gadget)) {\n" - "+\t\trndis = 0;\n" - " \t} else if (gadget_is_sa1100 (gadget)) {\n" - " \t\t/* hardware can't write zlps */\n" - " \t\tzlp = 0;\n" - "diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c\n" - "index ea09aaa..ae800e6 100644\n" - "--- a/drivers/usb/gadget/file_storage.c\n" - "+++ b/drivers/usb/gadget/file_storage.c\n" - "@@ -263,8 +263,14 @@ MODULE_LICENSE(\"Dual BSD/GPL\");\n" - " *\n" - " * DO NOT REUSE THESE IDs with any other driver!! Ever!!\n" - " * Instead: allocate your own, using normal USB-IF procedures. */\n" - "+\n" - "+#ifdef CONFIG_USB_GADGET_AU1200UDC\n" - "+#define DRIVER_VENDOR_ID\t0x0438 // AMD\n" - "+#define DRIVER_PRODUCT_ID\t0xdc02\t// AMD Linux-USB File-backed Storage Gadget (temporary)\n" - "+#else\n" - " #define DRIVER_VENDOR_ID\t0x0525\t// NetChip\n" - " #define DRIVER_PRODUCT_ID\t0xa4a5\t// Linux-USB File-backed Storage Gadget\n" - "+#endif\n" - " \n" - " \n" - " /*\n" - "@@ -3717,6 +3723,8 @@ static int __init check_parameters(struc\n" - " \t\tmod_data.can_stall = 0;\n" - " \n" - " \tif (mod_data.release == 0xffff) {\t// Parameter wasn't set\n" - "+\t\tif (gadget_is_au1200udc(fsg->gadget))\n" - "+\t\t\tmod_data.can_stall = 0;\n" - " \t\t/* The sa1100 controller is not supported */\n" - " \t\tif (gadget_is_sa1100(fsg->gadget))\n" - " \t\t\tgcnum = -1;\n" - "diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h\n" - "index 8cbae21..541fbd0 100644\n" - "--- a/drivers/usb/gadget/gadget_chips.h\n" - "+++ b/drivers/usb/gadget/gadget_chips.h\n" - "@@ -15,6 +15,12 @@\n" - " #define\tgadget_is_net2280(g)\t0\n" - " #endif\n" - " \n" - "+#ifdef CONFIG_USB_GADGET_AU1200UDC\n" - "+#define\tgadget_is_au1200udc(g)\t!strcmp(\"au1200udc\", (g)->name)\n" - "+#else\n" - "+#define\tgadget_is_au1200udc(g)\t0\n" - "+#endif\n" - "+\n" - " #ifdef CONFIG_USB_GADGET_DUMMY_HCD\n" - " #define\tgadget_is_dummy(g)\t!strcmp(\"dummy_udc\", (g)->name)\n" - " #else\n" - "@@ -143,5 +149,7 @@ static inline int usb_gadget_controller_\n" - " \t\treturn 0x13;\n" - " \telse if (gadget_is_imx(gadget))\n" - " \t\treturn 0x14;\n" - "+\telse if (gadget_is_au1200udc(gadget))\n" - "+\t\treturn 0x15;\n" - " \treturn -ENOENT;\n" - " }\n" - "diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c\n" - "index 6c58636..4ec28bb 100644\n" - "--- a/drivers/usb/gadget/zero.c\n" - "+++ b/drivers/usb/gadget/zero.c\n" - "@@ -193,6 +193,10 @@ module_param (loopdefault, bool, S_IRUGO\n" - " * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!!\n" - " * Instead: allocate your own, using normal USB-IF procedures.\n" - " */\n" - "+#ifdef CONFIG_USB_GADGET_AU1200UDC\n" - "+#define DRIVER_VENDOR_NUM\t0x0438\t\t/* AMD */\n" - "+#define DRIVER_PRODUCT_NUM\t0xdc00\t\t/* AMD Linux-USB \"Gadget Zero\" (temporary) */\n" - "+#else\n" - " #ifndef\tCONFIG_USB_ZERO_HNPTEST\n" - " #define DRIVER_VENDOR_NUM\t0x0525\t\t/* NetChip */\n" - " #define DRIVER_PRODUCT_NUM\t0xa4a0\t\t/* Linux-USB \"Gadget Zero\" */\n" - "@@ -200,6 +204,7 @@ module_param (loopdefault, bool, S_IRUGO\n" - " #define DRIVER_VENDOR_NUM\t0x1a0a\t\t/* OTG test device IDs */\n" - " #define DRIVER_PRODUCT_NUM\t0xbadd\n" - " #endif\n" - "+#endif\n" - " \n" - " /*-------------------------------------------------------------------------*/\n" - " \n" - "@@ -1127,8 +1132,11 @@ zero_unbind (struct usb_gadget *gadget)\n" - " \tDBG (dev, \"unbind\\n\");\n" - " \n" - " \t/* we've already been disconnected ... no i/o is active */\n" - "-\tif (dev->req)\n" - "+\tif (dev->req) {\n" - "+ /* free with original length */\n" - "+ dev->req->length = USB_BUFSIZ;\n" - " \t\tfree_ep_req (gadget->ep0, dev->req);\n" - "+ }\n" - " \tdel_timer_sync (&dev->resume);\n" - " \tkfree (dev);\n" - " \tset_gadget_data (gadget, NULL);" -e9b900bee412370fc0b388fecc4d37240691f454a8116c0385935337275e772d +5b37078013cd2e0a0422e351bd111283486fd2fdbfd3a2be6fb264fd33535024
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox