]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'usb/usb-next'
authorStephen Rothwell <sfr@canb.auug.org.au>
Thu, 5 Nov 2015 03:48:53 +0000 (14:48 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Thu, 5 Nov 2015 03:48:53 +0000 (14:48 +1100)
144 files changed:
Documentation/ABI/testing/sysfs-bus-usb
Documentation/devicetree/bindings/phy/brcm,cygnus-pcie-phy.txt [new file with mode: 0644]
Documentation/devicetree/bindings/phy/phy-mt65xx-usb.txt [new file with mode: 0644]
Documentation/devicetree/bindings/phy/samsung-phy.txt
Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
Documentation/devicetree/bindings/usb/dwc3.txt
Documentation/usb/authorization.txt
MAINTAINERS
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mach-s3c64xx/mach-smartq.c
arch/arm/mach-s3c64xx/mach-smdk6410.c
arch/arm/plat-samsung/devs.c
drivers/phy/Kconfig
drivers/phy/Makefile
drivers/phy/phy-bcm-cygnus-pcie.c [new file with mode: 0644]
drivers/phy/phy-mt65xx-usb3.c [new file with mode: 0644]
drivers/phy/phy-samsung-usb2.c
drivers/phy/phy-samsung-usb2.h
drivers/phy/phy-sun4i-usb.c
drivers/usb/Makefile
drivers/usb/chipidea/Kconfig
drivers/usb/chipidea/ci_hdrc_imx.c
drivers/usb/chipidea/ci_hdrc_pci.c
drivers/usb/chipidea/core.c
drivers/usb/chipidea/otg.c
drivers/usb/chipidea/usbmisc_imx.c
drivers/usb/common/common.c
drivers/usb/core/config.c
drivers/usb/core/driver.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/core/message.c
drivers/usb/core/sysfs.c
drivers/usb/core/urb.c
drivers/usb/core/usb.c
drivers/usb/core/usb.h
drivers/usb/dwc2/core.c
drivers/usb/dwc2/core.h
drivers/usb/dwc2/core_intr.c
drivers/usb/dwc2/debugfs.c
drivers/usb/dwc2/gadget.c
drivers/usb/dwc2/hcd.c
drivers/usb/dwc2/hcd.h
drivers/usb/dwc2/hcd_ddma.c
drivers/usb/dwc2/hcd_intr.c
drivers/usb/dwc2/hcd_queue.c
drivers/usb/dwc2/hw.h
drivers/usb/dwc2/platform.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/dwc3-st.c
drivers/usb/dwc3/gadget.c
drivers/usb/dwc3/platform_data.h
drivers/usb/gadget/Kconfig
drivers/usb/gadget/composite.c
drivers/usb/gadget/epautoconf.c
drivers/usb/gadget/function/f_acm.c
drivers/usb/gadget/function/f_ecm.c
drivers/usb/gadget/function/f_eem.c
drivers/usb/gadget/function/f_hid.c
drivers/usb/gadget/function/f_loopback.c
drivers/usb/gadget/function/f_mass_storage.c
drivers/usb/gadget/function/f_midi.c
drivers/usb/gadget/function/f_ncm.c
drivers/usb/gadget/function/f_obex.c
drivers/usb/gadget/function/f_phonet.c
drivers/usb/gadget/function/f_printer.c
drivers/usb/gadget/function/f_rndis.c
drivers/usb/gadget/function/f_serial.c
drivers/usb/gadget/function/f_sourcesink.c
drivers/usb/gadget/function/f_subset.c
drivers/usb/gadget/function/f_uac1.c
drivers/usb/gadget/function/f_uac2.c
drivers/usb/gadget/function/f_uvc.c
drivers/usb/gadget/function/u_ether.c
drivers/usb/gadget/function/u_serial.c
drivers/usb/gadget/legacy/dbgp.c
drivers/usb/gadget/legacy/tcm_usb_gadget.c
drivers/usb/gadget/udc/Kconfig
drivers/usb/gadget/udc/amd5536udc.c
drivers/usb/gadget/udc/amd5536udc.h
drivers/usb/gadget/udc/at91_udc.h
drivers/usb/gadget/udc/dummy_hcd.c
drivers/usb/gadget/udc/net2280.c
drivers/usb/gadget/udc/pch_udc.c
drivers/usb/host/Kconfig
drivers/usb/host/Makefile
drivers/usb/host/ehci-msm.c
drivers/usb/host/ehci-orion.c
drivers/usb/host/ehci-platform.c
drivers/usb/host/ehci-spear.c
drivers/usb/host/fotg210-hcd.c
drivers/usb/host/fotg210.h
drivers/usb/host/fsl-mph-dr-of.c
drivers/usb/host/fusbh200-hcd.c [deleted file]
drivers/usb/host/fusbh200.h [deleted file]
drivers/usb/host/ohci-nxp.c
drivers/usb/host/ohci-spear.c
drivers/usb/host/u132-hcd.c
drivers/usb/host/uhci-platform.c
drivers/usb/host/whci/init.c
drivers/usb/host/xhci-dbg.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/usb3503.c
drivers/usb/misc/usbtest.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musb_dsps.c
drivers/usb/musb/sunxi.c
drivers/usb/phy/phy-msm-usb.c
drivers/usb/phy/phy-qcom-8x16-usb.c
drivers/usb/phy/phy-tegra-usb.c
drivers/usb/serial/io_ti.c
drivers/usb/serial/option.c
drivers/usb/serial/qcserial.c
drivers/usb/serial/usb-wwan.h
drivers/usb/serial/usb_wwan.c
drivers/usb/storage/isd200.c
drivers/usb/storage/uas.c
drivers/usb/usbip/vhci_hcd.c
drivers/uwb/drp.c
drivers/uwb/neh.c
drivers/uwb/rsv.c
include/linux/platform_data/atmel.h
include/linux/platform_data/s3c-hsotg.h
include/linux/usb.h
include/linux/usb/ch9.h
include/linux/usb/chipidea.h
include/linux/usb/gadget.h
include/linux/usb/hcd.h
include/linux/usb/musb.h
include/linux/usb/of.h
include/linux/usb/otg.h
include/linux/usb/phy.h
include/uapi/linux/usb/ch9.h
tools/usb/testusb.c
tools/usb/usbip/src/usbip_detach.c

index 864637f25bee49a616865901ed6b0d4daa1791c8..3a4abfc44f5e0d8a9e358626c1ca8251d756003d 100644 (file)
@@ -1,3 +1,23 @@
+What:          /sys/bus/usb/devices/INTERFACE/authorized
+Date:          August 2015
+Description:
+               This allows to authorize (1) or deauthorize (0)
+               individual interfaces instead a whole device
+               in contrast to the device authorization.
+               If a deauthorized interface will be authorized
+               so the driver probing must be triggered manually
+               by writing INTERFACE to /sys/bus/usb/drivers_probe
+               This allows to avoid side-effects with drivers
+               that need multiple interfaces.
+               A deauthorized interface cannot be probed or claimed.
+
+What:          /sys/bus/usb/devices/usbX/interface_authorized_default
+Date:          August 2015
+Description:
+               This is used as value that determines if interfaces
+               would be authorized by default.
+               The value can be 1 or 0. It's by default 1.
+
 What:          /sys/bus/usb/device/.../authorized
 Date:          July 2008
 KernelVersion: 2.6.26
diff --git a/Documentation/devicetree/bindings/phy/brcm,cygnus-pcie-phy.txt b/Documentation/devicetree/bindings/phy/brcm,cygnus-pcie-phy.txt
new file mode 100644 (file)
index 0000000..761c4bc
--- /dev/null
@@ -0,0 +1,47 @@
+Broadcom Cygnus PCIe PHY
+
+Required properties:
+- compatible: must be "brcm,cygnus-pcie-phy"
+- reg: base address and length of the PCIe PHY block
+- #address-cells: must be 1
+- #size-cells: must be 0
+
+Each PCIe PHY should be represented by a child node
+
+Required properties For the child node:
+- reg: the PHY ID
+0 - PCIe RC 0
+1 - PCIe RC 1
+- #phy-cells: must be 0
+
+Example:
+       pcie_phy: phy@0301d0a0 {
+               compatible = "brcm,cygnus-pcie-phy";
+               reg = <0x0301d0a0 0x14>;
+
+               pcie0_phy: phy@0 {
+                       reg = <0>;
+                       #phy-cells = <0>;
+               };
+
+               pcie1_phy: phy@1 {
+                       reg = <1>;
+                       #phy-cells = <0>;
+               };
+       };
+
+       /* users of the PCIe phy */
+
+       pcie0: pcie@18012000 {
+               ...
+               ...
+               phys = <&pcie0_phy>;
+               phy-names = "pcie-phy";
+       };
+
+       pcie1: pcie@18013000 {
+               ...
+               ...
+               phys = <pcie1_phy>;
+               phy-names = "pcie-phy";
+       };
diff --git a/Documentation/devicetree/bindings/phy/phy-mt65xx-usb.txt b/Documentation/devicetree/bindings/phy/phy-mt65xx-usb.txt
new file mode 100644 (file)
index 0000000..00100cf
--- /dev/null
@@ -0,0 +1,68 @@
+mt65xx USB3.0 PHY binding
+--------------------------
+
+This binding describes a usb3.0 phy for mt65xx platforms of Medaitek SoC.
+
+Required properties (controller (parent) node):
+ - compatible  : should be "mediatek,mt8173-u3phy"
+ - reg         : offset and length of register for phy, exclude port's
+                 register.
+ - clocks      : a list of phandle + clock-specifier pairs, one for each
+                 entry in clock-names
+ - clock-names : must contain
+                 "u3phya_ref": for reference clock of usb3.0 analog phy.
+
+Required nodes : a sub-node is required for each port the controller
+                 provides. Address range information including the usual
+                 'reg' property is used inside these nodes to describe
+                 the controller's topology.
+
+Required properties (port (child) node):
+- reg          : address and length of the register set for the port.
+- #phy-cells   : should be 1 (See second example)
+                 cell after port phandle is phy type from:
+                       - PHY_TYPE_USB2
+                       - PHY_TYPE_USB3
+
+Example:
+
+u3phy: usb-phy@11290000 {
+       compatible = "mediatek,mt8173-u3phy";
+       reg = <0 0x11290000 0 0x800>;
+       clocks = <&apmixedsys CLK_APMIXED_REF2USB_TX>;
+       clock-names = "u3phya_ref";
+       #address-cells = <2>;
+       #size-cells = <2>;
+       ranges;
+       status = "okay";
+
+       phy_port0: port@11290800 {
+               reg = <0 0x11290800 0 0x800>;
+               #phy-cells = <1>;
+               status = "okay";
+       };
+
+       phy_port1: port@11291000 {
+               reg = <0 0x11291000 0 0x800>;
+               #phy-cells = <1>;
+               status = "okay";
+       };
+};
+
+Specifying phy control of devices
+---------------------------------
+
+Device nodes should specify the configuration required in their "phys"
+property, containing a phandle to the phy port node and a device type;
+phy-names for each port are optional.
+
+Example:
+
+#include <dt-bindings/phy/phy.h>
+
+usb30: usb@11270000 {
+       ...
+       phys = <&phy_port0 PHY_TYPE_USB3>;
+       phy-names = "usb3-0";
+       ...
+};
index 60c6f2a633e02d7b7179ec45c7b31bcda378f802..0289d3b07853e73f494106aca13780899a508abc 100644 (file)
@@ -44,6 +44,9 @@ Required properties:
        - the "ref" clock is used to get the rate of the clock provided to the
          PHY module
 
+Optional properties:
+- vbus-supply: power-supply phandle for vbus power source
+
 The first phandle argument in the PHY specifier identifies the PHY, its
 meaning is compatible dependent. For the currently supported SoCs (Exynos 4210
 and Exynos 4212) it is as follows:
index a057b75ba4b5f2d39b51f55c85b814b95f165820..781296bfbe4faacc951feb2756fb4232a0f8027c 100644 (file)
@@ -27,10 +27,6 @@ Optional properties:
 - vbus-supply: reference to the VBUS regulator
 - maximum-speed: limit the maximum connection speed to "full-speed".
 - tpl-support: TPL (Targeted Peripheral List) feature for targeted hosts
-- fsl,usbmisc: (FSL only) phandler of non-core register device, with one
-  argument that indicate usb controller index
-- disable-over-current: (FSL only) disable over current detect
-- external-vbus-divider: (FSL only) enables off-chip resistor divider for Vbus
 - itc-setting: interrupt threshold control register control, the setting
   should be aligned with ITC bits at register USBCMD.
 - ahb-burst-config: it is vendor dependent, the required value should be
@@ -41,11 +37,28 @@ Optional properties:
 - tx-burst-size-dword: it is vendor dependent, the tx burst size in dword
   (4 bytes), This register represents the maximum length of a the burst
   in 32-bit words while moving data from system memory to the USB
-  bus, changing this value takes effect only the SBUSCFG.AHBBRST is 0.
+  bus, the value of this property will only take effect if property
+  "ahb-burst-config" is set to 0, if this property is missing the reset
+  default of the hardware implementation will be used.
 - rx-burst-size-dword: it is vendor dependent, the rx burst size in dword
   (4 bytes), This register represents the maximum length of a the burst
   in 32-bit words while moving data from the USB bus to system memory,
-  changing this value takes effect only the SBUSCFG.AHBBRST is 0.
+  the value of this property will only take effect if property
+  "ahb-burst-config" is set to 0, if this property is missing the reset
+  default of the hardware implementation will be used.
+- extcon: phandles to external connector devices. First phandle should point to
+  external connector, which provide "USB" cable events, the second should point
+  to external connector device, which provide "USB-HOST" cable events. If one
+  of the external connector devices is not required, empty <0> phandle should
+  be specified.
+- phy-clkgate-delay-us: the delay time (us) between putting the PHY into
+  low power mode and gating the PHY clock.
+
+i.mx specific properties
+- fsl,usbmisc: phandler of non-core register device, with one
+  argument that indicate usb controller index
+- disable-over-current: disable over current detect
+- external-vbus-divider: enables off-chip resistor divider for Vbus
 
 Example:
 
@@ -62,4 +75,6 @@ Example:
                ahb-burst-config = <0x0>;
                tx-burst-size-dword = <0x10>; /* 64 bytes */
                rx-burst-size-dword = <0x10>;
+               extcon = <0>, <&usb_id>;
+               phy-clkgate-delay-us = <400>;
        };
index 9f64f69d153aeecc4573e6d3fe7c988a51401b24..fb2ad0acedbdbe0db4253b0fe4c2818f13f8ef71 100644 (file)
@@ -36,11 +36,16 @@ Optional properties:
                        LTSSM during USB3 Compliance mode.
  - snps,dis_u3_susphy_quirk: when set core will disable USB3 suspend phy.
  - snps,dis_u2_susphy_quirk: when set core will disable USB2 suspend phy.
+ - snps,dis_enblslpm_quirk: when set clears the enblslpm in GUSB2PHYCFG,
+                       disabling the suspend signal to the PHY.
  - snps,is-utmi-l1-suspend: true when DWC3 asserts output signal
                        utmi_l1_suspend_n, false when asserts utmi_sleep_n
  - snps,hird-threshold: HIRD threshold
  - snps,hsphy_interface: High-Speed PHY interface selection between "utmi" for
    UTMI+ and "ulpi" for ULPI when the DWC_USB3_HSPHY_INTERFACE has value 3.
+ - snps,quirk-frame-length-adjustment: Value for GFLADJ_30MHZ field of GFLADJ
+       register for post-silicon frame length adjustment when the
+       fladj_30mhz_sdbnd signal is invalid or incorrect.
 
 This is usually a subnode to DWC3 glue to which it is connected.
 
index c069b6884c779ffc855133f634cf6b640a81da00..c7e985f05d8f9f1ecd433ffe41fec1e199e8b898 100644 (file)
@@ -90,3 +90,34 @@ etc, but you get the idea. Anybody with access to a device gadget kit
 can fake descriptors and device info. Don't trust that. You are
 welcome.
 
+
+Interface authorization
+-----------------------
+There is a similar approach to allow or deny specific USB interfaces.
+That allows to block only a subset of an USB device.
+
+Authorize an interface:
+$ echo 1 > /sys/bus/usb/devices/INTERFACE/authorized
+
+Deauthorize an interface:
+$ echo 0 > /sys/bus/usb/devices/INTERFACE/authorized
+
+The default value for new interfaces
+on a particular USB bus can be changed, too.
+
+Allow interfaces per default:
+$ echo 1 > /sys/bus/usb/devices/usbX/interface_authorized_default
+
+Deny interfaces per default:
+$ echo 0 > /sys/bus/usb/devices/usbX/interface_authorized_default
+
+Per default the interface_authorized_default bit is 1.
+So all interfaces would authorized per default.
+
+Note:
+If a deauthorized interface will be authorized so the driver probing must
+be triggered manually by writing INTERFACE to /sys/bus/usb/drivers_probe
+
+For drivers that need multiple interfaces all needed interfaces should be
+authroized first. After that the drivers should be probed.
+This avoids side effects.
index d99d47c8c2f8695ce31161bcc5b1939ee27867f5..e059bae82c07da28d15023dcdcb1922e655edfb8 100644 (file)
@@ -1312,6 +1312,13 @@ F:       arch/arm/mach-mediatek/
 N:     mtk
 K:     mediatek
 
+ARM/Mediatek USB3 PHY DRIVER
+M:     Chunfeng Yun <chunfeng.yun@mediatek.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L:     linux-mediatek@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     drivers/phy/phy-mt65xx-usb3.c
+
 ARM/MICREL KS8695 ARCHITECTURE
 M:     Greg Ungerer <gerg@uclinux.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
index d13aa3f9bac48b70c81e20fca87741a40ca61b9c..f776adcdaee8c3e354d73eb65c1ced6c9a752f30 100644 (file)
@@ -813,7 +813,7 @@ static const struct gpio_led_platform_data gpio_leds_pdata = {
        .num_leds = ARRAY_SIZE(gpio_leds),
 };
 
-static struct s3c_hsotg_plat crag6410_hsotg_pdata;
+static struct dwc2_hsotg_plat crag6410_hsotg_pdata;
 
 static void __init crag6410_machine_init(void)
 {
@@ -839,7 +839,7 @@ static void __init crag6410_machine_init(void)
        s3c_i2c0_set_platdata(&i2c0_pdata);
        s3c_i2c1_set_platdata(&i2c1_pdata);
        s3c_fb_set_platdata(&crag6410_lcd_pdata);
-       s3c_hsotg_set_platdata(&crag6410_hsotg_pdata);
+       dwc2_hsotg_set_platdata(&crag6410_hsotg_pdata);
 
        i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
        i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
index 7b8a3699795c0e636210455535b36c7e57566606..acdfb5fac40f6f8124dd57b71a3b173ac2296c08 100644 (file)
@@ -193,7 +193,7 @@ static struct s3c_hwmon_pdata smartq_hwmon_pdata __initdata = {
        },
 };
 
-static struct s3c_hsotg_plat smartq_hsotg_pdata;
+static struct dwc2_hsotg_plat smartq_hsotg_pdata;
 
 static int __init smartq_lcd_setup_gpio(void)
 {
@@ -386,7 +386,7 @@ void __init smartq_map_io(void)
 void __init smartq_machine_init(void)
 {
        s3c_i2c0_set_platdata(NULL);
-       s3c_hsotg_set_platdata(&smartq_hsotg_pdata);
+       dwc2_hsotg_set_platdata(&smartq_hsotg_pdata);
        s3c_hwmon_set_platdata(&smartq_hwmon_pdata);
        s3c_sdhci1_set_platdata(&smartq_internal_hsmmc_pdata);
        s3c_sdhci2_set_platdata(&smartq_internal_hsmmc_pdata);
index 2722800d5c11ae6c760dbf436049c3c0029856f0..30fd27853072440a5a642d2cae86bcc2357d0247 100644 (file)
@@ -633,7 +633,7 @@ static struct platform_pwm_backlight_data smdk6410_bl_data = {
        .enable_gpio = -1,
 };
 
-static struct s3c_hsotg_plat smdk6410_hsotg_pdata;
+static struct dwc2_hsotg_plat smdk6410_hsotg_pdata;
 
 static void __init smdk6410_map_io(void)
 {
@@ -664,7 +664,7 @@ static void __init smdk6410_machine_init(void)
        s3c_i2c0_set_platdata(NULL);
        s3c_i2c1_set_platdata(NULL);
        s3c_fb_set_platdata(&smdk6410_lcd_pdata);
-       s3c_hsotg_set_platdata(&smdk6410_hsotg_pdata);
+       dwc2_hsotg_set_platdata(&smdk6410_hsotg_pdata);
 
        samsung_keypad_set_platdata(&smdk6410_keypad_data);
 
index 83c7d154bde0971a3b9abeadeb6fb8bfaa93143a..82074625de5cebfc7681f72c931c90d1b7e951ac 100644 (file)
@@ -1042,11 +1042,11 @@ struct platform_device s3c_device_usb_hsotg = {
        },
 };
 
-void __init s3c_hsotg_set_platdata(struct s3c_hsotg_plat *pd)
+void __init dwc2_hsotg_set_platdata(struct dwc2_hsotg_plat *pd)
 {
-       struct s3c_hsotg_plat *npd;
+       struct dwc2_hsotg_plat *npd;
 
-       npd = s3c_set_platdata(pd, sizeof(struct s3c_hsotg_plat),
+       npd = s3c_set_platdata(pd, sizeof(struct dwc2_hsotg_plat),
                        &s3c_device_usb_hsotg);
 
        if (!npd->phy_init)
index 47da573d0babd8bb9805c8cdb9a9d40323567bf8..7eb5859dd035fefabea842f40722580cfcdfe64a 100644 (file)
@@ -206,6 +206,15 @@ config PHY_HIX5HD2_SATA
        help
          Support for SATA PHY on Hisilicon hix5hd2 Soc.
 
+config PHY_MT65XX_USB3
+       tristate "Mediatek USB3.0 PHY Driver"
+       depends on ARCH_MEDIATEK && OF
+       select GENERIC_PHY
+       help
+         Say 'Y' here to add support for Mediatek USB3.0 PHY driver
+         for mt65xx SoCs. it supports two usb2.0 ports and
+         one usb3.0 port.
+
 config PHY_SUN4I_USB
        tristate "Allwinner sunxi SoC USB PHY driver"
        depends on ARCH_SUNXI && HAS_IOMEM && OF
@@ -371,4 +380,13 @@ config PHY_BRCMSTB_SATA
          Enable this to support the SATA3 PHY on 28nm Broadcom STB SoCs.
          Likely useful only with CONFIG_SATA_BRCMSTB enabled.
 
+config PHY_CYGNUS_PCIE
+       tristate "Broadcom Cygnus PCIe PHY driver"
+       depends on OF && (ARCH_BCM_CYGNUS || COMPILE_TEST)
+       select GENERIC_PHY
+       default ARCH_BCM_CYGNUS
+       help
+         Enable this to support the Broadcom Cygnus PCIe PHY.
+         If unsure, say N.
+
 endmenu
index a5b18c18fc12d78fce9c19021a0847f49ece504b..075db1a81aa5c30b5c786b3dd3ae4d63f4cd69ab 100644 (file)
@@ -23,6 +23,7 @@ obj-$(CONFIG_TI_PIPE3)                        += phy-ti-pipe3.o
 obj-$(CONFIG_TWL4030_USB)              += phy-twl4030-usb.o
 obj-$(CONFIG_PHY_EXYNOS5250_SATA)      += phy-exynos5250-sata.o
 obj-$(CONFIG_PHY_HIX5HD2_SATA)         += phy-hix5hd2-sata.o
+obj-$(CONFIG_PHY_MT65XX_USB3)          += phy-mt65xx-usb3.o
 obj-$(CONFIG_PHY_SUN4I_USB)            += phy-sun4i-usb.o
 obj-$(CONFIG_PHY_SUN9I_USB)            += phy-sun9i-usb.o
 obj-$(CONFIG_PHY_SAMSUNG_USB2)         += phy-exynos-usb2.o
@@ -46,3 +47,4 @@ obj-$(CONFIG_PHY_QCOM_UFS)    += phy-qcom-ufs-qmp-14nm.o
 obj-$(CONFIG_PHY_TUSB1210)             += phy-tusb1210.o
 obj-$(CONFIG_PHY_BRCMSTB_SATA)         += phy-brcmstb-sata.o
 obj-$(CONFIG_PHY_PISTACHIO_USB)                += phy-pistachio-usb.o
+obj-$(CONFIG_PHY_CYGNUS_PCIE)          += phy-bcm-cygnus-pcie.o
diff --git a/drivers/phy/phy-bcm-cygnus-pcie.c b/drivers/phy/phy-bcm-cygnus-pcie.c
new file mode 100644 (file)
index 0000000..7ad72b7
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2015 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+#define PCIE_CFG_OFFSET         0x00
+#define PCIE1_PHY_IDDQ_SHIFT    10
+#define PCIE0_PHY_IDDQ_SHIFT    2
+
+enum cygnus_pcie_phy_id {
+       CYGNUS_PHY_PCIE0 = 0,
+       CYGNUS_PHY_PCIE1,
+       MAX_NUM_PHYS,
+};
+
+struct cygnus_pcie_phy_core;
+
+/**
+ * struct cygnus_pcie_phy - Cygnus PCIe PHY device
+ * @core: pointer to the Cygnus PCIe PHY core control
+ * @id: internal ID to identify the Cygnus PCIe PHY
+ * @phy: pointer to the kernel PHY device
+ */
+struct cygnus_pcie_phy {
+       struct cygnus_pcie_phy_core *core;
+       enum cygnus_pcie_phy_id id;
+       struct phy *phy;
+};
+
+/**
+ * struct cygnus_pcie_phy_core - Cygnus PCIe PHY core control
+ * @dev: pointer to device
+ * @base: base register
+ * @lock: mutex to protect access to individual PHYs
+ * @phys: pointer to Cygnus PHY device
+ */
+struct cygnus_pcie_phy_core {
+       struct device *dev;
+       void __iomem *base;
+       struct mutex lock;
+       struct cygnus_pcie_phy phys[MAX_NUM_PHYS];
+};
+
+static int cygnus_pcie_power_config(struct cygnus_pcie_phy *phy, bool enable)
+{
+       struct cygnus_pcie_phy_core *core = phy->core;
+       unsigned shift;
+       u32 val;
+
+       mutex_lock(&core->lock);
+
+       switch (phy->id) {
+       case CYGNUS_PHY_PCIE0:
+               shift = PCIE0_PHY_IDDQ_SHIFT;
+               break;
+
+       case CYGNUS_PHY_PCIE1:
+               shift = PCIE1_PHY_IDDQ_SHIFT;
+               break;
+
+       default:
+               mutex_unlock(&core->lock);
+               dev_err(core->dev, "PCIe PHY %d invalid\n", phy->id);
+               return -EINVAL;
+       }
+
+       if (enable) {
+               val = readl(core->base + PCIE_CFG_OFFSET);
+               val &= ~BIT(shift);
+               writel(val, core->base + PCIE_CFG_OFFSET);
+               /*
+                * Wait 50 ms for the PCIe Serdes to stabilize after the analog
+                * front end is brought up
+                */
+               msleep(50);
+       } else {
+               val = readl(core->base + PCIE_CFG_OFFSET);
+               val |= BIT(shift);
+               writel(val, core->base + PCIE_CFG_OFFSET);
+       }
+
+       mutex_unlock(&core->lock);
+       dev_dbg(core->dev, "PCIe PHY %d %s\n", phy->id,
+               enable ? "enabled" : "disabled");
+       return 0;
+}
+
+static int cygnus_pcie_phy_power_on(struct phy *p)
+{
+       struct cygnus_pcie_phy *phy = phy_get_drvdata(p);
+
+       return cygnus_pcie_power_config(phy, true);
+}
+
+static int cygnus_pcie_phy_power_off(struct phy *p)
+{
+       struct cygnus_pcie_phy *phy = phy_get_drvdata(p);
+
+       return cygnus_pcie_power_config(phy, false);
+}
+
+static struct phy_ops cygnus_pcie_phy_ops = {
+       .power_on = cygnus_pcie_phy_power_on,
+       .power_off = cygnus_pcie_phy_power_off,
+       .owner = THIS_MODULE,
+};
+
+static int cygnus_pcie_phy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *node = dev->of_node, *child;
+       struct cygnus_pcie_phy_core *core;
+       struct phy_provider *provider;
+       struct resource *res;
+       unsigned cnt = 0;
+
+       if (of_get_child_count(node) == 0) {
+               dev_err(dev, "PHY no child node\n");
+               return -ENODEV;
+       }
+
+       core = devm_kzalloc(dev, sizeof(*core), GFP_KERNEL);
+       if (!core)
+               return -ENOMEM;
+
+       core->dev = dev;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       core->base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(core->base))
+               return PTR_ERR(core->base);
+
+       mutex_init(&core->lock);
+
+       for_each_available_child_of_node(node, child) {
+               unsigned int id;
+               struct cygnus_pcie_phy *p;
+
+               if (of_property_read_u32(child, "reg", &id)) {
+                       dev_err(dev, "missing reg property for %s\n",
+                               child->name);
+                       return -EINVAL;
+               }
+
+               if (id >= MAX_NUM_PHYS) {
+                       dev_err(dev, "invalid PHY id: %u\n", id);
+                       return -EINVAL;
+               }
+
+               if (core->phys[id].phy) {
+                       dev_err(dev, "duplicated PHY id: %u\n", id);
+                       return -EINVAL;
+               }
+
+               p = &core->phys[id];
+               p->phy = devm_phy_create(dev, child, &cygnus_pcie_phy_ops);
+               if (IS_ERR(p->phy)) {
+                       dev_err(dev, "failed to create PHY\n");
+                       return PTR_ERR(p->phy);
+               }
+
+               p->core = core;
+               p->id = id;
+               phy_set_drvdata(p->phy, p);
+               cnt++;
+       }
+
+       dev_set_drvdata(dev, core);
+
+       provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+       if (IS_ERR(provider)) {
+               dev_err(dev, "failed to register PHY provider\n");
+               return PTR_ERR(provider);
+       }
+
+       dev_dbg(dev, "registered %u PCIe PHY(s)\n", cnt);
+
+       return 0;
+}
+
+static const struct of_device_id cygnus_pcie_phy_match_table[] = {
+       { .compatible = "brcm,cygnus-pcie-phy" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, cygnus_pcie_phy_match_table);
+
+static struct platform_driver cygnus_pcie_phy_driver = {
+       .driver = {
+               .name = "cygnus-pcie-phy",
+               .of_match_table = cygnus_pcie_phy_match_table,
+       },
+       .probe = cygnus_pcie_phy_probe,
+};
+module_platform_driver(cygnus_pcie_phy_driver);
+
+MODULE_AUTHOR("Ray Jui <rjui@broadcom.com>");
+MODULE_DESCRIPTION("Broadcom Cygnus PCIe PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-mt65xx-usb3.c b/drivers/phy/phy-mt65xx-usb3.c
new file mode 100644 (file)
index 0000000..f30b28b
--- /dev/null
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2015 MediaTek Inc.
+ * Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+/*
+ * for sifslv2 register, but exclude port's;
+ * relative to USB3_SIF2_BASE base address
+ */
+#define SSUSB_SIFSLV_SPLLC             0x0000
+
+/* offsets of sub-segment in each port registers */
+#define SSUSB_SIFSLV_U2PHY_COM_BASE    0x0000
+#define SSUSB_SIFSLV_U3PHYD_BASE       0x0100
+#define SSUSB_USB30_PHYA_SIV_B_BASE    0x0300
+#define SSUSB_SIFSLV_U3PHYA_DA_BASE    0x0400
+
+#define U3P_USBPHYACR0         (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0000)
+#define PA0_RG_U2PLL_FORCE_ON          BIT(15)
+
+#define U3P_USBPHYACR2         (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0008)
+#define PA2_RG_SIF_U2PLL_FORCE_EN      BIT(18)
+
+#define U3P_USBPHYACR5         (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0014)
+#define PA5_RG_U2_HSTX_SRCTRL          GENMASK(14, 12)
+#define PA5_RG_U2_HSTX_SRCTRL_VAL(x)   ((0x7 & (x)) << 12)
+#define PA5_RG_U2_HS_100U_U3_EN        BIT(11)
+
+#define U3P_USBPHYACR6         (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0018)
+#define PA6_RG_U2_ISO_EN               BIT(31)
+#define PA6_RG_U2_BC11_SW_EN           BIT(23)
+#define PA6_RG_U2_OTG_VBUSCMP_EN       BIT(20)
+
+#define U3P_U2PHYACR4          (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0020)
+#define P2C_RG_USB20_GPIO_CTL          BIT(9)
+#define P2C_USB20_GPIO_MODE            BIT(8)
+#define P2C_U2_GPIO_CTR_MSK    (P2C_RG_USB20_GPIO_CTL | P2C_USB20_GPIO_MODE)
+
+#define U3D_U2PHYDCR0          (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0060)
+#define P2C_RG_SIF_U2PLL_FORCE_ON      BIT(24)
+
+#define U3P_U2PHYDTM0          (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x0068)
+#define P2C_FORCE_UART_EN              BIT(26)
+#define P2C_FORCE_DATAIN               BIT(23)
+#define P2C_FORCE_DM_PULLDOWN          BIT(21)
+#define P2C_FORCE_DP_PULLDOWN          BIT(20)
+#define P2C_FORCE_XCVRSEL              BIT(19)
+#define P2C_FORCE_SUSPENDM             BIT(18)
+#define P2C_FORCE_TERMSEL              BIT(17)
+#define P2C_RG_DATAIN                  GENMASK(13, 10)
+#define P2C_RG_DATAIN_VAL(x)           ((0xf & (x)) << 10)
+#define P2C_RG_DMPULLDOWN              BIT(7)
+#define P2C_RG_DPPULLDOWN              BIT(6)
+#define P2C_RG_XCVRSEL                 GENMASK(5, 4)
+#define P2C_RG_XCVRSEL_VAL(x)          ((0x3 & (x)) << 4)
+#define P2C_RG_SUSPENDM                        BIT(3)
+#define P2C_RG_TERMSEL                 BIT(2)
+#define P2C_DTM0_PART_MASK \
+               (P2C_FORCE_DATAIN | P2C_FORCE_DM_PULLDOWN | \
+               P2C_FORCE_DP_PULLDOWN | P2C_FORCE_XCVRSEL | \
+               P2C_FORCE_TERMSEL | P2C_RG_DMPULLDOWN | \
+               P2C_RG_DPPULLDOWN | P2C_RG_TERMSEL)
+
+#define U3P_U2PHYDTM1          (SSUSB_SIFSLV_U2PHY_COM_BASE + 0x006C)
+#define P2C_RG_UART_EN                 BIT(16)
+#define P2C_RG_VBUSVALID               BIT(5)
+#define P2C_RG_SESSEND                 BIT(4)
+#define P2C_RG_AVALID                  BIT(2)
+
+#define U3P_U3_PHYA_REG0       (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0000)
+#define P3A_RG_U3_VUSB10_ON            BIT(5)
+
+#define U3P_U3_PHYA_REG6       (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0018)
+#define P3A_RG_TX_EIDLE_CM             GENMASK(31, 28)
+#define P3A_RG_TX_EIDLE_CM_VAL(x)      ((0xf & (x)) << 28)
+
+#define U3P_U3_PHYA_REG9       (SSUSB_USB30_PHYA_SIV_B_BASE + 0x0024)
+#define P3A_RG_RX_DAC_MUX              GENMASK(5, 1)
+#define P3A_RG_RX_DAC_MUX_VAL(x)       ((0x1f & (x)) << 1)
+
+#define U3P_U3PHYA_DA_REG0     (SSUSB_SIFSLV_U3PHYA_DA_BASE + 0x0000)
+#define P3A_RG_XTAL_EXT_EN_U3          GENMASK(11, 10)
+#define P3A_RG_XTAL_EXT_EN_U3_VAL(x)   ((0x3 & (x)) << 10)
+
+#define U3P_PHYD_CDR1          (SSUSB_SIFSLV_U3PHYD_BASE + 0x005c)
+#define P3D_RG_CDR_BIR_LTD1            GENMASK(28, 24)
+#define P3D_RG_CDR_BIR_LTD1_VAL(x)     ((0x1f & (x)) << 24)
+#define P3D_RG_CDR_BIR_LTD0            GENMASK(12, 8)
+#define P3D_RG_CDR_BIR_LTD0_VAL(x)     ((0x1f & (x)) << 8)
+
+#define U3P_XTALCTL3           (SSUSB_SIFSLV_SPLLC + 0x0018)
+#define XC3_RG_U3_XTAL_RX_PWD          BIT(9)
+#define XC3_RG_U3_FRC_XTAL_RX_PWD      BIT(8)
+
+struct mt65xx_phy_instance {
+       struct phy *phy;
+       void __iomem *port_base;
+       u32 index;
+       u8 type;
+};
+
+struct mt65xx_u3phy {
+       struct device *dev;
+       void __iomem *sif_base; /* include sif2, but exclude port's */
+       struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */
+       struct mt65xx_phy_instance **phys;
+       int nphys;
+};
+
+static void phy_instance_init(struct mt65xx_u3phy *u3phy,
+       struct mt65xx_phy_instance *instance)
+{
+       void __iomem *port_base = instance->port_base;
+       u32 index = instance->index;
+       u32 tmp;
+
+       /* switch to USB function. (system register, force ip into usb mode) */
+       tmp = readl(port_base + U3P_U2PHYDTM0);
+       tmp &= ~P2C_FORCE_UART_EN;
+       tmp |= P2C_RG_XCVRSEL_VAL(1) | P2C_RG_DATAIN_VAL(0);
+       writel(tmp, port_base + U3P_U2PHYDTM0);
+
+       tmp = readl(port_base + U3P_U2PHYDTM1);
+       tmp &= ~P2C_RG_UART_EN;
+       writel(tmp, port_base + U3P_U2PHYDTM1);
+
+       if (!index) {
+               tmp = readl(port_base + U3P_U2PHYACR4);
+               tmp &= ~P2C_U2_GPIO_CTR_MSK;
+               writel(tmp, port_base + U3P_U2PHYACR4);
+
+               tmp = readl(port_base + U3P_USBPHYACR2);
+               tmp |= PA2_RG_SIF_U2PLL_FORCE_EN;
+               writel(tmp, port_base + U3P_USBPHYACR2);
+
+               tmp = readl(port_base + U3D_U2PHYDCR0);
+               tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
+               writel(tmp, port_base + U3D_U2PHYDCR0);
+       } else {
+               tmp = readl(port_base + U3D_U2PHYDCR0);
+               tmp |= P2C_RG_SIF_U2PLL_FORCE_ON;
+               writel(tmp, port_base + U3D_U2PHYDCR0);
+
+               tmp = readl(port_base + U3P_U2PHYDTM0);
+               tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM;
+               writel(tmp, port_base + U3P_U2PHYDTM0);
+       }
+
+       /* DP/DM BC1.1 path Disable */
+       tmp = readl(port_base + U3P_USBPHYACR6);
+       tmp &= ~PA6_RG_U2_BC11_SW_EN;
+       writel(tmp, port_base + U3P_USBPHYACR6);
+
+       tmp = readl(port_base + U3P_U3PHYA_DA_REG0);
+       tmp &= ~P3A_RG_XTAL_EXT_EN_U3;
+       tmp |= P3A_RG_XTAL_EXT_EN_U3_VAL(2);
+       writel(tmp, port_base + U3P_U3PHYA_DA_REG0);
+
+       tmp = readl(port_base + U3P_U3_PHYA_REG9);
+       tmp &= ~P3A_RG_RX_DAC_MUX;
+       tmp |= P3A_RG_RX_DAC_MUX_VAL(4);
+       writel(tmp, port_base + U3P_U3_PHYA_REG9);
+
+       tmp = readl(port_base + U3P_U3_PHYA_REG6);
+       tmp &= ~P3A_RG_TX_EIDLE_CM;
+       tmp |= P3A_RG_TX_EIDLE_CM_VAL(0xe);
+       writel(tmp, port_base + U3P_U3_PHYA_REG6);
+
+       tmp = readl(port_base + U3P_PHYD_CDR1);
+       tmp &= ~(P3D_RG_CDR_BIR_LTD0 | P3D_RG_CDR_BIR_LTD1);
+       tmp |= P3D_RG_CDR_BIR_LTD0_VAL(0xc) | P3D_RG_CDR_BIR_LTD1_VAL(0x3);
+       writel(tmp, port_base + U3P_PHYD_CDR1);
+
+       dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
+}
+
+static void phy_instance_power_on(struct mt65xx_u3phy *u3phy,
+       struct mt65xx_phy_instance *instance)
+{
+       void __iomem *port_base = instance->port_base;
+       u32 index = instance->index;
+       u32 tmp;
+
+       if (!index) {
+               /* Set RG_SSUSB_VUSB10_ON as 1 after VUSB10 ready */
+               tmp = readl(port_base + U3P_U3_PHYA_REG0);
+               tmp |= P3A_RG_U3_VUSB10_ON;
+               writel(tmp, port_base + U3P_U3_PHYA_REG0);
+       }
+
+       /* (force_suspendm=0) (let suspendm=1, enable usb 480MHz pll) */
+       tmp = readl(port_base + U3P_U2PHYDTM0);
+       tmp &= ~(P2C_FORCE_SUSPENDM | P2C_RG_XCVRSEL);
+       tmp &= ~(P2C_RG_DATAIN | P2C_DTM0_PART_MASK);
+       writel(tmp, port_base + U3P_U2PHYDTM0);
+
+       /* OTG Enable */
+       tmp = readl(port_base + U3P_USBPHYACR6);
+       tmp |= PA6_RG_U2_OTG_VBUSCMP_EN;
+       writel(tmp, port_base + U3P_USBPHYACR6);
+
+       if (!index) {
+               tmp = readl(u3phy->sif_base + U3P_XTALCTL3);
+               tmp |= XC3_RG_U3_XTAL_RX_PWD | XC3_RG_U3_FRC_XTAL_RX_PWD;
+               writel(tmp, u3phy->sif_base + U3P_XTALCTL3);
+
+               /* [mt8173]disable Change 100uA current from SSUSB */
+               tmp = readl(port_base + U3P_USBPHYACR5);
+               tmp &= ~PA5_RG_U2_HS_100U_U3_EN;
+               writel(tmp, port_base + U3P_USBPHYACR5);
+       }
+
+       tmp = readl(port_base + U3P_U2PHYDTM1);
+       tmp |= P2C_RG_VBUSVALID | P2C_RG_AVALID;
+       tmp &= ~P2C_RG_SESSEND;
+       writel(tmp, port_base + U3P_U2PHYDTM1);
+
+       /* USB 2.0 slew rate calibration */
+       tmp = readl(port_base + U3P_USBPHYACR5);
+       tmp &= ~PA5_RG_U2_HSTX_SRCTRL;
+       tmp |= PA5_RG_U2_HSTX_SRCTRL_VAL(4);
+       writel(tmp, port_base + U3P_USBPHYACR5);
+
+       if (index) {
+               tmp = readl(port_base + U3D_U2PHYDCR0);
+               tmp |= P2C_RG_SIF_U2PLL_FORCE_ON;
+               writel(tmp, port_base + U3D_U2PHYDCR0);
+
+               tmp = readl(port_base + U3P_U2PHYDTM0);
+               tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM;
+               writel(tmp, port_base + U3P_U2PHYDTM0);
+       }
+       dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
+}
+
+static void phy_instance_power_off(struct mt65xx_u3phy *u3phy,
+       struct mt65xx_phy_instance *instance)
+{
+       void __iomem *port_base = instance->port_base;
+       u32 index = instance->index;
+       u32 tmp;
+
+       tmp = readl(port_base + U3P_U2PHYDTM0);
+       tmp &= ~(P2C_RG_XCVRSEL | P2C_RG_DATAIN);
+       tmp |= P2C_FORCE_SUSPENDM;
+       writel(tmp, port_base + U3P_U2PHYDTM0);
+
+       /* OTG Disable */
+       tmp = readl(port_base + U3P_USBPHYACR6);
+       tmp &= ~PA6_RG_U2_OTG_VBUSCMP_EN;
+       writel(tmp, port_base + U3P_USBPHYACR6);
+
+       if (!index) {
+               /* (also disable)Change 100uA current switch to USB2.0 */
+               tmp = readl(port_base + U3P_USBPHYACR5);
+               tmp &= ~PA5_RG_U2_HS_100U_U3_EN;
+               writel(tmp, port_base + U3P_USBPHYACR5);
+       }
+
+       /* let suspendm=0, set utmi into analog power down */
+       tmp = readl(port_base + U3P_U2PHYDTM0);
+       tmp &= ~P2C_RG_SUSPENDM;
+       writel(tmp, port_base + U3P_U2PHYDTM0);
+       udelay(1);
+
+       tmp = readl(port_base + U3P_U2PHYDTM1);
+       tmp &= ~(P2C_RG_VBUSVALID | P2C_RG_AVALID);
+       tmp |= P2C_RG_SESSEND;
+       writel(tmp, port_base + U3P_U2PHYDTM1);
+
+       if (!index) {
+               tmp = readl(port_base + U3P_U3_PHYA_REG0);
+               tmp &= ~P3A_RG_U3_VUSB10_ON;
+               writel(tmp, port_base + U3P_U3_PHYA_REG0);
+       } else {
+               tmp = readl(port_base + U3D_U2PHYDCR0);
+               tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
+               writel(tmp, port_base + U3D_U2PHYDCR0);
+       }
+
+       dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
+}
+
+static void phy_instance_exit(struct mt65xx_u3phy *u3phy,
+       struct mt65xx_phy_instance *instance)
+{
+       void __iomem *port_base = instance->port_base;
+       u32 index = instance->index;
+       u32 tmp;
+
+       if (index) {
+               tmp = readl(port_base + U3D_U2PHYDCR0);
+               tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
+               writel(tmp, port_base + U3D_U2PHYDCR0);
+
+               tmp = readl(port_base + U3P_U2PHYDTM0);
+               tmp &= ~P2C_FORCE_SUSPENDM;
+               writel(tmp, port_base + U3P_U2PHYDTM0);
+       }
+}
+
+static int mt65xx_phy_init(struct phy *phy)
+{
+       struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
+       struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
+       int ret;
+
+       ret = clk_prepare_enable(u3phy->u3phya_ref);
+       if (ret) {
+               dev_err(u3phy->dev, "failed to enable u3phya_ref\n");
+               return ret;
+       }
+
+       phy_instance_init(u3phy, instance);
+       return 0;
+}
+
+static int mt65xx_phy_power_on(struct phy *phy)
+{
+       struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
+       struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
+
+       phy_instance_power_on(u3phy, instance);
+       return 0;
+}
+
+static int mt65xx_phy_power_off(struct phy *phy)
+{
+       struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
+       struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
+
+       phy_instance_power_off(u3phy, instance);
+       return 0;
+}
+
+static int mt65xx_phy_exit(struct phy *phy)
+{
+       struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
+       struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
+
+       phy_instance_exit(u3phy, instance);
+       clk_disable_unprepare(u3phy->u3phya_ref);
+       return 0;
+}
+
+static struct phy *mt65xx_phy_xlate(struct device *dev,
+                                       struct of_phandle_args *args)
+{
+       struct mt65xx_u3phy *u3phy = dev_get_drvdata(dev);
+       struct mt65xx_phy_instance *instance = NULL;
+       struct device_node *phy_np = args->np;
+       int index;
+
+
+       if (args->args_count != 1) {
+               dev_err(dev, "invalid number of cells in 'phy' property\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       for (index = 0; index < u3phy->nphys; index++)
+               if (phy_np == u3phy->phys[index]->phy->dev.of_node) {
+                       instance = u3phy->phys[index];
+                       break;
+               }
+
+       if (!instance) {
+               dev_err(dev, "failed to find appropriate phy\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       instance->type = args->args[0];
+
+       if (!(instance->type == PHY_TYPE_USB2 ||
+             instance->type == PHY_TYPE_USB3)) {
+               dev_err(dev, "unsupported device type: %d\n", instance->type);
+               return ERR_PTR(-EINVAL);
+       }
+
+       return instance->phy;
+}
+
+static struct phy_ops mt65xx_u3phy_ops = {
+       .init           = mt65xx_phy_init,
+       .exit           = mt65xx_phy_exit,
+       .power_on       = mt65xx_phy_power_on,
+       .power_off      = mt65xx_phy_power_off,
+       .owner          = THIS_MODULE,
+};
+
+static int mt65xx_u3phy_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct device_node *child_np;
+       struct phy_provider *provider;
+       struct resource *sif_res;
+       struct mt65xx_u3phy *u3phy;
+       struct resource res;
+       int port;
+
+       u3phy = devm_kzalloc(dev, sizeof(*u3phy), GFP_KERNEL);
+       if (!u3phy)
+               return -ENOMEM;
+
+       u3phy->nphys = of_get_child_count(np);
+       u3phy->phys = devm_kcalloc(dev, u3phy->nphys,
+                                      sizeof(*u3phy->phys), GFP_KERNEL);
+       if (!u3phy->phys)
+               return -ENOMEM;
+
+       u3phy->dev = dev;
+       platform_set_drvdata(pdev, u3phy);
+
+       sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       u3phy->sif_base = devm_ioremap_resource(dev, sif_res);
+       if (IS_ERR(u3phy->sif_base)) {
+               dev_err(dev, "failed to remap sif regs\n");
+               return PTR_ERR(u3phy->sif_base);
+       }
+
+       u3phy->u3phya_ref = devm_clk_get(dev, "u3phya_ref");
+       if (IS_ERR(u3phy->u3phya_ref)) {
+               dev_err(dev, "error to get u3phya_ref\n");
+               return PTR_ERR(u3phy->u3phya_ref);
+       }
+
+       port = 0;
+       for_each_child_of_node(np, child_np) {
+               struct mt65xx_phy_instance *instance;
+               struct phy *phy;
+               int retval;
+
+               instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
+               if (!instance)
+                       return -ENOMEM;
+
+               u3phy->phys[port] = instance;
+
+               phy = devm_phy_create(dev, child_np, &mt65xx_u3phy_ops);
+               if (IS_ERR(phy)) {
+                       dev_err(dev, "failed to create phy\n");
+                       return PTR_ERR(phy);
+               }
+
+               retval = of_address_to_resource(child_np, 0, &res);
+               if (retval) {
+                       dev_err(dev, "failed to get address resource(id-%d)\n",
+                               port);
+                       return retval;
+               }
+
+               instance->port_base = devm_ioremap_resource(&phy->dev, &res);
+               if (IS_ERR(instance->port_base)) {
+                       dev_err(dev, "failed to remap phy regs\n");
+                       return PTR_ERR(instance->port_base);
+               }
+
+               instance->phy = phy;
+               instance->index = port;
+               phy_set_drvdata(phy, instance);
+               port++;
+       }
+
+       provider = devm_of_phy_provider_register(dev, mt65xx_phy_xlate);
+
+       return PTR_ERR_OR_ZERO(provider);
+}
+
+static const struct of_device_id mt65xx_u3phy_id_table[] = {
+       { .compatible = "mediatek,mt8173-u3phy", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, mt65xx_u3phy_id_table);
+
+static struct platform_driver mt65xx_u3phy_driver = {
+       .probe          = mt65xx_u3phy_probe,
+       .driver         = {
+               .name   = "mt65xx-u3phy",
+               .of_match_table = mt65xx_u3phy_id_table,
+       },
+};
+
+module_platform_driver(mt65xx_u3phy_driver);
+
+MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
+MODULE_DESCRIPTION("mt65xx USB PHY driver");
+MODULE_LICENSE("GPL v2");
index f278a9c547e199c6228081f3445133dcdd9cda46..1d22d93b552d759df577a26228f0e7c7464c83c9 100644 (file)
@@ -27,6 +27,13 @@ static int samsung_usb2_phy_power_on(struct phy *phy)
 
        dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
                inst->cfg->label);
+
+       if (drv->vbus) {
+               ret = regulator_enable(drv->vbus);
+               if (ret)
+                       goto err_regulator;
+       }
+
        ret = clk_prepare_enable(drv->clk);
        if (ret)
                goto err_main_clk;
@@ -48,6 +55,9 @@ err_power_on:
 err_instance_clk:
        clk_disable_unprepare(drv->clk);
 err_main_clk:
+       if (drv->vbus)
+               regulator_disable(drv->vbus);
+err_regulator:
        return ret;
 }
 
@@ -55,7 +65,7 @@ static int samsung_usb2_phy_power_off(struct phy *phy)
 {
        struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
        struct samsung_usb2_phy_driver *drv = inst->drv;
-       int ret;
+       int ret = 0;
 
        dev_dbg(drv->dev, "Request to power_off \"%s\" usb phy\n",
                inst->cfg->label);
@@ -68,7 +78,10 @@ static int samsung_usb2_phy_power_off(struct phy *phy)
        }
        clk_disable_unprepare(drv->ref_clk);
        clk_disable_unprepare(drv->clk);
-       return 0;
+       if (drv->vbus)
+               ret = regulator_disable(drv->vbus);
+
+       return ret;
 }
 
 static const struct phy_ops samsung_usb2_phy_ops = {
@@ -203,6 +216,14 @@ static int samsung_usb2_phy_probe(struct platform_device *pdev)
                        return ret;
        }
 
+       drv->vbus = devm_regulator_get(dev, "vbus");
+       if (IS_ERR(drv->vbus)) {
+               ret = PTR_ERR(drv->vbus);
+               if (ret == -EPROBE_DEFER)
+                       return ret;
+               drv->vbus = NULL;
+       }
+
        for (i = 0; i < drv->cfg->num_phys; i++) {
                char *label = drv->cfg->phys[i].label;
                struct samsung_usb2_phy_instance *p = &drv->instances[i];
index 44bead9b8f34bb426440431217fa989a0f839734..6563e7ca0ac444824f4185277a33c1a5fee6a1bd 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/device.h>
 #include <linux/regmap.h>
 #include <linux/spinlock.h>
+#include <linux/regulator/consumer.h>
 
 #define KHZ 1000
 #define MHZ (KHZ * KHZ)
@@ -37,6 +38,7 @@ struct samsung_usb2_phy_driver {
        const struct samsung_usb2_phy_config *cfg;
        struct clk *clk;
        struct clk *ref_clk;
+       struct regulator *vbus;
        unsigned long ref_rate;
        u32 ref_reg_val;
        struct device *dev;
index 731b395d6e6a1621ee7fc36055b6c1a5f7367780..b12964b70625f6753997a1f529fb4c5f4c96b4d3 100644 (file)
@@ -551,19 +551,15 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
        if (IS_ERR(data->base))
                return PTR_ERR(data->base);
 
-       data->id_det_gpio = devm_gpiod_get(dev, "usb0_id_det", GPIOD_IN);
-       if (IS_ERR(data->id_det_gpio)) {
-               if (PTR_ERR(data->id_det_gpio) == -EPROBE_DEFER)
-                       return -EPROBE_DEFER;
-               data->id_det_gpio = NULL;
-       }
-
-       data->vbus_det_gpio = devm_gpiod_get(dev, "usb0_vbus_det", GPIOD_IN);
-       if (IS_ERR(data->vbus_det_gpio)) {
-               if (PTR_ERR(data->vbus_det_gpio) == -EPROBE_DEFER)
-                       return -EPROBE_DEFER;
-               data->vbus_det_gpio = NULL;
-       }
+       data->id_det_gpio = devm_gpiod_get_optional(dev, "usb0_id_det",
+                                                   GPIOD_IN);
+       if (IS_ERR(data->id_det_gpio))
+               return PTR_ERR(data->id_det_gpio);
+
+       data->vbus_det_gpio = devm_gpiod_get_optional(dev, "usb0_vbus_det",
+                                                     GPIOD_IN);
+       if (IS_ERR(data->vbus_det_gpio))
+               return PTR_ERR(data->vbus_det_gpio);
 
        if (of_find_property(np, "usb0_vbus_power-supply", NULL)) {
                data->vbus_power_supply = devm_power_supply_get_by_phandle(dev,
index d8926c6cd2a8ea4a374aef845522f40fdcba1cb7..d5c57f1e98fddfffb39c948159558ca4ea09b0f3 100644 (file)
@@ -27,7 +27,6 @@ obj-$(CONFIG_USB_R8A66597_HCD)        += host/
 obj-$(CONFIG_USB_HWA_HCD)      += host/
 obj-$(CONFIG_USB_IMX21_HCD)    += host/
 obj-$(CONFIG_USB_FSL_MPH_DR_OF)        += host/
-obj-$(CONFIG_USB_FUSBH200_HCD) += host/
 obj-$(CONFIG_USB_FOTG210_HCD)  += host/
 obj-$(CONFIG_USB_MAX3421_HCD)  += host/
 
index 5ce3f1d6a6ed340d8cf4db1a01c7fca3e6a6139a..5619b8ca3bf3f4d4e0b0651385a88c286a012967 100644 (file)
@@ -1,6 +1,7 @@
 config USB_CHIPIDEA
        tristate "ChipIdea Highspeed Dual Role Controller"
        depends on ((USB_EHCI_HCD && USB_GADGET) || (USB_EHCI_HCD && !USB_GADGET) || (!USB_EHCI_HCD && USB_GADGET)) && HAS_DMA
+       select EXTCON
        help
          Say Y here if your system has a dual role high speed USB
          controller based on ChipIdea silicon IP. Currently, only the
index ad53aed9b2806276defda453f5d3eda3c3cbfcc1..7c9b63064ea07e5308935ddfd5d4cef3504d512b 100644 (file)
@@ -56,12 +56,23 @@ static const struct ci_hdrc_imx_platform_flag imx6sx_usb_data = {
                CI_HDRC_DISABLE_HOST_STREAMING,
 };
 
+static const struct ci_hdrc_imx_platform_flag imx6ul_usb_data = {
+       .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
+               CI_HDRC_TURN_VBUS_EARLY_ON,
+};
+
+static const struct ci_hdrc_imx_platform_flag imx7d_usb_data = {
+       .flags = CI_HDRC_SUPPORTS_RUNTIME_PM,
+};
+
 static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
        { .compatible = "fsl,imx28-usb", .data = &imx28_usb_data},
        { .compatible = "fsl,imx27-usb", .data = &imx27_usb_data},
        { .compatible = "fsl,imx6q-usb", .data = &imx6q_usb_data},
        { .compatible = "fsl,imx6sl-usb", .data = &imx6sl_usb_data},
        { .compatible = "fsl,imx6sx-usb", .data = &imx6sx_usb_data},
+       { .compatible = "fsl,imx6ul-usb", .data = &imx6ul_usb_data},
+       { .compatible = "fsl,imx7d-usb", .data = &imx7d_usb_data},
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids);
index 773d150512fa4da6af83e5df10b069cc0276914c..b59195edf63634a3be94bcd3dc9ede6d87699185 100644 (file)
@@ -142,16 +142,16 @@ static const struct pci_device_id ci_hdrc_pci_id_table[] = {
                .driver_data = (kernel_ulong_t)&pci_platdata,
        },
        {
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0811),
+               PCI_VDEVICE(INTEL, 0x0811),
                .driver_data = (kernel_ulong_t)&langwell_pci_platdata,
        },
        {
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0829),
+               PCI_VDEVICE(INTEL, 0x0829),
                .driver_data = (kernel_ulong_t)&penwell_pci_platdata,
        },
        {
                /* Intel Clovertrail */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe006),
+               PCI_VDEVICE(INTEL, 0xe006),
                .driver_data = (kernel_ulong_t)&penwell_pci_platdata,
        },
        { 0 } /* end: all zeroes */
index 3feebf7f31f09259249c76fa121f747a2380ff9e..965d0e240dcb27674151e2073b984c89c90eb7ed 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/extcon.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <linux/module.h>
@@ -602,16 +603,52 @@ static irqreturn_t ci_irq(int irq, void *data)
        return ret;
 }
 
+static int ci_vbus_notifier(struct notifier_block *nb, unsigned long event,
+                           void *ptr)
+{
+       struct ci_hdrc_cable *vbus = container_of(nb, struct ci_hdrc_cable, nb);
+       struct ci_hdrc *ci = vbus->ci;
+
+       if (event)
+               vbus->state = true;
+       else
+               vbus->state = false;
+
+       vbus->changed = true;
+
+       ci_irq(ci->irq, ci);
+       return NOTIFY_DONE;
+}
+
+static int ci_id_notifier(struct notifier_block *nb, unsigned long event,
+                         void *ptr)
+{
+       struct ci_hdrc_cable *id = container_of(nb, struct ci_hdrc_cable, nb);
+       struct ci_hdrc *ci = id->ci;
+
+       if (event)
+               id->state = false;
+       else
+               id->state = true;
+
+       id->changed = true;
+
+       ci_irq(ci->irq, ci);
+       return NOTIFY_DONE;
+}
+
 static int ci_get_platdata(struct device *dev,
                struct ci_hdrc_platform_data *platdata)
 {
+       struct extcon_dev *ext_vbus, *ext_id;
+       struct ci_hdrc_cable *cable;
        int ret;
 
        if (!platdata->phy_mode)
                platdata->phy_mode = of_usb_get_phy_mode(dev->of_node);
 
        if (!platdata->dr_mode)
-               platdata->dr_mode = of_usb_get_dr_mode(dev->of_node);
+               platdata->dr_mode = usb_get_dr_mode(dev);
 
        if (platdata->dr_mode == USB_DR_MODE_UNKNOWN)
                platdata->dr_mode = USB_DR_MODE_OTG;
@@ -648,9 +685,13 @@ static int ci_get_platdata(struct device *dev,
                        return ret;
        }
 
-       if (of_usb_get_maximum_speed(dev->of_node) == USB_SPEED_FULL)
+       if (usb_get_maximum_speed(dev) == USB_SPEED_FULL)
                platdata->flags |= CI_HDRC_FORCE_FULLSPEED;
 
+       if (of_find_property(dev->of_node, "phy-clkgate-delay-us", NULL))
+               of_property_read_u32(dev->of_node, "phy-clkgate-delay-us",
+                                    &platdata->phy_clkgate_delay_us);
+
        platdata->itc_setting = 1;
        if (of_find_property(dev->of_node, "itc-setting", NULL)) {
                ret = of_property_read_u32(dev->of_node, "itc-setting",
@@ -695,9 +736,91 @@ static int ci_get_platdata(struct device *dev,
                platdata->flags |= CI_HDRC_OVERRIDE_RX_BURST;
        }
 
+       ext_id = ERR_PTR(-ENODEV);
+       ext_vbus = ERR_PTR(-ENODEV);
+       if (of_property_read_bool(dev->of_node, "extcon")) {
+               /* Each one of them is not mandatory */
+               ext_vbus = extcon_get_edev_by_phandle(dev, 0);
+               if (IS_ERR(ext_vbus) && PTR_ERR(ext_vbus) != -ENODEV)
+                       return PTR_ERR(ext_vbus);
+
+               ext_id = extcon_get_edev_by_phandle(dev, 1);
+               if (IS_ERR(ext_id) && PTR_ERR(ext_id) != -ENODEV)
+                       return PTR_ERR(ext_id);
+       }
+
+       cable = &platdata->vbus_extcon;
+       cable->nb.notifier_call = ci_vbus_notifier;
+       cable->edev = ext_vbus;
+
+       if (!IS_ERR(ext_vbus)) {
+               ret = extcon_get_cable_state_(cable->edev, EXTCON_USB);
+               if (ret)
+                       cable->state = true;
+               else
+                       cable->state = false;
+       }
+
+       cable = &platdata->id_extcon;
+       cable->nb.notifier_call = ci_id_notifier;
+       cable->edev = ext_id;
+
+       if (!IS_ERR(ext_id)) {
+               ret = extcon_get_cable_state_(cable->edev, EXTCON_USB_HOST);
+               if (ret)
+                       cable->state = false;
+               else
+                       cable->state = true;
+       }
+       return 0;
+}
+
+static int ci_extcon_register(struct ci_hdrc *ci)
+{
+       struct ci_hdrc_cable *id, *vbus;
+       int ret;
+
+       id = &ci->platdata->id_extcon;
+       id->ci = ci;
+       if (!IS_ERR(id->edev)) {
+               ret = extcon_register_notifier(id->edev, EXTCON_USB_HOST,
+                                              &id->nb);
+               if (ret < 0) {
+                       dev_err(ci->dev, "register ID failed\n");
+                       return ret;
+               }
+       }
+
+       vbus = &ci->platdata->vbus_extcon;
+       vbus->ci = ci;
+       if (!IS_ERR(vbus->edev)) {
+               ret = extcon_register_notifier(vbus->edev, EXTCON_USB,
+                                              &vbus->nb);
+               if (ret < 0) {
+                       extcon_unregister_notifier(id->edev, EXTCON_USB_HOST,
+                                                  &id->nb);
+                       dev_err(ci->dev, "register VBUS failed\n");
+                       return ret;
+               }
+       }
+
        return 0;
 }
 
+static void ci_extcon_unregister(struct ci_hdrc *ci)
+{
+       struct ci_hdrc_cable *cable;
+
+       cable = &ci->platdata->id_extcon;
+       if (!IS_ERR(cable->edev))
+               extcon_unregister_notifier(cable->edev, EXTCON_USB_HOST,
+                                          &cable->nb);
+
+       cable = &ci->platdata->vbus_extcon;
+       if (!IS_ERR(cable->edev))
+               extcon_unregister_notifier(cable->edev, EXTCON_USB, &cable->nb);
+}
+
 static DEFINE_IDA(ci_ida);
 
 struct platform_device *ci_hdrc_add_device(struct device *dev,
@@ -921,6 +1044,10 @@ static int ci_hdrc_probe(struct platform_device *pdev)
        if (ret)
                goto stop;
 
+       ret = ci_extcon_register(ci);
+       if (ret)
+               goto stop;
+
        if (ci->supports_runtime_pm) {
                pm_runtime_set_active(&pdev->dev);
                pm_runtime_enable(&pdev->dev);
@@ -938,6 +1065,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
        if (!ret)
                return 0;
 
+       ci_extcon_unregister(ci);
 stop:
        ci_role_destroy(ci);
 deinit_phy:
@@ -957,6 +1085,7 @@ static int ci_hdrc_remove(struct platform_device *pdev)
        }
 
        dbg_remove_files(ci);
+       ci_extcon_unregister(ci);
        ci_role_destroy(ci);
        ci_hdrc_enter_lpm(ci, true);
        ci_usb_phy_exit(ci);
@@ -996,6 +1125,9 @@ static void ci_controller_suspend(struct ci_hdrc *ci)
 {
        disable_irq(ci->irq);
        ci_hdrc_enter_lpm(ci, true);
+       if (ci->platdata->phy_clkgate_delay_us)
+               usleep_range(ci->platdata->phy_clkgate_delay_us,
+                            ci->platdata->phy_clkgate_delay_us + 50);
        usb_phy_set_suspend(ci->usb_phy, 1);
        ci->in_lpm = true;
        enable_irq(ci->irq);
index ad6c87a4653c2e4331eeb3b48787f525687e0c8a..45f86da1d6d37b4650ddfaf216879195ca9c6542 100644 (file)
  */
 u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask)
 {
-       return hw_read(ci, OP_OTGSC, mask);
+       struct ci_hdrc_cable *cable;
+       u32 val = hw_read(ci, OP_OTGSC, mask);
+
+       /*
+        * If using extcon framework for VBUS and/or ID signal
+        * detection overwrite OTGSC register value
+        */
+       cable = &ci->platdata->vbus_extcon;
+       if (!IS_ERR(cable->edev)) {
+               if (cable->changed)
+                       val |= OTGSC_BSVIS;
+               else
+                       val &= ~OTGSC_BSVIS;
+
+               cable->changed = false;
+
+               if (cable->state)
+                       val |= OTGSC_BSV;
+               else
+                       val &= ~OTGSC_BSV;
+       }
+
+       cable = &ci->platdata->id_extcon;
+       if (!IS_ERR(cable->edev)) {
+               if (cable->changed)
+                       val |= OTGSC_IDIS;
+               else
+                       val &= ~OTGSC_IDIS;
+
+               cable->changed = false;
+
+               if (cable->state)
+                       val |= OTGSC_ID;
+               else
+                       val &= ~OTGSC_ID;
+       }
+
+       return val;
 }
 
 /**
@@ -77,9 +114,12 @@ static void ci_handle_id_switch(struct ci_hdrc *ci)
                        ci_role(ci)->name, ci->roles[role]->name);
 
                ci_role_stop(ci);
-               /* wait vbus lower than OTGSC_BSV */
-               hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0,
-                               CI_VBUS_STABLE_TIMEOUT_MS);
+
+               if (role == CI_ROLE_GADGET)
+                       /* wait vbus lower than OTGSC_BSV */
+                       hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0,
+                                       CI_VBUS_STABLE_TIMEOUT_MS);
+
                ci_role_start(ci, role);
        }
 }
index 5ddab30ee240937d15d54cda0ad6642ea02247b5..fcea4eb36eeedbceac777ecd8d676e5ede74cba6 100644 (file)
 
 #define VF610_OVER_CUR_DIS             BIT(7)
 
+#define MX7D_USBNC_USB_CTRL2           0x4
+#define MX7D_USB_VBUS_WAKEUP_SOURCE_MASK       0x3
+#define MX7D_USB_VBUS_WAKEUP_SOURCE(v)         (v << 0)
+#define MX7D_USB_VBUS_WAKEUP_SOURCE_VBUS       MX7D_USB_VBUS_WAKEUP_SOURCE(0)
+#define MX7D_USB_VBUS_WAKEUP_SOURCE_AVALID     MX7D_USB_VBUS_WAKEUP_SOURCE(1)
+#define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID     MX7D_USB_VBUS_WAKEUP_SOURCE(2)
+#define MX7D_USB_VBUS_WAKEUP_SOURCE_SESS_END   MX7D_USB_VBUS_WAKEUP_SOURCE(3)
+
 struct usbmisc_ops {
        /* It's called once when probe a usb device */
        int (*init)(struct imx_usbmisc_data *data);
@@ -324,6 +332,55 @@ static int usbmisc_vf610_init(struct imx_usbmisc_data *data)
        return 0;
 }
 
+static int usbmisc_imx7d_set_wakeup
+       (struct imx_usbmisc_data *data, bool enabled)
+{
+       struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+       unsigned long flags;
+       u32 val;
+       u32 wakeup_setting = (MX6_BM_WAKEUP_ENABLE |
+               MX6_BM_VBUS_WAKEUP | MX6_BM_ID_WAKEUP);
+
+       spin_lock_irqsave(&usbmisc->lock, flags);
+       val = readl(usbmisc->base);
+       if (enabled) {
+               writel(val | wakeup_setting, usbmisc->base);
+       } else {
+               if (val & MX6_BM_WAKEUP_INTR)
+                       dev_dbg(data->dev, "wakeup int\n");
+               writel(val & ~wakeup_setting, usbmisc->base);
+       }
+       spin_unlock_irqrestore(&usbmisc->lock, flags);
+
+       return 0;
+}
+
+static int usbmisc_imx7d_init(struct imx_usbmisc_data *data)
+{
+       struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev);
+       unsigned long flags;
+       u32 reg;
+
+       if (data->index >= 1)
+               return -EINVAL;
+
+       spin_lock_irqsave(&usbmisc->lock, flags);
+       if (data->disable_oc) {
+               reg = readl(usbmisc->base);
+               writel(reg | MX6_BM_OVER_CUR_DIS, usbmisc->base);
+       }
+
+       reg = readl(usbmisc->base + MX7D_USBNC_USB_CTRL2);
+       reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK;
+       writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID,
+                usbmisc->base + MX7D_USBNC_USB_CTRL2);
+       spin_unlock_irqrestore(&usbmisc->lock, flags);
+
+       usbmisc_imx7d_set_wakeup(data, false);
+
+       return 0;
+}
+
 static const struct usbmisc_ops imx25_usbmisc_ops = {
        .init = usbmisc_imx25_init,
        .post = usbmisc_imx25_post,
@@ -351,6 +408,11 @@ static const struct usbmisc_ops imx6sx_usbmisc_ops = {
        .init = usbmisc_imx6sx_init,
 };
 
+static const struct usbmisc_ops imx7d_usbmisc_ops = {
+       .init = usbmisc_imx7d_init,
+       .set_wakeup = usbmisc_imx7d_set_wakeup,
+};
+
 int imx_usbmisc_init(struct imx_usbmisc_data *data)
 {
        struct imx_usbmisc *usbmisc;
@@ -426,6 +488,10 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = {
                .compatible = "fsl,imx6sx-usbmisc",
                .data = &imx6sx_usbmisc_ops,
        },
+       {
+               .compatible = "fsl,imx6ul-usbmisc",
+               .data = &imx6sx_usbmisc_ops,
+       },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
index 9e39286a4e5a1df458339cfbfd3076a3d08125ad..673d53038ed221c3b2e0c7c0d78d9309d307420a 100644 (file)
@@ -60,6 +60,24 @@ const char *usb_speed_string(enum usb_device_speed speed)
 }
 EXPORT_SYMBOL_GPL(usb_speed_string);
 
+enum usb_device_speed usb_get_maximum_speed(struct device *dev)
+{
+       const char *maximum_speed;
+       int err;
+       int i;
+
+       err = device_property_read_string(dev, "maximum-speed", &maximum_speed);
+       if (err < 0)
+               return USB_SPEED_UNKNOWN;
+
+       for (i = 0; i < ARRAY_SIZE(speed_names); i++)
+               if (strcmp(maximum_speed, speed_names[i]) == 0)
+                       return i;
+
+       return USB_SPEED_UNKNOWN;
+}
+EXPORT_SYMBOL_GPL(usb_get_maximum_speed);
+
 const char *usb_state_string(enum usb_device_state state)
 {
        static const char *const names[] = {
@@ -81,7 +99,6 @@ const char *usb_state_string(enum usb_device_state state)
 }
 EXPORT_SYMBOL_GPL(usb_state_string);
 
-#ifdef CONFIG_OF
 static const char *const usb_dr_modes[] = {
        [USB_DR_MODE_UNKNOWN]           = "",
        [USB_DR_MODE_HOST]              = "host",
@@ -89,19 +106,12 @@ static const char *const usb_dr_modes[] = {
        [USB_DR_MODE_OTG]               = "otg",
 };
 
-/**
- * of_usb_get_dr_mode - Get dual role mode for given device_node
- * @np:        Pointer to the given device_node
- *
- * The function gets phy interface string from property 'dr_mode',
- * and returns the correspondig enum usb_dr_mode
- */
-enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np)
+enum usb_dr_mode usb_get_dr_mode(struct device *dev)
 {
        const char *dr_mode;
        int err, i;
 
-       err = of_property_read_string(np, "dr_mode", &dr_mode);
+       err = device_property_read_string(dev, "dr_mode", &dr_mode);
        if (err < 0)
                return USB_DR_MODE_UNKNOWN;
 
@@ -111,34 +121,9 @@ enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np)
 
        return USB_DR_MODE_UNKNOWN;
 }
-EXPORT_SYMBOL_GPL(of_usb_get_dr_mode);
-
-/**
- * of_usb_get_maximum_speed - Get maximum requested speed for a given USB
- * controller.
- * @np: Pointer to the given device_node
- *
- * The function gets the maximum speed string from property "maximum-speed",
- * and returns the corresponding enum usb_device_speed.
- */
-enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np)
-{
-       const char *maximum_speed;
-       int err;
-       int i;
-
-       err = of_property_read_string(np, "maximum-speed", &maximum_speed);
-       if (err < 0)
-               return USB_SPEED_UNKNOWN;
-
-       for (i = 0; i < ARRAY_SIZE(speed_names); i++)
-               if (strcmp(maximum_speed, speed_names[i]) == 0)
-                       return i;
-
-       return USB_SPEED_UNKNOWN;
-}
-EXPORT_SYMBOL_GPL(of_usb_get_maximum_speed);
+EXPORT_SYMBOL_GPL(usb_get_dr_mode);
 
+#ifdef CONFIG_OF
 /**
  * of_usb_host_tpl_support - to get if Targeted Peripheral List is supported
  * for given targeted hosts (non-PC hosts)
index b9ddf0c1ffe5993893d5bd0d4f3ffe3f313ed435..7caff020106e23f26f9c3bb9c34585885064848d 100644 (file)
@@ -853,6 +853,10 @@ int usb_get_bos_descriptor(struct usb_device *dev)
                        dev->bos->ss_cap =
                                (struct usb_ss_cap_descriptor *)buffer;
                        break;
+               case USB_SSP_CAP_TYPE:
+                       dev->bos->ssp_cap =
+                               (struct usb_ssp_cap_descriptor *)buffer;
+                       break;
                case CONTAINER_ID_TYPE:
                        dev->bos->ss_id =
                                (struct usb_ss_container_id_descriptor *)buffer;
index 6b5063e7943fac720a266478d79b04a352d51e41..56593a9a87268cc0f6d8181cb5f8021c252b457b 100644 (file)
@@ -296,6 +296,10 @@ static int usb_probe_interface(struct device *dev)
        if (udev->authorized == 0) {
                dev_err(&intf->dev, "Device is not authorized for usage\n");
                return error;
+       } else if (intf->authorized == 0) {
+               dev_err(&intf->dev, "Interface %d is not authorized for usage\n",
+                               intf->altsetting->desc.bInterfaceNumber);
+               return error;
        }
 
        id = usb_match_dynamic_id(intf, driver);
@@ -417,12 +421,10 @@ static int usb_unbind_interface(struct device *dev)
                if (ep->streams == 0)
                        continue;
                if (j == 0) {
-                       eps = kmalloc(USB_MAXENDPOINTS * sizeof(void *),
+                       eps = kmalloc_array(USB_MAXENDPOINTS, sizeof(void *),
                                      GFP_KERNEL);
-                       if (!eps) {
-                               dev_warn(dev, "oom, leaking streams\n");
+                       if (!eps)
                                break;
-                       }
                }
                eps[j++] = ep;
        }
@@ -508,6 +510,10 @@ int usb_driver_claim_interface(struct usb_driver *driver,
        if (dev->driver)
                return -EBUSY;
 
+       /* reject claim if interface is not authorized */
+       if (!iface->authorized)
+               return -ENODEV;
+
        udev = interface_to_usbdev(iface);
 
        dev->driver = &driver->drvwrap.driver;
index 4d64e5c499e194d3c364543fca9f9e76442684b2..1c102d60cd9f4afe861a6933e9495662d74de4f5 100644 (file)
@@ -131,7 +131,7 @@ static inline int is_root_hub(struct usb_device *udev)
 /* usb 3.0 root hub device descriptor */
 static const u8 usb3_rh_dev_descriptor[18] = {
        0x12,       /*  __u8  bLength; */
-       0x01,       /*  __u8  bDescriptorType; Device */
+       USB_DT_DEVICE, /* __u8 bDescriptorType; Device */
        0x00, 0x03, /*  __le16 bcdUSB; v3.0 */
 
        0x09,       /*  __u8  bDeviceClass; HUB_CLASSCODE */
@@ -152,7 +152,7 @@ static const u8 usb3_rh_dev_descriptor[18] = {
 /* usb 2.5 (wireless USB 1.0) root hub device descriptor */
 static const u8 usb25_rh_dev_descriptor[18] = {
        0x12,       /*  __u8  bLength; */
-       0x01,       /*  __u8  bDescriptorType; Device */
+       USB_DT_DEVICE, /* __u8 bDescriptorType; Device */
        0x50, 0x02, /*  __le16 bcdUSB; v2.5 */
 
        0x09,       /*  __u8  bDeviceClass; HUB_CLASSCODE */
@@ -173,7 +173,7 @@ static const u8 usb25_rh_dev_descriptor[18] = {
 /* usb 2.0 root hub device descriptor */
 static const u8 usb2_rh_dev_descriptor[18] = {
        0x12,       /*  __u8  bLength; */
-       0x01,       /*  __u8  bDescriptorType; Device */
+       USB_DT_DEVICE, /* __u8 bDescriptorType; Device */
        0x00, 0x02, /*  __le16 bcdUSB; v2.0 */
 
        0x09,       /*  __u8  bDeviceClass; HUB_CLASSCODE */
@@ -196,7 +196,7 @@ static const u8 usb2_rh_dev_descriptor[18] = {
 /* usb 1.1 root hub device descriptor */
 static const u8 usb11_rh_dev_descriptor[18] = {
        0x12,       /*  __u8  bLength; */
-       0x01,       /*  __u8  bDescriptorType; Device */
+       USB_DT_DEVICE, /* __u8 bDescriptorType; Device */
        0x10, 0x01, /*  __le16 bcdUSB; v1.1 */
 
        0x09,       /*  __u8  bDeviceClass; HUB_CLASSCODE */
@@ -223,7 +223,7 @@ static const u8 fs_rh_config_descriptor[] = {
 
        /* one configuration */
        0x09,       /*  __u8  bLength; */
-       0x02,       /*  __u8  bDescriptorType; Configuration */
+       USB_DT_CONFIG, /* __u8 bDescriptorType; Configuration */
        0x19, 0x00, /*  __le16 wTotalLength; */
        0x01,       /*  __u8  bNumInterfaces; (1) */
        0x01,       /*  __u8  bConfigurationValue; */
@@ -248,7 +248,7 @@ static const u8 fs_rh_config_descriptor[] = {
 
        /* one interface */
        0x09,       /*  __u8  if_bLength; */
-       0x04,       /*  __u8  if_bDescriptorType; Interface */
+       USB_DT_INTERFACE,  /* __u8 if_bDescriptorType; Interface */
        0x00,       /*  __u8  if_bInterfaceNumber; */
        0x00,       /*  __u8  if_bAlternateSetting; */
        0x01,       /*  __u8  if_bNumEndpoints; */
@@ -259,7 +259,7 @@ static const u8 fs_rh_config_descriptor[] = {
 
        /* one endpoint (status change endpoint) */
        0x07,       /*  __u8  ep_bLength; */
-       0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
+       USB_DT_ENDPOINT, /* __u8 ep_bDescriptorType; Endpoint */
        0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
        0x03,       /*  __u8  ep_bmAttributes; Interrupt */
        0x02, 0x00, /*  __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
@@ -270,7 +270,7 @@ static const u8 hs_rh_config_descriptor[] = {
 
        /* one configuration */
        0x09,       /*  __u8  bLength; */
-       0x02,       /*  __u8  bDescriptorType; Configuration */
+       USB_DT_CONFIG, /* __u8 bDescriptorType; Configuration */
        0x19, 0x00, /*  __le16 wTotalLength; */
        0x01,       /*  __u8  bNumInterfaces; (1) */
        0x01,       /*  __u8  bConfigurationValue; */
@@ -295,7 +295,7 @@ static const u8 hs_rh_config_descriptor[] = {
 
        /* one interface */
        0x09,       /*  __u8  if_bLength; */
-       0x04,       /*  __u8  if_bDescriptorType; Interface */
+       USB_DT_INTERFACE, /* __u8 if_bDescriptorType; Interface */
        0x00,       /*  __u8  if_bInterfaceNumber; */
        0x00,       /*  __u8  if_bAlternateSetting; */
        0x01,       /*  __u8  if_bNumEndpoints; */
@@ -306,7 +306,7 @@ static const u8 hs_rh_config_descriptor[] = {
 
        /* one endpoint (status change endpoint) */
        0x07,       /*  __u8  ep_bLength; */
-       0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
+       USB_DT_ENDPOINT, /* __u8 ep_bDescriptorType; Endpoint */
        0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
        0x03,       /*  __u8  ep_bmAttributes; Interrupt */
                    /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8)
@@ -318,7 +318,7 @@ static const u8 hs_rh_config_descriptor[] = {
 static const u8 ss_rh_config_descriptor[] = {
        /* one configuration */
        0x09,       /*  __u8  bLength; */
-       0x02,       /*  __u8  bDescriptorType; Configuration */
+       USB_DT_CONFIG, /* __u8 bDescriptorType; Configuration */
        0x1f, 0x00, /*  __le16 wTotalLength; */
        0x01,       /*  __u8  bNumInterfaces; (1) */
        0x01,       /*  __u8  bConfigurationValue; */
@@ -332,7 +332,7 @@ static const u8 ss_rh_config_descriptor[] = {
 
        /* one interface */
        0x09,       /*  __u8  if_bLength; */
-       0x04,       /*  __u8  if_bDescriptorType; Interface */
+       USB_DT_INTERFACE, /* __u8 if_bDescriptorType; Interface */
        0x00,       /*  __u8  if_bInterfaceNumber; */
        0x00,       /*  __u8  if_bAlternateSetting; */
        0x01,       /*  __u8  if_bNumEndpoints; */
@@ -343,7 +343,7 @@ static const u8 ss_rh_config_descriptor[] = {
 
        /* one endpoint (status change endpoint) */
        0x07,       /*  __u8  ep_bLength; */
-       0x05,       /*  __u8  ep_bDescriptorType; Endpoint */
+       USB_DT_ENDPOINT, /* __u8 ep_bDescriptorType; Endpoint */
        0x81,       /*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
        0x03,       /*  __u8  ep_bmAttributes; Interrupt */
                    /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8)
@@ -353,7 +353,8 @@ static const u8 ss_rh_config_descriptor[] = {
 
        /* one SuperSpeed endpoint companion descriptor */
        0x06,        /* __u8 ss_bLength */
-       0x30,        /* __u8 ss_bDescriptorType; SuperSpeed EP Companion */
+       USB_DT_SS_ENDPOINT_COMP, /* __u8 ss_bDescriptorType; SuperSpeed EP */
+                    /* Companion */
        0x00,        /* __u8 ss_bMaxBurst; allows 1 TX between ACKs */
        0x00,        /* __u8 ss_bmAttributes; 1 packet per service interval */
        0x02, 0x00   /* __le16 ss_wBytesPerInterval; 15 bits for max 15 ports */
@@ -555,6 +556,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
                switch (wValue & 0xff00) {
                case USB_DT_DEVICE << 8:
                        switch (hcd->speed) {
+                       case HCD_USB31:
                        case HCD_USB3:
                                bufp = usb3_rh_dev_descriptor;
                                break;
@@ -576,6 +578,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
                        break;
                case USB_DT_CONFIG << 8:
                        switch (hcd->speed) {
+                       case HCD_USB31:
                        case HCD_USB3:
                                bufp = ss_rh_config_descriptor;
                                len = sizeof ss_rh_config_descriptor;
@@ -854,10 +857,10 @@ static ssize_t authorized_default_show(struct device *dev,
 {
        struct usb_device *rh_usb_dev = to_usb_device(dev);
        struct usb_bus *usb_bus = rh_usb_dev->bus;
-       struct usb_hcd *usb_hcd;
+       struct usb_hcd *hcd;
 
-       usb_hcd = bus_to_hcd(usb_bus);
-       return snprintf(buf, PAGE_SIZE, "%u\n", usb_hcd->authorized_default);
+       hcd = bus_to_hcd(usb_bus);
+       return snprintf(buf, PAGE_SIZE, "%u\n", !!HCD_DEV_AUTHORIZED(hcd));
 }
 
 static ssize_t authorized_default_store(struct device *dev,
@@ -868,12 +871,16 @@ static ssize_t authorized_default_store(struct device *dev,
        unsigned val;
        struct usb_device *rh_usb_dev = to_usb_device(dev);
        struct usb_bus *usb_bus = rh_usb_dev->bus;
-       struct usb_hcd *usb_hcd;
+       struct usb_hcd *hcd;
 
-       usb_hcd = bus_to_hcd(usb_bus);
+       hcd = bus_to_hcd(usb_bus);
        result = sscanf(buf, "%u\n", &val);
        if (result == 1) {
-               usb_hcd->authorized_default = val ? 1 : 0;
+               if (val)
+                       set_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags);
+               else
+                       clear_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags);
+
                result = size;
        } else {
                result = -EINVAL;
@@ -882,9 +889,53 @@ static ssize_t authorized_default_store(struct device *dev,
 }
 static DEVICE_ATTR_RW(authorized_default);
 
+/*
+ * interface_authorized_default_show - show default authorization status
+ * for USB interfaces
+ *
+ * note: interface_authorized_default is the default value
+ *       for initializing the authorized attribute of interfaces
+ */
+static ssize_t interface_authorized_default_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct usb_device *usb_dev = to_usb_device(dev);
+       struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
+
+       return sprintf(buf, "%u\n", !!HCD_INTF_AUTHORIZED(hcd));
+}
+
+/*
+ * interface_authorized_default_store - store default authorization status
+ * for USB interfaces
+ *
+ * note: interface_authorized_default is the default value
+ *       for initializing the authorized attribute of interfaces
+ */
+static ssize_t interface_authorized_default_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct usb_device *usb_dev = to_usb_device(dev);
+       struct usb_hcd *hcd = bus_to_hcd(usb_dev->bus);
+       int rc = count;
+       bool val;
+
+       if (strtobool(buf, &val) != 0)
+               return -EINVAL;
+
+       if (val)
+               set_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
+       else
+               clear_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
+
+       return rc;
+}
+static DEVICE_ATTR_RW(interface_authorized_default);
+
 /* Group all the USB bus attributes */
 static struct attribute *usb_bus_attrs[] = {
                &dev_attr_authorized_default.attr,
+               &dev_attr_interface_authorized_default.attr,
                NULL,
 };
 
@@ -2676,12 +2727,22 @@ int usb_add_hcd(struct usb_hcd *hcd,
        dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
 
        /* Keep old behaviour if authorized_default is not in [0, 1]. */
-       if (authorized_default < 0 || authorized_default > 1)
-               hcd->authorized_default = hcd->wireless ? 0 : 1;
-       else
-               hcd->authorized_default = authorized_default;
+       if (authorized_default < 0 || authorized_default > 1) {
+               if (hcd->wireless)
+                       clear_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags);
+               else
+                       set_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags);
+       } else {
+               if (authorized_default)
+                       set_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags);
+               else
+                       clear_bit(HCD_FLAG_DEV_AUTHORIZED, &hcd->flags);
+       }
        set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 
+       /* per default all interfaces are authorized */
+       set_bit(HCD_FLAG_INTF_AUTHORIZED, &hcd->flags);
+
        /* HC is in reset state, but accessible.  Now do the one-time init,
         * bottom up so that hcds can customize the root hubs before hub_wq
         * starts talking to them.  (Note, bus id is assigned early too.)
@@ -2717,6 +2778,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
                rhdev->speed = USB_SPEED_WIRELESS;
                break;
        case HCD_USB3:
+       case HCD_USB31:
                rhdev->speed = USB_SPEED_SUPER;
                break;
        default:
index 431839bd291f0b2ab2d66b0019c16f04421efc3e..bdeadc112d29f9b4545bf3ab82645b52982f5cfd 100644 (file)
@@ -1070,7 +1070,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
                 * for HUB_POST_RESET, but it's easier not to.
                 */
                if (type == HUB_INIT) {
-                       unsigned delay = hub_power_on_good_delay(hub);
+                       delay = hub_power_on_good_delay(hub);
 
                        hub_power_on(hub, false);
                        INIT_DELAYED_WORK(&hub->init_work, hub_init_func2);
@@ -1404,7 +1404,6 @@ static int hub_configure(struct usb_hub *hub,
        /* FIXME for USB 3.0, skip for now */
        if ((wHubCharacteristics & HUB_CHAR_COMPOUND) &&
                        !(hub_is_superspeed(hdev))) {
-               int     i;
                char    portstr[USB_MAXCHILDREN + 1];
 
                for (i = 0; i < maxchild; i++)
@@ -2240,39 +2239,49 @@ static int usb_enumerate_device_otg(struct usb_device *udev)
                        && udev->parent == udev->bus->root_hub) {
                struct usb_otg_descriptor       *desc = NULL;
                struct usb_bus                  *bus = udev->bus;
+               unsigned                        port1 = udev->portnum;
 
                /* descriptor may appear anywhere in config */
-               if (__usb_get_extra_descriptor(udev->rawdescriptors[0],
-                                       le16_to_cpu(udev->config[0].desc.wTotalLength),
-                                       USB_DT_OTG, (void **) &desc) == 0) {
-                       if (desc->bmAttributes & USB_OTG_HNP) {
-                               unsigned                port1 = udev->portnum;
+               err = __usb_get_extra_descriptor(udev->rawdescriptors[0],
+                               le16_to_cpu(udev->config[0].desc.wTotalLength),
+                               USB_DT_OTG, (void **) &desc);
+               if (err || !(desc->bmAttributes & USB_OTG_HNP))
+                       return 0;
 
-                               dev_info(&udev->dev,
-                                       "Dual-Role OTG device on %sHNP port\n",
-                                       (port1 == bus->otg_port)
-                                               ? "" : "non-");
-
-                               /* enable HNP before suspend, it's simpler */
-                               if (port1 == bus->otg_port)
-                                       bus->b_hnp_enable = 1;
-                               err = usb_control_msg(udev,
-                                       usb_sndctrlpipe(udev, 0),
-                                       USB_REQ_SET_FEATURE, 0,
-                                       bus->b_hnp_enable
-                                               ? USB_DEVICE_B_HNP_ENABLE
-                                               : USB_DEVICE_A_ALT_HNP_SUPPORT,
-                                       0, NULL, 0, USB_CTRL_SET_TIMEOUT);
-                               if (err < 0) {
-                                       /* OTG MESSAGE: report errors here,
-                                        * customize to match your product.
-                                        */
-                                       dev_info(&udev->dev,
-                                               "can't set HNP mode: %d\n",
-                                               err);
-                                       bus->b_hnp_enable = 0;
-                               }
+               dev_info(&udev->dev, "Dual-Role OTG device on %sHNP port\n",
+                                       (port1 == bus->otg_port) ? "" : "non-");
+
+               /* enable HNP before suspend, it's simpler */
+               if (port1 == bus->otg_port) {
+                       bus->b_hnp_enable = 1;
+                       err = usb_control_msg(udev,
+                               usb_sndctrlpipe(udev, 0),
+                               USB_REQ_SET_FEATURE, 0,
+                               USB_DEVICE_B_HNP_ENABLE,
+                               0, NULL, 0,
+                               USB_CTRL_SET_TIMEOUT);
+                       if (err < 0) {
+                               /*
+                                * OTG MESSAGE: report errors here,
+                                * customize to match your product.
+                                */
+                               dev_err(&udev->dev, "can't set HNP mode: %d\n",
+                                                                       err);
+                               bus->b_hnp_enable = 0;
                        }
+               } else if (desc->bLength == sizeof
+                               (struct usb_otg_descriptor)) {
+                       /* Set a_alt_hnp_support for legacy otg device */
+                       err = usb_control_msg(udev,
+                               usb_sndctrlpipe(udev, 0),
+                               USB_REQ_SET_FEATURE, 0,
+                               USB_DEVICE_A_ALT_HNP_SUPPORT,
+                               0, NULL, 0,
+                               USB_CTRL_SET_TIMEOUT);
+                       if (err < 0)
+                               dev_err(&udev->dev,
+                                       "set a_alt_hnp_support failed: %d\n",
+                                       err);
                }
        }
 #endif
@@ -4222,7 +4231,7 @@ static int hub_enable_device(struct usb_device *udev)
  * but it is still necessary to lock the port.
  */
 static int
-hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
+hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
                int retry_counter)
 {
        struct usb_device       *hdev = hub->hdev;
@@ -4526,7 +4535,7 @@ fail:
 }
 
 static void
-check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1)
+check_highspeed(struct usb_hub *hub, struct usb_device *udev, int port1)
 {
        struct usb_qualifier_descriptor *qual;
        int                             status;
@@ -4534,11 +4543,11 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1)
        if (udev->quirks & USB_QUIRK_DEVICE_QUALIFIER)
                return;
 
-       qual = kmalloc (sizeof *qual, GFP_KERNEL);
+       qual = kmalloc(sizeof *qual, GFP_KERNEL);
        if (qual == NULL)
                return;
 
-       status = usb_get_descriptor (udev, USB_DT_DEVICE_QUALIFIER, 0,
+       status = usb_get_descriptor(udev, USB_DT_DEVICE_QUALIFIER, 0,
                        qual, sizeof *qual);
        if (status == sizeof *qual) {
                dev_info(&udev->dev, "not running at top speed; "
@@ -4554,7 +4563,7 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1)
 }
 
 static unsigned
-hub_power_remaining (struct usb_hub *hub)
+hub_power_remaining(struct usb_hub *hub)
 {
        struct usb_device *hdev = hub->hdev;
        int remaining;
@@ -4741,7 +4750,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
                if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0200
                                && udev->speed == USB_SPEED_FULL
                                && highspeed_hubs != 0)
-                       check_highspeed (hub, udev, port1);
+                       check_highspeed(hub, udev, port1);
 
                /* Store the parent's children[] pointer.  At this point
                 * udev becomes globally accessible, although presumably
@@ -5115,7 +5124,7 @@ static const struct usb_device_id hub_id_table[] = {
     { }                                                /* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, hub_id_table);
+MODULE_DEVICE_TABLE(usb, hub_id_table);
 
 static struct usb_driver hub_driver = {
        .name =         "hub",
@@ -5227,7 +5236,7 @@ static int descriptors_changed(struct usb_device *udev,
                        changed = 1;
                        break;
                }
-               if (memcmp (buf, udev->rawdescriptors[index], old_length)
+               if (memcmp(buf, udev->rawdescriptors[index], old_length)
                                != 0) {
                        dev_dbg(&udev->dev, "config index %d changed (#%d)\n",
                                index,
index f368d2053da534ca975804dfad2bd8ddc77d5fba..8e641b5893edb7a6195c34e43248540fbff39aa6 100644 (file)
@@ -1387,8 +1387,6 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
         * new altsetting.
         */
        if (manual) {
-               int i;
-
                for (i = 0; i < alt->desc.bNumEndpoints; i++) {
                        epaddr = alt->endpoint[i].desc.bEndpointAddress;
                        pipe = __create_pipe(dev,
@@ -1555,6 +1553,44 @@ static void usb_release_interface(struct device *dev)
        kfree(intf);
 }
 
+/*
+ * usb_deauthorize_interface - deauthorize an USB interface
+ *
+ * @intf: USB interface structure
+ */
+void usb_deauthorize_interface(struct usb_interface *intf)
+{
+       struct device *dev = &intf->dev;
+
+       device_lock(dev->parent);
+
+       if (intf->authorized) {
+               device_lock(dev);
+               intf->authorized = 0;
+               device_unlock(dev);
+
+               usb_forced_unbind_intf(intf);
+       }
+
+       device_unlock(dev->parent);
+}
+
+/*
+ * usb_authorize_interface - authorize an USB interface
+ *
+ * @intf: USB interface structure
+ */
+void usb_authorize_interface(struct usb_interface *intf)
+{
+       struct device *dev = &intf->dev;
+
+       if (!intf->authorized) {
+               device_lock(dev);
+               intf->authorized = 1; /* authorize interface */
+               device_unlock(dev);
+       }
+}
+
 static int usb_if_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
        struct usb_device *usb_dev;
@@ -1807,6 +1843,7 @@ free_interfaces:
                intfc = cp->intf_cache[i];
                intf->altsetting = intfc->altsetting;
                intf->num_altsetting = intfc->num_altsetting;
+               intf->authorized = !!HCD_INTF_AUTHORIZED(hcd);
                kref_get(&intfc->ref);
 
                alt = usb_altnum_to_altsetting(intf, 0);
index cfc68c11c3f565d27bfb9898a9e0d18e7a5d58e6..d9ec2de6c4cf8dd38bb7afb85399448f88992961 100644 (file)
@@ -957,6 +957,41 @@ static ssize_t supports_autosuspend_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(supports_autosuspend);
 
+/*
+ * interface_authorized_show - show authorization status of an USB interface
+ * 1 is authorized, 0 is deauthorized
+ */
+static ssize_t interface_authorized_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct usb_interface *intf = to_usb_interface(dev);
+
+       return sprintf(buf, "%u\n", intf->authorized);
+}
+
+/*
+ * interface_authorized_store - authorize or deauthorize an USB interface
+ */
+static ssize_t interface_authorized_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct usb_interface *intf = to_usb_interface(dev);
+       bool val;
+
+       if (strtobool(buf, &val) != 0)
+               return -EINVAL;
+
+       if (val)
+               usb_authorize_interface(intf);
+       else
+               usb_deauthorize_interface(intf);
+
+       return count;
+}
+static struct device_attribute dev_attr_interface_authorized =
+               __ATTR(authorized, S_IRUGO | S_IWUSR,
+               interface_authorized_show, interface_authorized_store);
+
 static struct attribute *intf_attrs[] = {
        &dev_attr_bInterfaceNumber.attr,
        &dev_attr_bAlternateSetting.attr,
@@ -966,6 +1001,7 @@ static struct attribute *intf_attrs[] = {
        &dev_attr_bInterfaceProtocol.attr,
        &dev_attr_modalias.attr,
        &dev_attr_supports_autosuspend.attr,
+       &dev_attr_interface_authorized.attr,
        NULL,
 };
 static struct attribute_group intf_attr_grp = {
index c9e8ee81b6b747f72fe91085e8e9621f4ad1b0c3..3d274778caaf8f9f473aacc89b1be6c20de19ab2 100644 (file)
@@ -129,9 +129,8 @@ void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor)
        list_add_tail(&urb->anchor_list, &anchor->urb_list);
        urb->anchor = anchor;
 
-       if (unlikely(anchor->poisoned)) {
+       if (unlikely(anchor->poisoned))
                atomic_inc(&urb->reject);
-       }
 
        spin_unlock_irqrestore(&anchor->lock, flags);
 }
index 8d5b2f4113cd563004acbabb459f4e4212361138..f8bbd0b6d9fe44cb0077a200588c1ea054914580 100644 (file)
@@ -510,7 +510,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
        if (root_hub)   /* Root hub always ok [and always wired] */
                dev->authorized = 1;
        else {
-               dev->authorized = usb_hcd->authorized_default;
+               dev->authorized = !!HCD_DEV_AUTHORIZED(usb_hcd);
                dev->wusb = usb_bus_is_wusb(bus) ? 1 : 0;
        }
        return dev;
index 457255a3306a3c2837674d22aa9560bf30842220..05b5e17abf92fc158530d13f3e2ae8edf9923c5a 100644 (file)
@@ -27,6 +27,8 @@ extern void usb_release_interface_cache(struct kref *ref);
 extern void usb_disable_device(struct usb_device *dev, int skip_ep0);
 extern int usb_deauthorize_device(struct usb_device *);
 extern int usb_authorize_device(struct usb_device *);
+extern void usb_deauthorize_interface(struct usb_interface *);
+extern void usb_authorize_interface(struct usb_interface *);
 extern void usb_detect_quirks(struct usb_device *udev);
 extern void usb_detect_interface_quirks(struct usb_device *udev);
 extern int usb_remove_device(struct usb_device *udev);
index b00fe95391841f6c0cb968e7563eb65c0e83ac6f..ef73e498e98fc85501ff65cbeeaa20cd13ec9c4c 100644 (file)
@@ -73,13 +73,13 @@ static int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg)
 
        /* Backup Host regs */
        hr = &hsotg->hr_backup;
-       hr->hcfg = readl(hsotg->regs + HCFG);
-       hr->haintmsk = readl(hsotg->regs + HAINTMSK);
+       hr->hcfg = dwc2_readl(hsotg->regs + HCFG);
+       hr->haintmsk = dwc2_readl(hsotg->regs + HAINTMSK);
        for (i = 0; i < hsotg->core_params->host_channels; ++i)
-               hr->hcintmsk[i] = readl(hsotg->regs + HCINTMSK(i));
+               hr->hcintmsk[i] = dwc2_readl(hsotg->regs + HCINTMSK(i));
 
-       hr->hprt0 = readl(hsotg->regs + HPRT0);
-       hr->hfir = readl(hsotg->regs + HFIR);
+       hr->hprt0 = dwc2_read_hprt0(hsotg);
+       hr->hfir = dwc2_readl(hsotg->regs + HFIR);
        hr->valid = true;
 
        return 0;
@@ -108,14 +108,15 @@ static int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg)
        }
        hr->valid = false;
 
-       writel(hr->hcfg, hsotg->regs + HCFG);
-       writel(hr->haintmsk, hsotg->regs + HAINTMSK);
+       dwc2_writel(hr->hcfg, hsotg->regs + HCFG);
+       dwc2_writel(hr->haintmsk, hsotg->regs + HAINTMSK);
 
        for (i = 0; i < hsotg->core_params->host_channels; ++i)
-               writel(hr->hcintmsk[i], hsotg->regs + HCINTMSK(i));
+               dwc2_writel(hr->hcintmsk[i], hsotg->regs + HCINTMSK(i));
 
-       writel(hr->hprt0, hsotg->regs + HPRT0);
-       writel(hr->hfir, hsotg->regs + HFIR);
+       dwc2_writel(hr->hprt0, hsotg->regs + HPRT0);
+       dwc2_writel(hr->hfir, hsotg->regs + HFIR);
+       hsotg->frame_number = 0;
 
        return 0;
 }
@@ -146,15 +147,15 @@ static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
        /* Backup dev regs */
        dr = &hsotg->dr_backup;
 
-       dr->dcfg = readl(hsotg->regs + DCFG);
-       dr->dctl = readl(hsotg->regs + DCTL);
-       dr->daintmsk = readl(hsotg->regs + DAINTMSK);
-       dr->diepmsk = readl(hsotg->regs + DIEPMSK);
-       dr->doepmsk = readl(hsotg->regs + DOEPMSK);
+       dr->dcfg = dwc2_readl(hsotg->regs + DCFG);
+       dr->dctl = dwc2_readl(hsotg->regs + DCTL);
+       dr->daintmsk = dwc2_readl(hsotg->regs + DAINTMSK);
+       dr->diepmsk = dwc2_readl(hsotg->regs + DIEPMSK);
+       dr->doepmsk = dwc2_readl(hsotg->regs + DOEPMSK);
 
        for (i = 0; i < hsotg->num_of_eps; i++) {
                /* Backup IN EPs */
-               dr->diepctl[i] = readl(hsotg->regs + DIEPCTL(i));
+               dr->diepctl[i] = dwc2_readl(hsotg->regs + DIEPCTL(i));
 
                /* Ensure DATA PID is correctly configured */
                if (dr->diepctl[i] & DXEPCTL_DPID)
@@ -162,11 +163,11 @@ static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
                else
                        dr->diepctl[i] |= DXEPCTL_SETD0PID;
 
-               dr->dieptsiz[i] = readl(hsotg->regs + DIEPTSIZ(i));
-               dr->diepdma[i] = readl(hsotg->regs + DIEPDMA(i));
+               dr->dieptsiz[i] = dwc2_readl(hsotg->regs + DIEPTSIZ(i));
+               dr->diepdma[i] = dwc2_readl(hsotg->regs + DIEPDMA(i));
 
                /* Backup OUT EPs */
-               dr->doepctl[i] = readl(hsotg->regs + DOEPCTL(i));
+               dr->doepctl[i] = dwc2_readl(hsotg->regs + DOEPCTL(i));
 
                /* Ensure DATA PID is correctly configured */
                if (dr->doepctl[i] & DXEPCTL_DPID)
@@ -174,8 +175,8 @@ static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
                else
                        dr->doepctl[i] |= DXEPCTL_SETD0PID;
 
-               dr->doeptsiz[i] = readl(hsotg->regs + DOEPTSIZ(i));
-               dr->doepdma[i] = readl(hsotg->regs + DOEPDMA(i));
+               dr->doeptsiz[i] = dwc2_readl(hsotg->regs + DOEPTSIZ(i));
+               dr->doepdma[i] = dwc2_readl(hsotg->regs + DOEPDMA(i));
        }
        dr->valid = true;
        return 0;
@@ -205,28 +206,28 @@ static int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg)
        }
        dr->valid = false;
 
-       writel(dr->dcfg, hsotg->regs + DCFG);
-       writel(dr->dctl, hsotg->regs + DCTL);
-       writel(dr->daintmsk, hsotg->regs + DAINTMSK);
-       writel(dr->diepmsk, hsotg->regs + DIEPMSK);
-       writel(dr->doepmsk, hsotg->regs + DOEPMSK);
+       dwc2_writel(dr->dcfg, hsotg->regs + DCFG);
+       dwc2_writel(dr->dctl, hsotg->regs + DCTL);
+       dwc2_writel(dr->daintmsk, hsotg->regs + DAINTMSK);
+       dwc2_writel(dr->diepmsk, hsotg->regs + DIEPMSK);
+       dwc2_writel(dr->doepmsk, hsotg->regs + DOEPMSK);
 
        for (i = 0; i < hsotg->num_of_eps; i++) {
                /* Restore IN EPs */
-               writel(dr->diepctl[i], hsotg->regs + DIEPCTL(i));
-               writel(dr->dieptsiz[i], hsotg->regs + DIEPTSIZ(i));
-               writel(dr->diepdma[i], hsotg->regs + DIEPDMA(i));
+               dwc2_writel(dr->diepctl[i], hsotg->regs + DIEPCTL(i));
+               dwc2_writel(dr->dieptsiz[i], hsotg->regs + DIEPTSIZ(i));
+               dwc2_writel(dr->diepdma[i], hsotg->regs + DIEPDMA(i));
 
                /* Restore OUT EPs */
-               writel(dr->doepctl[i], hsotg->regs + DOEPCTL(i));
-               writel(dr->doeptsiz[i], hsotg->regs + DOEPTSIZ(i));
-               writel(dr->doepdma[i], hsotg->regs + DOEPDMA(i));
+               dwc2_writel(dr->doepctl[i], hsotg->regs + DOEPCTL(i));
+               dwc2_writel(dr->doeptsiz[i], hsotg->regs + DOEPTSIZ(i));
+               dwc2_writel(dr->doepdma[i], hsotg->regs + DOEPDMA(i));
        }
 
        /* Set the Power-On Programming done bit */
-       dctl = readl(hsotg->regs + DCTL);
+       dctl = dwc2_readl(hsotg->regs + DCTL);
        dctl |= DCTL_PWRONPRGDONE;
-       writel(dctl, hsotg->regs + DCTL);
+       dwc2_writel(dctl, hsotg->regs + DCTL);
 
        return 0;
 }
@@ -253,16 +254,16 @@ static int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg)
        /* Backup global regs */
        gr = &hsotg->gr_backup;
 
-       gr->gotgctl = readl(hsotg->regs + GOTGCTL);
-       gr->gintmsk = readl(hsotg->regs + GINTMSK);
-       gr->gahbcfg = readl(hsotg->regs + GAHBCFG);
-       gr->gusbcfg = readl(hsotg->regs + GUSBCFG);
-       gr->grxfsiz = readl(hsotg->regs + GRXFSIZ);
-       gr->gnptxfsiz = readl(hsotg->regs + GNPTXFSIZ);
-       gr->hptxfsiz = readl(hsotg->regs + HPTXFSIZ);
-       gr->gdfifocfg = readl(hsotg->regs + GDFIFOCFG);
+       gr->gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
+       gr->gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
+       gr->gahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
+       gr->gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
+       gr->grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ);
+       gr->gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ);
+       gr->hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ);
+       gr->gdfifocfg = dwc2_readl(hsotg->regs + GDFIFOCFG);
        for (i = 0; i < MAX_EPS_CHANNELS; i++)
-               gr->dtxfsiz[i] = readl(hsotg->regs + DPTXFSIZN(i));
+               gr->dtxfsiz[i] = dwc2_readl(hsotg->regs + DPTXFSIZN(i));
 
        gr->valid = true;
        return 0;
@@ -291,17 +292,17 @@ static int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg)
        }
        gr->valid = false;
 
-       writel(0xffffffff, hsotg->regs + GINTSTS);
-       writel(gr->gotgctl, hsotg->regs + GOTGCTL);
-       writel(gr->gintmsk, hsotg->regs + GINTMSK);
-       writel(gr->gusbcfg, hsotg->regs + GUSBCFG);
-       writel(gr->gahbcfg, hsotg->regs + GAHBCFG);
-       writel(gr->grxfsiz, hsotg->regs + GRXFSIZ);
-       writel(gr->gnptxfsiz, hsotg->regs + GNPTXFSIZ);
-       writel(gr->hptxfsiz, hsotg->regs + HPTXFSIZ);
-       writel(gr->gdfifocfg, hsotg->regs + GDFIFOCFG);
+       dwc2_writel(0xffffffff, hsotg->regs + GINTSTS);
+       dwc2_writel(gr->gotgctl, hsotg->regs + GOTGCTL);
+       dwc2_writel(gr->gintmsk, hsotg->regs + GINTMSK);
+       dwc2_writel(gr->gusbcfg, hsotg->regs + GUSBCFG);
+       dwc2_writel(gr->gahbcfg, hsotg->regs + GAHBCFG);
+       dwc2_writel(gr->grxfsiz, hsotg->regs + GRXFSIZ);
+       dwc2_writel(gr->gnptxfsiz, hsotg->regs + GNPTXFSIZ);
+       dwc2_writel(gr->hptxfsiz, hsotg->regs + HPTXFSIZ);
+       dwc2_writel(gr->gdfifocfg, hsotg->regs + GDFIFOCFG);
        for (i = 0; i < MAX_EPS_CHANNELS; i++)
-               writel(gr->dtxfsiz[i], hsotg->regs + DPTXFSIZN(i));
+               dwc2_writel(gr->dtxfsiz[i], hsotg->regs + DPTXFSIZN(i));
 
        return 0;
 }
@@ -320,17 +321,17 @@ int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore)
        if (!hsotg->core_params->hibernation)
                return -ENOTSUPP;
 
-       pcgcctl = readl(hsotg->regs + PCGCTL);
+       pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
        pcgcctl &= ~PCGCTL_STOPPCLK;
-       writel(pcgcctl, hsotg->regs + PCGCTL);
+       dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
 
-       pcgcctl = readl(hsotg->regs + PCGCTL);
+       pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
        pcgcctl &= ~PCGCTL_PWRCLMP;
-       writel(pcgcctl, hsotg->regs + PCGCTL);
+       dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
 
-       pcgcctl = readl(hsotg->regs + PCGCTL);
+       pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
        pcgcctl &= ~PCGCTL_RSTPDWNMODULE;
-       writel(pcgcctl, hsotg->regs + PCGCTL);
+       dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
 
        udelay(100);
        if (restore) {
@@ -397,19 +398,25 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg)
                }
        }
 
+       /*
+        * Clear any pending interrupts since dwc2 will not be able to
+        * clear them after entering hibernation.
+        */
+       dwc2_writel(0xffffffff, hsotg->regs + GINTSTS);
+
        /* Put the controller in low power state */
-       pcgcctl = readl(hsotg->regs + PCGCTL);
+       pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
 
        pcgcctl |= PCGCTL_PWRCLMP;
-       writel(pcgcctl, hsotg->regs + PCGCTL);
+       dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
        ndelay(20);
 
        pcgcctl |= PCGCTL_RSTPDWNMODULE;
-       writel(pcgcctl, hsotg->regs + PCGCTL);
+       dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
        ndelay(20);
 
        pcgcctl |= PCGCTL_STOPPCLK;
-       writel(pcgcctl, hsotg->regs + PCGCTL);
+       dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
 
        return ret;
 }
@@ -425,10 +432,10 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg)
        u32 intmsk;
 
        /* Clear any pending OTG Interrupts */
-       writel(0xffffffff, hsotg->regs + GOTGINT);
+       dwc2_writel(0xffffffff, hsotg->regs + GOTGINT);
 
        /* Clear any pending interrupts */
-       writel(0xffffffff, hsotg->regs + GINTSTS);
+       dwc2_writel(0xffffffff, hsotg->regs + GINTSTS);
 
        /* Enable the interrupts in the GINTMSK */
        intmsk = GINTSTS_MODEMIS | GINTSTS_OTGINT;
@@ -441,7 +448,7 @@ static void dwc2_enable_common_interrupts(struct dwc2_hsotg *hsotg)
        intmsk |= GINTSTS_WKUPINT | GINTSTS_USBSUSP |
                  GINTSTS_SESSREQINT;
 
-       writel(intmsk, hsotg->regs + GINTMSK);
+       dwc2_writel(intmsk, hsotg->regs + GINTMSK);
 }
 
 /*
@@ -464,10 +471,10 @@ static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg)
        }
 
        dev_dbg(hsotg->dev, "Initializing HCFG.FSLSPClkSel to %08x\n", val);
-       hcfg = readl(hsotg->regs + HCFG);
+       hcfg = dwc2_readl(hsotg->regs + HCFG);
        hcfg &= ~HCFG_FSLSPCLKSEL_MASK;
        hcfg |= val << HCFG_FSLSPCLKSEL_SHIFT;
-       writel(hcfg, hsotg->regs + HCFG);
+       dwc2_writel(hcfg, hsotg->regs + HCFG);
 }
 
 /*
@@ -485,7 +492,7 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg)
        /* Wait for AHB master IDLE state */
        do {
                usleep_range(20000, 40000);
-               greset = readl(hsotg->regs + GRSTCTL);
+               greset = dwc2_readl(hsotg->regs + GRSTCTL);
                if (++count > 50) {
                        dev_warn(hsotg->dev,
                                 "%s() HANG! AHB Idle GRSTCTL=%0x\n",
@@ -497,10 +504,10 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg)
        /* Core Soft Reset */
        count = 0;
        greset |= GRSTCTL_CSFTRST;
-       writel(greset, hsotg->regs + GRSTCTL);
+       dwc2_writel(greset, hsotg->regs + GRSTCTL);
        do {
                usleep_range(20000, 40000);
-               greset = readl(hsotg->regs + GRSTCTL);
+               greset = dwc2_readl(hsotg->regs + GRSTCTL);
                if (++count > 50) {
                        dev_warn(hsotg->dev,
                                 "%s() HANG! Soft Reset GRSTCTL=%0x\n",
@@ -510,20 +517,20 @@ static int dwc2_core_reset(struct dwc2_hsotg *hsotg)
        } while (greset & GRSTCTL_CSFTRST);
 
        if (hsotg->dr_mode == USB_DR_MODE_HOST) {
-               gusbcfg = readl(hsotg->regs + GUSBCFG);
+               gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
                gusbcfg &= ~GUSBCFG_FORCEDEVMODE;
                gusbcfg |= GUSBCFG_FORCEHOSTMODE;
-               writel(gusbcfg, hsotg->regs + GUSBCFG);
+               dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
        } else if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) {
-               gusbcfg = readl(hsotg->regs + GUSBCFG);
+               gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
                gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
                gusbcfg |= GUSBCFG_FORCEDEVMODE;
-               writel(gusbcfg, hsotg->regs + GUSBCFG);
+               dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
        } else if (hsotg->dr_mode == USB_DR_MODE_OTG) {
-               gusbcfg = readl(hsotg->regs + GUSBCFG);
+               gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
                gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
                gusbcfg &= ~GUSBCFG_FORCEDEVMODE;
-               writel(gusbcfg, hsotg->regs + GUSBCFG);
+               dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
        }
 
        /*
@@ -546,9 +553,9 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
         */
        if (select_phy) {
                dev_dbg(hsotg->dev, "FS PHY selected\n");
-               usbcfg = readl(hsotg->regs + GUSBCFG);
+               usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
                usbcfg |= GUSBCFG_PHYSEL;
-               writel(usbcfg, hsotg->regs + GUSBCFG);
+               dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
 
                /* Reset after a PHY select */
                retval = dwc2_core_reset(hsotg);
@@ -571,18 +578,18 @@ static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
                dev_dbg(hsotg->dev, "FS PHY enabling I2C\n");
 
                /* Program GUSBCFG.OtgUtmiFsSel to I2C */
-               usbcfg = readl(hsotg->regs + GUSBCFG);
+               usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
                usbcfg |= GUSBCFG_OTG_UTMI_FS_SEL;
-               writel(usbcfg, hsotg->regs + GUSBCFG);
+               dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
 
                /* Program GI2CCTL.I2CEn */
-               i2cctl = readl(hsotg->regs + GI2CCTL);
+               i2cctl = dwc2_readl(hsotg->regs + GI2CCTL);
                i2cctl &= ~GI2CCTL_I2CDEVADDR_MASK;
                i2cctl |= 1 << GI2CCTL_I2CDEVADDR_SHIFT;
                i2cctl &= ~GI2CCTL_I2CEN;
-               writel(i2cctl, hsotg->regs + GI2CCTL);
+               dwc2_writel(i2cctl, hsotg->regs + GI2CCTL);
                i2cctl |= GI2CCTL_I2CEN;
-               writel(i2cctl, hsotg->regs + GI2CCTL);
+               dwc2_writel(i2cctl, hsotg->regs + GI2CCTL);
        }
 
        return retval;
@@ -596,7 +603,7 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
        if (!select_phy)
                return 0;
 
-       usbcfg = readl(hsotg->regs + GUSBCFG);
+       usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
 
        /*
         * HS PHY parameters. These parameters are preserved during soft reset
@@ -624,7 +631,7 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
                break;
        }
 
-       writel(usbcfg, hsotg->regs + GUSBCFG);
+       dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
 
        /* Reset after setting the PHY parameters */
        retval = dwc2_core_reset(hsotg);
@@ -659,15 +666,15 @@ static int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
            hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED &&
            hsotg->core_params->ulpi_fs_ls > 0) {
                dev_dbg(hsotg->dev, "Setting ULPI FSLS\n");
-               usbcfg = readl(hsotg->regs + GUSBCFG);
+               usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
                usbcfg |= GUSBCFG_ULPI_FS_LS;
                usbcfg |= GUSBCFG_ULPI_CLK_SUSP_M;
-               writel(usbcfg, hsotg->regs + GUSBCFG);
+               dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
        } else {
-               usbcfg = readl(hsotg->regs + GUSBCFG);
+               usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
                usbcfg &= ~GUSBCFG_ULPI_FS_LS;
                usbcfg &= ~GUSBCFG_ULPI_CLK_SUSP_M;
-               writel(usbcfg, hsotg->regs + GUSBCFG);
+               dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
        }
 
        return retval;
@@ -675,7 +682,7 @@ static int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
 
 static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg)
 {
-       u32 ahbcfg = readl(hsotg->regs + GAHBCFG);
+       u32 ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
 
        switch (hsotg->hw_params.arch) {
        case GHWCFG2_EXT_DMA_ARCH:
@@ -714,7 +721,7 @@ static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg)
        if (hsotg->core_params->dma_enable > 0)
                ahbcfg |= GAHBCFG_DMA_EN;
 
-       writel(ahbcfg, hsotg->regs + GAHBCFG);
+       dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG);
 
        return 0;
 }
@@ -723,7 +730,7 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg)
 {
        u32 usbcfg;
 
-       usbcfg = readl(hsotg->regs + GUSBCFG);
+       usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
        usbcfg &= ~(GUSBCFG_HNPCAP | GUSBCFG_SRPCAP);
 
        switch (hsotg->hw_params.op_mode) {
@@ -751,7 +758,7 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg)
                break;
        }
 
-       writel(usbcfg, hsotg->regs + GUSBCFG);
+       dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
 }
 
 /**
@@ -769,7 +776,7 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq)
 
        dev_dbg(hsotg->dev, "%s(%p)\n", __func__, hsotg);
 
-       usbcfg = readl(hsotg->regs + GUSBCFG);
+       usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
 
        /* Set ULPI External VBUS bit if needed */
        usbcfg &= ~GUSBCFG_ULPI_EXT_VBUS_DRV;
@@ -782,7 +789,7 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq)
        if (hsotg->core_params->ts_dline > 0)
                usbcfg |= GUSBCFG_TERMSELDLPULSE;
 
-       writel(usbcfg, hsotg->regs + GUSBCFG);
+       dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
 
        /* Reset the Controller */
        retval = dwc2_core_reset(hsotg);
@@ -808,11 +815,11 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq)
        dwc2_gusbcfg_init(hsotg);
 
        /* Program the GOTGCTL register */
-       otgctl = readl(hsotg->regs + GOTGCTL);
+       otgctl = dwc2_readl(hsotg->regs + GOTGCTL);
        otgctl &= ~GOTGCTL_OTGVER;
        if (hsotg->core_params->otg_ver > 0)
                otgctl |= GOTGCTL_OTGVER;
-       writel(otgctl, hsotg->regs + GOTGCTL);
+       dwc2_writel(otgctl, hsotg->regs + GOTGCTL);
        dev_dbg(hsotg->dev, "OTG VER PARAM: %d\n", hsotg->core_params->otg_ver);
 
        /* Clear the SRP success bit for FS-I2c */
@@ -848,16 +855,16 @@ void dwc2_enable_host_interrupts(struct dwc2_hsotg *hsotg)
        dev_dbg(hsotg->dev, "%s()\n", __func__);
 
        /* Disable all interrupts */
-       writel(0, hsotg->regs + GINTMSK);
-       writel(0, hsotg->regs + HAINTMSK);
+       dwc2_writel(0, hsotg->regs + GINTMSK);
+       dwc2_writel(0, hsotg->regs + HAINTMSK);
 
        /* Enable the common interrupts */
        dwc2_enable_common_interrupts(hsotg);
 
        /* Enable host mode interrupts without disturbing common interrupts */
-       intmsk = readl(hsotg->regs + GINTMSK);
+       intmsk = dwc2_readl(hsotg->regs + GINTMSK);
        intmsk |= GINTSTS_DISCONNINT | GINTSTS_PRTINT | GINTSTS_HCHINT;
-       writel(intmsk, hsotg->regs + GINTMSK);
+       dwc2_writel(intmsk, hsotg->regs + GINTMSK);
 }
 
 /**
@@ -867,12 +874,12 @@ void dwc2_enable_host_interrupts(struct dwc2_hsotg *hsotg)
  */
 void dwc2_disable_host_interrupts(struct dwc2_hsotg *hsotg)
 {
-       u32 intmsk = readl(hsotg->regs + GINTMSK);
+       u32 intmsk = dwc2_readl(hsotg->regs + GINTMSK);
 
        /* Disable host mode interrupts without disturbing common interrupts */
        intmsk &= ~(GINTSTS_SOF | GINTSTS_PRTINT | GINTSTS_HCHINT |
-                   GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP);
-       writel(intmsk, hsotg->regs + GINTMSK);
+                   GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP | GINTSTS_DISCONNINT);
+       dwc2_writel(intmsk, hsotg->regs + GINTMSK);
 }
 
 /*
@@ -952,36 +959,37 @@ static void dwc2_config_fifos(struct dwc2_hsotg *hsotg)
        dwc2_calculate_dynamic_fifo(hsotg);
 
        /* Rx FIFO */
-       grxfsiz = readl(hsotg->regs + GRXFSIZ);
+       grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ);
        dev_dbg(hsotg->dev, "initial grxfsiz=%08x\n", grxfsiz);
        grxfsiz &= ~GRXFSIZ_DEPTH_MASK;
        grxfsiz |= params->host_rx_fifo_size <<
                   GRXFSIZ_DEPTH_SHIFT & GRXFSIZ_DEPTH_MASK;
-       writel(grxfsiz, hsotg->regs + GRXFSIZ);
-       dev_dbg(hsotg->dev, "new grxfsiz=%08x\n", readl(hsotg->regs + GRXFSIZ));
+       dwc2_writel(grxfsiz, hsotg->regs + GRXFSIZ);
+       dev_dbg(hsotg->dev, "new grxfsiz=%08x\n",
+               dwc2_readl(hsotg->regs + GRXFSIZ));
 
        /* Non-periodic Tx FIFO */
        dev_dbg(hsotg->dev, "initial gnptxfsiz=%08x\n",
-               readl(hsotg->regs + GNPTXFSIZ));
+               dwc2_readl(hsotg->regs + GNPTXFSIZ));
        nptxfsiz = params->host_nperio_tx_fifo_size <<
                   FIFOSIZE_DEPTH_SHIFT & FIFOSIZE_DEPTH_MASK;
        nptxfsiz |= params->host_rx_fifo_size <<
                    FIFOSIZE_STARTADDR_SHIFT & FIFOSIZE_STARTADDR_MASK;
-       writel(nptxfsiz, hsotg->regs + GNPTXFSIZ);
+       dwc2_writel(nptxfsiz, hsotg->regs + GNPTXFSIZ);
        dev_dbg(hsotg->dev, "new gnptxfsiz=%08x\n",
-               readl(hsotg->regs + GNPTXFSIZ));
+               dwc2_readl(hsotg->regs + GNPTXFSIZ));
 
        /* Periodic Tx FIFO */
        dev_dbg(hsotg->dev, "initial hptxfsiz=%08x\n",
-               readl(hsotg->regs + HPTXFSIZ));
+               dwc2_readl(hsotg->regs + HPTXFSIZ));
        hptxfsiz = params->host_perio_tx_fifo_size <<
                   FIFOSIZE_DEPTH_SHIFT & FIFOSIZE_DEPTH_MASK;
        hptxfsiz |= (params->host_rx_fifo_size +
                     params->host_nperio_tx_fifo_size) <<
                    FIFOSIZE_STARTADDR_SHIFT & FIFOSIZE_STARTADDR_MASK;
-       writel(hptxfsiz, hsotg->regs + HPTXFSIZ);
+       dwc2_writel(hptxfsiz, hsotg->regs + HPTXFSIZ);
        dev_dbg(hsotg->dev, "new hptxfsiz=%08x\n",
-               readl(hsotg->regs + HPTXFSIZ));
+               dwc2_readl(hsotg->regs + HPTXFSIZ));
 
        if (hsotg->core_params->en_multiple_tx_fifo > 0 &&
            hsotg->hw_params.snpsid <= DWC2_CORE_REV_2_94a) {
@@ -989,14 +997,14 @@ static void dwc2_config_fifos(struct dwc2_hsotg *hsotg)
                 * Global DFIFOCFG calculation for Host mode -
                 * include RxFIFO, NPTXFIFO and HPTXFIFO
                 */
-               dfifocfg = readl(hsotg->regs + GDFIFOCFG);
+               dfifocfg = dwc2_readl(hsotg->regs + GDFIFOCFG);
                dfifocfg &= ~GDFIFOCFG_EPINFOBASE_MASK;
                dfifocfg |= (params->host_rx_fifo_size +
                             params->host_nperio_tx_fifo_size +
                             params->host_perio_tx_fifo_size) <<
                            GDFIFOCFG_EPINFOBASE_SHIFT &
                            GDFIFOCFG_EPINFOBASE_MASK;
-               writel(dfifocfg, hsotg->regs + GDFIFOCFG);
+               dwc2_writel(dfifocfg, hsotg->regs + GDFIFOCFG);
        }
 }
 
@@ -1017,14 +1025,14 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
        dev_dbg(hsotg->dev, "%s(%p)\n", __func__, hsotg);
 
        /* Restart the Phy Clock */
-       writel(0, hsotg->regs + PCGCTL);
+       dwc2_writel(0, hsotg->regs + PCGCTL);
 
        /* Initialize Host Configuration Register */
        dwc2_init_fs_ls_pclk_sel(hsotg);
        if (hsotg->core_params->speed == DWC2_SPEED_PARAM_FULL) {
-               hcfg = readl(hsotg->regs + HCFG);
+               hcfg = dwc2_readl(hsotg->regs + HCFG);
                hcfg |= HCFG_FSLSSUPP;
-               writel(hcfg, hsotg->regs + HCFG);
+               dwc2_writel(hcfg, hsotg->regs + HCFG);
        }
 
        /*
@@ -1033,9 +1041,9 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
         * and its value must not be changed during runtime.
         */
        if (hsotg->core_params->reload_ctl > 0) {
-               hfir = readl(hsotg->regs + HFIR);
+               hfir = dwc2_readl(hsotg->regs + HFIR);
                hfir |= HFIR_RLDCTRL;
-               writel(hfir, hsotg->regs + HFIR);
+               dwc2_writel(hfir, hsotg->regs + HFIR);
        }
 
        if (hsotg->core_params->dma_desc_enable > 0) {
@@ -1051,9 +1059,9 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
                                "falling back to buffer DMA mode.\n");
                        hsotg->core_params->dma_desc_enable = 0;
                } else {
-                       hcfg = readl(hsotg->regs + HCFG);
+                       hcfg = dwc2_readl(hsotg->regs + HCFG);
                        hcfg |= HCFG_DESCDMA;
-                       writel(hcfg, hsotg->regs + HCFG);
+                       dwc2_writel(hcfg, hsotg->regs + HCFG);
                }
        }
 
@@ -1062,18 +1070,18 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
 
        /* TODO - check this */
        /* Clear Host Set HNP Enable in the OTG Control Register */
-       otgctl = readl(hsotg->regs + GOTGCTL);
+       otgctl = dwc2_readl(hsotg->regs + GOTGCTL);
        otgctl &= ~GOTGCTL_HSTSETHNPEN;
-       writel(otgctl, hsotg->regs + GOTGCTL);
+       dwc2_writel(otgctl, hsotg->regs + GOTGCTL);
 
        /* Make sure the FIFOs are flushed */
        dwc2_flush_tx_fifo(hsotg, 0x10 /* all TX FIFOs */);
        dwc2_flush_rx_fifo(hsotg);
 
        /* Clear Host Set HNP Enable in the OTG Control Register */
-       otgctl = readl(hsotg->regs + GOTGCTL);
+       otgctl = dwc2_readl(hsotg->regs + GOTGCTL);
        otgctl &= ~GOTGCTL_HSTSETHNPEN;
-       writel(otgctl, hsotg->regs + GOTGCTL);
+       dwc2_writel(otgctl, hsotg->regs + GOTGCTL);
 
        if (hsotg->core_params->dma_desc_enable <= 0) {
                int num_channels, i;
@@ -1082,25 +1090,25 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
                /* Flush out any leftover queued requests */
                num_channels = hsotg->core_params->host_channels;
                for (i = 0; i < num_channels; i++) {
-                       hcchar = readl(hsotg->regs + HCCHAR(i));
+                       hcchar = dwc2_readl(hsotg->regs + HCCHAR(i));
                        hcchar &= ~HCCHAR_CHENA;
                        hcchar |= HCCHAR_CHDIS;
                        hcchar &= ~HCCHAR_EPDIR;
-                       writel(hcchar, hsotg->regs + HCCHAR(i));
+                       dwc2_writel(hcchar, hsotg->regs + HCCHAR(i));
                }
 
                /* Halt all channels to put them into a known state */
                for (i = 0; i < num_channels; i++) {
                        int count = 0;
 
-                       hcchar = readl(hsotg->regs + HCCHAR(i));
+                       hcchar = dwc2_readl(hsotg->regs + HCCHAR(i));
                        hcchar |= HCCHAR_CHENA | HCCHAR_CHDIS;
                        hcchar &= ~HCCHAR_EPDIR;
-                       writel(hcchar, hsotg->regs + HCCHAR(i));
+                       dwc2_writel(hcchar, hsotg->regs + HCCHAR(i));
                        dev_dbg(hsotg->dev, "%s: Halt channel %d\n",
                                __func__, i);
                        do {
-                               hcchar = readl(hsotg->regs + HCCHAR(i));
+                               hcchar = dwc2_readl(hsotg->regs + HCCHAR(i));
                                if (++count > 1000) {
                                        dev_err(hsotg->dev,
                                                "Unable to clear enable on channel %d\n",
@@ -1121,7 +1129,7 @@ void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
                        !!(hprt0 & HPRT0_PWR));
                if (!(hprt0 & HPRT0_PWR)) {
                        hprt0 |= HPRT0_PWR;
-                       writel(hprt0, hsotg->regs + HPRT0);
+                       dwc2_writel(hprt0, hsotg->regs + HPRT0);
                }
        }
 
@@ -1201,7 +1209,7 @@ static void dwc2_hc_enable_slave_ints(struct dwc2_hsotg *hsotg,
                break;
        }
 
-       writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num));
+       dwc2_writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num));
        if (dbg_hc(chan))
                dev_vdbg(hsotg->dev, "set HCINTMSK to %08x\n", hcintmsk);
 }
@@ -1238,7 +1246,7 @@ static void dwc2_hc_enable_dma_ints(struct dwc2_hsotg *hsotg,
                }
        }
 
-       writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num));
+       dwc2_writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num));
        if (dbg_hc(chan))
                dev_vdbg(hsotg->dev, "set HCINTMSK to %08x\n", hcintmsk);
 }
@@ -1259,16 +1267,16 @@ static void dwc2_hc_enable_ints(struct dwc2_hsotg *hsotg,
        }
 
        /* Enable the top level host channel interrupt */
-       intmsk = readl(hsotg->regs + HAINTMSK);
+       intmsk = dwc2_readl(hsotg->regs + HAINTMSK);
        intmsk |= 1 << chan->hc_num;
-       writel(intmsk, hsotg->regs + HAINTMSK);
+       dwc2_writel(intmsk, hsotg->regs + HAINTMSK);
        if (dbg_hc(chan))
                dev_vdbg(hsotg->dev, "set HAINTMSK to %08x\n", intmsk);
 
        /* Make sure host channel interrupts are enabled */
-       intmsk = readl(hsotg->regs + GINTMSK);
+       intmsk = dwc2_readl(hsotg->regs + GINTMSK);
        intmsk |= GINTSTS_HCHINT;
-       writel(intmsk, hsotg->regs + GINTMSK);
+       dwc2_writel(intmsk, hsotg->regs + GINTMSK);
        if (dbg_hc(chan))
                dev_vdbg(hsotg->dev, "set GINTMSK to %08x\n", intmsk);
 }
@@ -1297,7 +1305,7 @@ void dwc2_hc_init(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan)
        /* Clear old interrupt conditions for this host channel */
        hcintmsk = 0xffffffff;
        hcintmsk &= ~HCINTMSK_RESERVED14_31;
-       writel(hcintmsk, hsotg->regs + HCINT(hc_num));
+       dwc2_writel(hcintmsk, hsotg->regs + HCINT(hc_num));
 
        /* Enable channel interrupts required for this transfer */
        dwc2_hc_enable_ints(hsotg, chan);
@@ -1314,7 +1322,7 @@ void dwc2_hc_init(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan)
                hcchar |= HCCHAR_LSPDDEV;
        hcchar |= chan->ep_type << HCCHAR_EPTYPE_SHIFT & HCCHAR_EPTYPE_MASK;
        hcchar |= chan->max_packet << HCCHAR_MPS_SHIFT & HCCHAR_MPS_MASK;
-       writel(hcchar, hsotg->regs + HCCHAR(hc_num));
+       dwc2_writel(hcchar, hsotg->regs + HCCHAR(hc_num));
        if (dbg_hc(chan)) {
                dev_vdbg(hsotg->dev, "set HCCHAR(%d) to %08x\n",
                         hc_num, hcchar);
@@ -1368,7 +1376,7 @@ void dwc2_hc_init(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan)
                }
        }
 
-       writel(hcsplt, hsotg->regs + HCSPLT(hc_num));
+       dwc2_writel(hcsplt, hsotg->regs + HCSPLT(hc_num));
 }
 
 /**
@@ -1420,14 +1428,14 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
                u32 hcintmsk = HCINTMSK_CHHLTD;
 
                dev_vdbg(hsotg->dev, "dequeue/error\n");
-               writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num));
+               dwc2_writel(hcintmsk, hsotg->regs + HCINTMSK(chan->hc_num));
 
                /*
                 * Make sure no other interrupts besides halt are currently
                 * pending. Handling another interrupt could cause a crash due
                 * to the QTD and QH state.
                 */
-               writel(~hcintmsk, hsotg->regs + HCINT(chan->hc_num));
+               dwc2_writel(~hcintmsk, hsotg->regs + HCINT(chan->hc_num));
 
                /*
                 * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR
@@ -1436,7 +1444,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
                 */
                chan->halt_status = halt_status;
 
-               hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+               hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num));
                if (!(hcchar & HCCHAR_CHENA)) {
                        /*
                         * The channel is either already halted or it hasn't
@@ -1464,7 +1472,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
                return;
        }
 
-       hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+       hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num));
 
        /* No need to set the bit in DDMA for disabling the channel */
        /* TODO check it everywhere channel is disabled */
@@ -1487,7 +1495,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
                if (chan->ep_type == USB_ENDPOINT_XFER_CONTROL ||
                    chan->ep_type == USB_ENDPOINT_XFER_BULK) {
                        dev_vdbg(hsotg->dev, "control/bulk\n");
-                       nptxsts = readl(hsotg->regs + GNPTXSTS);
+                       nptxsts = dwc2_readl(hsotg->regs + GNPTXSTS);
                        if ((nptxsts & TXSTS_QSPCAVAIL_MASK) == 0) {
                                dev_vdbg(hsotg->dev, "Disabling channel\n");
                                hcchar &= ~HCCHAR_CHENA;
@@ -1495,7 +1503,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
                } else {
                        if (dbg_perio())
                                dev_vdbg(hsotg->dev, "isoc/intr\n");
-                       hptxsts = readl(hsotg->regs + HPTXSTS);
+                       hptxsts = dwc2_readl(hsotg->regs + HPTXSTS);
                        if ((hptxsts & TXSTS_QSPCAVAIL_MASK) == 0 ||
                            hsotg->queuing_high_bandwidth) {
                                if (dbg_perio())
@@ -1508,7 +1516,7 @@ void dwc2_hc_halt(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan,
                        dev_vdbg(hsotg->dev, "DMA enabled\n");
        }
 
-       writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
+       dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
        chan->halt_status = halt_status;
 
        if (hcchar & HCCHAR_CHENA) {
@@ -1555,10 +1563,10 @@ void dwc2_hc_cleanup(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan)
         * Clear channel interrupt enables and any unhandled channel interrupt
         * conditions
         */
-       writel(0, hsotg->regs + HCINTMSK(chan->hc_num));
+       dwc2_writel(0, hsotg->regs + HCINTMSK(chan->hc_num));
        hcintmsk = 0xffffffff;
        hcintmsk &= ~HCINTMSK_RESERVED14_31;
-       writel(hcintmsk, hsotg->regs + HCINT(chan->hc_num));
+       dwc2_writel(hcintmsk, hsotg->regs + HCINT(chan->hc_num));
 }
 
 /**
@@ -1644,13 +1652,13 @@ static void dwc2_hc_write_packet(struct dwc2_hsotg *hsotg,
        if (((unsigned long)data_buf & 0x3) == 0) {
                /* xfer_buf is DWORD aligned */
                for (i = 0; i < dword_count; i++, data_buf++)
-                       writel(*data_buf, data_fifo);
+                       dwc2_writel(*data_buf, data_fifo);
        } else {
                /* xfer_buf is not DWORD aligned */
                for (i = 0; i < dword_count; i++, data_buf++) {
                        u32 data = data_buf[0] | data_buf[1] << 8 |
                                   data_buf[2] << 16 | data_buf[3] << 24;
-                       writel(data, data_fifo);
+                       dwc2_writel(data, data_fifo);
                }
        }
 
@@ -1803,7 +1811,7 @@ void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
        hctsiz |= num_packets << TSIZ_PKTCNT_SHIFT & TSIZ_PKTCNT_MASK;
        hctsiz |= chan->data_pid_start << TSIZ_SC_MC_PID_SHIFT &
                  TSIZ_SC_MC_PID_MASK;
-       writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num));
+       dwc2_writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num));
        if (dbg_hc(chan)) {
                dev_vdbg(hsotg->dev, "Wrote %08x to HCTSIZ(%d)\n",
                         hctsiz, chan->hc_num);
@@ -1831,7 +1839,7 @@ void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
                } else {
                        dma_addr = chan->xfer_dma;
                }
-               writel((u32)dma_addr, hsotg->regs + HCDMA(chan->hc_num));
+               dwc2_writel((u32)dma_addr, hsotg->regs + HCDMA(chan->hc_num));
                if (dbg_hc(chan))
                        dev_vdbg(hsotg->dev, "Wrote %08lx to HCDMA(%d)\n",
                                 (unsigned long)dma_addr, chan->hc_num);
@@ -1839,13 +1847,13 @@ void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
 
        /* Start the split */
        if (chan->do_split) {
-               u32 hcsplt = readl(hsotg->regs + HCSPLT(chan->hc_num));
+               u32 hcsplt = dwc2_readl(hsotg->regs + HCSPLT(chan->hc_num));
 
                hcsplt |= HCSPLT_SPLTENA;
-               writel(hcsplt, hsotg->regs + HCSPLT(chan->hc_num));
+               dwc2_writel(hcsplt, hsotg->regs + HCSPLT(chan->hc_num));
        }
 
-       hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+       hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num));
        hcchar &= ~HCCHAR_MULTICNT_MASK;
        hcchar |= chan->multi_count << HCCHAR_MULTICNT_SHIFT &
                  HCCHAR_MULTICNT_MASK;
@@ -1865,7 +1873,7 @@ void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg,
                         (hcchar & HCCHAR_MULTICNT_MASK) >>
                         HCCHAR_MULTICNT_SHIFT);
 
-       writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
+       dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
        if (dbg_hc(chan))
                dev_vdbg(hsotg->dev, "Wrote %08x to HCCHAR(%d)\n", hcchar,
                         chan->hc_num);
@@ -1924,18 +1932,18 @@ void dwc2_hc_start_transfer_ddma(struct dwc2_hsotg *hsotg,
                dev_vdbg(hsotg->dev, "   NTD: %d\n", chan->ntd - 1);
        }
 
-       writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num));
+       dwc2_writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num));
 
        hc_dma = (u32)chan->desc_list_addr & HCDMA_DMA_ADDR_MASK;
 
        /* Always start from first descriptor */
        hc_dma &= ~HCDMA_CTD_MASK;
-       writel(hc_dma, hsotg->regs + HCDMA(chan->hc_num));
+       dwc2_writel(hc_dma, hsotg->regs + HCDMA(chan->hc_num));
        if (dbg_hc(chan))
                dev_vdbg(hsotg->dev, "Wrote %08x to HCDMA(%d)\n",
                         hc_dma, chan->hc_num);
 
-       hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+       hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num));
        hcchar &= ~HCCHAR_MULTICNT_MASK;
        hcchar |= chan->multi_count << HCCHAR_MULTICNT_SHIFT &
                  HCCHAR_MULTICNT_MASK;
@@ -1954,7 +1962,7 @@ void dwc2_hc_start_transfer_ddma(struct dwc2_hsotg *hsotg,
                         (hcchar & HCCHAR_MULTICNT_MASK) >>
                         HCCHAR_MULTICNT_SHIFT);
 
-       writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
+       dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
        if (dbg_hc(chan))
                dev_vdbg(hsotg->dev, "Wrote %08x to HCCHAR(%d)\n", hcchar,
                         chan->hc_num);
@@ -2011,7 +2019,7 @@ int dwc2_hc_continue_transfer(struct dwc2_hsotg *hsotg,
                 * transfer completes, the extra requests for the channel will
                 * be flushed.
                 */
-               u32 hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+               u32 hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num));
 
                dwc2_hc_set_even_odd_frame(hsotg, chan, &hcchar);
                hcchar |= HCCHAR_CHENA;
@@ -2019,7 +2027,7 @@ int dwc2_hc_continue_transfer(struct dwc2_hsotg *hsotg,
                if (dbg_hc(chan))
                        dev_vdbg(hsotg->dev, "   IN xfer: hcchar = 0x%08x\n",
                                 hcchar);
-               writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
+               dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
                chan->requests++;
                return 1;
        }
@@ -2029,8 +2037,8 @@ int dwc2_hc_continue_transfer(struct dwc2_hsotg *hsotg,
        if (chan->xfer_count < chan->xfer_len) {
                if (chan->ep_type == USB_ENDPOINT_XFER_INT ||
                    chan->ep_type == USB_ENDPOINT_XFER_ISOC) {
-                       u32 hcchar = readl(hsotg->regs +
-                                          HCCHAR(chan->hc_num));
+                       u32 hcchar = dwc2_readl(hsotg->regs +
+                                               HCCHAR(chan->hc_num));
 
                        dwc2_hc_set_even_odd_frame(hsotg, chan,
                                                   &hcchar);
@@ -2066,12 +2074,12 @@ void dwc2_hc_do_ping(struct dwc2_hsotg *hsotg, struct dwc2_host_chan *chan)
 
        hctsiz = TSIZ_DOPNG;
        hctsiz |= 1 << TSIZ_PKTCNT_SHIFT;
-       writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num));
+       dwc2_writel(hctsiz, hsotg->regs + HCTSIZ(chan->hc_num));
 
-       hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
+       hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num));
        hcchar |= HCCHAR_CHENA;
        hcchar &= ~HCCHAR_CHDIS;
-       writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
+       dwc2_writel(hcchar, hsotg->regs + HCCHAR(chan->hc_num));
 }
 
 /**
@@ -2090,8 +2098,8 @@ u32 dwc2_calc_frame_interval(struct dwc2_hsotg *hsotg)
        u32 hprt0;
        int clock = 60; /* default value */
 
-       usbcfg = readl(hsotg->regs + GUSBCFG);
-       hprt0 = readl(hsotg->regs + HPRT0);
+       usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
+       hprt0 = dwc2_readl(hsotg->regs + HPRT0);
 
        if (!(usbcfg & GUSBCFG_PHYSEL) && (usbcfg & GUSBCFG_ULPI_UTMI_SEL) &&
            !(usbcfg & GUSBCFG_PHYIF16))
@@ -2147,7 +2155,7 @@ void dwc2_read_packet(struct dwc2_hsotg *hsotg, u8 *dest, u16 bytes)
        dev_vdbg(hsotg->dev, "%s(%p,%p,%d)\n", __func__, hsotg, dest, bytes);
 
        for (i = 0; i < word_count; i++, data_buf++)
-               *data_buf = readl(fifo);
+               *data_buf = dwc2_readl(fifo);
 }
 
 /**
@@ -2167,56 +2175,56 @@ void dwc2_dump_host_registers(struct dwc2_hsotg *hsotg)
        dev_dbg(hsotg->dev, "Host Global Registers\n");
        addr = hsotg->regs + HCFG;
        dev_dbg(hsotg->dev, "HCFG        @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + HFIR;
        dev_dbg(hsotg->dev, "HFIR        @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + HFNUM;
        dev_dbg(hsotg->dev, "HFNUM       @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + HPTXSTS;
        dev_dbg(hsotg->dev, "HPTXSTS     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + HAINT;
        dev_dbg(hsotg->dev, "HAINT       @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + HAINTMSK;
        dev_dbg(hsotg->dev, "HAINTMSK    @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        if (hsotg->core_params->dma_desc_enable > 0) {
                addr = hsotg->regs + HFLBADDR;
                dev_dbg(hsotg->dev, "HFLBADDR @0x%08lX : 0x%08X\n",
-                       (unsigned long)addr, readl(addr));
+                       (unsigned long)addr, dwc2_readl(addr));
        }
 
        addr = hsotg->regs + HPRT0;
        dev_dbg(hsotg->dev, "HPRT0       @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
 
        for (i = 0; i < hsotg->core_params->host_channels; i++) {
                dev_dbg(hsotg->dev, "Host Channel %d Specific Registers\n", i);
                addr = hsotg->regs + HCCHAR(i);
                dev_dbg(hsotg->dev, "HCCHAR      @0x%08lX : 0x%08X\n",
-                       (unsigned long)addr, readl(addr));
+                       (unsigned long)addr, dwc2_readl(addr));
                addr = hsotg->regs + HCSPLT(i);
                dev_dbg(hsotg->dev, "HCSPLT      @0x%08lX : 0x%08X\n",
-                       (unsigned long)addr, readl(addr));
+                       (unsigned long)addr, dwc2_readl(addr));
                addr = hsotg->regs + HCINT(i);
                dev_dbg(hsotg->dev, "HCINT       @0x%08lX : 0x%08X\n",
-                       (unsigned long)addr, readl(addr));
+                       (unsigned long)addr, dwc2_readl(addr));
                addr = hsotg->regs + HCINTMSK(i);
                dev_dbg(hsotg->dev, "HCINTMSK    @0x%08lX : 0x%08X\n",
-                       (unsigned long)addr, readl(addr));
+                       (unsigned long)addr, dwc2_readl(addr));
                addr = hsotg->regs + HCTSIZ(i);
                dev_dbg(hsotg->dev, "HCTSIZ      @0x%08lX : 0x%08X\n",
-                       (unsigned long)addr, readl(addr));
+                       (unsigned long)addr, dwc2_readl(addr));
                addr = hsotg->regs + HCDMA(i);
                dev_dbg(hsotg->dev, "HCDMA       @0x%08lX : 0x%08X\n",
-                       (unsigned long)addr, readl(addr));
+                       (unsigned long)addr, dwc2_readl(addr));
                if (hsotg->core_params->dma_desc_enable > 0) {
                        addr = hsotg->regs + HCDMAB(i);
                        dev_dbg(hsotg->dev, "HCDMAB      @0x%08lX : 0x%08X\n",
-                               (unsigned long)addr, readl(addr));
+                               (unsigned long)addr, dwc2_readl(addr));
                }
        }
 #endif
@@ -2238,80 +2246,80 @@ void dwc2_dump_global_registers(struct dwc2_hsotg *hsotg)
        dev_dbg(hsotg->dev, "Core Global Registers\n");
        addr = hsotg->regs + GOTGCTL;
        dev_dbg(hsotg->dev, "GOTGCTL     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GOTGINT;
        dev_dbg(hsotg->dev, "GOTGINT     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GAHBCFG;
        dev_dbg(hsotg->dev, "GAHBCFG     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GUSBCFG;
        dev_dbg(hsotg->dev, "GUSBCFG     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GRSTCTL;
        dev_dbg(hsotg->dev, "GRSTCTL     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GINTSTS;
        dev_dbg(hsotg->dev, "GINTSTS     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GINTMSK;
        dev_dbg(hsotg->dev, "GINTMSK     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GRXSTSR;
        dev_dbg(hsotg->dev, "GRXSTSR     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GRXFSIZ;
        dev_dbg(hsotg->dev, "GRXFSIZ     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GNPTXFSIZ;
        dev_dbg(hsotg->dev, "GNPTXFSIZ   @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GNPTXSTS;
        dev_dbg(hsotg->dev, "GNPTXSTS    @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GI2CCTL;
        dev_dbg(hsotg->dev, "GI2CCTL     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GPVNDCTL;
        dev_dbg(hsotg->dev, "GPVNDCTL    @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GGPIO;
        dev_dbg(hsotg->dev, "GGPIO       @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GUID;
        dev_dbg(hsotg->dev, "GUID        @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GSNPSID;
        dev_dbg(hsotg->dev, "GSNPSID     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GHWCFG1;
        dev_dbg(hsotg->dev, "GHWCFG1     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GHWCFG2;
        dev_dbg(hsotg->dev, "GHWCFG2     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GHWCFG3;
        dev_dbg(hsotg->dev, "GHWCFG3     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GHWCFG4;
        dev_dbg(hsotg->dev, "GHWCFG4     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GLPMCFG;
        dev_dbg(hsotg->dev, "GLPMCFG     @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GPWRDN;
        dev_dbg(hsotg->dev, "GPWRDN      @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + GDFIFOCFG;
        dev_dbg(hsotg->dev, "GDFIFOCFG   @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
        addr = hsotg->regs + HPTXFSIZ;
        dev_dbg(hsotg->dev, "HPTXFSIZ    @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
 
        addr = hsotg->regs + PCGCTL;
        dev_dbg(hsotg->dev, "PCGCTL      @0x%08lX : 0x%08X\n",
-               (unsigned long)addr, readl(addr));
+               (unsigned long)addr, dwc2_readl(addr));
 #endif
 }
 
@@ -2330,15 +2338,15 @@ void dwc2_flush_tx_fifo(struct dwc2_hsotg *hsotg, const int num)
 
        greset = GRSTCTL_TXFFLSH;
        greset |= num << GRSTCTL_TXFNUM_SHIFT & GRSTCTL_TXFNUM_MASK;
-       writel(greset, hsotg->regs + GRSTCTL);
+       dwc2_writel(greset, hsotg->regs + GRSTCTL);
 
        do {
-               greset = readl(hsotg->regs + GRSTCTL);
+               greset = dwc2_readl(hsotg->regs + GRSTCTL);
                if (++count > 10000) {
                        dev_warn(hsotg->dev,
                                 "%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n",
                                 __func__, greset,
-                                readl(hsotg->regs + GNPTXSTS));
+                                dwc2_readl(hsotg->regs + GNPTXSTS));
                        break;
                }
                udelay(1);
@@ -2361,10 +2369,10 @@ void dwc2_flush_rx_fifo(struct dwc2_hsotg *hsotg)
        dev_vdbg(hsotg->dev, "%s()\n", __func__);
 
        greset = GRSTCTL_RXFFLSH;
-       writel(greset, hsotg->regs + GRSTCTL);
+       dwc2_writel(greset, hsotg->regs + GRSTCTL);
 
        do {
-               greset = readl(hsotg->regs + GRSTCTL);
+               greset = dwc2_readl(hsotg->regs + GRSTCTL);
                if (++count > 10000) {
                        dev_warn(hsotg->dev, "%s() HANG! GRSTCTL=%0x\n",
                                 __func__, greset);
@@ -3062,7 +3070,7 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
         * 0x45f42xxx or 0x45f43xxx, which corresponds to either "OT2" or "OT3",
         * as in "OTG version 2.xx" or "OTG version 3.xx".
         */
-       hw->snpsid = readl(hsotg->regs + GSNPSID);
+       hw->snpsid = dwc2_readl(hsotg->regs + GSNPSID);
        if ((hw->snpsid & 0xfffff000) != 0x4f542000 &&
            (hw->snpsid & 0xfffff000) != 0x4f543000) {
                dev_err(hsotg->dev, "Bad value for GSNPSID: 0x%08x\n",
@@ -3074,11 +3082,11 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
                hw->snpsid >> 12 & 0xf, hw->snpsid >> 8 & 0xf,
                hw->snpsid >> 4 & 0xf, hw->snpsid & 0xf, hw->snpsid);
 
-       hwcfg1 = readl(hsotg->regs + GHWCFG1);
-       hwcfg2 = readl(hsotg->regs + GHWCFG2);
-       hwcfg3 = readl(hsotg->regs + GHWCFG3);
-       hwcfg4 = readl(hsotg->regs + GHWCFG4);
-       grxfsiz = readl(hsotg->regs + GRXFSIZ);
+       hwcfg1 = dwc2_readl(hsotg->regs + GHWCFG1);
+       hwcfg2 = dwc2_readl(hsotg->regs + GHWCFG2);
+       hwcfg3 = dwc2_readl(hsotg->regs + GHWCFG3);
+       hwcfg4 = dwc2_readl(hsotg->regs + GHWCFG4);
+       grxfsiz = dwc2_readl(hsotg->regs + GRXFSIZ);
 
        dev_dbg(hsotg->dev, "hwcfg1=%08x\n", hwcfg1);
        dev_dbg(hsotg->dev, "hwcfg2=%08x\n", hwcfg2);
@@ -3087,18 +3095,18 @@ int dwc2_get_hwparams(struct dwc2_hsotg *hsotg)
        dev_dbg(hsotg->dev, "grxfsiz=%08x\n", grxfsiz);
 
        /* Force host mode to get HPTXFSIZ / GNPTXFSIZ exact power on value */
-       gusbcfg = readl(hsotg->regs + GUSBCFG);
+       gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
        gusbcfg |= GUSBCFG_FORCEHOSTMODE;
-       writel(gusbcfg, hsotg->regs + GUSBCFG);
+       dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
        usleep_range(100000, 150000);
 
-       gnptxfsiz = readl(hsotg->regs + GNPTXFSIZ);
-       hptxfsiz = readl(hsotg->regs + HPTXFSIZ);
+       gnptxfsiz = dwc2_readl(hsotg->regs + GNPTXFSIZ);
+       hptxfsiz = dwc2_readl(hsotg->regs + HPTXFSIZ);
        dev_dbg(hsotg->dev, "gnptxfsiz=%08x\n", gnptxfsiz);
        dev_dbg(hsotg->dev, "hptxfsiz=%08x\n", hptxfsiz);
-       gusbcfg = readl(hsotg->regs + GUSBCFG);
+       gusbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
        gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
-       writel(gusbcfg, hsotg->regs + GUSBCFG);
+       dwc2_writel(gusbcfg, hsotg->regs + GUSBCFG);
        usleep_range(100000, 150000);
 
        /* hwcfg2 */
@@ -3233,7 +3241,7 @@ u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg)
 
 bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg)
 {
-       if (readl(hsotg->regs + GSNPSID) == 0xffffffff)
+       if (dwc2_readl(hsotg->regs + GSNPSID) == 0xffffffff)
                return false;
        else
                return true;
@@ -3247,10 +3255,10 @@ bool dwc2_is_controller_alive(struct dwc2_hsotg *hsotg)
  */
 void dwc2_enable_global_interrupts(struct dwc2_hsotg *hsotg)
 {
-       u32 ahbcfg = readl(hsotg->regs + GAHBCFG);
+       u32 ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
 
        ahbcfg |= GAHBCFG_GLBL_INTR_EN;
-       writel(ahbcfg, hsotg->regs + GAHBCFG);
+       dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG);
 }
 
 /**
@@ -3261,10 +3269,10 @@ void dwc2_enable_global_interrupts(struct dwc2_hsotg *hsotg)
  */
 void dwc2_disable_global_interrupts(struct dwc2_hsotg *hsotg)
 {
-       u32 ahbcfg = readl(hsotg->regs + GAHBCFG);
+       u32 ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
 
        ahbcfg &= ~GAHBCFG_GLBL_INTR_EN;
-       writel(ahbcfg, hsotg->regs + GAHBCFG);
+       dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG);
 }
 
 MODULE_DESCRIPTION("DESIGNWARE HS OTG Core");
index 0ed87620941b5606b83f7e628439266ca7831e18..a66d3cb62b65980fe670bc51bb5f4401a58d9df3 100644 (file)
 #include <linux/usb/phy.h>
 #include "hw.h"
 
-#ifdef DWC2_LOG_WRITES
-static inline void do_write(u32 value, void *addr)
+static inline u32 dwc2_readl(const void __iomem *addr)
 {
-       writel(value, addr);
-       pr_info("INFO:: wrote %08x to %p\n", value, addr);
+       u32 value = __raw_readl(addr);
+
+       /* In order to preserve endianness __raw_* operation is used. Therefore
+        * a barrier is needed to ensure IO access is not re-ordered across
+        * reads or writes
+        */
+       mb();
+       return value;
 }
 
-#undef writel
-#define writel(v, a)   do_write(v, a)
+static inline void dwc2_writel(u32 value, void __iomem *addr)
+{
+       __raw_writel(value, addr);
+
+       /*
+        * In order to preserve endianness __raw_* operation is used. Therefore
+        * a barrier is needed to ensure IO access is not re-ordered across
+        * reads or writes
+        */
+       mb();
+#ifdef DWC2_LOG_WRITES
+       pr_info("INFO:: wrote %08x to %p\n", value, addr);
 #endif
+}
 
 /* Maximum number of Endpoints/HostChannels */
 #define MAX_EPS_CHANNELS       16
 
-/* s3c-hsotg declarations */
-static const char * const s3c_hsotg_supply_names[] = {
+/* dwc2-hsotg declarations */
+static const char * const dwc2_hsotg_supply_names[] = {
        "vusb_d",               /* digital USB supply, 1.2V */
        "vusb_a",               /* analog USB supply, 1.1V */
 };
@@ -85,10 +101,10 @@ static const char * const s3c_hsotg_supply_names[] = {
 #define EP0_MPS_LIMIT   64
 
 struct dwc2_hsotg;
-struct s3c_hsotg_req;
+struct dwc2_hsotg_req;
 
 /**
- * struct s3c_hsotg_ep - driver endpoint definition.
+ * struct dwc2_hsotg_ep - driver endpoint definition.
  * @ep: The gadget layer representation of the endpoint.
  * @name: The driver generated name for the endpoint.
  * @queue: Queue of requests for this endpoint.
@@ -127,11 +143,11 @@ struct s3c_hsotg_req;
  * as in shared-fifo mode periodic in acts like a single-frame packet
  * buffer than a fifo)
  */
-struct s3c_hsotg_ep {
+struct dwc2_hsotg_ep {
        struct usb_ep           ep;
        struct list_head        queue;
        struct dwc2_hsotg       *parent;
-       struct s3c_hsotg_req    *req;
+       struct dwc2_hsotg_req    *req;
        struct dentry           *debugfs;
 
        unsigned long           total_data;
@@ -150,17 +166,18 @@ struct s3c_hsotg_ep {
        unsigned int            periodic:1;
        unsigned int            isochronous:1;
        unsigned int            send_zlp:1;
+       unsigned int            has_correct_parity:1;
 
        char                    name[10];
 };
 
 /**
- * struct s3c_hsotg_req - data transfer request
+ * struct dwc2_hsotg_req - data transfer request
  * @req: The USB gadget request
  * @queue: The list of requests for the endpoint this is queued for.
  * @saved_req_buf: variable to save req.buf when bounce buffers are used.
  */
-struct s3c_hsotg_req {
+struct dwc2_hsotg_req {
        struct usb_request      req;
        struct list_head        queue;
        void *saved_req_buf;
@@ -562,6 +579,15 @@ struct dwc2_hregs_backup {
  *                      - USB_DR_MODE_PERIPHERAL
  *                      - USB_DR_MODE_HOST
  *                      - USB_DR_MODE_OTG
+ * @hcd_enabled                Host mode sub-driver initialization indicator.
+ * @gadget_enabled     Peripheral mode sub-driver initialization indicator.
+ * @ll_hw_enabled      Status of low-level hardware resources.
+ * @phy:                The otg phy transceiver structure for phy control.
+ * @uphy:               The otg phy transceiver structure for old USB phy control.
+ * @plat:               The platform specific configuration data. This can be removed once
+ *                      all SoCs support usb transceiver.
+ * @supplies:           Definition of USB power supplies
+ * @phyif:              PHY interface width
  * @lock:              Spinlock that protects all the driver data structures
  * @priv:              Stores a pointer to the struct usb_hcd
  * @queuing_high_bandwidth: True if multiple packets of a high-bandwidth
@@ -654,12 +680,6 @@ struct dwc2_hregs_backup {
  * These are for peripheral mode:
  *
  * @driver:             USB gadget driver
- * @phy:                The otg phy transceiver structure for phy control.
- * @uphy:               The otg phy transceiver structure for old USB phy control.
- * @plat:               The platform specific configuration data. This can be removed once
- *                      all SoCs support usb transceiver.
- * @supplies:           Definition of USB power supplies
- * @phyif:              PHY interface width
  * @dedicated_fifos:    Set if the hardware has dedicated IN-EP fifos.
  * @num_of_eps:         Number of available EPs (excluding EP0)
  * @debug_root:         Root directrory for debugfs.
@@ -672,7 +692,6 @@ struct dwc2_hregs_backup {
  * @ctrl_req:           Request for EP0 control packets.
  * @ep0_state:          EP0 control transfers state
  * @test_mode:          USB test mode requested by the host
- * @last_rst:           Time of last reset
  * @eps:                The endpoints being supplied to the gadget framework
  * @g_using_dma:          Indicate if dma usage is enabled
  * @g_rx_fifo_sz:         Contains rx fifo size value
@@ -690,13 +709,15 @@ struct dwc2_hsotg {
        enum usb_dr_mode dr_mode;
        unsigned int hcd_enabled:1;
        unsigned int gadget_enabled:1;
+       unsigned int ll_hw_enabled:1;
 
        struct phy *phy;
        struct usb_phy *uphy;
-       struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsotg_supply_names)];
+       struct dwc2_hsotg_plat *plat;
+       struct regulator_bulk_data supplies[ARRAY_SIZE(dwc2_hsotg_supply_names)];
+       u32 phyif;
 
        spinlock_t lock;
-       struct mutex init_mutex;
        void *priv;
        int     irq;
        struct clk *clk;
@@ -748,6 +769,7 @@ struct dwc2_hsotg {
        u16 frame_usecs[8];
        u16 frame_number;
        u16 periodic_qh_count;
+       bool bus_suspended;
 
 #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
 #define FRAME_NUM_ARRAY_SIZE 1000
@@ -796,9 +818,6 @@ struct dwc2_hsotg {
 #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
        /* Gadget structures */
        struct usb_gadget_driver *driver;
-       struct s3c_hsotg_plat *plat;
-
-       u32 phyif;
        int fifo_mem;
        unsigned int dedicated_fifos:1;
        unsigned char num_of_eps;
@@ -814,9 +833,8 @@ struct dwc2_hsotg {
        struct usb_gadget gadget;
        unsigned int enabled:1;
        unsigned int connected:1;
-       unsigned long last_rst;
-       struct s3c_hsotg_ep *eps_in[MAX_EPS_CHANNELS];
-       struct s3c_hsotg_ep *eps_out[MAX_EPS_CHANNELS];
+       struct dwc2_hsotg_ep *eps_in[MAX_EPS_CHANNELS];
+       struct dwc2_hsotg_ep *eps_out[MAX_EPS_CHANNELS];
        u32 g_using_dma;
        u32 g_rx_fifo_sz;
        u32 g_np_g_tx_fifo_sz;
@@ -1088,7 +1106,8 @@ extern void dwc2_set_all_params(struct dwc2_core_params *params, int value);
 
 extern int dwc2_get_hwparams(struct dwc2_hsotg *hsotg);
 
-
+extern int dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg);
+extern int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg);
 
 /*
  * Dump core registers and SPRAM
@@ -1104,30 +1123,30 @@ extern u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg);
 
 /* Gadget defines */
 #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
-extern int s3c_hsotg_remove(struct dwc2_hsotg *hsotg);
-extern int s3c_hsotg_suspend(struct dwc2_hsotg *dwc2);
-extern int s3c_hsotg_resume(struct dwc2_hsotg *dwc2);
+extern int dwc2_hsotg_remove(struct dwc2_hsotg *hsotg);
+extern int dwc2_hsotg_suspend(struct dwc2_hsotg *dwc2);
+extern int dwc2_hsotg_resume(struct dwc2_hsotg *dwc2);
 extern int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq);
-extern void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
+extern void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
                bool reset);
-extern void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg);
-extern void s3c_hsotg_disconnect(struct dwc2_hsotg *dwc2);
-extern int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode);
+extern void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg);
+extern void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2);
+extern int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode);
 #define dwc2_is_device_connected(hsotg) (hsotg->connected)
 #else
-static inline int s3c_hsotg_remove(struct dwc2_hsotg *dwc2)
+static inline int dwc2_hsotg_remove(struct dwc2_hsotg *dwc2)
 { return 0; }
-static inline int s3c_hsotg_suspend(struct dwc2_hsotg *dwc2)
+static inline int dwc2_hsotg_suspend(struct dwc2_hsotg *dwc2)
 { return 0; }
-static inline int s3c_hsotg_resume(struct dwc2_hsotg *dwc2)
+static inline int dwc2_hsotg_resume(struct dwc2_hsotg *dwc2)
 { return 0; }
 static inline int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
 { return 0; }
-static inline void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
+static inline void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
                bool reset) {}
-static inline void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg) {}
-static inline void s3c_hsotg_disconnect(struct dwc2_hsotg *dwc2) {}
-static inline int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg,
+static inline void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg) {}
+static inline void dwc2_hsotg_disconnect(struct dwc2_hsotg *dwc2) {}
+static inline int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg,
                                                        int testmode)
 { return 0; }
 #define dwc2_is_device_connected(hsotg) (0)
index 927be1e8b3dc93951cb78ac7665eb0aa0bedfcf8..27daa42788b1a4ab2ac74200d15d8b1a6f212f38 100644 (file)
@@ -80,15 +80,15 @@ static const char *dwc2_op_state_str(struct dwc2_hsotg *hsotg)
  */
 static void dwc2_handle_usb_port_intr(struct dwc2_hsotg *hsotg)
 {
-       u32 hprt0 = readl(hsotg->regs + HPRT0);
+       u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0);
 
        if (hprt0 & HPRT0_ENACHG) {
                hprt0 &= ~HPRT0_ENA;
-               writel(hprt0, hsotg->regs + HPRT0);
+               dwc2_writel(hprt0, hsotg->regs + HPRT0);
        }
 
        /* Clear interrupt */
-       writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);
+       dwc2_writel(GINTSTS_PRTINT, hsotg->regs + GINTSTS);
 }
 
 /**
@@ -102,7 +102,7 @@ static void dwc2_handle_mode_mismatch_intr(struct dwc2_hsotg *hsotg)
                 dwc2_is_host_mode(hsotg) ? "Host" : "Device");
 
        /* Clear interrupt */
-       writel(GINTSTS_MODEMIS, hsotg->regs + GINTSTS);
+       dwc2_writel(GINTSTS_MODEMIS, hsotg->regs + GINTSTS);
 }
 
 /**
@@ -117,8 +117,8 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
        u32 gotgctl;
        u32 gintmsk;
 
-       gotgint = readl(hsotg->regs + GOTGINT);
-       gotgctl = readl(hsotg->regs + GOTGCTL);
+       gotgint = dwc2_readl(hsotg->regs + GOTGINT);
+       gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
        dev_dbg(hsotg->dev, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint,
                dwc2_op_state_str(hsotg));
 
@@ -126,10 +126,10 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
                dev_dbg(hsotg->dev,
                        " ++OTG Interrupt: Session End Detected++ (%s)\n",
                        dwc2_op_state_str(hsotg));
-               gotgctl = readl(hsotg->regs + GOTGCTL);
+               gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
 
                if (dwc2_is_device_mode(hsotg))
-                       s3c_hsotg_disconnect(hsotg);
+                       dwc2_hsotg_disconnect(hsotg);
 
                if (hsotg->op_state == OTG_STATE_B_HOST) {
                        hsotg->op_state = OTG_STATE_B_PERIPHERAL;
@@ -152,15 +152,15 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
                        hsotg->lx_state = DWC2_L0;
                }
 
-               gotgctl = readl(hsotg->regs + GOTGCTL);
+               gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
                gotgctl &= ~GOTGCTL_DEVHNPEN;
-               writel(gotgctl, hsotg->regs + GOTGCTL);
+               dwc2_writel(gotgctl, hsotg->regs + GOTGCTL);
        }
 
        if (gotgint & GOTGINT_SES_REQ_SUC_STS_CHNG) {
                dev_dbg(hsotg->dev,
                        " ++OTG Interrupt: Session Request Success Status Change++\n");
-               gotgctl = readl(hsotg->regs + GOTGCTL);
+               gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
                if (gotgctl & GOTGCTL_SESREQSCS) {
                        if (hsotg->core_params->phy_type ==
                                        DWC2_PHY_TYPE_PARAM_FS
@@ -168,9 +168,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
                                hsotg->srp_success = 1;
                        } else {
                                /* Clear Session Request */
-                               gotgctl = readl(hsotg->regs + GOTGCTL);
+                               gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
                                gotgctl &= ~GOTGCTL_SESREQ;
-                               writel(gotgctl, hsotg->regs + GOTGCTL);
+                               dwc2_writel(gotgctl, hsotg->regs + GOTGCTL);
                        }
                }
        }
@@ -180,7 +180,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
                 * Print statements during the HNP interrupt handling
                 * can cause it to fail
                 */
-               gotgctl = readl(hsotg->regs + GOTGCTL);
+               gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
                /*
                 * WA for 3.00a- HW is not setting cur_mode, even sometimes
                 * this does not help
@@ -200,9 +200,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
                                 * interrupt does not get handled and Linux
                                 * complains loudly.
                                 */
-                               gintmsk = readl(hsotg->regs + GINTMSK);
+                               gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
                                gintmsk &= ~GINTSTS_SOF;
-                               writel(gintmsk, hsotg->regs + GINTMSK);
+                               dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
 
                                /*
                                 * Call callback function with spin lock
@@ -216,9 +216,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
                                hsotg->op_state = OTG_STATE_B_HOST;
                        }
                } else {
-                       gotgctl = readl(hsotg->regs + GOTGCTL);
+                       gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
                        gotgctl &= ~(GOTGCTL_HNPREQ | GOTGCTL_DEVHNPEN);
-                       writel(gotgctl, hsotg->regs + GOTGCTL);
+                       dwc2_writel(gotgctl, hsotg->regs + GOTGCTL);
                        dev_dbg(hsotg->dev, "HNP Failed\n");
                        dev_err(hsotg->dev,
                                "Device Not Connected/Responding\n");
@@ -244,9 +244,9 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
                        hsotg->op_state = OTG_STATE_A_PERIPHERAL;
                } else {
                        /* Need to disable SOF interrupt immediately */
-                       gintmsk = readl(hsotg->regs + GINTMSK);
+                       gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
                        gintmsk &= ~GINTSTS_SOF;
-                       writel(gintmsk, hsotg->regs + GINTMSK);
+                       dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
                        spin_unlock(&hsotg->lock);
                        dwc2_hcd_start(hsotg);
                        spin_lock(&hsotg->lock);
@@ -261,7 +261,7 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
                dev_dbg(hsotg->dev, " ++OTG Interrupt: Debounce Done++\n");
 
        /* Clear GOTGINT */
-       writel(gotgint, hsotg->regs + GOTGINT);
+       dwc2_writel(gotgint, hsotg->regs + GOTGINT);
 }
 
 /**
@@ -276,11 +276,11 @@ static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
  */
 static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
 {
-       u32 gintmsk = readl(hsotg->regs + GINTMSK);
+       u32 gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
 
        /* Need to disable SOF interrupt immediately */
        gintmsk &= ~GINTSTS_SOF;
-       writel(gintmsk, hsotg->regs + GINTMSK);
+       dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
 
        dev_dbg(hsotg->dev, " ++Connector ID Status Change Interrupt++  (%s)\n",
                dwc2_is_host_mode(hsotg) ? "Host" : "Device");
@@ -297,7 +297,7 @@ static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
        }
 
        /* Clear interrupt */
-       writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
+       dwc2_writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
 }
 
 /**
@@ -313,16 +313,28 @@ static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
  */
 static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
 {
-       dev_dbg(hsotg->dev, "++Session Request Interrupt++\n");
+       int ret;
+
+       dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n",
+                                                       hsotg->lx_state);
 
        /* Clear interrupt */
-       writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
+       dwc2_writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
 
-       /*
-        * Report disconnect if there is any previous session established
-        */
-       if (dwc2_is_device_mode(hsotg))
-               s3c_hsotg_disconnect(hsotg);
+       if (dwc2_is_device_mode(hsotg)) {
+               if (hsotg->lx_state == DWC2_L2) {
+                       ret = dwc2_exit_hibernation(hsotg, true);
+                       if (ret && (ret != -ENOTSUPP))
+                               dev_err(hsotg->dev,
+                                       "exit hibernation failed\n");
+               }
+
+               /*
+                * Report disconnect if there is any previous session
+                * established
+                */
+               dwc2_hsotg_disconnect(hsotg);
+       }
 }
 
 /*
@@ -339,13 +351,14 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
        dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state);
 
        if (dwc2_is_device_mode(hsotg)) {
-               dev_dbg(hsotg->dev, "DSTS=0x%0x\n", readl(hsotg->regs + DSTS));
+               dev_dbg(hsotg->dev, "DSTS=0x%0x\n",
+                       dwc2_readl(hsotg->regs + DSTS));
                if (hsotg->lx_state == DWC2_L2) {
-                       u32 dctl = readl(hsotg->regs + DCTL);
+                       u32 dctl = dwc2_readl(hsotg->regs + DCTL);
 
                        /* Clear Remote Wakeup Signaling */
                        dctl &= ~DCTL_RMTWKUPSIG;
-                       writel(dctl, hsotg->regs + DCTL);
+                       dwc2_writel(dctl, hsotg->regs + DCTL);
                        ret = dwc2_exit_hibernation(hsotg, true);
                        if (ret && (ret != -ENOTSUPP))
                                dev_err(hsotg->dev, "exit hibernation failed\n");
@@ -355,12 +368,16 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
                /* Change to L0 state */
                hsotg->lx_state = DWC2_L0;
        } else {
+               if (hsotg->core_params->hibernation) {
+                       dwc2_writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS);
+                       return;
+               }
                if (hsotg->lx_state != DWC2_L1) {
-                       u32 pcgcctl = readl(hsotg->regs + PCGCTL);
+                       u32 pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
 
                        /* Restart the Phy Clock */
                        pcgcctl &= ~PCGCTL_STOPPCLK;
-                       writel(pcgcctl, hsotg->regs + PCGCTL);
+                       dwc2_writel(pcgcctl, hsotg->regs + PCGCTL);
                        mod_timer(&hsotg->wkp_timer,
                                  jiffies + msecs_to_jiffies(71));
                } else {
@@ -370,7 +387,7 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
        }
 
        /* Clear interrupt */
-       writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS);
+       dwc2_writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS);
 }
 
 /*
@@ -386,10 +403,7 @@ static void dwc2_handle_disconnect_intr(struct dwc2_hsotg *hsotg)
        if (hsotg->op_state == OTG_STATE_A_HOST)
                dwc2_hcd_disconnect(hsotg);
 
-       /* Change to L3 (OFF) state */
-       hsotg->lx_state = DWC2_L3;
-
-       writel(GINTSTS_DISCONNINT, hsotg->regs + GINTSTS);
+       dwc2_writel(GINTSTS_DISCONNINT, hsotg->regs + GINTSTS);
 }
 
 /*
@@ -412,7 +426,7 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
                 * Check the Device status register to determine if the Suspend
                 * state is active
                 */
-               dsts = readl(hsotg->regs + DSTS);
+               dsts = dwc2_readl(hsotg->regs + DSTS);
                dev_dbg(hsotg->dev, "DSTS=0x%0x\n", dsts);
                dev_dbg(hsotg->dev,
                        "DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d\n",
@@ -465,7 +479,7 @@ skip_power_saving:
 
 clear_int:
        /* Clear interrupt */
-       writel(GINTSTS_USBSUSP, hsotg->regs + GINTSTS);
+       dwc2_writel(GINTSTS_USBSUSP, hsotg->regs + GINTSTS);
 }
 
 #define GINTMSK_COMMON (GINTSTS_WKUPINT | GINTSTS_SESSREQINT |         \
@@ -483,9 +497,9 @@ static u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg)
        u32 gahbcfg;
        u32 gintmsk_common = GINTMSK_COMMON;
 
-       gintsts = readl(hsotg->regs + GINTSTS);
-       gintmsk = readl(hsotg->regs + GINTMSK);
-       gahbcfg = readl(hsotg->regs + GAHBCFG);
+       gintsts = dwc2_readl(hsotg->regs + GINTSTS);
+       gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
+       gahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
 
        /* If any common interrupts set */
        if (gintsts & gintmsk_common)
index ef2ee3d9a25d2e37a47028f53793ef077b857015..55d91f24f94ab3aefd21c74626d7244fdccd7947 100644 (file)
@@ -57,7 +57,7 @@ static ssize_t testmode_write(struct file *file, const char __user *ubuf, size_t
                testmode = 0;
 
        spin_lock_irqsave(&hsotg->lock, flags);
-       s3c_hsotg_set_test_mode(hsotg, testmode);
+       dwc2_hsotg_set_test_mode(hsotg, testmode);
        spin_unlock_irqrestore(&hsotg->lock, flags);
        return count;
 }
@@ -76,7 +76,7 @@ static int testmode_show(struct seq_file *s, void *unused)
        int dctl;
 
        spin_lock_irqsave(&hsotg->lock, flags);
-       dctl = readl(hsotg->regs + DCTL);
+       dctl = dwc2_readl(hsotg->regs + DCTL);
        dctl &= DCTL_TSTCTL_MASK;
        dctl >>= DCTL_TSTCTL_SHIFT;
        spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -137,38 +137,38 @@ static int state_show(struct seq_file *seq, void *v)
        int idx;
 
        seq_printf(seq, "DCFG=0x%08x, DCTL=0x%08x, DSTS=0x%08x\n",
-                readl(regs + DCFG),
-                readl(regs + DCTL),
-                readl(regs + DSTS));
+                dwc2_readl(regs + DCFG),
+                dwc2_readl(regs + DCTL),
+                dwc2_readl(regs + DSTS));
 
        seq_printf(seq, "DIEPMSK=0x%08x, DOEPMASK=0x%08x\n",
-                  readl(regs + DIEPMSK), readl(regs + DOEPMSK));
+                  dwc2_readl(regs + DIEPMSK), dwc2_readl(regs + DOEPMSK));
 
        seq_printf(seq, "GINTMSK=0x%08x, GINTSTS=0x%08x\n",
-                  readl(regs + GINTMSK),
-                  readl(regs + GINTSTS));
+                  dwc2_readl(regs + GINTMSK),
+                  dwc2_readl(regs + GINTSTS));
 
        seq_printf(seq, "DAINTMSK=0x%08x, DAINT=0x%08x\n",
-                  readl(regs + DAINTMSK),
-                  readl(regs + DAINT));
+                  dwc2_readl(regs + DAINTMSK),
+                  dwc2_readl(regs + DAINT));
 
        seq_printf(seq, "GNPTXSTS=0x%08x, GRXSTSR=%08x\n",
-                  readl(regs + GNPTXSTS),
-                  readl(regs + GRXSTSR));
+                  dwc2_readl(regs + GNPTXSTS),
+                  dwc2_readl(regs + GRXSTSR));
 
        seq_puts(seq, "\nEndpoint status:\n");
 
        for (idx = 0; idx < hsotg->num_of_eps; idx++) {
                u32 in, out;
 
-               in = readl(regs + DIEPCTL(idx));
-               out = readl(regs + DOEPCTL(idx));
+               in = dwc2_readl(regs + DIEPCTL(idx));
+               out = dwc2_readl(regs + DOEPCTL(idx));
 
                seq_printf(seq, "ep%d: DIEPCTL=0x%08x, DOEPCTL=0x%08x",
                           idx, in, out);
 
-               in = readl(regs + DIEPTSIZ(idx));
-               out = readl(regs + DOEPTSIZ(idx));
+               in = dwc2_readl(regs + DIEPTSIZ(idx));
+               out = dwc2_readl(regs + DOEPTSIZ(idx));
 
                seq_printf(seq, ", DIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x",
                           in, out);
@@ -208,9 +208,9 @@ static int fifo_show(struct seq_file *seq, void *v)
        int idx;
 
        seq_puts(seq, "Non-periodic FIFOs:\n");
-       seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + GRXFSIZ));
+       seq_printf(seq, "RXFIFO: Size %d\n", dwc2_readl(regs + GRXFSIZ));
 
-       val = readl(regs + GNPTXFSIZ);
+       val = dwc2_readl(regs + GNPTXFSIZ);
        seq_printf(seq, "NPTXFIFO: Size %d, Start 0x%08x\n",
                   val >> FIFOSIZE_DEPTH_SHIFT,
                   val & FIFOSIZE_DEPTH_MASK);
@@ -218,7 +218,7 @@ static int fifo_show(struct seq_file *seq, void *v)
        seq_puts(seq, "\nPeriodic TXFIFOs:\n");
 
        for (idx = 1; idx < hsotg->num_of_eps; idx++) {
-               val = readl(regs + DPTXFSIZN(idx));
+               val = dwc2_readl(regs + DPTXFSIZN(idx));
 
                seq_printf(seq, "\tDPTXFIFO%2d: Size %d, Start 0x%08x\n", idx,
                           val >> FIFOSIZE_DEPTH_SHIFT,
@@ -256,9 +256,9 @@ static const char *decode_direction(int is_in)
  */
 static int ep_show(struct seq_file *seq, void *v)
 {
-       struct s3c_hsotg_ep *ep = seq->private;
+       struct dwc2_hsotg_ep *ep = seq->private;
        struct dwc2_hsotg *hsotg = ep->parent;
-       struct s3c_hsotg_req *req;
+       struct dwc2_hsotg_req *req;
        void __iomem *regs = hsotg->regs;
        int index = ep->index;
        int show_limit = 15;
@@ -270,20 +270,20 @@ static int ep_show(struct seq_file *seq, void *v)
        /* first show the register state */
 
        seq_printf(seq, "\tDIEPCTL=0x%08x, DOEPCTL=0x%08x\n",
-                  readl(regs + DIEPCTL(index)),
-                  readl(regs + DOEPCTL(index)));
+                  dwc2_readl(regs + DIEPCTL(index)),
+                  dwc2_readl(regs + DOEPCTL(index)));
 
        seq_printf(seq, "\tDIEPDMA=0x%08x, DOEPDMA=0x%08x\n",
-                  readl(regs + DIEPDMA(index)),
-                  readl(regs + DOEPDMA(index)));
+                  dwc2_readl(regs + DIEPDMA(index)),
+                  dwc2_readl(regs + DOEPDMA(index)));
 
        seq_printf(seq, "\tDIEPINT=0x%08x, DOEPINT=0x%08x\n",
-                  readl(regs + DIEPINT(index)),
-                  readl(regs + DOEPINT(index)));
+                  dwc2_readl(regs + DIEPINT(index)),
+                  dwc2_readl(regs + DOEPINT(index)));
 
        seq_printf(seq, "\tDIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x\n",
-                  readl(regs + DIEPTSIZ(index)),
-                  readl(regs + DOEPTSIZ(index)));
+                  dwc2_readl(regs + DIEPTSIZ(index)),
+                  dwc2_readl(regs + DOEPTSIZ(index)));
 
        seq_puts(seq, "\n");
        seq_printf(seq, "mps %d\n", ep->ep.maxpacket);
@@ -326,7 +326,7 @@ static const struct file_operations ep_fops = {
 };
 
 /**
- * s3c_hsotg_create_debug - create debugfs directory and files
+ * dwc2_hsotg_create_debug - create debugfs directory and files
  * @hsotg: The driver state
  *
  * Create the debugfs files to allow the user to get information
@@ -334,7 +334,7 @@ static const struct file_operations ep_fops = {
  * with the same name as the device itself, in case we end up
  * with multiple blocks in future systems.
  */
-static void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_create_debug(struct dwc2_hsotg *hsotg)
 {
        struct dentry *root;
        struct dentry *file;
@@ -360,7 +360,7 @@ static void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg)
 
        /* Create one file for each out endpoint */
        for (epidx = 0; epidx < hsotg->num_of_eps; epidx++) {
-               struct s3c_hsotg_ep *ep;
+               struct dwc2_hsotg_ep *ep;
 
                ep = hsotg->eps_out[epidx];
                if (ep) {
@@ -373,7 +373,7 @@ static void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg)
        }
        /* Create one file for each in endpoint. EP0 is handled with out eps */
        for (epidx = 1; epidx < hsotg->num_of_eps; epidx++) {
-               struct s3c_hsotg_ep *ep;
+               struct dwc2_hsotg_ep *ep;
 
                ep = hsotg->eps_in[epidx];
                if (ep) {
@@ -386,10 +386,10 @@ static void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg)
        }
 }
 #else
-static inline void s3c_hsotg_create_debug(struct dwc2_hsotg *hsotg) {}
+static inline void dwc2_hsotg_create_debug(struct dwc2_hsotg *hsotg) {}
 #endif
 
-/* s3c_hsotg_delete_debug is removed as cleanup in done in dwc2_debugfs_exit */
+/* dwc2_hsotg_delete_debug is removed as cleanup in done in dwc2_debugfs_exit */
 
 #define dump_register(nm)      \
 {                              \
@@ -737,7 +737,7 @@ int dwc2_debugfs_init(struct dwc2_hsotg *hsotg)
        }
 
        /* Add gadget debugfs nodes */
-       s3c_hsotg_create_debug(hsotg);
+       dwc2_hsotg_create_debug(hsotg);
 
        hsotg->regset = devm_kzalloc(hsotg->dev, sizeof(*hsotg->regset),
                                                                GFP_KERNEL);
index 3ee5b4c77a1f42eeecf1f222ab63e822b1530c9a..0abf73c91beb0f5eef5f25a4e46b7070ee03fdc2 100644 (file)
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/slab.h>
-#include <linux/clk.h>
-#include <linux/regulator/consumer.h>
 #include <linux/of_platform.h>
-#include <linux/phy/phy.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/usb/phy.h>
-#include <linux/platform_data/s3c-hsotg.h>
 
 #include "core.h"
 #include "hw.h"
 
 /* conversion functions */
-static inline struct s3c_hsotg_req *our_req(struct usb_request *req)
+static inline struct dwc2_hsotg_req *our_req(struct usb_request *req)
 {
-       return container_of(req, struct s3c_hsotg_req, req);
+       return container_of(req, struct dwc2_hsotg_req, req);
 }
 
-static inline struct s3c_hsotg_ep *our_ep(struct usb_ep *ep)
+static inline struct dwc2_hsotg_ep *our_ep(struct usb_ep *ep)
 {
-       return container_of(ep, struct s3c_hsotg_ep, ep);
+       return container_of(ep, struct dwc2_hsotg_ep, ep);
 }
 
 static inline struct dwc2_hsotg *to_hsotg(struct usb_gadget *gadget)
@@ -56,15 +52,15 @@ static inline struct dwc2_hsotg *to_hsotg(struct usb_gadget *gadget)
 
 static inline void __orr32(void __iomem *ptr, u32 val)
 {
-       writel(readl(ptr) | val, ptr);
+       dwc2_writel(dwc2_readl(ptr) | val, ptr);
 }
 
 static inline void __bic32(void __iomem *ptr, u32 val)
 {
-       writel(readl(ptr) & ~val, ptr);
+       dwc2_writel(dwc2_readl(ptr) & ~val, ptr);
 }
 
-static inline struct s3c_hsotg_ep *index_to_ep(struct dwc2_hsotg *hsotg,
+static inline struct dwc2_hsotg_ep *index_to_ep(struct dwc2_hsotg *hsotg,
                                                u32 ep_index, u32 dir_in)
 {
        if (dir_in)
@@ -74,7 +70,7 @@ static inline struct s3c_hsotg_ep *index_to_ep(struct dwc2_hsotg *hsotg,
 }
 
 /* forward declaration of functions */
-static void s3c_hsotg_dump(struct dwc2_hsotg *hsotg);
+static void dwc2_hsotg_dump(struct dwc2_hsotg *hsotg);
 
 /**
  * using_dma - return the DMA status of the driver.
@@ -101,41 +97,41 @@ static inline bool using_dma(struct dwc2_hsotg *hsotg)
 }
 
 /**
- * s3c_hsotg_en_gsint - enable one or more of the general interrupt
+ * dwc2_hsotg_en_gsint - enable one or more of the general interrupt
  * @hsotg: The device state
  * @ints: A bitmask of the interrupts to enable
  */
-static void s3c_hsotg_en_gsint(struct dwc2_hsotg *hsotg, u32 ints)
+static void dwc2_hsotg_en_gsint(struct dwc2_hsotg *hsotg, u32 ints)
 {
-       u32 gsintmsk = readl(hsotg->regs + GINTMSK);
+       u32 gsintmsk = dwc2_readl(hsotg->regs + GINTMSK);
        u32 new_gsintmsk;
 
        new_gsintmsk = gsintmsk | ints;
 
        if (new_gsintmsk != gsintmsk) {
                dev_dbg(hsotg->dev, "gsintmsk now 0x%08x\n", new_gsintmsk);
-               writel(new_gsintmsk, hsotg->regs + GINTMSK);
+               dwc2_writel(new_gsintmsk, hsotg->regs + GINTMSK);
        }
 }
 
 /**
- * s3c_hsotg_disable_gsint - disable one or more of the general interrupt
+ * dwc2_hsotg_disable_gsint - disable one or more of the general interrupt
  * @hsotg: The device state
  * @ints: A bitmask of the interrupts to enable
  */
-static void s3c_hsotg_disable_gsint(struct dwc2_hsotg *hsotg, u32 ints)
+static void dwc2_hsotg_disable_gsint(struct dwc2_hsotg *hsotg, u32 ints)
 {
-       u32 gsintmsk = readl(hsotg->regs + GINTMSK);
+       u32 gsintmsk = dwc2_readl(hsotg->regs + GINTMSK);
        u32 new_gsintmsk;
 
        new_gsintmsk = gsintmsk & ~ints;
 
        if (new_gsintmsk != gsintmsk)
-               writel(new_gsintmsk, hsotg->regs + GINTMSK);
+               dwc2_writel(new_gsintmsk, hsotg->regs + GINTMSK);
 }
 
 /**
- * s3c_hsotg_ctrl_epint - enable/disable an endpoint irq
+ * dwc2_hsotg_ctrl_epint - enable/disable an endpoint irq
  * @hsotg: The device state
  * @ep: The endpoint index
  * @dir_in: True if direction is in.
@@ -144,7 +140,7 @@ static void s3c_hsotg_disable_gsint(struct dwc2_hsotg *hsotg, u32 ints)
  * Set or clear the mask for an individual endpoint's interrupt
  * request.
  */
-static void s3c_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg,
+static void dwc2_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg,
                                 unsigned int ep, unsigned int dir_in,
                                 unsigned int en)
 {
@@ -156,20 +152,20 @@ static void s3c_hsotg_ctrl_epint(struct dwc2_hsotg *hsotg,
                bit <<= 16;
 
        local_irq_save(flags);
-       daint = readl(hsotg->regs + DAINTMSK);
+       daint = dwc2_readl(hsotg->regs + DAINTMSK);
        if (en)
                daint |= bit;
        else
                daint &= ~bit;
-       writel(daint, hsotg->regs + DAINTMSK);
+       dwc2_writel(daint, hsotg->regs + DAINTMSK);
        local_irq_restore(flags);
 }
 
 /**
- * s3c_hsotg_init_fifo - initialise non-periodic FIFOs
+ * dwc2_hsotg_init_fifo - initialise non-periodic FIFOs
  * @hsotg: The device instance.
  */
-static void s3c_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
 {
        unsigned int ep;
        unsigned int addr;
@@ -181,8 +177,8 @@ static void s3c_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
        hsotg->fifo_map = 0;
 
        /* set RX/NPTX FIFO sizes */
-       writel(hsotg->g_rx_fifo_sz, hsotg->regs + GRXFSIZ);
-       writel((hsotg->g_rx_fifo_sz << FIFOSIZE_STARTADDR_SHIFT) |
+       dwc2_writel(hsotg->g_rx_fifo_sz, hsotg->regs + GRXFSIZ);
+       dwc2_writel((hsotg->g_rx_fifo_sz << FIFOSIZE_STARTADDR_SHIFT) |
                (hsotg->g_np_g_tx_fifo_sz << FIFOSIZE_DEPTH_SHIFT),
                hsotg->regs + GNPTXFSIZ);
 
@@ -210,7 +206,7 @@ static void s3c_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
                          "insufficient fifo memory");
                addr += hsotg->g_tx_fifo_sz[ep];
 
-               writel(val, hsotg->regs + DPTXFSIZN(ep));
+               dwc2_writel(val, hsotg->regs + DPTXFSIZN(ep));
        }
 
        /*
@@ -218,13 +214,13 @@ static void s3c_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
         * all fifos are flushed before continuing
         */
 
-       writel(GRSTCTL_TXFNUM(0x10) | GRSTCTL_TXFFLSH |
+       dwc2_writel(GRSTCTL_TXFNUM(0x10) | GRSTCTL_TXFFLSH |
               GRSTCTL_RXFFLSH, hsotg->regs + GRSTCTL);
 
        /* wait until the fifos are both flushed */
        timeout = 100;
        while (1) {
-               val = readl(hsotg->regs + GRSTCTL);
+               val = dwc2_readl(hsotg->regs + GRSTCTL);
 
                if ((val & (GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH)) == 0)
                        break;
@@ -248,12 +244,12 @@ static void s3c_hsotg_init_fifo(struct dwc2_hsotg *hsotg)
  *
  * Allocate a new USB request structure appropriate for the specified endpoint
  */
-static struct usb_request *s3c_hsotg_ep_alloc_request(struct usb_ep *ep,
+static struct usb_request *dwc2_hsotg_ep_alloc_request(struct usb_ep *ep,
                                                      gfp_t flags)
 {
-       struct s3c_hsotg_req *req;
+       struct dwc2_hsotg_req *req;
 
-       req = kzalloc(sizeof(struct s3c_hsotg_req), flags);
+       req = kzalloc(sizeof(struct dwc2_hsotg_req), flags);
        if (!req)
                return NULL;
 
@@ -269,23 +265,23 @@ static struct usb_request *s3c_hsotg_ep_alloc_request(struct usb_ep *ep,
  * Returns true if the endpoint is in periodic mode, meaning it is being
  * used for an Interrupt or ISO transfer.
  */
-static inline int is_ep_periodic(struct s3c_hsotg_ep *hs_ep)
+static inline int is_ep_periodic(struct dwc2_hsotg_ep *hs_ep)
 {
        return hs_ep->periodic;
 }
 
 /**
- * s3c_hsotg_unmap_dma - unmap the DMA memory being used for the request
+ * dwc2_hsotg_unmap_dma - unmap the DMA memory being used for the request
  * @hsotg: The device state.
  * @hs_ep: The endpoint for the request
  * @hs_req: The request being processed.
  *
- * This is the reverse of s3c_hsotg_map_dma(), called for the completion
+ * This is the reverse of dwc2_hsotg_map_dma(), called for the completion
  * of a request to ensure the buffer is ready for access by the caller.
  */
-static void s3c_hsotg_unmap_dma(struct dwc2_hsotg *hsotg,
-                               struct s3c_hsotg_ep *hs_ep,
-                               struct s3c_hsotg_req *hs_req)
+static void dwc2_hsotg_unmap_dma(struct dwc2_hsotg *hsotg,
+                               struct dwc2_hsotg_ep *hs_ep,
+                               struct dwc2_hsotg_req *hs_req)
 {
        struct usb_request *req = &hs_req->req;
 
@@ -297,7 +293,7 @@ static void s3c_hsotg_unmap_dma(struct dwc2_hsotg *hsotg,
 }
 
 /**
- * s3c_hsotg_write_fifo - write packet Data to the TxFIFO
+ * dwc2_hsotg_write_fifo - write packet Data to the TxFIFO
  * @hsotg: The controller state.
  * @hs_ep: The endpoint we're going to write for.
  * @hs_req: The request to write data for.
@@ -312,12 +308,12 @@ static void s3c_hsotg_unmap_dma(struct dwc2_hsotg *hsotg,
  *
  * This routine is only needed for PIO
  */
-static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
-                               struct s3c_hsotg_ep *hs_ep,
-                               struct s3c_hsotg_req *hs_req)
+static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
+                               struct dwc2_hsotg_ep *hs_ep,
+                               struct dwc2_hsotg_req *hs_req)
 {
        bool periodic = is_ep_periodic(hs_ep);
-       u32 gnptxsts = readl(hsotg->regs + GNPTXSTS);
+       u32 gnptxsts = dwc2_readl(hsotg->regs + GNPTXSTS);
        int buf_pos = hs_req->req.actual;
        int to_write = hs_ep->size_loaded;
        void *data;
@@ -332,7 +328,7 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
                return 0;
 
        if (periodic && !hsotg->dedicated_fifos) {
-               u32 epsize = readl(hsotg->regs + DIEPTSIZ(hs_ep->index));
+               u32 epsize = dwc2_readl(hsotg->regs + DIEPTSIZ(hs_ep->index));
                int size_left;
                int size_done;
 
@@ -348,7 +344,7 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
                 * previous data has been completely sent.
                 */
                if (hs_ep->fifo_load != 0) {
-                       s3c_hsotg_en_gsint(hsotg, GINTSTS_PTXFEMP);
+                       dwc2_hsotg_en_gsint(hsotg, GINTSTS_PTXFEMP);
                        return -ENOSPC;
                }
 
@@ -369,11 +365,11 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
                        __func__, can_write);
 
                if (can_write <= 0) {
-                       s3c_hsotg_en_gsint(hsotg, GINTSTS_PTXFEMP);
+                       dwc2_hsotg_en_gsint(hsotg, GINTSTS_PTXFEMP);
                        return -ENOSPC;
                }
        } else if (hsotg->dedicated_fifos && hs_ep->index != 0) {
-               can_write = readl(hsotg->regs + DTXFSTS(hs_ep->index));
+               can_write = dwc2_readl(hsotg->regs + DTXFSTS(hs_ep->index));
 
                can_write &= 0xffff;
                can_write *= 4;
@@ -383,7 +379,7 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
                                "%s: no queue slots available (0x%08x)\n",
                                __func__, gnptxsts);
 
-                       s3c_hsotg_en_gsint(hsotg, GINTSTS_NPTXFEMP);
+                       dwc2_hsotg_en_gsint(hsotg, GINTSTS_NPTXFEMP);
                        return -ENOSPC;
                }
 
@@ -414,7 +410,7 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
 
                /* it's needed only when we do not use dedicated fifos */
                if (!hsotg->dedicated_fifos)
-                       s3c_hsotg_en_gsint(hsotg,
+                       dwc2_hsotg_en_gsint(hsotg,
                                           periodic ? GINTSTS_PTXFEMP :
                                           GINTSTS_NPTXFEMP);
        }
@@ -443,7 +439,7 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
 
                /* it's needed only when we do not use dedicated fifos */
                if (!hsotg->dedicated_fifos)
-                       s3c_hsotg_en_gsint(hsotg,
+                       dwc2_hsotg_en_gsint(hsotg,
                                           periodic ? GINTSTS_PTXFEMP :
                                           GINTSTS_NPTXFEMP);
        }
@@ -475,7 +471,7 @@ static int s3c_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
  * Return the maximum data that can be queued in one go on a given endpoint
  * so that transfers that are too long can be split.
  */
-static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep)
+static unsigned get_ep_limit(struct dwc2_hsotg_ep *hs_ep)
 {
        int index = hs_ep->index;
        unsigned maxsize;
@@ -508,7 +504,7 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep)
 }
 
 /**
- * s3c_hsotg_start_req - start a USB request from an endpoint's queue
+ * dwc2_hsotg_start_req - start a USB request from an endpoint's queue
  * @hsotg: The controller state.
  * @hs_ep: The endpoint to process a request for
  * @hs_req: The request to start.
@@ -517,9 +513,9 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep)
  * Start the given request running by setting the endpoint registers
  * appropriately, and writing any data to the FIFOs.
  */
-static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg,
-                               struct s3c_hsotg_ep *hs_ep,
-                               struct s3c_hsotg_req *hs_req,
+static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
+                               struct dwc2_hsotg_ep *hs_ep,
+                               struct dwc2_hsotg_req *hs_req,
                                bool continuing)
 {
        struct usb_request *ureq = &hs_req->req;
@@ -550,13 +546,13 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg,
        epsize_reg = dir_in ? DIEPTSIZ(index) : DOEPTSIZ(index);
 
        dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x, ep %d, dir %s\n",
-               __func__, readl(hsotg->regs + epctrl_reg), index,
+               __func__, dwc2_readl(hsotg->regs + epctrl_reg), index,
                hs_ep->dir_in ? "in" : "out");
 
        /* If endpoint is stalled, we will restart request later */
-       ctrl = readl(hsotg->regs + epctrl_reg);
+       ctrl = dwc2_readl(hsotg->regs + epctrl_reg);
 
-       if (ctrl & DXEPCTL_STALL) {
+       if (index && ctrl & DXEPCTL_STALL) {
                dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index);
                return;
        }
@@ -618,18 +614,18 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg,
        hs_ep->req = hs_req;
 
        /* write size / packets */
-       writel(epsize, hsotg->regs + epsize_reg);
+       dwc2_writel(epsize, hsotg->regs + epsize_reg);
 
        if (using_dma(hsotg) && !continuing) {
                unsigned int dma_reg;
 
                /*
                 * write DMA address to control register, buffer already
-                * synced by s3c_hsotg_ep_queue().
+                * synced by dwc2_hsotg_ep_queue().
                 */
 
                dma_reg = dir_in ? DIEPDMA(index) : DOEPDMA(index);
-               writel(ureq->dma, hsotg->regs + dma_reg);
+               dwc2_writel(ureq->dma, hsotg->regs + dma_reg);
 
                dev_dbg(hsotg->dev, "%s: %pad => 0x%08x\n",
                        __func__, &ureq->dma, dma_reg);
@@ -645,7 +641,7 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg,
                ctrl |= DXEPCTL_CNAK;   /* clear NAK set by core */
 
        dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl);
-       writel(ctrl, hsotg->regs + epctrl_reg);
+       dwc2_writel(ctrl, hsotg->regs + epctrl_reg);
 
        /*
         * set these, it seems that DMA support increments past the end
@@ -659,7 +655,7 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg,
                /* set these anyway, we may need them for non-periodic in */
                hs_ep->fifo_load = 0;
 
-               s3c_hsotg_write_fifo(hsotg, hs_ep, hs_req);
+               dwc2_hsotg_write_fifo(hsotg, hs_ep, hs_req);
        }
 
        /*
@@ -667,7 +663,7 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg,
         * to debugging to see what is going on.
         */
        if (dir_in)
-               writel(DIEPMSK_INTKNTXFEMPMSK,
+               dwc2_writel(DIEPMSK_INTKNTXFEMPMSK,
                       hsotg->regs + DIEPINT(index));
 
        /*
@@ -676,20 +672,20 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg,
         */
 
        /* check ep is enabled */
-       if (!(readl(hsotg->regs + epctrl_reg) & DXEPCTL_EPENA))
+       if (!(dwc2_readl(hsotg->regs + epctrl_reg) & DXEPCTL_EPENA))
                dev_dbg(hsotg->dev,
                         "ep%d: failed to become enabled (DXEPCTL=0x%08x)?\n",
-                        index, readl(hsotg->regs + epctrl_reg));
+                        index, dwc2_readl(hsotg->regs + epctrl_reg));
 
        dev_dbg(hsotg->dev, "%s: DXEPCTL=0x%08x\n",
-               __func__, readl(hsotg->regs + epctrl_reg));
+               __func__, dwc2_readl(hsotg->regs + epctrl_reg));
 
        /* enable ep interrupts */
-       s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 1);
+       dwc2_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 1);
 }
 
 /**
- * s3c_hsotg_map_dma - map the DMA memory being used for the request
+ * dwc2_hsotg_map_dma - map the DMA memory being used for the request
  * @hsotg: The device state.
  * @hs_ep: The endpoint the request is on.
  * @req: The request being processed.
@@ -700,11 +696,11 @@ static void s3c_hsotg_start_req(struct dwc2_hsotg *hsotg,
  * DMA memory, then we map the memory and mark our request to allow us to
  * cleanup on completion.
  */
-static int s3c_hsotg_map_dma(struct dwc2_hsotg *hsotg,
-                            struct s3c_hsotg_ep *hs_ep,
+static int dwc2_hsotg_map_dma(struct dwc2_hsotg *hsotg,
+                            struct dwc2_hsotg_ep *hs_ep,
                             struct usb_request *req)
 {
-       struct s3c_hsotg_req *hs_req = our_req(req);
+       struct dwc2_hsotg_req *hs_req = our_req(req);
        int ret;
 
        /* if the length is zero, ignore the DMA data */
@@ -724,8 +720,8 @@ dma_error:
        return -EIO;
 }
 
-static int s3c_hsotg_handle_unaligned_buf_start(struct dwc2_hsotg *hsotg,
-       struct s3c_hsotg_ep *hs_ep, struct s3c_hsotg_req *hs_req)
+static int dwc2_hsotg_handle_unaligned_buf_start(struct dwc2_hsotg *hsotg,
+       struct dwc2_hsotg_ep *hs_ep, struct dwc2_hsotg_req *hs_req)
 {
        void *req_buf = hs_req->req.buf;
 
@@ -755,8 +751,8 @@ static int s3c_hsotg_handle_unaligned_buf_start(struct dwc2_hsotg *hsotg,
        return 0;
 }
 
-static void s3c_hsotg_handle_unaligned_buf_complete(struct dwc2_hsotg *hsotg,
-       struct s3c_hsotg_ep *hs_ep, struct s3c_hsotg_req *hs_req)
+static void dwc2_hsotg_handle_unaligned_buf_complete(struct dwc2_hsotg *hsotg,
+       struct dwc2_hsotg_ep *hs_ep, struct dwc2_hsotg_req *hs_req)
 {
        /* If dma is not being used or buffer was aligned */
        if (!using_dma(hsotg) || !hs_req->saved_req_buf)
@@ -777,11 +773,11 @@ static void s3c_hsotg_handle_unaligned_buf_complete(struct dwc2_hsotg *hsotg,
        hs_req->saved_req_buf = NULL;
 }
 
-static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
+static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
                              gfp_t gfp_flags)
 {
-       struct s3c_hsotg_req *hs_req = our_req(req);
-       struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+       struct dwc2_hsotg_req *hs_req = our_req(req);
+       struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
        struct dwc2_hsotg *hs = hs_ep->parent;
        bool first;
        int ret;
@@ -802,13 +798,13 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
        req->actual = 0;
        req->status = -EINPROGRESS;
 
-       ret = s3c_hsotg_handle_unaligned_buf_start(hs, hs_ep, hs_req);
+       ret = dwc2_hsotg_handle_unaligned_buf_start(hs, hs_ep, hs_req);
        if (ret)
                return ret;
 
        /* if we're using DMA, sync the buffers as necessary */
        if (using_dma(hs)) {
-               ret = s3c_hsotg_map_dma(hs, hs_ep, req);
+               ret = dwc2_hsotg_map_dma(hs, hs_ep, req);
                if (ret)
                        return ret;
        }
@@ -817,51 +813,51 @@ static int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
        list_add_tail(&hs_req->queue, &hs_ep->queue);
 
        if (first)
-               s3c_hsotg_start_req(hs, hs_ep, hs_req, false);
+               dwc2_hsotg_start_req(hs, hs_ep, hs_req, false);
 
        return 0;
 }
 
-static int s3c_hsotg_ep_queue_lock(struct usb_ep *ep, struct usb_request *req,
+static int dwc2_hsotg_ep_queue_lock(struct usb_ep *ep, struct usb_request *req,
                              gfp_t gfp_flags)
 {
-       struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+       struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
        struct dwc2_hsotg *hs = hs_ep->parent;
        unsigned long flags = 0;
        int ret = 0;
 
        spin_lock_irqsave(&hs->lock, flags);
-       ret = s3c_hsotg_ep_queue(ep, req, gfp_flags);
+       ret = dwc2_hsotg_ep_queue(ep, req, gfp_flags);
        spin_unlock_irqrestore(&hs->lock, flags);
 
        return ret;
 }
 
-static void s3c_hsotg_ep_free_request(struct usb_ep *ep,
+static void dwc2_hsotg_ep_free_request(struct usb_ep *ep,
                                      struct usb_request *req)
 {
-       struct s3c_hsotg_req *hs_req = our_req(req);
+       struct dwc2_hsotg_req *hs_req = our_req(req);
 
        kfree(hs_req);
 }
 
 /**
- * s3c_hsotg_complete_oursetup - setup completion callback
+ * dwc2_hsotg_complete_oursetup - setup completion callback
  * @ep: The endpoint the request was on.
  * @req: The request completed.
  *
  * Called on completion of any requests the driver itself
  * submitted that need cleaning up.
  */
-static void s3c_hsotg_complete_oursetup(struct usb_ep *ep,
+static void dwc2_hsotg_complete_oursetup(struct usb_ep *ep,
                                        struct usb_request *req)
 {
-       struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+       struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
        struct dwc2_hsotg *hsotg = hs_ep->parent;
 
        dev_dbg(hsotg->dev, "%s: ep %p, req %p\n", __func__, ep, req);
 
-       s3c_hsotg_ep_free_request(ep, req);
+       dwc2_hsotg_ep_free_request(ep, req);
 }
 
 /**
@@ -872,10 +868,10 @@ static void s3c_hsotg_complete_oursetup(struct usb_ep *ep,
  * Convert the given wIndex into a pointer to an driver endpoint
  * structure, or return NULL if it is not a valid endpoint.
  */
-static struct s3c_hsotg_ep *ep_from_windex(struct dwc2_hsotg *hsotg,
+static struct dwc2_hsotg_ep *ep_from_windex(struct dwc2_hsotg *hsotg,
                                           u32 windex)
 {
-       struct s3c_hsotg_ep *ep;
+       struct dwc2_hsotg_ep *ep;
        int dir = (windex & USB_DIR_IN) ? 1 : 0;
        int idx = windex & 0x7F;
 
@@ -894,14 +890,14 @@ static struct s3c_hsotg_ep *ep_from_windex(struct dwc2_hsotg *hsotg,
 }
 
 /**
- * s3c_hsotg_set_test_mode - Enable usb Test Modes
+ * dwc2_hsotg_set_test_mode - Enable usb Test Modes
  * @hsotg: The driver state.
  * @testmode: requested usb test mode
  * Enable usb Test Mode requested by the Host.
  */
-int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode)
+int dwc2_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode)
 {
-       int dctl = readl(hsotg->regs + DCTL);
+       int dctl = dwc2_readl(hsotg->regs + DCTL);
 
        dctl &= ~DCTL_TSTCTL_MASK;
        switch (testmode) {
@@ -915,12 +911,12 @@ int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode)
        default:
                return -EINVAL;
        }
-       writel(dctl, hsotg->regs + DCTL);
+       dwc2_writel(dctl, hsotg->regs + DCTL);
        return 0;
 }
 
 /**
- * s3c_hsotg_send_reply - send reply to control request
+ * dwc2_hsotg_send_reply - send reply to control request
  * @hsotg: The device state
  * @ep: Endpoint 0
  * @buff: Buffer for request
@@ -929,8 +925,8 @@ int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode)
  * Create a request and queue it on the given endpoint. This is useful as
  * an internal method of sending replies to certain control requests, etc.
  */
-static int s3c_hsotg_send_reply(struct dwc2_hsotg *hsotg,
-                               struct s3c_hsotg_ep *ep,
+static int dwc2_hsotg_send_reply(struct dwc2_hsotg *hsotg,
+                               struct dwc2_hsotg_ep *ep,
                                void *buff,
                                int length)
 {
@@ -939,7 +935,7 @@ static int s3c_hsotg_send_reply(struct dwc2_hsotg *hsotg,
 
        dev_dbg(hsotg->dev, "%s: buff %p, len %d\n", __func__, buff, length);
 
-       req = s3c_hsotg_ep_alloc_request(&ep->ep, GFP_ATOMIC);
+       req = dwc2_hsotg_ep_alloc_request(&ep->ep, GFP_ATOMIC);
        hsotg->ep0_reply = req;
        if (!req) {
                dev_warn(hsotg->dev, "%s: cannot alloc req\n", __func__);
@@ -953,12 +949,12 @@ static int s3c_hsotg_send_reply(struct dwc2_hsotg *hsotg,
         * STATUS stage.
         */
        req->zero = 0;
-       req->complete = s3c_hsotg_complete_oursetup;
+       req->complete = dwc2_hsotg_complete_oursetup;
 
        if (length)
                memcpy(req->buf, buff, length);
 
-       ret = s3c_hsotg_ep_queue(&ep->ep, req, GFP_ATOMIC);
+       ret = dwc2_hsotg_ep_queue(&ep->ep, req, GFP_ATOMIC);
        if (ret) {
                dev_warn(hsotg->dev, "%s: cannot queue req\n", __func__);
                return ret;
@@ -968,15 +964,15 @@ static int s3c_hsotg_send_reply(struct dwc2_hsotg *hsotg,
 }
 
 /**
- * s3c_hsotg_process_req_status - process request GET_STATUS
+ * dwc2_hsotg_process_req_status - process request GET_STATUS
  * @hsotg: The device state
  * @ctrl: USB control request
  */
-static int s3c_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
+static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
                                        struct usb_ctrlrequest *ctrl)
 {
-       struct s3c_hsotg_ep *ep0 = hsotg->eps_out[0];
-       struct s3c_hsotg_ep *ep;
+       struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0];
+       struct dwc2_hsotg_ep *ep;
        __le16 reply;
        int ret;
 
@@ -1013,7 +1009,7 @@ static int s3c_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
        if (le16_to_cpu(ctrl->wLength) != 2)
                return -EINVAL;
 
-       ret = s3c_hsotg_send_reply(hsotg, ep0, &reply, 2);
+       ret = dwc2_hsotg_send_reply(hsotg, ep0, &reply, 2);
        if (ret) {
                dev_err(hsotg->dev, "%s: failed to send reply\n", __func__);
                return ret;
@@ -1022,7 +1018,7 @@ static int s3c_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
        return 1;
 }
 
-static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value);
+static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value);
 
 /**
  * get_ep_head - return the first request on the endpoint
@@ -1030,27 +1026,27 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value);
  *
  * Get the first request on the endpoint.
  */
-static struct s3c_hsotg_req *get_ep_head(struct s3c_hsotg_ep *hs_ep)
+static struct dwc2_hsotg_req *get_ep_head(struct dwc2_hsotg_ep *hs_ep)
 {
        if (list_empty(&hs_ep->queue))
                return NULL;
 
-       return list_first_entry(&hs_ep->queue, struct s3c_hsotg_req, queue);
+       return list_first_entry(&hs_ep->queue, struct dwc2_hsotg_req, queue);
 }
 
 /**
- * s3c_hsotg_process_req_feature - process request {SET,CLEAR}_FEATURE
+ * dwc2_hsotg_process_req_feature - process request {SET,CLEAR}_FEATURE
  * @hsotg: The device state
  * @ctrl: USB control request
  */
-static int s3c_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
+static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
                                         struct usb_ctrlrequest *ctrl)
 {
-       struct s3c_hsotg_ep *ep0 = hsotg->eps_out[0];
-       struct s3c_hsotg_req *hs_req;
+       struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0];
+       struct dwc2_hsotg_req *hs_req;
        bool restart;
        bool set = (ctrl->bRequest == USB_REQ_SET_FEATURE);
-       struct s3c_hsotg_ep *ep;
+       struct dwc2_hsotg_ep *ep;
        int ret;
        bool halted;
        u32 recip;
@@ -1074,7 +1070,7 @@ static int s3c_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
                                return -EINVAL;
 
                        hsotg->test_mode = wIndex >> 8;
-                       ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0);
+                       ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
                        if (ret) {
                                dev_err(hsotg->dev,
                                        "%s: failed to send reply\n", __func__);
@@ -1098,9 +1094,9 @@ static int s3c_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
                case USB_ENDPOINT_HALT:
                        halted = ep->halted;
 
-                       s3c_hsotg_ep_sethalt(&ep->ep, set);
+                       dwc2_hsotg_ep_sethalt(&ep->ep, set);
 
-                       ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0);
+                       ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
                        if (ret) {
                                dev_err(hsotg->dev,
                                        "%s: failed to send reply\n", __func__);
@@ -1134,7 +1130,7 @@ static int s3c_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
                                        restart = !list_empty(&ep->queue);
                                        if (restart) {
                                                hs_req = get_ep_head(ep);
-                                               s3c_hsotg_start_req(hsotg, ep,
+                                               dwc2_hsotg_start_req(hsotg, ep,
                                                                hs_req, false);
                                        }
                                }
@@ -1152,17 +1148,17 @@ static int s3c_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
        return 1;
 }
 
-static void s3c_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg);
+static void dwc2_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg);
 
 /**
- * s3c_hsotg_stall_ep0 - stall ep0
+ * dwc2_hsotg_stall_ep0 - stall ep0
  * @hsotg: The device state
  *
  * Set stall for ep0 as response for setup request.
  */
-static void s3c_hsotg_stall_ep0(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_stall_ep0(struct dwc2_hsotg *hsotg)
 {
-       struct s3c_hsotg_ep *ep0 = hsotg->eps_out[0];
+       struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0];
        u32 reg;
        u32 ctrl;
 
@@ -1174,24 +1170,24 @@ static void s3c_hsotg_stall_ep0(struct dwc2_hsotg *hsotg)
         * taken effect, so no need to clear later.
         */
 
-       ctrl = readl(hsotg->regs + reg);
+       ctrl = dwc2_readl(hsotg->regs + reg);
        ctrl |= DXEPCTL_STALL;
        ctrl |= DXEPCTL_CNAK;
-       writel(ctrl, hsotg->regs + reg);
+       dwc2_writel(ctrl, hsotg->regs + reg);
 
        dev_dbg(hsotg->dev,
                "written DXEPCTL=0x%08x to %08x (DXEPCTL=0x%08x)\n",
-               ctrl, reg, readl(hsotg->regs + reg));
+               ctrl, reg, dwc2_readl(hsotg->regs + reg));
 
         /*
          * complete won't be called, so we enqueue
          * setup request here
          */
-        s3c_hsotg_enqueue_setup(hsotg);
+        dwc2_hsotg_enqueue_setup(hsotg);
 }
 
 /**
- * s3c_hsotg_process_control - process a control request
+ * dwc2_hsotg_process_control - process a control request
  * @hsotg: The device state
  * @ctrl: The control request received
  *
@@ -1199,16 +1195,17 @@ static void s3c_hsotg_stall_ep0(struct dwc2_hsotg *hsotg)
  * needs to work out what to do next (and whether to pass it on to the
  * gadget driver).
  */
-static void s3c_hsotg_process_control(struct dwc2_hsotg *hsotg,
+static void dwc2_hsotg_process_control(struct dwc2_hsotg *hsotg,
                                      struct usb_ctrlrequest *ctrl)
 {
-       struct s3c_hsotg_ep *ep0 = hsotg->eps_out[0];
+       struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0];
        int ret = 0;
        u32 dcfg;
 
-       dev_dbg(hsotg->dev, "ctrl Req=%02x, Type=%02x, V=%04x, L=%04x\n",
-                ctrl->bRequest, ctrl->bRequestType,
-                ctrl->wValue, ctrl->wLength);
+       dev_dbg(hsotg->dev,
+               "ctrl Type=%02x, Req=%02x, V=%04x, I=%04x, L=%04x\n",
+               ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
+               ctrl->wIndex, ctrl->wLength);
 
        if (ctrl->wLength == 0) {
                ep0->dir_in = 1;
@@ -1225,24 +1222,24 @@ static void s3c_hsotg_process_control(struct dwc2_hsotg *hsotg,
                switch (ctrl->bRequest) {
                case USB_REQ_SET_ADDRESS:
                        hsotg->connected = 1;
-                       dcfg = readl(hsotg->regs + DCFG);
+                       dcfg = dwc2_readl(hsotg->regs + DCFG);
                        dcfg &= ~DCFG_DEVADDR_MASK;
                        dcfg |= (le16_to_cpu(ctrl->wValue) <<
                                 DCFG_DEVADDR_SHIFT) & DCFG_DEVADDR_MASK;
-                       writel(dcfg, hsotg->regs + DCFG);
+                       dwc2_writel(dcfg, hsotg->regs + DCFG);
 
                        dev_info(hsotg->dev, "new address %d\n", ctrl->wValue);
 
-                       ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0);
+                       ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
                        return;
 
                case USB_REQ_GET_STATUS:
-                       ret = s3c_hsotg_process_req_status(hsotg, ctrl);
+                       ret = dwc2_hsotg_process_req_status(hsotg, ctrl);
                        break;
 
                case USB_REQ_CLEAR_FEATURE:
                case USB_REQ_SET_FEATURE:
-                       ret = s3c_hsotg_process_req_feature(hsotg, ctrl);
+                       ret = dwc2_hsotg_process_req_feature(hsotg, ctrl);
                        break;
                }
        }
@@ -1263,21 +1260,21 @@ static void s3c_hsotg_process_control(struct dwc2_hsotg *hsotg,
         */
 
        if (ret < 0)
-               s3c_hsotg_stall_ep0(hsotg);
+               dwc2_hsotg_stall_ep0(hsotg);
 }
 
 /**
- * s3c_hsotg_complete_setup - completion of a setup transfer
+ * dwc2_hsotg_complete_setup - completion of a setup transfer
  * @ep: The endpoint the request was on.
  * @req: The request completed.
  *
  * Called on completion of any requests the driver itself submitted for
  * EP0 setup packets
  */
-static void s3c_hsotg_complete_setup(struct usb_ep *ep,
+static void dwc2_hsotg_complete_setup(struct usb_ep *ep,
                                     struct usb_request *req)
 {
-       struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+       struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
        struct dwc2_hsotg *hsotg = hs_ep->parent;
 
        if (req->status < 0) {
@@ -1287,23 +1284,23 @@ static void s3c_hsotg_complete_setup(struct usb_ep *ep,
 
        spin_lock(&hsotg->lock);
        if (req->actual == 0)
-               s3c_hsotg_enqueue_setup(hsotg);
+               dwc2_hsotg_enqueue_setup(hsotg);
        else
-               s3c_hsotg_process_control(hsotg, req->buf);
+               dwc2_hsotg_process_control(hsotg, req->buf);
        spin_unlock(&hsotg->lock);
 }
 
 /**
- * s3c_hsotg_enqueue_setup - start a request for EP0 packets
+ * dwc2_hsotg_enqueue_setup - start a request for EP0 packets
  * @hsotg: The device state.
  *
  * Enqueue a request on EP0 if necessary to received any SETUP packets
  * received from the host.
  */
-static void s3c_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg)
 {
        struct usb_request *req = hsotg->ctrl_req;
-       struct s3c_hsotg_req *hs_req = our_req(req);
+       struct dwc2_hsotg_req *hs_req = our_req(req);
        int ret;
 
        dev_dbg(hsotg->dev, "%s: queueing setup request\n", __func__);
@@ -1311,7 +1308,7 @@ static void s3c_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg)
        req->zero = 0;
        req->length = 8;
        req->buf = hsotg->ctrl_buff;
-       req->complete = s3c_hsotg_complete_setup;
+       req->complete = dwc2_hsotg_complete_setup;
 
        if (!list_empty(&hs_req->queue)) {
                dev_dbg(hsotg->dev, "%s already queued???\n", __func__);
@@ -1322,7 +1319,7 @@ static void s3c_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg)
        hsotg->eps_out[0]->send_zlp = 0;
        hsotg->ep0_state = DWC2_EP0_SETUP;
 
-       ret = s3c_hsotg_ep_queue(&hsotg->eps_out[0]->ep, req, GFP_ATOMIC);
+       ret = dwc2_hsotg_ep_queue(&hsotg->eps_out[0]->ep, req, GFP_ATOMIC);
        if (ret < 0) {
                dev_err(hsotg->dev, "%s: failed queue (%d)\n", __func__, ret);
                /*
@@ -1332,8 +1329,8 @@ static void s3c_hsotg_enqueue_setup(struct dwc2_hsotg *hsotg)
        }
 }
 
-static void s3c_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
-                                       struct s3c_hsotg_ep *hs_ep)
+static void dwc2_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
+                                       struct dwc2_hsotg_ep *hs_ep)
 {
        u32 ctrl;
        u8 index = hs_ep->index;
@@ -1347,19 +1344,19 @@ static void s3c_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
                dev_dbg(hsotg->dev, "Receiving zero-length packet on ep%d\n",
                                                                        index);
 
-       writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
-                       DXEPTSIZ_XFERSIZE(0), hsotg->regs +
-                       epsiz_reg);
+       dwc2_writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
+                   DXEPTSIZ_XFERSIZE(0), hsotg->regs +
+                   epsiz_reg);
 
-       ctrl = readl(hsotg->regs + epctl_reg);
+       ctrl = dwc2_readl(hsotg->regs + epctl_reg);
        ctrl |= DXEPCTL_CNAK;  /* clear NAK set by core */
        ctrl |= DXEPCTL_EPENA; /* ensure ep enabled */
        ctrl |= DXEPCTL_USBACTEP;
-       writel(ctrl, hsotg->regs + epctl_reg);
+       dwc2_writel(ctrl, hsotg->regs + epctl_reg);
 }
 
 /**
- * s3c_hsotg_complete_request - complete a request given to us
+ * dwc2_hsotg_complete_request - complete a request given to us
  * @hsotg: The device state.
  * @hs_ep: The endpoint the request was on.
  * @hs_req: The request to complete.
@@ -1371,9 +1368,9 @@ static void s3c_hsotg_program_zlp(struct dwc2_hsotg *hsotg,
  *
  * Note, expects the ep to already be locked as appropriate.
  */
-static void s3c_hsotg_complete_request(struct dwc2_hsotg *hsotg,
-                                      struct s3c_hsotg_ep *hs_ep,
-                                      struct s3c_hsotg_req *hs_req,
+static void dwc2_hsotg_complete_request(struct dwc2_hsotg *hsotg,
+                                      struct dwc2_hsotg_ep *hs_ep,
+                                      struct dwc2_hsotg_req *hs_req,
                                       int result)
 {
        bool restart;
@@ -1394,14 +1391,14 @@ static void s3c_hsotg_complete_request(struct dwc2_hsotg *hsotg,
        if (hs_req->req.status == -EINPROGRESS)
                hs_req->req.status = result;
 
-       s3c_hsotg_handle_unaligned_buf_complete(hsotg, hs_ep, hs_req);
+       if (using_dma(hsotg))
+               dwc2_hsotg_unmap_dma(hsotg, hs_ep, hs_req);
+
+       dwc2_hsotg_handle_unaligned_buf_complete(hsotg, hs_ep, hs_req);
 
        hs_ep->req = NULL;
        list_del_init(&hs_req->queue);
 
-       if (using_dma(hsotg))
-               s3c_hsotg_unmap_dma(hsotg, hs_ep, hs_req);
-
        /*
         * call the complete request with the locks off, just in case the
         * request tries to queue more work for this endpoint.
@@ -1423,13 +1420,13 @@ static void s3c_hsotg_complete_request(struct dwc2_hsotg *hsotg,
                restart = !list_empty(&hs_ep->queue);
                if (restart) {
                        hs_req = get_ep_head(hs_ep);
-                       s3c_hsotg_start_req(hsotg, hs_ep, hs_req, false);
+                       dwc2_hsotg_start_req(hsotg, hs_ep, hs_req, false);
                }
        }
 }
 
 /**
- * s3c_hsotg_rx_data - receive data from the FIFO for an endpoint
+ * dwc2_hsotg_rx_data - receive data from the FIFO for an endpoint
  * @hsotg: The device state.
  * @ep_idx: The endpoint index for the data
  * @size: The size of data in the fifo, in bytes
@@ -1438,10 +1435,10 @@ static void s3c_hsotg_complete_request(struct dwc2_hsotg *hsotg,
  * endpoint, so sort out whether we need to read the data into a request
  * that has been made for that endpoint.
  */
-static void s3c_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
+static void dwc2_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
 {
-       struct s3c_hsotg_ep *hs_ep = hsotg->eps_out[ep_idx];
-       struct s3c_hsotg_req *hs_req = hs_ep->req;
+       struct dwc2_hsotg_ep *hs_ep = hsotg->eps_out[ep_idx];
+       struct dwc2_hsotg_req *hs_req = hs_ep->req;
        void __iomem *fifo = hsotg->regs + EPFIFO(ep_idx);
        int to_read;
        int max_req;
@@ -1449,7 +1446,7 @@ static void s3c_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
 
 
        if (!hs_req) {
-               u32 epctl = readl(hsotg->regs + DOEPCTL(ep_idx));
+               u32 epctl = dwc2_readl(hsotg->regs + DOEPCTL(ep_idx));
                int ptr;
 
                dev_dbg(hsotg->dev,
@@ -1458,7 +1455,7 @@ static void s3c_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
 
                /* dump the data from the FIFO, we've nothing we can do */
                for (ptr = 0; ptr < size; ptr += 4)
-                       (void)readl(fifo);
+                       (void)dwc2_readl(fifo);
 
                return;
        }
@@ -1492,7 +1489,7 @@ static void s3c_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
 }
 
 /**
- * s3c_hsotg_ep0_zlp - send/receive zero-length packet on control endpoint
+ * dwc2_hsotg_ep0_zlp - send/receive zero-length packet on control endpoint
  * @hsotg: The device instance
  * @dir_in: If IN zlp
  *
@@ -1503,17 +1500,30 @@ static void s3c_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
  * currently believed that we do not need to wait for any space in
  * the TxFIFO.
  */
-static void s3c_hsotg_ep0_zlp(struct dwc2_hsotg *hsotg, bool dir_in)
+static void dwc2_hsotg_ep0_zlp(struct dwc2_hsotg *hsotg, bool dir_in)
 {
        /* eps_out[0] is used in both directions */
        hsotg->eps_out[0]->dir_in = dir_in;
        hsotg->ep0_state = dir_in ? DWC2_EP0_STATUS_IN : DWC2_EP0_STATUS_OUT;
 
-       s3c_hsotg_program_zlp(hsotg, hsotg->eps_out[0]);
+       dwc2_hsotg_program_zlp(hsotg, hsotg->eps_out[0]);
+}
+
+static void dwc2_hsotg_change_ep_iso_parity(struct dwc2_hsotg *hsotg,
+                       u32 epctl_reg)
+{
+       u32 ctrl;
+
+       ctrl = dwc2_readl(hsotg->regs + epctl_reg);
+       if (ctrl & DXEPCTL_EOFRNUM)
+               ctrl |= DXEPCTL_SETEVENFR;
+       else
+               ctrl |= DXEPCTL_SETODDFR;
+       dwc2_writel(ctrl, hsotg->regs + epctl_reg);
 }
 
 /**
- * s3c_hsotg_handle_outdone - handle receiving OutDone/SetupDone from RXFIFO
+ * dwc2_hsotg_handle_outdone - handle receiving OutDone/SetupDone from RXFIFO
  * @hsotg: The device instance
  * @epnum: The endpoint received from
  *
@@ -1521,11 +1531,11 @@ static void s3c_hsotg_ep0_zlp(struct dwc2_hsotg *hsotg, bool dir_in)
  * transfer for an OUT endpoint has been completed, either by a short
  * packet or by the finish of a transfer.
  */
-static void s3c_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum)
+static void dwc2_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum)
 {
-       u32 epsize = readl(hsotg->regs + DOEPTSIZ(epnum));
-       struct s3c_hsotg_ep *hs_ep = hsotg->eps_out[epnum];
-       struct s3c_hsotg_req *hs_req = hs_ep->req;
+       u32 epsize = dwc2_readl(hsotg->regs + DOEPTSIZ(epnum));
+       struct dwc2_hsotg_ep *hs_ep = hsotg->eps_out[epnum];
+       struct dwc2_hsotg_req *hs_req = hs_ep->req;
        struct usb_request *req = &hs_req->req;
        unsigned size_left = DXEPTSIZ_XFERSIZE_GET(epsize);
        int result = 0;
@@ -1537,8 +1547,8 @@ static void s3c_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum)
 
        if (epnum == 0 && hsotg->ep0_state == DWC2_EP0_STATUS_OUT) {
                dev_dbg(hsotg->dev, "zlp packet received\n");
-               s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, 0);
-               s3c_hsotg_enqueue_setup(hsotg);
+               dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, 0);
+               dwc2_hsotg_enqueue_setup(hsotg);
                return;
        }
 
@@ -1562,7 +1572,7 @@ static void s3c_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum)
 
        /* if there is more request to do, schedule new transfer */
        if (req->actual < req->length && size_left == 0) {
-               s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true);
+               dwc2_hsotg_start_req(hsotg, hs_ep, hs_req, true);
                return;
        }
 
@@ -1578,24 +1588,34 @@ static void s3c_hsotg_handle_outdone(struct dwc2_hsotg *hsotg, int epnum)
 
        if (epnum == 0 && hsotg->ep0_state == DWC2_EP0_DATA_OUT) {
                /* Move to STATUS IN */
-               s3c_hsotg_ep0_zlp(hsotg, true);
+               dwc2_hsotg_ep0_zlp(hsotg, true);
                return;
        }
 
-       s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, result);
+       /*
+        * Slave mode OUT transfers do not go through XferComplete so
+        * adjust the ISOC parity here.
+        */
+       if (!using_dma(hsotg)) {
+               hs_ep->has_correct_parity = 1;
+               if (hs_ep->isochronous && hs_ep->interval == 1)
+                       dwc2_hsotg_change_ep_iso_parity(hsotg, DOEPCTL(epnum));
+       }
+
+       dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, result);
 }
 
 /**
- * s3c_hsotg_read_frameno - read current frame number
+ * dwc2_hsotg_read_frameno - read current frame number
  * @hsotg: The device instance
  *
  * Return the current frame number
  */
-static u32 s3c_hsotg_read_frameno(struct dwc2_hsotg *hsotg)
+static u32 dwc2_hsotg_read_frameno(struct dwc2_hsotg *hsotg)
 {
        u32 dsts;
 
-       dsts = readl(hsotg->regs + DSTS);
+       dsts = dwc2_readl(hsotg->regs + DSTS);
        dsts &= DSTS_SOFFN_MASK;
        dsts >>= DSTS_SOFFN_SHIFT;
 
@@ -1603,7 +1623,7 @@ static u32 s3c_hsotg_read_frameno(struct dwc2_hsotg *hsotg)
 }
 
 /**
- * s3c_hsotg_handle_rx - RX FIFO has data
+ * dwc2_hsotg_handle_rx - RX FIFO has data
  * @hsotg: The device instance
  *
  * The IRQ handler has detected that the RX FIFO has some data in it
@@ -1618,9 +1638,9 @@ static u32 s3c_hsotg_read_frameno(struct dwc2_hsotg *hsotg)
  * as the actual data should be sent to the memory directly and we turn
  * on the completion interrupts to get notifications of transfer completion.
  */
-static void s3c_hsotg_handle_rx(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_handle_rx(struct dwc2_hsotg *hsotg)
 {
-       u32 grxstsr = readl(hsotg->regs + GRXSTSP);
+       u32 grxstsr = dwc2_readl(hsotg->regs + GRXSTSP);
        u32 epnum, status, size;
 
        WARN_ON(using_dma(hsotg));
@@ -1641,55 +1661,55 @@ static void s3c_hsotg_handle_rx(struct dwc2_hsotg *hsotg)
 
        case GRXSTS_PKTSTS_OUTDONE:
                dev_dbg(hsotg->dev, "OutDone (Frame=0x%08x)\n",
-                       s3c_hsotg_read_frameno(hsotg));
+                       dwc2_hsotg_read_frameno(hsotg));
 
                if (!using_dma(hsotg))
-                       s3c_hsotg_handle_outdone(hsotg, epnum);
+                       dwc2_hsotg_handle_outdone(hsotg, epnum);
                break;
 
        case GRXSTS_PKTSTS_SETUPDONE:
                dev_dbg(hsotg->dev,
                        "SetupDone (Frame=0x%08x, DOPEPCTL=0x%08x)\n",
-                       s3c_hsotg_read_frameno(hsotg),
-                       readl(hsotg->regs + DOEPCTL(0)));
+                       dwc2_hsotg_read_frameno(hsotg),
+                       dwc2_readl(hsotg->regs + DOEPCTL(0)));
                /*
-                * Call s3c_hsotg_handle_outdone here if it was not called from
+                * Call dwc2_hsotg_handle_outdone here if it was not called from
                 * GRXSTS_PKTSTS_OUTDONE. That is, if the core didn't
                 * generate GRXSTS_PKTSTS_OUTDONE for setup packet.
                 */
                if (hsotg->ep0_state == DWC2_EP0_SETUP)
-                       s3c_hsotg_handle_outdone(hsotg, epnum);
+                       dwc2_hsotg_handle_outdone(hsotg, epnum);
                break;
 
        case GRXSTS_PKTSTS_OUTRX:
-               s3c_hsotg_rx_data(hsotg, epnum, size);
+               dwc2_hsotg_rx_data(hsotg, epnum, size);
                break;
 
        case GRXSTS_PKTSTS_SETUPRX:
                dev_dbg(hsotg->dev,
                        "SetupRX (Frame=0x%08x, DOPEPCTL=0x%08x)\n",
-                       s3c_hsotg_read_frameno(hsotg),
-                       readl(hsotg->regs + DOEPCTL(0)));
+                       dwc2_hsotg_read_frameno(hsotg),
+                       dwc2_readl(hsotg->regs + DOEPCTL(0)));
 
                WARN_ON(hsotg->ep0_state != DWC2_EP0_SETUP);
 
-               s3c_hsotg_rx_data(hsotg, epnum, size);
+               dwc2_hsotg_rx_data(hsotg, epnum, size);
                break;
 
        default:
                dev_warn(hsotg->dev, "%s: unknown status %08x\n",
                         __func__, grxstsr);
 
-               s3c_hsotg_dump(hsotg);
+               dwc2_hsotg_dump(hsotg);
                break;
        }
 }
 
 /**
- * s3c_hsotg_ep0_mps - turn max packet size into register setting
+ * dwc2_hsotg_ep0_mps - turn max packet size into register setting
  * @mps: The maximum packet size in bytes.
  */
-static u32 s3c_hsotg_ep0_mps(unsigned int mps)
+static u32 dwc2_hsotg_ep0_mps(unsigned int mps)
 {
        switch (mps) {
        case 64:
@@ -1708,7 +1728,7 @@ static u32 s3c_hsotg_ep0_mps(unsigned int mps)
 }
 
 /**
- * s3c_hsotg_set_ep_maxpacket - set endpoint's max-packet field
+ * dwc2_hsotg_set_ep_maxpacket - set endpoint's max-packet field
  * @hsotg: The driver state.
  * @ep: The index number of the endpoint
  * @mps: The maximum packet size in bytes
@@ -1716,10 +1736,10 @@ static u32 s3c_hsotg_ep0_mps(unsigned int mps)
  * Configure the maximum packet size for the given endpoint, updating
  * the hardware control registers to reflect this.
  */
-static void s3c_hsotg_set_ep_maxpacket(struct dwc2_hsotg *hsotg,
+static void dwc2_hsotg_set_ep_maxpacket(struct dwc2_hsotg *hsotg,
                        unsigned int ep, unsigned int mps, unsigned int dir_in)
 {
-       struct s3c_hsotg_ep *hs_ep;
+       struct dwc2_hsotg_ep *hs_ep;
        void __iomem *regs = hsotg->regs;
        u32 mpsval;
        u32 mcval;
@@ -1731,7 +1751,7 @@ static void s3c_hsotg_set_ep_maxpacket(struct dwc2_hsotg *hsotg,
 
        if (ep == 0) {
                /* EP0 is a special case */
-               mpsval = s3c_hsotg_ep0_mps(mps);
+               mpsval = dwc2_hsotg_ep0_mps(mps);
                if (mpsval > 3)
                        goto bad_mps;
                hs_ep->ep.maxpacket = mps;
@@ -1748,15 +1768,15 @@ static void s3c_hsotg_set_ep_maxpacket(struct dwc2_hsotg *hsotg,
        }
 
        if (dir_in) {
-               reg = readl(regs + DIEPCTL(ep));
+               reg = dwc2_readl(regs + DIEPCTL(ep));
                reg &= ~DXEPCTL_MPS_MASK;
                reg |= mpsval;
-               writel(reg, regs + DIEPCTL(ep));
+               dwc2_writel(reg, regs + DIEPCTL(ep));
        } else {
-               reg = readl(regs + DOEPCTL(ep));
+               reg = dwc2_readl(regs + DOEPCTL(ep));
                reg &= ~DXEPCTL_MPS_MASK;
                reg |= mpsval;
-               writel(reg, regs + DOEPCTL(ep));
+               dwc2_writel(reg, regs + DOEPCTL(ep));
        }
 
        return;
@@ -1766,23 +1786,23 @@ bad_mps:
 }
 
 /**
- * s3c_hsotg_txfifo_flush - flush Tx FIFO
+ * dwc2_hsotg_txfifo_flush - flush Tx FIFO
  * @hsotg: The driver state
  * @idx: The index for the endpoint (0..15)
  */
-static void s3c_hsotg_txfifo_flush(struct dwc2_hsotg *hsotg, unsigned int idx)
+static void dwc2_hsotg_txfifo_flush(struct dwc2_hsotg *hsotg, unsigned int idx)
 {
        int timeout;
        int val;
 
-       writel(GRSTCTL_TXFNUM(idx) | GRSTCTL_TXFFLSH,
-               hsotg->regs + GRSTCTL);
+       dwc2_writel(GRSTCTL_TXFNUM(idx) | GRSTCTL_TXFFLSH,
+                   hsotg->regs + GRSTCTL);
 
        /* wait until the fifo is flushed */
        timeout = 100;
 
        while (1) {
-               val = readl(hsotg->regs + GRSTCTL);
+               val = dwc2_readl(hsotg->regs + GRSTCTL);
 
                if ((val & (GRSTCTL_TXFFLSH)) == 0)
                        break;
@@ -1799,17 +1819,17 @@ static void s3c_hsotg_txfifo_flush(struct dwc2_hsotg *hsotg, unsigned int idx)
 }
 
 /**
- * s3c_hsotg_trytx - check to see if anything needs transmitting
+ * dwc2_hsotg_trytx - check to see if anything needs transmitting
  * @hsotg: The driver state
  * @hs_ep: The driver endpoint to check.
  *
  * Check to see if there is a request that has data to send, and if so
  * make an attempt to write data into the FIFO.
  */
-static int s3c_hsotg_trytx(struct dwc2_hsotg *hsotg,
-                          struct s3c_hsotg_ep *hs_ep)
+static int dwc2_hsotg_trytx(struct dwc2_hsotg *hsotg,
+                          struct dwc2_hsotg_ep *hs_ep)
 {
-       struct s3c_hsotg_req *hs_req = hs_ep->req;
+       struct dwc2_hsotg_req *hs_req = hs_ep->req;
 
        if (!hs_ep->dir_in || !hs_req) {
                /**
@@ -1817,7 +1837,7 @@ static int s3c_hsotg_trytx(struct dwc2_hsotg *hsotg,
                 * for endpoints, excepting ep0
                 */
                if (hs_ep->index != 0)
-                       s3c_hsotg_ctrl_epint(hsotg, hs_ep->index,
+                       dwc2_hsotg_ctrl_epint(hsotg, hs_ep->index,
                                             hs_ep->dir_in, 0);
                return 0;
        }
@@ -1825,25 +1845,25 @@ static int s3c_hsotg_trytx(struct dwc2_hsotg *hsotg,
        if (hs_req->req.actual < hs_req->req.length) {
                dev_dbg(hsotg->dev, "trying to write more for ep%d\n",
                        hs_ep->index);
-               return s3c_hsotg_write_fifo(hsotg, hs_ep, hs_req);
+               return dwc2_hsotg_write_fifo(hsotg, hs_ep, hs_req);
        }
 
        return 0;
 }
 
 /**
- * s3c_hsotg_complete_in - complete IN transfer
+ * dwc2_hsotg_complete_in - complete IN transfer
  * @hsotg: The device state.
  * @hs_ep: The endpoint that has just completed.
  *
  * An IN transfer has been completed, update the transfer's state and then
  * call the relevant completion routines.
  */
-static void s3c_hsotg_complete_in(struct dwc2_hsotg *hsotg,
-                                 struct s3c_hsotg_ep *hs_ep)
+static void dwc2_hsotg_complete_in(struct dwc2_hsotg *hsotg,
+                                 struct dwc2_hsotg_ep *hs_ep)
 {
-       struct s3c_hsotg_req *hs_req = hs_ep->req;
-       u32 epsize = readl(hsotg->regs + DIEPTSIZ(hs_ep->index));
+       struct dwc2_hsotg_req *hs_req = hs_ep->req;
+       u32 epsize = dwc2_readl(hsotg->regs + DIEPTSIZ(hs_ep->index));
        int size_left, size_done;
 
        if (!hs_req) {
@@ -1854,19 +1874,19 @@ static void s3c_hsotg_complete_in(struct dwc2_hsotg *hsotg,
        /* Finish ZLP handling for IN EP0 transactions */
        if (hs_ep->index == 0 && hsotg->ep0_state == DWC2_EP0_STATUS_IN) {
                dev_dbg(hsotg->dev, "zlp packet sent\n");
-               s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, 0);
+               dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, 0);
                if (hsotg->test_mode) {
                        int ret;
 
-                       ret = s3c_hsotg_set_test_mode(hsotg, hsotg->test_mode);
+                       ret = dwc2_hsotg_set_test_mode(hsotg, hsotg->test_mode);
                        if (ret < 0) {
                                dev_dbg(hsotg->dev, "Invalid Test #%d\n",
                                                hsotg->test_mode);
-                               s3c_hsotg_stall_ep0(hsotg);
+                               dwc2_hsotg_stall_ep0(hsotg);
                                return;
                        }
                }
-               s3c_hsotg_enqueue_setup(hsotg);
+               dwc2_hsotg_enqueue_setup(hsotg);
                return;
        }
 
@@ -1895,13 +1915,13 @@ static void s3c_hsotg_complete_in(struct dwc2_hsotg *hsotg,
 
        if (!size_left && hs_req->req.actual < hs_req->req.length) {
                dev_dbg(hsotg->dev, "%s trying more for req...\n", __func__);
-               s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true);
+               dwc2_hsotg_start_req(hsotg, hs_ep, hs_req, true);
                return;
        }
 
        /* Zlp for all endpoints, for ep0 only in DATA IN stage */
        if (hs_ep->send_zlp) {
-               s3c_hsotg_program_zlp(hsotg, hs_ep);
+               dwc2_hsotg_program_zlp(hsotg, hs_ep);
                hs_ep->send_zlp = 0;
                /* transfer will be completed on next complete interrupt */
                return;
@@ -1909,36 +1929,36 @@ static void s3c_hsotg_complete_in(struct dwc2_hsotg *hsotg,
 
        if (hs_ep->index == 0 && hsotg->ep0_state == DWC2_EP0_DATA_IN) {
                /* Move to STATUS OUT */
-               s3c_hsotg_ep0_zlp(hsotg, false);
+               dwc2_hsotg_ep0_zlp(hsotg, false);
                return;
        }
 
-       s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, 0);
+       dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, 0);
 }
 
 /**
- * s3c_hsotg_epint - handle an in/out endpoint interrupt
+ * dwc2_hsotg_epint - handle an in/out endpoint interrupt
  * @hsotg: The driver state
  * @idx: The index for the endpoint (0..15)
  * @dir_in: Set if this is an IN endpoint
  *
  * Process and clear any interrupt pending for an individual endpoint
  */
-static void s3c_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
+static void dwc2_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
                            int dir_in)
 {
-       struct s3c_hsotg_ep *hs_ep = index_to_ep(hsotg, idx, dir_in);
+       struct dwc2_hsotg_ep *hs_ep = index_to_ep(hsotg, idx, dir_in);
        u32 epint_reg = dir_in ? DIEPINT(idx) : DOEPINT(idx);
        u32 epctl_reg = dir_in ? DIEPCTL(idx) : DOEPCTL(idx);
        u32 epsiz_reg = dir_in ? DIEPTSIZ(idx) : DOEPTSIZ(idx);
        u32 ints;
        u32 ctrl;
 
-       ints = readl(hsotg->regs + epint_reg);
-       ctrl = readl(hsotg->regs + epctl_reg);
+       ints = dwc2_readl(hsotg->regs + epint_reg);
+       ctrl = dwc2_readl(hsotg->regs + epctl_reg);
 
        /* Clear endpoint interrupts */
-       writel(ints, hsotg->regs + epint_reg);
+       dwc2_writel(ints, hsotg->regs + epint_reg);
 
        if (!hs_ep) {
                dev_err(hsotg->dev, "%s:Interrupt for unconfigured ep%d(%s)\n",
@@ -1954,35 +1974,31 @@ static void s3c_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
                ints &= ~DXEPINT_XFERCOMPL;
 
        if (ints & DXEPINT_XFERCOMPL) {
-               if (hs_ep->isochronous && hs_ep->interval == 1) {
-                       if (ctrl & DXEPCTL_EOFRNUM)
-                               ctrl |= DXEPCTL_SETEVENFR;
-                       else
-                               ctrl |= DXEPCTL_SETODDFR;
-                       writel(ctrl, hsotg->regs + epctl_reg);
-               }
+               hs_ep->has_correct_parity = 1;
+               if (hs_ep->isochronous && hs_ep->interval == 1)
+                       dwc2_hsotg_change_ep_iso_parity(hsotg, epctl_reg);
 
                dev_dbg(hsotg->dev,
                        "%s: XferCompl: DxEPCTL=0x%08x, DXEPTSIZ=%08x\n",
-                       __func__, readl(hsotg->regs + epctl_reg),
-                       readl(hsotg->regs + epsiz_reg));
+                       __func__, dwc2_readl(hsotg->regs + epctl_reg),
+                       dwc2_readl(hsotg->regs + epsiz_reg));
 
                /*
                 * we get OutDone from the FIFO, so we only need to look
                 * at completing IN requests here
                 */
                if (dir_in) {
-                       s3c_hsotg_complete_in(hsotg, hs_ep);
+                       dwc2_hsotg_complete_in(hsotg, hs_ep);
 
                        if (idx == 0 && !hs_ep->req)
-                               s3c_hsotg_enqueue_setup(hsotg);
+                               dwc2_hsotg_enqueue_setup(hsotg);
                } else if (using_dma(hsotg)) {
                        /*
                         * We're using DMA, we need to fire an OutDone here
                         * as we ignore the RXFIFO.
                         */
 
-                       s3c_hsotg_handle_outdone(hsotg, idx);
+                       dwc2_hsotg_handle_outdone(hsotg, idx);
                }
        }
 
@@ -1990,16 +2006,16 @@ static void s3c_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
                dev_dbg(hsotg->dev, "%s: EPDisbld\n", __func__);
 
                if (dir_in) {
-                       int epctl = readl(hsotg->regs + epctl_reg);
+                       int epctl = dwc2_readl(hsotg->regs + epctl_reg);
 
-                       s3c_hsotg_txfifo_flush(hsotg, hs_ep->fifo_index);
+                       dwc2_hsotg_txfifo_flush(hsotg, hs_ep->fifo_index);
 
                        if ((epctl & DXEPCTL_STALL) &&
                                (epctl & DXEPCTL_EPTYPE_BULK)) {
-                               int dctl = readl(hsotg->regs + DCTL);
+                               int dctl = dwc2_readl(hsotg->regs + DCTL);
 
                                dctl |= DCTL_CGNPINNAK;
-                               writel(dctl, hsotg->regs + DCTL);
+                               dwc2_writel(dctl, hsotg->regs + DCTL);
                        }
                }
        }
@@ -2021,7 +2037,7 @@ static void s3c_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
                        if (dir_in)
                                WARN_ON_ONCE(1);
                        else
-                               s3c_hsotg_handle_outdone(hsotg, 0);
+                               dwc2_hsotg_handle_outdone(hsotg, 0);
                }
        }
 
@@ -2047,21 +2063,21 @@ static void s3c_hsotg_epint(struct dwc2_hsotg *hsotg, unsigned int idx,
                        dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n",
                                __func__, idx);
                        if (!using_dma(hsotg))
-                               s3c_hsotg_trytx(hsotg, hs_ep);
+                               dwc2_hsotg_trytx(hsotg, hs_ep);
                }
        }
 }
 
 /**
- * s3c_hsotg_irq_enumdone - Handle EnumDone interrupt (enumeration done)
+ * dwc2_hsotg_irq_enumdone - Handle EnumDone interrupt (enumeration done)
  * @hsotg: The device state.
  *
  * Handle updating the device settings after the enumeration phase has
  * been completed.
  */
-static void s3c_hsotg_irq_enumdone(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_irq_enumdone(struct dwc2_hsotg *hsotg)
 {
-       u32 dsts = readl(hsotg->regs + DSTS);
+       u32 dsts = dwc2_readl(hsotg->regs + DSTS);
        int ep0_mps = 0, ep_mps = 8;
 
        /*
@@ -2113,23 +2129,23 @@ static void s3c_hsotg_irq_enumdone(struct dwc2_hsotg *hsotg)
        if (ep0_mps) {
                int i;
                /* Initialize ep0 for both in and out directions */
-               s3c_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps, 1);
-               s3c_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps, 0);
+               dwc2_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps, 1);
+               dwc2_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps, 0);
                for (i = 1; i < hsotg->num_of_eps; i++) {
                        if (hsotg->eps_in[i])
-                               s3c_hsotg_set_ep_maxpacket(hsotg, i, ep_mps, 1);
+                               dwc2_hsotg_set_ep_maxpacket(hsotg, i, ep_mps, 1);
                        if (hsotg->eps_out[i])
-                               s3c_hsotg_set_ep_maxpacket(hsotg, i, ep_mps, 0);
+                               dwc2_hsotg_set_ep_maxpacket(hsotg, i, ep_mps, 0);
                }
        }
 
        /* ensure after enumeration our EP0 is active */
 
-       s3c_hsotg_enqueue_setup(hsotg);
+       dwc2_hsotg_enqueue_setup(hsotg);
 
        dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
-               readl(hsotg->regs + DIEPCTL0),
-               readl(hsotg->regs + DOEPCTL0));
+               dwc2_readl(hsotg->regs + DIEPCTL0),
+               dwc2_readl(hsotg->regs + DOEPCTL0));
 }
 
 /**
@@ -2142,34 +2158,34 @@ static void s3c_hsotg_irq_enumdone(struct dwc2_hsotg *hsotg)
  * completed with the given result code.
  */
 static void kill_all_requests(struct dwc2_hsotg *hsotg,
-                             struct s3c_hsotg_ep *ep,
+                             struct dwc2_hsotg_ep *ep,
                              int result)
 {
-       struct s3c_hsotg_req *req, *treq;
+       struct dwc2_hsotg_req *req, *treq;
        unsigned size;
 
        ep->req = NULL;
 
        list_for_each_entry_safe(req, treq, &ep->queue, queue)
-               s3c_hsotg_complete_request(hsotg, ep, req,
+               dwc2_hsotg_complete_request(hsotg, ep, req,
                                           result);
 
        if (!hsotg->dedicated_fifos)
                return;
-       size = (readl(hsotg->regs + DTXFSTS(ep->index)) & 0xffff) * 4;
+       size = (dwc2_readl(hsotg->regs + DTXFSTS(ep->index)) & 0xffff) * 4;
        if (size < ep->fifo_size)
-               s3c_hsotg_txfifo_flush(hsotg, ep->fifo_index);
+               dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index);
 }
 
 /**
- * s3c_hsotg_disconnect - disconnect service
+ * dwc2_hsotg_disconnect - disconnect service
  * @hsotg: The device state.
  *
  * The device has been disconnected. Remove all current
  * transactions and signal the gadget driver that this
  * has happened.
  */
-void s3c_hsotg_disconnect(struct dwc2_hsotg *hsotg)
+void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg)
 {
        unsigned ep;
 
@@ -2189,16 +2205,17 @@ void s3c_hsotg_disconnect(struct dwc2_hsotg *hsotg)
        }
 
        call_gadget(hsotg, disconnect);
+       hsotg->lx_state = DWC2_L3;
 }
 
 /**
- * s3c_hsotg_irq_fifoempty - TX FIFO empty interrupt handler
+ * dwc2_hsotg_irq_fifoempty - TX FIFO empty interrupt handler
  * @hsotg: The device state:
  * @periodic: True if this is a periodic FIFO interrupt
  */
-static void s3c_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic)
+static void dwc2_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic)
 {
-       struct s3c_hsotg_ep *ep;
+       struct dwc2_hsotg_ep *ep;
        int epno, ret;
 
        /* look through for any more data to transmit */
@@ -2215,7 +2232,7 @@ static void s3c_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic)
                    (!periodic && ep->periodic))
                        continue;
 
-               ret = s3c_hsotg_trytx(hsotg, ep);
+               ret = dwc2_hsotg_trytx(hsotg, ep);
                if (ret < 0)
                        break;
        }
@@ -2227,12 +2244,12 @@ static void s3c_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic)
                        GINTSTS_RXFLVL)
 
 /**
- * s3c_hsotg_corereset - issue softreset to the core
+ * dwc2_hsotg_corereset - issue softreset to the core
  * @hsotg: The device state
  *
  * Issue a soft reset to the core, and await the core finishing it.
  */
-static int s3c_hsotg_corereset(struct dwc2_hsotg *hsotg)
+static int dwc2_hsotg_corereset(struct dwc2_hsotg *hsotg)
 {
        int timeout;
        u32 grstctl;
@@ -2240,11 +2257,11 @@ static int s3c_hsotg_corereset(struct dwc2_hsotg *hsotg)
        dev_dbg(hsotg->dev, "resetting core\n");
 
        /* issue soft reset */
-       writel(GRSTCTL_CSFTRST, hsotg->regs + GRSTCTL);
+       dwc2_writel(GRSTCTL_CSFTRST, hsotg->regs + GRSTCTL);
 
        timeout = 10000;
        do {
-               grstctl = readl(hsotg->regs + GRSTCTL);
+               grstctl = dwc2_readl(hsotg->regs + GRSTCTL);
        } while ((grstctl & GRSTCTL_CSFTRST) && timeout-- > 0);
 
        if (grstctl & GRSTCTL_CSFTRST) {
@@ -2255,7 +2272,7 @@ static int s3c_hsotg_corereset(struct dwc2_hsotg *hsotg)
        timeout = 10000;
 
        while (1) {
-               u32 grstctl = readl(hsotg->regs + GRSTCTL);
+               u32 grstctl = dwc2_readl(hsotg->regs + GRSTCTL);
 
                if (timeout-- < 0) {
                        dev_info(hsotg->dev,
@@ -2275,18 +2292,23 @@ static int s3c_hsotg_corereset(struct dwc2_hsotg *hsotg)
 }
 
 /**
- * s3c_hsotg_core_init - issue softreset to the core
+ * dwc2_hsotg_core_init - issue softreset to the core
  * @hsotg: The device state
  *
  * Issue a soft reset to the core, and await the core finishing it.
  */
-void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
+void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
                                                bool is_usb_reset)
 {
+       u32 intmsk;
        u32 val;
 
+       /* Kill any ep0 requests as controller will be reinitialized */
+       kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
+
        if (!is_usb_reset)
-               s3c_hsotg_corereset(hsotg);
+               if (dwc2_hsotg_corereset(hsotg))
+                       return;
 
        /*
         * we must now enable ep0 ready for host detection and then
@@ -2295,39 +2317,42 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
 
        /* set the PLL on, remove the HNP/SRP and set the PHY */
        val = (hsotg->phyif == GUSBCFG_PHYIF8) ? 9 : 5;
-       writel(hsotg->phyif | GUSBCFG_TOUTCAL(7) |
+       dwc2_writel(hsotg->phyif | GUSBCFG_TOUTCAL(7) |
               (val << GUSBCFG_USBTRDTIM_SHIFT), hsotg->regs + GUSBCFG);
 
-       s3c_hsotg_init_fifo(hsotg);
+       dwc2_hsotg_init_fifo(hsotg);
 
        if (!is_usb_reset)
                __orr32(hsotg->regs + DCTL, DCTL_SFTDISCON);
 
-       writel(DCFG_EPMISCNT(1) | DCFG_DEVSPD_HS,  hsotg->regs + DCFG);
+       dwc2_writel(DCFG_EPMISCNT(1) | DCFG_DEVSPD_HS,  hsotg->regs + DCFG);
 
        /* Clear any pending OTG interrupts */
-       writel(0xffffffff, hsotg->regs + GOTGINT);
+       dwc2_writel(0xffffffff, hsotg->regs + GOTGINT);
 
        /* Clear any pending interrupts */
-       writel(0xffffffff, hsotg->regs + GINTSTS);
-
-       writel(GINTSTS_ERLYSUSP | GINTSTS_SESSREQINT |
+       dwc2_writel(0xffffffff, hsotg->regs + GINTSTS);
+       intmsk = GINTSTS_ERLYSUSP | GINTSTS_SESSREQINT |
                GINTSTS_GOUTNAKEFF | GINTSTS_GINNAKEFF |
-               GINTSTS_CONIDSTSCHNG | GINTSTS_USBRST |
-               GINTSTS_RESETDET | GINTSTS_ENUMDONE |
-               GINTSTS_OTGINT | GINTSTS_USBSUSP |
-               GINTSTS_WKUPINT,
-               hsotg->regs + GINTMSK);
+               GINTSTS_USBRST | GINTSTS_RESETDET |
+               GINTSTS_ENUMDONE | GINTSTS_OTGINT |
+               GINTSTS_USBSUSP | GINTSTS_WKUPINT |
+               GINTSTS_INCOMPL_SOIN | GINTSTS_INCOMPL_SOOUT;
+
+       if (hsotg->core_params->external_id_pin_ctl <= 0)
+               intmsk |= GINTSTS_CONIDSTSCHNG;
+
+       dwc2_writel(intmsk, hsotg->regs + GINTMSK);
 
        if (using_dma(hsotg))
-               writel(GAHBCFG_GLBL_INTR_EN | GAHBCFG_DMA_EN |
-                      (GAHBCFG_HBSTLEN_INCR4 << GAHBCFG_HBSTLEN_SHIFT),
-                      hsotg->regs + GAHBCFG);
+               dwc2_writel(GAHBCFG_GLBL_INTR_EN | GAHBCFG_DMA_EN |
+                           (GAHBCFG_HBSTLEN_INCR4 << GAHBCFG_HBSTLEN_SHIFT),
+                           hsotg->regs + GAHBCFG);
        else
-               writel(((hsotg->dedicated_fifos) ? (GAHBCFG_NP_TXF_EMP_LVL |
-                                                   GAHBCFG_P_TXF_EMP_LVL) : 0) |
-                      GAHBCFG_GLBL_INTR_EN,
-                      hsotg->regs + GAHBCFG);
+               dwc2_writel(((hsotg->dedicated_fifos) ?
+                                               (GAHBCFG_NP_TXF_EMP_LVL |
+                                                GAHBCFG_P_TXF_EMP_LVL) : 0) |
+                           GAHBCFG_GLBL_INTR_EN, hsotg->regs + GAHBCFG);
 
        /*
         * If INTknTXFEmpMsk is enabled, it's important to disable ep interrupts
@@ -2335,7 +2360,7 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
         * interrupts.
         */
 
-       writel(((hsotg->dedicated_fifos && !using_dma(hsotg)) ?
+       dwc2_writel(((hsotg->dedicated_fifos && !using_dma(hsotg)) ?
                DIEPMSK_TXFIFOEMPTY | DIEPMSK_INTKNTXFEMPMSK : 0) |
                DIEPMSK_EPDISBLDMSK | DIEPMSK_XFERCOMPLMSK |
                DIEPMSK_TIMEOUTMSK | DIEPMSK_AHBERRMSK |
@@ -2346,20 +2371,20 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
         * don't need XferCompl, we get that from RXFIFO in slave mode. In
         * DMA mode we may need this.
         */
-       writel((using_dma(hsotg) ? (DIEPMSK_XFERCOMPLMSK |
+       dwc2_writel((using_dma(hsotg) ? (DIEPMSK_XFERCOMPLMSK |
                                    DIEPMSK_TIMEOUTMSK) : 0) |
                DOEPMSK_EPDISBLDMSK | DOEPMSK_AHBERRMSK |
                DOEPMSK_SETUPMSK,
                hsotg->regs + DOEPMSK);
 
-       writel(0, hsotg->regs + DAINTMSK);
+       dwc2_writel(0, hsotg->regs + DAINTMSK);
 
        dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
-               readl(hsotg->regs + DIEPCTL0),
-               readl(hsotg->regs + DOEPCTL0));
+               dwc2_readl(hsotg->regs + DIEPCTL0),
+               dwc2_readl(hsotg->regs + DOEPCTL0));
 
        /* enable in and out endpoint interrupts */
-       s3c_hsotg_en_gsint(hsotg, GINTSTS_OEPINT | GINTSTS_IEPINT);
+       dwc2_hsotg_en_gsint(hsotg, GINTSTS_OEPINT | GINTSTS_IEPINT);
 
        /*
         * Enable the RXFIFO when in slave mode, as this is how we collect
@@ -2367,11 +2392,11 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
         * things we cannot process, so do not use it.
         */
        if (!using_dma(hsotg))
-               s3c_hsotg_en_gsint(hsotg, GINTSTS_RXFLVL);
+               dwc2_hsotg_en_gsint(hsotg, GINTSTS_RXFLVL);
 
        /* Enable interrupts for EP0 in and out */
-       s3c_hsotg_ctrl_epint(hsotg, 0, 0, 1);
-       s3c_hsotg_ctrl_epint(hsotg, 0, 1, 1);
+       dwc2_hsotg_ctrl_epint(hsotg, 0, 0, 1);
+       dwc2_hsotg_ctrl_epint(hsotg, 0, 1, 1);
 
        if (!is_usb_reset) {
                __orr32(hsotg->regs + DCTL, DCTL_PWRONPRGDONE);
@@ -2379,7 +2404,7 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
                __bic32(hsotg->regs + DCTL, DCTL_PWRONPRGDONE);
        }
 
-       dev_dbg(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + DCTL));
+       dev_dbg(hsotg->dev, "DCTL=0x%08x\n", dwc2_readl(hsotg->regs + DCTL));
 
        /*
         * DxEPCTL_USBActEp says RO in manual, but seems to be set by
@@ -2387,23 +2412,23 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
         */
 
        /* set to read 1 8byte packet */
-       writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
+       dwc2_writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
               DXEPTSIZ_XFERSIZE(8), hsotg->regs + DOEPTSIZ0);
 
-       writel(s3c_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) |
+       dwc2_writel(dwc2_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) |
               DXEPCTL_CNAK | DXEPCTL_EPENA |
               DXEPCTL_USBACTEP,
               hsotg->regs + DOEPCTL0);
 
        /* enable, but don't activate EP0in */
-       writel(s3c_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) |
+       dwc2_writel(dwc2_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) |
               DXEPCTL_USBACTEP, hsotg->regs + DIEPCTL0);
 
-       s3c_hsotg_enqueue_setup(hsotg);
+       dwc2_hsotg_enqueue_setup(hsotg);
 
        dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
-               readl(hsotg->regs + DIEPCTL0),
-               readl(hsotg->regs + DOEPCTL0));
+               dwc2_readl(hsotg->regs + DIEPCTL0),
+               dwc2_readl(hsotg->regs + DOEPCTL0));
 
        /* clear global NAKs */
        val = DCTL_CGOUTNAK | DCTL_CGNPINNAK;
@@ -2414,27 +2439,27 @@ void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
        /* must be at-least 3ms to allow bus to see disconnect */
        mdelay(3);
 
-       hsotg->last_rst = jiffies;
+       hsotg->lx_state = DWC2_L0;
 }
 
-static void s3c_hsotg_core_disconnect(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg)
 {
        /* set the soft-disconnect bit */
        __orr32(hsotg->regs + DCTL, DCTL_SFTDISCON);
 }
 
-void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg)
+void dwc2_hsotg_core_connect(struct dwc2_hsotg *hsotg)
 {
        /* remove the soft-disconnect and let's go */
        __bic32(hsotg->regs + DCTL, DCTL_SFTDISCON);
 }
 
 /**
- * s3c_hsotg_irq - handle device interrupt
+ * dwc2_hsotg_irq - handle device interrupt
  * @irq: The IRQ number triggered
  * @pw: The pw value when registered the handler.
  */
-static irqreturn_t s3c_hsotg_irq(int irq, void *pw)
+static irqreturn_t dwc2_hsotg_irq(int irq, void *pw)
 {
        struct dwc2_hsotg *hsotg = pw;
        int retry_count = 8;
@@ -2443,49 +2468,18 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw)
 
        spin_lock(&hsotg->lock);
 irq_retry:
-       gintsts = readl(hsotg->regs + GINTSTS);
-       gintmsk = readl(hsotg->regs + GINTMSK);
+       gintsts = dwc2_readl(hsotg->regs + GINTSTS);
+       gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
 
        dev_dbg(hsotg->dev, "%s: %08x %08x (%08x) retry %d\n",
                __func__, gintsts, gintsts & gintmsk, gintmsk, retry_count);
 
        gintsts &= gintmsk;
 
-       if (gintsts & GINTSTS_ENUMDONE) {
-               writel(GINTSTS_ENUMDONE, hsotg->regs + GINTSTS);
-
-               s3c_hsotg_irq_enumdone(hsotg);
-       }
-
-       if (gintsts & (GINTSTS_OEPINT | GINTSTS_IEPINT)) {
-               u32 daint = readl(hsotg->regs + DAINT);
-               u32 daintmsk = readl(hsotg->regs + DAINTMSK);
-               u32 daint_out, daint_in;
-               int ep;
-
-               daint &= daintmsk;
-               daint_out = daint >> DAINT_OUTEP_SHIFT;
-               daint_in = daint & ~(daint_out << DAINT_OUTEP_SHIFT);
-
-               dev_dbg(hsotg->dev, "%s: daint=%08x\n", __func__, daint);
-
-               for (ep = 0; ep < hsotg->num_of_eps && daint_out;
-                                               ep++, daint_out >>= 1) {
-                       if (daint_out & 1)
-                               s3c_hsotg_epint(hsotg, ep, 0);
-               }
-
-               for (ep = 0; ep < hsotg->num_of_eps  && daint_in;
-                                               ep++, daint_in >>= 1) {
-                       if (daint_in & 1)
-                               s3c_hsotg_epint(hsotg, ep, 1);
-               }
-       }
-
        if (gintsts & GINTSTS_RESETDET) {
                dev_dbg(hsotg->dev, "%s: USBRstDet\n", __func__);
 
-               writel(GINTSTS_RESETDET, hsotg->regs + GINTSTS);
+               dwc2_writel(GINTSTS_RESETDET, hsotg->regs + GINTSTS);
 
                /* This event must be used only if controller is suspended */
                if (hsotg->lx_state == DWC2_L2) {
@@ -2496,27 +2490,50 @@ irq_retry:
 
        if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET)) {
 
-               u32 usb_status = readl(hsotg->regs + GOTGCTL);
+               u32 usb_status = dwc2_readl(hsotg->regs + GOTGCTL);
+               u32 connected = hsotg->connected;
 
                dev_dbg(hsotg->dev, "%s: USBRst\n", __func__);
                dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
-                       readl(hsotg->regs + GNPTXSTS));
+                       dwc2_readl(hsotg->regs + GNPTXSTS));
 
-               writel(GINTSTS_USBRST, hsotg->regs + GINTSTS);
+               dwc2_writel(GINTSTS_USBRST, hsotg->regs + GINTSTS);
 
                /* Report disconnection if it is not already done. */
-               s3c_hsotg_disconnect(hsotg);
+               dwc2_hsotg_disconnect(hsotg);
+
+               if (usb_status & GOTGCTL_BSESVLD && connected)
+                       dwc2_hsotg_core_init_disconnected(hsotg, true);
+       }
 
-               if (usb_status & GOTGCTL_BSESVLD) {
-                       if (time_after(jiffies, hsotg->last_rst +
-                                      msecs_to_jiffies(200))) {
+       if (gintsts & GINTSTS_ENUMDONE) {
+               dwc2_writel(GINTSTS_ENUMDONE, hsotg->regs + GINTSTS);
 
-                               kill_all_requests(hsotg, hsotg->eps_out[0],
-                                                         -ECONNRESET);
+               dwc2_hsotg_irq_enumdone(hsotg);
+       }
 
-                               hsotg->lx_state = DWC2_L0;
-                               s3c_hsotg_core_init_disconnected(hsotg, true);
-                       }
+       if (gintsts & (GINTSTS_OEPINT | GINTSTS_IEPINT)) {
+               u32 daint = dwc2_readl(hsotg->regs + DAINT);
+               u32 daintmsk = dwc2_readl(hsotg->regs + DAINTMSK);
+               u32 daint_out, daint_in;
+               int ep;
+
+               daint &= daintmsk;
+               daint_out = daint >> DAINT_OUTEP_SHIFT;
+               daint_in = daint & ~(daint_out << DAINT_OUTEP_SHIFT);
+
+               dev_dbg(hsotg->dev, "%s: daint=%08x\n", __func__, daint);
+
+               for (ep = 0; ep < hsotg->num_of_eps && daint_out;
+                                               ep++, daint_out >>= 1) {
+                       if (daint_out & 1)
+                               dwc2_hsotg_epint(hsotg, ep, 0);
+               }
+
+               for (ep = 0; ep < hsotg->num_of_eps  && daint_in;
+                                               ep++, daint_in >>= 1) {
+                       if (daint_in & 1)
+                               dwc2_hsotg_epint(hsotg, ep, 1);
                }
        }
 
@@ -2531,8 +2548,8 @@ irq_retry:
                 * it needs re-enabling
                 */
 
-               s3c_hsotg_disable_gsint(hsotg, GINTSTS_NPTXFEMP);
-               s3c_hsotg_irq_fifoempty(hsotg, false);
+               dwc2_hsotg_disable_gsint(hsotg, GINTSTS_NPTXFEMP);
+               dwc2_hsotg_irq_fifoempty(hsotg, false);
        }
 
        if (gintsts & GINTSTS_PTXFEMP) {
@@ -2540,23 +2557,23 @@ irq_retry:
 
                /* See note in GINTSTS_NPTxFEmp */
 
-               s3c_hsotg_disable_gsint(hsotg, GINTSTS_PTXFEMP);
-               s3c_hsotg_irq_fifoempty(hsotg, true);
+               dwc2_hsotg_disable_gsint(hsotg, GINTSTS_PTXFEMP);
+               dwc2_hsotg_irq_fifoempty(hsotg, true);
        }
 
        if (gintsts & GINTSTS_RXFLVL) {
                /*
                 * note, since GINTSTS_RxFLvl doubles as FIFO-not-empty,
-                * we need to retry s3c_hsotg_handle_rx if this is still
+                * we need to retry dwc2_hsotg_handle_rx if this is still
                 * set.
                 */
 
-               s3c_hsotg_handle_rx(hsotg);
+               dwc2_hsotg_handle_rx(hsotg);
        }
 
        if (gintsts & GINTSTS_ERLYSUSP) {
                dev_dbg(hsotg->dev, "GINTSTS_ErlySusp\n");
-               writel(GINTSTS_ERLYSUSP, hsotg->regs + GINTSTS);
+               dwc2_writel(GINTSTS_ERLYSUSP, hsotg->regs + GINTSTS);
        }
 
        /*
@@ -2568,17 +2585,51 @@ irq_retry:
        if (gintsts & GINTSTS_GOUTNAKEFF) {
                dev_info(hsotg->dev, "GOUTNakEff triggered\n");
 
-               writel(DCTL_CGOUTNAK, hsotg->regs + DCTL);
+               dwc2_writel(DCTL_CGOUTNAK, hsotg->regs + DCTL);
 
-               s3c_hsotg_dump(hsotg);
+               dwc2_hsotg_dump(hsotg);
        }
 
        if (gintsts & GINTSTS_GINNAKEFF) {
                dev_info(hsotg->dev, "GINNakEff triggered\n");
 
-               writel(DCTL_CGNPINNAK, hsotg->regs + DCTL);
+               dwc2_writel(DCTL_CGNPINNAK, hsotg->regs + DCTL);
+
+               dwc2_hsotg_dump(hsotg);
+       }
+
+       if (gintsts & GINTSTS_INCOMPL_SOIN) {
+               u32 idx, epctl_reg;
+               struct dwc2_hsotg_ep *hs_ep;
+
+               dev_dbg(hsotg->dev, "%s: GINTSTS_INCOMPL_SOIN\n", __func__);
+               for (idx = 1; idx < hsotg->num_of_eps; idx++) {
+                       hs_ep = hsotg->eps_in[idx];
+
+                       if (!hs_ep->isochronous || hs_ep->has_correct_parity)
+                               continue;
+
+                       epctl_reg = DIEPCTL(idx);
+                       dwc2_hsotg_change_ep_iso_parity(hsotg, epctl_reg);
+               }
+               dwc2_writel(GINTSTS_INCOMPL_SOIN, hsotg->regs + GINTSTS);
+       }
+
+       if (gintsts & GINTSTS_INCOMPL_SOOUT) {
+               u32 idx, epctl_reg;
+               struct dwc2_hsotg_ep *hs_ep;
 
-               s3c_hsotg_dump(hsotg);
+               dev_dbg(hsotg->dev, "%s: GINTSTS_INCOMPL_SOOUT\n", __func__);
+               for (idx = 1; idx < hsotg->num_of_eps; idx++) {
+                       hs_ep = hsotg->eps_out[idx];
+
+                       if (!hs_ep->isochronous || hs_ep->has_correct_parity)
+                               continue;
+
+                       epctl_reg = DOEPCTL(idx);
+                       dwc2_hsotg_change_ep_iso_parity(hsotg, epctl_reg);
+               }
+               dwc2_writel(GINTSTS_INCOMPL_SOOUT, hsotg->regs + GINTSTS);
        }
 
        /*
@@ -2595,16 +2646,16 @@ irq_retry:
 }
 
 /**
- * s3c_hsotg_ep_enable - enable the given endpoint
+ * dwc2_hsotg_ep_enable - enable the given endpoint
  * @ep: The USB endpint to configure
  * @desc: The USB endpoint descriptor to configure with.
  *
  * This is called from the USB gadget code's usb_ep_enable().
  */
-static int s3c_hsotg_ep_enable(struct usb_ep *ep,
+static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
                               const struct usb_endpoint_descriptor *desc)
 {
-       struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+       struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
        struct dwc2_hsotg *hsotg = hs_ep->parent;
        unsigned long flags;
        unsigned int index = hs_ep->index;
@@ -2631,10 +2682,10 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
 
        mps = usb_endpoint_maxp(desc);
 
-       /* note, we handle this here instead of s3c_hsotg_set_ep_maxpacket */
+       /* note, we handle this here instead of dwc2_hsotg_set_ep_maxpacket */
 
        epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
-       epctrl = readl(hsotg->regs + epctrl_reg);
+       epctrl = dwc2_readl(hsotg->regs + epctrl_reg);
 
        dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x from 0x%08x\n",
                __func__, epctrl, epctrl_reg);
@@ -2660,13 +2711,14 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
        epctrl |= DXEPCTL_SNAK;
 
        /* update the endpoint state */
-       s3c_hsotg_set_ep_maxpacket(hsotg, hs_ep->index, mps, dir_in);
+       dwc2_hsotg_set_ep_maxpacket(hsotg, hs_ep->index, mps, dir_in);
 
        /* default, set to non-periodic */
        hs_ep->isochronous = 0;
        hs_ep->periodic = 0;
        hs_ep->halted = 0;
        hs_ep->interval = desc->bInterval;
+       hs_ep->has_correct_parity = 0;
 
        if (hs_ep->interval > 1 && hs_ep->mc > 1)
                dev_err(hsotg->dev, "MC > 1 when interval is not 1\n");
@@ -2718,7 +2770,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
                for (i = 1; i < hsotg->num_of_eps; ++i) {
                        if (hsotg->fifo_map & (1<<i))
                                continue;
-                       val = readl(hsotg->regs + DPTXFSIZN(i));
+                       val = dwc2_readl(hsotg->regs + DPTXFSIZN(i));
                        val = (val >> FIFOSIZE_DEPTH_SHIFT)*4;
                        if (val < size)
                                continue;
@@ -2747,12 +2799,12 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
        dev_dbg(hsotg->dev, "%s: write DxEPCTL=0x%08x\n",
                __func__, epctrl);
 
-       writel(epctrl, hsotg->regs + epctrl_reg);
+       dwc2_writel(epctrl, hsotg->regs + epctrl_reg);
        dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x\n",
-               __func__, readl(hsotg->regs + epctrl_reg));
+               __func__, dwc2_readl(hsotg->regs + epctrl_reg));
 
        /* enable the endpoint interrupt */
-       s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1);
+       dwc2_hsotg_ctrl_epint(hsotg, index, dir_in, 1);
 
 error:
        spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -2760,12 +2812,12 @@ error:
 }
 
 /**
- * s3c_hsotg_ep_disable - disable given endpoint
+ * dwc2_hsotg_ep_disable - disable given endpoint
  * @ep: The endpoint to disable.
  */
-static int s3c_hsotg_ep_disable(struct usb_ep *ep)
+static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
 {
-       struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+       struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
        struct dwc2_hsotg *hsotg = hs_ep->parent;
        int dir_in = hs_ep->dir_in;
        int index = hs_ep->index;
@@ -2788,16 +2840,16 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep)
        hs_ep->fifo_index = 0;
        hs_ep->fifo_size = 0;
 
-       ctrl = readl(hsotg->regs + epctrl_reg);
+       ctrl = dwc2_readl(hsotg->regs + epctrl_reg);
        ctrl &= ~DXEPCTL_EPENA;
        ctrl &= ~DXEPCTL_USBACTEP;
        ctrl |= DXEPCTL_SNAK;
 
        dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl);
-       writel(ctrl, hsotg->regs + epctrl_reg);
+       dwc2_writel(ctrl, hsotg->regs + epctrl_reg);
 
        /* disable endpoint interrupts */
-       s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0);
+       dwc2_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0);
 
        /* terminate all requests with shutdown */
        kill_all_requests(hsotg, hs_ep, -ESHUTDOWN);
@@ -2811,9 +2863,9 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep)
  * @ep: The endpoint to check.
  * @test: The request to test if it is on the endpoint.
  */
-static bool on_list(struct s3c_hsotg_ep *ep, struct s3c_hsotg_req *test)
+static bool on_list(struct dwc2_hsotg_ep *ep, struct dwc2_hsotg_req *test)
 {
-       struct s3c_hsotg_req *req, *treq;
+       struct dwc2_hsotg_req *req, *treq;
 
        list_for_each_entry_safe(req, treq, &ep->queue, queue) {
                if (req == test)
@@ -2823,15 +2875,88 @@ static bool on_list(struct s3c_hsotg_ep *ep, struct s3c_hsotg_req *test)
        return false;
 }
 
+static int dwc2_hsotg_wait_bit_set(struct dwc2_hsotg *hs_otg, u32 reg,
+                                                       u32 bit, u32 timeout)
+{
+       u32 i;
+
+       for (i = 0; i < timeout; i++) {
+               if (dwc2_readl(hs_otg->regs + reg) & bit)
+                       return 0;
+               udelay(1);
+       }
+
+       return -ETIMEDOUT;
+}
+
+static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg,
+                                               struct dwc2_hsotg_ep *hs_ep)
+{
+       u32 epctrl_reg;
+       u32 epint_reg;
+
+       epctrl_reg = hs_ep->dir_in ? DIEPCTL(hs_ep->index) :
+               DOEPCTL(hs_ep->index);
+       epint_reg = hs_ep->dir_in ? DIEPINT(hs_ep->index) :
+               DOEPINT(hs_ep->index);
+
+       dev_dbg(hsotg->dev, "%s: stopping transfer on %s\n", __func__,
+                       hs_ep->name);
+       if (hs_ep->dir_in) {
+               __orr32(hsotg->regs + epctrl_reg, DXEPCTL_SNAK);
+               /* Wait for Nak effect */
+               if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg,
+                                               DXEPINT_INEPNAKEFF, 100))
+                       dev_warn(hsotg->dev,
+                               "%s: timeout DIEPINT.NAKEFF\n", __func__);
+       } else {
+               /* Clear any pending nak effect interrupt */
+               dwc2_writel(GINTSTS_GINNAKEFF, hsotg->regs + GINTSTS);
+
+               __orr32(hsotg->regs + DCTL, DCTL_SGNPINNAK);
+
+               /* Wait for global nak to take effect */
+               if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS,
+                                               GINTSTS_GINNAKEFF, 100))
+                       dev_warn(hsotg->dev,
+                               "%s: timeout GINTSTS.GINNAKEFF\n", __func__);
+       }
+
+       /* Disable ep */
+       __orr32(hsotg->regs + epctrl_reg, DXEPCTL_EPDIS | DXEPCTL_SNAK);
+
+       /* Wait for ep to be disabled */
+       if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg, DXEPINT_EPDISBLD, 100))
+               dev_warn(hsotg->dev,
+                       "%s: timeout DOEPCTL.EPDisable\n", __func__);
+
+       if (hs_ep->dir_in) {
+               if (hsotg->dedicated_fifos) {
+                       dwc2_writel(GRSTCTL_TXFNUM(hs_ep->fifo_index) |
+                               GRSTCTL_TXFFLSH, hsotg->regs + GRSTCTL);
+                       /* Wait for fifo flush */
+                       if (dwc2_hsotg_wait_bit_set(hsotg, GRSTCTL,
+                                                       GRSTCTL_TXFFLSH, 100))
+                               dev_warn(hsotg->dev,
+                                       "%s: timeout flushing fifos\n",
+                                       __func__);
+               }
+               /* TODO: Flush shared tx fifo */
+       } else {
+               /* Remove global NAKs */
+               __bic32(hsotg->regs + DCTL, DCTL_SGNPINNAK);
+       }
+}
+
 /**
- * s3c_hsotg_ep_dequeue - dequeue given endpoint
+ * dwc2_hsotg_ep_dequeue - dequeue given endpoint
  * @ep: The endpoint to dequeue.
  * @req: The request to be removed from a queue.
  */
-static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
+static int dwc2_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
 {
-       struct s3c_hsotg_req *hs_req = our_req(req);
-       struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+       struct dwc2_hsotg_req *hs_req = our_req(req);
+       struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
        struct dwc2_hsotg *hs = hs_ep->parent;
        unsigned long flags;
 
@@ -2844,20 +2969,24 @@ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
                return -EINVAL;
        }
 
-       s3c_hsotg_complete_request(hs, hs_ep, hs_req, -ECONNRESET);
+       /* Dequeue already started request */
+       if (req == &hs_ep->req->req)
+               dwc2_hsotg_ep_stop_xfr(hs, hs_ep);
+
+       dwc2_hsotg_complete_request(hs, hs_ep, hs_req, -ECONNRESET);
        spin_unlock_irqrestore(&hs->lock, flags);
 
        return 0;
 }
 
 /**
- * s3c_hsotg_ep_sethalt - set halt on a given endpoint
+ * dwc2_hsotg_ep_sethalt - set halt on a given endpoint
  * @ep: The endpoint to set halt.
  * @value: Set or unset the halt.
  */
-static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
+static int dwc2_hsotg_ep_sethalt(struct usb_ep *ep, int value)
 {
-       struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+       struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
        struct dwc2_hsotg *hs = hs_ep->parent;
        int index = hs_ep->index;
        u32 epreg;
@@ -2868,7 +2997,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
 
        if (index == 0) {
                if (value)
-                       s3c_hsotg_stall_ep0(hs);
+                       dwc2_hsotg_stall_ep0(hs);
                else
                        dev_warn(hs->dev,
                                 "%s: can't clear halt on ep0\n", __func__);
@@ -2877,7 +3006,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
 
        if (hs_ep->dir_in) {
                epreg = DIEPCTL(index);
-               epctl = readl(hs->regs + epreg);
+               epctl = dwc2_readl(hs->regs + epreg);
 
                if (value) {
                        epctl |= DXEPCTL_STALL | DXEPCTL_SNAK;
@@ -2890,11 +3019,11 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
                                xfertype == DXEPCTL_EPTYPE_INTERRUPT)
                                        epctl |= DXEPCTL_SETD0PID;
                }
-               writel(epctl, hs->regs + epreg);
+               dwc2_writel(epctl, hs->regs + epreg);
        } else {
 
                epreg = DOEPCTL(index);
-               epctl = readl(hs->regs + epreg);
+               epctl = dwc2_readl(hs->regs + epreg);
 
                if (value)
                        epctl |= DXEPCTL_STALL;
@@ -2905,7 +3034,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
                                xfertype == DXEPCTL_EPTYPE_INTERRUPT)
                                        epctl |= DXEPCTL_SETD0PID;
                }
-               writel(epctl, hs->regs + epreg);
+               dwc2_writel(epctl, hs->regs + epreg);
        }
 
        hs_ep->halted = value;
@@ -2914,97 +3043,53 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
 }
 
 /**
- * s3c_hsotg_ep_sethalt_lock - set halt on a given endpoint with lock held
+ * dwc2_hsotg_ep_sethalt_lock - set halt on a given endpoint with lock held
  * @ep: The endpoint to set halt.
  * @value: Set or unset the halt.
  */
-static int s3c_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value)
+static int dwc2_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value)
 {
-       struct s3c_hsotg_ep *hs_ep = our_ep(ep);
+       struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
        struct dwc2_hsotg *hs = hs_ep->parent;
        unsigned long flags = 0;
        int ret = 0;
 
        spin_lock_irqsave(&hs->lock, flags);
-       ret = s3c_hsotg_ep_sethalt(ep, value);
+       ret = dwc2_hsotg_ep_sethalt(ep, value);
        spin_unlock_irqrestore(&hs->lock, flags);
 
        return ret;
 }
 
-static struct usb_ep_ops s3c_hsotg_ep_ops = {
-       .enable         = s3c_hsotg_ep_enable,
-       .disable        = s3c_hsotg_ep_disable,
-       .alloc_request  = s3c_hsotg_ep_alloc_request,
-       .free_request   = s3c_hsotg_ep_free_request,
-       .queue          = s3c_hsotg_ep_queue_lock,
-       .dequeue        = s3c_hsotg_ep_dequeue,
-       .set_halt       = s3c_hsotg_ep_sethalt_lock,
+static struct usb_ep_ops dwc2_hsotg_ep_ops = {
+       .enable         = dwc2_hsotg_ep_enable,
+       .disable        = dwc2_hsotg_ep_disable,
+       .alloc_request  = dwc2_hsotg_ep_alloc_request,
+       .free_request   = dwc2_hsotg_ep_free_request,
+       .queue          = dwc2_hsotg_ep_queue_lock,
+       .dequeue        = dwc2_hsotg_ep_dequeue,
+       .set_halt       = dwc2_hsotg_ep_sethalt_lock,
        /* note, don't believe we have any call for the fifo routines */
 };
 
 /**
- * s3c_hsotg_phy_enable - enable platform phy dev
- * @hsotg: The driver state
- *
- * A wrapper for platform code responsible for controlling
- * low-level USB code
- */
-static void s3c_hsotg_phy_enable(struct dwc2_hsotg *hsotg)
-{
-       struct platform_device *pdev = to_platform_device(hsotg->dev);
-
-       dev_dbg(hsotg->dev, "pdev 0x%p\n", pdev);
-
-       if (hsotg->uphy)
-               usb_phy_init(hsotg->uphy);
-       else if (hsotg->plat && hsotg->plat->phy_init)
-               hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
-       else {
-               phy_init(hsotg->phy);
-               phy_power_on(hsotg->phy);
-       }
-}
-
-/**
- * s3c_hsotg_phy_disable - disable platform phy dev
- * @hsotg: The driver state
- *
- * A wrapper for platform code responsible for controlling
- * low-level USB code
- */
-static void s3c_hsotg_phy_disable(struct dwc2_hsotg *hsotg)
-{
-       struct platform_device *pdev = to_platform_device(hsotg->dev);
-
-       if (hsotg->uphy)
-               usb_phy_shutdown(hsotg->uphy);
-       else if (hsotg->plat && hsotg->plat->phy_exit)
-               hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
-       else {
-               phy_power_off(hsotg->phy);
-               phy_exit(hsotg->phy);
-       }
-}
-
-/**
- * s3c_hsotg_init - initalize the usb core
+ * dwc2_hsotg_init - initalize the usb core
  * @hsotg: The driver state
  */
-static void s3c_hsotg_init(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_init(struct dwc2_hsotg *hsotg)
 {
        u32 trdtim;
        /* unmask subset of endpoint interrupts */
 
-       writel(DIEPMSK_TIMEOUTMSK | DIEPMSK_AHBERRMSK |
-               DIEPMSK_EPDISBLDMSK | DIEPMSK_XFERCOMPLMSK,
-               hsotg->regs + DIEPMSK);
+       dwc2_writel(DIEPMSK_TIMEOUTMSK | DIEPMSK_AHBERRMSK |
+                   DIEPMSK_EPDISBLDMSK | DIEPMSK_XFERCOMPLMSK,
+                   hsotg->regs + DIEPMSK);
 
-       writel(DOEPMSK_SETUPMSK | DOEPMSK_AHBERRMSK |
-               DOEPMSK_EPDISBLDMSK | DOEPMSK_XFERCOMPLMSK,
-               hsotg->regs + DOEPMSK);
+       dwc2_writel(DOEPMSK_SETUPMSK | DOEPMSK_AHBERRMSK |
+                   DOEPMSK_EPDISBLDMSK | DOEPMSK_XFERCOMPLMSK,
+                   hsotg->regs + DOEPMSK);
 
-       writel(0, hsotg->regs + DAINTMSK);
+       dwc2_writel(0, hsotg->regs + DAINTMSK);
 
        /* Be in disconnected state until gadget is registered */
        __orr32(hsotg->regs + DCTL, DCTL_SFTDISCON);
@@ -3012,14 +3097,14 @@ static void s3c_hsotg_init(struct dwc2_hsotg *hsotg)
        /* setup fifos */
 
        dev_dbg(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n",
-               readl(hsotg->regs + GRXFSIZ),
-               readl(hsotg->regs + GNPTXFSIZ));
+               dwc2_readl(hsotg->regs + GRXFSIZ),
+               dwc2_readl(hsotg->regs + GNPTXFSIZ));
 
-       s3c_hsotg_init_fifo(hsotg);
+       dwc2_hsotg_init_fifo(hsotg);
 
        /* set the PLL on, remove the HNP/SRP and set the PHY */
        trdtim = (hsotg->phyif == GUSBCFG_PHYIF8) ? 9 : 5;
-       writel(hsotg->phyif | GUSBCFG_TOUTCAL(7) |
+       dwc2_writel(hsotg->phyif | GUSBCFG_TOUTCAL(7) |
                (trdtim << GUSBCFG_USBTRDTIM_SHIFT),
                hsotg->regs + GUSBCFG);
 
@@ -3028,14 +3113,14 @@ static void s3c_hsotg_init(struct dwc2_hsotg *hsotg)
 }
 
 /**
- * s3c_hsotg_udc_start - prepare the udc for work
+ * dwc2_hsotg_udc_start - prepare the udc for work
  * @gadget: The usb gadget state
  * @driver: The usb gadget driver
  *
  * Perform initialization to prepare udc device and driver
  * to work.
  */
-static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
+static int dwc2_hsotg_udc_start(struct usb_gadget *gadget,
                           struct usb_gadget_driver *driver)
 {
        struct dwc2_hsotg *hsotg = to_hsotg(gadget);
@@ -3060,7 +3145,6 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
                return -EINVAL;
        }
 
-       mutex_lock(&hsotg->init_mutex);
        WARN_ON(hsotg->driver);
 
        driver->driver.bus = NULL;
@@ -3068,45 +3152,38 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
        hsotg->gadget.dev.of_node = hsotg->dev->of_node;
        hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 
-       clk_enable(hsotg->clk);
-
-       ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
-                                   hsotg->supplies);
-       if (ret) {
-               dev_err(hsotg->dev, "failed to enable supplies: %d\n", ret);
-               goto err;
+       if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) {
+               ret = dwc2_lowlevel_hw_enable(hsotg);
+               if (ret)
+                       goto err;
        }
 
-       s3c_hsotg_phy_enable(hsotg);
        if (!IS_ERR_OR_NULL(hsotg->uphy))
                otg_set_peripheral(hsotg->uphy->otg, &hsotg->gadget);
 
        spin_lock_irqsave(&hsotg->lock, flags);
-       s3c_hsotg_init(hsotg);
-       s3c_hsotg_core_init_disconnected(hsotg, false);
+       dwc2_hsotg_init(hsotg);
+       dwc2_hsotg_core_init_disconnected(hsotg, false);
        hsotg->enabled = 0;
        spin_unlock_irqrestore(&hsotg->lock, flags);
 
        dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name);
 
-       mutex_unlock(&hsotg->init_mutex);
-
        return 0;
 
 err:
-       mutex_unlock(&hsotg->init_mutex);
        hsotg->driver = NULL;
        return ret;
 }
 
 /**
- * s3c_hsotg_udc_stop - stop the udc
+ * dwc2_hsotg_udc_stop - stop the udc
  * @gadget: The usb gadget state
  * @driver: The usb gadget driver
  *
  * Stop udc hw block and stay tunned for future transmissions
  */
-static int s3c_hsotg_udc_stop(struct usb_gadget *gadget)
+static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget)
 {
        struct dwc2_hsotg *hsotg = to_hsotg(gadget);
        unsigned long flags = 0;
@@ -3115,14 +3192,12 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget)
        if (!hsotg)
                return -ENODEV;
 
-       mutex_lock(&hsotg->init_mutex);
-
        /* all endpoints should be shutdown */
        for (ep = 1; ep < hsotg->num_of_eps; ep++) {
                if (hsotg->eps_in[ep])
-                       s3c_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
+                       dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
                if (hsotg->eps_out[ep])
-                       s3c_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
+                       dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
        }
 
        spin_lock_irqsave(&hsotg->lock, flags);
@@ -3135,64 +3210,63 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget)
 
        if (!IS_ERR_OR_NULL(hsotg->uphy))
                otg_set_peripheral(hsotg->uphy->otg, NULL);
-       s3c_hsotg_phy_disable(hsotg);
 
-       regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
-
-       clk_disable(hsotg->clk);
-
-       mutex_unlock(&hsotg->init_mutex);
+       if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
+               dwc2_lowlevel_hw_disable(hsotg);
 
        return 0;
 }
 
 /**
- * s3c_hsotg_gadget_getframe - read the frame number
+ * dwc2_hsotg_gadget_getframe - read the frame number
  * @gadget: The usb gadget state
  *
  * Read the {micro} frame number
  */
-static int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget)
+static int dwc2_hsotg_gadget_getframe(struct usb_gadget *gadget)
 {
-       return s3c_hsotg_read_frameno(to_hsotg(gadget));
+       return dwc2_hsotg_read_frameno(to_hsotg(gadget));
 }
 
 /**
- * s3c_hsotg_pullup - connect/disconnect the USB PHY
+ * dwc2_hsotg_pullup - connect/disconnect the USB PHY
  * @gadget: The usb gadget state
  * @is_on: Current state of the USB PHY
  *
  * Connect/Disconnect the USB PHY pullup
  */
-static int s3c_hsotg_pullup(struct usb_gadget *gadget, int is_on)
+static int dwc2_hsotg_pullup(struct usb_gadget *gadget, int is_on)
 {
        struct dwc2_hsotg *hsotg = to_hsotg(gadget);
        unsigned long flags = 0;
 
-       dev_dbg(hsotg->dev, "%s: is_on: %d\n", __func__, is_on);
+       dev_dbg(hsotg->dev, "%s: is_on: %d op_state: %d\n", __func__, is_on,
+                       hsotg->op_state);
+
+       /* Don't modify pullup state while in host mode */
+       if (hsotg->op_state != OTG_STATE_B_PERIPHERAL) {
+               hsotg->enabled = is_on;
+               return 0;
+       }
 
-       mutex_lock(&hsotg->init_mutex);
        spin_lock_irqsave(&hsotg->lock, flags);
        if (is_on) {
-               clk_enable(hsotg->clk);
                hsotg->enabled = 1;
-               s3c_hsotg_core_init_disconnected(hsotg, false);
-               s3c_hsotg_core_connect(hsotg);
+               dwc2_hsotg_core_init_disconnected(hsotg, false);
+               dwc2_hsotg_core_connect(hsotg);
        } else {
-               s3c_hsotg_core_disconnect(hsotg);
-               s3c_hsotg_disconnect(hsotg);
+               dwc2_hsotg_core_disconnect(hsotg);
+               dwc2_hsotg_disconnect(hsotg);
                hsotg->enabled = 0;
-               clk_disable(hsotg->clk);
        }
 
        hsotg->gadget.speed = USB_SPEED_UNKNOWN;
        spin_unlock_irqrestore(&hsotg->lock, flags);
-       mutex_unlock(&hsotg->init_mutex);
 
        return 0;
 }
 
-static int s3c_hsotg_vbus_session(struct usb_gadget *gadget, int is_active)
+static int dwc2_hsotg_vbus_session(struct usb_gadget *gadget, int is_active)
 {
        struct dwc2_hsotg *hsotg = to_hsotg(gadget);
        unsigned long flags;
@@ -3200,23 +3274,22 @@ static int s3c_hsotg_vbus_session(struct usb_gadget *gadget, int is_active)
        dev_dbg(hsotg->dev, "%s: is_active: %d\n", __func__, is_active);
        spin_lock_irqsave(&hsotg->lock, flags);
 
+       /*
+        * If controller is hibernated, it must exit from hibernation
+        * before being initialized / de-initialized
+        */
+       if (hsotg->lx_state == DWC2_L2)
+               dwc2_exit_hibernation(hsotg, false);
+
        if (is_active) {
-               /*
-                * If controller is hibernated, it must exit from hibernation
-                * before being initialized
-                */
-               if (hsotg->lx_state == DWC2_L2) {
-                       dwc2_exit_hibernation(hsotg, false);
-                       hsotg->lx_state = DWC2_L0;
-               }
-               /* Kill any ep0 requests as controller will be reinitialized */
-               kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
-               s3c_hsotg_core_init_disconnected(hsotg, false);
+               hsotg->op_state = OTG_STATE_B_PERIPHERAL;
+
+               dwc2_hsotg_core_init_disconnected(hsotg, false);
                if (hsotg->enabled)
-                       s3c_hsotg_core_connect(hsotg);
+                       dwc2_hsotg_core_connect(hsotg);
        } else {
-               s3c_hsotg_core_disconnect(hsotg);
-               s3c_hsotg_disconnect(hsotg);
+               dwc2_hsotg_core_disconnect(hsotg);
+               dwc2_hsotg_disconnect(hsotg);
        }
 
        spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -3224,13 +3297,13 @@ static int s3c_hsotg_vbus_session(struct usb_gadget *gadget, int is_active)
 }
 
 /**
- * s3c_hsotg_vbus_draw - report bMaxPower field
+ * dwc2_hsotg_vbus_draw - report bMaxPower field
  * @gadget: The usb gadget state
  * @mA: Amount of current
  *
  * Report how much power the device may consume to the phy.
  */
-static int s3c_hsotg_vbus_draw(struct usb_gadget *gadget, unsigned mA)
+static int dwc2_hsotg_vbus_draw(struct usb_gadget *gadget, unsigned mA)
 {
        struct dwc2_hsotg *hsotg = to_hsotg(gadget);
 
@@ -3239,17 +3312,17 @@ static int s3c_hsotg_vbus_draw(struct usb_gadget *gadget, unsigned mA)
        return usb_phy_set_power(hsotg->uphy, mA);
 }
 
-static const struct usb_gadget_ops s3c_hsotg_gadget_ops = {
-       .get_frame      = s3c_hsotg_gadget_getframe,
-       .udc_start              = s3c_hsotg_udc_start,
-       .udc_stop               = s3c_hsotg_udc_stop,
-       .pullup                 = s3c_hsotg_pullup,
-       .vbus_session           = s3c_hsotg_vbus_session,
-       .vbus_draw              = s3c_hsotg_vbus_draw,
+static const struct usb_gadget_ops dwc2_hsotg_gadget_ops = {
+       .get_frame      = dwc2_hsotg_gadget_getframe,
+       .udc_start              = dwc2_hsotg_udc_start,
+       .udc_stop               = dwc2_hsotg_udc_stop,
+       .pullup                 = dwc2_hsotg_pullup,
+       .vbus_session           = dwc2_hsotg_vbus_session,
+       .vbus_draw              = dwc2_hsotg_vbus_draw,
 };
 
 /**
- * s3c_hsotg_initep - initialise a single endpoint
+ * dwc2_hsotg_initep - initialise a single endpoint
  * @hsotg: The device state.
  * @hs_ep: The endpoint to be initialised.
  * @epnum: The endpoint number
@@ -3258,8 +3331,8 @@ static const struct usb_gadget_ops s3c_hsotg_gadget_ops = {
  * creation) to give to the gadget driver. Setup the endpoint name, any
  * direction information and other state that may be required.
  */
-static void s3c_hsotg_initep(struct dwc2_hsotg *hsotg,
-                                      struct s3c_hsotg_ep *hs_ep,
+static void dwc2_hsotg_initep(struct dwc2_hsotg *hsotg,
+                                      struct dwc2_hsotg_ep *hs_ep,
                                       int epnum,
                                       bool dir_in)
 {
@@ -3287,7 +3360,7 @@ static void s3c_hsotg_initep(struct dwc2_hsotg *hsotg,
        hs_ep->parent = hsotg;
        hs_ep->ep.name = hs_ep->name;
        usb_ep_set_maxpacket_limit(&hs_ep->ep, epnum ? 1024 : EP0_MPS_LIMIT);
-       hs_ep->ep.ops = &s3c_hsotg_ep_ops;
+       hs_ep->ep.ops = &dwc2_hsotg_ep_ops;
 
        if (epnum == 0) {
                hs_ep->ep.caps.type_control = true;
@@ -3310,19 +3383,19 @@ static void s3c_hsotg_initep(struct dwc2_hsotg *hsotg,
        if (using_dma(hsotg)) {
                u32 next = DXEPCTL_NEXTEP((epnum + 1) % 15);
                if (dir_in)
-                       writel(next, hsotg->regs + DIEPCTL(epnum));
+                       dwc2_writel(next, hsotg->regs + DIEPCTL(epnum));
                else
-                       writel(next, hsotg->regs + DOEPCTL(epnum));
+                       dwc2_writel(next, hsotg->regs + DOEPCTL(epnum));
        }
 }
 
 /**
- * s3c_hsotg_hw_cfg - read HW configuration registers
+ * dwc2_hsotg_hw_cfg - read HW configuration registers
  * @param: The device state
  *
  * Read the USB core HW configuration registers
  */
-static int s3c_hsotg_hw_cfg(struct dwc2_hsotg *hsotg)
+static int dwc2_hsotg_hw_cfg(struct dwc2_hsotg *hsotg)
 {
        u32 cfg;
        u32 ep_type;
@@ -3330,41 +3403,41 @@ static int s3c_hsotg_hw_cfg(struct dwc2_hsotg *hsotg)
 
        /* check hardware configuration */
 
-       cfg = readl(hsotg->regs + GHWCFG2);
+       cfg = dwc2_readl(hsotg->regs + GHWCFG2);
        hsotg->num_of_eps = (cfg >> GHWCFG2_NUM_DEV_EP_SHIFT) & 0xF;
        /* Add ep0 */
        hsotg->num_of_eps++;
 
-       hsotg->eps_in[0] = devm_kzalloc(hsotg->dev, sizeof(struct s3c_hsotg_ep),
+       hsotg->eps_in[0] = devm_kzalloc(hsotg->dev, sizeof(struct dwc2_hsotg_ep),
                                                                GFP_KERNEL);
        if (!hsotg->eps_in[0])
                return -ENOMEM;
-       /* Same s3c_hsotg_ep is used in both directions for ep0 */
+       /* Same dwc2_hsotg_ep is used in both directions for ep0 */
        hsotg->eps_out[0] = hsotg->eps_in[0];
 
-       cfg = readl(hsotg->regs + GHWCFG1);
+       cfg = dwc2_readl(hsotg->regs + GHWCFG1);
        for (i = 1, cfg >>= 2; i < hsotg->num_of_eps; i++, cfg >>= 2) {
                ep_type = cfg & 3;
                /* Direction in or both */
                if (!(ep_type & 2)) {
                        hsotg->eps_in[i] = devm_kzalloc(hsotg->dev,
-                               sizeof(struct s3c_hsotg_ep), GFP_KERNEL);
+                               sizeof(struct dwc2_hsotg_ep), GFP_KERNEL);
                        if (!hsotg->eps_in[i])
                                return -ENOMEM;
                }
                /* Direction out or both */
                if (!(ep_type & 1)) {
                        hsotg->eps_out[i] = devm_kzalloc(hsotg->dev,
-                               sizeof(struct s3c_hsotg_ep), GFP_KERNEL);
+                               sizeof(struct dwc2_hsotg_ep), GFP_KERNEL);
                        if (!hsotg->eps_out[i])
                                return -ENOMEM;
                }
        }
 
-       cfg = readl(hsotg->regs + GHWCFG3);
+       cfg = dwc2_readl(hsotg->regs + GHWCFG3);
        hsotg->fifo_mem = (cfg >> GHWCFG3_DFIFO_DEPTH_SHIFT);
 
-       cfg = readl(hsotg->regs + GHWCFG4);
+       cfg = dwc2_readl(hsotg->regs + GHWCFG4);
        hsotg->dedicated_fifos = (cfg >> GHWCFG4_DED_FIFO_SHIFT) & 1;
 
        dev_info(hsotg->dev, "EPs: %d, %s fifos, %d entries in SPRAM\n",
@@ -3375,10 +3448,10 @@ static int s3c_hsotg_hw_cfg(struct dwc2_hsotg *hsotg)
 }
 
 /**
- * s3c_hsotg_dump - dump state of the udc
+ * dwc2_hsotg_dump - dump state of the udc
  * @param: The device state
  */
-static void s3c_hsotg_dump(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_dump(struct dwc2_hsotg *hsotg)
 {
 #ifdef DEBUG
        struct device *dev = hsotg->dev;
@@ -3387,19 +3460,19 @@ static void s3c_hsotg_dump(struct dwc2_hsotg *hsotg)
        int idx;
 
        dev_info(dev, "DCFG=0x%08x, DCTL=0x%08x, DIEPMSK=%08x\n",
-                readl(regs + DCFG), readl(regs + DCTL),
-                readl(regs + DIEPMSK));
+                dwc2_readl(regs + DCFG), dwc2_readl(regs + DCTL),
+                dwc2_readl(regs + DIEPMSK));
 
        dev_info(dev, "GAHBCFG=0x%08x, GHWCFG1=0x%08x\n",
-                readl(regs + GAHBCFG), readl(regs + GHWCFG1));
+                dwc2_readl(regs + GAHBCFG), dwc2_readl(regs + GHWCFG1));
 
        dev_info(dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n",
-                readl(regs + GRXFSIZ), readl(regs + GNPTXFSIZ));
+                dwc2_readl(regs + GRXFSIZ), dwc2_readl(regs + GNPTXFSIZ));
 
        /* show periodic fifo settings */
 
        for (idx = 1; idx < hsotg->num_of_eps; idx++) {
-               val = readl(regs + DPTXFSIZN(idx));
+               val = dwc2_readl(regs + DPTXFSIZN(idx));
                dev_info(dev, "DPTx[%d] FSize=%d, StAddr=0x%08x\n", idx,
                         val >> FIFOSIZE_DEPTH_SHIFT,
                         val & FIFOSIZE_STARTADDR_MASK);
@@ -3408,26 +3481,26 @@ static void s3c_hsotg_dump(struct dwc2_hsotg *hsotg)
        for (idx = 0; idx < hsotg->num_of_eps; idx++) {
                dev_info(dev,
                         "ep%d-in: EPCTL=0x%08x, SIZ=0x%08x, DMA=0x%08x\n", idx,
-                        readl(regs + DIEPCTL(idx)),
-                        readl(regs + DIEPTSIZ(idx)),
-                        readl(regs + DIEPDMA(idx)));
+                        dwc2_readl(regs + DIEPCTL(idx)),
+                        dwc2_readl(regs + DIEPTSIZ(idx)),
+                        dwc2_readl(regs + DIEPDMA(idx)));
 
-               val = readl(regs + DOEPCTL(idx));
+               val = dwc2_readl(regs + DOEPCTL(idx));
                dev_info(dev,
                         "ep%d-out: EPCTL=0x%08x, SIZ=0x%08x, DMA=0x%08x\n",
-                        idx, readl(regs + DOEPCTL(idx)),
-                        readl(regs + DOEPTSIZ(idx)),
-                        readl(regs + DOEPDMA(idx)));
+                        idx, dwc2_readl(regs + DOEPCTL(idx)),
+                        dwc2_readl(regs + DOEPTSIZ(idx)),
+                        dwc2_readl(regs + DOEPDMA(idx)));
 
        }
 
        dev_info(dev, "DVBUSDIS=0x%08x, DVBUSPULSE=%08x\n",
-                readl(regs + DVBUSDIS), readl(regs + DVBUSPULSE));
+                dwc2_readl(regs + DVBUSDIS), dwc2_readl(regs + DVBUSPULSE));
 #endif
 }
 
 #ifdef CONFIG_OF
-static void s3c_hsotg_of_probe(struct dwc2_hsotg *hsotg)
+static void dwc2_hsotg_of_probe(struct dwc2_hsotg *hsotg)
 {
        struct device_node *np = hsotg->dev->of_node;
        u32 len = 0;
@@ -3468,7 +3541,7 @@ rx_fifo:
                                                &hsotg->g_np_g_tx_fifo_sz);
 }
 #else
-static inline void s3c_hsotg_of_probe(struct dwc2_hsotg *hsotg) { }
+static inline void dwc2_hsotg_of_probe(struct dwc2_hsotg *hsotg) { }
 #endif
 
 /**
@@ -3479,23 +3552,17 @@ static inline void s3c_hsotg_of_probe(struct dwc2_hsotg *hsotg) { }
 int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
 {
        struct device *dev = hsotg->dev;
-       struct s3c_hsotg_plat *plat = dev->platform_data;
        int epnum;
        int ret;
        int i;
        u32 p_tx_fifo[] = DWC2_G_P_LEGACY_TX_FIFO_SIZE;
 
-       /* Set default UTMI width */
-       hsotg->phyif = GUSBCFG_PHYIF16;
-
-       s3c_hsotg_of_probe(hsotg);
-
        /* Initialize to legacy fifo configuration values */
        hsotg->g_rx_fifo_sz = 2048;
        hsotg->g_np_g_tx_fifo_sz = 1024;
        memcpy(&hsotg->g_tx_fifo_sz[1], p_tx_fifo, sizeof(p_tx_fifo));
        /* Device tree specific probe */
-       s3c_hsotg_of_probe(hsotg);
+       dwc2_hsotg_of_probe(hsotg);
        /* Dump fifo information */
        dev_dbg(dev, "NonPeriodic TXFIFO size: %d\n",
                                                hsotg->g_np_g_tx_fifo_sz);
@@ -3503,70 +3570,14 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
        for (i = 0; i < MAX_EPS_CHANNELS; i++)
                dev_dbg(dev, "Periodic TXFIFO%2d size: %d\n", i,
                                                hsotg->g_tx_fifo_sz[i]);
-       /*
-        * If platform probe couldn't find a generic PHY or an old style
-        * USB PHY, fall back to pdata
-        */
-       if (IS_ERR_OR_NULL(hsotg->phy) && IS_ERR_OR_NULL(hsotg->uphy)) {
-               plat = dev_get_platdata(dev);
-               if (!plat) {
-                       dev_err(dev,
-                       "no platform data or transceiver defined\n");
-                       return -EPROBE_DEFER;
-               }
-               hsotg->plat = plat;
-       } else if (hsotg->phy) {
-               /*
-                * If using the generic PHY framework, check if the PHY bus
-                * width is 8-bit and set the phyif appropriately.
-                */
-               if (phy_get_bus_width(hsotg->phy) == 8)
-                       hsotg->phyif = GUSBCFG_PHYIF8;
-       }
-
-       hsotg->clk = devm_clk_get(dev, "otg");
-       if (IS_ERR(hsotg->clk)) {
-               hsotg->clk = NULL;
-               dev_dbg(dev, "cannot get otg clock\n");
-       }
 
        hsotg->gadget.max_speed = USB_SPEED_HIGH;
-       hsotg->gadget.ops = &s3c_hsotg_gadget_ops;
+       hsotg->gadget.ops = &dwc2_hsotg_gadget_ops;
        hsotg->gadget.name = dev_name(dev);
        if (hsotg->dr_mode == USB_DR_MODE_OTG)
                hsotg->gadget.is_otg = 1;
-
-       /* reset the system */
-
-       ret = clk_prepare_enable(hsotg->clk);
-       if (ret) {
-               dev_err(dev, "failed to enable otg clk\n");
-               goto err_clk;
-       }
-
-
-       /* regulators */
-
-       for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++)
-               hsotg->supplies[i].supply = s3c_hsotg_supply_names[i];
-
-       ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies),
-                                hsotg->supplies);
-       if (ret) {
-               dev_err(dev, "failed to request supplies: %d\n", ret);
-               goto err_clk;
-       }
-
-       ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
-                                   hsotg->supplies);
-
-       if (ret) {
-               dev_err(dev, "failed to enable supplies: %d\n", ret);
-               goto err_clk;
-       }
-
-       /* usb phy enable */
-       s3c_hsotg_phy_enable(hsotg);
+       else if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
+               hsotg->op_state = OTG_STATE_B_PERIPHERAL;
 
        /*
         * Force Device mode before initialization.
@@ -3581,14 +3592,14 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
         */
        msleep(25);
 
-       s3c_hsotg_corereset(hsotg);
-       ret = s3c_hsotg_hw_cfg(hsotg);
+       dwc2_hsotg_corereset(hsotg);
+       ret = dwc2_hsotg_hw_cfg(hsotg);
        if (ret) {
                dev_err(hsotg->dev, "Hardware configuration failed: %d\n", ret);
-               goto err_clk;
+               return ret;
        }
 
-       s3c_hsotg_init(hsotg);
+       dwc2_hsotg_init(hsotg);
 
        /* Switch back to default configuration */
        __bic32(hsotg->regs + GUSBCFG, GUSBCFG_FORCEDEVMODE);
@@ -3597,35 +3608,28 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
                        DWC2_CTRL_BUFF_SIZE, GFP_KERNEL);
        if (!hsotg->ctrl_buff) {
                dev_err(dev, "failed to allocate ctrl request buff\n");
-               ret = -ENOMEM;
-               goto err_supplies;
+               return -ENOMEM;
        }
 
        hsotg->ep0_buff = devm_kzalloc(hsotg->dev,
                        DWC2_CTRL_BUFF_SIZE, GFP_KERNEL);
        if (!hsotg->ep0_buff) {
                dev_err(dev, "failed to allocate ctrl reply buff\n");
-               ret = -ENOMEM;
-               goto err_supplies;
+               return -ENOMEM;
        }
 
-       ret = devm_request_irq(hsotg->dev, irq, s3c_hsotg_irq, IRQF_SHARED,
+       ret = devm_request_irq(hsotg->dev, irq, dwc2_hsotg_irq, IRQF_SHARED,
                                dev_name(hsotg->dev), hsotg);
        if (ret < 0) {
-               s3c_hsotg_phy_disable(hsotg);
-               clk_disable_unprepare(hsotg->clk);
-               regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
-                                      hsotg->supplies);
                dev_err(dev, "cannot claim IRQ for gadget\n");
-               goto err_supplies;
+               return ret;
        }
 
        /* hsotg->num_of_eps holds number of EPs other than ep0 */
 
        if (hsotg->num_of_eps == 0) {
                dev_err(dev, "wrong number of EPs (zero)\n");
-               ret = -EINVAL;
-               goto err_supplies;
+               return -EINVAL;
        }
 
        /* setup endpoint information */
@@ -3635,71 +3639,49 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
 
        /* allocate EP0 request */
 
-       hsotg->ctrl_req = s3c_hsotg_ep_alloc_request(&hsotg->eps_out[0]->ep,
+       hsotg->ctrl_req = dwc2_hsotg_ep_alloc_request(&hsotg->eps_out[0]->ep,
                                                     GFP_KERNEL);
        if (!hsotg->ctrl_req) {
                dev_err(dev, "failed to allocate ctrl req\n");
-               ret = -ENOMEM;
-               goto err_supplies;
+               return -ENOMEM;
        }
 
        /* initialise the endpoints now the core has been initialised */
        for (epnum = 0; epnum < hsotg->num_of_eps; epnum++) {
                if (hsotg->eps_in[epnum])
-                       s3c_hsotg_initep(hsotg, hsotg->eps_in[epnum],
+                       dwc2_hsotg_initep(hsotg, hsotg->eps_in[epnum],
                                                                epnum, 1);
                if (hsotg->eps_out[epnum])
-                       s3c_hsotg_initep(hsotg, hsotg->eps_out[epnum],
+                       dwc2_hsotg_initep(hsotg, hsotg->eps_out[epnum],
                                                                epnum, 0);
        }
 
-       /* disable power and clock */
-       s3c_hsotg_phy_disable(hsotg);
-
-       ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
-                                   hsotg->supplies);
-       if (ret) {
-               dev_err(dev, "failed to disable supplies: %d\n", ret);
-               goto err_supplies;
-       }
-
        ret = usb_add_gadget_udc(dev, &hsotg->gadget);
        if (ret)
-               goto err_supplies;
+               return ret;
 
-       s3c_hsotg_dump(hsotg);
+       dwc2_hsotg_dump(hsotg);
 
        return 0;
-
-err_supplies:
-       s3c_hsotg_phy_disable(hsotg);
-err_clk:
-       clk_disable_unprepare(hsotg->clk);
-
-       return ret;
 }
 
 /**
- * s3c_hsotg_remove - remove function for hsotg driver
+ * dwc2_hsotg_remove - remove function for hsotg driver
  * @pdev: The platform information for the driver
  */
-int s3c_hsotg_remove(struct dwc2_hsotg *hsotg)
+int dwc2_hsotg_remove(struct dwc2_hsotg *hsotg)
 {
        usb_del_gadget_udc(&hsotg->gadget);
-       clk_disable_unprepare(hsotg->clk);
 
        return 0;
 }
 
-int s3c_hsotg_suspend(struct dwc2_hsotg *hsotg)
+int dwc2_hsotg_suspend(struct dwc2_hsotg *hsotg)
 {
        unsigned long flags;
-       int ret = 0;
 
        if (hsotg->lx_state != DWC2_L0)
-               return ret;
-
-       mutex_lock(&hsotg->init_mutex);
+               return 0;
 
        if (hsotg->driver) {
                int ep;
@@ -3709,57 +3691,39 @@ int s3c_hsotg_suspend(struct dwc2_hsotg *hsotg)
 
                spin_lock_irqsave(&hsotg->lock, flags);
                if (hsotg->enabled)
-                       s3c_hsotg_core_disconnect(hsotg);
-               s3c_hsotg_disconnect(hsotg);
+                       dwc2_hsotg_core_disconnect(hsotg);
+               dwc2_hsotg_disconnect(hsotg);
                hsotg->gadget.speed = USB_SPEED_UNKNOWN;
                spin_unlock_irqrestore(&hsotg->lock, flags);
 
-               s3c_hsotg_phy_disable(hsotg);
-
                for (ep = 0; ep < hsotg->num_of_eps; ep++) {
                        if (hsotg->eps_in[ep])
-                               s3c_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
+                               dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
                        if (hsotg->eps_out[ep])
-                               s3c_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
+                               dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
                }
-
-               ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
-                                            hsotg->supplies);
-               clk_disable(hsotg->clk);
        }
 
-       mutex_unlock(&hsotg->init_mutex);
-
-       return ret;
+       return 0;
 }
 
-int s3c_hsotg_resume(struct dwc2_hsotg *hsotg)
+int dwc2_hsotg_resume(struct dwc2_hsotg *hsotg)
 {
        unsigned long flags;
-       int ret = 0;
 
        if (hsotg->lx_state == DWC2_L2)
-               return ret;
-
-       mutex_lock(&hsotg->init_mutex);
+               return 0;
 
        if (hsotg->driver) {
                dev_info(hsotg->dev, "resuming usb gadget %s\n",
                         hsotg->driver->driver.name);
 
-               clk_enable(hsotg->clk);
-               ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
-                                           hsotg->supplies);
-
-               s3c_hsotg_phy_enable(hsotg);
-
                spin_lock_irqsave(&hsotg->lock, flags);
-               s3c_hsotg_core_init_disconnected(hsotg, false);
+               dwc2_hsotg_core_init_disconnected(hsotg, false);
                if (hsotg->enabled)
-                       s3c_hsotg_core_connect(hsotg);
+                       dwc2_hsotg_core_connect(hsotg);
                spin_unlock_irqrestore(&hsotg->lock, flags);
        }
-       mutex_unlock(&hsotg->init_mutex);
 
-       return ret;
+       return 0;
 }
index f845c41fe9e5e8c788c35d0fd7711b54debbe97e..e79baf73c234f58bf3162bb9d52d5efce9bca1ca 100644 (file)
@@ -80,10 +80,10 @@ static void dwc2_dump_channel_info(struct dwc2_hsotg *hsotg,
        if (chan == NULL)
                return;
 
-       hcchar = readl(hsotg->regs + HCCHAR(chan->hc_num));
-       hcsplt = readl(hsotg->regs + HCSPLT(chan->hc_num));
-       hctsiz = readl(hsotg->regs + HCTSIZ(chan->hc_num));
-       hc_dma = readl(hsotg->regs + HCDMA(chan->hc_num));
+       hcchar = dwc2_readl(hsotg->regs + HCCHAR(chan->hc_num));
+       hcsplt = dwc2_readl(hsotg->regs + HCSPLT(chan->hc_num));
+       hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chan->hc_num));
+       hc_dma = dwc2_readl(hsotg->regs + HCDMA(chan->hc_num));
 
        dev_dbg(hsotg->dev, "  Assigned to channel %p:\n", chan);
        dev_dbg(hsotg->dev, "    hcchar 0x%08x, hcsplt 0x%08x\n",
@@ -134,7 +134,7 @@ static void dwc2_kill_urbs_in_qh_list(struct dwc2_hsotg *hsotg,
        list_for_each_entry_safe(qh, qh_tmp, qh_list, qh_list_entry) {
                list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list,
                                         qtd_list_entry) {
-                       dwc2_host_complete(hsotg, qtd, -ETIMEDOUT);
+                       dwc2_host_complete(hsotg, qtd, -ECONNRESET);
                        dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
                }
        }
@@ -207,7 +207,7 @@ void dwc2_hcd_start(struct dwc2_hsotg *hsotg)
                 */
                hprt0 = dwc2_read_hprt0(hsotg);
                hprt0 |= HPRT0_RST;
-               writel(hprt0, hsotg->regs + HPRT0);
+               dwc2_writel(hprt0, hsotg->regs + HPRT0);
        }
 
        queue_delayed_work(hsotg->wq_otg, &hsotg->start_work,
@@ -228,11 +228,11 @@ static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg)
                        channel = hsotg->hc_ptr_array[i];
                        if (!list_empty(&channel->hc_list_entry))
                                continue;
-                       hcchar = readl(hsotg->regs + HCCHAR(i));
+                       hcchar = dwc2_readl(hsotg->regs + HCCHAR(i));
                        if (hcchar & HCCHAR_CHENA) {
                                hcchar &= ~(HCCHAR_CHENA | HCCHAR_EPDIR);
                                hcchar |= HCCHAR_CHDIS;
-                               writel(hcchar, hsotg->regs + HCCHAR(i));
+                               dwc2_writel(hcchar, hsotg->regs + HCCHAR(i));
                        }
                }
        }
@@ -241,11 +241,11 @@ static void dwc2_hcd_cleanup_channels(struct dwc2_hsotg *hsotg)
                channel = hsotg->hc_ptr_array[i];
                if (!list_empty(&channel->hc_list_entry))
                        continue;
-               hcchar = readl(hsotg->regs + HCCHAR(i));
+               hcchar = dwc2_readl(hsotg->regs + HCCHAR(i));
                if (hcchar & HCCHAR_CHENA) {
                        /* Halt the channel */
                        hcchar |= HCCHAR_CHDIS;
-                       writel(hcchar, hsotg->regs + HCCHAR(i));
+                       dwc2_writel(hcchar, hsotg->regs + HCCHAR(i));
                }
 
                dwc2_hc_cleanup(hsotg, channel);
@@ -287,11 +287,11 @@ void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg)
         * interrupt mask and status bits and disabling subsequent host
         * channel interrupts.
         */
-       intr = readl(hsotg->regs + GINTMSK);
+       intr = dwc2_readl(hsotg->regs + GINTMSK);
        intr &= ~(GINTSTS_NPTXFEMP | GINTSTS_PTXFEMP | GINTSTS_HCHINT);
-       writel(intr, hsotg->regs + GINTMSK);
+       dwc2_writel(intr, hsotg->regs + GINTMSK);
        intr = GINTSTS_NPTXFEMP | GINTSTS_PTXFEMP | GINTSTS_HCHINT;
-       writel(intr, hsotg->regs + GINTSTS);
+       dwc2_writel(intr, hsotg->regs + GINTSTS);
 
        /*
         * Turn off the vbus power only if the core has transitioned to device
@@ -301,7 +301,7 @@ void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg)
        if (dwc2_is_device_mode(hsotg)) {
                if (hsotg->op_state != OTG_STATE_A_SUSPEND) {
                        dev_dbg(hsotg->dev, "Disconnect: PortPower off\n");
-                       writel(0, hsotg->regs + HPRT0);
+                       dwc2_writel(0, hsotg->regs + HPRT0);
                }
 
                dwc2_disable_host_interrupts(hsotg);
@@ -354,7 +354,7 @@ void dwc2_hcd_stop(struct dwc2_hsotg *hsotg)
 
        /* Turn off the vbus power */
        dev_dbg(hsotg->dev, "PortPower off\n");
-       writel(0, hsotg->regs + HPRT0);
+       dwc2_writel(0, hsotg->regs + HPRT0);
 }
 
 /* Caller must hold driver lock */
@@ -378,7 +378,7 @@ static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg,
        if ((dev_speed == USB_SPEED_LOW) &&
            (hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED) &&
            (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI)) {
-               u32 hprt0 = readl(hsotg->regs + HPRT0);
+               u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0);
                u32 prtspd = (hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT;
 
                if (prtspd == HPRT0_SPD_FULL_SPEED)
@@ -397,7 +397,7 @@ static int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg,
                return retval;
        }
 
-       intr_mask = readl(hsotg->regs + GINTMSK);
+       intr_mask = dwc2_readl(hsotg->regs + GINTMSK);
        if (!(intr_mask & GINTSTS_SOF)) {
                enum dwc2_transaction_type tr_type;
 
@@ -1070,7 +1070,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
        if (dbg_perio())
                dev_vdbg(hsotg->dev, "Queue periodic transactions\n");
 
-       tx_status = readl(hsotg->regs + HPTXSTS);
+       tx_status = dwc2_readl(hsotg->regs + HPTXSTS);
        qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >>
                    TXSTS_QSPCAVAIL_SHIFT;
        fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >>
@@ -1085,7 +1085,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
 
        qh_ptr = hsotg->periodic_sched_assigned.next;
        while (qh_ptr != &hsotg->periodic_sched_assigned) {
-               tx_status = readl(hsotg->regs + HPTXSTS);
+               tx_status = dwc2_readl(hsotg->regs + HPTXSTS);
                qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >>
                            TXSTS_QSPCAVAIL_SHIFT;
                if (qspcavail == 0) {
@@ -1145,7 +1145,7 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
        }
 
        if (hsotg->core_params->dma_enable <= 0) {
-               tx_status = readl(hsotg->regs + HPTXSTS);
+               tx_status = dwc2_readl(hsotg->regs + HPTXSTS);
                qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >>
                            TXSTS_QSPCAVAIL_SHIFT;
                fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >>
@@ -1168,9 +1168,9 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
                         * level to ensure that new requests are loaded as
                         * soon as possible.)
                         */
-                       gintmsk = readl(hsotg->regs + GINTMSK);
+                       gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
                        gintmsk |= GINTSTS_PTXFEMP;
-                       writel(gintmsk, hsotg->regs + GINTMSK);
+                       dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
                } else {
                        /*
                         * Disable the Tx FIFO empty interrupt since there are
@@ -1179,9 +1179,9 @@ static void dwc2_process_periodic_channels(struct dwc2_hsotg *hsotg)
                         * handlers to queue more transactions as transfer
                         * states change.
                         */
-                       gintmsk = readl(hsotg->regs + GINTMSK);
+                       gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
                        gintmsk &= ~GINTSTS_PTXFEMP;
-                       writel(gintmsk, hsotg->regs + GINTMSK);
+                       dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
                }
        }
 }
@@ -1210,7 +1210,7 @@ static void dwc2_process_non_periodic_channels(struct dwc2_hsotg *hsotg)
 
        dev_vdbg(hsotg->dev, "Queue non-periodic transactions\n");
 
-       tx_status = readl(hsotg->regs + GNPTXSTS);
+       tx_status = dwc2_readl(hsotg->regs + GNPTXSTS);
        qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >>
                    TXSTS_QSPCAVAIL_SHIFT;
        fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >>
@@ -1233,7 +1233,7 @@ static void dwc2_process_non_periodic_channels(struct dwc2_hsotg *hsotg)
         * available in the request queue or the Tx FIFO
         */
        do {
-               tx_status = readl(hsotg->regs + GNPTXSTS);
+               tx_status = dwc2_readl(hsotg->regs + GNPTXSTS);
                qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >>
                            TXSTS_QSPCAVAIL_SHIFT;
                if (hsotg->core_params->dma_enable <= 0 && qspcavail == 0) {
@@ -1270,7 +1270,7 @@ next:
        } while (hsotg->non_periodic_qh_ptr != orig_qh_ptr);
 
        if (hsotg->core_params->dma_enable <= 0) {
-               tx_status = readl(hsotg->regs + GNPTXSTS);
+               tx_status = dwc2_readl(hsotg->regs + GNPTXSTS);
                qspcavail = (tx_status & TXSTS_QSPCAVAIL_MASK) >>
                            TXSTS_QSPCAVAIL_SHIFT;
                fspcavail = (tx_status & TXSTS_FSPCAVAIL_MASK) >>
@@ -1290,9 +1290,9 @@ next:
                         * level to ensure that new requests are loaded as
                         * soon as possible.)
                         */
-                       gintmsk = readl(hsotg->regs + GINTMSK);
+                       gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
                        gintmsk |= GINTSTS_NPTXFEMP;
-                       writel(gintmsk, hsotg->regs + GINTMSK);
+                       dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
                } else {
                        /*
                         * Disable the Tx FIFO empty interrupt since there are
@@ -1301,9 +1301,9 @@ next:
                         * handlers to queue more transactions as transfer
                         * states change.
                         */
-                       gintmsk = readl(hsotg->regs + GINTMSK);
+                       gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
                        gintmsk &= ~GINTSTS_NPTXFEMP;
-                       writel(gintmsk, hsotg->regs + GINTMSK);
+                       dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
                }
        }
 }
@@ -1341,10 +1341,10 @@ void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg,
                         * Ensure NP Tx FIFO empty interrupt is disabled when
                         * there are no non-periodic transfers to process
                         */
-                       u32 gintmsk = readl(hsotg->regs + GINTMSK);
+                       u32 gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
 
                        gintmsk &= ~GINTSTS_NPTXFEMP;
-                       writel(gintmsk, hsotg->regs + GINTMSK);
+                       dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
                }
        }
 }
@@ -1355,10 +1355,11 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
                                                wf_otg);
        u32 count = 0;
        u32 gotgctl;
+       unsigned long flags;
 
        dev_dbg(hsotg->dev, "%s()\n", __func__);
 
-       gotgctl = readl(hsotg->regs + GOTGCTL);
+       gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
        dev_dbg(hsotg->dev, "gotgctl=%0x\n", gotgctl);
        dev_dbg(hsotg->dev, "gotgctl.b.conidsts=%d\n",
                !!(gotgctl & GOTGCTL_CONID_B));
@@ -1382,8 +1383,10 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
                hsotg->op_state = OTG_STATE_B_PERIPHERAL;
                dwc2_core_init(hsotg, false, -1);
                dwc2_enable_global_interrupts(hsotg);
-               s3c_hsotg_core_init_disconnected(hsotg, false);
-               s3c_hsotg_core_connect(hsotg);
+               spin_lock_irqsave(&hsotg->lock, flags);
+               dwc2_hsotg_core_init_disconnected(hsotg, false);
+               spin_unlock_irqrestore(&hsotg->lock, flags);
+               dwc2_hsotg_core_connect(hsotg);
        } else {
                /* A-Device connector (Host Mode) */
                dev_dbg(hsotg->dev, "connId A\n");
@@ -1421,10 +1424,11 @@ static void dwc2_wakeup_detected(unsigned long data)
        hprt0 = dwc2_read_hprt0(hsotg);
        dev_dbg(hsotg->dev, "Resume: HPRT0=%0x\n", hprt0);
        hprt0 &= ~HPRT0_RES;
-       writel(hprt0, hsotg->regs + HPRT0);
+       dwc2_writel(hprt0, hsotg->regs + HPRT0);
        dev_dbg(hsotg->dev, "Clear Resume: HPRT0=%0x\n",
-               readl(hsotg->regs + HPRT0));
+               dwc2_readl(hsotg->regs + HPRT0));
 
+       hsotg->bus_suspended = 0;
        dwc2_hcd_rem_wakeup(hsotg);
 
        /* Change to L0 state */
@@ -1451,30 +1455,35 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)
        spin_lock_irqsave(&hsotg->lock, flags);
 
        if (windex == hsotg->otg_port && dwc2_host_is_b_hnp_enabled(hsotg)) {
-               gotgctl = readl(hsotg->regs + GOTGCTL);
+               gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
                gotgctl |= GOTGCTL_HSTSETHNPEN;
-               writel(gotgctl, hsotg->regs + GOTGCTL);
+               dwc2_writel(gotgctl, hsotg->regs + GOTGCTL);
                hsotg->op_state = OTG_STATE_A_SUSPEND;
        }
 
        hprt0 = dwc2_read_hprt0(hsotg);
        hprt0 |= HPRT0_SUSP;
-       writel(hprt0, hsotg->regs + HPRT0);
+       dwc2_writel(hprt0, hsotg->regs + HPRT0);
 
-       /* Update lx_state */
-       hsotg->lx_state = DWC2_L2;
+       hsotg->bus_suspended = 1;
 
-       /* Suspend the Phy Clock */
-       pcgctl = readl(hsotg->regs + PCGCTL);
-       pcgctl |= PCGCTL_STOPPCLK;
-       writel(pcgctl, hsotg->regs + PCGCTL);
-       udelay(10);
+       /*
+        * If hibernation is supported, Phy clock will be suspended
+        * after registers are backuped.
+        */
+       if (!hsotg->core_params->hibernation) {
+               /* Suspend the Phy Clock */
+               pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
+               pcgctl |= PCGCTL_STOPPCLK;
+               dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
+               udelay(10);
+       }
 
        /* For HNP the bus must be suspended for at least 200ms */
        if (dwc2_host_is_b_hnp_enabled(hsotg)) {
-               pcgctl = readl(hsotg->regs + PCGCTL);
+               pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
                pcgctl &= ~PCGCTL_STOPPCLK;
-               writel(pcgctl, hsotg->regs + PCGCTL);
+               dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
 
                spin_unlock_irqrestore(&hsotg->lock, flags);
 
@@ -1484,6 +1493,44 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)
        }
 }
 
+/* Must NOT be called with interrupt disabled or spinlock held */
+static void dwc2_port_resume(struct dwc2_hsotg *hsotg)
+{
+       unsigned long flags;
+       u32 hprt0;
+       u32 pcgctl;
+
+       spin_lock_irqsave(&hsotg->lock, flags);
+
+       /*
+        * If hibernation is supported, Phy clock is already resumed
+        * after registers restore.
+        */
+       if (!hsotg->core_params->hibernation) {
+               pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
+               pcgctl &= ~PCGCTL_STOPPCLK;
+               dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
+               spin_unlock_irqrestore(&hsotg->lock, flags);
+               usleep_range(20000, 40000);
+               spin_lock_irqsave(&hsotg->lock, flags);
+       }
+
+       hprt0 = dwc2_read_hprt0(hsotg);
+       hprt0 |= HPRT0_RES;
+       hprt0 &= ~HPRT0_SUSP;
+       dwc2_writel(hprt0, hsotg->regs + HPRT0);
+       spin_unlock_irqrestore(&hsotg->lock, flags);
+
+       msleep(USB_RESUME_TIMEOUT);
+
+       spin_lock_irqsave(&hsotg->lock, flags);
+       hprt0 = dwc2_read_hprt0(hsotg);
+       hprt0 &= ~(HPRT0_RES | HPRT0_SUSP);
+       dwc2_writel(hprt0, hsotg->regs + HPRT0);
+       hsotg->bus_suspended = 0;
+       spin_unlock_irqrestore(&hsotg->lock, flags);
+}
+
 /* Handles hub class-specific requests */
 static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
                                u16 wvalue, u16 windex, char *buf, u16 wlength)
@@ -1523,23 +1570,15 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
                                "ClearPortFeature USB_PORT_FEAT_ENABLE\n");
                        hprt0 = dwc2_read_hprt0(hsotg);
                        hprt0 |= HPRT0_ENA;
-                       writel(hprt0, hsotg->regs + HPRT0);
+                       dwc2_writel(hprt0, hsotg->regs + HPRT0);
                        break;
 
                case USB_PORT_FEAT_SUSPEND:
                        dev_dbg(hsotg->dev,
                                "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
-                       writel(0, hsotg->regs + PCGCTL);
-                       usleep_range(20000, 40000);
-
-                       hprt0 = dwc2_read_hprt0(hsotg);
-                       hprt0 |= HPRT0_RES;
-                       writel(hprt0, hsotg->regs + HPRT0);
-                       hprt0 &= ~HPRT0_SUSP;
-                       msleep(USB_RESUME_TIMEOUT);
 
-                       hprt0 &= ~HPRT0_RES;
-                       writel(hprt0, hsotg->regs + HPRT0);
+                       if (hsotg->bus_suspended)
+                               dwc2_port_resume(hsotg);
                        break;
 
                case USB_PORT_FEAT_POWER:
@@ -1547,7 +1586,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
                                "ClearPortFeature USB_PORT_FEAT_POWER\n");
                        hprt0 = dwc2_read_hprt0(hsotg);
                        hprt0 &= ~HPRT0_PWR;
-                       writel(hprt0, hsotg->regs + HPRT0);
+                       dwc2_writel(hprt0, hsotg->regs + HPRT0);
                        break;
 
                case USB_PORT_FEAT_INDICATOR:
@@ -1668,7 +1707,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
                        break;
                }
 
-               hprt0 = readl(hsotg->regs + HPRT0);
+               hprt0 = dwc2_readl(hsotg->regs + HPRT0);
                dev_vdbg(hsotg->dev, "  HPRT0: 0x%08x\n", hprt0);
 
                if (hprt0 & HPRT0_CONNSTS)
@@ -1733,18 +1772,18 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
                                "SetPortFeature - USB_PORT_FEAT_POWER\n");
                        hprt0 = dwc2_read_hprt0(hsotg);
                        hprt0 |= HPRT0_PWR;
-                       writel(hprt0, hsotg->regs + HPRT0);
+                       dwc2_writel(hprt0, hsotg->regs + HPRT0);
                        break;
 
                case USB_PORT_FEAT_RESET:
                        hprt0 = dwc2_read_hprt0(hsotg);
                        dev_dbg(hsotg->dev,
                                "SetPortFeature - USB_PORT_FEAT_RESET\n");
-                       pcgctl = readl(hsotg->regs + PCGCTL);
+                       pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
                        pcgctl &= ~(PCGCTL_ENBL_SLEEP_GATING | PCGCTL_STOPPCLK);
-                       writel(pcgctl, hsotg->regs + PCGCTL);
+                       dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
                        /* ??? Original driver does this */
-                       writel(0, hsotg->regs + PCGCTL);
+                       dwc2_writel(0, hsotg->regs + PCGCTL);
 
                        hprt0 = dwc2_read_hprt0(hsotg);
                        /* Clear suspend bit if resetting from suspend state */
@@ -1759,13 +1798,13 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
                                hprt0 |= HPRT0_PWR | HPRT0_RST;
                                dev_dbg(hsotg->dev,
                                        "In host mode, hprt0=%08x\n", hprt0);
-                               writel(hprt0, hsotg->regs + HPRT0);
+                               dwc2_writel(hprt0, hsotg->regs + HPRT0);
                        }
 
                        /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
                        usleep_range(50000, 70000);
                        hprt0 &= ~HPRT0_RST;
-                       writel(hprt0, hsotg->regs + HPRT0);
+                       dwc2_writel(hprt0, hsotg->regs + HPRT0);
                        hsotg->lx_state = DWC2_L0; /* Now back to On state */
                        break;
 
@@ -1781,7 +1820,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
                                "SetPortFeature - USB_PORT_FEAT_TEST\n");
                        hprt0 &= ~HPRT0_TSTCTL_MASK;
                        hprt0 |= (windex >> 8) << HPRT0_TSTCTL_SHIFT;
-                       writel(hprt0, hsotg->regs + HPRT0);
+                       dwc2_writel(hprt0, hsotg->regs + HPRT0);
                        break;
 
                default:
@@ -1838,7 +1877,7 @@ static int dwc2_hcd_is_status_changed(struct dwc2_hsotg *hsotg, int port)
 
 int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg)
 {
-       u32 hfnum = readl(hsotg->regs + HFNUM);
+       u32 hfnum = dwc2_readl(hsotg->regs + HFNUM);
 
 #ifdef DWC2_DEBUG_SOF
        dev_vdbg(hsotg->dev, "DWC OTG HCD GET FRAME NUMBER %d\n",
@@ -1941,11 +1980,11 @@ void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg)
                if (chan->xfer_started) {
                        u32 hfnum, hcchar, hctsiz, hcint, hcintmsk;
 
-                       hfnum = readl(hsotg->regs + HFNUM);
-                       hcchar = readl(hsotg->regs + HCCHAR(i));
-                       hctsiz = readl(hsotg->regs + HCTSIZ(i));
-                       hcint = readl(hsotg->regs + HCINT(i));
-                       hcintmsk = readl(hsotg->regs + HCINTMSK(i));
+                       hfnum = dwc2_readl(hsotg->regs + HFNUM);
+                       hcchar = dwc2_readl(hsotg->regs + HCCHAR(i));
+                       hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(i));
+                       hcint = dwc2_readl(hsotg->regs + HCINT(i));
+                       hcintmsk = dwc2_readl(hsotg->regs + HCINTMSK(i));
                        dev_dbg(hsotg->dev, "    hfnum: 0x%08x\n", hfnum);
                        dev_dbg(hsotg->dev, "    hcchar: 0x%08x\n", hcchar);
                        dev_dbg(hsotg->dev, "    hctsiz: 0x%08x\n", hctsiz);
@@ -1993,12 +2032,12 @@ void dwc2_hcd_dump_state(struct dwc2_hsotg *hsotg)
        dev_dbg(hsotg->dev, "  periodic_channels: %d\n",
                hsotg->periodic_channels);
        dev_dbg(hsotg->dev, "  periodic_usecs: %d\n", hsotg->periodic_usecs);
-       np_tx_status = readl(hsotg->regs + GNPTXSTS);
+       np_tx_status = dwc2_readl(hsotg->regs + GNPTXSTS);
        dev_dbg(hsotg->dev, "  NP Tx Req Queue Space Avail: %d\n",
                (np_tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT);
        dev_dbg(hsotg->dev, "  NP Tx FIFO Space Avail: %d\n",
                (np_tx_status & TXSTS_FSPCAVAIL_MASK) >> TXSTS_FSPCAVAIL_SHIFT);
-       p_tx_status = readl(hsotg->regs + HPTXSTS);
+       p_tx_status = dwc2_readl(hsotg->regs + HPTXSTS);
        dev_dbg(hsotg->dev, "  P Tx Req Queue Space Avail: %d\n",
                (p_tx_status & TXSTS_QSPCAVAIL_MASK) >> TXSTS_QSPCAVAIL_SHIFT);
        dev_dbg(hsotg->dev, "  P Tx FIFO Space Avail: %d\n",
@@ -2194,11 +2233,6 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
                         usb_pipein(urb->pipe) ? "IN" : "OUT", status,
                         urb->actual_length);
 
-       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS && dbg_perio()) {
-               for (i = 0; i < urb->number_of_packets; i++)
-                       dev_vdbg(hsotg->dev, " ISO Desc %d status %d\n",
-                                i, urb->iso_frame_desc[i].status);
-       }
 
        if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
                urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb);
@@ -2211,6 +2245,12 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
                }
        }
 
+       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS && dbg_perio()) {
+               for (i = 0; i < urb->number_of_packets; i++)
+                       dev_vdbg(hsotg->dev, " ISO Desc %d status %d\n",
+                                i, urb->iso_frame_desc[i].status);
+       }
+
        urb->status = status;
        if (!status) {
                if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
@@ -2262,7 +2302,7 @@ static void dwc2_hcd_reset_func(struct work_struct *work)
        dev_dbg(hsotg->dev, "USB RESET function called\n");
        hprt0 = dwc2_read_hprt0(hsotg);
        hprt0 &= ~HPRT0_RST;
-       writel(hprt0, hsotg->regs + HPRT0);
+       dwc2_writel(hprt0, hsotg->regs + HPRT0);
        hsotg->flags.b.port_reset_change = 1;
 }
 
@@ -2286,8 +2326,9 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd)
        dev_dbg(hsotg->dev, "DWC OTG HCD START\n");
 
        spin_lock_irqsave(&hsotg->lock, flags);
-
+       hsotg->lx_state = DWC2_L0;
        hcd->state = HC_STATE_RUNNING;
+       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 
        if (dwc2_is_device_mode(hsotg)) {
                spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -2316,8 +2357,19 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
        struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
        unsigned long flags;
 
+       /* Turn off all host-specific interrupts */
+       dwc2_disable_host_interrupts(hsotg);
+
+       /* Wait for interrupt processing to finish */
+       synchronize_irq(hcd->irq);
+
        spin_lock_irqsave(&hsotg->lock, flags);
+       /* Ensure hcd is disconnected */
+       dwc2_hcd_disconnect(hsotg);
        dwc2_hcd_stop(hsotg);
+       hsotg->lx_state = DWC2_L3;
+       hcd->state = HC_STATE_HALT;
+       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
        spin_unlock_irqrestore(&hsotg->lock, flags);
 
        usleep_range(1000, 3000);
@@ -2326,17 +2378,125 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
 static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
 {
        struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+       unsigned long flags;
+       int ret = 0;
+       u32 hprt0;
+
+       spin_lock_irqsave(&hsotg->lock, flags);
+
+       if (hsotg->lx_state != DWC2_L0)
+               goto unlock;
+
+       if (!HCD_HW_ACCESSIBLE(hcd))
+               goto unlock;
+
+       if (!hsotg->core_params->hibernation)
+               goto skip_power_saving;
 
+       /*
+        * Drive USB suspend and disable port Power
+        * if usb bus is not suspended.
+        */
+       if (!hsotg->bus_suspended) {
+               hprt0 = dwc2_read_hprt0(hsotg);
+               hprt0 |= HPRT0_SUSP;
+               hprt0 &= ~HPRT0_PWR;
+               dwc2_writel(hprt0, hsotg->regs + HPRT0);
+       }
+
+       /* Enter hibernation */
+       ret = dwc2_enter_hibernation(hsotg);
+       if (ret) {
+               if (ret != -ENOTSUPP)
+                       dev_err(hsotg->dev,
+                               "enter hibernation failed\n");
+               goto skip_power_saving;
+       }
+
+       /* Ask phy to be suspended */
+       if (!IS_ERR_OR_NULL(hsotg->uphy)) {
+               spin_unlock_irqrestore(&hsotg->lock, flags);
+               usb_phy_set_suspend(hsotg->uphy, true);
+               spin_lock_irqsave(&hsotg->lock, flags);
+       }
+
+       /* After entering hibernation, hardware is no more accessible */
+       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+skip_power_saving:
        hsotg->lx_state = DWC2_L2;
-       return 0;
+unlock:
+       spin_unlock_irqrestore(&hsotg->lock, flags);
+
+       return ret;
 }
 
 static int _dwc2_hcd_resume(struct usb_hcd *hcd)
 {
        struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+       unsigned long flags;
+       int ret = 0;
+
+       spin_lock_irqsave(&hsotg->lock, flags);
+
+       if (hsotg->lx_state != DWC2_L2)
+               goto unlock;
+
+       if (!hsotg->core_params->hibernation) {
+               hsotg->lx_state = DWC2_L0;
+               goto unlock;
+       }
+
+       /*
+        * Set HW accessible bit before powering on the controller
+        * since an interrupt may rise.
+        */
+       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+       /*
+        * Enable power if not already done.
+        * This must not be spinlocked since duration
+        * of this call is unknown.
+        */
+       if (!IS_ERR_OR_NULL(hsotg->uphy)) {
+               spin_unlock_irqrestore(&hsotg->lock, flags);
+               usb_phy_set_suspend(hsotg->uphy, false);
+               spin_lock_irqsave(&hsotg->lock, flags);
+       }
+
+       /* Exit hibernation */
+       ret = dwc2_exit_hibernation(hsotg, true);
+       if (ret && (ret != -ENOTSUPP))
+               dev_err(hsotg->dev, "exit hibernation failed\n");
 
        hsotg->lx_state = DWC2_L0;
-       return 0;
+
+       spin_unlock_irqrestore(&hsotg->lock, flags);
+
+       if (hsotg->bus_suspended) {
+               spin_lock_irqsave(&hsotg->lock, flags);
+               hsotg->flags.b.port_suspend_change = 1;
+               spin_unlock_irqrestore(&hsotg->lock, flags);
+               dwc2_port_resume(hsotg);
+       } else {
+               /* Wait for controller to correctly update D+/D- level */
+               usleep_range(3000, 5000);
+
+               /*
+                * Clear Port Enable and Port Status changes.
+                * Enable Port Power.
+                */
+               dwc2_writel(HPRT0_PWR | HPRT0_CONNDET |
+                               HPRT0_ENACHG, hsotg->regs + HPRT0);
+               /* Wait for controller to detect Port Connect */
+               usleep_range(5000, 7000);
+       }
+
+       return ret;
+unlock:
+       spin_unlock_irqrestore(&hsotg->lock, flags);
+
+       return ret;
 }
 
 /* Returns the current frame number */
@@ -2790,17 +2950,17 @@ static void dwc2_hcd_free(struct dwc2_hsotg *hsotg)
                hsotg->status_buf = NULL;
        }
 
-       ahbcfg = readl(hsotg->regs + GAHBCFG);
+       ahbcfg = dwc2_readl(hsotg->regs + GAHBCFG);
 
        /* Disable all interrupts */
        ahbcfg &= ~GAHBCFG_GLBL_INTR_EN;
-       writel(ahbcfg, hsotg->regs + GAHBCFG);
-       writel(0, hsotg->regs + GINTMSK);
+       dwc2_writel(ahbcfg, hsotg->regs + GAHBCFG);
+       dwc2_writel(0, hsotg->regs + GINTMSK);
 
        if (hsotg->hw_params.snpsid >= DWC2_CORE_REV_3_00a) {
-               dctl = readl(hsotg->regs + DCTL);
+               dctl = dwc2_readl(hsotg->regs + DCTL);
                dctl |= DCTL_SFTDISCON;
-               writel(dctl, hsotg->regs + DCTL);
+               dwc2_writel(dctl, hsotg->regs + DCTL);
        }
 
        if (hsotg->wq_otg) {
@@ -2841,7 +3001,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
 
        retval = -ENOMEM;
 
-       hcfg = readl(hsotg->regs + HCFG);
+       hcfg = dwc2_readl(hsotg->regs + HCFG);
        dev_dbg(hsotg->dev, "hcfg=%08x\n", hcfg);
 
 #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
index fc1054965552aca51fa7f9bcdf87bae769077437..f105bada2fd13bddb7005a3a36936bd21a4cf5a5 100644 (file)
@@ -371,10 +371,10 @@ static inline struct usb_hcd *dwc2_hsotg_to_hcd(struct dwc2_hsotg *hsotg)
  */
 static inline void disable_hc_int(struct dwc2_hsotg *hsotg, int chnum, u32 intr)
 {
-       u32 mask = readl(hsotg->regs + HCINTMSK(chnum));
+       u32 mask = dwc2_readl(hsotg->regs + HCINTMSK(chnum));
 
        mask &= ~intr;
-       writel(mask, hsotg->regs + HCINTMSK(chnum));
+       dwc2_writel(mask, hsotg->regs + HCINTMSK(chnum));
 }
 
 /*
@@ -382,11 +382,11 @@ static inline void disable_hc_int(struct dwc2_hsotg *hsotg, int chnum, u32 intr)
  */
 static inline int dwc2_is_host_mode(struct dwc2_hsotg *hsotg)
 {
-       return (readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) != 0;
+       return (dwc2_readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) != 0;
 }
 static inline int dwc2_is_device_mode(struct dwc2_hsotg *hsotg)
 {
-       return (readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) == 0;
+       return (dwc2_readl(hsotg->regs + GINTSTS) & GINTSTS_CURMODE_HOST) == 0;
 }
 
 /*
@@ -395,7 +395,7 @@ static inline int dwc2_is_device_mode(struct dwc2_hsotg *hsotg)
  */
 static inline u32 dwc2_read_hprt0(struct dwc2_hsotg *hsotg)
 {
-       u32 hprt0 = readl(hsotg->regs + HPRT0);
+       u32 hprt0 = dwc2_readl(hsotg->regs + HPRT0);
 
        hprt0 &= ~(HPRT0_ENA | HPRT0_CONNDET | HPRT0_ENACHG | HPRT0_OVRCURRCHG);
        return hprt0;
@@ -580,7 +580,8 @@ static inline u16 dwc2_micro_frame_num(u16 frame)
  */
 static inline u32 dwc2_read_core_intr(struct dwc2_hsotg *hsotg)
 {
-       return readl(hsotg->regs + GINTSTS) & readl(hsotg->regs + GINTMSK);
+       return dwc2_readl(hsotg->regs + GINTSTS) &
+              dwc2_readl(hsotg->regs + GINTMSK);
 }
 
 static inline u32 dwc2_hcd_urb_get_status(struct dwc2_hcd_urb *dwc2_urb)
@@ -732,7 +733,7 @@ do {                                                                        \
                           qtd_list_entry);                             \
        if (usb_pipeint(_qtd_->urb->pipe) &&                            \
            (_qh_)->start_split_frame != 0 && !_qtd_->complete_split) { \
-               _hfnum_.d32 = readl((_hcd_)->regs + HFNUM);             \
+               _hfnum_.d32 = dwc2_readl((_hcd_)->regs + HFNUM);        \
                switch (_hfnum_.b.frnum & 0x7) {                        \
                case 7:                                                 \
                        (_hcd_)->hfnum_7_samples_##_letter_++;          \
index 3376177e4d3c0c8b1998829ae79a47dcab953a9e..78993aba9335c7ec3263e4dcf82e88254c49895f 100644 (file)
@@ -169,19 +169,19 @@ static void dwc2_per_sched_enable(struct dwc2_hsotg *hsotg, u32 fr_list_en)
 
        spin_lock_irqsave(&hsotg->lock, flags);
 
-       hcfg = readl(hsotg->regs + HCFG);
+       hcfg = dwc2_readl(hsotg->regs + HCFG);
        if (hcfg & HCFG_PERSCHEDENA) {
                /* already enabled */
                spin_unlock_irqrestore(&hsotg->lock, flags);
                return;
        }
 
-       writel(hsotg->frame_list_dma, hsotg->regs + HFLBADDR);
+       dwc2_writel(hsotg->frame_list_dma, hsotg->regs + HFLBADDR);
 
        hcfg &= ~HCFG_FRLISTEN_MASK;
        hcfg |= fr_list_en | HCFG_PERSCHEDENA;
        dev_vdbg(hsotg->dev, "Enabling Periodic schedule\n");
-       writel(hcfg, hsotg->regs + HCFG);
+       dwc2_writel(hcfg, hsotg->regs + HCFG);
 
        spin_unlock_irqrestore(&hsotg->lock, flags);
 }
@@ -193,7 +193,7 @@ static void dwc2_per_sched_disable(struct dwc2_hsotg *hsotg)
 
        spin_lock_irqsave(&hsotg->lock, flags);
 
-       hcfg = readl(hsotg->regs + HCFG);
+       hcfg = dwc2_readl(hsotg->regs + HCFG);
        if (!(hcfg & HCFG_PERSCHEDENA)) {
                /* already disabled */
                spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -202,7 +202,7 @@ static void dwc2_per_sched_disable(struct dwc2_hsotg *hsotg)
 
        hcfg &= ~HCFG_PERSCHEDENA;
        dev_vdbg(hsotg->dev, "Disabling Periodic schedule\n");
-       writel(hcfg, hsotg->regs + HCFG);
+       dwc2_writel(hcfg, hsotg->regs + HCFG);
 
        spin_unlock_irqrestore(&hsotg->lock, flags);
 }
index 4cc95df4262d27eed328ea904b347e4ee520351f..bda0b21b850f695627efb5b1e70ae0e63de39638 100644 (file)
@@ -148,7 +148,7 @@ static void dwc2_sof_intr(struct dwc2_hsotg *hsotg)
                dwc2_hcd_queue_transactions(hsotg, tr_type);
 
        /* Clear interrupt */
-       writel(GINTSTS_SOF, hsotg->regs + GINTSTS);
+       dwc2_writel(GINTSTS_SOF, hsotg->regs + GINTSTS);
 }
 
 /*
@@ -164,7 +164,7 @@ static void dwc2_rx_fifo_level_intr(struct dwc2_hsotg *hsotg)
        if (dbg_perio())
                dev_vdbg(hsotg->dev, "--RxFIFO Level Interrupt--\n");
 
-       grxsts = readl(hsotg->regs + GRXSTSP);
+       grxsts = dwc2_readl(hsotg->regs + GRXSTSP);
        chnum = (grxsts & GRXSTS_HCHNUM_MASK) >> GRXSTS_HCHNUM_SHIFT;
        chan = hsotg->hc_ptr_array[chnum];
        if (!chan) {
@@ -247,11 +247,11 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0,
        dev_vdbg(hsotg->dev, "%s(%p)\n", __func__, hsotg);
 
        /* Every time when port enables calculate HFIR.FrInterval */
-       hfir = readl(hsotg->regs + HFIR);
+       hfir = dwc2_readl(hsotg->regs + HFIR);
        hfir &= ~HFIR_FRINT_MASK;
        hfir |= dwc2_calc_frame_interval(hsotg) << HFIR_FRINT_SHIFT &
                HFIR_FRINT_MASK;
-       writel(hfir, hsotg->regs + HFIR);
+       dwc2_writel(hfir, hsotg->regs + HFIR);
 
        /* Check if we need to adjust the PHY clock speed for low power */
        if (!params->host_support_fs_ls_low_power) {
@@ -260,7 +260,7 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0,
                return;
        }
 
-       usbcfg = readl(hsotg->regs + GUSBCFG);
+       usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
        prtspd = (hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT;
 
        if (prtspd == HPRT0_SPD_LOW_SPEED || prtspd == HPRT0_SPD_FULL_SPEED) {
@@ -268,11 +268,11 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0,
                if (!(usbcfg & GUSBCFG_PHY_LP_CLK_SEL)) {
                        /* Set PHY low power clock select for FS/LS devices */
                        usbcfg |= GUSBCFG_PHY_LP_CLK_SEL;
-                       writel(usbcfg, hsotg->regs + GUSBCFG);
+                       dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
                        do_reset = 1;
                }
 
-               hcfg = readl(hsotg->regs + HCFG);
+               hcfg = dwc2_readl(hsotg->regs + HCFG);
                fslspclksel = (hcfg & HCFG_FSLSPCLKSEL_MASK) >>
                              HCFG_FSLSPCLKSEL_SHIFT;
 
@@ -286,7 +286,7 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0,
                                fslspclksel = HCFG_FSLSPCLKSEL_6_MHZ;
                                hcfg &= ~HCFG_FSLSPCLKSEL_MASK;
                                hcfg |= fslspclksel << HCFG_FSLSPCLKSEL_SHIFT;
-                               writel(hcfg, hsotg->regs + HCFG);
+                               dwc2_writel(hcfg, hsotg->regs + HCFG);
                                do_reset = 1;
                        }
                } else {
@@ -297,7 +297,7 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0,
                                fslspclksel = HCFG_FSLSPCLKSEL_48_MHZ;
                                hcfg &= ~HCFG_FSLSPCLKSEL_MASK;
                                hcfg |= fslspclksel << HCFG_FSLSPCLKSEL_SHIFT;
-                               writel(hcfg, hsotg->regs + HCFG);
+                               dwc2_writel(hcfg, hsotg->regs + HCFG);
                                do_reset = 1;
                        }
                }
@@ -305,7 +305,7 @@ static void dwc2_hprt0_enable(struct dwc2_hsotg *hsotg, u32 hprt0,
                /* Not low power */
                if (usbcfg & GUSBCFG_PHY_LP_CLK_SEL) {
                        usbcfg &= ~GUSBCFG_PHY_LP_CLK_SEL;
-                       writel(usbcfg, hsotg->regs + GUSBCFG);
+                       dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
                        do_reset = 1;
                }
        }
@@ -332,7 +332,7 @@ static void dwc2_port_intr(struct dwc2_hsotg *hsotg)
 
        dev_vdbg(hsotg->dev, "--Port Interrupt--\n");
 
-       hprt0 = readl(hsotg->regs + HPRT0);
+       hprt0 = dwc2_readl(hsotg->regs + HPRT0);
        hprt0_modify = hprt0;
 
        /*
@@ -388,7 +388,7 @@ static void dwc2_port_intr(struct dwc2_hsotg *hsotg)
        }
 
        /* Clear Port Interrupts */
-       writel(hprt0_modify, hsotg->regs + HPRT0);
+       dwc2_writel(hprt0_modify, hsotg->regs + HPRT0);
 }
 
 /*
@@ -408,7 +408,7 @@ static u32 dwc2_get_actual_xfer_length(struct dwc2_hsotg *hsotg,
 {
        u32 hctsiz, count, length;
 
-       hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
+       hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum));
 
        if (halt_status == DWC2_HC_XFER_COMPLETE) {
                if (chan->ep_is_in) {
@@ -491,7 +491,7 @@ static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg,
                urb->status = 0;
        }
 
-       hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
+       hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum));
        dev_vdbg(hsotg->dev, "DWC_otg: %s: %s, channel %d\n",
                 __func__, (chan->ep_is_in ? "IN" : "OUT"), chnum);
        dev_vdbg(hsotg->dev, "  chan->xfer_len %d\n", chan->xfer_len);
@@ -514,7 +514,7 @@ void dwc2_hcd_save_data_toggle(struct dwc2_hsotg *hsotg,
                               struct dwc2_host_chan *chan, int chnum,
                               struct dwc2_qtd *qtd)
 {
-       u32 hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
+       u32 hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum));
        u32 pid = (hctsiz & TSIZ_SC_MC_PID_MASK) >> TSIZ_SC_MC_PID_SHIFT;
 
        if (chan->ep_type != USB_ENDPOINT_XFER_CONTROL) {
@@ -771,9 +771,9 @@ cleanup:
                }
        }
 
-       haintmsk = readl(hsotg->regs + HAINTMSK);
+       haintmsk = dwc2_readl(hsotg->regs + HAINTMSK);
        haintmsk &= ~(1 << chan->hc_num);
-       writel(haintmsk, hsotg->regs + HAINTMSK);
+       dwc2_writel(haintmsk, hsotg->regs + HAINTMSK);
 
        /* Try to queue more transfers now that there's a free channel */
        tr_type = dwc2_hcd_select_transactions(hsotg);
@@ -820,9 +820,9 @@ static void dwc2_halt_channel(struct dwc2_hsotg *hsotg,
                         * is enabled so that the non-periodic schedule will
                         * be processed
                         */
-                       gintmsk = readl(hsotg->regs + GINTMSK);
+                       gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
                        gintmsk |= GINTSTS_NPTXFEMP;
-                       writel(gintmsk, hsotg->regs + GINTMSK);
+                       dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
                } else {
                        dev_vdbg(hsotg->dev, "isoc/intr\n");
                        /*
@@ -839,9 +839,9 @@ static void dwc2_halt_channel(struct dwc2_hsotg *hsotg,
                         * enabled so that the periodic schedule will be
                         * processed
                         */
-                       gintmsk = readl(hsotg->regs + GINTMSK);
+                       gintmsk = dwc2_readl(hsotg->regs + GINTMSK);
                        gintmsk |= GINTSTS_PTXFEMP;
-                       writel(gintmsk, hsotg->regs + GINTMSK);
+                       dwc2_writel(gintmsk, hsotg->regs + GINTMSK);
                }
        }
 }
@@ -906,7 +906,7 @@ static void dwc2_complete_periodic_xfer(struct dwc2_hsotg *hsotg,
                                        struct dwc2_qtd *qtd,
                                        enum dwc2_halt_status halt_status)
 {
-       u32 hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
+       u32 hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum));
 
        qtd->error_count = 0;
 
@@ -1184,7 +1184,7 @@ static void dwc2_update_urb_state_abn(struct dwc2_hsotg *hsotg,
 
        urb->actual_length += xfer_length;
 
-       hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
+       hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum));
        dev_vdbg(hsotg->dev, "DWC_otg: %s: %s, channel %d\n",
                 __func__, (chan->ep_is_in ? "IN" : "OUT"), chnum);
        dev_vdbg(hsotg->dev, "  chan->start_pkt_count %d\n",
@@ -1505,10 +1505,10 @@ static void dwc2_hc_ahberr_intr(struct dwc2_hsotg *hsotg,
 
        dwc2_hc_handle_tt_clear(hsotg, chan, qtd);
 
-       hcchar = readl(hsotg->regs + HCCHAR(chnum));
-       hcsplt = readl(hsotg->regs + HCSPLT(chnum));
-       hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
-       hc_dma = readl(hsotg->regs + HCDMA(chnum));
+       hcchar = dwc2_readl(hsotg->regs + HCCHAR(chnum));
+       hcsplt = dwc2_readl(hsotg->regs + HCSPLT(chnum));
+       hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum));
+       hc_dma = dwc2_readl(hsotg->regs + HCDMA(chnum));
 
        dev_err(hsotg->dev, "AHB ERROR, Channel %d\n", chnum);
        dev_err(hsotg->dev, "  hcchar 0x%08x, hcsplt 0x%08x\n", hcchar, hcsplt);
@@ -1721,10 +1721,10 @@ static bool dwc2_halt_status_ok(struct dwc2_hsotg *hsotg,
                 * This code is here only as a check. This condition should
                 * never happen. Ignore the halt if it does occur.
                 */
-               hcchar = readl(hsotg->regs + HCCHAR(chnum));
-               hctsiz = readl(hsotg->regs + HCTSIZ(chnum));
-               hcintmsk = readl(hsotg->regs + HCINTMSK(chnum));
-               hcsplt = readl(hsotg->regs + HCSPLT(chnum));
+               hcchar = dwc2_readl(hsotg->regs + HCCHAR(chnum));
+               hctsiz = dwc2_readl(hsotg->regs + HCTSIZ(chnum));
+               hcintmsk = dwc2_readl(hsotg->regs + HCINTMSK(chnum));
+               hcsplt = dwc2_readl(hsotg->regs + HCSPLT(chnum));
                dev_dbg(hsotg->dev,
                        "%s: chan->halt_status DWC2_HC_XFER_NO_HALT_STATUS,\n",
                         __func__);
@@ -1748,7 +1748,7 @@ static bool dwc2_halt_status_ok(struct dwc2_hsotg *hsotg,
         * when the halt interrupt occurs. Halt the channel again if it does
         * occur.
         */
-       hcchar = readl(hsotg->regs + HCCHAR(chnum));
+       hcchar = dwc2_readl(hsotg->regs + HCCHAR(chnum));
        if (hcchar & HCCHAR_CHDIS) {
                dev_warn(hsotg->dev,
                         "%s: hcchar.chdis set unexpectedly, hcchar 0x%08x, trying to halt again\n",
@@ -1808,7 +1808,7 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg,
                return;
        }
 
-       hcintmsk = readl(hsotg->regs + HCINTMSK(chnum));
+       hcintmsk = dwc2_readl(hsotg->regs + HCINTMSK(chnum));
 
        if (chan->hcint & HCINTMSK_XFERCOMPL) {
                /*
@@ -1903,7 +1903,7 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg,
                                dev_err(hsotg->dev,
                                        "hcint 0x%08x, intsts 0x%08x\n",
                                        chan->hcint,
-                                       readl(hsotg->regs + GINTSTS));
+                                       dwc2_readl(hsotg->regs + GINTSTS));
                                goto error;
                        }
                }
@@ -1949,6 +1949,24 @@ static void dwc2_hc_chhltd_intr(struct dwc2_hsotg *hsotg,
        }
 }
 
+/*
+ * Check if the given qtd is still the top of the list (and thus valid).
+ *
+ * If dwc2_hcd_qtd_unlink_and_free() has been called since we grabbed
+ * the qtd from the top of the list, this will return false (otherwise true).
+ */
+static bool dwc2_check_qtd_still_ok(struct dwc2_qtd *qtd, struct dwc2_qh *qh)
+{
+       struct dwc2_qtd *cur_head;
+
+       if (qh == NULL)
+               return false;
+
+       cur_head = list_first_entry(&qh->qtd_list, struct dwc2_qtd,
+                                   qtd_list_entry);
+       return (cur_head == qtd);
+}
+
 /* Handles interrupt for a specific Host Channel */
 static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
 {
@@ -1958,11 +1976,11 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
 
        chan = hsotg->hc_ptr_array[chnum];
 
-       hcint = readl(hsotg->regs + HCINT(chnum));
-       hcintmsk = readl(hsotg->regs + HCINTMSK(chnum));
+       hcint = dwc2_readl(hsotg->regs + HCINT(chnum));
+       hcintmsk = dwc2_readl(hsotg->regs + HCINTMSK(chnum));
        if (!chan) {
                dev_err(hsotg->dev, "## hc_ptr_array for channel is NULL ##\n");
-               writel(hcint, hsotg->regs + HCINT(chnum));
+               dwc2_writel(hcint, hsotg->regs + HCINT(chnum));
                return;
        }
 
@@ -1974,7 +1992,7 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
                         hcint, hcintmsk, hcint & hcintmsk);
        }
 
-       writel(hcint, hsotg->regs + HCINT(chnum));
+       dwc2_writel(hcint, hsotg->regs + HCINT(chnum));
        chan->hcint = hcint;
        hcint &= hcintmsk;
 
@@ -2031,27 +2049,59 @@ static void dwc2_hc_n_intr(struct dwc2_hsotg *hsotg, int chnum)
                 */
                hcint &= ~HCINTMSK_NYET;
        }
-       if (hcint & HCINTMSK_CHHLTD)
+
+       if (hcint & HCINTMSK_CHHLTD) {
                dwc2_hc_chhltd_intr(hsotg, chan, chnum, qtd);
-       if (hcint & HCINTMSK_AHBERR)
+               if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+                       goto exit;
+       }
+       if (hcint & HCINTMSK_AHBERR) {
                dwc2_hc_ahberr_intr(hsotg, chan, chnum, qtd);
-       if (hcint & HCINTMSK_STALL)
+               if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+                       goto exit;
+       }
+       if (hcint & HCINTMSK_STALL) {
                dwc2_hc_stall_intr(hsotg, chan, chnum, qtd);
-       if (hcint & HCINTMSK_NAK)
+               if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+                       goto exit;
+       }
+       if (hcint & HCINTMSK_NAK) {
                dwc2_hc_nak_intr(hsotg, chan, chnum, qtd);
-       if (hcint & HCINTMSK_ACK)
+               if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+                       goto exit;
+       }
+       if (hcint & HCINTMSK_ACK) {
                dwc2_hc_ack_intr(hsotg, chan, chnum, qtd);
-       if (hcint & HCINTMSK_NYET)
+               if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+                       goto exit;
+       }
+       if (hcint & HCINTMSK_NYET) {
                dwc2_hc_nyet_intr(hsotg, chan, chnum, qtd);
-       if (hcint & HCINTMSK_XACTERR)
+               if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+                       goto exit;
+       }
+       if (hcint & HCINTMSK_XACTERR) {
                dwc2_hc_xacterr_intr(hsotg, chan, chnum, qtd);
-       if (hcint & HCINTMSK_BBLERR)
+               if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+                       goto exit;
+       }
+       if (hcint & HCINTMSK_BBLERR) {
                dwc2_hc_babble_intr(hsotg, chan, chnum, qtd);
-       if (hcint & HCINTMSK_FRMOVRUN)
+               if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+                       goto exit;
+       }
+       if (hcint & HCINTMSK_FRMOVRUN) {
                dwc2_hc_frmovrun_intr(hsotg, chan, chnum, qtd);
-       if (hcint & HCINTMSK_DATATGLERR)
+               if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+                       goto exit;
+       }
+       if (hcint & HCINTMSK_DATATGLERR) {
                dwc2_hc_datatglerr_intr(hsotg, chan, chnum, qtd);
+               if (!dwc2_check_qtd_still_ok(qtd, chan->qh))
+                       goto exit;
+       }
 
+exit:
        chan->hcint = 0;
 }
 
@@ -2066,7 +2116,7 @@ static void dwc2_hc_intr(struct dwc2_hsotg *hsotg)
        u32 haint;
        int i;
 
-       haint = readl(hsotg->regs + HAINT);
+       haint = dwc2_readl(hsotg->regs + HAINT);
        if (dbg_perio()) {
                dev_vdbg(hsotg->dev, "%s()\n", __func__);
 
@@ -2134,8 +2184,8 @@ irqreturn_t dwc2_handle_hcd_intr(struct dwc2_hsotg *hsotg)
                                 "DWC OTG HCD Finished Servicing Interrupts\n");
                        dev_vdbg(hsotg->dev,
                                 "DWC OTG HCD gintsts=0x%08x gintmsk=0x%08x\n",
-                                readl(hsotg->regs + GINTSTS),
-                                readl(hsotg->regs + GINTMSK));
+                                dwc2_readl(hsotg->regs + GINTSTS),
+                                dwc2_readl(hsotg->regs + GINTMSK));
                }
        }
 
index 3ad63d392e13f51c5e9aa8a31069de3795cdf86f..7d8d06cfe3c1df1d5bc1a5534205464d89f65a56 100644 (file)
@@ -106,6 +106,9 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
                                USB_SPEED_HIGH : dev_speed, qh->ep_is_in,
                                qh->ep_type == USB_ENDPOINT_XFER_ISOC,
                                bytecount));
+
+               /* Ensure frame_number corresponds to the reality */
+               hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg);
                /* Start in a slightly future (micro)frame */
                qh->sched_frame = dwc2_frame_num_inc(hsotg->frame_number,
                                                     SCHEDULE_SLOP);
@@ -115,7 +118,7 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
                if (qh->ep_type == USB_ENDPOINT_XFER_INT)
                        qh->interval = 8;
 #endif
-               hprt = readl(hsotg->regs + HPRT0);
+               hprt = dwc2_readl(hsotg->regs + HPRT0);
                prtspd = (hprt & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT;
                if (prtspd == HPRT0_SPD_HIGH_SPEED &&
                    (dev_speed == USB_SPEED_LOW ||
@@ -583,6 +586,14 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
                /* QH already in a schedule */
                return 0;
 
+       if (!dwc2_frame_num_le(qh->sched_frame, hsotg->frame_number) &&
+                       !hsotg->frame_number) {
+               dev_dbg(hsotg->dev,
+                               "reset frame number counter\n");
+               qh->sched_frame = dwc2_frame_num_inc(hsotg->frame_number,
+                               SCHEDULE_SLOP);
+       }
+
        /* Add the new QH to the appropriate schedule */
        if (dwc2_qh_is_non_per(qh)) {
                /* Always start in inactive schedule */
@@ -595,9 +606,9 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
        if (status)
                return status;
        if (!hsotg->periodic_qh_count) {
-               intr_mask = readl(hsotg->regs + GINTMSK);
+               intr_mask = dwc2_readl(hsotg->regs + GINTMSK);
                intr_mask |= GINTSTS_SOF;
-               writel(intr_mask, hsotg->regs + GINTMSK);
+               dwc2_writel(intr_mask, hsotg->regs + GINTMSK);
        }
        hsotg->periodic_qh_count++;
 
@@ -632,9 +643,9 @@ void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh)
        dwc2_deschedule_periodic(hsotg, qh);
        hsotg->periodic_qh_count--;
        if (!hsotg->periodic_qh_count) {
-               intr_mask = readl(hsotg->regs + GINTMSK);
+               intr_mask = dwc2_readl(hsotg->regs + GINTMSK);
                intr_mask &= ~GINTSTS_SOF;
-               writel(intr_mask, hsotg->regs + GINTMSK);
+               dwc2_writel(intr_mask, hsotg->regs + GINTMSK);
        }
 }
 
index d0a5ed8fa15a481bb7c659367b9da5f9212fbb59..553f24606c43c9ef77306bc97d1250535e878679 100644 (file)
 #define GINTSTS_RESETDET               (1 << 23)
 #define GINTSTS_FET_SUSP               (1 << 22)
 #define GINTSTS_INCOMPL_IP             (1 << 21)
+#define GINTSTS_INCOMPL_SOOUT          (1 << 21)
 #define GINTSTS_INCOMPL_SOIN           (1 << 20)
 #define GINTSTS_OEPINT                 (1 << 19)
 #define GINTSTS_IEPINT                 (1 << 18)
index 90935304185a01ab93bb28d9ad7ac4a2b5364e6e..5859b0fa19ee3f907b2bfa93945a6378ae10911a 100644 (file)
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/of_device.h>
 #include <linux/mutex.h>
 #include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_data/s3c-hsotg.h>
 
 #include <linux/usb/of.h>
 
@@ -111,6 +114,145 @@ static const struct dwc2_core_params params_rk3066 = {
        .hibernation                    = -1,
 };
 
+static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg)
+{
+       struct platform_device *pdev = to_platform_device(hsotg->dev);
+       int ret;
+
+       ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
+                                   hsotg->supplies);
+       if (ret)
+               return ret;
+
+       ret = clk_prepare_enable(hsotg->clk);
+       if (ret)
+               return ret;
+
+       if (hsotg->uphy)
+               ret = usb_phy_init(hsotg->uphy);
+       else if (hsotg->plat && hsotg->plat->phy_init)
+               ret = hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
+       else {
+               ret = phy_power_on(hsotg->phy);
+               if (ret == 0)
+                       ret = phy_init(hsotg->phy);
+       }
+
+       return ret;
+}
+
+/**
+ * dwc2_lowlevel_hw_enable - enable platform lowlevel hw resources
+ * @hsotg: The driver state
+ *
+ * A wrapper for platform code responsible for controlling
+ * low-level USB platform resources (phy, clock, regulators)
+ */
+int dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg)
+{
+       int ret = __dwc2_lowlevel_hw_enable(hsotg);
+
+       if (ret == 0)
+               hsotg->ll_hw_enabled = true;
+       return ret;
+}
+
+static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg)
+{
+       struct platform_device *pdev = to_platform_device(hsotg->dev);
+       int ret = 0;
+
+       if (hsotg->uphy)
+               usb_phy_shutdown(hsotg->uphy);
+       else if (hsotg->plat && hsotg->plat->phy_exit)
+               ret = hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
+       else {
+               ret = phy_exit(hsotg->phy);
+               if (ret == 0)
+                       ret = phy_power_off(hsotg->phy);
+       }
+       if (ret)
+               return ret;
+
+       clk_disable_unprepare(hsotg->clk);
+
+       ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
+                                    hsotg->supplies);
+
+       return ret;
+}
+
+/**
+ * dwc2_lowlevel_hw_disable - disable platform lowlevel hw resources
+ * @hsotg: The driver state
+ *
+ * A wrapper for platform code responsible for controlling
+ * low-level USB platform resources (phy, clock, regulators)
+ */
+int dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg)
+{
+       int ret = __dwc2_lowlevel_hw_disable(hsotg);
+
+       if (ret == 0)
+               hsotg->ll_hw_enabled = false;
+       return ret;
+}
+
+static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
+{
+       int i, ret;
+
+       /* Set default UTMI width */
+       hsotg->phyif = GUSBCFG_PHYIF16;
+
+       /*
+        * Attempt to find a generic PHY, then look for an old style
+        * USB PHY and then fall back to pdata
+        */
+       hsotg->phy = devm_phy_get(hsotg->dev, "usb2-phy");
+       if (IS_ERR(hsotg->phy)) {
+               hsotg->phy = NULL;
+               hsotg->uphy = devm_usb_get_phy(hsotg->dev, USB_PHY_TYPE_USB2);
+               if (IS_ERR(hsotg->uphy))
+                       hsotg->uphy = NULL;
+               else
+                       hsotg->plat = dev_get_platdata(hsotg->dev);
+       }
+
+       if (hsotg->phy) {
+               /*
+                * If using the generic PHY framework, check if the PHY bus
+                * width is 8-bit and set the phyif appropriately.
+                */
+               if (phy_get_bus_width(hsotg->phy) == 8)
+                       hsotg->phyif = GUSBCFG_PHYIF8;
+       }
+
+       if (!hsotg->phy && !hsotg->uphy && !hsotg->plat) {
+               dev_err(hsotg->dev, "no platform data or transceiver defined\n");
+               return -EPROBE_DEFER;
+       }
+
+       /* Clock */
+       hsotg->clk = devm_clk_get(hsotg->dev, "otg");
+       if (IS_ERR(hsotg->clk)) {
+               hsotg->clk = NULL;
+               dev_dbg(hsotg->dev, "cannot get otg clock\n");
+       }
+
+       /* Regulators */
+       for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++)
+               hsotg->supplies[i].supply = dwc2_hsotg_supply_names[i];
+
+       ret = devm_regulator_bulk_get(hsotg->dev, ARRAY_SIZE(hsotg->supplies),
+                                     hsotg->supplies);
+       if (ret) {
+               dev_err(hsotg->dev, "failed to request supplies: %d\n", ret);
+               return ret;
+       }
+       return 0;
+}
+
 /**
  * dwc2_driver_remove() - Called when the DWC_otg core is unregistered with the
  * DWC_otg driver
@@ -130,7 +272,10 @@ static int dwc2_driver_remove(struct platform_device *dev)
        if (hsotg->hcd_enabled)
                dwc2_hcd_remove(hsotg);
        if (hsotg->gadget_enabled)
-               s3c_hsotg_remove(hsotg);
+               dwc2_hsotg_remove(hsotg);
+
+       if (hsotg->ll_hw_enabled)
+               dwc2_lowlevel_hw_disable(hsotg);
 
        return 0;
 }
@@ -163,8 +308,6 @@ static int dwc2_driver_probe(struct platform_device *dev)
        struct dwc2_core_params defparams;
        struct dwc2_hsotg *hsotg;
        struct resource *res;
-       struct phy *phy;
-       struct usb_phy *uphy;
        int retval;
        int irq;
 
@@ -220,34 +363,25 @@ static int dwc2_driver_probe(struct platform_device *dev)
        dev_dbg(&dev->dev, "mapped PA %08lx to VA %p\n",
                (unsigned long)res->start, hsotg->regs);
 
-       hsotg->dr_mode = of_usb_get_dr_mode(dev->dev.of_node);
-
-       /*
-        * Attempt to find a generic PHY, then look for an old style
-        * USB PHY
-        */
-       phy = devm_phy_get(&dev->dev, "usb2-phy");
-       if (IS_ERR(phy)) {
-               hsotg->phy = NULL;
-               uphy = devm_usb_get_phy(&dev->dev, USB_PHY_TYPE_USB2);
-               if (IS_ERR(uphy))
-                       hsotg->uphy = NULL;
-               else
-                       hsotg->uphy = uphy;
-       } else {
-               hsotg->phy = phy;
-               phy_power_on(hsotg->phy);
-               phy_init(hsotg->phy);
+       hsotg->dr_mode = usb_get_dr_mode(&dev->dev);
+       if (IS_ENABLED(CONFIG_USB_DWC2_HOST) &&
+                       hsotg->dr_mode != USB_DR_MODE_HOST) {
+               hsotg->dr_mode = USB_DR_MODE_HOST;
+               dev_warn(hsotg->dev,
+                       "Configuration mismatch. Forcing host mode\n");
+       } else if (IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) &&
+                       hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) {
+               hsotg->dr_mode = USB_DR_MODE_PERIPHERAL;
+               dev_warn(hsotg->dev,
+                       "Configuration mismatch. Forcing peripheral mode\n");
        }
 
-       spin_lock_init(&hsotg->lock);
-       mutex_init(&hsotg->init_mutex);
-
-       /* Detect config values from hardware */
-       retval = dwc2_get_hwparams(hsotg);
+       retval = dwc2_lowlevel_hw_init(hsotg);
        if (retval)
                return retval;
 
+       spin_lock_init(&hsotg->lock);
+
        hsotg->core_params = devm_kzalloc(&dev->dev,
                                sizeof(*hsotg->core_params), GFP_KERNEL);
        if (!hsotg->core_params)
@@ -255,13 +389,22 @@ static int dwc2_driver_probe(struct platform_device *dev)
 
        dwc2_set_all_params(hsotg->core_params, -1);
 
+       retval = dwc2_lowlevel_hw_enable(hsotg);
+       if (retval)
+               return retval;
+
+       /* Detect config values from hardware */
+       retval = dwc2_get_hwparams(hsotg);
+       if (retval)
+               goto error;
+
        /* Validate parameter values */
        dwc2_set_parameters(hsotg, params);
 
        if (hsotg->dr_mode != USB_DR_MODE_HOST) {
                retval = dwc2_gadget_init(hsotg, irq);
                if (retval)
-                       return retval;
+                       goto error;
                hsotg->gadget_enabled = 1;
        }
 
@@ -269,8 +412,8 @@ static int dwc2_driver_probe(struct platform_device *dev)
                retval = dwc2_hcd_init(hsotg, irq);
                if (retval) {
                        if (hsotg->gadget_enabled)
-                               s3c_hsotg_remove(hsotg);
-                       return retval;
+                               dwc2_hsotg_remove(hsotg);
+                       goto error;
                }
                hsotg->hcd_enabled = 1;
        }
@@ -279,6 +422,14 @@ static int dwc2_driver_probe(struct platform_device *dev)
 
        dwc2_debugfs_init(hsotg);
 
+       /* Gadget code manages lowlevel hw on its own */
+       if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
+               dwc2_lowlevel_hw_disable(hsotg);
+
+       return 0;
+
+error:
+       dwc2_lowlevel_hw_disable(hsotg);
        return retval;
 }
 
@@ -287,15 +438,12 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
        struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
        int ret = 0;
 
-       if (dwc2_is_device_mode(dwc2)) {
-               ret = s3c_hsotg_suspend(dwc2);
-       } else {
-               if (dwc2->lx_state == DWC2_L0)
-                       return 0;
-               phy_exit(dwc2->phy);
-               phy_power_off(dwc2->phy);
+       if (dwc2_is_device_mode(dwc2))
+               dwc2_hsotg_suspend(dwc2);
+
+       if (dwc2->ll_hw_enabled)
+               ret = __dwc2_lowlevel_hw_disable(dwc2);
 
-       }
        return ret;
 }
 
@@ -304,13 +452,15 @@ static int __maybe_unused dwc2_resume(struct device *dev)
        struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
        int ret = 0;
 
-       if (dwc2_is_device_mode(dwc2)) {
-               ret = s3c_hsotg_resume(dwc2);
-       } else {
-               phy_power_on(dwc2->phy);
-               phy_init(dwc2->phy);
-
+       if (dwc2->ll_hw_enabled) {
+               ret = __dwc2_lowlevel_hw_enable(dwc2);
+               if (ret)
+                       return ret;
        }
+
+       if (dwc2_is_device_mode(dwc2))
+               ret = dwc2_hsotg_resume(dwc2);
+
        return ret;
 }
 
index 064123e445664a5e23bb28ba48cfb1755ec7fb88..22b4797383cd0021953b58e1f8d60178eeb89389 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/of.h>
 #include <linux/acpi.h>
+#include <linux/pinctrl/consumer.h>
 
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
@@ -143,6 +144,32 @@ static int dwc3_soft_reset(struct dwc3 *dwc)
        return 0;
 }
 
+/*
+ * dwc3_frame_length_adjustment - Adjusts frame length if required
+ * @dwc3: Pointer to our controller context structure
+ * @fladj: Value of GFLADJ_30MHZ to adjust frame length
+ */
+static void dwc3_frame_length_adjustment(struct dwc3 *dwc, u32 fladj)
+{
+       u32 reg;
+       u32 dft;
+
+       if (dwc->revision < DWC3_REVISION_250A)
+               return;
+
+       if (fladj == 0)
+               return;
+
+       reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
+       dft = reg & DWC3_GFLADJ_30MHZ_MASK;
+       if (!dev_WARN_ONCE(dwc->dev, dft == fladj,
+           "request value same as default, ignoring\n")) {
+               reg &= ~DWC3_GFLADJ_30MHZ_MASK;
+               reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | fladj;
+               dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
+       }
+}
+
 /**
  * dwc3_free_one_event_buffer - Frees one event buffer
  * @dwc: Pointer to our controller context structure
@@ -488,6 +515,9 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
        if (dwc->dis_u2_susphy_quirk)
                reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
 
+       if (dwc->dis_enblslpm_quirk)
+               reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
+
        dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
 
        return 0;
@@ -507,12 +537,18 @@ static int dwc3_core_init(struct dwc3 *dwc)
 
        reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
        /* This should read as U3 followed by revision number */
-       if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) {
+       if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) {
+               /* Detected DWC_usb3 IP */
+               dwc->revision = reg;
+       } else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) {
+               /* Detected DWC_usb31 IP */
+               dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER);
+               dwc->revision |= DWC3_REVISION_IS_DWC31;
+       } else {
                dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n");
                ret = -ENODEV;
                goto err0;
        }
-       dwc->revision = reg;
 
        /*
         * Write Linux Version Code to our GUID register so it's easy to figure
@@ -773,12 +809,12 @@ static int dwc3_probe(struct platform_device *pdev)
 {
        struct device           *dev = &pdev->dev;
        struct dwc3_platform_data *pdata = dev_get_platdata(dev);
-       struct device_node      *node = dev->of_node;
        struct resource         *res;
        struct dwc3             *dwc;
        u8                      lpm_nyet_threshold;
        u8                      tx_de_emphasis;
        u8                      hird_threshold;
+       u32                     fladj = 0;
 
        int                     ret;
 
@@ -842,51 +878,56 @@ static int dwc3_probe(struct platform_device *pdev)
         */
        hird_threshold = 12;
 
-       if (node) {
-               dwc->maximum_speed = of_usb_get_maximum_speed(node);
-               dwc->has_lpm_erratum = of_property_read_bool(node,
+       dwc->maximum_speed = usb_get_maximum_speed(dev);
+       dwc->dr_mode = usb_get_dr_mode(dev);
+
+       dwc->has_lpm_erratum = device_property_read_bool(dev,
                                "snps,has-lpm-erratum");
-               of_property_read_u8(node, "snps,lpm-nyet-threshold",
+       device_property_read_u8(dev, "snps,lpm-nyet-threshold",
                                &lpm_nyet_threshold);
-               dwc->is_utmi_l1_suspend = of_property_read_bool(node,
+       dwc->is_utmi_l1_suspend = device_property_read_bool(dev,
                                "snps,is-utmi-l1-suspend");
-               of_property_read_u8(node, "snps,hird-threshold",
+       device_property_read_u8(dev, "snps,hird-threshold",
                                &hird_threshold);
-               dwc->usb3_lpm_capable = of_property_read_bool(node,
+       dwc->usb3_lpm_capable = device_property_read_bool(dev,
                                "snps,usb3_lpm_capable");
 
-               dwc->needs_fifo_resize = of_property_read_bool(node,
+       dwc->needs_fifo_resize = device_property_read_bool(dev,
                                "tx-fifo-resize");
-               dwc->dr_mode = of_usb_get_dr_mode(node);
 
-               dwc->disable_scramble_quirk = of_property_read_bool(node,
+       dwc->disable_scramble_quirk = device_property_read_bool(dev,
                                "snps,disable_scramble_quirk");
-               dwc->u2exit_lfps_quirk = of_property_read_bool(node,
+       dwc->u2exit_lfps_quirk = device_property_read_bool(dev,
                                "snps,u2exit_lfps_quirk");
-               dwc->u2ss_inp3_quirk = of_property_read_bool(node,
+       dwc->u2ss_inp3_quirk = device_property_read_bool(dev,
                                "snps,u2ss_inp3_quirk");
-               dwc->req_p1p2p3_quirk = of_property_read_bool(node,
+       dwc->req_p1p2p3_quirk = device_property_read_bool(dev,
                                "snps,req_p1p2p3_quirk");
-               dwc->del_p1p2p3_quirk = of_property_read_bool(node,
+       dwc->del_p1p2p3_quirk = device_property_read_bool(dev,
                                "snps,del_p1p2p3_quirk");
-               dwc->del_phy_power_chg_quirk = of_property_read_bool(node,
+       dwc->del_phy_power_chg_quirk = device_property_read_bool(dev,
                                "snps,del_phy_power_chg_quirk");
-               dwc->lfps_filter_quirk = of_property_read_bool(node,
+       dwc->lfps_filter_quirk = device_property_read_bool(dev,
                                "snps,lfps_filter_quirk");
-               dwc->rx_detect_poll_quirk = of_property_read_bool(node,
+       dwc->rx_detect_poll_quirk = device_property_read_bool(dev,
                                "snps,rx_detect_poll_quirk");
-               dwc->dis_u3_susphy_quirk = of_property_read_bool(node,
+       dwc->dis_u3_susphy_quirk = device_property_read_bool(dev,
                                "snps,dis_u3_susphy_quirk");
-               dwc->dis_u2_susphy_quirk = of_property_read_bool(node,
+       dwc->dis_u2_susphy_quirk = device_property_read_bool(dev,
                                "snps,dis_u2_susphy_quirk");
+       dwc->dis_enblslpm_quirk = device_property_read_bool(dev,
+                               "snps,dis_enblslpm_quirk");
 
-               dwc->tx_de_emphasis_quirk = of_property_read_bool(node,
+       dwc->tx_de_emphasis_quirk = device_property_read_bool(dev,
                                "snps,tx_de_emphasis_quirk");
-               of_property_read_u8(node, "snps,tx_de_emphasis",
+       device_property_read_u8(dev, "snps,tx_de_emphasis",
                                &tx_de_emphasis);
-               of_property_read_string(node, "snps,hsphy_interface",
-                                       &dwc->hsphy_interface);
-       } else if (pdata) {
+       device_property_read_string(dev, "snps,hsphy_interface",
+                                   &dwc->hsphy_interface);
+       device_property_read_u32(dev, "snps,quirk-frame-length-adjustment",
+                                &fladj);
+
+       if (pdata) {
                dwc->maximum_speed = pdata->maximum_speed;
                dwc->has_lpm_erratum = pdata->has_lpm_erratum;
                if (pdata->lpm_nyet_threshold)
@@ -909,12 +950,14 @@ static int dwc3_probe(struct platform_device *pdev)
                dwc->rx_detect_poll_quirk = pdata->rx_detect_poll_quirk;
                dwc->dis_u3_susphy_quirk = pdata->dis_u3_susphy_quirk;
                dwc->dis_u2_susphy_quirk = pdata->dis_u2_susphy_quirk;
+               dwc->dis_enblslpm_quirk = pdata->dis_enblslpm_quirk;
 
                dwc->tx_de_emphasis_quirk = pdata->tx_de_emphasis_quirk;
                if (pdata->tx_de_emphasis)
                        tx_de_emphasis = pdata->tx_de_emphasis;
 
                dwc->hsphy_interface = pdata->hsphy_interface;
+               fladj = pdata->fladj_value;
        }
 
        /* default to superspeed if no maximum_speed passed */
@@ -971,6 +1014,9 @@ static int dwc3_probe(struct platform_device *pdev)
                goto err1;
        }
 
+       /* Adjust Frame Length */
+       dwc3_frame_length_adjustment(dwc, fladj);
+
        usb_phy_set_suspend(dwc->usb2_phy, 0);
        usb_phy_set_suspend(dwc->usb3_phy, 0);
        ret = phy_power_on(dwc->usb2_generic_phy);
@@ -1091,6 +1137,8 @@ static int dwc3_suspend(struct device *dev)
        phy_exit(dwc->usb2_generic_phy);
        phy_exit(dwc->usb3_generic_phy);
 
+       pinctrl_pm_select_sleep_state(dev);
+
        return 0;
 }
 
@@ -1100,6 +1148,8 @@ static int dwc3_resume(struct device *dev)
        unsigned long   flags;
        int             ret;
 
+       pinctrl_pm_select_default_state(dev);
+
        usb_phy_init(dwc->usb3_phy);
        usb_phy_init(dwc->usb2_phy);
        ret = phy_init(dwc->usb2_generic_phy);
index 0447788845856e57190561b1117253200c1050a6..36f1cb74588c5b7bff230e3ed91e42f73c3b47e8 100644 (file)
 #define DWC3_GPRTBIMAP_FS0     0xc188
 #define DWC3_GPRTBIMAP_FS1     0xc18c
 
+#define DWC3_VER_NUMBER                0xc1a0
+#define DWC3_VER_TYPE          0xc1a4
+
 #define DWC3_GUSB2PHYCFG(n)    (0xc200 + (n * 0x04))
 #define DWC3_GUSB2I2CCTL(n)    (0xc240 + (n * 0x04))
 
 #define DWC3_GEVNTCOUNT(n)     (0xc40c + (n * 0x10))
 
 #define DWC3_GHWPARAMS8                0xc600
+#define DWC3_GFLADJ            0xc630
 
 /* Device Registers */
 #define DWC3_DCFG              0xc700
 #define DWC3_GUSB2PHYCFG_PHYSOFTRST    (1 << 31)
 #define DWC3_GUSB2PHYCFG_SUSPHY                (1 << 6)
 #define DWC3_GUSB2PHYCFG_ULPI_UTMI     (1 << 4)
+#define DWC3_GUSB2PHYCFG_ENBLSLPM      (1 << 8)
 
 /* Global USB2 PHY Vendor Control Register */
 #define DWC3_GUSB2PHYACC_NEWREGREQ     (1 << 25)
 /* Global HWPARAMS6 Register */
 #define DWC3_GHWPARAMS6_EN_FPGA                        (1 << 7)
 
+/* Global Frame Length Adjustment Register */
+#define DWC3_GFLADJ_30MHZ_SDBND_SEL            (1 << 7)
+#define DWC3_GFLADJ_30MHZ_MASK                 0x3f
+
 /* Device Configuration Register */
 #define DWC3_DCFG_DEVADDR(addr)        ((addr) << 3)
 #define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f)
@@ -712,6 +721,8 @@ struct dwc3_scratchpad_array {
  * @rx_detect_poll_quirk: set if we enable rx_detect to polling lfps quirk
  * @dis_u3_susphy_quirk: set if we disable usb3 suspend phy
  * @dis_u2_susphy_quirk: set if we disable usb2 suspend phy
+ * @dis_enblslpm_quirk: set if we clear enblslpm in GUSB2PHYCFG,
+ *                      disabling the suspend signal to the PHY.
  * @tx_de_emphasis_quirk: set if we enable Tx de-emphasis quirk
  * @tx_de_emphasis: Tx de-emphasis value
  *     0       - -6dB de-emphasis
@@ -766,6 +777,14 @@ struct dwc3 {
        u32                     num_event_buffers;
        u32                     u1u2;
        u32                     maximum_speed;
+
+       /*
+        * All 3.1 IP version constants are greater than the 3.0 IP
+        * version constants. This works for most version checks in
+        * dwc3. However, in the future, this may not apply as
+        * features may be developed on newer versions of the 3.0 IP
+        * that are not in the 3.1 IP.
+        */
        u32                     revision;
 
 #define DWC3_REVISION_173A     0x5533173a
@@ -788,6 +807,13 @@ struct dwc3 {
 #define DWC3_REVISION_270A     0x5533270a
 #define DWC3_REVISION_280A     0x5533280a
 
+/*
+ * NOTICE: we're using bit 31 as a "is usb 3.1" flag. This is really
+ * just so dwc31 revisions are always larger than dwc3.
+ */
+#define DWC3_REVISION_IS_DWC31         0x80000000
+#define DWC3_USB31_REVISION_110A       (0x3131302a | DWC3_REVISION_IS_USB31)
+
        enum dwc3_ep0_next      ep0_next_event;
        enum dwc3_ep0_state     ep0state;
        enum dwc3_link_state    link_state;
@@ -841,6 +867,7 @@ struct dwc3 {
        unsigned                rx_detect_poll_quirk:1;
        unsigned                dis_u3_susphy_quirk:1;
        unsigned                dis_u2_susphy_quirk:1;
+       unsigned                dis_enblslpm_quirk:1;
 
        unsigned                tx_de_emphasis_quirk:1;
        unsigned                tx_de_emphasis:2;
index f62617999f3c7fb093ff09d18088560a6ecb003e..77a622cb48ab1555a87dfaf279f5d25368672e99 100644 (file)
 
 #include "platform_data.h"
 
-#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3        0xabcd
-#define PCI_DEVICE_ID_INTEL_BYT                0x0f37
-#define PCI_DEVICE_ID_INTEL_MRFLD      0x119e
-#define PCI_DEVICE_ID_INTEL_BSW                0x22B7
-#define PCI_DEVICE_ID_INTEL_SPTLP      0x9d30
-#define PCI_DEVICE_ID_INTEL_SPTH       0xa130
+#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3                0xabcd
+#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3_AXI    0xabce
+#define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB31       0xabcf
+#define PCI_DEVICE_ID_INTEL_BYT                        0x0f37
+#define PCI_DEVICE_ID_INTEL_MRFLD              0x119e
+#define PCI_DEVICE_ID_INTEL_BSW                        0x22b7
+#define PCI_DEVICE_ID_INTEL_SPTLP              0x9d30
+#define PCI_DEVICE_ID_INTEL_SPTH               0xa130
 
 static const struct acpi_gpio_params reset_gpios = { 0, 0, false };
 static const struct acpi_gpio_params cs_gpios = { 1, 0, false };
@@ -106,6 +108,22 @@ static int dwc3_pci_quirks(struct pci_dev *pdev)
                }
        }
 
+       if (pdev->vendor == PCI_VENDOR_ID_SYNOPSYS &&
+           (pdev->device == PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 ||
+            pdev->device == PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3_AXI ||
+            pdev->device == PCI_DEVICE_ID_SYNOPSYS_HAPSUSB31)) {
+
+               struct dwc3_platform_data pdata;
+
+               memset(&pdata, 0, sizeof(pdata));
+               pdata.usb3_lpm_capable = true;
+               pdata.has_lpm_erratum = true;
+               pdata.dis_enblslpm_quirk = true;
+
+               return platform_device_add_data(pci_get_drvdata(pdev), &pdata,
+                                               sizeof(pdata));
+       }
+
        return 0;
 }
 
@@ -154,6 +172,7 @@ static int dwc3_pci_probe(struct pci_dev *pci,
                goto err;
 
        dwc3->dev.parent = dev;
+       ACPI_COMPANION_SET(&dwc3->dev, ACPI_COMPANION(dev));
 
        ret = platform_device_add(dwc3);
        if (ret) {
@@ -178,6 +197,14 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
                PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
                                PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3),
        },
+       {
+               PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
+                               PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3_AXI),
+       },
+       {
+               PCI_DEVICE(PCI_VENDOR_ID_SYNOPSYS,
+                               PCI_DEVICE_ID_SYNOPSYS_HAPSUSB31),
+       },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BSW), },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT), },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MRFLD), },
index de4d52f62517a8ec744c0897e97edc516bd8643f..5c0adb9c6fb27baa778615f17705ac6ab7896079 100644 (file)
@@ -195,6 +195,7 @@ static int st_dwc3_probe(struct platform_device *pdev)
        struct resource *res;
        struct device *dev = &pdev->dev;
        struct device_node *node = dev->of_node, *child;
+       struct platform_device *child_pdev;
        struct regmap *regmap;
        int ret;
 
@@ -253,8 +254,6 @@ static int st_dwc3_probe(struct platform_device *pdev)
                goto undo_softreset;
        }
 
-       dwc3_data->dr_mode = of_usb_get_dr_mode(child);
-
        /* Allocate and initialize the core */
        ret = of_platform_populate(node, NULL, NULL, dev);
        if (ret) {
@@ -262,6 +261,15 @@ static int st_dwc3_probe(struct platform_device *pdev)
                goto undo_softreset;
        }
 
+       child_pdev = of_find_device_by_node(child);
+       if (!child_pdev) {
+               dev_err(dev, "failed to find dwc3 core device\n");
+               ret = -ENODEV;
+               goto undo_softreset;
+       }
+
+       dwc3_data->dr_mode = usb_get_dr_mode(&child_pdev->dev);
+
        /*
         * Configure the USB port as device or host according to the static
         * configuration passed from DT.
index 1e8bdf8178113af9db2c556488224acf6504e853..55ba447fdf8bf56720eeac029ed4f96d932ee0ea 100644 (file)
@@ -948,7 +948,6 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param,
                dwc3_trace(trace_dwc3_gadget, "%s: endpoint busy", dep->name);
                return -EBUSY;
        }
-       dep->flags &= ~DWC3_EP_PENDING_REQUEST;
 
        /*
         * If we are getting here after a short-out-packet we don't enqueue any
@@ -1050,6 +1049,8 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
        req->direction          = dep->direction;
        req->epnum              = dep->number;
 
+       trace_dwc3_ep_queue(req);
+
        /*
         * We only add to our list of requests now and
         * start consuming the list once we get XferNotReady
@@ -1069,6 +1070,19 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
 
        list_add_tail(&req->list, &dep->request_list);
 
+       /*
+        * If there are no pending requests and the endpoint isn't already
+        * busy, we will just start the request straight away.
+        *
+        * This will save one IRQ (XFER_NOT_READY) and possibly make it a
+        * little bit faster.
+        */
+       if (!usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
+                       !(dep->flags & DWC3_EP_BUSY)) {
+               ret = __dwc3_gadget_kick_transfer(dep, 0, true);
+               goto out;
+       }
+
        /*
         * There are a few special cases:
         *
@@ -1096,10 +1110,10 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
                }
 
                ret = __dwc3_gadget_kick_transfer(dep, 0, true);
-               if (ret && ret != -EBUSY)
-                       dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
-                                       dep->name);
-               return ret;
+               if (!ret)
+                       dep->flags &= ~DWC3_EP_PENDING_REQUEST;
+
+               goto out;
        }
 
        /*
@@ -1113,10 +1127,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
                WARN_ON_ONCE(!dep->resource_index);
                ret = __dwc3_gadget_kick_transfer(dep, dep->resource_index,
                                false);
-               if (ret && ret != -EBUSY)
-                       dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
-                                       dep->name);
-               return ret;
+               goto out;
        }
 
        /*
@@ -1124,14 +1135,17 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
         * right away, otherwise host will not know we have streams to be
         * handled.
         */
-       if (dep->stream_capable) {
+       if (dep->stream_capable)
                ret = __dwc3_gadget_kick_transfer(dep, 0, true);
-               if (ret && ret != -EBUSY)
-                       dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
-                                       dep->name);
-       }
 
-       return 0;
+out:
+       if (ret && ret != -EBUSY)
+               dev_dbg(dwc->dev, "%s: failed to kick transfers\n",
+                               dep->name);
+       if (ret == -EBUSY)
+               ret = 0;
+
+       return ret;
 }
 
 static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
@@ -1159,8 +1173,6 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
                goto out;
        }
 
-       trace_dwc3_ep_queue(req);
-
        ret = __dwc3_gadget_ep_queue(dep, req);
 
 out:
@@ -1872,27 +1884,32 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep,
        unsigned int            i;
        int                     ret;
 
-       req = next_request(&dep->req_queued);
-       if (!req) {
-               WARN_ON_ONCE(1);
-               return 1;
-       }
-       i = 0;
        do {
-               slot = req->start_slot + i;
-               if ((slot == DWC3_TRB_NUM - 1) &&
+               req = next_request(&dep->req_queued);
+               if (!req) {
+                       WARN_ON_ONCE(1);
+                       return 1;
+               }
+               i = 0;
+               do {
+                       slot = req->start_slot + i;
+                       if ((slot == DWC3_TRB_NUM - 1) &&
                                usb_endpoint_xfer_isoc(dep->endpoint.desc))
-                       slot++;
-               slot %= DWC3_TRB_NUM;
-               trb = &dep->trb_pool[slot];
+                               slot++;
+                       slot %= DWC3_TRB_NUM;
+                       trb = &dep->trb_pool[slot];
+
+                       ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
+                                       event, status);
+                       if (ret)
+                               break;
+               } while (++i < req->request.num_mapped_sgs);
+
+               dwc3_gadget_giveback(dep, req, status);
 
-               ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb,
-                               event, status);
                if (ret)
                        break;
-       } while (++i < req->request.num_mapped_sgs);
-
-       dwc3_gadget_giveback(dep, req, status);
+       } while (1);
 
        if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
                        list_empty(&dep->req_queued)) {
@@ -1955,6 +1972,14 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc,
 
                dwc->u1u2 = 0;
        }
+
+       if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
+               int ret;
+
+               ret = __dwc3_gadget_kick_transfer(dep, 0, is_xfer_complete);
+               if (!ret || ret == -EBUSY)
+                       return;
+       }
 }
 
 static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
@@ -1992,15 +2017,16 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
                if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
                        dwc3_gadget_start_isoc(dwc, dep, event);
                } else {
+                       int active;
                        int ret;
 
+                       active = event->status & DEPEVT_STATUS_TRANSFER_ACTIVE;
+
                        dwc3_trace(trace_dwc3_gadget, "%s: reason %s",
-                                       dep->name, event->status &
-                                       DEPEVT_STATUS_TRANSFER_ACTIVE
-                                       ? "Transfer Active"
+                                       dep->name, active ? "Transfer Active"
                                        : "Transfer Not Active");
 
-                       ret = __dwc3_gadget_kick_transfer(dep, 0, 1);
+                       ret = __dwc3_gadget_kick_transfer(dep, 0, !active);
                        if (!ret || ret == -EBUSY)
                                return;
 
index d3614ecbb9ca284cf6304eee2291ec3ce03a7990..2bb4d3ad0e6b724d71ceae0261955a2551c6859b 100644 (file)
@@ -42,9 +42,12 @@ struct dwc3_platform_data {
        unsigned rx_detect_poll_quirk:1;
        unsigned dis_u3_susphy_quirk:1;
        unsigned dis_u2_susphy_quirk:1;
+       unsigned dis_enblslpm_quirk:1;
 
        unsigned tx_de_emphasis_quirk:1;
        unsigned tx_de_emphasis:2;
 
+       u32 fladj_value;
+
        const char *hsphy_interface;
 };
index bcf83c0a6e62b340899ea661955de89bbfc9df11..33834aa09ed43be03b0dd0ad418febf0ca25432d 100644 (file)
@@ -113,7 +113,7 @@ config USB_GADGET_VBUS_DRAW
 
 config USB_GADGET_STORAGE_NUM_BUFFERS
        int "Number of storage pipeline buffers"
-       range 2 4
+       range 2 32
        default 2
        help
           Usually 2 buffers are enough to establish a good buffering
index b474499839d395289803501fdbb57d5c6c59b785..8b14c2a13ac51abc9d3f433a0261c599ec8cdaf6 100644 (file)
@@ -839,9 +839,7 @@ int usb_add_config(struct usb_composite_dev *cdev,
                }
        }
 
-       /* set_alt(), or next bind(), sets up
-        * ep->driver_data as needed.
-        */
+       /* set_alt(), or next bind(), sets up ep->claimed as needed */
        usb_ep_autoconfig_reset(cdev->gadget);
 
 done:
@@ -1506,6 +1504,8 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
                                } else {
                                        cdev->desc.bcdUSB = cpu_to_le16(0x0210);
                                }
+                       } else {
+                               cdev->desc.bcdUSB = cpu_to_le16(0x0200);
                        }
 
                        value = min(w_length, (u16) sizeof cdev->desc);
index 6399c106a3a55d2a380829af2dcc932c02193094..30fdab0ae38368b07dd957e34b141ddef88c2571 100644 (file)
  * the restrictions that may apply. Some combinations of driver
  * and hardware won't be able to autoconfigure.
  *
- * On success, this returns an un-claimed usb_ep, and modifies the endpoint
+ * On success, this returns an claimed usb_ep, and modifies the endpoint
  * descriptor bEndpointAddress.  For bulk endpoints, the wMaxPacket value
  * is initialized as if the endpoint were used at full speed and
  * the bmAttribute field in the ep companion descriptor is
  * updated with the assigned number of streams if it is
  * different from the original value. To prevent the endpoint
- * from being returned by a later autoconfig call, claim it by
+ * from being returned by a later autoconfig call, claims it by
  * assigning ep->claimed to true.
  *
  * On failure, this returns a null endpoint descriptor.
@@ -154,10 +154,10 @@ EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss);
  * USB controller, and it can't know all the restrictions that may apply.
  * Some combinations of driver and hardware won't be able to autoconfigure.
  *
- * On success, this returns an un-claimed usb_ep, and modifies the endpoint
+ * On success, this returns an claimed usb_ep, and modifies the endpoint
  * descriptor bEndpointAddress.  For bulk endpoints, the wMaxPacket value
  * is initialized as if the endpoint were used at full speed.  To prevent
- * the endpoint from being returned by a later autoconfig call, claim it
+ * the endpoint from being returned by a later autoconfig call, claims it
  * by assigning ep->claimed to true.
  *
  * On failure, this returns a null endpoint descriptor.
@@ -171,6 +171,23 @@ struct usb_ep *usb_ep_autoconfig(
 }
 EXPORT_SYMBOL_GPL(usb_ep_autoconfig);
 
+/**
+ * usb_ep_autoconfig_release - releases endpoint and set it to initial state
+ * @ep: endpoint which should be released
+ *
+ * This function can be used during function bind for endpoints obtained
+ * from usb_ep_autoconfig(). It unclaims endpoint claimed by
+ * usb_ep_autoconfig() to make it available for other functions. Endpoint
+ * which was released is no longer invalid and shouldn't be used in
+ * context of function which released it.
+ */
+void usb_ep_autoconfig_release(struct usb_ep *ep)
+{
+       ep->claimed = false;
+       ep->driver_data = NULL;
+}
+EXPORT_SYMBOL_GPL(usb_ep_autoconfig_release);
+
 /**
  * usb_ep_autoconfig_reset - reset endpoint autoconfig state
  * @gadget: device for which autoconfig state will be reset
index be9df09fde26508c6b658cd0686681fb43e1d4bb..22e723d12d36ff4a6a24b07b703ac6172cf799ba 100644 (file)
@@ -428,21 +428,18 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
        /* we know alt == 0, so this is an activation or a reset */
 
        if (intf == acm->ctrl_id) {
-               if (acm->notify->driver_data) {
-                       dev_vdbg(&cdev->gadget->dev,
-                                "reset acm control interface %d\n", intf);
-                       usb_ep_disable(acm->notify);
-               }
+               dev_vdbg(&cdev->gadget->dev,
+                               "reset acm control interface %d\n", intf);
+               usb_ep_disable(acm->notify);
 
                if (!acm->notify->desc)
                        if (config_ep_by_speed(cdev->gadget, f, acm->notify))
                                return -EINVAL;
 
                usb_ep_enable(acm->notify);
-               acm->notify->driver_data = acm;
 
        } else if (intf == acm->data_id) {
-               if (acm->port.in->driver_data) {
+               if (acm->notify->enabled) {
                        dev_dbg(&cdev->gadget->dev,
                                "reset acm ttyGS%d\n", acm->port_num);
                        gserial_disconnect(&acm->port);
@@ -475,7 +472,6 @@ static void acm_disable(struct usb_function *f)
        dev_dbg(&cdev->gadget->dev, "acm ttyGS%d deactivated\n", acm->port_num);
        gserial_disconnect(&acm->port);
        usb_ep_disable(acm->notify);
-       acm->notify->driver_data = NULL;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -655,19 +651,16 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
        if (!ep)
                goto fail;
        acm->port.in = ep;
-       ep->driver_data = cdev; /* claim */
 
        ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_out_desc);
        if (!ep)
                goto fail;
        acm->port.out = ep;
-       ep->driver_data = cdev; /* claim */
 
        ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_notify_desc);
        if (!ep)
                goto fail;
        acm->notify = ep;
-       ep->driver_data = cdev; /* claim */
 
        /* allocate notification */
        acm->notify_req = gs_alloc_req(ep,
@@ -709,14 +702,6 @@ fail:
        if (acm->notify_req)
                gs_free_req(acm->notify, acm->notify_req);
 
-       /* we might as well release our claims on endpoints */
-       if (acm->notify)
-               acm->notify->driver_data = NULL;
-       if (acm->port.out)
-               acm->port.out->driver_data = NULL;
-       if (acm->port.in)
-               acm->port.in->driver_data = NULL;
-
        ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status);
 
        return status;
index 7b7424f10dddce479fca8945cd238293a2f02cc6..4abca70cdaab9d52e529dcc85b2dabb30137d7e1 100644 (file)
@@ -541,24 +541,21 @@ static int ecm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
                if (alt != 0)
                        goto fail;
 
-               if (ecm->notify->driver_data) {
-                       VDBG(cdev, "reset ecm control %d\n", intf);
-                       usb_ep_disable(ecm->notify);
-               }
+               VDBG(cdev, "reset ecm control %d\n", intf);
+               usb_ep_disable(ecm->notify);
                if (!(ecm->notify->desc)) {
                        VDBG(cdev, "init ecm ctrl %d\n", intf);
                        if (config_ep_by_speed(cdev->gadget, f, ecm->notify))
                                goto fail;
                }
                usb_ep_enable(ecm->notify);
-               ecm->notify->driver_data = ecm;
 
        /* Data interface has two altsettings, 0 and 1 */
        } else if (intf == ecm->data_id) {
                if (alt > 1)
                        goto fail;
 
-               if (ecm->port.in_ep->driver_data) {
+               if (ecm->port.in_ep->enabled) {
                        DBG(cdev, "reset ecm\n");
                        gether_disconnect(&ecm->port);
                }
@@ -618,7 +615,7 @@ static int ecm_get_alt(struct usb_function *f, unsigned intf)
 
        if (intf == ecm->ctrl_id)
                return 0;
-       return ecm->port.in_ep->driver_data ? 1 : 0;
+       return ecm->port.in_ep->enabled ? 1 : 0;
 }
 
 static void ecm_disable(struct usb_function *f)
@@ -628,14 +625,11 @@ static void ecm_disable(struct usb_function *f)
 
        DBG(cdev, "ecm deactivated\n");
 
-       if (ecm->port.in_ep->driver_data)
+       if (ecm->port.in_ep->enabled)
                gether_disconnect(&ecm->port);
 
-       if (ecm->notify->driver_data) {
-               usb_ep_disable(ecm->notify);
-               ecm->notify->driver_data = NULL;
-               ecm->notify->desc = NULL;
-       }
+       usb_ep_disable(ecm->notify);
+       ecm->notify->desc = NULL;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -750,13 +744,11 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
        if (!ep)
                goto fail;
        ecm->port.in_ep = ep;
-       ep->driver_data = cdev; /* claim */
 
        ep = usb_ep_autoconfig(cdev->gadget, &fs_ecm_out_desc);
        if (!ep)
                goto fail;
        ecm->port.out_ep = ep;
-       ep->driver_data = cdev; /* claim */
 
        /* NOTE:  a status/notification endpoint is *OPTIONAL* but we
         * don't treat it that way.  It's simpler, and some newer CDC
@@ -766,7 +758,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
        if (!ep)
                goto fail;
        ecm->notify = ep;
-       ep->driver_data = cdev; /* claim */
 
        status = -ENOMEM;
 
@@ -820,14 +811,6 @@ fail:
                usb_ep_free_request(ecm->notify, ecm->notify_req);
        }
 
-       /* we might as well release our claims on endpoints */
-       if (ecm->notify)
-               ecm->notify->driver_data = NULL;
-       if (ecm->port.out_ep)
-               ecm->port.out_ep->driver_data = NULL;
-       if (ecm->port.in_ep)
-               ecm->port.in_ep->driver_data = NULL;
-
        ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
 
        return status;
index c9e90de5bdd9192c459dd3dea7a9aafa3c086c6b..9a55757c729b2f59f1d512a8f4f67dffa89c5feb 100644 (file)
@@ -195,11 +195,8 @@ static int eem_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
                goto fail;
 
        if (intf == eem->ctrl_id) {
-
-               if (eem->port.in_ep->driver_data) {
-                       DBG(cdev, "reset eem\n");
-                       gether_disconnect(&eem->port);
-               }
+               DBG(cdev, "reset eem\n");
+               gether_disconnect(&eem->port);
 
                if (!eem->port.in_ep->desc || !eem->port.out_ep->desc) {
                        DBG(cdev, "init eem\n");
@@ -237,7 +234,7 @@ static void eem_disable(struct usb_function *f)
 
        DBG(cdev, "eem deactivated\n");
 
-       if (eem->port.in_ep->driver_data)
+       if (eem->port.in_ep->enabled)
                gether_disconnect(&eem->port);
 }
 
@@ -293,13 +290,11 @@ static int eem_bind(struct usb_configuration *c, struct usb_function *f)
        if (!ep)
                goto fail;
        eem->port.in_ep = ep;
-       ep->driver_data = cdev; /* claim */
 
        ep = usb_ep_autoconfig(cdev->gadget, &eem_fs_out_desc);
        if (!ep)
                goto fail;
        eem->port.out_ep = ep;
-       ep->driver_data = cdev; /* claim */
 
        status = -ENOMEM;
 
@@ -325,11 +320,6 @@ static int eem_bind(struct usb_configuration *c, struct usb_function *f)
        return 0;
 
 fail:
-       if (eem->port.out_ep)
-               eem->port.out_ep->driver_data = NULL;
-       if (eem->port.in_ep)
-               eem->port.in_ep->driver_data = NULL;
-
        ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
 
        return status;
index 6df9715a4bcd31179cb190100df45b2dd975a0d2..21fcf18f53a0409ed00bc302ac62b4f012e5c766 100644 (file)
@@ -492,10 +492,7 @@ static void hidg_disable(struct usb_function *f)
        struct f_hidg_req_list *list, *next;
 
        usb_ep_disable(hidg->in_ep);
-       hidg->in_ep->driver_data = NULL;
-
        usb_ep_disable(hidg->out_ep);
-       hidg->out_ep->driver_data = NULL;
 
        list_for_each_entry_safe(list, next, &hidg->completed_out_req, list) {
                list_del(&list->list);
@@ -513,8 +510,7 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 
        if (hidg->in_ep != NULL) {
                /* restart endpoint */
-               if (hidg->in_ep->driver_data != NULL)
-                       usb_ep_disable(hidg->in_ep);
+               usb_ep_disable(hidg->in_ep);
 
                status = config_ep_by_speed(f->config->cdev->gadget, f,
                                            hidg->in_ep);
@@ -533,8 +529,7 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 
        if (hidg->out_ep != NULL) {
                /* restart endpoint */
-               if (hidg->out_ep->driver_data != NULL)
-                       usb_ep_disable(hidg->out_ep);
+               usb_ep_disable(hidg->out_ep);
 
                status = config_ep_by_speed(f->config->cdev->gadget, f,
                                            hidg->out_ep);
@@ -566,7 +561,6 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
                                                hidg->out_ep->name, status);
                        } else {
                                usb_ep_disable(hidg->out_ep);
-                               hidg->out_ep->driver_data = NULL;
                                status = -ENOMEM;
                                goto fail;
                        }
@@ -614,13 +608,11 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
        ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_in_ep_desc);
        if (!ep)
                goto fail;
-       ep->driver_data = c->cdev;      /* claim */
        hidg->in_ep = ep;
 
        ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_out_ep_desc);
        if (!ep)
                goto fail;
-       ep->driver_data = c->cdev;      /* claim */
        hidg->out_ep = ep;
 
        /* preallocate request and buffer */
index 6e2fe63b926741abf184f2ee54a0fe740a372e42..6b2102bc069973554db95d3311470b0545067727 100644 (file)
@@ -34,6 +34,9 @@ struct f_loopback {
 
        struct usb_ep           *in_ep;
        struct usb_ep           *out_ep;
+
+       unsigned                qlen;
+       unsigned                buflen;
 };
 
 static inline struct f_loopback *func_to_loop(struct usb_function *f)
@@ -41,13 +44,10 @@ static inline struct f_loopback *func_to_loop(struct usb_function *f)
        return container_of(f, struct f_loopback, function);
 }
 
-static unsigned qlen;
-static unsigned buflen;
-
 /*-------------------------------------------------------------------------*/
 
 static struct usb_interface_descriptor loopback_intf = {
-       .bLength =              sizeof loopback_intf,
+       .bLength =              sizeof(loopback_intf),
        .bDescriptorType =      USB_DT_INTERFACE,
 
        .bNumEndpoints =        2,
@@ -195,12 +195,10 @@ autoconf_fail:
                        f->name, cdev->gadget->name);
                return -ENODEV;
        }
-       loop->in_ep->driver_data = cdev;        /* claim */
 
        loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_sink_desc);
        if (!loop->out_ep)
                goto autoconf_fail;
-       loop->out_ep->driver_data = cdev;       /* claim */
 
        /* support high speed hardware */
        hs_loop_source_desc.bEndpointAddress =
@@ -245,22 +243,38 @@ static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
        int                     status = req->status;
 
        switch (status) {
-
        case 0:                         /* normal completion? */
                if (ep == loop->out_ep) {
-                       req->zero = (req->actual < req->length);
-                       req->length = req->actual;
+                       /*
+                        * We received some data from the host so let's
+                        * queue it so host can read the from our in ep
+                        */
+                       struct usb_request *in_req = req->context;
+
+                       in_req->zero = (req->actual < req->length);
+                       in_req->length = req->actual;
+                       ep = loop->in_ep;
+                       req = in_req;
+               } else {
+                       /*
+                        * We have just looped back a bunch of data
+                        * to host. Now let's wait for some more data.
+                        */
+                       req = req->context;
+                       ep = loop->out_ep;
                }
 
-               /* queue the buffer for some later OUT packet */
-               req->length = buflen;
+               /* queue the buffer back to host or for next bunch of data */
                status = usb_ep_queue(ep, req, GFP_ATOMIC);
-               if (status == 0)
+               if (status == 0) {
                        return;
+               } else {
+                       ERROR(cdev, "Unable to loop back buffer to %s: %d\n",
+                             ep->name, status);
+                       goto free_req;
+               }
 
                /* "should never get here" */
-               /* FALLTHROUGH */
-
        default:
                ERROR(cdev, "%s loop complete --> %d, %d/%d\n", ep->name,
                                status, req->actual, req->length);
@@ -274,6 +288,10 @@ static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
        case -ECONNABORTED:             /* hardware forced ep reset */
        case -ECONNRESET:               /* request dequeued */
        case -ESHUTDOWN:                /* disconnect from host */
+free_req:
+               usb_ep_free_request(ep == loop->in_ep ?
+                                   loop->out_ep : loop->in_ep,
+                                   req->context);
                free_ep_req(ep, req);
                return;
        }
@@ -290,53 +308,77 @@ static void disable_loopback(struct f_loopback *loop)
 
 static inline struct usb_request *lb_alloc_ep_req(struct usb_ep *ep, int len)
 {
-       return alloc_ep_req(ep, len, buflen);
+       struct f_loopback       *loop = ep->driver_data;
+
+       return alloc_ep_req(ep, len, loop->buflen);
 }
 
-static int enable_endpoint(struct usb_composite_dev *cdev, struct f_loopback *loop,
-               struct usb_ep *ep)
+static int alloc_requests(struct usb_composite_dev *cdev,
+                         struct f_loopback *loop)
 {
-       struct usb_request                      *req;
-       unsigned                                i;
-       int                                     result;
-
-       /*
-        * one endpoint writes data back IN to the host while another endpoint
-        * just reads OUT packets
-        */
-       result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
-       if (result)
-               goto fail0;
-       result = usb_ep_enable(ep);
-       if (result < 0)
-               goto fail0;
-       ep->driver_data = loop;
+       struct usb_request *in_req, *out_req;
+       int i;
+       int result = 0;
 
        /*
         * allocate a bunch of read buffers and queue them all at once.
-        * we buffer at most 'qlen' transfers; fewer if any need more
-        * than 'buflen' bytes each.
+        * we buffer at most 'qlen' transfers; We allocate buffers only
+        * for out transfer and reuse them in IN transfers to implement
+        * our loopback functionality
         */
-       for (i = 0; i < qlen && result == 0; i++) {
-               req = lb_alloc_ep_req(ep, 0);
-               if (!req)
-                       goto fail1;
+       for (i = 0; i < loop->qlen && result == 0; i++) {
+               result = -ENOMEM;
+
+               in_req = usb_ep_alloc_request(loop->in_ep, GFP_KERNEL);
+               if (!in_req)
+                       goto fail;
+
+               out_req = lb_alloc_ep_req(loop->out_ep, 0);
+               if (!out_req)
+                       goto fail_in;
 
-               req->complete = loopback_complete;
-               result = usb_ep_queue(ep, req, GFP_ATOMIC);
+               in_req->complete = loopback_complete;
+               out_req->complete = loopback_complete;
+
+               in_req->buf = out_req->buf;
+               /* length will be set in complete routine */
+               in_req->context = out_req;
+               out_req->context = in_req;
+
+               result = usb_ep_queue(loop->out_ep, out_req, GFP_ATOMIC);
                if (result) {
                        ERROR(cdev, "%s queue req --> %d\n",
-                                       ep->name, result);
-                       goto fail1;
+                                       loop->out_ep->name, result);
+                       goto fail_out;
                }
        }
 
        return 0;
 
-fail1:
-       usb_ep_disable(ep);
+fail_out:
+       free_ep_req(loop->out_ep, out_req);
+fail_in:
+       usb_ep_free_request(loop->in_ep, in_req);
+fail:
+       return result;
+}
+
+static int enable_endpoint(struct usb_composite_dev *cdev,
+                          struct f_loopback *loop, struct usb_ep *ep)
+{
+       int                                     result;
+
+       result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
+       if (result)
+               goto out;
 
-fail0:
+       result = usb_ep_enable(ep);
+       if (result < 0)
+               goto out;
+       ep->driver_data = loop;
+       result = 0;
+
+out:
        return result;
 }
 
@@ -347,13 +389,24 @@ enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
 
        result = enable_endpoint(cdev, loop, loop->in_ep);
        if (result)
-               return result;
+               goto out;
 
        result = enable_endpoint(cdev, loop, loop->out_ep);
        if (result)
-               return result;
+               goto disable_in;
+
+       result = alloc_requests(cdev, loop);
+       if (result)
+               goto disable_out;
 
        DBG(cdev, "%s enabled\n", loop->function.name);
+       return 0;
+
+disable_out:
+       usb_ep_disable(loop->out_ep);
+disable_in:
+       usb_ep_disable(loop->in_ep);
+out:
        return result;
 }
 
@@ -364,8 +417,7 @@ static int loopback_set_alt(struct usb_function *f,
        struct usb_composite_dev *cdev = f->config->cdev;
 
        /* we know alt is zero */
-       if (loop->in_ep->driver_data)
-               disable_loopback(loop);
+       disable_loopback(loop);
        return enable_loopback(cdev, loop);
 }
 
@@ -391,10 +443,10 @@ static struct usb_function *loopback_alloc(struct usb_function_instance *fi)
        lb_opts->refcnt++;
        mutex_unlock(&lb_opts->lock);
 
-       buflen = lb_opts->bulk_buflen;
-       qlen = lb_opts->qlen;
-       if (!qlen)
-               qlen = 32;
+       loop->buflen = lb_opts->bulk_buflen;
+       loop->qlen = lb_opts->qlen;
+       if (!loop->qlen)
+               loop->qlen = 32;
 
        loop->function.name = "loopback";
        loop->function.bind = loopback_bind;
@@ -434,7 +486,7 @@ static ssize_t f_lb_opts_qlen_show(struct f_lb_opts *opts, char *page)
        int result;
 
        mutex_lock(&opts->lock);
-       result = sprintf(page, "%d", opts->qlen);
+       result = sprintf(page, "%d\n", opts->qlen);
        mutex_unlock(&opts->lock);
 
        return result;
@@ -473,7 +525,7 @@ static ssize_t f_lb_opts_bulk_buflen_show(struct f_lb_opts *opts, char *page)
        int result;
 
        mutex_lock(&opts->lock);
-       result = sprintf(page, "%d", opts->bulk_buflen);
+       result = sprintf(page, "%d\n", opts->bulk_buflen);
        mutex_unlock(&opts->lock);
 
        return result;
index a6eb537d77689f53e7b0e31cff14c2f523c52fe4..cd54e72a6c50d74ee5088b015e71d772cddd9d38 100644 (file)
@@ -2258,12 +2258,10 @@ reset:
                /* Disable the endpoints */
                if (fsg->bulk_in_enabled) {
                        usb_ep_disable(fsg->bulk_in);
-                       fsg->bulk_in->driver_data = NULL;
                        fsg->bulk_in_enabled = 0;
                }
                if (fsg->bulk_out_enabled) {
                        usb_ep_disable(fsg->bulk_out);
-                       fsg->bulk_out->driver_data = NULL;
                        fsg->bulk_out_enabled = 0;
                }
 
@@ -2662,10 +2660,12 @@ EXPORT_SYMBOL_GPL(fsg_common_put);
 /* check if fsg_num_buffers is within a valid range */
 static inline int fsg_num_buffers_validate(unsigned int fsg_num_buffers)
 {
-       if (fsg_num_buffers >= 2 && fsg_num_buffers <= 4)
+#define FSG_MAX_NUM_BUFFERS    32
+
+       if (fsg_num_buffers >= 2 && fsg_num_buffers <= FSG_MAX_NUM_BUFFERS)
                return 0;
        pr_err("fsg_num_buffers %u is out of range (%d to %d)\n",
-              fsg_num_buffers, 2, 4);
+              fsg_num_buffers, 2, FSG_MAX_NUM_BUFFERS);
        return -EINVAL;
 }
 
@@ -3070,13 +3070,11 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
        ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc);
        if (!ep)
                goto autoconf_fail;
-       ep->driver_data = fsg->common;  /* claim the endpoint */
        fsg->bulk_in = ep;
 
        ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc);
        if (!ep)
                goto autoconf_fail;
-       ep->driver_data = fsg->common;  /* claim the endpoint */
        fsg->bulk_out = ep;
 
        /* Assume endpoint addresses are the same for both speeds */
index a287a48292731b2b9eda7a0294eed98dfd6b0987..ce3c8a629266c12d6de7638f2c9900af4085cd83 100644 (file)
@@ -302,8 +302,7 @@ static int f_midi_start_ep(struct f_midi *midi,
        int err;
        struct usb_composite_dev *cdev = f->config->cdev;
 
-       if (ep->driver_data)
-               usb_ep_disable(ep);
+       usb_ep_disable(ep);
 
        err = config_ep_by_speed(midi->gadget, f, ep);
        if (err) {
@@ -341,8 +340,7 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
        if (err)
                return err;
 
-       if (midi->out_ep->driver_data)
-               usb_ep_disable(midi->out_ep);
+       usb_ep_disable(midi->out_ep);
 
        err = config_ep_by_speed(midi->gadget, f, midi->out_ep);
        if (err) {
@@ -547,10 +545,16 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req)
                }
        }
 
-       if (req->length > 0)
-               usb_ep_queue(ep, req, GFP_ATOMIC);
-       else
+       if (req->length > 0) {
+               int err;
+
+               err = usb_ep_queue(ep, req, GFP_ATOMIC);
+               if (err < 0)
+                       ERROR(midi, "%s queue req: %d\n",
+                             midi->in_ep->name, err);
+       } else {
                free_ep_req(ep, req);
+       }
 }
 
 static void f_midi_in_tasklet(unsigned long data)
@@ -757,12 +761,10 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
        midi->in_ep = usb_ep_autoconfig(cdev->gadget, &bulk_in_desc);
        if (!midi->in_ep)
                goto fail;
-       midi->in_ep->driver_data = cdev;        /* claim */
 
        midi->out_ep = usb_ep_autoconfig(cdev->gadget, &bulk_out_desc);
        if (!midi->out_ep)
                goto fail;
-       midi->out_ep->driver_data = cdev;       /* claim */
 
        /* allocate temporary function list */
        midi_function = kcalloc((MAX_PORTS * 4) + 9, sizeof(*midi_function),
@@ -889,12 +891,6 @@ fail_f_midi:
 fail:
        f_midi_unregister_card(midi);
 fail_register:
-       /* we might as well release our claims on endpoints */
-       if (midi->out_ep)
-               midi->out_ep->driver_data = NULL;
-       if (midi->in_ep)
-               midi->in_ep->driver_data = NULL;
-
        ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
 
        return status;
index 3f05c6bd57f0c3353b5a2973a3e344593834b5b5..b6f7ed7d48a7fa6a297ccfeca6440465593462be 100644 (file)
@@ -586,7 +586,7 @@ static void ncm_ep0out_complete(struct usb_ep *ep, struct usb_request *req)
        unsigned                in_size;
        struct usb_function     *f = req->context;
        struct f_ncm            *ncm = func_to_ncm(f);
-       struct usb_composite_dev *cdev = ep->driver_data;
+       struct usb_composite_dev *cdev = f->config->cdev;
 
        req->context = NULL;
        if (req->status || req->actual != req->length) {
@@ -803,10 +803,8 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
                if (alt != 0)
                        goto fail;
 
-               if (ncm->notify->driver_data) {
-                       DBG(cdev, "reset ncm control %d\n", intf);
-                       usb_ep_disable(ncm->notify);
-               }
+               DBG(cdev, "reset ncm control %d\n", intf);
+               usb_ep_disable(ncm->notify);
 
                if (!(ncm->notify->desc)) {
                        DBG(cdev, "init ncm ctrl %d\n", intf);
@@ -814,14 +812,13 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
                                goto fail;
                }
                usb_ep_enable(ncm->notify);
-               ncm->notify->driver_data = ncm;
 
        /* Data interface has two altsettings, 0 and 1 */
        } else if (intf == ncm->data_id) {
                if (alt > 1)
                        goto fail;
 
-               if (ncm->port.in_ep->driver_data) {
+               if (ncm->port.in_ep->enabled) {
                        DBG(cdev, "reset ncm\n");
                        ncm->timer_stopping = true;
                        ncm->netdev = NULL;
@@ -885,7 +882,7 @@ static int ncm_get_alt(struct usb_function *f, unsigned intf)
 
        if (intf == ncm->ctrl_id)
                return 0;
-       return ncm->port.in_ep->driver_data ? 1 : 0;
+       return ncm->port.in_ep->enabled ? 1 : 0;
 }
 
 static struct sk_buff *package_for_tx(struct f_ncm *ncm)
@@ -1276,15 +1273,14 @@ static void ncm_disable(struct usb_function *f)
 
        DBG(cdev, "ncm deactivated\n");
 
-       if (ncm->port.in_ep->driver_data) {
+       if (ncm->port.in_ep->enabled) {
                ncm->timer_stopping = true;
                ncm->netdev = NULL;
                gether_disconnect(&ncm->port);
        }
 
-       if (ncm->notify->driver_data) {
+       if (ncm->notify->enabled) {
                usb_ep_disable(ncm->notify);
-               ncm->notify->driver_data = NULL;
                ncm->notify->desc = NULL;
        }
 }
@@ -1402,19 +1398,16 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
        if (!ep)
                goto fail;
        ncm->port.in_ep = ep;
-       ep->driver_data = cdev; /* claim */
 
        ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_out_desc);
        if (!ep)
                goto fail;
        ncm->port.out_ep = ep;
-       ep->driver_data = cdev; /* claim */
 
        ep = usb_ep_autoconfig(cdev->gadget, &fs_ncm_notify_desc);
        if (!ep)
                goto fail;
        ncm->notify = ep;
-       ep->driver_data = cdev; /* claim */
 
        status = -ENOMEM;
 
@@ -1468,14 +1461,6 @@ fail:
                usb_ep_free_request(ncm->notify, ncm->notify_req);
        }
 
-       /* we might as well release our claims on endpoints */
-       if (ncm->notify)
-               ncm->notify->driver_data = NULL;
-       if (ncm->port.out_ep)
-               ncm->port.out_ep->driver_data = NULL;
-       if (ncm->port.in_ep)
-               ncm->port.in_ep->driver_data = NULL;
-
        ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
 
        return status;
index 5460426057eb232d13e6a071a47f114fb8cd4e14..1c3d30ad2f92cb3edba2ab0eb3ca490378de86f1 100644 (file)
@@ -206,7 +206,7 @@ static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
                if (alt > 1)
                        goto fail;
 
-               if (obex->port.in->driver_data) {
+               if (obex->port.in->enabled) {
                        dev_dbg(&cdev->gadget->dev,
                                "reset obex ttyGS%d\n", obex->port_num);
                        gserial_disconnect(&obex->port);
@@ -348,13 +348,11 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f)
        if (!ep)
                goto fail;
        obex->port.in = ep;
-       ep->driver_data = cdev; /* claim */
 
        ep = usb_ep_autoconfig(cdev->gadget, &obex_fs_ep_out_desc);
        if (!ep)
                goto fail;
        obex->port.out = ep;
-       ep->driver_data = cdev; /* claim */
 
        /* support all relevant hardware speeds... we expect that when
         * hardware is dual speed, all bulk-capable endpoints work at
@@ -378,12 +376,6 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f)
        return 0;
 
 fail:
-       /* we might as well release our claims on endpoints */
-       if (obex->port.out)
-               obex->port.out->driver_data = NULL;
-       if (obex->port.in)
-               obex->port.in->driver_data = NULL;
-
        ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status);
 
        return status;
index c0c3ef272714b58ea4980ba25cf24076b502a105..62a198754029e1f707147a12713f758a186cdd8e 100644 (file)
@@ -418,7 +418,7 @@ static int pn_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 
                spin_lock(&port->lock);
 
-               if (fp->in_ep->driver_data)
+               if (fp->in_ep->enabled)
                        __pn_reset(f);
 
                if (alt == 1) {
@@ -530,13 +530,11 @@ static int pn_bind(struct usb_configuration *c, struct usb_function *f)
        if (!ep)
                goto err;
        fp->out_ep = ep;
-       ep->driver_data = fp; /* Claim */
 
        ep = usb_ep_autoconfig(gadget, &pn_fs_source_desc);
        if (!ep)
                goto err;
        fp->in_ep = ep;
-       ep->driver_data = fp; /* Claim */
 
        pn_hs_sink_desc.bEndpointAddress = pn_fs_sink_desc.bEndpointAddress;
        pn_hs_source_desc.bEndpointAddress = pn_fs_source_desc.bEndpointAddress;
@@ -575,10 +573,6 @@ err_req:
                usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
        usb_free_all_descriptors(f);
 err:
-       if (fp->out_ep)
-               fp->out_ep->driver_data = NULL;
-       if (fp->in_ep)
-               fp->in_ep->driver_data = NULL;
        ERROR(cdev, "USB CDC Phonet: cannot autoconfigure\n");
        return status;
 }
index 8e2b6bea07bc0e6a6fa1758aa38841a52afdcf3c..7fb3209ed52c31c662b24b1799e78ff9a4d38700 100644 (file)
@@ -1039,12 +1039,10 @@ autoconf_fail:
                        cdev->gadget->name);
                return -ENODEV;
        }
-       in_ep->driver_data = in_ep;     /* claim */
 
        out_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_out_desc);
        if (!out_ep)
                goto autoconf_fail;
-       out_ep->driver_data = out_ep;   /* claim */
 
        /* assumes that all endpoints are dual-speed */
        hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
index 32985dade8385145b6c4493a153656cc6b1aea22..fd301ed9e294fa480ad0336fc17833e772611765 100644 (file)
@@ -543,22 +543,20 @@ static int rndis_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
        /* we know alt == 0 */
 
        if (intf == rndis->ctrl_id) {
-               if (rndis->notify->driver_data) {
-                       VDBG(cdev, "reset rndis control %d\n", intf);
-                       usb_ep_disable(rndis->notify);
-               }
+               VDBG(cdev, "reset rndis control %d\n", intf);
+               usb_ep_disable(rndis->notify);
+
                if (!rndis->notify->desc) {
                        VDBG(cdev, "init rndis ctrl %d\n", intf);
                        if (config_ep_by_speed(cdev->gadget, f, rndis->notify))
                                goto fail;
                }
                usb_ep_enable(rndis->notify);
-               rndis->notify->driver_data = rndis;
 
        } else if (intf == rndis->data_id) {
                struct net_device       *net;
 
-               if (rndis->port.in_ep->driver_data) {
+               if (rndis->port.in_ep->enabled) {
                        DBG(cdev, "reset rndis\n");
                        gether_disconnect(&rndis->port);
                }
@@ -612,7 +610,7 @@ static void rndis_disable(struct usb_function *f)
        struct f_rndis          *rndis = func_to_rndis(f);
        struct usb_composite_dev *cdev = f->config->cdev;
 
-       if (!rndis->notify->driver_data)
+       if (!rndis->notify->enabled)
                return;
 
        DBG(cdev, "rndis deactivated\n");
@@ -621,7 +619,6 @@ static void rndis_disable(struct usb_function *f)
        gether_disconnect(&rndis->port);
 
        usb_ep_disable(rndis->notify);
-       rndis->notify->driver_data = NULL;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -745,13 +742,11 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
        if (!ep)
                goto fail;
        rndis->port.in_ep = ep;
-       ep->driver_data = cdev; /* claim */
 
        ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc);
        if (!ep)
                goto fail;
        rndis->port.out_ep = ep;
-       ep->driver_data = cdev; /* claim */
 
        /* NOTE:  a status/notification endpoint is, strictly speaking,
         * optional.  We don't treat it that way though!  It's simpler,
@@ -761,7 +756,6 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
        if (!ep)
                goto fail;
        rndis->notify = ep;
-       ep->driver_data = cdev; /* claim */
 
        status = -ENOMEM;
 
@@ -829,14 +823,6 @@ fail:
                usb_ep_free_request(rndis->notify, rndis->notify_req);
        }
 
-       /* we might as well release our claims on endpoints */
-       if (rndis->notify)
-               rndis->notify->driver_data = NULL;
-       if (rndis->port.out_ep)
-               rndis->port.out_ep->driver_data = NULL;
-       if (rndis->port.in_ep)
-               rndis->port.in_ep->driver_data = NULL;
-
        ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
 
        return status;
index 1d162e200e831ce1320a8e3d3f36f3bbd82b5a92..ba705e047d7e0fca31ce8a2ede4d67f595efb5ca 100644 (file)
@@ -153,7 +153,7 @@ static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 
        /* we know alt == 0, so this is an activation or a reset */
 
-       if (gser->port.in->driver_data) {
+       if (gser->port.in->enabled) {
                dev_dbg(&cdev->gadget->dev,
                        "reset generic ttyGS%d\n", gser->port_num);
                gserial_disconnect(&gser->port);
@@ -219,13 +219,11 @@ static int gser_bind(struct usb_configuration *c, struct usb_function *f)
        if (!ep)
                goto fail;
        gser->port.in = ep;
-       ep->driver_data = cdev; /* claim */
 
        ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_out_desc);
        if (!ep)
                goto fail;
        gser->port.out = ep;
-       ep->driver_data = cdev; /* claim */
 
        /* support all relevant hardware speeds... we expect that when
         * hardware is dual speed, all bulk-capable endpoints work at
@@ -249,12 +247,6 @@ static int gser_bind(struct usb_configuration *c, struct usb_function *f)
        return 0;
 
 fail:
-       /* we might as well release our claims on endpoints */
-       if (gser->port.out)
-               gser->port.out->driver_data = NULL;
-       if (gser->port.in)
-               gser->port.in->driver_data = NULL;
-
        ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
 
        return status;
index cbfaf86fe45652911744055d6549a88c88b056d3..d7646d3acd63ecb4aa87362e069b54faff909844 100644 (file)
@@ -50,6 +50,13 @@ struct f_sourcesink {
        struct usb_ep           *iso_in_ep;
        struct usb_ep           *iso_out_ep;
        int                     cur_alt;
+
+       unsigned pattern;
+       unsigned isoc_interval;
+       unsigned isoc_maxpacket;
+       unsigned isoc_mult;
+       unsigned isoc_maxburst;
+       unsigned buflen;
 };
 
 static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
@@ -57,13 +64,6 @@ static inline struct f_sourcesink *func_to_ss(struct usb_function *f)
        return container_of(f, struct f_sourcesink, function);
 }
 
-static unsigned pattern;
-static unsigned isoc_interval;
-static unsigned isoc_maxpacket;
-static unsigned isoc_mult;
-static unsigned isoc_maxburst;
-static unsigned buflen;
-
 /*-------------------------------------------------------------------------*/
 
 static struct usb_interface_descriptor source_sink_intf_alt0 = {
@@ -298,7 +298,9 @@ static struct usb_gadget_strings *sourcesink_strings[] = {
 
 static inline struct usb_request *ss_alloc_ep_req(struct usb_ep *ep, int len)
 {
-       return alloc_ep_req(ep, len, buflen);
+       struct f_sourcesink             *ss = ep->driver_data;
+
+       return alloc_ep_req(ep, len, ss->buflen);
 }
 
 void free_ep_req(struct usb_ep *ep, struct usb_request *req)
@@ -311,13 +313,9 @@ static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
 {
        int                     value;
 
-       if (ep->driver_data) {
-               value = usb_ep_disable(ep);
-               if (value < 0)
-                       DBG(cdev, "disable %s --> %d\n",
-                                       ep->name, value);
-               ep->driver_data = NULL;
-       }
+       value = usb_ep_disable(ep);
+       if (value < 0)
+               DBG(cdev, "disable %s --> %d\n", ep->name, value);
 }
 
 void disable_endpoints(struct usb_composite_dev *cdev,
@@ -355,42 +353,37 @@ autoconf_fail:
                        f->name, cdev->gadget->name);
                return -ENODEV;
        }
-       ss->in_ep->driver_data = cdev;  /* claim */
 
        ss->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_sink_desc);
        if (!ss->out_ep)
                goto autoconf_fail;
-       ss->out_ep->driver_data = cdev; /* claim */
 
        /* sanity check the isoc module parameters */
-       if (isoc_interval < 1)
-               isoc_interval = 1;
-       if (isoc_interval > 16)
-               isoc_interval = 16;
-       if (isoc_mult > 2)
-               isoc_mult = 2;
-       if (isoc_maxburst > 15)
-               isoc_maxburst = 15;
+       if (ss->isoc_interval < 1)
+               ss->isoc_interval = 1;
+       if (ss->isoc_interval > 16)
+               ss->isoc_interval = 16;
+       if (ss->isoc_mult > 2)
+               ss->isoc_mult = 2;
+       if (ss->isoc_maxburst > 15)
+               ss->isoc_maxburst = 15;
 
        /* fill in the FS isoc descriptors from the module parameters */
-       fs_iso_source_desc.wMaxPacketSize = isoc_maxpacket > 1023 ?
-                                               1023 : isoc_maxpacket;
-       fs_iso_source_desc.bInterval = isoc_interval;
-       fs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket > 1023 ?
-                                               1023 : isoc_maxpacket;
-       fs_iso_sink_desc.bInterval = isoc_interval;
+       fs_iso_source_desc.wMaxPacketSize = ss->isoc_maxpacket > 1023 ?
+                                               1023 : ss->isoc_maxpacket;
+       fs_iso_source_desc.bInterval = ss->isoc_interval;
+       fs_iso_sink_desc.wMaxPacketSize = ss->isoc_maxpacket > 1023 ?
+                                               1023 : ss->isoc_maxpacket;
+       fs_iso_sink_desc.bInterval = ss->isoc_interval;
 
        /* allocate iso endpoints */
        ss->iso_in_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_source_desc);
        if (!ss->iso_in_ep)
                goto no_iso;
-       ss->iso_in_ep->driver_data = cdev;      /* claim */
 
        ss->iso_out_ep = usb_ep_autoconfig(cdev->gadget, &fs_iso_sink_desc);
-       if (ss->iso_out_ep) {
-               ss->iso_out_ep->driver_data = cdev;     /* claim */
-       } else {
-               ss->iso_in_ep->driver_data = NULL;
+       if (!ss->iso_out_ep) {
+               usb_ep_autoconfig_release(ss->iso_in_ep);
                ss->iso_in_ep = NULL;
 no_iso:
                /*
@@ -403,8 +396,8 @@ no_iso:
                ss_source_sink_descs[SS_ALT_IFC_1_OFFSET] = NULL;
        }
 
-       if (isoc_maxpacket > 1024)
-               isoc_maxpacket = 1024;
+       if (ss->isoc_maxpacket > 1024)
+               ss->isoc_maxpacket = 1024;
 
        /* support high speed hardware */
        hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
@@ -415,15 +408,15 @@ no_iso:
         * We assume that the user knows what they are doing and won't
         * give parameters that their UDC doesn't support.
         */
-       hs_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
-       hs_iso_source_desc.wMaxPacketSize |= isoc_mult << 11;
-       hs_iso_source_desc.bInterval = isoc_interval;
+       hs_iso_source_desc.wMaxPacketSize = ss->isoc_maxpacket;
+       hs_iso_source_desc.wMaxPacketSize |= ss->isoc_mult << 11;
+       hs_iso_source_desc.bInterval = ss->isoc_interval;
        hs_iso_source_desc.bEndpointAddress =
                fs_iso_source_desc.bEndpointAddress;
 
-       hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
-       hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11;
-       hs_iso_sink_desc.bInterval = isoc_interval;
+       hs_iso_sink_desc.wMaxPacketSize = ss->isoc_maxpacket;
+       hs_iso_sink_desc.wMaxPacketSize |= ss->isoc_mult << 11;
+       hs_iso_sink_desc.bInterval = ss->isoc_interval;
        hs_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
 
        /* support super speed hardware */
@@ -437,21 +430,21 @@ no_iso:
         * We assume that the user knows what they are doing and won't
         * give parameters that their UDC doesn't support.
         */
-       ss_iso_source_desc.wMaxPacketSize = isoc_maxpacket;
-       ss_iso_source_desc.bInterval = isoc_interval;
-       ss_iso_source_comp_desc.bmAttributes = isoc_mult;
-       ss_iso_source_comp_desc.bMaxBurst = isoc_maxburst;
-       ss_iso_source_comp_desc.wBytesPerInterval =
-               isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
+       ss_iso_source_desc.wMaxPacketSize = ss->isoc_maxpacket;
+       ss_iso_source_desc.bInterval = ss->isoc_interval;
+       ss_iso_source_comp_desc.bmAttributes = ss->isoc_mult;
+       ss_iso_source_comp_desc.bMaxBurst = ss->isoc_maxburst;
+       ss_iso_source_comp_desc.wBytesPerInterval = ss->isoc_maxpacket *
+               (ss->isoc_mult + 1) * (ss->isoc_maxburst + 1);
        ss_iso_source_desc.bEndpointAddress =
                fs_iso_source_desc.bEndpointAddress;
 
-       ss_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
-       ss_iso_sink_desc.bInterval = isoc_interval;
-       ss_iso_sink_comp_desc.bmAttributes = isoc_mult;
-       ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst;
-       ss_iso_sink_comp_desc.wBytesPerInterval =
-               isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
+       ss_iso_sink_desc.wMaxPacketSize = ss->isoc_maxpacket;
+       ss_iso_sink_desc.bInterval = ss->isoc_interval;
+       ss_iso_sink_comp_desc.bmAttributes = ss->isoc_mult;
+       ss_iso_sink_comp_desc.bMaxBurst = ss->isoc_maxburst;
+       ss_iso_sink_comp_desc.wBytesPerInterval = ss->isoc_maxpacket *
+               (ss->isoc_mult + 1) * (ss->isoc_maxburst + 1);
        ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
 
        ret = usb_assign_descriptors(f, fs_source_sink_descs,
@@ -489,12 +482,13 @@ static int check_read_data(struct f_sourcesink *ss, struct usb_request *req)
        unsigned                i;
        u8                      *buf = req->buf;
        struct usb_composite_dev *cdev = ss->function.config->cdev;
+       int max_packet_size = le16_to_cpu(ss->out_ep->desc->wMaxPacketSize);
 
-       if (pattern == 2)
+       if (ss->pattern == 2)
                return 0;
 
        for (i = 0; i < req->actual; i++, buf++) {
-               switch (pattern) {
+               switch (ss->pattern) {
 
                /* all-zeroes has no synchronization issues */
                case 0:
@@ -510,7 +504,7 @@ static int check_read_data(struct f_sourcesink *ss, struct usb_request *req)
                 * stutter for any reason, including buffer duplication...)
                 */
                case 1:
-                       if (*buf == (u8)(i % 63))
+                       if (*buf == (u8)((i % max_packet_size) % 63))
                                continue;
                        break;
                }
@@ -525,14 +519,16 @@ static void reinit_write_data(struct usb_ep *ep, struct usb_request *req)
 {
        unsigned        i;
        u8              *buf = req->buf;
+       int max_packet_size = le16_to_cpu(ep->desc->wMaxPacketSize);
+       struct f_sourcesink *ss = ep->driver_data;
 
-       switch (pattern) {
+       switch (ss->pattern) {
        case 0:
                memset(req->buf, 0, req->length);
                break;
        case 1:
                for  (i = 0; i < req->length; i++)
-                       *buf++ = (u8) (i % 63);
+                       *buf++ = (u8) ((i % max_packet_size) % 63);
                break;
        case 2:
                break;
@@ -556,7 +552,7 @@ static void source_sink_complete(struct usb_ep *ep, struct usb_request *req)
        case 0:                         /* normal completion? */
                if (ep == ss->out_ep) {
                        check_read_data(ss, req);
-                       if (pattern != 2)
+                       if (ss->pattern != 2)
                                memset(req->buf, 0x55, req->length);
                }
                break;
@@ -605,15 +601,16 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
                if (is_iso) {
                        switch (speed) {
                        case USB_SPEED_SUPER:
-                               size = isoc_maxpacket * (isoc_mult + 1) *
-                                               (isoc_maxburst + 1);
+                               size = ss->isoc_maxpacket *
+                                               (ss->isoc_mult + 1) *
+                                               (ss->isoc_maxburst + 1);
                                break;
                        case USB_SPEED_HIGH:
-                               size = isoc_maxpacket * (isoc_mult + 1);
+                               size = ss->isoc_maxpacket * (ss->isoc_mult + 1);
                                break;
                        default:
-                               size = isoc_maxpacket > 1023 ?
-                                               1023 : isoc_maxpacket;
+                               size = ss->isoc_maxpacket > 1023 ?
+                                               1023 : ss->isoc_maxpacket;
                                break;
                        }
                        ep = is_in ? ss->iso_in_ep : ss->iso_out_ep;
@@ -629,7 +626,7 @@ static int source_sink_start_ep(struct f_sourcesink *ss, bool is_in,
                req->complete = source_sink_complete;
                if (is_in)
                        reinit_write_data(ep, req);
-               else if (pattern != 2)
+               else if (ss->pattern != 2)
                        memset(req->buf, 0x55, req->length);
 
                status = usb_ep_queue(ep, req, GFP_ATOMIC);
@@ -683,7 +680,6 @@ enable_source_sink(struct usb_composite_dev *cdev, struct f_sourcesink *ss,
 fail:
                ep = ss->in_ep;
                usb_ep_disable(ep);
-               ep->driver_data = NULL;
                return result;
        }
 
@@ -702,7 +698,6 @@ fail:
 fail2:
                ep = ss->out_ep;
                usb_ep_disable(ep);
-               ep->driver_data = NULL;
                goto fail;
        }
 
@@ -724,10 +719,8 @@ fail2:
                if (result < 0) {
 fail3:
                        ep = ss->iso_in_ep;
-                       if (ep) {
+                       if (ep)
                                usb_ep_disable(ep);
-                               ep->driver_data = NULL;
-                       }
                        goto fail2;
                }
        }
@@ -746,7 +739,6 @@ fail3:
                result = source_sink_start_ep(ss, false, true, speed);
                if (result < 0) {
                        usb_ep_disable(ep);
-                       ep->driver_data = NULL;
                        goto fail3;
                }
        }
@@ -763,8 +755,7 @@ static int sourcesink_set_alt(struct usb_function *f,
        struct f_sourcesink             *ss = func_to_ss(f);
        struct usb_composite_dev        *cdev = f->config->cdev;
 
-       if (ss->in_ep->driver_data)
-               disable_source_sink(ss);
+       disable_source_sink(ss);
        return enable_source_sink(cdev, ss, alt);
 }
 
@@ -872,12 +863,12 @@ static struct usb_function *source_sink_alloc_func(
        ss_opts->refcnt++;
        mutex_unlock(&ss_opts->lock);
 
-       pattern = ss_opts->pattern;
-       isoc_interval = ss_opts->isoc_interval;
-       isoc_maxpacket = ss_opts->isoc_maxpacket;
-       isoc_mult = ss_opts->isoc_mult;
-       isoc_maxburst = ss_opts->isoc_maxburst;
-       buflen = ss_opts->bulk_buflen;
+       ss->pattern = ss_opts->pattern;
+       ss->isoc_interval = ss_opts->isoc_interval;
+       ss->isoc_maxpacket = ss_opts->isoc_maxpacket;
+       ss->isoc_mult = ss_opts->isoc_mult;
+       ss->isoc_maxburst = ss_opts->isoc_maxburst;
+       ss->buflen = ss_opts->bulk_buflen;
 
        ss->function.name = "source/sink";
        ss->function.bind = sourcesink_bind;
@@ -919,7 +910,7 @@ static ssize_t f_ss_opts_pattern_show(struct f_ss_opts *opts, char *page)
        int result;
 
        mutex_lock(&opts->lock);
-       result = sprintf(page, "%u", opts->pattern);
+       result = sprintf(page, "%u\n", opts->pattern);
        mutex_unlock(&opts->lock);
 
        return result;
@@ -963,7 +954,7 @@ static ssize_t f_ss_opts_isoc_interval_show(struct f_ss_opts *opts, char *page)
        int result;
 
        mutex_lock(&opts->lock);
-       result = sprintf(page, "%u", opts->isoc_interval);
+       result = sprintf(page, "%u\n", opts->isoc_interval);
        mutex_unlock(&opts->lock);
 
        return result;
@@ -1007,7 +998,7 @@ static ssize_t f_ss_opts_isoc_maxpacket_show(struct f_ss_opts *opts, char *page)
        int result;
 
        mutex_lock(&opts->lock);
-       result = sprintf(page, "%u", opts->isoc_maxpacket);
+       result = sprintf(page, "%u\n", opts->isoc_maxpacket);
        mutex_unlock(&opts->lock);
 
        return result;
@@ -1051,7 +1042,7 @@ static ssize_t f_ss_opts_isoc_mult_show(struct f_ss_opts *opts, char *page)
        int result;
 
        mutex_lock(&opts->lock);
-       result = sprintf(page, "%u", opts->isoc_mult);
+       result = sprintf(page, "%u\n", opts->isoc_mult);
        mutex_unlock(&opts->lock);
 
        return result;
@@ -1095,7 +1086,7 @@ static ssize_t f_ss_opts_isoc_maxburst_show(struct f_ss_opts *opts, char *page)
        int result;
 
        mutex_lock(&opts->lock);
-       result = sprintf(page, "%u", opts->isoc_maxburst);
+       result = sprintf(page, "%u\n", opts->isoc_maxburst);
        mutex_unlock(&opts->lock);
 
        return result;
@@ -1139,7 +1130,7 @@ static ssize_t f_ss_opts_bulk_buflen_show(struct f_ss_opts *opts, char *page)
        int result;
 
        mutex_lock(&opts->lock);
-       result = sprintf(page, "%u", opts->bulk_buflen);
+       result = sprintf(page, "%u\n", opts->bulk_buflen);
        mutex_unlock(&opts->lock);
 
        return result;
index e3dfa675ff06db9ca627e6d211f30263f298eb8f..2e66e624e6e13dfed2fde71fff294a10a986bb7a 100644 (file)
@@ -262,7 +262,7 @@ static int geth_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 
        /* we know alt == 0, so this is an activation or a reset */
 
-       if (geth->port.in_ep->driver_data) {
+       if (geth->port.in_ep->enabled) {
                DBG(cdev, "reset cdc subset\n");
                gether_disconnect(&geth->port);
        }
@@ -343,13 +343,11 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
        if (!ep)
                goto fail;
        geth->port.in_ep = ep;
-       ep->driver_data = cdev; /* claim */
 
        ep = usb_ep_autoconfig(cdev->gadget, &fs_subset_out_desc);
        if (!ep)
                goto fail;
        geth->port.out_ep = ep;
-       ep->driver_data = cdev; /* claim */
 
        /* support all relevant hardware speeds... we expect that when
         * hardware is dual speed, all bulk-capable endpoints work at
@@ -380,12 +378,6 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
        return 0;
 
 fail:
-       /* we might as well release our claims on endpoints */
-       if (geth->port.out_ep)
-               geth->port.out_ep->driver_data = NULL;
-       if (geth->port.in_ep)
-               geth->port.in_ep->driver_data = NULL;
-
        ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
 
        return status;
index 7856b3394494b7d4250637277dd1f42f45d7a1ea..8ee701924d29d0c5ad27edfed1b3e23c15b5c3e7 100644 (file)
@@ -593,7 +593,6 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
                                return err;
 
                        usb_ep_enable(out_ep);
-                       out_ep->driver_data = audio;
                        audio->copy_buf = f_audio_buffer_alloc(audio_buf_size);
                        if (IS_ERR(audio->copy_buf))
                                return -ENOMEM;
@@ -718,7 +717,6 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
                goto fail;
        audio->out_ep = ep;
        audio->out_ep->desc = &as_out_ep_desc;
-       ep->driver_data = cdev; /* claim */
 
        status = -ENOMEM;
 
@@ -730,8 +728,6 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
 
 fail:
        gaudio_cleanup(&audio->card);
-       if (ep)
-               ep->driver_data = NULL;
        return status;
 }
 
index f8de7ea2a0c1e9585782e2fe60af23a41c072e37..63336e269898d07ac42c2ab66117c9aaed2ae142 100644 (file)
@@ -1081,14 +1081,12 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
                dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
                goto err;
        }
-       agdev->out_ep->driver_data = agdev;
 
        agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc);
        if (!agdev->in_ep) {
                dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
                goto err;
        }
-       agdev->in_ep->driver_data = agdev;
 
        uac2->p_prm.uac2 = uac2;
        uac2->c_prm.uac2 = uac2;
@@ -1132,10 +1130,6 @@ err_free_descs:
 err:
        kfree(agdev->uac2.p_prm.rbuf);
        kfree(agdev->uac2.c_prm.rbuf);
-       if (agdev->in_ep)
-               agdev->in_ep->driver_data = NULL;
-       if (agdev->out_ep)
-               agdev->out_ep->driver_data = NULL;
        return -EINVAL;
 }
 
@@ -1583,11 +1577,6 @@ static void afunc_unbind(struct usb_configuration *c, struct usb_function *f)
        prm = &agdev->uac2.c_prm;
        kfree(prm->rbuf);
        usb_free_all_descriptors(f);
-
-       if (agdev->in_ep)
-               agdev->in_ep->driver_data = NULL;
-       if (agdev->out_ep)
-               agdev->out_ep->driver_data = NULL;
 }
 
 static struct usb_function *afunc_alloc(struct usb_function_instance *fi)
index 743be34605dcbff26eaf066c80578fb5112e41cf..29b41b5dee04d2e0e3e87a6dc97d6dde84af49d0 100644 (file)
@@ -280,7 +280,7 @@ uvc_function_get_alt(struct usb_function *f, unsigned interface)
        else if (interface != uvc->streaming_intf)
                return -EINVAL;
        else
-               return uvc->video.ep->driver_data ? 1 : 0;
+               return uvc->video.ep->enabled ? 1 : 0;
 }
 
 static int
@@ -298,18 +298,14 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
                if (alt)
                        return -EINVAL;
 
-               if (uvc->control_ep->driver_data) {
-                       INFO(cdev, "reset UVC Control\n");
-                       usb_ep_disable(uvc->control_ep);
-                       uvc->control_ep->driver_data = NULL;
-               }
+               INFO(cdev, "reset UVC Control\n");
+               usb_ep_disable(uvc->control_ep);
 
                if (!uvc->control_ep->desc)
                        if (config_ep_by_speed(cdev->gadget, f, uvc->control_ep))
                                return -EINVAL;
 
                usb_ep_enable(uvc->control_ep);
-               uvc->control_ep->driver_data = uvc;
 
                if (uvc->state == UVC_STATE_DISCONNECTED) {
                        memset(&v4l2_event, 0, sizeof(v4l2_event));
@@ -336,10 +332,8 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
                if (uvc->state != UVC_STATE_STREAMING)
                        return 0;
 
-               if (uvc->video.ep) {
+               if (uvc->video.ep)
                        usb_ep_disable(uvc->video.ep);
-                       uvc->video.ep->driver_data = NULL;
-               }
 
                memset(&v4l2_event, 0, sizeof(v4l2_event));
                v4l2_event.type = UVC_EVENT_STREAMOFF;
@@ -355,18 +349,14 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
                if (!uvc->video.ep)
                        return -EINVAL;
 
-               if (uvc->video.ep->driver_data) {
-                       INFO(cdev, "reset UVC\n");
-                       usb_ep_disable(uvc->video.ep);
-                       uvc->video.ep->driver_data = NULL;
-               }
+               INFO(cdev, "reset UVC\n");
+               usb_ep_disable(uvc->video.ep);
 
                ret = config_ep_by_speed(f->config->cdev->gadget,
                                &(uvc->func), uvc->video.ep);
                if (ret)
                        return ret;
                usb_ep_enable(uvc->video.ep);
-               uvc->video.ep->driver_data = uvc;
 
                memset(&v4l2_event, 0, sizeof(v4l2_event));
                v4l2_event.type = UVC_EVENT_STREAMON;
@@ -392,15 +382,8 @@ uvc_function_disable(struct usb_function *f)
 
        uvc->state = UVC_STATE_DISCONNECTED;
 
-       if (uvc->video.ep->driver_data) {
-               usb_ep_disable(uvc->video.ep);
-               uvc->video.ep->driver_data = NULL;
-       }
-
-       if (uvc->control_ep->driver_data) {
-               usb_ep_disable(uvc->control_ep);
-               uvc->control_ep->driver_data = NULL;
-       }
+       usb_ep_disable(uvc->video.ep);
+       usb_ep_disable(uvc->control_ep);
 }
 
 /* --------------------------------------------------------------------------
@@ -651,7 +634,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
                goto error;
        }
        uvc->control_ep = ep;
-       ep->driver_data = uvc;
 
        if (gadget_is_superspeed(c->cdev->gadget))
                ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep,
@@ -666,7 +648,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
                goto error;
        }
        uvc->video.ep = ep;
-       ep->driver_data = uvc;
 
        uvc_fs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
        uvc_hs_streaming_ep.bEndpointAddress = uvc->video.ep->address;
@@ -755,11 +736,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 error:
        v4l2_device_unregister(&uvc->v4l2_dev);
 
-       if (uvc->control_ep)
-               uvc->control_ep->driver_data = NULL;
-       if (uvc->video.ep)
-               uvc->video.ep->driver_data = NULL;
-
        if (uvc->control_req)
                usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
        kfree(uvc->control_buf);
@@ -886,8 +862,6 @@ static void uvc_unbind(struct usb_configuration *c, struct usb_function *f)
 
        video_unregister_device(&uvc->vdev);
        v4l2_device_unregister(&uvc->v4l2_dev);
-       uvc->control_ep->driver_data = NULL;
-       uvc->video.ep->driver_data = NULL;
 
        usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
        kfree(uvc->control_buf);
index f1fd777ef4ec6bcf3bb233074c3aab53d62493a3..6554322af2c16a076385ba021b8ee15c8483bdc1 100644 (file)
 
 #define UETH__VERSION  "29-May-2008"
 
+/* Experiments show that both Linux and Windows hosts allow up to 16k
+ * frame sizes. Set the max size to 15k+52 to prevent allocating 32k
+ * blocks and still have efficient handling. */
+#define GETHER_MAX_ETH_FRAME_LEN 15412
+
 struct eth_dev {
        /* lock is held while accessing port_usb
         */
@@ -146,7 +151,7 @@ static int ueth_change_mtu(struct net_device *net, int new_mtu)
        spin_lock_irqsave(&dev->lock, flags);
        if (dev->port_usb)
                status = -EBUSY;
-       else if (new_mtu <= ETH_HLEN || new_mtu > ETH_FRAME_LEN)
+       else if (new_mtu <= ETH_HLEN || new_mtu > GETHER_MAX_ETH_FRAME_LEN)
                status = -ERANGE;
        else
                net->mtu = new_mtu;
@@ -294,7 +299,7 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
                while (skb2) {
                        if (status < 0
                                        || ETH_HLEN > skb2->len
-                                       || skb2->len > VLAN_ETH_FRAME_LEN) {
+                                       || skb2->len > GETHER_MAX_ETH_FRAME_LEN) {
                                dev->net->stats.rx_errors++;
                                dev->net->stats.rx_length_errors++;
                                DBG(dev, "rx length %d\n", skb2->len);
@@ -1144,7 +1149,6 @@ void gether_disconnect(struct gether *link)
                spin_lock(&dev->req_lock);
        }
        spin_unlock(&dev->req_lock);
-       link->in_ep->driver_data = NULL;
        link->in_ep->desc = NULL;
 
        usb_ep_disable(link->out_ep);
@@ -1159,7 +1163,6 @@ void gether_disconnect(struct gether *link)
                spin_lock(&dev->req_lock);
        }
        spin_unlock(&dev->req_lock);
-       link->out_ep->driver_data = NULL;
        link->out_ep->desc = NULL;
 
        /* finish forgetting about this USB link episode */
index 42894f58016eab5fae91534cdefec3fc3bb77e3e..f7771d86ad6c8d19e2016773c1b5ba4b2f3f33eb 100644 (file)
@@ -877,7 +877,6 @@ static void gs_close(struct tty_struct *tty, struct file *file)
        else
                gs_buf_clear(&port->port_write_buf);
 
-       tty->driver_data = NULL;
        port->port.tty = NULL;
 
        port->openclose = false;
@@ -1226,7 +1225,6 @@ int gserial_connect(struct gserial *gser, u8 port_num)
 
 fail_out:
        usb_ep_disable(gser->in);
-       gser->in->driver_data = NULL;
        return status;
 }
 EXPORT_SYMBOL_GPL(gserial_connect);
@@ -1266,10 +1264,7 @@ void gserial_disconnect(struct gserial *gser)
 
        /* disable endpoints, aborting down any active I/O */
        usb_ep_disable(gser->out);
-       gser->out->driver_data = NULL;
-
        usb_ep_disable(gser->in);
-       gser->in->driver_data = NULL;
 
        /* finally, free any unused/unusable I/O buffers */
        spin_lock_irqsave(&port->port_lock, flags);
index 5231a32aef55a4c6640a772038a260b76d7bf2b6..99ca3dabc4f34c6c2cacc7957323128b2b10f544 100644 (file)
@@ -79,10 +79,7 @@ static int dbgp_consume(char *buf, unsigned len)
 
 static void __disable_ep(struct usb_ep *ep)
 {
-       if (ep && ep->driver_data == dbgp.gadget) {
-               usb_ep_disable(ep);
-               ep->driver_data = NULL;
-       }
+       usb_ep_disable(ep);
 }
 
 static void dbgp_disable_ep(void)
@@ -171,7 +168,6 @@ static int __enable_ep(struct usb_ep *ep, struct usb_endpoint_descriptor *desc)
        int err;
        ep->desc = desc;
        err = usb_ep_enable(ep);
-       ep->driver_data = dbgp.gadget;
        return err;
 }
 
@@ -229,8 +225,6 @@ static void dbgp_unbind(struct usb_gadget *gadget)
                usb_ep_free_request(gadget->ep0, dbgp.req);
                dbgp.req = NULL;
        }
-
-       gadget->ep0->driver_data = NULL;
 }
 
 #ifdef CONFIG_USB_G_DBGP_SERIAL
@@ -249,18 +243,15 @@ static int dbgp_configure_endpoints(struct usb_gadget *gadget)
                goto fail_1;
        }
 
-       dbgp.i_ep->driver_data = gadget;
        i_desc.wMaxPacketSize =
                cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
 
        dbgp.o_ep = usb_ep_autoconfig(gadget, &o_desc);
        if (!dbgp.o_ep) {
-               dbgp.i_ep->driver_data = NULL;
                stp = 2;
-               goto fail_2;
+               goto fail_1;
        }
 
-       dbgp.o_ep->driver_data = gadget;
        o_desc.wMaxPacketSize =
                cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
 
@@ -277,8 +268,6 @@ static int dbgp_configure_endpoints(struct usb_gadget *gadget)
 
        return 0;
 
-fail_2:
-       dbgp.i_ep->driver_data = NULL;
 fail_1:
        dev_dbg(&dbgp.gadget->dev, "ep config: failure (%d)\n", stp);
        return -ENODEV;
@@ -306,7 +295,6 @@ static int dbgp_bind(struct usb_gadget *gadget,
        }
 
        dbgp.req->length = DBGP_REQ_EP0_LEN;
-       gadget->ep0->driver_data = gadget;
 
 #ifdef CONFIG_USB_G_DBGP_SERIAL
        dbgp.serial = kzalloc(sizeof(struct gserial), GFP_KERNEL);
@@ -356,8 +344,6 @@ static int dbgp_setup(struct usb_gadget *gadget,
        void *data = NULL;
        u16 len = 0;
 
-       gadget->ep0->driver_data = gadget;
-
        if (request == USB_REQ_GET_DESCRIPTOR) {
                switch (value>>8) {
                case USB_DT_DEVICE:
index c3c48088fced7b90703b068b2527635a6a5e01ea..778e42abb3cb8703fcf19b829e21f764ac798d1e 100644 (file)
@@ -2018,14 +2018,6 @@ static struct usb_configuration usbg_config_driver = {
        .bmAttributes           = USB_CONFIG_ATT_SELFPOWER,
 };
 
-static void give_back_ep(struct usb_ep **pep)
-{
-       struct usb_ep *ep = *pep;
-       if (!ep)
-               return;
-       ep->driver_data = NULL;
-}
-
 static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
 {
        struct f_uas            *fu = to_f_uas(f);
@@ -2045,29 +2037,24 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
                        &uasp_bi_ep_comp_desc);
        if (!ep)
                goto ep_fail;
-
-       ep->driver_data = fu;
        fu->ep_in = ep;
 
        ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_bo_desc,
                        &uasp_bo_ep_comp_desc);
        if (!ep)
                goto ep_fail;
-       ep->driver_data = fu;
        fu->ep_out = ep;
 
        ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_status_desc,
                        &uasp_status_in_ep_comp_desc);
        if (!ep)
                goto ep_fail;
-       ep->driver_data = fu;
        fu->ep_status = ep;
 
        ep = usb_ep_autoconfig_ss(gadget, &uasp_ss_cmd_desc,
                        &uasp_cmd_comp_desc);
        if (!ep)
                goto ep_fail;
-       ep->driver_data = fu;
        fu->ep_cmd = ep;
 
        /* Assume endpoint addresses are the same for both speeds */
@@ -2091,11 +2078,6 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
        return 0;
 ep_fail:
        pr_err("Can't claim all required eps\n");
-
-       give_back_ep(&fu->ep_in);
-       give_back_ep(&fu->ep_out);
-       give_back_ep(&fu->ep_status);
-       give_back_ep(&fu->ep_cmd);
        return -ENOTSUPP;
 }
 
index 9a3a6b00391aa41042836d78d1b88eed27b9ee73..cdbff54e07acc4365a387bdd726ce8e34546a389 100644 (file)
@@ -55,7 +55,7 @@ config USB_LPC32XX
 
 config USB_ATMEL_USBA
        tristate "Atmel USBA"
-       depends on AVR32 || ARCH_AT91
+       depends on ((AVR32 && !OF) || ARCH_AT91)
        help
          USBA is the integrated high-speed USB Device controller on
          the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel.
index 175ca93fe5e2d5159804301e99d12e6f048a47da..cd8764150861cf1c677bb25a52f4a1b00294b52e 100644 (file)
 
 static void udc_tasklet_disconnect(unsigned long);
 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);
 static struct udc_request *udc_alloc_bna_dummy(struct udc_ep *ep);
 static void udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq);
-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, gfp_t gfp_flags);
-static int udc_remote_wakeup(struct udc *dev);
-static int udc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id);
-static void udc_pci_remove(struct pci_dev *pdev);
 
 /* description */
 static const char mod_desc[] = UDC_MOD_DESCRIPTION;
@@ -615,6 +607,30 @@ udc_alloc_request(struct usb_ep *usbep, gfp_t gfp)
        return &req->req;
 }
 
+/* frees pci pool descriptors of a DMA chain */
+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(dev, "free chain req = %p\n", req);
+
+       /* do not free first desc., will be done by free for request */
+       td_last = req->td_data;
+       td = phys_to_virt(td_last->next);
+
+       for (i = 1; i < req->chain_len; i++) {
+               pci_pool_free(dev->data_requests, td,
+                             (dma_addr_t)td_last->next);
+               td_last = td;
+               td = phys_to_virt(td_last->next);
+       }
+
+       return ret_val;
+}
+
 /* Frees request packet, called by gadget driver */
 static void
 udc_free_request(struct usb_ep *usbep, struct usb_request *usbreq)
@@ -789,6 +805,123 @@ udc_rxfifo_read(struct udc_ep *ep, struct udc_request *req)
        return finished;
 }
 
+/* Creates or re-inits a DMA chain */
+static int udc_create_dma_chain(
+       struct udc_ep *ep,
+       struct udc_request *req,
+       unsigned long buf_len, gfp_t 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;
+
+       VDBG(ep->dev, "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;
+       }
+
+       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) {
+                       td = pci_pool_alloc(ep->dev->data_requests,
+                                           gfp_flags, &dma_addr);
+                       if (!td)
+                               return -ENOMEM;
+
+                       td->status = 0;
+               } else if (i == buf_len) {
+                       /* first td */
+                       td = (struct udc_data_dma *)phys_to_virt(
+                                               req->td_data->next);
+                       td->status = 0;
+               } else {
+                       td = (struct udc_data_dma *)phys_to_virt(last->next);
+                       td->status = 0;
+               }
+
+               if (td)
+                       td->bufptr = req->req.dma + i; /* assign buffer */
+               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);
+                       }
+               } 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);
+                       }
+               }
+               last = td;
+       }
+       /* set last bit */
+       if (td) {
+               td->status |= AMD_BIT(UDC_DMA_IN_STS_L);
+               /* last desc. points to itself */
+               req->td_data_last = td;
+       }
+
+       return 0;
+}
+
 /* create/re-init a DMA descriptor or a DMA descriptor chain */
 static int prep_dma(struct udc_ep *ep, struct udc_request *req, gfp_t gfp)
 {
@@ -913,32 +1046,6 @@ __acquires(ep->dev->lock)
        ep->halted = halted;
 }
 
-/* frees pci pool descriptors of a DMA chain */
-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(dev, "free chain req = %p\n", req);
-
-       /* do not free first desc., will be done by free for request */
-       td_last = req->td_data;
-       td = phys_to_virt(td_last->next);
-
-       for (i = 1; i < req->chain_len; i++) {
-
-               pci_pool_free(dev->data_requests, td,
-                               (dma_addr_t) td_last->next);
-               td_last = td;
-               td = phys_to_virt(td_last->next);
-       }
-
-       return ret_val;
-}
-
 /* Iterates to the end of a DMA chain and returns last descriptor */
 static struct udc_data_dma *udc_get_last_dma_desc(struct udc_request *req)
 {
@@ -975,125 +1082,6 @@ static u32 udc_get_ppbdu_rxbytes(struct udc_request *req)
 
 }
 
-/* Creates or re-inits a DMA chain */
-static int udc_create_dma_chain(
-       struct udc_ep *ep,
-       struct udc_request *req,
-       unsigned long buf_len, gfp_t 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;
-
-       VDBG(ep->dev, "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;
-       }
-
-       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) {
-
-                       td = pci_pool_alloc(ep->dev->data_requests,
-                                       gfp_flags, &dma_addr);
-                       if (!td)
-                               return -ENOMEM;
-
-                       td->status = 0;
-               } else if (i == buf_len) {
-                       /* first td */
-                       td = (struct udc_data_dma *) phys_to_virt(
-                                               req->td_data->next);
-                       td->status = 0;
-               } else {
-                       td = (struct udc_data_dma *) phys_to_virt(last->next);
-                       td->status = 0;
-               }
-
-
-               if (td)
-                       td->bufptr = req->req.dma + i; /* assign buffer */
-               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);
-                       }
-               } 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);
-                       }
-               }
-               last = td;
-       }
-       /* set last bit */
-       if (td) {
-               td->status |= AMD_BIT(UDC_DMA_IN_STS_L);
-               /* last desc. points to itself */
-               req->td_data_last = td;
-       }
-
-       return 0;
-}
-
 /* Enabling RX DMA */
 static void udc_set_rde(struct udc *dev)
 {
@@ -1453,6 +1441,26 @@ static int udc_get_frame(struct usb_gadget *gadget)
        return -EOPNOTSUPP;
 }
 
+/* Initiates a remote wakeup */
+static int udc_remote_wakeup(struct udc *dev)
+{
+       unsigned long flags;
+       u32 tmp;
+
+       DBG(dev, "UDC initiates remote wakeup\n");
+
+       spin_lock_irqsave(&dev->lock, flags);
+
+       tmp = readl(&dev->regs->ctl);
+       tmp |= AMD_BIT(UDC_DEVCTL_RES);
+       writel(tmp, &dev->regs->ctl);
+       tmp &= AMD_CLEAR_BIT(UDC_DEVCTL_RES);
+       writel(tmp, &dev->regs->ctl);
+
+       spin_unlock_irqrestore(&dev->lock, flags);
+       return 0;
+}
+
 /* Remote wakeup gadget interface */
 static int udc_wakeup(struct usb_gadget *gadget)
 {
@@ -1498,33 +1506,6 @@ static void make_ep_lists(struct udc *dev)
        dev->ep[UDC_EPOUT_IX].fifo_depth = UDC_RXFIFO_SIZE;
 }
 
-/* init registers at driver load time */
-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 */
 static void udc_basic_init(struct udc *dev)
 {
@@ -1563,6 +1544,33 @@ static void udc_basic_init(struct udc *dev)
        dev->data_ep_queued = 0;
 }
 
+/* init registers at driver load time */
+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;
+}
+
 /* Sets initial endpoint parameters */
 static void udc_setup_endpoints(struct udc *dev)
 {
@@ -2177,7 +2185,7 @@ static irqreturn_t udc_data_out_isr(struct udc *dev, int ep_ix)
                }
 
        /* DMA */
-       } else if (!ep->cancel_transfer && req != NULL) {
+       } else if (!ep->cancel_transfer && req) {
                ret_val = IRQ_HANDLED;
 
                /* check for DMA done */
@@ -3107,6 +3115,17 @@ static void udc_remove(struct udc *dev)
        udc = NULL;
 }
 
+/* free all the dma pools */
+static void free_dma_pools(struct udc *dev)
+{
+       dma_pool_free(dev->stp_requests, dev->ep[UDC_EP0OUT_IX].td,
+                     dev->ep[UDC_EP0OUT_IX].td_phys);
+       dma_pool_free(dev->stp_requests, dev->ep[UDC_EP0OUT_IX].td_stp,
+                     dev->ep[UDC_EP0OUT_IX].td_stp_dma);
+       dma_pool_destroy(dev->stp_requests);
+       dma_pool_destroy(dev->data_requests);
+}
+
 /* Reset all pci context */
 static void udc_pci_remove(struct pci_dev *pdev)
 {
@@ -3116,35 +3135,19 @@ static void udc_pci_remove(struct pci_dev *pdev)
 
        usb_del_gadget_udc(&udc->gadget);
        /* gadget driver must not be registered */
-       BUG_ON(dev->driver != NULL);
+       if (WARN_ON(dev->driver))
+               return;
 
        /* dma pool cleanup */
-       if (dev->data_requests)
-               pci_pool_destroy(dev->data_requests);
-
-       if (dev->stp_requests) {
-               /* cleanup DMA desc's for ep0in */
-               pci_pool_free(dev->stp_requests,
-                       dev->ep[UDC_EP0OUT_IX].td_stp,
-                       dev->ep[UDC_EP0OUT_IX].td_stp_dma);
-               pci_pool_free(dev->stp_requests,
-                       dev->ep[UDC_EP0OUT_IX].td,
-                       dev->ep[UDC_EP0OUT_IX].td_phys);
-
-               pci_pool_destroy(dev->stp_requests);
-       }
+       free_dma_pools(dev);
 
        /* reset controller */
        writel(AMD_BIT(UDC_DEVCFG_SOFTRESET), &dev->regs->cfg);
-       if (dev->irq_registered)
-               free_irq(pdev->irq, dev);
-       if (dev->virt_addr)
-               iounmap(dev->virt_addr);
-       if (dev->mem_region)
-               release_mem_region(pci_resource_start(pdev, 0),
-                               pci_resource_len(pdev, 0));
-       if (dev->active)
-               pci_disable_device(pdev);
+       free_irq(pdev->irq, dev);
+       iounmap(dev->virt_addr);
+       release_mem_region(pci_resource_start(pdev, 0),
+                          pci_resource_len(pdev, 0));
+       pci_disable_device(pdev);
 
        udc_remove(dev);
 }
@@ -3169,8 +3172,7 @@ static int init_dma_pools(struct udc *dev)
                sizeof(struct udc_data_dma), 0, 0);
        if (!dev->data_requests) {
                DBG(dev, "can't get request data pool\n");
-               retval = -ENOMEM;
-               goto finished;
+               return -ENOMEM;
        }
 
        /* EP0 in dma regs = dev control regs */
@@ -3182,27 +3184,101 @@ static int init_dma_pools(struct udc *dev)
        if (!dev->stp_requests) {
                DBG(dev, "can't get stp request pool\n");
                retval = -ENOMEM;
-               goto finished;
+               goto err_create_dma_pool;
        }
        /* setup */
        td_stp = dma_pool_alloc(dev->stp_requests, GFP_KERNEL,
                                &dev->ep[UDC_EP0OUT_IX].td_stp_dma);
-       if (td_stp == NULL) {
+       if (!td_stp) {
                retval = -ENOMEM;
-               goto finished;
+               goto err_alloc_dma;
        }
        dev->ep[UDC_EP0OUT_IX].td_stp = td_stp;
 
        /* data: 0 packets !? */
        td_data = dma_pool_alloc(dev->stp_requests, GFP_KERNEL,
                                &dev->ep[UDC_EP0OUT_IX].td_phys);
-       if (td_data == NULL) {
+       if (!td_data) {
                retval = -ENOMEM;
-               goto finished;
+               goto err_alloc_phys;
        }
        dev->ep[UDC_EP0OUT_IX].td = td_data;
        return 0;
 
+err_alloc_phys:
+       dma_pool_free(dev->stp_requests, dev->ep[UDC_EP0OUT_IX].td_stp,
+                     dev->ep[UDC_EP0OUT_IX].td_stp_dma);
+err_alloc_dma:
+       dma_pool_destroy(dev->stp_requests);
+       dev->stp_requests = NULL;
+err_create_dma_pool:
+       dma_pool_destroy(dev->data_requests);
+       dev->data_requests = NULL;
+       return retval;
+}
+
+/* general probe */
+static 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 */
+       dev->gadget.ops = &udc_ops;
+
+       dev_set_name(&dev->gadget.dev, "gadget");
+       dev->gadget.name = name;
+       dev->gadget.max_speed = USB_SPEED_HIGH;
+
+       /* init registers, interrupts, ... */
+       startup_registers(dev);
+
+       dev_info(&dev->pdev->dev, "%s\n", mod_desc);
+
+       snprintf(tmp, sizeof(tmp), "%d", dev->irq);
+       dev_info(&dev->pdev->dev,
+                "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);
+       if (dev->chiprev == UDC_HSA0_REV) {
+               dev_err(&dev->pdev->dev, "chip revision is A0; too old\n");
+               retval = -ENODEV;
+               goto finished;
+       }
+       dev_info(&dev->pdev->dev,
+                "driver version: %s(for Geode5536 B1)\n", tmp);
+       udc = dev;
+
+       retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
+                                           gadget_release);
+       if (retval)
+               goto finished;
+
+       /* 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;
+
+       /* 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;
 }
@@ -3234,7 +3310,6 @@ static int udc_pci_probe(
                retval = -ENODEV;
                goto err_pcidev;
        }
-       dev->active = 1;
 
        /* PCI resource allocation */
        resource = pci_resource_start(pdev, 0);
@@ -3245,10 +3320,9 @@ static int udc_pci_probe(
                retval = -EBUSY;
                goto err_memreg;
        }
-       dev->mem_region = 1;
 
        dev->virt_addr = ioremap_nocache(resource, len);
-       if (dev->virt_addr == NULL) {
+       if (!dev->virt_addr) {
                dev_dbg(&pdev->dev, "start address cannot be mapped\n");
                retval = -EFAULT;
                goto err_ioremap;
@@ -3276,7 +3350,6 @@ static int udc_pci_probe(
                retval = -EBUSY;
                goto err_irq;
        }
-       dev->irq_registered = 1;
 
        pci_set_drvdata(pdev, dev);
 
@@ -3290,7 +3363,7 @@ static int udc_pci_probe(
        if (use_dma) {
                retval = init_dma_pools(dev);
                if (retval != 0)
-                       goto finished;
+                       goto err_dma;
        }
 
        dev->phys_addr = resource;
@@ -3298,13 +3371,17 @@ static int udc_pci_probe(
        dev->pdev = pdev;
 
        /* general probing */
-       if (udc_probe(dev) == 0)
-               return 0;
-
-finished:
-       udc_pci_remove(pdev);
-       return retval;
+       if (udc_probe(dev)) {
+               retval = -ENODEV;
+               goto err_probe;
+       }
+       return 0;
 
+err_probe:
+       if (use_dma)
+               free_dma_pools(dev);
+err_dma:
+       free_irq(pdev->irq, dev);
 err_irq:
        iounmap(dev->virt_addr);
 err_ioremap:
@@ -3316,92 +3393,6 @@ err_pcidev:
        return retval;
 }
 
-/* general probe */
-static 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 */
-       dev->gadget.ops = &udc_ops;
-
-       dev_set_name(&dev->gadget.dev, "gadget");
-       dev->gadget.name = name;
-       dev->gadget.max_speed = USB_SPEED_HIGH;
-
-       /* init registers, interrupts, ... */
-       startup_registers(dev);
-
-       dev_info(&dev->pdev->dev, "%s\n", mod_desc);
-
-       snprintf(tmp, sizeof tmp, "%d", dev->irq);
-       dev_info(&dev->pdev->dev,
-               "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);
-       if (dev->chiprev == UDC_HSA0_REV) {
-               dev_err(&dev->pdev->dev, "chip revision is A0; too old\n");
-               retval = -ENODEV;
-               goto finished;
-       }
-       dev_info(&dev->pdev->dev,
-               "driver version: %s(for Geode5536 B1)\n", tmp);
-       udc = dev;
-
-       retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
-                       gadget_release);
-       if (retval)
-               goto finished;
-
-       /* 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;
-
-       /* 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 */
-static int udc_remote_wakeup(struct udc *dev)
-{
-       unsigned long flags;
-       u32 tmp;
-
-       DBG(dev, "UDC initiates remote wakeup\n");
-
-       spin_lock_irqsave(&dev->lock, flags);
-
-       tmp = readl(&dev->regs->ctl);
-       tmp |= AMD_BIT(UDC_DEVCTL_RES);
-       writel(tmp, &dev->regs->ctl);
-       tmp &= AMD_CLEAR_BIT(UDC_DEVCTL_RES);
-       writel(tmp, &dev->regs->ctl);
-
-       spin_unlock_irqrestore(&dev->lock, flags);
-       return 0;
-}
-
 /* PCI device parameters */
 static const struct pci_device_id pci_id[] = {
        {
index 6744d3b83109e6717425a450b14ed41f35088f71..4638d707f1698940eea06131fe0baf0cfbb2032f 100644 (file)
@@ -526,14 +526,11 @@ struct udc {
        struct udc_ep                   ep[UDC_EP_NUM];
        struct usb_gadget_driver        *driver;
        /* operational flags */
-       unsigned                        active : 1,
-                                       stall_ep0in : 1,
+       unsigned                        stall_ep0in : 1,
                                        waiting_zlp_ack_ep0in : 1,
                                        set_cfg_not_acked : 1,
-                                       irq_registered : 1,
                                        data_ep_enabled : 1,
                                        data_ep_queued : 1,
-                                       mem_region : 1,
                                        sys_suspended : 1,
                                        connected;
 
index 2679c8b217ccdbf829c8ce001d323c265e33f974..0a433e6b346bca3f170d83a497a3bfe68cb863b6 100644 (file)
@@ -112,6 +112,14 @@ struct at91_udc_caps {
        void (*pullup)(struct at91_udc *udc, int is_on);
 };
 
+struct at91_udc_data {
+       int     vbus_pin;               /* high == host powering us */
+       u8      vbus_active_low;        /* vbus polarity */
+       u8      vbus_polled;            /* Use polling, not interrupt */
+       int     pullup_pin;             /* active == D+ pulled up */
+       u8      pullup_active_low;      /* true == pullup_pin is active low */
+};
+
 /*
  * driver is non-SMP, and just blocks IRQs whenever it needs
  * access protection for chip registers or driver state
index 27af0f008b57dd0999241c3e72919e6635fd9014..dde44450dfa93f1fab90da1bd47fd501aaf554e8 100644 (file)
@@ -833,10 +833,10 @@ static const struct usb_ep_ops dummy_ep_ops = {
 /* there are both host and device side versions of this call ... */
 static int dummy_g_get_frame(struct usb_gadget *_gadget)
 {
-       struct timeval  tv;
+       struct timespec64 ts64;
 
-       do_gettimeofday(&tv);
-       return tv.tv_usec / 1000;
+       ktime_get_ts64(&ts64);
+       return ts64.tv_nsec / NSEC_PER_MSEC;
 }
 
 static int dummy_wakeup(struct usb_gadget *_gadget)
index cf0ed42f5591c93065d6d9c5741dea6967ad4829..6706aef907f4bdb32b308f148612a2566c2eb3b9 100644 (file)
@@ -1913,7 +1913,7 @@ static void defect7374_disable_data_eps(struct net2280 *dev)
 
        for (i = 1; i < 5; i++) {
                ep = &dev->ep[i];
-               writel(0, &ep->cfg->ep_cfg);
+               writel(i, &ep->cfg->ep_cfg);
        }
 
        /* CSROUT, CSRIN, PCIOUT, PCIIN, STATIN, RCIN */
index e5f4c5274298684576ac33794da6d929249af797..7a04157ff5796883f8c9ec3835b43c16155fbc3d 100644 (file)
@@ -330,7 +330,7 @@ struct pch_vbus_gpio_data {
  * @prot_stall:                protcol stall requested
  * @irq_registered:    irq registered with system
  * @mem_region:                device memory mapped
- * @registered:                driver regsitered with system
+ * @registered:                driver registered with system
  * @suspended:         driver in suspended state
  * @connected:         gadget driver associated
  * @vbus_session:      required vbus_session state
@@ -2747,18 +2747,18 @@ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr)
        if (dev_intr & UDC_DEVINT_US) {
                if (dev->driver
                        && dev->driver->suspend) {
-                       spin_lock(&dev->lock);
-                       dev->driver->suspend(&dev->gadget);
                        spin_unlock(&dev->lock);
+                       dev->driver->suspend(&dev->gadget);
+                       spin_lock(&dev->lock);
                }
 
                vbus = pch_vbus_gpio_get_value(dev);
                if ((dev->vbus_session == 0)
                        && (vbus != 1)) {
                        if (dev->driver && dev->driver->disconnect) {
-                               spin_lock(&dev->lock);
-                               dev->driver->disconnect(&dev->gadget);
                                spin_unlock(&dev->lock);
+                               dev->driver->disconnect(&dev->gadget);
+                               spin_lock(&dev->lock);
                        }
                        pch_udc_reconnect(dev);
                } else if ((dev->vbus_session == 0)
index 079991e283e9e0a1dd1abcaf5794aa6dbf1aceb8..3bb08870148f467de4869c133fa6adfef4602116 100644 (file)
@@ -348,16 +348,6 @@ config USB_ISP1362_HCD
          To compile this driver as a module, choose M here: the
          module will be called isp1362-hcd.
 
-config USB_FUSBH200_HCD
-       tristate "FUSBH200 HCD support"
-       depends on USB
-       ---help---
-       Faraday FUSBH200 is designed to meet USB2.0 EHCI specification
-       with minor modification.
-
-       To compile this driver as a module, choose M here: the
-       module will be called fusbh200-hcd.
-
 config USB_FOTG210_HCD
        tristate "FOTG210 HCD support"
        depends on USB
index 754efaa8ccf8fbebf2e2c591ec4c77ae83893952..e7558abc994d76be29a347ed6904bca36d3765de 100644 (file)
@@ -28,9 +28,6 @@ ifneq ($(CONFIG_USB), )
        obj-$(CONFIG_PCI)       += pci-quirks.o
 endif
 
-obj-$(CONFIG_USB_XHCI_PCI)     += xhci-pci.o
-obj-$(CONFIG_USB_XHCI_PLATFORM) += xhci-plat-hcd.o
-
 obj-$(CONFIG_USB_EHCI_HCD)     += ehci-hcd.o
 obj-$(CONFIG_USB_EHCI_PCI)     += ehci-pci.o
 obj-$(CONFIG_USB_EHCI_HCD_PLATFORM)    += ehci-platform.o
@@ -65,6 +62,8 @@ obj-$(CONFIG_USB_OHCI_HCD_PXA27X)     += ohci-pxa27x.o
 obj-$(CONFIG_USB_UHCI_HCD)     += uhci-hcd.o
 obj-$(CONFIG_USB_FHCI_HCD)     += fhci.o
 obj-$(CONFIG_USB_XHCI_HCD)     += xhci-hcd.o
+obj-$(CONFIG_USB_XHCI_PCI)     += xhci-pci.o
+obj-$(CONFIG_USB_XHCI_PLATFORM) += xhci-plat-hcd.o
 obj-$(CONFIG_USB_SL811_HCD)    += sl811-hcd.o
 obj-$(CONFIG_USB_SL811_CS)     += sl811_cs.o
 obj-$(CONFIG_USB_U132_HCD)     += u132-hcd.o
@@ -75,6 +74,5 @@ obj-$(CONFIG_USB_FSL_MPH_DR_OF)       += fsl-mph-dr-of.o
 obj-$(CONFIG_USB_EHCI_FSL)     += ehci-fsl.o
 obj-$(CONFIG_USB_HCD_BCMA)     += bcma-hcd.o
 obj-$(CONFIG_USB_HCD_SSB)      += ssb-hcd.o
-obj-$(CONFIG_USB_FUSBH200_HCD) += fusbh200-hcd.o
 obj-$(CONFIG_USB_FOTG210_HCD)  += fotg210-hcd.o
 obj-$(CONFIG_USB_MAX3421_HCD)  += max3421-hcd.o
index 275c92e53a5972615166310742b63af0a8d61cf5..c4f84c81de0194e33b9bad75e6aafd1c9074dd74 100644 (file)
@@ -80,12 +80,12 @@ static int ehci_msm_probe(struct platform_device *pdev)
                return  -ENOMEM;
        }
 
-       hcd->irq = platform_get_irq(pdev, 0);
-       if (hcd->irq < 0) {
+       ret = platform_get_irq(pdev, 0);
+       if (ret < 0) {
                dev_err(&pdev->dev, "Unable to get IRQ resource\n");
-               ret = hcd->irq;
                goto put_hcd;
        }
+       hcd->irq = ret;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
index bfcbb9aa8816bb5a4c84bef1d525ca8d086c8c66..ee8d5faa01947cd6d2c8cf708273c0521762a797 100644 (file)
@@ -224,7 +224,8 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)
        priv->phy = devm_phy_optional_get(&pdev->dev, "usb");
        if (IS_ERR(priv->phy)) {
                err = PTR_ERR(priv->phy);
-               goto err_phy_get;
+               if (err != -ENOSYS)
+                       goto err_phy_get;
        } else {
                err = phy_init(priv->phy);
                if (err)
index 5c3c0859868251233c7672baf9f2ea01c5b82364..bd7082f297bbe76b7db8c10ad091402c79f45786 100644 (file)
@@ -19,6 +19,7 @@
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
+#include <linux/acpi.h>
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
@@ -162,8 +163,10 @@ static int ehci_platform_probe(struct platform_device *dev)
 
        err = dma_coerce_mask_and_coherent(&dev->dev,
                pdata->dma_mask_64 ? DMA_BIT_MASK(64) : DMA_BIT_MASK(32));
-       if (err)
+       if (err) {
+               dev_err(&dev->dev, "Error: DMA mask configuration failed\n");
                return err;
+       }
 
        irq = platform_get_irq(dev, 0);
        if (irq < 0) {
@@ -385,6 +388,12 @@ static const struct of_device_id vt8500_ehci_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
 
+static const struct acpi_device_id ehci_acpi_match[] = {
+       { "PNP0D20", 0 }, /* EHCI controller without debug */
+       { }
+};
+MODULE_DEVICE_TABLE(acpi, ehci_acpi_match);
+
 static const struct platform_device_id ehci_platform_table[] = {
        { "ehci-platform", 0 },
        { }
@@ -403,6 +412,7 @@ static struct platform_driver ehci_platform_driver = {
                .name   = "ehci-platform",
                .pm     = &ehci_platform_pm_ops,
                .of_match_table = vt8500_ehci_ids,
+               .acpi_match_table = ACPI_PTR(ehci_acpi_match),
        }
 };
 
index 34e14746b92eab6280c50c19317a9fd80a5fb87a..3c4e5253955c336a89d507329cf687a3240410ec 100644 (file)
@@ -149,6 +149,7 @@ static const struct of_device_id spear_ehci_id_table[] = {
        { .compatible = "st,spear600-ehci", },
        { },
 };
+MODULE_DEVICE_TABLE(of, spear_ehci_id_table);
 
 static struct platform_driver spear_ehci_hcd_driver = {
        .probe          = spear_ehci_hcd_drv_probe,
index 000ed80ab592a0ce731023386a3636d3bd920976..787f4e3d16d81989dd71e9061d25992f789e000d 100644 (file)
@@ -1,5 +1,4 @@
-/*
- * Faraday FOTG210 EHCI-like driver
+/* Faraday FOTG210 EHCI-like driver
  *
  * Copyright (c) 2013 Faraday Technology Corporation
  *
 #include <asm/irq.h>
 #include <asm/unaligned.h>
 
-/*-------------------------------------------------------------------------*/
 #define DRIVER_AUTHOR "Yuan-Hsin Chen"
 #define DRIVER_DESC "FOTG210 Host Controller (EHCI) Driver"
-
-static const char      hcd_name[] = "fotg210_hcd";
+static const char hcd_name[] = "fotg210_hcd";
 
 #undef FOTG210_URB_TRACE
-
 #define FOTG210_STATS
 
 /* magic numbers that can affect system performance */
-#define        FOTG210_TUNE_CERR               3 /* 0-3 qtd retries; 0 == don't stop */
-#define        FOTG210_TUNE_RL_HS              4 /* nak throttle; see 4.9 */
-#define        FOTG210_TUNE_RL_TT              0
-#define        FOTG210_TUNE_MULT_HS    1       /* 1-3 transactions/uframe; 4.10.3 */
-#define        FOTG210_TUNE_MULT_TT    1
-/*
- * Some drivers think it's safe to schedule isochronous transfers more than
- * 256 ms into the future (partly as a result of an old bug in the scheduling
+#define FOTG210_TUNE_CERR      3 /* 0-3 qtd retries; 0 == don't stop */
+#define FOTG210_TUNE_RL_HS     4 /* nak throttle; see 4.9 */
+#define FOTG210_TUNE_RL_TT     0
+#define FOTG210_TUNE_MULT_HS   1 /* 1-3 transactions/uframe; 4.10.3 */
+#define FOTG210_TUNE_MULT_TT   1
+
+/* Some drivers think it's safe to schedule isochronous transfers more than 256
+ * ms into the future (partly as a result of an old bug in the scheduling
  * code).  In an attempt to avoid trouble, we will use a minimum scheduling
  * length of 512 frames instead of 256.
  */
-#define        FOTG210_TUNE_FLS                1 /* (medium) 512-frame schedule */
+#define FOTG210_TUNE_FLS 1 /* (medium) 512-frame schedule */
 
 /* Initial IRQ latency:  faster than hw default */
-static int log2_irq_thresh;            /* 0 to 6 */
+static int log2_irq_thresh; /* 0 to 6 */
 module_param(log2_irq_thresh, int, S_IRUGO);
 MODULE_PARM_DESC(log2_irq_thresh, "log2 IRQ latency, 1-64 microframes");
 
@@ -89,66 +85,57 @@ static unsigned int hird;
 module_param(hird, int, S_IRUGO);
 MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us");
 
-#define        INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
+#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
 
 #include "fotg210.h"
 
-/*-------------------------------------------------------------------------*/
-
 #define fotg210_dbg(fotg210, fmt, args...) \
-       dev_dbg(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args)
+       dev_dbg(fotg210_to_hcd(fotg210)->self.controller, fmt, ## args)
 #define fotg210_err(fotg210, fmt, args...) \
-       dev_err(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args)
+       dev_err(fotg210_to_hcd(fotg210)->self.controller, fmt, ## args)
 #define fotg210_info(fotg210, fmt, args...) \
-       dev_info(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args)
+       dev_info(fotg210_to_hcd(fotg210)->self.controller, fmt, ## args)
 #define fotg210_warn(fotg210, fmt, args...) \
-       dev_warn(fotg210_to_hcd(fotg210)->self.controller , fmt , ## args)
+       dev_warn(fotg210_to_hcd(fotg210)->self.controller, fmt, ## args)
 
-/* check the values in the HCSPARAMS register
- * (host controller _Structural_ parameters)
- * see EHCI spec, Table 2-4 for each value
+/* check the values in the HCSPARAMS register (host controller _Structural_
+ * parameters) see EHCI spec, Table 2-4 for each value
  */
 static void dbg_hcs_params(struct fotg210_hcd *fotg210, char *label)
 {
-       u32     params = fotg210_readl(fotg210, &fotg210->caps->hcs_params);
+       u32 params = fotg210_readl(fotg210, &fotg210->caps->hcs_params);
 
-       fotg210_dbg(fotg210,
-               "%s hcs_params 0x%x ports=%d\n",
-               label, params,
-               HCS_N_PORTS(params)
-               );
+       fotg210_dbg(fotg210, "%s hcs_params 0x%x ports=%d\n", label, params,
+                       HCS_N_PORTS(params));
 }
 
-/* check the values in the HCCPARAMS register
- * (host controller _Capability_ parameters)
- * see EHCI Spec, Table 2-5 for each value
- * */
+/* check the values in the HCCPARAMS register (host controller _Capability_
+ * parameters) see EHCI Spec, Table 2-5 for each value
+ */
 static void dbg_hcc_params(struct fotg210_hcd *fotg210, char *label)
 {
-       u32     params = fotg210_readl(fotg210, &fotg210->caps->hcc_params);
+       u32 params = fotg210_readl(fotg210, &fotg210->caps->hcc_params);
 
-       fotg210_dbg(fotg210,
-               "%s hcc_params %04x uframes %s%s\n",
-               label,
-               params,
-               HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024",
-               HCC_CANPARK(params) ? " park" : "");
+       fotg210_dbg(fotg210, "%s hcc_params %04x uframes %s%s\n", label,
+                       params,
+                       HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024",
+                       HCC_CANPARK(params) ? " park" : "");
 }
 
 static void __maybe_unused
 dbg_qtd(const char *label, struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd)
 {
        fotg210_dbg(fotg210, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
-               hc32_to_cpup(fotg210, &qtd->hw_next),
-               hc32_to_cpup(fotg210, &qtd->hw_alt_next),
-               hc32_to_cpup(fotg210, &qtd->hw_token),
-               hc32_to_cpup(fotg210, &qtd->hw_buf[0]));
+                       hc32_to_cpup(fotg210, &qtd->hw_next),
+                       hc32_to_cpup(fotg210, &qtd->hw_alt_next),
+                       hc32_to_cpup(fotg210, &qtd->hw_token),
+                       hc32_to_cpup(fotg210, &qtd->hw_buf[0]));
        if (qtd->hw_buf[1])
                fotg210_dbg(fotg210, "  p1=%08x p2=%08x p3=%08x p4=%08x\n",
-                       hc32_to_cpup(fotg210, &qtd->hw_buf[1]),
-                       hc32_to_cpup(fotg210, &qtd->hw_buf[2]),
-                       hc32_to_cpup(fotg210, &qtd->hw_buf[3]),
-                       hc32_to_cpup(fotg210, &qtd->hw_buf[4]));
+                               hc32_to_cpup(fotg210, &qtd->hw_buf[1]),
+                               hc32_to_cpup(fotg210, &qtd->hw_buf[2]),
+                               hc32_to_cpup(fotg210, &qtd->hw_buf[3]),
+                               hc32_to_cpup(fotg210, &qtd->hw_buf[4]));
 }
 
 static void __maybe_unused
@@ -156,101 +143,100 @@ dbg_qh(const char *label, struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
 {
        struct fotg210_qh_hw *hw = qh->hw;
 
-       fotg210_dbg(fotg210, "%s qh %p n%08x info %x %x qtd %x\n", label,
-               qh, hw->hw_next, hw->hw_info1, hw->hw_info2, hw->hw_current);
+       fotg210_dbg(fotg210, "%s qh %p n%08x info %x %x qtd %x\n", label, qh,
+                       hw->hw_next, hw->hw_info1, hw->hw_info2,
+                       hw->hw_current);
+
        dbg_qtd("overlay", fotg210, (struct fotg210_qtd *) &hw->hw_qtd_next);
 }
 
 static void __maybe_unused
 dbg_itd(const char *label, struct fotg210_hcd *fotg210, struct fotg210_itd *itd)
 {
-       fotg210_dbg(fotg210, "%s[%d] itd %p, next %08x, urb %p\n",
-               label, itd->frame, itd, hc32_to_cpu(fotg210, itd->hw_next),
-               itd->urb);
+       fotg210_dbg(fotg210, "%s[%d] itd %p, next %08x, urb %p\n", label,
+                       itd->frame, itd, hc32_to_cpu(fotg210, itd->hw_next),
+                       itd->urb);
+
        fotg210_dbg(fotg210,
-               "  trans: %08x %08x %08x %08x %08x %08x %08x %08x\n",
-               hc32_to_cpu(fotg210, itd->hw_transaction[0]),
-               hc32_to_cpu(fotg210, itd->hw_transaction[1]),
-               hc32_to_cpu(fotg210, itd->hw_transaction[2]),
-               hc32_to_cpu(fotg210, itd->hw_transaction[3]),
-               hc32_to_cpu(fotg210, itd->hw_transaction[4]),
-               hc32_to_cpu(fotg210, itd->hw_transaction[5]),
-               hc32_to_cpu(fotg210, itd->hw_transaction[6]),
-               hc32_to_cpu(fotg210, itd->hw_transaction[7]));
+                       "  trans: %08x %08x %08x %08x %08x %08x %08x %08x\n",
+                       hc32_to_cpu(fotg210, itd->hw_transaction[0]),
+                       hc32_to_cpu(fotg210, itd->hw_transaction[1]),
+                       hc32_to_cpu(fotg210, itd->hw_transaction[2]),
+                       hc32_to_cpu(fotg210, itd->hw_transaction[3]),
+                       hc32_to_cpu(fotg210, itd->hw_transaction[4]),
+                       hc32_to_cpu(fotg210, itd->hw_transaction[5]),
+                       hc32_to_cpu(fotg210, itd->hw_transaction[6]),
+                       hc32_to_cpu(fotg210, itd->hw_transaction[7]));
+
        fotg210_dbg(fotg210,
-               "  buf:   %08x %08x %08x %08x %08x %08x %08x\n",
-               hc32_to_cpu(fotg210, itd->hw_bufp[0]),
-               hc32_to_cpu(fotg210, itd->hw_bufp[1]),
-               hc32_to_cpu(fotg210, itd->hw_bufp[2]),
-               hc32_to_cpu(fotg210, itd->hw_bufp[3]),
-               hc32_to_cpu(fotg210, itd->hw_bufp[4]),
-               hc32_to_cpu(fotg210, itd->hw_bufp[5]),
-               hc32_to_cpu(fotg210, itd->hw_bufp[6]));
+                       "  buf:   %08x %08x %08x %08x %08x %08x %08x\n",
+                       hc32_to_cpu(fotg210, itd->hw_bufp[0]),
+                       hc32_to_cpu(fotg210, itd->hw_bufp[1]),
+                       hc32_to_cpu(fotg210, itd->hw_bufp[2]),
+                       hc32_to_cpu(fotg210, itd->hw_bufp[3]),
+                       hc32_to_cpu(fotg210, itd->hw_bufp[4]),
+                       hc32_to_cpu(fotg210, itd->hw_bufp[5]),
+                       hc32_to_cpu(fotg210, itd->hw_bufp[6]));
+
        fotg210_dbg(fotg210, "  index: %d %d %d %d %d %d %d %d\n",
-               itd->index[0], itd->index[1], itd->index[2],
-               itd->index[3], itd->index[4], itd->index[5],
-               itd->index[6], itd->index[7]);
+                       itd->index[0], itd->index[1], itd->index[2],
+                       itd->index[3], itd->index[4], itd->index[5],
+                       itd->index[6], itd->index[7]);
 }
 
 static int __maybe_unused
 dbg_status_buf(char *buf, unsigned len, const char *label, u32 status)
 {
-       return scnprintf(buf, len,
-               "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s",
-               label, label[0] ? " " : "", status,
-               (status & STS_ASS) ? " Async" : "",
-               (status & STS_PSS) ? " Periodic" : "",
-               (status & STS_RECL) ? " Recl" : "",
-               (status & STS_HALT) ? " Halt" : "",
-               (status & STS_IAA) ? " IAA" : "",
-               (status & STS_FATAL) ? " FATAL" : "",
-               (status & STS_FLR) ? " FLR" : "",
-               (status & STS_PCD) ? " PCD" : "",
-               (status & STS_ERR) ? " ERR" : "",
-               (status & STS_INT) ? " INT" : ""
-               );
+       return scnprintf(buf, len, "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s",
+                       label, label[0] ? " " : "", status,
+                       (status & STS_ASS) ? " Async" : "",
+                       (status & STS_PSS) ? " Periodic" : "",
+                       (status & STS_RECL) ? " Recl" : "",
+                       (status & STS_HALT) ? " Halt" : "",
+                       (status & STS_IAA) ? " IAA" : "",
+                       (status & STS_FATAL) ? " FATAL" : "",
+                       (status & STS_FLR) ? " FLR" : "",
+                       (status & STS_PCD) ? " PCD" : "",
+                       (status & STS_ERR) ? " ERR" : "",
+                       (status & STS_INT) ? " INT" : "");
 }
 
 static int __maybe_unused
 dbg_intr_buf(char *buf, unsigned len, const char *label, u32 enable)
 {
-       return scnprintf(buf, len,
-               "%s%sintrenable %02x%s%s%s%s%s%s",
-               label, label[0] ? " " : "", enable,
-               (enable & STS_IAA) ? " IAA" : "",
-               (enable & STS_FATAL) ? " FATAL" : "",
-               (enable & STS_FLR) ? " FLR" : "",
-               (enable & STS_PCD) ? " PCD" : "",
-               (enable & STS_ERR) ? " ERR" : "",
-               (enable & STS_INT) ? " INT" : ""
-               );
+       return scnprintf(buf, len, "%s%sintrenable %02x%s%s%s%s%s%s",
+                       label, label[0] ? " " : "", enable,
+                       (enable & STS_IAA) ? " IAA" : "",
+                       (enable & STS_FATAL) ? " FATAL" : "",
+                       (enable & STS_FLR) ? " FLR" : "",
+                       (enable & STS_PCD) ? " PCD" : "",
+                       (enable & STS_ERR) ? " ERR" : "",
+                       (enable & STS_INT) ? " INT" : "");
 }
 
 static const char *const fls_strings[] = { "1024", "512", "256", "??" };
 
-static int
-dbg_command_buf(char *buf, unsigned len, const char *label, u32 command)
+static int dbg_command_buf(char *buf, unsigned len, const char *label,
+               u32 command)
 {
        return scnprintf(buf, len,
-               "%s%scommand %07x %s=%d ithresh=%d%s%s%s "
-               "period=%s%s %s",
-               label, label[0] ? " " : "", command,
-               (command & CMD_PARK) ? " park" : "(park)",
-               CMD_PARK_CNT(command),
-               (command >> 16) & 0x3f,
-               (command & CMD_IAAD) ? " IAAD" : "",
-               (command & CMD_ASE) ? " Async" : "",
-               (command & CMD_PSE) ? " Periodic" : "",
-               fls_strings[(command >> 2) & 0x3],
-               (command & CMD_RESET) ? " Reset" : "",
-               (command & CMD_RUN) ? "RUN" : "HALT"
-               );
-}
-
-static char
-*dbg_port_buf(char *buf, unsigned len, const char *label, int port, u32 status)
-{
-       char    *sig;
+                       "%s%scommand %07x %s=%d ithresh=%d%s%s%s period=%s%s %s",
+                       label, label[0] ? " " : "", command,
+                       (command & CMD_PARK) ? " park" : "(park)",
+                       CMD_PARK_CNT(command),
+                       (command >> 16) & 0x3f,
+                       (command & CMD_IAAD) ? " IAAD" : "",
+                       (command & CMD_ASE) ? " Async" : "",
+                       (command & CMD_PSE) ? " Periodic" : "",
+                       fls_strings[(command >> 2) & 0x3],
+                       (command & CMD_RESET) ? " Reset" : "",
+                       (command & CMD_RUN) ? "RUN" : "HALT");
+}
+
+static char *dbg_port_buf(char *buf, unsigned len, const char *label, int port,
+               u32 status)
+{
+       char *sig;
 
        /* signaling state */
        switch (status & (3 << 10)) {
@@ -268,44 +254,41 @@ static char
                break;
        }
 
-       scnprintf(buf, len,
-               "%s%sport:%d status %06x %d "
-               "sig=%s%s%s%s%s%s%s%s",
-               label, label[0] ? " " : "", port, status,
-               status>>25,/*device address */
-               sig,
-               (status & PORT_RESET) ? " RESET" : "",
-               (status & PORT_SUSPEND) ? " SUSPEND" : "",
-               (status & PORT_RESUME) ? " RESUME" : "",
-               (status & PORT_PEC) ? " PEC" : "",
-               (status & PORT_PE) ? " PE" : "",
-               (status & PORT_CSC) ? " CSC" : "",
-               (status & PORT_CONNECT) ? " CONNECT" : "");
+       scnprintf(buf, len, "%s%sport:%d status %06x %d sig=%s%s%s%s%s%s%s%s",
+                       label, label[0] ? " " : "", port, status,
+                       status >> 25, /*device address */
+                       sig,
+                       (status & PORT_RESET) ? " RESET" : "",
+                       (status & PORT_SUSPEND) ? " SUSPEND" : "",
+                       (status & PORT_RESUME) ? " RESUME" : "",
+                       (status & PORT_PEC) ? " PEC" : "",
+                       (status & PORT_PE) ? " PE" : "",
+                       (status & PORT_CSC) ? " CSC" : "",
+                       (status & PORT_CONNECT) ? " CONNECT" : "");
+
        return buf;
 }
 
 /* functions have the "wrong" filename when they're output... */
-#define dbg_status(fotg210, label, status) { \
-       char _buf[80]; \
-       dbg_status_buf(_buf, sizeof(_buf), label, status); \
-       fotg210_dbg(fotg210, "%s\n", _buf); \
+#define dbg_status(fotg210, label, status) {                   \
+       char _buf[80];                                          \
+       dbg_status_buf(_buf, sizeof(_buf), label, status);      \
+       fotg210_dbg(fotg210, "%s\n", _buf);                     \
 }
 
-#define dbg_cmd(fotg210, label, command) { \
-       char _buf[80]; \
-       dbg_command_buf(_buf, sizeof(_buf), label, command); \
-       fotg210_dbg(fotg210, "%s\n", _buf); \
+#define dbg_cmd(fotg210, label, command) {                     \
+       char _buf[80];                                          \
+       dbg_command_buf(_buf, sizeof(_buf), label, command);    \
+       fotg210_dbg(fotg210, "%s\n", _buf);                     \
 }
 
-#define dbg_port(fotg210, label, port, status) { \
-       char _buf[80]; \
-       fotg210_dbg(fotg210, "%s\n", dbg_port_buf(_buf, sizeof(_buf), label, port, status) ); \
+#define dbg_port(fotg210, label, port, status) {                              \
+       char _buf[80];                                                         \
+       fotg210_dbg(fotg210, "%s\n",                                           \
+                       dbg_port_buf(_buf, sizeof(_buf), label, port, status));\
 }
 
-/*-------------------------------------------------------------------------*/
-
 /* troubleshooting help: expose state in debugfs */
-
 static int debug_async_open(struct inode *, struct file *);
 static int debug_periodic_open(struct inode *, struct file *);
 static int debug_registers_open(struct inode *, struct file *);
@@ -347,17 +330,22 @@ struct debug_buffer {
        size_t alloc_size;
 };
 
-#define speed_char(info1)({ char tmp; \
-               switch (info1 & (3 << 12)) { \
-               case QH_FULL_SPEED:     \
-                       tmp = 'f'; break; \
-               case QH_LOW_SPEED:      \
-                       tmp = 'l'; break; \
-               case QH_HIGH_SPEED:     \
-                       tmp = 'h'; break; \
-               default:                \
-                       tmp = '?'; break; \
-               } tmp; })
+static inline char speed_char(u32 scratch)
+{
+       switch (scratch & (3 << 12)) {
+       case QH_FULL_SPEED:
+               return 'f';
+
+       case QH_LOW_SPEED:
+               return 'l';
+
+       case QH_HIGH_SPEED:
+               return 'h';
+
+       default:
+               return '?';
+       }
+}
 
 static inline char token_mark(struct fotg210_hcd *fotg210, __hc32 token)
 {
@@ -373,33 +361,29 @@ static inline char token_mark(struct fotg210_hcd *fotg210, __hc32 token)
        return '/';
 }
 
-static void qh_lines(
-       struct fotg210_hcd *fotg210,
-       struct fotg210_qh *qh,
-       char **nextp,
-       unsigned *sizep
-)
-{
-       u32                     scratch;
-       u32                     hw_curr;
-       struct fotg210_qtd      *td;
-       unsigned                temp;
-       unsigned                size = *sizep;
-       char                    *next = *nextp;
-       char                    mark;
-       __le32                  list_end = FOTG210_LIST_END(fotg210);
-       struct fotg210_qh_hw    *hw = qh->hw;
-
-       if (hw->hw_qtd_next == list_end)        /* NEC does this */
+static void qh_lines(struct fotg210_hcd *fotg210, struct fotg210_qh *qh,
+               char **nextp, unsigned *sizep)
+{
+       u32 scratch;
+       u32 hw_curr;
+       struct fotg210_qtd *td;
+       unsigned temp;
+       unsigned size = *sizep;
+       char *next = *nextp;
+       char mark;
+       __le32 list_end = FOTG210_LIST_END(fotg210);
+       struct fotg210_qh_hw *hw = qh->hw;
+
+       if (hw->hw_qtd_next == list_end) /* NEC does this */
                mark = '@';
        else
                mark = token_mark(fotg210, hw->hw_token);
-       if (mark == '/') {      /* qh_alt_next controls qh advance? */
-               if ((hw->hw_alt_next & QTD_MASK(fotg210))
-                               == fotg210->async->hw->hw_alt_next)
-                       mark = '#';     /* blocked */
+       if (mark == '/') { /* qh_alt_next controls qh advance? */
+               if ((hw->hw_alt_next & QTD_MASK(fotg210)) ==
+                   fotg210->async->hw->hw_alt_next)
+                       mark = '#'; /* blocked */
                else if (hw->hw_alt_next == list_end)
-                       mark = '.';     /* use hw_qtd_next */
+                       mark = '.'; /* use hw_qtd_next */
                /* else alt_next points to some other qtd */
        }
        scratch = hc32_to_cpup(fotg210, &hw->hw_info1);
@@ -462,6 +446,7 @@ static void qh_lines(
        temp = snprintf(next, size, "\n");
        if (size < temp)
                temp = size;
+
        size -= temp;
        next += temp;
 
@@ -472,12 +457,12 @@ done:
 
 static ssize_t fill_async_buffer(struct debug_buffer *buf)
 {
-       struct usb_hcd          *hcd;
-       struct fotg210_hcd      *fotg210;
-       unsigned long           flags;
-       unsigned                temp, size;
-       char                    *next;
-       struct fotg210_qh               *qh;
+       struct usb_hcd *hcd;
+       struct fotg210_hcd *fotg210;
+       unsigned long flags;
+       unsigned temp, size;
+       char *next;
+       struct fotg210_qh *qh;
 
        hcd = bus_to_hcd(buf->bus);
        fotg210 = hcd_to_fotg210(hcd);
@@ -492,7 +477,7 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf)
         */
        spin_lock_irqsave(&fotg210->lock, flags);
        for (qh = fotg210->async->qh_next.qh; size > 0 && qh;
-            qh = qh->qh_next.qh)
+                       qh = qh->qh_next.qh)
                qh_lines(fotg210, qh, &next, &size);
        if (fotg210->async_unlink && size > 0) {
                temp = scnprintf(next, size, "\nunlink =\n");
@@ -508,21 +493,50 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf)
        return strlen(buf->output_buf);
 }
 
+/* count tds, get ep direction */
+static unsigned output_buf_tds_dir(char *buf, struct fotg210_hcd *fotg210,
+               struct fotg210_qh_hw *hw, struct fotg210_qh *qh, unsigned size)
+{
+       u32 scratch = hc32_to_cpup(fotg210, &hw->hw_info1);
+       struct fotg210_qtd *qtd;
+       char *type = "";
+       unsigned temp = 0;
+
+       /* count tds, get ep direction */
+       list_for_each_entry(qtd, &qh->qtd_list, qtd_list) {
+               temp++;
+               switch ((hc32_to_cpu(fotg210, qtd->hw_token) >> 8) & 0x03) {
+               case 0:
+                       type = "out";
+                       continue;
+               case 1:
+                       type = "in";
+                       continue;
+               }
+       }
+
+       return scnprintf(buf, size, "(%c%d ep%d%s [%d/%d] q%d p%d)",
+                       speed_char(scratch), scratch & 0x007f,
+                       (scratch >> 8) & 0x000f, type, qh->usecs,
+                       qh->c_usecs, temp, (scratch >> 16) & 0x7ff);
+}
+
 #define DBG_SCHED_LIMIT 64
 static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
 {
-       struct usb_hcd          *hcd;
-       struct fotg210_hcd              *fotg210;
-       unsigned long           flags;
-       union fotg210_shadow    p, *seen;
-       unsigned                temp, size, seen_count;
-       char                    *next;
-       unsigned                i;
-       __hc32                  tag;
-
-       seen = kmalloc(DBG_SCHED_LIMIT * sizeof(*seen), GFP_ATOMIC);
+       struct usb_hcd *hcd;
+       struct fotg210_hcd *fotg210;
+       unsigned long flags;
+       union fotg210_shadow p, *seen;
+       unsigned temp, size, seen_count;
+       char *next;
+       unsigned i;
+       __hc32 tag;
+
+       seen = kmalloc_array(DBG_SCHED_LIMIT, sizeof(*seen), GFP_ATOMIC);
        if (!seen)
                return 0;
+
        seen_count = 0;
 
        hcd = bus_to_hcd(buf->bus);
@@ -542,6 +556,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
                p = fotg210->pshadow[i];
                if (likely(!p.ptr))
                        continue;
+
                tag = Q_NEXT_TYPE(fotg210, fotg210->periodic[i]);
 
                temp = scnprintf(next, size, "%4d: ", i);
@@ -569,7 +584,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
                                                continue;
                                        if (p.qh->qh_next.ptr) {
                                                temp = scnprintf(next, size,
-                                                       " ...");
+                                                               " ...");
                                                size -= temp;
                                                next += temp;
                                        }
@@ -577,38 +592,9 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
                                }
                                /* show more info the first time around */
                                if (temp == seen_count) {
-                                       u32     scratch = hc32_to_cpup(fotg210,
-                                                       &hw->hw_info1);
-                                       struct fotg210_qtd      *qtd;
-                                       char            *type = "";
-
-                                       /* count tds, get ep direction */
-                                       temp = 0;
-                                       list_for_each_entry(qtd,
-                                                       &p.qh->qtd_list,
-                                                       qtd_list) {
-                                               temp++;
-                                               switch (0x03 & (hc32_to_cpu(
-                                                       fotg210,
-                                                       qtd->hw_token) >> 8)) {
-                                               case 0:
-                                                       type = "out";
-                                                       continue;
-                                               case 1:
-                                                       type = "in";
-                                                       continue;
-                                               }
-                                       }
-
-                                       temp = scnprintf(next, size,
-                                               "(%c%d ep%d%s "
-                                               "[%d/%d] q%d p%d)",
-                                               speed_char(scratch),
-                                               scratch & 0x007f,
-                                               (scratch >> 8) & 0x000f, type,
-                                               p.qh->usecs, p.qh->c_usecs,
-                                               temp,
-                                               0x7ff & (scratch >> 16));
+                                       temp = output_buf_tds_dir(next,
+                                                       fotg210, hw,
+                                                       p.qh, size);
 
                                        if (seen_count < DBG_SCHED_LIMIT)
                                                seen[seen_count++].qh = p.qh;
@@ -619,14 +605,14 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
                                break;
                        case Q_TYPE_FSTN:
                                temp = scnprintf(next, size,
-                                       " fstn-%8x/%p", p.fstn->hw_prev,
-                                       p.fstn);
+                                               " fstn-%8x/%p",
+                                               p.fstn->hw_prev, p.fstn);
                                tag = Q_NEXT_TYPE(fotg210, p.fstn->hw_next);
                                p = p.fstn->fstn_next;
                                break;
                        case Q_TYPE_ITD:
                                temp = scnprintf(next, size,
-                                       " itd/%p", p.itd);
+                                               " itd/%p", p.itd);
                                tag = Q_NEXT_TYPE(fotg210, p.itd->hw_next);
                                p = p.itd->itd_next;
                                break;
@@ -663,13 +649,13 @@ static const char *rh_state_string(struct fotg210_hcd *fotg210)
 
 static ssize_t fill_registers_buffer(struct debug_buffer *buf)
 {
-       struct usb_hcd          *hcd;
-       struct fotg210_hcd      *fotg210;
-       unsigned long           flags;
-       unsigned                temp, size, i;
-       char                    *next, scratch[80];
-       static const char       fmt[] = "%*s\n";
-       static const char       label[] = "";
+       struct usb_hcd *hcd;
+       struct fotg210_hcd *fotg210;
+       unsigned long flags;
+       unsigned temp, size, i;
+       char *next, scratch[80];
+       static const char fmt[] = "%*s\n";
+       static const char label[] = "";
 
        hcd = bus_to_hcd(buf->bus);
        fotg210 = hcd_to_fotg210(hcd);
@@ -680,26 +666,26 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
 
        if (!HCD_HW_ACCESSIBLE(hcd)) {
                size = scnprintf(next, size,
-                       "bus %s, device %s\n"
-                       "%s\n"
-                       "SUSPENDED(no register access)\n",
-                       hcd->self.controller->bus->name,
-                       dev_name(hcd->self.controller),
-                       hcd->product_desc);
+                               "bus %s, device %s\n"
+                               "%s\n"
+                               "SUSPENDED(no register access)\n",
+                               hcd->self.controller->bus->name,
+                               dev_name(hcd->self.controller),
+                               hcd->product_desc);
                goto done;
        }
 
        /* Capability Registers */
        i = HC_VERSION(fotg210, fotg210_readl(fotg210,
-                                             &fotg210->caps->hc_capbase));
+                       &fotg210->caps->hc_capbase));
        temp = scnprintf(next, size,
-               "bus %s, device %s\n"
-               "%s\n"
-               "EHCI %x.%02x, rh state %s\n",
-               hcd->self.controller->bus->name,
-               dev_name(hcd->self.controller),
-               hcd->product_desc,
-               i >> 8, i & 0x0ff, rh_state_string(fotg210));
+                       "bus %s, device %s\n"
+                       "%s\n"
+                       "EHCI %x.%02x, rh state %s\n",
+                       hcd->self.controller->bus->name,
+                       dev_name(hcd->self.controller),
+                       hcd->product_desc,
+                       i >> 8, i & 0x0ff, rh_state_string(fotg210));
        size -= temp;
        next += temp;
 
@@ -747,14 +733,14 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
 
 #ifdef FOTG210_STATS
        temp = scnprintf(next, size,
-               "irq normal %ld err %ld iaa %ld(lost %ld)\n",
-               fotg210->stats.normal, fotg210->stats.error, fotg210->stats.iaa,
-               fotg210->stats.lost_iaa);
+                       "irq normal %ld err %ld iaa %ld(lost %ld)\n",
+                       fotg210->stats.normal, fotg210->stats.error,
+                       fotg210->stats.iaa, fotg210->stats.lost_iaa);
        size -= temp;
        next += temp;
 
        temp = scnprintf(next, size, "complete %ld unlink %ld\n",
-               fotg210->stats.complete, fotg210->stats.unlink);
+                       fotg210->stats.complete, fotg210->stats.unlink);
        size -= temp;
        next += temp;
 #endif
@@ -765,8 +751,8 @@ done:
        return buf->alloc_size - size;
 }
 
-static struct debug_buffer *alloc_buffer(struct usb_bus *bus,
-                               ssize_t (*fill_func)(struct debug_buffer *))
+static struct debug_buffer
+*alloc_buffer(struct usb_bus *bus, ssize_t (*fill_func)(struct debug_buffer *))
 {
        struct debug_buffer *buf;
 
@@ -806,7 +792,7 @@ out:
 }
 
 static ssize_t debug_output(struct file *file, char __user *user_buf,
-                           size_t len, loff_t *offset)
+               size_t len, loff_t *offset)
 {
        struct debug_buffer *buf = file->private_data;
        int ret = 0;
@@ -822,7 +808,7 @@ static ssize_t debug_output(struct file *file, char __user *user_buf,
        mutex_unlock(&buf->mutex);
 
        ret = simple_read_from_buffer(user_buf, len, offset,
-                                     buf->output_buf, buf->count);
+                       buf->output_buf, buf->count);
 
 out:
        return ret;
@@ -850,6 +836,7 @@ static int debug_async_open(struct inode *inode, struct file *file)
 static int debug_periodic_open(struct inode *inode, struct file *file)
 {
        struct debug_buffer *buf;
+
        buf = alloc_buffer(inode->i_private, fill_periodic_buffer);
        if (!buf)
                return -ENOMEM;
@@ -862,7 +849,7 @@ static int debug_periodic_open(struct inode *inode, struct file *file)
 static int debug_registers_open(struct inode *inode, struct file *file)
 {
        file->private_data = alloc_buffer(inode->i_private,
-                                         fill_registers_buffer);
+                       fill_registers_buffer);
 
        return file->private_data ? 0 : -ENOMEM;
 }
@@ -872,20 +859,20 @@ static inline void create_debug_files(struct fotg210_hcd *fotg210)
        struct usb_bus *bus = &fotg210_to_hcd(fotg210)->self;
 
        fotg210->debug_dir = debugfs_create_dir(bus->bus_name,
-                                               fotg210_debug_root);
+                       fotg210_debug_root);
        if (!fotg210->debug_dir)
                return;
 
        if (!debugfs_create_file("async", S_IRUGO, fotg210->debug_dir, bus,
-                                               &debug_async_fops))
+                       &debug_async_fops))
                goto file_error;
 
        if (!debugfs_create_file("periodic", S_IRUGO, fotg210->debug_dir, bus,
-                                               &debug_periodic_fops))
+                       &debug_periodic_fops))
                goto file_error;
 
        if (!debugfs_create_file("registers", S_IRUGO, fotg210->debug_dir, bus,
-                                                   &debug_registers_fops))
+                       &debug_registers_fops))
                goto file_error;
 
        return;
@@ -899,10 +886,7 @@ static inline void remove_debug_files(struct fotg210_hcd *fotg210)
        debugfs_remove_recursive(fotg210->debug_dir);
 }
 
-/*-------------------------------------------------------------------------*/
-
-/*
- * handshake - spin reading hc until handshake completes or fails
+/* handshake - spin reading hc until handshake completes or fails
  * @ptr: address of hc register to be read
  * @mask: bits to look at in result of read
  * @done: value of those bits when handshake succeeds
@@ -919,9 +903,9 @@ static inline void remove_debug_files(struct fotg210_hcd *fotg210)
  * bridge shutdown:  shutting down the bridge before the devices using it.
  */
 static int handshake(struct fotg210_hcd *fotg210, void __iomem *ptr,
-                     u32 mask, u32 done, int usec)
+               u32 mask, u32 done, int usec)
 {
-       u32     result;
+       u32 result;
 
        do {
                result = fotg210_readl(fotg210, ptr);
@@ -936,13 +920,12 @@ static int handshake(struct fotg210_hcd *fotg210, void __iomem *ptr,
        return -ETIMEDOUT;
 }
 
-/*
- * Force HC to halt state from unknown (EHCI spec section 2.3).
+/* Force HC to halt state from unknown (EHCI spec section 2.3).
  * Must be called with interrupts enabled and the lock not held.
  */
 static int fotg210_halt(struct fotg210_hcd *fotg210)
 {
-       u32     temp;
+       u32 temp;
 
        spin_lock_irq(&fotg210->lock);
 
@@ -962,20 +945,20 @@ static int fotg210_halt(struct fotg210_hcd *fotg210)
        synchronize_irq(fotg210_to_hcd(fotg210)->irq);
 
        return handshake(fotg210, &fotg210->regs->status,
-                         STS_HALT, STS_HALT, 16 * 125);
+                       STS_HALT, STS_HALT, 16 * 125);
 }
 
-/*
- * Reset a non-running (STS_HALT == 1) controller.
+/* Reset a non-running (STS_HALT == 1) controller.
  * Must be called with interrupts enabled and the lock not held.
  */
 static int fotg210_reset(struct fotg210_hcd *fotg210)
 {
-       int     retval;
-       u32     command = fotg210_readl(fotg210, &fotg210->regs->command);
+       int retval;
+       u32 command = fotg210_readl(fotg210, &fotg210->regs->command);
 
        /* If the EHCI debug controller is active, special care must be
-        * taken before and after a host controller reset */
+        * taken before and after a host controller reset
+        */
        if (fotg210->debug && !dbgp_reset_prep(fotg210_to_hcd(fotg210)))
                fotg210->debug = NULL;
 
@@ -985,7 +968,7 @@ static int fotg210_reset(struct fotg210_hcd *fotg210)
        fotg210->rh_state = FOTG210_RH_HALTED;
        fotg210->next_statechange = jiffies;
        retval = handshake(fotg210, &fotg210->regs->command,
-                           CMD_RESET, 0, 250 * 1000);
+                       CMD_RESET, 0, 250 * 1000);
 
        if (retval)
                return retval;
@@ -998,13 +981,12 @@ static int fotg210_reset(struct fotg210_hcd *fotg210)
        return retval;
 }
 
-/*
- * Idle the controller (turn off the schedules).
+/* Idle the controller (turn off the schedules).
  * Must be called with interrupts enabled and the lock not held.
  */
 static void fotg210_quiesce(struct fotg210_hcd *fotg210)
 {
-       u32     temp;
+       u32 temp;
 
        if (fotg210->rh_state != FOTG210_RH_RUNNING)
                return;
@@ -1012,7 +994,7 @@ static void fotg210_quiesce(struct fotg210_hcd *fotg210)
        /* wait for any schedule enables/disables to take effect */
        temp = (fotg210->command << 10) & (STS_ASS | STS_PSS);
        handshake(fotg210, &fotg210->regs->status, STS_ASS | STS_PSS, temp,
-                 16 * 125);
+                       16 * 125);
 
        /* then disable anything that's still active */
        spin_lock_irq(&fotg210->lock);
@@ -1022,11 +1004,9 @@ static void fotg210_quiesce(struct fotg210_hcd *fotg210)
 
        /* hardware can take 16 microframes to turn off ... */
        handshake(fotg210, &fotg210->regs->status, STS_ASS | STS_PSS, 0,
-                 16 * 125);
+                       16 * 125);
 }
 
-/*-------------------------------------------------------------------------*/
-
 static void end_unlink_async(struct fotg210_hcd *fotg210);
 static void unlink_empty_async(struct fotg210_hcd *fotg210);
 static void fotg210_work(struct fotg210_hcd *fotg210);
@@ -1034,8 +1014,6 @@ static void start_unlink_intr(struct fotg210_hcd *fotg210,
                              struct fotg210_qh *qh);
 static void end_unlink_intr(struct fotg210_hcd *fotg210, struct fotg210_qh *qh);
 
-/*-------------------------------------------------------------------------*/
-
 /* Set a bit in the USBCMD register */
 static void fotg210_set_command_bit(struct fotg210_hcd *fotg210, u32 bit)
 {
@@ -1056,10 +1034,7 @@ static void fotg210_clear_command_bit(struct fotg210_hcd *fotg210, u32 bit)
        fotg210_readl(fotg210, &fotg210->regs->command);
 }
 
-/*-------------------------------------------------------------------------*/
-
-/*
- * EHCI timer support...  Now using hrtimers.
+/* EHCI timer support...  Now using hrtimers.
  *
  * Lots of different events are triggered from fotg210->hrtimer.  Whenever
  * the timer routine runs, it checks each possible event; events that are
@@ -1081,8 +1056,7 @@ static void fotg210_clear_command_bit(struct fotg210_hcd *fotg210, u32 bit)
  * allow for an expiration range of 1 ms.
  */
 
-/*
- * Delay lengths for the hrtimer event types.
+/* Delay lengths for the hrtimer event types.
  * Keep this list sorted by delay length, in the same order as
  * the event types indexed by enum fotg210_hrtimer_event in fotg210.h.
  */
@@ -1103,7 +1077,7 @@ static unsigned event_delays_ns[] = {
 static void fotg210_enable_event(struct fotg210_hcd *fotg210, unsigned event,
                bool resched)
 {
-       ktime_t         *timeout = &fotg210->hr_timeouts[event];
+       ktime_t *timeout = &fotg210->hr_timeouts[event];
 
        if (resched)
                *timeout = ktime_add(ktime_get(),
@@ -1122,7 +1096,7 @@ static void fotg210_enable_event(struct fotg210_hcd *fotg210, unsigned event,
 /* Poll the STS_ASS status bit; see when it agrees with CMD_ASE */
 static void fotg210_poll_ASS(struct fotg210_hcd *fotg210)
 {
-       unsigned        actual, want;
+       unsigned actual, want;
 
        /* Don't enable anything if the controller isn't running (e.g., died) */
        if (fotg210->rh_state != FOTG210_RH_RUNNING)
@@ -1136,7 +1110,7 @@ static void fotg210_poll_ASS(struct fotg210_hcd *fotg210)
                /* Poll again later, but give up after about 20 ms */
                if (fotg210->ASS_poll_count++ < 20) {
                        fotg210_enable_event(fotg210, FOTG210_HRTIMER_POLL_ASS,
-                                            true);
+                                       true);
                        return;
                }
                fotg210_dbg(fotg210, "Waited too long for the async schedule status (%x/%x), giving up\n",
@@ -1154,8 +1128,8 @@ static void fotg210_poll_ASS(struct fotg210_hcd *fotg210)
 
                        /* Turn off the schedule after a while */
                        fotg210_enable_event(fotg210,
-                                            FOTG210_HRTIMER_DISABLE_ASYNC,
-                                            true);
+                                       FOTG210_HRTIMER_DISABLE_ASYNC,
+                                       true);
                }
        }
 }
@@ -1170,7 +1144,7 @@ static void fotg210_disable_ASE(struct fotg210_hcd *fotg210)
 /* Poll the STS_PSS status bit; see when it agrees with CMD_PSE */
 static void fotg210_poll_PSS(struct fotg210_hcd *fotg210)
 {
-       unsigned        actual, want;
+       unsigned actual, want;
 
        /* Don't do anything if the controller isn't running (e.g., died) */
        if (fotg210->rh_state != FOTG210_RH_RUNNING)
@@ -1184,7 +1158,7 @@ static void fotg210_poll_PSS(struct fotg210_hcd *fotg210)
                /* Poll again later, but give up after about 20 ms */
                if (fotg210->PSS_poll_count++ < 20) {
                        fotg210_enable_event(fotg210, FOTG210_HRTIMER_POLL_PSS,
-                                            true);
+                                       true);
                        return;
                }
                fotg210_dbg(fotg210, "Waited too long for the periodic schedule status (%x/%x), giving up\n",
@@ -1202,8 +1176,8 @@ static void fotg210_poll_PSS(struct fotg210_hcd *fotg210)
 
                        /* Turn off the schedule after a while */
                        fotg210_enable_event(fotg210,
-                                            FOTG210_HRTIMER_DISABLE_PERIODIC,
-                                            true);
+                                       FOTG210_HRTIMER_DISABLE_PERIODIC,
+                                       true);
                }
        }
 }
@@ -1224,7 +1198,7 @@ static void fotg210_handle_controller_death(struct fotg210_hcd *fotg210)
                if (fotg210->died_poll_count++ < 5) {
                        /* Try again later */
                        fotg210_enable_event(fotg210,
-                                            FOTG210_HRTIMER_POLL_DEAD, true);
+                                       FOTG210_HRTIMER_POLL_DEAD, true);
                        return;
                }
                fotg210_warn(fotg210, "Waited too long for the controller to stop, giving up\n");
@@ -1243,7 +1217,7 @@ static void fotg210_handle_controller_death(struct fotg210_hcd *fotg210)
 /* Handle unlinked interrupt QHs once they are gone from the hardware */
 static void fotg210_handle_intr_unlinks(struct fotg210_hcd *fotg210)
 {
-       bool            stopped = (fotg210->rh_state < FOTG210_RH_RUNNING);
+       bool stopped = (fotg210->rh_state < FOTG210_RH_RUNNING);
 
        /*
         * Process all the QHs on the intr_unlink list that were added
@@ -1254,7 +1228,7 @@ static void fotg210_handle_intr_unlinks(struct fotg210_hcd *fotg210)
         */
        fotg210->intr_unlinking = true;
        while (fotg210->intr_unlink) {
-               struct fotg210_qh       *qh = fotg210->intr_unlink;
+               struct fotg210_qh *qh = fotg210->intr_unlink;
 
                if (!stopped && qh->unlink_cycle == fotg210->intr_unlink_cycle)
                        break;
@@ -1266,7 +1240,7 @@ static void fotg210_handle_intr_unlinks(struct fotg210_hcd *fotg210)
        /* Handle remaining entries later */
        if (fotg210->intr_unlink) {
                fotg210_enable_event(fotg210, FOTG210_HRTIMER_UNLINK_INTR,
-                                    true);
+                               true);
                ++fotg210->intr_unlink_cycle;
        }
        fotg210->intr_unlinking = false;
@@ -1288,7 +1262,7 @@ static void start_free_itds(struct fotg210_hcd *fotg210)
 /* Wait for controller to stop using old iTDs and siTDs */
 static void end_free_itds(struct fotg210_hcd *fotg210)
 {
-       struct fotg210_itd              *itd, *n;
+       struct fotg210_itd *itd, *n;
 
        if (fotg210->rh_state < FOTG210_RH_RUNNING)
                fotg210->last_itd_to_free = NULL;
@@ -1339,7 +1313,7 @@ static void fotg210_iaa_watchdog(struct fotg210_hcd *fotg210)
                if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
                        COUNT(fotg210->stats.lost_iaa);
                        fotg210_writel(fotg210, STS_IAA,
-                                      &fotg210->regs->status);
+                                       &fotg210->regs->status);
                }
 
                fotg210_dbg(fotg210, "IAA watchdog: status %x cmd %x\n",
@@ -1355,7 +1329,7 @@ static void turn_on_io_watchdog(struct fotg210_hcd *fotg210)
        /* Not needed if the controller isn't running or it's already enabled */
        if (fotg210->rh_state != FOTG210_RH_RUNNING ||
                        (fotg210->enabled_hrtimer_events &
-                               BIT(FOTG210_HRTIMER_IO_WATCHDOG)))
+                       BIT(FOTG210_HRTIMER_IO_WATCHDOG)))
                return;
 
        /*
@@ -1365,12 +1339,11 @@ static void turn_on_io_watchdog(struct fotg210_hcd *fotg210)
        if (fotg210->isoc_count > 0 || (fotg210->need_io_watchdog &&
                        fotg210->async_count + fotg210->intr_count > 0))
                fotg210_enable_event(fotg210, FOTG210_HRTIMER_IO_WATCHDOG,
-                                    true);
+                               true);
 }
 
 
-/*
- * Handler functions for the hrtimer event types.
+/* Handler functions for the hrtimer event types.
  * Keep this array in the same order as the event types indexed by
  * enum fotg210_hrtimer_event in fotg210.h.
  */
@@ -1391,10 +1364,10 @@ static enum hrtimer_restart fotg210_hrtimer_func(struct hrtimer *t)
 {
        struct fotg210_hcd *fotg210 =
                        container_of(t, struct fotg210_hcd, hrtimer);
-       ktime_t         now;
-       unsigned long   events;
-       unsigned long   flags;
-       unsigned        e;
+       ktime_t now;
+       unsigned long events;
+       unsigned long flags;
+       unsigned e;
 
        spin_lock_irqsave(&fotg210->lock, flags);
 
@@ -1418,50 +1391,37 @@ static enum hrtimer_restart fotg210_hrtimer_func(struct hrtimer *t)
        return HRTIMER_NORESTART;
 }
 
-/*-------------------------------------------------------------------------*/
-
-#define fotg210_bus_suspend    NULL
-#define fotg210_bus_resume     NULL
+#define fotg210_bus_suspend NULL
+#define fotg210_bus_resume NULL
 
-/*-------------------------------------------------------------------------*/
-
-static int check_reset_complete(
-       struct fotg210_hcd      *fotg210,
-       int             index,
-       u32 __iomem     *status_reg,
-       int             port_status
-) {
+static int check_reset_complete(struct fotg210_hcd *fotg210, int index,
+               u32 __iomem *status_reg, int port_status)
+{
        if (!(port_status & PORT_CONNECT))
                return port_status;
 
        /* if reset finished and it's still not enabled -- handoff */
-       if (!(port_status & PORT_PE)) {
+       if (!(port_status & PORT_PE))
                /* with integrated TT, there's nobody to hand it to! */
-               fotg210_dbg(fotg210,
-                       "Failed to enable port %d on root hub TT\n",
-                       index+1);
-               return port_status;
-       } else {
+               fotg210_dbg(fotg210, "Failed to enable port %d on root hub TT\n",
+                               index + 1);
+       else
                fotg210_dbg(fotg210, "port %d reset complete, port enabled\n",
-                       index + 1);
-       }
+                               index + 1);
 
        return port_status;
 }
 
-/*-------------------------------------------------------------------------*/
-
 
 /* build "status change" packet (one or two bytes) from HC registers */
 
-static int
-fotg210_hub_status_data(struct usb_hcd *hcd, char *buf)
+static int fotg210_hub_status_data(struct usb_hcd *hcd, char *buf)
 {
-       struct fotg210_hcd      *fotg210 = hcd_to_fotg210(hcd);
-       u32             temp, status;
-       u32             mask;
-       int             retval = 1;
-       unsigned long   flags;
+       struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+       u32 temp, status;
+       u32 mask;
+       int retval = 1;
+       unsigned long flags;
 
        /* init status to no-changes */
        buf[0] = 0;
@@ -1488,9 +1448,9 @@ fotg210_hub_status_data(struct usb_hcd *hcd, char *buf)
         * controller by the user.
         */
 
-       if ((temp & mask) != 0 || test_bit(0, &fotg210->port_c_suspend)
-                       || (fotg210->reset_done[0] && time_after_eq(
-                               jiffies, fotg210->reset_done[0]))) {
+       if ((temp & mask) != 0 || test_bit(0, &fotg210->port_c_suspend) ||
+                       (fotg210->reset_done[0] &&
+                       time_after_eq(jiffies, fotg210->reset_done[0]))) {
                buf[0] |= 1 << 1;
                status = STS_PCD;
        }
@@ -1499,15 +1459,11 @@ fotg210_hub_status_data(struct usb_hcd *hcd, char *buf)
        return status ? retval : 0;
 }
 
-/*-------------------------------------------------------------------------*/
-
-static void
-fotg210_hub_descriptor(
-       struct fotg210_hcd              *fotg210,
-       struct usb_hub_descriptor       *desc
-) {
-       int             ports = HCS_N_PORTS(fotg210->hcs_params);
-       u16             temp;
+static void fotg210_hub_descriptor(struct fotg210_hcd *fotg210,
+               struct usb_hub_descriptor *desc)
+{
+       int ports = HCS_N_PORTS(fotg210->hcs_params);
+       u16 temp;
 
        desc->bDescriptorType = USB_DT_HUB;
        desc->bPwrOn2PwrGood = 10;      /* fotg210 1.0, 2.3.9 says 20ms max */
@@ -1526,23 +1482,16 @@ fotg210_hub_descriptor(
        desc->wHubCharacteristics = cpu_to_le16(temp);
 }
 
-/*-------------------------------------------------------------------------*/
-
-static int fotg210_hub_control(
-       struct usb_hcd  *hcd,
-       u16             typeReq,
-       u16             wValue,
-       u16             wIndex,
-       char            *buf,
-       u16             wLength
-) {
-       struct fotg210_hcd      *fotg210 = hcd_to_fotg210(hcd);
-       int             ports = HCS_N_PORTS(fotg210->hcs_params);
-       u32 __iomem     *status_reg = &fotg210->regs->port_status;
-       u32             temp, temp1, status;
-       unsigned long   flags;
-       int             retval = 0;
-       unsigned        selector;
+static int fotg210_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+               u16 wIndex, char *buf, u16 wLength)
+{
+       struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+       int ports = HCS_N_PORTS(fotg210->hcs_params);
+       u32 __iomem *status_reg = &fotg210->regs->port_status;
+       u32 temp, temp1, status;
+       unsigned long flags;
+       int retval = 0;
+       unsigned selector;
 
        /*
         * FIXME:  support SetPortFeatures USB_PORT_FEAT_INDICATOR.
@@ -1605,7 +1554,7 @@ static int fotg210_hub_control(
                        break;
                case USB_PORT_FEAT_C_OVER_CURRENT:
                        fotg210_writel(fotg210, temp | OTGISR_OVC,
-                                      &fotg210->regs->otgisr);
+                                       &fotg210->regs->otgisr);
                        break;
                case USB_PORT_FEAT_C_RESET:
                        /* GetPortStatus clears reset */
@@ -1617,7 +1566,7 @@ static int fotg210_hub_control(
                break;
        case GetHubDescriptor:
                fotg210_hub_descriptor(fotg210, (struct usb_hub_descriptor *)
-                       buf);
+                               buf);
                break;
        case GetHubStatus:
                /* no hub-wide feature/status flags */
@@ -1663,16 +1612,16 @@ static int fotg210_hub_control(
 
                                /* stop resume signaling */
                                temp = fotg210_readl(fotg210, status_reg);
-                               fotg210_writel(fotg210,
-                                       temp & ~(PORT_RWC_BITS | PORT_RESUME),
-                                       status_reg);
+                               fotg210_writel(fotg210, temp &
+                                               ~(PORT_RWC_BITS | PORT_RESUME),
+                                               status_reg);
                                clear_bit(wIndex, &fotg210->resuming_ports);
                                retval = handshake(fotg210, status_reg,
-                                          PORT_RESUME, 0, 2000 /* 2msec */);
+                                               PORT_RESUME, 0, 2000);/* 2ms */
                                if (retval != 0) {
                                        fotg210_err(fotg210,
-                                               "port %d resume error %d\n",
-                                               wIndex + 1, retval);
+                                                       "port %d resume error %d\n",
+                                                       wIndex + 1, retval);
                                        goto error;
                                }
                                temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
@@ -1680,17 +1629,16 @@ static int fotg210_hub_control(
                }
 
                /* whoever resets must GetPortStatus to complete it!! */
-               if ((temp & PORT_RESET)
-                               && time_after_eq(jiffies,
-                                       fotg210->reset_done[wIndex])) {
+               if ((temp & PORT_RESET) && time_after_eq(jiffies,
+                               fotg210->reset_done[wIndex])) {
                        status |= USB_PORT_STAT_C_RESET << 16;
                        fotg210->reset_done[wIndex] = 0;
                        clear_bit(wIndex, &fotg210->resuming_ports);
 
                        /* force reset to complete */
                        fotg210_writel(fotg210,
-                                      temp & ~(PORT_RWC_BITS | PORT_RESET),
-                                      status_reg);
+                                       temp & ~(PORT_RWC_BITS | PORT_RESET),
+                                       status_reg);
                        /* REVISIT:  some hardware needs 550+ usec to clear
                         * this bit; seems too long to spin routinely...
                         */
@@ -1698,7 +1646,7 @@ static int fotg210_hub_control(
                                        PORT_RESET, 0, 1000);
                        if (retval != 0) {
                                fotg210_err(fotg210, "port %d reset error %d\n",
-                                       wIndex + 1, retval);
+                                               wIndex + 1, retval);
                                goto error;
                        }
 
@@ -1718,7 +1666,7 @@ static int fotg210_hub_control(
                        temp &= ~PORT_RWC_BITS;
                        fotg210_writel(fotg210, temp, status_reg);
                        fotg210_dbg(fotg210, "port %d --> companion\n",
-                                   wIndex + 1);
+                                       wIndex + 1);
                        temp = fotg210_readl(fotg210, status_reg);
                }
 
@@ -1788,7 +1736,7 @@ static int fotg210_hub_control(
                         * mode if we have hostpc feature
                         */
                        fotg210_writel(fotg210, temp | PORT_SUSPEND,
-                                      status_reg);
+                                       status_reg);
                        set_bit(wIndex, &fotg210->suspended_ports);
                        break;
                case USB_PORT_FEAT_RESET:
@@ -1866,9 +1814,8 @@ static int __maybe_unused fotg210_port_handed_over(struct usb_hcd *hcd,
 {
        return 0;
 }
-/*-------------------------------------------------------------------------*/
-/*
- * There's basically three types of memory:
+
+/* There's basically three types of memory:
  *     - data used only by the HCD ... kmalloc is fine
  *     - async and periodic schedules, shared by HC and HCD ... these
  *       need to use dma_pool or dma_alloc_coherent
@@ -1878,12 +1825,9 @@ static int __maybe_unused fotg210_port_handed_over(struct usb_hcd *hcd,
  * No memory seen by this driver is pageable.
  */
 
-/*-------------------------------------------------------------------------*/
-
 /* Allocate the key transfer structures from the previously allocated pool */
-
 static inline void fotg210_qtd_init(struct fotg210_hcd *fotg210,
-                                   struct fotg210_qtd *qtd, dma_addr_t dma)
+               struct fotg210_qtd *qtd, dma_addr_t dma)
 {
        memset(qtd, 0, sizeof(*qtd));
        qtd->qtd_dma = dma;
@@ -1894,10 +1838,10 @@ static inline void fotg210_qtd_init(struct fotg210_hcd *fotg210,
 }
 
 static struct fotg210_qtd *fotg210_qtd_alloc(struct fotg210_hcd *fotg210,
-                                            gfp_t flags)
+               gfp_t flags)
 {
-       struct fotg210_qtd              *qtd;
-       dma_addr_t              dma;
+       struct fotg210_qtd *qtd;
+       dma_addr_t dma;
 
        qtd = dma_pool_alloc(fotg210->qtd_pool, flags, &dma);
        if (qtd != NULL)
@@ -1907,7 +1851,7 @@ static struct fotg210_qtd *fotg210_qtd_alloc(struct fotg210_hcd *fotg210,
 }
 
 static inline void fotg210_qtd_free(struct fotg210_hcd *fotg210,
-                                   struct fotg210_qtd *qtd)
+               struct fotg210_qtd *qtd)
 {
        dma_pool_free(fotg210->qtd_pool, qtd, qtd->qtd_dma);
 }
@@ -1927,10 +1871,10 @@ static void qh_destroy(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
 }
 
 static struct fotg210_qh *fotg210_qh_alloc(struct fotg210_hcd *fotg210,
-                                          gfp_t flags)
+               gfp_t flags)
 {
-       struct fotg210_qh               *qh;
-       dma_addr_t              dma;
+       struct fotg210_qh *qh;
+       dma_addr_t dma;
 
        qh = kzalloc(sizeof(*qh), GFP_ATOMIC);
        if (!qh)
@@ -1958,8 +1902,6 @@ fail:
        return NULL;
 }
 
-/*-------------------------------------------------------------------------*/
-
 /* The queue heads and transfer descriptors are managed from pools tied
  * to each of the "per device" structures.
  * This is the initialisation and cleanup code.
@@ -1976,23 +1918,19 @@ static void fotg210_mem_cleanup(struct fotg210_hcd *fotg210)
        fotg210->dummy = NULL;
 
        /* DMA consistent memory and pools */
-       if (fotg210->qtd_pool)
-               dma_pool_destroy(fotg210->qtd_pool);
+       dma_pool_destroy(fotg210->qtd_pool);
        fotg210->qtd_pool = NULL;
 
-       if (fotg210->qh_pool) {
-               dma_pool_destroy(fotg210->qh_pool);
-               fotg210->qh_pool = NULL;
-       }
+       dma_pool_destroy(fotg210->qh_pool);
+       fotg210->qh_pool = NULL;
 
-       if (fotg210->itd_pool)
-               dma_pool_destroy(fotg210->itd_pool);
+       dma_pool_destroy(fotg210->itd_pool);
        fotg210->itd_pool = NULL;
 
        if (fotg210->periodic)
                dma_free_coherent(fotg210_to_hcd(fotg210)->self.controller,
-                       fotg210->periodic_size * sizeof(u32),
-                       fotg210->periodic, fotg210->periodic_dma);
+                               fotg210->periodic_size * sizeof(u32),
+                               fotg210->periodic, fotg210->periodic_dma);
        fotg210->periodic = NULL;
 
        /* shadow periodic table */
@@ -2039,8 +1977,8 @@ static int fotg210_mem_init(struct fotg210_hcd *fotg210, gfp_t flags)
        /* Hardware periodic table */
        fotg210->periodic = (__le32 *)
                dma_alloc_coherent(fotg210_to_hcd(fotg210)->self.controller,
-                       fotg210->periodic_size * sizeof(__le32),
-                       &fotg210->periodic_dma, 0);
+                               fotg210->periodic_size * sizeof(__le32),
+                               &fotg210->periodic_dma, 0);
        if (fotg210->periodic == NULL)
                goto fail;
 
@@ -2049,7 +1987,7 @@ static int fotg210_mem_init(struct fotg210_hcd *fotg210, gfp_t flags)
 
        /* software shadow of hardware table */
        fotg210->pshadow = kcalloc(fotg210->periodic_size, sizeof(void *),
-                                  flags);
+                       flags);
        if (fotg210->pshadow != NULL)
                return 0;
 
@@ -2058,9 +1996,7 @@ fail:
        fotg210_mem_cleanup(fotg210);
        return -ENOMEM;
 }
-/*-------------------------------------------------------------------------*/
-/*
- * EHCI hardware queue manipulation ... the core.  QH/QTD manipulation.
+/* EHCI hardware queue manipulation ... the core.  QH/QTD manipulation.
  *
  * Control, bulk, and interrupt traffic all use "qh" lists.  They list "qtd"
  * entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned
@@ -2077,16 +2013,12 @@ fail:
  * buffer low/full speed data so the host collects it at high speed.
  */
 
-/*-------------------------------------------------------------------------*/
-
 /* fill a qtd, returning how much of the buffer we were able to queue up */
-
-static int
-qtd_fill(struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd, dma_addr_t buf,
-                 size_t len, int token, int maxpacket)
+static int qtd_fill(struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd,
+               dma_addr_t buf, size_t len, int token, int maxpacket)
 {
-       int     i, count;
-       u64     addr = buf;
+       int i, count;
+       u64 addr = buf;
 
        /* one buffer entry per 4K ... first might be short or unaligned */
        qtd->hw_buf[0] = cpu_to_hc32(fotg210, (u32)addr);
@@ -2121,11 +2053,8 @@ qtd_fill(struct fotg210_hcd *fotg210, struct fotg210_qtd *qtd, dma_addr_t buf,
        return count;
 }
 
-/*-------------------------------------------------------------------------*/
-
-static inline void
-qh_update(struct fotg210_hcd *fotg210, struct fotg210_qh *qh,
-         struct fotg210_qtd *qtd)
+static inline void qh_update(struct fotg210_hcd *fotg210,
+               struct fotg210_qh *qh, struct fotg210_qtd *qtd)
 {
        struct fotg210_qh_hw *hw = qh->hw;
 
@@ -2141,7 +2070,7 @@ qh_update(struct fotg210_hcd *fotg210, struct fotg210_qh *qh,
         * ever clear it.
         */
        if (!(hw->hw_info1 & cpu_to_hc32(fotg210, QH_TOGGLE_CTL))) {
-               unsigned        is_out, epnum;
+               unsigned is_out, epnum;
 
                is_out = qh->is_out;
                epnum = (hc32_to_cpup(fotg210, &hw->hw_info1) >> 8) & 0x0f;
@@ -2158,8 +2087,7 @@ qh_update(struct fotg210_hcd *fotg210, struct fotg210_qh *qh,
  * overlay, so qh->hw_token wrongly becomes inactive/halted), only fault
  * recovery (including urb dequeue) would need software changes to a QH...
  */
-static void
-qh_refresh(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
+static void qh_refresh(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
 {
        struct fotg210_qtd *qtd;
 
@@ -2185,16 +2113,14 @@ qh_refresh(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
                qh_update(fotg210, qh, qtd);
 }
 
-/*-------------------------------------------------------------------------*/
-
 static void qh_link_async(struct fotg210_hcd *fotg210, struct fotg210_qh *qh);
 
 static void fotg210_clear_tt_buffer_complete(struct usb_hcd *hcd,
                struct usb_host_endpoint *ep)
 {
-       struct fotg210_hcd              *fotg210 = hcd_to_fotg210(hcd);
-       struct fotg210_qh               *qh = ep->hcpriv;
-       unsigned long           flags;
+       struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+       struct fotg210_qh *qh = ep->hcpriv;
+       unsigned long flags;
 
        spin_lock_irqsave(&fotg210->lock, flags);
        qh->clearing_tt = 0;
@@ -2205,8 +2131,7 @@ static void fotg210_clear_tt_buffer_complete(struct usb_hcd *hcd,
 }
 
 static void fotg210_clear_tt_buffer(struct fotg210_hcd *fotg210,
-                                   struct fotg210_qh *qh,
-                                   struct urb *urb, u32 token)
+               struct fotg210_qh *qh, struct urb *urb, u32 token)
 {
 
        /* If an async split transaction gets an error or is unlinked,
@@ -2217,27 +2142,24 @@ static void fotg210_clear_tt_buffer(struct fotg210_hcd *fotg210,
         */
        if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) {
                struct usb_device *tt = urb->dev->tt->hub;
+
                dev_dbg(&tt->dev,
-                       "clear tt buffer port %d, a%d ep%d t%08x\n",
-                       urb->dev->ttport, urb->dev->devnum,
-                       usb_pipeendpoint(urb->pipe), token);
+                               "clear tt buffer port %d, a%d ep%d t%08x\n",
+                               urb->dev->ttport, urb->dev->devnum,
+                               usb_pipeendpoint(urb->pipe), token);
 
                if (urb->dev->tt->hub !=
-                   fotg210_to_hcd(fotg210)->self.root_hub) {
+                               fotg210_to_hcd(fotg210)->self.root_hub) {
                        if (usb_hub_clear_tt_buffer(urb) == 0)
                                qh->clearing_tt = 1;
                }
        }
 }
 
-static int qtd_copy_status(
-       struct fotg210_hcd *fotg210,
-       struct urb *urb,
-       size_t length,
-       u32 token
-)
+static int qtd_copy_status(struct fotg210_hcd *fotg210, struct urb *urb,
+               size_t length, u32 token)
 {
-       int     status = -EINPROGRESS;
+       int status = -EINPROGRESS;
 
        /* count IN/OUT bytes, not SETUP (even short packets) */
        if (likely(QTD_PID(token) != 2))
@@ -2274,32 +2196,32 @@ static int qtd_copy_status(
                } else if (token & QTD_STS_XACT) {
                        /* timeout, bad CRC, wrong PID, etc */
                        fotg210_dbg(fotg210, "devpath %s ep%d%s 3strikes\n",
-                               urb->dev->devpath,
-                               usb_pipeendpoint(urb->pipe),
-                               usb_pipein(urb->pipe) ? "in" : "out");
+                                       urb->dev->devpath,
+                                       usb_pipeendpoint(urb->pipe),
+                                       usb_pipein(urb->pipe) ? "in" : "out");
                        status = -EPROTO;
                } else {        /* unknown */
                        status = -EPROTO;
                }
 
                fotg210_dbg(fotg210,
-                       "dev%d ep%d%s qtd token %08x --> status %d\n",
-                       usb_pipedevice(urb->pipe),
-                       usb_pipeendpoint(urb->pipe),
-                       usb_pipein(urb->pipe) ? "in" : "out",
-                       token, status);
+                               "dev%d ep%d%s qtd token %08x --> status %d\n",
+                               usb_pipedevice(urb->pipe),
+                               usb_pipeendpoint(urb->pipe),
+                               usb_pipein(urb->pipe) ? "in" : "out",
+                               token, status);
        }
 
        return status;
 }
 
-static void
-fotg210_urb_done(struct fotg210_hcd *fotg210, struct urb *urb, int status)
+static void fotg210_urb_done(struct fotg210_hcd *fotg210, struct urb *urb,
+               int status)
 __releases(fotg210->lock)
 __acquires(fotg210->lock)
 {
        if (likely(urb->hcpriv != NULL)) {
-               struct fotg210_qh       *qh = (struct fotg210_qh *) urb->hcpriv;
+               struct fotg210_qh *qh = (struct fotg210_qh *) urb->hcpriv;
 
                /* S-mask in a QH means it's an interrupt urb */
                if ((qh->hw->hw_info2 & cpu_to_hc32(fotg210, QH_SMASK)) != 0) {
@@ -2320,12 +2242,12 @@ __acquires(fotg210->lock)
 
 #ifdef FOTG210_URB_TRACE
        fotg210_dbg(fotg210,
-               "%s %s urb %p ep%d%s status %d len %d/%d\n",
-               __func__, urb->dev->devpath, urb,
-               usb_pipeendpoint(urb->pipe),
-               usb_pipein(urb->pipe) ? "in" : "out",
-               status,
-               urb->actual_length, urb->transfer_buffer_length);
+                       "%s %s urb %p ep%d%s status %d len %d/%d\n",
+                       __func__, urb->dev->devpath, urb,
+                       usb_pipeendpoint(urb->pipe),
+                       usb_pipein(urb->pipe) ? "in" : "out",
+                       status,
+                       urb->actual_length, urb->transfer_buffer_length);
 #endif
 
        /* complete() can reenter this HCD */
@@ -2337,21 +2259,20 @@ __acquires(fotg210->lock)
 
 static int qh_schedule(struct fotg210_hcd *fotg210, struct fotg210_qh *qh);
 
-/*
- * Process and free completed qtds for a qh, returning URBs to drivers.
+/* Process and free completed qtds for a qh, returning URBs to drivers.
  * Chases up to qh->hw_current.  Returns number of completions called,
  * indicating how much "real" work we did.
  */
-static unsigned
-qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
+static unsigned qh_completions(struct fotg210_hcd *fotg210,
+               struct fotg210_qh *qh)
 {
-       struct fotg210_qtd              *last, *end = qh->dummy;
-       struct list_head        *entry, *tmp;
-       int                     last_status;
-       int                     stopped;
-       unsigned                count = 0;
-       u8                      state;
-       struct fotg210_qh_hw    *hw = qh->hw;
+       struct fotg210_qtd *last, *end = qh->dummy;
+       struct list_head *entry, *tmp;
+       int last_status;
+       int stopped;
+       unsigned count = 0;
+       u8 state;
+       struct fotg210_qh_hw *hw = qh->hw;
 
        if (unlikely(list_empty(&qh->qtd_list)))
                return count;
@@ -2370,7 +2291,7 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
        qh->qh_state = QH_STATE_COMPLETING;
        stopped = (state == QH_STATE_IDLE);
 
- rescan:
+rescan:
        last = NULL;
        last_status = -EINPROGRESS;
        qh->needs_rescan = 0;
@@ -2381,9 +2302,9 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
         * if queue is stopped, handles unlinks.
         */
        list_for_each_safe(entry, tmp, &qh->qtd_list) {
-               struct fotg210_qtd      *qtd;
-               struct urb      *urb;
-               u32             token = 0;
+               struct fotg210_qtd *qtd;
+               struct urb *urb;
+               u32 token = 0;
 
                qtd = list_entry(entry, struct fotg210_qtd, qtd_list);
                urb = qtd->urb;
@@ -2392,7 +2313,7 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
                if (last) {
                        if (likely(last->urb != urb)) {
                                fotg210_urb_done(fotg210, last->urb,
-                                                last_status);
+                                               last_status);
                                count++;
                                last_status = -EINPROGRESS;
                        }
@@ -2409,20 +2330,17 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
                token = hc32_to_cpu(fotg210, qtd->hw_token);
 
                /* always clean up qtds the hc de-activated */
- retry_xacterr:
+retry_xacterr:
                if ((token & QTD_STS_ACTIVE) == 0) {
 
                        /* Report Data Buffer Error: non-fatal but useful */
                        if (token & QTD_STS_DBE)
                                fotg210_dbg(fotg210,
                                        "detected DataBufferErr for urb %p ep%d%s len %d, qtd %p [qh %p]\n",
-                                       urb,
-                                       usb_endpoint_num(&urb->ep->desc),
+                                       urb, usb_endpoint_num(&urb->ep->desc),
                                        usb_endpoint_dir_in(&urb->ep->desc)
                                                ? "in" : "out",
-                                       urb->transfer_buffer_length,
-                                       qtd,
-                                       qh);
+                                       urb->transfer_buffer_length, qtd, qh);
 
                        /* on STALL, error, and short reads this urb must
                         * complete and all its qtds must be recycled.
@@ -2433,12 +2351,14 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
                                 * reach the software xacterr limit
                                 */
                                if ((token & QTD_STS_XACT) &&
-                                       QTD_CERR(token) == 0 &&
-                                       ++qh->xacterrs < QH_XACTERR_MAX &&
-                                       !urb->unlinked) {
+                                               QTD_CERR(token) == 0 &&
+                                               ++qh->xacterrs < QH_XACTERR_MAX &&
+                                               !urb->unlinked) {
                                        fotg210_dbg(fotg210,
-       "detected XactErr len %zu/%zu retry %d\n",
-       qtd->length - QTD_LENGTH(token), qtd->length, qh->xacterrs);
+                                               "detected XactErr len %zu/%zu retry %d\n",
+                                               qtd->length - QTD_LENGTH(token),
+                                               qtd->length,
+                                               qh->xacterrs);
 
                                        /* reset the token in the qtd and the
                                         * qh overlay (which still contains
@@ -2466,9 +2386,9 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
                         * URB_SHORT_NOT_OK was set so the driver submitting
                         * the urbs could clean it up.
                         */
-                       } else if (IS_SHORT_READ(token)
-                                       && !(qtd->hw_alt_next
-                                               & FOTG210_LIST_END(fotg210))) {
+                       } else if (IS_SHORT_READ(token) &&
+                                       !(qtd->hw_alt_next &
+                                       FOTG210_LIST_END(fotg210))) {
                                stopped = 1;
                        }
 
@@ -2492,9 +2412,9 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
                                continue;
 
                        /* qh unlinked; token in overlay may be most current */
-                       if (state == QH_STATE_IDLE
-                                       && cpu_to_hc32(fotg210, qtd->qtd_dma)
-                                               == hw->hw_current) {
+                       if (state == QH_STATE_IDLE &&
+                                       cpu_to_hc32(fotg210, qtd->qtd_dma)
+                                       == hw->hw_current) {
                                token = hc32_to_cpu(fotg210, hw->hw_token);
 
                                /* An unlink may leave an incomplete
@@ -2502,7 +2422,7 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
                                 * We have to clear it.
                                 */
                                fotg210_clear_tt_buffer(fotg210, qh, urb,
-                                                       token);
+                                               token);
                        }
                }
 
@@ -2516,9 +2436,9 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
                if (last_status == -EINPROGRESS) {
                        last_status = qtd_copy_status(fotg210, urb,
                                        qtd->length, token);
-                       if (last_status == -EREMOTEIO
-                                       && (qtd->hw_alt_next
-                                               & FOTG210_LIST_END(fotg210)))
+                       if (last_status == -EREMOTEIO &&
+                                       (qtd->hw_alt_next &
+                                       FOTG210_LIST_END(fotg210)))
                                last_status = -EINPROGRESS;
 
                        /* As part of low/full-speed endpoint-halt processing
@@ -2537,7 +2457,7 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
                                 */
                                if (last_status != -EPIPE)
                                        fotg210_clear_tt_buffer(fotg210, qh,
-                                                               urb, token);
+                                                       urb, token);
                        }
                }
 
@@ -2615,26 +2535,21 @@ qh_completions(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
        return count;
 }
 
-/*-------------------------------------------------------------------------*/
-
 /* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
 #define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
 /* ... and packet size, for any kind of endpoint descriptor */
 #define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
 
-/*
- * reverse of qh_urb_transaction:  free a list of TDs.
+/* reverse of qh_urb_transaction:  free a list of TDs.
  * used for cleanup after errors, before HC sees an URB's TDs.
  */
-static void qtd_list_free(
-       struct fotg210_hcd              *fotg210,
-       struct urb              *urb,
-       struct list_head        *qtd_list
-) {
-       struct list_head        *entry, *temp;
+static void qtd_list_free(struct fotg210_hcd *fotg210, struct urb *urb,
+               struct list_head *qtd_list)
+{
+       struct list_head *entry, *temp;
 
        list_for_each_safe(entry, temp, qtd_list) {
-               struct fotg210_qtd      *qtd;
+               struct fotg210_qtd *qtd;
 
                qtd = list_entry(entry, struct fotg210_qtd, qtd_list);
                list_del(&qtd->qtd_list);
@@ -2642,23 +2557,18 @@ static void qtd_list_free(
        }
 }
 
-/*
- * create a list of filled qtds for this URB; won't link into qh.
+/* create a list of filled qtds for this URB; won't link into qh.
  */
-static struct list_head *
-qh_urb_transaction(
-       struct fotg210_hcd              *fotg210,
-       struct urb              *urb,
-       struct list_head        *head,
-       gfp_t                   flags
-) {
-       struct fotg210_qtd              *qtd, *qtd_prev;
-       dma_addr_t              buf;
-       int                     len, this_sg_len, maxpacket;
-       int                     is_input;
-       u32                     token;
-       int                     i;
-       struct scatterlist      *sg;
+static struct list_head *qh_urb_transaction(struct fotg210_hcd *fotg210,
+               struct urb *urb, struct list_head *head, gfp_t flags)
+{
+       struct fotg210_qtd *qtd, *qtd_prev;
+       dma_addr_t buf;
+       int len, this_sg_len, maxpacket;
+       int is_input;
+       u32 token;
+       int i;
+       struct scatterlist *sg;
 
        /*
         * URBs map to sequences of QTDs:  one logical transaction
@@ -2768,8 +2678,8 @@ qh_urb_transaction(
         * have the alt_next mechanism keep the queue running after the
         * last data qtd (the only one, for control and most other cases).
         */
-       if (likely((urb->transfer_flags & URB_SHORT_NOT_OK) == 0
-                               || usb_pipecontrol(urb->pipe)))
+       if (likely((urb->transfer_flags & URB_SHORT_NOT_OK) == 0 ||
+                       usb_pipecontrol(urb->pipe)))
                qtd->hw_alt_next = FOTG210_LIST_END(fotg210);
 
        /*
@@ -2778,7 +2688,7 @@ qh_urb_transaction(
         * (zero length).
         */
        if (likely(urb->transfer_buffer_length != 0)) {
-               int     one_more = 0;
+               int one_more = 0;
 
                if (usb_pipecontrol(urb->pipe)) {
                        one_more = 1;
@@ -2813,9 +2723,7 @@ cleanup:
        return NULL;
 }
 
-/*-------------------------------------------------------------------------*/
-/*
- * Would be best to create all qh's from config descriptors,
+/* Would be best to create all qh's from config descriptors,
  * when each interface/altsetting is established.  Unlink
  * any previous qh and cancel its urbs first; endpoints are
  * implicitly reset then (data toggle too).
@@ -2823,26 +2731,22 @@ cleanup:
 */
 
 
-/*
- * Each QH holds a qtd list; a QH is used for everything except iso.
+/* Each QH holds a qtd list; a QH is used for everything except iso.
  *
  * For interrupt urbs, the scheduler must set the microframe scheduling
  * mask(s) each time the QH gets scheduled.  For highspeed, that's
  * just one microframe in the s-mask.  For split interrupt transactions
  * there are additional complications: c-mask, maybe FSTNs.
  */
-static struct fotg210_qh *
-qh_make(
-       struct fotg210_hcd              *fotg210,
-       struct urb              *urb,
-       gfp_t                   flags
-) {
-       struct fotg210_qh               *qh = fotg210_qh_alloc(fotg210, flags);
-       u32                     info1 = 0, info2 = 0;
-       int                     is_input, type;
-       int                     maxp = 0;
-       struct usb_tt           *tt = urb->dev->tt;
-       struct fotg210_qh_hw    *hw;
+static struct fotg210_qh *qh_make(struct fotg210_hcd *fotg210, struct urb *urb,
+               gfp_t flags)
+{
+       struct fotg210_qh *qh = fotg210_qh_alloc(fotg210, flags);
+       u32 info1 = 0, info2 = 0;
+       int is_input, type;
+       int maxp = 0;
+       struct usb_tt *tt = urb->dev->tt;
+       struct fotg210_qh_hw *hw;
 
        if (!qh)
                return qh;
@@ -2862,7 +2766,7 @@ qh_make(
         */
        if (max_packet(maxp) > 1024) {
                fotg210_dbg(fotg210, "bogus qh maxpacket %d\n",
-                           max_packet(maxp));
+                               max_packet(maxp));
                goto done;
        }
 
@@ -2896,7 +2800,7 @@ qh_make(
                                urb->interval = qh->period << 3;
                        }
                } else {
-                       int             think_time;
+                       int think_time;
 
                        /* gap is f(FS/LS transfer times) */
                        qh->gap_uf = 1 + usb_calc_bus_time(urb->dev->speed,
@@ -2986,7 +2890,7 @@ qh_make(
                break;
        default:
                fotg210_dbg(fotg210, "bogus dev %p speed %d\n", urb->dev,
-                       urb->dev->speed);
+                               urb->dev->speed);
 done:
                qh_destroy(fotg210, qh);
                return NULL;
@@ -3005,8 +2909,6 @@ done:
        return qh;
 }
 
-/*-------------------------------------------------------------------------*/
-
 static void enable_async(struct fotg210_hcd *fotg210)
 {
        if (fotg210->async_count++)
@@ -3036,8 +2938,8 @@ static void disable_async(struct fotg210_hcd *fotg210)
 
 static void qh_link_async(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
 {
-       __hc32          dma = QH_NEXT(fotg210, qh->qh_dma);
-       struct fotg210_qh       *head;
+       __hc32 dma = QH_NEXT(fotg210, qh->qh_dma);
+       struct fotg210_qh *head;
 
        /* Don't link a QH if there's a Clear-TT-Buffer pending */
        if (unlikely(qh->clearing_tt))
@@ -3064,24 +2966,17 @@ static void qh_link_async(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
        enable_async(fotg210);
 }
 
-/*-------------------------------------------------------------------------*/
-
-/*
- * For control/bulk/interrupt, return QH with these TDs appended.
+/* For control/bulk/interrupt, return QH with these TDs appended.
  * Allocates and initializes the QH if necessary.
  * Returns null if it can't allocate a QH it needs to.
  * If the QH has TDs (urbs) already, that's great.
  */
-static struct fotg210_qh *qh_append_tds(
-       struct fotg210_hcd              *fotg210,
-       struct urb              *urb,
-       struct list_head        *qtd_list,
-       int                     epnum,
-       void                    **ptr
-)
+static struct fotg210_qh *qh_append_tds(struct fotg210_hcd *fotg210,
+               struct urb *urb, struct list_head *qtd_list,
+               int epnum, void **ptr)
 {
-       struct fotg210_qh               *qh = NULL;
-       __hc32                  qh_addr_mask = cpu_to_hc32(fotg210, 0x7f);
+       struct fotg210_qh *qh = NULL;
+       __hc32 qh_addr_mask = cpu_to_hc32(fotg210, 0x7f);
 
        qh = (struct fotg210_qh *) *ptr;
        if (unlikely(qh == NULL)) {
@@ -3090,7 +2985,7 @@ static struct fotg210_qh *qh_append_tds(
                *ptr = qh;
        }
        if (likely(qh != NULL)) {
-               struct fotg210_qtd      *qtd;
+               struct fotg210_qtd *qtd;
 
                if (unlikely(list_empty(qtd_list)))
                        qtd = NULL;
@@ -3109,9 +3004,9 @@ static struct fotg210_qh *qh_append_tds(
                 * only hc or qh_refresh() ever modify the overlay.
                 */
                if (likely(qtd != NULL)) {
-                       struct fotg210_qtd              *dummy;
-                       dma_addr_t              dma;
-                       __hc32                  token;
+                       struct fotg210_qtd *dummy;
+                       dma_addr_t dma;
+                       __hc32 token;
 
                        /* to avoid racing the HC, use the dummy td instead of
                         * the first td of our list (becomes new dummy).  both
@@ -3150,32 +3045,28 @@ static struct fotg210_qh *qh_append_tds(
        return qh;
 }
 
-/*-------------------------------------------------------------------------*/
-
-static int
-submit_async(
-       struct fotg210_hcd              *fotg210,
-       struct urb              *urb,
-       struct list_head        *qtd_list,
-       gfp_t                   mem_flags
-) {
-       int                     epnum;
-       unsigned long           flags;
-       struct fotg210_qh               *qh = NULL;
-       int                     rc;
+static int submit_async(struct fotg210_hcd *fotg210, struct urb *urb,
+               struct list_head *qtd_list, gfp_t mem_flags)
+{
+       int epnum;
+       unsigned long flags;
+       struct fotg210_qh *qh = NULL;
+       int rc;
 
        epnum = urb->ep->desc.bEndpointAddress;
 
 #ifdef FOTG210_URB_TRACE
        {
                struct fotg210_qtd *qtd;
+
                qtd = list_entry(qtd_list->next, struct fotg210_qtd, qtd_list);
                fotg210_dbg(fotg210,
-                        "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
-                        __func__, urb->dev->devpath, urb,
-                        epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out",
-                        urb->transfer_buffer_length,
-                        qtd, urb->ep->hcpriv);
+                               "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
+                               __func__, urb->dev->devpath, urb,
+                               epnum & 0x0f, (epnum & USB_DIR_IN)
+                                       ? "in" : "out",
+                               urb->transfer_buffer_length,
+                               qtd, urb->ep->hcpriv);
        }
 #endif
 
@@ -3200,19 +3091,17 @@ submit_async(
         */
        if (likely(qh->qh_state == QH_STATE_IDLE))
                qh_link_async(fotg210, qh);
- done:
+done:
        spin_unlock_irqrestore(&fotg210->lock, flags);
        if (unlikely(qh == NULL))
                qtd_list_free(fotg210, urb, qtd_list);
        return rc;
 }
 
-/*-------------------------------------------------------------------------*/
-
 static void single_unlink_async(struct fotg210_hcd *fotg210,
-                               struct fotg210_qh *qh)
+               struct fotg210_qh *qh)
 {
-       struct fotg210_qh               *prev;
+       struct fotg210_qh *prev;
 
        /* Add to the end of the list of QHs waiting for the next IAAD */
        qh->qh_state = QH_STATE_UNLINK;
@@ -3260,7 +3149,7 @@ static void start_iaa_cycle(struct fotg210_hcd *fotg210, bool nested)
                                &fotg210->regs->command);
                fotg210_readl(fotg210, &fotg210->regs->command);
                fotg210_enable_event(fotg210, FOTG210_HRTIMER_IAA_WATCHDOG,
-                                    true);
+                               true);
        }
 }
 
@@ -3268,10 +3157,10 @@ static void start_iaa_cycle(struct fotg210_hcd *fotg210, bool nested)
 
 static void end_unlink_async(struct fotg210_hcd *fotg210)
 {
-       struct fotg210_qh               *qh;
+       struct fotg210_qh *qh;
 
        /* Process the idle QHs */
- restart:
+restart:
        fotg210->async_unlinking = true;
        while (fotg210->async_iaa) {
                qh = fotg210->async_iaa;
@@ -3326,7 +3215,7 @@ static void unlink_empty_async(struct fotg210_hcd *fotg210)
        /* QHs that haven't been empty for long enough will be handled later */
        if (check_unlinks_later) {
                fotg210_enable_event(fotg210, FOTG210_HRTIMER_ASYNC_UNLINKS,
-                                    true);
+                               true);
                ++fotg210->async_unlink_cycle;
        }
 }
@@ -3335,7 +3224,7 @@ static void unlink_empty_async(struct fotg210_hcd *fotg210)
 /* caller must own fotg210->lock */
 
 static void start_unlink_async(struct fotg210_hcd *fotg210,
-                              struct fotg210_qh *qh)
+               struct fotg210_qh *qh)
 {
        /*
         * If the QH isn't linked then there's nothing we can do
@@ -3352,18 +3241,16 @@ static void start_unlink_async(struct fotg210_hcd *fotg210,
        start_iaa_cycle(fotg210, false);
 }
 
-/*-------------------------------------------------------------------------*/
-
 static void scan_async(struct fotg210_hcd *fotg210)
 {
-       struct fotg210_qh               *qh;
-       bool                    check_unlinks_later = false;
+       struct fotg210_qh *qh;
+       bool check_unlinks_later = false;
 
        fotg210->qh_scan_next = fotg210->async->qh_next.qh;
        while (fotg210->qh_scan_next) {
                qh = fotg210->qh_scan_next;
                fotg210->qh_scan_next = qh->qh_next.qh;
- rescan:
+rescan:
                /* clean any finished work for this qh */
                if (!list_empty(&qh->qtd_list)) {
                        int temp;
@@ -3395,15 +3282,13 @@ static void scan_async(struct fotg210_hcd *fotg210)
         */
        if (check_unlinks_later && fotg210->rh_state == FOTG210_RH_RUNNING &&
                        !(fotg210->enabled_hrtimer_events &
-                               BIT(FOTG210_HRTIMER_ASYNC_UNLINKS))) {
+                       BIT(FOTG210_HRTIMER_ASYNC_UNLINKS))) {
                fotg210_enable_event(fotg210,
-                                    FOTG210_HRTIMER_ASYNC_UNLINKS, true);
+                               FOTG210_HRTIMER_ASYNC_UNLINKS, true);
                ++fotg210->async_unlink_cycle;
        }
 }
-/*-------------------------------------------------------------------------*/
-/*
- * EHCI scheduled transaction support:  interrupt, iso, split iso
+/* EHCI scheduled transaction support:  interrupt, iso, split iso
  * These are called "periodic" transactions in the EHCI spec.
  *
  * Note that for interrupt transfers, the QH/QTD manipulation is shared
@@ -3414,19 +3299,14 @@ static void scan_async(struct fotg210_hcd *fotg210)
  * It keeps track of every ITD (or SITD) that's linked, and holds enough
  * pre-calculated schedule data to make appending to the queue be quick.
  */
-
 static int fotg210_get_frame(struct usb_hcd *hcd);
 
-/*-------------------------------------------------------------------------*/
-
-/*
- * periodic_next_shadow - return "next" pointer on shadow list
+/* periodic_next_shadow - return "next" pointer on shadow list
  * @periodic: host pointer to qh/itd
  * @tag: hardware tag for type of this record
  */
-static union fotg210_shadow *
-periodic_next_shadow(struct fotg210_hcd *fotg210,
-                    union fotg210_shadow *periodic, __hc32 tag)
+static union fotg210_shadow *periodic_next_shadow(struct fotg210_hcd *fotg210,
+               union fotg210_shadow *periodic, __hc32 tag)
 {
        switch (hc32_to_cpu(fotg210, tag)) {
        case Q_TYPE_QH:
@@ -3438,9 +3318,8 @@ periodic_next_shadow(struct fotg210_hcd *fotg210,
        }
 }
 
-static __hc32 *
-shadow_next_periodic(struct fotg210_hcd *fotg210,
-                    union fotg210_shadow *periodic, __hc32 tag)
+static __hc32 *shadow_next_periodic(struct fotg210_hcd *fotg210,
+               union fotg210_shadow *periodic, __hc32 tag)
 {
        switch (hc32_to_cpu(fotg210, tag)) {
        /* our fotg210_shadow.qh is actually software part */
@@ -3454,11 +3333,11 @@ shadow_next_periodic(struct fotg210_hcd *fotg210,
 
 /* caller must hold fotg210->lock */
 static void periodic_unlink(struct fotg210_hcd *fotg210, unsigned frame,
-                           void *ptr)
+               void *ptr)
 {
-       union fotg210_shadow    *prev_p = &fotg210->pshadow[frame];
-       __hc32                  *hw_p = &fotg210->periodic[frame];
-       union fotg210_shadow    here = *prev_p;
+       union fotg210_shadow *prev_p = &fotg210->pshadow[frame];
+       __hc32 *hw_p = &fotg210->periodic[frame];
+       union fotg210_shadow here = *prev_p;
 
        /* find predecessor of "ptr"; hw and shadow lists are in sync */
        while (here.ptr && here.ptr != ptr) {
@@ -3479,17 +3358,17 @@ static void periodic_unlink(struct fotg210_hcd *fotg210, unsigned frame,
                        Q_NEXT_TYPE(fotg210, *hw_p));
 
        *hw_p = *shadow_next_periodic(fotg210, &here,
-                               Q_NEXT_TYPE(fotg210, *hw_p));
+                       Q_NEXT_TYPE(fotg210, *hw_p));
 }
 
 /* how many of the uframe's 125 usecs are allocated? */
-static unsigned short
-periodic_usecs(struct fotg210_hcd *fotg210, unsigned frame, unsigned uframe)
+static unsigned short periodic_usecs(struct fotg210_hcd *fotg210,
+               unsigned frame, unsigned uframe)
 {
-       __hc32                  *hw_p = &fotg210->periodic[frame];
-       union fotg210_shadow    *q = &fotg210->pshadow[frame];
-       unsigned                usecs = 0;
-       struct fotg210_qh_hw    *hw;
+       __hc32 *hw_p = &fotg210->periodic[frame];
+       union fotg210_shadow *q = &fotg210->pshadow[frame];
+       unsigned usecs = 0;
+       struct fotg210_qh_hw *hw;
 
        while (q->ptr) {
                switch (hc32_to_cpu(fotg210, Q_NEXT_TYPE(fotg210, *hw_p))) {
@@ -3526,12 +3405,10 @@ periodic_usecs(struct fotg210_hcd *fotg210, unsigned frame, unsigned uframe)
        }
        if (usecs > fotg210->uframe_periodic_max)
                fotg210_err(fotg210, "uframe %d sched overrun: %d usecs\n",
-                       frame * 8 + uframe, usecs);
+                               frame * 8 + uframe, usecs);
        return usecs;
 }
 
-/*-------------------------------------------------------------------------*/
-
 static int same_tt(struct usb_device *dev1, struct usb_device *dev2)
 {
        if (!dev1->tt || !dev2->tt)
@@ -3548,13 +3425,8 @@ static int same_tt(struct usb_device *dev1, struct usb_device *dev2)
  * for a periodic transfer starting at the specified frame, using
  * all the uframes in the mask.
  */
-static int tt_no_collision(
-       struct fotg210_hcd              *fotg210,
-       unsigned                period,
-       struct usb_device       *dev,
-       unsigned                frame,
-       u32                     uf_mask
-)
+static int tt_no_collision(struct fotg210_hcd *fotg210, unsigned period,
+               struct usb_device *dev, unsigned frame, u32 uf_mask)
 {
        if (period == 0)        /* error */
                return 0;
@@ -3564,9 +3436,9 @@ static int tt_no_collision(
         * calling convention doesn't make that distinction.
         */
        for (; frame < fotg210->periodic_size; frame += period) {
-               union fotg210_shadow    here;
-               __hc32                  type;
-               struct fotg210_qh_hw    *hw;
+               union fotg210_shadow here;
+               __hc32 type;
+               struct fotg210_qh_hw *hw;
 
                here = fotg210->pshadow[frame];
                type = Q_NEXT_TYPE(fotg210, fotg210->periodic[frame]);
@@ -3579,7 +3451,7 @@ static int tt_no_collision(
                        case Q_TYPE_QH:
                                hw = here.qh->hw;
                                if (same_tt(dev, here.qh->dev)) {
-                                       u32             mask;
+                                       u32 mask;
 
                                        mask = hc32_to_cpu(fotg210,
                                                        hw->hw_info2);
@@ -3594,8 +3466,8 @@ static int tt_no_collision(
                        /* case Q_TYPE_FSTN: */
                        default:
                                fotg210_dbg(fotg210,
-                                       "periodic frame %d bogus type %d\n",
-                                       frame, type);
+                                               "periodic frame %d bogus type %d\n",
+                                               frame, type);
                        }
 
                        /* collision or error */
@@ -3607,8 +3479,6 @@ static int tt_no_collision(
        return 1;
 }
 
-/*-------------------------------------------------------------------------*/
-
 static void enable_periodic(struct fotg210_hcd *fotg210)
 {
        if (fotg210->periodic_count++)
@@ -3632,8 +3502,6 @@ static void disable_periodic(struct fotg210_hcd *fotg210)
        fotg210_poll_PSS(fotg210);
 }
 
-/*-------------------------------------------------------------------------*/
-
 /* periodic schedule slots have iso tds (normal or split) first, then a
  * sparse tree for active interrupt transfers.
  *
@@ -3642,24 +3510,24 @@ static void disable_periodic(struct fotg210_hcd *fotg210)
  */
 static void qh_link_periodic(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
 {
-       unsigned        i;
-       unsigned        period = qh->period;
+       unsigned i;
+       unsigned period = qh->period;
 
        dev_dbg(&qh->dev->dev,
-               "link qh%d-%04x/%p start %d [%d/%d us]\n",
-               period, hc32_to_cpup(fotg210, &qh->hw->hw_info2)
-                       & (QH_CMASK | QH_SMASK),
-               qh, qh->start, qh->usecs, qh->c_usecs);
+                       "link qh%d-%04x/%p start %d [%d/%d us]\n", period,
+                       hc32_to_cpup(fotg210, &qh->hw->hw_info2) &
+                       (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs,
+                       qh->c_usecs);
 
        /* high bandwidth, or otherwise every microframe */
        if (period == 0)
                period = 1;
 
        for (i = qh->start; i < fotg210->periodic_size; i += period) {
-               union fotg210_shadow    *prev = &fotg210->pshadow[i];
-               __hc32                  *hw_p = &fotg210->periodic[i];
-               union fotg210_shadow    here = *prev;
-               __hc32                  type = 0;
+               union fotg210_shadow *prev = &fotg210->pshadow[i];
+               __hc32 *hw_p = &fotg210->periodic[i];
+               union fotg210_shadow here = *prev;
+               __hc32 type = 0;
 
                /* skip the iso nodes at list head */
                while (here.ptr) {
@@ -3707,10 +3575,10 @@ static void qh_link_periodic(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
 }
 
 static void qh_unlink_periodic(struct fotg210_hcd *fotg210,
-                              struct fotg210_qh *qh)
+               struct fotg210_qh *qh)
 {
-       unsigned        i;
-       unsigned        period;
+       unsigned i;
+       unsigned period;
 
        /*
         * If qh is for a low/full-speed device, simply unlinking it
@@ -3741,10 +3609,10 @@ static void qh_unlink_periodic(struct fotg210_hcd *fotg210,
                : (qh->usecs * 8);
 
        dev_dbg(&qh->dev->dev,
-               "unlink qh%d-%04x/%p start %d [%d/%d us]\n",
-               qh->period,
-               hc32_to_cpup(fotg210, &qh->hw->hw_info2) &
-               (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs, qh->c_usecs);
+                       "unlink qh%d-%04x/%p start %d [%d/%d us]\n",
+                       qh->period, hc32_to_cpup(fotg210, &qh->hw->hw_info2) &
+                       (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs,
+                       qh->c_usecs);
 
        /* qh->qh_next still "live" to HC */
        qh->qh_state = QH_STATE_UNLINK;
@@ -3757,7 +3625,7 @@ static void qh_unlink_periodic(struct fotg210_hcd *fotg210,
 }
 
 static void start_unlink_intr(struct fotg210_hcd *fotg210,
-                             struct fotg210_qh *qh)
+               struct fotg210_qh *qh)
 {
        /* If the QH isn't linked then there's nothing we can do
         * unless we were called during a giveback, in which case
@@ -3794,15 +3662,15 @@ static void start_unlink_intr(struct fotg210_hcd *fotg210,
                fotg210_handle_intr_unlinks(fotg210);
        else if (fotg210->intr_unlink == qh) {
                fotg210_enable_event(fotg210, FOTG210_HRTIMER_UNLINK_INTR,
-                                    true);
+                               true);
                ++fotg210->intr_unlink_cycle;
        }
 }
 
 static void end_unlink_intr(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
 {
-       struct fotg210_qh_hw    *hw = qh->hw;
-       int                     rc;
+       struct fotg210_qh_hw *hw = qh->hw;
+       int rc;
 
        qh->qh_state = QH_STATE_IDLE;
        hw->hw_next = FOTG210_LIST_END(fotg210);
@@ -3811,7 +3679,7 @@ static void end_unlink_intr(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
 
        /* reschedule QH iff another request is queued */
        if (!list_empty(&qh->qtd_list) &&
-           fotg210->rh_state == FOTG210_RH_RUNNING) {
+                       fotg210->rh_state == FOTG210_RH_RUNNING) {
                rc = qh_schedule(fotg210, qh);
 
                /* An error here likely indicates handshake failure
@@ -3830,16 +3698,10 @@ static void end_unlink_intr(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
        disable_periodic(fotg210);
 }
 
-/*-------------------------------------------------------------------------*/
-
-static int check_period(
-       struct fotg210_hcd *fotg210,
-       unsigned        frame,
-       unsigned        uframe,
-       unsigned        period,
-       unsigned        usecs
-) {
-       int             claimed;
+static int check_period(struct fotg210_hcd *fotg210, unsigned frame,
+               unsigned uframe, unsigned period, unsigned usecs)
+{
+       int claimed;
 
        /* complete split running into next frame?
         * given FSTN support, we could sometimes check...
@@ -3857,7 +3719,7 @@ static int check_period(
                do {
                        for (uframe = 0; uframe < 7; uframe++) {
                                claimed = periodic_usecs(fotg210, frame,
-                                                        uframe);
+                                               uframe);
                                if (claimed > usecs)
                                        return 0;
                        }
@@ -3876,16 +3738,11 @@ static int check_period(
        return 1;
 }
 
-static int check_intr_schedule(
-       struct fotg210_hcd              *fotg210,
-       unsigned                frame,
-       unsigned                uframe,
-       const struct fotg210_qh *qh,
-       __hc32                  *c_maskp
-)
+static int check_intr_schedule(struct fotg210_hcd *fotg210, unsigned frame,
+               unsigned uframe, const struct fotg210_qh *qh, __hc32 *c_maskp)
 {
-       int             retval = -ENOSPC;
-       u8              mask = 0;
+       int retval = -ENOSPC;
+       u8 mask = 0;
 
        if (qh->c_usecs && uframe >= 6)         /* FSTN territory? */
                goto done;
@@ -3911,10 +3768,10 @@ static int check_intr_schedule(
        mask |= 1 << uframe;
        if (tt_no_collision(fotg210, qh->period, qh->dev, frame, mask)) {
                if (!check_period(fotg210, frame, uframe + qh->gap_uf + 1,
-                                       qh->period, qh->c_usecs))
+                               qh->period, qh->c_usecs))
                        goto done;
                if (!check_period(fotg210, frame, uframe + qh->gap_uf,
-                                       qh->period, qh->c_usecs))
+                               qh->period, qh->c_usecs))
                        goto done;
                retval = 0;
        }
@@ -3927,11 +3784,11 @@ done:
  */
 static int qh_schedule(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
 {
-       int             status;
-       unsigned        uframe;
-       __hc32          c_mask;
-       unsigned        frame;          /* 0..(qh->period - 1), or NO_FRAME */
-       struct fotg210_qh_hw    *hw = qh->hw;
+       int status;
+       unsigned uframe;
+       __hc32 c_mask;
+       unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */
+       struct fotg210_qh_hw *hw = qh->hw;
 
        qh_refresh(fotg210, qh);
        hw->hw_next = FOTG210_LIST_END(fotg210);
@@ -3954,7 +3811,7 @@ static int qh_schedule(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
        if (status) {
                /* "normal" case, uframing flexible except with splits */
                if (qh->period) {
-                       int             i;
+                       int i;
 
                        for (i = qh->period; status && i > 0; --i) {
                                frame = ++fotg210->random_frame % qh->period;
@@ -3971,7 +3828,7 @@ static int qh_schedule(struct fotg210_hcd *fotg210, struct fotg210_qh *qh)
                } else {
                        frame = 0;
                        status = check_intr_schedule(fotg210, 0, 0, qh,
-                                                    &c_mask);
+                                       &c_mask);
                }
                if (status)
                        goto done;
@@ -3992,17 +3849,14 @@ done:
        return status;
 }
 
-static int intr_submit(
-       struct fotg210_hcd              *fotg210,
-       struct urb              *urb,
-       struct list_head        *qtd_list,
-       gfp_t                   mem_flags
-) {
-       unsigned                epnum;
-       unsigned long           flags;
-       struct fotg210_qh               *qh;
-       int                     status;
-       struct list_head        empty;
+static int intr_submit(struct fotg210_hcd *fotg210, struct urb *urb,
+               struct list_head *qtd_list, gfp_t mem_flags)
+{
+       unsigned epnum;
+       unsigned long flags;
+       struct fotg210_qh *qh;
+       int status;
+       struct list_head empty;
 
        /* get endpoint and transfer/schedule data */
        epnum = urb->ep->desc.bEndpointAddress;
@@ -4050,11 +3904,11 @@ done_not_linked:
 
 static void scan_intr(struct fotg210_hcd *fotg210)
 {
-       struct fotg210_qh               *qh;
+       struct fotg210_qh *qh;
 
        list_for_each_entry_safe(qh, fotg210->qh_scan_next,
-                                &fotg210->intr_qh_list, intr_node) {
- rescan:
+                       &fotg210->intr_qh_list, intr_node) {
+rescan:
                /* clean any finished work for this qh */
                if (!list_empty(&qh->qtd_list)) {
                        int temp;
@@ -4069,7 +3923,7 @@ static void scan_intr(struct fotg210_hcd *fotg210)
                        temp = qh_completions(fotg210, qh);
                        if (unlikely(qh->needs_rescan ||
                                        (list_empty(&qh->qtd_list) &&
-                                        qh->qh_state == QH_STATE_LINKED)))
+                                       qh->qh_state == QH_STATE_LINKED)))
                                start_unlink_intr(fotg210, qh);
                        else if (temp != 0)
                                goto rescan;
@@ -4077,12 +3931,9 @@ static void scan_intr(struct fotg210_hcd *fotg210)
        }
 }
 
-/*-------------------------------------------------------------------------*/
-
 /* fotg210_iso_stream ops work with both ITD and SITD */
 
-static struct fotg210_iso_stream *
-iso_stream_alloc(gfp_t mem_flags)
+static struct fotg210_iso_stream *iso_stream_alloc(gfp_t mem_flags)
 {
        struct fotg210_iso_stream *stream;
 
@@ -4095,20 +3946,15 @@ iso_stream_alloc(gfp_t mem_flags)
        return stream;
 }
 
-static void
-iso_stream_init(
-       struct fotg210_hcd              *fotg210,
-       struct fotg210_iso_stream       *stream,
-       struct usb_device       *dev,
-       int                     pipe,
-       unsigned                interval
-)
+static void iso_stream_init(struct fotg210_hcd *fotg210,
+               struct fotg210_iso_stream *stream, struct usb_device *dev,
+               int pipe, unsigned interval)
 {
-       u32                     buf1;
-       unsigned                epnum, maxp;
-       int                     is_input;
-       long                    bandwidth;
-       unsigned                multi;
+       u32 buf1;
+       unsigned epnum, maxp;
+       int is_input;
+       long bandwidth;
+       unsigned multi;
 
        /*
         * this might be a "high bandwidth" highspeed endpoint,
@@ -4153,13 +3999,13 @@ iso_stream_init(
        stream->maxp = maxp;
 }
 
-static struct fotg210_iso_stream *
-iso_stream_find(struct fotg210_hcd *fotg210, struct urb *urb)
+static struct fotg210_iso_stream *iso_stream_find(struct fotg210_hcd *fotg210,
+               struct urb *urb)
 {
-       unsigned                epnum;
-       struct fotg210_iso_stream       *stream;
+       unsigned epnum;
+       struct fotg210_iso_stream *stream;
        struct usb_host_endpoint *ep;
-       unsigned long           flags;
+       unsigned long flags;
 
        epnum = usb_pipeendpoint(urb->pipe);
        if (usb_pipein(urb->pipe))
@@ -4182,8 +4028,8 @@ iso_stream_find(struct fotg210_hcd *fotg210, struct urb *urb)
        /* if dev->ep[epnum] is a QH, hw is set */
        } else if (unlikely(stream->hw != NULL)) {
                fotg210_dbg(fotg210, "dev %s ep%d%s, not iso??\n",
-                       urb->dev->devpath, epnum,
-                       usb_pipein(urb->pipe) ? "in" : "out");
+                               urb->dev->devpath, epnum,
+                               usb_pipein(urb->pipe) ? "in" : "out");
                stream = NULL;
        }
 
@@ -4191,15 +4037,13 @@ iso_stream_find(struct fotg210_hcd *fotg210, struct urb *urb)
        return stream;
 }
 
-/*-------------------------------------------------------------------------*/
-
 /* fotg210_iso_sched ops can be ITD-only or SITD-only */
 
-static struct fotg210_iso_sched *
-iso_sched_alloc(unsigned packets, gfp_t mem_flags)
+static struct fotg210_iso_sched *iso_sched_alloc(unsigned packets,
+               gfp_t mem_flags)
 {
-       struct fotg210_iso_sched        *iso_sched;
-       int                     size = sizeof(*iso_sched);
+       struct fotg210_iso_sched *iso_sched;
+       int size = sizeof(*iso_sched);
 
        size += packets * sizeof(struct fotg210_iso_packet);
        iso_sched = kzalloc(size, mem_flags);
@@ -4209,16 +4053,12 @@ iso_sched_alloc(unsigned packets, gfp_t mem_flags)
        return iso_sched;
 }
 
-static inline void
-itd_sched_init(
-       struct fotg210_hcd              *fotg210,
-       struct fotg210_iso_sched        *iso_sched,
-       struct fotg210_iso_stream       *stream,
-       struct urb              *urb
-)
+static inline void itd_sched_init(struct fotg210_hcd *fotg210,
+               struct fotg210_iso_sched *iso_sched,
+               struct fotg210_iso_stream *stream, struct urb *urb)
 {
-       unsigned        i;
-       dma_addr_t      dma = urb->transfer_dma;
+       unsigned i;
+       dma_addr_t dma = urb->transfer_dma;
 
        /* how many uframes are needed for these transfers */
        iso_sched->span = urb->number_of_packets * stream->interval;
@@ -4227,10 +4067,10 @@ itd_sched_init(
         * when we fit new itds into the schedule.
         */
        for (i = 0; i < urb->number_of_packets; i++) {
-               struct fotg210_iso_packet       *uframe = &iso_sched->packet[i];
-               unsigned                length;
-               dma_addr_t              buf;
-               u32                     trans;
+               struct fotg210_iso_packet *uframe = &iso_sched->packet[i];
+               unsigned length;
+               dma_addr_t buf;
+               u32 trans;
 
                length = urb->iso_frame_desc[i].length;
                buf = dma + urb->iso_frame_desc[i].offset;
@@ -4251,11 +4091,8 @@ itd_sched_init(
        }
 }
 
-static void
-iso_sched_free(
-       struct fotg210_iso_stream       *stream,
-       struct fotg210_iso_sched        *iso_sched
-)
+static void iso_sched_free(struct fotg210_iso_stream *stream,
+               struct fotg210_iso_sched *iso_sched)
 {
        if (!iso_sched)
                return;
@@ -4264,20 +4101,15 @@ iso_sched_free(
        kfree(iso_sched);
 }
 
-static int
-itd_urb_transaction(
-       struct fotg210_iso_stream       *stream,
-       struct fotg210_hcd              *fotg210,
-       struct urb              *urb,
-       gfp_t                   mem_flags
-)
+static int itd_urb_transaction(struct fotg210_iso_stream *stream,
+               struct fotg210_hcd *fotg210, struct urb *urb, gfp_t mem_flags)
 {
-       struct fotg210_itd              *itd;
-       dma_addr_t              itd_dma;
-       int                     i;
-       unsigned                num_itds;
-       struct fotg210_iso_sched        *sched;
-       unsigned long           flags;
+       struct fotg210_itd *itd;
+       dma_addr_t itd_dma;
+       int i;
+       unsigned num_itds;
+       struct fotg210_iso_sched *sched;
+       unsigned long flags;
 
        sched = iso_sched_alloc(urb->number_of_packets, mem_flags);
        if (unlikely(sched == NULL))
@@ -4306,7 +4138,7 @@ itd_urb_transaction(
                        list_del(&itd->itd_list);
                        itd_dma = itd->itd_dma;
                } else {
- alloc_itd:
+alloc_itd:
                        spin_unlock_irqrestore(&fotg210->lock, flags);
                        itd = dma_pool_alloc(fotg210->itd_pool, mem_flags,
                                        &itd_dma);
@@ -4330,16 +4162,8 @@ itd_urb_transaction(
        return 0;
 }
 
-/*-------------------------------------------------------------------------*/
-
-static inline int
-itd_slot_ok(
-       struct fotg210_hcd              *fotg210,
-       u32                     mod,
-       u32                     uframe,
-       u8                      usecs,
-       u32                     period
-)
+static inline int itd_slot_ok(struct fotg210_hcd *fotg210, u32 mod, u32 uframe,
+               u8 usecs, u32 period)
 {
        uframe %= period;
        do {
@@ -4354,8 +4178,7 @@ itd_slot_ok(
        return 1;
 }
 
-/*
- * This scheduler plans almost as far into the future as it has actual
+/* This scheduler plans almost as far into the future as it has actual
  * periodic schedule slots.  (Affected by TUNE_FLS, which defaults to
  * "as small as possible" to be cache-friendlier.)  That limits the size
  * transfers you can stream reliably; avoid more than 64 msec per urb.
@@ -4365,19 +4188,15 @@ itd_slot_ok(
  * given FOTG210_TUNE_FLS and the slop).  Or, write a smarter scheduler!
  */
 
-#define SCHEDULE_SLOP  80      /* microframes */
+#define SCHEDULE_SLOP 80 /* microframes */
 
-static int
-iso_stream_schedule(
-       struct fotg210_hcd              *fotg210,
-       struct urb              *urb,
-       struct fotg210_iso_stream       *stream
-)
+static int iso_stream_schedule(struct fotg210_hcd *fotg210, struct urb *urb,
+               struct fotg210_iso_stream *stream)
 {
-       u32                     now, next, start, period, span;
-       int                     status;
-       unsigned                mod = fotg210->periodic_size << 3;
-       struct fotg210_iso_sched        *sched = urb->hcpriv;
+       u32 now, next, start, period, span;
+       int status;
+       unsigned mod = fotg210->periodic_size << 3;
+       struct fotg210_iso_sched *sched = urb->hcpriv;
 
        period = urb->interval;
        span = sched->span;
@@ -4396,7 +4215,7 @@ iso_stream_schedule(
         * slot in the schedule, implicitly assuming URB_ISO_ASAP.
         */
        if (likely(!list_empty(&stream->td_list))) {
-               u32     excess;
+               u32 excess;
 
                /* For high speed devices, allow scheduling within the
                 * isochronous scheduling threshold.  For full speed devices
@@ -4435,6 +4254,7 @@ iso_stream_schedule(
         */
        else {
                int done = 0;
+
                start = SCHEDULE_SLOP + (now & ~0x07);
 
                /* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */
@@ -4457,15 +4277,15 @@ iso_stream_schedule(
                /* no room in the schedule */
                if (!done) {
                        fotg210_dbg(fotg210, "iso resched full %p (now %d max %d)\n",
-                               urb, now, now + mod);
+                                       urb, now, now + mod);
                        status = -ENOSPC;
                        goto fail;
                }
        }
 
        /* Tried to schedule too far into the future? */
-       if (unlikely(start - now + span - period
-                               >= mod - 2 * SCHEDULE_SLOP)) {
+       if (unlikely(start - now + span - period >=
+                       mod - 2 * SCHEDULE_SLOP)) {
                fotg210_dbg(fotg210, "request %p would overflow (%d+%d >= %d)\n",
                                urb, start - now, span - period,
                                mod - 2 * SCHEDULE_SLOP);
@@ -4485,17 +4305,14 @@ iso_stream_schedule(
                fotg210->next_frame = now >> 3;
        return 0;
 
- fail:
+fail:
        iso_sched_free(stream, sched);
        urb->hcpriv = NULL;
        return status;
 }
 
-/*-------------------------------------------------------------------------*/
-
-static inline void
-itd_init(struct fotg210_hcd *fotg210, struct fotg210_iso_stream *stream,
-               struct fotg210_itd *itd)
+static inline void itd_init(struct fotg210_hcd *fotg210,
+               struct fotg210_iso_stream *stream, struct fotg210_itd *itd)
 {
        int i;
 
@@ -4511,17 +4328,12 @@ itd_init(struct fotg210_hcd *fotg210, struct fotg210_iso_stream *stream,
        /* All other fields are filled when scheduling */
 }
 
-static inline void
-itd_patch(
-       struct fotg210_hcd              *fotg210,
-       struct fotg210_itd              *itd,
-       struct fotg210_iso_sched        *iso_sched,
-       unsigned                index,
-       u16                     uframe
-)
+static inline void itd_patch(struct fotg210_hcd *fotg210,
+               struct fotg210_itd *itd, struct fotg210_iso_sched *iso_sched,
+               unsigned index, u16 uframe)
 {
-       struct fotg210_iso_packet       *uf = &iso_sched->packet[index];
-       unsigned                pg = itd->pg;
+       struct fotg210_iso_packet *uf = &iso_sched->packet[index];
+       unsigned pg = itd->pg;
 
        uframe &= 0x07;
        itd->index[uframe] = index;
@@ -4533,7 +4345,7 @@ itd_patch(
 
        /* iso_frame_desc[].offset must be strictly increasing */
        if (unlikely(uf->cross)) {
-               u64     bufp = uf->bufp + 4096;
+               u64 bufp = uf->bufp + 4096;
 
                itd->pg = ++pg;
                itd->hw_bufp[pg] |= cpu_to_hc32(fotg210, bufp & ~(u32)0);
@@ -4541,13 +4353,13 @@ itd_patch(
        }
 }
 
-static inline void
-itd_link(struct fotg210_hcd *fotg210, unsigned frame, struct fotg210_itd *itd)
+static inline void itd_link(struct fotg210_hcd *fotg210, unsigned frame,
+               struct fotg210_itd *itd)
 {
-       union fotg210_shadow    *prev = &fotg210->pshadow[frame];
-       __hc32                  *hw_p = &fotg210->periodic[frame];
-       union fotg210_shadow    here = *prev;
-       __hc32                  type = 0;
+       union fotg210_shadow *prev = &fotg210->pshadow[frame];
+       __hc32 *hw_p = &fotg210->periodic[frame];
+       union fotg210_shadow here = *prev;
+       __hc32 type = 0;
 
        /* skip any iso nodes which might belong to previous microframes */
        while (here.ptr) {
@@ -4568,17 +4380,13 @@ itd_link(struct fotg210_hcd *fotg210, unsigned frame, struct fotg210_itd *itd)
 }
 
 /* fit urb's itds into the selected schedule slot; activate as needed */
-static void itd_link_urb(
-       struct fotg210_hcd              *fotg210,
-       struct urb              *urb,
-       unsigned                mod,
-       struct fotg210_iso_stream       *stream
-)
-{
-       int                     packet;
-       unsigned                next_uframe, uframe, frame;
-       struct fotg210_iso_sched        *iso_sched = urb->hcpriv;
-       struct fotg210_itd              *itd;
+static void itd_link_urb(struct fotg210_hcd *fotg210, struct urb *urb,
+               unsigned mod, struct fotg210_iso_stream *stream)
+{
+       int packet;
+       unsigned next_uframe, uframe, frame;
+       struct fotg210_iso_sched *iso_sched = urb->hcpriv;
+       struct fotg210_itd *itd;
 
        next_uframe = stream->next_uframe & (mod - 1);
 
@@ -4621,7 +4429,7 @@ static void itd_link_urb(
                if (((next_uframe >> 3) != frame)
                                || packet == urb->number_of_packets) {
                        itd_link(fotg210, frame & (fotg210->periodic_size - 1),
-                                itd);
+                                       itd);
                        itd = NULL;
                }
        }
@@ -4635,8 +4443,8 @@ static void itd_link_urb(
        enable_periodic(fotg210);
 }
 
-#define        ISO_ERRS (FOTG210_ISOC_BUF_ERR | FOTG210_ISOC_BABBLE |\
-                 FOTG210_ISOC_XACTERR)
+#define ISO_ERRS (FOTG210_ISOC_BUF_ERR | FOTG210_ISOC_BABBLE |\
+               FOTG210_ISOC_XACTERR)
 
 /* Process and recycle a completed ITD.  Return true iff its urb completed,
  * and hence its completion callback probably added things to the hardware
@@ -4650,14 +4458,14 @@ static void itd_link_urb(
  */
 static bool itd_complete(struct fotg210_hcd *fotg210, struct fotg210_itd *itd)
 {
-       struct urb                              *urb = itd->urb;
-       struct usb_iso_packet_descriptor        *desc;
-       u32                                     t;
-       unsigned                                uframe;
-       int                                     urb_index = -1;
-       struct fotg210_iso_stream                       *stream = itd->stream;
-       struct usb_device                       *dev;
-       bool                                    retval = false;
+       struct urb *urb = itd->urb;
+       struct usb_iso_packet_descriptor *desc;
+       u32 t;
+       unsigned uframe;
+       int urb_index = -1;
+       struct fotg210_iso_stream *stream = itd->stream;
+       struct usb_device *dev;
+       bool retval = false;
 
        /* for each uframe with a packet */
        for (uframe = 0; uframe < 8; uframe++) {
@@ -4702,8 +4510,8 @@ static bool itd_complete(struct fotg210_hcd *fotg210, struct fotg210_itd *itd)
                goto done;
 
        /* ASSERT: it's really the last itd for this urb
-       list_for_each_entry (itd, &stream->td_list, itd_list)
-               BUG_ON (itd->urb == urb);
+        * list_for_each_entry (itd, &stream->td_list, itd_list)
+        *      BUG_ON (itd->urb == urb);
         */
 
        /* give urb back to the driver; completion often (re)submits */
@@ -4740,14 +4548,12 @@ done:
        return retval;
 }
 
-/*-------------------------------------------------------------------------*/
-
 static int itd_submit(struct fotg210_hcd *fotg210, struct urb *urb,
-       gfp_t mem_flags)
+               gfp_t mem_flags)
 {
-       int                     status = -EINVAL;
-       unsigned long           flags;
-       struct fotg210_iso_stream       *stream;
+       int status = -EINVAL;
+       unsigned long flags;
+       struct fotg210_iso_stream *stream;
 
        /* Get iso_stream head */
        stream = iso_stream_find(fotg210, urb);
@@ -4756,22 +4562,22 @@ static int itd_submit(struct fotg210_hcd *fotg210, struct urb *urb,
                return -ENOMEM;
        }
        if (unlikely(urb->interval != stream->interval &&
-                     fotg210_port_speed(fotg210, 0) ==
-                               USB_PORT_STAT_HIGH_SPEED)) {
-                       fotg210_dbg(fotg210, "can't change iso interval %d --> %d\n",
+                       fotg210_port_speed(fotg210, 0) ==
+                       USB_PORT_STAT_HIGH_SPEED)) {
+               fotg210_dbg(fotg210, "can't change iso interval %d --> %d\n",
                                stream->interval, urb->interval);
-                       goto done;
+               goto done;
        }
 
 #ifdef FOTG210_URB_TRACE
        fotg210_dbg(fotg210,
-               "%s %s urb %p ep%d%s len %d, %d pkts %d uframes[%p]\n",
-               __func__, urb->dev->devpath, urb,
-               usb_pipeendpoint(urb->pipe),
-               usb_pipein(urb->pipe) ? "in" : "out",
-               urb->transfer_buffer_length,
-               urb->number_of_packets, urb->interval,
-               stream);
+                       "%s %s urb %p ep%d%s len %d, %d pkts %d uframes[%p]\n",
+                       __func__, urb->dev->devpath, urb,
+                       usb_pipeendpoint(urb->pipe),
+                       usb_pipein(urb->pipe) ? "in" : "out",
+                       urb->transfer_buffer_length,
+                       urb->number_of_packets, urb->interval,
+                       stream);
 #endif
 
        /* allocate ITDs w/o locking anything */
@@ -4795,19 +4601,87 @@ static int itd_submit(struct fotg210_hcd *fotg210, struct urb *urb,
                itd_link_urb(fotg210, urb, fotg210->periodic_size << 3, stream);
        else
                usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb);
- done_not_linked:
+done_not_linked:
        spin_unlock_irqrestore(&fotg210->lock, flags);
- done:
+done:
        return status;
 }
 
-/*-------------------------------------------------------------------------*/
+static inline int scan_frame_queue(struct fotg210_hcd *fotg210, unsigned frame,
+               unsigned now_frame, bool live)
+{
+       unsigned uf;
+       bool modified;
+       union fotg210_shadow q, *q_p;
+       __hc32 type, *hw_p;
+
+       /* scan each element in frame's queue for completions */
+       q_p = &fotg210->pshadow[frame];
+       hw_p = &fotg210->periodic[frame];
+       q.ptr = q_p->ptr;
+       type = Q_NEXT_TYPE(fotg210, *hw_p);
+       modified = false;
+
+       while (q.ptr) {
+               switch (hc32_to_cpu(fotg210, type)) {
+               case Q_TYPE_ITD:
+                       /* If this ITD is still active, leave it for
+                        * later processing ... check the next entry.
+                        * No need to check for activity unless the
+                        * frame is current.
+                        */
+                       if (frame == now_frame && live) {
+                               rmb();
+                               for (uf = 0; uf < 8; uf++) {
+                                       if (q.itd->hw_transaction[uf] &
+                                                       ITD_ACTIVE(fotg210))
+                                               break;
+                               }
+                               if (uf < 8) {
+                                       q_p = &q.itd->itd_next;
+                                       hw_p = &q.itd->hw_next;
+                                       type = Q_NEXT_TYPE(fotg210,
+                                                       q.itd->hw_next);
+                                       q = *q_p;
+                                       break;
+                               }
+                       }
+
+                       /* Take finished ITDs out of the schedule
+                        * and process them:  recycle, maybe report
+                        * URB completion.  HC won't cache the
+                        * pointer for much longer, if at all.
+                        */
+                       *q_p = q.itd->itd_next;
+                       *hw_p = q.itd->hw_next;
+                       type = Q_NEXT_TYPE(fotg210, q.itd->hw_next);
+                       wmb();
+                       modified = itd_complete(fotg210, q.itd);
+                       q = *q_p;
+                       break;
+               default:
+                       fotg210_dbg(fotg210, "corrupt type %d frame %d shadow %p\n",
+                                       type, frame, q.ptr);
+                       /* FALL THROUGH */
+               case Q_TYPE_QH:
+               case Q_TYPE_FSTN:
+                       /* End of the iTDs and siTDs */
+                       q.ptr = NULL;
+                       break;
+               }
+
+               /* assume completion callbacks modify the queue */
+               if (unlikely(modified && fotg210->isoc_count > 0))
+                       return -EINVAL;
+       }
+       return 0;
+}
 
 static void scan_isoc(struct fotg210_hcd *fotg210)
 {
-       unsigned        uf, now_frame, frame;
-       unsigned        fmask = fotg210->periodic_size - 1;
-       bool            modified, live;
+       unsigned uf, now_frame, frame, ret;
+       unsigned fmask = fotg210->periodic_size - 1;
+       bool live;
 
        /*
         * When running, scan from last scan point up to "now"
@@ -4826,69 +4700,10 @@ static void scan_isoc(struct fotg210_hcd *fotg210)
 
        frame = fotg210->next_frame;
        for (;;) {
-               union fotg210_shadow    q, *q_p;
-               __hc32                  type, *hw_p;
-
-restart:
-               /* scan each element in frame's queue for completions */
-               q_p = &fotg210->pshadow[frame];
-               hw_p = &fotg210->periodic[frame];
-               q.ptr = q_p->ptr;
-               type = Q_NEXT_TYPE(fotg210, *hw_p);
-               modified = false;
-
-               while (q.ptr != NULL) {
-                       switch (hc32_to_cpu(fotg210, type)) {
-                       case Q_TYPE_ITD:
-                               /* If this ITD is still active, leave it for
-                                * later processing ... check the next entry.
-                                * No need to check for activity unless the
-                                * frame is current.
-                                */
-                               if (frame == now_frame && live) {
-                                       rmb();
-                                       for (uf = 0; uf < 8; uf++) {
-                                               if (q.itd->hw_transaction[uf] &
-                                                           ITD_ACTIVE(fotg210))
-                                                       break;
-                                       }
-                                       if (uf < 8) {
-                                               q_p = &q.itd->itd_next;
-                                               hw_p = &q.itd->hw_next;
-                                               type = Q_NEXT_TYPE(fotg210,
-                                                       q.itd->hw_next);
-                                               q = *q_p;
-                                               break;
-                                       }
-                               }
-
-                               /* Take finished ITDs out of the schedule
-                                * and process them:  recycle, maybe report
-                                * URB completion.  HC won't cache the
-                                * pointer for much longer, if at all.
-                                */
-                               *q_p = q.itd->itd_next;
-                               *hw_p = q.itd->hw_next;
-                               type = Q_NEXT_TYPE(fotg210, q.itd->hw_next);
-                               wmb();
-                               modified = itd_complete(fotg210, q.itd);
-                               q = *q_p;
-                               break;
-                       default:
-                               fotg210_dbg(fotg210, "corrupt type %d frame %d shadow %p\n",
-                                       type, frame, q.ptr);
-                               /* FALL THROUGH */
-                       case Q_TYPE_QH:
-                       case Q_TYPE_FSTN:
-                               /* End of the iTDs and siTDs */
-                               q.ptr = NULL;
-                               break;
-                       }
-
-                       /* assume completion callbacks modify the queue */
-                       if (unlikely(modified && fotg210->isoc_count > 0))
-                               goto restart;
-               }
+               ret = 1;
+               while (ret != 0)
+                       ret = scan_frame_queue(fotg210, frame,
+                                       now_frame, live);
 
                /* Stop when we have reached the current frame */
                if (frame == now_frame)
@@ -4897,16 +4712,14 @@ restart:
        }
        fotg210->next_frame = now_frame;
 }
-/*-------------------------------------------------------------------------*/
-/*
- * Display / Set uframe_periodic_max
+
+/* Display / Set uframe_periodic_max
  */
 static ssize_t show_uframe_periodic_max(struct device *dev,
-                                       struct device_attribute *attr,
-                                       char *buf)
+               struct device_attribute *attr, char *buf)
 {
-       struct fotg210_hcd              *fotg210;
-       int                     n;
+       struct fotg210_hcd *fotg210;
+       int n;
 
        fotg210 = hcd_to_fotg210(bus_to_hcd(dev_get_drvdata(dev)));
        n = scnprintf(buf, PAGE_SIZE, "%d\n", fotg210->uframe_periodic_max);
@@ -4915,15 +4728,14 @@ static ssize_t show_uframe_periodic_max(struct device *dev,
 
 
 static ssize_t store_uframe_periodic_max(struct device *dev,
-                                       struct device_attribute *attr,
-                                       const char *buf, size_t count)
+               struct device_attribute *attr, const char *buf, size_t count)
 {
-       struct fotg210_hcd      *fotg210;
-       unsigned                uframe_periodic_max;
-       unsigned                frame, uframe;
-       unsigned short          allocated_max;
-       unsigned long           flags;
-       ssize_t                 ret;
+       struct fotg210_hcd *fotg210;
+       unsigned uframe_periodic_max;
+       unsigned frame, uframe;
+       unsigned short allocated_max;
+       unsigned long flags;
+       ssize_t ret;
 
        fotg210 = hcd_to_fotg210(bus_to_hcd(dev_get_drvdata(dev)));
        if (kstrtouint(buf, 0, &uframe_periodic_max) < 0)
@@ -4931,7 +4743,7 @@ static ssize_t store_uframe_periodic_max(struct device *dev,
 
        if (uframe_periodic_max < 100 || uframe_periodic_max >= 125) {
                fotg210_info(fotg210, "rejecting invalid request for uframe_periodic_max=%u\n",
-                            uframe_periodic_max);
+                               uframe_periodic_max);
                return -EINVAL;
        }
 
@@ -4954,22 +4766,22 @@ static ssize_t store_uframe_periodic_max(struct device *dev,
                for (frame = 0; frame < fotg210->periodic_size; ++frame)
                        for (uframe = 0; uframe < 7; ++uframe)
                                allocated_max = max(allocated_max,
-                                                   periodic_usecs(fotg210, frame, uframe));
+                                               periodic_usecs(fotg210, frame,
+                                               uframe));
 
                if (allocated_max > uframe_periodic_max) {
                        fotg210_info(fotg210,
-                               "cannot decrease uframe_periodic_max because "
-                               "periodic bandwidth is already allocated "
-                               "(%u > %u)\n",
-                               allocated_max, uframe_periodic_max);
+                                       "cannot decrease uframe_periodic_max because periodic bandwidth is already allocated (%u > %u)\n",
+                                       allocated_max, uframe_periodic_max);
                        goto out_unlock;
                }
        }
 
        /* increasing is always ok */
 
-       fotg210_info(fotg210, "setting max periodic bandwidth to %u%% (== %u usec/uframe)\n",
-                    100 * uframe_periodic_max/125, uframe_periodic_max);
+       fotg210_info(fotg210,
+                       "setting max periodic bandwidth to %u%% (== %u usec/uframe)\n",
+                       100 * uframe_periodic_max/125, uframe_periodic_max);
 
        if (uframe_periodic_max != 100)
                fotg210_warn(fotg210, "max periodic bandwidth set is non-standard\n");
@@ -4987,8 +4799,8 @@ static DEVICE_ATTR(uframe_periodic_max, 0644, show_uframe_periodic_max,
 
 static inline int create_sysfs_files(struct fotg210_hcd *fotg210)
 {
-       struct device   *controller = fotg210_to_hcd(fotg210)->self.controller;
-       int     i = 0;
+       struct device *controller = fotg210_to_hcd(fotg210)->self.controller;
+       int i = 0;
 
        if (i)
                goto out;
@@ -5000,12 +4812,10 @@ out:
 
 static inline void remove_sysfs_files(struct fotg210_hcd *fotg210)
 {
-       struct device   *controller = fotg210_to_hcd(fotg210)->self.controller;
+       struct device *controller = fotg210_to_hcd(fotg210)->self.controller;
 
        device_remove_file(controller, &dev_attr_uframe_periodic_max);
 }
-/*-------------------------------------------------------------------------*/
-
 /* On some systems, leaving remote wakeup enabled prevents system shutdown.
  * The firmware seems to think that powering off is a wakeup event!
  * This routine turns off remote wakeup and everything else, on all ports.
@@ -5017,8 +4827,7 @@ static void fotg210_turn_off_all_ports(struct fotg210_hcd *fotg210)
        fotg210_writel(fotg210, PORT_RWC_BITS, status_reg);
 }
 
-/*
- * Halt HC, turn off all ports, and let the BIOS use the companion controllers.
+/* Halt HC, turn off all ports, and let the BIOS use the companion controllers.
  * Must be called with interrupts enabled and the lock not held.
  */
 static void fotg210_silence_controller(struct fotg210_hcd *fotg210)
@@ -5037,7 +4846,7 @@ static void fotg210_silence_controller(struct fotg210_hcd *fotg210)
  */
 static void fotg210_shutdown(struct usb_hcd *hcd)
 {
-       struct fotg210_hcd      *fotg210 = hcd_to_fotg210(hcd);
+       struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
 
        spin_lock_irq(&fotg210->lock);
        fotg210->shutdown = true;
@@ -5050,10 +4859,7 @@ static void fotg210_shutdown(struct usb_hcd *hcd)
        hrtimer_cancel(&fotg210->hrtimer);
 }
 
-/*-------------------------------------------------------------------------*/
-
-/*
- * fotg210_work is called from some interrupts, timers, and so on.
+/* fotg210_work is called from some interrupts, timers, and so on.
  * it calls driver completion functions, after dropping fotg210->lock.
  */
 static void fotg210_work(struct fotg210_hcd *fotg210)
@@ -5068,7 +4874,7 @@ static void fotg210_work(struct fotg210_hcd *fotg210)
        }
        fotg210->scanning = true;
 
- rescan:
+rescan:
        fotg210->need_rescan = false;
        if (fotg210->async_count)
                scan_async(fotg210);
@@ -5087,12 +4893,11 @@ static void fotg210_work(struct fotg210_hcd *fotg210)
        turn_on_io_watchdog(fotg210);
 }
 
-/*
- * Called when the fotg210_hcd module is removed.
+/* Called when the fotg210_hcd module is removed.
  */
 static void fotg210_stop(struct usb_hcd *hcd)
 {
-       struct fotg210_hcd              *fotg210 = hcd_to_fotg210(hcd);
+       struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
 
        fotg210_dbg(fotg210, "stop\n");
 
@@ -5116,26 +4921,26 @@ static void fotg210_stop(struct usb_hcd *hcd)
        spin_unlock_irq(&fotg210->lock);
        fotg210_mem_cleanup(fotg210);
 
-#ifdef FOTG210_STATS
+#ifdef FOTG210_STATS
        fotg210_dbg(fotg210, "irq normal %ld err %ld iaa %ld (lost %ld)\n",
-               fotg210->stats.normal, fotg210->stats.error, fotg210->stats.iaa,
-               fotg210->stats.lost_iaa);
+                       fotg210->stats.normal, fotg210->stats.error,
+                       fotg210->stats.iaa, fotg210->stats.lost_iaa);
        fotg210_dbg(fotg210, "complete %ld unlink %ld\n",
-               fotg210->stats.complete, fotg210->stats.unlink);
+                       fotg210->stats.complete, fotg210->stats.unlink);
 #endif
 
        dbg_status(fotg210, "fotg210_stop completed",
-                   fotg210_readl(fotg210, &fotg210->regs->status));
+                       fotg210_readl(fotg210, &fotg210->regs->status));
 }
 
 /* one-time init, only for memory state */
 static int hcd_fotg210_init(struct usb_hcd *hcd)
 {
-       struct fotg210_hcd              *fotg210 = hcd_to_fotg210(hcd);
-       u32                     temp;
-       int                     retval;
-       u32                     hcc_params;
-       struct fotg210_qh_hw    *hw;
+       struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+       u32 temp;
+       int retval;
+       u32 hcc_params;
+       struct fotg210_qh_hw *hw;
 
        spin_lock_init(&fotg210->lock);
 
@@ -5238,18 +5043,18 @@ static int hcd_fotg210_init(struct usb_hcd *hcd)
 /* start HC running; it's halted, hcd_fotg210_init() has been run (once) */
 static int fotg210_run(struct usb_hcd *hcd)
 {
-       struct fotg210_hcd              *fotg210 = hcd_to_fotg210(hcd);
-       u32                     temp;
-       u32                     hcc_params;
+       struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+       u32 temp;
+       u32 hcc_params;
 
        hcd->uses_new_polling = 1;
 
        /* EHCI spec section 4.1 */
 
        fotg210_writel(fotg210, fotg210->periodic_dma,
-                      &fotg210->regs->frame_list);
+                       &fotg210->regs->frame_list);
        fotg210_writel(fotg210, (u32)fotg210->async->qh_dma,
-                      &fotg210->regs->async_next);
+                       &fotg210->regs->async_next);
 
        /*
         * hcc_params controls whether fotg210->regs->segment must (!!!)
@@ -5292,19 +5097,19 @@ static int fotg210_run(struct usb_hcd *hcd)
        fotg210->rh_state = FOTG210_RH_RUNNING;
        /* unblock posted writes */
        fotg210_readl(fotg210, &fotg210->regs->command);
-       msleep(5);
+       usleep_range(5000, 10000);
        up_write(&ehci_cf_port_reset_rwsem);
        fotg210->last_periodic_enable = ktime_get_real();
 
        temp = HC_VERSION(fotg210,
-                         fotg210_readl(fotg210, &fotg210->caps->hc_capbase));
+                       fotg210_readl(fotg210, &fotg210->caps->hc_capbase));
        fotg210_info(fotg210,
-               "USB %x.%x started, EHCI %x.%02x\n",
-               ((fotg210->sbrn & 0xf0)>>4), (fotg210->sbrn & 0x0f),
-               temp >> 8, temp & 0xff);
+                       "USB %x.%x started, EHCI %x.%02x\n",
+                       ((fotg210->sbrn & 0xf0) >> 4), (fotg210->sbrn & 0x0f),
+                       temp >> 8, temp & 0xff);
 
        fotg210_writel(fotg210, INTR_MASK,
-                   &fotg210->regs->intr_enable); /* Turn On Interrupts */
+                       &fotg210->regs->intr_enable); /* Turn On Interrupts */
 
        /* GRR this is run-once init(), being done every time the HC starts.
         * So long as they're part of class devices, we can't do it init()
@@ -5322,14 +5127,14 @@ static int fotg210_setup(struct usb_hcd *hcd)
        int retval;
 
        fotg210->regs = (void __iomem *)fotg210->caps +
-           HC_LENGTH(fotg210,
-                     fotg210_readl(fotg210, &fotg210->caps->hc_capbase));
+                       HC_LENGTH(fotg210,
+                       fotg210_readl(fotg210, &fotg210->caps->hc_capbase));
        dbg_hcs_params(fotg210, "reset");
        dbg_hcc_params(fotg210, "reset");
 
        /* cache this readonly data; minimize chip reads */
        fotg210->hcs_params = fotg210_readl(fotg210,
-                                           &fotg210->caps->hcs_params);
+                       &fotg210->caps->hcs_params);
 
        fotg210->sbrn = HCD_USB2;
 
@@ -5347,13 +5152,11 @@ static int fotg210_setup(struct usb_hcd *hcd)
        return 0;
 }
 
-/*-------------------------------------------------------------------------*/
-
 static irqreturn_t fotg210_irq(struct usb_hcd *hcd)
 {
-       struct fotg210_hcd              *fotg210 = hcd_to_fotg210(hcd);
-       u32                     status, masked_status, pcd_status = 0, cmd;
-       int                     bh;
+       struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+       u32 status, masked_status, pcd_status = 0, cmd;
+       int bh;
 
        spin_lock(&fotg210->lock);
 
@@ -5373,7 +5176,7 @@ static irqreturn_t fotg210_irq(struct usb_hcd *hcd)
 
        /* Shared IRQ? */
        if (!masked_status ||
-           unlikely(fotg210->rh_state == FOTG210_RH_HALTED)) {
+                       unlikely(fotg210->rh_state == FOTG210_RH_HALTED)) {
                spin_unlock(&fotg210->lock);
                return IRQ_NONE;
        }
@@ -5440,7 +5243,7 @@ static irqreturn_t fotg210_irq(struct usb_hcd *hcd)
 
                if (test_bit(0, &fotg210->suspended_ports) &&
                                ((pstatus & PORT_RESUME) ||
-                                       !(pstatus & PORT_SUSPEND)) &&
+                               !(pstatus & PORT_SUSPEND)) &&
                                (pstatus & PORT_PE) &&
                                fotg210->reset_done[0] == 0) {
 
@@ -5469,7 +5272,7 @@ dead:
                fotg210->rh_state = FOTG210_RH_STOPPING;
                fotg210->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE);
                fotg210_writel(fotg210, fotg210->command,
-                              &fotg210->regs->command);
+                               &fotg210->regs->command);
                fotg210_writel(fotg210, 0, &fotg210->regs->intr_enable);
                fotg210_handle_controller_death(fotg210);
 
@@ -5485,10 +5288,7 @@ dead:
        return IRQ_HANDLED;
 }
 
-/*-------------------------------------------------------------------------*/
-
-/*
- * non-error returns are a promise to giveback() the urb later
+/* non-error returns are a promise to giveback() the urb later
  * we drop ownership so next owner (or urb unlink) can get it
  *
  * urb + dev is in hcd.self.controller.urb_list
@@ -5499,13 +5299,11 @@ dead:
  * NOTE:  control, bulk, and interrupt share the same code to append TDs
  * to a (possibly active) QH, and the same QH scanning code.
  */
-static int fotg210_urb_enqueue(
-       struct usb_hcd  *hcd,
-       struct urb      *urb,
-       gfp_t           mem_flags
-) {
-       struct fotg210_hcd              *fotg210 = hcd_to_fotg210(hcd);
-       struct list_head        qtd_list;
+static int fotg210_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+               gfp_t mem_flags)
+{
+       struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+       struct list_head qtd_list;
 
        INIT_LIST_HEAD(&qtd_list);
 
@@ -5539,10 +5337,10 @@ static int fotg210_urb_enqueue(
 
 static int fotg210_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 {
-       struct fotg210_hcd              *fotg210 = hcd_to_fotg210(hcd);
-       struct fotg210_qh               *qh;
-       unsigned long           flags;
-       int                     rc;
+       struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+       struct fotg210_qh *qh;
+       unsigned long flags;
+       int rc;
 
        spin_lock_irqsave(&fotg210->lock, flags);
        rc = usb_hcd_check_unlink_urb(hcd, urb, status);
@@ -5603,16 +5401,14 @@ done:
        return rc;
 }
 
-/*-------------------------------------------------------------------------*/
-
 /* bulk qh holds the data toggle */
 
-static void
-fotg210_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+static void fotg210_endpoint_disable(struct usb_hcd *hcd,
+               struct usb_host_endpoint *ep)
 {
-       struct fotg210_hcd              *fotg210 = hcd_to_fotg210(hcd);
-       unsigned long           flags;
-       struct fotg210_qh               *qh, *tmp;
+       struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+       unsigned long flags;
+       struct fotg210_qh *qh, *tmp;
 
        /* ASSERT:  any requests/urbs are being unlinked */
        /* ASSERT:  nobody can be submitting urbs for this any more */
@@ -5627,7 +5423,7 @@ rescan:
         * accelerate iso completions ... so spin a while.
         */
        if (qh->hw == NULL) {
-               struct fotg210_iso_stream       *stream = ep->hcpriv;
+               struct fotg210_iso_stream *stream = ep->hcpriv;
 
                if (!list_empty(&stream->td_list))
                        goto idle_timeout;
@@ -5671,24 +5467,24 @@ idle_timeout:
                 * that's not our job.  just leak this memory.
                 */
                fotg210_err(fotg210, "qh %p (#%02x) state %d%s\n",
-                       qh, ep->desc.bEndpointAddress, qh->qh_state,
-                       list_empty(&qh->qtd_list) ? "" : "(has tds)");
+                               qh, ep->desc.bEndpointAddress, qh->qh_state,
+                               list_empty(&qh->qtd_list) ? "" : "(has tds)");
                break;
        }
- done:
+done:
        ep->hcpriv = NULL;
        spin_unlock_irqrestore(&fotg210->lock, flags);
 }
 
-static void
-fotg210_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
+static void fotg210_endpoint_reset(struct usb_hcd *hcd,
+               struct usb_host_endpoint *ep)
 {
-       struct fotg210_hcd              *fotg210 = hcd_to_fotg210(hcd);
-       struct fotg210_qh               *qh;
-       int                     eptype = usb_endpoint_type(&ep->desc);
-       int                     epnum = usb_endpoint_num(&ep->desc);
-       int                     is_out = usb_endpoint_dir_out(&ep->desc);
-       unsigned long           flags;
+       struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+       struct fotg210_qh *qh;
+       int eptype = usb_endpoint_type(&ep->desc);
+       int epnum = usb_endpoint_num(&ep->desc);
+       int is_out = usb_endpoint_dir_out(&ep->desc);
+       unsigned long flags;
 
        if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT)
                return;
@@ -5723,15 +5519,13 @@ fotg210_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
 
 static int fotg210_get_frame(struct usb_hcd *hcd)
 {
-       struct fotg210_hcd              *fotg210 = hcd_to_fotg210(hcd);
+       struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
+
        return (fotg210_read_frame_index(fotg210) >> 3) %
                fotg210->periodic_size;
 }
 
-/*-------------------------------------------------------------------------*/
-
-/*
- * The EHCI in ChipIdea HDRC cannot be a separate module or device,
+/* The EHCI in ChipIdea HDRC cannot be a separate module or device,
  * because its registers (and irq) are shared between host/gadget/otg
  * functions  and in order to facilitate role switching we cannot
  * give the fotg210 driver exclusive access to those.
@@ -5791,7 +5585,7 @@ static void fotg210_init(struct fotg210_hcd *fotg210)
        u32 value;
 
        iowrite32(GMIR_MDEV_INT | GMIR_MOTG_INT | GMIR_INT_POLARITY,
-                 &fotg210->regs->gmir);
+                       &fotg210->regs->gmir);
 
        value = ioread32(&fotg210->regs->otgcsr);
        value &= ~OTGCSR_A_BUS_DROP;
@@ -5808,12 +5602,12 @@ static void fotg210_init(struct fotg210_hcd *fotg210)
  */
 static int fotg210_hcd_probe(struct platform_device *pdev)
 {
-       struct device                   *dev = &pdev->dev;
-       struct usb_hcd                  *hcd;
-       struct resource                 *res;
-       int                             irq;
-       int                             retval = -ENODEV;
-       struct fotg210_hcd              *fotg210;
+       struct device *dev = &pdev->dev;
+       struct usb_hcd *hcd;
+       struct resource *res;
+       int irq;
+       int retval = -ENODEV;
+       struct fotg210_hcd *fotg210;
 
        if (usb_disabled())
                return -ENODEV;
@@ -5822,9 +5616,8 @@ static int fotg210_hcd_probe(struct platform_device *pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (!res) {
-               dev_err(dev,
-                       "Found HC with no IRQ. Check %s setup!\n",
-                       dev_name(dev));
+               dev_err(dev, "Found HC with no IRQ. Check %s setup!\n",
+                               dev_name(dev));
                return -ENODEV;
        }
 
@@ -5883,8 +5676,8 @@ fail_create_hcd:
  */
 static int fotg210_hcd_remove(struct platform_device *pdev)
 {
-       struct device *dev      = &pdev->dev;
-       struct usb_hcd *hcd     = dev_get_drvdata(dev);
+       struct device *dev = &pdev->dev;
+       struct usb_hcd *hcd = dev_get_drvdata(dev);
 
        if (!hcd)
                return 0;
@@ -5914,12 +5707,12 @@ static int __init fotg210_hcd_init(void)
        set_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
        if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) ||
                        test_bit(USB_OHCI_LOADED, &usb_hcds_loaded))
-               pr_warn(KERN_WARNING "Warning! fotg210_hcd should always be loaded before uhci_hcd and ohci_hcd, not after\n");
+               pr_warn("Warning! fotg210_hcd should always be loaded before uhci_hcd and ohci_hcd, not after\n");
 
        pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd\n",
-                hcd_name,
-                sizeof(struct fotg210_qh), sizeof(struct fotg210_qtd),
-                sizeof(struct fotg210_itd));
+                       hcd_name, sizeof(struct fotg210_qh),
+                       sizeof(struct fotg210_qtd),
+                       sizeof(struct fotg210_itd));
 
        fotg210_debug_root = debugfs_create_dir("fotg210", usb_debug_root);
        if (!fotg210_debug_root) {
@@ -5932,7 +5725,6 @@ static int __init fotg210_hcd_init(void)
                goto clean;
        return retval;
 
-       platform_driver_unregister(&fotg210_hcd_driver);
 clean:
        debugfs_remove(fotg210_debug_root);
        fotg210_debug_root = NULL;
index 3bad17859cd72aebabd07750693e5bfe1b9bb78c..b5cfa7aeb277c783a9931931e4d902e40c92bf3b 100644 (file)
@@ -137,19 +137,25 @@ struct fotg210_hcd {                      /* one per controller */
        /* per root hub port */
        unsigned long           reset_done[FOTG210_MAX_ROOT_PORTS];
 
-       /* bit vectors (one bit per port) */
-       unsigned long           bus_suspended;          /* which ports were
-                       already suspended at the start of a bus suspend */
-       unsigned long           companion_ports;        /* which ports are
-                       dedicated to the companion controller */
-       unsigned long           owned_ports;            /* which ports are
-                       owned by the companion during a bus suspend */
-       unsigned long           port_c_suspend;         /* which ports have
-                       the change-suspend feature turned on */
-       unsigned long           suspended_ports;        /* which ports are
-                       suspended */
-       unsigned long           resuming_ports;         /* which ports have
-                       started to resume */
+       /* bit vectors (one bit per port)
+        * which ports were already suspended at the start of a bus suspend
+        */
+       unsigned long           bus_suspended;
+
+       /* which ports are edicated to the companion controller */
+       unsigned long           companion_ports;
+
+       /* which ports are owned by the companion during a bus suspend */
+       unsigned long           owned_ports;
+
+       /* which ports have the change-suspend feature turned on */
+       unsigned long           port_c_suspend;
+
+       /* which ports are suspended */
+       unsigned long           suspended_ports;
+
+       /* which ports have started to resume */
+       unsigned long           resuming_ports;
 
        /* per-HC memory pools (could be per-bus, but ...) */
        struct dma_pool         *qh_pool;       /* qh per active urb */
@@ -585,10 +591,10 @@ struct fotg210_fstn {
 /* Prepare the PORTSC wakeup flags during controller suspend/resume */
 
 #define fotg210_prepare_ports_for_controller_suspend(fotg210, do_wakeup) \
-               fotg210_adjust_port_wakeup_flags(fotg210, true, do_wakeup);
+               fotg210_adjust_port_wakeup_flags(fotg210, true, do_wakeup)
 
 #define fotg210_prepare_ports_for_controller_resume(fotg210)           \
-               fotg210_adjust_port_wakeup_flags(fotg210, false, false);
+               fotg210_adjust_port_wakeup_flags(fotg210, false, false)
 
 /*-------------------------------------------------------------------------*/
 
index 534c4c5d278a31838f9afe7a7421a4397aa3d431..0c382652a3991fdd26cd5316b2eab9720d72b010 100644 (file)
@@ -351,6 +351,7 @@ static const struct of_device_id fsl_usb2_mph_dr_of_match[] = {
 #endif
        {},
 };
+MODULE_DEVICE_TABLE(of, fsl_usb2_mph_dr_of_match);
 
 static struct platform_driver fsl_usb2_mph_dr_driver = {
        .driver = {
diff --git a/drivers/usb/host/fusbh200-hcd.c b/drivers/usb/host/fusbh200-hcd.c
deleted file mode 100644 (file)
index 1fd8718..0000000
+++ /dev/null
@@ -1,5894 +0,0 @@
-/*
- * Faraday FUSBH200 EHCI-like driver
- *
- * Copyright (c) 2013 Faraday Technology Corporation
- *
- * Author: Yuan-Hsin Chen <yhchen@faraday-tech.com>
- *        Feng-Hsin Chiang <john453@faraday-tech.com>
- *        Po-Yu Chuang <ratbert.chuang@gmail.com>
- *
- * Most of code borrowed from the Linux-3.7 EHCI driver
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/dmapool.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/vmalloc.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/hrtimer.h>
-#include <linux/list.h>
-#include <linux/interrupt.h>
-#include <linux/usb.h>
-#include <linux/usb/hcd.h>
-#include <linux/moduleparam.h>
-#include <linux/dma-mapping.h>
-#include <linux/debugfs.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/platform_device.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/unaligned.h>
-
-/*-------------------------------------------------------------------------*/
-#define DRIVER_AUTHOR "Yuan-Hsin Chen"
-#define DRIVER_DESC "FUSBH200 Host Controller (EHCI) Driver"
-
-static const char      hcd_name [] = "fusbh200_hcd";
-
-#undef FUSBH200_URB_TRACE
-
-/* magic numbers that can affect system performance */
-#define        FUSBH200_TUNE_CERR              3       /* 0-3 qtd retries; 0 == don't stop */
-#define        FUSBH200_TUNE_RL_HS             4       /* nak throttle; see 4.9 */
-#define        FUSBH200_TUNE_RL_TT             0
-#define        FUSBH200_TUNE_MULT_HS   1       /* 1-3 transactions/uframe; 4.10.3 */
-#define        FUSBH200_TUNE_MULT_TT   1
-/*
- * Some drivers think it's safe to schedule isochronous transfers more than
- * 256 ms into the future (partly as a result of an old bug in the scheduling
- * code).  In an attempt to avoid trouble, we will use a minimum scheduling
- * length of 512 frames instead of 256.
- */
-#define        FUSBH200_TUNE_FLS               1       /* (medium) 512-frame schedule */
-
-/* Initial IRQ latency:  faster than hw default */
-static int log2_irq_thresh = 0;                // 0 to 6
-module_param (log2_irq_thresh, int, S_IRUGO);
-MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes");
-
-/* initial park setting:  slower than hw default */
-static unsigned park = 0;
-module_param (park, uint, S_IRUGO);
-MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets");
-
-/* for link power management(LPM) feature */
-static unsigned int hird;
-module_param(hird, int, S_IRUGO);
-MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us");
-
-#define        INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
-
-#include "fusbh200.h"
-
-/*-------------------------------------------------------------------------*/
-
-#define fusbh200_dbg(fusbh200, fmt, args...) \
-       dev_dbg (fusbh200_to_hcd(fusbh200)->self.controller , fmt , ## args )
-#define fusbh200_err(fusbh200, fmt, args...) \
-       dev_err (fusbh200_to_hcd(fusbh200)->self.controller , fmt , ## args )
-#define fusbh200_info(fusbh200, fmt, args...) \
-       dev_info (fusbh200_to_hcd(fusbh200)->self.controller , fmt , ## args )
-#define fusbh200_warn(fusbh200, fmt, args...) \
-       dev_warn (fusbh200_to_hcd(fusbh200)->self.controller , fmt , ## args )
-
-/* check the values in the HCSPARAMS register
- * (host controller _Structural_ parameters)
- * see EHCI spec, Table 2-4 for each value
- */
-static void dbg_hcs_params (struct fusbh200_hcd *fusbh200, char *label)
-{
-       u32     params = fusbh200_readl(fusbh200, &fusbh200->caps->hcs_params);
-
-       fusbh200_dbg (fusbh200,
-               "%s hcs_params 0x%x ports=%d\n",
-               label, params,
-               HCS_N_PORTS (params)
-               );
-}
-
-/* check the values in the HCCPARAMS register
- * (host controller _Capability_ parameters)
- * see EHCI Spec, Table 2-5 for each value
- * */
-static void dbg_hcc_params (struct fusbh200_hcd *fusbh200, char *label)
-{
-       u32     params = fusbh200_readl(fusbh200, &fusbh200->caps->hcc_params);
-
-       fusbh200_dbg (fusbh200,
-               "%s hcc_params %04x uframes %s%s\n",
-               label,
-               params,
-               HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024",
-               HCC_CANPARK(params) ? " park" : "");
-}
-
-static void __maybe_unused
-dbg_qtd (const char *label, struct fusbh200_hcd *fusbh200, struct fusbh200_qtd *qtd)
-{
-       fusbh200_dbg(fusbh200, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
-               hc32_to_cpup(fusbh200, &qtd->hw_next),
-               hc32_to_cpup(fusbh200, &qtd->hw_alt_next),
-               hc32_to_cpup(fusbh200, &qtd->hw_token),
-               hc32_to_cpup(fusbh200, &qtd->hw_buf [0]));
-       if (qtd->hw_buf [1])
-               fusbh200_dbg(fusbh200, "  p1=%08x p2=%08x p3=%08x p4=%08x\n",
-                       hc32_to_cpup(fusbh200, &qtd->hw_buf[1]),
-                       hc32_to_cpup(fusbh200, &qtd->hw_buf[2]),
-                       hc32_to_cpup(fusbh200, &qtd->hw_buf[3]),
-                       hc32_to_cpup(fusbh200, &qtd->hw_buf[4]));
-}
-
-static void __maybe_unused
-dbg_qh (const char *label, struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
-       struct fusbh200_qh_hw *hw = qh->hw;
-
-       fusbh200_dbg (fusbh200, "%s qh %p n%08x info %x %x qtd %x\n", label,
-               qh, hw->hw_next, hw->hw_info1, hw->hw_info2, hw->hw_current);
-       dbg_qtd("overlay", fusbh200, (struct fusbh200_qtd *) &hw->hw_qtd_next);
-}
-
-static void __maybe_unused
-dbg_itd (const char *label, struct fusbh200_hcd *fusbh200, struct fusbh200_itd *itd)
-{
-       fusbh200_dbg (fusbh200, "%s [%d] itd %p, next %08x, urb %p\n",
-               label, itd->frame, itd, hc32_to_cpu(fusbh200, itd->hw_next),
-               itd->urb);
-       fusbh200_dbg (fusbh200,
-               "  trans: %08x %08x %08x %08x %08x %08x %08x %08x\n",
-               hc32_to_cpu(fusbh200, itd->hw_transaction[0]),
-               hc32_to_cpu(fusbh200, itd->hw_transaction[1]),
-               hc32_to_cpu(fusbh200, itd->hw_transaction[2]),
-               hc32_to_cpu(fusbh200, itd->hw_transaction[3]),
-               hc32_to_cpu(fusbh200, itd->hw_transaction[4]),
-               hc32_to_cpu(fusbh200, itd->hw_transaction[5]),
-               hc32_to_cpu(fusbh200, itd->hw_transaction[6]),
-               hc32_to_cpu(fusbh200, itd->hw_transaction[7]));
-       fusbh200_dbg (fusbh200,
-               "  buf:   %08x %08x %08x %08x %08x %08x %08x\n",
-               hc32_to_cpu(fusbh200, itd->hw_bufp[0]),
-               hc32_to_cpu(fusbh200, itd->hw_bufp[1]),
-               hc32_to_cpu(fusbh200, itd->hw_bufp[2]),
-               hc32_to_cpu(fusbh200, itd->hw_bufp[3]),
-               hc32_to_cpu(fusbh200, itd->hw_bufp[4]),
-               hc32_to_cpu(fusbh200, itd->hw_bufp[5]),
-               hc32_to_cpu(fusbh200, itd->hw_bufp[6]));
-       fusbh200_dbg (fusbh200, "  index: %d %d %d %d %d %d %d %d\n",
-               itd->index[0], itd->index[1], itd->index[2],
-               itd->index[3], itd->index[4], itd->index[5],
-               itd->index[6], itd->index[7]);
-}
-
-static int __maybe_unused
-dbg_status_buf (char *buf, unsigned len, const char *label, u32 status)
-{
-       return scnprintf (buf, len,
-               "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s",
-               label, label [0] ? " " : "", status,
-               (status & STS_ASS) ? " Async" : "",
-               (status & STS_PSS) ? " Periodic" : "",
-               (status & STS_RECL) ? " Recl" : "",
-               (status & STS_HALT) ? " Halt" : "",
-               (status & STS_IAA) ? " IAA" : "",
-               (status & STS_FATAL) ? " FATAL" : "",
-               (status & STS_FLR) ? " FLR" : "",
-               (status & STS_PCD) ? " PCD" : "",
-               (status & STS_ERR) ? " ERR" : "",
-               (status & STS_INT) ? " INT" : ""
-               );
-}
-
-static int __maybe_unused
-dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable)
-{
-       return scnprintf (buf, len,
-               "%s%sintrenable %02x%s%s%s%s%s%s",
-               label, label [0] ? " " : "", enable,
-               (enable & STS_IAA) ? " IAA" : "",
-               (enable & STS_FATAL) ? " FATAL" : "",
-               (enable & STS_FLR) ? " FLR" : "",
-               (enable & STS_PCD) ? " PCD" : "",
-               (enable & STS_ERR) ? " ERR" : "",
-               (enable & STS_INT) ? " INT" : ""
-               );
-}
-
-static const char *const fls_strings [] =
-    { "1024", "512", "256", "??" };
-
-static int
-dbg_command_buf (char *buf, unsigned len, const char *label, u32 command)
-{
-       return scnprintf (buf, len,
-               "%s%scommand %07x %s=%d ithresh=%d%s%s%s "
-               "period=%s%s %s",
-               label, label [0] ? " " : "", command,
-               (command & CMD_PARK) ? " park" : "(park)",
-               CMD_PARK_CNT (command),
-               (command >> 16) & 0x3f,
-               (command & CMD_IAAD) ? " IAAD" : "",
-               (command & CMD_ASE) ? " Async" : "",
-               (command & CMD_PSE) ? " Periodic" : "",
-               fls_strings [(command >> 2) & 0x3],
-               (command & CMD_RESET) ? " Reset" : "",
-               (command & CMD_RUN) ? "RUN" : "HALT"
-               );
-}
-
-static int
-dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status)
-{
-       char    *sig;
-
-       /* signaling state */
-       switch (status & (3 << 10)) {
-       case 0 << 10: sig = "se0"; break;
-       case 1 << 10: sig = "k"; break;         /* low speed */
-       case 2 << 10: sig = "j"; break;
-       default: sig = "?"; break;
-       }
-
-       return scnprintf (buf, len,
-               "%s%sport:%d status %06x %d "
-               "sig=%s%s%s%s%s%s%s%s",
-               label, label [0] ? " " : "", port, status,
-               status>>25,/*device address */
-               sig,
-               (status & PORT_RESET) ? " RESET" : "",
-               (status & PORT_SUSPEND) ? " SUSPEND" : "",
-               (status & PORT_RESUME) ? " RESUME" : "",
-               (status & PORT_PEC) ? " PEC" : "",
-               (status & PORT_PE) ? " PE" : "",
-               (status & PORT_CSC) ? " CSC" : "",
-               (status & PORT_CONNECT) ? " CONNECT" : "");
-}
-
-/* functions have the "wrong" filename when they're output... */
-#define dbg_status(fusbh200, label, status) { \
-       char _buf [80]; \
-       dbg_status_buf (_buf, sizeof _buf, label, status); \
-       fusbh200_dbg (fusbh200, "%s\n", _buf); \
-}
-
-#define dbg_cmd(fusbh200, label, command) { \
-       char _buf [80]; \
-       dbg_command_buf (_buf, sizeof _buf, label, command); \
-       fusbh200_dbg (fusbh200, "%s\n", _buf); \
-}
-
-#define dbg_port(fusbh200, label, port, status) { \
-       char _buf [80]; \
-       dbg_port_buf (_buf, sizeof _buf, label, port, status); \
-       fusbh200_dbg (fusbh200, "%s\n", _buf); \
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* troubleshooting help: expose state in debugfs */
-
-static int debug_async_open(struct inode *, struct file *);
-static int debug_periodic_open(struct inode *, struct file *);
-static int debug_registers_open(struct inode *, struct file *);
-static int debug_async_open(struct inode *, struct file *);
-
-static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*);
-static int debug_close(struct inode *, struct file *);
-
-static const struct file_operations debug_async_fops = {
-       .owner          = THIS_MODULE,
-       .open           = debug_async_open,
-       .read           = debug_output,
-       .release        = debug_close,
-       .llseek         = default_llseek,
-};
-static const struct file_operations debug_periodic_fops = {
-       .owner          = THIS_MODULE,
-       .open           = debug_periodic_open,
-       .read           = debug_output,
-       .release        = debug_close,
-       .llseek         = default_llseek,
-};
-static const struct file_operations debug_registers_fops = {
-       .owner          = THIS_MODULE,
-       .open           = debug_registers_open,
-       .read           = debug_output,
-       .release        = debug_close,
-       .llseek         = default_llseek,
-};
-
-static struct dentry *fusbh200_debug_root;
-
-struct debug_buffer {
-       ssize_t (*fill_func)(struct debug_buffer *);    /* fill method */
-       struct usb_bus *bus;
-       struct mutex mutex;     /* protect filling of buffer */
-       size_t count;           /* number of characters filled into buffer */
-       char *output_buf;
-       size_t alloc_size;
-};
-
-#define speed_char(info1) ({ char tmp; \
-               switch (info1 & (3 << 12)) { \
-               case QH_FULL_SPEED: tmp = 'f'; break; \
-               case QH_LOW_SPEED:  tmp = 'l'; break; \
-               case QH_HIGH_SPEED: tmp = 'h'; break; \
-               default: tmp = '?'; break; \
-               } tmp; })
-
-static inline char token_mark(struct fusbh200_hcd *fusbh200, __hc32 token)
-{
-       __u32 v = hc32_to_cpu(fusbh200, token);
-
-       if (v & QTD_STS_ACTIVE)
-               return '*';
-       if (v & QTD_STS_HALT)
-               return '-';
-       if (!IS_SHORT_READ (v))
-               return ' ';
-       /* tries to advance through hw_alt_next */
-       return '/';
-}
-
-static void qh_lines (
-       struct fusbh200_hcd *fusbh200,
-       struct fusbh200_qh *qh,
-       char **nextp,
-       unsigned *sizep
-)
-{
-       u32                     scratch;
-       u32                     hw_curr;
-       struct fusbh200_qtd             *td;
-       unsigned                temp;
-       unsigned                size = *sizep;
-       char                    *next = *nextp;
-       char                    mark;
-       __le32                  list_end = FUSBH200_LIST_END(fusbh200);
-       struct fusbh200_qh_hw   *hw = qh->hw;
-
-       if (hw->hw_qtd_next == list_end)        /* NEC does this */
-               mark = '@';
-       else
-               mark = token_mark(fusbh200, hw->hw_token);
-       if (mark == '/') {      /* qh_alt_next controls qh advance? */
-               if ((hw->hw_alt_next & QTD_MASK(fusbh200))
-                               == fusbh200->async->hw->hw_alt_next)
-                       mark = '#';     /* blocked */
-               else if (hw->hw_alt_next == list_end)
-                       mark = '.';     /* use hw_qtd_next */
-               /* else alt_next points to some other qtd */
-       }
-       scratch = hc32_to_cpup(fusbh200, &hw->hw_info1);
-       hw_curr = (mark == '*') ? hc32_to_cpup(fusbh200, &hw->hw_current) : 0;
-       temp = scnprintf (next, size,
-                       "qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)",
-                       qh, scratch & 0x007f,
-                       speed_char (scratch),
-                       (scratch >> 8) & 0x000f,
-                       scratch, hc32_to_cpup(fusbh200, &hw->hw_info2),
-                       hc32_to_cpup(fusbh200, &hw->hw_token), mark,
-                       (cpu_to_hc32(fusbh200, QTD_TOGGLE) & hw->hw_token)
-                               ? "data1" : "data0",
-                       (hc32_to_cpup(fusbh200, &hw->hw_alt_next) >> 1) & 0x0f);
-       size -= temp;
-       next += temp;
-
-       /* hc may be modifying the list as we read it ... */
-       list_for_each_entry(td, &qh->qtd_list, qtd_list) {
-               scratch = hc32_to_cpup(fusbh200, &td->hw_token);
-               mark = ' ';
-               if (hw_curr == td->qtd_dma)
-                       mark = '*';
-               else if (hw->hw_qtd_next == cpu_to_hc32(fusbh200, td->qtd_dma))
-                       mark = '+';
-               else if (QTD_LENGTH (scratch)) {
-                       if (td->hw_alt_next == fusbh200->async->hw->hw_alt_next)
-                               mark = '#';
-                       else if (td->hw_alt_next != list_end)
-                               mark = '/';
-               }
-               temp = snprintf (next, size,
-                               "\n\t%p%c%s len=%d %08x urb %p",
-                               td, mark, ({ char *tmp;
-                                switch ((scratch>>8)&0x03) {
-                                case 0: tmp = "out"; break;
-                                case 1: tmp = "in"; break;
-                                case 2: tmp = "setup"; break;
-                                default: tmp = "?"; break;
-                                } tmp;}),
-                               (scratch >> 16) & 0x7fff,
-                               scratch,
-                               td->urb);
-               if (size < temp)
-                       temp = size;
-               size -= temp;
-               next += temp;
-               if (temp == size)
-                       goto done;
-       }
-
-       temp = snprintf (next, size, "\n");
-       if (size < temp)
-               temp = size;
-       size -= temp;
-       next += temp;
-
-done:
-       *sizep = size;
-       *nextp = next;
-}
-
-static ssize_t fill_async_buffer(struct debug_buffer *buf)
-{
-       struct usb_hcd          *hcd;
-       struct fusbh200_hcd     *fusbh200;
-       unsigned long           flags;
-       unsigned                temp, size;
-       char                    *next;
-       struct fusbh200_qh              *qh;
-
-       hcd = bus_to_hcd(buf->bus);
-       fusbh200 = hcd_to_fusbh200 (hcd);
-       next = buf->output_buf;
-       size = buf->alloc_size;
-
-       *next = 0;
-
-       /* dumps a snapshot of the async schedule.
-        * usually empty except for long-term bulk reads, or head.
-        * one QH per line, and TDs we know about
-        */
-       spin_lock_irqsave (&fusbh200->lock, flags);
-       for (qh = fusbh200->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh)
-               qh_lines (fusbh200, qh, &next, &size);
-       if (fusbh200->async_unlink && size > 0) {
-               temp = scnprintf(next, size, "\nunlink =\n");
-               size -= temp;
-               next += temp;
-
-               for (qh = fusbh200->async_unlink; size > 0 && qh;
-                               qh = qh->unlink_next)
-                       qh_lines (fusbh200, qh, &next, &size);
-       }
-       spin_unlock_irqrestore (&fusbh200->lock, flags);
-
-       return strlen(buf->output_buf);
-}
-
-#define DBG_SCHED_LIMIT 64
-static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
-{
-       struct usb_hcd          *hcd;
-       struct fusbh200_hcd             *fusbh200;
-       unsigned long           flags;
-       union fusbh200_shadow   p, *seen;
-       unsigned                temp, size, seen_count;
-       char                    *next;
-       unsigned                i;
-       __hc32                  tag;
-
-       seen = kmalloc(DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC);
-       if (!seen)
-               return 0;
-       seen_count = 0;
-
-       hcd = bus_to_hcd(buf->bus);
-       fusbh200 = hcd_to_fusbh200 (hcd);
-       next = buf->output_buf;
-       size = buf->alloc_size;
-
-       temp = scnprintf (next, size, "size = %d\n", fusbh200->periodic_size);
-       size -= temp;
-       next += temp;
-
-       /* dump a snapshot of the periodic schedule.
-        * iso changes, interrupt usually doesn't.
-        */
-       spin_lock_irqsave (&fusbh200->lock, flags);
-       for (i = 0; i < fusbh200->periodic_size; i++) {
-               p = fusbh200->pshadow [i];
-               if (likely (!p.ptr))
-                       continue;
-               tag = Q_NEXT_TYPE(fusbh200, fusbh200->periodic [i]);
-
-               temp = scnprintf (next, size, "%4d: ", i);
-               size -= temp;
-               next += temp;
-
-               do {
-                       struct fusbh200_qh_hw *hw;
-
-                       switch (hc32_to_cpu(fusbh200, tag)) {
-                       case Q_TYPE_QH:
-                               hw = p.qh->hw;
-                               temp = scnprintf (next, size, " qh%d-%04x/%p",
-                                               p.qh->period,
-                                               hc32_to_cpup(fusbh200,
-                                                       &hw->hw_info2)
-                                                       /* uframe masks */
-                                                       & (QH_CMASK | QH_SMASK),
-                                               p.qh);
-                               size -= temp;
-                               next += temp;
-                               /* don't repeat what follows this qh */
-                               for (temp = 0; temp < seen_count; temp++) {
-                                       if (seen [temp].ptr != p.ptr)
-                                               continue;
-                                       if (p.qh->qh_next.ptr) {
-                                               temp = scnprintf (next, size,
-                                                       " ...");
-                                               size -= temp;
-                                               next += temp;
-                                       }
-                                       break;
-                               }
-                               /* show more info the first time around */
-                               if (temp == seen_count) {
-                                       u32     scratch = hc32_to_cpup(fusbh200,
-                                                       &hw->hw_info1);
-                                       struct fusbh200_qtd     *qtd;
-                                       char            *type = "";
-
-                                       /* count tds, get ep direction */
-                                       temp = 0;
-                                       list_for_each_entry (qtd,
-                                                       &p.qh->qtd_list,
-                                                       qtd_list) {
-                                               temp++;
-                                               switch (0x03 & (hc32_to_cpu(
-                                                       fusbh200,
-                                                       qtd->hw_token) >> 8)) {
-                                               case 0: type = "out"; continue;
-                                               case 1: type = "in"; continue;
-                                               }
-                                       }
-
-                                       temp = scnprintf (next, size,
-                                               " (%c%d ep%d%s "
-                                               "[%d/%d] q%d p%d)",
-                                               speed_char (scratch),
-                                               scratch & 0x007f,
-                                               (scratch >> 8) & 0x000f, type,
-                                               p.qh->usecs, p.qh->c_usecs,
-                                               temp,
-                                               0x7ff & (scratch >> 16));
-
-                                       if (seen_count < DBG_SCHED_LIMIT)
-                                               seen [seen_count++].qh = p.qh;
-                               } else
-                                       temp = 0;
-                               tag = Q_NEXT_TYPE(fusbh200, hw->hw_next);
-                               p = p.qh->qh_next;
-                               break;
-                       case Q_TYPE_FSTN:
-                               temp = scnprintf (next, size,
-                                       " fstn-%8x/%p", p.fstn->hw_prev,
-                                       p.fstn);
-                               tag = Q_NEXT_TYPE(fusbh200, p.fstn->hw_next);
-                               p = p.fstn->fstn_next;
-                               break;
-                       case Q_TYPE_ITD:
-                               temp = scnprintf (next, size,
-                                       " itd/%p", p.itd);
-                               tag = Q_NEXT_TYPE(fusbh200, p.itd->hw_next);
-                               p = p.itd->itd_next;
-                               break;
-                       }
-                       size -= temp;
-                       next += temp;
-               } while (p.ptr);
-
-               temp = scnprintf (next, size, "\n");
-               size -= temp;
-               next += temp;
-       }
-       spin_unlock_irqrestore (&fusbh200->lock, flags);
-       kfree (seen);
-
-       return buf->alloc_size - size;
-}
-#undef DBG_SCHED_LIMIT
-
-static const char *rh_state_string(struct fusbh200_hcd *fusbh200)
-{
-       switch (fusbh200->rh_state) {
-       case FUSBH200_RH_HALTED:
-               return "halted";
-       case FUSBH200_RH_SUSPENDED:
-               return "suspended";
-       case FUSBH200_RH_RUNNING:
-               return "running";
-       case FUSBH200_RH_STOPPING:
-               return "stopping";
-       }
-       return "?";
-}
-
-static ssize_t fill_registers_buffer(struct debug_buffer *buf)
-{
-       struct usb_hcd          *hcd;
-       struct fusbh200_hcd     *fusbh200;
-       unsigned long           flags;
-       unsigned                temp, size, i;
-       char                    *next, scratch [80];
-       static char             fmt [] = "%*s\n";
-       static char             label [] = "";
-
-       hcd = bus_to_hcd(buf->bus);
-       fusbh200 = hcd_to_fusbh200 (hcd);
-       next = buf->output_buf;
-       size = buf->alloc_size;
-
-       spin_lock_irqsave (&fusbh200->lock, flags);
-
-       if (!HCD_HW_ACCESSIBLE(hcd)) {
-               size = scnprintf (next, size,
-                       "bus %s, device %s\n"
-                       "%s\n"
-                       "SUSPENDED (no register access)\n",
-                       hcd->self.controller->bus->name,
-                       dev_name(hcd->self.controller),
-                       hcd->product_desc);
-               goto done;
-       }
-
-       /* Capability Registers */
-       i = HC_VERSION(fusbh200, fusbh200_readl(fusbh200, &fusbh200->caps->hc_capbase));
-       temp = scnprintf (next, size,
-               "bus %s, device %s\n"
-               "%s\n"
-               "EHCI %x.%02x, rh state %s\n",
-               hcd->self.controller->bus->name,
-               dev_name(hcd->self.controller),
-               hcd->product_desc,
-               i >> 8, i & 0x0ff, rh_state_string(fusbh200));
-       size -= temp;
-       next += temp;
-
-       // FIXME interpret both types of params
-       i = fusbh200_readl(fusbh200, &fusbh200->caps->hcs_params);
-       temp = scnprintf (next, size, "structural params 0x%08x\n", i);
-       size -= temp;
-       next += temp;
-
-       i = fusbh200_readl(fusbh200, &fusbh200->caps->hcc_params);
-       temp = scnprintf (next, size, "capability params 0x%08x\n", i);
-       size -= temp;
-       next += temp;
-
-       /* Operational Registers */
-       temp = dbg_status_buf (scratch, sizeof scratch, label,
-                       fusbh200_readl(fusbh200, &fusbh200->regs->status));
-       temp = scnprintf (next, size, fmt, temp, scratch);
-       size -= temp;
-       next += temp;
-
-       temp = dbg_command_buf (scratch, sizeof scratch, label,
-                       fusbh200_readl(fusbh200, &fusbh200->regs->command));
-       temp = scnprintf (next, size, fmt, temp, scratch);
-       size -= temp;
-       next += temp;
-
-       temp = dbg_intr_buf (scratch, sizeof scratch, label,
-                       fusbh200_readl(fusbh200, &fusbh200->regs->intr_enable));
-       temp = scnprintf (next, size, fmt, temp, scratch);
-       size -= temp;
-       next += temp;
-
-       temp = scnprintf (next, size, "uframe %04x\n",
-                       fusbh200_read_frame_index(fusbh200));
-       size -= temp;
-       next += temp;
-
-       if (fusbh200->async_unlink) {
-               temp = scnprintf(next, size, "async unlink qh %p\n",
-                               fusbh200->async_unlink);
-               size -= temp;
-               next += temp;
-       }
-
-       temp = scnprintf (next, size,
-               "irq normal %ld err %ld iaa %ld (lost %ld)\n",
-               fusbh200->stats.normal, fusbh200->stats.error, fusbh200->stats.iaa,
-               fusbh200->stats.lost_iaa);
-       size -= temp;
-       next += temp;
-
-       temp = scnprintf (next, size, "complete %ld unlink %ld\n",
-               fusbh200->stats.complete, fusbh200->stats.unlink);
-       size -= temp;
-       next += temp;
-
-done:
-       spin_unlock_irqrestore (&fusbh200->lock, flags);
-
-       return buf->alloc_size - size;
-}
-
-static struct debug_buffer *alloc_buffer(struct usb_bus *bus,
-                               ssize_t (*fill_func)(struct debug_buffer *))
-{
-       struct debug_buffer *buf;
-
-       buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL);
-
-       if (buf) {
-               buf->bus = bus;
-               buf->fill_func = fill_func;
-               mutex_init(&buf->mutex);
-               buf->alloc_size = PAGE_SIZE;
-       }
-
-       return buf;
-}
-
-static int fill_buffer(struct debug_buffer *buf)
-{
-       int ret = 0;
-
-       if (!buf->output_buf)
-               buf->output_buf = vmalloc(buf->alloc_size);
-
-       if (!buf->output_buf) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       ret = buf->fill_func(buf);
-
-       if (ret >= 0) {
-               buf->count = ret;
-               ret = 0;
-       }
-
-out:
-       return ret;
-}
-
-static ssize_t debug_output(struct file *file, char __user *user_buf,
-                           size_t len, loff_t *offset)
-{
-       struct debug_buffer *buf = file->private_data;
-       int ret = 0;
-
-       mutex_lock(&buf->mutex);
-       if (buf->count == 0) {
-               ret = fill_buffer(buf);
-               if (ret != 0) {
-                       mutex_unlock(&buf->mutex);
-                       goto out;
-               }
-       }
-       mutex_unlock(&buf->mutex);
-
-       ret = simple_read_from_buffer(user_buf, len, offset,
-                                     buf->output_buf, buf->count);
-
-out:
-       return ret;
-
-}
-
-static int debug_close(struct inode *inode, struct file *file)
-{
-       struct debug_buffer *buf = file->private_data;
-
-       if (buf) {
-               vfree(buf->output_buf);
-               kfree(buf);
-       }
-
-       return 0;
-}
-static int debug_async_open(struct inode *inode, struct file *file)
-{
-       file->private_data = alloc_buffer(inode->i_private, fill_async_buffer);
-
-       return file->private_data ? 0 : -ENOMEM;
-}
-
-static int debug_periodic_open(struct inode *inode, struct file *file)
-{
-       struct debug_buffer *buf;
-       buf = alloc_buffer(inode->i_private, fill_periodic_buffer);
-       if (!buf)
-               return -ENOMEM;
-
-       buf->alloc_size = (sizeof(void *) == 4 ? 6 : 8)*PAGE_SIZE;
-       file->private_data = buf;
-       return 0;
-}
-
-static int debug_registers_open(struct inode *inode, struct file *file)
-{
-       file->private_data = alloc_buffer(inode->i_private,
-                                         fill_registers_buffer);
-
-       return file->private_data ? 0 : -ENOMEM;
-}
-
-static inline void create_debug_files (struct fusbh200_hcd *fusbh200)
-{
-       struct usb_bus *bus = &fusbh200_to_hcd(fusbh200)->self;
-
-       fusbh200->debug_dir = debugfs_create_dir(bus->bus_name, fusbh200_debug_root);
-       if (!fusbh200->debug_dir)
-               return;
-
-       if (!debugfs_create_file("async", S_IRUGO, fusbh200->debug_dir, bus,
-                                               &debug_async_fops))
-               goto file_error;
-
-       if (!debugfs_create_file("periodic", S_IRUGO, fusbh200->debug_dir, bus,
-                                               &debug_periodic_fops))
-               goto file_error;
-
-       if (!debugfs_create_file("registers", S_IRUGO, fusbh200->debug_dir, bus,
-                                                   &debug_registers_fops))
-               goto file_error;
-
-       return;
-
-file_error:
-       debugfs_remove_recursive(fusbh200->debug_dir);
-}
-
-static inline void remove_debug_files (struct fusbh200_hcd *fusbh200)
-{
-       debugfs_remove_recursive(fusbh200->debug_dir);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * handshake - spin reading hc until handshake completes or fails
- * @ptr: address of hc register to be read
- * @mask: bits to look at in result of read
- * @done: value of those bits when handshake succeeds
- * @usec: timeout in microseconds
- *
- * Returns negative errno, or zero on success
- *
- * Success happens when the "mask" bits have the specified value (hardware
- * handshake done).  There are two failure modes:  "usec" have passed (major
- * hardware flakeout), or the register reads as all-ones (hardware removed).
- *
- * That last failure should_only happen in cases like physical cardbus eject
- * before driver shutdown. But it also seems to be caused by bugs in cardbus
- * bridge shutdown:  shutting down the bridge before the devices using it.
- */
-static int handshake (struct fusbh200_hcd *fusbh200, void __iomem *ptr,
-                     u32 mask, u32 done, int usec)
-{
-       u32     result;
-
-       do {
-               result = fusbh200_readl(fusbh200, ptr);
-               if (result == ~(u32)0)          /* card removed */
-                       return -ENODEV;
-               result &= mask;
-               if (result == done)
-                       return 0;
-               udelay (1);
-               usec--;
-       } while (usec > 0);
-       return -ETIMEDOUT;
-}
-
-/*
- * Force HC to halt state from unknown (EHCI spec section 2.3).
- * Must be called with interrupts enabled and the lock not held.
- */
-static int fusbh200_halt (struct fusbh200_hcd *fusbh200)
-{
-       u32     temp;
-
-       spin_lock_irq(&fusbh200->lock);
-
-       /* disable any irqs left enabled by previous code */
-       fusbh200_writel(fusbh200, 0, &fusbh200->regs->intr_enable);
-
-       /*
-        * This routine gets called during probe before fusbh200->command
-        * has been initialized, so we can't rely on its value.
-        */
-       fusbh200->command &= ~CMD_RUN;
-       temp = fusbh200_readl(fusbh200, &fusbh200->regs->command);
-       temp &= ~(CMD_RUN | CMD_IAAD);
-       fusbh200_writel(fusbh200, temp, &fusbh200->regs->command);
-
-       spin_unlock_irq(&fusbh200->lock);
-       synchronize_irq(fusbh200_to_hcd(fusbh200)->irq);
-
-       return handshake(fusbh200, &fusbh200->regs->status,
-                         STS_HALT, STS_HALT, 16 * 125);
-}
-
-/*
- * Reset a non-running (STS_HALT == 1) controller.
- * Must be called with interrupts enabled and the lock not held.
- */
-static int fusbh200_reset (struct fusbh200_hcd *fusbh200)
-{
-       int     retval;
-       u32     command = fusbh200_readl(fusbh200, &fusbh200->regs->command);
-
-       /* If the EHCI debug controller is active, special care must be
-        * taken before and after a host controller reset */
-       if (fusbh200->debug && !dbgp_reset_prep(fusbh200_to_hcd(fusbh200)))
-               fusbh200->debug = NULL;
-
-       command |= CMD_RESET;
-       dbg_cmd (fusbh200, "reset", command);
-       fusbh200_writel(fusbh200, command, &fusbh200->regs->command);
-       fusbh200->rh_state = FUSBH200_RH_HALTED;
-       fusbh200->next_statechange = jiffies;
-       retval = handshake (fusbh200, &fusbh200->regs->command,
-                           CMD_RESET, 0, 250 * 1000);
-
-       if (retval)
-               return retval;
-
-       if (fusbh200->debug)
-               dbgp_external_startup(fusbh200_to_hcd(fusbh200));
-
-       fusbh200->port_c_suspend = fusbh200->suspended_ports =
-                       fusbh200->resuming_ports = 0;
-       return retval;
-}
-
-/*
- * Idle the controller (turn off the schedules).
- * Must be called with interrupts enabled and the lock not held.
- */
-static void fusbh200_quiesce (struct fusbh200_hcd *fusbh200)
-{
-       u32     temp;
-
-       if (fusbh200->rh_state != FUSBH200_RH_RUNNING)
-               return;
-
-       /* wait for any schedule enables/disables to take effect */
-       temp = (fusbh200->command << 10) & (STS_ASS | STS_PSS);
-       handshake(fusbh200, &fusbh200->regs->status, STS_ASS | STS_PSS, temp, 16 * 125);
-
-       /* then disable anything that's still active */
-       spin_lock_irq(&fusbh200->lock);
-       fusbh200->command &= ~(CMD_ASE | CMD_PSE);
-       fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command);
-       spin_unlock_irq(&fusbh200->lock);
-
-       /* hardware can take 16 microframes to turn off ... */
-       handshake(fusbh200, &fusbh200->regs->status, STS_ASS | STS_PSS, 0, 16 * 125);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void end_unlink_async(struct fusbh200_hcd *fusbh200);
-static void unlink_empty_async(struct fusbh200_hcd *fusbh200);
-static void fusbh200_work(struct fusbh200_hcd *fusbh200);
-static void start_unlink_intr(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh);
-static void end_unlink_intr(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh);
-
-/*-------------------------------------------------------------------------*/
-
-/* Set a bit in the USBCMD register */
-static void fusbh200_set_command_bit(struct fusbh200_hcd *fusbh200, u32 bit)
-{
-       fusbh200->command |= bit;
-       fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command);
-
-       /* unblock posted write */
-       fusbh200_readl(fusbh200, &fusbh200->regs->command);
-}
-
-/* Clear a bit in the USBCMD register */
-static void fusbh200_clear_command_bit(struct fusbh200_hcd *fusbh200, u32 bit)
-{
-       fusbh200->command &= ~bit;
-       fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command);
-
-       /* unblock posted write */
-       fusbh200_readl(fusbh200, &fusbh200->regs->command);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * EHCI timer support...  Now using hrtimers.
- *
- * Lots of different events are triggered from fusbh200->hrtimer.  Whenever
- * the timer routine runs, it checks each possible event; events that are
- * currently enabled and whose expiration time has passed get handled.
- * The set of enabled events is stored as a collection of bitflags in
- * fusbh200->enabled_hrtimer_events, and they are numbered in order of
- * increasing delay values (ranging between 1 ms and 100 ms).
- *
- * Rather than implementing a sorted list or tree of all pending events,
- * we keep track only of the lowest-numbered pending event, in
- * fusbh200->next_hrtimer_event.  Whenever fusbh200->hrtimer gets restarted, its
- * expiration time is set to the timeout value for this event.
- *
- * As a result, events might not get handled right away; the actual delay
- * could be anywhere up to twice the requested delay.  This doesn't
- * matter, because none of the events are especially time-critical.  The
- * ones that matter most all have a delay of 1 ms, so they will be
- * handled after 2 ms at most, which is okay.  In addition to this, we
- * allow for an expiration range of 1 ms.
- */
-
-/*
- * Delay lengths for the hrtimer event types.
- * Keep this list sorted by delay length, in the same order as
- * the event types indexed by enum fusbh200_hrtimer_event in fusbh200.h.
- */
-static unsigned event_delays_ns[] = {
-       1 * NSEC_PER_MSEC,      /* FUSBH200_HRTIMER_POLL_ASS */
-       1 * NSEC_PER_MSEC,      /* FUSBH200_HRTIMER_POLL_PSS */
-       1 * NSEC_PER_MSEC,      /* FUSBH200_HRTIMER_POLL_DEAD */
-       1125 * NSEC_PER_USEC,   /* FUSBH200_HRTIMER_UNLINK_INTR */
-       2 * NSEC_PER_MSEC,      /* FUSBH200_HRTIMER_FREE_ITDS */
-       6 * NSEC_PER_MSEC,      /* FUSBH200_HRTIMER_ASYNC_UNLINKS */
-       10 * NSEC_PER_MSEC,     /* FUSBH200_HRTIMER_IAA_WATCHDOG */
-       10 * NSEC_PER_MSEC,     /* FUSBH200_HRTIMER_DISABLE_PERIODIC */
-       15 * NSEC_PER_MSEC,     /* FUSBH200_HRTIMER_DISABLE_ASYNC */
-       100 * NSEC_PER_MSEC,    /* FUSBH200_HRTIMER_IO_WATCHDOG */
-};
-
-/* Enable a pending hrtimer event */
-static void fusbh200_enable_event(struct fusbh200_hcd *fusbh200, unsigned event,
-               bool resched)
-{
-       ktime_t         *timeout = &fusbh200->hr_timeouts[event];
-
-       if (resched)
-               *timeout = ktime_add(ktime_get(),
-                               ktime_set(0, event_delays_ns[event]));
-       fusbh200->enabled_hrtimer_events |= (1 << event);
-
-       /* Track only the lowest-numbered pending event */
-       if (event < fusbh200->next_hrtimer_event) {
-               fusbh200->next_hrtimer_event = event;
-               hrtimer_start_range_ns(&fusbh200->hrtimer, *timeout,
-                               NSEC_PER_MSEC, HRTIMER_MODE_ABS);
-       }
-}
-
-
-/* Poll the STS_ASS status bit; see when it agrees with CMD_ASE */
-static void fusbh200_poll_ASS(struct fusbh200_hcd *fusbh200)
-{
-       unsigned        actual, want;
-
-       /* Don't enable anything if the controller isn't running (e.g., died) */
-       if (fusbh200->rh_state != FUSBH200_RH_RUNNING)
-               return;
-
-       want = (fusbh200->command & CMD_ASE) ? STS_ASS : 0;
-       actual = fusbh200_readl(fusbh200, &fusbh200->regs->status) & STS_ASS;
-
-       if (want != actual) {
-
-               /* Poll again later, but give up after about 20 ms */
-               if (fusbh200->ASS_poll_count++ < 20) {
-                       fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_POLL_ASS, true);
-                       return;
-               }
-               fusbh200_dbg(fusbh200, "Waited too long for the async schedule status (%x/%x), giving up\n",
-                               want, actual);
-       }
-       fusbh200->ASS_poll_count = 0;
-
-       /* The status is up-to-date; restart or stop the schedule as needed */
-       if (want == 0) {        /* Stopped */
-               if (fusbh200->async_count > 0)
-                       fusbh200_set_command_bit(fusbh200, CMD_ASE);
-
-       } else {                /* Running */
-               if (fusbh200->async_count == 0) {
-
-                       /* Turn off the schedule after a while */
-                       fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_DISABLE_ASYNC,
-                                       true);
-               }
-       }
-}
-
-/* Turn off the async schedule after a brief delay */
-static void fusbh200_disable_ASE(struct fusbh200_hcd *fusbh200)
-{
-       fusbh200_clear_command_bit(fusbh200, CMD_ASE);
-}
-
-
-/* Poll the STS_PSS status bit; see when it agrees with CMD_PSE */
-static void fusbh200_poll_PSS(struct fusbh200_hcd *fusbh200)
-{
-       unsigned        actual, want;
-
-       /* Don't do anything if the controller isn't running (e.g., died) */
-       if (fusbh200->rh_state != FUSBH200_RH_RUNNING)
-               return;
-
-       want = (fusbh200->command & CMD_PSE) ? STS_PSS : 0;
-       actual = fusbh200_readl(fusbh200, &fusbh200->regs->status) & STS_PSS;
-
-       if (want != actual) {
-
-               /* Poll again later, but give up after about 20 ms */
-               if (fusbh200->PSS_poll_count++ < 20) {
-                       fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_POLL_PSS, true);
-                       return;
-               }
-               fusbh200_dbg(fusbh200, "Waited too long for the periodic schedule status (%x/%x), giving up\n",
-                               want, actual);
-       }
-       fusbh200->PSS_poll_count = 0;
-
-       /* The status is up-to-date; restart or stop the schedule as needed */
-       if (want == 0) {        /* Stopped */
-               if (fusbh200->periodic_count > 0)
-                       fusbh200_set_command_bit(fusbh200, CMD_PSE);
-
-       } else {                /* Running */
-               if (fusbh200->periodic_count == 0) {
-
-                       /* Turn off the schedule after a while */
-                       fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_DISABLE_PERIODIC,
-                                       true);
-               }
-       }
-}
-
-/* Turn off the periodic schedule after a brief delay */
-static void fusbh200_disable_PSE(struct fusbh200_hcd *fusbh200)
-{
-       fusbh200_clear_command_bit(fusbh200, CMD_PSE);
-}
-
-
-/* Poll the STS_HALT status bit; see when a dead controller stops */
-static void fusbh200_handle_controller_death(struct fusbh200_hcd *fusbh200)
-{
-       if (!(fusbh200_readl(fusbh200, &fusbh200->regs->status) & STS_HALT)) {
-
-               /* Give up after a few milliseconds */
-               if (fusbh200->died_poll_count++ < 5) {
-                       /* Try again later */
-                       fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_POLL_DEAD, true);
-                       return;
-               }
-               fusbh200_warn(fusbh200, "Waited too long for the controller to stop, giving up\n");
-       }
-
-       /* Clean up the mess */
-       fusbh200->rh_state = FUSBH200_RH_HALTED;
-       fusbh200_writel(fusbh200, 0, &fusbh200->regs->intr_enable);
-       fusbh200_work(fusbh200);
-       end_unlink_async(fusbh200);
-
-       /* Not in process context, so don't try to reset the controller */
-}
-
-
-/* Handle unlinked interrupt QHs once they are gone from the hardware */
-static void fusbh200_handle_intr_unlinks(struct fusbh200_hcd *fusbh200)
-{
-       bool            stopped = (fusbh200->rh_state < FUSBH200_RH_RUNNING);
-
-       /*
-        * Process all the QHs on the intr_unlink list that were added
-        * before the current unlink cycle began.  The list is in
-        * temporal order, so stop when we reach the first entry in the
-        * current cycle.  But if the root hub isn't running then
-        * process all the QHs on the list.
-        */
-       fusbh200->intr_unlinking = true;
-       while (fusbh200->intr_unlink) {
-               struct fusbh200_qh      *qh = fusbh200->intr_unlink;
-
-               if (!stopped && qh->unlink_cycle == fusbh200->intr_unlink_cycle)
-                       break;
-               fusbh200->intr_unlink = qh->unlink_next;
-               qh->unlink_next = NULL;
-               end_unlink_intr(fusbh200, qh);
-       }
-
-       /* Handle remaining entries later */
-       if (fusbh200->intr_unlink) {
-               fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_UNLINK_INTR, true);
-               ++fusbh200->intr_unlink_cycle;
-       }
-       fusbh200->intr_unlinking = false;
-}
-
-
-/* Start another free-iTDs/siTDs cycle */
-static void start_free_itds(struct fusbh200_hcd *fusbh200)
-{
-       if (!(fusbh200->enabled_hrtimer_events & BIT(FUSBH200_HRTIMER_FREE_ITDS))) {
-               fusbh200->last_itd_to_free = list_entry(
-                               fusbh200->cached_itd_list.prev,
-                               struct fusbh200_itd, itd_list);
-               fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_FREE_ITDS, true);
-       }
-}
-
-/* Wait for controller to stop using old iTDs and siTDs */
-static void end_free_itds(struct fusbh200_hcd *fusbh200)
-{
-       struct fusbh200_itd             *itd, *n;
-
-       if (fusbh200->rh_state < FUSBH200_RH_RUNNING) {
-               fusbh200->last_itd_to_free = NULL;
-       }
-
-       list_for_each_entry_safe(itd, n, &fusbh200->cached_itd_list, itd_list) {
-               list_del(&itd->itd_list);
-               dma_pool_free(fusbh200->itd_pool, itd, itd->itd_dma);
-               if (itd == fusbh200->last_itd_to_free)
-                       break;
-       }
-
-       if (!list_empty(&fusbh200->cached_itd_list))
-               start_free_itds(fusbh200);
-}
-
-
-/* Handle lost (or very late) IAA interrupts */
-static void fusbh200_iaa_watchdog(struct fusbh200_hcd *fusbh200)
-{
-       if (fusbh200->rh_state != FUSBH200_RH_RUNNING)
-               return;
-
-       /*
-        * Lost IAA irqs wedge things badly; seen first with a vt8235.
-        * So we need this watchdog, but must protect it against both
-        * (a) SMP races against real IAA firing and retriggering, and
-        * (b) clean HC shutdown, when IAA watchdog was pending.
-        */
-       if (fusbh200->async_iaa) {
-               u32 cmd, status;
-
-               /* If we get here, IAA is *REALLY* late.  It's barely
-                * conceivable that the system is so busy that CMD_IAAD
-                * is still legitimately set, so let's be sure it's
-                * clear before we read STS_IAA.  (The HC should clear
-                * CMD_IAAD when it sets STS_IAA.)
-                */
-               cmd = fusbh200_readl(fusbh200, &fusbh200->regs->command);
-
-               /*
-                * If IAA is set here it either legitimately triggered
-                * after the watchdog timer expired (_way_ late, so we'll
-                * still count it as lost) ... or a silicon erratum:
-                * - VIA seems to set IAA without triggering the IRQ;
-                * - IAAD potentially cleared without setting IAA.
-                */
-               status = fusbh200_readl(fusbh200, &fusbh200->regs->status);
-               if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
-                       COUNT(fusbh200->stats.lost_iaa);
-                       fusbh200_writel(fusbh200, STS_IAA, &fusbh200->regs->status);
-               }
-
-               fusbh200_dbg(fusbh200, "IAA watchdog: status %x cmd %x\n",
-                               status, cmd);
-               end_unlink_async(fusbh200);
-       }
-}
-
-
-/* Enable the I/O watchdog, if appropriate */
-static void turn_on_io_watchdog(struct fusbh200_hcd *fusbh200)
-{
-       /* Not needed if the controller isn't running or it's already enabled */
-       if (fusbh200->rh_state != FUSBH200_RH_RUNNING ||
-                       (fusbh200->enabled_hrtimer_events &
-                               BIT(FUSBH200_HRTIMER_IO_WATCHDOG)))
-               return;
-
-       /*
-        * Isochronous transfers always need the watchdog.
-        * For other sorts we use it only if the flag is set.
-        */
-       if (fusbh200->isoc_count > 0 || (fusbh200->need_io_watchdog &&
-                       fusbh200->async_count + fusbh200->intr_count > 0))
-               fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_IO_WATCHDOG, true);
-}
-
-
-/*
- * Handler functions for the hrtimer event types.
- * Keep this array in the same order as the event types indexed by
- * enum fusbh200_hrtimer_event in fusbh200.h.
- */
-static void (*event_handlers[])(struct fusbh200_hcd *) = {
-       fusbh200_poll_ASS,                      /* FUSBH200_HRTIMER_POLL_ASS */
-       fusbh200_poll_PSS,                      /* FUSBH200_HRTIMER_POLL_PSS */
-       fusbh200_handle_controller_death,       /* FUSBH200_HRTIMER_POLL_DEAD */
-       fusbh200_handle_intr_unlinks,   /* FUSBH200_HRTIMER_UNLINK_INTR */
-       end_free_itds,                  /* FUSBH200_HRTIMER_FREE_ITDS */
-       unlink_empty_async,             /* FUSBH200_HRTIMER_ASYNC_UNLINKS */
-       fusbh200_iaa_watchdog,          /* FUSBH200_HRTIMER_IAA_WATCHDOG */
-       fusbh200_disable_PSE,           /* FUSBH200_HRTIMER_DISABLE_PERIODIC */
-       fusbh200_disable_ASE,           /* FUSBH200_HRTIMER_DISABLE_ASYNC */
-       fusbh200_work,                  /* FUSBH200_HRTIMER_IO_WATCHDOG */
-};
-
-static enum hrtimer_restart fusbh200_hrtimer_func(struct hrtimer *t)
-{
-       struct fusbh200_hcd     *fusbh200 = container_of(t, struct fusbh200_hcd, hrtimer);
-       ktime_t         now;
-       unsigned long   events;
-       unsigned long   flags;
-       unsigned        e;
-
-       spin_lock_irqsave(&fusbh200->lock, flags);
-
-       events = fusbh200->enabled_hrtimer_events;
-       fusbh200->enabled_hrtimer_events = 0;
-       fusbh200->next_hrtimer_event = FUSBH200_HRTIMER_NO_EVENT;
-
-       /*
-        * Check each pending event.  If its time has expired, handle
-        * the event; otherwise re-enable it.
-        */
-       now = ktime_get();
-       for_each_set_bit(e, &events, FUSBH200_HRTIMER_NUM_EVENTS) {
-               if (now.tv64 >= fusbh200->hr_timeouts[e].tv64)
-                       event_handlers[e](fusbh200);
-               else
-                       fusbh200_enable_event(fusbh200, e, false);
-       }
-
-       spin_unlock_irqrestore(&fusbh200->lock, flags);
-       return HRTIMER_NORESTART;
-}
-
-/*-------------------------------------------------------------------------*/
-
-#define fusbh200_bus_suspend   NULL
-#define fusbh200_bus_resume    NULL
-
-/*-------------------------------------------------------------------------*/
-
-static int check_reset_complete (
-       struct fusbh200_hcd     *fusbh200,
-       int             index,
-       u32 __iomem     *status_reg,
-       int             port_status
-) {
-       if (!(port_status & PORT_CONNECT))
-               return port_status;
-
-       /* if reset finished and it's still not enabled -- handoff */
-       if (!(port_status & PORT_PE)) {
-               /* with integrated TT, there's nobody to hand it to! */
-               fusbh200_dbg (fusbh200,
-                       "Failed to enable port %d on root hub TT\n",
-                       index+1);
-               return port_status;
-       } else {
-               fusbh200_dbg(fusbh200, "port %d reset complete, port enabled\n",
-                       index + 1);
-       }
-
-       return port_status;
-}
-
-/*-------------------------------------------------------------------------*/
-
-
-/* build "status change" packet (one or two bytes) from HC registers */
-
-static int
-fusbh200_hub_status_data (struct usb_hcd *hcd, char *buf)
-{
-       struct fusbh200_hcd     *fusbh200 = hcd_to_fusbh200 (hcd);
-       u32             temp, status;
-       u32             mask;
-       int             retval = 1;
-       unsigned long   flags;
-
-       /* init status to no-changes */
-       buf [0] = 0;
-
-       /* Inform the core about resumes-in-progress by returning
-        * a non-zero value even if there are no status changes.
-        */
-       status = fusbh200->resuming_ports;
-
-       mask = PORT_CSC | PORT_PEC;
-       // PORT_RESUME from hardware ~= PORT_STAT_C_SUSPEND
-
-       /* no hub change reports (bit 0) for now (power, ...) */
-
-       /* port N changes (bit N)? */
-       spin_lock_irqsave (&fusbh200->lock, flags);
-
-       temp = fusbh200_readl(fusbh200, &fusbh200->regs->port_status);
-
-       /*
-        * Return status information even for ports with OWNER set.
-        * Otherwise hub_wq wouldn't see the disconnect event when a
-        * high-speed device is switched over to the companion
-        * controller by the user.
-        */
-
-       if ((temp & mask) != 0 || test_bit(0, &fusbh200->port_c_suspend)
-                       || (fusbh200->reset_done[0] && time_after_eq(
-                               jiffies, fusbh200->reset_done[0]))) {
-               buf [0] |= 1 << 1;
-               status = STS_PCD;
-       }
-       /* FIXME autosuspend idle root hubs */
-       spin_unlock_irqrestore (&fusbh200->lock, flags);
-       return status ? retval : 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void
-fusbh200_hub_descriptor (
-       struct fusbh200_hcd             *fusbh200,
-       struct usb_hub_descriptor       *desc
-) {
-       int             ports = HCS_N_PORTS (fusbh200->hcs_params);
-       u16             temp;
-
-       desc->bDescriptorType = USB_DT_HUB;
-       desc->bPwrOn2PwrGood = 10;      /* fusbh200 1.0, 2.3.9 says 20ms max */
-       desc->bHubContrCurrent = 0;
-
-       desc->bNbrPorts = ports;
-       temp = 1 + (ports / 8);
-       desc->bDescLength = 7 + 2 * temp;
-
-       /* two bitmaps:  ports removable, and usb 1.0 legacy PortPwrCtrlMask */
-       memset(&desc->u.hs.DeviceRemovable[0], 0, temp);
-       memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp);
-
-       temp = HUB_CHAR_INDV_PORT_OCPM; /* per-port overcurrent reporting */
-       temp |= HUB_CHAR_NO_LPSM;       /* no power switching */
-       desc->wHubCharacteristics = cpu_to_le16(temp);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int fusbh200_hub_control (
-       struct usb_hcd  *hcd,
-       u16             typeReq,
-       u16             wValue,
-       u16             wIndex,
-       char            *buf,
-       u16             wLength
-) {
-       struct fusbh200_hcd     *fusbh200 = hcd_to_fusbh200 (hcd);
-       int             ports = HCS_N_PORTS (fusbh200->hcs_params);
-       u32 __iomem     *status_reg = &fusbh200->regs->port_status;
-       u32             temp, temp1, status;
-       unsigned long   flags;
-       int             retval = 0;
-       unsigned        selector;
-
-       /*
-        * FIXME:  support SetPortFeatures USB_PORT_FEAT_INDICATOR.
-        * HCS_INDICATOR may say we can change LEDs to off/amber/green.
-        * (track current state ourselves) ... blink for diagnostics,
-        * power, "this is the one", etc.  EHCI spec supports this.
-        */
-
-       spin_lock_irqsave (&fusbh200->lock, flags);
-       switch (typeReq) {
-       case ClearHubFeature:
-               switch (wValue) {
-               case C_HUB_LOCAL_POWER:
-               case C_HUB_OVER_CURRENT:
-                       /* no hub-wide feature/status flags */
-                       break;
-               default:
-                       goto error;
-               }
-               break;
-       case ClearPortFeature:
-               if (!wIndex || wIndex > ports)
-                       goto error;
-               wIndex--;
-               temp = fusbh200_readl(fusbh200, status_reg);
-               temp &= ~PORT_RWC_BITS;
-
-               /*
-                * Even if OWNER is set, so the port is owned by the
-                * companion controller, hub_wq needs to be able to clear
-                * the port-change status bits (especially
-                * USB_PORT_STAT_C_CONNECTION).
-                */
-
-               switch (wValue) {
-               case USB_PORT_FEAT_ENABLE:
-                       fusbh200_writel(fusbh200, temp & ~PORT_PE, status_reg);
-                       break;
-               case USB_PORT_FEAT_C_ENABLE:
-                       fusbh200_writel(fusbh200, temp | PORT_PEC, status_reg);
-                       break;
-               case USB_PORT_FEAT_SUSPEND:
-                       if (temp & PORT_RESET)
-                               goto error;
-                       if (!(temp & PORT_SUSPEND))
-                               break;
-                       if ((temp & PORT_PE) == 0)
-                               goto error;
-
-                       fusbh200_writel(fusbh200, temp | PORT_RESUME, status_reg);
-                       fusbh200->reset_done[wIndex] = jiffies
-                                       + msecs_to_jiffies(USB_RESUME_TIMEOUT);
-                       break;
-               case USB_PORT_FEAT_C_SUSPEND:
-                       clear_bit(wIndex, &fusbh200->port_c_suspend);
-                       break;
-               case USB_PORT_FEAT_C_CONNECTION:
-                       fusbh200_writel(fusbh200, temp | PORT_CSC, status_reg);
-                       break;
-               case USB_PORT_FEAT_C_OVER_CURRENT:
-                       fusbh200_writel(fusbh200, temp | BMISR_OVC, &fusbh200->regs->bmisr);
-                       break;
-               case USB_PORT_FEAT_C_RESET:
-                       /* GetPortStatus clears reset */
-                       break;
-               default:
-                       goto error;
-               }
-               fusbh200_readl(fusbh200, &fusbh200->regs->command);     /* unblock posted write */
-               break;
-       case GetHubDescriptor:
-               fusbh200_hub_descriptor (fusbh200, (struct usb_hub_descriptor *)
-                       buf);
-               break;
-       case GetHubStatus:
-               /* no hub-wide feature/status flags */
-               memset (buf, 0, 4);
-               //cpu_to_le32s ((u32 *) buf);
-               break;
-       case GetPortStatus:
-               if (!wIndex || wIndex > ports)
-                       goto error;
-               wIndex--;
-               status = 0;
-               temp = fusbh200_readl(fusbh200, status_reg);
-
-               // wPortChange bits
-               if (temp & PORT_CSC)
-                       status |= USB_PORT_STAT_C_CONNECTION << 16;
-               if (temp & PORT_PEC)
-                       status |= USB_PORT_STAT_C_ENABLE << 16;
-
-               temp1 = fusbh200_readl(fusbh200, &fusbh200->regs->bmisr);
-               if (temp1 & BMISR_OVC)
-                       status |= USB_PORT_STAT_C_OVERCURRENT << 16;
-
-               /* whoever resumes must GetPortStatus to complete it!! */
-               if (temp & PORT_RESUME) {
-
-                       /* Remote Wakeup received? */
-                       if (!fusbh200->reset_done[wIndex]) {
-                               /* resume signaling for 20 msec */
-                               fusbh200->reset_done[wIndex] = jiffies
-                                               + msecs_to_jiffies(20);
-                               /* check the port again */
-                               mod_timer(&fusbh200_to_hcd(fusbh200)->rh_timer,
-                                               fusbh200->reset_done[wIndex]);
-                       }
-
-                       /* resume completed? */
-                       else if (time_after_eq(jiffies,
-                                       fusbh200->reset_done[wIndex])) {
-                               clear_bit(wIndex, &fusbh200->suspended_ports);
-                               set_bit(wIndex, &fusbh200->port_c_suspend);
-                               fusbh200->reset_done[wIndex] = 0;
-
-                               /* stop resume signaling */
-                               temp = fusbh200_readl(fusbh200, status_reg);
-                               fusbh200_writel(fusbh200,
-                                       temp & ~(PORT_RWC_BITS | PORT_RESUME),
-                                       status_reg);
-                               clear_bit(wIndex, &fusbh200->resuming_ports);
-                               retval = handshake(fusbh200, status_reg,
-                                          PORT_RESUME, 0, 2000 /* 2msec */);
-                               if (retval != 0) {
-                                       fusbh200_err(fusbh200,
-                                               "port %d resume error %d\n",
-                                               wIndex + 1, retval);
-                                       goto error;
-                               }
-                               temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
-                       }
-               }
-
-               /* whoever resets must GetPortStatus to complete it!! */
-               if ((temp & PORT_RESET)
-                               && time_after_eq(jiffies,
-                                       fusbh200->reset_done[wIndex])) {
-                       status |= USB_PORT_STAT_C_RESET << 16;
-                       fusbh200->reset_done [wIndex] = 0;
-                       clear_bit(wIndex, &fusbh200->resuming_ports);
-
-                       /* force reset to complete */
-                       fusbh200_writel(fusbh200, temp & ~(PORT_RWC_BITS | PORT_RESET),
-                                       status_reg);
-                       /* REVISIT:  some hardware needs 550+ usec to clear
-                        * this bit; seems too long to spin routinely...
-                        */
-                       retval = handshake(fusbh200, status_reg,
-                                       PORT_RESET, 0, 1000);
-                       if (retval != 0) {
-                               fusbh200_err (fusbh200, "port %d reset error %d\n",
-                                       wIndex + 1, retval);
-                               goto error;
-                       }
-
-                       /* see what we found out */
-                       temp = check_reset_complete (fusbh200, wIndex, status_reg,
-                                       fusbh200_readl(fusbh200, status_reg));
-               }
-
-               if (!(temp & (PORT_RESUME|PORT_RESET))) {
-                       fusbh200->reset_done[wIndex] = 0;
-                       clear_bit(wIndex, &fusbh200->resuming_ports);
-               }
-
-               /* transfer dedicated ports to the companion hc */
-               if ((temp & PORT_CONNECT) &&
-                               test_bit(wIndex, &fusbh200->companion_ports)) {
-                       temp &= ~PORT_RWC_BITS;
-                       fusbh200_writel(fusbh200, temp, status_reg);
-                       fusbh200_dbg(fusbh200, "port %d --> companion\n", wIndex + 1);
-                       temp = fusbh200_readl(fusbh200, status_reg);
-               }
-
-               /*
-                * Even if OWNER is set, there's no harm letting hub_wq
-                * see the wPortStatus values (they should all be 0 except
-                * for PORT_POWER anyway).
-                */
-
-               if (temp & PORT_CONNECT) {
-                       status |= USB_PORT_STAT_CONNECTION;
-                       status |= fusbh200_port_speed(fusbh200, temp);
-               }
-               if (temp & PORT_PE)
-                       status |= USB_PORT_STAT_ENABLE;
-
-               /* maybe the port was unsuspended without our knowledge */
-               if (temp & (PORT_SUSPEND|PORT_RESUME)) {
-                       status |= USB_PORT_STAT_SUSPEND;
-               } else if (test_bit(wIndex, &fusbh200->suspended_ports)) {
-                       clear_bit(wIndex, &fusbh200->suspended_ports);
-                       clear_bit(wIndex, &fusbh200->resuming_ports);
-                       fusbh200->reset_done[wIndex] = 0;
-                       if (temp & PORT_PE)
-                               set_bit(wIndex, &fusbh200->port_c_suspend);
-               }
-
-               temp1 = fusbh200_readl(fusbh200, &fusbh200->regs->bmisr);
-               if (temp1 & BMISR_OVC)
-                       status |= USB_PORT_STAT_OVERCURRENT;
-               if (temp & PORT_RESET)
-                       status |= USB_PORT_STAT_RESET;
-               if (test_bit(wIndex, &fusbh200->port_c_suspend))
-                       status |= USB_PORT_STAT_C_SUSPEND << 16;
-
-               if (status & ~0xffff)   /* only if wPortChange is interesting */
-                       dbg_port(fusbh200, "GetStatus", wIndex + 1, temp);
-               put_unaligned_le32(status, buf);
-               break;
-       case SetHubFeature:
-               switch (wValue) {
-               case C_HUB_LOCAL_POWER:
-               case C_HUB_OVER_CURRENT:
-                       /* no hub-wide feature/status flags */
-                       break;
-               default:
-                       goto error;
-               }
-               break;
-       case SetPortFeature:
-               selector = wIndex >> 8;
-               wIndex &= 0xff;
-
-               if (!wIndex || wIndex > ports)
-                       goto error;
-               wIndex--;
-               temp = fusbh200_readl(fusbh200, status_reg);
-               temp &= ~PORT_RWC_BITS;
-               switch (wValue) {
-               case USB_PORT_FEAT_SUSPEND:
-                       if ((temp & PORT_PE) == 0
-                                       || (temp & PORT_RESET) != 0)
-                               goto error;
-
-                       /* After above check the port must be connected.
-                        * Set appropriate bit thus could put phy into low power
-                        * mode if we have hostpc feature
-                        */
-                       fusbh200_writel(fusbh200, temp | PORT_SUSPEND, status_reg);
-                       set_bit(wIndex, &fusbh200->suspended_ports);
-                       break;
-               case USB_PORT_FEAT_RESET:
-                       if (temp & PORT_RESUME)
-                               goto error;
-                       /* line status bits may report this as low speed,
-                        * which can be fine if this root hub has a
-                        * transaction translator built in.
-                        */
-                       fusbh200_dbg(fusbh200, "port %d reset\n", wIndex + 1);
-                       temp |= PORT_RESET;
-                       temp &= ~PORT_PE;
-
-                       /*
-                        * caller must wait, then call GetPortStatus
-                        * usb 2.0 spec says 50 ms resets on root
-                        */
-                       fusbh200->reset_done [wIndex] = jiffies
-                                       + msecs_to_jiffies (50);
-                       fusbh200_writel(fusbh200, temp, status_reg);
-                       break;
-
-               /* For downstream facing ports (these):  one hub port is put
-                * into test mode according to USB2 11.24.2.13, then the hub
-                * must be reset (which for root hub now means rmmod+modprobe,
-                * or else system reboot).  See EHCI 2.3.9 and 4.14 for info
-                * about the EHCI-specific stuff.
-                */
-               case USB_PORT_FEAT_TEST:
-                       if (!selector || selector > 5)
-                               goto error;
-                       spin_unlock_irqrestore(&fusbh200->lock, flags);
-                       fusbh200_quiesce(fusbh200);
-                       spin_lock_irqsave(&fusbh200->lock, flags);
-
-                       /* Put all enabled ports into suspend */
-                       temp = fusbh200_readl(fusbh200, status_reg) & ~PORT_RWC_BITS;
-                       if (temp & PORT_PE)
-                               fusbh200_writel(fusbh200, temp | PORT_SUSPEND,
-                                               status_reg);
-
-                       spin_unlock_irqrestore(&fusbh200->lock, flags);
-                       fusbh200_halt(fusbh200);
-                       spin_lock_irqsave(&fusbh200->lock, flags);
-
-                       temp = fusbh200_readl(fusbh200, status_reg);
-                       temp |= selector << 16;
-                       fusbh200_writel(fusbh200, temp, status_reg);
-                       break;
-
-               default:
-                       goto error;
-               }
-               fusbh200_readl(fusbh200, &fusbh200->regs->command);     /* unblock posted writes */
-               break;
-
-       default:
-error:
-               /* "stall" on error */
-               retval = -EPIPE;
-       }
-       spin_unlock_irqrestore (&fusbh200->lock, flags);
-       return retval;
-}
-
-static void __maybe_unused fusbh200_relinquish_port(struct usb_hcd *hcd,
-               int portnum)
-{
-       return;
-}
-
-static int __maybe_unused fusbh200_port_handed_over(struct usb_hcd *hcd,
-               int portnum)
-{
-       return 0;
-}
-/*-------------------------------------------------------------------------*/
-/*
- * There's basically three types of memory:
- *     - data used only by the HCD ... kmalloc is fine
- *     - async and periodic schedules, shared by HC and HCD ... these
- *       need to use dma_pool or dma_alloc_coherent
- *     - driver buffers, read/written by HC ... single shot DMA mapped
- *
- * There's also "register" data (e.g. PCI or SOC), which is memory mapped.
- * No memory seen by this driver is pageable.
- */
-
-/*-------------------------------------------------------------------------*/
-
-/* Allocate the key transfer structures from the previously allocated pool */
-
-static inline void fusbh200_qtd_init(struct fusbh200_hcd *fusbh200, struct fusbh200_qtd *qtd,
-                                 dma_addr_t dma)
-{
-       memset (qtd, 0, sizeof *qtd);
-       qtd->qtd_dma = dma;
-       qtd->hw_token = cpu_to_hc32(fusbh200, QTD_STS_HALT);
-       qtd->hw_next = FUSBH200_LIST_END(fusbh200);
-       qtd->hw_alt_next = FUSBH200_LIST_END(fusbh200);
-       INIT_LIST_HEAD (&qtd->qtd_list);
-}
-
-static struct fusbh200_qtd *fusbh200_qtd_alloc (struct fusbh200_hcd *fusbh200, gfp_t flags)
-{
-       struct fusbh200_qtd             *qtd;
-       dma_addr_t              dma;
-
-       qtd = dma_pool_alloc (fusbh200->qtd_pool, flags, &dma);
-       if (qtd != NULL) {
-               fusbh200_qtd_init(fusbh200, qtd, dma);
-       }
-       return qtd;
-}
-
-static inline void fusbh200_qtd_free (struct fusbh200_hcd *fusbh200, struct fusbh200_qtd *qtd)
-{
-       dma_pool_free (fusbh200->qtd_pool, qtd, qtd->qtd_dma);
-}
-
-
-static void qh_destroy(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
-       /* clean qtds first, and know this is not linked */
-       if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) {
-               fusbh200_dbg (fusbh200, "unused qh not empty!\n");
-               BUG ();
-       }
-       if (qh->dummy)
-               fusbh200_qtd_free (fusbh200, qh->dummy);
-       dma_pool_free(fusbh200->qh_pool, qh->hw, qh->qh_dma);
-       kfree(qh);
-}
-
-static struct fusbh200_qh *fusbh200_qh_alloc (struct fusbh200_hcd *fusbh200, gfp_t flags)
-{
-       struct fusbh200_qh              *qh;
-       dma_addr_t              dma;
-
-       qh = kzalloc(sizeof *qh, GFP_ATOMIC);
-       if (!qh)
-               goto done;
-       qh->hw = (struct fusbh200_qh_hw *)
-               dma_pool_alloc(fusbh200->qh_pool, flags, &dma);
-       if (!qh->hw)
-               goto fail;
-       memset(qh->hw, 0, sizeof *qh->hw);
-       qh->qh_dma = dma;
-       // INIT_LIST_HEAD (&qh->qh_list);
-       INIT_LIST_HEAD (&qh->qtd_list);
-
-       /* dummy td enables safe urb queuing */
-       qh->dummy = fusbh200_qtd_alloc (fusbh200, flags);
-       if (qh->dummy == NULL) {
-               fusbh200_dbg (fusbh200, "no dummy td\n");
-               goto fail1;
-       }
-done:
-       return qh;
-fail1:
-       dma_pool_free(fusbh200->qh_pool, qh->hw, qh->qh_dma);
-fail:
-       kfree(qh);
-       return NULL;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* The queue heads and transfer descriptors are managed from pools tied
- * to each of the "per device" structures.
- * This is the initialisation and cleanup code.
- */
-
-static void fusbh200_mem_cleanup (struct fusbh200_hcd *fusbh200)
-{
-       if (fusbh200->async)
-               qh_destroy(fusbh200, fusbh200->async);
-       fusbh200->async = NULL;
-
-       if (fusbh200->dummy)
-               qh_destroy(fusbh200, fusbh200->dummy);
-       fusbh200->dummy = NULL;
-
-       /* DMA consistent memory and pools */
-       if (fusbh200->qtd_pool)
-               dma_pool_destroy (fusbh200->qtd_pool);
-       fusbh200->qtd_pool = NULL;
-
-       if (fusbh200->qh_pool) {
-               dma_pool_destroy (fusbh200->qh_pool);
-               fusbh200->qh_pool = NULL;
-       }
-
-       if (fusbh200->itd_pool)
-               dma_pool_destroy (fusbh200->itd_pool);
-       fusbh200->itd_pool = NULL;
-
-       if (fusbh200->periodic)
-               dma_free_coherent (fusbh200_to_hcd(fusbh200)->self.controller,
-                       fusbh200->periodic_size * sizeof (u32),
-                       fusbh200->periodic, fusbh200->periodic_dma);
-       fusbh200->periodic = NULL;
-
-       /* shadow periodic table */
-       kfree(fusbh200->pshadow);
-       fusbh200->pshadow = NULL;
-}
-
-/* remember to add cleanup code (above) if you add anything here */
-static int fusbh200_mem_init (struct fusbh200_hcd *fusbh200, gfp_t flags)
-{
-       int i;
-
-       /* QTDs for control/bulk/intr transfers */
-       fusbh200->qtd_pool = dma_pool_create ("fusbh200_qtd",
-                       fusbh200_to_hcd(fusbh200)->self.controller,
-                       sizeof (struct fusbh200_qtd),
-                       32 /* byte alignment (for hw parts) */,
-                       4096 /* can't cross 4K */);
-       if (!fusbh200->qtd_pool) {
-               goto fail;
-       }
-
-       /* QHs for control/bulk/intr transfers */
-       fusbh200->qh_pool = dma_pool_create ("fusbh200_qh",
-                       fusbh200_to_hcd(fusbh200)->self.controller,
-                       sizeof(struct fusbh200_qh_hw),
-                       32 /* byte alignment (for hw parts) */,
-                       4096 /* can't cross 4K */);
-       if (!fusbh200->qh_pool) {
-               goto fail;
-       }
-       fusbh200->async = fusbh200_qh_alloc (fusbh200, flags);
-       if (!fusbh200->async) {
-               goto fail;
-       }
-
-       /* ITD for high speed ISO transfers */
-       fusbh200->itd_pool = dma_pool_create ("fusbh200_itd",
-                       fusbh200_to_hcd(fusbh200)->self.controller,
-                       sizeof (struct fusbh200_itd),
-                       64 /* byte alignment (for hw parts) */,
-                       4096 /* can't cross 4K */);
-       if (!fusbh200->itd_pool) {
-               goto fail;
-       }
-
-       /* Hardware periodic table */
-       fusbh200->periodic = (__le32 *)
-               dma_alloc_coherent (fusbh200_to_hcd(fusbh200)->self.controller,
-                       fusbh200->periodic_size * sizeof(__le32),
-                       &fusbh200->periodic_dma, 0);
-       if (fusbh200->periodic == NULL) {
-               goto fail;
-       }
-
-               for (i = 0; i < fusbh200->periodic_size; i++)
-                       fusbh200->periodic[i] = FUSBH200_LIST_END(fusbh200);
-
-       /* software shadow of hardware table */
-       fusbh200->pshadow = kcalloc(fusbh200->periodic_size, sizeof(void *), flags);
-       if (fusbh200->pshadow != NULL)
-               return 0;
-
-fail:
-       fusbh200_dbg (fusbh200, "couldn't init memory\n");
-       fusbh200_mem_cleanup (fusbh200);
-       return -ENOMEM;
-}
-/*-------------------------------------------------------------------------*/
-/*
- * EHCI hardware queue manipulation ... the core.  QH/QTD manipulation.
- *
- * Control, bulk, and interrupt traffic all use "qh" lists.  They list "qtd"
- * entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned
- * buffers needed for the larger number).  We use one QH per endpoint, queue
- * multiple urbs (all three types) per endpoint.  URBs may need several qtds.
- *
- * ISO traffic uses "ISO TD" (itd) records, and (along with
- * interrupts) needs careful scheduling.  Performance improvements can be
- * an ongoing challenge.  That's in "ehci-sched.c".
- *
- * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs,
- * or otherwise through transaction translators (TTs) in USB 2.0 hubs using
- * (b) special fields in qh entries or (c) split iso entries.  TTs will
- * buffer low/full speed data so the host collects it at high speed.
- */
-
-/*-------------------------------------------------------------------------*/
-
-/* fill a qtd, returning how much of the buffer we were able to queue up */
-
-static int
-qtd_fill(struct fusbh200_hcd *fusbh200, struct fusbh200_qtd *qtd, dma_addr_t buf,
-                 size_t len, int token, int maxpacket)
-{
-       int     i, count;
-       u64     addr = buf;
-
-       /* one buffer entry per 4K ... first might be short or unaligned */
-       qtd->hw_buf[0] = cpu_to_hc32(fusbh200, (u32)addr);
-       qtd->hw_buf_hi[0] = cpu_to_hc32(fusbh200, (u32)(addr >> 32));
-       count = 0x1000 - (buf & 0x0fff);        /* rest of that page */
-       if (likely (len < count))               /* ... iff needed */
-               count = len;
-       else {
-               buf +=  0x1000;
-               buf &= ~0x0fff;
-
-               /* per-qtd limit: from 16K to 20K (best alignment) */
-               for (i = 1; count < len && i < 5; i++) {
-                       addr = buf;
-                       qtd->hw_buf[i] = cpu_to_hc32(fusbh200, (u32)addr);
-                       qtd->hw_buf_hi[i] = cpu_to_hc32(fusbh200,
-                                       (u32)(addr >> 32));
-                       buf += 0x1000;
-                       if ((count + 0x1000) < len)
-                               count += 0x1000;
-                       else
-                               count = len;
-               }
-
-               /* short packets may only terminate transfers */
-               if (count != len)
-                       count -= (count % maxpacket);
-       }
-       qtd->hw_token = cpu_to_hc32(fusbh200, (count << 16) | token);
-       qtd->length = count;
-
-       return count;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static inline void
-qh_update (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh, struct fusbh200_qtd *qtd)
-{
-       struct fusbh200_qh_hw *hw = qh->hw;
-
-       /* writes to an active overlay are unsafe */
-       BUG_ON(qh->qh_state != QH_STATE_IDLE);
-
-       hw->hw_qtd_next = QTD_NEXT(fusbh200, qtd->qtd_dma);
-       hw->hw_alt_next = FUSBH200_LIST_END(fusbh200);
-
-       /* Except for control endpoints, we make hardware maintain data
-        * toggle (like OHCI) ... here (re)initialize the toggle in the QH,
-        * and set the pseudo-toggle in udev. Only usb_clear_halt() will
-        * ever clear it.
-        */
-       if (!(hw->hw_info1 & cpu_to_hc32(fusbh200, QH_TOGGLE_CTL))) {
-               unsigned        is_out, epnum;
-
-               is_out = qh->is_out;
-               epnum = (hc32_to_cpup(fusbh200, &hw->hw_info1) >> 8) & 0x0f;
-               if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) {
-                       hw->hw_token &= ~cpu_to_hc32(fusbh200, QTD_TOGGLE);
-                       usb_settoggle (qh->dev, epnum, is_out, 1);
-               }
-       }
-
-       hw->hw_token &= cpu_to_hc32(fusbh200, QTD_TOGGLE | QTD_STS_PING);
-}
-
-/* if it weren't for a common silicon quirk (writing the dummy into the qh
- * overlay, so qh->hw_token wrongly becomes inactive/halted), only fault
- * recovery (including urb dequeue) would need software changes to a QH...
- */
-static void
-qh_refresh (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
-       struct fusbh200_qtd *qtd;
-
-       if (list_empty (&qh->qtd_list))
-               qtd = qh->dummy;
-       else {
-               qtd = list_entry (qh->qtd_list.next,
-                               struct fusbh200_qtd, qtd_list);
-               /*
-                * first qtd may already be partially processed.
-                * If we come here during unlink, the QH overlay region
-                * might have reference to the just unlinked qtd. The
-                * qtd is updated in qh_completions(). Update the QH
-                * overlay here.
-                */
-               if (cpu_to_hc32(fusbh200, qtd->qtd_dma) == qh->hw->hw_current) {
-                       qh->hw->hw_qtd_next = qtd->hw_next;
-                       qtd = NULL;
-               }
-       }
-
-       if (qtd)
-               qh_update (fusbh200, qh, qtd);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void qh_link_async(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh);
-
-static void fusbh200_clear_tt_buffer_complete(struct usb_hcd *hcd,
-               struct usb_host_endpoint *ep)
-{
-       struct fusbh200_hcd             *fusbh200 = hcd_to_fusbh200(hcd);
-       struct fusbh200_qh              *qh = ep->hcpriv;
-       unsigned long           flags;
-
-       spin_lock_irqsave(&fusbh200->lock, flags);
-       qh->clearing_tt = 0;
-       if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list)
-                       && fusbh200->rh_state == FUSBH200_RH_RUNNING)
-               qh_link_async(fusbh200, qh);
-       spin_unlock_irqrestore(&fusbh200->lock, flags);
-}
-
-static void fusbh200_clear_tt_buffer(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh,
-               struct urb *urb, u32 token)
-{
-
-       /* If an async split transaction gets an error or is unlinked,
-        * the TT buffer may be left in an indeterminate state.  We
-        * have to clear the TT buffer.
-        *
-        * Note: this routine is never called for Isochronous transfers.
-        */
-       if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) {
-               struct usb_device *tt = urb->dev->tt->hub;
-
-               dev_dbg(&tt->dev,
-                       "clear tt buffer port %d, a%d ep%d t%08x\n",
-                       urb->dev->ttport, urb->dev->devnum,
-                       usb_pipeendpoint(urb->pipe), token);
-
-               if (urb->dev->tt->hub !=
-                   fusbh200_to_hcd(fusbh200)->self.root_hub) {
-                       if (usb_hub_clear_tt_buffer(urb) == 0)
-                               qh->clearing_tt = 1;
-               }
-       }
-}
-
-static int qtd_copy_status (
-       struct fusbh200_hcd *fusbh200,
-       struct urb *urb,
-       size_t length,
-       u32 token
-)
-{
-       int     status = -EINPROGRESS;
-
-       /* count IN/OUT bytes, not SETUP (even short packets) */
-       if (likely (QTD_PID (token) != 2))
-               urb->actual_length += length - QTD_LENGTH (token);
-
-       /* don't modify error codes */
-       if (unlikely(urb->unlinked))
-               return status;
-
-       /* force cleanup after short read; not always an error */
-       if (unlikely (IS_SHORT_READ (token)))
-               status = -EREMOTEIO;
-
-       /* serious "can't proceed" faults reported by the hardware */
-       if (token & QTD_STS_HALT) {
-               if (token & QTD_STS_BABBLE) {
-                       /* FIXME "must" disable babbling device's port too */
-                       status = -EOVERFLOW;
-               /* CERR nonzero + halt --> stall */
-               } else if (QTD_CERR(token)) {
-                       status = -EPIPE;
-
-               /* In theory, more than one of the following bits can be set
-                * since they are sticky and the transaction is retried.
-                * Which to test first is rather arbitrary.
-                */
-               } else if (token & QTD_STS_MMF) {
-                       /* fs/ls interrupt xfer missed the complete-split */
-                       status = -EPROTO;
-               } else if (token & QTD_STS_DBE) {
-                       status = (QTD_PID (token) == 1) /* IN ? */
-                               ? -ENOSR  /* hc couldn't read data */
-                               : -ECOMM; /* hc couldn't write data */
-               } else if (token & QTD_STS_XACT) {
-                       /* timeout, bad CRC, wrong PID, etc */
-                       fusbh200_dbg(fusbh200, "devpath %s ep%d%s 3strikes\n",
-                               urb->dev->devpath,
-                               usb_pipeendpoint(urb->pipe),
-                               usb_pipein(urb->pipe) ? "in" : "out");
-                       status = -EPROTO;
-               } else {        /* unknown */
-                       status = -EPROTO;
-               }
-
-               fusbh200_dbg(fusbh200,
-                       "dev%d ep%d%s qtd token %08x --> status %d\n",
-                       usb_pipedevice (urb->pipe),
-                       usb_pipeendpoint (urb->pipe),
-                       usb_pipein (urb->pipe) ? "in" : "out",
-                       token, status);
-       }
-
-       return status;
-}
-
-static void
-fusbh200_urb_done(struct fusbh200_hcd *fusbh200, struct urb *urb, int status)
-__releases(fusbh200->lock)
-__acquires(fusbh200->lock)
-{
-       if (likely (urb->hcpriv != NULL)) {
-               struct fusbh200_qh      *qh = (struct fusbh200_qh *) urb->hcpriv;
-
-               /* S-mask in a QH means it's an interrupt urb */
-               if ((qh->hw->hw_info2 & cpu_to_hc32(fusbh200, QH_SMASK)) != 0) {
-
-                       /* ... update hc-wide periodic stats (for usbfs) */
-                       fusbh200_to_hcd(fusbh200)->self.bandwidth_int_reqs--;
-               }
-       }
-
-       if (unlikely(urb->unlinked)) {
-               COUNT(fusbh200->stats.unlink);
-       } else {
-               /* report non-error and short read status as zero */
-               if (status == -EINPROGRESS || status == -EREMOTEIO)
-                       status = 0;
-               COUNT(fusbh200->stats.complete);
-       }
-
-#ifdef FUSBH200_URB_TRACE
-       fusbh200_dbg (fusbh200,
-               "%s %s urb %p ep%d%s status %d len %d/%d\n",
-               __func__, urb->dev->devpath, urb,
-               usb_pipeendpoint (urb->pipe),
-               usb_pipein (urb->pipe) ? "in" : "out",
-               status,
-               urb->actual_length, urb->transfer_buffer_length);
-#endif
-
-       /* complete() can reenter this HCD */
-       usb_hcd_unlink_urb_from_ep(fusbh200_to_hcd(fusbh200), urb);
-       spin_unlock (&fusbh200->lock);
-       usb_hcd_giveback_urb(fusbh200_to_hcd(fusbh200), urb, status);
-       spin_lock (&fusbh200->lock);
-}
-
-static int qh_schedule (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh);
-
-/*
- * Process and free completed qtds for a qh, returning URBs to drivers.
- * Chases up to qh->hw_current.  Returns number of completions called,
- * indicating how much "real" work we did.
- */
-static unsigned
-qh_completions (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
-       struct fusbh200_qtd             *last, *end = qh->dummy;
-       struct list_head        *entry, *tmp;
-       int                     last_status;
-       int                     stopped;
-       unsigned                count = 0;
-       u8                      state;
-       struct fusbh200_qh_hw   *hw = qh->hw;
-
-       if (unlikely (list_empty (&qh->qtd_list)))
-               return count;
-
-       /* completions (or tasks on other cpus) must never clobber HALT
-        * till we've gone through and cleaned everything up, even when
-        * they add urbs to this qh's queue or mark them for unlinking.
-        *
-        * NOTE:  unlinking expects to be done in queue order.
-        *
-        * It's a bug for qh->qh_state to be anything other than
-        * QH_STATE_IDLE, unless our caller is scan_async() or
-        * scan_intr().
-        */
-       state = qh->qh_state;
-       qh->qh_state = QH_STATE_COMPLETING;
-       stopped = (state == QH_STATE_IDLE);
-
- rescan:
-       last = NULL;
-       last_status = -EINPROGRESS;
-       qh->needs_rescan = 0;
-
-       /* remove de-activated QTDs from front of queue.
-        * after faults (including short reads), cleanup this urb
-        * then let the queue advance.
-        * if queue is stopped, handles unlinks.
-        */
-       list_for_each_safe (entry, tmp, &qh->qtd_list) {
-               struct fusbh200_qtd     *qtd;
-               struct urb      *urb;
-               u32             token = 0;
-
-               qtd = list_entry (entry, struct fusbh200_qtd, qtd_list);
-               urb = qtd->urb;
-
-               /* clean up any state from previous QTD ...*/
-               if (last) {
-                       if (likely (last->urb != urb)) {
-                               fusbh200_urb_done(fusbh200, last->urb, last_status);
-                               count++;
-                               last_status = -EINPROGRESS;
-                       }
-                       fusbh200_qtd_free (fusbh200, last);
-                       last = NULL;
-               }
-
-               /* ignore urbs submitted during completions we reported */
-               if (qtd == end)
-                       break;
-
-               /* hardware copies qtd out of qh overlay */
-               rmb ();
-               token = hc32_to_cpu(fusbh200, qtd->hw_token);
-
-               /* always clean up qtds the hc de-activated */
- retry_xacterr:
-               if ((token & QTD_STS_ACTIVE) == 0) {
-
-                       /* Report Data Buffer Error: non-fatal but useful */
-                       if (token & QTD_STS_DBE)
-                               fusbh200_dbg(fusbh200,
-                                       "detected DataBufferErr for urb %p ep%d%s len %d, qtd %p [qh %p]\n",
-                                       urb,
-                                       usb_endpoint_num(&urb->ep->desc),
-                                       usb_endpoint_dir_in(&urb->ep->desc) ? "in" : "out",
-                                       urb->transfer_buffer_length,
-                                       qtd,
-                                       qh);
-
-                       /* on STALL, error, and short reads this urb must
-                        * complete and all its qtds must be recycled.
-                        */
-                       if ((token & QTD_STS_HALT) != 0) {
-
-                               /* retry transaction errors until we
-                                * reach the software xacterr limit
-                                */
-                               if ((token & QTD_STS_XACT) &&
-                                               QTD_CERR(token) == 0 &&
-                                               ++qh->xacterrs < QH_XACTERR_MAX &&
-                                               !urb->unlinked) {
-                                       fusbh200_dbg(fusbh200,
-       "detected XactErr len %zu/%zu retry %d\n",
-       qtd->length - QTD_LENGTH(token), qtd->length, qh->xacterrs);
-
-                                       /* reset the token in the qtd and the
-                                        * qh overlay (which still contains
-                                        * the qtd) so that we pick up from
-                                        * where we left off
-                                        */
-                                       token &= ~QTD_STS_HALT;
-                                       token |= QTD_STS_ACTIVE |
-                                                       (FUSBH200_TUNE_CERR << 10);
-                                       qtd->hw_token = cpu_to_hc32(fusbh200,
-                                                       token);
-                                       wmb();
-                                       hw->hw_token = cpu_to_hc32(fusbh200,
-                                                       token);
-                                       goto retry_xacterr;
-                               }
-                               stopped = 1;
-
-                       /* magic dummy for some short reads; qh won't advance.
-                        * that silicon quirk can kick in with this dummy too.
-                        *
-                        * other short reads won't stop the queue, including
-                        * control transfers (status stage handles that) or
-                        * most other single-qtd reads ... the queue stops if
-                        * URB_SHORT_NOT_OK was set so the driver submitting
-                        * the urbs could clean it up.
-                        */
-                       } else if (IS_SHORT_READ (token)
-                                       && !(qtd->hw_alt_next
-                                               & FUSBH200_LIST_END(fusbh200))) {
-                               stopped = 1;
-                       }
-
-               /* stop scanning when we reach qtds the hc is using */
-               } else if (likely (!stopped
-                               && fusbh200->rh_state >= FUSBH200_RH_RUNNING)) {
-                       break;
-
-               /* scan the whole queue for unlinks whenever it stops */
-               } else {
-                       stopped = 1;
-
-                       /* cancel everything if we halt, suspend, etc */
-                       if (fusbh200->rh_state < FUSBH200_RH_RUNNING)
-                               last_status = -ESHUTDOWN;
-
-                       /* this qtd is active; skip it unless a previous qtd
-                        * for its urb faulted, or its urb was canceled.
-                        */
-                       else if (last_status == -EINPROGRESS && !urb->unlinked)
-                               continue;
-
-                       /* qh unlinked; token in overlay may be most current */
-                       if (state == QH_STATE_IDLE
-                                       && cpu_to_hc32(fusbh200, qtd->qtd_dma)
-                                               == hw->hw_current) {
-                               token = hc32_to_cpu(fusbh200, hw->hw_token);
-
-                               /* An unlink may leave an incomplete
-                                * async transaction in the TT buffer.
-                                * We have to clear it.
-                                */
-                               fusbh200_clear_tt_buffer(fusbh200, qh, urb, token);
-                       }
-               }
-
-               /* unless we already know the urb's status, collect qtd status
-                * and update count of bytes transferred.  in common short read
-                * cases with only one data qtd (including control transfers),
-                * queue processing won't halt.  but with two or more qtds (for
-                * example, with a 32 KB transfer), when the first qtd gets a
-                * short read the second must be removed by hand.
-                */
-               if (last_status == -EINPROGRESS) {
-                       last_status = qtd_copy_status(fusbh200, urb,
-                                       qtd->length, token);
-                       if (last_status == -EREMOTEIO
-                                       && (qtd->hw_alt_next
-                                               & FUSBH200_LIST_END(fusbh200)))
-                               last_status = -EINPROGRESS;
-
-                       /* As part of low/full-speed endpoint-halt processing
-                        * we must clear the TT buffer (11.17.5).
-                        */
-                       if (unlikely(last_status != -EINPROGRESS &&
-                                       last_status != -EREMOTEIO)) {
-                               /* The TT's in some hubs malfunction when they
-                                * receive this request following a STALL (they
-                                * stop sending isochronous packets).  Since a
-                                * STALL can't leave the TT buffer in a busy
-                                * state (if you believe Figures 11-48 - 11-51
-                                * in the USB 2.0 spec), we won't clear the TT
-                                * buffer in this case.  Strictly speaking this
-                                * is a violation of the spec.
-                                */
-                               if (last_status != -EPIPE)
-                                       fusbh200_clear_tt_buffer(fusbh200, qh, urb,
-                                                       token);
-                       }
-               }
-
-               /* if we're removing something not at the queue head,
-                * patch the hardware queue pointer.
-                */
-               if (stopped && qtd->qtd_list.prev != &qh->qtd_list) {
-                       last = list_entry (qtd->qtd_list.prev,
-                                       struct fusbh200_qtd, qtd_list);
-                       last->hw_next = qtd->hw_next;
-               }
-
-               /* remove qtd; it's recycled after possible urb completion */
-               list_del (&qtd->qtd_list);
-               last = qtd;
-
-               /* reinit the xacterr counter for the next qtd */
-               qh->xacterrs = 0;
-       }
-
-       /* last urb's completion might still need calling */
-       if (likely (last != NULL)) {
-               fusbh200_urb_done(fusbh200, last->urb, last_status);
-               count++;
-               fusbh200_qtd_free (fusbh200, last);
-       }
-
-       /* Do we need to rescan for URBs dequeued during a giveback? */
-       if (unlikely(qh->needs_rescan)) {
-               /* If the QH is already unlinked, do the rescan now. */
-               if (state == QH_STATE_IDLE)
-                       goto rescan;
-
-               /* Otherwise we have to wait until the QH is fully unlinked.
-                * Our caller will start an unlink if qh->needs_rescan is
-                * set.  But if an unlink has already started, nothing needs
-                * to be done.
-                */
-               if (state != QH_STATE_LINKED)
-                       qh->needs_rescan = 0;
-       }
-
-       /* restore original state; caller must unlink or relink */
-       qh->qh_state = state;
-
-       /* be sure the hardware's done with the qh before refreshing
-        * it after fault cleanup, or recovering from silicon wrongly
-        * overlaying the dummy qtd (which reduces DMA chatter).
-        */
-       if (stopped != 0 || hw->hw_qtd_next == FUSBH200_LIST_END(fusbh200)) {
-               switch (state) {
-               case QH_STATE_IDLE:
-                       qh_refresh(fusbh200, qh);
-                       break;
-               case QH_STATE_LINKED:
-                       /* We won't refresh a QH that's linked (after the HC
-                        * stopped the queue).  That avoids a race:
-                        *  - HC reads first part of QH;
-                        *  - CPU updates that first part and the token;
-                        *  - HC reads rest of that QH, including token
-                        * Result:  HC gets an inconsistent image, and then
-                        * DMAs to/from the wrong memory (corrupting it).
-                        *
-                        * That should be rare for interrupt transfers,
-                        * except maybe high bandwidth ...
-                        */
-
-                       /* Tell the caller to start an unlink */
-                       qh->needs_rescan = 1;
-                       break;
-               /* otherwise, unlink already started */
-               }
-       }
-
-       return count;
-}
-
-/*-------------------------------------------------------------------------*/
-
-// high bandwidth multiplier, as encoded in highspeed endpoint descriptors
-#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
-// ... and packet size, for any kind of endpoint descriptor
-#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff)
-
-/*
- * reverse of qh_urb_transaction:  free a list of TDs.
- * used for cleanup after errors, before HC sees an URB's TDs.
- */
-static void qtd_list_free (
-       struct fusbh200_hcd             *fusbh200,
-       struct urb              *urb,
-       struct list_head        *qtd_list
-) {
-       struct list_head        *entry, *temp;
-
-       list_for_each_safe (entry, temp, qtd_list) {
-               struct fusbh200_qtd     *qtd;
-
-               qtd = list_entry (entry, struct fusbh200_qtd, qtd_list);
-               list_del (&qtd->qtd_list);
-               fusbh200_qtd_free (fusbh200, qtd);
-       }
-}
-
-/*
- * create a list of filled qtds for this URB; won't link into qh.
- */
-static struct list_head *
-qh_urb_transaction (
-       struct fusbh200_hcd             *fusbh200,
-       struct urb              *urb,
-       struct list_head        *head,
-       gfp_t                   flags
-) {
-       struct fusbh200_qtd             *qtd, *qtd_prev;
-       dma_addr_t              buf;
-       int                     len, this_sg_len, maxpacket;
-       int                     is_input;
-       u32                     token;
-       int                     i;
-       struct scatterlist      *sg;
-
-       /*
-        * URBs map to sequences of QTDs:  one logical transaction
-        */
-       qtd = fusbh200_qtd_alloc (fusbh200, flags);
-       if (unlikely (!qtd))
-               return NULL;
-       list_add_tail (&qtd->qtd_list, head);
-       qtd->urb = urb;
-
-       token = QTD_STS_ACTIVE;
-       token |= (FUSBH200_TUNE_CERR << 10);
-       /* for split transactions, SplitXState initialized to zero */
-
-       len = urb->transfer_buffer_length;
-       is_input = usb_pipein (urb->pipe);
-       if (usb_pipecontrol (urb->pipe)) {
-               /* SETUP pid */
-               qtd_fill(fusbh200, qtd, urb->setup_dma,
-                               sizeof (struct usb_ctrlrequest),
-                               token | (2 /* "setup" */ << 8), 8);
-
-               /* ... and always at least one more pid */
-               token ^= QTD_TOGGLE;
-               qtd_prev = qtd;
-               qtd = fusbh200_qtd_alloc (fusbh200, flags);
-               if (unlikely (!qtd))
-                       goto cleanup;
-               qtd->urb = urb;
-               qtd_prev->hw_next = QTD_NEXT(fusbh200, qtd->qtd_dma);
-               list_add_tail (&qtd->qtd_list, head);
-
-               /* for zero length DATA stages, STATUS is always IN */
-               if (len == 0)
-                       token |= (1 /* "in" */ << 8);
-       }
-
-       /*
-        * data transfer stage:  buffer setup
-        */
-       i = urb->num_mapped_sgs;
-       if (len > 0 && i > 0) {
-               sg = urb->sg;
-               buf = sg_dma_address(sg);
-
-               /* urb->transfer_buffer_length may be smaller than the
-                * size of the scatterlist (or vice versa)
-                */
-               this_sg_len = min_t(int, sg_dma_len(sg), len);
-       } else {
-               sg = NULL;
-               buf = urb->transfer_dma;
-               this_sg_len = len;
-       }
-
-       if (is_input)
-               token |= (1 /* "in" */ << 8);
-       /* else it's already initted to "out" pid (0 << 8) */
-
-       maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input));
-
-       /*
-        * buffer gets wrapped in one or more qtds;
-        * last one may be "short" (including zero len)
-        * and may serve as a control status ack
-        */
-       for (;;) {
-               int this_qtd_len;
-
-               this_qtd_len = qtd_fill(fusbh200, qtd, buf, this_sg_len, token,
-                               maxpacket);
-               this_sg_len -= this_qtd_len;
-               len -= this_qtd_len;
-               buf += this_qtd_len;
-
-               /*
-                * short reads advance to a "magic" dummy instead of the next
-                * qtd ... that forces the queue to stop, for manual cleanup.
-                * (this will usually be overridden later.)
-                */
-               if (is_input)
-                       qtd->hw_alt_next = fusbh200->async->hw->hw_alt_next;
-
-               /* qh makes control packets use qtd toggle; maybe switch it */
-               if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0)
-                       token ^= QTD_TOGGLE;
-
-               if (likely(this_sg_len <= 0)) {
-                       if (--i <= 0 || len <= 0)
-                               break;
-                       sg = sg_next(sg);
-                       buf = sg_dma_address(sg);
-                       this_sg_len = min_t(int, sg_dma_len(sg), len);
-               }
-
-               qtd_prev = qtd;
-               qtd = fusbh200_qtd_alloc (fusbh200, flags);
-               if (unlikely (!qtd))
-                       goto cleanup;
-               qtd->urb = urb;
-               qtd_prev->hw_next = QTD_NEXT(fusbh200, qtd->qtd_dma);
-               list_add_tail (&qtd->qtd_list, head);
-       }
-
-       /*
-        * unless the caller requires manual cleanup after short reads,
-        * have the alt_next mechanism keep the queue running after the
-        * last data qtd (the only one, for control and most other cases).
-        */
-       if (likely ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0
-                               || usb_pipecontrol (urb->pipe)))
-               qtd->hw_alt_next = FUSBH200_LIST_END(fusbh200);
-
-       /*
-        * control requests may need a terminating data "status" ack;
-        * other OUT ones may need a terminating short packet
-        * (zero length).
-        */
-       if (likely (urb->transfer_buffer_length != 0)) {
-               int     one_more = 0;
-
-               if (usb_pipecontrol (urb->pipe)) {
-                       one_more = 1;
-                       token ^= 0x0100;        /* "in" <--> "out"  */
-                       token |= QTD_TOGGLE;    /* force DATA1 */
-               } else if (usb_pipeout(urb->pipe)
-                               && (urb->transfer_flags & URB_ZERO_PACKET)
-                               && !(urb->transfer_buffer_length % maxpacket)) {
-                       one_more = 1;
-               }
-               if (one_more) {
-                       qtd_prev = qtd;
-                       qtd = fusbh200_qtd_alloc (fusbh200, flags);
-                       if (unlikely (!qtd))
-                               goto cleanup;
-                       qtd->urb = urb;
-                       qtd_prev->hw_next = QTD_NEXT(fusbh200, qtd->qtd_dma);
-                       list_add_tail (&qtd->qtd_list, head);
-
-                       /* never any data in such packets */
-                       qtd_fill(fusbh200, qtd, 0, 0, token, 0);
-               }
-       }
-
-       /* by default, enable interrupt on urb completion */
-       if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT)))
-               qtd->hw_token |= cpu_to_hc32(fusbh200, QTD_IOC);
-       return head;
-
-cleanup:
-       qtd_list_free (fusbh200, urb, head);
-       return NULL;
-}
-
-/*-------------------------------------------------------------------------*/
-
-// Would be best to create all qh's from config descriptors,
-// when each interface/altsetting is established.  Unlink
-// any previous qh and cancel its urbs first; endpoints are
-// implicitly reset then (data toggle too).
-// That'd mean updating how usbcore talks to HCDs. (2.7?)
-
-
-/*
- * Each QH holds a qtd list; a QH is used for everything except iso.
- *
- * For interrupt urbs, the scheduler must set the microframe scheduling
- * mask(s) each time the QH gets scheduled.  For highspeed, that's
- * just one microframe in the s-mask.  For split interrupt transactions
- * there are additional complications: c-mask, maybe FSTNs.
- */
-static struct fusbh200_qh *
-qh_make (
-       struct fusbh200_hcd             *fusbh200,
-       struct urb              *urb,
-       gfp_t                   flags
-) {
-       struct fusbh200_qh              *qh = fusbh200_qh_alloc (fusbh200, flags);
-       u32                     info1 = 0, info2 = 0;
-       int                     is_input, type;
-       int                     maxp = 0;
-       struct usb_tt           *tt = urb->dev->tt;
-       struct fusbh200_qh_hw   *hw;
-
-       if (!qh)
-               return qh;
-
-       /*
-        * init endpoint/device data for this QH
-        */
-       info1 |= usb_pipeendpoint (urb->pipe) << 8;
-       info1 |= usb_pipedevice (urb->pipe) << 0;
-
-       is_input = usb_pipein (urb->pipe);
-       type = usb_pipetype (urb->pipe);
-       maxp = usb_maxpacket (urb->dev, urb->pipe, !is_input);
-
-       /* 1024 byte maxpacket is a hardware ceiling.  High bandwidth
-        * acts like up to 3KB, but is built from smaller packets.
-        */
-       if (max_packet(maxp) > 1024) {
-               fusbh200_dbg(fusbh200, "bogus qh maxpacket %d\n", max_packet(maxp));
-               goto done;
-       }
-
-       /* Compute interrupt scheduling parameters just once, and save.
-        * - allowing for high bandwidth, how many nsec/uframe are used?
-        * - split transactions need a second CSPLIT uframe; same question
-        * - splits also need a schedule gap (for full/low speed I/O)
-        * - qh has a polling interval
-        *
-        * For control/bulk requests, the HC or TT handles these.
-        */
-       if (type == PIPE_INTERRUPT) {
-               qh->usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH,
-                               is_input, 0,
-                               hb_mult(maxp) * max_packet(maxp)));
-               qh->start = NO_FRAME;
-
-               if (urb->dev->speed == USB_SPEED_HIGH) {
-                       qh->c_usecs = 0;
-                       qh->gap_uf = 0;
-
-                       qh->period = urb->interval >> 3;
-                       if (qh->period == 0 && urb->interval != 1) {
-                               /* NOTE interval 2 or 4 uframes could work.
-                                * But interval 1 scheduling is simpler, and
-                                * includes high bandwidth.
-                                */
-                               urb->interval = 1;
-                       } else if (qh->period > fusbh200->periodic_size) {
-                               qh->period = fusbh200->periodic_size;
-                               urb->interval = qh->period << 3;
-                       }
-               } else {
-                       int             think_time;
-
-                       /* gap is f(FS/LS transfer times) */
-                       qh->gap_uf = 1 + usb_calc_bus_time (urb->dev->speed,
-                                       is_input, 0, maxp) / (125 * 1000);
-
-                       /* FIXME this just approximates SPLIT/CSPLIT times */
-                       if (is_input) {         // SPLIT, gap, CSPLIT+DATA
-                               qh->c_usecs = qh->usecs + HS_USECS (0);
-                               qh->usecs = HS_USECS (1);
-                       } else {                // SPLIT+DATA, gap, CSPLIT
-                               qh->usecs += HS_USECS (1);
-                               qh->c_usecs = HS_USECS (0);
-                       }
-
-                       think_time = tt ? tt->think_time : 0;
-                       qh->tt_usecs = NS_TO_US (think_time +
-                                       usb_calc_bus_time (urb->dev->speed,
-                                       is_input, 0, max_packet (maxp)));
-                       qh->period = urb->interval;
-                       if (qh->period > fusbh200->periodic_size) {
-                               qh->period = fusbh200->periodic_size;
-                               urb->interval = qh->period;
-                       }
-               }
-       }
-
-       /* support for tt scheduling, and access to toggles */
-       qh->dev = urb->dev;
-
-       /* using TT? */
-       switch (urb->dev->speed) {
-       case USB_SPEED_LOW:
-               info1 |= QH_LOW_SPEED;
-               /* FALL THROUGH */
-
-       case USB_SPEED_FULL:
-               /* EPS 0 means "full" */
-               if (type != PIPE_INTERRUPT)
-                       info1 |= (FUSBH200_TUNE_RL_TT << 28);
-               if (type == PIPE_CONTROL) {
-                       info1 |= QH_CONTROL_EP;         /* for TT */
-                       info1 |= QH_TOGGLE_CTL;         /* toggle from qtd */
-               }
-               info1 |= maxp << 16;
-
-               info2 |= (FUSBH200_TUNE_MULT_TT << 30);
-
-               /* Some Freescale processors have an erratum in which the
-                * port number in the queue head was 0..N-1 instead of 1..N.
-                */
-               if (fusbh200_has_fsl_portno_bug(fusbh200))
-                       info2 |= (urb->dev->ttport-1) << 23;
-               else
-                       info2 |= urb->dev->ttport << 23;
-
-               /* set the address of the TT; for TDI's integrated
-                * root hub tt, leave it zeroed.
-                */
-               if (tt && tt->hub != fusbh200_to_hcd(fusbh200)->self.root_hub)
-                       info2 |= tt->hub->devnum << 16;
-
-               /* NOTE:  if (PIPE_INTERRUPT) { scheduler sets c-mask } */
-
-               break;
-
-       case USB_SPEED_HIGH:            /* no TT involved */
-               info1 |= QH_HIGH_SPEED;
-               if (type == PIPE_CONTROL) {
-                       info1 |= (FUSBH200_TUNE_RL_HS << 28);
-                       info1 |= 64 << 16;      /* usb2 fixed maxpacket */
-                       info1 |= QH_TOGGLE_CTL; /* toggle from qtd */
-                       info2 |= (FUSBH200_TUNE_MULT_HS << 30);
-               } else if (type == PIPE_BULK) {
-                       info1 |= (FUSBH200_TUNE_RL_HS << 28);
-                       /* The USB spec says that high speed bulk endpoints
-                        * always use 512 byte maxpacket.  But some device
-                        * vendors decided to ignore that, and MSFT is happy
-                        * to help them do so.  So now people expect to use
-                        * such nonconformant devices with Linux too; sigh.
-                        */
-                       info1 |= max_packet(maxp) << 16;
-                       info2 |= (FUSBH200_TUNE_MULT_HS << 30);
-               } else {                /* PIPE_INTERRUPT */
-                       info1 |= max_packet (maxp) << 16;
-                       info2 |= hb_mult (maxp) << 30;
-               }
-               break;
-       default:
-               fusbh200_dbg(fusbh200, "bogus dev %p speed %d\n", urb->dev,
-                       urb->dev->speed);
-done:
-               qh_destroy(fusbh200, qh);
-               return NULL;
-       }
-
-       /* NOTE:  if (PIPE_INTERRUPT) { scheduler sets s-mask } */
-
-       /* init as live, toggle clear, advance to dummy */
-       qh->qh_state = QH_STATE_IDLE;
-       hw = qh->hw;
-       hw->hw_info1 = cpu_to_hc32(fusbh200, info1);
-       hw->hw_info2 = cpu_to_hc32(fusbh200, info2);
-       qh->is_out = !is_input;
-       usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
-       qh_refresh (fusbh200, qh);
-       return qh;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void enable_async(struct fusbh200_hcd *fusbh200)
-{
-       if (fusbh200->async_count++)
-               return;
-
-       /* Stop waiting to turn off the async schedule */
-       fusbh200->enabled_hrtimer_events &= ~BIT(FUSBH200_HRTIMER_DISABLE_ASYNC);
-
-       /* Don't start the schedule until ASS is 0 */
-       fusbh200_poll_ASS(fusbh200);
-       turn_on_io_watchdog(fusbh200);
-}
-
-static void disable_async(struct fusbh200_hcd *fusbh200)
-{
-       if (--fusbh200->async_count)
-               return;
-
-       /* The async schedule and async_unlink list are supposed to be empty */
-       WARN_ON(fusbh200->async->qh_next.qh || fusbh200->async_unlink);
-
-       /* Don't turn off the schedule until ASS is 1 */
-       fusbh200_poll_ASS(fusbh200);
-}
-
-/* move qh (and its qtds) onto async queue; maybe enable queue.  */
-
-static void qh_link_async (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
-       __hc32          dma = QH_NEXT(fusbh200, qh->qh_dma);
-       struct fusbh200_qh      *head;
-
-       /* Don't link a QH if there's a Clear-TT-Buffer pending */
-       if (unlikely(qh->clearing_tt))
-               return;
-
-       WARN_ON(qh->qh_state != QH_STATE_IDLE);
-
-       /* clear halt and/or toggle; and maybe recover from silicon quirk */
-       qh_refresh(fusbh200, qh);
-
-       /* splice right after start */
-       head = fusbh200->async;
-       qh->qh_next = head->qh_next;
-       qh->hw->hw_next = head->hw->hw_next;
-       wmb ();
-
-       head->qh_next.qh = qh;
-       head->hw->hw_next = dma;
-
-       qh->xacterrs = 0;
-       qh->qh_state = QH_STATE_LINKED;
-       /* qtd completions reported later by interrupt */
-
-       enable_async(fusbh200);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * For control/bulk/interrupt, return QH with these TDs appended.
- * Allocates and initializes the QH if necessary.
- * Returns null if it can't allocate a QH it needs to.
- * If the QH has TDs (urbs) already, that's great.
- */
-static struct fusbh200_qh *qh_append_tds (
-       struct fusbh200_hcd             *fusbh200,
-       struct urb              *urb,
-       struct list_head        *qtd_list,
-       int                     epnum,
-       void                    **ptr
-)
-{
-       struct fusbh200_qh              *qh = NULL;
-       __hc32                  qh_addr_mask = cpu_to_hc32(fusbh200, 0x7f);
-
-       qh = (struct fusbh200_qh *) *ptr;
-       if (unlikely (qh == NULL)) {
-               /* can't sleep here, we have fusbh200->lock... */
-               qh = qh_make (fusbh200, urb, GFP_ATOMIC);
-               *ptr = qh;
-       }
-       if (likely (qh != NULL)) {
-               struct fusbh200_qtd     *qtd;
-
-               if (unlikely (list_empty (qtd_list)))
-                       qtd = NULL;
-               else
-                       qtd = list_entry (qtd_list->next, struct fusbh200_qtd,
-                                       qtd_list);
-
-               /* control qh may need patching ... */
-               if (unlikely (epnum == 0)) {
-
-                        /* usb_reset_device() briefly reverts to address 0 */
-                        if (usb_pipedevice (urb->pipe) == 0)
-                               qh->hw->hw_info1 &= ~qh_addr_mask;
-               }
-
-               /* just one way to queue requests: swap with the dummy qtd.
-                * only hc or qh_refresh() ever modify the overlay.
-                */
-               if (likely (qtd != NULL)) {
-                       struct fusbh200_qtd             *dummy;
-                       dma_addr_t              dma;
-                       __hc32                  token;
-
-                       /* to avoid racing the HC, use the dummy td instead of
-                        * the first td of our list (becomes new dummy).  both
-                        * tds stay deactivated until we're done, when the
-                        * HC is allowed to fetch the old dummy (4.10.2).
-                        */
-                       token = qtd->hw_token;
-                       qtd->hw_token = HALT_BIT(fusbh200);
-
-                       dummy = qh->dummy;
-
-                       dma = dummy->qtd_dma;
-                       *dummy = *qtd;
-                       dummy->qtd_dma = dma;
-
-                       list_del (&qtd->qtd_list);
-                       list_add (&dummy->qtd_list, qtd_list);
-                       list_splice_tail(qtd_list, &qh->qtd_list);
-
-                       fusbh200_qtd_init(fusbh200, qtd, qtd->qtd_dma);
-                       qh->dummy = qtd;
-
-                       /* hc must see the new dummy at list end */
-                       dma = qtd->qtd_dma;
-                       qtd = list_entry (qh->qtd_list.prev,
-                                       struct fusbh200_qtd, qtd_list);
-                       qtd->hw_next = QTD_NEXT(fusbh200, dma);
-
-                       /* let the hc process these next qtds */
-                       wmb ();
-                       dummy->hw_token = token;
-
-                       urb->hcpriv = qh;
-               }
-       }
-       return qh;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int
-submit_async (
-       struct fusbh200_hcd             *fusbh200,
-       struct urb              *urb,
-       struct list_head        *qtd_list,
-       gfp_t                   mem_flags
-) {
-       int                     epnum;
-       unsigned long           flags;
-       struct fusbh200_qh              *qh = NULL;
-       int                     rc;
-
-       epnum = urb->ep->desc.bEndpointAddress;
-
-#ifdef FUSBH200_URB_TRACE
-       {
-               struct fusbh200_qtd *qtd;
-               qtd = list_entry(qtd_list->next, struct fusbh200_qtd, qtd_list);
-               fusbh200_dbg(fusbh200,
-                        "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
-                        __func__, urb->dev->devpath, urb,
-                        epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out",
-                        urb->transfer_buffer_length,
-                        qtd, urb->ep->hcpriv);
-       }
-#endif
-
-       spin_lock_irqsave (&fusbh200->lock, flags);
-       if (unlikely(!HCD_HW_ACCESSIBLE(fusbh200_to_hcd(fusbh200)))) {
-               rc = -ESHUTDOWN;
-               goto done;
-       }
-       rc = usb_hcd_link_urb_to_ep(fusbh200_to_hcd(fusbh200), urb);
-       if (unlikely(rc))
-               goto done;
-
-       qh = qh_append_tds(fusbh200, urb, qtd_list, epnum, &urb->ep->hcpriv);
-       if (unlikely(qh == NULL)) {
-               usb_hcd_unlink_urb_from_ep(fusbh200_to_hcd(fusbh200), urb);
-               rc = -ENOMEM;
-               goto done;
-       }
-
-       /* Control/bulk operations through TTs don't need scheduling,
-        * the HC and TT handle it when the TT has a buffer ready.
-        */
-       if (likely (qh->qh_state == QH_STATE_IDLE))
-               qh_link_async(fusbh200, qh);
- done:
-       spin_unlock_irqrestore (&fusbh200->lock, flags);
-       if (unlikely (qh == NULL))
-               qtd_list_free (fusbh200, urb, qtd_list);
-       return rc;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void single_unlink_async(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
-       struct fusbh200_qh              *prev;
-
-       /* Add to the end of the list of QHs waiting for the next IAAD */
-       qh->qh_state = QH_STATE_UNLINK;
-       if (fusbh200->async_unlink)
-               fusbh200->async_unlink_last->unlink_next = qh;
-       else
-               fusbh200->async_unlink = qh;
-       fusbh200->async_unlink_last = qh;
-
-       /* Unlink it from the schedule */
-       prev = fusbh200->async;
-       while (prev->qh_next.qh != qh)
-               prev = prev->qh_next.qh;
-
-       prev->hw->hw_next = qh->hw->hw_next;
-       prev->qh_next = qh->qh_next;
-       if (fusbh200->qh_scan_next == qh)
-               fusbh200->qh_scan_next = qh->qh_next.qh;
-}
-
-static void start_iaa_cycle(struct fusbh200_hcd *fusbh200, bool nested)
-{
-       /*
-        * Do nothing if an IAA cycle is already running or
-        * if one will be started shortly.
-        */
-       if (fusbh200->async_iaa || fusbh200->async_unlinking)
-               return;
-
-       /* Do all the waiting QHs at once */
-       fusbh200->async_iaa = fusbh200->async_unlink;
-       fusbh200->async_unlink = NULL;
-
-       /* If the controller isn't running, we don't have to wait for it */
-       if (unlikely(fusbh200->rh_state < FUSBH200_RH_RUNNING)) {
-               if (!nested)            /* Avoid recursion */
-                       end_unlink_async(fusbh200);
-
-       /* Otherwise start a new IAA cycle */
-       } else if (likely(fusbh200->rh_state == FUSBH200_RH_RUNNING)) {
-               /* Make sure the unlinks are all visible to the hardware */
-               wmb();
-
-               fusbh200_writel(fusbh200, fusbh200->command | CMD_IAAD,
-                               &fusbh200->regs->command);
-               fusbh200_readl(fusbh200, &fusbh200->regs->command);
-               fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_IAA_WATCHDOG, true);
-       }
-}
-
-/* the async qh for the qtds being unlinked are now gone from the HC */
-
-static void end_unlink_async(struct fusbh200_hcd *fusbh200)
-{
-       struct fusbh200_qh              *qh;
-
-       /* Process the idle QHs */
- restart:
-       fusbh200->async_unlinking = true;
-       while (fusbh200->async_iaa) {
-               qh = fusbh200->async_iaa;
-               fusbh200->async_iaa = qh->unlink_next;
-               qh->unlink_next = NULL;
-
-               qh->qh_state = QH_STATE_IDLE;
-               qh->qh_next.qh = NULL;
-
-               qh_completions(fusbh200, qh);
-               if (!list_empty(&qh->qtd_list) &&
-                               fusbh200->rh_state == FUSBH200_RH_RUNNING)
-                       qh_link_async(fusbh200, qh);
-               disable_async(fusbh200);
-       }
-       fusbh200->async_unlinking = false;
-
-       /* Start a new IAA cycle if any QHs are waiting for it */
-       if (fusbh200->async_unlink) {
-               start_iaa_cycle(fusbh200, true);
-               if (unlikely(fusbh200->rh_state < FUSBH200_RH_RUNNING))
-                       goto restart;
-       }
-}
-
-static void unlink_empty_async(struct fusbh200_hcd *fusbh200)
-{
-       struct fusbh200_qh              *qh, *next;
-       bool                    stopped = (fusbh200->rh_state < FUSBH200_RH_RUNNING);
-       bool                    check_unlinks_later = false;
-
-       /* Unlink all the async QHs that have been empty for a timer cycle */
-       next = fusbh200->async->qh_next.qh;
-       while (next) {
-               qh = next;
-               next = qh->qh_next.qh;
-
-               if (list_empty(&qh->qtd_list) &&
-                               qh->qh_state == QH_STATE_LINKED) {
-                       if (!stopped && qh->unlink_cycle ==
-                                       fusbh200->async_unlink_cycle)
-                               check_unlinks_later = true;
-                       else
-                               single_unlink_async(fusbh200, qh);
-               }
-       }
-
-       /* Start a new IAA cycle if any QHs are waiting for it */
-       if (fusbh200->async_unlink)
-               start_iaa_cycle(fusbh200, false);
-
-       /* QHs that haven't been empty for long enough will be handled later */
-       if (check_unlinks_later) {
-               fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_ASYNC_UNLINKS, true);
-               ++fusbh200->async_unlink_cycle;
-       }
-}
-
-/* makes sure the async qh will become idle */
-/* caller must own fusbh200->lock */
-
-static void start_unlink_async(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
-       /*
-        * If the QH isn't linked then there's nothing we can do
-        * unless we were called during a giveback, in which case
-        * qh_completions() has to deal with it.
-        */
-       if (qh->qh_state != QH_STATE_LINKED) {
-               if (qh->qh_state == QH_STATE_COMPLETING)
-                       qh->needs_rescan = 1;
-               return;
-       }
-
-       single_unlink_async(fusbh200, qh);
-       start_iaa_cycle(fusbh200, false);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void scan_async (struct fusbh200_hcd *fusbh200)
-{
-       struct fusbh200_qh              *qh;
-       bool                    check_unlinks_later = false;
-
-       fusbh200->qh_scan_next = fusbh200->async->qh_next.qh;
-       while (fusbh200->qh_scan_next) {
-               qh = fusbh200->qh_scan_next;
-               fusbh200->qh_scan_next = qh->qh_next.qh;
- rescan:
-               /* clean any finished work for this qh */
-               if (!list_empty(&qh->qtd_list)) {
-                       int temp;
-
-                       /*
-                        * Unlinks could happen here; completion reporting
-                        * drops the lock.  That's why fusbh200->qh_scan_next
-                        * always holds the next qh to scan; if the next qh
-                        * gets unlinked then fusbh200->qh_scan_next is adjusted
-                        * in single_unlink_async().
-                        */
-                       temp = qh_completions(fusbh200, qh);
-                       if (qh->needs_rescan) {
-                               start_unlink_async(fusbh200, qh);
-                       } else if (list_empty(&qh->qtd_list)
-                                       && qh->qh_state == QH_STATE_LINKED) {
-                               qh->unlink_cycle = fusbh200->async_unlink_cycle;
-                               check_unlinks_later = true;
-                       } else if (temp != 0)
-                               goto rescan;
-               }
-       }
-
-       /*
-        * Unlink empty entries, reducing DMA usage as well
-        * as HCD schedule-scanning costs.  Delay for any qh
-        * we just scanned, there's a not-unusual case that it
-        * doesn't stay idle for long.
-        */
-       if (check_unlinks_later && fusbh200->rh_state == FUSBH200_RH_RUNNING &&
-                       !(fusbh200->enabled_hrtimer_events &
-                               BIT(FUSBH200_HRTIMER_ASYNC_UNLINKS))) {
-               fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_ASYNC_UNLINKS, true);
-               ++fusbh200->async_unlink_cycle;
-       }
-}
-/*-------------------------------------------------------------------------*/
-/*
- * EHCI scheduled transaction support:  interrupt, iso, split iso
- * These are called "periodic" transactions in the EHCI spec.
- *
- * Note that for interrupt transfers, the QH/QTD manipulation is shared
- * with the "asynchronous" transaction support (control/bulk transfers).
- * The only real difference is in how interrupt transfers are scheduled.
- *
- * For ISO, we make an "iso_stream" head to serve the same role as a QH.
- * It keeps track of every ITD (or SITD) that's linked, and holds enough
- * pre-calculated schedule data to make appending to the queue be quick.
- */
-
-static int fusbh200_get_frame (struct usb_hcd *hcd);
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * periodic_next_shadow - return "next" pointer on shadow list
- * @periodic: host pointer to qh/itd
- * @tag: hardware tag for type of this record
- */
-static union fusbh200_shadow *
-periodic_next_shadow(struct fusbh200_hcd *fusbh200, union fusbh200_shadow *periodic,
-               __hc32 tag)
-{
-       switch (hc32_to_cpu(fusbh200, tag)) {
-       case Q_TYPE_QH:
-               return &periodic->qh->qh_next;
-       case Q_TYPE_FSTN:
-               return &periodic->fstn->fstn_next;
-       default:
-               return &periodic->itd->itd_next;
-       }
-}
-
-static __hc32 *
-shadow_next_periodic(struct fusbh200_hcd *fusbh200, union fusbh200_shadow *periodic,
-               __hc32 tag)
-{
-       switch (hc32_to_cpu(fusbh200, tag)) {
-       /* our fusbh200_shadow.qh is actually software part */
-       case Q_TYPE_QH:
-               return &periodic->qh->hw->hw_next;
-       /* others are hw parts */
-       default:
-               return periodic->hw_next;
-       }
-}
-
-/* caller must hold fusbh200->lock */
-static void periodic_unlink (struct fusbh200_hcd *fusbh200, unsigned frame, void *ptr)
-{
-       union fusbh200_shadow   *prev_p = &fusbh200->pshadow[frame];
-       __hc32                  *hw_p = &fusbh200->periodic[frame];
-       union fusbh200_shadow   here = *prev_p;
-
-       /* find predecessor of "ptr"; hw and shadow lists are in sync */
-       while (here.ptr && here.ptr != ptr) {
-               prev_p = periodic_next_shadow(fusbh200, prev_p,
-                               Q_NEXT_TYPE(fusbh200, *hw_p));
-               hw_p = shadow_next_periodic(fusbh200, &here,
-                               Q_NEXT_TYPE(fusbh200, *hw_p));
-               here = *prev_p;
-       }
-       /* an interrupt entry (at list end) could have been shared */
-       if (!here.ptr)
-               return;
-
-       /* update shadow and hardware lists ... the old "next" pointers
-        * from ptr may still be in use, the caller updates them.
-        */
-       *prev_p = *periodic_next_shadow(fusbh200, &here,
-                       Q_NEXT_TYPE(fusbh200, *hw_p));
-
-       *hw_p = *shadow_next_periodic(fusbh200, &here,
-                               Q_NEXT_TYPE(fusbh200, *hw_p));
-}
-
-/* how many of the uframe's 125 usecs are allocated? */
-static unsigned short
-periodic_usecs (struct fusbh200_hcd *fusbh200, unsigned frame, unsigned uframe)
-{
-       __hc32                  *hw_p = &fusbh200->periodic [frame];
-       union fusbh200_shadow   *q = &fusbh200->pshadow [frame];
-       unsigned                usecs = 0;
-       struct fusbh200_qh_hw   *hw;
-
-       while (q->ptr) {
-               switch (hc32_to_cpu(fusbh200, Q_NEXT_TYPE(fusbh200, *hw_p))) {
-               case Q_TYPE_QH:
-                       hw = q->qh->hw;
-                       /* is it in the S-mask? */
-                       if (hw->hw_info2 & cpu_to_hc32(fusbh200, 1 << uframe))
-                               usecs += q->qh->usecs;
-                       /* ... or C-mask? */
-                       if (hw->hw_info2 & cpu_to_hc32(fusbh200,
-                                       1 << (8 + uframe)))
-                               usecs += q->qh->c_usecs;
-                       hw_p = &hw->hw_next;
-                       q = &q->qh->qh_next;
-                       break;
-               // case Q_TYPE_FSTN:
-               default:
-                       /* for "save place" FSTNs, count the relevant INTR
-                        * bandwidth from the previous frame
-                        */
-                       if (q->fstn->hw_prev != FUSBH200_LIST_END(fusbh200)) {
-                               fusbh200_dbg (fusbh200, "ignoring FSTN cost ...\n");
-                       }
-                       hw_p = &q->fstn->hw_next;
-                       q = &q->fstn->fstn_next;
-                       break;
-               case Q_TYPE_ITD:
-                       if (q->itd->hw_transaction[uframe])
-                               usecs += q->itd->stream->usecs;
-                       hw_p = &q->itd->hw_next;
-                       q = &q->itd->itd_next;
-                       break;
-               }
-       }
-       if (usecs > fusbh200->uframe_periodic_max)
-               fusbh200_err (fusbh200, "uframe %d sched overrun: %d usecs\n",
-                       frame * 8 + uframe, usecs);
-       return usecs;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int same_tt (struct usb_device *dev1, struct usb_device *dev2)
-{
-       if (!dev1->tt || !dev2->tt)
-               return 0;
-       if (dev1->tt != dev2->tt)
-               return 0;
-       if (dev1->tt->multi)
-               return dev1->ttport == dev2->ttport;
-       else
-               return 1;
-}
-
-/* return true iff the device's transaction translator is available
- * for a periodic transfer starting at the specified frame, using
- * all the uframes in the mask.
- */
-static int tt_no_collision (
-       struct fusbh200_hcd             *fusbh200,
-       unsigned                period,
-       struct usb_device       *dev,
-       unsigned                frame,
-       u32                     uf_mask
-)
-{
-       if (period == 0)        /* error */
-               return 0;
-
-       /* note bandwidth wastage:  split never follows csplit
-        * (different dev or endpoint) until the next uframe.
-        * calling convention doesn't make that distinction.
-        */
-       for (; frame < fusbh200->periodic_size; frame += period) {
-               union fusbh200_shadow   here;
-               __hc32                  type;
-               struct fusbh200_qh_hw   *hw;
-
-               here = fusbh200->pshadow [frame];
-               type = Q_NEXT_TYPE(fusbh200, fusbh200->periodic [frame]);
-               while (here.ptr) {
-                       switch (hc32_to_cpu(fusbh200, type)) {
-                       case Q_TYPE_ITD:
-                               type = Q_NEXT_TYPE(fusbh200, here.itd->hw_next);
-                               here = here.itd->itd_next;
-                               continue;
-                       case Q_TYPE_QH:
-                               hw = here.qh->hw;
-                               if (same_tt (dev, here.qh->dev)) {
-                                       u32             mask;
-
-                                       mask = hc32_to_cpu(fusbh200,
-                                                       hw->hw_info2);
-                                       /* "knows" no gap is needed */
-                                       mask |= mask >> 8;
-                                       if (mask & uf_mask)
-                                               break;
-                               }
-                               type = Q_NEXT_TYPE(fusbh200, hw->hw_next);
-                               here = here.qh->qh_next;
-                               continue;
-                       // case Q_TYPE_FSTN:
-                       default:
-                               fusbh200_dbg (fusbh200,
-                                       "periodic frame %d bogus type %d\n",
-                                       frame, type);
-                       }
-
-                       /* collision or error */
-                       return 0;
-               }
-       }
-
-       /* no collision */
-       return 1;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void enable_periodic(struct fusbh200_hcd *fusbh200)
-{
-       if (fusbh200->periodic_count++)
-               return;
-
-       /* Stop waiting to turn off the periodic schedule */
-       fusbh200->enabled_hrtimer_events &= ~BIT(FUSBH200_HRTIMER_DISABLE_PERIODIC);
-
-       /* Don't start the schedule until PSS is 0 */
-       fusbh200_poll_PSS(fusbh200);
-       turn_on_io_watchdog(fusbh200);
-}
-
-static void disable_periodic(struct fusbh200_hcd *fusbh200)
-{
-       if (--fusbh200->periodic_count)
-               return;
-
-       /* Don't turn off the schedule until PSS is 1 */
-       fusbh200_poll_PSS(fusbh200);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* periodic schedule slots have iso tds (normal or split) first, then a
- * sparse tree for active interrupt transfers.
- *
- * this just links in a qh; caller guarantees uframe masks are set right.
- * no FSTN support (yet; fusbh200 0.96+)
- */
-static void qh_link_periodic(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
-       unsigned        i;
-       unsigned        period = qh->period;
-
-       dev_dbg (&qh->dev->dev,
-               "link qh%d-%04x/%p start %d [%d/%d us]\n",
-               period, hc32_to_cpup(fusbh200, &qh->hw->hw_info2)
-                       & (QH_CMASK | QH_SMASK),
-               qh, qh->start, qh->usecs, qh->c_usecs);
-
-       /* high bandwidth, or otherwise every microframe */
-       if (period == 0)
-               period = 1;
-
-       for (i = qh->start; i < fusbh200->periodic_size; i += period) {
-               union fusbh200_shadow   *prev = &fusbh200->pshadow[i];
-               __hc32                  *hw_p = &fusbh200->periodic[i];
-               union fusbh200_shadow   here = *prev;
-               __hc32                  type = 0;
-
-               /* skip the iso nodes at list head */
-               while (here.ptr) {
-                       type = Q_NEXT_TYPE(fusbh200, *hw_p);
-                       if (type == cpu_to_hc32(fusbh200, Q_TYPE_QH))
-                               break;
-                       prev = periodic_next_shadow(fusbh200, prev, type);
-                       hw_p = shadow_next_periodic(fusbh200, &here, type);
-                       here = *prev;
-               }
-
-               /* sorting each branch by period (slow-->fast)
-                * enables sharing interior tree nodes
-                */
-               while (here.ptr && qh != here.qh) {
-                       if (qh->period > here.qh->period)
-                               break;
-                       prev = &here.qh->qh_next;
-                       hw_p = &here.qh->hw->hw_next;
-                       here = *prev;
-               }
-               /* link in this qh, unless some earlier pass did that */
-               if (qh != here.qh) {
-                       qh->qh_next = here;
-                       if (here.qh)
-                               qh->hw->hw_next = *hw_p;
-                       wmb ();
-                       prev->qh = qh;
-                       *hw_p = QH_NEXT (fusbh200, qh->qh_dma);
-               }
-       }
-       qh->qh_state = QH_STATE_LINKED;
-       qh->xacterrs = 0;
-
-       /* update per-qh bandwidth for usbfs */
-       fusbh200_to_hcd(fusbh200)->self.bandwidth_allocated += qh->period
-               ? ((qh->usecs + qh->c_usecs) / qh->period)
-               : (qh->usecs * 8);
-
-       list_add(&qh->intr_node, &fusbh200->intr_qh_list);
-
-       /* maybe enable periodic schedule processing */
-       ++fusbh200->intr_count;
-       enable_periodic(fusbh200);
-}
-
-static void qh_unlink_periodic(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
-       unsigned        i;
-       unsigned        period;
-
-       /*
-        * If qh is for a low/full-speed device, simply unlinking it
-        * could interfere with an ongoing split transaction.  To unlink
-        * it safely would require setting the QH_INACTIVATE bit and
-        * waiting at least one frame, as described in EHCI 4.12.2.5.
-        *
-        * We won't bother with any of this.  Instead, we assume that the
-        * only reason for unlinking an interrupt QH while the current URB
-        * is still active is to dequeue all the URBs (flush the whole
-        * endpoint queue).
-        *
-        * If rebalancing the periodic schedule is ever implemented, this
-        * approach will no longer be valid.
-        */
-
-       /* high bandwidth, or otherwise part of every microframe */
-       if ((period = qh->period) == 0)
-               period = 1;
-
-       for (i = qh->start; i < fusbh200->periodic_size; i += period)
-               periodic_unlink (fusbh200, i, qh);
-
-       /* update per-qh bandwidth for usbfs */
-       fusbh200_to_hcd(fusbh200)->self.bandwidth_allocated -= qh->period
-               ? ((qh->usecs + qh->c_usecs) / qh->period)
-               : (qh->usecs * 8);
-
-       dev_dbg (&qh->dev->dev,
-               "unlink qh%d-%04x/%p start %d [%d/%d us]\n",
-               qh->period,
-               hc32_to_cpup(fusbh200, &qh->hw->hw_info2) & (QH_CMASK | QH_SMASK),
-               qh, qh->start, qh->usecs, qh->c_usecs);
-
-       /* qh->qh_next still "live" to HC */
-       qh->qh_state = QH_STATE_UNLINK;
-       qh->qh_next.ptr = NULL;
-
-       if (fusbh200->qh_scan_next == qh)
-               fusbh200->qh_scan_next = list_entry(qh->intr_node.next,
-                               struct fusbh200_qh, intr_node);
-       list_del(&qh->intr_node);
-}
-
-static void start_unlink_intr(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
-       /* If the QH isn't linked then there's nothing we can do
-        * unless we were called during a giveback, in which case
-        * qh_completions() has to deal with it.
-        */
-       if (qh->qh_state != QH_STATE_LINKED) {
-               if (qh->qh_state == QH_STATE_COMPLETING)
-                       qh->needs_rescan = 1;
-               return;
-       }
-
-       qh_unlink_periodic (fusbh200, qh);
-
-       /* Make sure the unlinks are visible before starting the timer */
-       wmb();
-
-       /*
-        * The EHCI spec doesn't say how long it takes the controller to
-        * stop accessing an unlinked interrupt QH.  The timer delay is
-        * 9 uframes; presumably that will be long enough.
-        */
-       qh->unlink_cycle = fusbh200->intr_unlink_cycle;
-
-       /* New entries go at the end of the intr_unlink list */
-       if (fusbh200->intr_unlink)
-               fusbh200->intr_unlink_last->unlink_next = qh;
-       else
-               fusbh200->intr_unlink = qh;
-       fusbh200->intr_unlink_last = qh;
-
-       if (fusbh200->intr_unlinking)
-               ;       /* Avoid recursive calls */
-       else if (fusbh200->rh_state < FUSBH200_RH_RUNNING)
-               fusbh200_handle_intr_unlinks(fusbh200);
-       else if (fusbh200->intr_unlink == qh) {
-               fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_UNLINK_INTR, true);
-               ++fusbh200->intr_unlink_cycle;
-       }
-}
-
-static void end_unlink_intr(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
-       struct fusbh200_qh_hw   *hw = qh->hw;
-       int                     rc;
-
-       qh->qh_state = QH_STATE_IDLE;
-       hw->hw_next = FUSBH200_LIST_END(fusbh200);
-
-       qh_completions(fusbh200, qh);
-
-       /* reschedule QH iff another request is queued */
-       if (!list_empty(&qh->qtd_list) && fusbh200->rh_state == FUSBH200_RH_RUNNING) {
-               rc = qh_schedule(fusbh200, qh);
-
-               /* An error here likely indicates handshake failure
-                * or no space left in the schedule.  Neither fault
-                * should happen often ...
-                *
-                * FIXME kill the now-dysfunctional queued urbs
-                */
-               if (rc != 0)
-                       fusbh200_err(fusbh200, "can't reschedule qh %p, err %d\n",
-                                       qh, rc);
-       }
-
-       /* maybe turn off periodic schedule */
-       --fusbh200->intr_count;
-       disable_periodic(fusbh200);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int check_period (
-       struct fusbh200_hcd *fusbh200,
-       unsigned        frame,
-       unsigned        uframe,
-       unsigned        period,
-       unsigned        usecs
-) {
-       int             claimed;
-
-       /* complete split running into next frame?
-        * given FSTN support, we could sometimes check...
-        */
-       if (uframe >= 8)
-               return 0;
-
-       /* convert "usecs we need" to "max already claimed" */
-       usecs = fusbh200->uframe_periodic_max - usecs;
-
-       /* we "know" 2 and 4 uframe intervals were rejected; so
-        * for period 0, check _every_ microframe in the schedule.
-        */
-       if (unlikely (period == 0)) {
-               do {
-                       for (uframe = 0; uframe < 7; uframe++) {
-                               claimed = periodic_usecs (fusbh200, frame, uframe);
-                               if (claimed > usecs)
-                                       return 0;
-                       }
-               } while ((frame += 1) < fusbh200->periodic_size);
-
-       /* just check the specified uframe, at that period */
-       } else {
-               do {
-                       claimed = periodic_usecs (fusbh200, frame, uframe);
-                       if (claimed > usecs)
-                               return 0;
-               } while ((frame += period) < fusbh200->periodic_size);
-       }
-
-       // success!
-       return 1;
-}
-
-static int check_intr_schedule (
-       struct fusbh200_hcd             *fusbh200,
-       unsigned                frame,
-       unsigned                uframe,
-       const struct fusbh200_qh        *qh,
-       __hc32                  *c_maskp
-)
-{
-       int             retval = -ENOSPC;
-       u8              mask = 0;
-
-       if (qh->c_usecs && uframe >= 6)         /* FSTN territory? */
-               goto done;
-
-       if (!check_period (fusbh200, frame, uframe, qh->period, qh->usecs))
-               goto done;
-       if (!qh->c_usecs) {
-               retval = 0;
-               *c_maskp = 0;
-               goto done;
-       }
-
-       /* Make sure this tt's buffer is also available for CSPLITs.
-        * We pessimize a bit; probably the typical full speed case
-        * doesn't need the second CSPLIT.
-        *
-        * NOTE:  both SPLIT and CSPLIT could be checked in just
-        * one smart pass...
-        */
-       mask = 0x03 << (uframe + qh->gap_uf);
-       *c_maskp = cpu_to_hc32(fusbh200, mask << 8);
-
-       mask |= 1 << uframe;
-       if (tt_no_collision (fusbh200, qh->period, qh->dev, frame, mask)) {
-               if (!check_period (fusbh200, frame, uframe + qh->gap_uf + 1,
-                                       qh->period, qh->c_usecs))
-                       goto done;
-               if (!check_period (fusbh200, frame, uframe + qh->gap_uf,
-                                       qh->period, qh->c_usecs))
-                       goto done;
-               retval = 0;
-       }
-done:
-       return retval;
-}
-
-/* "first fit" scheduling policy used the first time through,
- * or when the previous schedule slot can't be re-used.
- */
-static int qh_schedule(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh)
-{
-       int             status;
-       unsigned        uframe;
-       __hc32          c_mask;
-       unsigned        frame;          /* 0..(qh->period - 1), or NO_FRAME */
-       struct fusbh200_qh_hw   *hw = qh->hw;
-
-       qh_refresh(fusbh200, qh);
-       hw->hw_next = FUSBH200_LIST_END(fusbh200);
-       frame = qh->start;
-
-       /* reuse the previous schedule slots, if we can */
-       if (frame < qh->period) {
-               uframe = ffs(hc32_to_cpup(fusbh200, &hw->hw_info2) & QH_SMASK);
-               status = check_intr_schedule (fusbh200, frame, --uframe,
-                               qh, &c_mask);
-       } else {
-               uframe = 0;
-               c_mask = 0;
-               status = -ENOSPC;
-       }
-
-       /* else scan the schedule to find a group of slots such that all
-        * uframes have enough periodic bandwidth available.
-        */
-       if (status) {
-               /* "normal" case, uframing flexible except with splits */
-               if (qh->period) {
-                       int             i;
-
-                       for (i = qh->period; status && i > 0; --i) {
-                               frame = ++fusbh200->random_frame % qh->period;
-                               for (uframe = 0; uframe < 8; uframe++) {
-                                       status = check_intr_schedule (fusbh200,
-                                                       frame, uframe, qh,
-                                                       &c_mask);
-                                       if (status == 0)
-                                               break;
-                               }
-                       }
-
-               /* qh->period == 0 means every uframe */
-               } else {
-                       frame = 0;
-                       status = check_intr_schedule (fusbh200, 0, 0, qh, &c_mask);
-               }
-               if (status)
-                       goto done;
-               qh->start = frame;
-
-               /* reset S-frame and (maybe) C-frame masks */
-               hw->hw_info2 &= cpu_to_hc32(fusbh200, ~(QH_CMASK | QH_SMASK));
-               hw->hw_info2 |= qh->period
-                       ? cpu_to_hc32(fusbh200, 1 << uframe)
-                       : cpu_to_hc32(fusbh200, QH_SMASK);
-               hw->hw_info2 |= c_mask;
-       } else
-               fusbh200_dbg (fusbh200, "reused qh %p schedule\n", qh);
-
-       /* stuff into the periodic schedule */
-       qh_link_periodic(fusbh200, qh);
-done:
-       return status;
-}
-
-static int intr_submit (
-       struct fusbh200_hcd             *fusbh200,
-       struct urb              *urb,
-       struct list_head        *qtd_list,
-       gfp_t                   mem_flags
-) {
-       unsigned                epnum;
-       unsigned long           flags;
-       struct fusbh200_qh              *qh;
-       int                     status;
-       struct list_head        empty;
-
-       /* get endpoint and transfer/schedule data */
-       epnum = urb->ep->desc.bEndpointAddress;
-
-       spin_lock_irqsave (&fusbh200->lock, flags);
-
-       if (unlikely(!HCD_HW_ACCESSIBLE(fusbh200_to_hcd(fusbh200)))) {
-               status = -ESHUTDOWN;
-               goto done_not_linked;
-       }
-       status = usb_hcd_link_urb_to_ep(fusbh200_to_hcd(fusbh200), urb);
-       if (unlikely(status))
-               goto done_not_linked;
-
-       /* get qh and force any scheduling errors */
-       INIT_LIST_HEAD (&empty);
-       qh = qh_append_tds(fusbh200, urb, &empty, epnum, &urb->ep->hcpriv);
-       if (qh == NULL) {
-               status = -ENOMEM;
-               goto done;
-       }
-       if (qh->qh_state == QH_STATE_IDLE) {
-               if ((status = qh_schedule (fusbh200, qh)) != 0)
-                       goto done;
-       }
-
-       /* then queue the urb's tds to the qh */
-       qh = qh_append_tds(fusbh200, urb, qtd_list, epnum, &urb->ep->hcpriv);
-       BUG_ON (qh == NULL);
-
-       /* ... update usbfs periodic stats */
-       fusbh200_to_hcd(fusbh200)->self.bandwidth_int_reqs++;
-
-done:
-       if (unlikely(status))
-               usb_hcd_unlink_urb_from_ep(fusbh200_to_hcd(fusbh200), urb);
-done_not_linked:
-       spin_unlock_irqrestore (&fusbh200->lock, flags);
-       if (status)
-               qtd_list_free (fusbh200, urb, qtd_list);
-
-       return status;
-}
-
-static void scan_intr(struct fusbh200_hcd *fusbh200)
-{
-       struct fusbh200_qh              *qh;
-
-       list_for_each_entry_safe(qh, fusbh200->qh_scan_next, &fusbh200->intr_qh_list,
-                       intr_node) {
- rescan:
-               /* clean any finished work for this qh */
-               if (!list_empty(&qh->qtd_list)) {
-                       int temp;
-
-                       /*
-                        * Unlinks could happen here; completion reporting
-                        * drops the lock.  That's why fusbh200->qh_scan_next
-                        * always holds the next qh to scan; if the next qh
-                        * gets unlinked then fusbh200->qh_scan_next is adjusted
-                        * in qh_unlink_periodic().
-                        */
-                       temp = qh_completions(fusbh200, qh);
-                       if (unlikely(qh->needs_rescan ||
-                                       (list_empty(&qh->qtd_list) &&
-                                               qh->qh_state == QH_STATE_LINKED)))
-                               start_unlink_intr(fusbh200, qh);
-                       else if (temp != 0)
-                               goto rescan;
-               }
-       }
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* fusbh200_iso_stream ops work with both ITD and SITD */
-
-static struct fusbh200_iso_stream *
-iso_stream_alloc (gfp_t mem_flags)
-{
-       struct fusbh200_iso_stream *stream;
-
-       stream = kzalloc(sizeof *stream, mem_flags);
-       if (likely (stream != NULL)) {
-               INIT_LIST_HEAD(&stream->td_list);
-               INIT_LIST_HEAD(&stream->free_list);
-               stream->next_uframe = -1;
-       }
-       return stream;
-}
-
-static void
-iso_stream_init (
-       struct fusbh200_hcd             *fusbh200,
-       struct fusbh200_iso_stream      *stream,
-       struct usb_device       *dev,
-       int                     pipe,
-       unsigned                interval
-)
-{
-       u32                     buf1;
-       unsigned                epnum, maxp;
-       int                     is_input;
-       long                    bandwidth;
-       unsigned                multi;
-
-       /*
-        * this might be a "high bandwidth" highspeed endpoint,
-        * as encoded in the ep descriptor's wMaxPacket field
-        */
-       epnum = usb_pipeendpoint (pipe);
-       is_input = usb_pipein (pipe) ? USB_DIR_IN : 0;
-       maxp = usb_maxpacket(dev, pipe, !is_input);
-       if (is_input) {
-               buf1 = (1 << 11);
-       } else {
-               buf1 = 0;
-       }
-
-       maxp = max_packet(maxp);
-       multi = hb_mult(maxp);
-       buf1 |= maxp;
-       maxp *= multi;
-
-       stream->buf0 = cpu_to_hc32(fusbh200, (epnum << 8) | dev->devnum);
-       stream->buf1 = cpu_to_hc32(fusbh200, buf1);
-       stream->buf2 = cpu_to_hc32(fusbh200, multi);
-
-       /* usbfs wants to report the average usecs per frame tied up
-        * when transfers on this endpoint are scheduled ...
-        */
-       if (dev->speed == USB_SPEED_FULL) {
-               interval <<= 3;
-               stream->usecs = NS_TO_US(usb_calc_bus_time(dev->speed,
-                               is_input, 1, maxp));
-               stream->usecs /= 8;
-       } else {
-               stream->highspeed = 1;
-               stream->usecs = HS_USECS_ISO (maxp);
-       }
-       bandwidth = stream->usecs * 8;
-       bandwidth /= interval;
-
-       stream->bandwidth = bandwidth;
-       stream->udev = dev;
-       stream->bEndpointAddress = is_input | epnum;
-       stream->interval = interval;
-       stream->maxp = maxp;
-}
-
-static struct fusbh200_iso_stream *
-iso_stream_find (struct fusbh200_hcd *fusbh200, struct urb *urb)
-{
-       unsigned                epnum;
-       struct fusbh200_iso_stream      *stream;
-       struct usb_host_endpoint *ep;
-       unsigned long           flags;
-
-       epnum = usb_pipeendpoint (urb->pipe);
-       if (usb_pipein(urb->pipe))
-               ep = urb->dev->ep_in[epnum];
-       else
-               ep = urb->dev->ep_out[epnum];
-
-       spin_lock_irqsave (&fusbh200->lock, flags);
-       stream = ep->hcpriv;
-
-       if (unlikely (stream == NULL)) {
-               stream = iso_stream_alloc(GFP_ATOMIC);
-               if (likely (stream != NULL)) {
-                       ep->hcpriv = stream;
-                       stream->ep = ep;
-                       iso_stream_init(fusbh200, stream, urb->dev, urb->pipe,
-                                       urb->interval);
-               }
-
-       /* if dev->ep [epnum] is a QH, hw is set */
-       } else if (unlikely (stream->hw != NULL)) {
-               fusbh200_dbg (fusbh200, "dev %s ep%d%s, not iso??\n",
-                       urb->dev->devpath, epnum,
-                       usb_pipein(urb->pipe) ? "in" : "out");
-               stream = NULL;
-       }
-
-       spin_unlock_irqrestore (&fusbh200->lock, flags);
-       return stream;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* fusbh200_iso_sched ops can be ITD-only or SITD-only */
-
-static struct fusbh200_iso_sched *
-iso_sched_alloc (unsigned packets, gfp_t mem_flags)
-{
-       struct fusbh200_iso_sched       *iso_sched;
-       int                     size = sizeof *iso_sched;
-
-       size += packets * sizeof (struct fusbh200_iso_packet);
-       iso_sched = kzalloc(size, mem_flags);
-       if (likely (iso_sched != NULL)) {
-               INIT_LIST_HEAD (&iso_sched->td_list);
-       }
-       return iso_sched;
-}
-
-static inline void
-itd_sched_init(
-       struct fusbh200_hcd             *fusbh200,
-       struct fusbh200_iso_sched       *iso_sched,
-       struct fusbh200_iso_stream      *stream,
-       struct urb              *urb
-)
-{
-       unsigned        i;
-       dma_addr_t      dma = urb->transfer_dma;
-
-       /* how many uframes are needed for these transfers */
-       iso_sched->span = urb->number_of_packets * stream->interval;
-
-       /* figure out per-uframe itd fields that we'll need later
-        * when we fit new itds into the schedule.
-        */
-       for (i = 0; i < urb->number_of_packets; i++) {
-               struct fusbh200_iso_packet      *uframe = &iso_sched->packet [i];
-               unsigned                length;
-               dma_addr_t              buf;
-               u32                     trans;
-
-               length = urb->iso_frame_desc [i].length;
-               buf = dma + urb->iso_frame_desc [i].offset;
-
-               trans = FUSBH200_ISOC_ACTIVE;
-               trans |= buf & 0x0fff;
-               if (unlikely (((i + 1) == urb->number_of_packets))
-                               && !(urb->transfer_flags & URB_NO_INTERRUPT))
-                       trans |= FUSBH200_ITD_IOC;
-               trans |= length << 16;
-               uframe->transaction = cpu_to_hc32(fusbh200, trans);
-
-               /* might need to cross a buffer page within a uframe */
-               uframe->bufp = (buf & ~(u64)0x0fff);
-               buf += length;
-               if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff))))
-                       uframe->cross = 1;
-       }
-}
-
-static void
-iso_sched_free (
-       struct fusbh200_iso_stream      *stream,
-       struct fusbh200_iso_sched       *iso_sched
-)
-{
-       if (!iso_sched)
-               return;
-       // caller must hold fusbh200->lock!
-       list_splice (&iso_sched->td_list, &stream->free_list);
-       kfree (iso_sched);
-}
-
-static int
-itd_urb_transaction (
-       struct fusbh200_iso_stream      *stream,
-       struct fusbh200_hcd             *fusbh200,
-       struct urb              *urb,
-       gfp_t                   mem_flags
-)
-{
-       struct fusbh200_itd             *itd;
-       dma_addr_t              itd_dma;
-       int                     i;
-       unsigned                num_itds;
-       struct fusbh200_iso_sched       *sched;
-       unsigned long           flags;
-
-       sched = iso_sched_alloc (urb->number_of_packets, mem_flags);
-       if (unlikely (sched == NULL))
-               return -ENOMEM;
-
-       itd_sched_init(fusbh200, sched, stream, urb);
-
-       if (urb->interval < 8)
-               num_itds = 1 + (sched->span + 7) / 8;
-       else
-               num_itds = urb->number_of_packets;
-
-       /* allocate/init ITDs */
-       spin_lock_irqsave (&fusbh200->lock, flags);
-       for (i = 0; i < num_itds; i++) {
-
-               /*
-                * Use iTDs from the free list, but not iTDs that may
-                * still be in use by the hardware.
-                */
-               if (likely(!list_empty(&stream->free_list))) {
-                       itd = list_first_entry(&stream->free_list,
-                                       struct fusbh200_itd, itd_list);
-                       if (itd->frame == fusbh200->now_frame)
-                               goto alloc_itd;
-                       list_del (&itd->itd_list);
-                       itd_dma = itd->itd_dma;
-               } else {
- alloc_itd:
-                       spin_unlock_irqrestore (&fusbh200->lock, flags);
-                       itd = dma_pool_alloc (fusbh200->itd_pool, mem_flags,
-                                       &itd_dma);
-                       spin_lock_irqsave (&fusbh200->lock, flags);
-                       if (!itd) {
-                               iso_sched_free(stream, sched);
-                               spin_unlock_irqrestore(&fusbh200->lock, flags);
-                               return -ENOMEM;
-                       }
-               }
-
-               memset (itd, 0, sizeof *itd);
-               itd->itd_dma = itd_dma;
-               list_add (&itd->itd_list, &sched->td_list);
-       }
-       spin_unlock_irqrestore (&fusbh200->lock, flags);
-
-       /* temporarily store schedule info in hcpriv */
-       urb->hcpriv = sched;
-       urb->error_count = 0;
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static inline int
-itd_slot_ok (
-       struct fusbh200_hcd             *fusbh200,
-       u32                     mod,
-       u32                     uframe,
-       u8                      usecs,
-       u32                     period
-)
-{
-       uframe %= period;
-       do {
-               /* can't commit more than uframe_periodic_max usec */
-               if (periodic_usecs (fusbh200, uframe >> 3, uframe & 0x7)
-                               > (fusbh200->uframe_periodic_max - usecs))
-                       return 0;
-
-               /* we know urb->interval is 2^N uframes */
-               uframe += period;
-       } while (uframe < mod);
-       return 1;
-}
-
-/*
- * This scheduler plans almost as far into the future as it has actual
- * periodic schedule slots.  (Affected by TUNE_FLS, which defaults to
- * "as small as possible" to be cache-friendlier.)  That limits the size
- * transfers you can stream reliably; avoid more than 64 msec per urb.
- * Also avoid queue depths of less than fusbh200's worst irq latency (affected
- * by the per-urb URB_NO_INTERRUPT hint, the log2_irq_thresh module parameter,
- * and other factors); or more than about 230 msec total (for portability,
- * given FUSBH200_TUNE_FLS and the slop).  Or, write a smarter scheduler!
- */
-
-#define SCHEDULE_SLOP  80      /* microframes */
-
-static int
-iso_stream_schedule (
-       struct fusbh200_hcd             *fusbh200,
-       struct urb              *urb,
-       struct fusbh200_iso_stream      *stream
-)
-{
-       u32                     now, next, start, period, span;
-       int                     status;
-       unsigned                mod = fusbh200->periodic_size << 3;
-       struct fusbh200_iso_sched       *sched = urb->hcpriv;
-
-       period = urb->interval;
-       span = sched->span;
-
-       if (span > mod - SCHEDULE_SLOP) {
-               fusbh200_dbg (fusbh200, "iso request %p too long\n", urb);
-               status = -EFBIG;
-               goto fail;
-       }
-
-       now = fusbh200_read_frame_index(fusbh200) & (mod - 1);
-
-       /* Typical case: reuse current schedule, stream is still active.
-        * Hopefully there are no gaps from the host falling behind
-        * (irq delays etc), but if there are we'll take the next
-        * slot in the schedule, implicitly assuming URB_ISO_ASAP.
-        */
-       if (likely (!list_empty (&stream->td_list))) {
-               u32     excess;
-
-               /* For high speed devices, allow scheduling within the
-                * isochronous scheduling threshold.  For full speed devices
-                * and Intel PCI-based controllers, don't (work around for
-                * Intel ICH9 bug).
-                */
-               if (!stream->highspeed && fusbh200->fs_i_thresh)
-                       next = now + fusbh200->i_thresh;
-               else
-                       next = now;
-
-               /* Fell behind (by up to twice the slop amount)?
-                * We decide based on the time of the last currently-scheduled
-                * slot, not the time of the next available slot.
-                */
-               excess = (stream->next_uframe - period - next) & (mod - 1);
-               if (excess >= mod - 2 * SCHEDULE_SLOP)
-                       start = next + excess - mod + period *
-                                       DIV_ROUND_UP(mod - excess, period);
-               else
-                       start = next + excess + period;
-               if (start - now >= mod) {
-                       fusbh200_dbg(fusbh200, "request %p would overflow (%d+%d >= %d)\n",
-                                       urb, start - now - period, period,
-                                       mod);
-                       status = -EFBIG;
-                       goto fail;
-               }
-       }
-
-       /* need to schedule; when's the next (u)frame we could start?
-        * this is bigger than fusbh200->i_thresh allows; scheduling itself
-        * isn't free, the slop should handle reasonably slow cpus.  it
-        * can also help high bandwidth if the dma and irq loads don't
-        * jump until after the queue is primed.
-        */
-       else {
-               int done = 0;
-               start = SCHEDULE_SLOP + (now & ~0x07);
-
-               /* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */
-
-               /* find a uframe slot with enough bandwidth.
-                * Early uframes are more precious because full-speed
-                * iso IN transfers can't use late uframes,
-                * and therefore they should be allocated last.
-                */
-               next = start;
-               start += period;
-               do {
-                       start--;
-                       /* check schedule: enough space? */
-                       if (itd_slot_ok(fusbh200, mod, start,
-                                       stream->usecs, period))
-                               done = 1;
-               } while (start > next && !done);
-
-               /* no room in the schedule */
-               if (!done) {
-                       fusbh200_dbg(fusbh200, "iso resched full %p (now %d max %d)\n",
-                               urb, now, now + mod);
-                       status = -ENOSPC;
-                       goto fail;
-               }
-       }
-
-       /* Tried to schedule too far into the future? */
-       if (unlikely(start - now + span - period
-                               >= mod - 2 * SCHEDULE_SLOP)) {
-               fusbh200_dbg(fusbh200, "request %p would overflow (%d+%d >= %d)\n",
-                               urb, start - now, span - period,
-                               mod - 2 * SCHEDULE_SLOP);
-               status = -EFBIG;
-               goto fail;
-       }
-
-       stream->next_uframe = start & (mod - 1);
-
-       /* report high speed start in uframes; full speed, in frames */
-       urb->start_frame = stream->next_uframe;
-       if (!stream->highspeed)
-               urb->start_frame >>= 3;
-
-       /* Make sure scan_isoc() sees these */
-       if (fusbh200->isoc_count == 0)
-               fusbh200->next_frame = now >> 3;
-       return 0;
-
- fail:
-       iso_sched_free(stream, sched);
-       urb->hcpriv = NULL;
-       return status;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static inline void
-itd_init(struct fusbh200_hcd *fusbh200, struct fusbh200_iso_stream *stream,
-               struct fusbh200_itd *itd)
-{
-       int i;
-
-       /* it's been recently zeroed */
-       itd->hw_next = FUSBH200_LIST_END(fusbh200);
-       itd->hw_bufp [0] = stream->buf0;
-       itd->hw_bufp [1] = stream->buf1;
-       itd->hw_bufp [2] = stream->buf2;
-
-       for (i = 0; i < 8; i++)
-               itd->index[i] = -1;
-
-       /* All other fields are filled when scheduling */
-}
-
-static inline void
-itd_patch(
-       struct fusbh200_hcd             *fusbh200,
-       struct fusbh200_itd             *itd,
-       struct fusbh200_iso_sched       *iso_sched,
-       unsigned                index,
-       u16                     uframe
-)
-{
-       struct fusbh200_iso_packet      *uf = &iso_sched->packet [index];
-       unsigned                pg = itd->pg;
-
-       // BUG_ON (pg == 6 && uf->cross);
-
-       uframe &= 0x07;
-       itd->index [uframe] = index;
-
-       itd->hw_transaction[uframe] = uf->transaction;
-       itd->hw_transaction[uframe] |= cpu_to_hc32(fusbh200, pg << 12);
-       itd->hw_bufp[pg] |= cpu_to_hc32(fusbh200, uf->bufp & ~(u32)0);
-       itd->hw_bufp_hi[pg] |= cpu_to_hc32(fusbh200, (u32)(uf->bufp >> 32));
-
-       /* iso_frame_desc[].offset must be strictly increasing */
-       if (unlikely (uf->cross)) {
-               u64     bufp = uf->bufp + 4096;
-
-               itd->pg = ++pg;
-               itd->hw_bufp[pg] |= cpu_to_hc32(fusbh200, bufp & ~(u32)0);
-               itd->hw_bufp_hi[pg] |= cpu_to_hc32(fusbh200, (u32)(bufp >> 32));
-       }
-}
-
-static inline void
-itd_link (struct fusbh200_hcd *fusbh200, unsigned frame, struct fusbh200_itd *itd)
-{
-       union fusbh200_shadow   *prev = &fusbh200->pshadow[frame];
-       __hc32                  *hw_p = &fusbh200->periodic[frame];
-       union fusbh200_shadow   here = *prev;
-       __hc32                  type = 0;
-
-       /* skip any iso nodes which might belong to previous microframes */
-       while (here.ptr) {
-               type = Q_NEXT_TYPE(fusbh200, *hw_p);
-               if (type == cpu_to_hc32(fusbh200, Q_TYPE_QH))
-                       break;
-               prev = periodic_next_shadow(fusbh200, prev, type);
-               hw_p = shadow_next_periodic(fusbh200, &here, type);
-               here = *prev;
-       }
-
-       itd->itd_next = here;
-       itd->hw_next = *hw_p;
-       prev->itd = itd;
-       itd->frame = frame;
-       wmb ();
-       *hw_p = cpu_to_hc32(fusbh200, itd->itd_dma | Q_TYPE_ITD);
-}
-
-/* fit urb's itds into the selected schedule slot; activate as needed */
-static void itd_link_urb(
-       struct fusbh200_hcd             *fusbh200,
-       struct urb              *urb,
-       unsigned                mod,
-       struct fusbh200_iso_stream      *stream
-)
-{
-       int                     packet;
-       unsigned                next_uframe, uframe, frame;
-       struct fusbh200_iso_sched       *iso_sched = urb->hcpriv;
-       struct fusbh200_itd             *itd;
-
-       next_uframe = stream->next_uframe & (mod - 1);
-
-       if (unlikely (list_empty(&stream->td_list))) {
-               fusbh200_to_hcd(fusbh200)->self.bandwidth_allocated
-                               += stream->bandwidth;
-               fusbh200_dbg(fusbh200,
-                       "schedule devp %s ep%d%s-iso period %d start %d.%d\n",
-                       urb->dev->devpath, stream->bEndpointAddress & 0x0f,
-                       (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
-                       urb->interval,
-                       next_uframe >> 3, next_uframe & 0x7);
-       }
-
-       /* fill iTDs uframe by uframe */
-       for (packet = 0, itd = NULL; packet < urb->number_of_packets; ) {
-               if (itd == NULL) {
-                       /* ASSERT:  we have all necessary itds */
-                       // BUG_ON (list_empty (&iso_sched->td_list));
-
-                       /* ASSERT:  no itds for this endpoint in this uframe */
-
-                       itd = list_entry (iso_sched->td_list.next,
-                                       struct fusbh200_itd, itd_list);
-                       list_move_tail (&itd->itd_list, &stream->td_list);
-                       itd->stream = stream;
-                       itd->urb = urb;
-                       itd_init (fusbh200, stream, itd);
-               }
-
-               uframe = next_uframe & 0x07;
-               frame = next_uframe >> 3;
-
-               itd_patch(fusbh200, itd, iso_sched, packet, uframe);
-
-               next_uframe += stream->interval;
-               next_uframe &= mod - 1;
-               packet++;
-
-               /* link completed itds into the schedule */
-               if (((next_uframe >> 3) != frame)
-                               || packet == urb->number_of_packets) {
-                       itd_link(fusbh200, frame & (fusbh200->periodic_size - 1), itd);
-                       itd = NULL;
-               }
-       }
-       stream->next_uframe = next_uframe;
-
-       /* don't need that schedule data any more */
-       iso_sched_free (stream, iso_sched);
-       urb->hcpriv = NULL;
-
-       ++fusbh200->isoc_count;
-       enable_periodic(fusbh200);
-}
-
-#define        ISO_ERRS (FUSBH200_ISOC_BUF_ERR | FUSBH200_ISOC_BABBLE | FUSBH200_ISOC_XACTERR)
-
-/* Process and recycle a completed ITD.  Return true iff its urb completed,
- * and hence its completion callback probably added things to the hardware
- * schedule.
- *
- * Note that we carefully avoid recycling this descriptor until after any
- * completion callback runs, so that it won't be reused quickly.  That is,
- * assuming (a) no more than two urbs per frame on this endpoint, and also
- * (b) only this endpoint's completions submit URBs.  It seems some silicon
- * corrupts things if you reuse completed descriptors very quickly...
- */
-static bool itd_complete(struct fusbh200_hcd *fusbh200, struct fusbh200_itd *itd)
-{
-       struct urb                              *urb = itd->urb;
-       struct usb_iso_packet_descriptor        *desc;
-       u32                                     t;
-       unsigned                                uframe;
-       int                                     urb_index = -1;
-       struct fusbh200_iso_stream                      *stream = itd->stream;
-       struct usb_device                       *dev;
-       bool                                    retval = false;
-
-       /* for each uframe with a packet */
-       for (uframe = 0; uframe < 8; uframe++) {
-               if (likely (itd->index[uframe] == -1))
-                       continue;
-               urb_index = itd->index[uframe];
-               desc = &urb->iso_frame_desc [urb_index];
-
-               t = hc32_to_cpup(fusbh200, &itd->hw_transaction [uframe]);
-               itd->hw_transaction [uframe] = 0;
-
-               /* report transfer status */
-               if (unlikely (t & ISO_ERRS)) {
-                       urb->error_count++;
-                       if (t & FUSBH200_ISOC_BUF_ERR)
-                               desc->status = usb_pipein (urb->pipe)
-                                       ? -ENOSR  /* hc couldn't read */
-                                       : -ECOMM; /* hc couldn't write */
-                       else if (t & FUSBH200_ISOC_BABBLE)
-                               desc->status = -EOVERFLOW;
-                       else /* (t & FUSBH200_ISOC_XACTERR) */
-                               desc->status = -EPROTO;
-
-                       /* HC need not update length with this error */
-                       if (!(t & FUSBH200_ISOC_BABBLE)) {
-                               desc->actual_length = fusbh200_itdlen(urb, desc, t);
-                               urb->actual_length += desc->actual_length;
-                       }
-               } else if (likely ((t & FUSBH200_ISOC_ACTIVE) == 0)) {
-                       desc->status = 0;
-                       desc->actual_length = fusbh200_itdlen(urb, desc, t);
-                       urb->actual_length += desc->actual_length;
-               } else {
-                       /* URB was too late */
-                       desc->status = -EXDEV;
-               }
-       }
-
-       /* handle completion now? */
-       if (likely ((urb_index + 1) != urb->number_of_packets))
-               goto done;
-
-       /* ASSERT: it's really the last itd for this urb
-       list_for_each_entry (itd, &stream->td_list, itd_list)
-               BUG_ON (itd->urb == urb);
-        */
-
-       /* give urb back to the driver; completion often (re)submits */
-       dev = urb->dev;
-       fusbh200_urb_done(fusbh200, urb, 0);
-       retval = true;
-       urb = NULL;
-
-       --fusbh200->isoc_count;
-       disable_periodic(fusbh200);
-
-       if (unlikely(list_is_singular(&stream->td_list))) {
-               fusbh200_to_hcd(fusbh200)->self.bandwidth_allocated
-                               -= stream->bandwidth;
-               fusbh200_dbg(fusbh200,
-                       "deschedule devp %s ep%d%s-iso\n",
-                       dev->devpath, stream->bEndpointAddress & 0x0f,
-                       (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out");
-       }
-
-done:
-       itd->urb = NULL;
-
-       /* Add to the end of the free list for later reuse */
-       list_move_tail(&itd->itd_list, &stream->free_list);
-
-       /* Recycle the iTDs when the pipeline is empty (ep no longer in use) */
-       if (list_empty(&stream->td_list)) {
-               list_splice_tail_init(&stream->free_list,
-                               &fusbh200->cached_itd_list);
-               start_free_itds(fusbh200);
-       }
-
-       return retval;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static int itd_submit (struct fusbh200_hcd *fusbh200, struct urb *urb,
-       gfp_t mem_flags)
-{
-       int                     status = -EINVAL;
-       unsigned long           flags;
-       struct fusbh200_iso_stream      *stream;
-
-       /* Get iso_stream head */
-       stream = iso_stream_find (fusbh200, urb);
-       if (unlikely (stream == NULL)) {
-               fusbh200_dbg (fusbh200, "can't get iso stream\n");
-               return -ENOMEM;
-       }
-       if (unlikely (urb->interval != stream->interval &&
-                     fusbh200_port_speed(fusbh200, 0) == USB_PORT_STAT_HIGH_SPEED)) {
-                       fusbh200_dbg (fusbh200, "can't change iso interval %d --> %d\n",
-                               stream->interval, urb->interval);
-                       goto done;
-       }
-
-#ifdef FUSBH200_URB_TRACE
-       fusbh200_dbg (fusbh200,
-               "%s %s urb %p ep%d%s len %d, %d pkts %d uframes [%p]\n",
-               __func__, urb->dev->devpath, urb,
-               usb_pipeendpoint (urb->pipe),
-               usb_pipein (urb->pipe) ? "in" : "out",
-               urb->transfer_buffer_length,
-               urb->number_of_packets, urb->interval,
-               stream);
-#endif
-
-       /* allocate ITDs w/o locking anything */
-       status = itd_urb_transaction (stream, fusbh200, urb, mem_flags);
-       if (unlikely (status < 0)) {
-               fusbh200_dbg (fusbh200, "can't init itds\n");
-               goto done;
-       }
-
-       /* schedule ... need to lock */
-       spin_lock_irqsave (&fusbh200->lock, flags);
-       if (unlikely(!HCD_HW_ACCESSIBLE(fusbh200_to_hcd(fusbh200)))) {
-               status = -ESHUTDOWN;
-               goto done_not_linked;
-       }
-       status = usb_hcd_link_urb_to_ep(fusbh200_to_hcd(fusbh200), urb);
-       if (unlikely(status))
-               goto done_not_linked;
-       status = iso_stream_schedule(fusbh200, urb, stream);
-       if (likely (status == 0))
-               itd_link_urb (fusbh200, urb, fusbh200->periodic_size << 3, stream);
-       else
-               usb_hcd_unlink_urb_from_ep(fusbh200_to_hcd(fusbh200), urb);
- done_not_linked:
-       spin_unlock_irqrestore (&fusbh200->lock, flags);
- done:
-       return status;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static void scan_isoc(struct fusbh200_hcd *fusbh200)
-{
-       unsigned        uf, now_frame, frame;
-       unsigned        fmask = fusbh200->periodic_size - 1;
-       bool            modified, live;
-
-       /*
-        * When running, scan from last scan point up to "now"
-        * else clean up by scanning everything that's left.
-        * Touches as few pages as possible:  cache-friendly.
-        */
-       if (fusbh200->rh_state >= FUSBH200_RH_RUNNING) {
-               uf = fusbh200_read_frame_index(fusbh200);
-               now_frame = (uf >> 3) & fmask;
-               live = true;
-       } else  {
-               now_frame = (fusbh200->next_frame - 1) & fmask;
-               live = false;
-       }
-       fusbh200->now_frame = now_frame;
-
-       frame = fusbh200->next_frame;
-       for (;;) {
-               union fusbh200_shadow   q, *q_p;
-               __hc32                  type, *hw_p;
-
-restart:
-               /* scan each element in frame's queue for completions */
-               q_p = &fusbh200->pshadow [frame];
-               hw_p = &fusbh200->periodic [frame];
-               q.ptr = q_p->ptr;
-               type = Q_NEXT_TYPE(fusbh200, *hw_p);
-               modified = false;
-
-               while (q.ptr != NULL) {
-                       switch (hc32_to_cpu(fusbh200, type)) {
-                       case Q_TYPE_ITD:
-                               /* If this ITD is still active, leave it for
-                                * later processing ... check the next entry.
-                                * No need to check for activity unless the
-                                * frame is current.
-                                */
-                               if (frame == now_frame && live) {
-                                       rmb();
-                                       for (uf = 0; uf < 8; uf++) {
-                                               if (q.itd->hw_transaction[uf] &
-                                                           ITD_ACTIVE(fusbh200))
-                                                       break;
-                                       }
-                                       if (uf < 8) {
-                                               q_p = &q.itd->itd_next;
-                                               hw_p = &q.itd->hw_next;
-                                               type = Q_NEXT_TYPE(fusbh200,
-                                                       q.itd->hw_next);
-                                               q = *q_p;
-                                               break;
-                                       }
-                               }
-
-                               /* Take finished ITDs out of the schedule
-                                * and process them:  recycle, maybe report
-                                * URB completion.  HC won't cache the
-                                * pointer for much longer, if at all.
-                                */
-                               *q_p = q.itd->itd_next;
-                               *hw_p = q.itd->hw_next;
-                               type = Q_NEXT_TYPE(fusbh200, q.itd->hw_next);
-                               wmb();
-                               modified = itd_complete (fusbh200, q.itd);
-                               q = *q_p;
-                               break;
-                       default:
-                               fusbh200_dbg(fusbh200, "corrupt type %d frame %d shadow %p\n",
-                                       type, frame, q.ptr);
-                               // BUG ();
-                               /* FALL THROUGH */
-                       case Q_TYPE_QH:
-                       case Q_TYPE_FSTN:
-                               /* End of the iTDs and siTDs */
-                               q.ptr = NULL;
-                               break;
-                       }
-
-                       /* assume completion callbacks modify the queue */
-                       if (unlikely(modified && fusbh200->isoc_count > 0))
-                               goto restart;
-               }
-
-               /* Stop when we have reached the current frame */
-               if (frame == now_frame)
-                       break;
-               frame = (frame + 1) & fmask;
-       }
-       fusbh200->next_frame = now_frame;
-}
-/*-------------------------------------------------------------------------*/
-/*
- * Display / Set uframe_periodic_max
- */
-static ssize_t show_uframe_periodic_max(struct device *dev,
-                                       struct device_attribute *attr,
-                                       char *buf)
-{
-       struct fusbh200_hcd             *fusbh200;
-       int                     n;
-
-       fusbh200 = hcd_to_fusbh200(bus_to_hcd(dev_get_drvdata(dev)));
-       n = scnprintf(buf, PAGE_SIZE, "%d\n", fusbh200->uframe_periodic_max);
-       return n;
-}
-
-
-static ssize_t store_uframe_periodic_max(struct device *dev,
-                                       struct device_attribute *attr,
-                                       const char *buf, size_t count)
-{
-       struct fusbh200_hcd             *fusbh200;
-       unsigned                uframe_periodic_max;
-       unsigned                frame, uframe;
-       unsigned short          allocated_max;
-       unsigned long           flags;
-       ssize_t                 ret;
-
-       fusbh200 = hcd_to_fusbh200(bus_to_hcd(dev_get_drvdata(dev)));
-       if (kstrtouint(buf, 0, &uframe_periodic_max) < 0)
-               return -EINVAL;
-
-       if (uframe_periodic_max < 100 || uframe_periodic_max >= 125) {
-               fusbh200_info(fusbh200, "rejecting invalid request for "
-                               "uframe_periodic_max=%u\n", uframe_periodic_max);
-               return -EINVAL;
-       }
-
-       ret = -EINVAL;
-
-       /*
-        * lock, so that our checking does not race with possible periodic
-        * bandwidth allocation through submitting new urbs.
-        */
-       spin_lock_irqsave (&fusbh200->lock, flags);
-
-       /*
-        * for request to decrease max periodic bandwidth, we have to check
-        * every microframe in the schedule to see whether the decrease is
-        * possible.
-        */
-       if (uframe_periodic_max < fusbh200->uframe_periodic_max) {
-               allocated_max = 0;
-
-               for (frame = 0; frame < fusbh200->periodic_size; ++frame)
-                       for (uframe = 0; uframe < 7; ++uframe)
-                               allocated_max = max(allocated_max,
-                                                   periodic_usecs (fusbh200, frame, uframe));
-
-               if (allocated_max > uframe_periodic_max) {
-                       fusbh200_info(fusbh200,
-                               "cannot decrease uframe_periodic_max because "
-                               "periodic bandwidth is already allocated "
-                               "(%u > %u)\n",
-                               allocated_max, uframe_periodic_max);
-                       goto out_unlock;
-               }
-       }
-
-       /* increasing is always ok */
-
-       fusbh200_info(fusbh200, "setting max periodic bandwidth to %u%% "
-                       "(== %u usec/uframe)\n",
-                       100*uframe_periodic_max/125, uframe_periodic_max);
-
-       if (uframe_periodic_max != 100)
-               fusbh200_warn(fusbh200, "max periodic bandwidth set is non-standard\n");
-
-       fusbh200->uframe_periodic_max = uframe_periodic_max;
-       ret = count;
-
-out_unlock:
-       spin_unlock_irqrestore (&fusbh200->lock, flags);
-       return ret;
-}
-static DEVICE_ATTR(uframe_periodic_max, 0644, show_uframe_periodic_max, store_uframe_periodic_max);
-
-
-static inline int create_sysfs_files(struct fusbh200_hcd *fusbh200)
-{
-       struct device   *controller = fusbh200_to_hcd(fusbh200)->self.controller;
-       int     i = 0;
-
-       if (i)
-               goto out;
-
-       i = device_create_file(controller, &dev_attr_uframe_periodic_max);
-out:
-       return i;
-}
-
-static inline void remove_sysfs_files(struct fusbh200_hcd *fusbh200)
-{
-       struct device   *controller = fusbh200_to_hcd(fusbh200)->self.controller;
-
-       device_remove_file(controller, &dev_attr_uframe_periodic_max);
-}
-/*-------------------------------------------------------------------------*/
-
-/* On some systems, leaving remote wakeup enabled prevents system shutdown.
- * The firmware seems to think that powering off is a wakeup event!
- * This routine turns off remote wakeup and everything else, on all ports.
- */
-static void fusbh200_turn_off_all_ports(struct fusbh200_hcd *fusbh200)
-{
-       u32 __iomem *status_reg = &fusbh200->regs->port_status;
-
-       fusbh200_writel(fusbh200, PORT_RWC_BITS, status_reg);
-}
-
-/*
- * Halt HC, turn off all ports, and let the BIOS use the companion controllers.
- * Must be called with interrupts enabled and the lock not held.
- */
-static void fusbh200_silence_controller(struct fusbh200_hcd *fusbh200)
-{
-       fusbh200_halt(fusbh200);
-
-       spin_lock_irq(&fusbh200->lock);
-       fusbh200->rh_state = FUSBH200_RH_HALTED;
-       fusbh200_turn_off_all_ports(fusbh200);
-       spin_unlock_irq(&fusbh200->lock);
-}
-
-/* fusbh200_shutdown kick in for silicon on any bus (not just pci, etc).
- * This forcibly disables dma and IRQs, helping kexec and other cases
- * where the next system software may expect clean state.
- */
-static void fusbh200_shutdown(struct usb_hcd *hcd)
-{
-       struct fusbh200_hcd     *fusbh200 = hcd_to_fusbh200(hcd);
-
-       spin_lock_irq(&fusbh200->lock);
-       fusbh200->shutdown = true;
-       fusbh200->rh_state = FUSBH200_RH_STOPPING;
-       fusbh200->enabled_hrtimer_events = 0;
-       spin_unlock_irq(&fusbh200->lock);
-
-       fusbh200_silence_controller(fusbh200);
-
-       hrtimer_cancel(&fusbh200->hrtimer);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * fusbh200_work is called from some interrupts, timers, and so on.
- * it calls driver completion functions, after dropping fusbh200->lock.
- */
-static void fusbh200_work (struct fusbh200_hcd *fusbh200)
-{
-       /* another CPU may drop fusbh200->lock during a schedule scan while
-        * it reports urb completions.  this flag guards against bogus
-        * attempts at re-entrant schedule scanning.
-        */
-       if (fusbh200->scanning) {
-               fusbh200->need_rescan = true;
-               return;
-       }
-       fusbh200->scanning = true;
-
- rescan:
-       fusbh200->need_rescan = false;
-       if (fusbh200->async_count)
-               scan_async(fusbh200);
-       if (fusbh200->intr_count > 0)
-               scan_intr(fusbh200);
-       if (fusbh200->isoc_count > 0)
-               scan_isoc(fusbh200);
-       if (fusbh200->need_rescan)
-               goto rescan;
-       fusbh200->scanning = false;
-
-       /* the IO watchdog guards against hardware or driver bugs that
-        * misplace IRQs, and should let us run completely without IRQs.
-        * such lossage has been observed on both VT6202 and VT8235.
-        */
-       turn_on_io_watchdog(fusbh200);
-}
-
-/*
- * Called when the fusbh200_hcd module is removed.
- */
-static void fusbh200_stop (struct usb_hcd *hcd)
-{
-       struct fusbh200_hcd             *fusbh200 = hcd_to_fusbh200 (hcd);
-
-       fusbh200_dbg (fusbh200, "stop\n");
-
-       /* no more interrupts ... */
-
-       spin_lock_irq(&fusbh200->lock);
-       fusbh200->enabled_hrtimer_events = 0;
-       spin_unlock_irq(&fusbh200->lock);
-
-       fusbh200_quiesce(fusbh200);
-       fusbh200_silence_controller(fusbh200);
-       fusbh200_reset (fusbh200);
-
-       hrtimer_cancel(&fusbh200->hrtimer);
-       remove_sysfs_files(fusbh200);
-       remove_debug_files (fusbh200);
-
-       /* root hub is shut down separately (first, when possible) */
-       spin_lock_irq (&fusbh200->lock);
-       end_free_itds(fusbh200);
-       spin_unlock_irq (&fusbh200->lock);
-       fusbh200_mem_cleanup (fusbh200);
-
-       fusbh200_dbg(fusbh200, "irq normal %ld err %ld iaa %ld (lost %ld)\n",
-               fusbh200->stats.normal, fusbh200->stats.error, fusbh200->stats.iaa,
-               fusbh200->stats.lost_iaa);
-       fusbh200_dbg (fusbh200, "complete %ld unlink %ld\n",
-               fusbh200->stats.complete, fusbh200->stats.unlink);
-
-       dbg_status (fusbh200, "fusbh200_stop completed",
-                   fusbh200_readl(fusbh200, &fusbh200->regs->status));
-}
-
-/* one-time init, only for memory state */
-static int hcd_fusbh200_init(struct usb_hcd *hcd)
-{
-       struct fusbh200_hcd             *fusbh200 = hcd_to_fusbh200(hcd);
-       u32                     temp;
-       int                     retval;
-       u32                     hcc_params;
-       struct fusbh200_qh_hw   *hw;
-
-       spin_lock_init(&fusbh200->lock);
-
-       /*
-        * keep io watchdog by default, those good HCDs could turn off it later
-        */
-       fusbh200->need_io_watchdog = 1;
-
-       hrtimer_init(&fusbh200->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
-       fusbh200->hrtimer.function = fusbh200_hrtimer_func;
-       fusbh200->next_hrtimer_event = FUSBH200_HRTIMER_NO_EVENT;
-
-       hcc_params = fusbh200_readl(fusbh200, &fusbh200->caps->hcc_params);
-
-       /*
-        * by default set standard 80% (== 100 usec/uframe) max periodic
-        * bandwidth as required by USB 2.0
-        */
-       fusbh200->uframe_periodic_max = 100;
-
-       /*
-        * hw default: 1K periodic list heads, one per frame.
-        * periodic_size can shrink by USBCMD update if hcc_params allows.
-        */
-       fusbh200->periodic_size = DEFAULT_I_TDPS;
-       INIT_LIST_HEAD(&fusbh200->intr_qh_list);
-       INIT_LIST_HEAD(&fusbh200->cached_itd_list);
-
-       if (HCC_PGM_FRAMELISTLEN(hcc_params)) {
-               /* periodic schedule size can be smaller than default */
-               switch (FUSBH200_TUNE_FLS) {
-               case 0: fusbh200->periodic_size = 1024; break;
-               case 1: fusbh200->periodic_size = 512; break;
-               case 2: fusbh200->periodic_size = 256; break;
-               default:        BUG();
-               }
-       }
-       if ((retval = fusbh200_mem_init(fusbh200, GFP_KERNEL)) < 0)
-               return retval;
-
-       /* controllers may cache some of the periodic schedule ... */
-       fusbh200->i_thresh = 2;
-
-       /*
-        * dedicate a qh for the async ring head, since we couldn't unlink
-        * a 'real' qh without stopping the async schedule [4.8].  use it
-        * as the 'reclamation list head' too.
-        * its dummy is used in hw_alt_next of many tds, to prevent the qh
-        * from automatically advancing to the next td after short reads.
-        */
-       fusbh200->async->qh_next.qh = NULL;
-       hw = fusbh200->async->hw;
-       hw->hw_next = QH_NEXT(fusbh200, fusbh200->async->qh_dma);
-       hw->hw_info1 = cpu_to_hc32(fusbh200, QH_HEAD);
-       hw->hw_token = cpu_to_hc32(fusbh200, QTD_STS_HALT);
-       hw->hw_qtd_next = FUSBH200_LIST_END(fusbh200);
-       fusbh200->async->qh_state = QH_STATE_LINKED;
-       hw->hw_alt_next = QTD_NEXT(fusbh200, fusbh200->async->dummy->qtd_dma);
-
-       /* clear interrupt enables, set irq latency */
-       if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
-               log2_irq_thresh = 0;
-       temp = 1 << (16 + log2_irq_thresh);
-       if (HCC_CANPARK(hcc_params)) {
-               /* HW default park == 3, on hardware that supports it (like
-                * NVidia and ALI silicon), maximizes throughput on the async
-                * schedule by avoiding QH fetches between transfers.
-                *
-                * With fast usb storage devices and NForce2, "park" seems to
-                * make problems:  throughput reduction (!), data errors...
-                */
-               if (park) {
-                       park = min(park, (unsigned) 3);
-                       temp |= CMD_PARK;
-                       temp |= park << 8;
-               }
-               fusbh200_dbg(fusbh200, "park %d\n", park);
-       }
-       if (HCC_PGM_FRAMELISTLEN(hcc_params)) {
-               /* periodic schedule size can be smaller than default */
-               temp &= ~(3 << 2);
-               temp |= (FUSBH200_TUNE_FLS << 2);
-       }
-       fusbh200->command = temp;
-
-       /* Accept arbitrarily long scatter-gather lists */
-       if (!(hcd->driver->flags & HCD_LOCAL_MEM))
-               hcd->self.sg_tablesize = ~0;
-       return 0;
-}
-
-/* start HC running; it's halted, hcd_fusbh200_init() has been run (once) */
-static int fusbh200_run (struct usb_hcd *hcd)
-{
-       struct fusbh200_hcd             *fusbh200 = hcd_to_fusbh200 (hcd);
-       u32                     temp;
-       u32                     hcc_params;
-
-       hcd->uses_new_polling = 1;
-
-       /* EHCI spec section 4.1 */
-
-       fusbh200_writel(fusbh200, fusbh200->periodic_dma, &fusbh200->regs->frame_list);
-       fusbh200_writel(fusbh200, (u32)fusbh200->async->qh_dma, &fusbh200->regs->async_next);
-
-       /*
-        * hcc_params controls whether fusbh200->regs->segment must (!!!)
-        * be used; it constrains QH/ITD/SITD and QTD locations.
-        * pci_pool consistent memory always uses segment zero.
-        * streaming mappings for I/O buffers, like pci_map_single(),
-        * can return segments above 4GB, if the device allows.
-        *
-        * NOTE:  the dma mask is visible through dma_supported(), so
-        * drivers can pass this info along ... like NETIF_F_HIGHDMA,
-        * Scsi_Host.highmem_io, and so forth.  It's readonly to all
-        * host side drivers though.
-        */
-       hcc_params = fusbh200_readl(fusbh200, &fusbh200->caps->hcc_params);
-
-       // Philips, Intel, and maybe others need CMD_RUN before the
-       // root hub will detect new devices (why?); NEC doesn't
-       fusbh200->command &= ~(CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET);
-       fusbh200->command |= CMD_RUN;
-       fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command);
-       dbg_cmd (fusbh200, "init", fusbh200->command);
-
-       /*
-        * Start, enabling full USB 2.0 functionality ... usb 1.1 devices
-        * are explicitly handed to companion controller(s), so no TT is
-        * involved with the root hub.  (Except where one is integrated,
-        * and there's no companion controller unless maybe for USB OTG.)
-        *
-        * Turning on the CF flag will transfer ownership of all ports
-        * from the companions to the EHCI controller.  If any of the
-        * companions are in the middle of a port reset at the time, it
-        * could cause trouble.  Write-locking ehci_cf_port_reset_rwsem
-        * guarantees that no resets are in progress.  After we set CF,
-        * a short delay lets the hardware catch up; new resets shouldn't
-        * be started before the port switching actions could complete.
-        */
-       down_write(&ehci_cf_port_reset_rwsem);
-       fusbh200->rh_state = FUSBH200_RH_RUNNING;
-       fusbh200_readl(fusbh200, &fusbh200->regs->command);     /* unblock posted writes */
-       msleep(5);
-       up_write(&ehci_cf_port_reset_rwsem);
-       fusbh200->last_periodic_enable = ktime_get_real();
-
-       temp = HC_VERSION(fusbh200, fusbh200_readl(fusbh200, &fusbh200->caps->hc_capbase));
-       fusbh200_info (fusbh200,
-               "USB %x.%x started, EHCI %x.%02x\n",
-               ((fusbh200->sbrn & 0xf0)>>4), (fusbh200->sbrn & 0x0f),
-               temp >> 8, temp & 0xff);
-
-       fusbh200_writel(fusbh200, INTR_MASK,
-                   &fusbh200->regs->intr_enable); /* Turn On Interrupts */
-
-       /* GRR this is run-once init(), being done every time the HC starts.
-        * So long as they're part of class devices, we can't do it init()
-        * since the class device isn't created that early.
-        */
-       create_debug_files(fusbh200);
-       create_sysfs_files(fusbh200);
-
-       return 0;
-}
-
-static int fusbh200_setup(struct usb_hcd *hcd)
-{
-       struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200(hcd);
-       int retval;
-
-       fusbh200->regs = (void __iomem *)fusbh200->caps +
-           HC_LENGTH(fusbh200, fusbh200_readl(fusbh200, &fusbh200->caps->hc_capbase));
-       dbg_hcs_params(fusbh200, "reset");
-       dbg_hcc_params(fusbh200, "reset");
-
-       /* cache this readonly data; minimize chip reads */
-       fusbh200->hcs_params = fusbh200_readl(fusbh200, &fusbh200->caps->hcs_params);
-
-       fusbh200->sbrn = HCD_USB2;
-
-       /* data structure init */
-       retval = hcd_fusbh200_init(hcd);
-       if (retval)
-               return retval;
-
-       retval = fusbh200_halt(fusbh200);
-       if (retval)
-               return retval;
-
-       fusbh200_reset(fusbh200);
-
-       return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
-static irqreturn_t fusbh200_irq (struct usb_hcd *hcd)
-{
-       struct fusbh200_hcd             *fusbh200 = hcd_to_fusbh200 (hcd);
-       u32                     status, masked_status, pcd_status = 0, cmd;
-       int                     bh;
-
-       spin_lock (&fusbh200->lock);
-
-       status = fusbh200_readl(fusbh200, &fusbh200->regs->status);
-
-       /* e.g. cardbus physical eject */
-       if (status == ~(u32) 0) {
-               fusbh200_dbg (fusbh200, "device removed\n");
-               goto dead;
-       }
-
-       /*
-        * We don't use STS_FLR, but some controllers don't like it to
-        * remain on, so mask it out along with the other status bits.
-        */
-       masked_status = status & (INTR_MASK | STS_FLR);
-
-       /* Shared IRQ? */
-       if (!masked_status || unlikely(fusbh200->rh_state == FUSBH200_RH_HALTED)) {
-               spin_unlock(&fusbh200->lock);
-               return IRQ_NONE;
-       }
-
-       /* clear (just) interrupts */
-       fusbh200_writel(fusbh200, masked_status, &fusbh200->regs->status);
-       cmd = fusbh200_readl(fusbh200, &fusbh200->regs->command);
-       bh = 0;
-
-       /* normal [4.15.1.2] or error [4.15.1.1] completion */
-       if (likely ((status & (STS_INT|STS_ERR)) != 0)) {
-               if (likely ((status & STS_ERR) == 0))
-                       COUNT (fusbh200->stats.normal);
-               else
-                       COUNT (fusbh200->stats.error);
-               bh = 1;
-       }
-
-       /* complete the unlinking of some qh [4.15.2.3] */
-       if (status & STS_IAA) {
-
-               /* Turn off the IAA watchdog */
-               fusbh200->enabled_hrtimer_events &= ~BIT(FUSBH200_HRTIMER_IAA_WATCHDOG);
-
-               /*
-                * Mild optimization: Allow another IAAD to reset the
-                * hrtimer, if one occurs before the next expiration.
-                * In theory we could always cancel the hrtimer, but
-                * tests show that about half the time it will be reset
-                * for some other event anyway.
-                */
-               if (fusbh200->next_hrtimer_event == FUSBH200_HRTIMER_IAA_WATCHDOG)
-                       ++fusbh200->next_hrtimer_event;
-
-               /* guard against (alleged) silicon errata */
-               if (cmd & CMD_IAAD)
-                       fusbh200_dbg(fusbh200, "IAA with IAAD still set?\n");
-               if (fusbh200->async_iaa) {
-                       COUNT(fusbh200->stats.iaa);
-                       end_unlink_async(fusbh200);
-               } else
-                       fusbh200_dbg(fusbh200, "IAA with nothing unlinked?\n");
-       }
-
-       /* remote wakeup [4.3.1] */
-       if (status & STS_PCD) {
-               int pstatus;
-               u32 __iomem *status_reg = &fusbh200->regs->port_status;
-
-               /* kick root hub later */
-               pcd_status = status;
-
-               /* resume root hub? */
-               if (fusbh200->rh_state == FUSBH200_RH_SUSPENDED)
-                       usb_hcd_resume_root_hub(hcd);
-
-               pstatus = fusbh200_readl(fusbh200, status_reg);
-
-               if (test_bit(0, &fusbh200->suspended_ports) &&
-                               ((pstatus & PORT_RESUME) ||
-                                       !(pstatus & PORT_SUSPEND)) &&
-                               (pstatus & PORT_PE) &&
-                               fusbh200->reset_done[0] == 0) {
-
-                       /* start 20 msec resume signaling from this port,
-                        * and make hub_wq collect PORT_STAT_C_SUSPEND to
-                        * stop that signaling.  Use 5 ms extra for safety,
-                        * like usb_port_resume() does.
-                        */
-                       fusbh200->reset_done[0] = jiffies + msecs_to_jiffies(25);
-                       set_bit(0, &fusbh200->resuming_ports);
-                       fusbh200_dbg (fusbh200, "port 1 remote wakeup\n");
-                       mod_timer(&hcd->rh_timer, fusbh200->reset_done[0]);
-               }
-       }
-
-       /* PCI errors [4.15.2.4] */
-       if (unlikely ((status & STS_FATAL) != 0)) {
-               fusbh200_err(fusbh200, "fatal error\n");
-               dbg_cmd(fusbh200, "fatal", cmd);
-               dbg_status(fusbh200, "fatal", status);
-dead:
-               usb_hc_died(hcd);
-
-               /* Don't let the controller do anything more */
-               fusbh200->shutdown = true;
-               fusbh200->rh_state = FUSBH200_RH_STOPPING;
-               fusbh200->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE);
-               fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command);
-               fusbh200_writel(fusbh200, 0, &fusbh200->regs->intr_enable);
-               fusbh200_handle_controller_death(fusbh200);
-
-               /* Handle completions when the controller stops */
-               bh = 0;
-       }
-
-       if (bh)
-               fusbh200_work (fusbh200);
-       spin_unlock (&fusbh200->lock);
-       if (pcd_status)
-               usb_hcd_poll_rh_status(hcd);
-       return IRQ_HANDLED;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * non-error returns are a promise to giveback() the urb later
- * we drop ownership so next owner (or urb unlink) can get it
- *
- * urb + dev is in hcd.self.controller.urb_list
- * we're queueing TDs onto software and hardware lists
- *
- * hcd-specific init for hcpriv hasn't been done yet
- *
- * NOTE:  control, bulk, and interrupt share the same code to append TDs
- * to a (possibly active) QH, and the same QH scanning code.
- */
-static int fusbh200_urb_enqueue (
-       struct usb_hcd  *hcd,
-       struct urb      *urb,
-       gfp_t           mem_flags
-) {
-       struct fusbh200_hcd             *fusbh200 = hcd_to_fusbh200 (hcd);
-       struct list_head        qtd_list;
-
-       INIT_LIST_HEAD (&qtd_list);
-
-       switch (usb_pipetype (urb->pipe)) {
-       case PIPE_CONTROL:
-               /* qh_completions() code doesn't handle all the fault cases
-                * in multi-TD control transfers.  Even 1KB is rare anyway.
-                */
-               if (urb->transfer_buffer_length > (16 * 1024))
-                       return -EMSGSIZE;
-               /* FALLTHROUGH */
-       /* case PIPE_BULK: */
-       default:
-               if (!qh_urb_transaction (fusbh200, urb, &qtd_list, mem_flags))
-                       return -ENOMEM;
-               return submit_async(fusbh200, urb, &qtd_list, mem_flags);
-
-       case PIPE_INTERRUPT:
-               if (!qh_urb_transaction (fusbh200, urb, &qtd_list, mem_flags))
-                       return -ENOMEM;
-               return intr_submit(fusbh200, urb, &qtd_list, mem_flags);
-
-       case PIPE_ISOCHRONOUS:
-               return itd_submit (fusbh200, urb, mem_flags);
-       }
-}
-
-/* remove from hardware lists
- * completions normally happen asynchronously
- */
-
-static int fusbh200_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
-{
-       struct fusbh200_hcd             *fusbh200 = hcd_to_fusbh200 (hcd);
-       struct fusbh200_qh              *qh;
-       unsigned long           flags;
-       int                     rc;
-
-       spin_lock_irqsave (&fusbh200->lock, flags);
-       rc = usb_hcd_check_unlink_urb(hcd, urb, status);
-       if (rc)
-               goto done;
-
-       switch (usb_pipetype (urb->pipe)) {
-       // case PIPE_CONTROL:
-       // case PIPE_BULK:
-       default:
-               qh = (struct fusbh200_qh *) urb->hcpriv;
-               if (!qh)
-                       break;
-               switch (qh->qh_state) {
-               case QH_STATE_LINKED:
-               case QH_STATE_COMPLETING:
-                       start_unlink_async(fusbh200, qh);
-                       break;
-               case QH_STATE_UNLINK:
-               case QH_STATE_UNLINK_WAIT:
-                       /* already started */
-                       break;
-               case QH_STATE_IDLE:
-                       /* QH might be waiting for a Clear-TT-Buffer */
-                       qh_completions(fusbh200, qh);
-                       break;
-               }
-               break;
-
-       case PIPE_INTERRUPT:
-               qh = (struct fusbh200_qh *) urb->hcpriv;
-               if (!qh)
-                       break;
-               switch (qh->qh_state) {
-               case QH_STATE_LINKED:
-               case QH_STATE_COMPLETING:
-                       start_unlink_intr(fusbh200, qh);
-                       break;
-               case QH_STATE_IDLE:
-                       qh_completions (fusbh200, qh);
-                       break;
-               default:
-                       fusbh200_dbg (fusbh200, "bogus qh %p state %d\n",
-                                       qh, qh->qh_state);
-                       goto done;
-               }
-               break;
-
-       case PIPE_ISOCHRONOUS:
-               // itd...
-
-               // wait till next completion, do it then.
-               // completion irqs can wait up to 1024 msec,
-               break;
-       }
-done:
-       spin_unlock_irqrestore (&fusbh200->lock, flags);
-       return rc;
-}
-
-/*-------------------------------------------------------------------------*/
-
-// bulk qh holds the data toggle
-
-static void
-fusbh200_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
-{
-       struct fusbh200_hcd             *fusbh200 = hcd_to_fusbh200 (hcd);
-       unsigned long           flags;
-       struct fusbh200_qh              *qh, *tmp;
-
-       /* ASSERT:  any requests/urbs are being unlinked */
-       /* ASSERT:  nobody can be submitting urbs for this any more */
-
-rescan:
-       spin_lock_irqsave (&fusbh200->lock, flags);
-       qh = ep->hcpriv;
-       if (!qh)
-               goto done;
-
-       /* endpoints can be iso streams.  for now, we don't
-        * accelerate iso completions ... so spin a while.
-        */
-       if (qh->hw == NULL) {
-               struct fusbh200_iso_stream      *stream = ep->hcpriv;
-
-               if (!list_empty(&stream->td_list))
-                       goto idle_timeout;
-
-               /* BUG_ON(!list_empty(&stream->free_list)); */
-               kfree(stream);
-               goto done;
-       }
-
-       if (fusbh200->rh_state < FUSBH200_RH_RUNNING)
-               qh->qh_state = QH_STATE_IDLE;
-       switch (qh->qh_state) {
-       case QH_STATE_LINKED:
-       case QH_STATE_COMPLETING:
-               for (tmp = fusbh200->async->qh_next.qh;
-                               tmp && tmp != qh;
-                               tmp = tmp->qh_next.qh)
-                       continue;
-               /* periodic qh self-unlinks on empty, and a COMPLETING qh
-                * may already be unlinked.
-                */
-               if (tmp)
-                       start_unlink_async(fusbh200, qh);
-               /* FALL THROUGH */
-       case QH_STATE_UNLINK:           /* wait for hw to finish? */
-       case QH_STATE_UNLINK_WAIT:
-idle_timeout:
-               spin_unlock_irqrestore (&fusbh200->lock, flags);
-               schedule_timeout_uninterruptible(1);
-               goto rescan;
-       case QH_STATE_IDLE:             /* fully unlinked */
-               if (qh->clearing_tt)
-                       goto idle_timeout;
-               if (list_empty (&qh->qtd_list)) {
-                       qh_destroy(fusbh200, qh);
-                       break;
-               }
-               /* else FALL THROUGH */
-       default:
-               /* caller was supposed to have unlinked any requests;
-                * that's not our job.  just leak this memory.
-                */
-               fusbh200_err (fusbh200, "qh %p (#%02x) state %d%s\n",
-                       qh, ep->desc.bEndpointAddress, qh->qh_state,
-                       list_empty (&qh->qtd_list) ? "" : "(has tds)");
-               break;
-       }
- done:
-       ep->hcpriv = NULL;
-       spin_unlock_irqrestore (&fusbh200->lock, flags);
-}
-
-static void
-fusbh200_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
-{
-       struct fusbh200_hcd             *fusbh200 = hcd_to_fusbh200(hcd);
-       struct fusbh200_qh              *qh;
-       int                     eptype = usb_endpoint_type(&ep->desc);
-       int                     epnum = usb_endpoint_num(&ep->desc);
-       int                     is_out = usb_endpoint_dir_out(&ep->desc);
-       unsigned long           flags;
-
-       if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT)
-               return;
-
-       spin_lock_irqsave(&fusbh200->lock, flags);
-       qh = ep->hcpriv;
-
-       /* For Bulk and Interrupt endpoints we maintain the toggle state
-        * in the hardware; the toggle bits in udev aren't used at all.
-        * When an endpoint is reset by usb_clear_halt() we must reset
-        * the toggle bit in the QH.
-        */
-       if (qh) {
-               usb_settoggle(qh->dev, epnum, is_out, 0);
-               if (!list_empty(&qh->qtd_list)) {
-                       WARN_ONCE(1, "clear_halt for a busy endpoint\n");
-               } else if (qh->qh_state == QH_STATE_LINKED ||
-                               qh->qh_state == QH_STATE_COMPLETING) {
-
-                       /* The toggle value in the QH can't be updated
-                        * while the QH is active.  Unlink it now;
-                        * re-linking will call qh_refresh().
-                        */
-                       if (eptype == USB_ENDPOINT_XFER_BULK)
-                               start_unlink_async(fusbh200, qh);
-                       else
-                               start_unlink_intr(fusbh200, qh);
-               }
-       }
-       spin_unlock_irqrestore(&fusbh200->lock, flags);
-}
-
-static int fusbh200_get_frame (struct usb_hcd *hcd)
-{
-       struct fusbh200_hcd             *fusbh200 = hcd_to_fusbh200 (hcd);
-       return (fusbh200_read_frame_index(fusbh200) >> 3) % fusbh200->periodic_size;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * The EHCI in ChipIdea HDRC cannot be a separate module or device,
- * because its registers (and irq) are shared between host/gadget/otg
- * functions  and in order to facilitate role switching we cannot
- * give the fusbh200 driver exclusive access to those.
- */
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR (DRIVER_AUTHOR);
-MODULE_LICENSE ("GPL");
-
-static const struct hc_driver fusbh200_fusbh200_hc_driver = {
-       .description            = hcd_name,
-       .product_desc           = "Faraday USB2.0 Host Controller",
-       .hcd_priv_size          = sizeof(struct fusbh200_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq                    = fusbh200_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2,
-
-       /*
-        * basic lifecycle operations
-        */
-       .reset                  = hcd_fusbh200_init,
-       .start                  = fusbh200_run,
-       .stop                   = fusbh200_stop,
-       .shutdown               = fusbh200_shutdown,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue            = fusbh200_urb_enqueue,
-       .urb_dequeue            = fusbh200_urb_dequeue,
-       .endpoint_disable       = fusbh200_endpoint_disable,
-       .endpoint_reset         = fusbh200_endpoint_reset,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number       = fusbh200_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data        = fusbh200_hub_status_data,
-       .hub_control            = fusbh200_hub_control,
-       .bus_suspend            = fusbh200_bus_suspend,
-       .bus_resume             = fusbh200_bus_resume,
-
-       .relinquish_port        = fusbh200_relinquish_port,
-       .port_handed_over       = fusbh200_port_handed_over,
-
-       .clear_tt_buffer_complete = fusbh200_clear_tt_buffer_complete,
-};
-
-static void fusbh200_init(struct fusbh200_hcd *fusbh200)
-{
-       u32 reg;
-
-       reg = fusbh200_readl(fusbh200, &fusbh200->regs->bmcsr);
-       reg |= BMCSR_INT_POLARITY;
-       reg &= ~BMCSR_VBUS_OFF;
-       fusbh200_writel(fusbh200, reg, &fusbh200->regs->bmcsr);
-
-       reg = fusbh200_readl(fusbh200, &fusbh200->regs->bmier);
-       fusbh200_writel(fusbh200, reg | BMIER_OVC_EN | BMIER_VBUS_ERR_EN,
-               &fusbh200->regs->bmier);
-}
-
-/**
- * fusbh200_hcd_probe - initialize faraday FUSBH200 HCDs
- *
- * Allocates basic resources for this USB host controller, and
- * then invokes the start() method for the HCD associated with it
- * through the hotplug entry's driver_data.
- */
-static int fusbh200_hcd_probe(struct platform_device *pdev)
-{
-       struct device                   *dev = &pdev->dev;
-       struct usb_hcd                  *hcd;
-       struct resource                 *res;
-       int                             irq;
-       int                             retval = -ENODEV;
-       struct fusbh200_hcd             *fusbh200;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       pdev->dev.power.power_state = PMSG_ON;
-
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-       if (!res) {
-               dev_err(dev,
-                       "Found HC with no IRQ. Check %s setup!\n",
-                       dev_name(dev));
-               return -ENODEV;
-       }
-
-       irq = res->start;
-
-       hcd = usb_create_hcd(&fusbh200_fusbh200_hc_driver, dev,
-                       dev_name(dev));
-       if (!hcd) {
-               dev_err(dev, "failed to create hcd with err %d\n", retval);
-               retval = -ENOMEM;
-               goto fail_create_hcd;
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev,
-                       "Found HC with no register addr. Check %s setup!\n",
-                       dev_name(dev));
-               retval = -ENODEV;
-               goto fail_request_resource;
-       }
-
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-       hcd->has_tt = 1;
-
-       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
-                               fusbh200_fusbh200_hc_driver.description)) {
-               dev_dbg(dev, "controller already in use\n");
-               retval = -EBUSY;
-               goto fail_request_resource;
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       if (!res) {
-               dev_err(dev,
-                       "Found HC with no register addr. Check %s setup!\n",
-                       dev_name(dev));
-               retval = -ENODEV;
-               goto fail_request_resource;
-       }
-
-       hcd->regs = ioremap_nocache(res->start, resource_size(res));
-       if (hcd->regs == NULL) {
-               dev_dbg(dev, "error mapping memory\n");
-               retval = -EFAULT;
-               goto fail_ioremap;
-       }
-
-       fusbh200 = hcd_to_fusbh200(hcd);
-
-       fusbh200->caps = hcd->regs;
-
-       retval = fusbh200_setup(hcd);
-       if (retval)
-               goto fail_add_hcd;
-
-       fusbh200_init(fusbh200);
-
-       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
-       if (retval) {
-               dev_err(dev, "failed to add hcd with err %d\n", retval);
-               goto fail_add_hcd;
-       }
-       device_wakeup_enable(hcd->self.controller);
-
-       return retval;
-
-fail_add_hcd:
-       iounmap(hcd->regs);
-fail_ioremap:
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-fail_request_resource:
-       usb_put_hcd(hcd);
-fail_create_hcd:
-       dev_err(dev, "init %s fail, %d\n", dev_name(dev), retval);
-       return retval;
-}
-
-/**
- * fusbh200_hcd_remove - shutdown processing for EHCI HCDs
- * @dev: USB Host Controller being removed
- *
- * Reverses the effect of fotg2xx_usb_hcd_probe(), first invoking
- * the HCD's stop() method.  It is always called from a thread
- * context, normally "rmmod", "apmd", or something similar.
- */
-static int fusbh200_hcd_remove(struct platform_device *pdev)
-{
-       struct device *dev      = &pdev->dev;
-       struct usb_hcd *hcd     = dev_get_drvdata(dev);
-
-       if (!hcd)
-               return 0;
-
-       usb_remove_hcd(hcd);
-       iounmap(hcd->regs);
-       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
-       usb_put_hcd(hcd);
-
-       return 0;
-}
-
-static struct platform_driver fusbh200_hcd_fusbh200_driver = {
-       .driver = {
-               .name   = "fusbh200",
-       },
-       .probe  = fusbh200_hcd_probe,
-       .remove = fusbh200_hcd_remove,
-};
-
-static int __init fusbh200_hcd_init(void)
-{
-       int retval = 0;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name);
-       set_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
-       if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) ||
-                       test_bit(USB_OHCI_LOADED, &usb_hcds_loaded))
-               printk(KERN_WARNING "Warning! fusbh200_hcd should always be loaded"
-                               " before uhci_hcd and ohci_hcd, not after\n");
-
-       pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd\n",
-                hcd_name,
-                sizeof(struct fusbh200_qh), sizeof(struct fusbh200_qtd),
-                sizeof(struct fusbh200_itd));
-
-       fusbh200_debug_root = debugfs_create_dir("fusbh200", usb_debug_root);
-       if (!fusbh200_debug_root) {
-               retval = -ENOENT;
-               goto err_debug;
-       }
-
-       retval = platform_driver_register(&fusbh200_hcd_fusbh200_driver);
-       if (retval < 0)
-               goto clean;
-       return retval;
-
-       platform_driver_unregister(&fusbh200_hcd_fusbh200_driver);
-clean:
-       debugfs_remove(fusbh200_debug_root);
-       fusbh200_debug_root = NULL;
-err_debug:
-       clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
-       return retval;
-}
-module_init(fusbh200_hcd_init);
-
-static void __exit fusbh200_hcd_cleanup(void)
-{
-       platform_driver_unregister(&fusbh200_hcd_fusbh200_driver);
-       debugfs_remove(fusbh200_debug_root);
-       clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
-}
-module_exit(fusbh200_hcd_cleanup);
diff --git a/drivers/usb/host/fusbh200.h b/drivers/usb/host/fusbh200.h
deleted file mode 100644 (file)
index d6e5b3d..0000000
+++ /dev/null
@@ -1,675 +0,0 @@
-#ifndef __LINUX_FUSBH200_H
-#define __LINUX_FUSBH200_H
-
-#include <linux/usb/ehci-dbgp.h>
-
-/* definitions used for the EHCI driver */
-
-/*
- * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to
- * __leXX (normally) or __beXX (given FUSBH200_BIG_ENDIAN_DESC), depending on
- * the host controller implementation.
- *
- * To facilitate the strongest possible byte-order checking from "sparse"
- * and so on, we use __leXX unless that's not practical.
- */
-#define __hc32 __le32
-#define __hc16 __le16
-
-/* statistics can be kept for tuning/monitoring */
-struct fusbh200_stats {
-       /* irq usage */
-       unsigned long           normal;
-       unsigned long           error;
-       unsigned long           iaa;
-       unsigned long           lost_iaa;
-
-       /* termination of urbs from core */
-       unsigned long           complete;
-       unsigned long           unlink;
-};
-
-/* fusbh200_hcd->lock guards shared data against other CPUs:
- *   fusbh200_hcd:     async, unlink, periodic (and shadow), ...
- *   usb_host_endpoint: hcpriv
- *   fusbh200_qh:      qh_next, qtd_list
- *   fusbh200_qtd:     qtd_list
- *
- * Also, hold this lock when talking to HC registers or
- * when updating hw_* fields in shared qh/qtd/... structures.
- */
-
-#define        FUSBH200_MAX_ROOT_PORTS 1               /* see HCS_N_PORTS */
-
-/*
- * fusbh200_rh_state values of FUSBH200_RH_RUNNING or above mean that the
- * controller may be doing DMA.  Lower values mean there's no DMA.
- */
-enum fusbh200_rh_state {
-       FUSBH200_RH_HALTED,
-       FUSBH200_RH_SUSPENDED,
-       FUSBH200_RH_RUNNING,
-       FUSBH200_RH_STOPPING
-};
-
-/*
- * Timer events, ordered by increasing delay length.
- * Always update event_delays_ns[] and event_handlers[] (defined in
- * ehci-timer.c) in parallel with this list.
- */
-enum fusbh200_hrtimer_event {
-       FUSBH200_HRTIMER_POLL_ASS,              /* Poll for async schedule off */
-       FUSBH200_HRTIMER_POLL_PSS,              /* Poll for periodic schedule off */
-       FUSBH200_HRTIMER_POLL_DEAD,             /* Wait for dead controller to stop */
-       FUSBH200_HRTIMER_UNLINK_INTR,   /* Wait for interrupt QH unlink */
-       FUSBH200_HRTIMER_FREE_ITDS,             /* Wait for unused iTDs and siTDs */
-       FUSBH200_HRTIMER_ASYNC_UNLINKS, /* Unlink empty async QHs */
-       FUSBH200_HRTIMER_IAA_WATCHDOG,  /* Handle lost IAA interrupts */
-       FUSBH200_HRTIMER_DISABLE_PERIODIC,      /* Wait to disable periodic sched */
-       FUSBH200_HRTIMER_DISABLE_ASYNC, /* Wait to disable async sched */
-       FUSBH200_HRTIMER_IO_WATCHDOG,   /* Check for missing IRQs */
-       FUSBH200_HRTIMER_NUM_EVENTS             /* Must come last */
-};
-#define FUSBH200_HRTIMER_NO_EVENT      99
-
-struct fusbh200_hcd {                  /* one per controller */
-       /* timing support */
-       enum fusbh200_hrtimer_event     next_hrtimer_event;
-       unsigned                enabled_hrtimer_events;
-       ktime_t                 hr_timeouts[FUSBH200_HRTIMER_NUM_EVENTS];
-       struct hrtimer          hrtimer;
-
-       int                     PSS_poll_count;
-       int                     ASS_poll_count;
-       int                     died_poll_count;
-
-       /* glue to PCI and HCD framework */
-       struct fusbh200_caps __iomem *caps;
-       struct fusbh200_regs __iomem *regs;
-       struct ehci_dbg_port __iomem *debug;
-
-       __u32                   hcs_params;     /* cached register copy */
-       spinlock_t              lock;
-       enum fusbh200_rh_state  rh_state;
-
-       /* general schedule support */
-       bool                    scanning:1;
-       bool                    need_rescan:1;
-       bool                    intr_unlinking:1;
-       bool                    async_unlinking:1;
-       bool                    shutdown:1;
-       struct fusbh200_qh              *qh_scan_next;
-
-       /* async schedule support */
-       struct fusbh200_qh              *async;
-       struct fusbh200_qh              *dummy;         /* For AMD quirk use */
-       struct fusbh200_qh              *async_unlink;
-       struct fusbh200_qh              *async_unlink_last;
-       struct fusbh200_qh              *async_iaa;
-       unsigned                async_unlink_cycle;
-       unsigned                async_count;    /* async activity count */
-
-       /* periodic schedule support */
-#define        DEFAULT_I_TDPS          1024            /* some HCs can do less */
-       unsigned                periodic_size;
-       __hc32                  *periodic;      /* hw periodic table */
-       dma_addr_t              periodic_dma;
-       struct list_head        intr_qh_list;
-       unsigned                i_thresh;       /* uframes HC might cache */
-
-       union fusbh200_shadow   *pshadow;       /* mirror hw periodic table */
-       struct fusbh200_qh              *intr_unlink;
-       struct fusbh200_qh              *intr_unlink_last;
-       unsigned                intr_unlink_cycle;
-       unsigned                now_frame;      /* frame from HC hardware */
-       unsigned                next_frame;     /* scan periodic, start here */
-       unsigned                intr_count;     /* intr activity count */
-       unsigned                isoc_count;     /* isoc activity count */
-       unsigned                periodic_count; /* periodic activity count */
-       unsigned                uframe_periodic_max; /* max periodic time per uframe */
-
-
-       /* list of itds completed while now_frame was still active */
-       struct list_head        cached_itd_list;
-       struct fusbh200_itd     *last_itd_to_free;
-
-       /* per root hub port */
-       unsigned long           reset_done [FUSBH200_MAX_ROOT_PORTS];
-
-       /* bit vectors (one bit per port) */
-       unsigned long           bus_suspended;          /* which ports were
-                       already suspended at the start of a bus suspend */
-       unsigned long           companion_ports;        /* which ports are
-                       dedicated to the companion controller */
-       unsigned long           owned_ports;            /* which ports are
-                       owned by the companion during a bus suspend */
-       unsigned long           port_c_suspend;         /* which ports have
-                       the change-suspend feature turned on */
-       unsigned long           suspended_ports;        /* which ports are
-                       suspended */
-       unsigned long           resuming_ports;         /* which ports have
-                       started to resume */
-
-       /* per-HC memory pools (could be per-bus, but ...) */
-       struct dma_pool         *qh_pool;       /* qh per active urb */
-       struct dma_pool         *qtd_pool;      /* one or more per qh */
-       struct dma_pool         *itd_pool;      /* itd per iso urb */
-
-       unsigned                random_frame;
-       unsigned long           next_statechange;
-       ktime_t                 last_periodic_enable;
-       u32                     command;
-
-       /* SILICON QUIRKS */
-       unsigned                need_io_watchdog:1;
-       unsigned                fs_i_thresh:1;  /* Intel iso scheduling */
-
-       u8                      sbrn;           /* packed release number */
-
-       /* irq statistics */
-       struct fusbh200_stats   stats;
-#      define COUNT(x) do { (x)++; } while (0)
-
-       /* debug files */
-       struct dentry           *debug_dir;
-};
-
-/* convert between an HCD pointer and the corresponding FUSBH200_HCD */
-static inline struct fusbh200_hcd *hcd_to_fusbh200 (struct usb_hcd *hcd)
-{
-       return (struct fusbh200_hcd *) (hcd->hcd_priv);
-}
-static inline struct usb_hcd *fusbh200_to_hcd (struct fusbh200_hcd *fusbh200)
-{
-       return container_of ((void *) fusbh200, struct usb_hcd, hcd_priv);
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* EHCI register interface, corresponds to EHCI Revision 0.95 specification */
-
-/* Section 2.2 Host Controller Capability Registers */
-struct fusbh200_caps {
-       /* these fields are specified as 8 and 16 bit registers,
-        * but some hosts can't perform 8 or 16 bit PCI accesses.
-        * some hosts treat caplength and hciversion as parts of a 32-bit
-        * register, others treat them as two separate registers, this
-        * affects the memory map for big endian controllers.
-        */
-       u32             hc_capbase;
-#define HC_LENGTH(fusbh200, p) (0x00ff&((p) >> /* bits 7:0 / offset 00h */ \
-                               (fusbh200_big_endian_capbase(fusbh200) ? 24 : 0)))
-#define HC_VERSION(fusbh200, p)        (0xffff&((p) >> /* bits 31:16 / offset 02h */ \
-                               (fusbh200_big_endian_capbase(fusbh200) ? 0 : 16)))
-       u32             hcs_params;     /* HCSPARAMS - offset 0x4 */
-#define HCS_N_PORTS(p)         (((p)>>0)&0xf)  /* bits 3:0, ports on HC */
-
-       u32             hcc_params;      /* HCCPARAMS - offset 0x8 */
-#define HCC_CANPARK(p)         ((p)&(1 << 2))  /* true: can park on async qh */
-#define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1))  /* true: periodic_size changes*/
-       u8              portroute[8];    /* nibbles for routing - offset 0xC */
-};
-
-
-/* Section 2.3 Host Controller Operational Registers */
-struct fusbh200_regs {
-
-       /* USBCMD: offset 0x00 */
-       u32             command;
-
-/* EHCI 1.1 addendum */
-/* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */
-#define CMD_PARK       (1<<11)         /* enable "park" on async qh */
-#define CMD_PARK_CNT(c)        (((c)>>8)&3)    /* how many transfers to park for */
-#define CMD_IAAD       (1<<6)          /* "doorbell" interrupt async advance */
-#define CMD_ASE                (1<<5)          /* async schedule enable */
-#define CMD_PSE                (1<<4)          /* periodic schedule enable */
-/* 3:2 is periodic frame list size */
-#define CMD_RESET      (1<<1)          /* reset HC not bus */
-#define CMD_RUN                (1<<0)          /* start/stop HC */
-
-       /* USBSTS: offset 0x04 */
-       u32             status;
-#define STS_ASS                (1<<15)         /* Async Schedule Status */
-#define STS_PSS                (1<<14)         /* Periodic Schedule Status */
-#define STS_RECL       (1<<13)         /* Reclamation */
-#define STS_HALT       (1<<12)         /* Not running (any reason) */
-/* some bits reserved */
-       /* these STS_* flags are also intr_enable bits (USBINTR) */
-#define STS_IAA                (1<<5)          /* Interrupted on async advance */
-#define STS_FATAL      (1<<4)          /* such as some PCI access errors */
-#define STS_FLR                (1<<3)          /* frame list rolled over */
-#define STS_PCD                (1<<2)          /* port change detect */
-#define STS_ERR                (1<<1)          /* "error" completion (overflow, ...) */
-#define STS_INT                (1<<0)          /* "normal" completion (short, ...) */
-
-       /* USBINTR: offset 0x08 */
-       u32             intr_enable;
-
-       /* FRINDEX: offset 0x0C */
-       u32             frame_index;    /* current microframe number */
-       /* CTRLDSSEGMENT: offset 0x10 */
-       u32             segment;        /* address bits 63:32 if needed */
-       /* PERIODICLISTBASE: offset 0x14 */
-       u32             frame_list;     /* points to periodic list */
-       /* ASYNCLISTADDR: offset 0x18 */
-       u32             async_next;     /* address of next async queue head */
-
-       u32     reserved1;
-       /* PORTSC: offset 0x20 */
-       u32     port_status;
-/* 31:23 reserved */
-#define PORT_USB11(x) (((x)&(3<<10)) == (1<<10))       /* USB 1.1 device */
-#define PORT_RESET     (1<<8)          /* reset port */
-#define PORT_SUSPEND   (1<<7)          /* suspend port */
-#define PORT_RESUME    (1<<6)          /* resume it */
-#define PORT_PEC       (1<<3)          /* port enable change */
-#define PORT_PE                (1<<2)          /* port enable */
-#define PORT_CSC       (1<<1)          /* connect status change */
-#define PORT_CONNECT   (1<<0)          /* device connected */
-#define PORT_RWC_BITS   (PORT_CSC | PORT_PEC)
-
-       u32     reserved2[3];
-
-       /* BMCSR: offset 0x30 */
-       u32     bmcsr; /* Bus Moniter Control/Status Register */
-#define BMCSR_HOST_SPD_TYP     (3<<9)
-#define BMCSR_VBUS_OFF         (1<<4)
-#define BMCSR_INT_POLARITY     (1<<3)
-
-       /* BMISR: offset 0x34 */
-       u32     bmisr; /* Bus Moniter Interrupt Status Register*/
-#define BMISR_OVC              (1<<1)
-
-       /* BMIER: offset 0x38 */
-       u32     bmier; /* Bus Moniter Interrupt Enable Register */
-#define BMIER_OVC_EN           (1<<1)
-#define BMIER_VBUS_ERR_EN      (1<<0)
-};
-
-/*-------------------------------------------------------------------------*/
-
-#define        QTD_NEXT(fusbh200, dma) cpu_to_hc32(fusbh200, (u32)dma)
-
-/*
- * EHCI Specification 0.95 Section 3.5
- * QTD: describe data transfer components (buffer, direction, ...)
- * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram".
- *
- * These are associated only with "QH" (Queue Head) structures,
- * used with control, bulk, and interrupt transfers.
- */
-struct fusbh200_qtd {
-       /* first part defined by EHCI spec */
-       __hc32                  hw_next;        /* see EHCI 3.5.1 */
-       __hc32                  hw_alt_next;    /* see EHCI 3.5.2 */
-       __hc32                  hw_token;       /* see EHCI 3.5.3 */
-#define        QTD_TOGGLE      (1 << 31)       /* data toggle */
-#define        QTD_LENGTH(tok) (((tok)>>16) & 0x7fff)
-#define        QTD_IOC         (1 << 15)       /* interrupt on complete */
-#define        QTD_CERR(tok)   (((tok)>>10) & 0x3)
-#define        QTD_PID(tok)    (((tok)>>8) & 0x3)
-#define        QTD_STS_ACTIVE  (1 << 7)        /* HC may execute this */
-#define        QTD_STS_HALT    (1 << 6)        /* halted on error */
-#define        QTD_STS_DBE     (1 << 5)        /* data buffer error (in HC) */
-#define        QTD_STS_BABBLE  (1 << 4)        /* device was babbling (qtd halted) */
-#define        QTD_STS_XACT    (1 << 3)        /* device gave illegal response */
-#define        QTD_STS_MMF     (1 << 2)        /* incomplete split transaction */
-#define        QTD_STS_STS     (1 << 1)        /* split transaction state */
-#define        QTD_STS_PING    (1 << 0)        /* issue PING? */
-
-#define ACTIVE_BIT(fusbh200)   cpu_to_hc32(fusbh200, QTD_STS_ACTIVE)
-#define HALT_BIT(fusbh200)             cpu_to_hc32(fusbh200, QTD_STS_HALT)
-#define STATUS_BIT(fusbh200)   cpu_to_hc32(fusbh200, QTD_STS_STS)
-
-       __hc32                  hw_buf [5];        /* see EHCI 3.5.4 */
-       __hc32                  hw_buf_hi [5];        /* Appendix B */
-
-       /* the rest is HCD-private */
-       dma_addr_t              qtd_dma;                /* qtd address */
-       struct list_head        qtd_list;               /* sw qtd list */
-       struct urb              *urb;                   /* qtd's urb */
-       size_t                  length;                 /* length of buffer */
-} __attribute__ ((aligned (32)));
-
-/* mask NakCnt+T in qh->hw_alt_next */
-#define QTD_MASK(fusbh200)     cpu_to_hc32 (fusbh200, ~0x1f)
-
-#define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1)
-
-/*-------------------------------------------------------------------------*/
-
-/* type tag from {qh,itd,fstn}->hw_next */
-#define Q_NEXT_TYPE(fusbh200,dma)      ((dma) & cpu_to_hc32(fusbh200, 3 << 1))
-
-/*
- * Now the following defines are not converted using the
- * cpu_to_le32() macro anymore, since we have to support
- * "dynamic" switching between be and le support, so that the driver
- * can be used on one system with SoC EHCI controller using big-endian
- * descriptors as well as a normal little-endian PCI EHCI controller.
- */
-/* values for that type tag */
-#define Q_TYPE_ITD     (0 << 1)
-#define Q_TYPE_QH      (1 << 1)
-#define Q_TYPE_SITD    (2 << 1)
-#define Q_TYPE_FSTN    (3 << 1)
-
-/* next async queue entry, or pointer to interrupt/periodic QH */
-#define QH_NEXT(fusbh200,dma)  (cpu_to_hc32(fusbh200, (((u32)dma)&~0x01f)|Q_TYPE_QH))
-
-/* for periodic/async schedules and qtd lists, mark end of list */
-#define FUSBH200_LIST_END(fusbh200)    cpu_to_hc32(fusbh200, 1) /* "null pointer" to hw */
-
-/*
- * Entries in periodic shadow table are pointers to one of four kinds
- * of data structure.  That's dictated by the hardware; a type tag is
- * encoded in the low bits of the hardware's periodic schedule.  Use
- * Q_NEXT_TYPE to get the tag.
- *
- * For entries in the async schedule, the type tag always says "qh".
- */
-union fusbh200_shadow {
-       struct fusbh200_qh      *qh;            /* Q_TYPE_QH */
-       struct fusbh200_itd     *itd;           /* Q_TYPE_ITD */
-       struct fusbh200_fstn    *fstn;          /* Q_TYPE_FSTN */
-       __hc32                  *hw_next;       /* (all types) */
-       void                    *ptr;
-};
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * EHCI Specification 0.95 Section 3.6
- * QH: describes control/bulk/interrupt endpoints
- * See Fig 3-7 "Queue Head Structure Layout".
- *
- * These appear in both the async and (for interrupt) periodic schedules.
- */
-
-/* first part defined by EHCI spec */
-struct fusbh200_qh_hw {
-       __hc32                  hw_next;        /* see EHCI 3.6.1 */
-       __hc32                  hw_info1;       /* see EHCI 3.6.2 */
-#define        QH_CONTROL_EP   (1 << 27)       /* FS/LS control endpoint */
-#define        QH_HEAD         (1 << 15)       /* Head of async reclamation list */
-#define        QH_TOGGLE_CTL   (1 << 14)       /* Data toggle control */
-#define        QH_HIGH_SPEED   (2 << 12)       /* Endpoint speed */
-#define        QH_LOW_SPEED    (1 << 12)
-#define        QH_FULL_SPEED   (0 << 12)
-#define        QH_INACTIVATE   (1 << 7)        /* Inactivate on next transaction */
-       __hc32                  hw_info2;        /* see EHCI 3.6.2 */
-#define        QH_SMASK        0x000000ff
-#define        QH_CMASK        0x0000ff00
-#define        QH_HUBADDR      0x007f0000
-#define        QH_HUBPORT      0x3f800000
-#define        QH_MULT         0xc0000000
-       __hc32                  hw_current;     /* qtd list - see EHCI 3.6.4 */
-
-       /* qtd overlay (hardware parts of a struct fusbh200_qtd) */
-       __hc32                  hw_qtd_next;
-       __hc32                  hw_alt_next;
-       __hc32                  hw_token;
-       __hc32                  hw_buf [5];
-       __hc32                  hw_buf_hi [5];
-} __attribute__ ((aligned(32)));
-
-struct fusbh200_qh {
-       struct fusbh200_qh_hw   *hw;            /* Must come first */
-       /* the rest is HCD-private */
-       dma_addr_t              qh_dma;         /* address of qh */
-       union fusbh200_shadow   qh_next;        /* ptr to qh; or periodic */
-       struct list_head        qtd_list;       /* sw qtd list */
-       struct list_head        intr_node;      /* list of intr QHs */
-       struct fusbh200_qtd             *dummy;
-       struct fusbh200_qh              *unlink_next;   /* next on unlink list */
-
-       unsigned                unlink_cycle;
-
-       u8                      needs_rescan;   /* Dequeue during giveback */
-       u8                      qh_state;
-#define        QH_STATE_LINKED         1               /* HC sees this */
-#define        QH_STATE_UNLINK         2               /* HC may still see this */
-#define        QH_STATE_IDLE           3               /* HC doesn't see this */
-#define        QH_STATE_UNLINK_WAIT    4               /* LINKED and on unlink q */
-#define        QH_STATE_COMPLETING     5               /* don't touch token.HALT */
-
-       u8                      xacterrs;       /* XactErr retry counter */
-#define        QH_XACTERR_MAX          32              /* XactErr retry limit */
-
-       /* periodic schedule info */
-       u8                      usecs;          /* intr bandwidth */
-       u8                      gap_uf;         /* uframes split/csplit gap */
-       u8                      c_usecs;        /* ... split completion bw */
-       u16                     tt_usecs;       /* tt downstream bandwidth */
-       unsigned short          period;         /* polling interval */
-       unsigned short          start;          /* where polling starts */
-#define NO_FRAME ((unsigned short)~0)                  /* pick new start */
-
-       struct usb_device       *dev;           /* access to TT */
-       unsigned                is_out:1;       /* bulk or intr OUT */
-       unsigned                clearing_tt:1;  /* Clear-TT-Buf in progress */
-};
-
-/*-------------------------------------------------------------------------*/
-
-/* description of one iso transaction (up to 3 KB data if highspeed) */
-struct fusbh200_iso_packet {
-       /* These will be copied to iTD when scheduling */
-       u64                     bufp;           /* itd->hw_bufp{,_hi}[pg] |= */
-       __hc32                  transaction;    /* itd->hw_transaction[i] |= */
-       u8                      cross;          /* buf crosses pages */
-       /* for full speed OUT splits */
-       u32                     buf1;
-};
-
-/* temporary schedule data for packets from iso urbs (both speeds)
- * each packet is one logical usb transaction to the device (not TT),
- * beginning at stream->next_uframe
- */
-struct fusbh200_iso_sched {
-       struct list_head        td_list;
-       unsigned                span;
-       struct fusbh200_iso_packet      packet [0];
-};
-
-/*
- * fusbh200_iso_stream - groups all (s)itds for this endpoint.
- * acts like a qh would, if EHCI had them for ISO.
- */
-struct fusbh200_iso_stream {
-       /* first field matches fusbh200_hq, but is NULL */
-       struct fusbh200_qh_hw   *hw;
-
-       u8                      bEndpointAddress;
-       u8                      highspeed;
-       struct list_head        td_list;        /* queued itds */
-       struct list_head        free_list;      /* list of unused itds */
-       struct usb_device       *udev;
-       struct usb_host_endpoint *ep;
-
-       /* output of (re)scheduling */
-       int                     next_uframe;
-       __hc32                  splits;
-
-       /* the rest is derived from the endpoint descriptor,
-        * trusting urb->interval == f(epdesc->bInterval) and
-        * including the extra info for hw_bufp[0..2]
-        */
-       u8                      usecs, c_usecs;
-       u16                     interval;
-       u16                     tt_usecs;
-       u16                     maxp;
-       u16                     raw_mask;
-       unsigned                bandwidth;
-
-       /* This is used to initialize iTD's hw_bufp fields */
-       __hc32                  buf0;
-       __hc32                  buf1;
-       __hc32                  buf2;
-
-       /* this is used to initialize sITD's tt info */
-       __hc32                  address;
-};
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * EHCI Specification 0.95 Section 3.3
- * Fig 3-4 "Isochronous Transaction Descriptor (iTD)"
- *
- * Schedule records for high speed iso xfers
- */
-struct fusbh200_itd {
-       /* first part defined by EHCI spec */
-       __hc32                  hw_next;           /* see EHCI 3.3.1 */
-       __hc32                  hw_transaction [8]; /* see EHCI 3.3.2 */
-#define FUSBH200_ISOC_ACTIVE        (1<<31)        /* activate transfer this slot */
-#define FUSBH200_ISOC_BUF_ERR       (1<<30)        /* Data buffer error */
-#define FUSBH200_ISOC_BABBLE        (1<<29)        /* babble detected */
-#define FUSBH200_ISOC_XACTERR       (1<<28)        /* XactErr - transaction error */
-#define        FUSBH200_ITD_LENGTH(tok)        (((tok)>>16) & 0x0fff)
-#define        FUSBH200_ITD_IOC                (1 << 15)       /* interrupt on complete */
-
-#define ITD_ACTIVE(fusbh200)   cpu_to_hc32(fusbh200, FUSBH200_ISOC_ACTIVE)
-
-       __hc32                  hw_bufp [7];    /* see EHCI 3.3.3 */
-       __hc32                  hw_bufp_hi [7]; /* Appendix B */
-
-       /* the rest is HCD-private */
-       dma_addr_t              itd_dma;        /* for this itd */
-       union fusbh200_shadow   itd_next;       /* ptr to periodic q entry */
-
-       struct urb              *urb;
-       struct fusbh200_iso_stream      *stream;        /* endpoint's queue */
-       struct list_head        itd_list;       /* list of stream's itds */
-
-       /* any/all hw_transactions here may be used by that urb */
-       unsigned                frame;          /* where scheduled */
-       unsigned                pg;
-       unsigned                index[8];       /* in urb->iso_frame_desc */
-} __attribute__ ((aligned (32)));
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * EHCI Specification 0.96 Section 3.7
- * Periodic Frame Span Traversal Node (FSTN)
- *
- * Manages split interrupt transactions (using TT) that span frame boundaries
- * into uframes 0/1; see 4.12.2.2.  In those uframes, a "save place" FSTN
- * makes the HC jump (back) to a QH to scan for fs/ls QH completions until
- * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work.
- */
-struct fusbh200_fstn {
-       __hc32                  hw_next;        /* any periodic q entry */
-       __hc32                  hw_prev;        /* qh or FUSBH200_LIST_END */
-
-       /* the rest is HCD-private */
-       dma_addr_t              fstn_dma;
-       union fusbh200_shadow   fstn_next;      /* ptr to periodic q entry */
-} __attribute__ ((aligned (32)));
-
-/*-------------------------------------------------------------------------*/
-
-/* Prepare the PORTSC wakeup flags during controller suspend/resume */
-
-#define fusbh200_prepare_ports_for_controller_suspend(fusbh200, do_wakeup)     \
-               fusbh200_adjust_port_wakeup_flags(fusbh200, true, do_wakeup);
-
-#define fusbh200_prepare_ports_for_controller_resume(fusbh200)                 \
-               fusbh200_adjust_port_wakeup_flags(fusbh200, false, false);
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Some EHCI controllers have a Transaction Translator built into the
- * root hub. This is a non-standard feature.  Each controller will need
- * to add code to the following inline functions, and call them as
- * needed (mostly in root hub code).
- */
-
-static inline unsigned int
-fusbh200_get_speed(struct fusbh200_hcd *fusbh200, unsigned int portsc)
-{
-       return (readl(&fusbh200->regs->bmcsr)
-               & BMCSR_HOST_SPD_TYP) >> 9;
-}
-
-/* Returns the speed of a device attached to a port on the root hub. */
-static inline unsigned int
-fusbh200_port_speed(struct fusbh200_hcd *fusbh200, unsigned int portsc)
-{
-       switch (fusbh200_get_speed(fusbh200, portsc)) {
-       case 0:
-               return 0;
-       case 1:
-               return USB_PORT_STAT_LOW_SPEED;
-       case 2:
-       default:
-               return USB_PORT_STAT_HIGH_SPEED;
-       }
-}
-
-/*-------------------------------------------------------------------------*/
-
-#define        fusbh200_has_fsl_portno_bug(e)          (0)
-
-/*
- * While most USB host controllers implement their registers in
- * little-endian format, a minority (celleb companion chip) implement
- * them in big endian format.
- *
- * This attempts to support either format at compile time without a
- * runtime penalty, or both formats with the additional overhead
- * of checking a flag bit.
- *
- */
-
-#define fusbh200_big_endian_mmio(e)    0
-#define fusbh200_big_endian_capbase(e) 0
-
-static inline unsigned int fusbh200_readl(const struct fusbh200_hcd *fusbh200,
-               __u32 __iomem * regs)
-{
-       return readl(regs);
-}
-
-static inline void fusbh200_writel(const struct fusbh200_hcd *fusbh200,
-               const unsigned int val, __u32 __iomem *regs)
-{
-       writel(val, regs);
-}
-
-/* cpu to fusbh200 */
-static inline __hc32 cpu_to_hc32 (const struct fusbh200_hcd *fusbh200, const u32 x)
-{
-       return cpu_to_le32(x);
-}
-
-/* fusbh200 to cpu */
-static inline u32 hc32_to_cpu (const struct fusbh200_hcd *fusbh200, const __hc32 x)
-{
-       return le32_to_cpu(x);
-}
-
-static inline u32 hc32_to_cpup (const struct fusbh200_hcd *fusbh200, const __hc32 *x)
-{
-       return le32_to_cpup(x);
-}
-
-/*-------------------------------------------------------------------------*/
-
-static inline unsigned fusbh200_read_frame_index(struct fusbh200_hcd *fusbh200)
-{
-       return fusbh200_readl(fusbh200, &fusbh200->regs->frame_index);
-}
-
-#define fusbh200_itdlen(urb, desc, t) ({                       \
-       usb_pipein((urb)->pipe) ?                               \
-       (desc)->length - FUSBH200_ITD_LENGTH(t) :                       \
-       FUSBH200_ITD_LENGTH(t);                                 \
-})
-/*-------------------------------------------------------------------------*/
-
-#endif /* __LINUX_FUSBH200_H */
index d9f0481d7258aaa16b78f381518fe697af1e22a8..cfa94275c52c24d668cde3833e3694162ce52f9f 100644 (file)
@@ -203,7 +203,7 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
                goto fail_disable;
        }
 
-       ret = clk_enable(usb_pll_clk);
+       ret = clk_prepare_enable(usb_pll_clk);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to start USB PLL\n");
                goto fail_disable;
@@ -223,7 +223,7 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
                goto fail_rate;
        }
 
-       ret = clk_enable(usb_dev_clk);
+       ret = clk_prepare_enable(usb_dev_clk);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to start USB DEV Clock\n");
                goto fail_rate;
@@ -239,7 +239,7 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
 
        __raw_writel(__raw_readl(USB_CTRL) | USB_HOST_NEED_CLK_EN, USB_CTRL);
 
-       ret = clk_enable(usb_otg_clk);
+       ret = clk_prepare_enable(usb_otg_clk);
        if (ret < 0) {
                dev_err(&pdev->dev, "failed to start USB DEV Clock\n");
                goto fail_otg;
@@ -283,11 +283,11 @@ static int ohci_hcd_nxp_probe(struct platform_device *pdev)
 fail_resource:
        usb_put_hcd(hcd);
 fail_hcd:
-       clk_disable(usb_otg_clk);
+       clk_disable_unprepare(usb_otg_clk);
 fail_otg:
-       clk_disable(usb_dev_clk);
+       clk_disable_unprepare(usb_dev_clk);
 fail_rate:
-       clk_disable(usb_pll_clk);
+       clk_disable_unprepare(usb_pll_clk);
 fail_disable:
        isp1301_i2c_client = NULL;
        return ret;
@@ -300,9 +300,9 @@ static int ohci_hcd_nxp_remove(struct platform_device *pdev)
        usb_remove_hcd(hcd);
        ohci_nxp_stop_hc();
        usb_put_hcd(hcd);
-       clk_disable(usb_pll_clk);
-       clk_disable(usb_dev_clk);
-       i2c_unregister_device(isp1301_i2c_client);
+       clk_disable_unprepare(usb_otg_clk);
+       clk_disable_unprepare(usb_dev_clk);
+       clk_disable_unprepare(usb_pll_clk);
        isp1301_i2c_client = NULL;
 
        return 0;
index 707437c88d03e578379ab2bab66cec2012a86202..56478ed2f932fc4dc74d32d156a643f90672c31a 100644 (file)
@@ -161,6 +161,7 @@ static const struct of_device_id spear_ohci_id_table[] = {
        { .compatible = "st,spear600-ohci", },
        { },
 };
+MODULE_DEVICE_TABLE(of, spear_ohci_id_table);
 
 /* Driver definition to register with the platform bus */
 static struct platform_driver spear_ohci_hcd_driver = {
index a67bd509033097cfc156f84605f43f3617b951d8..0a94895a358d47e8e51cf32722afbdce0d6104d9 100644 (file)
@@ -2245,8 +2245,7 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
        struct u132 *u132 = hcd_to_u132(hcd);
        if (irqs_disabled()) {
                if (__GFP_WAIT & mem_flags) {
-                       printk(KERN_ERR "invalid context for function that migh"
-                               "t sleep\n");
+                       printk(KERN_ERR "invalid context for function that might sleep\n");
                        return -EINVAL;
                }
        }
index 3a3e3eeba291882b03484d6048a508194d57d82e..32a6f3d8deecf54abd4deaaa330bcd44f752cc11 100644 (file)
@@ -140,6 +140,7 @@ static const struct of_device_id platform_uhci_ids[] = {
        { .compatible = "platform-uhci", },
        {}
 };
+MODULE_DEVICE_TABLE(of, platform_uhci_ids);
 
 static struct platform_driver uhci_platform_driver = {
        .probe          = uhci_hcd_platform_probe,
index d3e13b640d4ba28493f27ca99fc26cfd3677981f..e36372393bb1f8719293a3cc979c95c075277e85 100644 (file)
@@ -175,8 +175,7 @@ void whc_clean_up(struct whc *whc)
        pzl_clean_up(whc);
        asl_clean_up(whc);
 
-       if (whc->qset_pool)
-               dma_pool_destroy(whc->qset_pool);
+       dma_pool_destroy(whc->qset_pool);
 
        len   = resource_size(&whc->umc->resource);
        if (whc->base)
index 2d16faefb429b03a529304136c1eaf19deb15572..74c42f7226780b4c6a4924489f711d27a1b90f37 100644 (file)
@@ -58,16 +58,17 @@ void xhci_dbg_regs(struct xhci_hcd *xhci)
 static void xhci_print_cap_regs(struct xhci_hcd *xhci)
 {
        u32 temp;
+       u32 hci_version;
 
        xhci_dbg(xhci, "xHCI capability registers at %p:\n", xhci->cap_regs);
 
        temp = readl(&xhci->cap_regs->hc_capbase);
+       hci_version = HC_VERSION(temp);
        xhci_dbg(xhci, "CAPLENGTH AND HCIVERSION 0x%x:\n",
                        (unsigned int) temp);
        xhci_dbg(xhci, "CAPLENGTH: 0x%x\n",
                        (unsigned int) HC_LENGTH(temp));
-       xhci_dbg(xhci, "HCIVERSION: 0x%x\n",
-                       (unsigned int) HC_VERSION(temp));
+       xhci_dbg(xhci, "HCIVERSION: 0x%x\n", hci_version);
 
        temp = readl(&xhci->cap_regs->hcs_params1);
        xhci_dbg(xhci, "HCSPARAMS 1: 0x%x\n",
@@ -108,6 +109,18 @@ static void xhci_print_cap_regs(struct xhci_hcd *xhci)
 
        temp = readl(&xhci->cap_regs->run_regs_off);
        xhci_dbg(xhci, "RTSOFF 0x%x:\n", temp & RTSOFF_MASK);
+
+       /* xhci 1.1 controllers have the HCCPARAMS2 register */
+       if (hci_version > 100) {
+               temp = readl(&xhci->cap_regs->hcc_params2);
+               xhci_dbg(xhci, "HCC PARAMS2 0x%x:\n", (unsigned int) temp);
+               xhci_dbg(xhci, "  HC %s Force save context capability",
+                        HCC2_FSC(temp) ? "supports" : "doesn't support");
+               xhci_dbg(xhci, "  HC %s Large ESIT Payload Capability",
+                        HCC2_LEC(temp) ? "supports" : "doesn't support");
+               xhci_dbg(xhci, "  HC %s Extended TBC capability",
+                        HCC2_ETC(temp) ? "supports" : "doesn't support");
+       }
 }
 
 static void xhci_print_command_reg(struct xhci_hcd *xhci)
index 78241b5550df877fb09189936867f7821e09d11a..5d2d7e954bd4cb8dbaa51ec1121e236e8f472dce 100644 (file)
 #define        PORT_RWC_BITS   (PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \
                         PORT_RC | PORT_PLC | PORT_PE)
 
-/* USB 3.0 BOS descriptor and a capability descriptor, combined */
+/* USB 3 BOS descriptor and a capability descriptors, combined.
+ * Fields will be adjusted and added later in xhci_create_usb3_bos_desc()
+ */
 static u8 usb_bos_descriptor [] = {
        USB_DT_BOS_SIZE,                /*  __u8 bLength, 5 bytes */
        USB_DT_BOS,                     /*  __u8 bDescriptorType */
        0x0F, 0x00,                     /*  __le16 wTotalLength, 15 bytes */
        0x1,                            /*  __u8 bNumDeviceCaps */
-       /* First device capability */
+       /* First device capability, SuperSpeed */
        USB_DT_USB_SS_CAP_SIZE,         /*  __u8 bLength, 10 bytes */
        USB_DT_DEVICE_CAPABILITY,       /* Device Capability */
        USB_SS_CAP_TYPE,                /* bDevCapabilityType, SUPERSPEED_USB */
@@ -46,9 +48,108 @@ static u8 usb_bos_descriptor [] = {
        0x03,                           /* bFunctionalitySupport,
                                           USB 3.0 speed only */
        0x00,                           /* bU1DevExitLat, set later. */
-       0x00, 0x00                      /* __le16 bU2DevExitLat, set later. */
+       0x00, 0x00,                     /* __le16 bU2DevExitLat, set later. */
+       /* Second device capability, SuperSpeedPlus */
+       0x0c,                           /* bLength 12, will be adjusted later */
+       USB_DT_DEVICE_CAPABILITY,       /* Device Capability */
+       USB_SSP_CAP_TYPE,               /* bDevCapabilityType SUPERSPEED_PLUS */
+       0x00,                           /* bReserved 0 */
+       0x00, 0x00, 0x00, 0x00,         /* bmAttributes, get from xhci psic */
+       0x00, 0x00,                     /* wFunctionalitySupport */
+       0x00, 0x00,                     /* wReserved 0 */
+       /* Sublink Speed Attributes are added in xhci_create_usb3_bos_desc() */
 };
 
+static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
+                                    u16 wLength)
+{
+       int i, ssa_count;
+       u32 temp;
+       u16 desc_size, ssp_cap_size, ssa_size = 0;
+       bool usb3_1 = false;
+
+       desc_size = USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE;
+       ssp_cap_size = sizeof(usb_bos_descriptor) - desc_size;
+
+       /* does xhci support USB 3.1 Enhanced SuperSpeed */
+       if (xhci->usb3_rhub.min_rev >= 0x01 && xhci->usb3_rhub.psi_uid_count) {
+               /* two SSA entries for each unique PSI ID, one RX and one TX */
+               ssa_count = xhci->usb3_rhub.psi_uid_count * 2;
+               ssa_size = ssa_count * sizeof(u32);
+               desc_size += ssp_cap_size;
+               usb3_1 = true;
+       }
+       memcpy(buf, &usb_bos_descriptor, min(desc_size, wLength));
+
+       if (usb3_1) {
+               /* modify bos descriptor bNumDeviceCaps and wTotalLength */
+               buf[4] += 1;
+               put_unaligned_le16(desc_size + ssa_size, &buf[2]);
+       }
+
+       if (wLength < USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE)
+               return wLength;
+
+       /* Indicate whether the host has LTM support. */
+       temp = readl(&xhci->cap_regs->hcc_params);
+       if (HCC_LTC(temp))
+               buf[8] |= USB_LTM_SUPPORT;
+
+       /* Set the U1 and U2 exit latencies. */
+       if ((xhci->quirks & XHCI_LPM_SUPPORT)) {
+               temp = readl(&xhci->cap_regs->hcs_params3);
+               buf[12] = HCS_U1_LATENCY(temp);
+               put_unaligned_le16(HCS_U2_LATENCY(temp), &buf[13]);
+       }
+
+       if (usb3_1) {
+               u32 ssp_cap_base, bm_attrib, psi;
+               int offset;
+
+               ssp_cap_base = USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE;
+
+               if (wLength < desc_size)
+                       return wLength;
+               buf[ssp_cap_base] = ssp_cap_size + ssa_size;
+
+               /* attribute count SSAC bits 4:0 and ID count SSIC bits 8:5 */
+               bm_attrib = (ssa_count - 1) & 0x1f;
+               bm_attrib |= (xhci->usb3_rhub.psi_uid_count - 1) << 5;
+               put_unaligned_le32(bm_attrib, &buf[ssp_cap_base + 4]);
+
+               if (wLength < desc_size + ssa_size)
+                       return wLength;
+               /*
+                * Create the Sublink Speed Attributes (SSA) array.
+                * The xhci PSI field and USB 3.1 SSA fields are very similar,
+                * but link type bits 7:6 differ for values 01b and 10b.
+                * xhci has also only one PSI entry for a symmetric link when
+                * USB 3.1 requires two SSA entries (RX and TX) for every link
+                */
+               offset = desc_size;
+               for (i = 0; i < xhci->usb3_rhub.psi_count; i++) {
+                       psi = xhci->usb3_rhub.psi[i];
+                       psi &= ~USB_SSP_SUBLINK_SPEED_RSVD;
+                       if ((psi & PLT_MASK) == PLT_SYM) {
+                       /* Symmetric, create SSA RX and TX from one PSI entry */
+                               put_unaligned_le32(psi, &buf[offset]);
+                               psi |= 1 << 7;  /* turn entry to TX */
+                               offset += 4;
+                               if (offset >= desc_size + ssa_size)
+                                       return desc_size + ssa_size;
+                       } else if ((psi & PLT_MASK) == PLT_ASYM_RX) {
+                               /* Asymetric RX, flip bits 7:6 for SSA */
+                               psi ^= PLT_MASK;
+                       }
+                       put_unaligned_le32(psi, &buf[offset]);
+                       offset += 4;
+                       if (offset >= desc_size + ssa_size)
+                               return desc_size + ssa_size;
+               }
+       }
+       /* ssa_size is 0 for other than usb 3.1 hosts */
+       return desc_size + ssa_size;
+}
 
 static void xhci_common_hub_descriptor(struct xhci_hcd *xhci,
                struct usb_hub_descriptor *desc, int ports)
@@ -161,7 +262,7 @@ static void xhci_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
                struct usb_hub_descriptor *desc)
 {
 
-       if (hcd->speed == HCD_USB3)
+       if (hcd->speed >= HCD_USB3)
                xhci_usb3_hub_descriptor(hcd, xhci, desc);
        else
                xhci_usb2_hub_descriptor(hcd, xhci, desc);
@@ -250,7 +351,7 @@ int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
                if (!xhci->devs[i])
                        continue;
                speed = xhci->devs[i]->udev->speed;
-               if (((speed == USB_SPEED_SUPER) == (hcd->speed == HCD_USB3))
+               if (((speed >= USB_SPEED_SUPER) == (hcd->speed >= HCD_USB3))
                                && xhci->devs[i]->fake_port == port) {
                        slot_id = i;
                        break;
@@ -339,7 +440,7 @@ static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
                u16 wIndex, __le32 __iomem *addr, u32 port_status)
 {
        /* Don't allow the USB core to disable SuperSpeed ports. */
-       if (hcd->speed == HCD_USB3) {
+       if (hcd->speed >= HCD_USB3) {
                xhci_dbg(xhci, "Ignoring request to disable "
                                "SuperSpeed port.\n");
                return;
@@ -407,7 +508,7 @@ static int xhci_get_ports(struct usb_hcd *hcd, __le32 __iomem ***port_array)
        int max_ports;
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 
-       if (hcd->speed == HCD_USB3) {
+       if (hcd->speed >= HCD_USB3) {
                max_ports = xhci->num_usb3_ports;
                *port_array = xhci->usb3_ports;
        } else {
@@ -558,6 +659,22 @@ static void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status,
        }
 }
 
+static u32 xhci_get_ext_port_status(u32 raw_port_status, u32 port_li)
+{
+       u32 ext_stat = 0;
+       int speed_id;
+
+       /* only support rx and tx lane counts of 1 in usb3.1 spec */
+       speed_id = DEV_PORT_SPEED(raw_port_status);
+       ext_stat |= speed_id;           /* bits 3:0, RX speed id */
+       ext_stat |= speed_id << 4;      /* bits 7:4, TX speed id */
+
+       ext_stat |= PORT_RX_LANES(port_li) << 8;  /* bits 11:8 Rx lane count */
+       ext_stat |= PORT_TX_LANES(port_li) << 12; /* bits 15:12 Tx lane count */
+
+       return ext_stat;
+}
+
 /*
  * Converts a raw xHCI port status into the format that external USB 2.0 or USB
  * 3.0 hubs use.
@@ -590,7 +707,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
        if ((raw_port_status & PORT_RC))
                status |= USB_PORT_STAT_C_RESET << 16;
        /* USB3.0 only */
-       if (hcd->speed == HCD_USB3) {
+       if (hcd->speed >= HCD_USB3) {
                /* Port link change with port in resume state should not be
                 * reported to usbcore, as this is an internal state to be
                 * handled by xhci driver. Reporting PLC to usbcore may
@@ -606,13 +723,13 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
                        status |= USB_PORT_STAT_C_CONFIG_ERROR << 16;
        }
 
-       if (hcd->speed != HCD_USB3) {
+       if (hcd->speed < HCD_USB3) {
                if ((raw_port_status & PORT_PLS_MASK) == XDEV_U3
                                && (raw_port_status & PORT_POWER))
                        status |= USB_PORT_STAT_SUSPEND;
        }
        if ((raw_port_status & PORT_PLS_MASK) == XDEV_RESUME &&
-                       !DEV_SUPERSPEED(raw_port_status)) {
+               !DEV_SUPERSPEED_ANY(raw_port_status)) {
                if ((raw_port_status & PORT_RESET) ||
                                !(raw_port_status & PORT_PE))
                        return 0xffffffff;
@@ -669,7 +786,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
                        && (raw_port_status & PORT_POWER)
                        && (bus_state->suspended_ports & (1 << wIndex))) {
                bus_state->suspended_ports &= ~(1 << wIndex);
-               if (hcd->speed != HCD_USB3)
+               if (hcd->speed < HCD_USB3)
                        bus_state->port_c_suspend |= 1 << wIndex;
        }
        if (raw_port_status & PORT_CONNECT) {
@@ -683,13 +800,13 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
        if (raw_port_status & PORT_RESET)
                status |= USB_PORT_STAT_RESET;
        if (raw_port_status & PORT_POWER) {
-               if (hcd->speed == HCD_USB3)
+               if (hcd->speed >= HCD_USB3)
                        status |= USB_SS_PORT_STAT_POWER;
                else
                        status |= USB_PORT_STAT_POWER;
        }
        /* Update Port Link State */
-       if (hcd->speed == HCD_USB3) {
+       if (hcd->speed >= HCD_USB3) {
                xhci_hub_report_usb3_link_state(xhci, &status, raw_port_status);
                /*
                 * Verify if all USB3 Ports Have entered U0 already.
@@ -734,7 +851,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                 * descriptor for the USB 3.0 roothub.  If not, we stall the
                 * endpoint, like external hubs do.
                 */
-               if (hcd->speed == HCD_USB3 &&
+               if (hcd->speed >= HCD_USB3 &&
                                (wLength < USB_DT_SS_HUB_SIZE ||
                                 wValue != (USB_DT_SS_HUB << 8))) {
                        xhci_dbg(xhci, "Wrong hub descriptor type for "
@@ -748,25 +865,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                if ((wValue & 0xff00) != (USB_DT_BOS << 8))
                        goto error;
 
-               if (hcd->speed != HCD_USB3)
+               if (hcd->speed < HCD_USB3)
                        goto error;
 
-               /* Set the U1 and U2 exit latencies. */
-               memcpy(buf, &usb_bos_descriptor,
-                               USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE);
-               if ((xhci->quirks & XHCI_LPM_SUPPORT)) {
-                       temp = readl(&xhci->cap_regs->hcs_params3);
-                       buf[12] = HCS_U1_LATENCY(temp);
-                       put_unaligned_le16(HCS_U2_LATENCY(temp), &buf[13]);
-               }
-
-               /* Indicate whether the host has LTM support. */
-               temp = readl(&xhci->cap_regs->hcc_params);
-               if (HCC_LTC(temp))
-                       buf[8] |= USB_LTM_SUPPORT;
-
+               retval = xhci_create_usb3_bos_desc(xhci, buf, wLength);
                spin_unlock_irqrestore(&xhci->lock, flags);
-               return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE;
+               return retval;
        case GetPortStatus:
                if (!wIndex || wIndex > max_ports)
                        goto error;
@@ -786,6 +890,19 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
 
                put_unaligned(cpu_to_le32(status), (__le32 *) buf);
+               /* if USB 3.1 extended port status return additional 4 bytes */
+               if (wValue == 0x02) {
+                       u32 port_li;
+
+                       if (hcd->speed < HCD_USB31 || wLength != 8) {
+                               xhci_err(xhci, "get ext port status invalid parameter\n");
+                               retval = -EINVAL;
+                               break;
+                       }
+                       port_li = readl(port_array[wIndex] + PORTLI);
+                       status = xhci_get_ext_port_status(temp, port_li);
+                       put_unaligned_le32(cpu_to_le32(status), &buf[4]);
+               }
                break;
        case SetPortFeature:
                if (wValue == USB_PORT_FEAT_LINK_STATE)
@@ -952,7 +1069,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        temp = readl(port_array[wIndex]);
                        break;
                case USB_PORT_FEAT_U1_TIMEOUT:
-                       if (hcd->speed != HCD_USB3)
+                       if (hcd->speed < HCD_USB3)
                                goto error;
                        temp = readl(port_array[wIndex] + PORTPMSC);
                        temp &= ~PORT_U1_TIMEOUT_MASK;
@@ -960,7 +1077,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        writel(temp, port_array[wIndex] + PORTPMSC);
                        break;
                case USB_PORT_FEAT_U2_TIMEOUT:
-                       if (hcd->speed != HCD_USB3)
+                       if (hcd->speed < HCD_USB3)
                                goto error;
                        temp = readl(port_array[wIndex] + PORTPMSC);
                        temp &= ~PORT_U2_TIMEOUT_MASK;
@@ -1223,14 +1340,14 @@ int xhci_bus_resume(struct usb_hcd *hcd)
                u32 temp;
 
                temp = readl(port_array[port_index]);
-               if (DEV_SUPERSPEED(temp))
+               if (DEV_SUPERSPEED_ANY(temp))
                        temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS);
                else
                        temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
                if (test_bit(port_index, &bus_state->bus_suspended) &&
                    (temp & PORT_PLS_MASK)) {
                        set_bit(port_index, &port_was_suspended);
-                       if (!DEV_SUPERSPEED(temp)) {
+                       if (!DEV_SUPERSPEED_ANY(temp)) {
                                xhci_set_link_state(xhci, port_array,
                                                port_index, XDEV_RESUME);
                                need_usb2_u3_exit = true;
index 41f841fa6c4de6a57edb702c2875e4351a4cbff8..c48cbe731356539abf7df8ac1c94a09701b546f7 100644 (file)
@@ -1828,24 +1828,20 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
        for (i = 1; i < MAX_HC_SLOTS; ++i)
                xhci_free_virt_device(xhci, i);
 
-       if (xhci->segment_pool)
-               dma_pool_destroy(xhci->segment_pool);
+       dma_pool_destroy(xhci->segment_pool);
        xhci->segment_pool = NULL;
        xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed segment pool");
 
-       if (xhci->device_pool)
-               dma_pool_destroy(xhci->device_pool);
+       dma_pool_destroy(xhci->device_pool);
        xhci->device_pool = NULL;
        xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed device context pool");
 
-       if (xhci->small_streams_pool)
-               dma_pool_destroy(xhci->small_streams_pool);
+       dma_pool_destroy(xhci->small_streams_pool);
        xhci->small_streams_pool = NULL;
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "Freed small stream array pool");
 
-       if (xhci->medium_streams_pool)
-               dma_pool_destroy(xhci->medium_streams_pool);
+       dma_pool_destroy(xhci->medium_streams_pool);
        xhci->medium_streams_pool = NULL;
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "Freed medium stream array pool");
@@ -2072,14 +2068,23 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
 {
        u32 temp, port_offset, port_count;
        int i;
+       struct xhci_hub *rhub;
 
-       if (major_revision > 0x03) {
+       temp = readl(addr);
+
+       if (XHCI_EXT_PORT_MAJOR(temp) == 0x03) {
+               rhub = &xhci->usb3_rhub;
+       } else if (XHCI_EXT_PORT_MAJOR(temp) <= 0x02) {
+               rhub = &xhci->usb2_rhub;
+       } else {
                xhci_warn(xhci, "Ignoring unknown port speed, "
                                "Ext Cap %p, revision = 0x%x\n",
                                addr, major_revision);
                /* Ignoring port protocol we can't understand. FIXME */
                return;
        }
+       rhub->maj_rev = XHCI_EXT_PORT_MAJOR(temp);
+       rhub->min_rev = XHCI_EXT_PORT_MINOR(temp);
 
        /* Port offset and count in the third dword, see section 7.2 */
        temp = readl(addr + 2);
@@ -2094,6 +2099,33 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
                /* WTF? "Valid values are â€˜1’ to MaxPorts" */
                return;
 
+       rhub->psi_count = XHCI_EXT_PORT_PSIC(temp);
+       if (rhub->psi_count) {
+               rhub->psi = kcalloc(rhub->psi_count, sizeof(*rhub->psi),
+                                   GFP_KERNEL);
+               if (!rhub->psi)
+                       rhub->psi_count = 0;
+
+               rhub->psi_uid_count++;
+               for (i = 0; i < rhub->psi_count; i++) {
+                       rhub->psi[i] = readl(addr + 4 + i);
+
+                       /* count unique ID values, two consecutive entries can
+                        * have the same ID if link is assymetric
+                        */
+                       if (i && (XHCI_EXT_PORT_PSIV(rhub->psi[i]) !=
+                                 XHCI_EXT_PORT_PSIV(rhub->psi[i - 1])))
+                               rhub->psi_uid_count++;
+
+                       xhci_dbg(xhci, "PSIV:%d PSIE:%d PLT:%d PFD:%d LP:%d PSIM:%d\n",
+                                 XHCI_EXT_PORT_PSIV(rhub->psi[i]),
+                                 XHCI_EXT_PORT_PSIE(rhub->psi[i]),
+                                 XHCI_EXT_PORT_PLT(rhub->psi[i]),
+                                 XHCI_EXT_PORT_PFD(rhub->psi[i]),
+                                 XHCI_EXT_PORT_LP(rhub->psi[i]),
+                                 XHCI_EXT_PORT_PSIM(rhub->psi[i]));
+               }
+       }
        /* cache usb2 port capabilities */
        if (major_revision < 0x03 && xhci->num_ext_caps < max_caps)
                xhci->ext_caps[xhci->num_ext_caps++] = temp;
index c47d3e48058659230e8d48ed342f9c163b08732d..17f6897acde2a5a7674ccff44ddc55f0db192166 100644 (file)
@@ -201,15 +201,17 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
        struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
        int                     retval;
 
+       xhci = hcd_to_xhci(hcd);
+       if (!xhci->sbrn)
+               pci_read_config_byte(pdev, XHCI_SBRN_OFFSET, &xhci->sbrn);
+
        retval = xhci_gen_setup(hcd, xhci_pci_quirks);
        if (retval)
                return retval;
 
-       xhci = hcd_to_xhci(hcd);
        if (!usb_hcd_is_primary_hcd(hcd))
                return 0;
 
-       pci_read_config_byte(pdev, XHCI_SBRN_OFFSET, &xhci->sbrn);
        xhci_dbg(xhci, "Got SBRN %u\n", (unsigned int) xhci->sbrn);
 
        /* Find any debug ports */
index 890ad9d9d32991c7e74b02d9580b5cfbcd4d595e..05647e6753cd833f9b9e87924832be5d3e2c2216 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/usb/phy.h>
 #include <linux/slab.h>
 #include <linux/usb/xhci_pdriver.h>
+#include <linux/acpi.h>
 
 #include "xhci.h"
 #include "xhci-mvebu.h"
@@ -93,14 +94,20 @@ static int xhci_plat_probe(struct platform_device *pdev)
        if (irq < 0)
                return -ENODEV;
 
-       /* Initialize dma_mask and coherent_dma_mask to 32-bits */
-       ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
-       if (ret)
-               return ret;
-       if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+       /* Try to set 64-bit DMA first */
+       if (WARN_ON(!pdev->dev.dma_mask))
+               /* Platform did not initialize dma_mask */
+               ret = dma_coerce_mask_and_coherent(&pdev->dev,
+                                                  DMA_BIT_MASK(64));
        else
-               dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+               ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+
+       /* If seting 64-bit DMA mask fails, fall back to 32-bit DMA mask */
+       if (ret) {
+               ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+               if (ret)
+                       return ret;
+       }
 
        hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
        if (!hcd)
@@ -262,6 +269,13 @@ static const struct of_device_id usb_xhci_of_match[] = {
 MODULE_DEVICE_TABLE(of, usb_xhci_of_match);
 #endif
 
+static const struct acpi_device_id usb_xhci_acpi_match[] = {
+       /* XHCI-compliant USB Controller */
+       { "PNP0D10", },
+       { }
+};
+MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match);
+
 static struct platform_driver usb_xhci_driver = {
        .probe  = xhci_plat_probe,
        .remove = xhci_plat_remove,
@@ -269,6 +283,7 @@ static struct platform_driver usb_xhci_driver = {
                .name = "xhci-hcd",
                .pm = DEV_PM_OPS,
                .of_match_table = of_match_ptr(usb_xhci_of_match),
+               .acpi_match_table = ACPI_PTR(usb_xhci_acpi_match),
        },
 };
 MODULE_ALIAS("platform:xhci-hcd");
index 97ffe39972735109f1ca1f86e003fe2550e4f936..fa836251ca21e4f19c59b3fd37b3b788b7b81008 100644 (file)
@@ -1453,7 +1453,7 @@ static unsigned int find_faked_portnum_from_hw_portnum(struct usb_hcd *hcd,
                 * 1.1 ports are under the USB 2.0 hub.  If the port speed
                 * matches the device speed, it's a similar speed port.
                 */
-               if ((port_speed == 0x03) == (hcd->speed == HCD_USB3))
+               if ((port_speed == 0x03) == (hcd->speed >= HCD_USB3))
                        num_similar_speed_ports++;
        }
        return num_similar_speed_ports;
@@ -1515,7 +1515,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
 
        /* Find the right roothub. */
        hcd = xhci_to_hcd(xhci);
-       if ((major_revision == 0x03) != (hcd->speed == HCD_USB3))
+       if ((major_revision == 0x03) != (hcd->speed >= HCD_USB3))
                hcd = xhci->shared_hcd;
 
        if (major_revision == 0) {
@@ -1541,7 +1541,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
         * correct bus_state structure.
         */
        bus_state = &xhci->bus_state[hcd_index(hcd)];
-       if (hcd->speed == HCD_USB3)
+       if (hcd->speed >= HCD_USB3)
                port_array = xhci->usb3_ports;
        else
                port_array = xhci->usb2_ports;
@@ -1555,7 +1555,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
                usb_hcd_resume_root_hub(hcd);
        }
 
-       if (hcd->speed == HCD_USB3 && (temp & PORT_PLS_MASK) == XDEV_INACTIVE)
+       if (hcd->speed >= HCD_USB3 && (temp & PORT_PLS_MASK) == XDEV_INACTIVE)
                bus_state->port_remote_wakeup &= ~(1 << faked_port_index);
 
        if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_RESUME) {
@@ -1567,7 +1567,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
                        goto cleanup;
                }
 
-               if (DEV_SUPERSPEED(temp)) {
+               if (DEV_SUPERSPEED_ANY(temp)) {
                        xhci_dbg(xhci, "remote wake SS port %d\n", port_id);
                        /* Set a flag to say the port signaled remote wakeup,
                         * so we can tell the difference between the end of
@@ -1595,7 +1595,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
        }
 
        if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_U0 &&
-                       DEV_SUPERSPEED(temp)) {
+                       DEV_SUPERSPEED_ANY(temp)) {
                xhci_dbg(xhci, "resume SS port %d finished\n", port_id);
                /* We've just brought the device into U0 through either the
                 * Resume state after a device remote wakeup, or through the
@@ -1625,7 +1625,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
         * RExit to a disconnect state).  If so, let the the driver know it's
         * out of the RExit state.
         */
-       if (!DEV_SUPERSPEED(temp) &&
+       if (!DEV_SUPERSPEED_ANY(temp) &&
                        test_and_clear_bit(faked_port_index,
                                &bus_state->rexit_ports)) {
                complete(&bus_state->rexit_done[faked_port_index]);
@@ -1633,7 +1633,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
                goto cleanup;
        }
 
-       if (hcd->speed != HCD_USB3)
+       if (hcd->speed < HCD_USB3)
                xhci_test_and_clear_bit(xhci, port_array, faked_port_index,
                                        PORT_PLC);
 
@@ -3048,21 +3048,6 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        return xhci_queue_bulk_tx(xhci, mem_flags, urb, slot_id, ep_index);
 }
 
-/*
- * The TD size is the number of bytes remaining in the TD (including this TRB),
- * right shifted by 10.
- * It must fit in bits 21:17, so it can't be bigger than 31.
- */
-static u32 xhci_td_remainder(unsigned int remainder)
-{
-       u32 max = (1 << (21 - 17 + 1)) - 1;
-
-       if ((remainder >> 10) >= max)
-               return max << 17;
-       else
-               return (remainder >> 10) << 17;
-}
-
 /*
  * For xHCI 1.0 host controllers, TD size is the number of max packet sized
  * packets remaining in the TD (*not* including this TRB).
@@ -3075,30 +3060,36 @@ static u32 xhci_td_remainder(unsigned int remainder)
  *
  * TD size = total_packet_count - packets_transferred
  *
- * It must fit in bits 21:17, so it can't be bigger than 31.
+ * For xHCI 0.96 and older, TD size field should be the remaining bytes
+ * including this TRB, right shifted by 10
+ *
+ * For all hosts it must fit in bits 21:17, so it can't be bigger than 31.
+ * This is taken care of in the TRB_TD_SIZE() macro
+ *
  * The last TRB in a TD must have the TD size set to zero.
  */
-static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len,
-               unsigned int total_packet_count, struct urb *urb,
-               unsigned int num_trbs_left)
+static u32 xhci_td_remainder(struct xhci_hcd *xhci, int transferred,
+                             int trb_buff_len, unsigned int td_total_len,
+                             struct urb *urb, unsigned int num_trbs_left)
 {
-       int packets_transferred;
+       u32 maxp, total_packet_count;
+
+       if (xhci->hci_version < 0x100)
+               return ((td_total_len - transferred) >> 10);
+
+       maxp = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
+       total_packet_count = DIV_ROUND_UP(td_total_len, maxp);
 
        /* One TRB with a zero-length data packet. */
-       if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0))
+       if (num_trbs_left == 0 || (transferred == 0 && trb_buff_len == 0) ||
+           trb_buff_len == td_total_len)
                return 0;
 
-       /* All the TRB queueing functions don't count the current TRB in
-        * running_total.
-        */
-       packets_transferred = (running_total + trb_buff_len) /
-               GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc));
-
-       if ((total_packet_count - packets_transferred) > 31)
-               return 31 << 17;
-       return (total_packet_count - packets_transferred) << 17;
+       /* Queueing functions don't count the current TRB into transferred */
+       return (total_packet_count - ((transferred + trb_buff_len) / maxp));
 }
 
+
 static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                struct urb *urb, int slot_id, unsigned int ep_index)
 {
@@ -3220,17 +3211,12 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                }
 
                /* Set the TRB length, TD size, and interrupter fields. */
-               if (xhci->hci_version < 0x100) {
-                       remainder = xhci_td_remainder(
-                                       urb->transfer_buffer_length -
-                                       running_total);
-               } else {
-                       remainder = xhci_v1_0_td_remainder(running_total,
-                                       trb_buff_len, total_packet_count, urb,
-                                       num_trbs - 1);
-               }
+               remainder = xhci_td_remainder(xhci, running_total, trb_buff_len,
+                                          urb->transfer_buffer_length,
+                                          urb, num_trbs - 1);
+
                length_field = TRB_LEN(trb_buff_len) |
-                       remainder |
+                       TRB_TD_SIZE(remainder) |
                        TRB_INTR_TARGET(0);
 
                if (num_trbs > 1)
@@ -3393,17 +3379,12 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                        field |= TRB_ISP;
 
                /* Set the TRB length, TD size, and interrupter fields. */
-               if (xhci->hci_version < 0x100) {
-                       remainder = xhci_td_remainder(
-                                       urb->transfer_buffer_length -
-                                       running_total);
-               } else {
-                       remainder = xhci_v1_0_td_remainder(running_total,
-                                       trb_buff_len, total_packet_count, urb,
-                                       num_trbs - 1);
-               }
+               remainder = xhci_td_remainder(xhci, running_total, trb_buff_len,
+                                          urb->transfer_buffer_length,
+                                          urb, num_trbs - 1);
+
                length_field = TRB_LEN(trb_buff_len) |
-                       remainder |
+                       TRB_TD_SIZE(remainder) |
                        TRB_INTR_TARGET(0);
 
                if (num_trbs > 1)
@@ -3441,7 +3422,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        struct usb_ctrlrequest *setup;
        struct xhci_generic_trb *start_trb;
        int start_cycle;
-       u32 field, length_field;
+       u32 field, length_field, remainder;
        struct urb_priv *urb_priv;
        struct xhci_td *td;
 
@@ -3514,9 +3495,15 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
        else
                field = TRB_TYPE(TRB_DATA);
 
+       remainder = xhci_td_remainder(xhci, 0,
+                                  urb->transfer_buffer_length,
+                                  urb->transfer_buffer_length,
+                                  urb, 1);
+
        length_field = TRB_LEN(urb->transfer_buffer_length) |
-               xhci_td_remainder(urb->transfer_buffer_length) |
+               TRB_TD_SIZE(remainder) |
                TRB_INTR_TARGET(0);
+
        if (urb->transfer_buffer_length > 0) {
                if (setup->bRequestType & USB_DIR_IN)
                        field |= TRB_DIR_IN;
@@ -3845,17 +3832,12 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                                trb_buff_len = td_remain_len;
 
                        /* Set the TRB length, TD size, & interrupter fields. */
-                       if (xhci->hci_version < 0x100) {
-                               remainder = xhci_td_remainder(
-                                               td_len - running_total);
-                       } else {
-                               remainder = xhci_v1_0_td_remainder(
-                                               running_total, trb_buff_len,
-                                               total_packet_count, urb,
-                                               (trbs_per_td - j - 1));
-                       }
+                       remainder = xhci_td_remainder(xhci, running_total,
+                                                  trb_buff_len, td_len,
+                                                  urb, trbs_per_td - j - 1);
+
                        length_field = TRB_LEN(trb_buff_len) |
-                               remainder |
+                               TRB_TD_SIZE(remainder) |
                                TRB_INTR_TARGET(0);
 
                        queue_trb(xhci, ep_ring, more_trbs_coming,
index 9957bd96d4bc383dd9f27a557af157c8d7343fc8..6e7dc6f93978c54e300caaa1b53155a672c91019 100644 (file)
@@ -3973,7 +3973,7 @@ int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1)
        __le32 __iomem *addr;
        int raw_port;
 
-       if (hcd->speed != HCD_USB3)
+       if (hcd->speed < HCD_USB3)
                addr = xhci->usb2_ports[port1 - 1];
        else
                addr = xhci->usb3_ports[port1 - 1];
@@ -4124,7 +4124,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
        int             hird, exit_latency;
        int             ret;
 
-       if (hcd->speed == HCD_USB3 || !xhci->hw_lpm_support ||
+       if (hcd->speed >= HCD_USB3 || !xhci->hw_lpm_support ||
                        !udev->lpm_capable)
                return -EPERM;
 
@@ -4241,7 +4241,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
        int             portnum = udev->portnum - 1;
 
-       if (hcd->speed == HCD_USB3 || !xhci->sw_lpm_support ||
+       if (hcd->speed >= HCD_USB3 || !xhci->sw_lpm_support ||
                        !udev->lpm_capable)
                return 0;
 
@@ -4841,8 +4841,9 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
        /* XHCI controllers don't stop the ep queue on short packets :| */
        hcd->self.no_stop_on_short = 1;
 
+       xhci = hcd_to_xhci(hcd);
+
        if (usb_hcd_is_primary_hcd(hcd)) {
-               xhci = hcd_to_xhci(hcd);
                xhci->main_hcd = hcd;
                /* Mark the first roothub as being USB 2.0.
                 * The xHCI driver will register the USB 3.0 roothub.
@@ -4856,6 +4857,10 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
                 */
                hcd->has_tt = 1;
        } else {
+               if (xhci->sbrn == 0x31) {
+                       xhci_info(xhci, "Host supports USB 3.1 Enhanced SuperSpeed\n");
+                       hcd->speed = HCD_USB31;
+               }
                /* xHCI private pointer was set in xhci_pci_probe for the second
                 * registered roothub.
                 */
@@ -4875,6 +4880,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
        xhci->hcc_params = readl(&xhci->cap_regs->hc_capbase);
        xhci->hci_version = HC_VERSION(xhci->hcc_params);
        xhci->hcc_params = readl(&xhci->cap_regs->hcc_params);
+       if (xhci->hci_version > 0x100)
+               xhci->hcc_params2 = readl(&xhci->cap_regs->hcc_params2);
        xhci_print_registers(xhci);
 
        xhci->quirks = quirks;
@@ -4906,6 +4913,16 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
                        !dma_set_mask(dev, DMA_BIT_MASK(64))) {
                xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
                dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
+       } else {
+               /*
+                * This is to avoid error in cases where a 32-bit USB
+                * controller is used on a 64-bit capable system.
+                */
+               retval = dma_set_mask(dev, DMA_BIT_MASK(32));
+               if (retval)
+                       return retval;
+               xhci_dbg(xhci, "Enabling 32-bit DMA addresses.\n");
+               dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
        }
 
        xhci_dbg(xhci, "Calling HCD init\n");
@@ -5020,7 +5037,7 @@ static int __init xhci_hcd_init(void)
        BUILD_BUG_ON(sizeof(struct xhci_stream_ctx) != 4*32/8);
        BUILD_BUG_ON(sizeof(union xhci_trb) != 4*32/8);
        BUILD_BUG_ON(sizeof(struct xhci_erst_entry) != 4*32/8);
-       BUILD_BUG_ON(sizeof(struct xhci_cap_regs) != 7*32/8);
+       BUILD_BUG_ON(sizeof(struct xhci_cap_regs) != 8*32/8);
        BUILD_BUG_ON(sizeof(struct xhci_intr_reg) != 8*32/8);
        /* xhci_run_regs has eight fields and embeds 128 xhci_intr_regs */
        BUILD_BUG_ON(sizeof(struct xhci_run_regs) != (8+8*128)*32/8);
index dbda41e91c843f2e289c4a4aa0d4129f2641f2a9..be9048e2d4d4f1cc4f40003e89c2553358420122 100644 (file)
@@ -29,6 +29,8 @@
 #include <linux/kernel.h>
 #include <linux/usb/hcd.h>
 
+#include <asm-generic/io-64-nonatomic-lo-hi.h>
+
 /* Code sharing between pci-quirks and xhci hcd */
 #include       "xhci-ext-caps.h"
 #include "pci-quirks.h"
@@ -56,6 +58,7 @@
  * @hcc_params:                HCCPARAMS - Capability Parameters
  * @db_off:            DBOFF - Doorbell array offset
  * @run_regs_off:      RTSOFF - Runtime register space offset
+ * @hcc_params2:       HCCPARAMS2 Capability Parameters 2, xhci 1.1 only
  */
 struct xhci_cap_regs {
        __le32  hc_capbase;
@@ -65,6 +68,7 @@ struct xhci_cap_regs {
        __le32  hcc_params;
        __le32  db_off;
        __le32  run_regs_off;
+       __le32  hcc_params2; /* xhci 1.1 */
        /* Reserved up to (CAPLENGTH - 0x1C) */
 };
 
@@ -134,6 +138,21 @@ struct xhci_cap_regs {
 /* run_regs_off bitmask - bits 0:4 reserved */
 #define        RTSOFF_MASK     (~0x1f)
 
+/* HCCPARAMS2 - hcc_params2 - bitmasks */
+/* true: HC supports U3 entry Capability */
+#define        HCC2_U3C(p)             ((p) & (1 << 0))
+/* true: HC supports Configure endpoint command Max exit latency too large */
+#define        HCC2_CMC(p)             ((p) & (1 << 1))
+/* true: HC supports Force Save context Capability */
+#define        HCC2_FSC(p)             ((p) & (1 << 2))
+/* true: HC supports Compliance Transition Capability */
+#define        HCC2_CTC(p)             ((p) & (1 << 3))
+/* true: HC support Large ESIT payload Capability > 48k */
+#define        HCC2_LEC(p)             ((p) & (1 << 4))
+/* true: HC support Configuration Information Capability */
+#define        HCC2_CIC(p)             ((p) & (1 << 5))
+/* true: HC support Extended TBC Capability, Isoc burst count > 65535 */
+#define        HCC2_ETC(p)             ((p) & (1 << 6))
 
 /* Number of registers per port */
 #define        NUM_PORT_REGS   4
@@ -269,7 +288,11 @@ struct xhci_op_regs {
 /* CONFIG - Configure Register - config_reg bitmasks */
 /* bits 0:7 - maximum number of device slots enabled (NumSlotsEn) */
 #define MAX_DEVS(p)    ((p) & 0xff)
-/* bits 8:31 - reserved and should be preserved */
+/* bit 8: U3 Entry Enabled, assert PLC when root port enters U3, xhci 1.1 */
+#define CONFIG_U3E             (1 << 8)
+/* bit 9: Configuration Information Enable, xhci 1.1 */
+#define CONFIG_CIE             (1 << 9)
+/* bits 10:31 - reserved and should be preserved */
 
 /* PORTSC - Port Status and Control Register - port_status_base bitmasks */
 /* true: device connected */
@@ -306,11 +329,16 @@ struct xhci_op_regs {
 #define        XDEV_LS                 (0x2 << 10)
 #define        XDEV_HS                 (0x3 << 10)
 #define        XDEV_SS                 (0x4 << 10)
+#define        XDEV_SSP                (0x5 << 10)
 #define DEV_UNDEFSPEED(p)      (((p) & DEV_SPEED_MASK) == (0x0<<10))
 #define DEV_FULLSPEED(p)       (((p) & DEV_SPEED_MASK) == XDEV_FS)
 #define DEV_LOWSPEED(p)                (((p) & DEV_SPEED_MASK) == XDEV_LS)
 #define DEV_HIGHSPEED(p)       (((p) & DEV_SPEED_MASK) == XDEV_HS)
 #define DEV_SUPERSPEED(p)      (((p) & DEV_SPEED_MASK) == XDEV_SS)
+#define DEV_SUPERSPEEDPLUS(p)  (((p) & DEV_SPEED_MASK) == XDEV_SSP)
+#define DEV_SUPERSPEED_ANY(p)  (((p) & DEV_SPEED_MASK) >= XDEV_SS)
+#define DEV_PORT_SPEED(p)      (((p) >> 10) & 0x0f)
+
 /* Bits 20:23 in the Slot Context are the speed for the device */
 #define        SLOT_SPEED_FS           (XDEV_FS << 10)
 #define        SLOT_SPEED_LS           (XDEV_LS << 10)
@@ -394,6 +422,9 @@ struct xhci_op_regs {
 #define        PORT_L1DS(p)            (((p) & 0xff) << 8)
 #define        PORT_HLE                (1 << 16)
 
+/* USB3 Protocol PORTLI  Port Link Information */
+#define PORT_RX_LANES(p)       (((p) >> 16) & 0xf)
+#define PORT_TX_LANES(p)       (((p) >> 20) & 0xf)
 
 /* USB2 Protocol PORTHLPMC */
 #define PORT_HIRDM(p)((p) & 3)
@@ -519,9 +550,23 @@ struct xhci_protocol_caps {
 };
 
 #define        XHCI_EXT_PORT_MAJOR(x)  (((x) >> 24) & 0xff)
+#define        XHCI_EXT_PORT_MINOR(x)  (((x) >> 16) & 0xff)
+#define        XHCI_EXT_PORT_PSIC(x)   (((x) >> 28) & 0x0f)
 #define        XHCI_EXT_PORT_OFF(x)    ((x) & 0xff)
 #define        XHCI_EXT_PORT_COUNT(x)  (((x) >> 8) & 0xff)
 
+#define        XHCI_EXT_PORT_PSIV(x)   (((x) >> 0) & 0x0f)
+#define        XHCI_EXT_PORT_PSIE(x)   (((x) >> 4) & 0x03)
+#define        XHCI_EXT_PORT_PLT(x)    (((x) >> 6) & 0x03)
+#define        XHCI_EXT_PORT_PFD(x)    (((x) >> 8) & 0x01)
+#define        XHCI_EXT_PORT_LP(x)     (((x) >> 14) & 0x03)
+#define        XHCI_EXT_PORT_PSIM(x)   (((x) >> 16) & 0xffff)
+
+#define PLT_MASK        (0x03 << 6)
+#define PLT_SYM         (0x00 << 6)
+#define PLT_ASYM_RX     (0x02 << 6)
+#define PLT_ASYM_TX     (0x03 << 6)
+
 /**
  * struct xhci_container_ctx
  * @type: Type of context.  Used to calculated offsets to contained contexts.
@@ -1136,6 +1181,8 @@ enum xhci_setup_dev {
 /* Normal TRB fields */
 /* transfer_len bitmasks - bits 0:16 */
 #define        TRB_LEN(p)              ((p) & 0x1ffff)
+/* TD Size, packets remaining in this TD, bits 21:17 (5 bits, so max 31) */
+#define TRB_TD_SIZE(p)          (min((p), (u32)31) << 17)
 /* Interrupter Target - which MSI-X vector to target the completion event at */
 #define TRB_INTR_TARGET(p)     (((p) & 0x3ff) << 22)
 #define GET_INTR_TARGET(p)     (((p) >> 22) & 0x3ff)
@@ -1448,6 +1495,14 @@ static inline unsigned int hcd_index(struct usb_hcd *hcd)
                return 1;
 }
 
+struct xhci_hub {
+       u8      maj_rev;
+       u8      min_rev;
+       u32     *psi;           /* array of protocol speed ID entries */
+       u8      psi_count;
+       u8      psi_uid_count;
+};
+
 /* There is one xhci_hcd structure per controller */
 struct xhci_hcd {
        struct usb_hcd *main_hcd;
@@ -1465,6 +1520,7 @@ struct xhci_hcd {
        __u32           hcs_params2;
        __u32           hcs_params3;
        __u32           hcc_params;
+       __u32           hcc_params2;
 
        spinlock_t      lock;
 
@@ -1586,6 +1642,8 @@ struct xhci_hcd {
        unsigned int            num_usb3_ports;
        /* Array of pointers to USB 2.0 PORTSC registers */
        __le32 __iomem          **usb2_ports;
+       struct xhci_hub         usb2_rhub;
+       struct xhci_hub         usb3_rhub;
        unsigned int            num_usb2_ports;
        /* support xHCI 0.96 spec USB2 software LPM */
        unsigned                sw_lpm_support:1;
@@ -1651,20 +1709,12 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci)
 static inline u64 xhci_read_64(const struct xhci_hcd *xhci,
                __le64 __iomem *regs)
 {
-       __u32 __iomem *ptr = (__u32 __iomem *) regs;
-       u64 val_lo = readl(ptr);
-       u64 val_hi = readl(ptr + 1);
-       return val_lo + (val_hi << 32);
+       return lo_hi_readq(regs);
 }
 static inline void xhci_write_64(struct xhci_hcd *xhci,
                                 const u64 val, __le64 __iomem *regs)
 {
-       __u32 __iomem *ptr = (__u32 __iomem *) regs;
-       u32 val_lo = lower_32_bits(val);
-       u32 val_hi = upper_32_bits(val);
-
-       writel(val_lo, ptr);
-       writel(val_hi, ptr + 1);
+       lo_hi_writeq(val, regs);
 }
 
 static inline int xhci_link_trb_quirk(struct xhci_hcd *xhci)
index 64ff5b91752d2187c0c949927dfa311b49531460..b45cb77c0744599a2ae7f77a12f3e014a59cba7a 100644 (file)
@@ -410,7 +410,7 @@ static int __init usb3503_init(void)
 {
        int err;
 
-       err = i2c_register_driver(THIS_MODULE, &usb3503_i2c_driver);
+       err = i2c_add_driver(&usb3503_i2c_driver);
        if (err != 0)
                pr_err("usb3503: Failed to register I2C driver: %d\n", err);
 
index 9517812a50e2982aa45db4102092c90e9732598f..637f3f7cfce8b884167ccd6e25c9d6de9cd0eaf6 100644 (file)
@@ -17,6 +17,7 @@
 static int override_alt = -1;
 module_param_named(alt, override_alt, int, 0644);
 MODULE_PARM_DESC(alt, ">= 0 to override altsetting selection");
+static void complicated_callback(struct urb *urb);
 
 /*-------------------------------------------------------------------------*/
 
@@ -95,6 +96,7 @@ static struct usb_device *testdev_to_usbdev(struct usbtest_dev *test)
        dev_warn(&(tdev)->intf->dev , fmt , ## args)
 
 #define GUARD_BYTE     0xA5
+#define MAX_SGLEN      128
 
 /*-------------------------------------------------------------------------*/
 
@@ -238,7 +240,8 @@ static struct urb *usbtest_alloc_urb(
        unsigned long           bytes,
        unsigned                transfer_flags,
        unsigned                offset,
-       u8                      bInterval)
+       u8                      bInterval,
+       usb_complete_t          complete_fn)
 {
        struct urb              *urb;
 
@@ -247,10 +250,10 @@ static struct urb *usbtest_alloc_urb(
                return urb;
 
        if (bInterval)
-               usb_fill_int_urb(urb, udev, pipe, NULL, bytes, simple_callback,
+               usb_fill_int_urb(urb, udev, pipe, NULL, bytes, complete_fn,
                                NULL, bInterval);
        else
-               usb_fill_bulk_urb(urb, udev, pipe, NULL, bytes, simple_callback,
+               usb_fill_bulk_urb(urb, udev, pipe, NULL, bytes, complete_fn,
                                NULL);
 
        urb->interval = (udev->speed == USB_SPEED_HIGH)
@@ -295,7 +298,17 @@ static struct urb *simple_alloc_urb(
        u8                      bInterval)
 {
        return usbtest_alloc_urb(udev, pipe, bytes, URB_NO_TRANSFER_DMA_MAP, 0,
-                       bInterval);
+                       bInterval, simple_callback);
+}
+
+static struct urb *complicated_alloc_urb(
+       struct usb_device       *udev,
+       int                     pipe,
+       unsigned long           bytes,
+       u8                      bInterval)
+{
+       return usbtest_alloc_urb(udev, pipe, bytes, URB_NO_TRANSFER_DMA_MAP, 0,
+                       bInterval, complicated_callback);
 }
 
 static unsigned pattern;
@@ -303,11 +316,20 @@ static unsigned mod_pattern;
 module_param_named(pattern, mod_pattern, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(mod_pattern, "i/o pattern (0 == zeroes)");
 
-static inline void simple_fill_buf(struct urb *urb)
+static unsigned get_maxpacket(struct usb_device *udev, int pipe)
+{
+       struct usb_host_endpoint        *ep;
+
+       ep = usb_pipe_endpoint(udev, pipe);
+       return le16_to_cpup(&ep->desc.wMaxPacketSize);
+}
+
+static void simple_fill_buf(struct urb *urb)
 {
        unsigned        i;
        u8              *buf = urb->transfer_buffer;
        unsigned        len = urb->transfer_buffer_length;
+       unsigned        maxpacket;
 
        switch (pattern) {
        default:
@@ -316,8 +338,9 @@ static inline void simple_fill_buf(struct urb *urb)
                memset(buf, 0, len);
                break;
        case 1:                 /* mod63 */
+               maxpacket = get_maxpacket(urb->dev, urb->pipe);
                for (i = 0; i < len; i++)
-                       *buf++ = (u8) (i % 63);
+                       *buf++ = (u8) ((i % maxpacket) % 63);
                break;
        }
 }
@@ -349,6 +372,7 @@ static int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb)
        u8              expected;
        u8              *buf = urb->transfer_buffer;
        unsigned        len = urb->actual_length;
+       unsigned        maxpacket = get_maxpacket(urb->dev, urb->pipe);
 
        int ret = check_guard_bytes(tdev, urb);
        if (ret)
@@ -366,7 +390,7 @@ static int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb)
                 * with set_interface or set_config.
                 */
                case 1:                 /* mod63 */
-                       expected = i % 63;
+                       expected = (i % maxpacket) % 63;
                        break;
                /* always fail unsupported patterns */
                default:
@@ -478,11 +502,13 @@ static void free_sglist(struct scatterlist *sg, int nents)
 }
 
 static struct scatterlist *
-alloc_sglist(int nents, int max, int vary)
+alloc_sglist(int nents, int max, int vary, struct usbtest_dev *dev, int pipe)
 {
        struct scatterlist      *sg;
        unsigned                i;
        unsigned                size = max;
+       unsigned                maxpacket =
+               get_maxpacket(interface_to_usbdev(dev->intf), pipe);
 
        if (max == 0)
                return NULL;
@@ -511,7 +537,7 @@ alloc_sglist(int nents, int max, int vary)
                        break;
                case 1:
                        for (j = 0; j < size; j++)
-                               *buf++ = (u8) (j % 63);
+                               *buf++ = (u8) ((j % maxpacket) % 63);
                        break;
                }
 
@@ -1719,7 +1745,7 @@ static int ctrl_out(struct usbtest_dev *dev,
        for (i = 0; i < count; i++) {
                /* write patterned data */
                for (j = 0; j < len; j++)
-                       buf[j] = i + j;
+                       buf[j] = (u8)(i + j);
                retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                                0x5b, USB_DIR_OUT|USB_TYPE_VENDOR,
                                0, 0, buf, len, USB_CTRL_SET_TIMEOUT);
@@ -1749,9 +1775,9 @@ static int ctrl_out(struct usbtest_dev *dev,
 
                /* fail if we can't verify */
                for (j = 0; j < len; j++) {
-                       if (buf[j] != (u8) (i + j)) {
+                       if (buf[j] != (u8)(i + j)) {
                                ERROR(dev, "ctrl_out, byte %d is %d not %d\n",
-                                       j, buf[j], (u8) i + j);
+                                       j, buf[j], (u8)(i + j));
                                retval = -EBADMSG;
                                break;
                        }
@@ -1781,12 +1807,12 @@ static int ctrl_out(struct usbtest_dev *dev,
 
 /*-------------------------------------------------------------------------*/
 
-/* ISO tests ... mimics common usage
+/* ISO/BULK tests ... mimics common usage
  *  - buffer length is split into N packets (mostly maxpacket sized)
  *  - multi-buffers according to sglen
  */
 
-struct iso_context {
+struct transfer_context {
        unsigned                count;
        unsigned                pending;
        spinlock_t              lock;
@@ -1795,11 +1821,12 @@ struct iso_context {
        unsigned long           errors;
        unsigned long           packet_count;
        struct usbtest_dev      *dev;
+       bool                    is_iso;
 };
 
-static void iso_callback(struct urb *urb)
+static void complicated_callback(struct urb *urb)
 {
-       struct iso_context      *ctx = urb->context;
+       struct transfer_context *ctx = urb->context;
 
        spin_lock(&ctx->lock);
        ctx->count--;
@@ -1808,7 +1835,7 @@ static void iso_callback(struct urb *urb)
        if (urb->error_count > 0)
                ctx->errors += urb->error_count;
        else if (urb->status != 0)
-               ctx->errors += urb->number_of_packets;
+               ctx->errors += (ctx->is_iso ? urb->number_of_packets : 1);
        else if (urb->actual_length != urb->transfer_buffer_length)
                ctx->errors++;
        else if (check_guard_bytes(ctx->dev, urb) != 0)
@@ -1895,7 +1922,7 @@ static struct urb *iso_alloc_urb(
                urb->iso_frame_desc[i].offset = maxp * i;
        }
 
-       urb->complete = iso_callback;
+       urb->complete = complicated_callback;
        /* urb->context = SET BY CALLER */
        urb->interval = 1 << (desc->bInterval - 1);
        urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
@@ -1903,37 +1930,33 @@ static struct urb *iso_alloc_urb(
 }
 
 static int
-test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param,
+test_queue(struct usbtest_dev *dev, struct usbtest_param *param,
                int pipe, struct usb_endpoint_descriptor *desc, unsigned offset)
 {
-       struct iso_context      context;
+       struct transfer_context context;
        struct usb_device       *udev;
        unsigned                i;
        unsigned long           packets = 0;
        int                     status = 0;
-       struct urb              *urbs[10];      /* FIXME no limit */
-
-       if (param->sglen > 10)
-               return -EDOM;
+       struct urb              *urbs[param->sglen];
 
        memset(&context, 0, sizeof(context));
        context.count = param->iterations * param->sglen;
        context.dev = dev;
+       context.is_iso = !!desc;
        init_completion(&context.done);
        spin_lock_init(&context.lock);
 
-       memset(urbs, 0, sizeof(urbs));
        udev = testdev_to_usbdev(dev);
-       dev_info(&dev->intf->dev,
-               "iso period %d %sframes, wMaxPacket %d, transactions: %d\n",
-               1 << (desc->bInterval - 1),
-               (udev->speed == USB_SPEED_HIGH) ? "micro" : "",
-               usb_endpoint_maxp(desc) & 0x7ff,
-               1 + (0x3 & (usb_endpoint_maxp(desc) >> 11)));
 
        for (i = 0; i < param->sglen; i++) {
-               urbs[i] = iso_alloc_urb(udev, pipe, desc,
+               if (context.is_iso)
+                       urbs[i] = iso_alloc_urb(udev, pipe, desc,
                                        param->length, offset);
+               else
+                       urbs[i] = complicated_alloc_urb(udev, pipe,
+                                       param->length, 0);
+
                if (!urbs[i]) {
                        status = -ENOMEM;
                        goto fail;
@@ -1942,11 +1965,21 @@ test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param,
                urbs[i]->context = &context;
        }
        packets *= param->iterations;
-       dev_info(&dev->intf->dev,
-               "total %lu msec (%lu packets)\n",
-               (packets * (1 << (desc->bInterval - 1)))
-                       / ((udev->speed == USB_SPEED_HIGH) ? 8 : 1),
-               packets);
+
+       if (context.is_iso) {
+               dev_info(&dev->intf->dev,
+                       "iso period %d %sframes, wMaxPacket %d, transactions: %d\n",
+                       1 << (desc->bInterval - 1),
+                       (udev->speed == USB_SPEED_HIGH) ? "micro" : "",
+                       usb_endpoint_maxp(desc) & 0x7ff,
+                       1 + (0x3 & (usb_endpoint_maxp(desc) >> 11)));
+
+               dev_info(&dev->intf->dev,
+                       "total %lu msec (%lu packets)\n",
+                       (packets * (1 << (desc->bInterval - 1)))
+                               / ((udev->speed == USB_SPEED_HIGH) ? 8 : 1),
+                       packets);
+       }
 
        spin_lock_irq(&context.lock);
        for (i = 0; i < param->sglen; i++) {
@@ -1983,7 +2016,8 @@ test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param,
                ;
        else if (context.submit_error)
                status = -EACCES;
-       else if (context.errors > context.packet_count / 10)
+       else if (context.errors >
+                       (context.is_iso ? context.packet_count / 10 : 0))
                status = -EIO;
        return status;
 
@@ -2004,8 +2038,8 @@ static int test_unaligned_bulk(
        const char *label)
 {
        int retval;
-       struct urb *urb = usbtest_alloc_urb(
-               testdev_to_usbdev(tdev), pipe, length, transfer_flags, 1, 0);
+       struct urb *urb = usbtest_alloc_urb(testdev_to_usbdev(tdev),
+                       pipe, length, transfer_flags, 1, 0, simple_callback);
 
        if (!urb)
                return -ENOMEM;
@@ -2061,6 +2095,9 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
        if (param->iterations <= 0)
                return -EINVAL;
 
+       if (param->sglen > MAX_SGLEN)
+               return -EINVAL;
+
        if (mutex_lock_interruptible(&dev->lock))
                return -ERESTARTSYS;
 
@@ -2176,7 +2213,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
                        "TEST 5:  write %d sglists %d entries of %d bytes\n",
                                param->iterations,
                                param->sglen, param->length);
-               sg = alloc_sglist(param->sglen, param->length, 0);
+               sg = alloc_sglist(param->sglen, param->length,
+                               0, dev, dev->out_pipe);
                if (!sg) {
                        retval = -ENOMEM;
                        break;
@@ -2194,7 +2232,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
                        "TEST 6:  read %d sglists %d entries of %d bytes\n",
                                param->iterations,
                                param->sglen, param->length);
-               sg = alloc_sglist(param->sglen, param->length, 0);
+               sg = alloc_sglist(param->sglen, param->length,
+                               0, dev, dev->in_pipe);
                if (!sg) {
                        retval = -ENOMEM;
                        break;
@@ -2211,7 +2250,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
                        "TEST 7:  write/%d %d sglists %d entries 0..%d bytes\n",
                                param->vary, param->iterations,
                                param->sglen, param->length);
-               sg = alloc_sglist(param->sglen, param->length, param->vary);
+               sg = alloc_sglist(param->sglen, param->length,
+                               param->vary, dev, dev->out_pipe);
                if (!sg) {
                        retval = -ENOMEM;
                        break;
@@ -2228,7 +2268,8 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
                        "TEST 8:  read/%d %d sglists %d entries 0..%d bytes\n",
                                param->vary, param->iterations,
                                param->sglen, param->length);
-               sg = alloc_sglist(param->sglen, param->length, param->vary);
+               sg = alloc_sglist(param->sglen, param->length,
+                               param->vary, dev, dev->in_pipe);
                if (!sg) {
                        retval = -ENOMEM;
                        break;
@@ -2325,7 +2366,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
                                param->iterations,
                                param->sglen, param->length);
                /* FIRMWARE:  iso sink */
-               retval = test_iso_queue(dev, param,
+               retval = test_queue(dev, param,
                                dev->out_iso_pipe, dev->iso_out, 0);
                break;
 
@@ -2338,7 +2379,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
                                param->iterations,
                                param->sglen, param->length);
                /* FIRMWARE:  iso source */
-               retval = test_iso_queue(dev, param,
+               retval = test_queue(dev, param,
                                dev->in_iso_pipe, dev->iso_in, 0);
                break;
 
@@ -2419,7 +2460,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
                        "TEST 22:  write %d iso odd, %d entries of %d bytes\n",
                                param->iterations,
                                param->sglen, param->length);
-               retval = test_iso_queue(dev, param,
+               retval = test_queue(dev, param,
                                dev->out_iso_pipe, dev->iso_out, 1);
                break;
 
@@ -2430,7 +2471,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
                        "TEST 23:  read %d iso odd, %d entries of %d bytes\n",
                                param->iterations,
                                param->sglen, param->length);
-               retval = test_iso_queue(dev, param,
+               retval = test_queue(dev, param,
                                dev->in_iso_pipe, dev->iso_in, 1);
                break;
 
@@ -2487,6 +2528,25 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf)
                retval = simple_io(dev, urb, param->iterations, 0, 0, "test26");
                simple_free_urb(urb);
                break;
+       case 27:
+               /* We do performance test, so ignore data compare */
+               if (dev->out_pipe == 0 || param->sglen == 0 || pattern != 0)
+                       break;
+               dev_info(&intf->dev,
+                       "TEST 27: bulk write %dMbytes\n", (param->iterations *
+                       param->sglen * param->length) / (1024 * 1024));
+               retval = test_queue(dev, param,
+                               dev->out_pipe, NULL, 0);
+               break;
+       case 28:
+               if (dev->in_pipe == 0 || param->sglen == 0 || pattern != 0)
+                       break;
+               dev_info(&intf->dev,
+                       "TEST 28: bulk read %dMbytes\n", (param->iterations *
+                       param->sglen * param->length) / (1024 * 1024));
+               retval = test_queue(dev, param,
+                               dev->in_pipe, NULL, 0);
+               break;
        }
        do_gettimeofday(&param->duration);
        param->duration.tv_sec -= start.tv_sec;
index 4a518ff123106b0931082bd51f0705c8e8ca0bb7..ba13529cbd52ff82658e88bdba30db82a8e99790 100644 (file)
@@ -1028,18 +1028,22 @@ void musb_start(struct musb *musb)
 {
        void __iomem    *regs = musb->mregs;
        u8              devctl = musb_readb(regs, MUSB_DEVCTL);
+       u8              power;
 
        dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
 
        musb_enable_interrupts(musb);
        musb_writeb(regs, MUSB_TESTMODE, 0);
 
-       /* put into basic highspeed mode and start session */
-       musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE
-                       | MUSB_POWER_HSENAB
-                       /* ENSUSPEND wedges tusb */
-                       /* | MUSB_POWER_ENSUSPEND */
-                  );
+       power = MUSB_POWER_ISOUPDATE;
+       /*
+        * treating UNKNOWN as unspecified maximum speed, in which case
+        * we will default to high-speed.
+        */
+       if (musb->config->maximum_speed == USB_SPEED_HIGH ||
+                       musb->config->maximum_speed == USB_SPEED_UNKNOWN)
+               power |= MUSB_POWER_HSENAB;
+       musb_writeb(regs, MUSB_POWER, power);
 
        musb->is_active = 0;
        devctl = musb_readb(regs, MUSB_DEVCTL);
@@ -1771,13 +1775,20 @@ musb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf)
        unsigned long   flags;
        unsigned long   val;
        int             vbus;
+       u8              devctl;
 
        spin_lock_irqsave(&musb->lock, flags);
        val = musb->a_wait_bcon;
-       /* FIXME get_vbus_status() is normally #defined as false...
-        * and is effectively TUSB-specific.
-        */
        vbus = musb_platform_get_vbus_status(musb);
+       if (vbus < 0) {
+               /* Use default MUSB method by means of DEVCTL register */
+               devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+               if ((devctl & MUSB_DEVCTL_VBUS)
+                               == (3 << MUSB_DEVCTL_VBUS_SHIFT))
+                       vbus = 1;
+               else
+                       vbus = 0;
+       }
        spin_unlock_irqrestore(&musb->lock, flags);
 
        return sprintf(buf, "Vbus %s, timeout %lu msec\n",
index 4b886d0f6bdf1bcf10ca5477b9ea0820efc8d5b1..2337d7a7d62d66c75cfd2761b8e796352244d64a 100644 (file)
@@ -579,7 +579,7 @@ static inline int  musb_platform_recover(struct musb *musb)
 static inline int musb_platform_get_vbus_status(struct musb *musb)
 {
        if (!musb->ops->vbus_status)
-               return 0;
+               return -EINVAL;
 
        return musb->ops->vbus_status(musb);
 }
index 84512d1d5eee1583fb057d6f45613f25293dc25b..eeb7d9ecf7df34ea1aa906330f55ba40952f4be1 100644 (file)
@@ -666,7 +666,7 @@ static int get_musb_port_mode(struct device *dev)
 {
        enum usb_dr_mode mode;
 
-       mode = of_usb_get_dr_mode(dev->of_node);
+       mode = usb_get_dr_mode(dev);
        switch (mode) {
        case USB_DR_MODE_HOST:
                return MUSB_PORT_MODE_HOST;
@@ -747,6 +747,19 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue,
        if (!ret && val)
                config->multipoint = true;
 
+       config->maximum_speed = usb_get_maximum_speed(&parent->dev);
+       switch (config->maximum_speed) {
+       case USB_SPEED_LOW:
+       case USB_SPEED_FULL:
+               break;
+       case USB_SPEED_SUPER:
+               dev_warn(dev, "ignore incorrect maximum_speed "
+                               "(super-speed) setting in dts");
+               /* fall through */
+       default:
+               config->maximum_speed = USB_SPEED_HIGH;
+       }
+
        ret = platform_device_add_data(musb, &pdata, sizeof(pdata));
        if (ret) {
                dev_err(dev, "failed to add platform_data\n");
index f9f6304ad854777fe7680a4d03e2432c98ba6a58..d9b0dc461439aa414b9942826453fb44fd6941de 100644 (file)
@@ -341,6 +341,16 @@ static void sunxi_musb_disable(struct musb *musb)
        clear_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags);
 }
 
+struct dma_controller *sunxi_musb_dma_controller_create(struct musb *musb,
+                                                   void __iomem *base)
+{
+       return NULL;
+}
+
+void sunxi_musb_dma_controller_destroy(struct dma_controller *c)
+{
+}
+
 /*
  * sunxi musb register layout
  * 0x00 - 0x17 fifo regs, 1 long per fifo
@@ -566,6 +576,8 @@ static const struct musb_platform_ops sunxi_musb_ops = {
        .writeb         = sunxi_musb_writeb,
        .readw          = sunxi_musb_readw,
        .writew         = sunxi_musb_writew,
+       .dma_init       = sunxi_musb_dma_controller_create,
+       .dma_exit       = sunxi_musb_dma_controller_destroy,
        .set_vbus       = sunxi_musb_set_vbus,
        .pre_root_reset_end = sunxi_musb_pre_root_reset_end,
        .post_root_reset_end = sunxi_musb_post_root_reset_end,
@@ -617,7 +629,7 @@ static int sunxi_musb_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        memset(&pdata, 0, sizeof(pdata));
-       switch (of_usb_get_dr_mode(np)) {
+       switch (usb_get_dr_mode(&pdev->dev)) {
 #if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_HOST
        case USB_DR_MODE_HOST:
                pdata.mode = MUSB_PORT_MODE_HOST;
index c58c3c0dbe35edebec10a89ad7477484f4cab902..80eb991c2506c758315cc2e6e1f39b6ebbf319f4 100644 (file)
@@ -1529,7 +1529,7 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
        if (IS_ERR(motg->phy_rst))
                motg->phy_rst = NULL;
 
-       pdata->mode = of_usb_get_dr_mode(node);
+       pdata->mode = usb_get_dr_mode(&pdev->dev);
        if (pdata->mode == USB_DR_MODE_UNKNOWN)
                pdata->mode = USB_DR_MODE_OTG;
 
index 5d357a94599ecb91f2070e6e8b5d79302fd6b917..579587d972177338e97ca7ece02fabbc60fdcf55 100644 (file)
@@ -71,7 +71,7 @@ struct phy_8x16 {
 
        struct reset_control            *phy_reset;
 
-       struct extcon_specific_cable_nb vbus_cable;
+       struct extcon_dev               *vbus_edev;
        struct notifier_block           vbus_notify;
 
        struct gpio_desc                *switch_gpio;
@@ -234,7 +234,7 @@ static int phy_8x16_init(struct usb_phy *phy)
        val = ULPI_PWR_OTG_COMP_DISABLE;
        usb_phy_io_write(phy, val, ULPI_SET(ULPI_PWR_CLK_MNG_REG));
 
-       state = extcon_get_cable_state(qphy->vbus_cable.edev, "USB");
+       state = extcon_get_cable_state_(qphy->vbus_edev, EXTCON_USB);
        if (state)
                phy_8x16_vbus_on(qphy);
        else
@@ -314,7 +314,6 @@ static int phy_8x16_reboot_notify(struct notifier_block *this,
 
 static int phy_8x16_probe(struct platform_device *pdev)
 {
-       struct extcon_dev *edev;
        struct phy_8x16 *qphy;
        struct resource *res;
        struct usb_phy *phy;
@@ -349,9 +348,9 @@ static int phy_8x16_probe(struct platform_device *pdev)
        if (ret < 0)
                return ret;
 
-       edev = extcon_get_edev_by_phandle(phy->dev, 0);
-       if (IS_ERR(edev))
-               return PTR_ERR(edev);
+       qphy->vbus_edev = extcon_get_edev_by_phandle(phy->dev, 0);
+       if (IS_ERR(qphy->vbus_edev))
+               return PTR_ERR(qphy->vbus_edev);
 
        ret = clk_set_rate(qphy->core_clk, INT_MAX);
        if (ret < 0)
@@ -370,8 +369,8 @@ static int phy_8x16_probe(struct platform_device *pdev)
                goto off_clks;
 
        qphy->vbus_notify.notifier_call = phy_8x16_vbus_notify;
-       ret = extcon_register_interest(&qphy->vbus_cable, edev->name,
-                                      "USB", &qphy->vbus_notify);
+       ret = extcon_register_notifier(qphy->vbus_edev, EXTCON_USB,
+                                      &qphy->vbus_notify);
        if (ret < 0)
                goto off_power;
 
@@ -385,7 +384,8 @@ static int phy_8x16_probe(struct platform_device *pdev)
        return 0;
 
 off_extcon:
-       extcon_unregister_interest(&qphy->vbus_cable);
+       extcon_unregister_notifier(qphy->vbus_edev, EXTCON_USB,
+                                  &qphy->vbus_notify);
 off_power:
        phy_8x16_regulators_disable(qphy);
 off_clks:
@@ -400,7 +400,8 @@ static int phy_8x16_remove(struct platform_device *pdev)
        struct phy_8x16 *qphy = platform_get_drvdata(pdev);
 
        unregister_reboot_notifier(&qphy->reboot_notify);
-       extcon_unregister_interest(&qphy->vbus_cable);
+       extcon_unregister_notifier(qphy->vbus_edev, EXTCON_USB,
+                                  &qphy->vbus_notify);
 
        /*
         * Ensure that D+/D- lines are routed to uB connector, so
index ab025b00964c393b7622b0187486b53dc44f829f..5fe4a5704bde329caf492451be7fdb0593bb3548 100644 (file)
@@ -1029,7 +1029,7 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
        }
 
        if (of_find_property(np, "dr_mode", NULL))
-               tegra_phy->mode = of_usb_get_dr_mode(np);
+               tegra_phy->mode = usb_get_dr_mode(&pdev->dev);
        else
                tegra_phy->mode = USB_DR_MODE_HOST;
 
index 0ac1b10be1f73a6d28a825a85dd9e468c9f2a48c..fce82fd79f77bf59db864c2d1f09e166aa5d018a 100644 (file)
 #define        TI_MODE_CONFIGURING     0   /* Device has not entered start device */
 #define        TI_MODE_BOOT            1   /* Staying in boot mode                */
 #define TI_MODE_DOWNLOAD       2   /* Made it to download mode            */
-#define TI_MODE_TRANSITIONING  3   /* Currently in boot mode but
-                                      transitioning to download mode      */
+#define TI_MODE_TRANSITIONING  3   /*
+                                    * Currently in boot mode but
+                                    * transitioning to download mode
+                                    */
 
 /* read urb state */
 #define EDGE_READ_URB_RUNNING  0
@@ -97,9 +99,11 @@ struct edgeport_port {
        __u8 shadow_mcr;
        __u8 shadow_lsr;
        __u8 lsr_mask;
-       __u32 ump_read_timeout;         /* Number of milliseconds the UMP will
-                                          wait without data before completing
-                                          a read short */
+       __u32 ump_read_timeout;         /*
+                                        * Number of milliseconds the UMP will
+                                        * wait without data before completing
+                                        * a read short
+                                        */
        int baud_rate;
        int close_pending;
        int lsr_event;
@@ -115,8 +119,10 @@ struct edgeport_port {
 struct edgeport_serial {
        struct product_info product_info;
        u8 TI_I2C_Type;                 /* Type of I2C in UMP */
-       u8 TiReadI2C;                   /* Set to TRUE if we have read the
-                                          I2c in Boot Mode */
+       u8 TiReadI2C;                   /*
+                                        * Set to TRUE if we have read the
+                                        * I2c in Boot Mode
+                                        */
        struct mutex es_lock;
        int num_ports_open;
        struct usb_serial *serial;
@@ -223,6 +229,11 @@ static void edge_set_termios(struct tty_struct *tty,
                struct usb_serial_port *port, struct ktermios *old_termios);
 static void edge_send(struct usb_serial_port *port, struct tty_struct *tty);
 
+static int do_download_mode(struct edgeport_serial *serial,
+               const struct firmware *fw);
+static int do_boot_mode(struct edgeport_serial *serial,
+               const struct firmware *fw);
+
 /* sysfs attributes */
 static int edge_create_sysfs_attrs(struct usb_serial_port *port);
 static int edge_remove_sysfs_attrs(struct usb_serial_port *port);
@@ -324,7 +335,8 @@ static int read_download_mem(struct usb_device *dev, int start_address,
 
        dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, length);
 
-       /* Read in blocks of 64 bytes
+       /*
+        * Read in blocks of 64 bytes
         * (TI firmware can't handle more than 64 byte reads)
         */
        while (length) {
@@ -430,7 +442,6 @@ static int write_boot_mem(struct edgeport_serial *serial,
        return status;
 }
 
-
 /* Write edgeport I2C memory to TI chip        */
 static int write_i2c_mem(struct edgeport_serial *serial,
                int start_address, int length, __u8 address_type, __u8 *buffer)
@@ -472,8 +483,10 @@ static int write_i2c_mem(struct edgeport_serial *serial,
        start_address   += write_length;
        buffer          += write_length;
 
-       /* We should be aligned now -- can write
-          max page size bytes at a time */
+       /*
+        * We should be aligned now -- can write max page size bytes at a
+        * time.
+        */
        while (length) {
                if (length > EPROM_PAGE_SIZE)
                        write_length = EPROM_PAGE_SIZE;
@@ -506,7 +519,8 @@ static int write_i2c_mem(struct edgeport_serial *serial,
        return status;
 }
 
-/* Examine the UMP DMA registers and LSR
+/*
+ * Examine the UMP DMA registers and LSR
  *
  * Check the MSBit of the X and Y DMA byte count registers.
  * A zero in this bit indicates that the TX DMA buffers are empty
@@ -523,9 +537,11 @@ static int tx_active(struct edgeport_port *port)
        if (!oedb)
                return -ENOMEM;
 
-       lsr = kmalloc(1, GFP_KERNEL);   /* Sigh, that's right, just one byte,
-                                          as not all platforms can do DMA
-                                          from stack */
+       /*
+        * Sigh, that's right, just one byte, as not all platforms can
+        * do DMA from stack
+        */
+       lsr = kmalloc(1, GFP_KERNEL);
        if (!lsr) {
                kfree(oedb);
                return -ENOMEM;
@@ -615,8 +631,6 @@ static int write_rom(struct edgeport_serial *serial, int start_address,
        return -EINVAL;
 }
 
-
-
 /* Read a descriptor header from I2C based on type */
 static int get_descriptor_addr(struct edgeport_serial *serial,
                                int desc_type, struct ti_i2c_desc *rom_desc)
@@ -785,8 +799,7 @@ exit:
 }
 
 /* Build firmware header used for firmware update */
-static int build_i2c_fw_hdr(u8 *header, struct device *dev,
-               const struct firmware *fw)
+static int build_i2c_fw_hdr(u8 *header, const struct firmware *fw)
 {
        __u8 *buffer;
        int buffer_size;
@@ -797,7 +810,8 @@ static int build_i2c_fw_hdr(u8 *header, struct device *dev,
        struct ti_i2c_firmware_rec *firmware_rec;
        struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
 
-       /* In order to update the I2C firmware we must change the type 2 record
+       /*
+        * In order to update the I2C firmware we must change the type 2 record
         * to type 0xF2.  This will force the UMP to come up in Boot Mode.
         * Then while in boot mode, the driver will download the latest
         * firmware (padded to 15.5k) into the UMP ram.  And finally when the
@@ -806,8 +820,10 @@ static int build_i2c_fw_hdr(u8 *header, struct device *dev,
         * update the record type from 0xf2 to 0x02.
         */
 
-       /* Allocate a 15.5k buffer + 2 bytes for version number
-        * (Firmware Record) */
+       /*
+        * Allocate a 15.5k buffer + 2 bytes for version number (Firmware
+        * Record)
+        */
        buffer_size = (((1024 * 16) - 512 ) +
                        sizeof(struct ti_i2c_firmware_rec));
 
@@ -815,7 +831,7 @@ static int build_i2c_fw_hdr(u8 *header, struct device *dev,
        if (!buffer)
                return -ENOMEM;
 
-       // Set entire image of 0xffs
+       /* Set entire image of 0xffs */
        memset(buffer, 0xff, buffer_size);
 
        /* Copy version number into firmware record */
@@ -981,32 +997,41 @@ static int check_fw_sanity(struct edgeport_serial *serial,
        return 0;
 }
 
-/**
+/*
  * DownloadTIFirmware - Download run-time operating firmware to the TI5052
  *
  * This routine downloads the main operating code into the TI5052, using the
  * boot code already burned into E2PROM or ROM.
  */
-static int download_fw(struct edgeport_serial *serial,
-               const struct firmware *fw)
+static int download_fw(struct edgeport_serial *serial)
 {
-       struct device *dev = &serial->serial->dev->dev;
+       struct device *dev = &serial->serial->interface->dev;
        int status = 0;
-       int start_address;
-       struct edge_ti_manuf_descriptor *ti_manuf_desc;
        struct usb_interface_descriptor *interface;
-       int download_cur_ver;
-       int download_new_ver;
-       struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
+       const struct firmware *fw;
+       const char *fw_name = "edgeport/down3.bin";
+       struct edgeport_fw_hdr *fw_hdr;
 
-       if (check_fw_sanity(serial, fw))
-               return -EINVAL;
+       status = request_firmware(&fw, fw_name, dev);
+       if (status) {
+               dev_err(dev, "Failed to load image \"%s\" err %d\n",
+                               fw_name, status);
+               return status;
+       }
+
+       if (check_fw_sanity(serial, fw)) {
+               status = -EINVAL;
+               goto out;
+       }
 
-       /* If on-board version is newer, "fw_version" will be updated below. */
+       fw_hdr = (struct edgeport_fw_hdr *)fw->data;
+
+       /* If on-board version is newer, "fw_version" will be updated later. */
        serial->fw_version = (fw_hdr->major_version << 8) +
                        fw_hdr->minor_version;
 
-       /* This routine is entered by both the BOOT mode and the Download mode
+       /*
+        * This routine is entered by both the BOOT mode and the Download mode
         * We can determine which code is running by the reading the config
         * descriptor and if we have only one bulk pipe it is in boot mode
         */
@@ -1017,12 +1042,13 @@ static int download_fw(struct edgeport_serial *serial,
 
        status = choose_config(serial->serial->dev);
        if (status)
-               return status;
+               goto out;
 
        interface = &serial->serial->interface->cur_altsetting->desc;
        if (!interface) {
                dev_err(dev, "%s - no interface set, error!\n", __func__);
-               return -ENODEV;
+               status = -ENODEV;
+               goto out;
        }
 
        /*
@@ -1030,190 +1056,219 @@ static int download_fw(struct edgeport_serial *serial,
         * if we have more than one endpoint we are definitely in download
         * mode
         */
-       if (interface->bNumEndpoints > 1)
+       if (interface->bNumEndpoints > 1) {
                serial->product_info.TiMode = TI_MODE_DOWNLOAD;
-       else
+               status = do_download_mode(serial, fw);
+       } else {
                /* Otherwise we will remain in configuring mode */
                serial->product_info.TiMode = TI_MODE_CONFIGURING;
+               status = do_boot_mode(serial, fw);
+       }
 
-       /********************************************************************/
-       /* Download Mode */
-       /********************************************************************/
-       if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) {
-               struct ti_i2c_desc *rom_desc;
+out:
+       release_firmware(fw);
+       return status;
+}
 
-               dev_dbg(dev, "%s - RUNNING IN DOWNLOAD MODE\n", __func__);
+static int do_download_mode(struct edgeport_serial *serial,
+               const struct firmware *fw)
+{
+       struct device *dev = &serial->serial->interface->dev;
+       int status = 0;
+       int start_address;
+       struct edge_ti_manuf_descriptor *ti_manuf_desc;
+       int download_cur_ver;
+       int download_new_ver;
+       struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
+       struct ti_i2c_desc *rom_desc;
 
-               status = check_i2c_image(serial);
-               if (status) {
-                       dev_dbg(dev, "%s - DOWNLOAD MODE -- BAD I2C\n", __func__);
-                       return status;
-               }
+       dev_dbg(dev, "%s - RUNNING IN DOWNLOAD MODE\n", __func__);
 
-               /* Validate Hardware version number
-                * Read Manufacturing Descriptor from TI Based Edgeport
-                */
-               ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
-               if (!ti_manuf_desc)
+       status = check_i2c_image(serial);
+       if (status) {
+               dev_dbg(dev, "%s - DOWNLOAD MODE -- BAD I2C\n", __func__);
+               return status;
+       }
+
+       /*
+        * Validate Hardware version number
+        * Read Manufacturing Descriptor from TI Based Edgeport
+        */
+       ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
+       if (!ti_manuf_desc)
+               return -ENOMEM;
+
+       status = get_manuf_info(serial, (__u8 *)ti_manuf_desc);
+       if (status) {
+               kfree(ti_manuf_desc);
+               return status;
+       }
+
+       /* Check version number of ION descriptor */
+       if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) {
+               dev_dbg(dev, "%s - Wrong CPU Rev %d (Must be 2)\n",
+                       __func__, ti_cpu_rev(ti_manuf_desc));
+               kfree(ti_manuf_desc);
+               return -EINVAL;
+       }
+
+       rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
+       if (!rom_desc) {
+               kfree(ti_manuf_desc);
+               return -ENOMEM;
+       }
+
+       /* Search for type 2 record (firmware record) */
+       start_address = get_descriptor_addr(serial,
+                       I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc);
+       if (start_address != 0) {
+               struct ti_i2c_firmware_rec *firmware_version;
+               u8 *record;
+
+               dev_dbg(dev, "%s - Found Type FIRMWARE (Type 2) record\n",
+                               __func__);
+
+               firmware_version = kmalloc(sizeof(*firmware_version),
+                                                       GFP_KERNEL);
+               if (!firmware_version) {
+                       kfree(rom_desc);
+                       kfree(ti_manuf_desc);
                        return -ENOMEM;
+               }
 
-               status = get_manuf_info(serial, (__u8 *)ti_manuf_desc);
+               /*
+                * Validate version number
+                * Read the descriptor data
+                */
+               status = read_rom(serial, start_address +
+                               sizeof(struct ti_i2c_desc),
+                               sizeof(struct ti_i2c_firmware_rec),
+                               (__u8 *)firmware_version);
                if (status) {
+                       kfree(firmware_version);
+                       kfree(rom_desc);
                        kfree(ti_manuf_desc);
                        return status;
                }
 
-               /* Check version number of ION descriptor */
-               if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) {
-                       dev_dbg(dev, "%s - Wrong CPU Rev %d (Must be 2)\n",
-                               __func__, ti_cpu_rev(ti_manuf_desc));
-                       kfree(ti_manuf_desc);
-                       return -EINVAL;
-               }
+               /*
+                * Check version number of download with current
+                * version in I2c
+                */
+               download_cur_ver = (firmware_version->Ver_Major << 8) +
+                                  (firmware_version->Ver_Minor);
+               download_new_ver = (fw_hdr->major_version << 8) +
+                                  (fw_hdr->minor_version);
 
-               rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
-               if (!rom_desc) {
-                       kfree(ti_manuf_desc);
-                       return -ENOMEM;
-               }
+               dev_dbg(dev, "%s - >> FW Versions Device %d.%d  Driver %d.%d\n",
+                       __func__, firmware_version->Ver_Major,
+                       firmware_version->Ver_Minor,
+                       fw_hdr->major_version, fw_hdr->minor_version);
 
-               /* Search for type 2 record (firmware record) */
-               start_address = get_descriptor_addr(serial,
-                               I2C_DESC_TYPE_FIRMWARE_BASIC, rom_desc);
-               if (start_address != 0) {
-                       struct ti_i2c_firmware_rec *firmware_version;
-                       u8 *record;
-
-                       dev_dbg(dev, "%s - Found Type FIRMWARE (Type 2) record\n", __func__);
+               /*
+                * Check if we have an old version in the I2C and
+                * update if necessary
+                */
+               if (download_cur_ver < download_new_ver) {
+                       dev_dbg(dev, "%s - Update I2C dld from %d.%d to %d.%d\n",
+                               __func__,
+                               firmware_version->Ver_Major,
+                               firmware_version->Ver_Minor,
+                               fw_hdr->major_version,
+                               fw_hdr->minor_version);
 
-                       firmware_version = kmalloc(sizeof(*firmware_version),
-                                                               GFP_KERNEL);
-                       if (!firmware_version) {
+                       record = kmalloc(1, GFP_KERNEL);
+                       if (!record) {
+                               kfree(firmware_version);
                                kfree(rom_desc);
                                kfree(ti_manuf_desc);
                                return -ENOMEM;
                        }
+                       /*
+                        * In order to update the I2C firmware we must
+                        * change the type 2 record to type 0xF2. This
+                        * will force the UMP to come up in Boot Mode.
+                        * Then while in boot mode, the driver will
+                        * download the latest firmware (padded to
+                        * 15.5k) into the UMP ram. Finally when the
+                        * device comes back up in download mode the
+                        * driver will cause the new firmware to be
+                        * copied from the UMP Ram to I2C and the
+                        * firmware will update the record type from
+                        * 0xf2 to 0x02.
+                        */
+                       *record = I2C_DESC_TYPE_FIRMWARE_BLANK;
 
-                       /* Validate version number
-                        * Read the descriptor data
+                       /*
+                        * Change the I2C Firmware record type to
+                        * 0xf2 to trigger an update
                         */
-                       status = read_rom(serial, start_address +
-                                       sizeof(struct ti_i2c_desc),
-                                       sizeof(struct ti_i2c_firmware_rec),
-                                       (__u8 *)firmware_version);
+                       status = write_rom(serial, start_address,
+                                       sizeof(*record), record);
                        if (status) {
+                               kfree(record);
                                kfree(firmware_version);
                                kfree(rom_desc);
                                kfree(ti_manuf_desc);
                                return status;
                        }
 
-                       /* Check version number of download with current
-                          version in I2c */
-                       download_cur_ver = (firmware_version->Ver_Major << 8) +
-                                          (firmware_version->Ver_Minor);
-                       download_new_ver = (fw_hdr->major_version << 8) +
-                                          (fw_hdr->minor_version);
-
-                       dev_dbg(dev, "%s - >> FW Versions Device %d.%d  Driver %d.%d\n",
-                               __func__, firmware_version->Ver_Major,
-                               firmware_version->Ver_Minor,
-                               fw_hdr->major_version, fw_hdr->minor_version);
+                       /*
+                        * verify the write -- must do this in order
+                        * for write to complete before we do the
+                        * hardware reset
+                        */
+                       status = read_rom(serial,
+                                               start_address,
+                                               sizeof(*record),
+                                               record);
+                       if (status) {
+                               kfree(record);
+                               kfree(firmware_version);
+                               kfree(rom_desc);
+                               kfree(ti_manuf_desc);
+                               return status;
+                       }
 
-                       /* Check if we have an old version in the I2C and
-                          update if necessary */
-                       if (download_cur_ver < download_new_ver) {
-                               dev_dbg(dev, "%s - Update I2C dld from %d.%d to %d.%d\n",
-                                       __func__,
-                                       firmware_version->Ver_Major,
-                                       firmware_version->Ver_Minor,
-                                       fw_hdr->major_version,
-                                       fw_hdr->minor_version);
-
-                               record = kmalloc(1, GFP_KERNEL);
-                               if (!record) {
-                                       kfree(firmware_version);
-                                       kfree(rom_desc);
-                                       kfree(ti_manuf_desc);
-                                       return -ENOMEM;
-                               }
-                               /* In order to update the I2C firmware we must
-                                * change the type 2 record to type 0xF2. This
-                                * will force the UMP to come up in Boot Mode.
-                                * Then while in boot mode, the driver will
-                                * download the latest firmware (padded to
-                                * 15.5k) into the UMP ram. Finally when the
-                                * device comes back up in download mode the
-                                * driver will cause the new firmware to be
-                                * copied from the UMP Ram to I2C and the
-                                * firmware will update the record type from
-                                * 0xf2 to 0x02.
-                                */
-                               *record = I2C_DESC_TYPE_FIRMWARE_BLANK;
-
-                               /* Change the I2C Firmware record type to
-                                  0xf2 to trigger an update */
-                               status = write_rom(serial, start_address,
-                                               sizeof(*record), record);
-                               if (status) {
-                                       kfree(record);
-                                       kfree(firmware_version);
-                                       kfree(rom_desc);
-                                       kfree(ti_manuf_desc);
-                                       return status;
-                               }
-
-                               /* verify the write -- must do this in order
-                                * for write to complete before we do the
-                                * hardware reset
-                                */
-                               status = read_rom(serial,
-                                                       start_address,
-                                                       sizeof(*record),
-                                                       record);
-                               if (status) {
-                                       kfree(record);
-                                       kfree(firmware_version);
-                                       kfree(rom_desc);
-                                       kfree(ti_manuf_desc);
-                                       return status;
-                               }
-
-                               if (*record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
-                                       dev_err(dev, "%s - error resetting device\n", __func__);
-                                       kfree(record);
-                                       kfree(firmware_version);
-                                       kfree(rom_desc);
-                                       kfree(ti_manuf_desc);
-                                       return -ENODEV;
-                               }
-
-                               dev_dbg(dev, "%s - HARDWARE RESET\n", __func__);
-
-                               /* Reset UMP -- Back to BOOT MODE */
-                               status = ti_vsend_sync(serial->serial->dev,
-                                               UMPC_HARDWARE_RESET,
-                                               0, 0, NULL, 0,
-                                               TI_VSEND_TIMEOUT_DEFAULT);
-
-                               dev_dbg(dev, "%s - HARDWARE RESET return %d\n", __func__, status);
-
-                               /* return an error on purpose. */
+                       if (*record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
+                               dev_err(dev, "%s - error resetting device\n",
+                                               __func__);
                                kfree(record);
                                kfree(firmware_version);
                                kfree(rom_desc);
                                kfree(ti_manuf_desc);
                                return -ENODEV;
-                       } else {
-                               /* Same or newer fw version is already loaded */
-                               serial->fw_version = download_cur_ver;
                        }
+
+                       dev_dbg(dev, "%s - HARDWARE RESET\n", __func__);
+
+                       /* Reset UMP -- Back to BOOT MODE */
+                       status = ti_vsend_sync(serial->serial->dev,
+                                       UMPC_HARDWARE_RESET,
+                                       0, 0, NULL, 0,
+                                       TI_VSEND_TIMEOUT_DEFAULT);
+
+                       dev_dbg(dev, "%s - HARDWARE RESET return %d\n",
+                                       __func__, status);
+
+                       /* return an error on purpose. */
+                       kfree(record);
                        kfree(firmware_version);
+                       kfree(rom_desc);
+                       kfree(ti_manuf_desc);
+                       return -ENODEV;
                }
-               /* Search for type 0xF2 record (firmware blank record) */
-               else if ((start_address = get_descriptor_addr(serial, I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc)) != 0) {
+               /* Same or newer fw version is already loaded */
+               serial->fw_version = download_cur_ver;
+               kfree(firmware_version);
+       }
+       /* Search for type 0xF2 record (firmware blank record) */
+       else {
+               start_address = get_descriptor_addr(serial,
+                               I2C_DESC_TYPE_FIRMWARE_BLANK, rom_desc);
+               if (start_address != 0) {
 #define HEADER_SIZE    (sizeof(struct ti_i2c_desc) + \
-                                       sizeof(struct ti_i2c_firmware_rec))
+                               sizeof(struct ti_i2c_firmware_rec))
                        __u8 *header;
                        __u8 *vheader;
 
@@ -1232,7 +1287,8 @@ static int download_fw(struct edgeport_serial *serial,
                                return -ENOMEM;
                        }
 
-                       dev_dbg(dev, "%s - Found Type BLANK FIRMWARE (Type F2) record\n", __func__);
+                       dev_dbg(dev, "%s - Found Type BLANK FIRMWARE (Type F2) record\n",
+                                       __func__);
 
                        /*
                         * In order to update the I2C firmware we must change
@@ -1245,7 +1301,7 @@ static int download_fw(struct edgeport_serial *serial,
                         * UMP Ram to I2C and the firmware will update the
                         * record type from 0xf2 to 0x02.
                         */
-                       status = build_i2c_fw_hdr(header, dev, fw);
+                       status = build_i2c_fw_hdr(header, fw);
                        if (status) {
                                kfree(vheader);
                                kfree(header);
@@ -1254,8 +1310,10 @@ static int download_fw(struct edgeport_serial *serial,
                                return -EINVAL;
                        }
 
-                       /* Update I2C with type 0xf2 record with correct
-                          size and checksum */
+                       /*
+                        * Update I2C with type 0xf2 record with correct
+                        * size and checksum
+                        */
                        status = write_rom(serial,
                                                start_address,
                                                HEADER_SIZE,
@@ -1268,13 +1326,16 @@ static int download_fw(struct edgeport_serial *serial,
                                return -EINVAL;
                        }
 
-                       /* verify the write -- must do this in order for
-                          write to complete before we do the hardware reset */
+                       /*
+                        * verify the write -- must do this in order for
+                        * write to complete before we do the hardware reset
+                        */
                        status = read_rom(serial, start_address,
                                                        HEADER_SIZE, vheader);
 
                        if (status) {
-                               dev_dbg(dev, "%s - can't read header back\n", __func__);
+                               dev_dbg(dev, "%s - can't read header back\n",
+                                               __func__);
                                kfree(vheader);
                                kfree(header);
                                kfree(rom_desc);
@@ -1282,7 +1343,8 @@ static int download_fw(struct edgeport_serial *serial,
                                return status;
                        }
                        if (memcmp(vheader, header, HEADER_SIZE)) {
-                               dev_dbg(dev, "%s - write download record failed\n", __func__);
+                               dev_dbg(dev, "%s - write download record failed\n",
+                                               __func__);
                                kfree(vheader);
                                kfree(header);
                                kfree(rom_desc);
@@ -1301,26 +1363,33 @@ static int download_fw(struct edgeport_serial *serial,
                                        0, 0, NULL, 0,
                                        TI_VSEND_TIMEOUT_FW_DOWNLOAD);
 
-                       dev_dbg(dev, "%s - Update complete 0x%x\n", __func__, status);
+                       dev_dbg(dev, "%s - Update complete 0x%x\n", __func__,
+                                       status);
                        if (status) {
                                dev_err(dev,
                                        "%s - UMPC_COPY_DNLD_TO_I2C failed\n",
-                                                               __func__);
+                                       __func__);
                                kfree(rom_desc);
                                kfree(ti_manuf_desc);
                                return status;
                        }
                }
-
-               // The device is running the download code
-               kfree(rom_desc);
-               kfree(ti_manuf_desc);
-               return 0;
        }
 
-       /********************************************************************/
-       /* Boot Mode */
-       /********************************************************************/
+       /* The device is running the download code */
+       kfree(rom_desc);
+       kfree(ti_manuf_desc);
+       return 0;
+}
+
+static int do_boot_mode(struct edgeport_serial *serial,
+               const struct firmware *fw)
+{
+       struct device *dev = &serial->serial->interface->dev;
+       int status = 0;
+       struct edge_ti_manuf_descriptor *ti_manuf_desc;
+       struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
+
        dev_dbg(dev, "%s - RUNNING IN BOOT MODE\n", __func__);
 
        /* Configure the TI device so we can use the BULK pipes for download */
@@ -1336,8 +1405,10 @@ static int download_fw(struct edgeport_serial *serial,
                goto stayinbootmode;
        }
 
-       /* We have an ION device (I2c Must be programmed)
-          Determine I2C image type */
+       /*
+        * We have an ION device (I2c Must be programmed)
+        * Determine I2C image type
+        */
        if (i2c_type_bootmode(serial))
                goto stayinbootmode;
 
@@ -1349,7 +1420,8 @@ static int download_fw(struct edgeport_serial *serial,
                __u8 *buffer;
                int buffer_size;
 
-               /* Validate Hardware version number
+               /*
+                * Validate Hardware version number
                 * Read Manufacturing Descriptor from TI Based Edgeport
                 */
                ti_manuf_desc = kmalloc(sizeof(*ti_manuf_desc), GFP_KERNEL);
@@ -1439,7 +1511,6 @@ stayinbootmode:
        return 0;
 }
 
-
 static int ti_do_config(struct edgeport_port *port, int feature, int on)
 {
        int port_number = port->port->port_number;
@@ -1450,7 +1521,6 @@ static int ti_do_config(struct edgeport_port *port, int feature, int on)
                        on, NULL, 0);
 }
 
-
 static int restore_mcr(struct edgeport_port *port, __u8 mcr)
 {
        int status = 0;
@@ -1556,7 +1626,6 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,
                icount->frame++;
 }
 
-
 static void edge_interrupt_callback(struct urb *urb)
 {
        struct edgeport_serial *edge_serial = urb->context;
@@ -1616,8 +1685,9 @@ static void edge_interrupt_callback(struct urb *urb)
        case TIUMP_INTERRUPT_CODE_LSR:
                lsr = map_line_status(data[1]);
                if (lsr & UMP_UART_LSR_DATA_MASK) {
-                       /* Save the LSR event for bulk read
-                          completion routine */
+                       /*
+                        * Save the LSR event for bulk read completion routine
+                        */
                        dev_dbg(dev, "%s - LSR Event Port %u LSR Status = %02x\n",
                                __func__, port_number, lsr);
                        edge_port->lsr_event = 1;
@@ -1925,8 +1995,10 @@ static void edge_close(struct usb_serial_port *port)
        if (edge_serial == NULL || edge_port == NULL)
                return;
 
-       /* The bulkreadcompletion routine will check
-        * this flag and dump add read data */
+       /*
+        * The bulkreadcompletion routine will check
+        * this flag and dump add read data
+        */
        edge_port->close_pending = 1;
 
        usb_kill_urb(port->read_urb);
@@ -2016,8 +2088,10 @@ static void edge_send(struct usb_serial_port *port, struct tty_struct *tty)
        } else
                edge_port->port->icount.tx += count;
 
-       /* wakeup any process waiting for writes to complete */
-       /* there is now more room in the buffer for new writes */
+       /*
+        * wakeup any process waiting for writes to complete
+        * there is now more room in the buffer for new writes
+        */
        if (tty)
                tty_wakeup(tty);
 }
@@ -2089,8 +2163,10 @@ static void edge_throttle(struct tty_struct *tty)
                }
        }
 
-       /* if we are implementing RTS/CTS, stop reads */
-       /* and the Edgeport will clear the RTS line */
+       /*
+        * if we are implementing RTS/CTS, stop reads
+        * and the Edgeport will clear the RTS line
+        */
        if (C_CRTSCTS(tty))
                stop_read(edge_port);
 
@@ -2113,8 +2189,10 @@ static void edge_unthrottle(struct tty_struct *tty)
                        dev_err(&port->dev, "%s - failed to write start character, %d\n", __func__, status);
                }
        }
-       /* if we are implementing RTS/CTS, restart reads */
-       /* are the Edgeport will assert the RTS line */
+       /*
+        * if we are implementing RTS/CTS, restart reads
+        * are the Edgeport will assert the RTS line
+        */
        if (C_CRTSCTS(tty)) {
                status = restart_read(edge_port);
                if (status)
@@ -2236,8 +2314,10 @@ static void change_port_settings(struct tty_struct *tty,
                restart_read(edge_port);
        }
 
-       /* if we are implementing XON/XOFF, set the start and stop
-          character in the device */
+       /*
+        * if we are implementing XON/XOFF, set the start and stop
+        * character in the device
+        */
        config->cXon  = START_CHAR(tty);
        config->cXoff = STOP_CHAR(tty);
 
@@ -2467,9 +2547,6 @@ static int edge_startup(struct usb_serial *serial)
 {
        struct edgeport_serial *edge_serial;
        int status;
-       const struct firmware *fw;
-       const char *fw_name = "edgeport/down3.bin";
-       struct device *dev = &serial->interface->dev;
        u16 product_id;
 
        /* create our private serial structure */
@@ -2481,16 +2558,7 @@ static int edge_startup(struct usb_serial *serial)
        edge_serial->serial = serial;
        usb_set_serial_data(serial, edge_serial);
 
-       status = request_firmware(&fw, fw_name, dev);
-       if (status) {
-               dev_err(dev, "Failed to load image \"%s\" err %d\n",
-                               fw_name, status);
-               kfree(edge_serial);
-               return status;
-       }
-
-       status = download_fw(edge_serial, fw);
-       release_firmware(fw);
+       status = download_fw(edge_serial);
        if (status) {
                kfree(edge_serial);
                return status;
index 6956c4f6221614a79a09429c6b9f541dc54baa5e..685fef71d3d14e28ce125983b3508ae73ed6579c 100644 (file)
@@ -48,7 +48,6 @@ static int  option_probe(struct usb_serial *serial,
                        const struct usb_device_id *id);
 static int option_attach(struct usb_serial *serial);
 static void option_release(struct usb_serial *serial);
-static int option_send_setup(struct usb_serial_port *port);
 static void option_instat_callback(struct urb *urb);
 
 /* Vendor and product IDs */
@@ -234,8 +233,6 @@ static void option_instat_callback(struct urb *urb);
 
 #define QUALCOMM_VENDOR_ID                     0x05C6
 
-#define SIERRA_VENDOR_ID                       0x1199
-
 #define CMOTECH_VENDOR_ID                      0x16d8
 #define CMOTECH_PRODUCT_6001                   0x6001
 #define CMOTECH_PRODUCT_CMU_300                        0x6002
@@ -611,11 +608,6 @@ static const struct option_blacklist_info telit_le920_blacklist = {
        .reserved = BIT(1) | BIT(5),
 };
 
-static const struct option_blacklist_info sierra_mc73xx_blacklist = {
-       .sendsetup = BIT(0) | BIT(2),
-       .reserved = BIT(8) | BIT(10) | BIT(11),
-};
-
 static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -1113,10 +1105,6 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
-       { USB_DEVICE_INTERFACE_CLASS(SIERRA_VENDOR_ID, 0x68c0, 0xff),
-         .driver_info = (kernel_ulong_t)&sierra_mc73xx_blacklist }, /* MC73xx */
-       { USB_DEVICE_INTERFACE_CLASS(SIERRA_VENDOR_ID, 0x9041, 0xff),
-         .driver_info = (kernel_ulong_t)&sierra_mc73xx_blacklist }, /* MC7305/MC7355 */
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
        { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
@@ -1835,10 +1823,6 @@ static struct usb_serial_driver * const serial_drivers[] = {
        &option_1port_device, NULL
 };
 
-struct option_private {
-       u8 bInterfaceNumber;
-};
-
 module_usb_serial_driver(serial_drivers, option_ids);
 
 static int option_probe(struct usb_serial *serial,
@@ -1882,29 +1866,19 @@ static int option_attach(struct usb_serial *serial)
        struct usb_interface_descriptor *iface_desc;
        const struct option_blacklist_info *blacklist;
        struct usb_wwan_intf_private *data;
-       struct option_private *priv;
 
        data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
 
-       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-       if (!priv) {
-               kfree(data);
-               return -ENOMEM;
-       }
-
        /* Retrieve blacklist info stored at probe. */
        blacklist = usb_get_serial_data(serial);
 
        iface_desc = &serial->interface->cur_altsetting->desc;
 
-       priv->bInterfaceNumber = iface_desc->bInterfaceNumber;
-       data->private = priv;
-
        if (!blacklist || !test_bit(iface_desc->bInterfaceNumber,
                                                &blacklist->sendsetup)) {
-               data->send_setup = option_send_setup;
+               data->use_send_setup = 1;
        }
        spin_lock_init(&data->susp_lock);
 
@@ -1916,9 +1890,7 @@ static int option_attach(struct usb_serial *serial)
 static void option_release(struct usb_serial *serial)
 {
        struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
-       struct option_private *priv = intfdata->private;
 
-       kfree(priv);
        kfree(intfdata);
 }
 
@@ -1977,40 +1949,6 @@ static void option_instat_callback(struct urb *urb)
        }
 }
 
-/** send RTS/DTR state to the port.
- *
- * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
- * CDC.
-*/
-static int option_send_setup(struct usb_serial_port *port)
-{
-       struct usb_serial *serial = port->serial;
-       struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
-       struct option_private *priv = intfdata->private;
-       struct usb_wwan_port_private *portdata;
-       int val = 0;
-       int res;
-
-       portdata = usb_get_serial_port_data(port);
-
-       if (portdata->dtr_state)
-               val |= 0x01;
-       if (portdata->rts_state)
-               val |= 0x02;
-
-       res = usb_autopm_get_interface(serial->interface);
-       if (res)
-               return res;
-
-       res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-                               0x22, 0x21, val, priv->bInterfaceNumber, NULL,
-                               0, USB_CTRL_SET_TIMEOUT);
-
-       usb_autopm_put_interface(serial->interface);
-
-       return res;
-}
-
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
index ebcec8cda85840d4d336f92b2558747f6efb2843..5022fcfa02605a604f6998ef7dcbf0d3f0b2b590 100644 (file)
@@ -143,9 +143,11 @@ static const struct usb_device_id id_table[] = {
        {DEVICE_SWI(0x0f3d, 0x68a2)},   /* Sierra Wireless MC7700 */
        {DEVICE_SWI(0x114f, 0x68a2)},   /* Sierra Wireless MC7750 */
        {DEVICE_SWI(0x1199, 0x68a2)},   /* Sierra Wireless MC7710 */
+       {DEVICE_SWI(0x1199, 0x68c0)},   /* Sierra Wireless MC7304/MC7354 */
        {DEVICE_SWI(0x1199, 0x901c)},   /* Sierra Wireless EM7700 */
        {DEVICE_SWI(0x1199, 0x901f)},   /* Sierra Wireless EM7355 */
        {DEVICE_SWI(0x1199, 0x9040)},   /* Sierra Wireless Modem */
+       {DEVICE_SWI(0x1199, 0x9041)},   /* Sierra Wireless MC7305/MC7355 */
        {DEVICE_SWI(0x1199, 0x9051)},   /* Netgear AirCard 340U */
        {DEVICE_SWI(0x1199, 0x9053)},   /* Sierra Wireless Modem */
        {DEVICE_SWI(0x1199, 0x9054)},   /* Sierra Wireless Modem */
@@ -153,6 +155,8 @@ static const struct usb_device_id id_table[] = {
        {DEVICE_SWI(0x1199, 0x9056)},   /* Sierra Wireless Modem */
        {DEVICE_SWI(0x1199, 0x9060)},   /* Sierra Wireless Modem */
        {DEVICE_SWI(0x1199, 0x9061)},   /* Sierra Wireless Modem */
+       {DEVICE_SWI(0x1199, 0x9070)},   /* Sierra Wireless MC74xx/EM74xx */
+       {DEVICE_SWI(0x1199, 0x9071)},   /* Sierra Wireless MC74xx/EM74xx */
        {DEVICE_SWI(0x413c, 0x81a2)},   /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */
        {DEVICE_SWI(0x413c, 0x81a3)},   /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */
        {DEVICE_SWI(0x413c, 0x81a4)},   /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
@@ -175,6 +179,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
        __u8 nintf;
        __u8 ifnum;
        int altsetting = -1;
+       bool sendsetup = false;
 
        nintf = serial->dev->actconfig->desc.bNumInterfaces;
        dev_dbg(dev, "Num Interfaces = %d\n", nintf);
@@ -286,6 +291,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
                        break;
                case 3:
                        dev_dbg(dev, "Modem port found\n");
+                       sendsetup = true;
                        break;
                default:
                        /* don't claim any unsupported interface */
@@ -337,17 +343,25 @@ done:
                }
        }
 
+       if (!retval)
+               usb_set_serial_data(serial, (void *)(unsigned long)sendsetup);
+
        return retval;
 }
 
 static int qc_attach(struct usb_serial *serial)
 {
        struct usb_wwan_intf_private *data;
+       bool sendsetup;
 
        data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
 
+       sendsetup = !!(unsigned long)(usb_get_serial_data(serial));
+       if (sendsetup)
+               data->use_send_setup = 1;
+
        spin_lock_init(&data->susp_lock);
 
        usb_set_serial_data(serial, data);
@@ -374,6 +388,7 @@ static struct usb_serial_driver qcdevice = {
        .probe               = qcprobe,
        .open                = usb_wwan_open,
        .close               = usb_wwan_close,
+       .dtr_rts             = usb_wwan_dtr_rts,
        .write               = usb_wwan_write,
        .write_room          = usb_wwan_write_room,
        .chars_in_buffer     = usb_wwan_chars_in_buffer,
index f22dff58b587a4c1da3fae281069dfb8bd6759df..44b25c08c68a15aa7db54056621576313a6bff48 100644 (file)
@@ -34,9 +34,9 @@ extern int usb_wwan_resume(struct usb_serial *serial);
 struct usb_wwan_intf_private {
        spinlock_t susp_lock;
        unsigned int suspended:1;
+       unsigned int use_send_setup:1;
        int in_flight;
        unsigned int open_ports;
-       int (*send_setup) (struct usb_serial_port *port);
        void *private;
 };
 
index 825305cb71d9dda11ce5a429feaed075a959a508..be9cb61b4d1987659828e32a7d461f8c92a09847 100644 (file)
 #include <linux/serial.h>
 #include "usb-wwan.h"
 
+/*
+ * Generate DTR/RTS signals on the port using the SET_CONTROL_LINE_STATE request
+ * in CDC ACM.
+ */
+static int usb_wwan_send_setup(struct usb_serial_port *port)
+{
+       struct usb_serial *serial = port->serial;
+       struct usb_wwan_port_private *portdata;
+       int val = 0;
+       int ifnum;
+       int res;
+
+       portdata = usb_get_serial_port_data(port);
+
+       if (portdata->dtr_state)
+               val |= 0x01;
+       if (portdata->rts_state)
+               val |= 0x02;
+
+       ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+
+       res = usb_autopm_get_interface(serial->interface);
+       if (res)
+               return res;
+
+       res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                               0x22, 0x21, val, ifnum, NULL, 0,
+                               USB_CTRL_SET_TIMEOUT);
+
+       usb_autopm_put_interface(port->serial->interface);
+
+       return res;
+}
+
 void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
 {
        struct usb_wwan_port_private *portdata;
@@ -43,7 +77,7 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
 
        intfdata = usb_get_serial_data(port->serial);
 
-       if (!intfdata->send_setup)
+       if (!intfdata->use_send_setup)
                return;
 
        portdata = usb_get_serial_port_data(port);
@@ -51,7 +85,7 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on)
        portdata->rts_state = on;
        portdata->dtr_state = on;
 
-       intfdata->send_setup(port);
+       usb_wwan_send_setup(port);
 }
 EXPORT_SYMBOL(usb_wwan_dtr_rts);
 
@@ -84,7 +118,7 @@ int usb_wwan_tiocmset(struct tty_struct *tty,
        portdata = usb_get_serial_port_data(port);
        intfdata = usb_get_serial_data(port->serial);
 
-       if (!intfdata->send_setup)
+       if (!intfdata->use_send_setup)
                return -EINVAL;
 
        /* FIXME: what locks portdata fields ? */
@@ -97,7 +131,7 @@ int usb_wwan_tiocmset(struct tty_struct *tty,
                portdata->rts_state = 0;
        if (clear & TIOCM_DTR)
                portdata->dtr_state = 0;
-       return intfdata->send_setup(port);
+       return usb_wwan_send_setup(port);
 }
 EXPORT_SYMBOL(usb_wwan_tiocmset);
 
index 1bac215202d20b0783890b28d9dbef886a5af35b..39afd7045c43d3148ee746f428a89a99cb7ad458 100644 (file)
@@ -1456,30 +1456,26 @@ static void isd200_free_info_ptrs(void *info_)
  */
 static int isd200_init_info(struct us_data *us)
 {
-       int retStatus = ISD200_GOOD;
        struct isd200_info *info;
 
        info = kzalloc(sizeof(struct isd200_info), GFP_KERNEL);
        if (!info)
-               retStatus = ISD200_ERROR;
-       else {
-               info->id = kzalloc(ATA_ID_WORDS * 2, GFP_KERNEL);
-               info->RegsBuf = kmalloc(sizeof(info->ATARegs), GFP_KERNEL);
-               info->srb.sense_buffer =
-                               kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
-               if (!info->id || !info->RegsBuf || !info->srb.sense_buffer) {
-                       isd200_free_info_ptrs(info);
-                       kfree(info);
-                       retStatus = ISD200_ERROR;
-               }
-       }
+               return ISD200_ERROR;
 
-       if (retStatus == ISD200_GOOD) {
-               us->extra = info;
-               us->extra_destructor = isd200_free_info_ptrs;
+       info->id = kzalloc(ATA_ID_WORDS * 2, GFP_KERNEL);
+       info->RegsBuf = kmalloc(sizeof(info->ATARegs), GFP_KERNEL);
+       info->srb.sense_buffer = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
+
+       if (!info->id || !info->RegsBuf || !info->srb.sense_buffer) {
+               isd200_free_info_ptrs(info);
+               kfree(info);
+               return ISD200_ERROR;
        }
 
-       return retStatus;
+       us->extra = info;
+       us->extra_destructor = isd200_free_info_ptrs;
+
+       return ISD200_GOOD;
 }
 
 /**************************************************************************
index f689219095526a76076010eee2d1e3df82fa8e73..48ca9c204354168f079a1e9e5ceaf2ac4b74a0f5 100644 (file)
@@ -257,17 +257,16 @@ static void uas_stat_cmplt(struct urb *urb)
        struct uas_cmd_info *cmdinfo;
        unsigned long flags;
        unsigned int idx;
+       int status = urb->status;
 
        spin_lock_irqsave(&devinfo->lock, flags);
 
        if (devinfo->resetting)
                goto out;
 
-       if (urb->status) {
-               if (urb->status != -ENOENT && urb->status != -ECONNRESET) {
-                       dev_err(&urb->dev->dev, "stat urb: status %d\n",
-                               urb->status);
-               }
+       if (status) {
+               if (status != -ENOENT && status != -ECONNRESET && status != -ESHUTDOWN)
+                       dev_err(&urb->dev->dev, "stat urb: status %d\n", status);
                goto out;
        }
 
@@ -348,6 +347,7 @@ static void uas_data_cmplt(struct urb *urb)
        struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
        struct scsi_data_buffer *sdb = NULL;
        unsigned long flags;
+       int status = urb->status;
 
        spin_lock_irqsave(&devinfo->lock, flags);
 
@@ -374,9 +374,9 @@ static void uas_data_cmplt(struct urb *urb)
                goto out;
        }
 
-       if (urb->status) {
-               if (urb->status != -ENOENT && urb->status != -ECONNRESET)
-                       uas_log_cmd_state(cmnd, "data cmplt err", urb->status);
+       if (status) {
+               if (status != -ENOENT && status != -ECONNRESET && status != -ESHUTDOWN)
+                       uas_log_cmd_state(cmnd, "data cmplt err", status);
                /* error: no data transfered */
                sdb->resid = sdb->length;
        } else {
index e9ef1eccdace88f1c4f9adb93d8ab566eb759de6..7fbe19d5279e5c11159f141fdd20b6a3ac7ff568 100644 (file)
@@ -218,7 +218,7 @@ static inline void hub_descriptor(struct usb_hub_descriptor *desc)
        memset(desc, 0, sizeof(*desc));
        desc->bDescriptorType = USB_DT_HUB;
        desc->bDescLength = 9;
-       desc->wHubCharacteristics = __constant_cpu_to_le16(
+       desc->wHubCharacteristics = cpu_to_le16(
                HUB_CHAR_INDV_PORT_LPSM | HUB_CHAR_COMMON_OCPM);
        desc->bNbrPorts = VHCI_NPORTS;
        desc->u.hs.DeviceRemovable[0] = 0xff;
@@ -565,7 +565,9 @@ no_need_xmit:
        usb_hcd_unlink_urb_from_ep(hcd, urb);
 no_need_unlink:
        spin_unlock(&the_controller->lock);
-       usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status);
+       if (!ret)
+               usb_hcd_giveback_urb(vhci_to_hcd(the_controller),
+                                    urb, urb->status);
        return ret;
 }
 
@@ -629,7 +631,7 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
                /* URB was never linked! or will be soon given back by
                 * vhci_rx. */
                spin_unlock(&the_controller->lock);
-               return 0;
+               return -EIDRM;
        }
 
        {
index 8fc1b787dceddd333b6c98cb99a4ea95fa81ec08..38d0504a1bbc50a29a3d639a772648ef385e5692 100644 (file)
@@ -642,9 +642,7 @@ static void uwb_drp_handle_alien_drp(struct uwb_rc *rc, struct uwb_ie_drp *drp_i
        }
 
        INIT_LIST_HEAD(&cnflt->rc_node);
-       init_timer(&cnflt->timer);
-       cnflt->timer.function = uwb_cnflt_timer;
-       cnflt->timer.data     = (unsigned long)cnflt;
+       setup_timer(&cnflt->timer, uwb_cnflt_timer, (unsigned long)cnflt);
 
        cnflt->rc = rc;
        INIT_WORK(&cnflt->cnflt_update_work, uwb_cnflt_update_work);
index 8cb71bb333c2ea830881ddc8bf19afd4096b3d60..36b5cb62c15dba7b734ffa61460fdeb3a31e79cc 100644 (file)
@@ -223,9 +223,7 @@ struct uwb_rc_neh *uwb_rc_neh_add(struct uwb_rc *rc, struct uwb_rccb *cmd,
 
        kref_init(&neh->kref);
        INIT_LIST_HEAD(&neh->list_node);
-       init_timer(&neh->timer);
-       neh->timer.function = uwb_rc_neh_timer;
-       neh->timer.data     = (unsigned long)neh;
+       setup_timer(&neh->timer, uwb_rc_neh_timer, (unsigned long)neh);
 
        neh->rc = rc;
        neh->evt_type = expected_type;
index 536ad42b0a4b1d7ed0091e4e943a19abf9d0980d..f5e27247a38feac0a0294a57fa49ad0a260be637 100644 (file)
@@ -470,9 +470,7 @@ static struct uwb_rsv *uwb_rsv_alloc(struct uwb_rc *rc)
        INIT_LIST_HEAD(&rsv->rc_node);
        INIT_LIST_HEAD(&rsv->pal_node);
        kref_init(&rsv->kref);
-       init_timer(&rsv->timer);
-       rsv->timer.function = uwb_rsv_timer;
-       rsv->timer.data     = (unsigned long)rsv;
+       setup_timer(&rsv->timer, uwb_rsv_timer, (unsigned long)rsv);
 
        rsv->rc = rc;
        INIT_WORK(&rsv->handle_timeout_work, uwb_rsv_handle_timeout_work);
@@ -989,9 +987,8 @@ void uwb_rsv_init(struct uwb_rc *rc)
        rc->bow.can_reserve_extra_mases = true;
        rc->bow.total_expired = 0;
        rc->bow.window = UWB_DRP_BACKOFF_WIN_MIN >> 1;
-       init_timer(&rc->bow.timer);
-       rc->bow.timer.function = uwb_rsv_backoff_win_timer;
-       rc->bow.timer.data     = (unsigned long)&rc->bow;
+       setup_timer(&rc->bow.timer, uwb_rsv_backoff_win_timer,
+                       (unsigned long)&rc->bow);
 
        bitmap_complement(rc->uwb_dev.streams, rc->uwb_dev.streams, UWB_NUM_STREAMS);
 }
index e649d8d370f8954435b79728e95db462795add5f..3c8825b67298fafe60f22c803206f9f0789fc8f7 100644 (file)
 #include <linux/mtd/partitions.h>
 #include <linux/serial.h>
 
- /* USB Device */
-struct at91_udc_data {
-       int     vbus_pin;               /* high == host powering us */
-       u8      vbus_active_low;        /* vbus polarity */
-       u8      vbus_polled;            /* Use polling, not interrupt */
-       int     pullup_pin;             /* active == D+ pulled up */
-       u8      pullup_active_low;      /* true == pullup_pin is active low */
-};
-
  /* Compact Flash */
 struct at91_cf_data {
        int     irq_pin;                /* I/O IRQ */
index 3f1cbf95ec3ba9cd98849ae92e846cb14a19e90f..3982586ba6df43f6cf294834c3599bce2b352070 100644 (file)
 
 struct platform_device;
 
-enum s3c_hsotg_dmamode {
+enum dwc2_hsotg_dmamode {
        S3C_HSOTG_DMA_NONE,     /* do not use DMA at-all */
        S3C_HSOTG_DMA_ONLY,     /* always use DMA */
        S3C_HSOTG_DMA_DRV,      /* DMA is chosen by driver */
 };
 
 /**
- * struct s3c_hsotg_plat - platform data for high-speed otg/udc
+ * struct dwc2_hsotg_plat - platform data for high-speed otg/udc
  * @dma: Whether to use DMA or not.
  * @is_osc: The clock source is an oscillator, not a crystal
  */
-struct s3c_hsotg_plat {
-       enum s3c_hsotg_dmamode  dma;
+struct dwc2_hsotg_plat {
+       enum dwc2_hsotg_dmamode dma;
        unsigned int            is_osc:1;
        int                     phy_type;
 
@@ -37,6 +37,6 @@ struct s3c_hsotg_plat {
        int (*phy_exit)(struct platform_device *pdev, int type);
 };
 
-extern void s3c_hsotg_set_platdata(struct s3c_hsotg_plat *pd);
+extern void dwc2_hsotg_set_platdata(struct dwc2_hsotg_plat *pd);
 
 #endif /* __LINUX_USB_S3C_HSOTG_H */
index 447fe29b55b451148c452b82cb0043d510a26eae..b9a28074210f218e05383099b8c043d4ca9fff93 100644 (file)
@@ -122,6 +122,8 @@ enum usb_interface_condition {
  *     has been deferred.
  * @needs_binding: flag set when the driver should be re-probed or unbound
  *     following a reset or suspend operation it doesn't support.
+ * @authorized: This allows to (de)authorize individual interfaces instead
+ *     a whole device in contrast to the device authorization.
  * @dev: driver model's view of this device
  * @usb_dev: if an interface is bound to the USB major, this will point
  *     to the sysfs representation for that device.
@@ -178,6 +180,7 @@ struct usb_interface {
        unsigned needs_altsetting0:1;   /* switch to altsetting 0 is pending */
        unsigned needs_binding:1;       /* needs delayed unbind/rebind */
        unsigned resetting_device:1;    /* true: bandwidth alloc after reset */
+       unsigned authorized:1;          /* used for interface authorization */
 
        struct device dev;              /* interface specific device info */
        struct device *usb_dev;
@@ -325,6 +328,7 @@ struct usb_host_bos {
        /* wireless cap descriptor is handled by wusb */
        struct usb_ext_cap_descriptor   *ext_cap;
        struct usb_ss_cap_descriptor    *ss_cap;
+       struct usb_ssp_cap_descriptor   *ssp_cap;
        struct usb_ss_container_id_descriptor   *ss_id;
 };
 
index 27603bcbb9b99dccd86f9ac7f720e13fde4c8bd0..6cc96bb12ddcf4f02fae841b801b3a9870ca5c2a 100644 (file)
@@ -32,9 +32,9 @@
 #ifndef __LINUX_USB_CH9_H
 #define __LINUX_USB_CH9_H
 
+#include <linux/device.h>
 #include <uapi/linux/usb/ch9.h>
 
-
 /**
  * usb_speed_string() - Returns human readable-name of the speed.
  * @speed: The speed to return human-readable name for.  If it's not
  */
 extern const char *usb_speed_string(enum usb_device_speed speed);
 
+/**
+ * usb_get_maximum_speed - Get maximum requested speed for a given USB
+ * controller.
+ * @dev: Pointer to the given USB controller device
+ *
+ * The function gets the maximum speed string from property "maximum-speed",
+ * and returns the corresponding enum usb_device_speed.
+ */
+extern enum usb_device_speed usb_get_maximum_speed(struct device *dev);
 
 /**
  * usb_state_string - Returns human readable name for the state.
index a41833cd184c64dbc99a02731b508ade382e2538..5dd75fa47dd823fbfd2c58ae19d65bb27ee120e1 100644 (file)
@@ -5,9 +5,28 @@
 #ifndef __LINUX_USB_CHIPIDEA_H
 #define __LINUX_USB_CHIPIDEA_H
 
+#include <linux/extcon.h>
 #include <linux/usb/otg.h>
 
 struct ci_hdrc;
+
+/**
+ * struct ci_hdrc_cable - structure for external connector cable state tracking
+ * @state: current state of the line
+ * @changed: set to true when extcon event happen
+ * @edev: device which generate events
+ * @ci: driver state of the chipidea device
+ * @nb: hold event notification callback
+ * @conn: used for notification registration
+ */
+struct ci_hdrc_cable {
+       bool                            state;
+       bool                            changed;
+       struct extcon_dev               *edev;
+       struct ci_hdrc                  *ci;
+       struct notifier_block           nb;
+};
+
 struct ci_hdrc_platform_data {
        const char      *name;
        /* offset of the capability registers */
@@ -48,6 +67,11 @@ struct ci_hdrc_platform_data {
        u32                     ahb_burst_config;
        u32                     tx_burst_size;
        u32                     rx_burst_size;
+
+       /* VBUS and ID signal state tracking, using extcon framework */
+       struct ci_hdrc_cable            vbus_extcon;
+       struct ci_hdrc_cable            id_extcon;
+       u32                     phy_clkgate_delay_us;
 };
 
 /* Default offset of capability registers */
index c14a69b36d27b14afc1da26ab616797e7daaaf8d..3d583a10b9269bd7a0f77c0eca1b1b037e11392d 100644 (file)
@@ -215,6 +215,7 @@ struct usb_ep {
        struct list_head        ep_list;
        struct usb_ep_caps      caps;
        bool                    claimed;
+       bool                    enabled;
        unsigned                maxpacket:16;
        unsigned                maxpacket_limit:16;
        unsigned                max_streams:16;
@@ -264,7 +265,18 @@ static inline void usb_ep_set_maxpacket_limit(struct usb_ep *ep,
  */
 static inline int usb_ep_enable(struct usb_ep *ep)
 {
-       return ep->ops->enable(ep, ep->desc);
+       int ret;
+
+       if (ep->enabled)
+               return 0;
+
+       ret = ep->ops->enable(ep, ep->desc);
+       if (ret)
+               return ret;
+
+       ep->enabled = true;
+
+       return 0;
 }
 
 /**
@@ -281,7 +293,18 @@ static inline int usb_ep_enable(struct usb_ep *ep)
  */
 static inline int usb_ep_disable(struct usb_ep *ep)
 {
-       return ep->ops->disable(ep);
+       int ret;
+
+       if (!ep->enabled)
+               return 0;
+
+       ret = ep->ops->disable(ep);
+       if (ret)
+               return ret;
+
+       ep->enabled = false;
+
+       return 0;
 }
 
 /**
@@ -1233,6 +1256,8 @@ extern struct usb_ep *usb_ep_autoconfig_ss(struct usb_gadget *,
                        struct usb_endpoint_descriptor *,
                        struct usb_ss_ep_comp_descriptor *);
 
+extern void usb_ep_autoconfig_release(struct usb_ep *);
+
 extern void usb_ep_autoconfig_reset(struct usb_gadget *);
 
 #endif /* __LINUX_USB_GADGET_H */
index d2784c10bfe2ce23dfcd64d773dbe3beaeb34c22..f89c24bd53a4cc071db1d1fc8c585f8a07cc696b 100644 (file)
  *
  * Since "struct usb_bus" is so thin, you can't share much code in it.
  * This framework is a layer over that, and should be more sharable.
- *
- * @authorized_default: Specifies if new devices are authorized to
- *                      connect by default or they require explicit
- *                      user space authorization; this bit is settable
- *                      through /sys/class/usb_host/X/authorized_default.
- *                      For the rest is RO, so we don't lock to r/w it.
  */
 
 /*-------------------------------------------------------------------------*/
@@ -120,6 +114,8 @@ struct usb_hcd {
 #define HCD_FLAG_WAKEUP_PENDING                4       /* root hub is resuming? */
 #define HCD_FLAG_RH_RUNNING            5       /* root hub is running? */
 #define HCD_FLAG_DEAD                  6       /* controller has died? */
+#define HCD_FLAG_INTF_AUTHORIZED       7       /* authorize interfaces? */
+#define HCD_FLAG_DEV_AUTHORIZED                8       /* authorize devices? */
 
        /* The flags can be tested using these macros; they are likely to
         * be slightly faster than test_bit().
@@ -131,6 +127,22 @@ struct usb_hcd {
 #define HCD_RH_RUNNING(hcd)    ((hcd)->flags & (1U << HCD_FLAG_RH_RUNNING))
 #define HCD_DEAD(hcd)          ((hcd)->flags & (1U << HCD_FLAG_DEAD))
 
+       /*
+        * Specifies if interfaces are authorized by default
+        * or they require explicit user space authorization; this bit is
+        * settable through /sys/class/usb_host/X/interface_authorized_default
+        */
+#define HCD_INTF_AUTHORIZED(hcd) \
+       ((hcd)->flags & (1U << HCD_FLAG_INTF_AUTHORIZED))
+
+       /*
+        * Specifies if devices are authorized by default
+        * or they require explicit user space authorization; this bit is
+        * settable through /sys/class/usb_host/X/authorized_default
+        */
+#define HCD_DEV_AUTHORIZED(hcd) \
+       ((hcd)->flags & (1U << HCD_FLAG_DEV_AUTHORIZED))
+
        /* Flags that get set only during HCD registration or removal. */
        unsigned                rh_registered:1;/* is root hub registered? */
        unsigned                rh_pollable:1;  /* may we poll the root hub? */
@@ -141,7 +153,6 @@ struct usb_hcd {
         * support the new root-hub polling mechanism. */
        unsigned                uses_new_polling:1;
        unsigned                wireless:1;     /* Wireless USB HCD */
-       unsigned                authorized_default:1;
        unsigned                has_tt:1;       /* Integrated TT in root hub */
        unsigned                amd_resume_bug:1; /* AMD remote wakeup quirk */
        unsigned                can_do_streams:1; /* HC supports streams */
@@ -239,6 +250,7 @@ struct hc_driver {
 #define        HCD_USB2        0x0020          /* USB 2.0 */
 #define        HCD_USB25       0x0030          /* Wireless USB 1.0 (USB 2.5)*/
 #define        HCD_USB3        0x0040          /* USB 3.0 */
+#define        HCD_USB31       0x0050          /* USB 3.1 */
 #define        HCD_MASK        0x0070
 #define        HCD_BH          0x0100          /* URB complete in BH context */
 
index a4ee1b582183119557ccc2b59b3d188ad173d8e6..fa6dc132bd1b9b298ee2503871e245a4aa37de94 100644 (file)
@@ -95,7 +95,7 @@ struct musb_hdrc_config {
        /* musb CLKIN in Blackfin in MHZ */
        unsigned char   clkin;
 #endif
-
+       u32             maximum_speed;
 };
 
 struct musb_hdrc_platform_data {
index 8c5a818ec2447aca31ce542e1cbb087f7b6fb04e..c3fe9e48ce27cb251e069247e0dec09b9848a09d 100644 (file)
 #include <linux/usb/phy.h>
 
 #if IS_ENABLED(CONFIG_OF)
-enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np);
-enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np);
 bool of_usb_host_tpl_support(struct device_node *np);
 int of_usb_update_otg_caps(struct device_node *np,
                        struct usb_otg_caps *otg_caps);
 #else
-static inline enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np)
-{
-       return USB_DR_MODE_UNKNOWN;
-}
-
-static inline enum usb_device_speed
-of_usb_get_maximum_speed(struct device_node *np)
-{
-       return USB_SPEED_UNKNOWN;
-}
 static inline bool of_usb_host_tpl_support(struct device_node *np)
 {
        return false;
index bd1dcf8161009d78153082c23e7890a57f1b6b4f..67929df86df5df44ffb3db4fd89ad0a317a6c3cd 100644 (file)
@@ -119,4 +119,13 @@ enum usb_dr_mode {
        USB_DR_MODE_OTG,
 };
 
+/**
+ * usb_get_dr_mode - Get dual role mode for given device
+ * @dev: Pointer to the given device
+ *
+ * The function gets phy interface string from property 'dr_mode',
+ * and returns the correspondig enum usb_dr_mode
+ */
+extern enum usb_dr_mode usb_get_dr_mode(struct device *dev);
+
 #endif /* __LINUX_USB_OTG_H */
index e39f251cf861e08483a411493fd5030d2bf319dc..31a8068c42a56aded5bbdf0d779eebc5b9d628c2 100644 (file)
@@ -63,7 +63,7 @@ enum usb_otg_state {
 struct usb_phy;
 struct usb_otg;
 
-/* for transceivers connected thru an ULPI interface, the user must
+/* for phys connected thru an ULPI interface, the user must
  * provide access ops
  */
 struct usb_phy_io_ops {
@@ -92,10 +92,10 @@ struct usb_phy {
        u16                     port_status;
        u16                     port_change;
 
-       /* to support controllers that have multiple transceivers */
+       /* to support controllers that have multiple phys */
        struct list_head        head;
 
-       /* initialize/shutdown the OTG controller */
+       /* initialize/shutdown the phy */
        int     (*init)(struct usb_phy *x);
        void    (*shutdown)(struct usb_phy *x);
 
@@ -106,7 +106,7 @@ struct usb_phy {
        int     (*set_power)(struct usb_phy *x,
                                unsigned mA);
 
-       /* Set transceiver into suspend mode */
+       /* Set phy into suspend mode */
        int     (*set_suspend)(struct usb_phy *x,
                                int suspend);
 
index f7adc6e01f9ea4544363d6f1bfa446854c813dec..4338eb7b09b3ad705f766fa1c3e1f8a100ae049e 100644 (file)
@@ -866,6 +866,35 @@ struct usb_ss_container_id_descriptor {
 } __attribute__((packed));
 
 #define USB_DT_USB_SS_CONTN_ID_SIZE    20
+
+/*
+ * SuperSpeed Plus USB Capability descriptor: Defines the set of
+ * SuperSpeed Plus USB specific device level capabilities
+ */
+#define        USB_SSP_CAP_TYPE        0xa
+struct usb_ssp_cap_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDevCapabilityType;
+       __u8  bReserved;
+       __le32 bmAttributes;
+#define USB_SSP_SUBLINK_SPEED_ATTRIBS  (0x1f << 0) /* sublink speed entries */
+#define USB_SSP_SUBLINK_SPEED_IDS      (0xf << 5)  /* speed ID entries */
+       __u16  wFunctionalitySupport;
+#define USB_SSP_MIN_SUBLINK_SPEED_ATTRIBUTE_ID (0xf)
+#define USB_SSP_MIN_RX_LANE_COUNT              (0xf << 8)
+#define USB_SSP_MIN_TX_LANE_COUNT              (0xf << 12)
+       __le16 wReserved;
+       __le32 bmSublinkSpeedAttr[1]; /* list of sublink speed attrib entries */
+#define USB_SSP_SUBLINK_SPEED_SSID     (0xf)           /* sublink speed ID */
+#define USB_SSP_SUBLINK_SPEED_LSE      (0x3 << 4)      /* Lanespeed exponent */
+#define USB_SSP_SUBLINK_SPEED_ST       (0x3 << 6)      /* Sublink type */
+#define USB_SSP_SUBLINK_SPEED_RSVD     (0x3f << 8)     /* Reserved */
+#define USB_SSP_SUBLINK_SPEED_LP       (0x3 << 14)     /* Link protocol */
+#define USB_SSP_SUBLINK_SPEED_LSM      (0xff << 16)    /* Lanespeed mantissa */
+} __attribute__((packed));
+
+
 /*-------------------------------------------------------------------------*/
 
 /* USB_DT_WIRELESS_ENDPOINT_COMP:  companion descriptor associated with
index 879f9870a6bcb0c9df42ce683e1ab99041b6e932..0692d99b6d8f3076fc073e5fc8dee05b40e6740b 100644 (file)
@@ -394,7 +394,7 @@ int main (int argc, char **argv)
         *      low speed, interrupt    8 *  1     =     8
         */
        param.iterations = 1000;
-       param.length = 512;
+       param.length = 1024;
        param.vary = 512;
        param.sglen = 32;
 
@@ -454,10 +454,10 @@ usage:
                        "\t-t testnum   only run specified case\n"
                        "\t-n           no test running, show devices to be tested\n"
                        "Case arguments:\n"
-                       "\t-c iterations        default 1000\n"
-                       "\t-s packetsize        default 512\n"
-                       "\t-g sglen     default 32\n"
-                       "\t-v vary              default 512\n",
+                       "\t-c iterations                default 1000\n"
+                       "\t-s transfer length   default 1024\n"
+                       "\t-g sglen             default 32\n"
+                       "\t-v vary                      default 512\n",
                        argv[0]);
                return 1;
        }
index 05c6d15856eb649d1b1e46e685988ebb1accdb46..9db9d21bb2ecee75c89c027ccb07cfdeb21062de 100644 (file)
@@ -47,7 +47,9 @@ static int detach_port(char *port)
        uint8_t portnum;
        char path[PATH_MAX+1];
 
-       for (unsigned int i = 0; i < strlen(port); i++)
+       unsigned int port_len = strlen(port);
+
+       for (unsigned int i = 0; i < port_len; i++)
                if (!isdigit(port[i])) {
                        err("invalid port %s", port);
                        return -1;