]> Pileus Git - ~andy/linux/commitdiff
Merge tag 'usb-3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 29 Apr 2013 19:19:23 +0000 (12:19 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 29 Apr 2013 19:19:23 +0000 (12:19 -0700)
Pull USB patches from Greg Kroah-Hartman:
 "Here's the big USB pull request for 3.10-rc1.

  Lots of USB patches here, the majority being USB gadget changes and
  USB-serial driver cleanups, the rest being ARM build fixes / cleanups,
  and individual driver updates.  We also finally got some chipidea
  fixes, which have been delayed for a number of kernel releases, as the
  maintainer has now reappeared.

  All of these have been in linux-next for a while"

* tag 'usb-3.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (568 commits)
  USB: ehci-msm: USB_MSM_OTG needs USB_PHY
  USB: OHCI: avoid conflicting platform drivers
  USB: OMAP: ISP1301 needs USB_PHY
  USB: lpc32xx: ISP1301 needs USB_PHY
  USB: ftdi_sio: enable two UART ports on ST Microconnect Lite
  usb: phy: tegra: don't call into tegra-ehci directly
  usb: phy: phy core cannot yet be a module
  USB: Fix initconst in ehci driver
  usb-storage: CY7C68300A chips do not support Cypress ATACB
  USB: serial: option: Added support Olivetti Olicard 145
  USB: ftdi_sio: correct ST Micro Connect Lite PIDs
  ARM: mxs_defconfig: add CONFIG_USB_PHY
  ARM: imx_v6_v7_defconfig: add CONFIG_USB_PHY
  usb: phy: remove exported function from __init section
  usb: gadget: zero: put function instances on unbind
  usb: gadget: f_sourcesink.c: correct a copy-paste misnomer
  usb: gadget: cdc2: fix error return code in cdc_do_config()
  usb: gadget: multi: fix error return code in rndis_do_config()
  usb: gadget: f_obex: fix error return code in obex_bind()
  USB: storage: convert to use module_usb_driver()
  ...

323 files changed:
Documentation/ABI/testing/sysfs-bus-usb
Documentation/devicetree/bindings/usb/ci13xxx-imx.txt
Documentation/devicetree/bindings/usb/ehci-omap.txt [new file with mode: 0644]
Documentation/devicetree/bindings/usb/ohci-omap3.txt [new file with mode: 0644]
Documentation/devicetree/bindings/usb/omap-usb.txt
Documentation/devicetree/bindings/usb/samsung-usbphy.txt
Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt [new file with mode: 0644]
Documentation/ioctl/ioctl-number.txt
Documentation/usb/power-management.txt
arch/arm/Kconfig
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/lpc32xx_defconfig
arch/arm/configs/mxs_defconfig
arch/arm/configs/omap1_defconfig
arch/arm/mach-exynos/setup-usb-phy.c
arch/arm/mach-mmp/aspenite.c
arch/arm/mach-mmp/ttc_dkb.c
arch/arm/mach-s3c64xx/setup-usb-phy.c
arch/arm/mach-s5pv210/setup-usb-phy.c
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/board-kzm9g.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-tegra/Kconfig
arch/arm/plat-samsung/include/plat/usb-phy.h
arch/mips/Kconfig
arch/powerpc/platforms/44x/Kconfig
arch/powerpc/platforms/512x/Kconfig
arch/sh/boards/mach-ecovec24/setup.c
arch/sparc/Kconfig
drivers/Makefile
drivers/hid/usbhid/hid-core.c
drivers/net/usb/cdc_mbim.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/smsc75xx.c
drivers/net/usb/smsc95xx.c
drivers/power/Kconfig
drivers/power/pda_power.c
drivers/usb/Kconfig
drivers/usb/Makefile
drivers/usb/atm/Kconfig
drivers/usb/atm/usbatm.c
drivers/usb/chipidea/Makefile
drivers/usb/chipidea/ci.h
drivers/usb/chipidea/ci13xxx_imx.c
drivers/usb/chipidea/ci13xxx_imx.h
drivers/usb/chipidea/ci13xxx_pci.c
drivers/usb/chipidea/core.c
drivers/usb/chipidea/debug.c
drivers/usb/chipidea/debug.h
drivers/usb/chipidea/udc.c
drivers/usb/chipidea/udc.h
drivers/usb/chipidea/usbmisc_imx.c [new file with mode: 0644]
drivers/usb/chipidea/usbmisc_imx6q.c [deleted file]
drivers/usb/class/Kconfig
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-wdm.c
drivers/usb/class/usbtmc.c
drivers/usb/core/Kconfig
drivers/usb/core/devio.c
drivers/usb/core/driver.c
drivers/usb/core/generic.c
drivers/usb/core/hcd-pci.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/core/port.c
drivers/usb/core/quirks.c
drivers/usb/core/sysfs.c
drivers/usb/core/urb.c
drivers/usb/core/usb.c
drivers/usb/core/usb.h
drivers/usb/dwc3/Kconfig
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/debugfs.c
drivers/usb/dwc3/dwc3-exynos.c
drivers/usb/dwc3/dwc3-omap.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/Makefile
drivers/usb/gadget/acm_ms.c
drivers/usb/gadget/amd5536udc.c
drivers/usb/gadget/amd5536udc.h
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/atmel_usba_udc.c
drivers/usb/gadget/atmel_usba_udc.h
drivers/usb/gadget/bcm63xx_udc.c
drivers/usb/gadget/cdc2.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/configfs.c [new file with mode: 0644]
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/ether.c
drivers/usb/gadget/f_acm.c
drivers/usb/gadget/f_ecm.c
drivers/usb/gadget/f_eem.c
drivers/usb/gadget/f_ncm.c
drivers/usb/gadget/f_obex.c
drivers/usb/gadget/f_rndis.c
drivers/usb/gadget/f_serial.c
drivers/usb/gadget/f_sourcesink.c
drivers/usb/gadget/f_subset.c
drivers/usb/gadget/f_uvc.c
drivers/usb/gadget/f_uvc.h
drivers/usb/gadget/fsl_qe_udc.c
drivers/usb/gadget/fsl_udc_core.c
drivers/usb/gadget/fusb300_udc.c
drivers/usb/gadget/fusb300_udc.h
drivers/usb/gadget/g_ffs.c
drivers/usb/gadget/goku_udc.c
drivers/usb/gadget/goku_udc.h
drivers/usb/gadget/imx_udc.c
drivers/usb/gadget/lpc32xx_udc.c
drivers/usb/gadget/m66592-udc.c
drivers/usb/gadget/multi.c
drivers/usb/gadget/mv_u3d_core.c
drivers/usb/gadget/mv_udc.h
drivers/usb/gadget/mv_udc_core.c
drivers/usb/gadget/ncm.c
drivers/usb/gadget/net2272.c
drivers/usb/gadget/net2280.c
drivers/usb/gadget/nokia.c
drivers/usb/gadget/omap_udc.c
drivers/usb/gadget/pch_udc.c
drivers/usb/gadget/pxa25x_udc.c
drivers/usb/gadget/pxa27x_udc.c
drivers/usb/gadget/r8a66597-udc.c
drivers/usb/gadget/s3c-hsotg.c
drivers/usb/gadget/s3c-hsudc.c
drivers/usb/gadget/s3c2410_udc.c
drivers/usb/gadget/serial.c
drivers/usb/gadget/u_ether.c
drivers/usb/gadget/u_ether.h
drivers/usb/gadget/u_serial.h
drivers/usb/gadget/udc-core.c
drivers/usb/gadget/uvc.h
drivers/usb/gadget/uvc_queue.c
drivers/usb/gadget/uvc_queue.h
drivers/usb/gadget/uvc_v4l2.c
drivers/usb/gadget/uvc_video.c
drivers/usb/gadget/zero.c
drivers/usb/host/Kconfig
drivers/usb/host/Makefile
drivers/usb/host/ehci-atmel.c
drivers/usb/host/ehci-dbg.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-msm.c
drivers/usb/host/ehci-mv.c
drivers/usb/host/ehci-mxc.c
drivers/usb/host/ehci-omap.c
drivers/usb/host/ehci-orion.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ehci-platform.c
drivers/usb/host/ehci-ps3.c
drivers/usb/host/ehci-q.c
drivers/usb/host/ehci-s5p.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci-sh.c
drivers/usb/host/ehci-spear.c
drivers/usb/host/ehci-tegra.c
drivers/usb/host/ehci-timer.c
drivers/usb/host/ehci-vt8500.c [deleted file]
drivers/usb/host/ehci.h
drivers/usb/host/ohci-exynos.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-hub.c
drivers/usb/host/ohci-omap3.c
drivers/usb/host/sl811-hcd.c
drivers/usb/host/u132-hcd.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/image/Kconfig
drivers/usb/misc/Kconfig
drivers/usb/misc/appledisplay.c
drivers/usb/misc/sisusbvga/Kconfig
drivers/usb/misc/sisusbvga/sisusb.c
drivers/usb/misc/usb3503.c
drivers/usb/mon/Kconfig
drivers/usb/musb/Kconfig
drivers/usb/musb/am35x.c
drivers/usb/musb/blackfin.c
drivers/usb/musb/cppi_dma.c
drivers/usb/musb/da8xx.c
drivers/usb/musb/davinci.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_dsps.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/musb_gadget_ep0.c
drivers/usb/musb/musb_host.c
drivers/usb/musb/musb_virthub.c
drivers/usb/musb/omap2430.c
drivers/usb/musb/tusb6010.c
drivers/usb/musb/ux500.c
drivers/usb/musb/ux500_dma.c
drivers/usb/otg/Kconfig [deleted file]
drivers/usb/otg/Makefile [deleted file]
drivers/usb/otg/ab8500-usb.c [deleted file]
drivers/usb/phy/Kconfig
drivers/usb/phy/Makefile
drivers/usb/phy/isp1301.c [deleted file]
drivers/usb/phy/phy-ab8500-usb.c [new file with mode: 0644]
drivers/usb/phy/phy-fsl-usb.c [moved from drivers/usb/otg/fsl_otg.c with 97% similarity]
drivers/usb/phy/phy-fsl-usb.h [moved from drivers/usb/otg/fsl_otg.h with 100% similarity]
drivers/usb/phy/phy-fsm-usb.c [moved from drivers/usb/otg/otg_fsm.c with 99% similarity]
drivers/usb/phy/phy-fsm-usb.h [moved from drivers/usb/otg/otg_fsm.h with 100% similarity]
drivers/usb/phy/phy-gpio-vbus-usb.c [moved from drivers/usb/otg/gpio_vbus.c with 98% similarity]
drivers/usb/phy/phy-isp1301-omap.c [moved from drivers/usb/otg/isp1301_omap.c with 99% similarity]
drivers/usb/phy/phy-isp1301.c [new file with mode: 0644]
drivers/usb/phy/phy-msm-usb.c [moved from drivers/usb/otg/msm_otg.c with 100% similarity]
drivers/usb/phy/phy-mv-u3d-usb.c [moved from drivers/usb/phy/mv_u3d_phy.c with 99% similarity]
drivers/usb/phy/phy-mv-u3d-usb.h [moved from drivers/usb/phy/mv_u3d_phy.h with 100% similarity]
drivers/usb/phy/phy-mv-usb.c [moved from drivers/usb/otg/mv_otg.c with 97% similarity]
drivers/usb/phy/phy-mv-usb.h [moved from drivers/usb/otg/mv_otg.h with 99% similarity]
drivers/usb/phy/phy-mxs-usb.c [moved from drivers/usb/otg/mxs-phy.c with 84% similarity]
drivers/usb/phy/phy-nop.c [moved from drivers/usb/otg/nop-usb-xceiv.c with 55% similarity]
drivers/usb/phy/phy-omap-control.c [moved from drivers/usb/phy/omap-control-usb.c with 100% similarity]
drivers/usb/phy/phy-omap-usb2.c [moved from drivers/usb/phy/omap-usb2.c with 100% similarity]
drivers/usb/phy/phy-omap-usb3.c [moved from drivers/usb/phy/omap-usb3.c with 100% similarity]
drivers/usb/phy/phy-rcar-usb.c [moved from drivers/usb/phy/rcar-phy.c with 100% similarity]
drivers/usb/phy/phy-samsung-usb.c [new file with mode: 0644]
drivers/usb/phy/phy-samsung-usb.h [new file with mode: 0644]
drivers/usb/phy/phy-samsung-usb2.c [new file with mode: 0644]
drivers/usb/phy/phy-samsung-usb3.c [new file with mode: 0644]
drivers/usb/phy/phy-tegra-usb.c [moved from drivers/usb/phy/tegra_usb_phy.c with 98% similarity]
drivers/usb/phy/phy-twl4030-usb.c [moved from drivers/usb/otg/twl4030-usb.c with 84% similarity]
drivers/usb/phy/phy-twl6030-usb.c [moved from drivers/usb/otg/twl6030-usb.c with 97% similarity]
drivers/usb/phy/phy-ulpi-viewport.c [moved from drivers/usb/otg/ulpi_viewport.c with 100% similarity]
drivers/usb/phy/phy-ulpi.c [moved from drivers/usb/otg/ulpi.c with 100% similarity]
drivers/usb/phy/phy.c [moved from drivers/usb/otg/otg.c with 88% similarity]
drivers/usb/phy/samsung-usbphy.c [deleted file]
drivers/usb/renesas_usbhs/Kconfig
drivers/usb/renesas_usbhs/fifo.c
drivers/usb/renesas_usbhs/fifo.h
drivers/usb/renesas_usbhs/mod_gadget.c
drivers/usb/serial/Kconfig
drivers/usb/serial/Makefile
drivers/usb/serial/ark3116.c
drivers/usb/serial/bus.c
drivers/usb/serial/ch341.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/cyberjack.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/f81232.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/garmin_gps.c
drivers/usb/serial/generic.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/io_tables.h
drivers/usb/serial/io_ti.c
drivers/usb/serial/iuu_phoenix.c
drivers/usb/serial/keyspan.c
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/kobil_sct.c
drivers/usb/serial/mct_u232.c
drivers/usb/serial/metro-usb.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/omninet.c
drivers/usb/serial/opticon.c
drivers/usb/serial/option.c
drivers/usb/serial/oti6858.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/quatech2.c
drivers/usb/serial/sierra.c
drivers/usb/serial/spcp8x5.c
drivers/usb/serial/ssu100.c
drivers/usb/serial/symbolserial.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb-serial.c
drivers/usb/serial/usb_wwan.c
drivers/usb/serial/visor.c
drivers/usb/serial/wishbone-serial.c [new file with mode: 0644]
drivers/usb/storage/Kconfig
drivers/usb/storage/alauda.c
drivers/usb/storage/cypress_atacb.c
drivers/usb/storage/datafab.c
drivers/usb/storage/debug.c
drivers/usb/storage/debug.h
drivers/usb/storage/ene_ub6250.c
drivers/usb/storage/freecom.c
drivers/usb/storage/initializers.c
drivers/usb/storage/isd200.c
drivers/usb/storage/jumpshot.c
drivers/usb/storage/karma.c
drivers/usb/storage/onetouch.c
drivers/usb/storage/option_ms.c
drivers/usb/storage/realtek_cr.c
drivers/usb/storage/scsiglue.c
drivers/usb/storage/sddr09.c
drivers/usb/storage/sddr55.c
drivers/usb/storage/shuttle_usbat.c
drivers/usb/storage/sierra_ms.c
drivers/usb/storage/transport.c
drivers/usb/storage/usb.c
drivers/usb/usb-common.c
drivers/usb/usb-skeleton.c
drivers/usb/wusbcore/Kconfig
include/linux/platform_data/dwc3-omap.h
include/linux/platform_data/mv_usb.h
include/linux/usb.h
include/linux/usb/cdc-wdm.h
include/linux/usb/ch9.h
include/linux/usb/composite.h
include/linux/usb/dwc3-omap.h
include/linux/usb/gadget.h
include/linux/usb/gadget_configfs.h [new file with mode: 0644]
include/linux/usb/hcd.h
include/linux/usb/musb-ux500.h [new file with mode: 0644]
include/linux/usb/nop-usb-xceiv.h
include/linux/usb/otg.h
include/linux/usb/phy.h
include/linux/usb/renesas_usbhs.h
include/linux/usb/serial.h
include/linux/usb/tegra_usb_phy.h
include/uapi/linux/usb/cdc-wdm.h [new file with mode: 0644]
include/uapi/linux/usb/ch9.h

index c8baaf53594a862fb8be7fadd880cb534de8acea..f093e59cbe5f017531b74ce45dcc3d130ddfd44d 100644 (file)
@@ -32,7 +32,7 @@ Date:         January 2008
 KernelVersion: 2.6.25
 Contact:       Sarah Sharp <sarah.a.sharp@intel.com>
 Description:
-               If CONFIG_PM and CONFIG_USB_SUSPEND are enabled, then this file
+               If CONFIG_PM_RUNTIME is enabled then this file
                is present.  When read, it returns the total time (in msec)
                that the USB device has been connected to the machine.  This
                file is read-only.
@@ -45,7 +45,7 @@ Date:         January 2008
 KernelVersion: 2.6.25
 Contact:       Sarah Sharp <sarah.a.sharp@intel.com>
 Description:
-               If CONFIG_PM and CONFIG_USB_SUSPEND are enabled, then this file
+               If CONFIG_PM_RUNTIME is enabled then this file
                is present.  When read, it returns the total time (in msec)
                that the USB device has been active, i.e. not in a suspended
                state.  This file is read-only.
@@ -187,7 +187,7 @@ What:               /sys/bus/usb/devices/.../power/usb2_hardware_lpm
 Date:          September 2011
 Contact:       Andiry Xu <andiry.xu@amd.com>
 Description:
-               If CONFIG_USB_SUSPEND is set and a USB 2.0 lpm-capable device
+               If CONFIG_PM_RUNTIME is set and a USB 2.0 lpm-capable device
                is plugged in to a xHCI host which support link PM, it will
                perform a LPM test; if the test is passed and host supports
                USB2 hardware LPM (xHCI 1.0 feature), USB2 hardware LPM will
index 5778b9c83bd845692a4eda281ec842eb1864ac6e..1c04a4c9515f981e570fe778b748bfeb3d5b3e92 100644 (file)
@@ -11,6 +11,7 @@ Optional properties:
   that indicate usb controller index
 - vbus-supply: regulator for vbus
 - disable-over-current: disable over current detect
+- external-vbus-divider: enables off-chip resistor divider for Vbus
 
 Examples:
 usb@02184000 { /* USB OTG */
@@ -20,4 +21,5 @@ usb@02184000 { /* USB OTG */
        fsl,usbphy = <&usbphy1>;
        fsl,usbmisc = <&usbmisc 0>;
        disable-over-current;
+       external-vbus-divider;
 };
diff --git a/Documentation/devicetree/bindings/usb/ehci-omap.txt b/Documentation/devicetree/bindings/usb/ehci-omap.txt
new file mode 100644 (file)
index 0000000..485a9a1
--- /dev/null
@@ -0,0 +1,32 @@
+OMAP HS USB EHCI controller
+
+This device is usually the child of the omap-usb-host
+Documentation/devicetree/bindings/mfd/omap-usb-host.txt
+
+Required properties:
+
+- compatible: should be "ti,ehci-omap"
+- reg: should contain one register range i.e. start and length
+- interrupts: description of the interrupt line
+
+Optional properties:
+
+- phys: list of phandles to PHY nodes.
+  This property is required if at least one of the ports are in
+  PHY mode i.e. OMAP_EHCI_PORT_MODE_PHY
+
+To specify the port mode, see
+Documentation/devicetree/bindings/mfd/omap-usb-host.txt
+
+Example for OMAP4:
+
+usbhsehci: ehci@4a064c00 {
+       compatible = "ti,ehci-omap", "usb-ehci";
+       reg = <0x4a064c00 0x400>;
+       interrupts = <0 77 0x4>;
+};
+
+&usbhsehci {
+       phys = <&hsusb1_phy 0 &hsusb3_phy>;
+};
+
diff --git a/Documentation/devicetree/bindings/usb/ohci-omap3.txt b/Documentation/devicetree/bindings/usb/ohci-omap3.txt
new file mode 100644 (file)
index 0000000..14ab428
--- /dev/null
@@ -0,0 +1,15 @@
+OMAP HS USB OHCI controller (OMAP3 and later)
+
+Required properties:
+
+- compatible: should be "ti,ohci-omap3"
+- reg: should contain one register range i.e. start and length
+- interrupts: description of the interrupt line
+
+Example for OMAP4:
+
+usbhsohci: ohci@4a064800 {
+       compatible = "ti,ohci-omap3", "usb-ohci";
+       reg = <0x4a064800 0x400>;
+       interrupts = <0 76 0x4>;
+};
index 1ef0ce71f8faa0f00bb0e459c7c94a36d6abdb1b..662f0f1d23150b236bb9c5af15a376a0052afc39 100644 (file)
@@ -8,10 +8,10 @@ OMAP MUSB GLUE
    and disconnect.
  - multipoint : Should be "1" indicating the musb controller supports
    multipoint. This is a MUSB configuration-specific setting.
- - num_eps : Specifies the number of endpoints. This is also a
+ - num-eps : Specifies the number of endpoints. This is also a
    MUSB configuration-specific setting. Should be set to "16"
- - ram_bits : Specifies the ram address size. Should be set to "12"
- - interface_type : This is a board specific setting to describe the type of
+ - ram-bits : Specifies the ram address size. Should be set to "12"
+ - interface-type : This is a board specific setting to describe the type of
    interface between the controller and the phy. It should be "0" or "1"
    specifying ULPI and UTMI respectively.
  - mode : Should be "3" to represent OTG. "1" signifies HOST and "2"
@@ -29,18 +29,46 @@ usb_otg_hs: usb_otg_hs@4a0ab000 {
        ti,hwmods = "usb_otg_hs";
        ti,has-mailbox;
        multipoint = <1>;
-       num_eps = <16>;
-       ram_bits = <12>;
+       num-eps = <16>;
+       ram-bits = <12>;
        ctrl-module = <&omap_control_usb>;
 };
 
 Board specific device node entry
 &usb_otg_hs {
-       interface_type = <1>;
+       interface-type = <1>;
        mode = <3>;
        power = <50>;
 };
 
+OMAP DWC3 GLUE
+ - compatible : Should be "ti,dwc3"
+ - ti,hwmods : Should be "usb_otg_ss"
+ - reg : Address and length of the register set for the device.
+ - interrupts : The irq number of this device that is used to interrupt the
+   MPU
+ - #address-cells, #size-cells : Must be present if the device has sub-nodes
+ - utmi-mode : controls the source of UTMI/PIPE status for VBUS and OTG ID.
+   It should be set to "1" for HW mode and "2" for SW mode.
+ - ranges: the child address space are mapped 1:1 onto the parent address space
+
+Sub-nodes:
+The dwc3 core should be added as subnode to omap dwc3 glue.
+- dwc3 :
+   The binding details of dwc3 can be found in:
+   Documentation/devicetree/bindings/usb/dwc3.txt
+
+omap_dwc3 {
+       compatible = "ti,dwc3";
+       ti,hwmods = "usb_otg_ss";
+       reg = <0x4a020000 0x1ff>;
+       interrupts = <0 93 4>;
+       #address-cells = <1>;
+       #size-cells = <1>;
+       utmi-mode = <2>;
+       ranges;
+};
+
 OMAP CONTROL USB
 
 Required properties:
index 033194934f64287f84f152ec13acce2739d4cf0d..f575302e5173032143347644c0c29b9591936cc9 100644 (file)
@@ -1,20 +1,25 @@
-* Samsung's usb phy transceiver
+SAMSUNG USB-PHY controllers
 
-The Samsung's phy transceiver is used for controlling usb phy for
-s3c-hsotg as well as ehci-s5p and ohci-exynos usb controllers
-across Samsung SOCs.
+** Samsung's usb 2.0 phy transceiver
+
+The Samsung's usb 2.0 phy transceiver is used for controlling
+usb 2.0 phy for s3c-hsotg as well as ehci-s5p and ohci-exynos
+usb controllers across Samsung SOCs.
 TODO: Adding the PHY binding with controller(s) according to the under
 developement generic PHY driver.
 
 Required properties:
 
 Exynos4210:
-- compatible : should be "samsung,exynos4210-usbphy"
+- compatible : should be "samsung,exynos4210-usb2phy"
 - reg : base physical address of the phy registers and length of memory mapped
        region.
+- clocks: Clock IDs array as required by the controller.
+- clock-names: names of clock correseponding IDs clock property as requested
+              by the controller driver.
 
 Exynos5250:
-- compatible : should be "samsung,exynos5250-usbphy"
+- compatible : should be "samsung,exynos5250-usb2phy"
 - reg : base physical address of the phy registers and length of memory mapped
        region.
 
@@ -44,12 +49,69 @@ Example:
        usbphy@125B0000 {
                #address-cells = <1>;
                #size-cells = <1>;
-               compatible = "samsung,exynos4210-usbphy";
+               compatible = "samsung,exynos4210-usb2phy";
                reg = <0x125B0000 0x100>;
                ranges;
 
+               clocks = <&clock 2>, <&clock 305>;
+               clock-names = "xusbxti", "otg";
+
                usbphy-sys {
                        /* USB device and host PHY_CONTROL registers */
                        reg = <0x10020704 0x8>;
                };
        };
+
+
+** Samsung's usb 3.0 phy transceiver
+
+Starting exynso5250, Samsung's SoC have usb 3.0 phy transceiver
+which is used for controlling usb 3.0 phy for dwc3-exynos usb 3.0
+controllers across Samsung SOCs.
+
+Required properties:
+
+Exynos5250:
+- compatible : should be "samsung,exynos5250-usb3phy"
+- reg : base physical address of the phy registers and length of memory mapped
+       region.
+- clocks: Clock IDs array as required by the controller.
+- clock-names: names of clocks correseponding to IDs in the clock property
+              as requested by the controller driver.
+
+Optional properties:
+- #address-cells: should be '1' when usbphy node has a child node with 'reg'
+                 property.
+- #size-cells: should be '1' when usbphy node has a child node with 'reg'
+              property.
+- ranges: allows valid translation between child's address space and parent's
+         address space.
+
+- The child node 'usbphy-sys' to the node 'usbphy' is for the system controller
+  interface for usb-phy. It should provide the following information required by
+  usb-phy controller to control phy.
+  - reg : base physical address of PHY_CONTROL registers.
+         The size of this register is the total sum of size of all PHY_CONTROL
+         registers that the SoC has. For example, the size will be
+         '0x4' in case we have only one PHY_CONTROL register (e.g.
+         OTHERS register in S3C64XX or USB_PHY_CONTROL register in S5PV210)
+         and, '0x8' in case we have two PHY_CONTROL registers (e.g.
+         USBDEVICE_PHY_CONTROL and USBHOST_PHY_CONTROL registers in exynos4x).
+         and so on.
+
+Example:
+       usbphy@12100000 {
+               compatible = "samsung,exynos5250-usb3phy";
+               reg = <0x12100000 0x100>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               clocks = <&clock 1>, <&clock 286>;
+               clock-names = "ext_xtal", "usbdrd30";
+
+               usbphy-sys {
+                       /* USB device and host PHY_CONTROL registers */
+                       reg = <0x10040704 0x8>;
+               };
+       };
diff --git a/Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt b/Documentation/devicetree/bindings/usb/usb-nop-xceiv.txt
new file mode 100644 (file)
index 0000000..d7e2726
--- /dev/null
@@ -0,0 +1,34 @@
+USB NOP PHY
+
+Required properties:
+- compatible: should be usb-nop-xceiv
+
+Optional properties:
+- clocks: phandle to the PHY clock. Use as per Documentation/devicetree
+  /bindings/clock/clock-bindings.txt
+  This property is required if clock-frequency is specified.
+
+- clock-names: Should be "main_clk"
+
+- clock-frequency: the clock frequency (in Hz) that the PHY clock must
+  be configured to.
+
+- vcc-supply: phandle to the regulator that provides RESET to the PHY.
+
+- reset-supply: phandle to the regulator that provides power to the PHY.
+
+Example:
+
+       hsusb1_phy {
+               compatible = "usb-nop-xceiv";
+               clock-frequency = <19200000>;
+               clocks = <&osc 0>;
+               clock-names = "main_clk";
+               vcc-supply = <&hsusb1_vcc_regulator>;
+               reset-supply = <&hsusb1_reset_regulator>;
+       };
+
+hsusb1_phy is a NOP USB PHY device that gets its clock from an oscillator
+and expects that clock to be configured to 19.2MHz by the NOP PHY driver.
+hsusb1_vcc_regulator provides power to the PHY and hsusb1_reset_regulator
+controls RESET.
index 3210540f8bd355d3e8dd8171f6c71d932abc6df4..237acab169dd723b5a3f9ec3e40c79d55246f48a 100644 (file)
@@ -131,6 +131,7 @@ Code  Seq#(hex)     Include File            Comments
 'H'    40-4F   sound/hdspm.h           conflict!
 'H'    40-4F   sound/hdsp.h            conflict!
 'H'    90      sound/usb/usx2y/usb_stream.h
+'H'    A0      uapi/linux/usb/cdc-wdm.h
 'H'    C0-F0   net/bluetooth/hci.h     conflict!
 'H'    C0-DF   net/bluetooth/hidp/hidp.h       conflict!
 'H'    C0-DF   net/bluetooth/cmtp/cmtp.h       conflict!
index 4204eb01fd3839187da2d20654a39f1f9a134b7e..1392b61d6ebe59c87bbe616cc4a9796cba9a160f 100644 (file)
@@ -33,6 +33,10 @@ built with CONFIG_USB_SUSPEND enabled (which depends on
 CONFIG_PM_RUNTIME).  System PM support is present only if the kernel
 was built with CONFIG_SUSPEND or CONFIG_HIBERNATION enabled.
 
+(Starting with the 3.10 kernel release, dynamic PM support for USB is
+present whenever the kernel was built with CONFIG_PM_RUNTIME enabled.
+The CONFIG_USB_SUSPEND option has been eliminated.)
+
 
        What is Remote Wakeup?
        ----------------------
@@ -206,10 +210,8 @@ initialized to 5.  (The idle-delay values for already existing devices
 will not be affected.)
 
 Setting the initial default idle-delay to -1 will prevent any
-autosuspend of any USB device.  This is a simple alternative to
-disabling CONFIG_USB_SUSPEND and rebuilding the kernel, and it has the
-added benefit of allowing you to enable autosuspend for selected
-devices.
+autosuspend of any USB device.  This has the benefit of allowing you
+then to enable autosuspend for selected devices.
 
 
        Warnings
index 1cacda426a0ea6699528dd0eeedf83032825e09e..bbddefea77bbb63ad11edfec2931ed4b4972ac0f 100644 (file)
@@ -549,6 +549,8 @@ config ARCH_IXP4XX
        select GENERIC_CLOCKEVENTS
        select MIGHT_HAVE_PCI
        select NEED_MACH_IO_H
+       select USB_EHCI_BIG_ENDIAN_MMIO
+       select USB_EHCI_BIG_ENDIAN_DESC
        help
          Support for Intel's IXP4XX (XScale) family of processors.
 
index e36b01025321112439ef6b53b585ec8073b0cb73..088d6c11a0fa1cb896cf9e2c04351d9382b98b17 100644 (file)
@@ -188,6 +188,7 @@ CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MXC=y
 CONFIG_USB_CHIPIDEA=y
 CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_USB_PHY=y
 CONFIG_USB_MXS_PHY=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
index 92386b20bd096cf27a9410c29e8e8822d2554964..afa7249fac6e57d9ed6dc99e31863d493b2c500d 100644 (file)
@@ -134,6 +134,7 @@ CONFIG_SND_DEBUG_VERBOSE=y
 # CONFIG_SND_SPI is not set
 CONFIG_SND_SOC=y
 CONFIG_USB=y
+CONFIG_USB_PHY=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
index 6a99e30f81d2ac992da503ba5338571c2d2731ba..87924d671115928509d5bd360f1ea92a8c50acc6 100644 (file)
@@ -120,6 +120,7 @@ CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_CHIPIDEA=y
 CONFIG_USB_CHIPIDEA_HOST=y
 CONFIG_USB_STORAGE=y
+CONFIG_USB_PHY=y
 CONFIG_USB_MXS_PHY=y
 CONFIG_MMC=y
 CONFIG_MMC_MXS=y
index 42eab9a2a0fd53ba4cb26eb36c1a7a7c29909587..7e0ebb64a7f9dafe5c73b9201c39e344c309ef93 100644 (file)
@@ -195,6 +195,7 @@ CONFIG_SND_SOC=y
 CONFIG_SND_OMAP_SOC=y
 # CONFIG_USB_HID is not set
 CONFIG_USB=y
+CONFIG_USB_PHY=y
 CONFIG_USB_DEBUG=y
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_DEVICE_CLASS is not set
index b81cc569a8ddab4e7a247752297b1b4fac732542..6af40662a4495691da35dda9d267b485387cfe43 100644 (file)
@@ -204,9 +204,9 @@ static int exynos4210_usb_phy1_exit(struct platform_device *pdev)
 
 int s5p_usb_phy_init(struct platform_device *pdev, int type)
 {
-       if (type == S5P_USB_PHY_DEVICE)
+       if (type == USB_PHY_TYPE_DEVICE)
                return exynos4210_usb_phy0_init(pdev);
-       else if (type == S5P_USB_PHY_HOST)
+       else if (type == USB_PHY_TYPE_HOST)
                return exynos4210_usb_phy1_init(pdev);
 
        return -EINVAL;
@@ -214,9 +214,9 @@ int s5p_usb_phy_init(struct platform_device *pdev, int type)
 
 int s5p_usb_phy_exit(struct platform_device *pdev, int type)
 {
-       if (type == S5P_USB_PHY_DEVICE)
+       if (type == USB_PHY_TYPE_DEVICE)
                return exynos4210_usb_phy0_exit(pdev);
-       else if (type == S5P_USB_PHY_HOST)
+       else if (type == USB_PHY_TYPE_HOST)
                return exynos4210_usb_phy1_exit(pdev);
 
        return -EINVAL;
index 9f64d5632e07af34ab02e2f67ed07937c98ac77b..76901f4ce611aba80c2e102700e69407dcd88772 100644 (file)
@@ -223,13 +223,7 @@ static struct pxa27x_keypad_platform_data aspenite_keypad_info __initdata = {
 };
 
 #if defined(CONFIG_USB_EHCI_MV)
-static char *pxa168_sph_clock_name[] = {
-       [0] = "PXA168-USBCLK",
-};
-
 static struct mv_usb_platform_data pxa168_sph_pdata = {
-       .clknum         = 1,
-       .clkname        = pxa168_sph_clock_name,
        .mode           = MV_USB_MODE_HOST,
        .phy_init       = pxa_usb_phy_init,
        .phy_deinit     = pxa_usb_phy_deinit,
index 22a9058f9f4de1fdf3f413596c1dc7473881c7cc..6528a5fa6a26ce924cf3538684c1f828137809d5 100644 (file)
@@ -162,13 +162,7 @@ static struct i2c_board_info ttc_dkb_i2c_info[] = {
 #ifdef CONFIG_USB_SUPPORT
 #if defined(CONFIG_USB_MV_UDC) || defined(CONFIG_USB_EHCI_MV_U2O)
 
-static char *pxa910_usb_clock_name[] = {
-       [0] = "U2OCLK",
-};
-
 static struct mv_usb_platform_data ttc_usb_pdata = {
-       .clknum         = 1,
-       .clkname        = pxa910_usb_clock_name,
        .vbus           = NULL,
        .mode           = MV_USB_MODE_OTG,
        .otg_force_a_bus_req = 1,
index c8174d95339b384e4c3584f9ca6a93ed0e3a4969..ca960bda02fdc00adde8bfeb0c9666166b1dfc8d 100644 (file)
@@ -76,7 +76,7 @@ static int s3c_usb_otgphy_exit(struct platform_device *pdev)
 
 int s5p_usb_phy_init(struct platform_device *pdev, int type)
 {
-       if (type == S5P_USB_PHY_DEVICE)
+       if (type == USB_PHY_TYPE_DEVICE)
                return s3c_usb_otgphy_init(pdev);
 
        return -EINVAL;
@@ -84,7 +84,7 @@ int s5p_usb_phy_init(struct platform_device *pdev, int type)
 
 int s5p_usb_phy_exit(struct platform_device *pdev, int type)
 {
-       if (type == S5P_USB_PHY_DEVICE)
+       if (type == USB_PHY_TYPE_DEVICE)
                return s3c_usb_otgphy_exit(pdev);
 
        return -EINVAL;
index 356a0900af03478f28e7d76831f64f61bb1949b7..b2ee5333f89cc88b09426735fad9ab97613c7c2f 100644 (file)
@@ -80,7 +80,7 @@ static int s5pv210_usb_otgphy_exit(struct platform_device *pdev)
 
 int s5p_usb_phy_init(struct platform_device *pdev, int type)
 {
-       if (type == S5P_USB_PHY_DEVICE)
+       if (type == USB_PHY_TYPE_DEVICE)
                return s5pv210_usb_otgphy_init(pdev);
 
        return -EINVAL;
@@ -88,7 +88,7 @@ int s5p_usb_phy_init(struct platform_device *pdev, int type)
 
 int s5p_usb_phy_exit(struct platform_device *pdev, int type)
 {
-       if (type == S5P_USB_PHY_DEVICE)
+       if (type == USB_PHY_TYPE_DEVICE)
                return s5pv210_usb_otgphy_exit(pdev);
 
        return -EINVAL;
index f2ec0777cfbe89ca5c998dfe1b6d581b5d5320bf..ff8b7ba9b93c9d34337f7c838c65358e2a24a3da 100644 (file)
@@ -169,7 +169,7 @@ static int usbhsf_get_id(struct platform_device *pdev)
        return USBHS_GADGET;
 }
 
-static void usbhsf_power_ctrl(struct platform_device *pdev,
+static int usbhsf_power_ctrl(struct platform_device *pdev,
                              void __iomem *base, int enable)
 {
        struct usbhsf_private *priv = usbhsf_get_priv(pdev);
@@ -223,6 +223,8 @@ static void usbhsf_power_ctrl(struct platform_device *pdev,
                clk_disable(priv->pci);         /* usb work around */
                clk_disable(priv->usb24);       /* usb work around */
        }
+
+       return 0;
 }
 
 static int usbhsf_get_vbus(struct platform_device *pdev)
@@ -239,7 +241,7 @@ static irqreturn_t usbhsf_interrupt(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-static void usbhsf_hardware_exit(struct platform_device *pdev)
+static int usbhsf_hardware_exit(struct platform_device *pdev)
 {
        struct usbhsf_private *priv = usbhsf_get_priv(pdev);
 
@@ -264,6 +266,8 @@ static void usbhsf_hardware_exit(struct platform_device *pdev)
        priv->usbh_base = NULL;
 
        free_irq(IRQ7, pdev);
+
+       return 0;
 }
 
 static int usbhsf_hardware_init(struct platform_device *pdev)
index 7f3a6b7e7b7cfdfd1697560d2e3ecb6b3a6c6f38..a385f570bbfc81b14184f0b79e58a1328361b125 100644 (file)
@@ -155,12 +155,14 @@ static int usbhs_get_vbus(struct platform_device *pdev)
        return !((1 << 7) & __raw_readw(priv->cr2));
 }
 
-static void usbhs_phy_reset(struct platform_device *pdev)
+static int usbhs_phy_reset(struct platform_device *pdev)
 {
        struct usbhs_private *priv = usbhs_get_priv(pdev);
 
        /* init phy */
        __raw_writew(0x8a0a, priv->cr2);
+
+       return 0;
 }
 
 static int usbhs_get_id(struct platform_device *pdev)
@@ -202,7 +204,7 @@ static int usbhs_hardware_init(struct platform_device *pdev)
        return 0;
 }
 
-static void usbhs_hardware_exit(struct platform_device *pdev)
+static int usbhs_hardware_exit(struct platform_device *pdev)
 {
        struct usbhs_private *priv = usbhs_get_priv(pdev);
 
@@ -210,6 +212,8 @@ static void usbhs_hardware_exit(struct platform_device *pdev)
        __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->phy);
 
        free_irq(IRQ15, pdev);
+
+       return 0;
 }
 
 static u32 usbhs_pipe_cfg[] = {
index db968a585ff0c6ab296e2416369769c7517a4796..979237c18dadac08e6a9c8d3ff41ce49ed879315 100644 (file)
@@ -596,12 +596,14 @@ static int usbhs_get_vbus(struct platform_device *pdev)
        return usbhs_is_connected(usbhs_get_priv(pdev));
 }
 
-static void usbhs_phy_reset(struct platform_device *pdev)
+static int usbhs_phy_reset(struct platform_device *pdev)
 {
        struct usbhs_private *priv = usbhs_get_priv(pdev);
 
        /* init phy */
        __raw_writew(0x8a0a, priv->usbcrcaddr);
+
+       return 0;
 }
 
 static int usbhs0_get_id(struct platform_device *pdev)
@@ -628,11 +630,13 @@ static int usbhs0_hardware_init(struct platform_device *pdev)
        return 0;
 }
 
-static void usbhs0_hardware_exit(struct platform_device *pdev)
+static int usbhs0_hardware_exit(struct platform_device *pdev)
 {
        struct usbhs_private *priv = usbhs_get_priv(pdev);
 
        cancel_delayed_work_sync(&priv->work);
+
+       return 0;
 }
 
 static struct usbhs_private usbhs0_private = {
@@ -735,7 +739,7 @@ static int usbhs1_hardware_init(struct platform_device *pdev)
        return 0;
 }
 
-static void usbhs1_hardware_exit(struct platform_device *pdev)
+static int usbhs1_hardware_exit(struct platform_device *pdev)
 {
        struct usbhs_private *priv = usbhs_get_priv(pdev);
 
@@ -743,6 +747,8 @@ static void usbhs1_hardware_exit(struct platform_device *pdev)
        __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr);
 
        free_irq(IRQ8, pdev);
+
+       return 0;
 }
 
 static int usbhs1_get_id(struct platform_device *pdev)
index d1c4893894cee26e23f1ba962c9ac45c3915f2cd..dbc653ea851c4f1a619f6d09cd779f2435fe1c76 100644 (file)
@@ -18,8 +18,8 @@ config ARCH_TEGRA_2x_SOC
        select PL310_ERRATA_727915 if CACHE_L2X0
        select PL310_ERRATA_769419 if CACHE_L2X0
        select USB_ARCH_HAS_EHCI if USB_SUPPORT
-       select USB_ULPI if USB
-       select USB_ULPI_VIEWPORT if USB_SUPPORT
+       select USB_ULPI if USB_PHY
+       select USB_ULPI_VIEWPORT if USB_PHY
        help
          Support for NVIDIA Tegra AP20 and T20 processors, based on the
          ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -37,8 +37,8 @@ config ARCH_TEGRA_3x_SOC
        select PINCTRL_TEGRA30
        select PL310_ERRATA_769419 if CACHE_L2X0
        select USB_ARCH_HAS_EHCI if USB_SUPPORT
-       select USB_ULPI if USB
-       select USB_ULPI_VIEWPORT if USB_SUPPORT
+       select USB_ULPI if USB_PHY
+       select USB_ULPI_VIEWPORT if USB_PHY
        help
          Support for NVIDIA Tegra T30 processor family, based on the
          ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
index 959bcdb03a25ffe916da39957aaec7e44efb395a..ab34dfadb7f97373604b66d7ebd68772a668c198 100644 (file)
 #ifndef __PLAT_SAMSUNG_USB_PHY_H
 #define __PLAT_SAMSUNG_USB_PHY_H __FILE__
 
-enum s5p_usb_phy_type {
-       S5P_USB_PHY_DEVICE,
-       S5P_USB_PHY_HOST,
-};
+#include <linux/usb/samsung_usb_phy.h>
 
 extern int s5p_usb_phy_init(struct platform_device *pdev, int type);
 extern int s5p_usb_phy_exit(struct platform_device *pdev, int type);
index 51244bf972718a54876e7ba2ab78ae1790c98e59..3a7b3954ce1b58075cf809a26becc2bb68dec261 100644 (file)
@@ -404,6 +404,8 @@ config PMC_MSP
        select IRQ_CPU
        select SERIAL_8250
        select SERIAL_8250_CONSOLE
+       select USB_EHCI_BIG_ENDIAN_MMIO
+       select USB_EHCI_BIG_ENDIAN_DESC
        help
          This adds support for the PMC-Sierra family of Multi-Service
          Processor System-On-A-Chips.  These parts include a number
@@ -1433,6 +1435,7 @@ config CPU_CAVIUM_OCTEON
        select CPU_SUPPORTS_HUGEPAGES
        select LIBFDT
        select USE_OF
+       select USB_EHCI_BIG_ENDIAN_MMIO
        help
          The Cavium Octeon processor is a highly integrated chip containing
          many ethernet hardware widgets for networking tasks. The processor
index 0effe9f5a1eaf56b3c37f6b0b8d9b79a191d7718..7be93367d92f4dccbb4f0c4eeea747b2b0334402 100644 (file)
@@ -274,6 +274,8 @@ config 440EPX
        select IBM_EMAC_EMAC4
        select IBM_EMAC_RGMII
        select IBM_EMAC_ZMII
+       select USB_EHCI_BIG_ENDIAN_MMIO
+       select USB_EHCI_BIG_ENDIAN_DESC
 
 config 440GRX
        bool
index c16999802ecff6a5b960a1ffae9fba5c83c60f1f..381a592826a214887f29570d3d6b3c69e8fb2369 100644 (file)
@@ -7,6 +7,8 @@ config PPC_MPC512x
        select PPC_PCI_CHOICE
        select FSL_PCI if PCI
        select ARCH_WANT_OPTIONAL_GPIOLIB
+       select USB_EHCI_BIG_ENDIAN_MMIO
+       select USB_EHCI_BIG_ENDIAN_DESC
 
 config MPC5121_ADS
        bool "Freescale MPC5121E ADS"
index aaff7671101b301cedc1e30edf2055fc6aa008c8..764530c85aa9a30ba94dcf5a941c4ce300995fea 100644 (file)
@@ -254,11 +254,13 @@ static int usbhs_get_id(struct platform_device *pdev)
        return gpio_get_value(GPIO_PTB3);
 }
 
-static void usbhs_phy_reset(struct platform_device *pdev)
+static int usbhs_phy_reset(struct platform_device *pdev)
 {
        /* enable vbus if HOST */
        if (!gpio_get_value(GPIO_PTB3))
                gpio_set_value(GPIO_PTB5, 1);
+
+       return 0;
 }
 
 static struct renesas_usbhs_platform_info usbhs_info = {
index 3d361f236308c13cde14286379ec418af3e52990..66dc562950aea8c9b631ca87dce6f23f5d52b430 100644 (file)
@@ -407,6 +407,8 @@ config SERIAL_CONSOLE
 config SPARC_LEON
        bool "Sparc Leon processor family"
        depends on SPARC32
+       select USB_EHCI_BIG_ENDIAN_MMIO
+       select USB_EHCI_BIG_ENDIAN_DESC
        ---help---
          If you say Y here if you are running on a SPARC-LEON processor.
          The LEON processor is a synthesizable VHDL model of the
index 4865ed24708ab8a6717cee2c2083cb08451678f5..33360de63650b99f1771bdfccbcd4e3eaf01aea3 100644 (file)
@@ -79,7 +79,7 @@ obj-$(CONFIG_ATA_OVER_ETH)    += block/aoe/
 obj-$(CONFIG_PARIDE)           += block/paride/
 obj-$(CONFIG_TC)               += tc/
 obj-$(CONFIG_UWB)              += uwb/
-obj-$(CONFIG_USB_OTG_UTILS)    += usb/
+obj-$(CONFIG_USB_PHY)          += usb/
 obj-$(CONFIG_USB)              += usb/
 obj-$(CONFIG_PCI)              += usb/
 obj-$(CONFIG_USB_GADGET)       += usb/
index 8e0c4bf94ebc44b8a3cf214bfd82b9000a7b874a..1f9e56bfeaa0499ee9522aa0813e5da43f36164a 100644 (file)
@@ -1493,7 +1493,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
 {
        struct hid_device *hid = usb_get_intfdata(intf);
        struct usbhid_device *usbhid = hid->driver_data;
-       int status;
+       int status = 0;
        bool driver_suspended = false;
 
        if (PMSG_IS_AUTO(message)) {
@@ -1520,19 +1520,15 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
                }
 
        } else {
-               if (hid->driver && hid->driver->suspend) {
+               /* TODO: resume() might need to handle suspend failure */
+               if (hid->driver && hid->driver->suspend)
                        status = hid->driver->suspend(hid, message);
-                       if (status < 0)
-                               return status;
-               }
                driver_suspended = true;
                spin_lock_irq(&usbhid->lock);
                set_bit(HID_SUSPENDED, &usbhid->iofl);
                spin_unlock_irq(&usbhid->lock);
-               if (usbhid_wait_io(hid) < 0) {
+               if (usbhid_wait_io(hid) < 0)
                        status = -EIO;
-                       goto failed;
-               }
        }
 
        hid_cancel_delayed_stuff(usbhid);
@@ -1544,7 +1540,7 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
                goto failed;
        }
        dev_dbg(&intf->dev, "suspend\n");
-       return 0;
+       return status;
 
  failed:
        hid_resume_common(hid, driver_suspended);
index 6bd91676d2cbb9a46b43108ae1fa994d4fca84f9..32a76059e7dae84b8c32ea7f08a2595e84c663f8 100644 (file)
@@ -323,6 +323,11 @@ static int cdc_mbim_suspend(struct usb_interface *intf, pm_message_t message)
                goto error;
        }
 
+       /*
+        * Both usbnet_suspend() and subdriver->suspend() MUST return 0
+        * in system sleep context, otherwise, the resume callback has
+        * to recover device from previous suspend failure.
+        */
        ret = usbnet_suspend(intf, message);
        if (ret < 0)
                goto error;
index 2a3579f679103da7864260f114f98419852eaecd..5a88e72090ce7d0709d024a8c4b1f8fc173063a9 100644 (file)
@@ -374,6 +374,11 @@ static int qmi_wwan_suspend(struct usb_interface *intf, pm_message_t message)
        struct qmi_wwan_state *info = (void *)&dev->data;
        int ret;
 
+       /*
+        * Both usbnet_suspend() and subdriver->suspend() MUST return 0
+        * in system sleep context, otherwise, the resume callback has
+        * to recover device from previous suspend failure.
+        */
        ret = usbnet_suspend(intf, message);
        if (ret < 0)
                goto err;
index 1a15ec14c386f3c4e05808722bd84a196d82f3a8..75409748c77470da8cc5bcc7390e9f4c5a94ea6a 100644 (file)
@@ -2015,7 +2015,11 @@ static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
        ret = smsc75xx_enter_suspend0(dev);
 
 done:
-       if (ret)
+       /*
+        * TODO: resume() might need to handle the suspend failure
+        * in system sleep
+        */
+       if (ret && PMSG_IS_AUTO(message))
                usbnet_resume(intf);
        return ret;
 }
index e6d2dea1373ce29fcd5275c2d84547c561ba20d0..3f38ba868f6182152093e8efad0a864439c5cef0 100644 (file)
@@ -1660,7 +1660,11 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
        ret = smsc95xx_enter_suspend0(dev);
 
 done:
-       if (ret)
+       /*
+        * TODO: resume() might need to handle the suspend failure
+        * in system sleep
+        */
+       if (ret && PMSG_IS_AUTO(message))
                usbnet_resume(intf);
        return ret;
 }
index 9e00c389e777d95d43abf84836a901f1a7a4e3e2..ffe02fb7cbc78a64c40818d2a0323b07a1f7a515 100644 (file)
@@ -254,7 +254,7 @@ config BATTERY_RX51
 
 config CHARGER_ISP1704
        tristate "ISP1704 USB Charger Detection"
-       depends on USB_OTG_UTILS
+       depends on USB_PHY
        help
          Say Y to enable support for USB Charger Detection with
          ISP1707/ISP1704 USB transceivers.
index 7df7c5facc10fee68e4d9a89b0f1e549ea16b3f7..0c52e2a0d90cdba166a5cdfda72f70d86f5a2572 100644 (file)
@@ -35,7 +35,7 @@ static struct timer_list supply_timer;
 static struct timer_list polling_timer;
 static int polling;
 
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 static struct usb_phy *transceiver;
 static struct notifier_block otg_nb;
 #endif
@@ -218,7 +218,7 @@ static void polling_timer_func(unsigned long unused)
                  jiffies + msecs_to_jiffies(pdata->polling_interval));
 }
 
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 static int otg_is_usb_online(void)
 {
        return (transceiver->last_event == USB_EVENT_VBUS ||
@@ -315,7 +315,7 @@ static int pda_power_probe(struct platform_device *pdev)
                pda_psy_usb.num_supplicants = pdata->num_supplicants;
        }
 
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
        transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
        if (!IS_ERR_OR_NULL(transceiver)) {
                if (!pdata->is_usb_online)
@@ -367,7 +367,7 @@ static int pda_power_probe(struct platform_device *pdev)
                }
        }
 
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
        if (!IS_ERR_OR_NULL(transceiver) && pdata->use_otg_notifier) {
                otg_nb.notifier_call = otg_handle_notification;
                ret = usb_register_notifier(transceiver, &otg_nb);
@@ -391,7 +391,7 @@ static int pda_power_probe(struct platform_device *pdev)
 
        return 0;
 
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 otg_reg_notifier_failed:
        if (pdata->is_usb_online && usb_irq)
                free_irq(usb_irq->start, &pda_psy_usb);
@@ -402,7 +402,7 @@ usb_irq_failed:
 usb_supply_failed:
        if (pdata->is_ac_online && ac_irq)
                free_irq(ac_irq->start, &pda_psy_ac);
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
        if (!IS_ERR_OR_NULL(transceiver))
                usb_put_phy(transceiver);
 #endif
@@ -437,7 +437,7 @@ static int pda_power_remove(struct platform_device *pdev)
                power_supply_unregister(&pda_psy_usb);
        if (pdata->is_ac_online)
                power_supply_unregister(&pda_psy_ac);
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
        if (!IS_ERR_OR_NULL(transceiver))
                usb_put_phy(transceiver);
 #endif
index 640ae6c6d2d2ae67f504cb72582c40a8e85c9216..92e1dc94ecc87d2bd11cc8033a7bf4acc6a088a5 100644 (file)
@@ -122,9 +122,9 @@ config USB
          To compile this driver as a module, choose M here: the
          module will be called usbcore.
 
-source "drivers/usb/core/Kconfig"
+if USB
 
-source "drivers/usb/dwc3/Kconfig"
+source "drivers/usb/core/Kconfig"
 
 source "drivers/usb/mon/Kconfig"
 
@@ -134,8 +134,6 @@ source "drivers/usb/host/Kconfig"
 
 source "drivers/usb/musb/Kconfig"
 
-source "drivers/usb/chipidea/Kconfig"
-
 source "drivers/usb/renesas_usbhs/Kconfig"
 
 source "drivers/usb/class/Kconfig"
@@ -144,12 +142,19 @@ source "drivers/usb/storage/Kconfig"
 
 source "drivers/usb/image/Kconfig"
 
+endif
+
+source "drivers/usb/dwc3/Kconfig"
+
+source "drivers/usb/chipidea/Kconfig"
+
 comment "USB port drivers"
-       depends on USB
+
+if USB
 
 config USB_USS720
        tristate "USS720 parport driver"
-       depends on USB && PARPORT
+       depends on PARPORT
        select PARPORT_NOT_PC
        ---help---
          This driver is for USB parallel port adapters that use the Lucent
@@ -180,12 +185,12 @@ source "drivers/usb/serial/Kconfig"
 
 source "drivers/usb/misc/Kconfig"
 
-source "drivers/usb/phy/Kconfig"
-
 source "drivers/usb/atm/Kconfig"
 
-source "drivers/usb/gadget/Kconfig"
+endif # USB
+
+source "drivers/usb/phy/Kconfig"
 
-source "drivers/usb/otg/Kconfig"
+source "drivers/usb/gadget/Kconfig"
 
 endif # USB_SUPPORT
index 8f5ebced5df0010e4d881c7978a5e132d92c8306..c41feba8d5c0737c926aa6a576f50b0c290a626a 100644 (file)
@@ -6,8 +6,6 @@
 
 obj-$(CONFIG_USB)              += core/
 
-obj-$(CONFIG_USB_OTG_UTILS)    += otg/
-
 obj-$(CONFIG_USB_DWC3)         += dwc3/
 
 obj-$(CONFIG_USB_MON)          += mon/
@@ -46,7 +44,7 @@ obj-$(CONFIG_USB_MICROTEK)    += image/
 obj-$(CONFIG_USB_SERIAL)       += serial/
 
 obj-$(CONFIG_USB)              += misc/
-obj-$(CONFIG_USB_OTG_UTILS)    += phy/
+obj-$(CONFIG_USB_PHY)          += phy/
 obj-$(CONFIG_EARLY_PRINTK_DBGP)        += early/
 
 obj-$(CONFIG_USB_ATM)          += atm/
index be0b8daac9c7de2681191161415877cb3289961e..0f922942a07aca8a114058cb9f36a7899229bec9 100644 (file)
@@ -4,7 +4,7 @@
 
 menuconfig USB_ATM
        tristate "USB DSL modem support"
-       depends on USB && ATM
+       depends on ATM
        select CRC32
        default n
        help
index 35f10bfe15dbff615823234e02d0e80732e7bda6..d3527dd8b90cc17e518ca5324ec517a265a8798b 100644 (file)
@@ -672,9 +672,6 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
        struct usbatm_control *ctrl = UDSL_SKB(skb);
        int err;
 
-       vdbg(&instance->usb_intf->dev, "%s called (skb 0x%p, len %u)", __func__,
-            skb, skb->len);
-
        /* racy disconnection check - fine */
        if (!instance || instance->disconnected) {
 #ifdef DEBUG
@@ -684,6 +681,9 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb)
                goto fail;
        }
 
+       vdbg(&instance->usb_intf->dev, "%s called (skb 0x%p, len %u)", __func__,
+            skb, skb->len);
+
        if (vcc->qos.aal != ATM_AAL5) {
                atm_rldbg(instance, "%s: unsupported ATM type %d!\n", __func__, vcc->qos.aal);
                err = -EINVAL;
index d92ca325b104f9ccd6b7a27cf2b7177b443190c4..4ab83e98219b7b9c15ebcc78ca2716b650653574 100644 (file)
@@ -17,5 +17,5 @@ ifneq ($(CONFIG_PCI),)
 endif
 
 ifneq ($(CONFIG_OF_DEVICE),)
-       obj-$(CONFIG_USB_CHIPIDEA)      += ci13xxx_imx.o usbmisc_imx6q.o
+       obj-$(CONFIG_USB_CHIPIDEA)      += ci13xxx_imx.o usbmisc_imx.o
 endif
index e25d1263da13edd9cc8737030982cc9f81402105..b0a6bce064ca9a4f6ed7e4b19657165c48821686 100644 (file)
@@ -21,6 +21,7 @@
 /******************************************************************************
  * DEFINE
  *****************************************************************************/
+#define TD_PAGE_COUNT      5
 #define CI13XXX_PAGE_SIZE  4096ul /* page size for TD's */
 #define ENDPT_MAX          32
 
@@ -129,6 +130,7 @@ struct hw_bank {
  * @vbus_active: is VBUS active
  * @transceiver: pointer to USB PHY, if any
  * @hcd: pointer to usb_hcd for ehci host driver
+ * @debugfs: root dentry for this controller in debugfs
  */
 struct ci13xxx {
        struct device                   *dev;
@@ -139,7 +141,6 @@ struct ci13xxx {
        enum ci_role                    role;
        bool                            is_otg;
        struct work_struct              work;
-       struct work_struct              vbus_work;
        struct workqueue_struct         *wq;
 
        struct dma_pool                 *qh_pool;
@@ -165,6 +166,7 @@ struct ci13xxx {
        bool                            global_phy;
        struct usb_phy                  *transceiver;
        struct usb_hcd                  *hcd;
+       struct dentry                   *debugfs;
 };
 
 static inline struct ci_role_driver *ci_role(struct ci13xxx *ci)
@@ -233,19 +235,6 @@ enum ci13xxx_regs {
        OP_LAST = OP_ENDPTCTRL + ENDPT_MAX / 2,
 };
 
-/**
- * ffs_nr: find first (least significant) bit set
- * @x: the word to search
- *
- * This function returns bit number (instead of position)
- */
-static inline int ffs_nr(u32 x)
-{
-       int n = ffs(x);
-
-       return n ? n-1 : 32;
-}
-
 /**
  * hw_read: reads from a hw register
  * @reg:  register index
@@ -304,7 +293,7 @@ static inline u32 hw_test_and_write(struct ci13xxx *ci, enum ci13xxx_regs reg,
        u32 val = hw_read(ci, reg, ~0);
 
        hw_write(ci, reg, mask, data);
-       return (val & mask) >> ffs_nr(mask);
+       return (val & mask) >> __ffs(mask);
 }
 
 int hw_device_reset(struct ci13xxx *ci, u32 mode);
index 8c291220be7f9ffd1117eb0fe0bd0cc7b6df4a5b..8faec9dbbb84326d436ffc568451b322eb95a1a3 100644 (file)
@@ -79,6 +79,9 @@ int usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev)
        if (of_find_property(np, "disable-over-current", NULL))
                usbdev->disable_oc = 1;
 
+       if (of_find_property(np, "external-vbus-divider", NULL))
+               usbdev->evdo = 1;
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(usbmisc_get_init_data);
@@ -202,6 +205,15 @@ static int ci13xxx_imx_probe(struct platform_device *pdev)
                goto err;
        }
 
+       if (usbmisc_ops && usbmisc_ops->post) {
+               ret = usbmisc_ops->post(&pdev->dev);
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "usbmisc post failed, ret=%d\n", ret);
+                       goto put_np;
+               }
+       }
+
        data->ci_pdev = plat_ci;
        platform_set_drvdata(pdev, data);
 
index 9cd2e910b1ca3ae03ecd5a1fa81f5204698d45bf..550bfa4576202c6f6f8f9c3f73ab8921971fd234 100644 (file)
@@ -13,6 +13,8 @@
 struct usbmisc_ops {
        /* It's called once when probe a usb device */
        int (*init)(struct device *dev);
+       /* It's called once after adding a usb device */
+       int (*post)(struct device *dev);
 };
 
 struct usbmisc_usb_device {
@@ -20,6 +22,7 @@ struct usbmisc_usb_device {
        int index;
 
        unsigned int disable_oc:1; /* over current detect disabled */
+       unsigned int evdo:1; /* set external vbus divider option */
 };
 
 int usbmisc_set_ops(const struct usbmisc_ops *ops);
index 9b227e39299af9bd4e51887c974c276eecb9fb30..4e1fc61b9d95201c5bfd119cd8be8f6e9b8db6ba 100644 (file)
 /******************************************************************************
  * PCI block
  *****************************************************************************/
-struct ci13xxx_platform_data pci_platdata = {
+static struct ci13xxx_platform_data pci_platdata = {
        .name           = UDC_DRIVER_NAME,
        .capoffset      = DEF_CAPOFFSET,
 };
 
-struct ci13xxx_platform_data langwell_pci_platdata = {
+static struct ci13xxx_platform_data langwell_pci_platdata = {
        .name           = UDC_DRIVER_NAME,
        .capoffset      = 0,
 };
 
-struct ci13xxx_platform_data penwell_pci_platdata = {
+static struct ci13xxx_platform_data penwell_pci_platdata = {
        .name           = UDC_DRIVER_NAME,
        .capoffset      = 0,
        .power_budget   = 200,
index 57cae1f897b21b7b4797e2ea54f7cfe51042618b..450107e5f657a32a3b7d5b0fd1e310a99e77ec66 100644 (file)
  */
 #include <linux/delay.h>
 #include <linux/device.h>
-#include <linux/dmapool.h>
 #include <linux/dma-mapping.h>
-#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/module.h>
 #include <linux/idr.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
-#include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
@@ -158,7 +155,7 @@ int hw_port_test_set(struct ci13xxx *ci, u8 mode)
        if (mode > TEST_MODE_MAX)
                return -EINVAL;
 
-       hw_write(ci, OP_PORTSC, PORTSC_PTC, mode << ffs_nr(PORTSC_PTC));
+       hw_write(ci, OP_PORTSC, PORTSC_PTC, mode << __ffs(PORTSC_PTC));
        return 0;
 }
 
@@ -169,7 +166,7 @@ int hw_port_test_set(struct ci13xxx *ci, u8 mode)
  */
 u8 hw_port_test_get(struct ci13xxx *ci)
 {
-       return hw_read(ci, OP_PORTSC, PORTSC_PTC) >> ffs_nr(PORTSC_PTC);
+       return hw_read(ci, OP_PORTSC, PORTSC_PTC) >> __ffs(PORTSC_PTC);
 }
 
 static int hw_device_init(struct ci13xxx *ci, void __iomem *base)
@@ -181,11 +178,11 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base)
 
        ci->hw_bank.cap = ci->hw_bank.abs;
        ci->hw_bank.cap += ci->platdata->capoffset;
-       ci->hw_bank.op = ci->hw_bank.cap + ioread8(ci->hw_bank.cap);
+       ci->hw_bank.op = ci->hw_bank.cap + (ioread32(ci->hw_bank.cap) & 0xff);
 
        hw_alloc_regmap(ci, false);
        reg = hw_read(ci, CAP_HCCPARAMS, HCCPARAMS_LEN) >>
-               ffs_nr(HCCPARAMS_LEN);
+               __ffs(HCCPARAMS_LEN);
        ci->hw_bank.lpm  = reg;
        hw_alloc_regmap(ci, !!reg);
        ci->hw_bank.size = ci->hw_bank.op - ci->hw_bank.abs;
@@ -193,7 +190,7 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base)
        ci->hw_bank.size /= sizeof(u32);
 
        reg = hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_DEN) >>
-               ffs_nr(DCCPARAMS_DEN);
+               __ffs(DCCPARAMS_DEN);
        ci->hw_ep_max = reg * 2;   /* cache hw ENDPT_MAX */
 
        if (ci->hw_ep_max > ENDPT_MAX)
@@ -283,38 +280,6 @@ static void ci_role_work(struct work_struct *work)
        }
 }
 
-static ssize_t show_role(struct device *dev, struct device_attribute *attr,
-                        char *buf)
-{
-       struct ci13xxx *ci = dev_get_drvdata(dev);
-
-       return sprintf(buf, "%s\n", ci_role(ci)->name);
-}
-
-static ssize_t store_role(struct device *dev, struct device_attribute *attr,
-                         const char *buf, size_t count)
-{
-       struct ci13xxx *ci = dev_get_drvdata(dev);
-       enum ci_role role;
-       int ret;
-
-       for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++)
-               if (ci->roles[role] && !strcmp(buf, ci->roles[role]->name))
-                       break;
-
-       if (role == CI_ROLE_END || role == ci->role)
-               return -EINVAL;
-
-       ci_role_stop(ci);
-       ret = ci_role_start(ci, role);
-       if (ret)
-               return ret;
-
-       return count;
-}
-
-static DEVICE_ATTR(role, S_IRUSR | S_IWUSR, show_role, store_role);
-
 static irqreturn_t ci_irq(int irq, void *data)
 {
        struct ci13xxx *ci = data;
@@ -410,11 +375,9 @@ static int ci_hdrc_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       base = devm_request_and_ioremap(dev, res);
-       if (!base) {
-               dev_err(dev, "can't request and ioremap resource\n");
-               return -ENOMEM;
-       }
+       base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
 
        ci = devm_kzalloc(dev, sizeof(*ci), GFP_KERNEL);
        if (!ci) {
@@ -489,17 +452,14 @@ static int ci_hdrc_probe(struct platform_device *pdev)
        if (ret)
                goto stop;
 
-       ret = device_create_file(dev, &dev_attr_role);
-       if (ret)
-               goto rm_attr;
-
        if (ci->is_otg)
                hw_write(ci, OP_OTGSC, OTGSC_IDIE, OTGSC_IDIE);
 
-       return ret;
+       ret = dbg_create_files(ci);
+       if (!ret)
+               return 0;
 
-rm_attr:
-       device_remove_file(dev, &dev_attr_role);
+       free_irq(ci->irq, ci);
 stop:
        ci_role_stop(ci);
 rm_wq:
@@ -513,9 +473,9 @@ static int ci_hdrc_remove(struct platform_device *pdev)
 {
        struct ci13xxx *ci = platform_get_drvdata(pdev);
 
+       dbg_remove_files(ci);
        flush_workqueue(ci->wq);
        destroy_workqueue(ci->wq);
-       device_remove_file(ci->dev, &dev_attr_role);
        free_irq(ci->irq, ci);
        ci_role_stop(ci);
 
index a62c4a47d52c6685787ff01e174f67040241502f..36a7063a6cba04f55e1b25ea062f2896f9524dda 100644 (file)
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/dmapool.h>
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
 #include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/pm_runtime.h>
+#include <linux/device.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/uaccess.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/chipidea.h>
 
 #include "ci.h"
 #include "udc.h"
 #include "bits.h"
 #include "debug.h"
 
-/* Interrupt statistics */
-#define ISR_MASK   0x1F
-static struct isr_statistics {
-       u32 test;
-       u32 ui;
-       u32 uei;
-       u32 pci;
-       u32 uri;
-       u32 sli;
-       u32 none;
-       struct {
-               u32 cnt;
-               u32 buf[ISR_MASK+1];
-               u32 idx;
-       } hndl;
-} isr_statistics;
-
-void dbg_interrupt(u32 intmask)
-{
-       if (!intmask) {
-               isr_statistics.none++;
-               return;
-       }
-
-       isr_statistics.hndl.buf[isr_statistics.hndl.idx++] = intmask;
-       isr_statistics.hndl.idx &= ISR_MASK;
-       isr_statistics.hndl.cnt++;
-
-       if (USBi_URI & intmask)
-               isr_statistics.uri++;
-       if (USBi_PCI & intmask)
-               isr_statistics.pci++;
-       if (USBi_UEI & intmask)
-               isr_statistics.uei++;
-       if (USBi_UI  & intmask)
-               isr_statistics.ui++;
-       if (USBi_SLI & intmask)
-               isr_statistics.sli++;
-}
-
 /**
- * hw_register_read: reads all device registers (execute without interruption)
- * @buf:  destination buffer
- * @size: buffer size
- *
- * This function returns number of registers read
+ * ci_device_show: prints information about device capabilities and status
  */
-static size_t hw_register_read(struct ci13xxx *ci, u32 *buf, size_t size)
+static int ci_device_show(struct seq_file *s, void *data)
 {
-       unsigned i;
-
-       if (size > ci->hw_bank.size)
-               size = ci->hw_bank.size;
-
-       for (i = 0; i < size; i++)
-               buf[i] = hw_read(ci, i * sizeof(u32), ~0);
-
-       return size;
-}
-
-/**
- * hw_register_write: writes to register
- * @addr: register address
- * @data: register value
- *
- * This function returns an error code
- */
-static int hw_register_write(struct ci13xxx *ci, u16 addr, u32 data)
-{
-       /* align */
-       addr /= sizeof(u32);
-
-       if (addr >= ci->hw_bank.size)
-               return -EINVAL;
-
-       /* align */
-       addr *= sizeof(u32);
-
-       hw_write(ci, addr, ~0, data);
-       return 0;
-}
-
-/**
- * hw_intr_clear: disables interrupt & clears interrupt status (execute without
- *                interruption)
- * @n: interrupt bit
- *
- * This function returns an error code
- */
-static int hw_intr_clear(struct ci13xxx *ci, int n)
-{
-       if (n >= REG_BITS)
-               return -EINVAL;
-
-       hw_write(ci, OP_USBINTR, BIT(n), 0);
-       hw_write(ci, OP_USBSTS,  BIT(n), BIT(n));
-       return 0;
-}
-
-/**
- * hw_intr_force: enables interrupt & forces interrupt status (execute without
- *                interruption)
- * @n: interrupt bit
- *
- * This function returns an error code
- */
-static int hw_intr_force(struct ci13xxx *ci, int n)
-{
-       if (n >= REG_BITS)
-               return -EINVAL;
-
-       hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
-       hw_write(ci, OP_USBINTR,  BIT(n), BIT(n));
-       hw_write(ci, OP_USBSTS,   BIT(n), BIT(n));
-       hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, 0);
-       return 0;
-}
-
-/**
- * show_device: prints information about device capabilities and status
- *
- * Check "device.h" for details
- */
-static ssize_t show_device(struct device *dev, struct device_attribute *attr,
-                          char *buf)
-{
-       struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+       struct ci13xxx *ci = s->private;
        struct usb_gadget *gadget = &ci->gadget;
-       int n = 0;
 
-       if (attr == NULL || buf == NULL) {
-               dev_err(ci->dev, "[%s] EINVAL\n", __func__);
+       seq_printf(s, "speed             = %d\n", gadget->speed);
+       seq_printf(s, "max_speed         = %d\n", gadget->max_speed);
+       seq_printf(s, "is_otg            = %d\n", gadget->is_otg);
+       seq_printf(s, "is_a_peripheral   = %d\n", gadget->is_a_peripheral);
+       seq_printf(s, "b_hnp_enable      = %d\n", gadget->b_hnp_enable);
+       seq_printf(s, "a_hnp_support     = %d\n", gadget->a_hnp_support);
+       seq_printf(s, "a_alt_hnp_support = %d\n", gadget->a_alt_hnp_support);
+       seq_printf(s, "name              = %s\n",
+                  (gadget->name ? gadget->name : ""));
+
+       if (!ci->driver)
                return 0;
-       }
-
-       n += scnprintf(buf + n, PAGE_SIZE - n, "speed             = %d\n",
-                      gadget->speed);
-       n += scnprintf(buf + n, PAGE_SIZE - n, "max_speed         = %d\n",
-                      gadget->max_speed);
-       n += scnprintf(buf + n, PAGE_SIZE - n, "is_otg            = %d\n",
-                      gadget->is_otg);
-       n += scnprintf(buf + n, PAGE_SIZE - n, "is_a_peripheral   = %d\n",
-                      gadget->is_a_peripheral);
-       n += scnprintf(buf + n, PAGE_SIZE - n, "b_hnp_enable      = %d\n",
-                      gadget->b_hnp_enable);
-       n += scnprintf(buf + n, PAGE_SIZE - n, "a_hnp_support     = %d\n",
-                      gadget->a_hnp_support);
-       n += scnprintf(buf + n, PAGE_SIZE - n, "a_alt_hnp_support = %d\n",
-                      gadget->a_alt_hnp_support);
-       n += scnprintf(buf + n, PAGE_SIZE - n, "name              = %s\n",
-                      (gadget->name ? gadget->name : ""));
-
-       return n;
-}
-static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
-
-/**
- * show_driver: prints information about attached gadget (if any)
- *
- * Check "device.h" for details
- */
-static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
-                          char *buf)
-{
-       struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
-       struct usb_gadget_driver *driver = ci->driver;
-       int n = 0;
-
-       if (attr == NULL || buf == NULL) {
-               dev_err(dev, "[%s] EINVAL\n", __func__);
-               return 0;
-       }
-
-       if (driver == NULL)
-               return scnprintf(buf, PAGE_SIZE,
-                                "There is no gadget attached!\n");
 
-       n += scnprintf(buf + n, PAGE_SIZE - n, "function  = %s\n",
-                      (driver->function ? driver->function : ""));
-       n += scnprintf(buf + n, PAGE_SIZE - n, "max speed = %d\n",
-                      driver->max_speed);
+       seq_printf(s, "gadget function   = %s\n",
+                      (ci->driver->function ? ci->driver->function : ""));
+       seq_printf(s, "gadget max speed  = %d\n", ci->driver->max_speed);
 
-       return n;
-}
-static DEVICE_ATTR(driver, S_IRUSR, show_driver, NULL);
-
-/* Maximum event message length */
-#define DBG_DATA_MSG   64UL
-
-/* Maximum event messages */
-#define DBG_DATA_MAX   128UL
-
-/* Event buffer descriptor */
-static struct {
-       char     (buf[DBG_DATA_MAX])[DBG_DATA_MSG];   /* buffer */
-       unsigned idx;   /* index */
-       unsigned tty;   /* print to console? */
-       rwlock_t lck;   /* lock */
-} dbg_data = {
-       .idx = 0,
-       .tty = 0,
-       .lck = __RW_LOCK_UNLOCKED(dbg_data.lck)
-};
-
-/**
- * dbg_dec: decrements debug event index
- * @idx: buffer index
- */
-static void dbg_dec(unsigned *idx)
-{
-       *idx = (*idx - 1) & (DBG_DATA_MAX-1);
-}
-
-/**
- * dbg_inc: increments debug event index
- * @idx: buffer index
- */
-static void dbg_inc(unsigned *idx)
-{
-       *idx = (*idx + 1) & (DBG_DATA_MAX-1);
-}
-
-/**
- * dbg_print:  prints the common part of the event
- * @addr:   endpoint address
- * @name:   event name
- * @status: status
- * @extra:  extra information
- */
-static void dbg_print(u8 addr, const char *name, int status, const char *extra)
-{
-       struct timeval tval;
-       unsigned int stamp;
-       unsigned long flags;
-
-       write_lock_irqsave(&dbg_data.lck, flags);
-
-       do_gettimeofday(&tval);
-       stamp = tval.tv_sec & 0xFFFF;   /* 2^32 = 4294967296. Limit to 4096s */
-       stamp = stamp * 1000000 + tval.tv_usec;
-
-       scnprintf(dbg_data.buf[dbg_data.idx], DBG_DATA_MSG,
-                 "%04X\t? %02X %-7.7s %4i ?\t%s\n",
-                 stamp, addr, name, status, extra);
-
-       dbg_inc(&dbg_data.idx);
-
-       write_unlock_irqrestore(&dbg_data.lck, flags);
-
-       if (dbg_data.tty != 0)
-               pr_notice("%04X\t? %02X %-7.7s %4i ?\t%s\n",
-                         stamp, addr, name, status, extra);
-}
-
-/**
- * dbg_done: prints a DONE event
- * @addr:   endpoint address
- * @td:     transfer descriptor
- * @status: status
- */
-void dbg_done(u8 addr, const u32 token, int status)
-{
-       char msg[DBG_DATA_MSG];
-
-       scnprintf(msg, sizeof(msg), "%d %02X",
-                 (int)(token & TD_TOTAL_BYTES) >> ffs_nr(TD_TOTAL_BYTES),
-                 (int)(token & TD_STATUS)      >> ffs_nr(TD_STATUS));
-       dbg_print(addr, "DONE", status, msg);
-}
-
-/**
- * dbg_event: prints a generic event
- * @addr:   endpoint address
- * @name:   event name
- * @status: status
- */
-void dbg_event(u8 addr, const char *name, int status)
-{
-       if (name != NULL)
-               dbg_print(addr, name, status, "");
-}
-
-/*
- * dbg_queue: prints a QUEUE event
- * @addr:   endpoint address
- * @req:    USB request
- * @status: status
- */
-void dbg_queue(u8 addr, const struct usb_request *req, int status)
-{
-       char msg[DBG_DATA_MSG];
-
-       if (req != NULL) {
-               scnprintf(msg, sizeof(msg),
-                         "%d %d", !req->no_interrupt, req->length);
-               dbg_print(addr, "QUEUE", status, msg);
-       }
-}
-
-/**
- * dbg_setup: prints a SETUP event
- * @addr: endpoint address
- * @req:  setup request
- */
-void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
-{
-       char msg[DBG_DATA_MSG];
-
-       if (req != NULL) {
-               scnprintf(msg, sizeof(msg),
-                         "%02X %02X %04X %04X %d", req->bRequestType,
-                         req->bRequest, le16_to_cpu(req->wValue),
-                         le16_to_cpu(req->wIndex), le16_to_cpu(req->wLength));
-               dbg_print(addr, "SETUP", 0, msg);
-       }
+       return 0;
 }
 
-/**
- * show_events: displays the event buffer
- *
- * Check "device.h" for details
- */
-static ssize_t show_events(struct device *dev, struct device_attribute *attr,
-                          char *buf)
+static int ci_device_open(struct inode *inode, struct file *file)
 {
-       unsigned long flags;
-       unsigned i, j, n = 0;
-
-       if (attr == NULL || buf == NULL) {
-               dev_err(dev->parent, "[%s] EINVAL\n", __func__);
-               return 0;
-       }
-
-       read_lock_irqsave(&dbg_data.lck, flags);
-
-       i = dbg_data.idx;
-       for (dbg_dec(&i); i != dbg_data.idx; dbg_dec(&i)) {
-               n += strlen(dbg_data.buf[i]);
-               if (n >= PAGE_SIZE) {
-                       n -= strlen(dbg_data.buf[i]);
-                       break;
-               }
-       }
-       for (j = 0, dbg_inc(&i); j < n; dbg_inc(&i))
-               j += scnprintf(buf + j, PAGE_SIZE - j,
-                              "%s", dbg_data.buf[i]);
-
-       read_unlock_irqrestore(&dbg_data.lck, flags);
-
-       return n;
+       return single_open(file, ci_device_show, inode->i_private);
 }
 
-/**
- * store_events: configure if events are going to be also printed to console
- *
- * Check "device.h" for details
- */
-static ssize_t store_events(struct device *dev, struct device_attribute *attr,
-                           const char *buf, size_t count)
-{
-       unsigned tty;
-
-       if (attr == NULL || buf == NULL) {
-               dev_err(dev, "[%s] EINVAL\n", __func__);
-               goto done;
-       }
-
-       if (sscanf(buf, "%u", &tty) != 1 || tty > 1) {
-               dev_err(dev, "<1|0>: enable|disable console log\n");
-               goto done;
-       }
-
-       dbg_data.tty = tty;
-       dev_info(dev, "tty = %u", dbg_data.tty);
-
- done:
-       return count;
-}
-static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
+static const struct file_operations ci_device_fops = {
+       .open           = ci_device_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
 
 /**
- * show_inters: interrupt status, enable status and historic
- *
- * Check "device.h" for details
+ * ci_port_test_show: reads port test mode
  */
-static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
-                          char *buf)
+static int ci_port_test_show(struct seq_file *s, void *data)
 {
-       struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+       struct ci13xxx *ci = s->private;
        unsigned long flags;
-       u32 intr;
-       unsigned i, j, n = 0;
-
-       if (attr == NULL || buf == NULL) {
-               dev_err(ci->dev, "[%s] EINVAL\n", __func__);
-               return 0;
-       }
+       unsigned mode;
 
        spin_lock_irqsave(&ci->lock, flags);
-
-       /*n += scnprintf(buf + n, PAGE_SIZE - n,
-                      "status = %08x\n", hw_read_intr_status(ci));
-       n += scnprintf(buf + n, PAGE_SIZE - n,
-       "enable = %08x\n", hw_read_intr_enable(ci));*/
-
-       n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
-                      isr_statistics.test);
-       n += scnprintf(buf + n, PAGE_SIZE - n, "? ui  = %d\n",
-                      isr_statistics.ui);
-       n += scnprintf(buf + n, PAGE_SIZE - n, "? uei = %d\n",
-                      isr_statistics.uei);
-       n += scnprintf(buf + n, PAGE_SIZE - n, "? pci = %d\n",
-                      isr_statistics.pci);
-       n += scnprintf(buf + n, PAGE_SIZE - n, "? uri = %d\n",
-                      isr_statistics.uri);
-       n += scnprintf(buf + n, PAGE_SIZE - n, "? sli = %d\n",
-                      isr_statistics.sli);
-       n += scnprintf(buf + n, PAGE_SIZE - n, "*none = %d\n",
-                      isr_statistics.none);
-       n += scnprintf(buf + n, PAGE_SIZE - n, "*hndl = %d\n",
-                      isr_statistics.hndl.cnt);
-
-       for (i = isr_statistics.hndl.idx, j = 0; j <= ISR_MASK; j++, i++) {
-               i   &= ISR_MASK;
-               intr = isr_statistics.hndl.buf[i];
-
-               if (USBi_UI  & intr)
-                       n += scnprintf(buf + n, PAGE_SIZE - n, "ui  ");
-               intr &= ~USBi_UI;
-               if (USBi_UEI & intr)
-                       n += scnprintf(buf + n, PAGE_SIZE - n, "uei ");
-               intr &= ~USBi_UEI;
-               if (USBi_PCI & intr)
-                       n += scnprintf(buf + n, PAGE_SIZE - n, "pci ");
-               intr &= ~USBi_PCI;
-               if (USBi_URI & intr)
-                       n += scnprintf(buf + n, PAGE_SIZE - n, "uri ");
-               intr &= ~USBi_URI;
-               if (USBi_SLI & intr)
-                       n += scnprintf(buf + n, PAGE_SIZE - n, "sli ");
-               intr &= ~USBi_SLI;
-               if (intr)
-                       n += scnprintf(buf + n, PAGE_SIZE - n, "??? ");
-               if (isr_statistics.hndl.buf[i])
-                       n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
-       }
-
+       mode = hw_port_test_get(ci);
        spin_unlock_irqrestore(&ci->lock, flags);
 
-       return n;
-}
-
-/**
- * store_inters: enable & force or disable an individual interrutps
- *                   (to be used for test purposes only)
- *
- * Check "device.h" for details
- */
-static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
-                           const char *buf, size_t count)
-{
-       struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
-       unsigned long flags;
-       unsigned en, bit;
-
-       if (attr == NULL || buf == NULL) {
-               dev_err(ci->dev, "EINVAL\n");
-               goto done;
-       }
+       seq_printf(s, "mode = %u\n", mode);
 
-       if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
-               dev_err(ci->dev, "<1|0> <bit>: enable|disable interrupt\n");
-               goto done;
-       }
-
-       spin_lock_irqsave(&ci->lock, flags);
-       if (en) {
-               if (hw_intr_force(ci, bit))
-                       dev_err(dev, "invalid bit number\n");
-               else
-                       isr_statistics.test++;
-       } else {
-               if (hw_intr_clear(ci, bit))
-                       dev_err(dev, "invalid bit number\n");
-       }
-       spin_unlock_irqrestore(&ci->lock, flags);
-
- done:
-       return count;
+       return 0;
 }
-static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
 
 /**
- * show_port_test: reads port test mode
- *
- * Check "device.h" for details
+ * ci_port_test_write: writes port test mode
  */
-static ssize_t show_port_test(struct device *dev,
-                             struct device_attribute *attr, char *buf)
+static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf,
+                                 size_t count, loff_t *ppos)
 {
-       struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+       struct seq_file *s = file->private_data;
+       struct ci13xxx *ci = s->private;
        unsigned long flags;
        unsigned mode;
+       char buf[32];
+       int ret;
 
-       if (attr == NULL || buf == NULL) {
-               dev_err(ci->dev, "EINVAL\n");
-               return 0;
-       }
+       if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
+               return -EFAULT;
+
+       if (sscanf(buf, "%u", &mode) != 1)
+               return -EINVAL;
 
        spin_lock_irqsave(&ci->lock, flags);
-       mode = hw_port_test_get(ci);
+       ret = hw_port_test_set(ci, mode);
        spin_unlock_irqrestore(&ci->lock, flags);
 
-       return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
+       return ret ? ret : count;
 }
 
-/**
- * store_port_test: writes port test mode
- *
- * Check "device.h" for details
- */
-static ssize_t store_port_test(struct device *dev,
-                              struct device_attribute *attr,
-                              const char *buf, size_t count)
+static int ci_port_test_open(struct inode *inode, struct file *file)
 {
-       struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
-       unsigned long flags;
-       unsigned mode;
-
-       if (attr == NULL || buf == NULL) {
-               dev_err(ci->dev, "[%s] EINVAL\n", __func__);
-               goto done;
-       }
-
-       if (sscanf(buf, "%u", &mode) != 1) {
-               dev_err(ci->dev, "<mode>: set port test mode");
-               goto done;
-       }
-
-       spin_lock_irqsave(&ci->lock, flags);
-       if (hw_port_test_set(ci, mode))
-               dev_err(ci->dev, "invalid mode\n");
-       spin_unlock_irqrestore(&ci->lock, flags);
-
- done:
-       return count;
+       return single_open(file, ci_port_test_show, inode->i_private);
 }
-static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
-                  show_port_test, store_port_test);
+
+static const struct file_operations ci_port_test_fops = {
+       .open           = ci_port_test_open,
+       .write          = ci_port_test_write,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
 
 /**
- * show_qheads: DMA contents of all queue heads
- *
- * Check "device.h" for details
+ * ci_qheads_show: DMA contents of all queue heads
  */
-static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
-                          char *buf)
+static int ci_qheads_show(struct seq_file *s, void *data)
 {
-       struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+       struct ci13xxx *ci = s->private;
        unsigned long flags;
-       unsigned i, j, n = 0;
+       unsigned i, j;
 
-       if (attr == NULL || buf == NULL) {
-               dev_err(ci->dev, "[%s] EINVAL\n", __func__);
+       if (ci->role != CI_ROLE_GADGET) {
+               seq_printf(s, "not in gadget mode\n");
                return 0;
        }
 
@@ -593,209 +129,173 @@ static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
                struct ci13xxx_ep *mEpRx = &ci->ci13xxx_ep[i];
                struct ci13xxx_ep *mEpTx =
                        &ci->ci13xxx_ep[i + ci->hw_ep_max/2];
-               n += scnprintf(buf + n, PAGE_SIZE - n,
-                              "EP=%02i: RX=%08X TX=%08X\n",
-                              i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
-               for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) {
-                       n += scnprintf(buf + n, PAGE_SIZE - n,
-                                      " %04X:    %08X    %08X\n", j,
-                                      *((u32 *)mEpRx->qh.ptr + j),
-                                      *((u32 *)mEpTx->qh.ptr + j));
-               }
+               seq_printf(s, "EP=%02i: RX=%08X TX=%08X\n",
+                          i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
+               for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++)
+                       seq_printf(s, " %04X:    %08X    %08X\n", j,
+                                  *((u32 *)mEpRx->qh.ptr + j),
+                                  *((u32 *)mEpTx->qh.ptr + j));
        }
        spin_unlock_irqrestore(&ci->lock, flags);
 
-       return n;
+       return 0;
+}
+
+static int ci_qheads_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, ci_qheads_show, inode->i_private);
 }
-static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
+
+static const struct file_operations ci_qheads_fops = {
+       .open           = ci_qheads_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
 
 /**
- * show_registers: dumps all registers
- *
- * Check "device.h" for details
+ * ci_requests_show: DMA contents of all requests currently queued (all endpts)
  */
-#define DUMP_ENTRIES   512
-static ssize_t show_registers(struct device *dev,
-                             struct device_attribute *attr, char *buf)
+static int ci_requests_show(struct seq_file *s, void *data)
 {
-       struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+       struct ci13xxx *ci = s->private;
        unsigned long flags;
-       u32 *dump;
-       unsigned i, k, n = 0;
-
-       if (attr == NULL || buf == NULL) {
-               dev_err(ci->dev, "[%s] EINVAL\n", __func__);
-               return 0;
-       }
+       struct list_head   *ptr = NULL;
+       struct ci13xxx_req *req = NULL;
+       unsigned i, j, qsize = sizeof(struct ci13xxx_td)/sizeof(u32);
 
-       dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
-       if (!dump) {
-               dev_err(ci->dev, "%s: out of memory\n", __func__);
+       if (ci->role != CI_ROLE_GADGET) {
+               seq_printf(s, "not in gadget mode\n");
                return 0;
        }
 
        spin_lock_irqsave(&ci->lock, flags);
-       k = hw_register_read(ci, dump, DUMP_ENTRIES);
-       spin_unlock_irqrestore(&ci->lock, flags);
+       for (i = 0; i < ci->hw_ep_max; i++)
+               list_for_each(ptr, &ci->ci13xxx_ep[i].qh.queue) {
+                       req = list_entry(ptr, struct ci13xxx_req, queue);
 
-       for (i = 0; i < k; i++) {
-               n += scnprintf(buf + n, PAGE_SIZE - n,
-                              "reg[0x%04X] = 0x%08X\n",
-                              i * (unsigned)sizeof(u32), dump[i]);
-       }
-       kfree(dump);
+                       seq_printf(s, "EP=%02i: TD=%08X %s\n",
+                                  i % (ci->hw_ep_max / 2), (u32)req->dma,
+                                  ((i < ci->hw_ep_max/2) ? "RX" : "TX"));
+
+                       for (j = 0; j < qsize; j++)
+                               seq_printf(s, " %04X:    %08X\n", j,
+                                          *((u32 *)req->ptr + j));
+               }
+       spin_unlock_irqrestore(&ci->lock, flags);
 
-       return n;
+       return 0;
 }
 
-/**
- * store_registers: writes value to register address
- *
- * Check "device.h" for details
- */
-static ssize_t store_registers(struct device *dev,
-                              struct device_attribute *attr,
-                              const char *buf, size_t count)
+static int ci_requests_open(struct inode *inode, struct file *file)
 {
-       struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
-       unsigned long addr, data, flags;
+       return single_open(file, ci_requests_show, inode->i_private);
+}
 
-       if (attr == NULL || buf == NULL) {
-               dev_err(ci->dev, "[%s] EINVAL\n", __func__);
-               goto done;
-       }
+static const struct file_operations ci_requests_fops = {
+       .open           = ci_requests_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
 
-       if (sscanf(buf, "%li %li", &addr, &data) != 2) {
-               dev_err(ci->dev,
-                       "<addr> <data>: write data to register address\n");
-               goto done;
-       }
+static int ci_role_show(struct seq_file *s, void *data)
+{
+       struct ci13xxx *ci = s->private;
 
-       spin_lock_irqsave(&ci->lock, flags);
-       if (hw_register_write(ci, addr, data))
-               dev_err(ci->dev, "invalid address range\n");
-       spin_unlock_irqrestore(&ci->lock, flags);
+       seq_printf(s, "%s\n", ci_role(ci)->name);
 
- done:
-       return count;
+       return 0;
 }
-static DEVICE_ATTR(registers, S_IRUSR | S_IWUSR,
-                  show_registers, store_registers);
 
-/**
- * show_requests: DMA contents of all requests currently queued (all endpts)
- *
- * Check "device.h" for details
- */
-static ssize_t show_requests(struct device *dev, struct device_attribute *attr,
-                            char *buf)
+static ssize_t ci_role_write(struct file *file, const char __user *ubuf,
+                            size_t count, loff_t *ppos)
 {
-       struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
-       unsigned long flags;
-       struct list_head   *ptr = NULL;
-       struct ci13xxx_req *req = NULL;
-       unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32);
-
-       if (attr == NULL || buf == NULL) {
-               dev_err(ci->dev, "[%s] EINVAL\n", __func__);
-               return 0;
-       }
+       struct seq_file *s = file->private_data;
+       struct ci13xxx *ci = s->private;
+       enum ci_role role;
+       char buf[8];
+       int ret;
+
+       if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
+               return -EFAULT;
+
+       for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++)
+               if (ci->roles[role] &&
+                   !strncmp(buf, ci->roles[role]->name,
+                            strlen(ci->roles[role]->name)))
+                       break;
 
-       spin_lock_irqsave(&ci->lock, flags);
-       for (i = 0; i < ci->hw_ep_max; i++)
-               list_for_each(ptr, &ci->ci13xxx_ep[i].qh.queue)
-               {
-                       req = list_entry(ptr, struct ci13xxx_req, queue);
+       if (role == CI_ROLE_END || role == ci->role)
+               return -EINVAL;
 
-                       n += scnprintf(buf + n, PAGE_SIZE - n,
-                                       "EP=%02i: TD=%08X %s\n",
-                                       i % ci->hw_ep_max/2, (u32)req->dma,
-                                       ((i < ci->hw_ep_max/2) ? "RX" : "TX"));
+       ci_role_stop(ci);
+       ret = ci_role_start(ci, role);
 
-                       for (j = 0; j < qSize; j++)
-                               n += scnprintf(buf + n, PAGE_SIZE - n,
-                                               " %04X:    %08X\n", j,
-                                               *((u32 *)req->ptr + j));
-               }
-       spin_unlock_irqrestore(&ci->lock, flags);
+       return ret ? ret : count;
+}
 
-       return n;
+static int ci_role_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, ci_role_show, inode->i_private);
 }
-static DEVICE_ATTR(requests, S_IRUSR, show_requests, NULL);
+
+static const struct file_operations ci_role_fops = {
+       .open           = ci_role_open,
+       .write          = ci_role_write,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
 
 /**
  * dbg_create_files: initializes the attribute interface
- * @dev: device
+ * @ci: device
  *
  * This function returns an error code
  */
-int dbg_create_files(struct device *dev)
+int dbg_create_files(struct ci13xxx *ci)
 {
-       int retval = 0;
-
-       if (dev == NULL)
-               return -EINVAL;
-       retval = device_create_file(dev, &dev_attr_device);
-       if (retval)
-               goto done;
-       retval = device_create_file(dev, &dev_attr_driver);
-       if (retval)
-               goto rm_device;
-       retval = device_create_file(dev, &dev_attr_events);
-       if (retval)
-               goto rm_driver;
-       retval = device_create_file(dev, &dev_attr_inters);
-       if (retval)
-               goto rm_events;
-       retval = device_create_file(dev, &dev_attr_port_test);
-       if (retval)
-               goto rm_inters;
-       retval = device_create_file(dev, &dev_attr_qheads);
-       if (retval)
-               goto rm_port_test;
-       retval = device_create_file(dev, &dev_attr_registers);
-       if (retval)
-               goto rm_qheads;
-       retval = device_create_file(dev, &dev_attr_requests);
-       if (retval)
-               goto rm_registers;
-       return 0;
-
- rm_registers:
-       device_remove_file(dev, &dev_attr_registers);
- rm_qheads:
-       device_remove_file(dev, &dev_attr_qheads);
- rm_port_test:
-       device_remove_file(dev, &dev_attr_port_test);
- rm_inters:
-       device_remove_file(dev, &dev_attr_inters);
- rm_events:
-       device_remove_file(dev, &dev_attr_events);
- rm_driver:
-       device_remove_file(dev, &dev_attr_driver);
- rm_device:
-       device_remove_file(dev, &dev_attr_device);
- done:
-       return retval;
+       struct dentry *dent;
+
+       ci->debugfs = debugfs_create_dir(dev_name(ci->dev), NULL);
+       if (!ci->debugfs)
+               return -ENOMEM;
+
+       dent = debugfs_create_file("device", S_IRUGO, ci->debugfs, ci,
+                                  &ci_device_fops);
+       if (!dent)
+               goto err;
+
+       dent = debugfs_create_file("port_test", S_IRUGO | S_IWUSR, ci->debugfs,
+                                  ci, &ci_port_test_fops);
+       if (!dent)
+               goto err;
+
+       dent = debugfs_create_file("qheads", S_IRUGO, ci->debugfs, ci,
+                                  &ci_qheads_fops);
+       if (!dent)
+               goto err;
+
+       dent = debugfs_create_file("requests", S_IRUGO, ci->debugfs, ci,
+                                  &ci_requests_fops);
+       if (!dent)
+               goto err;
+
+       dent = debugfs_create_file("role", S_IRUGO | S_IWUSR, ci->debugfs, ci,
+                                  &ci_role_fops);
+       if (dent)
+               return 0;
+err:
+       debugfs_remove_recursive(ci->debugfs);
+       return -ENOMEM;
 }
 
 /**
  * dbg_remove_files: destroys the attribute interface
- * @dev: device
- *
- * This function returns an error code
+ * @ci: device
  */
-int dbg_remove_files(struct device *dev)
+void dbg_remove_files(struct ci13xxx *ci)
 {
-       if (dev == NULL)
-               return -EINVAL;
-       device_remove_file(dev, &dev_attr_requests);
-       device_remove_file(dev, &dev_attr_registers);
-       device_remove_file(dev, &dev_attr_qheads);
-       device_remove_file(dev, &dev_attr_port_test);
-       device_remove_file(dev, &dev_attr_inters);
-       device_remove_file(dev, &dev_attr_events);
-       device_remove_file(dev, &dev_attr_driver);
-       device_remove_file(dev, &dev_attr_device);
-       return 0;
+       debugfs_remove_recursive(ci->debugfs);
 }
index 80d96865775c6e3b3bb28be933baa12e610e11eb..7ca6ca0a24a5056726c1c9af68baa3c34410c744 100644 (file)
 #define __DRIVERS_USB_CHIPIDEA_DEBUG_H
 
 #ifdef CONFIG_USB_CHIPIDEA_DEBUG
-void dbg_interrupt(u32 intmask);
-void dbg_done(u8 addr, const u32 token, int status);
-void dbg_event(u8 addr, const char *name, int status);
-void dbg_queue(u8 addr, const struct usb_request *req, int status);
-void dbg_setup(u8 addr, const struct usb_ctrlrequest *req);
-int dbg_create_files(struct device *dev);
-int dbg_remove_files(struct device *dev);
+int dbg_create_files(struct ci13xxx *ci);
+void dbg_remove_files(struct ci13xxx *ci);
 #else
-static inline void dbg_interrupt(u32 intmask)
-{
-}
-
-static inline void dbg_done(u8 addr, const u32 token, int status)
-{
-}
-
-static inline void dbg_event(u8 addr, const char *name, int status)
-{
-}
-
-static inline void dbg_queue(u8 addr, const struct usb_request *req, int status)
-{
-}
-
-static inline void dbg_setup(u8 addr, const struct usb_ctrlrequest *req)
-{
-}
-
-static inline int dbg_create_files(struct device *dev)
+static inline int dbg_create_files(struct ci13xxx *ci)
 {
        return 0;
 }
 
-static inline int dbg_remove_files(struct device *dev)
+static inline void dbg_remove_files(struct ci13xxx *ci)
 {
-       return 0;
 }
 #endif
 
index f64fbea1cf20aa689452ea50198ea9f8f70701b3..519ead2443c5630baaacaa4e1023e8ec766a2e39 100644 (file)
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/dmapool.h>
-#include <linux/dma-mapping.h>
 #include <linux/err.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
+#include <linux/irqreturn.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
@@ -146,7 +140,7 @@ static int hw_ep_enable(struct ci13xxx *ci, int num, int dir, int type)
 
        if (dir) {
                mask  = ENDPTCTRL_TXT;  /* type    */
-               data  = type << ffs_nr(mask);
+               data  = type << __ffs(mask);
 
                mask |= ENDPTCTRL_TXS;  /* unstall */
                mask |= ENDPTCTRL_TXR;  /* reset data toggle */
@@ -155,7 +149,7 @@ static int hw_ep_enable(struct ci13xxx *ci, int num, int dir, int type)
                data |= ENDPTCTRL_TXE;
        } else {
                mask  = ENDPTCTRL_RXT;  /* type    */
-               data  = type << ffs_nr(mask);
+               data  = type << __ffs(mask);
 
                mask |= ENDPTCTRL_RXS;  /* unstall */
                mask |= ENDPTCTRL_RXR;  /* reset data toggle */
@@ -305,18 +299,6 @@ static u32 hw_test_and_clear_intr_active(struct ci13xxx *ci)
        return reg;
 }
 
-static void hw_enable_vbus_intr(struct ci13xxx *ci)
-{
-       hw_write(ci, OP_OTGSC, OTGSC_AVVIS, OTGSC_AVVIS);
-       hw_write(ci, OP_OTGSC, OTGSC_AVVIE, OTGSC_AVVIE);
-       queue_work(ci->wq, &ci->vbus_work);
-}
-
-static void hw_disable_vbus_intr(struct ci13xxx *ci)
-{
-       hw_write(ci, OP_OTGSC, OTGSC_AVVIE, 0);
-}
-
 /**
  * hw_test_and_clear_setup_guard: test & clear setup guard (execute without
  *                                interruption)
@@ -349,7 +331,7 @@ static int hw_test_and_set_setup_guard(struct ci13xxx *ci)
 static void hw_usb_set_address(struct ci13xxx *ci, u8 value)
 {
        hw_write(ci, OP_DEVICEADDR, DEVICEADDR_USBADR,
-                value << ffs_nr(DEVICEADDR_USBADR));
+                value << __ffs(DEVICEADDR_USBADR));
 }
 
 /**
@@ -383,16 +365,6 @@ static int hw_usb_reset(struct ci13xxx *ci)
        return 0;
 }
 
-static void vbus_work(struct work_struct *work)
-{
-       struct ci13xxx *ci = container_of(work, struct ci13xxx, vbus_work);
-
-       if (hw_read(ci, OP_OTGSC, OTGSC_AVV))
-               usb_gadget_vbus_connect(&ci->gadget);
-       else
-               usb_gadget_vbus_disconnect(&ci->gadget);
-}
-
 /******************************************************************************
  * UTIL block
  *****************************************************************************/
@@ -432,10 +404,10 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
                        return -ENOMEM;
 
                memset(mReq->zptr, 0, sizeof(*mReq->zptr));
-               mReq->zptr->next    = TD_TERMINATE;
-               mReq->zptr->token   = TD_STATUS_ACTIVE;
+               mReq->zptr->next    = cpu_to_le32(TD_TERMINATE);
+               mReq->zptr->token   = cpu_to_le32(TD_STATUS_ACTIVE);
                if (!mReq->req.no_interrupt)
-                       mReq->zptr->token   |= TD_IOC;
+                       mReq->zptr->token   |= cpu_to_le32(TD_IOC);
        }
        ret = usb_gadget_map_request(&ci->gadget, &mReq->req, mEp->dir);
        if (ret)
@@ -446,32 +418,37 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
         * TODO - handle requests which spawns into several TDs
         */
        memset(mReq->ptr, 0, sizeof(*mReq->ptr));
-       mReq->ptr->token    = length << ffs_nr(TD_TOTAL_BYTES);
-       mReq->ptr->token   &= TD_TOTAL_BYTES;
-       mReq->ptr->token   |= TD_STATUS_ACTIVE;
+       mReq->ptr->token    = cpu_to_le32(length << __ffs(TD_TOTAL_BYTES));
+       mReq->ptr->token   &= cpu_to_le32(TD_TOTAL_BYTES);
+       mReq->ptr->token   |= cpu_to_le32(TD_STATUS_ACTIVE);
        if (mReq->zptr) {
-               mReq->ptr->next    = mReq->zdma;
+               mReq->ptr->next    = cpu_to_le32(mReq->zdma);
        } else {
-               mReq->ptr->next    = TD_TERMINATE;
+               mReq->ptr->next    = cpu_to_le32(TD_TERMINATE);
                if (!mReq->req.no_interrupt)
-                       mReq->ptr->token  |= TD_IOC;
+                       mReq->ptr->token  |= cpu_to_le32(TD_IOC);
+       }
+       mReq->ptr->page[0]  = cpu_to_le32(mReq->req.dma);
+       for (i = 1; i < TD_PAGE_COUNT; i++) {
+               u32 page = mReq->req.dma + i * CI13XXX_PAGE_SIZE;
+               page &= ~TD_RESERVED_MASK;
+               mReq->ptr->page[i] = cpu_to_le32(page);
        }
-       mReq->ptr->page[0]  = mReq->req.dma;
-       for (i = 1; i < 5; i++)
-               mReq->ptr->page[i] =
-                       (mReq->req.dma + i * CI13XXX_PAGE_SIZE) & ~TD_RESERVED_MASK;
+
+       wmb();
 
        if (!list_empty(&mEp->qh.queue)) {
                struct ci13xxx_req *mReqPrev;
                int n = hw_ep_bit(mEp->num, mEp->dir);
                int tmp_stat;
+               u32 next = mReq->dma & TD_ADDR_MASK;
 
                mReqPrev = list_entry(mEp->qh.queue.prev,
                                struct ci13xxx_req, queue);
                if (mReqPrev->zptr)
-                       mReqPrev->zptr->next = mReq->dma & TD_ADDR_MASK;
+                       mReqPrev->zptr->next = cpu_to_le32(next);
                else
-                       mReqPrev->ptr->next = mReq->dma & TD_ADDR_MASK;
+                       mReqPrev->ptr->next = cpu_to_le32(next);
                wmb();
                if (hw_read(ci, OP_ENDPTPRIME, BIT(n)))
                        goto done;
@@ -485,9 +462,9 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
        }
 
        /*  QH configuration */
-       mEp->qh.ptr->td.next   = mReq->dma;    /* TERMINATE = 0 */
-       mEp->qh.ptr->td.token &= ~TD_STATUS;   /* clear status */
-       mEp->qh.ptr->cap |=  QH_ZLT;
+       mEp->qh.ptr->td.next   = cpu_to_le32(mReq->dma);    /* TERMINATE = 0 */
+       mEp->qh.ptr->td.token &=
+               cpu_to_le32(~(TD_STATUS_HALTED|TD_STATUS_ACTIVE));
 
        wmb();   /* synchronize before ep prime */
 
@@ -506,14 +483,16 @@ done:
  */
 static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
 {
+       u32 tmptoken = le32_to_cpu(mReq->ptr->token);
+
        if (mReq->req.status != -EALREADY)
                return -EINVAL;
 
-       if ((TD_STATUS_ACTIVE & mReq->ptr->token) != 0)
+       if ((TD_STATUS_ACTIVE & tmptoken) != 0)
                return -EBUSY;
 
        if (mReq->zptr) {
-               if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
+               if ((cpu_to_le32(TD_STATUS_ACTIVE) & mReq->zptr->token) != 0)
                        return -EBUSY;
                dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
                mReq->zptr = NULL;
@@ -523,7 +502,7 @@ static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
 
        usb_gadget_unmap_request(&mEp->ci->gadget, &mReq->req, mEp->dir);
 
-       mReq->req.status = mReq->ptr->token & TD_STATUS;
+       mReq->req.status = tmptoken & TD_STATUS;
        if ((TD_STATUS_HALTED & mReq->req.status) != 0)
                mReq->req.status = -1;
        else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0)
@@ -531,8 +510,8 @@ static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
        else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0)
                mReq->req.status = -1;
 
-       mReq->req.actual   = mReq->ptr->token & TD_TOTAL_BYTES;
-       mReq->req.actual >>= ffs_nr(TD_TOTAL_BYTES);
+       mReq->req.actual   = tmptoken & TD_TOTAL_BYTES;
+       mReq->req.actual >>= __ffs(TD_TOTAL_BYTES);
        mReq->req.actual   = mReq->req.length - mReq->req.actual;
        mReq->req.actual   = mReq->req.status ? 0 : mReq->req.actual;
 
@@ -561,6 +540,12 @@ __acquires(mEp->lock)
                struct ci13xxx_req *mReq = \
                        list_entry(mEp->qh.queue.next,
                                   struct ci13xxx_req, queue);
+
+               if (mReq->zptr) {
+                       dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
+                       mReq->zptr = NULL;
+               }
+
                list_del_init(&mReq->queue);
                mReq->req.status = -ESHUTDOWN;
 
@@ -629,8 +614,6 @@ __acquires(ci->lock)
 {
        int retval;
 
-       dbg_event(0xFF, "BUS RST", 0);
-
        spin_unlock(&ci->lock);
        retval = _gadget_stop_activity(&ci->gadget);
        if (retval)
@@ -667,6 +650,59 @@ static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req)
        usb_ep_free_request(ep, req);
 }
 
+/**
+ * _ep_queue: queues (submits) an I/O request to an endpoint
+ *
+ * Caller must hold lock
+ */
+static int _ep_queue(struct usb_ep *ep, struct usb_request *req,
+                   gfp_t __maybe_unused gfp_flags)
+{
+       struct ci13xxx_ep  *mEp  = container_of(ep,  struct ci13xxx_ep, ep);
+       struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
+       struct ci13xxx *ci = mEp->ci;
+       int retval = 0;
+
+       if (ep == NULL || req == NULL || mEp->ep.desc == NULL)
+               return -EINVAL;
+
+       if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
+               if (req->length)
+                       mEp = (ci->ep0_dir == RX) ?
+                              ci->ep0out : ci->ep0in;
+               if (!list_empty(&mEp->qh.queue)) {
+                       _ep_nuke(mEp);
+                       retval = -EOVERFLOW;
+                       dev_warn(mEp->ci->dev, "endpoint ctrl %X nuked\n",
+                                _usb_addr(mEp));
+               }
+       }
+
+       /* first nuke then test link, e.g. previous status has not sent */
+       if (!list_empty(&mReq->queue)) {
+               dev_err(mEp->ci->dev, "request already in queue\n");
+               return -EBUSY;
+       }
+
+       if (req->length > (TD_PAGE_COUNT - 1) * CI13XXX_PAGE_SIZE) {
+               dev_err(mEp->ci->dev, "request bigger than one td\n");
+               return -EMSGSIZE;
+       }
+
+       /* push request */
+       mReq->req.status = -EINPROGRESS;
+       mReq->req.actual = 0;
+
+       retval = _hardware_enqueue(mEp, mReq);
+
+       if (retval == -EALREADY)
+               retval = 0;
+       if (!retval)
+               list_add_tail(&mReq->queue, &mEp->qh.queue);
+
+       return retval;
+}
+
 /**
  * isr_get_status_response: get_status request response
  * @ci: ci struct
@@ -714,9 +750,7 @@ __acquires(mEp->lock)
        }
        /* else do nothing; reserved for future use */
 
-       spin_unlock(mEp->lock);
-       retval = usb_ep_queue(&mEp->ep, req, gfp_flags);
-       spin_lock(mEp->lock);
+       retval = _ep_queue(&mEp->ep, req, gfp_flags);
        if (retval)
                goto err_free_buf;
 
@@ -763,8 +797,6 @@ isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
  * This function returns an error code
  */
 static int isr_setup_status_phase(struct ci13xxx *ci)
-__releases(mEp->lock)
-__acquires(mEp->lock)
 {
        int retval;
        struct ci13xxx_ep *mEp;
@@ -773,9 +805,7 @@ __acquires(mEp->lock)
        ci->status->context = ci;
        ci->status->complete = isr_setup_status_complete;
 
-       spin_unlock(mEp->lock);
-       retval = usb_ep_queue(&mEp->ep, ci->status, GFP_ATOMIC);
-       spin_lock(mEp->lock);
+       retval = _ep_queue(&mEp->ep, ci->status, GFP_ATOMIC);
 
        return retval;
 }
@@ -801,7 +831,6 @@ __acquires(mEp->lock)
                if (retval < 0)
                        break;
                list_del_init(&mReq->queue);
-               dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
                if (mReq->req.complete != NULL) {
                        spin_unlock(mEp->lock);
                        if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
@@ -814,8 +843,6 @@ __acquires(mEp->lock)
 
        if (retval == -EBUSY)
                retval = 0;
-       if (retval < 0)
-               dbg_event(_usb_addr(mEp), "DONE", retval);
 
        return retval;
 }
@@ -847,8 +874,6 @@ __acquires(ci->lock)
                                if (err > 0)   /* needs status phase */
                                        err = isr_setup_status_phase(ci);
                                if (err < 0) {
-                                       dbg_event(_usb_addr(mEp),
-                                                 "ERROR", err);
                                        spin_unlock(&ci->lock);
                                        if (usb_ep_set_halt(&mEp->ep))
                                                dev_err(ci->dev,
@@ -884,8 +909,6 @@ __acquires(ci->lock)
 
                ci->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
 
-               dbg_setup(_usb_addr(mEp), &req);
-
                switch (req.bRequest) {
                case USB_REQ_CLEAR_FEATURE:
                        if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
@@ -997,8 +1020,6 @@ delegate:
                }
 
                if (err < 0) {
-                       dbg_event(_usb_addr(mEp), "ERROR", err);
-
                        spin_unlock(&ci->lock);
                        if (usb_ep_set_halt(&mEp->ep))
                                dev_err(ci->dev, "error: ep_set_halt\n");
@@ -1021,6 +1042,7 @@ static int ep_enable(struct usb_ep *ep,
        struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep);
        int retval = 0;
        unsigned long flags;
+       u32 cap = 0;
 
        if (ep == NULL || desc == NULL)
                return -EINVAL;
@@ -1040,20 +1062,15 @@ static int ep_enable(struct usb_ep *ep,
 
        mEp->ep.maxpacket = usb_endpoint_maxp(desc);
 
-       dbg_event(_usb_addr(mEp), "ENABLE", 0);
-
-       mEp->qh.ptr->cap = 0;
-
        if (mEp->type == USB_ENDPOINT_XFER_CONTROL)
-               mEp->qh.ptr->cap |=  QH_IOS;
-       else if (mEp->type == USB_ENDPOINT_XFER_ISOC)
-               mEp->qh.ptr->cap &= ~QH_MULT;
-       else
-               mEp->qh.ptr->cap &= ~QH_ZLT;
+               cap |= QH_IOS;
+       if (mEp->num)
+               cap |= QH_ZLT;
+       cap |= (mEp->ep.maxpacket << __ffs(QH_MAX_PKT)) & QH_MAX_PKT;
+
+       mEp->qh.ptr->cap = cpu_to_le32(cap);
 
-       mEp->qh.ptr->cap |=
-               (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
-       mEp->qh.ptr->td.next |= TD_TERMINATE;   /* needed? */
+       mEp->qh.ptr->td.next |= cpu_to_le32(TD_TERMINATE);   /* needed? */
 
        /*
         * Enable endpoints in the HW other than ep0 as ep0
@@ -1088,8 +1105,6 @@ static int ep_disable(struct usb_ep *ep)
 
        direction = mEp->dir;
        do {
-               dbg_event(_usb_addr(mEp), "DISABLE", 0);
-
                retval |= _ep_nuke(mEp);
                retval |= hw_ep_disable(mEp->ci, mEp->num, mEp->dir);
 
@@ -1129,8 +1144,6 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
                }
        }
 
-       dbg_event(_usb_addr(mEp), "ALLOC", mReq == NULL);
-
        return (mReq == NULL) ? NULL : &mReq->req;
 }
 
@@ -1158,8 +1171,6 @@ static void ep_free_request(struct usb_ep *ep, struct usb_request *req)
                dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma);
        kfree(mReq);
 
-       dbg_event(_usb_addr(mEp), "FREE", 0);
-
        spin_unlock_irqrestore(mEp->lock, flags);
 }
 
@@ -1172,8 +1183,6 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
                    gfp_t __maybe_unused gfp_flags)
 {
        struct ci13xxx_ep  *mEp  = container_of(ep,  struct ci13xxx_ep, ep);
-       struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req);
-       struct ci13xxx *ci = mEp->ci;
        int retval = 0;
        unsigned long flags;
 
@@ -1181,48 +1190,7 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
                return -EINVAL;
 
        spin_lock_irqsave(mEp->lock, flags);
-
-       if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
-               if (req->length)
-                       mEp = (ci->ep0_dir == RX) ?
-                              ci->ep0out : ci->ep0in;
-               if (!list_empty(&mEp->qh.queue)) {
-                       _ep_nuke(mEp);
-                       retval = -EOVERFLOW;
-                       dev_warn(mEp->ci->dev, "endpoint ctrl %X nuked\n",
-                                _usb_addr(mEp));
-               }
-       }
-
-       /* first nuke then test link, e.g. previous status has not sent */
-       if (!list_empty(&mReq->queue)) {
-               retval = -EBUSY;
-               dev_err(mEp->ci->dev, "request already in queue\n");
-               goto done;
-       }
-
-       if (req->length > 4 * CI13XXX_PAGE_SIZE) {
-               req->length = 4 * CI13XXX_PAGE_SIZE;
-               retval = -EMSGSIZE;
-               dev_warn(mEp->ci->dev, "request length truncated\n");
-       }
-
-       dbg_queue(_usb_addr(mEp), req, retval);
-
-       /* push request */
-       mReq->req.status = -EINPROGRESS;
-       mReq->req.actual = 0;
-
-       retval = _hardware_enqueue(mEp, mReq);
-
-       if (retval == -EALREADY) {
-               dbg_event(_usb_addr(mEp), "QUEUE", retval);
-               retval = 0;
-       }
-       if (!retval)
-               list_add_tail(&mReq->queue, &mEp->qh.queue);
-
- done:
+       retval = _ep_queue(ep, req, gfp_flags);
        spin_unlock_irqrestore(mEp->lock, flags);
        return retval;
 }
@@ -1245,8 +1213,6 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
 
        spin_lock_irqsave(mEp->lock, flags);
 
-       dbg_event(_usb_addr(mEp), "DEQUEUE", 0);
-
        hw_ep_flush(mEp->ci, mEp->num, mEp->dir);
 
        /* pop request */
@@ -1293,7 +1259,6 @@ static int ep_set_halt(struct usb_ep *ep, int value)
 
        direction = mEp->dir;
        do {
-               dbg_event(_usb_addr(mEp), "HALT", value);
                retval |= hw_ep_set_halt(mEp->ci, mEp->num, mEp->dir, value);
 
                if (!value)
@@ -1322,10 +1287,7 @@ static int ep_set_wedge(struct usb_ep *ep)
                return -EINVAL;
 
        spin_lock_irqsave(mEp->lock, flags);
-
-       dbg_event(_usb_addr(mEp), "WEDGE", 0);
        mEp->wedge = 1;
-
        spin_unlock_irqrestore(mEp->lock, flags);
 
        return usb_ep_set_halt(ep);
@@ -1348,7 +1310,6 @@ static void ep_fifo_flush(struct usb_ep *ep)
 
        spin_lock_irqsave(mEp->lock, flags);
 
-       dbg_event(_usb_addr(mEp), "FFLUSH", 0);
        hw_ep_flush(mEp->ci, mEp->num, mEp->dir);
 
        spin_unlock_irqrestore(mEp->lock, flags);
@@ -1392,7 +1353,6 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active)
                if (is_active) {
                        pm_runtime_get_sync(&_gadget->dev);
                        hw_device_reset(ci, USBMODE_CM_DC);
-                       hw_enable_vbus_intr(ci);
                        hw_device_state(ci, ci->ep0out->qh.dma);
                } else {
                        hw_device_state(ci, 0);
@@ -1567,10 +1527,8 @@ static int ci13xxx_start(struct usb_gadget *gadget,
        pm_runtime_get_sync(&ci->gadget.dev);
        if (ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) {
                if (ci->vbus_active) {
-                       if (ci->platdata->flags & CI13XXX_REGS_SHARED) {
+                       if (ci->platdata->flags & CI13XXX_REGS_SHARED)
                                hw_device_reset(ci, USBMODE_CM_DC);
-                               hw_enable_vbus_intr(ci);
-                       }
                } else {
                        pm_runtime_put_sync(&ci->gadget.dev);
                        goto done;
@@ -1642,7 +1600,6 @@ static irqreturn_t udc_irq(struct ci13xxx *ci)
                }
        }
        intr = hw_test_and_clear_intr_active(ci);
-       dbg_interrupt(intr);
 
        if (intr) {
                /* order defines priority - do NOT change it */
@@ -1676,28 +1633,11 @@ static irqreturn_t udc_irq(struct ci13xxx *ci)
        } else {
                retval = IRQ_NONE;
        }
-
-       intr = hw_read(ci, OP_OTGSC, ~0);
-       hw_write(ci, OP_OTGSC, ~0, intr);
-
-       if (intr & (OTGSC_AVVIE & OTGSC_AVVIS))
-               queue_work(ci->wq, &ci->vbus_work);
-
        spin_unlock(&ci->lock);
 
        return retval;
 }
 
-/**
- * udc_release: driver release function
- * @dev: device
- *
- * Currently does nothing
- */
-static void udc_release(struct device *dev)
-{
-}
-
 /**
  * udc_start: initialize gadget role
  * @ci: chipidea controller
@@ -1717,12 +1657,6 @@ static int udc_start(struct ci13xxx *ci)
 
        INIT_LIST_HEAD(&ci->gadget.ep_list);
 
-       dev_set_name(&ci->gadget.dev, "gadget");
-       ci->gadget.dev.dma_mask = dev->dma_mask;
-       ci->gadget.dev.coherent_dma_mask = dev->coherent_dma_mask;
-       ci->gadget.dev.parent   = dev;
-       ci->gadget.dev.release  = udc_release;
-
        /* alloc resources */
        ci->qh_pool = dma_pool_create("ci13xxx_qh", dev,
                                       sizeof(struct ci13xxx_qh),
@@ -1758,24 +1692,13 @@ static int udc_start(struct ci13xxx *ci)
                retval = hw_device_reset(ci, USBMODE_CM_DC);
                if (retval)
                        goto put_transceiver;
-               hw_enable_vbus_intr(ci);
-       }
-
-       retval = device_register(&ci->gadget.dev);
-       if (retval) {
-               put_device(&ci->gadget.dev);
-               goto put_transceiver;
        }
 
-       retval = dbg_create_files(ci->dev);
-       if (retval)
-               goto unreg_device;
-
        if (!IS_ERR_OR_NULL(ci->transceiver)) {
                retval = otg_set_peripheral(ci->transceiver->otg,
                                                &ci->gadget);
                if (retval)
-                       goto remove_dbg;
+                       goto put_transceiver;
        }
 
        retval = usb_add_gadget_udc(dev, &ci->gadget);
@@ -1795,10 +1718,6 @@ remove_trans:
        }
 
        dev_err(dev, "error = %i\n", retval);
-remove_dbg:
-       dbg_remove_files(ci->dev);
-unreg_device:
-       device_unregister(&ci->gadget.dev);
 put_transceiver:
        if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy)
                usb_put_phy(ci->transceiver);
@@ -1821,9 +1740,6 @@ static void udc_stop(struct ci13xxx *ci)
        if (ci == NULL)
                return;
 
-       hw_disable_vbus_intr(ci);
-       cancel_work_sync(&ci->vbus_work);
-
        usb_del_gadget_udc(&ci->gadget);
 
        destroy_eps(ci);
@@ -1836,8 +1752,6 @@ static void udc_stop(struct ci13xxx *ci)
                if (ci->global_phy)
                        usb_put_phy(ci->transceiver);
        }
-       dbg_remove_files(ci->dev);
-       device_unregister(&ci->gadget.dev);
        /* my kobject is dynamic, I swear! */
        memset(&ci->gadget, 0, sizeof(ci->gadget));
 }
@@ -1864,7 +1778,6 @@ int ci_hdrc_gadget_init(struct ci13xxx *ci)
        rdrv->irq       = udc_irq;
        rdrv->name      = "gadget";
        ci->roles[CI_ROLE_GADGET] = rdrv;
-       INIT_WORK(&ci->vbus_work, vbus_work);
 
        return 0;
 }
index 4ff2384d7ca8170ca0a57d1e04e8b5b6237643e0..d12e8b59b11028bf497e561eacaab2cd513a5076 100644 (file)
@@ -40,7 +40,7 @@ struct ci13xxx_td {
 #define TD_CURR_OFFSET        (0x0FFFUL <<  0)
 #define TD_FRAME_NUM          (0x07FFUL <<  0)
 #define TD_RESERVED_MASK      (0x0FFFUL <<  0)
-} __attribute__ ((packed));
+} __attribute__ ((packed, aligned(4)));
 
 /* DMA layout of queue heads */
 struct ci13xxx_qh {
@@ -57,7 +57,7 @@ struct ci13xxx_qh {
        /* 9 */
        u32 RESERVED;
        struct usb_ctrlrequest   setup;
-} __attribute__ ((packed));
+} __attribute__ ((packed, aligned(4)));
 
 /**
  * struct ci13xxx_req - usb request representation
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
new file mode 100644 (file)
index 0000000..714a6bd
--- /dev/null
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#include "ci13xxx_imx.h"
+
+#define USB_DEV_MAX 4
+
+#define MX25_USB_PHY_CTRL_OFFSET       0x08
+#define MX25_BM_EXTERNAL_VBUS_DIVIDER  BIT(23)
+
+#define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08
+#define MX53_USB_UH2_CTRL_OFFSET       0x14
+#define MX53_USB_UH3_CTRL_OFFSET       0x18
+#define MX53_BM_OVER_CUR_DIS_H1                BIT(5)
+#define MX53_BM_OVER_CUR_DIS_OTG       BIT(8)
+#define MX53_BM_OVER_CUR_DIS_UHx       BIT(30)
+
+#define MX6_BM_OVER_CUR_DIS            BIT(7)
+
+struct imx_usbmisc {
+       void __iomem *base;
+       spinlock_t lock;
+       struct clk *clk;
+       struct usbmisc_usb_device usbdev[USB_DEV_MAX];
+       const struct usbmisc_ops *ops;
+};
+
+static struct imx_usbmisc *usbmisc;
+
+static struct usbmisc_usb_device *get_usbdev(struct device *dev)
+{
+       int i, ret;
+
+       for (i = 0; i < USB_DEV_MAX; i++) {
+               if (usbmisc->usbdev[i].dev == dev)
+                       return &usbmisc->usbdev[i];
+               else if (!usbmisc->usbdev[i].dev)
+                       break;
+       }
+
+       if (i >= USB_DEV_MAX)
+               return ERR_PTR(-EBUSY);
+
+       ret = usbmisc_get_init_data(dev, &usbmisc->usbdev[i]);
+       if (ret)
+               return ERR_PTR(ret);
+
+       return &usbmisc->usbdev[i];
+}
+
+static int usbmisc_imx25_post(struct device *dev)
+{
+       struct usbmisc_usb_device *usbdev;
+       void __iomem *reg;
+       unsigned long flags;
+       u32 val;
+
+       usbdev = get_usbdev(dev);
+       if (IS_ERR(usbdev))
+               return PTR_ERR(usbdev);
+
+       reg = usbmisc->base + MX25_USB_PHY_CTRL_OFFSET;
+
+       if (usbdev->evdo) {
+               spin_lock_irqsave(&usbmisc->lock, flags);
+               val = readl(reg);
+               writel(val | MX25_BM_EXTERNAL_VBUS_DIVIDER, reg);
+               spin_unlock_irqrestore(&usbmisc->lock, flags);
+               usleep_range(5000, 10000); /* needed to stabilize voltage */
+       }
+
+       return 0;
+}
+
+static int usbmisc_imx53_init(struct device *dev)
+{
+       struct usbmisc_usb_device *usbdev;
+       void __iomem *reg = NULL;
+       unsigned long flags;
+       u32 val = 0;
+
+       usbdev = get_usbdev(dev);
+       if (IS_ERR(usbdev))
+               return PTR_ERR(usbdev);
+
+       if (usbdev->disable_oc) {
+               spin_lock_irqsave(&usbmisc->lock, flags);
+               switch (usbdev->index) {
+               case 0:
+                       reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
+                       val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
+                       break;
+               case 1:
+                       reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
+                       val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1;
+                       break;
+               case 2:
+                       reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
+                       val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
+                       break;
+               case 3:
+                       reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
+                       val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
+                       break;
+               }
+               if (reg && val)
+                       writel(val, reg);
+               spin_unlock_irqrestore(&usbmisc->lock, flags);
+       }
+
+       return 0;
+}
+
+static int usbmisc_imx6q_init(struct device *dev)
+{
+
+       struct usbmisc_usb_device *usbdev;
+       unsigned long flags;
+       u32 reg;
+
+       usbdev = get_usbdev(dev);
+       if (IS_ERR(usbdev))
+               return PTR_ERR(usbdev);
+
+       if (usbdev->disable_oc) {
+               spin_lock_irqsave(&usbmisc->lock, flags);
+               reg = readl(usbmisc->base + usbdev->index * 4);
+               writel(reg | MX6_BM_OVER_CUR_DIS,
+                       usbmisc->base + usbdev->index * 4);
+               spin_unlock_irqrestore(&usbmisc->lock, flags);
+       }
+
+       return 0;
+}
+
+static const struct usbmisc_ops imx25_usbmisc_ops = {
+       .post = usbmisc_imx25_post,
+};
+
+static const struct usbmisc_ops imx53_usbmisc_ops = {
+       .init = usbmisc_imx53_init,
+};
+
+static const struct usbmisc_ops imx6q_usbmisc_ops = {
+       .init = usbmisc_imx6q_init,
+};
+
+static const struct of_device_id usbmisc_imx_dt_ids[] = {
+       {
+               .compatible = "fsl,imx25-usbmisc",
+               .data = &imx25_usbmisc_ops,
+       },
+       {
+               .compatible = "fsl,imx53-usbmisc",
+               .data = &imx53_usbmisc_ops,
+       },
+       {
+               .compatible = "fsl,imx6q-usbmisc",
+               .data = &imx6q_usbmisc_ops,
+       },
+       { /* sentinel */ }
+};
+
+static int usbmisc_imx_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       struct imx_usbmisc *data;
+       int ret;
+       struct of_device_id *tmp_dev;
+
+       if (usbmisc)
+               return -EBUSY;
+
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       spin_lock_init(&data->lock);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       data->base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(data->base))
+               return PTR_ERR(data->base);
+
+       data->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(data->clk)) {
+               dev_err(&pdev->dev,
+                       "failed to get clock, err=%ld\n", PTR_ERR(data->clk));
+               return PTR_ERR(data->clk);
+       }
+
+       ret = clk_prepare_enable(data->clk);
+       if (ret) {
+               dev_err(&pdev->dev,
+                       "clk_prepare_enable failed, err=%d\n", ret);
+               return ret;
+       }
+
+       tmp_dev = (struct of_device_id *)
+               of_match_device(usbmisc_imx_dt_ids, &pdev->dev);
+       data->ops = (const struct usbmisc_ops *)tmp_dev->data;
+       usbmisc = data;
+       ret = usbmisc_set_ops(data->ops);
+       if (ret) {
+               usbmisc = NULL;
+               clk_disable_unprepare(data->clk);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int usbmisc_imx_remove(struct platform_device *pdev)
+{
+       usbmisc_unset_ops(usbmisc->ops);
+       clk_disable_unprepare(usbmisc->clk);
+       usbmisc = NULL;
+       return 0;
+}
+
+static struct platform_driver usbmisc_imx_driver = {
+       .probe = usbmisc_imx_probe,
+       .remove = usbmisc_imx_remove,
+       .driver = {
+               .name = "usbmisc_imx",
+               .owner = THIS_MODULE,
+               .of_match_table = usbmisc_imx_dt_ids,
+        },
+};
+
+int usbmisc_imx_drv_init(void)
+{
+       return platform_driver_register(&usbmisc_imx_driver);
+}
+subsys_initcall(usbmisc_imx_drv_init);
+
+void usbmisc_imx_drv_exit(void)
+{
+       platform_driver_unregister(&usbmisc_imx_driver);
+}
+module_exit(usbmisc_imx_drv_exit);
+
+MODULE_ALIAS("platform:usbmisc-imx");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("driver for imx usb non-core registers");
+MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
diff --git a/drivers/usb/chipidea/usbmisc_imx6q.c b/drivers/usb/chipidea/usbmisc_imx6q.c
deleted file mode 100644 (file)
index a1bce39..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 2012 Freescale Semiconductor, Inc.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/module.h>
-#include <linux/of_platform.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-
-#include "ci13xxx_imx.h"
-
-#define USB_DEV_MAX 4
-
-#define BM_OVER_CUR_DIS                BIT(7)
-
-struct imx6q_usbmisc {
-       void __iomem *base;
-       spinlock_t lock;
-       struct clk *clk;
-       struct usbmisc_usb_device usbdev[USB_DEV_MAX];
-};
-
-static struct imx6q_usbmisc *usbmisc;
-
-static struct usbmisc_usb_device *get_usbdev(struct device *dev)
-{
-       int i, ret;
-
-       for (i = 0; i < USB_DEV_MAX; i++) {
-               if (usbmisc->usbdev[i].dev == dev)
-                       return &usbmisc->usbdev[i];
-               else if (!usbmisc->usbdev[i].dev)
-                       break;
-       }
-
-       if (i >= USB_DEV_MAX)
-               return ERR_PTR(-EBUSY);
-
-       ret = usbmisc_get_init_data(dev, &usbmisc->usbdev[i]);
-       if (ret)
-               return ERR_PTR(ret);
-
-       return &usbmisc->usbdev[i];
-}
-
-static int usbmisc_imx6q_init(struct device *dev)
-{
-
-       struct usbmisc_usb_device *usbdev;
-       unsigned long flags;
-       u32 reg;
-
-       usbdev = get_usbdev(dev);
-       if (IS_ERR(usbdev))
-               return PTR_ERR(usbdev);
-
-       if (usbdev->disable_oc) {
-               spin_lock_irqsave(&usbmisc->lock, flags);
-               reg = readl(usbmisc->base + usbdev->index * 4);
-               writel(reg | BM_OVER_CUR_DIS,
-                       usbmisc->base + usbdev->index * 4);
-               spin_unlock_irqrestore(&usbmisc->lock, flags);
-       }
-
-       return 0;
-}
-
-static const struct usbmisc_ops imx6q_usbmisc_ops = {
-       .init = usbmisc_imx6q_init,
-};
-
-static const struct of_device_id usbmisc_imx6q_dt_ids[] = {
-       { .compatible = "fsl,imx6q-usbmisc"},
-       { /* sentinel */ }
-};
-
-static int usbmisc_imx6q_probe(struct platform_device *pdev)
-{
-       struct resource *res;
-       struct imx6q_usbmisc *data;
-       int ret;
-
-       if (usbmisc)
-               return -EBUSY;
-
-       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       spin_lock_init(&data->lock);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       data->base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(data->base))
-               return PTR_ERR(data->base);
-
-       data->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(data->clk)) {
-               dev_err(&pdev->dev,
-                       "failed to get clock, err=%ld\n", PTR_ERR(data->clk));
-               return PTR_ERR(data->clk);
-       }
-
-       ret = clk_prepare_enable(data->clk);
-       if (ret) {
-               dev_err(&pdev->dev,
-                       "clk_prepare_enable failed, err=%d\n", ret);
-               return ret;
-       }
-
-       ret = usbmisc_set_ops(&imx6q_usbmisc_ops);
-       if (ret) {
-               clk_disable_unprepare(data->clk);
-               return ret;
-       }
-
-       usbmisc = data;
-
-       return 0;
-}
-
-static int usbmisc_imx6q_remove(struct platform_device *pdev)
-{
-       usbmisc_unset_ops(&imx6q_usbmisc_ops);
-       clk_disable_unprepare(usbmisc->clk);
-       return 0;
-}
-
-static struct platform_driver usbmisc_imx6q_driver = {
-       .probe = usbmisc_imx6q_probe,
-       .remove = usbmisc_imx6q_remove,
-       .driver = {
-               .name = "usbmisc_imx6q",
-               .owner = THIS_MODULE,
-               .of_match_table = usbmisc_imx6q_dt_ids,
-        },
-};
-
-int __init usbmisc_imx6q_drv_init(void)
-{
-       return platform_driver_register(&usbmisc_imx6q_driver);
-}
-subsys_initcall(usbmisc_imx6q_drv_init);
-
-void __exit usbmisc_imx6q_drv_exit(void)
-{
-       platform_driver_unregister(&usbmisc_imx6q_driver);
-}
-module_exit(usbmisc_imx6q_drv_exit);
-
-MODULE_ALIAS("platform:usbmisc-imx6q");
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("driver for imx6q usb non-core registers");
-MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
index 316aac8e4ca1934a34989d0d39c68bc47b46786a..bb8b73682a70ccf28dc7669368c892a187594007 100644 (file)
@@ -2,11 +2,10 @@
 # USB Class driver configuration
 #
 comment "USB Device Class drivers"
-       depends on USB
 
 config USB_ACM
        tristate "USB Modem (CDC ACM) support"
-       depends on USB && TTY
+       depends on TTY
        ---help---
          This driver supports USB modems and ISDN adapters which support the
          Communication Device Class Abstract Control Model interface.
@@ -21,7 +20,6 @@ config USB_ACM
 
 config USB_PRINTER
        tristate "USB Printer support"
-       depends on USB
        help
          Say Y here if you want to connect a USB printer to your computer's
          USB port.
@@ -31,7 +29,6 @@ config USB_PRINTER
 
 config USB_WDM
        tristate "USB Wireless Device Management support"
-       depends on USB
        ---help---
          This driver supports the WMC Device Management functionality
          of cell phones compliant to the CDC WMC specification. You can use
@@ -42,7 +39,6 @@ config USB_WDM
 
 config USB_TMC
        tristate "USB Test and Measurement Class support"
-       depends on USB
        help
          Say Y here if you want to connect a USB device that follows
          the USB.org specification for USB Test and Measurement devices
index c77f7ae48f1c1ed93260bea354e6c6b148a235f5..171d7a9df3aedd31fe660b4a7fec2cb5f9e1e6d8 100644 (file)
@@ -828,14 +828,6 @@ static int acm_tty_ioctl(struct tty_struct *tty,
        return rv;
 }
 
-static const __u32 acm_tty_speed[] = {
-       0, 50, 75, 110, 134, 150, 200, 300, 600,
-       1200, 1800, 2400, 4800, 9600, 19200, 38400,
-       57600, 115200, 230400, 460800, 500000, 576000,
-       921600, 1000000, 1152000, 1500000, 2000000,
-       2500000, 3000000, 3500000, 4000000
-};
-
 static void acm_tty_set_termios(struct tty_struct *tty,
                                                struct ktermios *termios_old)
 {
index 122d056d96d570c2d59762fda22e0e973ac081b5..8a230f0ef77c77b9acef90b86ab902e9cd4999eb 100644 (file)
@@ -13,6 +13,7 @@
  */
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <linux/ioctl.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
@@ -644,6 +645,22 @@ static int wdm_release(struct inode *inode, struct file *file)
        return 0;
 }
 
+static long wdm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct wdm_device *desc = file->private_data;
+       int rv = 0;
+
+       switch (cmd) {
+       case IOCTL_WDM_MAX_COMMAND:
+               if (copy_to_user((void __user *)arg, &desc->wMaxCommand, sizeof(desc->wMaxCommand)))
+                       rv = -EFAULT;
+               break;
+       default:
+               rv = -ENOTTY;
+       }
+       return rv;
+}
+
 static const struct file_operations wdm_fops = {
        .owner =        THIS_MODULE,
        .read =         wdm_read,
@@ -652,6 +669,8 @@ static const struct file_operations wdm_fops = {
        .flush =        wdm_flush,
        .release =      wdm_release,
        .poll =         wdm_poll,
+       .unlocked_ioctl = wdm_ioctl,
+       .compat_ioctl = wdm_ioctl,
        .llseek =       noop_llseek,
 };
 
index 70d69d06054f2faeaa1d4c9b2954d5cc0ca6e5b4..4c5506ae5e450db8a0977a618eb5e697bd6be1d0 100644 (file)
@@ -718,50 +718,32 @@ exit:
 
 static int usbtmc_ioctl_clear_out_halt(struct usbtmc_device_data *data)
 {
-       u8 *buffer;
        int rv;
 
-       buffer = kmalloc(2, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
-
        rv = usb_clear_halt(data->usb_dev,
                            usb_sndbulkpipe(data->usb_dev, data->bulk_out));
 
        if (rv < 0) {
                dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n",
                        rv);
-               goto exit;
+               return rv;
        }
-       rv = 0;
-
-exit:
-       kfree(buffer);
-       return rv;
+       return 0;
 }
 
 static int usbtmc_ioctl_clear_in_halt(struct usbtmc_device_data *data)
 {
-       u8 *buffer;
        int rv;
 
-       buffer = kmalloc(2, GFP_KERNEL);
-       if (!buffer)
-               return -ENOMEM;
-
        rv = usb_clear_halt(data->usb_dev,
                            usb_rcvbulkpipe(data->usb_dev, data->bulk_in));
 
        if (rv < 0) {
                dev_err(&data->usb_dev->dev, "usb_control_msg returned %d\n",
                        rv);
-               goto exit;
+               return rv;
        }
-       rv = 0;
-
-exit:
-       kfree(buffer);
-       return rv;
+       return 0;
 }
 
 static int get_capabilities(struct usbtmc_device_data *data)
index f70c1a1694ade4237e7ec7fee06f6c1342e46af1..8772b3659296b90b2c009774fd3bba8c0498236e 100644 (file)
@@ -3,7 +3,6 @@
 #
 config USB_DEBUG
        bool "USB verbose debug messages"
-       depends on USB
        help
          Say Y here if you want the USB core & hub drivers to produce a bunch
          of debug messages to the system log. Select this if you are having a
@@ -11,7 +10,6 @@ config USB_DEBUG
 
 config USB_ANNOUNCE_NEW_DEVICES
        bool "USB announce new devices"
-       depends on USB
        default N
        help
          Say Y here if you want the USB core to always announce the
@@ -25,11 +23,24 @@ config USB_ANNOUNCE_NEW_DEVICES
          log, or have any doubts about this, say N here.
 
 comment "Miscellaneous USB options"
-       depends on USB
+
+config USB_DEFAULT_PERSIST
+       bool "Enable USB persist by default"
+       default y
+       help
+         Say N here if you don't want USB power session persistance
+         enabled by default.  If you say N it will make suspended USB
+         devices that lose power get reenumerated as if they had been
+         unplugged, causing any mounted filesystems to be lost.  The
+         persist feature can still be enabled for individual devices
+         through the power/persist sysfs node. See
+         Documentation/usb/persist.txt for more info.
+
+         If you have any questions about this, say Y here, only say N
+         if you know exactly what you are doing.
 
 config USB_DYNAMIC_MINORS
        bool "Dynamic USB minor allocation"
-       depends on USB
        help
          If you say Y here, the USB subsystem will use dynamic minor
          allocation for any device that uses the USB major number.
@@ -38,25 +49,8 @@ config USB_DYNAMIC_MINORS
 
          If you are unsure about this, say N here.
 
-config USB_SUSPEND
-       bool "USB runtime power management (autosuspend) and wakeup"
-       depends on USB && PM_RUNTIME
-       help
-         If you say Y here, you can use driver calls or the sysfs
-         "power/control" file to enable or disable autosuspend for
-         individual USB peripherals (see
-         Documentation/usb/power-management.txt for more details).
-
-         Also, USB "remote wakeup" signaling is supported, whereby some
-         USB devices (like keyboards and network adapters) can wake up
-         their parent hub.  That wakeup cascades up the USB tree, and
-         could wake the system from states like suspend-to-RAM.
-
-         If you are unsure about this, say N here.
-
 config USB_OTG
        bool "OTG support"
-       depends on USB
        depends on USB_SUSPEND
        default n
        help
index 8823e98989fe9fe1a760d8c276a31ae718103f59..caefc800f2986defa9f66973d071fc7140d632d4 100644 (file)
@@ -739,6 +739,8 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,
        index &= 0xff;
        switch (requesttype & USB_RECIP_MASK) {
        case USB_RECIP_ENDPOINT:
+               if ((index & ~USB_DIR_IN) == 0)
+                       return 0;
                ret = findintfep(ps->dev, index);
                if (ret >= 0)
                        ret = checkintf(ps, ret);
index d938b2b99e31fcee332a2f83ae46e4998907190a..6eab440e1542e450f7733fb4cbbf35b1b1044313 100644 (file)
@@ -1196,9 +1196,14 @@ done:
  *
  * This is the central routine for suspending USB devices.  It calls the
  * suspend methods for all the interface drivers in @udev and then calls
- * the suspend method for @udev itself.  If an error occurs at any stage,
- * all the interfaces which were suspended are resumed so that they remain
- * in the same state as the device.
+ * the suspend method for @udev itself.  When the routine is called in
+ * autosuspend, if an error occurs at any stage, all the interfaces
+ * which were suspended are resumed so that they remain in the same
+ * state as the device, but when called from system sleep, all error
+ * from suspend methods of interfaces and the non-root-hub device itself
+ * are simply ignored, so all suspended interfaces are only resumed
+ * to the device's state when @udev is root-hub and its suspend method
+ * returns failure.
  *
  * Autosuspend requests originating from a child device or an interface
  * driver may be made without the protection of @udev's device lock, but
@@ -1248,10 +1253,12 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
 
        /* If the suspend failed, resume interfaces that did get suspended */
        if (status != 0) {
-               msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME);
-               while (++i < n) {
-                       intf = udev->actconfig->interface[i];
-                       usb_resume_interface(udev, intf, msg, 0);
+               if (udev->actconfig) {
+                       msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME);
+                       while (++i < n) {
+                               intf = udev->actconfig->interface[i];
+                               usb_resume_interface(udev, intf, msg, 0);
+                       }
                }
 
        /* If the suspend succeeded then prevent any more URB submissions
@@ -1407,7 +1414,7 @@ int usb_resume(struct device *dev, pm_message_t msg)
 
 #endif /* CONFIG_PM */
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 
 /**
  * usb_enable_autosuspend - allow a USB device to be autosuspended
@@ -1775,7 +1782,7 @@ int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
        return ret;
 }
 
-#endif /* CONFIG_USB_SUSPEND */
+#endif /* CONFIG_PM_RUNTIME */
 
 struct bus_type usb_bus_type = {
        .name =         "usb",
index 271e761f563ee42e54f59eb175e23e06e4d19c5b..acbfeb0a011903289a0d6a17fddcab275792fc72 100644 (file)
@@ -169,7 +169,7 @@ static int generic_probe(struct usb_device *udev)
                c = usb_choose_configuration(udev);
                if (c >= 0) {
                        err = usb_set_configuration(udev, c);
-                       if (err) {
+                       if (err && err != -ENODEV) {
                                dev_err(&udev->dev, "can't set config #%d, error %d\n",
                                        c, err);
                                /* This need not be fatal.  The user can try to
index 2b487d4797bd74057a9ad88148af199360d9de1d..caeb8d6d39fbb8b2e93cb4a0e1cf9d5bd54c2a67 100644 (file)
 
 /* PCI-based HCs are common, but plenty of non-PCI HCs are used too */
 
-#ifdef CONFIG_PM_SLEEP
-
-/* Coordinate handoffs between EHCI and companion controllers
- * during system resume
+/*
+ * Coordinate handoffs between EHCI and companion controllers
+ * during EHCI probing and system resume.
  */
 
-static DEFINE_MUTEX(companions_mutex);
+static DECLARE_RWSEM(companions_rwsem);
 
 #define CL_UHCI                PCI_CLASS_SERIAL_USB_UHCI
 #define CL_OHCI                PCI_CLASS_SERIAL_USB_OHCI
 #define CL_EHCI                PCI_CLASS_SERIAL_USB_EHCI
 
-enum companion_action {
-       SET_HS_COMPANION, CLEAR_HS_COMPANION, WAIT_FOR_COMPANIONS
-};
+static inline int is_ohci_or_uhci(struct pci_dev *pdev)
+{
+       return pdev->class == CL_OHCI || pdev->class == CL_UHCI;
+}
+
+typedef void (*companion_fn)(struct pci_dev *pdev, struct usb_hcd *hcd,
+               struct pci_dev *companion, struct usb_hcd *companion_hcd);
 
-static void companion_common(struct pci_dev *pdev, struct usb_hcd *hcd,
-               enum companion_action action)
+/* Iterate over PCI devices in the same slot as pdev and call fn for each */
+static void for_each_companion(struct pci_dev *pdev, struct usb_hcd *hcd,
+               companion_fn fn)
 {
        struct pci_dev          *companion;
        struct usb_hcd          *companion_hcd;
        unsigned int            slot = PCI_SLOT(pdev->devfn);
 
-       /* Iterate through other PCI functions in the same slot.
-        * If pdev is OHCI or UHCI then we are looking for EHCI, and
-        * vice versa.
+       /*
+        * Iterate through other PCI functions in the same slot.
+        * If the function's drvdata isn't set then it isn't bound to
+        * a USB host controller driver, so skip it.
         */
        companion = NULL;
        for_each_pci_dev(companion) {
                if (companion->bus != pdev->bus ||
                                PCI_SLOT(companion->devfn) != slot)
                        continue;
-
                companion_hcd = pci_get_drvdata(companion);
                if (!companion_hcd)
                        continue;
-
-               /* For SET_HS_COMPANION, store a pointer to the EHCI bus in
-                * the OHCI/UHCI companion bus structure.
-                * For CLEAR_HS_COMPANION, clear the pointer to the EHCI bus
-                * in the OHCI/UHCI companion bus structure.
-                * For WAIT_FOR_COMPANIONS, wait until the OHCI/UHCI
-                * companion controllers have fully resumed.
-                */
-
-               if ((pdev->class == CL_OHCI || pdev->class == CL_UHCI) &&
-                               companion->class == CL_EHCI) {
-                       /* action must be SET_HS_COMPANION */
-                       dev_dbg(&companion->dev, "HS companion for %s\n",
-                                       dev_name(&pdev->dev));
-                       hcd->self.hs_companion = &companion_hcd->self;
-
-               } else if (pdev->class == CL_EHCI &&
-                               (companion->class == CL_OHCI ||
-                               companion->class == CL_UHCI)) {
-                       switch (action) {
-                       case SET_HS_COMPANION:
-                               dev_dbg(&pdev->dev, "HS companion for %s\n",
-                                               dev_name(&companion->dev));
-                               companion_hcd->self.hs_companion = &hcd->self;
-                               break;
-                       case CLEAR_HS_COMPANION:
-                               companion_hcd->self.hs_companion = NULL;
-                               break;
-                       case WAIT_FOR_COMPANIONS:
-                               device_pm_wait_for_dev(&pdev->dev,
-                                               &companion->dev);
-                               break;
-                       }
-               }
+               fn(pdev, hcd, companion, companion_hcd);
        }
 }
 
-static void set_hs_companion(struct pci_dev *pdev, struct usb_hcd *hcd)
+/*
+ * We're about to add an EHCI controller, which will unceremoniously grab
+ * all the port connections away from its companions.  To prevent annoying
+ * error messages, lock the companion's root hub and gracefully unconfigure
+ * it beforehand.  Leave it locked until the EHCI controller is all set.
+ */
+static void ehci_pre_add(struct pci_dev *pdev, struct usb_hcd *hcd,
+               struct pci_dev *companion, struct usb_hcd *companion_hcd)
 {
-       mutex_lock(&companions_mutex);
-       dev_set_drvdata(&pdev->dev, hcd);
-       companion_common(pdev, hcd, SET_HS_COMPANION);
-       mutex_unlock(&companions_mutex);
+       struct usb_device *udev;
+
+       if (is_ohci_or_uhci(companion)) {
+               udev = companion_hcd->self.root_hub;
+               usb_lock_device(udev);
+               usb_set_configuration(udev, 0);
+       }
 }
 
-static void clear_hs_companion(struct pci_dev *pdev, struct usb_hcd *hcd)
+/*
+ * Adding the EHCI controller has either succeeded or failed.  Set the
+ * companion pointer accordingly, and in either case, reconfigure and
+ * unlock the root hub.
+ */
+static void ehci_post_add(struct pci_dev *pdev, struct usb_hcd *hcd,
+               struct pci_dev *companion, struct usb_hcd *companion_hcd)
 {
-       mutex_lock(&companions_mutex);
-       dev_set_drvdata(&pdev->dev, NULL);
+       struct usb_device *udev;
 
-       /* If pdev is OHCI or UHCI, just clear its hs_companion pointer */
-       if (pdev->class == CL_OHCI || pdev->class == CL_UHCI)
-               hcd->self.hs_companion = NULL;
+       if (is_ohci_or_uhci(companion)) {
+               if (dev_get_drvdata(&pdev->dev)) {      /* Succeeded */
+                       dev_dbg(&pdev->dev, "HS companion for %s\n",
+                                       dev_name(&companion->dev));
+                       companion_hcd->self.hs_companion = &hcd->self;
+               }
+               udev = companion_hcd->self.root_hub;
+               usb_set_configuration(udev, 1);
+               usb_unlock_device(udev);
+       }
+}
 
-       /* Otherwise search for companion buses and clear their pointers */
-       else
-               companion_common(pdev, hcd, CLEAR_HS_COMPANION);
-       mutex_unlock(&companions_mutex);
+/*
+ * We just added a non-EHCI controller.  Find the EHCI controller to
+ * which it is a companion, and store a pointer to the bus structure.
+ */
+static void non_ehci_add(struct pci_dev *pdev, struct usb_hcd *hcd,
+               struct pci_dev *companion, struct usb_hcd *companion_hcd)
+{
+       if (is_ohci_or_uhci(pdev) && companion->class == CL_EHCI) {
+               dev_dbg(&pdev->dev, "FS/LS companion for %s\n",
+                               dev_name(&companion->dev));
+               hcd->self.hs_companion = &companion_hcd->self;
+       }
 }
 
-static void wait_for_companions(struct pci_dev *pdev, struct usb_hcd *hcd)
+/* We are removing an EHCI controller.  Clear the companions' pointers. */
+static void ehci_remove(struct pci_dev *pdev, struct usb_hcd *hcd,
+               struct pci_dev *companion, struct usb_hcd *companion_hcd)
 {
-       /* Only EHCI controllers need to wait.
-        * No locking is needed because a controller cannot be resumed
-        * while one of its companions is getting unbound.
-        */
-       if (pdev->class == CL_EHCI)
-               companion_common(pdev, hcd, WAIT_FOR_COMPANIONS);
+       if (is_ohci_or_uhci(companion))
+               companion_hcd->self.hs_companion = NULL;
 }
 
-#else /* !CONFIG_PM_SLEEP */
+#ifdef CONFIG_PM
 
-static inline void set_hs_companion(struct pci_dev *d, struct usb_hcd *h) {}
-static inline void clear_hs_companion(struct pci_dev *d, struct usb_hcd *h) {}
-static inline void wait_for_companions(struct pci_dev *d, struct usb_hcd *h) {}
+/* An EHCI controller must wait for its companions before resuming. */
+static void ehci_wait_for_companions(struct pci_dev *pdev, struct usb_hcd *hcd,
+               struct pci_dev *companion, struct usb_hcd *companion_hcd)
+{
+       if (is_ohci_or_uhci(companion))
+               device_pm_wait_for_dev(&pdev->dev, &companion->dev);
+}
 
-#endif /* !CONFIG_PM_SLEEP */
+#endif /* CONFIG_PM */
 
 /*-------------------------------------------------------------------------*/
 
@@ -217,7 +221,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
                                driver->description)) {
                        dev_dbg(&dev->dev, "controller already in use\n");
                        retval = -EBUSY;
-                       goto clear_companion;
+                       goto put_hcd;
                }
                hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
                if (hcd->regs == NULL) {
@@ -244,16 +248,35 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
                if (region == PCI_ROM_RESOURCE) {
                        dev_dbg(&dev->dev, "no i/o regions available\n");
                        retval = -EBUSY;
-                       goto clear_companion;
+                       goto put_hcd;
                }
        }
 
        pci_set_master(dev);
 
-       retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED);
+       /* Note: dev_set_drvdata must be called while holding the rwsem */
+       if (dev->class == CL_EHCI) {
+               down_write(&companions_rwsem);
+               dev_set_drvdata(&dev->dev, hcd);
+               for_each_companion(dev, hcd, ehci_pre_add);
+               retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED);
+               if (retval != 0)
+                       dev_set_drvdata(&dev->dev, NULL);
+               for_each_companion(dev, hcd, ehci_post_add);
+               up_write(&companions_rwsem);
+       } else {
+               down_read(&companions_rwsem);
+               dev_set_drvdata(&dev->dev, hcd);
+               retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED);
+               if (retval != 0)
+                       dev_set_drvdata(&dev->dev, NULL);
+               else
+                       for_each_companion(dev, hcd, non_ehci_add);
+               up_read(&companions_rwsem);
+       }
+
        if (retval != 0)
                goto unmap_registers;
-       set_hs_companion(dev, hcd);
 
        if (pci_dev_run_wake(dev))
                pm_runtime_put_noidle(&dev->dev);
@@ -266,8 +289,7 @@ release_mem_region:
                release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
        } else
                release_region(hcd->rsrc_start, hcd->rsrc_len);
-clear_companion:
-       clear_hs_companion(dev, hcd);
+put_hcd:
        usb_put_hcd(hcd);
 disable_pci:
        pci_disable_device(dev);
@@ -310,14 +332,29 @@ void usb_hcd_pci_remove(struct pci_dev *dev)
        usb_hcd_irq(0, hcd);
        local_irq_enable();
 
-       usb_remove_hcd(hcd);
+       /* Note: dev_set_drvdata must be called while holding the rwsem */
+       if (dev->class == CL_EHCI) {
+               down_write(&companions_rwsem);
+               for_each_companion(dev, hcd, ehci_remove);
+               usb_remove_hcd(hcd);
+               dev_set_drvdata(&dev->dev, NULL);
+               up_write(&companions_rwsem);
+       } else {
+               /* Not EHCI; just clear the companion pointer */
+               down_read(&companions_rwsem);
+               hcd->self.hs_companion = NULL;
+               usb_remove_hcd(hcd);
+               dev_set_drvdata(&dev->dev, NULL);
+               up_read(&companions_rwsem);
+       }
+
        if (hcd->driver->flags & HCD_MEMORY) {
                iounmap(hcd->regs);
                release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
        } else {
                release_region(hcd->rsrc_start, hcd->rsrc_len);
        }
-       clear_hs_companion(dev, hcd);
+
        usb_put_hcd(hcd);
        pci_disable_device(dev);
 }
@@ -463,8 +500,15 @@ static int resume_common(struct device *dev, int event)
        pci_set_master(pci_dev);
 
        if (hcd->driver->pci_resume && !HCD_DEAD(hcd)) {
-               if (event != PM_EVENT_AUTO_RESUME)
-                       wait_for_companions(pci_dev, hcd);
+
+               /*
+                * Only EHCI controllers have to wait for their companions.
+                * No locking is needed because PCI controller drivers do not
+                * get unbound during system resume.
+                */
+               if (pci_dev->class == CL_EHCI && event != PM_EVENT_AUTO_RESUME)
+                       for_each_companion(pci_dev, hcd,
+                                       ehci_wait_for_companions);
 
                retval = hcd->driver->pci_resume(hcd,
                                event == PM_EVENT_RESTORE);
index f9ec44cbb82fb1ff6fa8e620367de8a9daec2c70..d53547d2e4c744c92b43ce55883351aa241f8fb4 100644 (file)
@@ -2125,7 +2125,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg)
 
 #endif /* CONFIG_PM */
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 
 /* Workqueue routine for root-hub remote wakeup */
 static void hcd_resume_work(struct work_struct *work)
@@ -2160,7 +2160,7 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd)
 }
 EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
 
-#endif /* CONFIG_USB_SUSPEND */
+#endif /* CONFIG_PM_RUNTIME */
 
 /*-------------------------------------------------------------------------*/
 
@@ -2336,7 +2336,7 @@ struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,
        init_timer(&hcd->rh_timer);
        hcd->rh_timer.function = rh_timer_func;
        hcd->rh_timer.data = (unsigned long) hcd;
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
        INIT_WORK(&hcd->wakeup_work, hcd_resume_work);
 #endif
 
@@ -2590,7 +2590,7 @@ error_create_attr_group:
        hcd->rh_registered = 0;
        spin_unlock_irq(&hcd_root_hub_lock);
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
        cancel_work_sync(&hcd->wakeup_work);
 #endif
        mutex_lock(&usb_bus_list_lock);
@@ -2645,7 +2645,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
        hcd->rh_registered = 0;
        spin_unlock_irq (&hcd_root_hub_lock);
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
        cancel_work_sync(&hcd->wakeup_work);
 #endif
 
index 5480352f984dc2df418902a430979c828cb5df52..feef9351463d99845a379ee3cdd1cb32b6772a4c 100644 (file)
@@ -555,8 +555,9 @@ static int hub_port_status(struct usb_hub *hub, int port1,
        mutex_lock(&hub->status_mutex);
        ret = get_port_status(hub->hdev, port1, &hub->status->port);
        if (ret < 4) {
-               dev_err(hub->intfdev,
-                       "%s failed (err = %d)\n", __func__, ret);
+               if (ret != -ENODEV)
+                       dev_err(hub->intfdev,
+                               "%s failed (err = %d)\n", __func__, ret);
                if (ret >= 0)
                        ret = -EIO;
        } else {
@@ -699,7 +700,7 @@ static void hub_tt_work(struct work_struct *work)
                /* drop lock so HCD can concurrently report other TT errors */
                spin_unlock_irqrestore (&hub->tt.lock, flags);
                status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt);
-               if (status)
+               if (status && status != -ENODEV)
                        dev_err (&hdev->dev,
                                "clear tt %d (%04x) error %d\n",
                                clear->tt, clear->devinfo, status);
@@ -837,10 +838,11 @@ static int hub_hub_status(struct usb_hub *hub,
 
        mutex_lock(&hub->status_mutex);
        ret = get_hub_status(hub->hdev, &hub->status->hub);
-       if (ret < 0)
-               dev_err (hub->intfdev,
-                       "%s failed (err = %d)\n", __func__, ret);
-       else {
+       if (ret < 0) {
+               if (ret != -ENODEV)
+                       dev_err(hub->intfdev,
+                               "%s failed (err = %d)\n", __func__, ret);
+       } else {
                *status = le16_to_cpu(hub->status->hub.wHubStatus);
                *change = le16_to_cpu(hub->status->hub.wHubChange); 
                ret = 0;
@@ -877,11 +879,8 @@ static int hub_usb3_port_disable(struct usb_hub *hub, int port1)
                return -EINVAL;
 
        ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED);
-       if (ret) {
-               dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
-                               port1, ret);
+       if (ret)
                return ret;
-       }
 
        /* Wait for the link to enter the disabled state. */
        for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) {
@@ -918,7 +917,7 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
                        ret = usb_clear_port_feature(hdev, port1,
                                        USB_PORT_FEAT_ENABLE);
        }
-       if (ret)
+       if (ret && ret != -ENODEV)
                dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
                                port1, ret);
        return ret;
@@ -1317,6 +1316,10 @@ static int hub_configure(struct usb_hub *hub,
                message = "hub has too many ports!";
                ret = -ENODEV;
                goto fail;
+       } else if (hub->descriptor->bNbrPorts == 0) {
+               message = "hub doesn't have any ports!";
+               ret = -ENODEV;
+               goto fail;
        }
 
        hdev->maxchild = hub->descriptor->bNbrPorts;
@@ -2192,8 +2195,9 @@ static int usb_enumerate_device(struct usb_device *udev)
        if (udev->config == NULL) {
                err = usb_get_configuration(udev);
                if (err < 0) {
-                       dev_err(&udev->dev, "can't read configurations, error %d\n",
-                               err);
+                       if (err != -ENODEV)
+                               dev_err(&udev->dev, "can't read configurations, error %d\n",
+                                               err);
                        return err;
                }
        }
@@ -2640,14 +2644,16 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
                status = set_port_feature(hub->hdev, port1, (warm ?
                                        USB_PORT_FEAT_BH_PORT_RESET :
                                        USB_PORT_FEAT_RESET));
-               if (status) {
+               if (status == -ENODEV) {
+                       ;       /* The hub is gone */
+               } else if (status) {
                        dev_err(hub->intfdev,
                                        "cannot %sreset port %d (err = %d)\n",
                                        warm ? "warm " : "", port1, status);
                } else {
                        status = hub_port_wait_reset(hub, port1, udev, delay,
                                                                warm);
-                       if (status && status != -ENOTCONN)
+                       if (status && status != -ENOTCONN && status != -ENODEV)
                                dev_dbg(hub->intfdev,
                                                "port_wait_reset: err = %d\n",
                                                status);
@@ -2821,7 +2827,7 @@ void usb_enable_ltm(struct usb_device *udev)
 }
 EXPORT_SYMBOL_GPL(usb_enable_ltm);
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM
 /*
  * usb_disable_function_remotewakeup - disable usb3.0
  * device's function remote wakeup
@@ -2880,9 +2886,11 @@ static int usb_disable_function_remotewakeup(struct usb_device *udev)
  * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
  * timer, no SRP, no requests through sysfs.
  *
- * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when
- * the root hub for their bus goes into global suspend ... so we don't
- * (falsely) update the device power state to say it suspended.
+ * If Runtime PM isn't enabled or used, non-SuperSpeed devices really get
+ * suspended only when their bus goes into global suspend (i.e., the root
+ * hub is suspended).  Nevertheless, we change @udev->state to
+ * USB_STATE_SUSPENDED as this is the device's "logical" state.  The actual
+ * upstream port setting is stored in @udev->port_is_suspended.
  *
  * Returns 0 on success, else negative errno.
  */
@@ -2893,6 +2901,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
        enum pm_qos_flags_status pm_qos_stat;
        int             port1 = udev->portnum;
        int             status;
+       bool            really_suspend = true;
 
        /* enable remote wakeup when appropriate; this lets the device
         * wake up the upstream hub (including maybe the root hub).
@@ -2949,9 +2958,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
        /* see 7.1.7.6 */
        if (hub_is_superspeed(hub->hdev))
                status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U3);
-       else
+       else if (PMSG_IS_AUTO(msg))
                status = set_port_feature(hub->hdev, port1,
                                                USB_PORT_FEAT_SUSPEND);
+       /*
+        * For system suspend, we do not need to enable the suspend feature
+        * on individual USB-2 ports.  The devices will automatically go
+        * into suspend a few ms after the root hub stops sending packets.
+        * The USB 2.0 spec calls this "global suspend".
+        */
+       else {
+               really_suspend = false;
+               status = 0;
+       }
        if (status) {
                dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
                                port1, status);
@@ -2987,8 +3006,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
                                (PMSG_IS_AUTO(msg) ? "auto-" : ""),
                                udev->do_remote_wakeup);
                usb_set_device_state(udev, USB_STATE_SUSPENDED);
-               udev->port_is_suspended = 1;
-               msleep(10);
+               if (really_suspend) {
+                       udev->port_is_suspended = 1;
+                       msleep(10);
+               }
        }
 
        /*
@@ -3226,6 +3247,10 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
        return status;
 }
 
+#endif /* CONFIG_PM */
+
+#ifdef CONFIG_PM_RUNTIME
+
 /* caller has locked udev */
 int usb_remote_wakeup(struct usb_device *udev)
 {
@@ -3242,38 +3267,6 @@ int usb_remote_wakeup(struct usb_device *udev)
        return status;
 }
 
-#else  /* CONFIG_USB_SUSPEND */
-
-/* When CONFIG_USB_SUSPEND isn't set, we never suspend or resume any ports. */
-
-int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
-{
-       return 0;
-}
-
-/* However we may need to do a reset-resume */
-
-int usb_port_resume(struct usb_device *udev, pm_message_t msg)
-{
-       struct usb_hub  *hub = usb_hub_to_struct_hub(udev->parent);
-       int             port1 = udev->portnum;
-       int             status;
-       u16             portchange, portstatus;
-
-       status = hub_port_status(hub, port1, &portstatus, &portchange);
-       status = check_port_resume_type(udev,
-                       hub, port1, status, portchange, portstatus);
-
-       if (status) {
-               dev_dbg(&udev->dev, "can't resume, status %d\n", status);
-               hub_port_logical_disconnect(hub, port1);
-       } else if (udev->reset_resume) {
-               dev_dbg(&udev->dev, "reset-resume\n");
-               status = usb_reset_and_verify_device(udev);
-       }
-       return status;
-}
-
 #endif
 
 static int check_ports_changed(struct usb_hub *hub)
@@ -4090,9 +4083,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
                                goto fail;
                        }
                        if (r) {
-                               dev_err(&udev->dev,
-                                       "device descriptor read/64, error %d\n",
-                                       r);
+                               if (r != -ENODEV)
+                                       dev_err(&udev->dev, "device descriptor read/64, error %d\n",
+                                                       r);
                                retval = -EMSGSIZE;
                                continue;
                        }
@@ -4112,9 +4105,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
                                msleep(200);
                        }
                        if (retval < 0) {
-                               dev_err(&udev->dev,
-                                       "device not accepting address %d, error %d\n",
-                                       devnum, retval);
+                               if (retval != -ENODEV)
+                                       dev_err(&udev->dev, "device not accepting address %d, error %d\n",
+                                                       devnum, retval);
                                goto fail;
                        }
                        if (udev->speed == USB_SPEED_SUPER) {
@@ -4136,7 +4129,8 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
 
                retval = usb_get_device_descriptor(udev, 8);
                if (retval < 8) {
-                       dev_err(&udev->dev,
+                       if (retval != -ENODEV)
+                               dev_err(&udev->dev,
                                        "device descriptor read/8, error %d\n",
                                        retval);
                        if (retval >= 0)
@@ -4190,8 +4184,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
   
        retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
        if (retval < (signed)sizeof(udev->descriptor)) {
-               dev_err(&udev->dev, "device descriptor read/all, error %d\n",
-                       retval);
+               if (retval != -ENODEV)
+                       dev_err(&udev->dev, "device descriptor read/all, error %d\n",
+                                       retval);
                if (retval >= 0)
                        retval = -ENOMSG;
                goto fail;
@@ -4333,7 +4328,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
                if (portstatus & USB_PORT_STAT_ENABLE) {
                        status = 0;             /* Nothing to do */
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
                } else if (udev->state == USB_STATE_SUSPENDED &&
                                udev->persist_enabled) {
                        /* For a suspended device, treat this as a
@@ -4373,7 +4368,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
                                USB_PORT_STAT_C_ENABLE)) {
                status = hub_port_debounce_be_stable(hub, port1);
                if (status < 0) {
-                       if (printk_ratelimit())
+                       if (status != -ENODEV && printk_ratelimit())
                                dev_err(hub_dev, "connect-debounce failed, "
                                                "port %d disabled\n", port1);
                        portstatus &= ~USB_PORT_STAT_CONNECTION;
@@ -4402,6 +4397,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
        else
                unit_load = 100;
 
+       status = 0;
        for (i = 0; i < SET_CONFIG_TRIES; i++) {
 
                /* reallocate for each attempt, since references
@@ -4526,9 +4522,11 @@ loop:
        }
        if (hub->hdev->parent ||
                        !hcd->driver->port_handed_over ||
-                       !(hcd->driver->port_handed_over)(hcd, port1))
-               dev_err(hub_dev, "unable to enumerate USB device on port %d\n",
-                               port1);
+                       !(hcd->driver->port_handed_over)(hcd, port1)) {
+               if (status != -ENOTCONN && status != -ENODEV)
+                       dev_err(hub_dev, "unable to enumerate USB device on port %d\n",
+                                       port1);
+       }
  
 done:
        hub_port_disable(hub, port1, 1);
index 65d4e55552c68f01fa606331afcd3096bdc31300..b8bad294eeb8d168d58a30e92875cb55c1dbbe81 100644 (file)
@@ -70,7 +70,7 @@ static void usb_port_device_release(struct device *dev)
        kfree(port_dev);
 }
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 static int usb_port_runtime_resume(struct device *dev)
 {
        struct usb_port *port_dev = to_usb_port(dev);
@@ -138,7 +138,7 @@ static int usb_port_runtime_suspend(struct device *dev)
 #endif
 
 static const struct dev_pm_ops usb_port_pm_ops = {
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
        .runtime_suspend =      usb_port_runtime_suspend,
        .runtime_resume =       usb_port_runtime_resume,
        .runtime_idle =         pm_generic_runtime_idle,
index 3113c1d71442953d3f9659afff042064bca8a9b9..ab5638d9c707c0524eb37a58fc1ce3e95d1a7ae9 100644 (file)
@@ -201,20 +201,14 @@ void usb_detect_quirks(struct usb_device *udev)
                dev_dbg(&udev->dev, "USB quirks for this device: %x\n",
                        udev->quirks);
 
-       /* For the present, all devices default to USB-PERSIST enabled */
-#if 0          /* was: #ifdef CONFIG_PM */
-       /* Hubs are automatically enabled for USB-PERSIST */
-       if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
+#ifdef CONFIG_USB_DEFAULT_PERSIST
+       if (!(udev->quirks & USB_QUIRK_RESET))
                udev->persist_enabled = 1;
-
 #else
-       /* In the absence of PM, we can safely enable USB-PERSIST
-        * for all devices.  It will affect things like hub resets
-        * and EMF-related port disables.
-        */
-       if (!(udev->quirks & USB_QUIRK_RESET))
+       /* Hubs are automatically enabled for USB-PERSIST */
+       if (udev->descriptor.bDeviceClass == USB_CLASS_HUB)
                udev->persist_enabled = 1;
-#endif /* CONFIG_PM */
+#endif /* CONFIG_USB_DEFAULT_PERSIST */
 }
 
 void usb_detect_interface_quirks(struct usb_device *udev)
index 3f81a3dc6867638a17ab4b0e2850aa1d79ec33c3..aa38db44818a99ab9331c11d2c670669d014498f 100644 (file)
@@ -338,7 +338,7 @@ static void remove_persist_attributes(struct device *dev)
 
 #endif /* CONFIG_PM */
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 
 static ssize_t
 show_connected_duration(struct device *dev, struct device_attribute *attr,
@@ -544,7 +544,7 @@ static void remove_power_attributes(struct device *dev)
 #define add_power_attributes(dev)      0
 #define remove_power_attributes(dev)   do {} while (0)
 
-#endif /* CONFIG_USB_SUSPEND */
+#endif /* CONFIG_PM_RUNTIME */
 
 
 /* Descriptor fields */
index e0d9d948218c665ce09730c00730757a5c33986e..16927fa88fbd61d2e81d02a42b6d1dfefac1fa65 100644 (file)
@@ -683,10 +683,13 @@ EXPORT_SYMBOL_GPL(usb_kill_urb);
 void usb_poison_urb(struct urb *urb)
 {
        might_sleep();
-       if (!(urb && urb->dev && urb->ep))
+       if (!urb)
                return;
        atomic_inc(&urb->reject);
 
+       if (!urb->dev || !urb->ep)
+               return;
+
        usb_hcd_unlink_urb(urb, -ENOENT);
        wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
 }
index e092b414dc50c776c2e9fab2f8247fe99a390359..b10da720f2b4d612385e778578a86b2562eb11ed 100644 (file)
@@ -49,7 +49,7 @@ const char *usbcore_name = "usbcore";
 
 static bool nousb;     /* Disable USB when built into kernel image */
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 static int usb_autosuspend_delay = 2;          /* Default delay value,
                                                 * in seconds */
 module_param_named(autosuspend, usb_autosuspend_delay, int, 0644);
@@ -307,7 +307,7 @@ static const struct dev_pm_ops usb_device_pm_ops = {
        .thaw =         usb_dev_thaw,
        .poweroff =     usb_dev_poweroff,
        .restore =      usb_dev_restore,
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
        .runtime_suspend =      usb_runtime_suspend,
        .runtime_resume =       usb_runtime_resume,
        .runtime_idle =         usb_runtime_idle,
index a7f20bde0e5e2a18d202a346b1e4024af28fd796..823857767a16f3384730dcf1f90c42f8eedc3588 100644 (file)
@@ -93,7 +93,7 @@ static inline int usb_port_resume(struct usb_device *udev, pm_message_t msg)
 
 #endif
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 
 extern void usb_autosuspend_device(struct usb_device *udev);
 extern int usb_autoresume_device(struct usb_device *udev);
index 68e9a2c5a01a7d62d1c10dfc1ceccf117582d22d..ea5ee9c21c3514cc7a0fe87ff2f6d15bcc206eb2 100644 (file)
@@ -1,7 +1,6 @@
 config USB_DWC3
        tristate "DesignWare USB3 DRD Core Support"
        depends on (USB || USB_GADGET) && GENERIC_HARDIRQS
-       select USB_OTG_UTILS
        select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD
        help
          Say Y or M here if your system has a Dual Role SuperSpeed
index ffa6b004a84bec3b4d58b9e5b6bd515d499e603d..c35d49d39b7615f83e7e71a9f009643e33c8d760 100644 (file)
@@ -140,7 +140,8 @@ static void dwc3_free_one_event_buffer(struct dwc3 *dwc,
  * Returns a pointer to the allocated event buffer structure on success
  * otherwise ERR_PTR(errno).
  */
-static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, unsigned length)
+static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc,
+               unsigned length)
 {
        struct dwc3_event_buffer        *evt;
 
@@ -259,6 +260,17 @@ static void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
        }
 }
 
+static void dwc3_core_num_eps(struct dwc3 *dwc)
+{
+       struct dwc3_hwparams    *parms = &dwc->hwparams;
+
+       dwc->num_in_eps = DWC3_NUM_IN_EPS(parms);
+       dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps;
+
+       dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n",
+                       dwc->num_in_eps, dwc->num_out_eps);
+}
+
 static void dwc3_cache_hwparams(struct dwc3 *dwc)
 {
        struct dwc3_hwparams    *parms = &dwc->hwparams;
@@ -335,13 +347,9 @@ static int dwc3_core_init(struct dwc3 *dwc)
        if (dwc->revision < DWC3_REVISION_190A)
                reg |= DWC3_GCTL_U2RSTECN;
 
-       dwc3_writel(dwc->regs, DWC3_GCTL, reg);
+       dwc3_core_num_eps(dwc);
 
-       ret = dwc3_event_buffers_setup(dwc);
-       if (ret) {
-               dev_err(dwc->dev, "failed to setup event buffers\n");
-               goto err0;
-       }
+       dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 
        return 0;
 
@@ -351,8 +359,6 @@ err0:
 
 static void dwc3_core_exit(struct dwc3 *dwc)
 {
-       dwc3_event_buffers_cleanup(dwc);
-
        usb_phy_shutdown(dwc->usb2_phy);
        usb_phy_shutdown(dwc->usb3_phy);
 }
@@ -428,12 +434,32 @@ static int dwc3_probe(struct platform_device *pdev)
                dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
        }
 
-       if (IS_ERR_OR_NULL(dwc->usb2_phy)) {
+       if (IS_ERR(dwc->usb2_phy)) {
+               ret = PTR_ERR(dwc->usb2_phy);
+
+               /*
+                * if -ENXIO is returned, it means PHY layer wasn't
+                * enabled, so it makes no sense to return -EPROBE_DEFER
+                * in that case, since no PHY driver will ever probe.
+                */
+               if (ret == -ENXIO)
+                       return ret;
+
                dev_err(dev, "no usb2 phy configured\n");
                return -EPROBE_DEFER;
        }
 
-       if (IS_ERR_OR_NULL(dwc->usb3_phy)) {
+       if (IS_ERR(dwc->usb3_phy)) {
+               ret = PTR_ERR(dwc->usb2_phy);
+
+               /*
+                * if -ENXIO is returned, it means PHY layer wasn't
+                * enabled, so it makes no sense to return -EPROBE_DEFER
+                * in that case, since no PHY driver will ever probe.
+                */
+               if (ret == -ENXIO)
+                       return ret;
+
                dev_err(dev, "no usb3 phy configured\n");
                return -EPROBE_DEFER;
        }
@@ -448,6 +474,10 @@ static int dwc3_probe(struct platform_device *pdev)
        dwc->regs_size  = resource_size(res);
        dwc->dev        = dev;
 
+       dev->dma_mask   = dev->parent->dma_mask;
+       dev->dma_parms  = dev->parent->dma_parms;
+       dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask);
+
        if (!strncmp("super", maximum_speed, 5))
                dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
        else if (!strncmp("high", maximum_speed, 4))
@@ -480,7 +510,18 @@ static int dwc3_probe(struct platform_device *pdev)
                goto err0;
        }
 
-       mode = DWC3_MODE(dwc->hwparams.hwparams0);
+       ret = dwc3_event_buffers_setup(dwc);
+       if (ret) {
+               dev_err(dwc->dev, "failed to setup event buffers\n");
+               goto err1;
+       }
+
+       if (IS_ENABLED(CONFIG_USB_DWC3_HOST))
+               mode = DWC3_MODE_HOST;
+       else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET))
+               mode = DWC3_MODE_DEVICE;
+       else
+               mode = DWC3_MODE_DRD;
 
        switch (mode) {
        case DWC3_MODE_DEVICE:
@@ -488,7 +529,7 @@ static int dwc3_probe(struct platform_device *pdev)
                ret = dwc3_gadget_init(dwc);
                if (ret) {
                        dev_err(dev, "failed to initialize gadget\n");
-                       goto err1;
+                       goto err2;
                }
                break;
        case DWC3_MODE_HOST:
@@ -496,7 +537,7 @@ static int dwc3_probe(struct platform_device *pdev)
                ret = dwc3_host_init(dwc);
                if (ret) {
                        dev_err(dev, "failed to initialize host\n");
-                       goto err1;
+                       goto err2;
                }
                break;
        case DWC3_MODE_DRD:
@@ -504,32 +545,32 @@ static int dwc3_probe(struct platform_device *pdev)
                ret = dwc3_host_init(dwc);
                if (ret) {
                        dev_err(dev, "failed to initialize host\n");
-                       goto err1;
+                       goto err2;
                }
 
                ret = dwc3_gadget_init(dwc);
                if (ret) {
                        dev_err(dev, "failed to initialize gadget\n");
-                       goto err1;
+                       goto err2;
                }
                break;
        default:
                dev_err(dev, "Unsupported mode of operation %d\n", mode);
-               goto err1;
+               goto err2;
        }
        dwc->mode = mode;
 
        ret = dwc3_debugfs_init(dwc);
        if (ret) {
                dev_err(dev, "failed to initialize debugfs\n");
-               goto err2;
+               goto err3;
        }
 
        pm_runtime_allow(dev);
 
        return 0;
 
-err2:
+err3:
        switch (mode) {
        case DWC3_MODE_DEVICE:
                dwc3_gadget_exit(dwc);
@@ -546,6 +587,9 @@ err2:
                break;
        }
 
+err2:
+       dwc3_event_buffers_cleanup(dwc);
+
 err1:
        dwc3_core_exit(dwc);
 
@@ -583,12 +627,130 @@ static int dwc3_remove(struct platform_device *pdev)
                break;
        }
 
+       dwc3_event_buffers_cleanup(dwc);
        dwc3_free_event_buffers(dwc);
        dwc3_core_exit(dwc);
 
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int dwc3_prepare(struct device *dev)
+{
+       struct dwc3     *dwc = dev_get_drvdata(dev);
+       unsigned long   flags;
+
+       spin_lock_irqsave(&dwc->lock, flags);
+
+       switch (dwc->mode) {
+       case DWC3_MODE_DEVICE:
+       case DWC3_MODE_DRD:
+               dwc3_gadget_prepare(dwc);
+               /* FALLTHROUGH */
+       case DWC3_MODE_HOST:
+       default:
+               dwc3_event_buffers_cleanup(dwc);
+               break;
+       }
+
+       spin_unlock_irqrestore(&dwc->lock, flags);
+
+       return 0;
+}
+
+static void dwc3_complete(struct device *dev)
+{
+       struct dwc3     *dwc = dev_get_drvdata(dev);
+       unsigned long   flags;
+
+       spin_lock_irqsave(&dwc->lock, flags);
+
+       switch (dwc->mode) {
+       case DWC3_MODE_DEVICE:
+       case DWC3_MODE_DRD:
+               dwc3_gadget_complete(dwc);
+               /* FALLTHROUGH */
+       case DWC3_MODE_HOST:
+       default:
+               dwc3_event_buffers_setup(dwc);
+               break;
+       }
+
+       spin_unlock_irqrestore(&dwc->lock, flags);
+}
+
+static int dwc3_suspend(struct device *dev)
+{
+       struct dwc3     *dwc = dev_get_drvdata(dev);
+       unsigned long   flags;
+
+       spin_lock_irqsave(&dwc->lock, flags);
+
+       switch (dwc->mode) {
+       case DWC3_MODE_DEVICE:
+       case DWC3_MODE_DRD:
+               dwc3_gadget_suspend(dwc);
+               /* FALLTHROUGH */
+       case DWC3_MODE_HOST:
+       default:
+               /* do nothing */
+               break;
+       }
+
+       dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL);
+       spin_unlock_irqrestore(&dwc->lock, flags);
+
+       usb_phy_shutdown(dwc->usb3_phy);
+       usb_phy_shutdown(dwc->usb2_phy);
+
+       return 0;
+}
+
+static int dwc3_resume(struct device *dev)
+{
+       struct dwc3     *dwc = dev_get_drvdata(dev);
+       unsigned long   flags;
+
+       usb_phy_init(dwc->usb3_phy);
+       usb_phy_init(dwc->usb2_phy);
+       msleep(100);
+
+       spin_lock_irqsave(&dwc->lock, flags);
+
+       dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl);
+
+       switch (dwc->mode) {
+       case DWC3_MODE_DEVICE:
+       case DWC3_MODE_DRD:
+               dwc3_gadget_resume(dwc);
+               /* FALLTHROUGH */
+       case DWC3_MODE_HOST:
+       default:
+               /* do nothing */
+               break;
+       }
+
+       spin_unlock_irqrestore(&dwc->lock, flags);
+
+       pm_runtime_disable(dev);
+       pm_runtime_set_active(dev);
+       pm_runtime_enable(dev);
+
+       return 0;
+}
+
+static const struct dev_pm_ops dwc3_dev_pm_ops = {
+       .prepare        = dwc3_prepare,
+       .complete       = dwc3_complete,
+
+       SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
+};
+
+#define DWC3_PM_OPS    &(dwc3_dev_pm_ops)
+#else
+#define DWC3_PM_OPS    NULL
+#endif
+
 #ifdef CONFIG_OF
 static const struct of_device_id of_dwc3_match[] = {
        {
@@ -605,6 +767,7 @@ static struct platform_driver dwc3_driver = {
        .driver         = {
                .name   = "dwc3",
                .of_match_table = of_match_ptr(of_dwc3_match),
+               .pm     = DWC3_PM_OPS,
        },
 };
 
index b4175066023590e9697c216c145c6f4a9b667b0c..b69d322e3cab51c4bcdb784d8f0e3eeda66028e2 100644 (file)
 /* OTG Registers */
 #define DWC3_OCFG              0xcc00
 #define DWC3_OCTL              0xcc04
-#define DWC3_OEVTEN            0xcc08
-#define DWC3_OSTS              0xcc0C
+#define DWC3_OEVT              0xcc08
+#define DWC3_OEVTEN            0xcc0C
+#define DWC3_OSTS              0xcc10
 
 /* Bit fields */
 
@@ -369,6 +370,9 @@ struct dwc3_trb;
  * @list: a list of event buffers
  * @buf: _THE_ buffer
  * @length: size of this buffer
+ * @lpos: event offset
+ * @count: cache of last read event count register
+ * @flags: flags related to this event buffer
  * @dma: dma_addr_t
  * @dwc: pointer to DWC controller
  */
@@ -376,6 +380,10 @@ struct dwc3_event_buffer {
        void                    *buf;
        unsigned                length;
        unsigned int            lpos;
+       unsigned int            count;
+       unsigned int            flags;
+
+#define DWC3_EVENT_PENDING     BIT(0)
 
        dma_addr_t              dma;
 
@@ -487,12 +495,6 @@ enum dwc3_link_state {
        DWC3_LINK_STATE_MASK            = 0x0f,
 };
 
-enum dwc3_device_state {
-       DWC3_DEFAULT_STATE,
-       DWC3_ADDRESS_STATE,
-       DWC3_CONFIGURED_STATE,
-};
-
 /* TRB Length, PCM and Status */
 #define DWC3_TRB_SIZE_MASK     (0x00ffffff)
 #define DWC3_TRB_SIZE_LENGTH(n)        ((n) & DWC3_TRB_SIZE_MASK)
@@ -574,6 +576,14 @@ struct dwc3_hwparams {
 /* HWPARAMS1 */
 #define DWC3_NUM_INT(n)                (((n) & (0x3f << 15)) >> 15)
 
+/* HWPARAMS3 */
+#define DWC3_NUM_IN_EPS_MASK   (0x1f << 18)
+#define DWC3_NUM_EPS_MASK      (0x3f << 12)
+#define DWC3_NUM_EPS(p)                (((p)->hwparams3 &              \
+                       (DWC3_NUM_EPS_MASK)) >> 12)
+#define DWC3_NUM_IN_EPS(p)     (((p)->hwparams3 &              \
+                       (DWC3_NUM_IN_EPS_MASK)) >> 18)
+
 /* HWPARAMS7 */
 #define DWC3_RAM1_DEPTH(n)     ((n) & 0xffff)
 
@@ -618,7 +628,6 @@ struct dwc3_scratchpad_array {
  * @gadget_driver: pointer to the gadget driver
  * @regs: base address for our registers
  * @regs_size: address space size
- * @irq: IRQ number
  * @num_event_buffers: calculated number of event buffers
  * @u1u2: only used on revisions <1.83a for workaround
  * @maximum_speed: maximum speed requested (mainly for testing purposes)
@@ -626,6 +635,8 @@ struct dwc3_scratchpad_array {
  * @mode: mode of operation
  * @usb2_phy: pointer to USB2 PHY
  * @usb3_phy: pointer to USB3 PHY
+ * @dcfg: saved contents of DCFG register
+ * @gctl: saved contents of GCTL register
  * @is_selfpowered: true when we are selfpowered
  * @three_stage_setup: set if we perform a three phase setup
  * @ep0_bounced: true when we used bounce buffer
@@ -639,6 +650,8 @@ struct dwc3_scratchpad_array {
  * @u2pel: parameter from Set SEL request.
  * @u1sel: parameter from Set SEL request.
  * @u1pel: parameter from Set SEL request.
+ * @num_out_eps: number of out endpoints
+ * @num_in_eps: number of in endpoints
  * @ep0_next_event: hold the next expected event
  * @ep0state: state of endpoint zero
  * @link_state: link state
@@ -656,8 +669,10 @@ struct dwc3 {
        dma_addr_t              ep0_trb_addr;
        dma_addr_t              ep0_bounce_addr;
        struct dwc3_request     ep0_usb_req;
+
        /* device lock */
        spinlock_t              lock;
+
        struct device           *dev;
 
        struct platform_device  *xhci;
@@ -675,6 +690,10 @@ struct dwc3 {
        void __iomem            *regs;
        size_t                  regs_size;
 
+       /* used for suspend/resume */
+       u32                     dcfg;
+       u32                     gctl;
+
        u32                     num_event_buffers;
        u32                     u1u2;
        u32                     maximum_speed;
@@ -694,6 +713,9 @@ struct dwc3 {
 #define DWC3_REVISION_202A     0x5533202a
 #define DWC3_REVISION_210A     0x5533210a
 #define DWC3_REVISION_220A     0x5533220a
+#define DWC3_REVISION_230A     0x5533230a
+#define DWC3_REVISION_240A     0x5533240a
+#define DWC3_REVISION_250A     0x5533250a
 
        unsigned                is_selfpowered:1;
        unsigned                three_stage_setup:1;
@@ -704,11 +726,11 @@ struct dwc3 {
        unsigned                delayed_status:1;
        unsigned                needs_fifo_resize:1;
        unsigned                resize_fifos:1;
+       unsigned                pullups_connected:1;
 
        enum dwc3_ep0_next      ep0_next_event;
        enum dwc3_ep0_state     ep0state;
        enum dwc3_link_state    link_state;
-       enum dwc3_device_state  dev_state;
 
        u16                     isoch_delay;
        u16                     u2sel;
@@ -718,6 +740,9 @@ struct dwc3 {
 
        u8                      speed;
 
+       u8                      num_out_eps;
+       u8                      num_in_eps;
+
        void                    *mem;
 
        struct dwc3_hwparams    hwparams;
@@ -884,4 +909,31 @@ static inline void dwc3_gadget_exit(struct dwc3 *dwc)
 { }
 #endif
 
+/* power management interface */
+#if !IS_ENABLED(CONFIG_USB_DWC3_HOST)
+int dwc3_gadget_prepare(struct dwc3 *dwc);
+void dwc3_gadget_complete(struct dwc3 *dwc);
+int dwc3_gadget_suspend(struct dwc3 *dwc);
+int dwc3_gadget_resume(struct dwc3 *dwc);
+#else
+static inline int dwc3_gadget_prepare(struct dwc3 *dwc)
+{
+       return 0;
+}
+
+static inline void dwc3_gadget_complete(struct dwc3 *dwc)
+{
+}
+
+static inline int dwc3_gadget_suspend(struct dwc3 *dwc)
+{
+       return 0;
+}
+
+static inline int dwc3_gadget_resume(struct dwc3 *dwc)
+{
+       return 0;
+}
+#endif /* !IS_ENABLED(CONFIG_USB_DWC3_HOST) */
+
 #endif /* __DRIVERS_USB_DWC3_CORE_H */
index 4a752e730c5f7d65424558a8f1529134f80c9d45..9e9f122162f2987919d18478be2cef3370e1c186 100644 (file)
@@ -59,7 +59,7 @@
        .offset = DWC3_ ##nm - DWC3_GLOBALS_REGS_START, \
 }
 
-static struct debugfs_reg32 dwc3_regs[] = {
+static const struct debugfs_reg32 dwc3_regs[] = {
        dump_register(GSBUSCFG0),
        dump_register(GSBUSCFG1),
        dump_register(GTXTHRCFG),
@@ -372,6 +372,7 @@ static struct debugfs_reg32 dwc3_regs[] = {
 
        dump_register(OCFG),
        dump_register(OCTL),
+       dump_register(OEVT),
        dump_register(OEVTEN),
        dump_register(OSTS),
 };
@@ -577,8 +578,14 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused)
        case DWC3_LINK_STATE_LPBK:
                seq_printf(s, "Loopback\n");
                break;
+       case DWC3_LINK_STATE_RESET:
+               seq_printf(s, "Reset\n");
+               break;
+       case DWC3_LINK_STATE_RESUME:
+               seq_printf(s, "Resume\n");
+               break;
        default:
-               seq_printf(s, "UNKNOWN %d\n", reg);
+               seq_printf(s, "UNKNOWN %d\n", state);
        }
 
        return 0;
@@ -661,28 +668,31 @@ int dwc3_debugfs_init(struct dwc3 *dwc)
                goto err1;
        }
 
-#if IS_ENABLED(CONFIG_USB_DWC3_GADGET)
-       file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root,
-                       dwc, &dwc3_mode_fops);
-       if (!file) {
-               ret = -ENOMEM;
-               goto err1;
-       }
-
-       file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root,
-                       dwc, &dwc3_testmode_fops);
-       if (!file) {
-               ret = -ENOMEM;
-               goto err1;
+       if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) {
+               file = debugfs_create_file("mode", S_IRUGO | S_IWUSR, root,
+                               dwc, &dwc3_mode_fops);
+               if (!file) {
+                       ret = -ENOMEM;
+                       goto err1;
+               }
        }
 
-       file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root,
-                       dwc, &dwc3_link_state_fops);
-       if (!file) {
-               ret = -ENOMEM;
-               goto err1;
+       if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) ||
+                       IS_ENABLED(CONFIG_USB_DWC3_GADGET)) {
+               file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root,
+                               dwc, &dwc3_testmode_fops);
+               if (!file) {
+                       ret = -ENOMEM;
+                       goto err1;
+               }
+
+               file = debugfs_create_file("link_state", S_IRUGO | S_IWUSR, root,
+                               dwc, &dwc3_link_state_fops);
+               if (!file) {
+                       ret = -ENOMEM;
+                       goto err1;
+               }
        }
-#endif
 
        return 0;
 
index b082bec7343e0e79cd3e1d062c2aba16173ffbab..a8afe6e2662186e50e45cf578d967c901c9a7456 100644 (file)
@@ -22,9 +22,9 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/nop-usb-xceiv.h>
 #include <linux/of.h>
+#include <linux/of_platform.h>
 
 struct dwc3_exynos {
-       struct platform_device  *dwc3;
        struct platform_device  *usb2_phy;
        struct platform_device  *usb3_phy;
        struct device           *dev;
@@ -86,21 +86,30 @@ err1:
        return ret;
 }
 
+static int dwc3_exynos_remove_child(struct device *dev, void *unused)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+
+       platform_device_unregister(pdev);
+
+       return 0;
+}
+
 static u64 dwc3_exynos_dma_mask = DMA_BIT_MASK(32);
 
 static int dwc3_exynos_probe(struct platform_device *pdev)
 {
-       struct platform_device  *dwc3;
        struct dwc3_exynos      *exynos;
        struct clk              *clk;
        struct device           *dev = &pdev->dev;
+       struct device_node      *node = dev->of_node;
 
        int                     ret = -ENOMEM;
 
        exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);
        if (!exynos) {
                dev_err(dev, "not enough memory\n");
-               return -ENOMEM;
+               goto err1;
        }
 
        /*
@@ -108,21 +117,15 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
         * Since shared usb code relies on it, set it here for now.
         * Once we move to full device tree support this will vanish off.
         */
-       if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &dwc3_exynos_dma_mask;
+       if (!dev->dma_mask)
+               dev->dma_mask = &dwc3_exynos_dma_mask;
 
        platform_set_drvdata(pdev, exynos);
 
        ret = dwc3_exynos_register_phys(exynos);
        if (ret) {
                dev_err(dev, "couldn't register PHYs\n");
-               return ret;
-       }
-
-       dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
-       if (!dwc3) {
-               dev_err(dev, "couldn't allocate dwc3 device\n");
-               return -ENOMEM;
+               goto err1;
        }
 
        clk = devm_clk_get(dev, "usbdrd30");
@@ -132,37 +135,28 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
                goto err1;
        }
 
-       dma_set_coherent_mask(&dwc3->dev, dev->coherent_dma_mask);
-
-       dwc3->dev.parent = dev;
-       dwc3->dev.dma_mask = dev->dma_mask;
-       dwc3->dev.dma_parms = dev->dma_parms;
-       exynos->dwc3    = dwc3;
        exynos->dev     = dev;
        exynos->clk     = clk;
 
-       clk_enable(exynos->clk);
-
-       ret = platform_device_add_resources(dwc3, pdev->resource,
-                       pdev->num_resources);
-       if (ret) {
-               dev_err(dev, "couldn't add resources to dwc3 device\n");
-               goto err2;
-       }
-
-       ret = platform_device_add(dwc3);
-       if (ret) {
-               dev_err(dev, "failed to register dwc3 device\n");
+       clk_prepare_enable(exynos->clk);
+
+       if (node) {
+               ret = of_platform_populate(node, NULL, NULL, dev);
+               if (ret) {
+                       dev_err(dev, "failed to add dwc3 core\n");
+                       goto err2;
+               }
+       } else {
+               dev_err(dev, "no device node, failed to add dwc3 core\n");
+               ret = -ENODEV;
                goto err2;
        }
 
        return 0;
 
 err2:
-       clk_disable(clk);
+       clk_disable_unprepare(clk);
 err1:
-       platform_device_put(dwc3);
-
        return ret;
 }
 
@@ -170,11 +164,11 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
 {
        struct dwc3_exynos      *exynos = platform_get_drvdata(pdev);
 
-       platform_device_unregister(exynos->dwc3);
        platform_device_unregister(exynos->usb2_phy);
        platform_device_unregister(exynos->usb3_phy);
+       device_for_each_child(&pdev->dev, NULL, dwc3_exynos_remove_child);
 
-       clk_disable(exynos->clk);
+       clk_disable_unprepare(exynos->clk);
 
        return 0;
 }
@@ -187,12 +181,46 @@ static const struct of_device_id exynos_dwc3_match[] = {
 MODULE_DEVICE_TABLE(of, exynos_dwc3_match);
 #endif
 
+#ifdef CONFIG_PM_SLEEP
+static int dwc3_exynos_suspend(struct device *dev)
+{
+       struct dwc3_exynos *exynos = dev_get_drvdata(dev);
+
+       clk_disable(exynos->clk);
+
+       return 0;
+}
+
+static int dwc3_exynos_resume(struct device *dev)
+{
+       struct dwc3_exynos *exynos = dev_get_drvdata(dev);
+
+       clk_enable(exynos->clk);
+
+       /* runtime set active to reflect active state. */
+       pm_runtime_disable(dev);
+       pm_runtime_set_active(dev);
+       pm_runtime_enable(dev);
+
+       return 0;
+}
+
+static const struct dev_pm_ops dwc3_exynos_dev_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(dwc3_exynos_suspend, dwc3_exynos_resume)
+};
+
+#define DEV_PM_OPS     (&dwc3_exynos_dev_pm_ops)
+#else
+#define DEV_PM_OPS     NULL
+#endif /* CONFIG_PM_SLEEP */
+
 static struct platform_driver dwc3_exynos_driver = {
        .probe          = dwc3_exynos_probe,
        .remove         = dwc3_exynos_remove,
        .driver         = {
                .name   = "exynos-dwc3",
                .of_match_table = of_match_ptr(exynos_dwc3_match),
+               .pm     = DEV_PM_OPS,
        },
 };
 
index afa05e3c9cf40b9b731e6d16f8543c07a6cb62c8..34638b92500d0606e1718a3e6ae43a7d3d2d0b46 100644 (file)
@@ -52,7 +52,6 @@
 #include <linux/of_platform.h>
 
 #include <linux/usb/otg.h>
-#include <linux/usb/nop-usb-xceiv.h>
 
 /*
  * All these registers belong to OMAP's Wrapper around the
@@ -117,20 +116,17 @@ struct dwc3_omap {
        /* device lock */
        spinlock_t              lock;
 
-       struct platform_device  *usb2_phy;
-       struct platform_device  *usb3_phy;
        struct device           *dev;
 
        int                     irq;
        void __iomem            *base;
 
-       void                    *context;
-       u32                     resource_size;
+       u32                     utmi_otg_status;
 
        u32                     dma_status:1;
 };
 
-struct dwc3_omap               *_omap;
+static struct dwc3_omap                *_omap;
 
 static inline u32 dwc3_omap_readl(void __iomem *base, u32 offset)
 {
@@ -142,11 +138,14 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value)
        writel(value, base + offset);
 }
 
-void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
+int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
 {
        u32                     val;
        struct dwc3_omap        *omap = _omap;
 
+       if (!omap)
+               return -EPROBE_DEFER;
+
        switch (status) {
        case OMAP_DWC3_ID_GROUND:
                dev_dbg(omap->dev, "ID GND\n");
@@ -189,63 +188,9 @@ void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
                dev_dbg(omap->dev, "ID float\n");
        }
 
-       return;
-}
-EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
-
-static int dwc3_omap_register_phys(struct dwc3_omap *omap)
-{
-       struct nop_usb_xceiv_platform_data pdata;
-       struct platform_device  *pdev;
-       int                     ret;
-
-       memset(&pdata, 0x00, sizeof(pdata));
-
-       pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
-       if (!pdev)
-               return -ENOMEM;
-
-       omap->usb2_phy = pdev;
-       pdata.type = USB_PHY_TYPE_USB2;
-
-       ret = platform_device_add_data(omap->usb2_phy, &pdata, sizeof(pdata));
-       if (ret)
-               goto err1;
-
-       pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO);
-       if (!pdev) {
-               ret = -ENOMEM;
-               goto err1;
-       }
-
-       omap->usb3_phy = pdev;
-       pdata.type = USB_PHY_TYPE_USB3;
-
-       ret = platform_device_add_data(omap->usb3_phy, &pdata, sizeof(pdata));
-       if (ret)
-               goto err2;
-
-       ret = platform_device_add(omap->usb2_phy);
-       if (ret)
-               goto err2;
-
-       ret = platform_device_add(omap->usb3_phy);
-       if (ret)
-               goto err3;
-
        return 0;
-
-err3:
-       platform_device_del(omap->usb2_phy);
-
-err2:
-       platform_device_put(omap->usb3_phy);
-
-err1:
-       platform_device_put(omap->usb2_phy);
-
-       return ret;
 }
+EXPORT_SYMBOL_GPL(dwc3_omap_mailbox);
 
 static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap)
 {
@@ -307,24 +252,57 @@ static int dwc3_omap_remove_core(struct device *dev, void *c)
        return 0;
 }
 
+static void dwc3_omap_enable_irqs(struct dwc3_omap *omap)
+{
+       u32                     reg;
+
+       /* enable all IRQs */
+       reg = USBOTGSS_IRQO_COREIRQ_ST;
+       dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg);
+
+       reg = (USBOTGSS_IRQ1_OEVT |
+                       USBOTGSS_IRQ1_DRVVBUS_RISE |
+                       USBOTGSS_IRQ1_CHRGVBUS_RISE |
+                       USBOTGSS_IRQ1_DISCHRGVBUS_RISE |
+                       USBOTGSS_IRQ1_IDPULLUP_RISE |
+                       USBOTGSS_IRQ1_DRVVBUS_FALL |
+                       USBOTGSS_IRQ1_CHRGVBUS_FALL |
+                       USBOTGSS_IRQ1_DISCHRGVBUS_FALL |
+                       USBOTGSS_IRQ1_IDPULLUP_FALL);
+
+       dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);
+}
+
+static void dwc3_omap_disable_irqs(struct dwc3_omap *omap)
+{
+       /* disable all IRQs */
+       dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, 0x00);
+       dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, 0x00);
+}
+
+static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32);
+
 static int dwc3_omap_probe(struct platform_device *pdev)
 {
-       struct dwc3_omap_data   *pdata = pdev->dev.platform_data;
        struct device_node      *node = pdev->dev.of_node;
 
        struct dwc3_omap        *omap;
        struct resource         *res;
        struct device           *dev = &pdev->dev;
 
-       int                     size;
        int                     ret = -ENOMEM;
        int                     irq;
 
-       const u32               *utmi_mode;
+       int                     utmi_mode = 0;
+
        u32                     reg;
 
        void __iomem            *base;
-       void                    *context;
+
+       if (!node) {
+               dev_err(dev, "device node not found\n");
+               return -EINVAL;
+       }
 
        omap = devm_kzalloc(dev, sizeof(*omap), GFP_KERNEL);
        if (!omap) {
@@ -334,13 +312,13 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, omap);
 
-       irq = platform_get_irq(pdev, 1);
+       irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                dev_err(dev, "missing IRQ resource\n");
                return -EINVAL;
        }
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(dev, "missing memory base resource\n");
                return -EINVAL;
@@ -352,25 +330,12 @@ static int dwc3_omap_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
-       ret = dwc3_omap_register_phys(omap);
-       if (ret) {
-               dev_err(dev, "couldn't register PHYs\n");
-               return ret;
-       }
-
-       context = devm_kzalloc(dev, resource_size(res), GFP_KERNEL);
-       if (!context) {
-               dev_err(dev, "couldn't allocate dwc3 context memory\n");
-               return -ENOMEM;
-       }
-
        spin_lock_init(&omap->lock);
 
-       omap->resource_size = resource_size(res);
-       omap->context   = context;
        omap->dev       = dev;
        omap->irq       = irq;
        omap->base      = base;
+       dev->dma_mask   = &dwc3_omap_dma_mask;
 
        /*
         * REVISIT if we ever have two instances of the wrapper, we will be
@@ -387,25 +352,17 @@ static int dwc3_omap_probe(struct platform_device *pdev)
 
        reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS);
 
-       utmi_mode = of_get_property(node, "utmi-mode", &size);
-       if (utmi_mode && size == sizeof(*utmi_mode)) {
-               reg |= *utmi_mode;
-       } else {
-               if (!pdata) {
-                       dev_dbg(dev, "missing platform data\n");
-               } else {
-                       switch (pdata->utmi_mode) {
-                       case DWC3_OMAP_UTMI_MODE_SW:
-                               reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
-                               break;
-                       case DWC3_OMAP_UTMI_MODE_HW:
-                               reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
-                               break;
-                       default:
-                               dev_dbg(dev, "UNKNOWN utmi mode %d\n",
-                                               pdata->utmi_mode);
-                       }
-               }
+       of_property_read_u32(node, "utmi-mode", &utmi_mode);
+
+       switch (utmi_mode) {
+       case DWC3_OMAP_UTMI_MODE_SW:
+               reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+               break;
+       case DWC3_OMAP_UTMI_MODE_HW:
+               reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+               break;
+       default:
+               dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode);
        }
 
        dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg);
@@ -422,29 +379,12 @@ static int dwc3_omap_probe(struct platform_device *pdev)
                return ret;
        }
 
-       /* enable all IRQs */
-       reg = USBOTGSS_IRQO_COREIRQ_ST;
-       dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg);
+       dwc3_omap_enable_irqs(omap);
 
-       reg = (USBOTGSS_IRQ1_OEVT |
-                       USBOTGSS_IRQ1_DRVVBUS_RISE |
-                       USBOTGSS_IRQ1_CHRGVBUS_RISE |
-                       USBOTGSS_IRQ1_DISCHRGVBUS_RISE |
-                       USBOTGSS_IRQ1_IDPULLUP_RISE |
-                       USBOTGSS_IRQ1_DRVVBUS_FALL |
-                       USBOTGSS_IRQ1_CHRGVBUS_FALL |
-                       USBOTGSS_IRQ1_DISCHRGVBUS_FALL |
-                       USBOTGSS_IRQ1_IDPULLUP_FALL);
-
-       dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg);
-
-       if (node) {
-               ret = of_platform_populate(node, NULL, NULL, dev);
-               if (ret) {
-                       dev_err(&pdev->dev,
-                               "failed to add create dwc3 core\n");
-                       return ret;
-               }
+       ret = of_platform_populate(node, NULL, NULL, dev);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to create dwc3 core\n");
+               return ret;
        }
 
        return 0;
@@ -454,8 +394,7 @@ static int dwc3_omap_remove(struct platform_device *pdev)
 {
        struct dwc3_omap        *omap = platform_get_drvdata(pdev);
 
-       platform_device_unregister(omap->usb2_phy);
-       platform_device_unregister(omap->usb3_phy);
+       dwc3_omap_disable_irqs(omap);
        pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
        device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
@@ -465,18 +404,72 @@ static int dwc3_omap_remove(struct platform_device *pdev)
 
 static const struct of_device_id of_dwc3_match[] = {
        {
-               "ti,dwc3",
+               .compatible =   "ti,dwc3"
        },
        { },
 };
 MODULE_DEVICE_TABLE(of, of_dwc3_match);
 
+#ifdef CONFIG_PM_SLEEP
+static int dwc3_omap_prepare(struct device *dev)
+{
+       struct dwc3_omap        *omap = dev_get_drvdata(dev);
+
+       dwc3_omap_disable_irqs(omap);
+
+       return 0;
+}
+
+static void dwc3_omap_complete(struct device *dev)
+{
+       struct dwc3_omap        *omap = dev_get_drvdata(dev);
+
+       dwc3_omap_enable_irqs(omap);
+}
+
+static int dwc3_omap_suspend(struct device *dev)
+{
+       struct dwc3_omap        *omap = dev_get_drvdata(dev);
+
+       omap->utmi_otg_status = dwc3_omap_readl(omap->base,
+                       USBOTGSS_UTMI_OTG_STATUS);
+
+       return 0;
+}
+
+static int dwc3_omap_resume(struct device *dev)
+{
+       struct dwc3_omap        *omap = dev_get_drvdata(dev);
+
+       dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS,
+                       omap->utmi_otg_status);
+
+       pm_runtime_disable(dev);
+       pm_runtime_set_active(dev);
+       pm_runtime_enable(dev);
+
+       return 0;
+}
+
+static const struct dev_pm_ops dwc3_omap_dev_pm_ops = {
+       .prepare        = dwc3_omap_prepare,
+       .complete       = dwc3_omap_complete,
+
+       SET_SYSTEM_SLEEP_PM_OPS(dwc3_omap_suspend, dwc3_omap_resume)
+};
+
+#define DEV_PM_OPS     (&dwc3_omap_dev_pm_ops)
+#else
+#define DEV_PM_OPS     NULL
+#endif /* CONFIG_PM_SLEEP */
+
 static struct platform_driver dwc3_omap_driver = {
        .probe          = dwc3_omap_probe,
        .remove         = dwc3_omap_remove,
        .driver         = {
                .name   = "omap-dwc3",
                .of_match_table = of_dwc3_match,
+               .pm     = DEV_PM_OPS,
        },
 };
 
index e8d77689a322d941042643a980e423545f7bc365..227d4a7acad7595d4774e9fc335a790c742087be 100644 (file)
@@ -212,11 +212,49 @@ static DEFINE_PCI_DEVICE_TABLE(dwc3_pci_id_table) = {
 };
 MODULE_DEVICE_TABLE(pci, dwc3_pci_id_table);
 
+#ifdef CONFIG_PM
+static int dwc3_pci_suspend(struct device *dev)
+{
+       struct pci_dev  *pci = to_pci_dev(dev);
+
+       pci_disable_device(pci);
+
+       return 0;
+}
+
+static int dwc3_pci_resume(struct device *dev)
+{
+       struct pci_dev  *pci = to_pci_dev(dev);
+       int             ret;
+
+       ret = pci_enable_device(pci);
+       if (ret) {
+               dev_err(dev, "can't re-enable device --> %d\n", ret);
+               return ret;
+       }
+
+       pci_set_master(pci);
+
+       return 0;
+}
+
+static const struct dev_pm_ops dwc3_pci_dev_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume)
+};
+
+#define DEV_PM_OPS     (&dwc3_pci_dev_pm_ops)
+#else
+#define DEV_PM_OPS     NULL
+#endif /* CONFIG_PM */
+
 static struct pci_driver dwc3_pci_driver = {
        .name           = "dwc3-pci",
        .id_table       = dwc3_pci_id_table,
        .probe          = dwc3_pci_probe,
        .remove         = dwc3_pci_remove,
+       .driver         = {
+               .pm     = DEV_PM_OPS,
+       },
 };
 
 MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
index 1d139ca05ef17bdd56cdfa3ba9027ea70c337d88..5acbb948b7048ffb22c6e921e93f6617bec1cbe7 100644 (file)
@@ -394,10 +394,13 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
        u32                     wIndex;
        u32                     reg;
        int                     ret;
+       enum usb_device_state   state;
 
        wValue = le16_to_cpu(ctrl->wValue);
        wIndex = le16_to_cpu(ctrl->wIndex);
        recip = ctrl->bRequestType & USB_RECIP_MASK;
+       state = dwc->gadget.state;
+
        switch (recip) {
        case USB_RECIP_DEVICE:
 
@@ -409,7 +412,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
                 * default control pipe
                 */
                case USB_DEVICE_U1_ENABLE:
-                       if (dwc->dev_state != DWC3_CONFIGURED_STATE)
+                       if (state != USB_STATE_CONFIGURED)
                                return -EINVAL;
                        if (dwc->speed != DWC3_DSTS_SUPERSPEED)
                                return -EINVAL;
@@ -423,7 +426,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
                        break;
 
                case USB_DEVICE_U2_ENABLE:
-                       if (dwc->dev_state != DWC3_CONFIGURED_STATE)
+                       if (state != USB_STATE_CONFIGURED)
                                return -EINVAL;
                        if (dwc->speed != DWC3_DSTS_SUPERSPEED)
                                return -EINVAL;
@@ -493,6 +496,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
 
 static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 {
+       enum usb_device_state state = dwc->gadget.state;
        u32 addr;
        u32 reg;
 
@@ -502,7 +506,7 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
                return -EINVAL;
        }
 
-       if (dwc->dev_state == DWC3_CONFIGURED_STATE) {
+       if (state == USB_STATE_CONFIGURED) {
                dev_dbg(dwc->dev, "trying to set address when configured\n");
                return -EINVAL;
        }
@@ -513,9 +517,9 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
        dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 
        if (addr)
-               dwc->dev_state = DWC3_ADDRESS_STATE;
+               usb_gadget_set_state(&dwc->gadget, USB_STATE_ADDRESS);
        else
-               dwc->dev_state = DWC3_DEFAULT_STATE;
+               usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
 
        return 0;
 }
@@ -532,6 +536,7 @@ static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 
 static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 {
+       enum usb_device_state state = dwc->gadget.state;
        u32 cfg;
        int ret;
        u32 reg;
@@ -539,16 +544,18 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
        dwc->start_config_issued = false;
        cfg = le16_to_cpu(ctrl->wValue);
 
-       switch (dwc->dev_state) {
-       case DWC3_DEFAULT_STATE:
+       switch (state) {
+       case USB_STATE_DEFAULT:
                return -EINVAL;
                break;
 
-       case DWC3_ADDRESS_STATE:
+       case USB_STATE_ADDRESS:
                ret = dwc3_ep0_delegate_req(dwc, ctrl);
                /* if the cfg matches and the cfg is non zero */
                if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
-                       dwc->dev_state = DWC3_CONFIGURED_STATE;
+                       usb_gadget_set_state(&dwc->gadget,
+                                       USB_STATE_CONFIGURED);
+
                        /*
                         * Enable transition to U1/U2 state when
                         * nothing is pending from application.
@@ -562,10 +569,11 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
                }
                break;
 
-       case DWC3_CONFIGURED_STATE:
+       case USB_STATE_CONFIGURED:
                ret = dwc3_ep0_delegate_req(dwc, ctrl);
                if (!cfg)
-                       dwc->dev_state = DWC3_ADDRESS_STATE;
+                       usb_gadget_set_state(&dwc->gadget,
+                                       USB_STATE_ADDRESS);
                break;
        default:
                ret = -EINVAL;
@@ -620,10 +628,11 @@ static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req)
 static int dwc3_ep0_set_sel(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 {
        struct dwc3_ep  *dep;
+       enum usb_device_state state = dwc->gadget.state;
        u16             wLength;
        u16             wValue;
 
-       if (dwc->dev_state == DWC3_DEFAULT_STATE)
+       if (state == USB_STATE_DEFAULT)
                return -EINVAL;
 
        wValue = le16_to_cpu(ctrl->wValue);
index 82e160e96fcafd20f15c4443cba953d569c071f1..2b6e7e0012071259464c1db3acf6c54b55e5971e 100644 (file)
@@ -1425,8 +1425,10 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
                if (dwc->revision >= DWC3_REVISION_194A)
                        reg &= ~DWC3_DCTL_KEEP_CONNECT;
                reg |= DWC3_DCTL_RUN_STOP;
+               dwc->pullups_connected = true;
        } else {
                reg &= ~DWC3_DCTL_RUN_STOP;
+               dwc->pullups_connected = false;
        }
 
        dwc3_writel(dwc->regs, DWC3_DCTL, reg);
@@ -1469,6 +1471,33 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
        return ret;
 }
 
+static void dwc3_gadget_enable_irq(struct dwc3 *dwc)
+{
+       u32                     reg;
+
+       /* Enable all but Start and End of Frame IRQs */
+       reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
+                       DWC3_DEVTEN_EVNTOVERFLOWEN |
+                       DWC3_DEVTEN_CMDCMPLTEN |
+                       DWC3_DEVTEN_ERRTICERREN |
+                       DWC3_DEVTEN_WKUPEVTEN |
+                       DWC3_DEVTEN_ULSTCNGEN |
+                       DWC3_DEVTEN_CONNECTDONEEN |
+                       DWC3_DEVTEN_USBRSTEN |
+                       DWC3_DEVTEN_DISCONNEVTEN);
+
+       dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
+}
+
+static void dwc3_gadget_disable_irq(struct dwc3 *dwc)
+{
+       /* mask all interrupts */
+       dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
+}
+
+static irqreturn_t dwc3_interrupt(int irq, void *_dwc);
+static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc);
+
 static int dwc3_gadget_start(struct usb_gadget *g,
                struct usb_gadget_driver *driver)
 {
@@ -1476,6 +1505,7 @@ static int dwc3_gadget_start(struct usb_gadget *g,
        struct dwc3_ep          *dep;
        unsigned long           flags;
        int                     ret = 0;
+       int                     irq;
        u32                     reg;
 
        spin_lock_irqsave(&dwc->lock, flags);
@@ -1489,7 +1519,6 @@ static int dwc3_gadget_start(struct usb_gadget *g,
        }
 
        dwc->gadget_driver      = driver;
-       dwc->gadget.dev.driver  = &driver->driver;
 
        reg = dwc3_readl(dwc->regs, DWC3_DCFG);
        reg &= ~(DWC3_DCFG_SPEED_MASK);
@@ -1536,6 +1565,17 @@ static int dwc3_gadget_start(struct usb_gadget *g,
        dwc->ep0state = EP0_SETUP_PHASE;
        dwc3_ep0_out_start(dwc);
 
+       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+       ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
+                       IRQF_SHARED | IRQF_ONESHOT, "dwc3", dwc);
+       if (ret) {
+               dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
+                               irq, ret);
+               goto err1;
+       }
+
+       dwc3_gadget_enable_irq(dwc);
+
        spin_unlock_irqrestore(&dwc->lock, flags);
 
        return 0;
@@ -1554,14 +1594,18 @@ static int dwc3_gadget_stop(struct usb_gadget *g,
 {
        struct dwc3             *dwc = gadget_to_dwc(g);
        unsigned long           flags;
+       int                     irq;
 
        spin_lock_irqsave(&dwc->lock, flags);
 
+       dwc3_gadget_disable_irq(dwc);
+       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
+       free_irq(irq, dwc);
+
        __dwc3_gadget_ep_disable(dwc->eps[0]);
        __dwc3_gadget_ep_disable(dwc->eps[1]);
 
        dwc->gadget_driver      = NULL;
-       dwc->gadget.dev.driver  = NULL;
 
        spin_unlock_irqrestore(&dwc->lock, flags);
 
@@ -1579,14 +1623,15 @@ static const struct usb_gadget_ops dwc3_gadget_ops = {
 
 /* -------------------------------------------------------------------------- */
 
-static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
+static int dwc3_gadget_init_hw_endpoints(struct dwc3 *dwc,
+               u8 num, u32 direction)
 {
        struct dwc3_ep                  *dep;
-       u8                              epnum;
+       u8                              i;
 
-       INIT_LIST_HEAD(&dwc->gadget.ep_list);
+       for (i = 0; i < num; i++) {
+               u8 epnum = (i << 1) | (!!direction);
 
-       for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
                dep = kzalloc(sizeof(*dep), GFP_KERNEL);
                if (!dep) {
                        dev_err(dwc->dev, "can't allocate endpoint %d\n",
@@ -1600,6 +1645,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
 
                snprintf(dep->name, sizeof(dep->name), "ep%d%s", epnum >> 1,
                                (epnum & 1) ? "in" : "out");
+
                dep->endpoint.name = dep->name;
                dep->direction = (epnum & 1);
 
@@ -1630,6 +1676,27 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
        return 0;
 }
 
+static int dwc3_gadget_init_endpoints(struct dwc3 *dwc)
+{
+       int                             ret;
+
+       INIT_LIST_HEAD(&dwc->gadget.ep_list);
+
+       ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_out_eps, 0);
+       if (ret < 0) {
+               dev_vdbg(dwc->dev, "failed to allocate OUT endpoints\n");
+               return ret;
+       }
+
+       ret = dwc3_gadget_init_hw_endpoints(dwc, dwc->num_in_eps, 1);
+       if (ret < 0) {
+               dev_vdbg(dwc->dev, "failed to allocate IN endpoints\n");
+               return ret;
+       }
+
+       return 0;
+}
+
 static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
 {
        struct dwc3_ep                  *dep;
@@ -1637,6 +1704,9 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
 
        for (epnum = 0; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
                dep = dwc->eps[epnum];
+               if (!dep)
+                       continue;
+
                dwc3_free_trb_pool(dep);
 
                if (epnum != 0 && epnum != 1)
@@ -1646,12 +1716,8 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc)
        }
 }
 
-static void dwc3_gadget_release(struct device *dev)
-{
-       dev_dbg(dev, "%s\n", __func__);
-}
-
 /* -------------------------------------------------------------------------- */
+
 static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep,
                struct dwc3_request *req, struct dwc3_trb *trb,
                const struct dwc3_event_depevt *event, int status)
@@ -1975,6 +2041,9 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc)
                struct dwc3_ep *dep;
 
                dep = dwc->eps[epnum];
+               if (!dep)
+                       continue;
+
                if (!(dep->flags & DWC3_EP_ENABLED))
                        continue;
 
@@ -1992,6 +2061,8 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
                int ret;
 
                dep = dwc->eps[epnum];
+               if (!dep)
+                       continue;
 
                if (!(dep->flags & DWC3_EP_STALL))
                        continue;
@@ -2091,7 +2162,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
        }
 
        /* after reset -> Default State */
-       dwc->dev_state = DWC3_DEFAULT_STATE;
+       usb_gadget_set_state(&dwc->gadget, USB_STATE_DEFAULT);
 
        /* Recent versions support automatic phy suspend and don't need this */
        if (dwc->revision < DWC3_REVISION_194A) {
@@ -2277,6 +2348,34 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
                unsigned int evtinfo)
 {
        enum dwc3_link_state    next = evtinfo & DWC3_LINK_STATE_MASK;
+       unsigned int            pwropt;
+
+       /*
+        * WORKAROUND: DWC3 < 2.50a have an issue when configured without
+        * Hibernation mode enabled which would show up when device detects
+        * host-initiated U3 exit.
+        *
+        * In that case, device will generate a Link State Change Interrupt
+        * from U3 to RESUME which is only necessary if Hibernation is
+        * configured in.
+        *
+        * There are no functional changes due to such spurious event and we
+        * just need to ignore it.
+        *
+        * Refers to:
+        *
+        * STAR#9000570034 RTL: SS Resume event generated in non-Hibernation
+        * operational mode
+        */
+       pwropt = DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1);
+       if ((dwc->revision < DWC3_REVISION_250A) &&
+                       (pwropt != DWC3_GHWPARAMS1_EN_PWROPT_HIB)) {
+               if ((dwc->link_state == DWC3_LINK_STATE_U3) &&
+                               (next == DWC3_LINK_STATE_RESUME)) {
+                       dev_vdbg(dwc->dev, "ignoring transition U3 -> Resume\n");
+                       return;
+               }
+       }
 
        /*
         * WORKAROUND: DWC3 Revisions <1.83a have an issue which, depending
@@ -2387,40 +2486,73 @@ static void dwc3_process_event_entry(struct dwc3 *dwc,
        }
 }
 
+static irqreturn_t dwc3_thread_interrupt(int irq, void *_dwc)
+{
+       struct dwc3 *dwc = _dwc;
+       unsigned long flags;
+       irqreturn_t ret = IRQ_NONE;
+       int i;
+
+       spin_lock_irqsave(&dwc->lock, flags);
+
+       for (i = 0; i < dwc->num_event_buffers; i++) {
+               struct dwc3_event_buffer *evt;
+               int                     left;
+
+               evt = dwc->ev_buffs[i];
+               left = evt->count;
+
+               if (!(evt->flags & DWC3_EVENT_PENDING))
+                       continue;
+
+               while (left > 0) {
+                       union dwc3_event event;
+
+                       event.raw = *(u32 *) (evt->buf + evt->lpos);
+
+                       dwc3_process_event_entry(dwc, &event);
+
+                       /*
+                        * FIXME we wrap around correctly to the next entry as
+                        * almost all entries are 4 bytes in size. There is one
+                        * entry which has 12 bytes which is a regular entry
+                        * followed by 8 bytes data. ATM I don't know how
+                        * things are organized if we get next to the a
+                        * boundary so I worry about that once we try to handle
+                        * that.
+                        */
+                       evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
+                       left -= 4;
+
+                       dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(i), 4);
+               }
+
+               evt->count = 0;
+               evt->flags &= ~DWC3_EVENT_PENDING;
+               ret = IRQ_HANDLED;
+       }
+
+       spin_unlock_irqrestore(&dwc->lock, flags);
+
+       return ret;
+}
+
 static irqreturn_t dwc3_process_event_buf(struct dwc3 *dwc, u32 buf)
 {
        struct dwc3_event_buffer *evt;
-       int left;
        u32 count;
 
+       evt = dwc->ev_buffs[buf];
+
        count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(buf));
        count &= DWC3_GEVNTCOUNT_MASK;
        if (!count)
                return IRQ_NONE;
 
-       evt = dwc->ev_buffs[buf];
-       left = count;
-
-       while (left > 0) {
-               union dwc3_event event;
-
-               event.raw = *(u32 *) (evt->buf + evt->lpos);
+       evt->count = count;
+       evt->flags |= DWC3_EVENT_PENDING;
 
-               dwc3_process_event_entry(dwc, &event);
-               /*
-                * XXX we wrap around correctly to the next entry as almost all
-                * entries are 4 bytes in size. There is one entry which has 12
-                * bytes which is a regular entry followed by 8 bytes data. ATM
-                * I don't know how things are organized if were get next to the
-                * a boundary so I worry about that once we try to handle that.
-                */
-               evt->lpos = (evt->lpos + 4) % DWC3_EVENT_BUFFERS_SIZE;
-               left -= 4;
-
-               dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(buf), 4);
-       }
-
-       return IRQ_HANDLED;
+       return IRQ_WAKE_THREAD;
 }
 
 static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
@@ -2435,7 +2567,7 @@ static irqreturn_t dwc3_interrupt(int irq, void *_dwc)
                irqreturn_t status;
 
                status = dwc3_process_event_buf(dwc, i);
-               if (status == IRQ_HANDLED)
+               if (status == IRQ_WAKE_THREAD)
                        ret = status;
        }
 
@@ -2454,7 +2586,6 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 {
        u32                                     reg;
        int                                     ret;
-       int                                     irq;
 
        dwc->ctrl_req = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
                        &dwc->ctrl_req_addr, GFP_KERNEL);
@@ -2488,19 +2619,10 @@ int dwc3_gadget_init(struct dwc3 *dwc)
                goto err3;
        }
 
-       dev_set_name(&dwc->gadget.dev, "gadget");
-
        dwc->gadget.ops                 = &dwc3_gadget_ops;
        dwc->gadget.max_speed           = USB_SPEED_SUPER;
        dwc->gadget.speed               = USB_SPEED_UNKNOWN;
-       dwc->gadget.dev.parent          = dwc->dev;
        dwc->gadget.sg_supported        = true;
-
-       dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask);
-
-       dwc->gadget.dev.dma_parms       = dwc->dev->dma_parms;
-       dwc->gadget.dev.dma_mask        = dwc->dev->dma_mask;
-       dwc->gadget.dev.release         = dwc3_gadget_release;
        dwc->gadget.name                = "dwc3-gadget";
 
        /*
@@ -2512,60 +2634,24 @@ int dwc3_gadget_init(struct dwc3 *dwc)
        if (ret)
                goto err4;
 
-       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-
-       ret = request_irq(irq, dwc3_interrupt, IRQF_SHARED,
-                       "dwc3", dwc);
-       if (ret) {
-               dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
-                               irq, ret);
-               goto err5;
-       }
-
        reg = dwc3_readl(dwc->regs, DWC3_DCFG);
        reg |= DWC3_DCFG_LPM_CAP;
        dwc3_writel(dwc->regs, DWC3_DCFG, reg);
 
-       /* Enable all but Start and End of Frame IRQs */
-       reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
-                       DWC3_DEVTEN_EVNTOVERFLOWEN |
-                       DWC3_DEVTEN_CMDCMPLTEN |
-                       DWC3_DEVTEN_ERRTICERREN |
-                       DWC3_DEVTEN_WKUPEVTEN |
-                       DWC3_DEVTEN_ULSTCNGEN |
-                       DWC3_DEVTEN_CONNECTDONEEN |
-                       DWC3_DEVTEN_USBRSTEN |
-                       DWC3_DEVTEN_DISCONNEVTEN);
-       dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
-
-       /* automatic phy suspend only on recent versions */
+       /* Enable USB2 LPM and automatic phy suspend only on recent versions */
        if (dwc->revision >= DWC3_REVISION_194A) {
                dwc3_gadget_usb2_phy_suspend(dwc, false);
                dwc3_gadget_usb3_phy_suspend(dwc, false);
        }
 
-       ret = device_register(&dwc->gadget.dev);
-       if (ret) {
-               dev_err(dwc->dev, "failed to register gadget device\n");
-               put_device(&dwc->gadget.dev);
-               goto err6;
-       }
-
        ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
        if (ret) {
                dev_err(dwc->dev, "failed to register udc\n");
-               goto err7;
+               goto err5;
        }
 
        return 0;
 
-err7:
-       device_unregister(&dwc->gadget.dev);
-
-err6:
-       dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
-       free_irq(irq, dwc);
-
 err5:
        dwc3_gadget_free_endpoints(dwc);
 
@@ -2588,15 +2674,11 @@ err0:
        return ret;
 }
 
+/* -------------------------------------------------------------------------- */
+
 void dwc3_gadget_exit(struct dwc3 *dwc)
 {
-       int                     irq;
-
        usb_del_gadget_udc(&dwc->gadget);
-       irq = platform_get_irq(to_platform_device(dwc->dev), 0);
-
-       dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
-       free_irq(irq, dwc);
 
        dwc3_gadget_free_endpoints(dwc);
 
@@ -2610,6 +2692,63 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
 
        dma_free_coherent(dwc->dev, sizeof(*dwc->ctrl_req),
                        dwc->ctrl_req, dwc->ctrl_req_addr);
+}
 
-       device_unregister(&dwc->gadget.dev);
+int dwc3_gadget_prepare(struct dwc3 *dwc)
+{
+       if (dwc->pullups_connected)
+               dwc3_gadget_disable_irq(dwc);
+
+       return 0;
+}
+
+void dwc3_gadget_complete(struct dwc3 *dwc)
+{
+       if (dwc->pullups_connected) {
+               dwc3_gadget_enable_irq(dwc);
+               dwc3_gadget_run_stop(dwc, true);
+       }
+}
+
+int dwc3_gadget_suspend(struct dwc3 *dwc)
+{
+       __dwc3_gadget_ep_disable(dwc->eps[0]);
+       __dwc3_gadget_ep_disable(dwc->eps[1]);
+
+       dwc->dcfg = dwc3_readl(dwc->regs, DWC3_DCFG);
+
+       return 0;
+}
+
+int dwc3_gadget_resume(struct dwc3 *dwc)
+{
+       struct dwc3_ep          *dep;
+       int                     ret;
+
+       /* Start with SuperSpeed Default */
+       dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
+
+       dep = dwc->eps[0];
+       ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
+       if (ret)
+               goto err0;
+
+       dep = dwc->eps[1];
+       ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false);
+       if (ret)
+               goto err1;
+
+       /* begin to receive SETUP packets */
+       dwc->ep0state = EP0_SETUP_PHASE;
+       dwc3_ep0_out_start(dwc);
+
+       dwc3_writel(dwc->regs, DWC3_DCFG, dwc->dcfg);
+
+       return 0;
+
+err1:
+       __dwc3_gadget_ep_disable(dwc->eps[0]);
+
+err0:
+       return ret;
 }
index c7525b1cad74a0f92dc1057621dca509f80d671c..83300d94a8933ff97a52992466799874cdeacb20 100644 (file)
@@ -144,6 +144,7 @@ config USB_AT91
 config USB_LPC32XX
        tristate "LPC32XX USB Peripheral Controller"
        depends on ARCH_LPC32XX
+       depends on USB_PHY
        select USB_ISP1301
        select USB_OTG_UTILS
        help
@@ -195,8 +196,8 @@ config USB_FUSB300
 config USB_OMAP
        tristate "OMAP USB Device Controller"
        depends on ARCH_OMAP1
+       depends on USB_PHY
        select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
-       select USB_OTG_UTILS if ARCH_OMAP
        help
           Many Texas Instruments OMAP processors have flexible full
           speed USB device controllers, with support for up to 30
@@ -211,7 +212,6 @@ config USB_OMAP
 config USB_PXA25X
        tristate "PXA 25x or IXP 4xx"
        depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
-       select USB_OTG_UTILS
        help
           Intel's PXA 25x series XScale ARM-5TE processors include
           an integrated full speed USB 1.1 device controller.  The
@@ -259,8 +259,6 @@ config USB_RENESAS_USBHS_UDC
 
 config USB_PXA27X
        tristate "PXA 27x"
-       depends on ARCH_PXA && (PXA27x || PXA3xx)
-       select USB_OTG_UTILS
        help
           Intel's PXA 27x series XScale ARM v5TE processors include
           an integrated full speed USB 1.1 device controller.
@@ -329,9 +327,6 @@ config USB_MV_UDC
 
 config USB_MV_U3D
        tristate "MARVELL PXA2128 USB 3.0 controller"
-       depends on CPU_MMP3
-       select USB_GADGET_DUALSPEED
-       select USB_GADGET_SUPERSPEED
        help
          MARVELL PXA2128 Processor series include a super speed USB3.0 device
          controller, which support super speed USB peripheral.
@@ -501,6 +496,7 @@ endmenu
 # composite based drivers
 config USB_LIBCOMPOSITE
        tristate
+       select CONFIGFS_FS
        depends on USB_GADGET
 
 config USB_F_ACM
@@ -512,6 +508,12 @@ config USB_F_SS_LB
 config USB_U_SERIAL
        tristate
 
+config USB_F_SERIAL
+       tristate
+
+config USB_F_OBEX
+       tristate
+
 choice
        tristate "USB Gadget Drivers"
        default USB_ETH
@@ -766,6 +768,8 @@ config USB_G_SERIAL
        depends on TTY
        select USB_U_SERIAL
        select USB_F_ACM
+       select USB_F_SERIAL
+       select USB_F_OBEX
        select USB_LIBCOMPOSITE
        help
          The Serial Gadget talks to the Linux-USB generic serial driver.
@@ -839,6 +843,7 @@ config USB_G_NOKIA
        depends on PHONET
        select USB_LIBCOMPOSITE
        select USB_U_SERIAL
+       select USB_F_ACM
        help
          The Nokia composite gadget provides support for acm, obex
          and phonet in only one composite gadget driver.
@@ -957,6 +962,7 @@ config USB_G_WEBCAM
        tristate "USB Webcam Gadget"
        depends on VIDEO_DEV
        select USB_LIBCOMPOSITE
+       select VIDEOBUF2_VMALLOC
        help
          The Webcam Gadget acts as a composite USB Audio and Video Class
          device. It provides a userspace API to process UVC control requests
index 82fb22511356d4ffd610d57b2787f457a93e5f9e..6afd16659e78d719c8fe7a5bf3702fa40329eba4 100644 (file)
@@ -6,7 +6,7 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG
 obj-$(CONFIG_USB_GADGET)       += udc-core.o
 obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o
 libcomposite-y                 := usbstring.o config.o epautoconf.o
-libcomposite-y                 += composite.o functions.o
+libcomposite-y                 += composite.o functions.o configfs.o
 obj-$(CONFIG_USB_DUMMY_HCD)    += dummy_hcd.o
 obj-$(CONFIG_USB_NET2272)      += net2272.o
 obj-$(CONFIG_USB_NET2280)      += net2280.o
@@ -36,10 +36,15 @@ obj-$(CONFIG_USB_FUSB300)   += fusb300_udc.o
 obj-$(CONFIG_USB_MV_U3D)       += mv_u3d_core.o
 
 # USB Functions
-obj-$(CONFIG_USB_F_ACM)                += f_acm.o
-f_ss_lb-y                      := f_loopback.o f_sourcesink.o
-obj-$(CONFIG_USB_F_SS_LB)      += f_ss_lb.o
+usb_f_acm-y                    := f_acm.o
+obj-$(CONFIG_USB_F_ACM)                += usb_f_acm.o
+usb_f_ss_lb-y                  := f_loopback.o f_sourcesink.o
+obj-$(CONFIG_USB_F_SS_LB)      += usb_f_ss_lb.o
 obj-$(CONFIG_USB_U_SERIAL)     += u_serial.o
+usb_f_serial-y                 := f_serial.o
+obj-$(CONFIG_USB_F_SERIAL)     += usb_f_serial.o
+usb_f_obex-y                   := f_obex.o
+obj-$(CONFIG_USB_F_OBEX)       += usb_f_obex.o
 
 #
 # USB gadget drivers
index 8f2b0e391534f251a576fca2bbc1e18b511e1db2..4b947bb50f62acdd17bebee987b5b14faa26e253 100644 (file)
@@ -109,7 +109,6 @@ FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
 static struct fsg_common fsg_common;
 
 /*-------------------------------------------------------------------------*/
-static unsigned char tty_line;
 static struct usb_function *f_acm;
 static struct usb_function_instance *f_acm_inst;
 /*
@@ -117,7 +116,6 @@ static struct usb_function_instance *f_acm_inst;
  */
 static int __init acm_ms_do_config(struct usb_configuration *c)
 {
-       struct f_serial_opts *opts;
        int     status;
 
        if (gadget_is_otg(c->cdev->gadget)) {
@@ -129,9 +127,6 @@ static int __init acm_ms_do_config(struct usb_configuration *c)
        if (IS_ERR(f_acm_inst))
                return PTR_ERR(f_acm_inst);
 
-       opts = container_of(f_acm_inst, struct f_serial_opts, func_inst);
-       opts->port_num = tty_line;
-
        f_acm = usb_get_function(f_acm_inst);
        if (IS_ERR(f_acm)) {
                status = PTR_ERR(f_acm);
@@ -171,16 +166,11 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
        int                     status;
        void                    *retp;
 
-       /* set up serial link layer */
-       status = gserial_alloc_line(&tty_line);
-       if (status < 0)
-               return status;
-
        /* set up mass storage function */
        retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data);
        if (IS_ERR(retp)) {
                status = PTR_ERR(retp);
-               goto fail0;
+               return PTR_ERR(retp);
        }
 
        /*
@@ -207,8 +197,6 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev)
        /* error recovery */
 fail1:
        fsg_common_put(&fsg_common);
-fail0:
-       gserial_free_line(tty_line);
        return status;
 }
 
@@ -216,7 +204,6 @@ static int __exit acm_ms_unbind(struct usb_composite_dev *cdev)
 {
        usb_put_function(f_acm);
        usb_put_function_instance(f_acm_inst);
-       gserial_free_line(tty_line);
        return 0;
 }
 
index 75973f33a4c80590ab6f8a012f9a1dec58c7ccbe..f52dcfe8f545077df80aca9cb97f1ec2e72b6261 100644 (file)
@@ -1922,7 +1922,6 @@ static int amd5536_udc_start(struct usb_gadget *g,
 
        driver->driver.bus = NULL;
        dev->driver = driver;
-       dev->gadget.dev.driver = &driver->driver;
 
        /* Some gadget drivers use both ep0 directions.
         * NOTE: to gadget driver, ep0 is just one endpoint...
@@ -1973,7 +1972,6 @@ static int amd5536_udc_stop(struct usb_gadget *g,
        shutdown(dev, driver);
        spin_unlock_irqrestore(&dev->lock, flags);
 
-       dev->gadget.dev.driver = NULL;
        dev->driver = NULL;
 
        /* set SD */
@@ -3080,7 +3078,6 @@ static void udc_pci_remove(struct pci_dev *pdev)
        if (dev->active)
                pci_disable_device(pdev);
 
-       device_unregister(&dev->gadget.dev);
        pci_set_drvdata(pdev, NULL);
 
        udc_remove(dev);
@@ -3245,8 +3242,6 @@ static int udc_pci_probe(
        dev->phys_addr = resource;
        dev->irq = pdev->irq;
        dev->pdev = pdev;
-       dev->gadget.dev.parent = &pdev->dev;
-       dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
 
        /* general probing */
        if (udc_probe(dev) == 0)
@@ -3273,7 +3268,6 @@ static int udc_probe(struct udc *dev)
        dev->gadget.ops = &udc_ops;
 
        dev_set_name(&dev->gadget.dev, "gadget");
-       dev->gadget.dev.release = gadget_release;
        dev->gadget.name = name;
        dev->gadget.max_speed = USB_SPEED_HIGH;
 
@@ -3297,17 +3291,11 @@ static int udc_probe(struct udc *dev)
                "driver version: %s(for Geode5536 B1)\n", tmp);
        udc = dev;
 
-       retval = usb_add_gadget_udc(&udc->pdev->dev, &dev->gadget);
+       retval = usb_add_gadget_udc_release(&udc->pdev->dev, &dev->gadget,
+                       gadget_release);
        if (retval)
                goto finished;
 
-       retval = device_register(&dev->gadget.dev);
-       if (retval) {
-               usb_del_gadget_udc(&dev->gadget);
-               put_device(&dev->gadget.dev);
-               goto finished;
-       }
-
        /* timer init */
        init_timer(&udc_timer);
        udc_timer.function = udc_timer_function;
index f1bf32e6b8d8b5c5ffa93c6bb94ed6c78ba53ba4..6744d3b83109e6717425a450b14ed41f35088f71 100644 (file)
@@ -472,7 +472,6 @@ struct udc_request {
 
        /* flags */
        unsigned                        dma_going : 1,
-                                       dma_mapping : 1,
                                        dma_done : 1;
        /* phys. address */
        dma_addr_t                      td_phys;
index 45dd2929a6710227fc13761503177774153539a8..a690d64217f403599d00c078bc91cec1b79dcf11 100644 (file)
@@ -1631,7 +1631,6 @@ static int at91_start(struct usb_gadget *gadget,
 
        udc = container_of(gadget, struct at91_udc, gadget);
        udc->driver = driver;
-       udc->gadget.dev.driver = &driver->driver;
        udc->gadget.dev.of_node = udc->pdev->dev.of_node;
        udc->enabled = 1;
        udc->selfpowered = 1;
@@ -1652,7 +1651,6 @@ static int at91_stop(struct usb_gadget *gadget,
        at91_udp_write(udc, AT91_UDP_IDR, ~0);
        spin_unlock_irqrestore(&udc->lock, flags);
 
-       udc->gadget.dev.driver = NULL;
        udc->driver = NULL;
 
        DBG("unbound from %s\n", driver->driver.name);
@@ -1780,13 +1778,7 @@ static int at91udc_probe(struct platform_device *pdev)
                DBG("clocks missing\n");
                retval = -ENODEV;
                /* NOTE: we "know" here that refcounts on these are NOPs */
-               goto fail0b;
-       }
-
-       retval = device_register(&udc->gadget.dev);
-       if (retval < 0) {
-               put_device(&udc->gadget.dev);
-               goto fail0b;
+               goto fail1;
        }
 
        /* don't do anything until we have both gadget driver and VBUS */
@@ -1857,8 +1849,6 @@ fail3:
 fail2:
        free_irq(udc->udp_irq, udc);
 fail1:
-       device_unregister(&udc->gadget.dev);
-fail0b:
        iounmap(udc->udp_baseaddr);
 fail0a:
        if (cpu_is_at91rm9200())
@@ -1892,8 +1882,6 @@ static int __exit at91udc_remove(struct platform_device *pdev)
                gpio_free(udc->board.vbus_pin);
        }
        free_irq(udc->udp_irq, udc);
-       device_unregister(&udc->gadget.dev);
-
        iounmap(udc->udp_baseaddr);
 
        if (cpu_is_at91rm9200())
index b66130c97269ec964011347da915abee66705162..f2a970f75bfa949b2c28db72c183e00790fea280 100644 (file)
@@ -489,13 +489,8 @@ request_complete(struct usba_ep *ep, struct usba_request *req, int status)
        if (req->req.status == -EINPROGRESS)
                req->req.status = status;
 
-       if (req->mapped) {
-               dma_unmap_single(
-                       &udc->pdev->dev, req->req.dma, req->req.length,
-                       ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-               req->req.dma = DMA_ADDR_INVALID;
-               req->mapped = 0;
-       }
+       if (req->using_dma)
+               usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
 
        DBG(DBG_GADGET | DBG_REQ,
                "%s: req %p complete: status %d, actual %u\n",
@@ -684,7 +679,6 @@ usba_ep_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
                return NULL;
 
        INIT_LIST_HEAD(&req->queue);
-       req->req.dma = DMA_ADDR_INVALID;
 
        return &req->req;
 }
@@ -717,20 +711,11 @@ static int queue_dma(struct usba_udc *udc, struct usba_ep *ep,
                return -EINVAL;
        }
 
-       req->using_dma = 1;
-
-       if (req->req.dma == DMA_ADDR_INVALID) {
-               req->req.dma = dma_map_single(
-                       &udc->pdev->dev, req->req.buf, req->req.length,
-                       ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-               req->mapped = 1;
-       } else {
-               dma_sync_single_for_device(
-                       &udc->pdev->dev, req->req.dma, req->req.length,
-                       ep->is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-               req->mapped = 0;
-       }
+       ret = usb_gadget_map_request(&udc->gadget, &req->req, ep->is_in);
+       if (ret)
+               return ret;
 
+       req->using_dma = 1;
        req->ctrl = USBA_BF(DMA_BUF_LEN, req->req.length)
                        | USBA_DMA_CH_EN | USBA_DMA_END_BUF_IE
                        | USBA_DMA_END_TR_EN | USBA_DMA_END_TR_IE;
@@ -1799,7 +1784,6 @@ static int atmel_usba_start(struct usb_gadget *gadget,
 
        udc->devstatus = 1 << USB_DEVICE_SELF_POWERED;
        udc->driver = driver;
-       udc->gadget.dev.driver = &driver->driver;
        spin_unlock_irqrestore(&udc->lock, flags);
 
        clk_enable(udc->pclk);
@@ -1841,7 +1825,6 @@ static int atmel_usba_stop(struct usb_gadget *gadget,
        toggle_bias(0);
        usba_writel(udc, CTRL, USBA_DISABLE_MASK);
 
-       udc->gadget.dev.driver = NULL;
        udc->driver = NULL;
 
        clk_disable(udc->hclk);
@@ -1900,10 +1883,6 @@ static int __init usba_udc_probe(struct platform_device *pdev)
        dev_info(&pdev->dev, "FIFO at 0x%08lx mapped at %p\n",
                 (unsigned long)fifo->start, udc->fifo);
 
-       device_initialize(&udc->gadget.dev);
-       udc->gadget.dev.parent = &pdev->dev;
-       udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
-
        platform_set_drvdata(pdev, udc);
 
        /* Make sure we start from a clean slate */
@@ -1962,12 +1941,6 @@ static int __init usba_udc_probe(struct platform_device *pdev)
        }
        udc->irq = irq;
 
-       ret = device_add(&udc->gadget.dev);
-       if (ret) {
-               dev_dbg(&pdev->dev, "Could not add gadget: %d\n", ret);
-               goto err_device_add;
-       }
-
        if (gpio_is_valid(pdata->vbus_pin)) {
                if (!gpio_request(pdata->vbus_pin, "atmel_usba_udc")) {
                        udc->vbus_pin = pdata->vbus_pin;
@@ -2007,9 +1980,6 @@ err_add_udc:
                gpio_free(udc->vbus_pin);
        }
 
-       device_unregister(&udc->gadget.dev);
-
-err_device_add:
        free_irq(irq, udc);
 err_request_irq:
        kfree(usba_ep);
@@ -2053,8 +2023,6 @@ static int __exit usba_udc_remove(struct platform_device *pdev)
        clk_put(udc->hclk);
        clk_put(udc->pclk);
 
-       device_unregister(&udc->gadget.dev);
-
        return 0;
 }
 
index 9791259cbda7b48e215562a254d2fb3be51232f8..d65a61851d3d8ca28b8c1f68ddf27b269a9d9e42 100644 (file)
 #define EP0_EPT_SIZE           USBA_EPT_SIZE_64
 #define EP0_NR_BANKS           1
 
-/*
- * REVISIT: Try to eliminate this value. Can we rely on req->mapped to
- * provide this information?
- */
-#define DMA_ADDR_INVALID (~(dma_addr_t)0)
-
 #define FIFO_IOMEM_ID  0
 #define CTRL_IOMEM_ID  1
 
index 8cc8253f1100490fc65bf288042daaef57b62b1f..6e6518264c42253b810bb41d93fbcd46da7a4906 100644 (file)
@@ -1819,7 +1819,6 @@ static int bcm63xx_udc_start(struct usb_gadget *gadget,
 
        udc->driver = driver;
        driver->driver.bus = NULL;
-       udc->gadget.dev.driver = &driver->driver;
        udc->gadget.dev.of_node = udc->dev->of_node;
 
        spin_unlock_irqrestore(&udc->lock, flags);
@@ -1841,7 +1840,6 @@ static int bcm63xx_udc_stop(struct usb_gadget *gadget,
        spin_lock_irqsave(&udc->lock, flags);
 
        udc->driver = NULL;
-       udc->gadget.dev.driver = NULL;
 
        /*
         * If we switch the PHY too abruptly after dropping D+, the host
@@ -2305,17 +2303,6 @@ static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc)
  * Driver init/exit
  ***********************************************************************/
 
-/**
- * bcm63xx_udc_gadget_release - Called from device_release().
- * @dev: Unused.
- *
- * We get a warning if this function doesn't exist, but it's empty because
- * we don't have to free any of the memory allocated with the devm_* APIs.
- */
-static void bcm63xx_udc_gadget_release(struct device *dev)
-{
-}
-
 /**
  * bcm63xx_udc_probe - Initialize a new instance of the UDC.
  * @pdev: Platform device struct from the bcm63xx BSP code.
@@ -2368,13 +2355,9 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
 
        spin_lock_init(&udc->lock);
        INIT_WORK(&udc->ep0_wq, bcm63xx_ep0_process);
-       dev_set_name(&udc->gadget.dev, "gadget");
 
        udc->gadget.ops = &bcm63xx_udc_ops;
        udc->gadget.name = dev_name(dev);
-       udc->gadget.dev.parent = dev;
-       udc->gadget.dev.release = bcm63xx_udc_gadget_release;
-       udc->gadget.dev.dma_mask = dev->dma_mask;
 
        if (!pd->use_fullspeed && !use_fullspeed)
                udc->gadget.max_speed = USB_SPEED_HIGH;
@@ -2414,17 +2397,12 @@ static int bcm63xx_udc_probe(struct platform_device *pdev)
                }
        }
 
-       rc = device_register(&udc->gadget.dev);
-       if (rc)
-               goto out_uninit;
-
        bcm63xx_udc_init_debugfs(udc);
        rc = usb_add_gadget_udc(dev, &udc->gadget);
        if (!rc)
                return 0;
 
        bcm63xx_udc_cleanup_debugfs(udc);
-       device_unregister(&udc->gadget.dev);
 out_uninit:
        bcm63xx_uninit_udc_hw(udc);
        return rc;
@@ -2440,7 +2418,6 @@ static int bcm63xx_udc_remove(struct platform_device *pdev)
 
        bcm63xx_udc_cleanup_debugfs(udc);
        usb_del_gadget_udc(&udc->gadget);
-       device_unregister(&udc->gadget.dev);
        BUG_ON(udc->driver);
 
        platform_set_drvdata(pdev, NULL);
index a7d6f7026757299bce4c2b700bdc821a849e6428..2c52551827692c5bd119bf78513e32e3f0fd7116 100644 (file)
@@ -103,18 +103,16 @@ static struct usb_gadget_strings *dev_strings[] = {
 };
 
 static u8 hostaddr[ETH_ALEN];
-
+static struct eth_dev *the_dev;
 /*-------------------------------------------------------------------------*/
 static struct usb_function *f_acm;
 static struct usb_function_instance *fi_serial;
 
-static unsigned char tty_line;
 /*
  * We _always_ have both CDC ECM and CDC ACM functions.
  */
 static int __init cdc_do_config(struct usb_configuration *c)
 {
-       struct f_serial_opts *opts;
        int     status;
 
        if (gadget_is_otg(c->cdev->gadget)) {
@@ -122,7 +120,7 @@ static int __init cdc_do_config(struct usb_configuration *c)
                c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
        }
 
-       status = ecm_bind_config(c, hostaddr);
+       status = ecm_bind_config(c, hostaddr, the_dev);
        if (status < 0)
                return status;
 
@@ -130,12 +128,11 @@ static int __init cdc_do_config(struct usb_configuration *c)
        if (IS_ERR(fi_serial))
                return PTR_ERR(fi_serial);
 
-       opts = container_of(fi_serial, struct f_serial_opts, func_inst);
-       opts->port_num = tty_line;
-
        f_acm = usb_get_function(fi_serial);
-       if (IS_ERR(f_acm))
+       if (IS_ERR(f_acm)) {
+               status = PTR_ERR(f_acm);
                goto err_func_acm;
+       }
 
        status = usb_add_function(c, f_acm);
        if (status)
@@ -169,14 +166,9 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
        }
 
        /* set up network link layer */
-       status = gether_setup(cdev->gadget, hostaddr);
-       if (status < 0)
-               return status;
-
-       /* set up serial link layer */
-       status = gserial_alloc_line(&tty_line);
-       if (status < 0)
-               goto fail0;
+       the_dev = gether_setup(cdev->gadget, hostaddr);
+       if (IS_ERR(the_dev))
+               return PTR_ERR(the_dev);
 
        /* Allocate string descriptor numbers ... note that string
         * contents can be overridden by the composite_dev glue.
@@ -200,9 +192,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev)
        return 0;
 
 fail1:
-       gserial_free_line(tty_line);
-fail0:
-       gether_cleanup();
+       gether_cleanup(the_dev);
        return status;
 }
 
@@ -210,8 +200,7 @@ static int __exit cdc_unbind(struct usb_composite_dev *cdev)
 {
        usb_put_function(f_acm);
        usb_put_function_instance(fi_serial);
-       gserial_free_line(tty_line);
-       gether_cleanup();
+       gether_cleanup(the_dev);
        return 0;
 }
 
index c0d62b2786104a6ed2a3501d2bd74e739841c970..55f4df60f327a654bf5863bdc68d2e79d82a8530 100644 (file)
@@ -1637,6 +1637,7 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)
                kfree(cdev->req->buf);
                usb_ep_free_request(cdev->gadget->ep0, cdev->req);
        }
+       cdev->next_string_id = 0;
        device_remove_file(&cdev->gadget->dev, &dev_attr_suspended);
 }
 
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
new file mode 100644 (file)
index 0000000..3d5cfc9
--- /dev/null
@@ -0,0 +1,1003 @@
+#include <linux/configfs.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/usb/composite.h>
+#include <linux/usb/gadget_configfs.h>
+
+int check_user_usb_string(const char *name,
+               struct usb_gadget_strings *stringtab_dev)
+{
+       unsigned primary_lang;
+       unsigned sub_lang;
+       u16 num;
+       int ret;
+
+       ret = kstrtou16(name, 0, &num);
+       if (ret)
+               return ret;
+
+       primary_lang = num & 0x3ff;
+       sub_lang = num >> 10;
+
+       /* simple sanity check for valid langid */
+       switch (primary_lang) {
+       case 0:
+       case 0x62 ... 0xfe:
+       case 0x100 ... 0x3ff:
+               return -EINVAL;
+       }
+       if (!sub_lang)
+               return -EINVAL;
+
+       stringtab_dev->language = num;
+       return 0;
+}
+
+#define MAX_NAME_LEN   40
+#define MAX_USB_STRING_LANGS 2
+
+struct gadget_info {
+       struct config_group group;
+       struct config_group functions_group;
+       struct config_group configs_group;
+       struct config_group strings_group;
+       struct config_group *default_groups[4];
+
+       struct mutex lock;
+       struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1];
+       struct list_head string_list;
+       struct list_head available_func;
+
+       const char *udc_name;
+#ifdef CONFIG_USB_OTG
+       struct usb_otg_descriptor otg;
+#endif
+       struct usb_composite_driver composite;
+       struct usb_composite_dev cdev;
+};
+
+struct config_usb_cfg {
+       struct config_group group;
+       struct config_group strings_group;
+       struct config_group *default_groups[2];
+       struct list_head string_list;
+       struct usb_configuration c;
+       struct list_head func_list;
+       struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1];
+};
+
+struct gadget_strings {
+       struct usb_gadget_strings stringtab_dev;
+       struct usb_string strings[USB_GADGET_FIRST_AVAIL_IDX];
+       char *manufacturer;
+       char *product;
+       char *serialnumber;
+
+       struct config_group group;
+       struct list_head list;
+};
+
+struct gadget_config_name {
+       struct usb_gadget_strings stringtab_dev;
+       struct usb_string strings;
+       char *configuration;
+
+       struct config_group group;
+       struct list_head list;
+};
+
+static int usb_string_copy(const char *s, char **s_copy)
+{
+       int ret;
+       char *str;
+       char *copy = *s_copy;
+       ret = strlen(s);
+       if (ret > 126)
+               return -EOVERFLOW;
+
+       str = kstrdup(s, GFP_KERNEL);
+       if (!str)
+               return -ENOMEM;
+       if (str[ret - 1] == '\n')
+               str[ret - 1] = '\0';
+       kfree(copy);
+       *s_copy = str;
+       return 0;
+}
+
+CONFIGFS_ATTR_STRUCT(gadget_info);
+CONFIGFS_ATTR_STRUCT(config_usb_cfg);
+
+#define GI_DEVICE_DESC_ITEM_ATTR(name) \
+       static struct gadget_info_attribute gadget_cdev_desc_##name = \
+               __CONFIGFS_ATTR(name,  S_IRUGO | S_IWUSR,               \
+                               gadget_dev_desc_##name##_show,          \
+                               gadget_dev_desc_##name##_store)
+
+#define GI_DEVICE_DESC_SIMPLE_R_u8(__name)     \
+       static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \
+                       char *page)     \
+{      \
+       return sprintf(page, "0x%02x\n", gi->cdev.desc.__name); \
+}
+
+#define GI_DEVICE_DESC_SIMPLE_R_u16(__name)    \
+       static ssize_t gadget_dev_desc_##__name##_show(struct gadget_info *gi, \
+                       char *page)     \
+{      \
+       return sprintf(page, "0x%04x\n", le16_to_cpup(&gi->cdev.desc.__name)); \
+}
+
+
+#define GI_DEVICE_DESC_SIMPLE_W_u8(_name)              \
+       static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \
+               const char *page, size_t len)           \
+{                                                      \
+       u8 val;                                         \
+       int ret;                                        \
+       ret = kstrtou8(page, 0, &val);                  \
+       if (ret)                                        \
+               return ret;                             \
+       gi->cdev.desc._name = val;                      \
+       return len;                                     \
+}
+
+#define GI_DEVICE_DESC_SIMPLE_W_u16(_name)     \
+       static ssize_t gadget_dev_desc_##_name##_store(struct gadget_info *gi, \
+               const char *page, size_t len)           \
+{                                                      \
+       u16 val;                                        \
+       int ret;                                        \
+       ret = kstrtou16(page, 0, &val);                 \
+       if (ret)                                        \
+               return ret;                             \
+       gi->cdev.desc._name = cpu_to_le16p(&val);       \
+       return len;                                     \
+}
+
+#define GI_DEVICE_DESC_SIMPLE_RW(_name, _type) \
+       GI_DEVICE_DESC_SIMPLE_R_##_type(_name)  \
+       GI_DEVICE_DESC_SIMPLE_W_##_type(_name)
+
+GI_DEVICE_DESC_SIMPLE_R_u16(bcdUSB);
+GI_DEVICE_DESC_SIMPLE_RW(bDeviceClass, u8);
+GI_DEVICE_DESC_SIMPLE_RW(bDeviceSubClass, u8);
+GI_DEVICE_DESC_SIMPLE_RW(bDeviceProtocol, u8);
+GI_DEVICE_DESC_SIMPLE_RW(bMaxPacketSize0, u8);
+GI_DEVICE_DESC_SIMPLE_RW(idVendor, u16);
+GI_DEVICE_DESC_SIMPLE_RW(idProduct, u16);
+GI_DEVICE_DESC_SIMPLE_R_u16(bcdDevice);
+
+static ssize_t is_valid_bcd(u16 bcd_val)
+{
+       if ((bcd_val & 0xf) > 9)
+               return -EINVAL;
+       if (((bcd_val >> 4) & 0xf) > 9)
+               return -EINVAL;
+       if (((bcd_val >> 8) & 0xf) > 9)
+               return -EINVAL;
+       if (((bcd_val >> 12) & 0xf) > 9)
+               return -EINVAL;
+       return 0;
+}
+
+static ssize_t gadget_dev_desc_bcdDevice_store(struct gadget_info *gi,
+               const char *page, size_t len)
+{
+       u16 bcdDevice;
+       int ret;
+
+       ret = kstrtou16(page, 0, &bcdDevice);
+       if (ret)
+               return ret;
+       ret = is_valid_bcd(bcdDevice);
+       if (ret)
+               return ret;
+
+       gi->cdev.desc.bcdDevice = cpu_to_le16(bcdDevice);
+       return len;
+}
+
+static ssize_t gadget_dev_desc_bcdUSB_store(struct gadget_info *gi,
+               const char *page, size_t len)
+{
+       u16 bcdUSB;
+       int ret;
+
+       ret = kstrtou16(page, 0, &bcdUSB);
+       if (ret)
+               return ret;
+       ret = is_valid_bcd(bcdUSB);
+       if (ret)
+               return ret;
+
+       gi->cdev.desc.bcdUSB = cpu_to_le16(bcdUSB);
+       return len;
+}
+
+static ssize_t gadget_dev_desc_UDC_show(struct gadget_info *gi, char *page)
+{
+       return sprintf(page, "%s\n", gi->udc_name ?: "");
+}
+
+static int unregister_gadget(struct gadget_info *gi)
+{
+       int ret;
+
+       if (!gi->udc_name)
+               return -ENODEV;
+
+       ret = usb_gadget_unregister_driver(&gi->composite.gadget_driver);
+       if (ret)
+               return ret;
+       kfree(gi->udc_name);
+       gi->udc_name = NULL;
+       return 0;
+}
+
+static ssize_t gadget_dev_desc_UDC_store(struct gadget_info *gi,
+               const char *page, size_t len)
+{
+       char *name;
+       int ret;
+
+       name = kstrdup(page, GFP_KERNEL);
+       if (!name)
+               return -ENOMEM;
+       if (name[len - 1] == '\n')
+               name[len - 1] = '\0';
+
+       mutex_lock(&gi->lock);
+
+       if (!strlen(name)) {
+               ret = unregister_gadget(gi);
+               if (ret)
+                       goto err;
+       } else {
+               if (gi->udc_name) {
+                       ret = -EBUSY;
+                       goto err;
+               }
+               ret = udc_attach_driver(name, &gi->composite.gadget_driver);
+               if (ret)
+                       goto err;
+               gi->udc_name = name;
+       }
+       mutex_unlock(&gi->lock);
+       return len;
+err:
+       kfree(name);
+       mutex_unlock(&gi->lock);
+       return ret;
+}
+
+GI_DEVICE_DESC_ITEM_ATTR(bDeviceClass);
+GI_DEVICE_DESC_ITEM_ATTR(bDeviceSubClass);
+GI_DEVICE_DESC_ITEM_ATTR(bDeviceProtocol);
+GI_DEVICE_DESC_ITEM_ATTR(bMaxPacketSize0);
+GI_DEVICE_DESC_ITEM_ATTR(idVendor);
+GI_DEVICE_DESC_ITEM_ATTR(idProduct);
+GI_DEVICE_DESC_ITEM_ATTR(bcdDevice);
+GI_DEVICE_DESC_ITEM_ATTR(bcdUSB);
+GI_DEVICE_DESC_ITEM_ATTR(UDC);
+
+static struct configfs_attribute *gadget_root_attrs[] = {
+       &gadget_cdev_desc_bDeviceClass.attr,
+       &gadget_cdev_desc_bDeviceSubClass.attr,
+       &gadget_cdev_desc_bDeviceProtocol.attr,
+       &gadget_cdev_desc_bMaxPacketSize0.attr,
+       &gadget_cdev_desc_idVendor.attr,
+       &gadget_cdev_desc_idProduct.attr,
+       &gadget_cdev_desc_bcdDevice.attr,
+       &gadget_cdev_desc_bcdUSB.attr,
+       &gadget_cdev_desc_UDC.attr,
+       NULL,
+};
+
+static inline struct gadget_info *to_gadget_info(struct config_item *item)
+{
+        return container_of(to_config_group(item), struct gadget_info, group);
+}
+
+static inline struct gadget_strings *to_gadget_strings(struct config_item *item)
+{
+        return container_of(to_config_group(item), struct gadget_strings,
+                        group);
+}
+
+static inline struct gadget_config_name *to_gadget_config_name(
+               struct config_item *item)
+{
+        return container_of(to_config_group(item), struct gadget_config_name,
+                        group);
+}
+
+static inline struct config_usb_cfg *to_config_usb_cfg(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct config_usb_cfg,
+                       group);
+}
+
+static inline struct usb_function_instance *to_usb_function_instance(
+               struct config_item *item)
+{
+        return container_of(to_config_group(item),
+                        struct usb_function_instance, group);
+}
+
+static void gadget_info_attr_release(struct config_item *item)
+{
+       struct gadget_info *gi = to_gadget_info(item);
+
+       WARN_ON(!list_empty(&gi->cdev.configs));
+       WARN_ON(!list_empty(&gi->string_list));
+       WARN_ON(!list_empty(&gi->available_func));
+       kfree(gi->composite.gadget_driver.function);
+       kfree(gi);
+}
+
+CONFIGFS_ATTR_OPS(gadget_info);
+
+static struct configfs_item_operations gadget_root_item_ops = {
+       .release                = gadget_info_attr_release,
+       .show_attribute         = gadget_info_attr_show,
+       .store_attribute        = gadget_info_attr_store,
+};
+
+static void gadget_config_attr_release(struct config_item *item)
+{
+       struct config_usb_cfg *cfg = to_config_usb_cfg(item);
+
+       WARN_ON(!list_empty(&cfg->c.functions));
+       list_del(&cfg->c.list);
+       kfree(cfg->c.label);
+       kfree(cfg);
+}
+
+static int config_usb_cfg_link(
+       struct config_item *usb_cfg_ci,
+       struct config_item *usb_func_ci)
+{
+       struct config_usb_cfg *cfg = to_config_usb_cfg(usb_cfg_ci);
+       struct usb_composite_dev *cdev = cfg->c.cdev;
+       struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev);
+
+       struct config_group *group = to_config_group(usb_func_ci);
+       struct usb_function_instance *fi = container_of(group,
+                       struct usb_function_instance, group);
+       struct usb_function_instance *a_fi;
+       struct usb_function *f;
+       int ret;
+
+       mutex_lock(&gi->lock);
+       /*
+        * Make sure this function is from within our _this_ gadget and not
+        * from another gadget or a random directory.
+        * Also a function instance can only be linked once.
+        */
+       list_for_each_entry(a_fi, &gi->available_func, cfs_list) {
+               if (a_fi == fi)
+                       break;
+       }
+       if (a_fi != fi) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       list_for_each_entry(f, &cfg->func_list, list) {
+               if (f->fi == fi) {
+                       ret = -EEXIST;
+                       goto out;
+               }
+       }
+
+       f = usb_get_function(fi);
+       if (IS_ERR(f)) {
+               ret = PTR_ERR(f);
+               goto out;
+       }
+
+       /* stash the function until we bind it to the gadget */
+       list_add_tail(&f->list, &cfg->func_list);
+       ret = 0;
+out:
+       mutex_unlock(&gi->lock);
+       return ret;
+}
+
+static int config_usb_cfg_unlink(
+       struct config_item *usb_cfg_ci,
+       struct config_item *usb_func_ci)
+{
+       struct config_usb_cfg *cfg = to_config_usb_cfg(usb_cfg_ci);
+       struct usb_composite_dev *cdev = cfg->c.cdev;
+       struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev);
+
+       struct config_group *group = to_config_group(usb_func_ci);
+       struct usb_function_instance *fi = container_of(group,
+                       struct usb_function_instance, group);
+       struct usb_function *f;
+
+       /*
+        * ideally I would like to forbid to unlink functions while a gadget is
+        * bound to an UDC. Since this isn't possible at the moment, we simply
+        * force an unbind, the function is available here and then we can
+        * remove the function.
+        */
+       mutex_lock(&gi->lock);
+       if (gi->udc_name)
+               unregister_gadget(gi);
+       WARN_ON(gi->udc_name);
+
+       list_for_each_entry(f, &cfg->func_list, list) {
+               if (f->fi == fi) {
+                       list_del(&f->list);
+                       usb_put_function(f);
+                       mutex_unlock(&gi->lock);
+                       return 0;
+               }
+       }
+       mutex_unlock(&gi->lock);
+       WARN(1, "Unable to locate function to unbind\n");
+       return 0;
+}
+
+CONFIGFS_ATTR_OPS(config_usb_cfg);
+
+static struct configfs_item_operations gadget_config_item_ops = {
+       .release                = gadget_config_attr_release,
+       .show_attribute         = config_usb_cfg_attr_show,
+       .store_attribute        = config_usb_cfg_attr_store,
+       .allow_link             = config_usb_cfg_link,
+       .drop_link              = config_usb_cfg_unlink,
+};
+
+
+static ssize_t gadget_config_desc_MaxPower_show(struct config_usb_cfg *cfg,
+               char *page)
+{
+       return sprintf(page, "%u\n", cfg->c.MaxPower);
+}
+
+static ssize_t gadget_config_desc_MaxPower_store(struct config_usb_cfg *cfg,
+               const char *page, size_t len)
+{
+       u16 val;
+       int ret;
+       ret = kstrtou16(page, 0, &val);
+       if (ret)
+               return ret;
+       if (DIV_ROUND_UP(val, 8) > 0xff)
+               return -ERANGE;
+       cfg->c.MaxPower = val;
+       return len;
+}
+
+static ssize_t gadget_config_desc_bmAttributes_show(struct config_usb_cfg *cfg,
+               char *page)
+{
+       return sprintf(page, "0x%02x\n", cfg->c.bmAttributes);
+}
+
+static ssize_t gadget_config_desc_bmAttributes_store(struct config_usb_cfg *cfg,
+               const char *page, size_t len)
+{
+       u8 val;
+       int ret;
+       ret = kstrtou8(page, 0, &val);
+       if (ret)
+               return ret;
+       if (!(val & USB_CONFIG_ATT_ONE))
+               return -EINVAL;
+       if (val & ~(USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER |
+                               USB_CONFIG_ATT_WAKEUP))
+               return -EINVAL;
+       cfg->c.bmAttributes = val;
+       return len;
+}
+
+#define CFG_CONFIG_DESC_ITEM_ATTR(name)        \
+       static struct config_usb_cfg_attribute gadget_usb_cfg_##name = \
+               __CONFIGFS_ATTR(name,  S_IRUGO | S_IWUSR,               \
+                               gadget_config_desc_##name##_show,       \
+                               gadget_config_desc_##name##_store)
+
+CFG_CONFIG_DESC_ITEM_ATTR(MaxPower);
+CFG_CONFIG_DESC_ITEM_ATTR(bmAttributes);
+
+static struct configfs_attribute *gadget_config_attrs[] = {
+       &gadget_usb_cfg_MaxPower.attr,
+       &gadget_usb_cfg_bmAttributes.attr,
+       NULL,
+};
+
+static struct config_item_type gadget_config_type = {
+       .ct_item_ops    = &gadget_config_item_ops,
+       .ct_attrs       = gadget_config_attrs,
+       .ct_owner       = THIS_MODULE,
+};
+
+static struct config_item_type gadget_root_type = {
+       .ct_item_ops    = &gadget_root_item_ops,
+       .ct_attrs       = gadget_root_attrs,
+       .ct_owner       = THIS_MODULE,
+};
+
+static void composite_init_dev(struct usb_composite_dev *cdev)
+{
+       spin_lock_init(&cdev->lock);
+       INIT_LIST_HEAD(&cdev->configs);
+       INIT_LIST_HEAD(&cdev->gstrings);
+}
+
+static struct config_group *function_make(
+               struct config_group *group,
+               const char *name)
+{
+       struct gadget_info *gi;
+       struct usb_function_instance *fi;
+       char buf[MAX_NAME_LEN];
+       char *func_name;
+       char *instance_name;
+       int ret;
+
+       ret = snprintf(buf, MAX_NAME_LEN, "%s", name);
+       if (ret >= MAX_NAME_LEN)
+               return ERR_PTR(-ENAMETOOLONG);
+
+       func_name = buf;
+       instance_name = strchr(func_name, '.');
+       if (!instance_name) {
+               pr_err("Unable to locate . in FUNC.INSTANCE\n");
+               return ERR_PTR(-EINVAL);
+       }
+       *instance_name = '\0';
+       instance_name++;
+
+       fi = usb_get_function_instance(func_name);
+       if (IS_ERR(fi))
+               return ERR_PTR(PTR_ERR(fi));
+
+       ret = config_item_set_name(&fi->group.cg_item, name);
+       if (ret) {
+               usb_put_function_instance(fi);
+               return ERR_PTR(ret);
+       }
+
+       gi = container_of(group, struct gadget_info, functions_group);
+
+       mutex_lock(&gi->lock);
+       list_add_tail(&fi->cfs_list, &gi->available_func);
+       mutex_unlock(&gi->lock);
+       return &fi->group;
+}
+
+static void function_drop(
+               struct config_group *group,
+               struct config_item *item)
+{
+       struct usb_function_instance *fi = to_usb_function_instance(item);
+       struct gadget_info *gi;
+
+       gi = container_of(group, struct gadget_info, functions_group);
+
+       mutex_lock(&gi->lock);
+       list_del(&fi->cfs_list);
+       mutex_unlock(&gi->lock);
+       config_item_put(item);
+}
+
+static struct configfs_group_operations functions_ops = {
+       .make_group     = &function_make,
+       .drop_item      = &function_drop,
+};
+
+static struct config_item_type functions_type = {
+       .ct_group_ops   = &functions_ops,
+       .ct_owner       = THIS_MODULE,
+};
+
+CONFIGFS_ATTR_STRUCT(gadget_config_name);
+GS_STRINGS_RW(gadget_config_name, configuration);
+
+static struct configfs_attribute *gadget_config_name_langid_attrs[] = {
+       &gadget_config_name_configuration.attr,
+       NULL,
+};
+
+static void gadget_config_name_attr_release(struct config_item *item)
+{
+       struct gadget_config_name *cn = to_gadget_config_name(item);
+
+       kfree(cn->configuration);
+
+       list_del(&cn->list);
+       kfree(cn);
+}
+
+USB_CONFIG_STRING_RW_OPS(gadget_config_name);
+USB_CONFIG_STRINGS_LANG(gadget_config_name, config_usb_cfg);
+
+static struct config_group *config_desc_make(
+               struct config_group *group,
+               const char *name)
+{
+       struct gadget_info *gi;
+       struct config_usb_cfg *cfg;
+       char buf[MAX_NAME_LEN];
+       char *num_str;
+       u8 num;
+       int ret;
+
+       gi = container_of(group, struct gadget_info, configs_group);
+       ret = snprintf(buf, MAX_NAME_LEN, "%s", name);
+       if (ret >= MAX_NAME_LEN)
+               return ERR_PTR(-ENAMETOOLONG);
+
+       num_str = strchr(buf, '.');
+       if (!num_str) {
+               pr_err("Unable to locate . in name.bConfigurationValue\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       *num_str = '\0';
+       num_str++;
+
+       if (!strlen(buf))
+               return ERR_PTR(-EINVAL);
+
+       ret = kstrtou8(num_str, 0, &num);
+       if (ret)
+               return ERR_PTR(ret);
+
+       cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
+       if (!cfg)
+               return ERR_PTR(-ENOMEM);
+       cfg->c.label = kstrdup(buf, GFP_KERNEL);
+       if (!cfg->c.label) {
+               ret = -ENOMEM;
+               goto err;
+       }
+       cfg->c.bConfigurationValue = num;
+       cfg->c.MaxPower = CONFIG_USB_GADGET_VBUS_DRAW;
+       cfg->c.bmAttributes = USB_CONFIG_ATT_ONE;
+       INIT_LIST_HEAD(&cfg->string_list);
+       INIT_LIST_HEAD(&cfg->func_list);
+
+       cfg->group.default_groups = cfg->default_groups;
+       cfg->default_groups[0] = &cfg->strings_group;
+
+       config_group_init_type_name(&cfg->group, name,
+                               &gadget_config_type);
+       config_group_init_type_name(&cfg->strings_group, "strings",
+                       &gadget_config_name_strings_type);
+
+       ret = usb_add_config_only(&gi->cdev, &cfg->c);
+       if (ret)
+               goto err;
+
+       return &cfg->group;
+err:
+       kfree(cfg->c.label);
+       kfree(cfg);
+       return ERR_PTR(ret);
+}
+
+static void config_desc_drop(
+               struct config_group *group,
+               struct config_item *item)
+{
+       config_item_put(item);
+}
+
+static struct configfs_group_operations config_desc_ops = {
+       .make_group     = &config_desc_make,
+       .drop_item      = &config_desc_drop,
+};
+
+static struct config_item_type config_desc_type = {
+       .ct_group_ops   = &config_desc_ops,
+       .ct_owner       = THIS_MODULE,
+};
+
+CONFIGFS_ATTR_STRUCT(gadget_strings);
+GS_STRINGS_RW(gadget_strings, manufacturer);
+GS_STRINGS_RW(gadget_strings, product);
+GS_STRINGS_RW(gadget_strings, serialnumber);
+
+static struct configfs_attribute *gadget_strings_langid_attrs[] = {
+       &gadget_strings_manufacturer.attr,
+       &gadget_strings_product.attr,
+       &gadget_strings_serialnumber.attr,
+       NULL,
+};
+
+static void gadget_strings_attr_release(struct config_item *item)
+{
+       struct gadget_strings *gs = to_gadget_strings(item);
+
+       kfree(gs->manufacturer);
+       kfree(gs->product);
+       kfree(gs->serialnumber);
+
+       list_del(&gs->list);
+       kfree(gs);
+}
+
+USB_CONFIG_STRING_RW_OPS(gadget_strings);
+USB_CONFIG_STRINGS_LANG(gadget_strings, gadget_info);
+
+static int configfs_do_nothing(struct usb_composite_dev *cdev)
+{
+       WARN_ON(1);
+       return -EINVAL;
+}
+
+int composite_dev_prepare(struct usb_composite_driver *composite,
+               struct usb_composite_dev *dev);
+
+static void purge_configs_funcs(struct gadget_info *gi)
+{
+       struct usb_configuration        *c;
+
+       list_for_each_entry(c, &gi->cdev.configs, list) {
+               struct usb_function *f, *tmp;
+               struct config_usb_cfg *cfg;
+
+               cfg = container_of(c, struct config_usb_cfg, c);
+
+               list_for_each_entry_safe(f, tmp, &c->functions, list) {
+
+                       list_move_tail(&f->list, &cfg->func_list);
+                       if (f->unbind) {
+                               dev_err(&gi->cdev.gadget->dev, "unbind function"
+                                               " '%s'/%p\n", f->name, f);
+                               f->unbind(c, f);
+                       }
+               }
+               c->next_interface_id = 0;
+               c->superspeed = 0;
+               c->highspeed = 0;
+               c->fullspeed = 0;
+       }
+}
+
+static int configfs_composite_bind(struct usb_gadget *gadget,
+               struct usb_gadget_driver *gdriver)
+{
+       struct usb_composite_driver     *composite = to_cdriver(gdriver);
+       struct gadget_info              *gi = container_of(composite,
+                                               struct gadget_info, composite);
+       struct usb_composite_dev        *cdev = &gi->cdev;
+       struct usb_configuration        *c;
+       struct usb_string               *s;
+       unsigned                        i;
+       int                             ret;
+
+       /* the gi->lock is hold by the caller */
+       cdev->gadget = gadget;
+       set_gadget_data(gadget, cdev);
+       ret = composite_dev_prepare(composite, cdev);
+       if (ret)
+               return ret;
+       /* and now the gadget bind */
+       ret = -EINVAL;
+
+       if (list_empty(&gi->cdev.configs)) {
+               pr_err("Need atleast one configuration in %s.\n",
+                               gi->composite.name);
+               goto err_comp_cleanup;
+       }
+
+
+       list_for_each_entry(c, &gi->cdev.configs, list) {
+               struct config_usb_cfg *cfg;
+
+               cfg = container_of(c, struct config_usb_cfg, c);
+               if (list_empty(&cfg->func_list)) {
+                       pr_err("Config %s/%d of %s needs atleast one function.\n",
+                             c->label, c->bConfigurationValue,
+                             gi->composite.name);
+                       goto err_comp_cleanup;
+               }
+       }
+
+       /* init all strings */
+       if (!list_empty(&gi->string_list)) {
+               struct gadget_strings *gs;
+
+               i = 0;
+               list_for_each_entry(gs, &gi->string_list, list) {
+
+                       gi->gstrings[i] = &gs->stringtab_dev;
+                       gs->stringtab_dev.strings = gs->strings;
+                       gs->strings[USB_GADGET_MANUFACTURER_IDX].s =
+                               gs->manufacturer;
+                       gs->strings[USB_GADGET_PRODUCT_IDX].s = gs->product;
+                       gs->strings[USB_GADGET_SERIAL_IDX].s = gs->serialnumber;
+                       i++;
+               }
+               gi->gstrings[i] = NULL;
+               s = usb_gstrings_attach(&gi->cdev, gi->gstrings,
+                               USB_GADGET_FIRST_AVAIL_IDX);
+               if (IS_ERR(s))
+                       goto err_comp_cleanup;
+
+               gi->cdev.desc.iManufacturer = s[USB_GADGET_MANUFACTURER_IDX].id;
+               gi->cdev.desc.iProduct = s[USB_GADGET_PRODUCT_IDX].id;
+               gi->cdev.desc.iSerialNumber = s[USB_GADGET_SERIAL_IDX].id;
+       }
+
+       /* Go through all configs, attach all functions */
+       list_for_each_entry(c, &gi->cdev.configs, list) {
+               struct config_usb_cfg *cfg;
+               struct usb_function *f;
+               struct usb_function *tmp;
+               struct gadget_config_name *cn;
+
+               cfg = container_of(c, struct config_usb_cfg, c);
+               if (!list_empty(&cfg->string_list)) {
+                       i = 0;
+                       list_for_each_entry(cn, &cfg->string_list, list) {
+                               cfg->gstrings[i] = &cn->stringtab_dev;
+                               cn->stringtab_dev.strings = &cn->strings;
+                               cn->strings.s = cn->configuration;
+                               i++;
+                       }
+                       cfg->gstrings[i] = NULL;
+                       s = usb_gstrings_attach(&gi->cdev, cfg->gstrings, 1);
+                       if (IS_ERR(s))
+                               goto err_comp_cleanup;
+                       c->iConfiguration = s[0].id;
+               }
+
+               list_for_each_entry_safe(f, tmp, &cfg->func_list, list) {
+                       list_del(&f->list);
+                       ret = usb_add_function(c, f);
+                       if (ret)
+                               goto err_purge_funcs;
+               }
+               usb_ep_autoconfig_reset(cdev->gadget);
+       }
+       usb_ep_autoconfig_reset(cdev->gadget);
+       return 0;
+
+err_purge_funcs:
+       purge_configs_funcs(gi);
+err_comp_cleanup:
+       composite_dev_cleanup(cdev);
+       return ret;
+}
+
+static void configfs_composite_unbind(struct usb_gadget *gadget)
+{
+       struct usb_composite_dev        *cdev;
+       struct gadget_info              *gi;
+
+       /* the gi->lock is hold by the caller */
+
+       cdev = get_gadget_data(gadget);
+       gi = container_of(cdev, struct gadget_info, cdev);
+
+       purge_configs_funcs(gi);
+       composite_dev_cleanup(cdev);
+       usb_ep_autoconfig_reset(cdev->gadget);
+       cdev->gadget = NULL;
+       set_gadget_data(gadget, NULL);
+}
+
+static const struct usb_gadget_driver configfs_driver_template = {
+       .bind           = configfs_composite_bind,
+       .unbind         = configfs_composite_unbind,
+
+       .setup          = composite_setup,
+       .disconnect     = composite_disconnect,
+
+       .max_speed      = USB_SPEED_SUPER,
+       .driver = {
+               .owner          = THIS_MODULE,
+               .name           = "configfs-gadget",
+       },
+};
+
+static struct config_group *gadgets_make(
+               struct config_group *group,
+               const char *name)
+{
+       struct gadget_info *gi;
+
+       gi = kzalloc(sizeof(*gi), GFP_KERNEL);
+       if (!gi)
+               return ERR_PTR(-ENOMEM);
+
+       gi->group.default_groups = gi->default_groups;
+       gi->group.default_groups[0] = &gi->functions_group;
+       gi->group.default_groups[1] = &gi->configs_group;
+       gi->group.default_groups[2] = &gi->strings_group;
+
+       config_group_init_type_name(&gi->functions_group, "functions",
+                       &functions_type);
+       config_group_init_type_name(&gi->configs_group, "configs",
+                       &config_desc_type);
+       config_group_init_type_name(&gi->strings_group, "strings",
+                       &gadget_strings_strings_type);
+
+       gi->composite.bind = configfs_do_nothing;
+       gi->composite.unbind = configfs_do_nothing;
+       gi->composite.suspend = NULL;
+       gi->composite.resume = NULL;
+       gi->composite.max_speed = USB_SPEED_SUPER;
+
+       mutex_init(&gi->lock);
+       INIT_LIST_HEAD(&gi->string_list);
+       INIT_LIST_HEAD(&gi->available_func);
+
+       composite_init_dev(&gi->cdev);
+       gi->cdev.desc.bLength = USB_DT_DEVICE_SIZE;
+       gi->cdev.desc.bDescriptorType = USB_DT_DEVICE;
+       gi->cdev.desc.bcdDevice = cpu_to_le16(get_default_bcdDevice());
+
+       gi->composite.gadget_driver = configfs_driver_template;
+
+       gi->composite.gadget_driver.function = kstrdup(name, GFP_KERNEL);
+       gi->composite.name = gi->composite.gadget_driver.function;
+
+       if (!gi->composite.gadget_driver.function)
+               goto err;
+
+#ifdef CONFIG_USB_OTG
+       gi->otg.bLength = sizeof(struct usb_otg_descriptor);
+       gi->otg.bDescriptorType = USB_DT_OTG;
+       gi->otg.bmAttributes = USB_OTG_SRP | USB_OTG_HNP;
+#endif
+
+       config_group_init_type_name(&gi->group, name,
+                               &gadget_root_type);
+       return &gi->group;
+err:
+       kfree(gi);
+       return ERR_PTR(-ENOMEM);
+}
+
+static void gadgets_drop(struct config_group *group, struct config_item *item)
+{
+       config_item_put(item);
+}
+
+static struct configfs_group_operations gadgets_ops = {
+       .make_group     = &gadgets_make,
+       .drop_item      = &gadgets_drop,
+};
+
+static struct config_item_type gadgets_type = {
+       .ct_group_ops   = &gadgets_ops,
+       .ct_owner       = THIS_MODULE,
+};
+
+static struct configfs_subsystem gadget_subsys = {
+       .su_group = {
+               .cg_item = {
+                       .ci_namebuf = "usb_gadget",
+                       .ci_type = &gadgets_type,
+               },
+       },
+       .su_mutex = __MUTEX_INITIALIZER(gadget_subsys.su_mutex),
+};
+
+static int __init gadget_cfs_init(void)
+{
+       int ret;
+
+       config_group_init(&gadget_subsys.su_group);
+
+       ret = configfs_register_subsystem(&gadget_subsys);
+       return ret;
+}
+module_init(gadget_cfs_init);
+
+static void __exit gadget_cfs_exit(void)
+{
+       configfs_unregister_subsystem(&gadget_subsys);
+}
+module_exit(gadget_cfs_exit);
index 8cf0c0f6fa1fb83bab5f26ab4d54a24e7bda3875..a792e322f4f1b84c58e20538b48d1e7beea4082f 100644 (file)
@@ -912,7 +912,6 @@ static int dummy_udc_start(struct usb_gadget *g,
        dum->devstatus = 0;
 
        dum->driver = driver;
-       dum->gadget.dev.driver = &driver->driver;
        dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n",
                        driver->driver.name);
        return 0;
@@ -927,7 +926,6 @@ static int dummy_udc_stop(struct usb_gadget *g,
        dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n",
                        driver->driver.name);
 
-       dum->gadget.dev.driver = NULL;
        dum->driver = NULL;
 
        return 0;
@@ -937,11 +935,6 @@ static int dummy_udc_stop(struct usb_gadget *g,
 
 /* The gadget structure is stored inside the hcd structure and will be
  * released along with it. */
-static void dummy_gadget_release(struct device *dev)
-{
-       return;
-}
-
 static void init_dummy_udc_hw(struct dummy *dum)
 {
        int i;
@@ -984,15 +977,7 @@ static int dummy_udc_probe(struct platform_device *pdev)
        dum->gadget.ops = &dummy_ops;
        dum->gadget.max_speed = USB_SPEED_SUPER;
 
-       dev_set_name(&dum->gadget.dev, "gadget");
        dum->gadget.dev.parent = &pdev->dev;
-       dum->gadget.dev.release = dummy_gadget_release;
-       rc = device_register(&dum->gadget.dev);
-       if (rc < 0) {
-               put_device(&dum->gadget.dev);
-               return rc;
-       }
-
        init_dummy_udc_hw(dum);
 
        rc = usb_add_gadget_udc(&pdev->dev, &dum->gadget);
@@ -1008,7 +993,6 @@ static int dummy_udc_probe(struct platform_device *pdev)
 err_dev:
        usb_del_gadget_udc(&dum->gadget);
 err_udc:
-       device_unregister(&dum->gadget.dev);
        return rc;
 }
 
@@ -1019,7 +1003,6 @@ static int dummy_udc_remove(struct platform_device *pdev)
        usb_del_gadget_udc(&dum->gadget);
        platform_set_drvdata(pdev, NULL);
        device_remove_file(&dum->gadget.dev, &dev_attr_function);
-       device_unregister(&dum->gadget.dev);
        return 0;
 }
 
@@ -1923,7 +1906,7 @@ done:
 }
 
 /* usb 3.0 root hub device descriptor */
-struct {
+static struct {
        struct usb_bos_descriptor bos;
        struct usb_ss_cap_descriptor ss_cap;
 } __packed usb3_bos_desc = {
index 18c3f423706e2855154e74495b6b56ab961995c3..56c8ecae9bc3213781b762e697ad626c23063e59 100644 (file)
@@ -207,7 +207,7 @@ static struct usb_gadget_strings *dev_strings[] = {
 };
 
 static u8 hostaddr[ETH_ALEN];
-
+static struct eth_dev *the_dev;
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -224,7 +224,7 @@ static int __init rndis_do_config(struct usb_configuration *c)
                c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
        }
 
-       return rndis_bind_config(c, hostaddr);
+       return rndis_bind_config(c, hostaddr, the_dev);
 }
 
 static struct usb_configuration rndis_config_driver = {
@@ -257,11 +257,11 @@ static int __init eth_do_config(struct usb_configuration *c)
        }
 
        if (use_eem)
-               return eem_bind_config(c);
+               return eem_bind_config(c, the_dev);
        else if (can_support_ecm(c->cdev->gadget))
-               return ecm_bind_config(c, hostaddr);
+               return ecm_bind_config(c, hostaddr, the_dev);
        else
-               return geth_bind_config(c, hostaddr);
+               return geth_bind_config(c, hostaddr, the_dev);
 }
 
 static struct usb_configuration eth_config_driver = {
@@ -279,9 +279,9 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
        int                     status;
 
        /* set up network link layer */
-       status = gether_setup(cdev->gadget, hostaddr);
-       if (status < 0)
-               return status;
+       the_dev = gether_setup(cdev->gadget, hostaddr);
+       if (IS_ERR(the_dev))
+               return PTR_ERR(the_dev);
 
        /* set up main config label and device descriptor */
        if (use_eem) {
@@ -338,13 +338,13 @@ static int __init eth_bind(struct usb_composite_dev *cdev)
        return 0;
 
 fail:
-       gether_cleanup();
+       gether_cleanup(the_dev);
        return status;
 }
 
 static int __exit eth_unbind(struct usb_composite_dev *cdev)
 {
-       gether_cleanup();
+       gether_cleanup(the_dev);
        return 0;
 }
 
index 1ae180baa597fdaac26b19d32fe2390231c2c8eb..4b7e33e5d9c624a452ee4917d3511f085717ffaf 100644 (file)
@@ -715,13 +715,31 @@ fail:
        return status;
 }
 
-static struct f_acm *acm_alloc_basic_func(void)
+static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+       struct f_acm            *acm = func_to_acm(f);
+
+       acm_string_defs[0].id = 0;
+       usb_free_all_descriptors(f);
+       if (acm->notify_req)
+               gs_free_req(acm->notify, acm->notify_req);
+}
+
+static void acm_free_func(struct usb_function *f)
+{
+       struct f_acm            *acm = func_to_acm(f);
+
+       kfree(acm);
+}
+
+static struct usb_function *acm_alloc_func(struct usb_function_instance *fi)
 {
-       struct f_acm    *acm;
+       struct f_serial_opts *opts;
+       struct f_acm *acm;
 
        acm = kzalloc(sizeof(*acm), GFP_KERNEL);
        if (!acm)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        spin_lock_init(&acm->lock);
 
@@ -730,109 +748,100 @@ static struct f_acm *acm_alloc_basic_func(void)
        acm->port.send_break = acm_send_break;
 
        acm->port.func.name = "acm";
+       acm->port.func.strings = acm_strings;
        /* descriptors are per-instance copies */
        acm->port.func.bind = acm_bind;
        acm->port.func.set_alt = acm_set_alt;
        acm->port.func.setup = acm_setup;
        acm->port.func.disable = acm_disable;
 
-       return acm;
+       opts = container_of(fi, struct f_serial_opts, func_inst);
+       acm->port_num = opts->port_num;
+       acm->port.func.unbind = acm_unbind;
+       acm->port.func.free_func = acm_free_func;
+
+       return &acm->port.func;
 }
 
-#ifdef USB_FACM_INCLUDED
-static void
-acm_old_unbind(struct usb_configuration *c, struct usb_function *f)
+static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
 {
-       struct f_acm            *acm = func_to_acm(f);
-
-       usb_free_all_descriptors(f);
-       if (acm->notify_req)
-               gs_free_req(acm->notify, acm->notify_req);
-       kfree(acm);
+       return container_of(to_config_group(item), struct f_serial_opts,
+                       func_inst.group);
 }
 
-/**
- * acm_bind_config - add a CDC ACM function to a configuration
- * @c: the configuration to support the CDC ACM instance
- * @port_num: /dev/ttyGS* port this interface will use
- * Context: single threaded during gadget setup
- *
- * Returns zero on success, else negative errno.
- *
- */
-int acm_bind_config(struct usb_configuration *c, u8 port_num)
+CONFIGFS_ATTR_STRUCT(f_serial_opts);
+static ssize_t f_acm_attr_show(struct config_item *item,
+                                struct configfs_attribute *attr,
+                                char *page)
 {
-       struct f_acm    *acm;
-       int             status;
-
-       /* allocate and initialize one new instance */
-       acm = acm_alloc_basic_func();
-       if (!acm)
-               return -ENOMEM;
-
-       acm->port_num = port_num;
-       acm->port.func.unbind = acm_old_unbind;
-
-       status = usb_add_function(c, &acm->port.func);
-       if (status)
-               kfree(acm);
-       return status;
+       struct f_serial_opts *opts = to_f_serial_opts(item);
+       struct f_serial_opts_attribute *f_serial_opts_attr =
+               container_of(attr, struct f_serial_opts_attribute, attr);
+       ssize_t ret = 0;
+
+       if (f_serial_opts_attr->show)
+               ret = f_serial_opts_attr->show(opts, page);
+       return ret;
 }
 
-#else
-
-static void acm_unbind(struct usb_configuration *c, struct usb_function *f)
+static void acm_attr_release(struct config_item *item)
 {
-       struct f_acm            *acm = func_to_acm(f);
+       struct f_serial_opts *opts = to_f_serial_opts(item);
 
-       acm_string_defs[0].id = 0;
-       usb_free_all_descriptors(f);
-       if (acm->notify_req)
-               gs_free_req(acm->notify, acm->notify_req);
+       usb_put_function_instance(&opts->func_inst);
 }
 
-static void acm_free_func(struct usb_function *f)
-{
-       struct f_acm            *acm = func_to_acm(f);
+static struct configfs_item_operations acm_item_ops = {
+       .release                = acm_attr_release,
+       .show_attribute         = f_acm_attr_show,
+};
 
-       kfree(acm);
+static ssize_t f_acm_port_num_show(struct f_serial_opts *opts, char *page)
+{
+       return sprintf(page, "%u\n", opts->port_num);
 }
 
-static struct usb_function *acm_alloc_func(struct usb_function_instance *fi)
-{
-       struct f_serial_opts *opts;
-       struct f_acm *acm;
+static struct f_serial_opts_attribute f_acm_port_num =
+       __CONFIGFS_ATTR_RO(port_num, f_acm_port_num_show);
 
-       acm = acm_alloc_basic_func();
-       if (!acm)
-               return ERR_PTR(-ENOMEM);
 
-       opts = container_of(fi, struct f_serial_opts, func_inst);
-       acm->port_num = opts->port_num;
-       acm->port.func.unbind = acm_unbind;
-       acm->port.func.free_func = acm_free_func;
+static struct configfs_attribute *acm_attrs[] = {
+       &f_acm_port_num.attr,
+       NULL,
+};
 
-       return &acm->port.func;
-}
+static struct config_item_type acm_func_type = {
+       .ct_item_ops    = &acm_item_ops,
+       .ct_attrs       = acm_attrs,
+       .ct_owner       = THIS_MODULE,
+};
 
 static void acm_free_instance(struct usb_function_instance *fi)
 {
        struct f_serial_opts *opts;
 
        opts = container_of(fi, struct f_serial_opts, func_inst);
+       gserial_free_line(opts->port_num);
        kfree(opts);
 }
 
 static struct usb_function_instance *acm_alloc_instance(void)
 {
        struct f_serial_opts *opts;
+       int ret;
 
        opts = kzalloc(sizeof(*opts), GFP_KERNEL);
        if (!opts)
                return ERR_PTR(-ENOMEM);
        opts->func_inst.free_func_inst = acm_free_instance;
+       ret = gserial_alloc_line(&opts->port_num);
+       if (ret) {
+               kfree(opts);
+               return ERR_PTR(ret);
+       }
+       config_group_init_type_name(&opts->func_inst.group, "",
+                       &acm_func_type);
        return &opts->func_inst;
 }
 DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func);
 MODULE_LICENSE("GPL");
-#endif
index 83420a310fb71784db5b269bf39e7939ef9af1b3..d893d69290794efa9c8d1e064fe1abd62077ff6a 100644 (file)
@@ -824,7 +824,8 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
  * for calling @gether_cleanup() before module unload.
  */
 int
-ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+               struct eth_dev *dev)
 {
        struct f_ecm    *ecm;
        int             status;
@@ -852,6 +853,7 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
        snprintf(ecm->ethaddr, sizeof ecm->ethaddr, "%pm", ethaddr);
        ecm_string_defs[1].s = ecm->ethaddr;
 
+       ecm->port.ioport = dev;
        ecm->port.cdc_filter = DEFAULT_FILTER;
 
        ecm->port.func.name = "cdc_ethernet";
index cf0ebee855636c9412b76f17d484c3f1b86bd3e8..f4e0bbef602a3ed05c2df67b06d55884dfaf2161 100644 (file)
@@ -528,7 +528,7 @@ error:
  * Caller must have called @gether_setup().  Caller is also responsible
  * for calling @gether_cleanup() before module unload.
  */
-int __init eem_bind_config(struct usb_configuration *c)
+int __init eem_bind_config(struct usb_configuration *c, struct eth_dev *dev)
 {
        struct f_eem    *eem;
        int             status;
@@ -549,6 +549,7 @@ int __init eem_bind_config(struct usb_configuration *c)
        if (!eem)
                return -ENOMEM;
 
+       eem->port.ioport = dev;
        eem->port.cdc_filter = DEFAULT_FILTER;
 
        eem->port.func.name = "cdc_eem";
index 5e7557e23ecca7858365190a497bed3e99d8c242..ee19bc8d0040c1c4efa868d32e7c2e2336875ed4 100644 (file)
@@ -1287,7 +1287,8 @@ ncm_unbind(struct usb_configuration *c, struct usb_function *f)
  * Caller must have called @gether_setup().  Caller is also responsible
  * for calling @gether_cleanup() before module unload.
  */
-int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+               struct eth_dev *dev)
 {
        struct f_ncm    *ncm;
        int             status;
@@ -1321,6 +1322,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
 
        spin_lock_init(&ncm->lock);
        ncm_reset_values(ncm);
+       ncm->port.ioport = dev;
        ncm->port.is_fixed = true;
 
        ncm->port.func.name = "cdc_network";
index 36a004563b8208ab4ae23b6dedbf410fc9230b61..8aa2be5329bcff2a3619c4aa0044c944afa5566f 100644 (file)
@@ -72,7 +72,7 @@ static struct usb_gadget_strings *obex_strings[] = {
 
 /*-------------------------------------------------------------------------*/
 
-static struct usb_interface_descriptor obex_control_intf __initdata = {
+static struct usb_interface_descriptor obex_control_intf = {
        .bLength                = sizeof(obex_control_intf),
        .bDescriptorType        = USB_DT_INTERFACE,
        .bInterfaceNumber       = 0,
@@ -83,7 +83,7 @@ static struct usb_interface_descriptor obex_control_intf __initdata = {
        .bInterfaceSubClass     = USB_CDC_SUBCLASS_OBEX,
 };
 
-static struct usb_interface_descriptor obex_data_nop_intf __initdata = {
+static struct usb_interface_descriptor obex_data_nop_intf = {
        .bLength                = sizeof(obex_data_nop_intf),
        .bDescriptorType        = USB_DT_INTERFACE,
        .bInterfaceNumber       = 1,
@@ -93,7 +93,7 @@ static struct usb_interface_descriptor obex_data_nop_intf __initdata = {
        .bInterfaceClass        = USB_CLASS_CDC_DATA,
 };
 
-static struct usb_interface_descriptor obex_data_intf __initdata = {
+static struct usb_interface_descriptor obex_data_intf = {
        .bLength                = sizeof(obex_data_intf),
        .bDescriptorType        = USB_DT_INTERFACE,
        .bInterfaceNumber       = 2,
@@ -103,14 +103,14 @@ static struct usb_interface_descriptor obex_data_intf __initdata = {
        .bInterfaceClass        = USB_CLASS_CDC_DATA,
 };
 
-static struct usb_cdc_header_desc obex_cdc_header_desc __initdata = {
+static struct usb_cdc_header_desc obex_cdc_header_desc = {
        .bLength                = sizeof(obex_cdc_header_desc),
        .bDescriptorType        = USB_DT_CS_INTERFACE,
        .bDescriptorSubType     = USB_CDC_HEADER_TYPE,
        .bcdCDC                 = cpu_to_le16(0x0120),
 };
 
-static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {
+static struct usb_cdc_union_desc obex_cdc_union_desc = {
        .bLength                = sizeof(obex_cdc_union_desc),
        .bDescriptorType        = USB_DT_CS_INTERFACE,
        .bDescriptorSubType     = USB_CDC_UNION_TYPE,
@@ -118,7 +118,7 @@ static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {
        .bSlaveInterface0       = 2,
 };
 
-static struct usb_cdc_obex_desc obex_desc __initdata = {
+static struct usb_cdc_obex_desc obex_desc = {
        .bLength                = sizeof(obex_desc),
        .bDescriptorType        = USB_DT_CS_INTERFACE,
        .bDescriptorSubType     = USB_CDC_OBEX_TYPE,
@@ -127,7 +127,7 @@ static struct usb_cdc_obex_desc obex_desc __initdata = {
 
 /* High-Speed Support */
 
-static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = {
+static struct usb_endpoint_descriptor obex_hs_ep_out_desc = {
        .bLength                = USB_DT_ENDPOINT_SIZE,
        .bDescriptorType        = USB_DT_ENDPOINT,
 
@@ -136,7 +136,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = {
        .wMaxPacketSize         = cpu_to_le16(512),
 };
 
-static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
+static struct usb_endpoint_descriptor obex_hs_ep_in_desc = {
        .bLength                = USB_DT_ENDPOINT_SIZE,
        .bDescriptorType        = USB_DT_ENDPOINT,
 
@@ -145,7 +145,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
        .wMaxPacketSize         = cpu_to_le16(512),
 };
 
-static struct usb_descriptor_header *hs_function[] __initdata = {
+static struct usb_descriptor_header *hs_function[] = {
        (struct usb_descriptor_header *) &obex_control_intf,
        (struct usb_descriptor_header *) &obex_cdc_header_desc,
        (struct usb_descriptor_header *) &obex_desc,
@@ -160,7 +160,7 @@ static struct usb_descriptor_header *hs_function[] __initdata = {
 
 /* Full-Speed Support */
 
-static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = {
+static struct usb_endpoint_descriptor obex_fs_ep_in_desc = {
        .bLength                = USB_DT_ENDPOINT_SIZE,
        .bDescriptorType        = USB_DT_ENDPOINT,
 
@@ -168,7 +168,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = {
        .bmAttributes           = USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = {
+static struct usb_endpoint_descriptor obex_fs_ep_out_desc = {
        .bLength                = USB_DT_ENDPOINT_SIZE,
        .bDescriptorType        = USB_DT_ENDPOINT,
 
@@ -176,7 +176,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = {
        .bmAttributes           = USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_descriptor_header *fs_function[] __initdata = {
+static struct usb_descriptor_header *fs_function[] = {
        (struct usb_descriptor_header *) &obex_control_intf,
        (struct usb_descriptor_header *) &obex_cdc_header_desc,
        (struct usb_descriptor_header *) &obex_desc,
@@ -290,14 +290,43 @@ static void obex_disconnect(struct gserial *g)
 
 /*-------------------------------------------------------------------------*/
 
-static int __init
-obex_bind(struct usb_configuration *c, struct usb_function *f)
+/* Some controllers can't support CDC OBEX ... */
+static inline bool can_support_obex(struct usb_configuration *c)
+{
+       /* Since the first interface is a NOP, we can ignore the
+        * issue of multi-interface support on most controllers.
+        *
+        * Altsettings are mandatory, however...
+        */
+       if (!gadget_supports_altsettings(c->cdev->gadget))
+               return false;
+
+       /* everything else is *probably* fine ... */
+       return true;
+}
+
+static int obex_bind(struct usb_configuration *c, struct usb_function *f)
 {
        struct usb_composite_dev *cdev = c->cdev;
        struct f_obex           *obex = func_to_obex(f);
        int                     status;
        struct usb_ep           *ep;
 
+       if (!can_support_obex(c))
+               return -EINVAL;
+
+       if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
+               status = usb_string_ids_tab(c->cdev, obex_string_defs);
+               if (status < 0)
+                       return status;
+               obex_control_intf.iInterface =
+                       obex_string_defs[OBEX_CTRL_IDX].id;
+
+               status = obex_string_defs[OBEX_DATA_IDX].id;
+               obex_data_nop_intf.iInterface = status;
+               obex_data_intf.iInterface = status;
+       }
+
        /* allocate instance-specific interface IDs, and patch descriptors */
 
        status = usb_interface_id(c, f);
@@ -319,6 +348,7 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
 
        /* allocate instance-specific endpoints */
 
+       status = -ENODEV;
        ep = usb_ep_autoconfig(cdev->gadget, &obex_fs_ep_in_desc);
        if (!ep)
                goto fail;
@@ -376,29 +406,16 @@ fail:
        return status;
 }
 
+#ifdef USBF_OBEX_INCLUDED
+
 static void
-obex_unbind(struct usb_configuration *c, struct usb_function *f)
+obex_old_unbind(struct usb_configuration *c, struct usb_function *f)
 {
        obex_string_defs[OBEX_CTRL_IDX].id = 0;
        usb_free_all_descriptors(f);
        kfree(func_to_obex(f));
 }
 
-/* Some controllers can't support CDC OBEX ... */
-static inline bool can_support_obex(struct usb_configuration *c)
-{
-       /* Since the first interface is a NOP, we can ignore the
-        * issue of multi-interface support on most controllers.
-        *
-        * Altsettings are mandatory, however...
-        */
-       if (!gadget_supports_altsettings(c->cdev->gadget))
-               return false;
-
-       /* everything else is *probably* fine ... */
-       return true;
-}
-
 /**
  * obex_bind_config - add a CDC OBEX function to a configuration
  * @c: the configuration to support the CDC OBEX instance
@@ -412,21 +429,6 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
        struct f_obex   *obex;
        int             status;
 
-       if (!can_support_obex(c))
-               return -EINVAL;
-
-       if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
-               status = usb_string_ids_tab(c->cdev, obex_string_defs);
-               if (status < 0)
-                       return status;
-               obex_control_intf.iInterface =
-                       obex_string_defs[OBEX_CTRL_IDX].id;
-
-               status = obex_string_defs[OBEX_DATA_IDX].id;
-               obex_data_nop_intf.iInterface = status;
-               obex_data_intf.iInterface = status;
-       }
-
        /* allocate and initialize one new instance */
        obex = kzalloc(sizeof *obex, GFP_KERNEL);
        if (!obex)
@@ -441,7 +443,7 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
        obex->port.func.strings = obex_strings;
        /* descriptors are per-instance copies */
        obex->port.func.bind = obex_bind;
-       obex->port.func.unbind = obex_unbind;
+       obex->port.func.unbind = obex_old_unbind;
        obex->port.func.set_alt = obex_set_alt;
        obex->port.func.get_alt = obex_get_alt;
        obex->port.func.disable = obex_disable;
@@ -453,5 +455,138 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
        return status;
 }
 
+#else
+
+static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct f_serial_opts,
+                           func_inst.group);
+}
+
+CONFIGFS_ATTR_STRUCT(f_serial_opts);
+static ssize_t f_obex_attr_show(struct config_item *item,
+                               struct configfs_attribute *attr,
+                               char *page)
+{
+       struct f_serial_opts *opts = to_f_serial_opts(item);
+       struct f_serial_opts_attribute *f_serial_opts_attr =
+               container_of(attr, struct f_serial_opts_attribute, attr);
+       ssize_t ret = 0;
+
+       if (f_serial_opts_attr->show)
+               ret = f_serial_opts_attr->show(opts, page);
+
+       return ret;
+}
+
+static void obex_attr_release(struct config_item *item)
+{
+       struct f_serial_opts *opts = to_f_serial_opts(item);
+
+       usb_put_function_instance(&opts->func_inst);
+}
+
+static struct configfs_item_operations obex_item_ops = {
+       .release        = obex_attr_release,
+       .show_attribute = f_obex_attr_show,
+};
+
+static ssize_t f_obex_port_num_show(struct f_serial_opts *opts, char *page)
+{
+       return sprintf(page, "%u\n", opts->port_num);
+}
+
+static struct f_serial_opts_attribute f_obex_port_num =
+       __CONFIGFS_ATTR_RO(port_num, f_obex_port_num_show);
+
+static struct configfs_attribute *acm_attrs[] = {
+       &f_obex_port_num.attr,
+       NULL,
+};
+
+static struct config_item_type obex_func_type = {
+       .ct_item_ops    = &obex_item_ops,
+       .ct_attrs       = acm_attrs,
+       .ct_owner       = THIS_MODULE,
+};
+
+static void obex_free_inst(struct usb_function_instance *f)
+{
+       struct f_serial_opts *opts;
+
+       opts = container_of(f, struct f_serial_opts, func_inst);
+       gserial_free_line(opts->port_num);
+       kfree(opts);
+}
+
+static struct usb_function_instance *obex_alloc_inst(void)
+{
+       struct f_serial_opts *opts;
+       int ret;
+
+       opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+       if (!opts)
+               return ERR_PTR(-ENOMEM);
+
+       opts->func_inst.free_func_inst = obex_free_inst;
+       ret = gserial_alloc_line(&opts->port_num);
+       if (ret) {
+               kfree(opts);
+               return ERR_PTR(ret);
+       }
+       config_group_init_type_name(&opts->func_inst.group, "",
+                                   &obex_func_type);
+
+       return &opts->func_inst;
+}
+
+static void obex_free(struct usb_function *f)
+{
+       struct f_obex *obex;
+
+       obex = func_to_obex(f);
+       kfree(obex);
+}
+
+static void obex_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+       obex_string_defs[OBEX_CTRL_IDX].id = 0;
+       usb_free_all_descriptors(f);
+}
+
+struct usb_function *obex_alloc(struct usb_function_instance *fi)
+{
+       struct f_obex   *obex;
+       struct f_serial_opts *opts;
+
+       /* allocate and initialize one new instance */
+       obex = kzalloc(sizeof(*obex), GFP_KERNEL);
+       if (!obex)
+               return ERR_PTR(-ENOMEM);
+
+       opts = container_of(fi, struct f_serial_opts, func_inst);
+
+       obex->port_num = opts->port_num;
+
+       obex->port.connect = obex_connect;
+       obex->port.disconnect = obex_disconnect;
+
+       obex->port.func.name = "obex";
+       obex->port.func.strings = obex_strings;
+       /* descriptors are per-instance copies */
+       obex->port.func.bind = obex_bind;
+       obex->port.func.unbind = obex_unbind;
+       obex->port.func.set_alt = obex_set_alt;
+       obex->port.func.get_alt = obex_get_alt;
+       obex->port.func.disable = obex_disable;
+       obex->port.func.free_func = obex_free;
+
+       return &obex->port.func;
+}
+
+DECLARE_USB_FUNCTION_INIT(obex, obex_alloc_inst, obex_alloc);
+
+#endif
+
 MODULE_AUTHOR("Felipe Balbi");
 MODULE_LICENSE("GPL");
index cc9c49c57c803a9e787887fd8977e05c585d630e..36e8c44d8e5e2fb04222b86b4e9fbc4d3a493083 100644 (file)
@@ -813,7 +813,7 @@ static inline bool can_support_rndis(struct usb_configuration *c)
 
 int
 rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-                               u32 vendorID, const char *manufacturer)
+               u32 vendorID, const char *manufacturer, struct eth_dev *dev)
 {
        struct f_rndis  *rndis;
        int             status;
@@ -846,6 +846,7 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
        rndis->vendorID = vendorID;
        rndis->manufacturer = manufacturer;
 
+       rndis->port.ioport = dev;
        /* RNDIS activates when the host changes this filter */
        rndis->port.cdc_filter = 0;
 
index da33cfb3031df2b34d3ccdfb202530124fd3f907..981113c9924d53ad60084f809736c4d880481495 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/slab.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/device.h>
 
 #include "u_serial.h"
@@ -42,7 +43,7 @@ static inline struct f_gser *func_to_gser(struct usb_function *f)
 
 /* interface descriptor: */
 
-static struct usb_interface_descriptor gser_interface_desc __initdata = {
+static struct usb_interface_descriptor gser_interface_desc = {
        .bLength =              USB_DT_INTERFACE_SIZE,
        .bDescriptorType =      USB_DT_INTERFACE,
        /* .bInterfaceNumber = DYNAMIC */
@@ -55,21 +56,21 @@ static struct usb_interface_descriptor gser_interface_desc __initdata = {
 
 /* full speed support: */
 
-static struct usb_endpoint_descriptor gser_fs_in_desc __initdata = {
+static struct usb_endpoint_descriptor gser_fs_in_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
        .bEndpointAddress =     USB_DIR_IN,
        .bmAttributes =         USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_endpoint_descriptor gser_fs_out_desc __initdata = {
+static struct usb_endpoint_descriptor gser_fs_out_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
        .bEndpointAddress =     USB_DIR_OUT,
        .bmAttributes =         USB_ENDPOINT_XFER_BULK,
 };
 
-static struct usb_descriptor_header *gser_fs_function[] __initdata = {
+static struct usb_descriptor_header *gser_fs_function[] = {
        (struct usb_descriptor_header *) &gser_interface_desc,
        (struct usb_descriptor_header *) &gser_fs_in_desc,
        (struct usb_descriptor_header *) &gser_fs_out_desc,
@@ -78,47 +79,47 @@ static struct usb_descriptor_header *gser_fs_function[] __initdata = {
 
 /* high speed support: */
 
-static struct usb_endpoint_descriptor gser_hs_in_desc __initdata = {
+static struct usb_endpoint_descriptor gser_hs_in_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
        .bmAttributes =         USB_ENDPOINT_XFER_BULK,
        .wMaxPacketSize =       cpu_to_le16(512),
 };
 
-static struct usb_endpoint_descriptor gser_hs_out_desc __initdata = {
+static struct usb_endpoint_descriptor gser_hs_out_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
        .bmAttributes =         USB_ENDPOINT_XFER_BULK,
        .wMaxPacketSize =       cpu_to_le16(512),
 };
 
-static struct usb_descriptor_header *gser_hs_function[] __initdata = {
+static struct usb_descriptor_header *gser_hs_function[] = {
        (struct usb_descriptor_header *) &gser_interface_desc,
        (struct usb_descriptor_header *) &gser_hs_in_desc,
        (struct usb_descriptor_header *) &gser_hs_out_desc,
        NULL,
 };
 
-static struct usb_endpoint_descriptor gser_ss_in_desc __initdata = {
+static struct usb_endpoint_descriptor gser_ss_in_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
        .bmAttributes =         USB_ENDPOINT_XFER_BULK,
        .wMaxPacketSize =       cpu_to_le16(1024),
 };
 
-static struct usb_endpoint_descriptor gser_ss_out_desc __initdata = {
+static struct usb_endpoint_descriptor gser_ss_out_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
        .bDescriptorType =      USB_DT_ENDPOINT,
        .bmAttributes =         USB_ENDPOINT_XFER_BULK,
        .wMaxPacketSize =       cpu_to_le16(1024),
 };
 
-static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc __initdata = {
+static struct usb_ss_ep_comp_descriptor gser_ss_bulk_comp_desc = {
        .bLength =              sizeof gser_ss_bulk_comp_desc,
        .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
 };
 
-static struct usb_descriptor_header *gser_ss_function[] __initdata = {
+static struct usb_descriptor_header *gser_ss_function[] = {
        (struct usb_descriptor_header *) &gser_interface_desc,
        (struct usb_descriptor_header *) &gser_ss_in_desc,
        (struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
@@ -183,14 +184,25 @@ static void gser_disable(struct usb_function *f)
 
 /* serial function driver setup/binding */
 
-static int __init
-gser_bind(struct usb_configuration *c, struct usb_function *f)
+static int gser_bind(struct usb_configuration *c, struct usb_function *f)
 {
        struct usb_composite_dev *cdev = c->cdev;
        struct f_gser           *gser = func_to_gser(f);
        int                     status;
        struct usb_ep           *ep;
 
+       /* REVISIT might want instance-specific strings to help
+        * distinguish instances ...
+        */
+
+       /* maybe allocate device-global string ID */
+       if (gser_string_defs[0].id == 0) {
+               status = usb_string_id(c->cdev);
+               if (status < 0)
+                       return status;
+               gser_string_defs[0].id = status;
+       }
+
        /* allocate instance-specific interface IDs */
        status = usb_interface_id(c, f);
        if (status < 0)
@@ -246,44 +258,115 @@ fail:
        return status;
 }
 
-static void
-gser_unbind(struct usb_configuration *c, struct usb_function *f)
+static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item)
 {
-       usb_free_all_descriptors(f);
-       kfree(func_to_gser(f));
+       return container_of(to_config_group(item), struct f_serial_opts,
+                           func_inst.group);
 }
 
-/**
- * gser_bind_config - add a generic serial function to a configuration
- * @c: the configuration to support the serial instance
- * @port_num: /dev/ttyGS* port this interface will use
- * Context: single threaded during gadget setup
- *
- * Returns zero on success, else negative errno.
- */
-int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
+CONFIGFS_ATTR_STRUCT(f_serial_opts);
+static ssize_t f_serial_attr_show(struct config_item *item,
+                                 struct configfs_attribute *attr,
+                                 char *page)
 {
-       struct f_gser   *gser;
-       int             status;
+       struct f_serial_opts *opts = to_f_serial_opts(item);
+       struct f_serial_opts_attribute *f_serial_opts_attr =
+               container_of(attr, struct f_serial_opts_attribute, attr);
+       ssize_t ret = 0;
 
-       /* REVISIT might want instance-specific strings to help
-        * distinguish instances ...
-        */
+       if (f_serial_opts_attr->show)
+               ret = f_serial_opts_attr->show(opts, page);
 
-       /* maybe allocate device-global string ID */
-       if (gser_string_defs[0].id == 0) {
-               status = usb_string_id(c->cdev);
-               if (status < 0)
-                       return status;
-               gser_string_defs[0].id = status;
+       return ret;
+}
+
+static void serial_attr_release(struct config_item *item)
+{
+       struct f_serial_opts *opts = to_f_serial_opts(item);
+
+       usb_put_function_instance(&opts->func_inst);
+}
+
+static struct configfs_item_operations serial_item_ops = {
+       .release        = serial_attr_release,
+       .show_attribute = f_serial_attr_show,
+};
+
+static ssize_t f_serial_port_num_show(struct f_serial_opts *opts, char *page)
+{
+       return sprintf(page, "%u\n", opts->port_num);
+}
+
+static struct f_serial_opts_attribute f_serial_port_num =
+       __CONFIGFS_ATTR_RO(port_num, f_serial_port_num_show);
+
+static struct configfs_attribute *acm_attrs[] = {
+       &f_serial_port_num.attr,
+       NULL,
+};
+
+static struct config_item_type serial_func_type = {
+       .ct_item_ops    = &serial_item_ops,
+       .ct_attrs       = acm_attrs,
+       .ct_owner       = THIS_MODULE,
+};
+
+static void gser_free_inst(struct usb_function_instance *f)
+{
+       struct f_serial_opts *opts;
+
+       opts = container_of(f, struct f_serial_opts, func_inst);
+       gserial_free_line(opts->port_num);
+       kfree(opts);
+}
+
+static struct usb_function_instance *gser_alloc_inst(void)
+{
+       struct f_serial_opts *opts;
+       int ret;
+
+       opts = kzalloc(sizeof(*opts), GFP_KERNEL);
+       if (!opts)
+               return ERR_PTR(-ENOMEM);
+
+       opts->func_inst.free_func_inst = gser_free_inst;
+       ret = gserial_alloc_line(&opts->port_num);
+       if (ret) {
+               kfree(opts);
+               return ERR_PTR(ret);
        }
+       config_group_init_type_name(&opts->func_inst.group, "",
+                                   &serial_func_type);
+
+       return &opts->func_inst;
+}
+
+static void gser_free(struct usb_function *f)
+{
+       struct f_gser *serial;
+
+       serial = func_to_gser(f);
+       kfree(serial);
+}
+
+static void gser_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+       usb_free_all_descriptors(f);
+}
+
+struct usb_function *gser_alloc(struct usb_function_instance *fi)
+{
+       struct f_gser   *gser;
+       struct f_serial_opts *opts;
 
        /* allocate and initialize one new instance */
-       gser = kzalloc(sizeof *gser, GFP_KERNEL);
+       gser = kzalloc(sizeof(*gser), GFP_KERNEL);
        if (!gser)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
-       gser->port_num = port_num;
+       opts = container_of(fi, struct f_serial_opts, func_inst);
+
+       gser->port_num = opts->port_num;
 
        gser->port.func.name = "gser";
        gser->port.func.strings = gser_strings;
@@ -291,9 +374,12 @@ int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
        gser->port.func.unbind = gser_unbind;
        gser->port.func.set_alt = gser_set_alt;
        gser->port.func.disable = gser_disable;
+       gser->port.func.free_func = gser_free;
 
-       status = usb_add_function(c, &gser->port.func);
-       if (status)
-               kfree(gser);
-       return status;
+       return &gser->port.func;
 }
+
+DECLARE_USB_FUNCTION_INIT(gser, gser_alloc_inst, gser_alloc);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Al Borchers");
+MODULE_AUTHOR("David Brownell");
index 41adf3ef96c2b48234c962d0817a4811a0f6d4aa..a8895859a221ce7f54f385284d155aa869cbd438 100644 (file)
@@ -898,7 +898,7 @@ static struct usb_function *source_sink_alloc_func(
        return &ss->function;
 }
 
-static void acm_free_instance(struct usb_function_instance *fi)
+static void source_sink_free_instance(struct usb_function_instance *fi)
 {
        struct f_ss_opts *ss_opts;
 
@@ -913,7 +913,7 @@ static struct usb_function_instance *source_sink_alloc_inst(void)
        ss_opts = kzalloc(sizeof(*ss_opts), GFP_KERNEL);
        if (!ss_opts)
                return ERR_PTR(-ENOMEM);
-       ss_opts->func_inst.free_func_inst = acm_free_instance;
+       ss_opts->func_inst.free_func_inst = source_sink_free_instance;
        return &ss_opts->func_inst;
 }
 DECLARE_USB_FUNCTION(SourceSink, source_sink_alloc_inst,
index f172bd152fbb905d34906a468e79e0422e98483b..185d6f5e4e4d15a933aeaa5b5e8ab0edc2c642b5 100644 (file)
@@ -380,7 +380,8 @@ geth_unbind(struct usb_configuration *c, struct usb_function *f)
  * Caller must have called @gether_setup().  Caller is also responsible
  * for calling @gether_cleanup() before module unload.
  */
-int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+               struct eth_dev *dev)
 {
        struct f_gether *geth;
        int             status;
@@ -406,6 +407,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
        snprintf(geth->ethaddr, sizeof geth->ethaddr, "%pm", ethaddr);
        geth_string_defs[1].s = geth->ethaddr;
 
+       geth->port.ioport = dev;
        geth->port.cdc_filter = DEFAULT_FILTER;
 
        geth->port.func.name = "cdc_subset";
index 92efd6ec48afde2333f2edf2a6000d70bbfbd098..38dcedddc52c0bb43b70e6c5faa8ac3857d5c466 100644 (file)
@@ -33,19 +33,15 @@ unsigned int uvc_gadget_trace_param;
 /*-------------------------------------------------------------------------*/
 
 /* module parameters specific to the Video streaming endpoint */
-static unsigned streaming_interval = 1;
+static unsigned int streaming_interval = 1;
 module_param(streaming_interval, uint, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(streaming_interval, "1 - 16");
 
-static unsigned streaming_maxpacket = 1024;
+static unsigned int streaming_maxpacket = 1024;
 module_param(streaming_maxpacket, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(streaming_maxpacket, "0 - 1023 (fs), 0 - 1024 (hs/ss)");
+MODULE_PARM_DESC(streaming_maxpacket, "1 - 1023 (FS), 1 - 3072 (hs/ss)");
 
-static unsigned streaming_mult;
-module_param(streaming_mult, uint, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(streaming_mult, "0 - 2 (hs/ss only)");
-
-static unsigned streaming_maxburst;
+static unsigned int streaming_maxburst;
 module_param(streaming_maxburst, uint, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
 
@@ -55,13 +51,11 @@ MODULE_PARM_DESC(streaming_maxburst, "0 - 15 (ss only)");
 
 /* string IDs are assigned dynamically */
 
-#define UVC_STRING_ASSOCIATION_IDX             0
-#define UVC_STRING_CONTROL_IDX                 1
-#define UVC_STRING_STREAMING_IDX               2
+#define UVC_STRING_CONTROL_IDX                 0
+#define UVC_STRING_STREAMING_IDX               1
 
 static struct usb_string uvc_en_us_strings[] = {
-       [UVC_STRING_ASSOCIATION_IDX].s = "UVC Camera",
-       [UVC_STRING_CONTROL_IDX].s = "Video Control",
+       [UVC_STRING_CONTROL_IDX].s = "UVC Camera",
        [UVC_STRING_STREAMING_IDX].s = "Video Streaming",
        {  }
 };
@@ -79,7 +73,7 @@ static struct usb_gadget_strings *uvc_function_strings[] = {
 #define UVC_INTF_VIDEO_CONTROL                 0
 #define UVC_INTF_VIDEO_STREAMING               1
 
-#define STATUS_BYTECOUNT                       16      /* 16 bytes status */
+#define UVC_STATUS_MAX_PACKET_SIZE             16      /* 16 bytes status */
 
 static struct usb_interface_assoc_descriptor uvc_iad __initdata = {
        .bLength                = sizeof(uvc_iad),
@@ -104,20 +98,29 @@ static struct usb_interface_descriptor uvc_control_intf __initdata = {
        .iInterface             = 0,
 };
 
-static struct usb_endpoint_descriptor uvc_fs_control_ep __initdata = {
+static struct usb_endpoint_descriptor uvc_control_ep __initdata = {
        .bLength                = USB_DT_ENDPOINT_SIZE,
        .bDescriptorType        = USB_DT_ENDPOINT,
        .bEndpointAddress       = USB_DIR_IN,
        .bmAttributes           = USB_ENDPOINT_XFER_INT,
-       .wMaxPacketSize         = cpu_to_le16(STATUS_BYTECOUNT),
+       .wMaxPacketSize         = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
        .bInterval              = 8,
 };
 
+static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = {
+       .bLength                = sizeof(uvc_ss_control_comp),
+       .bDescriptorType        = USB_DT_SS_ENDPOINT_COMP,
+       /* The following 3 values can be tweaked if necessary. */
+       .bMaxBurst              = 0,
+       .bmAttributes           = 0,
+       .wBytesPerInterval      = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
+};
+
 static struct uvc_control_endpoint_descriptor uvc_control_cs_ep __initdata = {
        .bLength                = UVC_DT_CONTROL_ENDPOINT_SIZE,
        .bDescriptorType        = USB_DT_CS_ENDPOINT,
        .bDescriptorSubType     = UVC_EP_INTERRUPT,
-       .wMaxTransferSize       = cpu_to_le16(STATUS_BYTECOUNT),
+       .wMaxTransferSize       = cpu_to_le16(UVC_STATUS_MAX_PACKET_SIZE),
 };
 
 static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = {
@@ -144,63 +147,53 @@ static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = {
        .iInterface             = 0,
 };
 
-static struct usb_endpoint_descriptor uvc_fs_streaming_ep = {
+static struct usb_endpoint_descriptor uvc_fs_streaming_ep __initdata = {
        .bLength                = USB_DT_ENDPOINT_SIZE,
        .bDescriptorType        = USB_DT_ENDPOINT,
        .bEndpointAddress       = USB_DIR_IN,
-       .bmAttributes           = USB_ENDPOINT_XFER_ISOC,
-       .wMaxPacketSize         = cpu_to_le16(512),
-       .bInterval              = 1,
+       .bmAttributes           = USB_ENDPOINT_SYNC_ASYNC
+                               | USB_ENDPOINT_XFER_ISOC,
+       /* The wMaxPacketSize and bInterval values will be initialized from
+        * module parameters.
+        */
+       .wMaxPacketSize         = 0,
+       .bInterval              = 0,
 };
 
-static struct usb_endpoint_descriptor uvc_hs_streaming_ep = {
+static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = {
        .bLength                = USB_DT_ENDPOINT_SIZE,
        .bDescriptorType        = USB_DT_ENDPOINT,
        .bEndpointAddress       = USB_DIR_IN,
-       .bmAttributes           = USB_ENDPOINT_XFER_ISOC,
-       .wMaxPacketSize         = cpu_to_le16(1024),
-       .bInterval              = 1,
-};
-
-/* super speed support */
-static struct usb_endpoint_descriptor uvc_ss_control_ep __initdata = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
-
-       .bEndpointAddress =     USB_DIR_IN,
-       .bmAttributes =         USB_ENDPOINT_XFER_INT,
-       .wMaxPacketSize =       cpu_to_le16(STATUS_BYTECOUNT),
-       .bInterval =            8,
-};
-
-static struct usb_ss_ep_comp_descriptor uvc_ss_control_comp __initdata = {
-       .bLength =              sizeof uvc_ss_control_comp,
-       .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
-
-       /* the following 3 values can be tweaked if necessary */
-       /* .bMaxBurst =         0, */
-       /* .bmAttributes =      0, */
-       .wBytesPerInterval =    cpu_to_le16(STATUS_BYTECOUNT),
+       .bmAttributes           = USB_ENDPOINT_SYNC_ASYNC
+                               | USB_ENDPOINT_XFER_ISOC,
+       /* The wMaxPacketSize and bInterval values will be initialized from
+        * module parameters.
+        */
+       .wMaxPacketSize         = 0,
+       .bInterval              = 0,
 };
 
 static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = {
-       .bLength =              USB_DT_ENDPOINT_SIZE,
-       .bDescriptorType =      USB_DT_ENDPOINT,
+       .bLength                = USB_DT_ENDPOINT_SIZE,
+       .bDescriptorType        = USB_DT_ENDPOINT,
 
-       .bEndpointAddress =     USB_DIR_IN,
-       .bmAttributes =         USB_ENDPOINT_XFER_ISOC,
-       .wMaxPacketSize =       cpu_to_le16(1024),
-       .bInterval =            4,
+       .bEndpointAddress       = USB_DIR_IN,
+       .bmAttributes           = USB_ENDPOINT_SYNC_ASYNC
+                               | USB_ENDPOINT_XFER_ISOC,
+       /* The wMaxPacketSize and bInterval values will be initialized from
+        * module parameters.
+        */
+       .wMaxPacketSize         = 0,
+       .bInterval              = 0,
 };
 
-static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp = {
-       .bLength =              sizeof uvc_ss_streaming_comp,
-       .bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
-
-       /* the following 3 values can be tweaked if necessary */
-       .bMaxBurst =            0,
-       .bmAttributes = 0,
-       .wBytesPerInterval =    cpu_to_le16(1024),
+static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp __initdata = {
+       .bLength                = sizeof(uvc_ss_streaming_comp),
+       .bDescriptorType        = USB_DT_SS_ENDPOINT_COMP,
+       /* The following 3 values can be tweaked if necessary. */
+       .bMaxBurst              = 0,
+       .bmAttributes           = 0,
+       .wBytesPerInterval      = cpu_to_le16(1024),
 };
 
 static const struct usb_descriptor_header * const uvc_fs_streaming[] = {
@@ -273,6 +266,13 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
        return 0;
 }
 
+void uvc_function_setup_continue(struct uvc_device *uvc)
+{
+       struct usb_composite_dev *cdev = uvc->func.config->cdev;
+
+       usb_composite_setup_continue(cdev);
+}
+
 static int
 uvc_function_get_alt(struct usb_function *f, unsigned interface)
 {
@@ -335,7 +335,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
                v4l2_event_queue(uvc->vdev, &v4l2_event);
 
                uvc->state = UVC_STATE_CONNECTED;
-               break;
+               return 0;
 
        case 1:
                if (uvc->state != UVC_STATE_CONNECTED)
@@ -352,15 +352,11 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt)
                memset(&v4l2_event, 0, sizeof(v4l2_event));
                v4l2_event.type = UVC_EVENT_STREAMON;
                v4l2_event_queue(uvc->vdev, &v4l2_event);
-
-               uvc->state = UVC_STATE_STREAMING;
-               break;
+               return USB_GADGET_DELAYED_STATUS;
 
        default:
                return -EINVAL;
        }
-
-       return 0;
 }
 
 static void
@@ -454,7 +450,6 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
        const struct uvc_descriptor_header * const *uvc_streaming_cls;
        const struct usb_descriptor_header * const *uvc_streaming_std;
        const struct usb_descriptor_header * const *src;
-       static struct usb_endpoint_descriptor *uvc_control_ep;
        struct usb_descriptor_header **dst;
        struct usb_descriptor_header **hdr;
        unsigned int control_size;
@@ -468,14 +463,12 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
                uvc_control_desc = uvc->desc.ss_control;
                uvc_streaming_cls = uvc->desc.ss_streaming;
                uvc_streaming_std = uvc_ss_streaming;
-               uvc_control_ep = &uvc_ss_control_ep;
                break;
 
        case USB_SPEED_HIGH:
                uvc_control_desc = uvc->desc.fs_control;
                uvc_streaming_cls = uvc->desc.hs_streaming;
                uvc_streaming_std = uvc_hs_streaming;
-               uvc_control_ep = &uvc_fs_control_ep;
                break;
 
        case USB_SPEED_FULL:
@@ -483,7 +476,6 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
                uvc_control_desc = uvc->desc.fs_control;
                uvc_streaming_cls = uvc->desc.fs_streaming;
                uvc_streaming_std = uvc_fs_streaming;
-               uvc_control_ep = &uvc_fs_control_ep;
                break;
        }
 
@@ -494,6 +486,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
         * Class-specific UVC control descriptors
         * uvc_control_ep
         * uvc_control_cs_ep
+        * uvc_ss_control_comp (for SS only)
         * uvc_streaming_intf_alt0
         * Class-specific UVC streaming descriptors
         * uvc_{fs|hs}_streaming
@@ -503,7 +496,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
        control_size = 0;
        streaming_size = 0;
        bytes = uvc_iad.bLength + uvc_control_intf.bLength
-             + uvc_control_ep->bLength + uvc_control_cs_ep.bLength
+             + uvc_control_ep.bLength + uvc_control_cs_ep.bLength
              + uvc_streaming_intf_alt0.bLength;
 
        if (speed == USB_SPEED_SUPER) {
@@ -514,13 +507,13 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
        }
 
        for (src = (const struct usb_descriptor_header **)uvc_control_desc;
-                       *src; ++src) {
+            *src; ++src) {
                control_size += (*src)->bLength;
                bytes += (*src)->bLength;
                n_desc++;
        }
        for (src = (const struct usb_descriptor_header **)uvc_streaming_cls;
-                       *src; ++src) {
+            *src; ++src) {
                streaming_size += (*src)->bLength;
                bytes += (*src)->bLength;
                n_desc++;
@@ -549,7 +542,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
        uvc_control_header->bInCollection = 1;
        uvc_control_header->baInterfaceNr[0] = uvc->streaming_intf;
 
-       UVC_COPY_DESCRIPTOR(mem, dst, uvc_control_ep);
+       UVC_COPY_DESCRIPTOR(mem, dst, &uvc_control_ep);
        if (speed == USB_SPEED_SUPER)
                UVC_COPY_DESCRIPTOR(mem, dst, &uvc_ss_control_comp);
 
@@ -560,8 +553,7 @@ uvc_copy_descriptors(struct uvc_device *uvc, enum usb_device_speed speed)
        UVC_COPY_DESCRIPTORS(mem, dst,
                (const struct usb_descriptor_header**)uvc_streaming_cls);
        uvc_streaming_header->wTotalLength = cpu_to_le16(streaming_size);
-       uvc_streaming_header->bEndpointAddress =
-               uvc_fs_streaming_ep.bEndpointAddress;
+       uvc_streaming_header->bEndpointAddress = uvc->video.ep->address;
 
        UVC_COPY_DESCRIPTORS(mem, dst, uvc_streaming_std);
 
@@ -581,7 +573,7 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f)
        uvc->control_ep->driver_data = NULL;
        uvc->video.ep->driver_data = NULL;
 
-       uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = 0;
+       uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = 0;
        usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
        kfree(uvc->control_buf);
 
@@ -595,31 +587,52 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
 {
        struct usb_composite_dev *cdev = c->cdev;
        struct uvc_device *uvc = to_uvc(f);
+       unsigned int max_packet_mult;
+       unsigned int max_packet_size;
        struct usb_ep *ep;
        int ret = -EINVAL;
 
        INFO(cdev, "uvc_function_bind\n");
 
-       /* sanity check the streaming endpoint module parameters */
-       if (streaming_interval < 1)
-               streaming_interval = 1;
-       if (streaming_interval > 16)
-               streaming_interval = 16;
-       if (streaming_mult > 2)
-               streaming_mult = 2;
-       if (streaming_maxburst > 15)
-               streaming_maxburst = 15;
-
-       /*
-        * fill in the FS video streaming specific descriptors from the
-        * module parameters
+       /* Sanity check the streaming endpoint module parameters.
         */
-       uvc_fs_streaming_ep.wMaxPacketSize = streaming_maxpacket > 1023 ?
-                                               1023 : streaming_maxpacket;
+       streaming_interval = clamp(streaming_interval, 1U, 16U);
+       streaming_maxpacket = clamp(streaming_maxpacket, 1U, 3072U);
+       streaming_maxburst = min(streaming_maxburst, 15U);
+
+       /* Fill in the FS/HS/SS Video Streaming specific descriptors from the
+        * module parameters.
+        *
+        * NOTE: We assume that the user knows what they are doing and won't
+        * give parameters that their UDC doesn't support.
+        */
+       if (streaming_maxpacket <= 1024) {
+               max_packet_mult = 1;
+               max_packet_size = streaming_maxpacket;
+       } else if (streaming_maxpacket <= 2048) {
+               max_packet_mult = 2;
+               max_packet_size = streaming_maxpacket / 2;
+       } else {
+               max_packet_mult = 3;
+               max_packet_size = streaming_maxpacket / 3;
+       }
+
+       uvc_fs_streaming_ep.wMaxPacketSize = min(streaming_maxpacket, 1023U);
        uvc_fs_streaming_ep.bInterval = streaming_interval;
 
+       uvc_hs_streaming_ep.wMaxPacketSize = max_packet_size;
+       uvc_hs_streaming_ep.wMaxPacketSize |= ((max_packet_mult - 1) << 11);
+       uvc_hs_streaming_ep.bInterval = streaming_interval;
+
+       uvc_ss_streaming_ep.wMaxPacketSize = max_packet_size;
+       uvc_ss_streaming_ep.bInterval = streaming_interval;
+       uvc_ss_streaming_comp.bmAttributes = max_packet_mult - 1;
+       uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
+       uvc_ss_streaming_comp.wBytesPerInterval =
+               max_packet_size * max_packet_mult * streaming_maxburst;
+
        /* Allocate endpoints. */
-       ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_control_ep);
+       ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep);
        if (!ep) {
                INFO(cdev, "Unable to allocate control EP\n");
                goto error;
@@ -627,7 +640,14 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
        uvc->control_ep = ep;
        ep->driver_data = uvc;
 
-       ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep);
+       if (gadget_is_superspeed(c->cdev->gadget))
+               ep = usb_ep_autoconfig_ss(cdev->gadget, &uvc_ss_streaming_ep,
+                                         &uvc_ss_streaming_comp);
+       else if (gadget_is_dualspeed(cdev->gadget))
+               ep = usb_ep_autoconfig(cdev->gadget, &uvc_hs_streaming_ep);
+       else
+               ep = usb_ep_autoconfig(cdev->gadget, &uvc_fs_streaming_ep);
+
        if (!ep) {
                INFO(cdev, "Unable to allocate streaming EP\n");
                goto error;
@@ -635,6 +655,10 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
        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;
+       uvc_ss_streaming_ep.bEndpointAddress = uvc->video.ep->address;
+
        /* Allocate interface IDs. */
        if ((ret = usb_interface_id(c, f)) < 0)
                goto error;
@@ -648,37 +672,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
        uvc_streaming_intf_alt1.bInterfaceNumber = ret;
        uvc->streaming_intf = ret;
 
-       /* sanity check the streaming endpoint module parameters */
-       if (streaming_maxpacket > 1024)
-               streaming_maxpacket = 1024;
-       /*
-        * Fill in the HS descriptors from the module parameters for the Video
-        * Streaming endpoint.
-        * NOTE: We assume that the user knows what they are doing and won't
-        * give parameters that their UDC doesn't support.
-        */
-       uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket;
-       uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11;
-       uvc_hs_streaming_ep.bInterval = streaming_interval;
-       uvc_hs_streaming_ep.bEndpointAddress =
-               uvc_fs_streaming_ep.bEndpointAddress;
-
-       /*
-        * Fill in the SS descriptors from the module parameters for the Video
-        * Streaming endpoint.
-        * NOTE: We assume that the user knows what they are doing and won't
-        * give parameters that their UDC doesn't support.
-        */
-       uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
-       uvc_ss_streaming_ep.bInterval = streaming_interval;
-       uvc_ss_streaming_comp.bmAttributes = streaming_mult;
-       uvc_ss_streaming_comp.bMaxBurst = streaming_maxburst;
-       uvc_ss_streaming_comp.wBytesPerInterval =
-               streaming_maxpacket * (streaming_mult + 1) *
-               (streaming_maxburst + 1);
-       uvc_ss_streaming_ep.bEndpointAddress =
-               uvc_fs_streaming_ep.bEndpointAddress;
-
        /* Copy descriptors */
        f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
        if (gadget_is_dualspeed(cdev->gadget))
@@ -775,23 +768,23 @@ uvc_bind_config(struct usb_configuration *c,
 
        /* Validate the descriptors. */
        if (fs_control == NULL || fs_control[0] == NULL ||
-               fs_control[0]->bDescriptorSubType != UVC_VC_HEADER)
+           fs_control[0]->bDescriptorSubType != UVC_VC_HEADER)
                goto error;
 
        if (ss_control == NULL || ss_control[0] == NULL ||
-               ss_control[0]->bDescriptorSubType != UVC_VC_HEADER)
+           ss_control[0]->bDescriptorSubType != UVC_VC_HEADER)
                goto error;
 
        if (fs_streaming == NULL || fs_streaming[0] == NULL ||
-               fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
+           fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
                goto error;
 
        if (hs_streaming == NULL || hs_streaming[0] == NULL ||
-               hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
+           hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
                goto error;
 
        if (ss_streaming == NULL || ss_streaming[0] == NULL ||
-               ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
+           ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
                goto error;
 
        uvc->desc.fs_control = fs_control;
@@ -800,13 +793,16 @@ uvc_bind_config(struct usb_configuration *c,
        uvc->desc.hs_streaming = hs_streaming;
        uvc->desc.ss_streaming = ss_streaming;
 
-       /* Allocate string descriptor numbers. */
-       if (uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id == 0) {
+       /* String descriptors are global, we only need to allocate string IDs
+        * for the first UVC function. UVC functions beyond the first (if any)
+        * will reuse the same IDs.
+        */
+       if (uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id == 0) {
                ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings);
                if (ret)
                        goto error;
                uvc_iad.iFunction =
-                       uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id;
+                       uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
                uvc_control_intf.iInterface =
                        uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
                ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id;
index c3d258d301880021ed8f533004cb344189ea8bf0..ec52752f7326d2d422be5e8ea054bb4932f113dc 100644 (file)
 #include <linux/usb/composite.h>
 #include <linux/usb/video.h>
 
-extern int uvc_bind_config(struct usb_configuration *c,
-                  const struct uvc_descriptor_header * const *fs_control,
-                  const struct uvc_descriptor_header * const *hs_control,
-                  const struct uvc_descriptor_header * const *fs_streaming,
-                  const struct uvc_descriptor_header * const *hs_streaming,
-                  const struct uvc_descriptor_header * const *ss_streaming);
+int uvc_bind_config(struct usb_configuration *c,
+                   const struct uvc_descriptor_header * const *fs_control,
+                   const struct uvc_descriptor_header * const *hs_control,
+                   const struct uvc_descriptor_header * const *fs_streaming,
+                   const struct uvc_descriptor_header * const *hs_streaming,
+                   const struct uvc_descriptor_header * const *ss_streaming);
 
 #endif /* _F_UVC_H_ */
 
index 034477ce77c69d298a41c3018a939464a810f6ab..9a7ee3347e4d925e55645c2e0f1de7ef03ca312a 100644 (file)
@@ -2296,7 +2296,6 @@ static int fsl_qe_start(struct usb_gadget *gadget,
        driver->driver.bus = NULL;
        /* hook up the driver */
        udc->driver = driver;
-       udc->gadget.dev.driver = &driver->driver;
        udc->gadget.speed = driver->max_speed;
 
        /* Enable IRQ reg and Set usbcmd reg EN bit */
@@ -2338,7 +2337,6 @@ static int fsl_qe_stop(struct usb_gadget *gadget,
                nuke(loop_ep, -ESHUTDOWN);
        spin_unlock_irqrestore(&udc->lock, flags);
 
-       udc->gadget.dev.driver = NULL;
        udc->driver = NULL;
 
        dev_info(udc->dev, "unregistered gadget driver '%s'\r\n",
@@ -2523,12 +2521,6 @@ static int qe_udc_probe(struct platform_device *ofdev)
 
        /* name: Identifies the controller hardware type. */
        udc->gadget.name = driver_name;
-
-       device_initialize(&udc->gadget.dev);
-
-       dev_set_name(&udc->gadget.dev, "gadget");
-
-       udc->gadget.dev.release = qe_udc_release;
        udc->gadget.dev.parent = &ofdev->dev;
 
        /* initialize qe_ep struct */
@@ -2592,22 +2584,17 @@ static int qe_udc_probe(struct platform_device *ofdev)
                goto err5;
        }
 
-       ret = device_add(&udc->gadget.dev);
+       ret = usb_add_gadget_udc_release(&ofdev->dev, &udc->gadget,
+                       qe_udc_release);
        if (ret)
                goto err6;
 
-       ret = usb_add_gadget_udc(&ofdev->dev, &udc->gadget);
-       if (ret)
-               goto err7;
-
        dev_set_drvdata(&ofdev->dev, udc);
        dev_info(udc->dev,
                        "%s USB controller initialized as device\n",
                        (udc->soc_type == PORT_QE) ? "QE" : "CPM");
        return 0;
 
-err7:
-       device_unregister(&udc->gadget.dev);
 err6:
        free_irq(udc->usb_irq, udc);
 err5:
@@ -2702,7 +2689,6 @@ static int qe_udc_remove(struct platform_device *ofdev)
 
        iounmap(udc->usb_regs);
 
-       device_unregister(&udc->gadget.dev);
        /* wait for release() of gadget.dev to free udc */
        wait_for_completion(&done);
 
index 04d5fef1440cf591d923b88e0099473610c53ef1..7c2a101d19acfd9702aab4f0505db25226a0b79b 100644 (file)
@@ -185,20 +185,7 @@ static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
                dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma);
        }
 
-       if (req->mapped) {
-               dma_unmap_single(ep->udc->gadget.dev.parent,
-                       req->req.dma, req->req.length,
-                       ep_is_in(ep)
-                               ? DMA_TO_DEVICE
-                               : DMA_FROM_DEVICE);
-               req->req.dma = DMA_ADDR_INVALID;
-               req->mapped = 0;
-       } else
-               dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
-                       req->req.dma, req->req.length,
-                       ep_is_in(ep)
-                               ? DMA_TO_DEVICE
-                               : DMA_FROM_DEVICE);
+       usb_gadget_unmap_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
 
        if (status && (status != -ESHUTDOWN))
                VDBG("complete %s req %p stat %d len %u/%u",
@@ -888,6 +875,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
        struct fsl_req *req = container_of(_req, struct fsl_req, req);
        struct fsl_udc *udc;
        unsigned long flags;
+       int ret;
 
        /* catch various bogus parameters */
        if (!_req || !req->req.complete || !req->req.buf
@@ -910,22 +898,9 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 
        req->ep = ep;
 
-       /* map virtual address to hardware */
-       if (req->req.dma == DMA_ADDR_INVALID) {
-               req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
-                                       req->req.buf,
-                                       req->req.length, ep_is_in(ep)
-                                               ? DMA_TO_DEVICE
-                                               : DMA_FROM_DEVICE);
-               req->mapped = 1;
-       } else {
-               dma_sync_single_for_device(ep->udc->gadget.dev.parent,
-                                       req->req.dma, req->req.length,
-                                       ep_is_in(ep)
-                                               ? DMA_TO_DEVICE
-                                               : DMA_FROM_DEVICE);
-               req->mapped = 0;
-       }
+       ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
+       if (ret)
+               return ret;
 
        req->req.status = -EINPROGRESS;
        req->req.actual = 0;
@@ -1290,6 +1265,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
 {
        struct fsl_req *req = udc->status_req;
        struct fsl_ep *ep;
+       int ret;
 
        if (direction == EP_DIR_IN)
                udc->ep0_dir = USB_DIR_IN;
@@ -1307,10 +1283,9 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
        req->req.complete = NULL;
        req->dtd_count = 0;
 
-       req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
-                       req->req.buf, req->req.length,
-                       ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-       req->mapped = 1;
+       ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
+       if (ret)
+               return ret;
 
        if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)
                fsl_queue_td(ep, req);
@@ -1353,6 +1328,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
        u16 tmp = 0;            /* Status, cpu endian */
        struct fsl_req *req;
        struct fsl_ep *ep;
+       int ret;
 
        ep = &udc->eps[0];
 
@@ -1390,10 +1366,9 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
        req->req.complete = NULL;
        req->dtd_count = 0;
 
-       req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
-                               req->req.buf, req->req.length,
-                               ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-       req->mapped = 1;
+       ret = usb_gadget_map_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
+       if (ret)
+               goto stall;
 
        /* prime the data phase */
        if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0))
@@ -1964,7 +1939,6 @@ static int fsl_udc_start(struct usb_gadget *g,
        driver->driver.bus = NULL;
        /* hook up the driver */
        udc_controller->driver = driver;
-       udc_controller->gadget.dev.driver = &driver->driver;
        spin_unlock_irqrestore(&udc_controller->lock, flags);
 
        if (!IS_ERR_OR_NULL(udc_controller->transceiver)) {
@@ -1980,7 +1954,6 @@ static int fsl_udc_start(struct usb_gadget *g,
                        if (retval < 0) {
                                ERR("can't bind to transceiver\n");
                                driver->unbind(&udc_controller->gadget);
-                               udc_controller->gadget.dev.driver = 0;
                                udc_controller->driver = 0;
                                return retval;
                        }
@@ -2023,7 +1996,6 @@ static int fsl_udc_stop(struct usb_gadget *g,
                nuke(loop_ep, -ESHUTDOWN);
        spin_unlock_irqrestore(&udc_controller->lock, flags);
 
-       udc_controller->gadget.dev.driver = NULL;
        udc_controller->driver = NULL;
 
        return 0;
@@ -2521,12 +2493,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 
        /* Setup gadget.dev and register with kernel */
        dev_set_name(&udc_controller->gadget.dev, "gadget");
-       udc_controller->gadget.dev.release = fsl_udc_release;
-       udc_controller->gadget.dev.parent = &pdev->dev;
        udc_controller->gadget.dev.of_node = pdev->dev.of_node;
-       ret = device_register(&udc_controller->gadget.dev);
-       if (ret < 0)
-               goto err_free_irq;
 
        if (!IS_ERR_OR_NULL(udc_controller->transceiver))
                udc_controller->gadget.is_otg = 1;
@@ -2559,10 +2526,11 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
                        DTD_ALIGNMENT, UDC_DMA_BOUNDARY);
        if (udc_controller->td_pool == NULL) {
                ret = -ENOMEM;
-               goto err_unregister;
+               goto err_free_irq;
        }
 
-       ret = usb_add_gadget_udc(&pdev->dev, &udc_controller->gadget);
+       ret = usb_add_gadget_udc_release(&pdev->dev, &udc_controller->gadget,
+                       fsl_udc_release);
        if (ret)
                goto err_del_udc;
 
@@ -2571,8 +2539,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 
 err_del_udc:
        dma_pool_destroy(udc_controller->td_pool);
-err_unregister:
-       device_unregister(&udc_controller->gadget.dev);
 err_free_irq:
        free_irq(udc_controller->irq, udc_controller);
 err_iounmap:
@@ -2622,7 +2588,6 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
        if (pdata->operating_mode == FSL_USB2_DR_DEVICE)
                release_mem_region(res->start, resource_size(res));
 
-       device_unregister(&udc_controller->gadget.dev);
        /* free udc --wait for the release() finished */
        wait_for_completion(&done);
 
@@ -2747,21 +2712,7 @@ static struct platform_driver udc_driver = {
        },
 };
 
-static int __init udc_init(void)
-{
-       printk(KERN_INFO "%s (%s)\n", driver_desc, DRIVER_VERSION);
-       return platform_driver_probe(&udc_driver, fsl_udc_probe);
-}
-
-module_init(udc_init);
-
-static void __exit udc_exit(void)
-{
-       platform_driver_unregister(&udc_driver);
-       printk(KERN_WARNING "%s unregistered\n", driver_desc);
-}
-
-module_exit(udc_exit);
+module_platform_driver_probe(udc_driver, fsl_udc_probe);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR(DRIVER_AUTHOR);
index 066cb89376deb620b366779315cd208aaed87424..cec8871b77f9d9acd91b2c845175b6f9150e8571 100644 (file)
@@ -394,7 +394,7 @@ static void fusb300_clear_epnstall(struct fusb300 *fusb300, u8 ep)
 
        if (reg & FUSB300_EPSET0_STL) {
                printk(KERN_DEBUG "EP%d stall... Clear!!\n", ep);
-               reg &= ~FUSB300_EPSET0_STL;
+               reg |= FUSB300_EPSET0_STL_CLR;
                iowrite32(reg, fusb300->reg + FUSB300_OFFSET_EPSET0(ep));
        }
 }
@@ -930,33 +930,33 @@ static void fusb300_wait_idma_finished(struct fusb300_ep *ep)
 
        fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGR0,
                FUSB300_IGR0_EPn_PRD_INT(ep->epnum));
+       return;
+
 IDMA_RESET:
-       fusb300_clear_int(ep->fusb300, FUSB300_OFFSET_IGER0,
-               FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
+       reg = ioread32(ep->fusb300->reg + FUSB300_OFFSET_IGER0);
+       reg &= ~FUSB300_IGER0_EEPn_PRD_INT(ep->epnum);
+       iowrite32(reg, ep->fusb300->reg + FUSB300_OFFSET_IGER0);
 }
 
-static void  fusb300_set_idma(struct fusb300_ep *ep,
+static void fusb300_set_idma(struct fusb300_ep *ep,
                        struct fusb300_request *req)
 {
-       dma_addr_t d;
-
-       d = dma_map_single(NULL, req->req.buf, req->req.length, DMA_TO_DEVICE);
+       int ret;
 
-       if (dma_mapping_error(NULL, d)) {
-               printk(KERN_DEBUG "dma_mapping_error\n");
+       ret = usb_gadget_map_request(&ep->fusb300->gadget,
+                       &req->req, DMA_TO_DEVICE);
+       if (ret)
                return;
-       }
-
-       dma_sync_single_for_device(NULL, d, req->req.length, DMA_TO_DEVICE);
 
        fusb300_enable_bit(ep->fusb300, FUSB300_OFFSET_IGER0,
                FUSB300_IGER0_EEPn_PRD_INT(ep->epnum));
 
-       fusb300_fill_idma_prdtbl(ep, d, req->req.length);
+       fusb300_fill_idma_prdtbl(ep, req->req.dma, req->req.length);
        /* check idma is done */
        fusb300_wait_idma_finished(ep);
 
-       dma_unmap_single(NULL, d, req->req.length, DMA_TO_DEVICE);
+       usb_gadget_unmap_request(&ep->fusb300->gadget,
+                       &req->req, DMA_TO_DEVICE);
 }
 
 static void in_ep_fifo_handler(struct fusb300_ep *ep)
@@ -1316,7 +1316,6 @@ static int fusb300_udc_start(struct usb_gadget *g,
        /* hook up the driver */
        driver->driver.bus = NULL;
        fusb300->driver = driver;
-       fusb300->gadget.dev.driver = &driver->driver;
 
        return 0;
 }
@@ -1327,7 +1326,6 @@ static int fusb300_udc_stop(struct usb_gadget *g,
        struct fusb300 *fusb300 = to_fusb300(g);
 
        driver->unbind(&fusb300->gadget);
-       fusb300->gadget.dev.driver = NULL;
 
        init_controller(fusb300);
        fusb300->driver = NULL;
@@ -1422,14 +1420,7 @@ static int __init fusb300_probe(struct platform_device *pdev)
 
        fusb300->gadget.ops = &fusb300_gadget_ops;
 
-       device_initialize(&fusb300->gadget.dev);
-
-       dev_set_name(&fusb300->gadget.dev, "gadget");
-
        fusb300->gadget.max_speed = USB_SPEED_HIGH;
-       fusb300->gadget.dev.parent = &pdev->dev;
-       fusb300->gadget.dev.dma_mask = pdev->dev.dma_mask;
-       fusb300->gadget.dev.release = pdev->dev.release;
        fusb300->gadget.name = udc_name;
        fusb300->reg = reg;
 
@@ -1478,19 +1469,10 @@ static int __init fusb300_probe(struct platform_device *pdev)
        if (ret)
                goto err_add_udc;
 
-       ret = device_add(&fusb300->gadget.dev);
-       if (ret) {
-               pr_err("device_add error (%d)\n", ret);
-               goto err_add_device;
-       }
-
        dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION);
 
        return 0;
 
-err_add_device:
-       usb_del_gadget_udc(&fusb300->gadget);
-
 err_add_udc:
        fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req);
 
index 6ba444ae8dd546e22b637fc150cd6b7abe88df52..ae811d8d38b435d9cd198369b399b1cf58bda63c 100644 (file)
 /*
  * * EPn Setting 0 (EPn_SET0, offset = 020H+(n-1)*30H, n=1~15 )
  * */
+#define FUSB300_EPSET0_STL_CLR         (1 << 3)
 #define FUSB300_EPSET0_CLRSEQNUM       (1 << 2)
-#define FUSB300_EPSET0_EPn_TX0BYTE     (1 << 1)
 #define FUSB300_EPSET0_STL             (1 << 0)
 
 /*
index 3b343b23e4b0cfee227fc56965565bb0fb768d33..787a78e92aa2d277a7c0e82661397d0a3843d481 100644 (file)
@@ -13,7 +13,6 @@
 #define pr_fmt(fmt) "g_ffs: " fmt
 
 #include <linux/module.h>
-
 /*
  * kbuild is not very cooperative with respect to linking separately
  * compiled library objects into one module.  So for now we won't use
 #  include "u_ether.c"
 
 static u8 gfs_hostaddr[ETH_ALEN];
+static struct eth_dev *the_dev;
 #  ifdef CONFIG_USB_FUNCTIONFS_ETH
-static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
+static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+               struct eth_dev *dev);
 #  endif
 #else
-#  define gether_cleanup() do { } while (0)
-#  define gether_setup(gadget, hostaddr)   ((int)0)
+#  define the_dev      NULL
+#  define gether_cleanup(dev) do { } while (0)
 #  define gfs_hostaddr NULL
+struct eth_dev;
 #endif
 
 #include "f_fs.c"
@@ -137,7 +139,8 @@ static struct usb_gadget_strings *gfs_dev_strings[] = {
 
 struct gfs_configuration {
        struct usb_configuration c;
-       int (*eth)(struct usb_configuration *c, u8 *ethaddr);
+       int (*eth)(struct usb_configuration *c, u8 *ethaddr,
+                       struct eth_dev *dev);
 } gfs_configurations[] = {
 #ifdef CONFIG_USB_FUNCTIONFS_RNDIS
        {
@@ -346,10 +349,13 @@ static int gfs_bind(struct usb_composite_dev *cdev)
 
        if (missing_funcs)
                return -ENODEV;
-
-       ret = gether_setup(cdev->gadget, gfs_hostaddr);
-       if (unlikely(ret < 0))
+#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
+       the_dev = gether_setup(cdev->gadget, gfs_hostaddr);
+#endif
+       if (IS_ERR(the_dev)) {
+               ret = PTR_ERR(the_dev);
                goto error_quick;
+       }
        gfs_ether_setup = true;
 
        ret = usb_string_ids_tab(cdev, gfs_strings);
@@ -386,7 +392,7 @@ error_unbind:
        for (i = 0; i < func_num; i++)
                functionfs_unbind(ffs_tab[i].ffs_data);
 error:
-       gether_cleanup();
+       gether_cleanup(the_dev);
 error_quick:
        gfs_ether_setup = false;
        return ret;
@@ -410,7 +416,7 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
         * do...?
         */
        if (gfs_ether_setup)
-               gether_cleanup();
+               gether_cleanup(the_dev);
        gfs_ether_setup = false;
 
        for (i = func_num; i--; )
@@ -440,7 +446,7 @@ static int gfs_do_config(struct usb_configuration *c)
        }
 
        if (gc->eth) {
-               ret = gc->eth(c, gfs_hostaddr);
+               ret = gc->eth(c, gfs_hostaddr, the_dev);
                if (unlikely(ret < 0))
                        return ret;
        }
@@ -469,11 +475,12 @@ static int gfs_do_config(struct usb_configuration *c)
 
 #ifdef CONFIG_USB_FUNCTIONFS_ETH
 
-static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+               struct eth_dev *dev)
 {
        return can_support_ecm(c->cdev->gadget)
-               ? ecm_bind_config(c, ethaddr)
-               : geth_bind_config(c, ethaddr);
+               ? ecm_bind_config(c, ethaddr, dev)
+               : geth_bind_config(c, ethaddr, dev);
 }
 
 #endif
index 85742d4c67dfa2708a763bd607d580936c38cd88..991aba390d9d3e34fc967e3aeeda3e582a8eeaa3 100644 (file)
@@ -51,8 +51,6 @@
 #define        DRIVER_DESC             "TC86C001 USB Device Controller"
 #define        DRIVER_VERSION          "30-Oct 2003"
 
-#define        DMA_ADDR_INVALID        (~(dma_addr_t)0)
-
 static const char driver_name [] = "goku_udc";
 static const char driver_desc [] = DRIVER_DESC;
 
@@ -275,7 +273,6 @@ goku_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
        if (!req)
                return NULL;
 
-       req->req.dma = DMA_ADDR_INVALID;
        INIT_LIST_HEAD(&req->queue);
        return &req->req;
 }
@@ -1354,7 +1351,6 @@ static int goku_udc_start(struct usb_gadget *g,
        /* hook up the driver */
        driver->driver.bus = NULL;
        dev->driver = driver;
-       dev->gadget.dev.driver = &driver->driver;
 
        /*
         * then enable host detection and ep0; and we're ready
@@ -1394,7 +1390,6 @@ static int goku_udc_stop(struct usb_gadget *g,
        dev->driver = NULL;
        stop_activity(dev, driver);
        spin_unlock_irqrestore(&dev->lock, flags);
-       dev->gadget.dev.driver = NULL;
 
        return 0;
 }
@@ -1716,8 +1711,6 @@ static void goku_remove(struct pci_dev *pdev)
                                pci_resource_len (pdev, 0));
        if (dev->enabled)
                pci_disable_device(pdev);
-       if (dev->registered)
-               device_unregister(&dev->gadget.dev);
 
        pci_set_drvdata(pdev, NULL);
        dev->regs = NULL;
@@ -1756,10 +1749,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        dev->gadget.max_speed = USB_SPEED_FULL;
 
        /* the "gadget" abstracts/virtualizes the controller */
-       dev_set_name(&dev->gadget.dev, "gadget");
-       dev->gadget.dev.parent = &pdev->dev;
-       dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
-       dev->gadget.dev.release = gadget_release;
        dev->gadget.name = driver_name;
 
        /* now all the pci goodies ... */
@@ -1810,13 +1799,8 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev);
 #endif
 
-       retval = device_register(&dev->gadget.dev);
-       if (retval) {
-               put_device(&dev->gadget.dev);
-               goto err;
-       }
-       dev->registered = 1;
-       retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
+       retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
+                       gadget_release);
        if (retval)
                goto err;
 
index b4470d2b1d8603fe9dc6782144696ab48f7c2ba5..86d2adafe149a1ccfb811584f1284ce331e34ab5 100644 (file)
@@ -250,8 +250,7 @@ struct goku_udc {
                                        got_region:1,
                                        req_config:1,
                                        configured:1,
-                                       enabled:1,
-                                       registered:1;
+                                       enabled:1;
 
        /* pci state used to access those endpoints */
        struct pci_dev                  *pdev;
index 5bd930d779b9dd957b51d610469b4e6e4ead5663..b5cebd6b0d7af170128ede0f90754052b694aeb2 100644 (file)
@@ -1338,7 +1338,6 @@ static int imx_udc_start(struct usb_gadget *gadget,
        imx_usb = container_of(gadget, struct imx_udc_struct, gadget);
        /* first hook up the driver ... */
        imx_usb->driver = driver;
-       imx_usb->gadget.dev.driver = &driver->driver;
 
        D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n",
                __func__, driver->driver.name);
@@ -1358,7 +1357,6 @@ static int imx_udc_stop(struct usb_gadget *gadget,
        imx_udc_disable(imx_usb);
        del_timer(&imx_usb->timer);
 
-       imx_usb->gadget.dev.driver = NULL;
        imx_usb->driver = NULL;
 
        D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n",
@@ -1461,15 +1459,6 @@ static int __init imx_udc_probe(struct platform_device *pdev)
        imx_usb->clk = clk;
        imx_usb->dev = &pdev->dev;
 
-       device_initialize(&imx_usb->gadget.dev);
-
-       imx_usb->gadget.dev.parent = &pdev->dev;
-       imx_usb->gadget.dev.dma_mask = pdev->dev.dma_mask;
-
-       ret = device_add(&imx_usb->gadget.dev);
-       if (retval)
-               goto fail4;
-
        platform_set_drvdata(pdev, imx_usb);
 
        usb_init_data(imx_usb);
@@ -1481,11 +1470,9 @@ static int __init imx_udc_probe(struct platform_device *pdev)
 
        ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget);
        if (ret)
-               goto fail5;
+               goto fail4;
 
        return 0;
-fail5:
-       device_unregister(&imx_usb->gadget.dev);
 fail4:
        for (i = 0; i < IMX_USB_NB_EP + 1; i++)
                free_irq(imx_usb->usbd_int[i], imx_usb);
@@ -1509,7 +1496,6 @@ static int __exit imx_udc_remove(struct platform_device *pdev)
        int i;
 
        usb_del_gadget_udc(&imx_usb->gadget);
-       device_unregister(&imx_usb->gadget.dev);
        imx_udc_disable(imx_usb);
        del_timer(&imx_usb->timer);
 
index aa04089d6899fc4768537eb6257700acf91ad71e..b943d8cdfbf75d056eb50cba2899ace0fbdb55a5 100644 (file)
@@ -1469,23 +1469,7 @@ static void done(struct lpc32xx_ep *ep, struct lpc32xx_request *req, int status)
                status = req->req.status;
 
        if (ep->lep) {
-               enum dma_data_direction direction;
-
-               if (ep->is_in)
-                       direction = DMA_TO_DEVICE;
-               else
-                       direction = DMA_FROM_DEVICE;
-
-               if (req->mapped) {
-                       dma_unmap_single(ep->udc->gadget.dev.parent,
-                                       req->req.dma, req->req.length,
-                                       direction);
-                       req->req.dma = 0;
-                       req->mapped = 0;
-               } else
-                       dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
-                                               req->req.dma, req->req.length,
-                                               direction);
+               usb_gadget_unmap_request(&udc->gadget, &req->req, ep->is_in);
 
                /* Free DDs */
                udc_dd_free(udc, req->dd_desc_ptr);
@@ -1841,26 +1825,11 @@ static int lpc32xx_ep_queue(struct usb_ep *_ep,
        }
 
        if (ep->lep) {
-               enum dma_data_direction direction;
                struct lpc32xx_usbd_dd_gad *dd;
 
-               /* Map DMA pointer */
-               if (ep->is_in)
-                       direction = DMA_TO_DEVICE;
-               else
-                       direction = DMA_FROM_DEVICE;
-
-               if (req->req.dma == 0) {
-                       req->req.dma = dma_map_single(
-                               ep->udc->gadget.dev.parent,
-                               req->req.buf, req->req.length, direction);
-                       req->mapped = 1;
-               } else {
-                       dma_sync_single_for_device(
-                               ep->udc->gadget.dev.parent, req->req.dma,
-                               req->req.length, direction);
-                       req->mapped = 0;
-               }
+               status = usb_gadget_map_request(&udc->gadget, _req, ep->is_in);
+               if (status)
+                       return status;
 
                /* For the request, build a list of DDs */
                dd = udc_dd_alloc(udc);
@@ -2977,7 +2946,6 @@ static int lpc32xx_start(struct usb_gadget *gadget,
        }
 
        udc->driver = driver;
-       udc->gadget.dev.driver = &driver->driver;
        udc->gadget.dev.of_node = udc->dev->of_node;
        udc->enabled = 1;
        udc->selfpowered = 1;
@@ -3026,7 +2994,6 @@ static int lpc32xx_stop(struct usb_gadget *gadget,
        }
 
        udc->enabled = 0;
-       udc->gadget.dev.driver = NULL;
        udc->driver = NULL;
 
        return 0;
@@ -3248,12 +3215,6 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev)
        udc_disable(udc);
        udc_reinit(udc);
 
-       retval = device_register(&udc->gadget.dev);
-       if (retval < 0) {
-               dev_err(udc->dev, "Device registration failure\n");
-               goto dev_register_fail;
-       }
-
        /* Request IRQs - low and high priority USB device IRQs are routed to
         * the same handler, while the DMA interrupt is routed elsewhere */
        retval = request_irq(udc->udp_irq[IRQ_USB_LP], lpc32xx_usb_lp_irq,
@@ -3320,8 +3281,6 @@ irq_dev_fail:
 irq_hp_fail:
        free_irq(udc->udp_irq[IRQ_USB_LP], udc);
 irq_lp_fail:
-       device_unregister(&udc->gadget.dev);
-dev_register_fail:
        dma_pool_destroy(udc->dd_cache);
 dma_alloc_fail:
        dma_free_coherent(&pdev->dev, UDCA_BUFF_SIZE,
@@ -3376,8 +3335,6 @@ static int lpc32xx_udc_remove(struct platform_device *pdev)
        free_irq(udc->udp_irq[IRQ_USB_HP], udc);
        free_irq(udc->udp_irq[IRQ_USB_LP], udc);
 
-       device_unregister(&udc->gadget.dev);
-
        clk_disable(udc->usb_otg_clk);
        clk_put(udc->usb_otg_clk);
        clk_disable(udc->usb_slv_clk);
index c1b8c2dd808d31a09032ba2e78bf87eb376786ff..866ef09992478e18c114592305297efe640d225f 100644 (file)
@@ -1471,7 +1471,6 @@ static int m66592_udc_start(struct usb_gadget *g,
        /* hook up the driver */
        driver->driver.bus = NULL;
        m66592->driver = driver;
-       m66592->gadget.dev.driver = &driver->driver;
 
        m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
        if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) {
@@ -1494,7 +1493,6 @@ static int m66592_udc_stop(struct usb_gadget *g,
        m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0);
 
        driver->unbind(&m66592->gadget);
-       m66592->gadget.dev.driver = NULL;
 
        init_controller(m66592);
        disable_controller(m66592);
@@ -1538,7 +1536,6 @@ static int __exit m66592_remove(struct platform_device *pdev)
        struct m66592           *m66592 = dev_get_drvdata(&pdev->dev);
 
        usb_del_gadget_udc(&m66592->gadget);
-       device_del(&m66592->gadget.dev);
 
        del_timer_sync(&m66592->timer);
        iounmap(m66592->reg);
@@ -1608,12 +1605,7 @@ static int __init m66592_probe(struct platform_device *pdev)
        dev_set_drvdata(&pdev->dev, m66592);
 
        m66592->gadget.ops = &m66592_gadget_ops;
-       device_initialize(&m66592->gadget.dev);
-       dev_set_name(&m66592->gadget.dev, "gadget");
        m66592->gadget.max_speed = USB_SPEED_HIGH;
-       m66592->gadget.dev.parent = &pdev->dev;
-       m66592->gadget.dev.dma_mask = pdev->dev.dma_mask;
-       m66592->gadget.dev.release = pdev->dev.release;
        m66592->gadget.name = udc_name;
 
        init_timer(&m66592->timer);
@@ -1674,12 +1666,6 @@ static int __init m66592_probe(struct platform_device *pdev)
 
        init_controller(m66592);
 
-       ret = device_add(&m66592->gadget.dev);
-       if (ret) {
-               pr_err("device_add error (%d)\n", ret);
-               goto err_device_add;
-       }
-
        ret = usb_add_gadget_udc(&pdev->dev, &m66592->gadget);
        if (ret)
                goto err_add_udc;
@@ -1688,9 +1674,6 @@ static int __init m66592_probe(struct platform_device *pdev)
        return 0;
 
 err_add_udc:
-       device_del(&m66592->gadget.dev);
-
-err_device_add:
        m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req);
 
 clean_up3:
index 20bbbf917fc2cc6b8eb827ed67a3222cbf1c5eb7..4a45e80c6e384f6adb0fa4cfe6a1efc909419625 100644 (file)
@@ -135,8 +135,8 @@ static struct fsg_common fsg_common;
 
 static u8 hostaddr[ETH_ALEN];
 
-static unsigned char tty_line;
 static struct usb_function_instance *fi_acm;
+static struct eth_dev *the_dev;
 
 /********** RNDIS **********/
 
@@ -152,13 +152,15 @@ static __init int rndis_do_config(struct usb_configuration *c)
                c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
        }
 
-       ret = rndis_bind_config(c, hostaddr);
+       ret = rndis_bind_config(c, hostaddr, the_dev);
        if (ret < 0)
                return ret;
 
        f_acm_rndis = usb_get_function(fi_acm);
-       if (IS_ERR(f_acm_rndis))
+       if (IS_ERR(f_acm_rndis)) {
+               ret = PTR_ERR(f_acm_rndis);
                goto err_func_acm;
+       }
 
        ret = usb_add_function(c, f_acm_rndis);
        if (ret)
@@ -214,7 +216,7 @@ static __init int cdc_do_config(struct usb_configuration *c)
                c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
        }
 
-       ret = ecm_bind_config(c, hostaddr);
+       ret = ecm_bind_config(c, hostaddr, the_dev);
        if (ret < 0)
                return ret;
 
@@ -269,7 +271,6 @@ static int cdc_config_register(struct usb_composite_dev *cdev)
 static int __ref multi_bind(struct usb_composite_dev *cdev)
 {
        struct usb_gadget *gadget = cdev->gadget;
-       struct f_serial_opts *opts;
        int status;
 
        if (!can_support_ecm(cdev->gadget)) {
@@ -279,24 +280,17 @@ static int __ref multi_bind(struct usb_composite_dev *cdev)
        }
 
        /* set up network link layer */
-       status = gether_setup(cdev->gadget, hostaddr);
-       if (status < 0)
-               return status;
+       the_dev = gether_setup(cdev->gadget, hostaddr);
+       if (IS_ERR(the_dev))
+               return PTR_ERR(the_dev);
 
        /* set up serial link layer */
-       status = gserial_alloc_line(&tty_line);
-       if (status < 0)
-               goto fail0;
-
        fi_acm = usb_get_function_instance("acm");
        if (IS_ERR(fi_acm)) {
                status = PTR_ERR(fi_acm);
-               goto fail0dot5;
+               goto fail0;
        }
 
-       opts = container_of(fi_acm, struct f_serial_opts, func_inst);
-       opts->port_num = tty_line;
-
        /* set up mass storage function */
        {
                void *retp;
@@ -334,10 +328,8 @@ fail2:
        fsg_common_put(&fsg_common);
 fail1:
        usb_put_function_instance(fi_acm);
-fail0dot5:
-       gserial_free_line(tty_line);
 fail0:
-       gether_cleanup();
+       gether_cleanup(the_dev);
        return status;
 }
 
@@ -350,8 +342,7 @@ static int __exit multi_unbind(struct usb_composite_dev *cdev)
        usb_put_function(f_acm_rndis);
 #endif
        usb_put_function_instance(fi_acm);
-       gserial_free_line(tty_line);
-       gether_cleanup();
+       gether_cleanup(the_dev);
        return 0;
 }
 
index b5cea273c95760bdc0227caa8743d22d32b55e68..58288e9cf728e2e34a71e67183edeb6cf0532118 100644 (file)
@@ -30,9 +30,6 @@
 #include <linux/platform_device.h>
 #include <linux/platform_data/mv_usb.h>
 #include <linux/clk.h>
-#include <asm/system.h>
-#include <asm/unaligned.h>
-#include <asm/byteorder.h>
 
 #include "mv_u3d.h"
 
@@ -125,7 +122,7 @@ static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,
        struct mv_u3d_trb       *curr_trb;
        dma_addr_t cur_deq_lo;
        struct mv_u3d_ep_context        *curr_ep_context;
-       int trb_complete, actual, remaining_length;
+       int trb_complete, actual, remaining_length = 0;
        int direction, ep_num;
        int retval = 0;
        u32 tmp, status, length;
@@ -189,6 +186,8 @@ static int mv_u3d_process_ep_req(struct mv_u3d *u3d, int index,
  */
 static
 void mv_u3d_done(struct mv_u3d_ep *ep, struct mv_u3d_req *req, int status)
+       __releases(&ep->udc->lock)
+       __acquires(&ep->udc->lock)
 {
        struct mv_u3d *u3d = (struct mv_u3d *)ep->u3d;
 
@@ -812,19 +811,19 @@ mv_u3d_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
                return 0;
        }
 
-       dev_dbg(u3d->dev, "%s: %s, req: 0x%x\n",
-                       __func__, _ep->name, (u32)req);
+       dev_dbg(u3d->dev, "%s: %s, req: 0x%p\n",
+                       __func__, _ep->name, req);
 
        /* catch various bogus parameters */
        if (!req->req.complete || !req->req.buf
                        || !list_empty(&req->queue)) {
                dev_err(u3d->dev,
-                       "%s, bad params, _req: 0x%x,"
-                       "req->req.complete: 0x%x, req->req.buf: 0x%x,"
+                       "%s, bad params, _req: 0x%p,"
+                       "req->req.complete: 0x%p, req->req.buf: 0x%p,"
                        "list_empty: 0x%x\n",
-                       __func__, (u32)_req,
-                       (u32)req->req.complete, (u32)req->req.buf,
-                       (u32)list_empty(&req->queue));
+                       __func__, _req,
+                       req->req.complete, req->req.buf,
+                       list_empty(&req->queue));
                return -EINVAL;
        }
        if (unlikely(!ep->ep.desc)) {
@@ -905,7 +904,7 @@ static int mv_u3d_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
                                        struct mv_u3d_req, queue);
 
                        /* Point first TRB of next request to the EP context. */
-                       iowrite32((u32) next_req->trb_head,
+                       iowrite32((unsigned long) next_req->trb_head,
                                        &ep_context->trb_addr_lo);
                } else {
                        struct mv_u3d_ep_context *ep_context;
@@ -1264,7 +1263,6 @@ static int mv_u3d_start(struct usb_gadget *g,
        /* hook up the driver ... */
        driver->driver.bus = NULL;
        u3d->driver = driver;
-       u3d->gadget.dev.driver = &driver->driver;
 
        u3d->ep0_dir = USB_DIR_OUT;
 
@@ -1302,7 +1300,6 @@ static int mv_u3d_stop(struct usb_gadget *g,
 
        spin_unlock_irqrestore(&u3d->lock, flags);
 
-       u3d->gadget.dev.driver = NULL;
        u3d->driver = NULL;
 
        return 0;
@@ -1525,6 +1522,8 @@ static int mv_u3d_is_set_configuration(struct usb_ctrlrequest *setup)
 
 static void mv_u3d_handle_setup_packet(struct mv_u3d *u3d, u8 ep_num,
        struct usb_ctrlrequest *setup)
+       __releases(&u3c->lock)
+       __acquires(&u3c->lock)
 {
        bool delegate = false;
 
@@ -1758,11 +1757,6 @@ static irqreturn_t mv_u3d_irq(int irq, void *dev)
        return IRQ_HANDLED;
 }
 
-static void mv_u3d_gadget_release(struct device *dev)
-{
-       dev_dbg(dev, "%s\n", __func__);
-}
-
 static int mv_u3d_remove(struct platform_device *dev)
 {
        struct mv_u3d *u3d = platform_get_drvdata(dev);
@@ -1792,8 +1786,6 @@ static int mv_u3d_remove(struct platform_device *dev)
 
        clk_put(u3d->clk);
 
-       device_unregister(&u3d->gadget.dev);
-
        platform_set_drvdata(dev, NULL);
 
        kfree(u3d);
@@ -1829,7 +1821,7 @@ static int mv_u3d_probe(struct platform_device *dev)
        u3d->dev = &dev->dev;
        u3d->vbus = pdata->vbus;
 
-       u3d->clk = clk_get(&dev->dev, pdata->clkname[0]);
+       u3d->clk = clk_get(&dev->dev, NULL);
        if (IS_ERR(u3d->clk)) {
                retval = PTR_ERR(u3d->clk);
                goto err_get_clk;
@@ -1849,8 +1841,9 @@ static int mv_u3d_probe(struct platform_device *dev)
                retval = -EBUSY;
                goto err_map_cap_regs;
        } else {
-               dev_dbg(&dev->dev, "cap_regs address: 0x%x/0x%x\n",
-                       (unsigned int)r->start, (unsigned int)u3d->cap_regs);
+               dev_dbg(&dev->dev, "cap_regs address: 0x%lx/0x%lx\n",
+                       (unsigned long) r->start,
+                       (unsigned long) u3d->cap_regs);
        }
 
        /* we will access controller register, so enable the u3d controller */
@@ -1864,10 +1857,10 @@ static int mv_u3d_probe(struct platform_device *dev)
                }
        }
 
-       u3d->op_regs = (struct mv_u3d_op_regs __iomem *)((u32)u3d->cap_regs
+       u3d->op_regs = (struct mv_u3d_op_regs __iomem *)(u3d->cap_regs
                + MV_U3D_USB3_OP_REGS_OFFSET);
 
-       u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)((u32)u3d->cap_regs
+       u3d->vuc_regs = (struct mv_u3d_vuc_regs __iomem *)(u3d->cap_regs
                + ioread32(&u3d->cap_regs->vuoff));
 
        u3d->max_eps = 16;
@@ -1957,16 +1950,8 @@ static int mv_u3d_probe(struct platform_device *dev)
        u3d->gadget.speed = USB_SPEED_UNKNOWN;  /* speed */
 
        /* the "gadget" abstracts/virtualizes the controller */
-       dev_set_name(&u3d->gadget.dev, "gadget");
-       u3d->gadget.dev.parent = &dev->dev;
-       u3d->gadget.dev.dma_mask = dev->dev.dma_mask;
-       u3d->gadget.dev.release = mv_u3d_gadget_release;
        u3d->gadget.name = driver_name;         /* gadget name */
 
-       retval = device_register(&u3d->gadget.dev);
-       if (retval)
-               goto err_register_gadget_device;
-
        mv_u3d_eps_init(u3d);
 
        /* external vbus detection */
@@ -1991,8 +1976,6 @@ static int mv_u3d_probe(struct platform_device *dev)
        return 0;
 
 err_unregister:
-       device_unregister(&u3d->gadget.dev);
-err_register_gadget_device:
        free_irq(u3d->irq, &dev->dev);
 err_request_irq:
 err_get_irq:
@@ -2021,7 +2004,7 @@ err_pdata:
        return retval;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int mv_u3d_suspend(struct device *dev)
 {
        struct mv_u3d *u3d = dev_get_drvdata(dev);
@@ -2064,10 +2047,10 @@ static int mv_u3d_resume(struct device *dev)
 
        return 0;
 }
-
-SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume);
 #endif
 
+static SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume);
+
 static void mv_u3d_shutdown(struct platform_device *dev)
 {
        struct mv_u3d *u3d = dev_get_drvdata(&dev->dev);
@@ -2080,14 +2063,12 @@ static void mv_u3d_shutdown(struct platform_device *dev)
 
 static struct platform_driver mv_u3d_driver = {
        .probe          = mv_u3d_probe,
-       .remove         = __exit_p(mv_u3d_remove),
+       .remove         = mv_u3d_remove,
        .shutdown       = mv_u3d_shutdown,
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "mv-u3d",
-#ifdef CONFIG_PM
                .pm     = &mv_u3d_pm_ops,
-#endif
        },
 };
 
index 9073436d8b24af891be72d608c2ad2ef787265b9..be77f207dbafd82d8096aaf752cabeeeccf53e47 100644 (file)
@@ -222,8 +222,7 @@ struct mv_udc {
        struct mv_usb_platform_data     *pdata;
 
        /* some SOC has mutiple clock sources for USB*/
-       unsigned int    clknum;
-       struct clk      *clk[0];
+       struct clk      *clk;
 };
 
 /* endpoint data structure */
index c8cf959057fe186962960b1e177a72114d8b37d6..c2a57023e4671ccbb5a9e7f8930fecb67226901a 100644 (file)
@@ -212,6 +212,8 @@ static int process_ep_req(struct mv_udc *udc, int index,
  * request is still in progress.
  */
 static void done(struct mv_ep *ep, struct mv_req *req, int status)
+       __releases(&ep->udc->lock)
+       __acquires(&ep->udc->lock)
 {
        struct mv_udc *udc = NULL;
        unsigned char stopped = ep->stopped;
@@ -237,18 +239,7 @@ static void done(struct mv_ep *ep, struct mv_req *req, int status)
                dma_pool_free(udc->dtd_pool, curr_td, curr_td->td_dma);
        }
 
-       if (req->mapped) {
-               dma_unmap_single(ep->udc->gadget.dev.parent,
-                       req->req.dma, req->req.length,
-                       ((ep_dir(ep) == EP_DIR_IN) ?
-                               DMA_TO_DEVICE : DMA_FROM_DEVICE));
-               req->req.dma = DMA_ADDR_INVALID;
-               req->mapped = 0;
-       } else
-               dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
-                       req->req.dma, req->req.length,
-                       ((ep_dir(ep) == EP_DIR_IN) ?
-                               DMA_TO_DEVICE : DMA_FROM_DEVICE));
+       usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep));
 
        if (status && (status != -ESHUTDOWN))
                dev_info(&udc->dev->dev, "complete %s req %p stat %d len %u/%u",
@@ -732,21 +723,9 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
        req->ep = ep;
 
        /* map virtual address to hardware */
-       if (req->req.dma == DMA_ADDR_INVALID) {
-               req->req.dma = dma_map_single(ep->udc->gadget.dev.parent,
-                                       req->req.buf,
-                                       req->req.length, ep_dir(ep)
-                                               ? DMA_TO_DEVICE
-                                               : DMA_FROM_DEVICE);
-               req->mapped = 1;
-       } else {
-               dma_sync_single_for_device(ep->udc->gadget.dev.parent,
-                                       req->req.dma, req->req.length,
-                                       ep_dir(ep)
-                                               ? DMA_TO_DEVICE
-                                               : DMA_FROM_DEVICE);
-               req->mapped = 0;
-       }
+       retval = usb_gadget_map_request(&udc->gadget, _req, ep_dir(ep));
+       if (retval)
+               return retval;
 
        req->req.status = -EINPROGRESS;
        req->req.actual = 0;
@@ -780,18 +759,7 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
        return 0;
 
 err_unmap_dma:
-       if (req->mapped) {
-               dma_unmap_single(ep->udc->gadget.dev.parent,
-                               req->req.dma, req->req.length,
-                               ((ep_dir(ep) == EP_DIR_IN) ?
-                               DMA_TO_DEVICE : DMA_FROM_DEVICE));
-               req->req.dma = DMA_ADDR_INVALID;
-               req->mapped = 0;
-       } else
-               dma_sync_single_for_cpu(ep->udc->gadget.dev.parent,
-                               req->req.dma, req->req.length,
-                               ((ep_dir(ep) == EP_DIR_IN) ?
-                               DMA_TO_DEVICE : DMA_FROM_DEVICE));
+       usb_gadget_unmap_request(&udc->gadget, _req, ep_dir(ep));
 
        return retval;
 }
@@ -1006,18 +974,12 @@ static struct usb_ep_ops mv_ep_ops = {
 
 static void udc_clock_enable(struct mv_udc *udc)
 {
-       unsigned int i;
-
-       for (i = 0; i < udc->clknum; i++)
-               clk_prepare_enable(udc->clk[i]);
+       clk_prepare_enable(udc->clk);
 }
 
 static void udc_clock_disable(struct mv_udc *udc)
 {
-       unsigned int i;
-
-       for (i = 0; i < udc->clknum; i++)
-               clk_disable_unprepare(udc->clk[i]);
+       clk_disable_unprepare(udc->clk);
 }
 
 static void udc_stop(struct mv_udc *udc)
@@ -1386,7 +1348,6 @@ static int mv_udc_start(struct usb_gadget *gadget,
        /* hook up the driver ... */
        driver->driver.bus = NULL;
        udc->driver = driver;
-       udc->gadget.dev.driver = &driver->driver;
 
        udc->usb_state = USB_STATE_ATTACHED;
        udc->ep0_state = WAIT_FOR_SETUP;
@@ -1401,7 +1362,6 @@ static int mv_udc_start(struct usb_gadget *gadget,
                        dev_err(&udc->dev->dev,
                                "unable to register peripheral to otg\n");
                        udc->driver = NULL;
-                       udc->gadget.dev.driver = NULL;
                        return retval;
                }
        }
@@ -1437,7 +1397,6 @@ static int mv_udc_stop(struct usb_gadget *gadget,
        spin_unlock_irqrestore(&udc->lock, flags);
 
        /* unbind gadget driver */
-       udc->gadget.dev.driver = NULL;
        udc->driver = NULL;
 
        return 0;
@@ -1528,14 +1487,7 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty)
 
        return 0;
 out:
-       if (req->mapped) {
-               dma_unmap_single(ep->udc->gadget.dev.parent,
-                               req->req.dma, req->req.length,
-                               ((ep_dir(ep) == EP_DIR_IN) ?
-                               DMA_TO_DEVICE : DMA_FROM_DEVICE));
-               req->req.dma = DMA_ADDR_INVALID;
-               req->mapped = 0;
-       }
+       usb_gadget_unmap_request(&udc->gadget, &req->req, ep_dir(ep));
 
        return retval;
 }
@@ -1695,6 +1647,8 @@ out:
 
 static void handle_setup_packet(struct mv_udc *udc, u8 ep_num,
        struct usb_ctrlrequest *setup)
+       __releases(&ep->udc->lock)
+       __acquires(&ep->udc->lock)
 {
        bool delegate = false;
 
@@ -1891,7 +1845,7 @@ static void irq_process_tr_complete(struct mv_udc *udc)
        }
 }
 
-void irq_process_reset(struct mv_udc *udc)
+static void irq_process_reset(struct mv_udc *udc)
 {
        u32 tmp;
        unsigned int loops;
@@ -2138,8 +2092,6 @@ static int mv_udc_remove(struct platform_device *pdev)
 
        mv_udc_disable(udc);
 
-       device_unregister(&udc->gadget.dev);
-
        /* free dev, wait for the release() finished */
        wait_for_completion(udc->done);
 
@@ -2151,7 +2103,6 @@ static int mv_udc_probe(struct platform_device *pdev)
        struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
        struct mv_udc *udc;
        int retval = 0;
-       int clk_i = 0;
        struct resource *r;
        size_t size;
 
@@ -2160,8 +2111,7 @@ static int mv_udc_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       size = sizeof(*udc) + sizeof(struct clk *) * pdata->clknum;
-       udc = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+       udc = devm_kzalloc(&pdev->dev, sizeof(*udc), GFP_KERNEL);
        if (udc == NULL) {
                dev_err(&pdev->dev, "failed to allocate memory for udc\n");
                return -ENOMEM;
@@ -2173,26 +2123,24 @@ static int mv_udc_probe(struct platform_device *pdev)
 
        udc->dev = pdev;
 
-#ifdef CONFIG_USB_OTG_UTILS
        if (pdata->mode == MV_USB_MODE_OTG) {
                udc->transceiver = devm_usb_get_phy(&pdev->dev,
                                        USB_PHY_TYPE_USB2);
-               if (IS_ERR_OR_NULL(udc->transceiver)) {
+               if (IS_ERR(udc->transceiver)) {
+                       retval = PTR_ERR(udc->transceiver);
+
+                       if (retval == -ENXIO)
+                               return retval;
+
                        udc->transceiver = NULL;
-                       return -ENODEV;
+                       return -EPROBE_DEFER;
                }
        }
-#endif
 
-       udc->clknum = pdata->clknum;
-       for (clk_i = 0; clk_i < udc->clknum; clk_i++) {
-               udc->clk[clk_i] = devm_clk_get(&pdev->dev,
-                                       pdata->clkname[clk_i]);
-               if (IS_ERR(udc->clk[clk_i])) {
-                       retval = PTR_ERR(udc->clk[clk_i]);
-                       return retval;
-               }
-       }
+       /* udc only have one sysclk. */
+       udc->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(udc->clk))
+               return PTR_ERR(udc->clk);
 
        r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs");
        if (r == NULL) {
@@ -2311,16 +2259,8 @@ static int mv_udc_probe(struct platform_device *pdev)
        udc->gadget.max_speed = USB_SPEED_HIGH; /* support dual speed */
 
        /* the "gadget" abstracts/virtualizes the controller */
-       dev_set_name(&udc->gadget.dev, "gadget");
-       udc->gadget.dev.parent = &pdev->dev;
-       udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
-       udc->gadget.dev.release = gadget_release;
        udc->gadget.name = driver_name;         /* gadget name */
 
-       retval = device_register(&udc->gadget.dev);
-       if (retval)
-               goto err_destroy_dma;
-
        eps_init(udc);
 
        /* VBUS detect: we can disable/enable clock on demand.*/
@@ -2342,7 +2282,7 @@ static int mv_udc_probe(struct platform_device *pdev)
                if (!udc->qwork) {
                        dev_err(&pdev->dev, "cannot create workqueue\n");
                        retval = -ENOMEM;
-                       goto err_unregister;
+                       goto err_destroy_dma;
                }
 
                INIT_WORK(&udc->vbus_work, mv_udc_vbus_work);
@@ -2358,7 +2298,8 @@ static int mv_udc_probe(struct platform_device *pdev)
        else
                udc->vbus_active = 1;
 
-       retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
+       retval = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
+                       gadget_release);
        if (retval)
                goto err_create_workqueue;
 
@@ -2370,8 +2311,6 @@ static int mv_udc_probe(struct platform_device *pdev)
 
 err_create_workqueue:
        destroy_workqueue(udc->qwork);
-err_unregister:
-       device_unregister(&udc->gadget.dev);
 err_destroy_dma:
        dma_pool_destroy(udc->dtd_pool);
 err_free_dma:
index a22ad9af0565d3a7132f08b1c21b939679322473..3b02fd4649ce9f8daaae203ec72129f2c4683b1a 100644 (file)
@@ -111,6 +111,7 @@ static struct usb_gadget_strings *dev_strings[] = {
        NULL,
 };
 
+struct eth_dev *the_dev;
 static u8 hostaddr[ETH_ALEN];
 
 /*-------------------------------------------------------------------------*/
@@ -124,7 +125,7 @@ static int __init ncm_do_config(struct usb_configuration *c)
                c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
        }
 
-       return ncm_bind_config(c, hostaddr);
+       return ncm_bind_config(c, hostaddr, the_dev);
 }
 
 static struct usb_configuration ncm_config_driver = {
@@ -143,9 +144,9 @@ static int __init gncm_bind(struct usb_composite_dev *cdev)
        int                     status;
 
        /* set up network link layer */
-       status = gether_setup(cdev->gadget, hostaddr);
-       if (status < 0)
-               return status;
+       the_dev = gether_setup(cdev->gadget, hostaddr);
+       if (IS_ERR(the_dev))
+               return PTR_ERR(the_dev);
 
        /* Allocate string descriptor numbers ... note that string
         * contents can be overridden by the composite_dev glue.
@@ -168,13 +169,13 @@ static int __init gncm_bind(struct usb_composite_dev *cdev)
        return 0;
 
 fail:
-       gether_cleanup();
+       gether_cleanup(the_dev);
        return status;
 }
 
 static int __exit gncm_unbind(struct usb_composite_dev *cdev)
 {
-       gether_cleanup();
+       gether_cleanup(the_dev);
        return 0;
 }
 
index 32524b631959eda7a62e2e2b005c3ba7a2e88f4b..f1e50a3e322d9368d5e7d8f968f423ef9d928153 100644 (file)
@@ -58,7 +58,6 @@ static const char * const ep_name[] = {
        "ep-a", "ep-b", "ep-c",
 };
 
-#define DMA_ADDR_INVALID       (~(dma_addr_t)0)
 #ifdef CONFIG_USB_NET2272_DMA
 /*
  * use_dma: the NET2272 can use an external DMA controller.
@@ -341,7 +340,6 @@ net2272_alloc_request(struct usb_ep *_ep, gfp_t gfp_flags)
        if (!req)
                return NULL;
 
-       req->req.dma = DMA_ADDR_INVALID;
        INIT_LIST_HEAD(&req->queue);
 
        return &req->req;
@@ -913,7 +911,7 @@ net2272_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
                        }
                }
        }
-       if (likely(req != 0))
+       if (likely(req))
                list_add_tail(&req->queue, &ep->queue);
 
        if (likely(!list_empty(&ep->queue)))
@@ -1467,7 +1465,6 @@ static int net2272_start(struct usb_gadget *_gadget,
        dev->softconnect = 1;
        driver->driver.bus = NULL;
        dev->driver = driver;
-       dev->gadget.dev.driver = &driver->driver;
 
        /* ... then enable host detection and ep0; and we're ready
         * for set_configuration as well as eventual disconnect.
@@ -1517,7 +1514,6 @@ static int net2272_stop(struct usb_gadget *_gadget,
        stop_activity(dev, driver);
        spin_unlock_irqrestore(&dev->lock, flags);
 
-       dev->gadget.dev.driver = NULL;
        dev->driver = NULL;
 
        dev_dbg(dev->dev, "unregistered driver '%s'\n", driver->driver.name);
@@ -1549,7 +1545,7 @@ net2272_handle_dma(struct net2272_ep *ep)
              | (ep->dev->dma_eot_polarity << EOT_POLARITY)
              | (ep->dev->dma_dack_polarity << DACK_POLARITY)
              | (ep->dev->dma_dreq_polarity << DREQ_POLARITY)
-             | ((ep->dma >> 1) << DMA_ENDPOINT_SELECT));
+             | (ep->dma << DMA_ENDPOINT_SELECT));
 
        ep->dev->dma_busy = 0;
 
@@ -1622,7 +1618,7 @@ net2272_handle_ep(struct net2272_ep *ep)
        ep->irqs++;
 
        dev_vdbg(ep->dev->dev, "%s ack ep_stat0 %02x, ep_stat1 %02x, req %p\n",
-               ep->ep.name, stat0, stat1, req ? &req->req : 0);
+               ep->ep.name, stat0, stat1, req ? &req->req : NULL);
 
        net2272_ep_write(ep, EP_STAT0, stat0 &
                ~((1 << NAK_OUT_PACKETS)
@@ -2216,7 +2212,6 @@ net2272_remove(struct net2272 *dev)
        free_irq(dev->irq, dev);
        iounmap(dev->base_addr);
 
-       device_unregister(&dev->gadget.dev);
        device_remove_file(dev->dev, &dev_attr_registers);
 
        dev_info(dev->dev, "unbind\n");
@@ -2243,10 +2238,6 @@ static struct net2272 *net2272_probe_init(struct device *dev, unsigned int irq)
        ret->gadget.max_speed = USB_SPEED_HIGH;
 
        /* the "gadget" abstracts/virtualizes the controller */
-       dev_set_name(&ret->gadget.dev, "gadget");
-       ret->gadget.dev.parent = dev;
-       ret->gadget.dev.dma_mask = dev->dma_mask;
-       ret->gadget.dev.release = net2272_gadget_release;
        ret->gadget.name = driver_name;
 
        return ret;
@@ -2282,14 +2273,12 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
                dma_mode_string());
        dev_info(dev->dev, "version: %s\n", driver_vers);
 
-       ret = device_register(&dev->gadget.dev);
-       if (ret)
-               goto err_irq;
        ret = device_create_file(dev->dev, &dev_attr_registers);
        if (ret)
-               goto err_dev_reg;
+               goto err_irq;
 
-       ret = usb_add_gadget_udc(dev->dev, &dev->gadget);
+       ret = usb_add_gadget_udc_release(dev->dev, &dev->gadget,
+                       net2272_gadget_release);
        if (ret)
                goto err_add_udc;
 
@@ -2297,8 +2286,6 @@ net2272_probe_fin(struct net2272 *dev, unsigned int irqflags)
 
 err_add_udc:
        device_remove_file(dev->dev, &dev_attr_registers);
- err_dev_reg:
-       device_unregister(&dev->gadget.dev);
  err_irq:
        free_irq(dev->irq, dev);
  err:
index 3bd0f992fb49aebe5b5c4dc9e45356bb77c01581..fbd006ab31d3bf1f25151dab6be694279f4d8928 100644 (file)
@@ -65,7 +65,6 @@
 #define        DRIVER_DESC             "PLX NET228x USB Peripheral Controller"
 #define        DRIVER_VERSION          "2005 Sept 27"
 
-#define        DMA_ADDR_INVALID        (~(dma_addr_t)0)
 #define        EP_DONTUSE              13      /* nonzero */
 
 #define USE_RDK_LEDS           /* GPIO pins control three LEDs */
@@ -406,7 +405,6 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
        if (!req)
                return NULL;
 
-       req->req.dma = DMA_ADDR_INVALID;
        INIT_LIST_HEAD (&req->queue);
 
        /* this dma descriptor may be swapped with the previous dummy */
@@ -420,7 +418,6 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
                        return NULL;
                }
                td->dmacount = 0;       /* not VALID */
-               td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);
                td->dmadesc = td->dmaaddr;
                req->td = td;
        }
@@ -1896,7 +1893,6 @@ static int net2280_start(struct usb_gadget *_gadget,
        dev->softconnect = 1;
        driver->driver.bus = NULL;
        dev->driver = driver;
-       dev->gadget.dev.driver = &driver->driver;
 
        retval = device_create_file (&dev->pdev->dev, &dev_attr_function);
        if (retval) goto err_unbind;
@@ -1924,7 +1920,6 @@ static int net2280_start(struct usb_gadget *_gadget,
 err_func:
        device_remove_file (&dev->pdev->dev, &dev_attr_function);
 err_unbind:
-       dev->gadget.dev.driver = NULL;
        dev->driver = NULL;
        return retval;
 }
@@ -1967,7 +1962,6 @@ static int net2280_stop(struct usb_gadget *_gadget,
        stop_activity (dev, driver);
        spin_unlock_irqrestore (&dev->lock, flags);
 
-       dev->gadget.dev.driver = NULL;
        dev->driver = NULL;
 
        net2280_led_active (dev, 0);
@@ -2072,7 +2066,7 @@ static void handle_ep_small (struct net2280_ep *ep)
                return;
 
        /* manual DMA queue advance after short OUT */
-       if (likely (ep->dma != 0)) {
+       if (likely (ep->dma)) {
                if (t & (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)) {
                        u32     count;
                        int     stopped = ep->stopped;
@@ -2330,7 +2324,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
                        /* hw handles device and interface status */
                        if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
                                goto delegate;
-                       if ((e = get_ep_by_addr (dev, w_index)) == 0
+                       if ((e = get_ep_by_addr (dev, w_index)) == NULL
                                        || w_length > 2)
                                goto do_stall;
 
@@ -2358,7 +2352,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
                        if (w_value != USB_ENDPOINT_HALT
                                        || w_length != 0)
                                goto do_stall;
-                       if ((e = get_ep_by_addr (dev, w_index)) == 0)
+                       if ((e = get_ep_by_addr (dev, w_index)) == NULL)
                                goto do_stall;
                        if (e->wedged) {
                                VDEBUG(dev, "%s wedged, halt not cleared\n",
@@ -2380,7 +2374,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
                        if (w_value != USB_ENDPOINT_HALT
                                        || w_length != 0)
                                goto do_stall;
-                       if ((e = get_ep_by_addr (dev, w_index)) == 0)
+                       if ((e = get_ep_by_addr (dev, w_index)) == NULL)
                                goto do_stall;
                        if (e->ep.name == ep0name)
                                goto do_stall;
@@ -2685,7 +2679,6 @@ static void net2280_remove (struct pci_dev *pdev)
                                pci_resource_len (pdev, 0));
        if (dev->enabled)
                pci_disable_device (pdev);
-       device_unregister (&dev->gadget.dev);
        device_remove_file (&pdev->dev, &dev_attr_registers);
        pci_set_drvdata (pdev, NULL);
 
@@ -2717,10 +2710,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
        dev->gadget.max_speed = USB_SPEED_HIGH;
 
        /* the "gadget" abstracts/virtualizes the controller */
-       dev_set_name(&dev->gadget.dev, "gadget");
-       dev->gadget.dev.parent = &pdev->dev;
-       dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
-       dev->gadget.dev.release = gadget_release;
        dev->gadget.name = driver_name;
 
        /* now all the pci goodies ... */
@@ -2802,7 +2791,6 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
                        goto done;
                }
                td->dmacount = 0;       /* not VALID */
-               td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID);
                td->dmadesc = td->dmaaddr;
                dev->ep [i].dummy = td;
        }
@@ -2829,12 +2817,11 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
                        use_dma
                                ? (use_dma_chaining ? "chaining" : "enabled")
                                : "disabled");
-       retval = device_register (&dev->gadget.dev);
-       if (retval) goto done;
        retval = device_create_file (&pdev->dev, &dev_attr_registers);
        if (retval) goto done;
 
-       retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
+       retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
+                       gadget_release);
        if (retval)
                goto done;
        return 0;
index def37403989a6ee79cdc9d1cb414cce51c13d3d3..3b344b41a167e2c69ecfb5720a29d74684315428 100644 (file)
  * the runtime footprint, and giving us at least some parts of what
  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
  */
-#define USB_FACM_INCLUDED
-#include "f_acm.c"
+#define USBF_OBEX_INCLUDED
 #include "f_ecm.c"
 #include "f_obex.c"
-#include "f_serial.c"
 #include "f_phonet.c"
 #include "u_ether.c"
 
@@ -98,20 +96,40 @@ MODULE_AUTHOR("Felipe Balbi");
 MODULE_LICENSE("GPL");
 
 /*-------------------------------------------------------------------------*/
-
+static struct usb_function *f_acm_cfg1;
+static struct usb_function *f_acm_cfg2;
 static u8 hostaddr[ETH_ALEN];
+static struct eth_dev *the_dev;
 
 enum {
        TTY_PORT_OBEX0,
        TTY_PORT_OBEX1,
-       TTY_PORT_ACM,
        TTY_PORTS_MAX,
 };
 
 static unsigned char tty_lines[TTY_PORTS_MAX];
 
+static struct usb_configuration nokia_config_500ma_driver = {
+       .label          = "Bus Powered",
+       .bConfigurationValue = 1,
+       /* .iConfiguration = DYNAMIC */
+       .bmAttributes   = USB_CONFIG_ATT_ONE,
+       .MaxPower       = 500,
+};
+
+static struct usb_configuration nokia_config_100ma_driver = {
+       .label          = "Self Powered",
+       .bConfigurationValue = 2,
+       /* .iConfiguration = DYNAMIC */
+       .bmAttributes   = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
+       .MaxPower       = 100,
+};
+
+static struct usb_function_instance *fi_acm;
+
 static int __init nokia_bind_config(struct usb_configuration *c)
 {
+       struct usb_function *f_acm;
        int status = 0;
 
        status = phonet_bind_config(c);
@@ -126,33 +144,32 @@ static int __init nokia_bind_config(struct usb_configuration *c)
        if (status)
                printk(KERN_DEBUG "could not bind obex config %d\n", 0);
 
-       status = acm_bind_config(c, tty_lines[TTY_PORT_ACM]);
-       if (status)
-               printk(KERN_DEBUG "could not bind acm config\n");
+       f_acm = usb_get_function(fi_acm);
+       if (IS_ERR(f_acm))
+               return PTR_ERR(f_acm);
 
-       status = ecm_bind_config(c, hostaddr);
+       status = usb_add_function(c, f_acm);
        if (status)
-               printk(KERN_DEBUG "could not bind ecm config\n");
+               goto err_conf;
+
+       status = ecm_bind_config(c, hostaddr, the_dev);
+       if (status) {
+               pr_debug("could not bind ecm config %d\n", status);
+               goto err_ecm;
+       }
+       if (c == &nokia_config_500ma_driver)
+               f_acm_cfg1 = f_acm;
+       else
+               f_acm_cfg2 = f_acm;
 
        return status;
+err_ecm:
+       usb_remove_function(c, f_acm);
+err_conf:
+       usb_put_function(f_acm);
+       return status;
 }
 
-static struct usb_configuration nokia_config_500ma_driver = {
-       .label          = "Bus Powered",
-       .bConfigurationValue = 1,
-       /* .iConfiguration = DYNAMIC */
-       .bmAttributes   = USB_CONFIG_ATT_ONE,
-       .MaxPower       = 500,
-};
-
-static struct usb_configuration nokia_config_100ma_driver = {
-       .label          = "Self Powered",
-       .bConfigurationValue = 2,
-       /* .iConfiguration = DYNAMIC */
-       .bmAttributes   = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
-       .MaxPower       = 100,
-};
-
 static int __init nokia_bind(struct usb_composite_dev *cdev)
 {
        struct usb_gadget       *gadget = cdev->gadget;
@@ -169,9 +186,11 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
                        goto err_ether;
        }
 
-       status = gether_setup(cdev->gadget, hostaddr);
-       if (status < 0)
+       the_dev = gether_setup(cdev->gadget, hostaddr);
+       if (IS_ERR(the_dev)) {
+               status = PTR_ERR(the_dev);
                goto err_ether;
+       }
 
        status = usb_string_ids_tab(cdev, strings_dev);
        if (status < 0)
@@ -185,24 +204,32 @@ static int __init nokia_bind(struct usb_composite_dev *cdev)
        if (!gadget_supports_altsettings(gadget))
                goto err_usb;
 
+       fi_acm = usb_get_function_instance("acm");
+       if (IS_ERR(fi_acm))
+               goto err_usb;
+
        /* finally register the configuration */
        status = usb_add_config(cdev, &nokia_config_500ma_driver,
                        nokia_bind_config);
        if (status < 0)
-               goto err_usb;
+               goto err_acm_inst;
 
        status = usb_add_config(cdev, &nokia_config_100ma_driver,
                        nokia_bind_config);
        if (status < 0)
-               goto err_usb;
+               goto err_put_cfg1;
 
        usb_composite_overwrite_options(cdev, &coverwrite);
        dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME);
 
        return 0;
 
+err_put_cfg1:
+       usb_put_function(f_acm_cfg1);
+err_acm_inst:
+       usb_put_function_instance(fi_acm);
 err_usb:
-       gether_cleanup();
+       gether_cleanup(the_dev);
 err_ether:
        cur_line--;
        while (cur_line >= 0)
@@ -217,12 +244,15 @@ static int __exit nokia_unbind(struct usb_composite_dev *cdev)
 {
        int i;
 
+       usb_put_function(f_acm_cfg1);
+       usb_put_function(f_acm_cfg2);
+       usb_put_function_instance(fi_acm);
        gphonet_cleanup();
 
        for (i = 0; i < TTY_PORTS_MAX; i++)
                gserial_free_line(tty_lines[i]);
 
-       gether_cleanup();
+       gether_cleanup(the_dev);
 
        return 0;
 }
@@ -247,4 +277,3 @@ static void __exit nokia_cleanup(void)
        usb_composite_unregister(&nokia_driver);
 }
 module_exit(nokia_cleanup);
-
index f8445653577fbb107256576fec5481b4b94f758f..b8ed74a823cbb41c6f585fe422483905fc2567ea 100644 (file)
@@ -2067,7 +2067,6 @@ static int omap_udc_start(struct usb_gadget *g,
        /* hook up the driver */
        driver->driver.bus = NULL;
        udc->driver = driver;
-       udc->gadget.dev.driver = &driver->driver;
        spin_unlock_irqrestore(&udc->lock, flags);
 
        if (udc->dc_clk != NULL)
@@ -2083,7 +2082,6 @@ static int omap_udc_start(struct usb_gadget *g,
                        ERR("can't bind to transceiver\n");
                        if (driver->unbind) {
                                driver->unbind(&udc->gadget);
-                               udc->gadget.dev.driver = NULL;
                                udc->driver = NULL;
                        }
                        goto done;
@@ -2129,7 +2127,6 @@ static int omap_udc_stop(struct usb_gadget *g,
        udc_quiesce(udc);
        spin_unlock_irqrestore(&udc->lock, flags);
 
-       udc->gadget.dev.driver = NULL;
        udc->driver = NULL;
 
        if (udc->dc_clk != NULL)
@@ -2631,14 +2628,6 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
        udc->gadget.speed = USB_SPEED_UNKNOWN;
        udc->gadget.max_speed = USB_SPEED_FULL;
        udc->gadget.name = driver_name;
-
-       device_initialize(&udc->gadget.dev);
-       dev_set_name(&udc->gadget.dev, "gadget");
-       udc->gadget.dev.release = omap_udc_release;
-       udc->gadget.dev.parent = &odev->dev;
-       if (use_dma)
-               udc->gadget.dev.dma_mask = odev->dev.dma_mask;
-
        udc->transceiver = xceiv;
 
        /* ep0 is special; put it right after the SETUP buffer */
@@ -2912,14 +2901,13 @@ bad_on_1710:
        }
 
        create_proc_file();
-       status = device_add(&udc->gadget.dev);
+       status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
+                       omap_udc_release);
        if (status)
                goto cleanup4;
 
-       status = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
-       if (!status)
-               return status;
-       /* If fail, fall through */
+       return 0;
+
 cleanup4:
        remove_proc_file();
 
@@ -2990,7 +2978,6 @@ static int omap_udc_remove(struct platform_device *pdev)
        release_mem_region(pdev->resource[0].start,
                        pdev->resource[0].end - pdev->resource[0].start + 1);
 
-       device_unregister(&udc->gadget.dev);
        wait_for_completion(&done);
 
        return 0;
index a787a8ef672b0fc60f0969075dda6eaa3d4f7e0c..24174e1d15642be63c652340c80e81dc61d1bb15 100644 (file)
@@ -358,7 +358,6 @@ struct pch_udc_dev {
                        prot_stall:1,
                        irq_registered:1,
                        mem_region:1,
-                       registered:1,
                        suspended:1,
                        connected:1,
                        vbus_session:1,
@@ -1441,6 +1440,8 @@ static void pch_vbus_gpio_free(struct pch_udc_dev *dev)
  */
 static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req,
                                                                 int status)
+       __releases(&dev->lock)
+       __acquires(&dev->lock)
 {
        struct pch_udc_dev      *dev;
        unsigned halted = ep->halted;
@@ -2382,6 +2383,8 @@ static void pch_udc_svc_control_in(struct pch_udc_dev *dev)
  * @dev:       Reference to the device structure
  */
 static void pch_udc_svc_control_out(struct pch_udc_dev *dev)
+       __releases(&dev->lock)
+       __acquires(&dev->lock)
 {
        u32     stat;
        int setup_supported;
@@ -2989,7 +2992,6 @@ static int pch_udc_start(struct usb_gadget *g,
 
        driver->driver.bus = NULL;
        dev->driver = driver;
-       dev->gadget.dev.driver = &driver->driver;
 
        /* get ready for ep0 traffic */
        pch_udc_setup_ep0(dev);
@@ -3010,7 +3012,6 @@ static int pch_udc_stop(struct usb_gadget *g,
        pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK);
 
        /* Assures that there are no pending requests with this driver */
-       dev->gadget.dev.driver = NULL;
        dev->driver = NULL;
        dev->connected = 0;
 
@@ -3078,8 +3079,6 @@ static void pch_udc_remove(struct pci_dev *pdev)
                                   pci_resource_len(pdev, PCH_UDC_PCI_BAR));
        if (dev->active)
                pci_disable_device(pdev);
-       if (dev->registered)
-               device_unregister(&dev->gadget.dev);
        kfree(dev);
        pci_set_drvdata(pdev, NULL);
 }
@@ -3196,21 +3195,13 @@ static int pch_udc_probe(struct pci_dev *pdev,
        if (retval)
                goto finished;
 
-       dev_set_name(&dev->gadget.dev, "gadget");
-       dev->gadget.dev.parent = &pdev->dev;
-       dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
-       dev->gadget.dev.release = gadget_release;
        dev->gadget.name = KBUILD_MODNAME;
        dev->gadget.max_speed = USB_SPEED_HIGH;
 
-       retval = device_register(&dev->gadget.dev);
-       if (retval)
-               goto finished;
-       dev->registered = 1;
-
        /* Put the device in disconnected state till a driver is bound */
        pch_udc_set_disconnect(dev);
-       retval = usb_add_gadget_udc(&pdev->dev, &dev->gadget);
+       retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget,
+                       gadget_release);
        if (retval)
                goto finished;
        return 0;
index d0f37484b6b0cf67faf1875db8440521b030f1a2..ef47495dec8f5e638e97ee4171b0a54b22dc2ba4 100644 (file)
@@ -1263,7 +1263,6 @@ static int pxa25x_udc_start(struct usb_gadget *g,
 
        /* first hook up the driver ... */
        dev->driver = driver;
-       dev->gadget.dev.driver = &driver->driver;
        dev->pullup = 1;
 
        /* ... then enable host detection and ep0; and we're ready
@@ -1325,7 +1324,6 @@ static int pxa25x_udc_stop(struct usb_gadget*g,
        if (!IS_ERR_OR_NULL(dev->transceiver))
                (void) otg_set_peripheral(dev->transceiver->otg, NULL);
 
-       dev->gadget.dev.driver = NULL;
        dev->driver = NULL;
 
        dump_state(dev);
@@ -2138,17 +2136,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
        dev->timer.function = udc_watchdog;
        dev->timer.data = (unsigned long) dev;
 
-       device_initialize(&dev->gadget.dev);
-       dev->gadget.dev.parent = &pdev->dev;
-       dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
-
-       retval = device_add(&dev->gadget.dev);
-       if (retval) {
-               dev->driver = NULL;
-               dev->gadget.dev.driver = NULL;
-               goto err_device_add;
-       }
-
        the_controller = dev;
        platform_set_drvdata(pdev, dev);
 
@@ -2199,8 +2186,6 @@ lubbock_fail0:
        free_irq(irq, dev);
 #endif
  err_irq1:
-       device_unregister(&dev->gadget.dev);
- err_device_add:
        if (gpio_is_valid(dev->mach->gpio_pullup))
                gpio_free(dev->mach->gpio_pullup);
  err_gpio_pullup:
@@ -2226,7 +2211,6 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
                return -EBUSY;
 
        usb_del_gadget_udc(&dev->gadget);
-       device_unregister(&dev->gadget.dev);
        dev->pullup = 0;
        pullup(dev);
 
index 2fc867652ef5df8f97e55c7c3ebe45196c672ab7..6b4c7d95853f2ee0caead3191b22c0e017153c9b 100644 (file)
 #include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/prefetch.h>
-
-#include <asm/byteorder.h>
-#include <mach/hardware.h>
+#include <linux/byteorder/generic.h>
+#include <linux/platform_data/pxa2xx_udc.h>
 
 #include <linux/usb.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
-#include <mach/udc.h>
 
 #include "pxa27x_udc.h"
 
@@ -611,7 +609,7 @@ static void inc_ep_stats_bytes(struct pxa_ep *ep, int count, int is_in)
  *
  * Find the physical pxa27x ep, and setup its UDCCR
  */
-static __init void pxa_ep_setup(struct pxa_ep *ep)
+static void pxa_ep_setup(struct pxa_ep *ep)
 {
        u32 new_udccr;
 
@@ -633,7 +631,7 @@ static __init void pxa_ep_setup(struct pxa_ep *ep)
  *
  * Setup all pxa physical endpoints, except ep0
  */
-static __init void pxa_eps_setup(struct pxa_udc *dev)
+static void pxa_eps_setup(struct pxa_udc *dev)
 {
        unsigned int i;
 
@@ -1718,7 +1716,7 @@ static void udc_disable(struct pxa_udc *udc)
  * Initializes gadget endpoint list, endpoints locks. No action is taken
  * on the hardware.
  */
-static __init void udc_init_data(struct pxa_udc *dev)
+static void udc_init_data(struct pxa_udc *dev)
 {
        int i;
        struct pxa_ep *ep;
@@ -1811,7 +1809,6 @@ static int pxa27x_udc_start(struct usb_gadget *g,
 
        /* first hook up the driver ... */
        udc->driver = driver;
-       udc->gadget.dev.driver = &driver->driver;
        dplus_pullup(udc, 1);
 
        if (!IS_ERR_OR_NULL(udc->transceiver)) {
@@ -1829,7 +1826,6 @@ static int pxa27x_udc_start(struct usb_gadget *g,
 
 fail:
        udc->driver = NULL;
-       udc->gadget.dev.driver = NULL;
        return retval;
 }
 
@@ -1871,7 +1867,6 @@ static int pxa27x_udc_stop(struct usb_gadget *g,
 
        udc->driver = NULL;
 
-
        if (!IS_ERR_OR_NULL(udc->transceiver))
                return otg_set_peripheral(udc->transceiver->otg, NULL);
        return 0;
@@ -2413,7 +2408,7 @@ static struct pxa_udc memory = {
  * Perform basic init : allocates udc clock, creates sysfs files, requests
  * irq.
  */
-static int __init pxa_udc_probe(struct platform_device *pdev)
+static int pxa_udc_probe(struct platform_device *pdev)
 {
        struct resource *regs;
        struct pxa_udc *udc = &memory;
@@ -2456,9 +2451,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
                goto err_map;
        }
 
-       device_initialize(&udc->gadget.dev);
-       udc->gadget.dev.parent = &pdev->dev;
-       udc->gadget.dev.dma_mask = NULL;
        udc->vbus_sensed = 0;
 
        the_controller = udc;
@@ -2475,12 +2467,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
                goto err_irq;
        }
 
-       retval = device_add(&udc->gadget.dev);
-       if (retval) {
-               dev_err(udc->dev, "device_add error %d\n", retval);
-               goto err_dev_add;
-       }
-
        retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
        if (retval)
                goto err_add_udc;
@@ -2490,8 +2476,6 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
        return 0;
 
 err_add_udc:
-       device_unregister(&udc->gadget.dev);
-err_dev_add:
        free_irq(udc->irq, udc);
 err_irq:
        iounmap(udc->regs);
@@ -2506,13 +2490,12 @@ err_clk:
  * pxa_udc_remove - removes the udc device driver
  * @_dev: platform device
  */
-static int __exit pxa_udc_remove(struct platform_device *_dev)
+static int pxa_udc_remove(struct platform_device *_dev)
 {
        struct pxa_udc *udc = platform_get_drvdata(_dev);
        int gpio = udc->mach->gpio_pullup;
 
        usb_del_gadget_udc(&udc->gadget);
-       device_del(&udc->gadget.dev);
        usb_gadget_unregister_driver(udc->driver);
        free_irq(udc->irq, udc);
        pxa_cleanup_debugfs(udc);
@@ -2625,7 +2608,8 @@ static struct platform_driver udc_driver = {
                .name   = "pxa27x-udc",
                .owner  = THIS_MODULE,
        },
-       .remove         = __exit_p(pxa_udc_remove),
+       .probe          = pxa_udc_probe,
+       .remove         = pxa_udc_remove,
        .shutdown       = pxa_udc_shutdown,
 #ifdef CONFIG_PM
        .suspend        = pxa_udc_suspend,
@@ -2633,22 +2617,7 @@ static struct platform_driver udc_driver = {
 #endif
 };
 
-static int __init udc_init(void)
-{
-       if (!cpu_is_pxa27x() && !cpu_is_pxa3xx())
-               return -ENODEV;
-
-       printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION);
-       return platform_driver_probe(&udc_driver, pxa_udc_probe);
-}
-module_init(udc_init);
-
-
-static void __exit udc_exit(void)
-{
-       platform_driver_unregister(&udc_driver);
-}
-module_exit(udc_exit);
+module_platform_driver(udc_driver);
 
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_AUTHOR("Robert Jarzmik");
index f46a1b77ce3e4d586182888972060cc3e737d99b..0b742d171843fc8579691930791d0926a7f3d958 100644 (file)
@@ -1837,7 +1837,6 @@ static int __exit r8a66597_remove(struct platform_device *pdev)
                clk_put(r8a66597->clk);
        }
 
-       device_unregister(&r8a66597->gadget.dev);
        kfree(r8a66597);
        return 0;
 }
@@ -1915,17 +1914,8 @@ static int __init r8a66597_probe(struct platform_device *pdev)
        r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
 
        r8a66597->gadget.ops = &r8a66597_gadget_ops;
-       dev_set_name(&r8a66597->gadget.dev, "gadget");
        r8a66597->gadget.max_speed = USB_SPEED_HIGH;
-       r8a66597->gadget.dev.parent = &pdev->dev;
-       r8a66597->gadget.dev.dma_mask = pdev->dev.dma_mask;
-       r8a66597->gadget.dev.release = pdev->dev.release;
        r8a66597->gadget.name = udc_name;
-       ret = device_register(&r8a66597->gadget.dev);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "device_register failed\n");
-               goto clean_up;
-       }
 
        init_timer(&r8a66597->timer);
        r8a66597->timer.function = r8a66597_timer;
@@ -1939,7 +1929,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
                                clk_name);
                        ret = PTR_ERR(r8a66597->clk);
-                       goto clean_up_dev;
+                       goto clean_up;
                }
                clk_enable(r8a66597->clk);
        }
@@ -2007,8 +1997,6 @@ clean_up2:
                clk_disable(r8a66597->clk);
                clk_put(r8a66597->clk);
        }
-clean_up_dev:
-       device_unregister(&r8a66597->gadget.dev);
 clean_up:
        if (r8a66597) {
                if (r8a66597->sudmac_reg)
index c26564f29a2cd9e5b1eb31c3b43c5c2929bc8e24..a3cdc32115d52c646f2ae2b89ded1fcf378a9d70 100644 (file)
@@ -39,8 +39,6 @@
 
 #include "s3c-hsotg.h"
 
-#define DMA_ADDR_INVALID (~((dma_addr_t)0))
-
 static const char * const s3c_hsotg_supply_names[] = {
        "vusb_d",               /* digital USB supply, 1.2V */
        "vusb_a",               /* analog USB supply, 1.1V */
@@ -405,7 +403,6 @@ static struct usb_request *s3c_hsotg_ep_alloc_request(struct usb_ep *ep,
 
        INIT_LIST_HEAD(&req->queue);
 
-       req->req.dma = DMA_ADDR_INVALID;
        return &req->req;
 }
 
@@ -435,24 +432,12 @@ static void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg,
                                struct s3c_hsotg_req *hs_req)
 {
        struct usb_request *req = &hs_req->req;
-       enum dma_data_direction dir;
-
-       dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 
        /* ignore this if we're not moving any data */
        if (hs_req->req.length == 0)
                return;
 
-       if (hs_req->mapped) {
-               /* we mapped this, so unmap and remove the dma */
-
-               dma_unmap_single(hsotg->dev, req->dma, req->length, dir);
-
-               req->dma = DMA_ADDR_INVALID;
-               hs_req->mapped = 0;
-       } else {
-               dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir);
-       }
+       usb_gadget_unmap_request(&hsotg->gadget, hs_req, hs_ep->dir_in);
 }
 
 /**
@@ -852,37 +837,16 @@ static int s3c_hsotg_map_dma(struct s3c_hsotg *hsotg,
                             struct s3c_hsotg_ep *hs_ep,
                             struct usb_request *req)
 {
-       enum dma_data_direction dir;
        struct s3c_hsotg_req *hs_req = our_req(req);
-
-       dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+       int ret;
 
        /* if the length is zero, ignore the DMA data */
        if (hs_req->req.length == 0)
                return 0;
 
-       if (req->dma == DMA_ADDR_INVALID) {
-               dma_addr_t dma;
-
-               dma = dma_map_single(hsotg->dev, req->buf, req->length, dir);
-
-               if (unlikely(dma_mapping_error(hsotg->dev, dma)))
-                       goto dma_error;
-
-               if (dma & 3) {
-                       dev_err(hsotg->dev, "%s: unaligned dma buffer\n",
-                               __func__);
-
-                       dma_unmap_single(hsotg->dev, dma, req->length, dir);
-                       return -EINVAL;
-               }
-
-               hs_req->mapped = 1;
-               req->dma = dma;
-       } else {
-               dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir);
-               hs_req->mapped = 0;
-       }
+       ret = usb_gadget_map_request(&hsotg->gadget, req, hs_ep->dir_in);
+       if (ret)
+               goto dma_error;
 
        return 0;
 
@@ -2961,9 +2925,7 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
 
        driver->driver.bus = NULL;
        hsotg->driver = driver;
-       hsotg->gadget.dev.driver = &driver->driver;
        hsotg->gadget.dev.of_node = hsotg->dev->of_node;
-       hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask;
        hsotg->gadget.speed = USB_SPEED_UNKNOWN;
 
        ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
@@ -2979,7 +2941,6 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
 
 err:
        hsotg->driver = NULL;
-       hsotg->gadget.dev.driver = NULL;
        return ret;
 }
 
@@ -3014,7 +2975,6 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,
 
        hsotg->driver = NULL;
        hsotg->gadget.speed = USB_SPEED_UNKNOWN;
-       hsotg->gadget.dev.driver = NULL;
 
        spin_unlock_irqrestore(&hsotg->lock, flags);
 
@@ -3483,16 +3443,6 @@ static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg)
        debugfs_remove(hsotg->debug_root);
 }
 
-/**
- * s3c_hsotg_release - release callback for hsotg device
- * @dev: Device to for which release is called
- *
- * Nothing to do as the resource is allocated using devm_ API.
- */
-static void s3c_hsotg_release(struct device *dev)
-{
-}
-
 /**
  * s3c_hsotg_probe - probe function for hsotg driver
  * @pdev: The platform information for the driver
@@ -3517,7 +3467,7 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
        }
 
        phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
-       if (IS_ERR_OR_NULL(phy)) {
+       if (IS_ERR(phy)) {
                /* Fallback for pdata */
                plat = pdev->dev.platform_data;
                if (!plat) {
@@ -3567,18 +3517,10 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 
        dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq);
 
-       device_initialize(&hsotg->gadget.dev);
-
-       dev_set_name(&hsotg->gadget.dev, "gadget");
-
        hsotg->gadget.max_speed = USB_SPEED_HIGH;
        hsotg->gadget.ops = &s3c_hsotg_gadget_ops;
        hsotg->gadget.name = dev_name(dev);
 
-       hsotg->gadget.dev.parent = dev;
-       hsotg->gadget.dev.dma_mask = dev->dma_mask;
-       hsotg->gadget.dev.release = s3c_hsotg_release;
-
        /* reset the system */
 
        clk_prepare_enable(hsotg->clk);
@@ -3658,12 +3600,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 
        s3c_hsotg_phy_disable(hsotg);
 
-       ret = device_add(&hsotg->gadget.dev);
-       if (ret) {
-               put_device(&hsotg->gadget.dev);
-               goto err_ep_mem;
-       }
-
        ret = usb_add_gadget_udc(&pdev->dev, &hsotg->gadget);
        if (ret)
                goto err_ep_mem;
@@ -3702,10 +3638,8 @@ static int s3c_hsotg_remove(struct platform_device *pdev)
        }
 
        s3c_hsotg_phy_disable(hsotg);
-
        clk_disable_unprepare(hsotg->clk);
 
-       device_unregister(&hsotg->gadget.dev);
        return 0;
 }
 
index 458965a1b138febdd0dde37fcba7a3a2fa00bc77..b1f0771fbd3def2b35714515c40f0c5b14fadc21 100644 (file)
@@ -283,7 +283,6 @@ static void s3c_hsudc_nuke_ep(struct s3c_hsudc_ep *hsep, int status)
 /**
  * s3c_hsudc_stop_activity - Stop activity on all endpoints.
  * @hsudc: Device controller for which EP activity is to be stopped.
- * @driver: Reference to the gadget driver which is currently active.
  *
  * All the endpoints are stopped and any pending transfer requests if any on
  * the endpoint are terminated.
@@ -1154,7 +1153,6 @@ static int s3c_hsudc_start(struct usb_gadget *gadget,
                return -EBUSY;
 
        hsudc->driver = driver;
-       hsudc->gadget.dev.driver = &driver->driver;
 
        ret = regulator_bulk_enable(ARRAY_SIZE(hsudc->supplies),
                                    hsudc->supplies);
@@ -1190,7 +1188,6 @@ err_otg:
        regulator_bulk_disable(ARRAY_SIZE(hsudc->supplies), hsudc->supplies);
 err_supplies:
        hsudc->driver = NULL;
-       hsudc->gadget.dev.driver = NULL;
        return ret;
 }
 
@@ -1208,7 +1205,6 @@ static int s3c_hsudc_stop(struct usb_gadget *gadget,
 
        spin_lock_irqsave(&hsudc->lock, flags);
        hsudc->driver = NULL;
-       hsudc->gadget.dev.driver = NULL;
        hsudc->gadget.speed = USB_SPEED_UNKNOWN;
        s3c_hsudc_uninit_phy();
 
@@ -1303,15 +1299,10 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
 
        spin_lock_init(&hsudc->lock);
 
-       dev_set_name(&hsudc->gadget.dev, "gadget");
-
        hsudc->gadget.max_speed = USB_SPEED_HIGH;
        hsudc->gadget.ops = &s3c_hsudc_gadget_ops;
        hsudc->gadget.name = dev_name(dev);
-       hsudc->gadget.dev.parent = dev;
-       hsudc->gadget.dev.dma_mask = dev->dma_mask;
        hsudc->gadget.ep0 = &hsudc->ep[0].ep;
-
        hsudc->gadget.is_otg = 0;
        hsudc->gadget.is_a_peripheral = 0;
        hsudc->gadget.speed = USB_SPEED_UNKNOWN;
@@ -1345,12 +1336,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
        disable_irq(hsudc->irq);
        local_irq_enable();
 
-       ret = device_register(&hsudc->gadget.dev);
-       if (ret) {
-               put_device(&hsudc->gadget.dev);
-               goto err_add_device;
-       }
-
        ret = usb_add_gadget_udc(&pdev->dev, &hsudc->gadget);
        if (ret)
                goto err_add_udc;
@@ -1359,7 +1344,6 @@ static int s3c_hsudc_probe(struct platform_device *pdev)
 
        return 0;
 err_add_udc:
-       device_unregister(&hsudc->gadget.dev);
 err_add_device:
        clk_disable(hsudc->uclk);
 err_res:
index 08f89652533baa0702bf4a85429d282b56973695..d0e75e1b3ccb9323de0a29622586894710fd2679 100644 (file)
@@ -1674,7 +1674,6 @@ static int s3c2410_udc_start(struct usb_gadget *g,
 
        /* Hook the driver */
        udc->driver = driver;
-       udc->gadget.dev.driver = &driver->driver;
 
        /* Enable udc */
        s3c2410_udc_enable(udc);
@@ -1824,17 +1823,6 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
                goto err_mem;
        }
 
-       device_initialize(&udc->gadget.dev);
-       udc->gadget.dev.parent = &pdev->dev;
-       udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
-
-       /* Bind the driver */
-       retval = device_add(&udc->gadget.dev);
-       if (retval) {
-               dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval);
-               goto err_device_add;
-       }
-
        the_controller = udc;
        platform_set_drvdata(pdev, udc);
 
@@ -1923,8 +1911,6 @@ err_gpio_claim:
 err_int:
        free_irq(IRQ_USBD, udc);
 err_map:
-       device_unregister(&udc->gadget.dev);
-err_device_add:
        iounmap(base_addr);
 err_mem:
        release_mem_region(rsrc_start, rsrc_len);
@@ -1946,7 +1932,6 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
                return -EBUSY;
 
        usb_del_gadget_udc(&udc->gadget);
-       device_unregister(&udc->gadget.dev);
        debugfs_remove(udc->regs_info);
 
        if (udc_info && !udc_info->udc_command &&
index 68d7bb06ebcb83245658bbe6473892a529eb05b2..1f5f978d35d5318be56d1e069750d42e18b6b3c5 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/kernel.h>
 #include <linux/device.h>
+#include <linux/module.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 
 #define GS_LONG_NAME                   "Gadget Serial"
 #define GS_VERSION_NAME                        GS_LONG_NAME " " GS_VERSION_STR
 
-/*-------------------------------------------------------------------------*/
-
-/*
- * Kbuild is not very cooperative with respect to linking separately
- * compiled library objects into one module.  So for now we won't use
- * separate compilation ... ensuring init/exit sections work to shrink
- * the runtime footprint, and giving us at least some parts of what
- * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
- */
-#include "f_obex.c"
-#include "f_serial.c"
-
 /*-------------------------------------------------------------------------*/
 USB_GADGET_COMPOSITE_OPTIONS();
 
@@ -126,27 +115,6 @@ module_param(n_ports, uint, 0);
 MODULE_PARM_DESC(n_ports, "number of ports to create, default=1");
 
 /*-------------------------------------------------------------------------*/
-static unsigned char tty_lines[MAX_U_SERIAL_PORTS];
-
-static int __init serial_bind_obex_config(struct usb_configuration *c)
-{
-       unsigned i;
-       int status = 0;
-
-       for (i = 0; i < n_ports && status == 0; i++)
-               status = obex_bind_config(c, tty_lines[i]);
-       return status;
-}
-
-static int __init serial_bind_gser_config(struct usb_configuration *c)
-{
-       unsigned i;
-       int status = 0;
-
-       for (i = 0; i < n_ports && status == 0; i++)
-               status = gser_bind_config(c, tty_lines[i]);
-       return status;
-}
 
 static struct usb_configuration serial_config_driver = {
        /* .label = f(use_acm) */
@@ -169,15 +137,12 @@ static int serial_register_ports(struct usb_composite_dev *cdev,
                goto out;
 
        for (i = 0; i < n_ports; i++) {
-               struct f_serial_opts *opts;
 
                fi_serial[i] = usb_get_function_instance(f_name);
                if (IS_ERR(fi_serial[i])) {
                        ret = PTR_ERR(fi_serial[i]);
                        goto fail;
                }
-               opts = container_of(fi_serial[i], struct f_serial_opts, func_inst);
-               opts->port_num = tty_lines[i];
 
                f_serial[i] = usb_get_function(fi_serial[i]);
                if (IS_ERR(f_serial[i])) {
@@ -212,13 +177,6 @@ out:
 static int __init gs_bind(struct usb_composite_dev *cdev)
 {
        int                     status;
-       int                     cur_line;
-
-       for (cur_line = 0; cur_line < n_ports; cur_line++) {
-               status = gserial_alloc_line(&tty_lines[cur_line]);
-               if (status)
-                       goto fail;
-       }
 
        /* Allocate string descriptor numbers ... note that string
         * contents can be overridden by the composite_dev glue.
@@ -243,11 +201,12 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
                                "acm");
                usb_ep_autoconfig_reset(cdev->gadget);
        } else if (use_obex)
-               status = usb_add_config(cdev, &serial_config_driver,
-                               serial_bind_obex_config);
-       else
-               status = usb_add_config(cdev, &serial_config_driver,
-                               serial_bind_gser_config);
+               status = serial_register_ports(cdev, &serial_config_driver,
+                               "obex");
+       else {
+               status = serial_register_ports(cdev, &serial_config_driver,
+                               "gser");
+       }
        if (status < 0)
                goto fail;
 
@@ -257,9 +216,6 @@ static int __init gs_bind(struct usb_composite_dev *cdev)
        return 0;
 
 fail:
-       cur_line--;
-       while (cur_line >= 0)
-               gserial_free_line(tty_lines[cur_line--]);
        return status;
 }
 
@@ -270,7 +226,6 @@ static int gs_unbind(struct usb_composite_dev *cdev)
        for (i = 0; i < n_ports; i++) {
                usb_put_function(f_serial[i]);
                usb_put_function_instance(fi_serial[i]);
-               gserial_free_line(tty_lines[i]);
        }
        return 0;
 }
index a0aa721d8b216bb29350be51270a9e4c6330eaed..4b76124ce96b8dfaeab5ab0f0a89bf4f5abf15a6 100644 (file)
@@ -50,7 +50,6 @@
 
 struct eth_dev {
        /* lock is held while accessing port_usb
-        * or updating its backlink port_usb->ioport
         */
        spinlock_t              lock;
        struct gether           *port_usb;
@@ -729,8 +728,6 @@ static int get_ether_addr(const char *str, u8 *dev_addr)
        return 1;
 }
 
-static struct eth_dev *the_dev;
-
 static const struct net_device_ops eth_netdev_ops = {
        .ndo_open               = eth_open,
        .ndo_stop               = eth_stop,
@@ -758,19 +755,16 @@ static struct device_type gadget_type = {
  *
  * Returns negative errno, or zero on success
  */
-int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
+struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
                const char *netname)
 {
        struct eth_dev          *dev;
        struct net_device       *net;
        int                     status;
 
-       if (the_dev)
-               return -EBUSY;
-
        net = alloc_etherdev(sizeof *dev);
        if (!net)
-               return -ENOMEM;
+               return ERR_PTR(-ENOMEM);
 
        dev = netdev_priv(net);
        spin_lock_init(&dev->lock);
@@ -807,12 +801,11 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
        if (status < 0) {
                dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
                free_netdev(net);
+               dev = ERR_PTR(status);
        } else {
                INFO(dev, "MAC %pM\n", net->dev_addr);
                INFO(dev, "HOST MAC %pM\n", dev->host_mac);
 
-               the_dev = dev;
-
                /* two kinds of host-initiated state changes:
                 *  - iff DATA transfer is active, carrier is "on"
                 *  - tx queueing enabled if open *and* carrier is "on"
@@ -820,7 +813,7 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
                netif_carrier_off(net);
        }
 
-       return status;
+       return dev;
 }
 
 /**
@@ -829,19 +822,16 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
  *
  * This is called to free all resources allocated by @gether_setup().
  */
-void gether_cleanup(void)
+void gether_cleanup(struct eth_dev *dev)
 {
-       if (!the_dev)
+       if (!dev)
                return;
 
-       unregister_netdev(the_dev->net);
-       flush_work(&the_dev->work);
-       free_netdev(the_dev->net);
-
-       the_dev = NULL;
+       unregister_netdev(dev->net);
+       flush_work(&dev->work);
+       free_netdev(dev->net);
 }
 
-
 /**
  * gether_connect - notify network layer that USB link is active
  * @link: the USB link, set up with endpoints, descriptors matching
@@ -860,7 +850,7 @@ void gether_cleanup(void)
  */
 struct net_device *gether_connect(struct gether *link)
 {
-       struct eth_dev          *dev = the_dev;
+       struct eth_dev          *dev = link->ioport;
        int                     result = 0;
 
        if (!dev)
@@ -895,7 +885,6 @@ struct net_device *gether_connect(struct gether *link)
 
                spin_lock(&dev->lock);
                dev->port_usb = link;
-               link->ioport = dev;
                if (netif_running(dev->net)) {
                        if (link->open)
                                link->open(link);
@@ -989,6 +978,5 @@ void gether_disconnect(struct gether *link)
 
        spin_lock(&dev->lock);
        dev->port_usb = NULL;
-       link->ioport = NULL;
        spin_unlock(&dev->lock);
 }
index 6f4a1623d8545c2af122ec61e8319342eca8ae26..02522338a7081abad0f92c3506a84724f61df23b 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "gadget_chips.h"
 
+struct eth_dev;
 
 /*
  * This represents the USB side of an "ethernet" link, managed by a USB
@@ -70,7 +71,7 @@ struct gether {
                        |USB_CDC_PACKET_TYPE_DIRECTED)
 
 /* variant of gether_setup that allows customizing network device name */
-int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
+struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
                const char *netname);
 
 /* netdev setup/teardown as directed by the gadget driver */
@@ -86,12 +87,13 @@ int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN],
  *
  * Returns negative errno, or zero on success
  */
-static inline int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN])
+static inline struct eth_dev *gether_setup(struct usb_gadget *g,
+               u8 ethaddr[ETH_ALEN])
 {
        return gether_setup_name(g, ethaddr, "usb");
 }
 
-void gether_cleanup(void);
+void gether_cleanup(struct eth_dev *dev);
 
 /* connect/disconnect is handled by individual functions */
 struct net_device *gether_connect(struct gether *);
@@ -111,21 +113,24 @@ static inline bool can_support_ecm(struct usb_gadget *gadget)
 }
 
 /* each configuration may bind one instance of an ethernet link */
-int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
-int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
-int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
-int eem_bind_config(struct usb_configuration *c);
+int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+               struct eth_dev *dev);
+int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+               struct eth_dev *dev);
+int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+               struct eth_dev *dev);
+int eem_bind_config(struct usb_configuration *c, struct eth_dev *dev);
 
 #ifdef USB_ETH_RNDIS
 
 int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-                               u32 vendorID, const char *manufacturer);
+               u32 vendorID, const char *manufacturer, struct eth_dev *dev);
 
 #else
 
 static inline int
 rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
-                               u32 vendorID, const char *manufacturer)
+               u32 vendorID, const char *manufacturer, struct eth_dev *dev)
 {
        return 0;
 }
@@ -145,9 +150,9 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
  * for calling @gether_cleanup() before module unload.
  */
 static inline int rndis_bind_config(struct usb_configuration *c,
-                                   u8 ethaddr[ETH_ALEN])
+               u8 ethaddr[ETH_ALEN], struct eth_dev *dev)
 {
-       return rndis_bind_config_vendor(c, ethaddr, 0, NULL);
+       return rndis_bind_config_vendor(c, ethaddr, 0, NULL, dev);
 }
 
 
index 66ce73a0050999a1ed1c9d2a97e8b79febdc76ae..c20210c0babdb10c2aac26a8d94c0ee6f020db8e 100644 (file)
@@ -65,7 +65,6 @@ int gserial_connect(struct gserial *, u8 port_num);
 void gserial_disconnect(struct gserial *);
 
 /* functions are bound to configurations by a config or gadget driver */
-int acm_bind_config(struct usb_configuration *c, u8 port_num);
 int gser_bind_config(struct usb_configuration *c, u8 port_num);
 int obex_bind_config(struct usb_configuration *c, u8 port_num);
 
index f8f62c3ed65e7a468b97f7348aac97ea133bbcf1..ffd8fa5411015f823bc5701777e20cd928848f56 100644 (file)
@@ -101,6 +101,16 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
 
 /* ------------------------------------------------------------------------- */
 
+void usb_gadget_set_state(struct usb_gadget *gadget,
+               enum usb_device_state state)
+{
+       gadget->state = state;
+       sysfs_notify(&gadget->dev.kobj, NULL, "status");
+}
+EXPORT_SYMBOL_GPL(usb_gadget_set_state);
+
+/* ------------------------------------------------------------------------- */
+
 /**
  * usb_gadget_udc_start - tells usb device controller to start up
  * @gadget: The gadget we want to get started
@@ -156,15 +166,23 @@ static void usb_udc_release(struct device *dev)
 }
 
 static const struct attribute_group *usb_udc_attr_groups[];
+
+static void usb_udc_nop_release(struct device *dev)
+{
+       dev_vdbg(dev, "%s\n", __func__);
+}
+
 /**
- * usb_add_gadget_udc - adds a new gadget to the udc class driver list
- * @parent: the parent device to this udc. Usually the controller
- * driver's device.
- * @gadget: the gadget to be added to the list
+ * usb_add_gadget_udc_release - adds a new gadget to the udc class driver list
+ * @parent: the parent device to this udc. Usually the controller driver's
+ * device.
+ * @gadget: the gadget to be added to the list.
+ * @release: a gadget release function.
  *
  * Returns zero on success, negative errno otherwise.
  */
-int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
+int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
+               void (*release)(struct device *dev))
 {
        struct usb_udc          *udc;
        int                     ret = -ENOMEM;
@@ -173,6 +191,22 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
        if (!udc)
                goto err1;
 
+       dev_set_name(&gadget->dev, "gadget");
+       gadget->dev.parent = parent;
+
+       dma_set_coherent_mask(&gadget->dev, parent->coherent_dma_mask);
+       gadget->dev.dma_parms = parent->dma_parms;
+       gadget->dev.dma_mask = parent->dma_mask;
+
+       if (release)
+               gadget->dev.release = release;
+       else
+               gadget->dev.release = usb_udc_nop_release;
+
+       ret = device_register(&gadget->dev);
+       if (ret)
+               goto err2;
+
        device_initialize(&udc->dev);
        udc->dev.release = usb_udc_release;
        udc->dev.class = udc_class;
@@ -180,7 +214,7 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
        udc->dev.parent = parent;
        ret = dev_set_name(&udc->dev, "%s", kobject_name(&parent->kobj));
        if (ret)
-               goto err2;
+               goto err3;
 
        udc->gadget = gadget;
 
@@ -189,21 +223,42 @@ int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
 
        ret = device_add(&udc->dev);
        if (ret)
-               goto err3;
+               goto err4;
+
+       usb_gadget_set_state(gadget, USB_STATE_NOTATTACHED);
 
        mutex_unlock(&udc_lock);
 
        return 0;
-err3:
+
+err4:
        list_del(&udc->list);
        mutex_unlock(&udc_lock);
 
-err2:
+err3:
        put_device(&udc->dev);
 
+err2:
+       put_device(&gadget->dev);
+       kfree(udc);
+
 err1:
        return ret;
 }
+EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release);
+
+/**
+ * usb_add_gadget_udc - adds a new gadget to the udc class driver list
+ * @parent: the parent device to this udc. Usually the controller
+ * driver's device.
+ * @gadget: the gadget to be added to the list
+ *
+ * Returns zero on success, negative errno otherwise.
+ */
+int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget)
+{
+       return usb_add_gadget_udc_release(parent, gadget, NULL);
+}
 EXPORT_SYMBOL_GPL(usb_add_gadget_udc);
 
 static void usb_gadget_remove_driver(struct usb_udc *udc)
@@ -220,6 +275,7 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
 
        udc->driver = NULL;
        udc->dev.driver = NULL;
+       udc->gadget->dev.driver = NULL;
 }
 
 /**
@@ -254,6 +310,7 @@ found:
 
        kobject_uevent(&udc->dev.kobj, KOBJ_REMOVE);
        device_unregister(&udc->dev);
+       device_unregister(&gadget->dev);
 }
 EXPORT_SYMBOL_GPL(usb_del_gadget_udc);
 
@@ -268,6 +325,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri
 
        udc->driver = driver;
        udc->dev.driver = &driver->driver;
+       udc->gadget->dev.driver = &driver->driver;
 
        ret = driver->bind(udc->gadget, driver);
        if (ret)
@@ -286,6 +344,7 @@ err1:
                        udc->driver->function, ret);
        udc->driver = NULL;
        udc->dev.driver = NULL;
+       udc->gadget->dev.driver = NULL;
        return ret;
 }
 
@@ -395,6 +454,16 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
 }
 static DEVICE_ATTR(soft_connect, S_IWUSR, NULL, usb_udc_softconn_store);
 
+static ssize_t usb_gadget_state_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       struct usb_udc          *udc = container_of(dev, struct usb_udc, dev);
+       struct usb_gadget       *gadget = udc->gadget;
+
+       return sprintf(buf, "%s\n", usb_state_string(gadget->state));
+}
+static DEVICE_ATTR(state, S_IRUGO, usb_gadget_state_show, NULL);
+
 #define USB_UDC_SPEED_ATTR(name, param)                                        \
 ssize_t usb_udc_##param##_show(struct device *dev,                     \
                struct device_attribute *attr, char *buf)               \
@@ -403,7 +472,7 @@ ssize_t usb_udc_##param##_show(struct device *dev,                  \
        return snprintf(buf, PAGE_SIZE, "%s\n",                         \
                        usb_speed_string(udc->gadget->param));          \
 }                                                                      \
-static DEVICE_ATTR(name, S_IRUSR, usb_udc_##param##_show, NULL)
+static DEVICE_ATTR(name, S_IRUGO, usb_udc_##param##_show, NULL)
 
 static USB_UDC_SPEED_ATTR(current_speed, speed);
 static USB_UDC_SPEED_ATTR(maximum_speed, max_speed);
@@ -428,6 +497,7 @@ static USB_UDC_ATTR(a_alt_hnp_support);
 static struct attribute *usb_udc_attrs[] = {
        &dev_attr_srp.attr,
        &dev_attr_soft_connect.attr,
+       &dev_attr_state.attr,
        &dev_attr_current_speed.attr,
        &dev_attr_maximum_speed.attr,
 
index 93b0c11911150a8b42a2c46915d273626f9aec85..817e9e19cecf75c34253f0ebbb75d7e9282e383a 100644 (file)
@@ -98,8 +98,6 @@ extern unsigned int uvc_gadget_trace_param;
 #define DRIVER_VERSION                         "0.1.0"
 #define DRIVER_VERSION_NUMBER                  KERNEL_VERSION(0, 1, 0)
 
-#define DMA_ADDR_INVALID                       (~(dma_addr_t)0)
-
 #define UVC_NUM_REQUESTS                       4
 #define UVC_MAX_REQUEST_SIZE                   64
 #define UVC_MAX_EVENTS                         4
@@ -190,6 +188,7 @@ struct uvc_file_handle
  * Functions
  */
 
+extern void uvc_function_setup_continue(struct uvc_device *uvc);
 extern void uvc_endpoint_stream(struct uvc_device *dev);
 
 extern void uvc_function_connect(struct uvc_device *uvc);
index 104ae9c812519ed9981afc5cd83cde655bc7c300..7ce27e35550b7e50c887764b53f6907e4fc5864d 100644 (file)
@@ -10,6 +10,7 @@
  *     (at your option) any later version.
  */
 
+#include <linux/atomic.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/list.h>
@@ -18,7 +19,8 @@
 #include <linux/videodev2.h>
 #include <linux/vmalloc.h>
 #include <linux/wait.h>
-#include <linux/atomic.h>
+
+#include <media/videobuf2-vmalloc.h>
 
 #include "uvc.h"
 
  * Video queues is initialized by uvc_queue_init(). The function performs
  * basic initialization of the uvc_video_queue struct and never fails.
  *
- * Video buffer allocation and freeing are performed by uvc_alloc_buffers and
- * uvc_free_buffers respectively. The former acquires the video queue lock,
- * while the later must be called with the lock held (so that allocation can
- * free previously allocated buffers). Trying to free buffers that are mapped
- * to user space will return -EBUSY.
- *
- * Video buffers are managed using two queues. However, unlike most USB video
- * drivers that use an in queue and an out queue, we use a main queue to hold
- * all queued buffers (both 'empty' and 'done' buffers), and an irq queue to
- * hold empty buffers. This design (copied from video-buf) minimizes locking
- * in interrupt, as only one queue is shared between interrupt and user
- * contexts.
- *
- * Use cases
- * ---------
- *
- * Unless stated otherwise, all operations that modify the irq buffers queue
- * are protected by the irq spinlock.
- *
- * 1. The user queues the buffers, starts streaming and dequeues a buffer.
- *
- *    The buffers are added to the main and irq queues. Both operations are
- *    protected by the queue lock, and the later is protected by the irq
- *    spinlock as well.
- *
- *    The completion handler fetches a buffer from the irq queue and fills it
- *    with video data. If no buffer is available (irq queue empty), the handler
- *    returns immediately.
- *
- *    When the buffer is full, the completion handler removes it from the irq
- *    queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue.
- *    At that point, any process waiting on the buffer will be woken up. If a
- *    process tries to dequeue a buffer after it has been marked ready, the
- *    dequeing will succeed immediately.
- *
- * 2. Buffers are queued, user is waiting on a buffer and the device gets
- *    disconnected.
- *
- *    When the device is disconnected, the kernel calls the completion handler
- *    with an appropriate status code. The handler marks all buffers in the
- *    irq queue as being erroneous (UVC_BUF_STATE_ERROR) and wakes them up so
- *    that any process waiting on a buffer gets woken up.
- *
- *    Waking up up the first buffer on the irq list is not enough, as the
- *    process waiting on the buffer might restart the dequeue operation
- *    immediately.
- *
+ * Video buffers are managed by videobuf2. The driver uses a mutex to protect
+ * the videobuf2 queue operations by serializing calls to videobuf2 and a
+ * spinlock to protect the IRQ queue that holds the buffers to be processed by
+ * the driver.
  */
 
-static void
-uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
-{
-       mutex_init(&queue->mutex);
-       spin_lock_init(&queue->irqlock);
-       INIT_LIST_HEAD(&queue->mainqueue);
-       INIT_LIST_HEAD(&queue->irqqueue);
-       queue->type = type;
-}
-
-/*
- * Free the video buffers.
- *
- * This function must be called with the queue lock held.
+/* -----------------------------------------------------------------------------
+ * videobuf2 queue operations
  */
-static int uvc_free_buffers(struct uvc_video_queue *queue)
+
+static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+                          unsigned int *nbuffers, unsigned int *nplanes,
+                          unsigned int sizes[], void *alloc_ctxs[])
 {
-       unsigned int i;
+       struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
+       struct uvc_video *video = container_of(queue, struct uvc_video, queue);
 
-       for (i = 0; i < queue->count; ++i) {
-               if (queue->buffer[i].vma_use_count != 0)
-                       return -EBUSY;
-       }
+       if (*nbuffers > UVC_MAX_VIDEO_BUFFERS)
+               *nbuffers = UVC_MAX_VIDEO_BUFFERS;
 
-       if (queue->count) {
-               vfree(queue->mem);
-               queue->count = 0;
-       }
+       *nplanes = 1;
+
+       sizes[0] = video->imagesize;
 
        return 0;
 }
 
-/*
- * Allocate the video buffers.
- *
- * Pages are reserved to make sure they will not be swapped, as they will be
- * filled in the URB completion handler.
- *
- * Buffers will be individually mapped, so they must all be page aligned.
- */
-static int
-uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
-                 unsigned int buflength)
+static int uvc_buffer_prepare(struct vb2_buffer *vb)
 {
-       unsigned int bufsize = PAGE_ALIGN(buflength);
-       unsigned int i;
-       void *mem = NULL;
-       int ret;
+       struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+       struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
 
-       if (nbuffers > UVC_MAX_VIDEO_BUFFERS)
-               nbuffers = UVC_MAX_VIDEO_BUFFERS;
+       if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+           vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
+               uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
+               return -EINVAL;
+       }
 
-       mutex_lock(&queue->mutex);
+       if (unlikely(queue->flags & UVC_QUEUE_DISCONNECTED))
+               return -ENODEV;
 
-       if ((ret = uvc_free_buffers(queue)) < 0)
-               goto done;
+       buf->state = UVC_BUF_STATE_QUEUED;
+       buf->mem = vb2_plane_vaddr(vb, 0);
+       buf->length = vb2_plane_size(vb, 0);
+       if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               buf->bytesused = 0;
+       else
+               buf->bytesused = vb2_get_plane_payload(vb, 0);
 
-       /* Bail out if no buffers should be allocated. */
-       if (nbuffers == 0)
-               goto done;
+       return 0;
+}
 
-       /* Decrement the number of buffers until allocation succeeds. */
-       for (; nbuffers > 0; --nbuffers) {
-               mem = vmalloc_32(nbuffers * bufsize);
-               if (mem != NULL)
-                       break;
-       }
+static void uvc_buffer_queue(struct vb2_buffer *vb)
+{
+       struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+       struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
+       unsigned long flags;
 
-       if (mem == NULL) {
-               ret = -ENOMEM;
-               goto done;
-       }
+       spin_lock_irqsave(&queue->irqlock, flags);
 
-       for (i = 0; i < nbuffers; ++i) {
-               memset(&queue->buffer[i], 0, sizeof queue->buffer[i]);
-               queue->buffer[i].buf.index = i;
-               queue->buffer[i].buf.m.offset = i * bufsize;
-               queue->buffer[i].buf.length = buflength;
-               queue->buffer[i].buf.type = queue->type;
-               queue->buffer[i].buf.sequence = 0;
-               queue->buffer[i].buf.field = V4L2_FIELD_NONE;
-               queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP;
-               queue->buffer[i].buf.flags = 0;
-               init_waitqueue_head(&queue->buffer[i].wait);
+       if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) {
+               list_add_tail(&buf->queue, &queue->irqqueue);
+       } else {
+               /* If the device is disconnected return the buffer to userspace
+                * directly. The next QBUF call will fail with -ENODEV.
+                */
+               buf->state = UVC_BUF_STATE_ERROR;
+               vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
        }
 
-       queue->mem = mem;
-       queue->count = nbuffers;
-       queue->buf_size = bufsize;
-       ret = nbuffers;
-
-done:
-       mutex_unlock(&queue->mutex);
-       return ret;
+       spin_unlock_irqrestore(&queue->irqlock, flags);
 }
 
-static void __uvc_query_buffer(struct uvc_buffer *buf,
-               struct v4l2_buffer *v4l2_buf)
-{
-       memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf);
-
-       if (buf->vma_use_count)
-               v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED;
-
-       switch (buf->state) {
-       case UVC_BUF_STATE_ERROR:
-       case UVC_BUF_STATE_DONE:
-               v4l2_buf->flags |= V4L2_BUF_FLAG_DONE;
-               break;
-       case UVC_BUF_STATE_QUEUED:
-       case UVC_BUF_STATE_ACTIVE:
-               v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
-               break;
-       case UVC_BUF_STATE_IDLE:
-       default:
-               break;
-       }
-}
+static struct vb2_ops uvc_queue_qops = {
+       .queue_setup = uvc_queue_setup,
+       .buf_prepare = uvc_buffer_prepare,
+       .buf_queue = uvc_buffer_queue,
+};
 
-static int
-uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
+static int uvc_queue_init(struct uvc_video_queue *queue,
+                         enum v4l2_buf_type type)
 {
-       int ret = 0;
+       int ret;
 
-       mutex_lock(&queue->mutex);
-       if (v4l2_buf->index >= queue->count) {
-               ret = -EINVAL;
-               goto done;
-       }
+       queue->queue.type = type;
+       queue->queue.io_modes = VB2_MMAP | VB2_USERPTR;
+       queue->queue.drv_priv = queue;
+       queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
+       queue->queue.ops = &uvc_queue_qops;
+       queue->queue.mem_ops = &vb2_vmalloc_memops;
+       ret = vb2_queue_init(&queue->queue);
+       if (ret)
+               return ret;
+
+       mutex_init(&queue->mutex);
+       spin_lock_init(&queue->irqlock);
+       INIT_LIST_HEAD(&queue->irqqueue);
+       queue->flags = 0;
 
-       __uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf);
+       return 0;
+}
 
-done:
+/*
+ * Free the video buffers.
+ */
+static void uvc_free_buffers(struct uvc_video_queue *queue)
+{
+       mutex_lock(&queue->mutex);
+       vb2_queue_release(&queue->queue);
        mutex_unlock(&queue->mutex);
-       return ret;
 }
 
 /*
- * Queue a video buffer. Attempting to queue a buffer that has already been
- * queued will return -EINVAL.
+ * Allocate the video buffers.
  */
-static int
-uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
+static int uvc_alloc_buffers(struct uvc_video_queue *queue,
+                            struct v4l2_requestbuffers *rb)
 {
-       struct uvc_buffer *buf;
-       unsigned long flags;
-       int ret = 0;
+       int ret;
 
-       uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index);
+       mutex_lock(&queue->mutex);
+       ret = vb2_reqbufs(&queue->queue, rb);
+       mutex_unlock(&queue->mutex);
 
-       if (v4l2_buf->type != queue->type ||
-           v4l2_buf->memory != V4L2_MEMORY_MMAP) {
-               uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
-                       "and/or memory (%u).\n", v4l2_buf->type,
-                       v4l2_buf->memory);
-               return -EINVAL;
-       }
+       return ret ? ret : rb->count;
+}
 
-       mutex_lock(&queue->mutex);
-       if (v4l2_buf->index >= queue->count) {
-               uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n");
-               ret = -EINVAL;
-               goto done;
-       }
+static int uvc_query_buffer(struct uvc_video_queue *queue,
+                           struct v4l2_buffer *buf)
+{
+       int ret;
 
-       buf = &queue->buffer[v4l2_buf->index];
-       if (buf->state != UVC_BUF_STATE_IDLE) {
-               uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state "
-                       "(%u).\n", buf->state);
-               ret = -EINVAL;
-               goto done;
-       }
+       mutex_lock(&queue->mutex);
+       ret = vb2_querybuf(&queue->queue, buf);
+       mutex_unlock(&queue->mutex);
 
-       if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-           v4l2_buf->bytesused > buf->buf.length) {
-               uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
-               ret = -EINVAL;
-               goto done;
-       }
+       return ret;
+}
 
-       if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-               buf->buf.bytesused = 0;
-       else
-               buf->buf.bytesused = v4l2_buf->bytesused;
+static int uvc_queue_buffer(struct uvc_video_queue *queue,
+                           struct v4l2_buffer *buf)
+{
+       unsigned long flags;
+       int ret;
 
+       mutex_lock(&queue->mutex);
+       ret = vb2_qbuf(&queue->queue, buf);
        spin_lock_irqsave(&queue->irqlock, flags);
-       if (queue->flags & UVC_QUEUE_DISCONNECTED) {
-               spin_unlock_irqrestore(&queue->irqlock, flags);
-               ret = -ENODEV;
-               goto done;
-       }
-       buf->state = UVC_BUF_STATE_QUEUED;
-
        ret = (queue->flags & UVC_QUEUE_PAUSED) != 0;
        queue->flags &= ~UVC_QUEUE_PAUSED;
-
-       list_add_tail(&buf->stream, &queue->mainqueue);
-       list_add_tail(&buf->queue, &queue->irqqueue);
        spin_unlock_irqrestore(&queue->irqlock, flags);
-
-done:
        mutex_unlock(&queue->mutex);
-       return ret;
-}
 
-static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking)
-{
-       if (nonblocking) {
-               return (buf->state != UVC_BUF_STATE_QUEUED &&
-                       buf->state != UVC_BUF_STATE_ACTIVE)
-                       ? 0 : -EAGAIN;
-       }
-
-       return wait_event_interruptible(buf->wait,
-               buf->state != UVC_BUF_STATE_QUEUED &&
-               buf->state != UVC_BUF_STATE_ACTIVE);
+       return ret;
 }
 
 /*
  * Dequeue a video buffer. If nonblocking is false, block until a buffer is
  * available.
  */
-static int
-uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf,
-                  int nonblocking)
+static int uvc_dequeue_buffer(struct uvc_video_queue *queue,
+                             struct v4l2_buffer *buf, int nonblocking)
 {
-       struct uvc_buffer *buf;
-       int ret = 0;
-
-       if (v4l2_buf->type != queue->type ||
-           v4l2_buf->memory != V4L2_MEMORY_MMAP) {
-               uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
-                       "and/or memory (%u).\n", v4l2_buf->type,
-                       v4l2_buf->memory);
-               return -EINVAL;
-       }
+       int ret;
 
        mutex_lock(&queue->mutex);
-       if (list_empty(&queue->mainqueue)) {
-               uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n");
-               ret = -EINVAL;
-               goto done;
-       }
-
-       buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
-       if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0)
-               goto done;
-
-       uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n",
-               buf->buf.index, buf->state, buf->buf.bytesused);
-
-       switch (buf->state) {
-       case UVC_BUF_STATE_ERROR:
-               uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data "
-                       "(transmission error).\n");
-               ret = -EIO;
-       case UVC_BUF_STATE_DONE:
-               buf->state = UVC_BUF_STATE_IDLE;
-               break;
-
-       case UVC_BUF_STATE_IDLE:
-       case UVC_BUF_STATE_QUEUED:
-       case UVC_BUF_STATE_ACTIVE:
-       default:
-               uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u "
-                       "(driver bug?).\n", buf->state);
-               ret = -EINVAL;
-               goto done;
-       }
-
-       list_del(&buf->stream);
-       __uvc_query_buffer(buf, v4l2_buf);
-
-done:
+       ret = vb2_dqbuf(&queue->queue, buf, nonblocking);
        mutex_unlock(&queue->mutex);
+
        return ret;
 }
 
@@ -361,105 +208,47 @@ done:
  * This function implements video queue polling and is intended to be used by
  * the device poll handler.
  */
-static unsigned int
-uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
-              poll_table *wait)
+static unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
+                                  struct file *file, poll_table *wait)
 {
-       struct uvc_buffer *buf;
-       unsigned int mask = 0;
+       unsigned int ret;
 
        mutex_lock(&queue->mutex);
-       if (list_empty(&queue->mainqueue))
-               goto done;
-
-       buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
-
-       poll_wait(file, &buf->wait, wait);
-       if (buf->state == UVC_BUF_STATE_DONE ||
-           buf->state == UVC_BUF_STATE_ERROR)
-               mask |= POLLOUT | POLLWRNORM;
-
-done:
+       ret = vb2_poll(&queue->queue, file, wait);
        mutex_unlock(&queue->mutex);
-       return mask;
-}
 
-/*
- * VMA operations.
- */
-static void uvc_vm_open(struct vm_area_struct *vma)
-{
-       struct uvc_buffer *buffer = vma->vm_private_data;
-       buffer->vma_use_count++;
+       return ret;
 }
 
-static void uvc_vm_close(struct vm_area_struct *vma)
+static int uvc_queue_mmap(struct uvc_video_queue *queue,
+                         struct vm_area_struct *vma)
 {
-       struct uvc_buffer *buffer = vma->vm_private_data;
-       buffer->vma_use_count--;
-}
+       int ret;
 
-static struct vm_operations_struct uvc_vm_ops = {
-       .open           = uvc_vm_open,
-       .close          = uvc_vm_close,
-};
+       mutex_lock(&queue->mutex);
+       ret = vb2_mmap(&queue->queue, vma);
+       mutex_unlock(&queue->mutex);
+
+       return ret;
+}
 
+#ifndef CONFIG_MMU
 /*
- * Memory-map a buffer.
+ * Get unmapped area.
  *
- * This function implements video buffer memory mapping and is intended to be
- * used by the device mmap handler.
+ * NO-MMU arch need this function to make mmap() work correctly.
  */
-static int
-uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
+static unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue,
+               unsigned long pgoff)
 {
-       struct uvc_buffer *uninitialized_var(buffer);
-       struct page *page;
-       unsigned long addr, start, size;
-       unsigned int i;
-       int ret = 0;
-
-       start = vma->vm_start;
-       size = vma->vm_end - vma->vm_start;
+       unsigned long ret;
 
        mutex_lock(&queue->mutex);
-
-       for (i = 0; i < queue->count; ++i) {
-               buffer = &queue->buffer[i];
-               if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
-                       break;
-       }
-
-       if (i == queue->count || size != queue->buf_size) {
-               ret = -EINVAL;
-               goto done;
-       }
-
-       /*
-        * VM_IO marks the area as being an mmaped region for I/O to a
-        * device. It also prevents the region from being core dumped.
-        */
-       vma->vm_flags |= VM_IO;
-
-       addr = (unsigned long)queue->mem + buffer->buf.m.offset;
-       while (size > 0) {
-               page = vmalloc_to_page((void *)addr);
-               if ((ret = vm_insert_page(vma, start, page)) < 0)
-                       goto done;
-
-               start += PAGE_SIZE;
-               addr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-
-       vma->vm_ops = &uvc_vm_ops;
-       vma->vm_private_data = buffer;
-       uvc_vm_open(vma);
-
-done:
+       ret = vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0);
        mutex_unlock(&queue->mutex);
        return ret;
 }
+#endif
 
 /*
  * Cancel the video buffers queue.
@@ -484,7 +273,7 @@ static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
                                       queue);
                list_del(&buf->queue);
                buf->state = UVC_BUF_STATE_ERROR;
-               wake_up(&buf->wait);
+               vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
        }
        /* This must be protected by the irqlock spinlock to avoid race
         * conditions between uvc_queue_buffer and the disconnection event that
@@ -516,26 +305,33 @@ static void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
  */
 static int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
 {
-       unsigned int i;
+       unsigned long flags;
        int ret = 0;
 
        mutex_lock(&queue->mutex);
        if (enable) {
-               if (uvc_queue_streaming(queue)) {
-                       ret = -EBUSY;
+               ret = vb2_streamon(&queue->queue, queue->queue.type);
+               if (ret < 0)
                        goto done;
-               }
+
                queue->sequence = 0;
-               queue->flags |= UVC_QUEUE_STREAMING;
                queue->buf_used = 0;
        } else {
-               uvc_queue_cancel(queue, 0);
-               INIT_LIST_HEAD(&queue->mainqueue);
+               ret = vb2_streamoff(&queue->queue, queue->queue.type);
+               if (ret < 0)
+                       goto done;
 
-               for (i = 0; i < queue->count; ++i)
-                       queue->buffer[i].state = UVC_BUF_STATE_IDLE;
+               spin_lock_irqsave(&queue->irqlock, flags);
+               INIT_LIST_HEAD(&queue->irqqueue);
 
-               queue->flags &= ~UVC_QUEUE_STREAMING;
+               /*
+                * FIXME: We need to clear the DISCONNECTED flag to ensure that
+                * applications will be able to queue buffers for the next
+                * streaming run. However, clearing it here doesn't guarantee
+                * that the device will be reconnected in the meantime.
+                */
+               queue->flags &= ~UVC_QUEUE_DISCONNECTED;
+               spin_unlock_irqrestore(&queue->irqlock, flags);
        }
 
 done:
@@ -544,15 +340,15 @@ done:
 }
 
 /* called with &queue_irqlock held.. */
-static struct uvc_buffer *
-uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
+static struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
+                                               struct uvc_buffer *buf)
 {
        struct uvc_buffer *nextbuf;
 
        if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
-           buf->buf.length != buf->buf.bytesused) {
+            buf->length != buf->bytesused) {
                buf->state = UVC_BUF_STATE_QUEUED;
-               buf->buf.bytesused = 0;
+               vb2_set_plane_payload(&buf->buf, 0, 0);
                return buf;
        }
 
@@ -563,10 +359,18 @@ uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
        else
                nextbuf = NULL;
 
-       buf->buf.sequence = queue->sequence++;
-       do_gettimeofday(&buf->buf.timestamp);
+       /*
+        * FIXME: with videobuf2, the sequence number or timestamp fields
+        * are valid only for video capture devices and the UVC gadget usually
+        * is a video output device. Keeping these until the specs are clear on
+        * this aspect.
+        */
+       buf->buf.v4l2_buf.sequence = queue->sequence++;
+       do_gettimeofday(&buf->buf.v4l2_buf.timestamp);
+
+       vb2_set_plane_payload(&buf->buf, 0, buf->bytesused);
+       vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
 
-       wake_up(&buf->wait);
        return nextbuf;
 }
 
index 1812a8ecc5d0d567cbb48c39c69c0b21ca5efb80..8e76ce982f1eadb525b2045e8c7549c6255a723d 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/kernel.h>
 #include <linux/poll.h>
 #include <linux/videodev2.h>
+#include <media/videobuf2-core.h>
 
 /* Maximum frame size in bytes, for sanity checking. */
 #define UVC_MAX_FRAME_SIZE     (16*1024*1024)
@@ -25,42 +26,35 @@ enum uvc_buffer_state {
 };
 
 struct uvc_buffer {
-       unsigned long vma_use_count;
-       struct list_head stream;
-
-       /* Touched by interrupt handler. */
-       struct v4l2_buffer buf;
+       struct vb2_buffer buf;
        struct list_head queue;
-       wait_queue_head_t wait;
+
        enum uvc_buffer_state state;
+       void *mem;
+       unsigned int length;
+       unsigned int bytesused;
 };
 
-#define UVC_QUEUE_STREAMING            (1 << 0)
-#define UVC_QUEUE_DISCONNECTED         (1 << 1)
-#define UVC_QUEUE_DROP_INCOMPLETE      (1 << 2)
-#define UVC_QUEUE_PAUSED               (1 << 3)
+#define UVC_QUEUE_DISCONNECTED         (1 << 0)
+#define UVC_QUEUE_DROP_INCOMPLETE      (1 << 1)
+#define UVC_QUEUE_PAUSED               (1 << 2)
 
 struct uvc_video_queue {
-       enum v4l2_buf_type type;
+       struct vb2_queue queue;
+       struct mutex mutex;     /* Protects queue */
 
-       void *mem;
        unsigned int flags;
        __u32 sequence;
 
-       unsigned int count;
-       unsigned int buf_size;
        unsigned int buf_used;
-       struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS];
-       struct mutex mutex;     /* protects buffers and mainqueue */
-       spinlock_t irqlock;     /* protects irqqueue */
 
-       struct list_head mainqueue;
+       spinlock_t irqlock;     /* Protects flags and irqqueue */
        struct list_head irqqueue;
 };
 
 static inline int uvc_queue_streaming(struct uvc_video_queue *queue)
 {
-       return queue->flags & UVC_QUEUE_STREAMING;
+       return vb2_is_streaming(&queue->queue);
 }
 
 #endif /* __KERNEL__ */
index 2ca9386d655bc69fa5b02f55b14e5bcae3b0d4ad..ad48e81155e2c0c838f0092e2da671a7bdaddf5f 100644 (file)
@@ -41,9 +41,8 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)
 
        req->length = min_t(unsigned int, uvc->event_length, data->length);
        req->zero = data->length < uvc->event_length;
-       req->dma = DMA_ADDR_INVALID;
 
-       memcpy(req->buf, data->data, data->length);
+       memcpy(req->buf, data->data, req->length);
 
        return usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL);
 }
@@ -148,16 +147,13 @@ uvc_v4l2_release(struct file *file)
        uvc_function_disconnect(uvc);
 
        uvc_video_enable(video, 0);
-       mutex_lock(&video->queue.mutex);
-       if (uvc_free_buffers(&video->queue) < 0)
-               printk(KERN_ERR "uvc_v4l2_release: Unable to free "
-                               "buffers.\n");
-       mutex_unlock(&video->queue.mutex);
+       uvc_free_buffers(&video->queue);
 
        file->private_data = NULL;
        v4l2_fh_del(&handle->vfh);
        v4l2_fh_exit(&handle->vfh);
        kfree(handle);
+
        return 0;
 }
 
@@ -178,9 +174,9 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                struct v4l2_capability *cap = arg;
 
                memset(cap, 0, sizeof *cap);
-               strncpy(cap->driver, "g_uvc", sizeof(cap->driver));
-               strncpy(cap->card, cdev->gadget->name, sizeof(cap->card));
-               strncpy(cap->bus_info, dev_name(&cdev->gadget->dev),
+               strlcpy(cap->driver, "g_uvc", sizeof(cap->driver));
+               strlcpy(cap->card, cdev->gadget->name, sizeof(cap->card));
+               strlcpy(cap->bus_info, dev_name(&cdev->gadget->dev),
                        sizeof cap->bus_info);
                cap->version = DRIVER_VERSION_NUMBER;
                cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
@@ -192,7 +188,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        {
                struct v4l2_format *fmt = arg;
 
-               if (fmt->type != video->queue.type)
+               if (fmt->type != video->queue.queue.type)
                        return -EINVAL;
 
                return uvc_v4l2_get_format(video, fmt);
@@ -202,7 +198,7 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        {
                struct v4l2_format *fmt = arg;
 
-               if (fmt->type != video->queue.type)
+               if (fmt->type != video->queue.queue.type)
                        return -EINVAL;
 
                return uvc_v4l2_set_format(video, fmt);
@@ -213,16 +209,13 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        {
                struct v4l2_requestbuffers *rb = arg;
 
-               if (rb->type != video->queue.type ||
-                   rb->memory != V4L2_MEMORY_MMAP)
+               if (rb->type != video->queue.queue.type)
                        return -EINVAL;
 
-               ret = uvc_alloc_buffers(&video->queue, rb->count,
-                                       video->imagesize);
+               ret = uvc_alloc_buffers(&video->queue, rb);
                if (ret < 0)
                        return ret;
 
-               rb->count = ret;
                ret = 0;
                break;
        }
@@ -231,9 +224,6 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        {
                struct v4l2_buffer *buf = arg;
 
-               if (buf->type != video->queue.type)
-                       return -EINVAL;
-
                return uvc_query_buffer(&video->queue, buf);
        }
 
@@ -251,24 +241,36 @@ uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        {
                int *type = arg;
 
-               if (*type != video->queue.type)
+               if (*type != video->queue.queue.type)
                        return -EINVAL;
 
-               return uvc_video_enable(video, 1);
+               /* Enable UVC video. */
+               ret = uvc_video_enable(video, 1);
+               if (ret < 0)
+                       return ret;
+
+               /*
+                * Complete the alternate setting selection setup phase now that
+                * userspace is ready to provide video frames.
+                */
+               uvc_function_setup_continue(uvc);
+               uvc->state = UVC_STATE_STREAMING;
+
+               return 0;
        }
 
        case VIDIOC_STREAMOFF:
        {
                int *type = arg;
 
-               if (*type != video->queue.type)
+               if (*type != video->queue.queue.type)
                        return -EINVAL;
 
                return uvc_video_enable(video, 0);
        }
 
        /* Events */
-        case VIDIOC_DQEVENT:
+       case VIDIOC_DQEVENT:
        {
                struct v4l2_event *event = arg;
 
@@ -333,17 +335,21 @@ uvc_v4l2_poll(struct file *file, poll_table *wait)
 {
        struct video_device *vdev = video_devdata(file);
        struct uvc_device *uvc = video_get_drvdata(vdev);
-       struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
-       unsigned int mask = 0;
 
-       poll_wait(file, &handle->vfh.wait, wait);
-       if (v4l2_event_pending(&handle->vfh))
-               mask |= POLLPRI;
+       return uvc_queue_poll(&uvc->video.queue, file, wait);
+}
 
-       mask |= uvc_queue_poll(&uvc->video.queue, file, wait);
+#ifndef CONFIG_MMU
+static unsigned long uvc_v4l2_get_unmapped_area(struct file *file,
+               unsigned long addr, unsigned long len, unsigned long pgoff,
+               unsigned long flags)
+{
+       struct video_device *vdev = video_devdata(file);
+       struct uvc_device *uvc = video_get_drvdata(vdev);
 
-       return mask;
+       return uvc_queue_get_unmapped_area(&uvc->video.queue, pgoff);
 }
+#endif
 
 static struct v4l2_file_operations uvc_v4l2_fops = {
        .owner          = THIS_MODULE,
@@ -352,5 +358,8 @@ static struct v4l2_file_operations uvc_v4l2_fops = {
        .ioctl          = uvc_v4l2_ioctl,
        .mmap           = uvc_v4l2_mmap,
        .poll           = uvc_v4l2_poll,
+#ifndef CONFIG_MMU
+       .get_unmapped_area = uvc_v4l2_get_unmapped_area,
+#endif
 };
 
index b0e53a8ea4f7a68ea1156e2446dfbda401bcd1d2..71e896d4c5ae481d189e582609d8cb456a8187c3 100644 (file)
@@ -32,7 +32,7 @@ uvc_video_encode_header(struct uvc_video *video, struct uvc_buffer *buf,
        data[0] = 2;
        data[1] = UVC_STREAM_EOH | video->fid;
 
-       if (buf->buf.bytesused - video->queue.buf_used <= len - 2)
+       if (buf->bytesused - video->queue.buf_used <= len - 2)
                data[1] |= UVC_STREAM_EOF;
 
        return 2;
@@ -47,8 +47,8 @@ uvc_video_encode_data(struct uvc_video *video, struct uvc_buffer *buf,
        void *mem;
 
        /* Copy video data to the USB buffer. */
-       mem = queue->mem + buf->buf.m.offset + queue->buf_used;
-       nbytes = min((unsigned int)len, buf->buf.bytesused - queue->buf_used);
+       mem = buf->mem + queue->buf_used;
+       nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used);
 
        memcpy(data, mem, nbytes);
        queue->buf_used += nbytes;
@@ -82,7 +82,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
        req->length = video->req_size - len;
        req->zero = video->payload_size == video->max_payload_size;
 
-       if (buf->buf.bytesused == video->queue.buf_used) {
+       if (buf->bytesused == video->queue.buf_used) {
                video->queue.buf_used = 0;
                buf->state = UVC_BUF_STATE_DONE;
                uvc_queue_next_buffer(&video->queue, buf);
@@ -92,7 +92,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
        }
 
        if (video->payload_size == video->max_payload_size ||
-           buf->buf.bytesused == video->queue.buf_used)
+           buf->bytesused == video->queue.buf_used)
                video->payload_size = 0;
 }
 
@@ -115,7 +115,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
 
        req->length = video->req_size - len;
 
-       if (buf->buf.bytesused == video->queue.buf_used) {
+       if (buf->bytesused == video->queue.buf_used) {
                video->queue.buf_used = 0;
                buf->state = UVC_BUF_STATE_DONE;
                uvc_queue_next_buffer(&video->queue, buf);
@@ -161,6 +161,7 @@ static void
 uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
 {
        struct uvc_video *video = req->context;
+       struct uvc_video_queue *queue = &video->queue;
        struct uvc_buffer *buf;
        unsigned long flags;
        int ret;
@@ -169,13 +170,15 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
        case 0:
                break;
 
-       case -ESHUTDOWN:
+       case -ESHUTDOWN:        /* disconnect from host. */
                printk(KERN_INFO "VS request cancelled.\n");
+               uvc_queue_cancel(queue, 1);
                goto requeue;
 
        default:
                printk(KERN_INFO "VS request completed with status %d.\n",
                        req->status);
+               uvc_queue_cancel(queue, 0);
                goto requeue;
        }
 
@@ -229,13 +232,18 @@ uvc_video_free_requests(struct uvc_video *video)
 static int
 uvc_video_alloc_requests(struct uvc_video *video)
 {
+       unsigned int req_size;
        unsigned int i;
        int ret = -ENOMEM;
 
        BUG_ON(video->req_size);
 
+       req_size = video->ep->maxpacket
+                * max_t(unsigned int, video->ep->maxburst, 1)
+                * (video->ep->mult + 1);
+
        for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
-               video->req_buffer[i] = kmalloc(video->ep->maxpacket, GFP_KERNEL);
+               video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL);
                if (video->req_buffer[i] == NULL)
                        goto error;
 
@@ -245,14 +253,14 @@ uvc_video_alloc_requests(struct uvc_video *video)
 
                video->req[i]->buf = video->req_buffer[i];
                video->req[i]->length = 0;
-               video->req[i]->dma = DMA_ADDR_INVALID;
                video->req[i]->complete = uvc_video_complete;
                video->req[i]->context = video;
 
                list_add_tail(&video->req[i]->list, &video->req_free);
        }
 
-       video->req_size = video->ep->maxpacket;
+       video->req_size = req_size;
+
        return 0;
 
 error:
@@ -309,7 +317,8 @@ uvc_video_pump(struct uvc_video *video)
                video->encode(req, video, buf);
 
                /* Queue the USB request */
-               if ((ret = usb_ep_queue(video->ep, req, GFP_KERNEL)) < 0) {
+               ret = usb_ep_queue(video->ep, req, GFP_ATOMIC);
+               if (ret < 0) {
                        printk(KERN_INFO "Failed to queue request (%d)\n", ret);
                        usb_ep_set_halt(video->ep);
                        spin_unlock_irqrestore(&video->queue.irqlock, flags);
index 685fa681cb6542abcea1f3b3fb02218201019551..2cd6262e8b7149a23d8458e76e5ef6ef3b919f1c 100644 (file)
@@ -368,8 +368,10 @@ static int zero_unbind(struct usb_composite_dev *cdev)
        del_timer_sync(&autoresume_timer);
        if (!IS_ERR_OR_NULL(func_ss))
                usb_put_function(func_ss);
+       usb_put_function_instance(func_inst_ss);
        if (!IS_ERR_OR_NULL(func_lb))
                usb_put_function(func_lb);
+       usb_put_function_instance(func_inst_lb);
        return 0;
 }
 
index c59a1126926f3210dd47d524d6ae5d184a5d535c..de94f2699063b12dd3c0cd1613a9cd2e37cd00c6 100644 (file)
@@ -2,11 +2,9 @@
 # USB Host Controller Drivers
 #
 comment "USB Host Controller Drivers"
-       depends on USB
 
 config USB_C67X00_HCD
        tristate "Cypress C67x00 HCD support"
-       depends on USB
        help
          The Cypress C67x00 (EZ-Host/EZ-OTG) chips are dual-role
          host/peripheral/OTG USB controllers.
@@ -19,7 +17,7 @@ config USB_C67X00_HCD
 
 config USB_XHCI_HCD
        tristate "xHCI HCD (USB 3.0) support"
-       depends on USB && USB_ARCH_HAS_XHCI
+       depends on USB_ARCH_HAS_XHCI
        ---help---
          The eXtensible Host Controller Interface (xHCI) is standard for USB 3.0
          "SuperSpeed" host controller hardware.
@@ -27,13 +25,13 @@ config USB_XHCI_HCD
          To compile this driver as a module, choose M here: the
          module will be called xhci-hcd.
 
+if USB_XHCI_HCD
+
 config USB_XHCI_PLATFORM
        tristate
-       depends on USB_XHCI_HCD
 
 config USB_XHCI_HCD_DEBUGGING
        bool "Debugging for the xHCI host controller"
-       depends on USB_XHCI_HCD
        ---help---
          Say 'Y' to turn on debugging for the xHCI host controller driver.
          This will spew debugging output, even in interrupt context.
@@ -41,9 +39,11 @@ config USB_XHCI_HCD_DEBUGGING
 
          If unsure, say N.
 
+endif # USB_XHCI_HCD
+
 config USB_EHCI_HCD
        tristate "EHCI HCD (USB 2.0) support"
-       depends on USB && USB_ARCH_HAS_EHCI
+       depends on USB_ARCH_HAS_EHCI
        ---help---
          The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0
          "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware.
@@ -95,14 +95,19 @@ config USB_EHCI_TT_NEWSCHED
 
          If unsure, say Y.
 
+config USB_FSL_MPH_DR_OF
+       tristate
+
+if USB_EHCI_HCD
+
 config USB_EHCI_PCI
        tristate
-       depends on USB_EHCI_HCD && PCI
+       depends on PCI
        default y
 
 config USB_EHCI_HCD_PMC_MSP
        tristate "EHCI support for on-chip PMC MSP71xx USB controller"
-       depends on USB_EHCI_HCD && MSP_HAS_USB
+       depends on MSP_HAS_USB
        default n
        select USB_EHCI_BIG_ENDIAN_DESC
        select USB_EHCI_BIG_ENDIAN_MMIO
@@ -112,22 +117,13 @@ config USB_EHCI_HCD_PMC_MSP
 
 config USB_EHCI_BIG_ENDIAN_MMIO
        bool
-       depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || \
-                                   ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
-                                   PPC_MPC512x || CPU_CAVIUM_OCTEON || \
-                                   PMC_MSP || SPARC_LEON || MIPS_SEAD3)
-       default y
 
 config USB_EHCI_BIG_ENDIAN_DESC
        bool
-       depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
-                                   PPC_MPC512x || PMC_MSP || SPARC_LEON || \
-                                   MIPS_SEAD3)
-       default y
 
 config XPS_USB_HCD_XILINX
        bool "Use Xilinx usb host EHCI controller core"
-       depends on USB_EHCI_HCD && (PPC32 || MICROBLAZE)
+       depends on (PPC32 || MICROBLAZE)
        select USB_EHCI_BIG_ENDIAN_DESC
        select USB_EHCI_BIG_ENDIAN_MMIO
        ---help---
@@ -136,12 +132,9 @@ config XPS_USB_HCD_XILINX
                support both high speed and full speed devices, or high speed
                devices only.
 
-config USB_FSL_MPH_DR_OF
-       tristate
-
 config USB_EHCI_FSL
        bool "Support for Freescale PPC on-chip EHCI USB controller"
-       depends on USB_EHCI_HCD && FSL_SOC
+       depends on FSL_SOC
        select USB_EHCI_ROOT_HUB_TT
        select USB_FSL_MPH_DR_OF if OF
        ---help---
@@ -149,22 +142,53 @@ config USB_EHCI_FSL
 
 config USB_EHCI_MXC
        tristate "Support for Freescale i.MX on-chip EHCI USB controller"
-       depends on USB_EHCI_HCD && ARCH_MXC
+       depends on ARCH_MXC
        select USB_EHCI_ROOT_HUB_TT
        ---help---
          Variation of ARC USB block used in some Freescale chips.
 
 config USB_EHCI_HCD_OMAP
-       bool "EHCI support for OMAP3 and later chips"
-       depends on USB_EHCI_HCD && ARCH_OMAP
+       tristate "EHCI support for OMAP3 and later chips"
+       depends on ARCH_OMAP
        default y
        ---help---
          Enables support for the on-chip EHCI controller on
          OMAP3 and later chips.
+         If your system uses a PHY on the USB port, you will need to
+         enable USB_PHY and the appropriate PHY driver as well. Most
+         boards need the NOP_USB_XCEIV PHY driver.
+
+config USB_EHCI_HCD_ORION
+       tristate  "Support for Marvell EBU on-chip EHCI USB controller"
+       depends on USB_EHCI_HCD && PLAT_ORION
+       default y
+       ---help---
+         Enables support for the on-chip EHCI controller on Marvell's
+         embedded ARM SoCs, including Orion, Kirkwood, Dove, Armada XP,
+         Armada 370.  This is different from the EHCI implementation
+         on Marvell's mobile PXA and MMP SoC, see "EHCI support for
+         Marvell PXA/MMP USB controller" for those.
+
+config USB_EHCI_HCD_SPEAR
+        tristate "Support for ST SPEAr on-chip EHCI USB controller"
+        depends on USB_EHCI_HCD && PLAT_SPEAR
+        default y
+        ---help---
+          Enables support for the on-chip EHCI controller on
+          ST SPEAr chips.
+
+config USB_EHCI_HCD_AT91
+        tristate  "Support for Atmel on-chip EHCI USB controller"
+        depends on USB_EHCI_HCD && ARCH_AT91
+        default y
+        ---help---
+          Enables support for the on-chip EHCI controller on
+          Atmel chips.
 
 config USB_EHCI_MSM
-       bool "Support for MSM on-chip EHCI USB controller"
-       depends on USB_EHCI_HCD && ARCH_MSM
+       tristate "Support for Qualcomm QSD/MSM on-chip EHCI USB controller"
+       depends on ARCH_MSM
+       depends on USB_PHY
        select USB_EHCI_ROOT_HUB_TT
        select USB_MSM_OTG
        ---help---
@@ -177,15 +201,16 @@ config USB_EHCI_MSM
 
 config USB_EHCI_TEGRA
        boolean "NVIDIA Tegra HCD support"
-       depends on USB_EHCI_HCD && ARCH_TEGRA
+       depends on ARCH_TEGRA
        select USB_EHCI_ROOT_HUB_TT
+       select USB_PHY
        help
          This driver enables support for the internal USB Host Controllers
          found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.
 
 config USB_EHCI_HCD_PPC_OF
        bool "EHCI support for PPC USB controller on OF platform bus"
-       depends on USB_EHCI_HCD && PPC_OF
+       depends on PPC_OF
        default y
        ---help---
          Enables support for the USB controller present on the PowerPC
@@ -193,35 +218,40 @@ config USB_EHCI_HCD_PPC_OF
 
 config USB_EHCI_SH
        bool "EHCI support for SuperH USB controller"
-       depends on USB_EHCI_HCD && SUPERH
+       depends on SUPERH
        ---help---
          Enables support for the on-chip EHCI controller on the SuperH.
          If you use the PCI EHCI controller, this option is not necessary.
 
 config USB_EHCI_S5P
-       boolean "S5P EHCI support"
-       depends on USB_EHCI_HCD && PLAT_S5P
+       tristate "EHCI support for Samsung S5P/EXYNOS SoC Series"
+       depends on PLAT_S5P
        help
-        Enable support for the S5P SOC's on-chip EHCI controller.
+       Enable support for the Samsung S5Pxxxx and Exynos3/4/5 SOC's
+       on-chip EHCI controller.
 
 config USB_EHCI_MV
-       bool "EHCI support for Marvell on-chip controller"
-       depends on USB_EHCI_HCD && (ARCH_PXA || ARCH_MMP)
+       bool "EHCI support for Marvell PXA/MMP USB controller"
+       depends on (ARCH_PXA || ARCH_MMP)
        select USB_EHCI_ROOT_HUB_TT
        ---help---
          Enables support for Marvell (including PXA and MMP series) on-chip
          USB SPH and OTG controller. SPH is a single port host, and it can
          only be EHCI host. OTG is controller that can switch to host mode.
+         Note that this driver will not work on Marvell's other EHCI
+         controller used by the EBU-type SoCs including Orion, Kirkwood,
+         Dova, Armada 370 and Armada XP. See "Support for Marvell EBU
+         on-chip EHCI USB controller" for those.
 
 config USB_W90X900_EHCI
        bool "W90X900(W90P910) EHCI support"
-       depends on USB_EHCI_HCD && ARCH_W90X900
+       depends on ARCH_W90X900
        ---help---
                Enables support for the W90X900 USB controller
 
 config USB_CNS3XXX_EHCI
        bool "Cavium CNS3XXX EHCI Module (DEPRECATED)"
-       depends on USB_EHCI_HCD && ARCH_CNS3XXX
+       depends on ARCH_CNS3XXX
        select USB_EHCI_HCD_PLATFORM
        ---help---
          This option is deprecated now and the driver was removed, use
@@ -233,7 +263,7 @@ config USB_CNS3XXX_EHCI
 
 config USB_EHCI_ATH79
        bool "EHCI support for AR7XXX/AR9XXX SoCs (DEPRECATED)"
-       depends on USB_EHCI_HCD && (SOC_AR71XX || SOC_AR724X || SOC_AR913X || SOC_AR933X)
+       depends on (SOC_AR71XX || SOC_AR724X || SOC_AR913X || SOC_AR933X)
        select USB_EHCI_ROOT_HUB_TT
        select USB_EHCI_HCD_PLATFORM
        default y
@@ -244,9 +274,31 @@ config USB_EHCI_ATH79
          Enables support for the built-in EHCI controller present
          on the Atheros AR7XXX/AR9XXX SoCs.
 
+config USB_EHCI_HCD_PLATFORM
+       tristate "Generic EHCI driver for a platform device"
+       default n
+       ---help---
+         Adds an EHCI host driver for a generic platform device, which
+         provides a memory space and an irq.
+
+         If unsure, say N.
+
+config USB_OCTEON_EHCI
+       bool "Octeon on-chip EHCI support"
+       depends on CPU_CAVIUM_OCTEON
+       default n
+       select USB_EHCI_BIG_ENDIAN_MMIO
+       help
+         Enable support for the Octeon II SOC's on-chip EHCI
+         controller.  It is needed for high-speed (480Mbit/sec)
+         USB 2.0 device support.  All CN6XXX based chips with USB are
+         supported.
+
+endif # USB_EHCI_HCD
+
 config USB_OXU210HP_HCD
        tristate "OXU210HP HCD support"
-       depends on USB && GENERIC_HARDIRQS
+       depends on GENERIC_HARDIRQS
        ---help---
          The OXU210HP is an USB host/OTG/device controller. Enable this
          option if your board has this chip. If unsure, say N.
@@ -259,7 +311,6 @@ config USB_OXU210HP_HCD
 
 config USB_ISP116X_HCD
        tristate "ISP116X HCD support"
-       depends on USB
        ---help---
          The ISP1160 and ISP1161 chips are USB host controllers. Enable this
          option if your board has this chip. If unsure, say N.
@@ -271,7 +322,6 @@ config USB_ISP116X_HCD
 
 config USB_ISP1760_HCD
        tristate "ISP 1760 HCD support"
-       depends on USB
        ---help---
          The ISP1760 chip is a USB 2.0 host controller.
 
@@ -286,7 +336,6 @@ config USB_ISP1760_HCD
 
 config USB_ISP1362_HCD
        tristate "ISP1362 HCD support"
-       depends on USB
        default N
        ---help---
          Supports the Philips ISP1362 chip as a host controller
@@ -298,9 +347,8 @@ config USB_ISP1362_HCD
 
 config USB_OHCI_HCD
        tristate "OHCI HCD support"
-       depends on USB && USB_ARCH_HAS_OHCI
+       depends on USB_ARCH_HAS_OHCI
        select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
-       select USB_OTG_UTILS if ARCH_OMAP
        depends on USB_ISP1301 || !ARCH_LPC32XX
        ---help---
          The Open Host Controller Interface (OHCI) is a standard for accessing
@@ -315,16 +363,18 @@ config USB_OHCI_HCD
          To compile this driver as a module, choose M here: the
          module will be called ohci-hcd.
 
+if USB_OHCI_HCD
+
 config USB_OHCI_HCD_OMAP1
        bool "OHCI support for OMAP1/2 chips"
-       depends on USB_OHCI_HCD && ARCH_OMAP1
+       depends on ARCH_OMAP1
        default y
        ---help---
          Enables support for the OHCI controller on OMAP1/2 chips.
 
 config USB_OHCI_HCD_OMAP3
        bool "OHCI support for OMAP3 and later chips"
-       depends on USB_OHCI_HCD && (ARCH_OMAP3 || ARCH_OMAP4)
+       depends on (ARCH_OMAP3 || ARCH_OMAP4)
        default y
        ---help---
          Enables support for the on-chip OHCI controller on
@@ -332,7 +382,7 @@ config USB_OHCI_HCD_OMAP3
 
 config USB_OHCI_ATH79
        bool "USB OHCI support for the Atheros AR71XX/AR7240 SoCs (DEPRECATED)"
-       depends on USB_OHCI_HCD && (SOC_AR71XX || SOC_AR724X)
+       depends on (SOC_AR71XX || SOC_AR724X)
        select USB_OHCI_HCD_PLATFORM
        default y
        help
@@ -344,7 +394,7 @@ config USB_OHCI_ATH79
 
 config USB_OHCI_HCD_PPC_OF_BE
        bool "OHCI support for OF platform bus (big endian)"
-       depends on USB_OHCI_HCD && PPC_OF
+       depends on PPC_OF
        select USB_OHCI_BIG_ENDIAN_DESC
        select USB_OHCI_BIG_ENDIAN_MMIO
        ---help---
@@ -353,7 +403,7 @@ config USB_OHCI_HCD_PPC_OF_BE
 
 config USB_OHCI_HCD_PPC_OF_LE
        bool "OHCI support for OF platform bus (little endian)"
-       depends on USB_OHCI_HCD && PPC_OF
+       depends on PPC_OF
        select USB_OHCI_LITTLE_ENDIAN
        ---help---
          Enables support for little-endian USB controllers present on the
@@ -361,12 +411,12 @@ config USB_OHCI_HCD_PPC_OF_LE
 
 config USB_OHCI_HCD_PPC_OF
        bool
-       depends on USB_OHCI_HCD && PPC_OF
+       depends on PPC_OF
        default USB_OHCI_HCD_PPC_OF_BE || USB_OHCI_HCD_PPC_OF_LE
 
 config USB_OHCI_HCD_PCI
        bool "OHCI support for PCI-bus USB controllers"
-       depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx || USB_OHCI_HCD_PPC_OF)
+       depends on PCI && (STB03xxx || PPC_MPC52xx || USB_OHCI_HCD_PPC_OF)
        default y
        select USB_OHCI_LITTLE_ENDIAN
        ---help---
@@ -375,7 +425,7 @@ config USB_OHCI_HCD_PCI
 
 config USB_OHCI_HCD_SSB
        bool "OHCI support for Broadcom SSB OHCI core (DEPRECATED)"
-       depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD)
+       depends on (SSB = y || SSB = USB_OHCI_HCD)
        select USB_HCD_SSB
        select USB_OHCI_HCD_PLATFORM
        default n
@@ -393,7 +443,7 @@ config USB_OHCI_HCD_SSB
 
 config USB_OHCI_SH
        bool "OHCI support for SuperH USB controller (DEPRECATED)"
-       depends on USB_OHCI_HCD && SUPERH
+       depends on SUPERH
        select USB_OHCI_HCD_PLATFORM
        ---help---
          This option is deprecated now and the driver was removed, use
@@ -404,13 +454,13 @@ config USB_OHCI_SH
 
 config USB_OHCI_EXYNOS
        boolean "OHCI support for Samsung EXYNOS SoC Series"
-       depends on USB_OHCI_HCD && ARCH_EXYNOS
+       depends on ARCH_EXYNOS
        help
         Enable support for the Samsung Exynos SOC's on-chip OHCI controller.
 
 config USB_CNS3XXX_OHCI
        bool "Cavium CNS3XXX OHCI Module (DEPRECATED)"
-       depends on USB_OHCI_HCD && ARCH_CNS3XXX
+       depends on ARCH_CNS3XXX
        select USB_OHCI_HCD_PLATFORM
        ---help---
          This option is deprecated now and the driver was removed, use
@@ -421,7 +471,6 @@ config USB_CNS3XXX_OHCI
 
 config USB_OHCI_HCD_PLATFORM
        bool "Generic OHCI driver for a platform device"
-       depends on USB_OHCI_HCD
        default n
        ---help---
          Adds an OHCI host driver for a generic platform device, which
@@ -429,35 +478,36 @@ config USB_OHCI_HCD_PLATFORM
 
          If unsure, say N.
 
-config USB_EHCI_HCD_PLATFORM
-       tristate "Generic EHCI driver for a platform device"
-       depends on USB_EHCI_HCD
-       default n
-       ---help---
-         Adds an EHCI host driver for a generic platform device, which
-         provides a memory space and an irq.
+config USB_OCTEON_OHCI
+       bool "Octeon on-chip OHCI support"
+       depends on CPU_CAVIUM_OCTEON
+       default USB_OCTEON_EHCI
+       select USB_OHCI_BIG_ENDIAN_MMIO
+       select USB_OHCI_LITTLE_ENDIAN
+       help
+         Enable support for the Octeon II SOC's on-chip OHCI
+         controller.  It is needed for low-speed USB 1.0 device
+         support.  All CN6XXX based chips with USB are supported.
 
-         If unsure, say N.
 
 config USB_OHCI_BIG_ENDIAN_DESC
        bool
-       depends on USB_OHCI_HCD
        default n
 
 config USB_OHCI_BIG_ENDIAN_MMIO
        bool
-       depends on USB_OHCI_HCD
        default n
 
 config USB_OHCI_LITTLE_ENDIAN
        bool
-       depends on USB_OHCI_HCD
        default n if STB03xxx || PPC_MPC52xx
        default y
 
+endif # USB_OHCI_HCD
+
 config USB_UHCI_HCD
        tristate "UHCI HCD (most Intel and VIA) support"
-       depends on USB && (PCI || SPARC_LEON || ARCH_VT8500)
+       depends on PCI || SPARC_LEON || ARCH_VT8500
        ---help---
          The Universal Host Controller Interface is a standard by Intel for
          accessing the USB hardware in the PC (which is also called the USB
@@ -497,7 +547,7 @@ config USB_UHCI_BIG_ENDIAN_DESC
 
 config USB_FHCI_HCD
        tristate "Freescale QE USB Host Controller support"
-       depends on USB && OF_GPIO && QE_GPIO && QUICC_ENGINE
+       depends on OF_GPIO && QE_GPIO && QUICC_ENGINE
        select FSL_GTM
        select QE_USB
        help
@@ -514,7 +564,7 @@ config FHCI_DEBUG
 
 config USB_U132_HCD
        tristate "Elan U132 Adapter Host Controller"
-       depends on USB && USB_FTDI_ELAN
+       depends on USB_FTDI_ELAN
        default M
        help
          The U132 adapter is a USB to CardBus adapter specifically designed
@@ -542,7 +592,6 @@ config USB_U132_HCD
 
 config USB_SL811_HCD
        tristate "SL811HS HCD support"
-       depends on USB
        help
          The SL811HS is a single-port USB controller that supports either
          host side or peripheral side roles.  Enable this option if your
@@ -574,7 +623,6 @@ config USB_SL811_CS
 
 config USB_R8A66597_HCD
        tristate "R8A66597 HCD support"
-       depends on USB
        help
          The R8A66597 is a USB 2.0 host and peripheral controller.
 
@@ -586,7 +634,6 @@ config USB_R8A66597_HCD
 
 config USB_RENESAS_USBHS_HCD
        tristate "Renesas USBHS HCD support"
-       depends on USB
        depends on USB_RENESAS_USBHS
        help
          The Renesas USBHS is a USB 2.0 host and peripheral controller.
@@ -611,7 +658,7 @@ config USB_WHCI_HCD
 
 config USB_HWA_HCD
        tristate "Host Wire Adapter (HWA) driver"
-       depends on USB && UWB
+       depends on UWB
        select USB_WUSB
        select UWB_HWA
        help
@@ -625,7 +672,7 @@ config USB_HWA_HCD
 
 config USB_IMX21_HCD
        tristate "i.MX21 HCD support"
-       depends on USB && ARM && ARCH_MXC
+       depends on ARM && ARCH_MXC
        help
          This driver enables support for the on-chip USB host in the
          i.MX21 processor.
@@ -633,27 +680,7 @@ config USB_IMX21_HCD
          To compile this driver as a module, choose M here: the
          module will be called "imx21-hcd".
 
-config USB_OCTEON_EHCI
-       bool "Octeon on-chip EHCI support"
-       depends on USB && USB_EHCI_HCD && CPU_CAVIUM_OCTEON
-       default n
-       select USB_EHCI_BIG_ENDIAN_MMIO
-       help
-         Enable support for the Octeon II SOC's on-chip EHCI
-         controller.  It is needed for high-speed (480Mbit/sec)
-         USB 2.0 device support.  All CN6XXX based chips with USB are
-         supported.
 
-config USB_OCTEON_OHCI
-       bool "Octeon on-chip OHCI support"
-       depends on USB && USB_OHCI_HCD && CPU_CAVIUM_OCTEON
-       default USB_OCTEON_EHCI
-       select USB_OHCI_BIG_ENDIAN_MMIO
-       select USB_OHCI_LITTLE_ENDIAN
-       help
-         Enable support for the Octeon II SOC's on-chip OHCI
-         controller.  It is needed for low-speed USB 1.0 device
-         support.  All CN6XXX based chips with USB are supported.
 
 config USB_OCTEON2_COMMON
        bool
index 001fbff2fdefedbb346f71db705f8e687201e454..4fb73c156d72ac998fc8f6f60684bc212d26919d 100644 (file)
@@ -27,6 +27,12 @@ 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
 obj-$(CONFIG_USB_EHCI_MXC)     += ehci-mxc.o
+obj-$(CONFIG_USB_EHCI_HCD_OMAP)        += ehci-omap.o
+obj-$(CONFIG_USB_EHCI_HCD_ORION)       += ehci-orion.o
+obj-$(CONFIG_USB_EHCI_HCD_SPEAR)       += ehci-spear.o
+obj-$(CONFIG_USB_EHCI_S5P)     += ehci-s5p.o
+obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
+obj-$(CONFIG_USB_EHCI_MSM)     += ehci-msm.o
 
 obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
 obj-$(CONFIG_USB_ISP116X_HCD)  += isp116x-hcd.o
index f3beac4d06b81fdb1fd90a61f0ff679dd77b2f4b..66420097c24234eb3db9d09a656345cd80edcc9f 100644 (file)
  */
 
 #include <linux/clk.h>
-#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ehci.h"
+
+#define DRIVER_DESC "EHCI Atmel driver"
+
+static const char hcd_name[] = "ehci-atmel";
+static struct hc_driver __read_mostly ehci_atmel_hc_driver;
 
 /* interface and function clocks */
 static struct clk *iclk, *fclk;
@@ -50,51 +63,6 @@ static void atmel_stop_ehci(struct platform_device *pdev)
 
 /*-------------------------------------------------------------------------*/
 
-static int ehci_atmel_setup(struct usb_hcd *hcd)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-
-       /* registers start at offset 0x0 */
-       ehci->caps = hcd->regs;
-
-       return ehci_setup(hcd);
-}
-
-static const struct hc_driver ehci_atmel_hc_driver = {
-       .description            = hcd_name,
-       .product_desc           = "Atmel EHCI UHP HS",
-       .hcd_priv_size          = sizeof(struct ehci_hcd),
-
-       /* generic hardware linkage */
-       .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2,
-
-       /* basic lifecycle operations */
-       .reset                  = ehci_atmel_setup,
-       .start                  = ehci_run,
-       .stop                   = ehci_stop,
-       .shutdown               = ehci_shutdown,
-
-       /* managing i/o requests and associated device resources */
-       .urb_enqueue            = ehci_urb_enqueue,
-       .urb_dequeue            = ehci_urb_dequeue,
-       .endpoint_disable       = ehci_endpoint_disable,
-       .endpoint_reset         = ehci_endpoint_reset,
-
-       /* scheduling support */
-       .get_frame_number       = ehci_get_frame,
-
-       /* root hub support */
-       .hub_status_data        = ehci_hub_status_data,
-       .hub_control            = ehci_hub_control,
-       .bus_suspend            = ehci_bus_suspend,
-       .bus_resume             = ehci_bus_resume,
-       .relinquish_port        = ehci_relinquish_port,
-       .port_handed_over       = ehci_port_handed_over,
-
-       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
-};
-
 static u64 at91_ehci_dma_mask = DMA_BIT_MASK(32);
 
 static int ehci_atmel_drv_probe(struct platform_device *pdev)
@@ -102,6 +70,7 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev)
        struct usb_hcd *hcd;
        const struct hc_driver *driver = &ehci_atmel_hc_driver;
        struct resource *res;
+       struct ehci_hcd *ehci;
        int irq;
        int retval;
 
@@ -162,6 +131,10 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev)
                goto fail_request_resource;
        }
 
+       ehci = hcd_to_ehci(hcd);
+       /* registers start at offset 0x0 */
+       ehci->caps = hcd->regs;
+
        atmel_start_ehci(pdev);
 
        retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
@@ -185,7 +158,6 @@ static int ehci_atmel_drv_remove(struct platform_device *pdev)
 {
        struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
-       ehci_shutdown(hcd);
        usb_remove_hcd(hcd);
        usb_put_hcd(hcd);
 
@@ -213,3 +185,25 @@ static struct platform_driver ehci_atmel_driver = {
                .of_match_table = of_match_ptr(atmel_ehci_dt_ids),
        },
 };
+
+static int __init ehci_atmel_init(void)
+{
+       if (usb_disabled())
+               return -ENODEV;
+
+       pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+       ehci_init_driver(&ehci_atmel_hc_driver, NULL);
+       return platform_driver_register(&ehci_atmel_driver);
+}
+module_init(ehci_atmel_init);
+
+static void __exit ehci_atmel_cleanup(void)
+{
+       platform_driver_unregister(&ehci_atmel_driver);
+}
+module_exit(ehci_atmel_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_ALIAS("platform:atmel-ehci");
+MODULE_AUTHOR("Nicolas Ferre");
+MODULE_LICENSE("GPL");
index 70b496dc18a008c0bbfc261f5005bdd5ca50d204..5429d2645bbc943eb616b1438af21027aa49f124 100644 (file)
@@ -510,14 +510,16 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf)
        spin_lock_irqsave (&ehci->lock, flags);
        for (qh = ehci->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh)
                qh_lines (ehci, qh, &next, &size);
-       if (ehci->async_unlink && size > 0) {
+       if (!list_empty(&ehci->async_unlink) && size > 0) {
                temp = scnprintf(next, size, "\nunlink =\n");
                size -= temp;
                next += temp;
 
-               for (qh = ehci->async_unlink; size > 0 && qh;
-                               qh = qh->unlink_next)
-                       qh_lines (ehci, qh, &next, &size);
+               list_for_each_entry(qh, &ehci->async_unlink, unlink_node) {
+                       if (size <= 0)
+                               break;
+                       qh_lines(ehci, qh, &next, &size);
+               }
        }
        spin_unlock_irqrestore (&ehci->lock, flags);
 
@@ -814,9 +816,10 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
                }
        }
 
-       if (ehci->async_unlink) {
+       if (!list_empty(&ehci->async_unlink)) {
                temp = scnprintf(next, size, "async unlink qh %p\n",
-                               ehci->async_unlink);
+                               list_first_entry(&ehci->async_unlink,
+                                               struct ehci_qh, unlink_node));
                size -= temp;
                next += temp;
        }
index d81d2fcbff1894d79f0606d831d91b628c44f71e..3be3df233a0e0b73b8bdc198d5aae050b6e520be 100644 (file)
@@ -370,6 +370,15 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
        /* EHCI registers start at offset 0x100 */
        ehci->caps = hcd->regs + 0x100;
 
+#ifdef CONFIG_PPC_83xx
+       /*
+        * Deal with MPC834X that need port power to be cycled after the power
+        * fault condition is removed. Otherwise the state machine does not
+        * reflect PORTSC[CSC] correctly.
+        */
+       ehci->need_oc_pp_cycle = 1;
+#endif
+
        hcd->has_tt = 1;
 
        retval = ehci_setup(hcd);
index 416a6dce5e11c8adeeed2eef487b93c93dd5d728..312fc10da3c7aade0225cd126f28e372f1906058 100644 (file)
@@ -482,6 +482,9 @@ static int ehci_init(struct usb_hcd *hcd)
         * periodic_size can shrink by USBCMD update if hcc_params allows.
         */
        ehci->periodic_size = DEFAULT_I_TDPS;
+       INIT_LIST_HEAD(&ehci->async_unlink);
+       INIT_LIST_HEAD(&ehci->async_idle);
+       INIT_LIST_HEAD(&ehci->intr_unlink);
        INIT_LIST_HEAD(&ehci->intr_qh_list);
        INIT_LIST_HEAD(&ehci->cached_itd_list);
        INIT_LIST_HEAD(&ehci->cached_sitd_list);
@@ -670,9 +673,6 @@ int ehci_setup(struct usb_hcd *hcd)
        if (retval)
                return retval;
 
-       if (ehci_is_TDI(ehci))
-               tdi_reset(ehci);
-
        ehci_reset(ehci);
 
        return 0;
@@ -749,7 +749,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
                /* guard against (alleged) silicon errata */
                if (cmd & CMD_IAAD)
                        ehci_dbg(ehci, "IAA with IAAD still set?\n");
-               if (ehci->async_iaa)
+               if (ehci->iaa_in_progress)
                        COUNT(ehci->stats.iaa);
                end_unlink_async(ehci);
        }
@@ -757,7 +757,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
        /* remote wakeup [4.3.1] */
        if (status & STS_PCD) {
                unsigned        i = HCS_N_PORTS (ehci->hcs_params);
-               u32             ppcd = 0;
+               u32             ppcd = ~0;
 
                /* kick root hub later */
                pcd_status = status;
@@ -774,7 +774,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
                        int pstatus;
 
                        /* leverage per-port change bits feature */
-                       if (ehci->has_ppcd && !(ppcd & (1 << i)))
+                       if (!(ppcd & (1 << i)))
                                continue;
                        pstatus = ehci_readl(ehci,
                                         &ehci->regs->port_status[i]);
@@ -896,17 +896,24 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
        if (rc)
                goto done;
 
-       switch (usb_pipetype (urb->pipe)) {
-       // case PIPE_CONTROL:
-       // case PIPE_BULK:
-       default:
+       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+               /*
+                * We don't expedite dequeue for isochronous URBs.
+                * Just wait until they complete normally or their
+                * time slot expires.
+                */
+       } else {
                qh = (struct ehci_qh *) urb->hcpriv;
-               if (!qh)
-                       break;
+               qh->exception = 1;
                switch (qh->qh_state) {
                case QH_STATE_LINKED:
+                       if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)
+                               start_unlink_intr(ehci, qh);
+                       else
+                               start_unlink_async(ehci, qh);
+                       break;
                case QH_STATE_COMPLETING:
-                       start_unlink_async(ehci, qh);
+                       qh->dequeue_during_giveback = 1;
                        break;
                case QH_STATE_UNLINK:
                case QH_STATE_UNLINK_WAIT:
@@ -917,33 +924,6 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
                        qh_completions(ehci, qh);
                        break;
                }
-               break;
-
-       case PIPE_INTERRUPT:
-               qh = (struct ehci_qh *) urb->hcpriv;
-               if (!qh)
-                       break;
-               switch (qh->qh_state) {
-               case QH_STATE_LINKED:
-               case QH_STATE_COMPLETING:
-                       start_unlink_intr(ehci, qh);
-                       break;
-               case QH_STATE_IDLE:
-                       qh_completions (ehci, qh);
-                       break;
-               default:
-                       ehci_dbg (ehci, "bogus qh %p state %d\n",
-                                       qh, qh->qh_state);
-                       goto done;
-               }
-               break;
-
-       case PIPE_ISOCHRONOUS:
-               // itd or sitd ...
-
-               // wait till next completion, do it then.
-               // completion irqs can wait up to 1024 msec,
-               break;
        }
 done:
        spin_unlock_irqrestore (&ehci->lock, flags);
@@ -984,6 +964,7 @@ rescan:
                goto done;
        }
 
+       qh->exception = 1;
        if (ehci->rh_state < EHCI_RH_RUNNING)
                qh->qh_state = QH_STATE_IDLE;
        switch (qh->qh_state) {
@@ -1052,13 +1033,12 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)
                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) {
-
+               } else {
                        /* The toggle value in the QH can't be updated
                         * while the QH is active.  Unlink it now;
                         * re-linking will call qh_refresh().
                         */
+                       qh->exception = 1;
                        if (eptype == USB_ENDPOINT_XFER_BULK)
                                start_unlink_async(ehci, qh);
                        else
@@ -1251,11 +1231,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ehci_hcd_sh_driver
 #endif
 
-#ifdef CONFIG_USB_EHCI_HCD_OMAP
-#include "ehci-omap.c"
-#define        PLATFORM_DRIVER         ehci_hcd_omap_driver
-#endif
-
 #ifdef CONFIG_PPC_PS3
 #include "ehci-ps3.c"
 #define        PS3_SYSTEM_BUS_DRIVER   ps3_ehci_driver
@@ -1271,41 +1246,16 @@ MODULE_LICENSE ("GPL");
 #define XILINX_OF_PLATFORM_DRIVER      ehci_hcd_xilinx_of_driver
 #endif
 
-#ifdef CONFIG_PLAT_ORION
-#include "ehci-orion.c"
-#define        PLATFORM_DRIVER         ehci_orion_driver
-#endif
-
 #ifdef CONFIG_USB_W90X900_EHCI
 #include "ehci-w90x900.c"
 #define        PLATFORM_DRIVER         ehci_hcd_w90x900_driver
 #endif
 
-#ifdef CONFIG_ARCH_AT91
-#include "ehci-atmel.c"
-#define        PLATFORM_DRIVER         ehci_atmel_driver
-#endif
-
 #ifdef CONFIG_USB_OCTEON_EHCI
 #include "ehci-octeon.c"
 #define PLATFORM_DRIVER                ehci_octeon_driver
 #endif
 
-#ifdef CONFIG_ARCH_VT8500
-#include "ehci-vt8500.c"
-#define        PLATFORM_DRIVER         vt8500_ehci_driver
-#endif
-
-#ifdef CONFIG_PLAT_SPEAR
-#include "ehci-spear.c"
-#define PLATFORM_DRIVER                spear_ehci_hcd_driver
-#endif
-
-#ifdef CONFIG_USB_EHCI_MSM
-#include "ehci-msm.c"
-#define PLATFORM_DRIVER                ehci_msm_driver
-#endif
-
 #ifdef CONFIG_TILE_USB
 #include "ehci-tilegx.c"
 #define        PLATFORM_DRIVER         ehci_hcd_tilegx_driver
@@ -1321,11 +1271,6 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                tegra_ehci_driver
 #endif
 
-#ifdef CONFIG_USB_EHCI_S5P
-#include "ehci-s5p.c"
-#define PLATFORM_DRIVER                s5p_ehci_driver
-#endif
-
 #ifdef CONFIG_SPARC_LEON
 #include "ehci-grlib.c"
 #define PLATFORM_DRIVER                ehci_grlib_driver
@@ -1345,6 +1290,12 @@ MODULE_LICENSE ("GPL");
        !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \
        !IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \
        !IS_ENABLED(CONFIG_USB_EHCI_MXC) && \
+       !IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \
+       !IS_ENABLED(CONFIG_USB_EHCI_HCD_ORION) && \
+       !IS_ENABLED(CONFIG_USB_EHCI_HCD_SPEAR) && \
+       !IS_ENABLED(CONFIG_USB_EHCI_S5P) && \
+       !IS_ENABLED(CONFIG_USB_EHCI_HCD_AT91) && \
+       !IS_ENABLED(CONFIG_USB_EHCI_MSM) && \
        !defined(PLATFORM_DRIVER) && \
        !defined(PS3_SYSTEM_BUS_DRIVER) && \
        !defined(OF_PLATFORM_DRIVER) && \
index 7d06e77f6c4fa0116ea69ad239753ea4dffe20fd..9ab4a4d9768a5a3ed3fa791746e01977445ba840 100644 (file)
@@ -464,7 +464,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
        while (i--) {
                temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
                if (test_bit(i, &resume_needed)) {
-                       temp &= ~(PORT_RWC_BITS | PORT_RESUME);
+                       temp &= ~(PORT_RWC_BITS | PORT_SUSPEND | PORT_RESUME);
                        ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
                        ehci_vdbg (ehci, "resumed port %d\n", i + 1);
                }
@@ -590,7 +590,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
        u32             mask;
        int             ports, i, retval = 1;
        unsigned long   flags;
-       u32             ppcd = 0;
+       u32             ppcd = ~0;
 
        /* init status to no-changes */
        buf [0] = 0;
@@ -628,9 +628,10 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
 
        for (i = 0; i < ports; i++) {
                /* leverage per-port change bits feature */
-               if (ehci->has_ppcd && !(ppcd & (1 << i)))
-                       continue;
-               temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
+               if (ppcd & (1 << i))
+                       temp = ehci_readl(ehci, &ehci->regs->port_status[i]);
+               else
+                       temp = 0;
 
                /*
                 * Return status information even for ports with OWNER set.
@@ -839,7 +840,8 @@ static int ehci_hub_control (
                         * power switching; they're allowed to just limit the
                         * current.  khubd will turn the power back on.
                         */
-                       if ((temp & PORT_OC) && HCS_PPC(ehci->hcs_params)) {
+                       if (((temp & PORT_OC) || (ehci->need_oc_pp_cycle))
+                                       && HCS_PPC(ehci->hcs_params)) {
                                ehci_writel(ehci,
                                        temp & ~(PORT_RWC_BITS | PORT_POWER),
                                        status_reg);
@@ -870,10 +872,9 @@ static int ehci_hub_control (
                                usb_hcd_end_port_resume(&hcd->self, wIndex);
 
                                /* stop resume signaling */
-                               temp = ehci_readl(ehci, status_reg);
-                               ehci_writel(ehci,
-                                       temp & ~(PORT_RWC_BITS | PORT_RESUME),
-                                       status_reg);
+                               temp &= ~(PORT_RWC_BITS |
+                                               PORT_SUSPEND | PORT_RESUME);
+                               ehci_writel(ehci, temp, status_reg);
                                clear_bit(wIndex, &ehci->resuming_ports);
                                retval = handshake(ehci, status_reg,
                                           PORT_RESUME, 0, 2000 /* 2msec */);
@@ -883,7 +884,7 @@ static int ehci_hub_control (
                                                wIndex + 1, retval);
                                        goto error;
                                }
-                               temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10));
+                               temp = ehci_readl(ehci, status_reg);
                        }
                }
 
index 88a49c87e7484846c845dc79cc99a5410799d8a4..0f717dc688b7276fb75f65a9920bb799facfb164 100644 (file)
  * along with this program; if not, you can find it at http://www.fsf.org
  */
 
-#include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
-
 #include <linux/usb/otg.h>
 #include <linux/usb/msm_hsusb_hw.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ehci.h"
 
 #define MSM_USB_BASE (hcd->regs)
 
+#define DRIVER_DESC "Qualcomm On-Chip EHCI Host Controller"
+
+static const char hcd_name[] = "ehci-msm";
+static struct hc_driver __read_mostly msm_hc_driver;
 static struct usb_phy *phy;
 
 static int ehci_msm_reset(struct usb_hcd *hcd)
@@ -56,52 +66,6 @@ static int ehci_msm_reset(struct usb_hcd *hcd)
        return 0;
 }
 
-static struct hc_driver msm_hc_driver = {
-       .description            = hcd_name,
-       .product_desc           = "Qualcomm On-Chip EHCI Host Controller",
-       .hcd_priv_size          = sizeof(struct ehci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq                    = ehci_irq,
-       .flags                  = HCD_USB2 | HCD_MEMORY,
-
-       .reset                  = ehci_msm_reset,
-       .start                  = ehci_run,
-
-       .stop                   = ehci_stop,
-       .shutdown               = ehci_shutdown,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue            = ehci_urb_enqueue,
-       .urb_dequeue            = ehci_urb_dequeue,
-       .endpoint_disable       = ehci_endpoint_disable,
-       .endpoint_reset         = ehci_endpoint_reset,
-       .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number       = ehci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data        = ehci_hub_status_data,
-       .hub_control            = ehci_hub_control,
-       .relinquish_port        = ehci_relinquish_port,
-       .port_handed_over       = ehci_port_handed_over,
-
-       /*
-        * PM support
-        */
-       .bus_suspend            = ehci_bus_suspend,
-       .bus_resume             = ehci_bus_resume,
-};
-
 static int ehci_msm_probe(struct platform_device *pdev)
 {
        struct usb_hcd *hcd;
@@ -145,7 +109,7 @@ static int ehci_msm_probe(struct platform_device *pdev)
         * management.
         */
        phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-       if (IS_ERR_OR_NULL(phy)) {
+       if (IS_ERR(phy)) {
                dev_err(&pdev->dev, "unable to find transceiver\n");
                ret = -ENODEV;
                goto put_hcd;
@@ -165,6 +129,8 @@ static int ehci_msm_probe(struct platform_device *pdev)
        pm_runtime_no_callbacks(&pdev->dev);
        pm_runtime_enable(&pdev->dev);
 
+       /* FIXME: need to call usb_add_hcd() here? */
+
        return 0;
 
 put_hcd:
@@ -183,6 +149,8 @@ static int ehci_msm_remove(struct platform_device *pdev)
 
        otg_set_host(phy->otg, NULL);
 
+       /* FIXME: need to call usb_remove_hcd() here? */
+
        usb_put_hcd(hcd);
 
        return 0;
@@ -226,3 +194,28 @@ static struct platform_driver ehci_msm_driver = {
                   .pm = &ehci_msm_dev_pm_ops,
        },
 };
+
+static const struct ehci_driver_overrides msm_overrides __initdata = {
+       .reset = ehci_msm_reset,
+};
+
+static int __init ehci_msm_init(void)
+{
+       if (usb_disabled())
+               return -ENODEV;
+
+       pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+       ehci_init_driver(&msm_hc_driver, &msm_overrides);
+       return platform_driver_register(&ehci_msm_driver);
+}
+module_init(ehci_msm_init);
+
+static void __exit ehci_msm_cleanup(void)
+{
+       platform_driver_unregister(&ehci_msm_driver);
+}
+module_exit(ehci_msm_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_ALIAS("platform:msm-ehci");
+MODULE_LICENSE("GPL");
index 3065809546b159c1966b87f5fe4cdc6c333bc3da..402062973f032ca58e048a0d331ce526be4b8e0c 100644 (file)
@@ -33,25 +33,17 @@ struct ehci_hcd_mv {
 
        struct mv_usb_platform_data *pdata;
 
-       /* clock source and total clock number */
-       unsigned int clknum;
-       struct clk *clk[0];
+       struct clk *clk;
 };
 
 static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv)
 {
-       unsigned int i;
-
-       for (i = 0; i < ehci_mv->clknum; i++)
-               clk_prepare_enable(ehci_mv->clk[i]);
+       clk_prepare_enable(ehci_mv->clk);
 }
 
 static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv)
 {
-       unsigned int i;
-
-       for (i = 0; i < ehci_mv->clknum; i++)
-               clk_disable_unprepare(ehci_mv->clk[i]);
+       clk_disable_unprepare(ehci_mv->clk);
 }
 
 static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv)
@@ -144,9 +136,8 @@ static int mv_ehci_probe(struct platform_device *pdev)
        struct ehci_hcd *ehci;
        struct ehci_hcd_mv *ehci_mv;
        struct resource *r;
-       int clk_i, retval = -ENODEV;
+       int retval = -ENODEV;
        u32 offset;
-       size_t size;
 
        if (!pdata) {
                dev_err(&pdev->dev, "missing platform_data\n");
@@ -160,8 +151,7 @@ static int mv_ehci_probe(struct platform_device *pdev)
        if (!hcd)
                return -ENOMEM;
 
-       size = sizeof(*ehci_mv) + sizeof(struct clk *) * pdata->clknum;
-       ehci_mv = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+       ehci_mv = devm_kzalloc(&pdev->dev, sizeof(*ehci_mv), GFP_KERNEL);
        if (ehci_mv == NULL) {
                dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n");
                retval = -ENOMEM;
@@ -172,16 +162,11 @@ static int mv_ehci_probe(struct platform_device *pdev)
        ehci_mv->pdata = pdata;
        ehci_mv->hcd = hcd;
 
-       ehci_mv->clknum = pdata->clknum;
-       for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) {
-               ehci_mv->clk[clk_i] =
-                   devm_clk_get(&pdev->dev, pdata->clkname[clk_i]);
-               if (IS_ERR(ehci_mv->clk[clk_i])) {
-                       dev_err(&pdev->dev, "error get clck \"%s\"\n",
-                               pdata->clkname[clk_i]);
-                       retval = PTR_ERR(ehci_mv->clk[clk_i]);
-                       goto err_clear_drvdata;
-               }
+       ehci_mv->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(ehci_mv->clk)) {
+               dev_err(&pdev->dev, "error getting clock\n");
+               retval = PTR_ERR(ehci_mv->clk);
+               goto err_clear_drvdata;
        }
 
        r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phyregs");
@@ -225,7 +210,7 @@ static int mv_ehci_probe(struct platform_device *pdev)
                (void __iomem *) ((unsigned long) ehci_mv->cap_regs + offset);
 
        hcd->rsrc_start = r->start;
-       hcd->rsrc_len = r->end - r->start + 1;
+       hcd->rsrc_len = resource_size(r);
        hcd->regs = ehci_mv->op_regs;
 
        hcd->irq = platform_get_irq(pdev, 0);
@@ -240,12 +225,16 @@ static int mv_ehci_probe(struct platform_device *pdev)
 
        ehci_mv->mode = pdata->mode;
        if (ehci_mv->mode == MV_USB_MODE_OTG) {
-#ifdef CONFIG_USB_OTG_UTILS
                ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-               if (IS_ERR_OR_NULL(ehci_mv->otg)) {
-                       dev_err(&pdev->dev,
-                               "unable to find transceiver\n");
-                       retval = -ENODEV;
+               if (IS_ERR(ehci_mv->otg)) {
+                       retval = PTR_ERR(ehci_mv->otg);
+
+                       if (retval == -ENXIO)
+                               dev_info(&pdev->dev, "MV_USB_MODE_OTG "
+                                               "must have CONFIG_USB_PHY enabled\n");
+                       else
+                               dev_err(&pdev->dev,
+                                               "unable to find transceiver\n");
                        goto err_disable_clk;
                }
 
@@ -258,11 +247,6 @@ static int mv_ehci_probe(struct platform_device *pdev)
                }
                /* otg will enable clock before use as host */
                mv_ehci_disable(ehci_mv);
-#else
-               dev_info(&pdev->dev, "MV_USB_MODE_OTG "
-                        "must have CONFIG_USB_OTG_UTILS enabled\n");
-               goto err_disable_clk;
-#endif
        } else {
                if (pdata->set_vbus)
                        pdata->set_vbus(1);
index e9301fb97eaa328337dc2ef0a4dd1329457575d3..c369767b00e26de940eb6e8eca2e1ebe00b7e975 100644 (file)
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
-
 #include <linux/platform_data/usb-ehci-mxc.h>
-
-#include <asm/mach-types.h>
-
 #include "ehci.h"
 
 #define DRIVER_DESC "Freescale On-Chip EHCI Host driver"
@@ -47,7 +43,7 @@ struct ehci_mxc_priv {
 
 static struct hc_driver __read_mostly ehci_mxc_hc_driver;
 
-static const struct ehci_driver_overrides ehci_mxc_overrides __initdata = {
+static const struct ehci_driver_overrides ehci_mxc_overrides __initconst = {
        .extra_priv_size =      sizeof(struct ehci_mxc_priv),
 };
 
@@ -61,8 +57,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct ehci_hcd *ehci;
 
-       dev_info(&pdev->dev, "initializing i.MX USB Controller\n");
-
        if (!pdata) {
                dev_err(dev, "No platform data given, bailing out.\n");
                return -EINVAL;
@@ -178,7 +172,7 @@ err_alloc:
        return ret;
 }
 
-static int __exit ehci_mxc_drv_remove(struct platform_device *pdev)
+static int ehci_mxc_drv_remove(struct platform_device *pdev)
 {
        struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data;
        struct usb_hcd *hcd = platform_get_drvdata(pdev);
index 0555ee42d7cb1882cf284a2f8019ce8a091be961..3d1491b5f3605e68b0a72e1d5786233f5ad94d7b 100644 (file)
@@ -4,10 +4,11 @@
  * Bus Glue for the EHCI controllers in OMAP3/4
  * Tested on several OMAP3 boards, and OMAP4 Pandaboard
  *
- * Copyright (C) 2007-2011 Texas Instruments, Inc.
+ * Copyright (C) 2007-2013 Texas Instruments, Inc.
  *     Author: Vikram Pandita <vikram.pandita@ti.com>
  *     Author: Anand Gadiyar <gadiyar@ti.com>
  *     Author: Keshava Munegowda <keshava_mgowda@ti.com>
+ *     Author: Roger Quadros <rogerq@ti.com>
  *
  * Copyright (C) 2009 Nokia Corporation
  *     Contact: Felipe Balbi <felipe.balbi@nokia.com>
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  *
- * TODO (last updated Feb 27, 2010):
- *     - add kernel-doc
- *     - enable AUTOIDLE
- *     - add suspend/resume
- *     - add HSIC and TLL support
- *     - convert to use hwmod and runtime PM
  */
 
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/usb/ulpi.h>
-#include <linux/regulator/consumer.h>
 #include <linux/pm_runtime.h>
 #include <linux/gpio.h>
 #include <linux/clk.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/of.h>
+#include <linux/dma-mapping.h>
+
+#include "ehci.h"
 
 #include <linux/platform_data/usb-omap.h>
 
 #define        EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT             8
 #define        EHCI_INSNREG05_ULPI_WRDATA_SHIFT                0
 
-/*-------------------------------------------------------------------------*/
+#define DRIVER_DESC "OMAP-EHCI Host Controller driver"
+
+static const char hcd_name[] = "ehci-omap";
 
-static const struct hc_driver ehci_omap_hc_driver;
+/*-------------------------------------------------------------------------*/
 
+struct omap_hcd {
+       struct usb_phy *phy[OMAP3_HS_USB_PORTS]; /* one PHY for each port */
+       int nports;
+};
 
 static inline void ehci_write(void __iomem *base, u32 reg, u32 val)
 {
@@ -72,99 +81,16 @@ static inline u32 ehci_read(void __iomem *base, u32 reg)
        return __raw_readl(base + reg);
 }
 
+/* configure so an HC device and id are always provided */
+/* always called with process context; sleeping is OK */
 
-static void omap_ehci_soft_phy_reset(struct usb_hcd *hcd, u8 port)
-{
-       unsigned long timeout = jiffies + msecs_to_jiffies(1000);
-       unsigned reg = 0;
-
-       reg = ULPI_FUNC_CTRL_RESET
-               /* FUNCTION_CTRL_SET register */
-               | (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT)
-               /* Write */
-               | (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT)
-               /* PORTn */
-               | ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT)
-               /* start ULPI access*/
-               | (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT);
-
-       ehci_write(hcd->regs, EHCI_INSNREG05_ULPI, reg);
-
-       /* Wait for ULPI access completion */
-       while ((ehci_read(hcd->regs, EHCI_INSNREG05_ULPI)
-                       & (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) {
-               cpu_relax();
-
-               if (time_after(jiffies, timeout)) {
-                       dev_dbg(hcd->self.controller,
-                                       "phy reset operation timed out\n");
-                       break;
-               }
-       }
-}
-
-static int omap_ehci_init(struct usb_hcd *hcd)
-{
-       struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
-       int                     rc;
-       struct usbhs_omap_platform_data *pdata;
-
-       pdata = hcd->self.controller->platform_data;
-
-       /* Hold PHYs in reset while initializing EHCI controller */
-       if (pdata->phy_reset) {
-               if (gpio_is_valid(pdata->reset_gpio_port[0]))
-                       gpio_set_value_cansleep(pdata->reset_gpio_port[0], 0);
-
-               if (gpio_is_valid(pdata->reset_gpio_port[1]))
-                       gpio_set_value_cansleep(pdata->reset_gpio_port[1], 0);
-
-               /* Hold the PHY in RESET for enough time till DIR is high */
-               udelay(10);
-       }
-
-       /* Soft reset the PHY using PHY reset command over ULPI */
-       if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY)
-               omap_ehci_soft_phy_reset(hcd, 0);
-       if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY)
-               omap_ehci_soft_phy_reset(hcd, 1);
-
-       /* we know this is the memory we want, no need to ioremap again */
-       ehci->caps = hcd->regs;
-
-       rc = ehci_setup(hcd);
-
-       if (pdata->phy_reset) {
-               /* Hold the PHY in RESET for enough time till
-                * PHY is settled and ready
-                */
-               udelay(10);
-
-               if (gpio_is_valid(pdata->reset_gpio_port[0]))
-                       gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1);
-
-               if (gpio_is_valid(pdata->reset_gpio_port[1]))
-                       gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
-       }
-
-       return rc;
-}
+static struct hc_driver __read_mostly ehci_omap_hc_driver;
 
-static void disable_put_regulator(
-               struct usbhs_omap_platform_data *pdata)
-{
-       int i;
-
-       for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
-               if (pdata->regulator[i]) {
-                       regulator_disable(pdata->regulator[i]);
-                       regulator_put(pdata->regulator[i]);
-               }
-       }
-}
+static const struct ehci_driver_overrides ehci_omap_overrides __initdata = {
+       .extra_priv_size = sizeof(struct omap_hcd),
+};
 
-/* configure so an HC device and id are always provided */
-/* always called with process context; sleeping is OK */
+static u64 omap_ehci_dma_mask = DMA_BIT_MASK(32);
 
 /**
  * ehci_hcd_omap_probe - initialize TI-based HCDs
@@ -175,15 +101,15 @@ static void disable_put_regulator(
  */
 static int ehci_hcd_omap_probe(struct platform_device *pdev)
 {
-       struct device                           *dev = &pdev->dev;
-       struct usbhs_omap_platform_data         *pdata = dev->platform_data;
-       struct resource                         *res;
-       struct usb_hcd                          *hcd;
-       void __iomem                            *regs;
-       int                                     ret = -ENODEV;
-       int                                     irq;
-       int                                     i;
-       char                                    supply[7];
+       struct device *dev = &pdev->dev;
+       struct usbhs_omap_platform_data *pdata = dev->platform_data;
+       struct resource *res;
+       struct usb_hcd  *hcd;
+       void __iomem *regs;
+       int ret = -ENODEV;
+       int irq;
+       int i;
+       struct omap_hcd *omap;
 
        if (usb_disabled())
                return -ENODEV;
@@ -193,52 +119,74 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       irq = platform_get_irq_byname(pdev, "ehci-irq");
-       if (irq < 0) {
-               dev_err(dev, "EHCI irq failed\n");
-               return -ENODEV;
+       /* For DT boot, get platform data from parent. i.e. usbhshost */
+       if (dev->of_node) {
+               pdata = dev->parent->platform_data;
+               dev->platform_data = pdata;
        }
 
-       res =  platform_get_resource_byname(pdev,
-                               IORESOURCE_MEM, "ehci");
-       if (!res) {
-               dev_err(dev, "UHH EHCI get resource failed\n");
+       if (!pdata) {
+               dev_err(dev, "Missing platform data\n");
                return -ENODEV;
        }
 
-       regs = ioremap(res->start, resource_size(res));
-       if (!regs) {
-               dev_err(dev, "UHH EHCI ioremap failed\n");
-               return -ENOMEM;
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(dev, "EHCI irq failed\n");
+               return -ENODEV;
        }
 
+       res =  platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       regs = devm_ioremap_resource(dev, res);
+       if (IS_ERR(regs))
+               return PTR_ERR(regs);
+
+       /*
+        * Right now device-tree probed devices don't get dma_mask set.
+        * Since shared usb code relies on it, set it here for now.
+        * Once we have dma capability bindings this can go away.
+        */
+       if (!pdev->dev.dma_mask)
+               pdev->dev.dma_mask = &omap_ehci_dma_mask;
+
        hcd = usb_create_hcd(&ehci_omap_hc_driver, dev,
                        dev_name(dev));
        if (!hcd) {
-               dev_err(dev, "failed to create hcd with err %d\n", ret);
-               ret = -ENOMEM;
-               goto err_io;
+               dev_err(dev, "Failed to create HCD\n");
+               return -ENOMEM;
        }
 
        hcd->rsrc_start = res->start;
        hcd->rsrc_len = resource_size(res);
        hcd->regs = regs;
-
-       /* get ehci regulator and enable */
-       for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
-               if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) {
-                       pdata->regulator[i] = NULL;
-                       continue;
-               }
-               snprintf(supply, sizeof(supply), "hsusb%d", i);
-               pdata->regulator[i] = regulator_get(dev, supply);
-               if (IS_ERR(pdata->regulator[i])) {
-                       pdata->regulator[i] = NULL;
-                       dev_dbg(dev,
-                       "failed to get ehci port%d regulator\n", i);
-               } else {
-                       regulator_enable(pdata->regulator[i]);
+       hcd_to_ehci(hcd)->caps = regs;
+
+       omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv;
+       omap->nports = pdata->nports;
+
+       platform_set_drvdata(pdev, hcd);
+
+       /* get the PHY devices if needed */
+       for (i = 0 ; i < omap->nports ; i++) {
+               struct usb_phy *phy;
+
+               /* get the PHY device */
+               if (dev->of_node)
+                       phy = devm_usb_get_phy_by_phandle(dev, "phys", i);
+               else
+                       phy = devm_usb_get_phy_dev(dev, i);
+               if (IS_ERR(phy)) {
+                       /* Don't bail out if PHY is not absolutely necessary */
+                       if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY)
+                               continue;
+
+                       ret = PTR_ERR(phy);
+                       dev_err(dev, "Can't get PHY device for port %d: %d\n",
+                                       i, ret);
+                       goto err_phy;
                }
+
+               omap->phy[i] = phy;
        }
 
        pm_runtime_enable(dev);
@@ -262,16 +210,34 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
                goto err_pm_runtime;
        }
 
+       /*
+        * Bring PHYs out of reset.
+        * Even though HSIC mode is a PHY-less mode, the reset
+        * line exists between the chips and can be modelled
+        * as a PHY device for reset control.
+        */
+       for (i = 0; i < omap->nports; i++) {
+               if (!omap->phy[i])
+                       continue;
+
+               usb_phy_init(omap->phy[i]);
+               /* bring PHY out of suspend */
+               usb_phy_set_suspend(omap->phy[i], 0);
+       }
 
        return 0;
 
 err_pm_runtime:
-       disable_put_regulator(pdata);
        pm_runtime_put_sync(dev);
+
+err_phy:
+       for (i = 0; i < omap->nports; i++) {
+               if (omap->phy[i])
+                       usb_phy_shutdown(omap->phy[i]);
+       }
+
        usb_put_hcd(hcd);
 
-err_io:
-       iounmap(regs);
        return ret;
 }
 
@@ -286,14 +252,19 @@ err_io:
  */
 static int ehci_hcd_omap_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);
+       struct omap_hcd *omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv;
+       int i;
 
        usb_remove_hcd(hcd);
-       disable_put_regulator(dev->platform_data);
-       iounmap(hcd->regs);
-       usb_put_hcd(hcd);
 
+       for (i = 0; i < omap->nports; i++) {
+               if (omap->phy[i])
+                       usb_phy_shutdown(omap->phy[i]);
+       }
+
+       usb_put_hcd(hcd);
        pm_runtime_put_sync(dev);
        pm_runtime_disable(dev);
 
@@ -308,6 +279,13 @@ static void ehci_hcd_omap_shutdown(struct platform_device *pdev)
                hcd->driver->shutdown(hcd);
 }
 
+static const struct of_device_id omap_ehci_dt_ids[] = {
+       { .compatible = "ti,ehci-omap" },
+       { }
+};
+
+MODULE_DEVICE_TABLE(of, omap_ehci_dt_ids);
+
 static struct platform_driver ehci_hcd_omap_driver = {
        .probe                  = ehci_hcd_omap_probe,
        .remove                 = ehci_hcd_omap_remove,
@@ -315,56 +293,35 @@ static struct platform_driver ehci_hcd_omap_driver = {
        /*.suspend              = ehci_hcd_omap_suspend, */
        /*.resume               = ehci_hcd_omap_resume, */
        .driver = {
-               .name           = "ehci-omap",
+               .name           = hcd_name,
+               .of_match_table = of_match_ptr(omap_ehci_dt_ids),
        }
 };
 
 /*-------------------------------------------------------------------------*/
 
-static const struct hc_driver ehci_omap_hc_driver = {
-       .description            = hcd_name,
-       .product_desc           = "OMAP-EHCI Host Controller",
-       .hcd_priv_size          = sizeof(struct ehci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2,
-
-       /*
-        * basic lifecycle operations
-        */
-       .reset                  = omap_ehci_init,
-       .start                  = ehci_run,
-       .stop                   = ehci_stop,
-       .shutdown               = ehci_shutdown,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue            = ehci_urb_enqueue,
-       .urb_dequeue            = ehci_urb_dequeue,
-       .endpoint_disable       = ehci_endpoint_disable,
-       .endpoint_reset         = ehci_endpoint_reset,
+static int __init ehci_omap_init(void)
+{
+       if (usb_disabled())
+               return -ENODEV;
 
-       /*
-        * scheduling support
-        */
-       .get_frame_number       = ehci_get_frame,
+       pr_info("%s: " DRIVER_DESC "\n", hcd_name);
 
-       /*
-        * root hub support
-        */
-       .hub_status_data        = ehci_hub_status_data,
-       .hub_control            = ehci_hub_control,
-       .bus_suspend            = ehci_bus_suspend,
-       .bus_resume             = ehci_bus_resume,
+       ehci_init_driver(&ehci_omap_hc_driver, &ehci_omap_overrides);
+       return platform_driver_register(&ehci_hcd_omap_driver);
+}
+module_init(ehci_omap_init);
 
-       .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
+static void __exit ehci_omap_cleanup(void)
+{
+       platform_driver_unregister(&ehci_hcd_omap_driver);
+}
+module_exit(ehci_omap_cleanup);
 
 MODULE_ALIAS("platform:ehci-omap");
 MODULE_AUTHOR("Texas Instruments, Inc.");
 MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>");
+MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
 
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
index 914a3ecfb5d361501a9a9e939d82388e34b795bc..54c57948515051867df3dc8d218699ba6806e5ff 100644 (file)
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+
+#include "ehci.h"
 
 #define rdl(off)       __raw_readl(hcd->regs + (off))
 #define wrl(off, val)  __raw_writel((val), hcd->regs + (off))
 #define USB_PHY_IVREF_CTRL     0x440
 #define USB_PHY_TST_GRP_CTRL   0x450
 
+#define DRIVER_DESC "EHCI orion driver"
+
+static const char hcd_name[] = "ehci-orion";
+
+static struct hc_driver __read_mostly ehci_orion_hc_driver;
+
 /*
  * Implement Orion USB controller specification guidelines
  */
@@ -104,51 +116,6 @@ static void orion_usb_phy_v1_setup(struct usb_hcd *hcd)
        wrl(USB_MODE, 0x13);
 }
 
-static const struct hc_driver ehci_orion_hc_driver = {
-       .description = hcd_name,
-       .product_desc = "Marvell Orion EHCI",
-       .hcd_priv_size = sizeof(struct ehci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq = ehci_irq,
-       .flags = HCD_MEMORY | HCD_USB2,
-
-       /*
-        * basic lifecycle operations
-        */
-       .reset = ehci_setup,
-       .start = ehci_run,
-       .stop = ehci_stop,
-       .shutdown = ehci_shutdown,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue = ehci_urb_enqueue,
-       .urb_dequeue = ehci_urb_dequeue,
-       .endpoint_disable = ehci_endpoint_disable,
-       .endpoint_reset = ehci_endpoint_reset,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number = ehci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data = ehci_hub_status_data,
-       .hub_control = ehci_hub_control,
-       .bus_suspend = ehci_bus_suspend,
-       .bus_resume = ehci_bus_resume,
-       .relinquish_port = ehci_relinquish_port,
-       .port_handed_over = ehci_port_handed_over,
-
-       .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-};
-
 static void
 ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
                             const struct mbus_dram_target_info *dram)
@@ -305,7 +272,7 @@ err1:
        return err;
 }
 
-static int __exit ehci_orion_drv_remove(struct platform_device *pdev)
+static int ehci_orion_drv_remove(struct platform_device *pdev)
 {
        struct usb_hcd *hcd = platform_get_drvdata(pdev);
        struct clk *clk;
@@ -323,8 +290,6 @@ static int __exit ehci_orion_drv_remove(struct platform_device *pdev)
        return 0;
 }
 
-MODULE_ALIAS("platform:orion-ehci");
-
 static const struct of_device_id ehci_orion_dt_ids[] = {
        { .compatible = "marvell,orion-ehci", },
        {},
@@ -333,7 +298,7 @@ MODULE_DEVICE_TABLE(of, ehci_orion_dt_ids);
 
 static struct platform_driver ehci_orion_driver = {
        .probe          = ehci_orion_drv_probe,
-       .remove         = __exit_p(ehci_orion_drv_remove),
+       .remove         = ehci_orion_drv_remove,
        .shutdown       = usb_hcd_platform_shutdown,
        .driver = {
                .name   = "orion-ehci",
@@ -341,3 +306,26 @@ static struct platform_driver ehci_orion_driver = {
                .of_match_table = of_match_ptr(ehci_orion_dt_ids),
        },
 };
+
+static int __init ehci_orion_init(void)
+{
+       if (usb_disabled())
+               return -ENODEV;
+
+       pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+       ehci_init_driver(&ehci_orion_hc_driver, NULL);
+       return platform_driver_register(&ehci_orion_driver);
+}
+module_init(ehci_orion_init);
+
+static void __exit ehci_orion_cleanup(void)
+{
+       platform_driver_unregister(&ehci_orion_driver);
+}
+module_exit(ehci_orion_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_ALIAS("platform:orion-ehci");
+MODULE_AUTHOR("Tzachi Perelstein");
+MODULE_LICENSE("GPL v2");
index 170b9399e09f34b42ec798b8e02985c5b0f71190..595d210655b67ef79e95fdbd5cc0c347060089c6 100644 (file)
@@ -292,17 +292,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                }
        }
 
-#ifdef CONFIG_USB_SUSPEND
-       /* REVISIT: the controller works fine for wakeup iff the root hub
-        * itself is "globally" suspended, but usbcore currently doesn't
-        * understand such things.
-        *
-        * System suspend currently expects to be able to suspend the entire
-        * device tree, device-at-a-time.  If we failed selective suspend
-        * reports, system suspend would fail; so the root hub code must claim
-        * success.  That's lying to usbcore, and it matters for runtime
-        * PM scenarios with selective suspend and remote wakeup...
-        */
+#ifdef CONFIG_PM_RUNTIME
        if (ehci->no_selective_suspend && device_can_wakeup(&pdev->dev))
                ehci_warn(ehci, "selective suspend/wakeup unavailable\n");
 #endif
@@ -385,7 +375,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
 
 static struct hc_driver __read_mostly ehci_pci_hc_driver;
 
-static const struct ehci_driver_overrides pci_overrides __initdata = {
+static const struct ehci_driver_overrides pci_overrides __initconst = {
        .reset =                ehci_pci_setup,
 };
 
index ca7506390542bf0e5c75232724477e4832f68f1c..f47f2594c9d43f337719daaaf771c2ad7e5fd9d8 100644 (file)
  *
  * Licensed under the GNU/GPL. See COPYING for details.
  */
+#include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/hrtimer.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
@@ -58,26 +60,36 @@ static int ehci_platform_reset(struct usb_hcd *hcd)
 
 static struct hc_driver __read_mostly ehci_platform_hc_driver;
 
-static const struct ehci_driver_overrides platform_overrides __initdata = {
+static const struct ehci_driver_overrides platform_overrides __initconst = {
        .reset =        ehci_platform_reset,
 };
 
+static struct usb_ehci_pdata ehci_platform_defaults;
+
 static int ehci_platform_probe(struct platform_device *dev)
 {
        struct usb_hcd *hcd;
        struct resource *res_mem;
-       struct usb_ehci_pdata *pdata = dev->dev.platform_data;
+       struct usb_ehci_pdata *pdata;
        int irq;
        int err = -ENOMEM;
 
-       if (!pdata) {
-               WARN_ON(1);
-               return -ENODEV;
-       }
-
        if (usb_disabled())
                return -ENODEV;
 
+       /*
+        * use reasonable defaults so platforms don't have to provide these.
+        * with DT probing on ARM, none of these are set.
+        */
+       if (!dev->dev.platform_data)
+               dev->dev.platform_data = &ehci_platform_defaults;
+       if (!dev->dev.dma_mask)
+               dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
+       if (!dev->dev.coherent_dma_mask)
+               dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+
+       pdata = dev->dev.platform_data;
+
        irq = platform_get_irq(dev, 0);
        if (irq < 0) {
                dev_err(&dev->dev, "no irq provided");
@@ -139,6 +151,9 @@ static int ehci_platform_remove(struct platform_device *dev)
        if (pdata->power_off)
                pdata->power_off(dev);
 
+       if (pdata == &ehci_platform_defaults)
+               dev->dev.platform_data = NULL;
+
        return 0;
 }
 
@@ -183,6 +198,12 @@ static int ehci_platform_resume(struct device *dev)
 #define ehci_platform_resume   NULL
 #endif /* CONFIG_PM */
 
+static const struct of_device_id vt8500_ehci_ids[] = {
+       { .compatible = "via,vt8500-ehci", },
+       { .compatible = "wm,prizm-ehci", },
+       {}
+};
+
 static const struct platform_device_id ehci_platform_table[] = {
        { "ehci-platform", 0 },
        { }
@@ -203,6 +224,7 @@ static struct platform_driver ehci_platform_driver = {
                .owner  = THIS_MODULE,
                .name   = "ehci-platform",
                .pm     = &ehci_platform_pm_ops,
+               .of_match_table = of_match_ptr(vt8500_ehci_ids),
        }
 };
 
index df5925a4f0dba9f6eef083d9e2ad148d308e1d4d..fd983771b02559cb56c6210e6813d9b223a80f7a 100644 (file)
@@ -221,7 +221,6 @@ static int ps3_ehci_remove(struct ps3_system_bus_device *dev)
 
        tmp = hcd->irq;
 
-       ehci_shutdown(hcd);
        usb_remove_hcd(hcd);
 
        ps3_system_bus_set_drvdata(dev, NULL);
index 23d13690428591b3c71d6c10bc9b29a4ffd0c973..d34b399b78e2c30665792857a34615b6c9a0c227 100644 (file)
@@ -90,7 +90,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)
        struct ehci_qh_hw *hw = qh->hw;
 
        /* writes to an active overlay are unsafe */
-       BUG_ON(qh->qh_state != QH_STATE_IDLE);
+       WARN_ON(qh->qh_state != QH_STATE_IDLE);
 
        hw->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);
        hw->hw_alt_next = EHCI_LIST_END(ehci);
@@ -123,26 +123,19 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
        struct ehci_qtd *qtd;
 
-       if (list_empty (&qh->qtd_list))
-               qtd = qh->dummy;
-       else {
-               qtd = list_entry (qh->qtd_list.next,
-                               struct ehci_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 (qh->hw->hw_token & ACTIVE_BIT(ehci)) {
-                       qh->hw->hw_qtd_next = qtd->hw_next;
-                       qtd = NULL;
-               }
-       }
+       qtd = list_entry(qh->qtd_list.next, struct ehci_qtd, qtd_list);
 
-       if (qtd)
-               qh_update (ehci, qh, qtd);
+       /*
+        * 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 (qh->hw->hw_token & ACTIVE_BIT(ehci))
+               qh->hw->hw_qtd_next = qtd->hw_next;
+       else
+               qh_update(ehci, qh, qtd);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -299,8 +292,8 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_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.
+ * Chases up to qh->hw_current.  Returns nonzero if the caller should
+ * unlink qh.
  */
 static unsigned
 qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
@@ -309,13 +302,9 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
        struct list_head        *entry, *tmp;
        int                     last_status;
        int                     stopped;
-       unsigned                count = 0;
        u8                      state;
        struct ehci_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.
@@ -333,7 +322,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
  rescan:
        last = NULL;
        last_status = -EINPROGRESS;
-       qh->needs_rescan = 0;
+       qh->dequeue_during_giveback = 0;
 
        /* remove de-activated QTDs from front of queue.
         * after faults (including short reads), cleanup this urb
@@ -352,7 +341,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
                if (last) {
                        if (likely (last->urb != urb)) {
                                ehci_urb_done(ehci, last->urb, last_status);
-                               count++;
                                last_status = -EINPROGRESS;
                        }
                        ehci_qtd_free (ehci, last);
@@ -526,23 +514,16 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
        /* last urb's completion might still need calling */
        if (likely (last != NULL)) {
                ehci_urb_done(ehci, last->urb, last_status);
-               count++;
                ehci_qtd_free (ehci, last);
        }
 
        /* Do we need to rescan for URBs dequeued during a giveback? */
-       if (unlikely(qh->needs_rescan)) {
+       if (unlikely(qh->dequeue_during_giveback)) {
                /* 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;
+               /* Otherwise the caller must unlink the QH. */
        }
 
        /* restore original state; caller must unlink or relink */
@@ -551,33 +532,23 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
        /* 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).
+        *
+        * 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 ...
         */
-       if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci)) {
-               switch (state) {
-               case QH_STATE_IDLE:
-                       qh_refresh(ehci, 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 ...
-                        */
+       if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci))
+               qh->exception = 1;
 
-                       /* Tell the caller to start an unlink */
-                       qh->needs_rescan = 1;
-                       break;
-               /* otherwise, unlink already started */
-               }
-       }
-
-       return count;
+       /* Let the caller know if the QH needs to be unlinked. */
+       return qh->exception;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -957,14 +928,13 @@ done:
 
        /* NOTE:  if (PIPE_INTERRUPT) { scheduler sets s-mask } */
 
-       /* init as live, toggle clear, advance to dummy */
+       /* init as live, toggle clear */
        qh->qh_state = QH_STATE_IDLE;
        hw = qh->hw;
        hw->hw_info1 = cpu_to_hc32(ehci, info1);
        hw->hw_info2 = cpu_to_hc32(ehci, info2);
        qh->is_out = !is_input;
        usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1);
-       qh_refresh (ehci, qh);
        return qh;
 }
 
@@ -988,8 +958,9 @@ static void disable_async(struct ehci_hcd *ehci)
        if (--ehci->async_count)
                return;
 
-       /* The async schedule and async_unlink list are supposed to be empty */
-       WARN_ON(ehci->async->qh_next.qh || ehci->async_unlink);
+       /* The async schedule and unlink lists are supposed to be empty */
+       WARN_ON(ehci->async->qh_next.qh || !list_empty(&ehci->async_unlink) ||
+                       !list_empty(&ehci->async_idle));
 
        /* Don't turn off the schedule until ASS is 1 */
        ehci_poll_ASS(ehci);
@@ -1020,8 +991,9 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
        head->qh_next.qh = qh;
        head->hw->hw_next = dma;
 
-       qh->xacterrs = 0;
        qh->qh_state = QH_STATE_LINKED;
+       qh->xacterrs = 0;
+       qh->exception = 0;
        /* qtd completions reported later by interrupt */
 
        enable_async(ehci);
@@ -1179,11 +1151,7 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
 
        /* Add to the end of the list of QHs waiting for the next IAAD */
        qh->qh_state = QH_STATE_UNLINK_WAIT;
-       if (ehci->async_unlink)
-               ehci->async_unlink_last->unlink_next = qh;
-       else
-               ehci->async_unlink = qh;
-       ehci->async_unlink_last = qh;
+       list_add_tail(&qh->unlink_node, &ehci->async_unlink);
 
        /* Unlink it from the schedule */
        prev = ehci->async;
@@ -1196,44 +1164,19 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
                ehci->qh_scan_next = qh->qh_next.qh;
 }
 
-static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
+static void start_iaa_cycle(struct ehci_hcd *ehci)
 {
-       /*
-        * Do nothing if an IAA cycle is already running or
-        * if one will be started shortly.
-        */
-       if (ehci->async_iaa || ehci->async_unlinking)
+       /* Do nothing if an IAA cycle is already running */
+       if (ehci->iaa_in_progress)
                return;
+       ehci->iaa_in_progress = true;
 
        /* If the controller isn't running, we don't have to wait for it */
        if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) {
-
-               /* Do all the waiting QHs */
-               ehci->async_iaa = ehci->async_unlink;
-               ehci->async_unlink = NULL;
-
-               if (!nested)            /* Avoid recursion */
-                       end_unlink_async(ehci);
+               end_unlink_async(ehci);
 
        /* Otherwise start a new IAA cycle */
        } else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) {
-               struct ehci_qh          *qh;
-
-               /* Do only the first waiting QH (nVidia bug?) */
-               qh = ehci->async_unlink;
-
-               /*
-                * Intel (?) bug: The HC can write back the overlay region
-                * even after the IAA interrupt occurs.  In self-defense,
-                * always go through two IAA cycles for each QH.
-                */
-               if (qh->qh_state == QH_STATE_UNLINK_WAIT) {
-                       qh->qh_state = QH_STATE_UNLINK;
-               } else {
-                       ehci->async_iaa = qh;
-                       ehci->async_unlink = qh->unlink_next;
-                       qh->unlink_next = NULL;
-               }
 
                /* Make sure the unlinks are all visible to the hardware */
                wmb();
@@ -1250,36 +1193,73 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
 static void end_unlink_async(struct ehci_hcd *ehci)
 {
        struct ehci_qh          *qh;
+       bool                    early_exit;
 
        if (ehci->has_synopsys_hc_bug)
                ehci_writel(ehci, (u32) ehci->async->qh_dma,
                            &ehci->regs->async_next);
 
+       /* The current IAA cycle has ended */
+       ehci->iaa_in_progress = false;
+
+       if (list_empty(&ehci->async_unlink))
+               return;
+       qh = list_first_entry(&ehci->async_unlink, struct ehci_qh,
+                       unlink_node);   /* QH whose IAA cycle just ended */
+
+       /*
+        * If async_unlinking is set then this routine is already running,
+        * either on the stack or on another CPU.
+        */
+       early_exit = ehci->async_unlinking;
+
+       /* If the controller isn't running, process all the waiting QHs */
+       if (ehci->rh_state < EHCI_RH_RUNNING)
+               list_splice_tail_init(&ehci->async_unlink, &ehci->async_idle);
+
+       /*
+        * Intel (?) bug: The HC can write back the overlay region even
+        * after the IAA interrupt occurs.  In self-defense, always go
+        * through two IAA cycles for each QH.
+        */
+       else if (qh->qh_state == QH_STATE_UNLINK_WAIT) {
+               qh->qh_state = QH_STATE_UNLINK;
+               early_exit = true;
+       }
+
+       /* Otherwise process only the first waiting QH (NVIDIA bug?) */
+       else
+               list_move_tail(&qh->unlink_node, &ehci->async_idle);
+
+       /* Start a new IAA cycle if any QHs are waiting for it */
+       if (!list_empty(&ehci->async_unlink))
+               start_iaa_cycle(ehci);
+
+       /*
+        * Don't allow nesting or concurrent calls,
+        * or wait for the second IAA cycle for the next QH.
+        */
+       if (early_exit)
+               return;
+
        /* Process the idle QHs */
- restart:
        ehci->async_unlinking = true;
-       while (ehci->async_iaa) {
-               qh = ehci->async_iaa;
-               ehci->async_iaa = qh->unlink_next;
-               qh->unlink_next = NULL;
+       while (!list_empty(&ehci->async_idle)) {
+               qh = list_first_entry(&ehci->async_idle, struct ehci_qh,
+                               unlink_node);
+               list_del(&qh->unlink_node);
 
                qh->qh_state = QH_STATE_IDLE;
                qh->qh_next.qh = NULL;
 
-               qh_completions(ehci, qh);
+               if (!list_empty(&qh->qtd_list))
+                       qh_completions(ehci, qh);
                if (!list_empty(&qh->qtd_list) &&
                                ehci->rh_state == EHCI_RH_RUNNING)
                        qh_link_async(ehci, qh);
                disable_async(ehci);
        }
        ehci->async_unlinking = false;
-
-       /* Start a new IAA cycle if any QHs are waiting for it */
-       if (ehci->async_unlink) {
-               start_iaa_cycle(ehci, true);
-               if (unlikely(ehci->rh_state < EHCI_RH_RUNNING))
-                       goto restart;
-       }
 }
 
 static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh);
@@ -1288,7 +1268,6 @@ static void unlink_empty_async(struct ehci_hcd *ehci)
 {
        struct ehci_qh          *qh;
        struct ehci_qh          *qh_to_unlink = NULL;
-       bool                    check_unlinks_later = false;
        int                     count = 0;
 
        /* Find the last async QH which has been empty for a timer cycle */
@@ -1296,15 +1275,13 @@ static void unlink_empty_async(struct ehci_hcd *ehci)
                if (list_empty(&qh->qtd_list) &&
                                qh->qh_state == QH_STATE_LINKED) {
                        ++count;
-                       if (qh->unlink_cycle == ehci->async_unlink_cycle)
-                               check_unlinks_later = true;
-                       else
+                       if (qh->unlink_cycle != ehci->async_unlink_cycle)
                                qh_to_unlink = qh;
                }
        }
 
        /* If nothing else is being unlinked, unlink the last empty QH */
-       if (!ehci->async_iaa && !ehci->async_unlink && qh_to_unlink) {
+       if (list_empty(&ehci->async_unlink) && qh_to_unlink) {
                start_unlink_async(ehci, qh_to_unlink);
                --count;
        }
@@ -1317,7 +1294,7 @@ static void unlink_empty_async(struct ehci_hcd *ehci)
 }
 
 /* The root hub is suspended; unlink all the async QHs */
-static void unlink_empty_async_suspended(struct ehci_hcd *ehci)
+static void __maybe_unused unlink_empty_async_suspended(struct ehci_hcd *ehci)
 {
        struct ehci_qh          *qh;
 
@@ -1326,7 +1303,7 @@ static void unlink_empty_async_suspended(struct ehci_hcd *ehci)
                WARN_ON(!list_empty(&qh->qtd_list));
                single_unlink_async(ehci, qh);
        }
-       start_iaa_cycle(ehci, false);
+       start_iaa_cycle(ehci);
 }
 
 /* makes sure the async qh will become idle */
@@ -1334,19 +1311,12 @@ static void unlink_empty_async_suspended(struct ehci_hcd *ehci)
 
 static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_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;
+       /* If the QH isn't linked then there's nothing we can do. */
+       if (qh->qh_state != QH_STATE_LINKED)
                return;
-       }
 
        single_unlink_async(ehci, qh);
-       start_iaa_cycle(ehci, false);
+       start_iaa_cycle(ehci);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1360,7 +1330,7 @@ static void scan_async (struct ehci_hcd *ehci)
        while (ehci->qh_scan_next) {
                qh = ehci->qh_scan_next;
                ehci->qh_scan_next = qh->qh_next.qh;
- rescan:
+
                /* clean any finished work for this qh */
                if (!list_empty(&qh->qtd_list)) {
                        int temp;
@@ -1373,14 +1343,13 @@ static void scan_async (struct ehci_hcd *ehci)
                         * in single_unlink_async().
                         */
                        temp = qh_completions(ehci, qh);
-                       if (qh->needs_rescan) {
+                       if (unlikely(temp)) {
                                start_unlink_async(ehci, qh);
                        } else if (list_empty(&qh->qtd_list)
                                        && qh->qh_state == QH_STATE_LINKED) {
                                qh->unlink_cycle = ehci->async_unlink_cycle;
                                check_unlinks_later = true;
-                       } else if (temp != 0)
-                               goto rescan;
+                       }
                }
        }
 
index 20ebf6a8b7f4736c9cd448a9653de41b9d88c48a..635775278c7fec525a1a3566fce05bb77f3ad77e 100644 (file)
  */
 
 #include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/of.h>
-#include <linux/platform_device.h>
 #include <linux/of_gpio.h>
+#include <linux/platform_device.h>
 #include <linux/platform_data/usb-ehci-s5p.h>
 #include <linux/usb/phy.h>
 #include <linux/usb/samsung_usb_phy.h>
-#include <plat/usb-phy.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/otg.h>
+
+#include "ehci.h"
+
+#define DRIVER_DESC "EHCI s5p driver"
 
 #define EHCI_INSNREG00(base)                   (base + 0x90)
 #define EHCI_INSNREG00_ENA_INCR16              (0x1 << 25)
        (EHCI_INSNREG00_ENA_INCR16 | EHCI_INSNREG00_ENA_INCR8 | \
         EHCI_INSNREG00_ENA_INCR4 | EHCI_INSNREG00_ENA_INCRX_ALIGN)
 
+static const char hcd_name[] = "ehci-s5p";
+static struct hc_driver __read_mostly s5p_ehci_hc_driver;
+
 struct s5p_ehci_hcd {
-       struct device *dev;
-       struct usb_hcd *hcd;
        struct clk *clk;
        struct usb_phy *phy;
        struct usb_otg *otg;
        struct s5p_ehci_platdata *pdata;
 };
 
-static const struct hc_driver s5p_ehci_hc_driver = {
-       .description            = hcd_name,
-       .product_desc           = "S5P EHCI Host Controller",
-       .hcd_priv_size          = sizeof(struct ehci_hcd),
-
-       .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2,
-
-       .reset                  = ehci_setup,
-       .start                  = ehci_run,
-       .stop                   = ehci_stop,
-       .shutdown               = ehci_shutdown,
-
-       .get_frame_number       = ehci_get_frame,
-
-       .urb_enqueue            = ehci_urb_enqueue,
-       .urb_dequeue            = ehci_urb_dequeue,
-       .endpoint_disable       = ehci_endpoint_disable,
-       .endpoint_reset         = ehci_endpoint_reset,
-
-       .hub_status_data        = ehci_hub_status_data,
-       .hub_control            = ehci_hub_control,
-       .bus_suspend            = ehci_bus_suspend,
-       .bus_resume             = ehci_bus_resume,
-
-       .relinquish_port        = ehci_relinquish_port,
-       .port_handed_over       = ehci_port_handed_over,
-
-       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
-};
-
-static void s5p_ehci_phy_enable(struct s5p_ehci_hcd *s5p_ehci)
-{
-       struct platform_device *pdev = to_platform_device(s5p_ehci->dev);
-
-       if (s5p_ehci->phy)
-               usb_phy_init(s5p_ehci->phy);
-       else if (s5p_ehci->pdata->phy_init)
-               s5p_ehci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
-}
-
-static void s5p_ehci_phy_disable(struct s5p_ehci_hcd *s5p_ehci)
-{
-       struct platform_device *pdev = to_platform_device(s5p_ehci->dev);
-
-       if (s5p_ehci->phy)
-               usb_phy_shutdown(s5p_ehci->phy);
-       else if (s5p_ehci->pdata->phy_exit)
-               s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
-}
+#define to_s5p_ehci(hcd)      (struct s5p_ehci_hcd *)(hcd_to_ehci(hcd)->priv)
 
 static void s5p_setup_vbus_gpio(struct platform_device *pdev)
 {
+       struct device *dev = &pdev->dev;
        int err;
        int gpio;
 
-       if (!pdev->dev.of_node)
+       if (!dev->of_node)
                return;
 
-       gpio = of_get_named_gpio(pdev->dev.of_node,
-                       "samsung,vbus-gpio", 0);
+       gpio = of_get_named_gpio(dev->of_node, "samsung,vbus-gpio", 0);
        if (!gpio_is_valid(gpio))
                return;
 
-       err = gpio_request_one(gpio, GPIOF_OUT_INIT_HIGH, "ehci_vbus_gpio");
+       err = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_HIGH,
+                                   "ehci_vbus_gpio");
        if (err)
-               dev_err(&pdev->dev, "can't request ehci vbus gpio %d", gpio);
+               dev_err(dev, "can't request ehci vbus gpio %d", gpio);
 }
 
 static u64 ehci_s5p_dma_mask = DMA_BIT_MASK(32);
@@ -133,13 +96,15 @@ static int s5p_ehci_probe(struct platform_device *pdev)
 
        s5p_setup_vbus_gpio(pdev);
 
-       s5p_ehci = devm_kzalloc(&pdev->dev, sizeof(struct s5p_ehci_hcd),
-                               GFP_KERNEL);
-       if (!s5p_ehci)
+       hcd = usb_create_hcd(&s5p_ehci_hc_driver,
+                            &pdev->dev, dev_name(&pdev->dev));
+       if (!hcd) {
+               dev_err(&pdev->dev, "Unable to create HCD\n");
                return -ENOMEM;
-
+       }
+       s5p_ehci = to_s5p_ehci(hcd);
        phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-       if (IS_ERR_OR_NULL(phy)) {
+       if (IS_ERR(phy)) {
                /* Fallback to pdata */
                if (!pdata) {
                        dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
@@ -152,16 +117,6 @@ static int s5p_ehci_probe(struct platform_device *pdev)
                s5p_ehci->otg = phy->otg;
        }
 
-       s5p_ehci->dev = &pdev->dev;
-
-       hcd = usb_create_hcd(&s5p_ehci_hc_driver, &pdev->dev,
-                                       dev_name(&pdev->dev));
-       if (!hcd) {
-               dev_err(&pdev->dev, "Unable to create HCD\n");
-               return -ENOMEM;
-       }
-
-       s5p_ehci->hcd = hcd;
        s5p_ehci->clk = devm_clk_get(&pdev->dev, "usbhost");
 
        if (IS_ERR(s5p_ehci->clk)) {
@@ -198,9 +153,12 @@ static int s5p_ehci_probe(struct platform_device *pdev)
        }
 
        if (s5p_ehci->otg)
-               s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
+               s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self);
 
-       s5p_ehci_phy_enable(s5p_ehci);
+       if (s5p_ehci->phy)
+               usb_phy_init(s5p_ehci->phy);
+       else if (s5p_ehci->pdata->phy_init)
+               s5p_ehci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
 
        ehci = hcd_to_ehci(hcd);
        ehci->caps = hcd->regs;
@@ -214,12 +172,15 @@ static int s5p_ehci_probe(struct platform_device *pdev)
                goto fail_add_hcd;
        }
 
-       platform_set_drvdata(pdev, s5p_ehci);
+       platform_set_drvdata(pdev, hcd);
 
        return 0;
 
 fail_add_hcd:
-       s5p_ehci_phy_disable(s5p_ehci);
+       if (s5p_ehci->phy)
+               usb_phy_shutdown(s5p_ehci->phy);
+       else if (s5p_ehci->pdata->phy_exit)
+               s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
 fail_io:
        clk_disable_unprepare(s5p_ehci->clk);
 fail_clk:
@@ -229,15 +190,18 @@ fail_clk:
 
 static int s5p_ehci_remove(struct platform_device *pdev)
 {
-       struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev);
-       struct usb_hcd *hcd = s5p_ehci->hcd;
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
+       struct s5p_ehci_hcd *s5p_ehci = to_s5p_ehci(hcd);
 
        usb_remove_hcd(hcd);
 
        if (s5p_ehci->otg)
-               s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
+               s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self);
 
-       s5p_ehci_phy_disable(s5p_ehci);
+       if (s5p_ehci->phy)
+               usb_phy_shutdown(s5p_ehci->phy);
+       else if (s5p_ehci->pdata->phy_exit)
+               s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
 
        clk_disable_unprepare(s5p_ehci->clk);
 
@@ -248,8 +212,7 @@ static int s5p_ehci_remove(struct platform_device *pdev)
 
 static void s5p_ehci_shutdown(struct platform_device *pdev)
 {
-       struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev);
-       struct usb_hcd *hcd = s5p_ehci->hcd;
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
        if (hcd->driver->shutdown)
                hcd->driver->shutdown(hcd);
@@ -258,17 +221,22 @@ static void s5p_ehci_shutdown(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int s5p_ehci_suspend(struct device *dev)
 {
-       struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
-       struct usb_hcd *hcd = s5p_ehci->hcd;
+       struct usb_hcd *hcd = dev_get_drvdata(dev);
+       struct s5p_ehci_hcd *s5p_ehci = to_s5p_ehci(hcd);
+       struct platform_device *pdev = to_platform_device(dev);
+
        bool do_wakeup = device_may_wakeup(dev);
        int rc;
 
        rc = ehci_suspend(hcd, do_wakeup);
 
        if (s5p_ehci->otg)
-               s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
+               s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self);
 
-       s5p_ehci_phy_disable(s5p_ehci);
+       if (s5p_ehci->phy)
+               usb_phy_shutdown(s5p_ehci->phy);
+       else if (s5p_ehci->pdata->phy_exit)
+               s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
 
        clk_disable_unprepare(s5p_ehci->clk);
 
@@ -277,15 +245,19 @@ static int s5p_ehci_suspend(struct device *dev)
 
 static int s5p_ehci_resume(struct device *dev)
 {
-       struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
-       struct usb_hcd *hcd = s5p_ehci->hcd;
+       struct usb_hcd *hcd = dev_get_drvdata(dev);
+       struct  s5p_ehci_hcd *s5p_ehci = to_s5p_ehci(hcd);
+       struct platform_device *pdev = to_platform_device(dev);
 
        clk_prepare_enable(s5p_ehci->clk);
 
        if (s5p_ehci->otg)
-               s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
+               s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self);
 
-       s5p_ehci_phy_enable(s5p_ehci);
+       if (s5p_ehci->phy)
+               usb_phy_init(s5p_ehci->phy);
+       else if (s5p_ehci->pdata->phy_init)
+               s5p_ehci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
 
        /* DMA burst Enable */
        writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
@@ -322,5 +294,29 @@ static struct platform_driver s5p_ehci_driver = {
                .of_match_table = of_match_ptr(exynos_ehci_match),
        }
 };
+static const struct ehci_driver_overrides s5p_overrides __initdata = {
+       .extra_priv_size = sizeof(struct s5p_ehci_hcd),
+};
+
+static int __init ehci_s5p_init(void)
+{
+       if (usb_disabled())
+               return -ENODEV;
+
+       pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+       ehci_init_driver(&s5p_ehci_hc_driver, &s5p_overrides);
+       return platform_driver_register(&s5p_ehci_driver);
+}
+module_init(ehci_s5p_init);
+
+static void __exit ehci_s5p_cleanup(void)
+{
+       platform_driver_unregister(&s5p_ehci_driver);
+}
+module_exit(ehci_s5p_cleanup);
 
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_ALIAS("platform:s5p-ehci");
+MODULE_AUTHOR("Jingoo Han");
+MODULE_AUTHOR("Joonyoung Shim");
+MODULE_LICENSE("GPL v2");
index 010f686d8881fc9796fd3bbee1c1f5c3aa71e878..acff5b8f6e89dd89edf37d30377c2b1b86307c68 100644 (file)
@@ -539,6 +539,7 @@ static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
        }
        qh->qh_state = QH_STATE_LINKED;
        qh->xacterrs = 0;
+       qh->exception = 0;
 
        /* update per-qh bandwidth for usbfs */
        ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->period
@@ -602,15 +603,9 @@ static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)
 
 static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_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;
+       /* If the QH isn't linked then there's nothing we can do. */
+       if (qh->qh_state != QH_STATE_LINKED)
                return;
-       }
 
        qh_unlink_periodic (ehci, qh);
 
@@ -625,17 +620,13 @@ static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
        qh->unlink_cycle = ehci->intr_unlink_cycle;
 
        /* New entries go at the end of the intr_unlink list */
-       if (ehci->intr_unlink)
-               ehci->intr_unlink_last->unlink_next = qh;
-       else
-               ehci->intr_unlink = qh;
-       ehci->intr_unlink_last = qh;
+       list_add_tail(&qh->unlink_node, &ehci->intr_unlink);
 
        if (ehci->intr_unlinking)
                ;       /* Avoid recursive calls */
        else if (ehci->rh_state < EHCI_RH_RUNNING)
                ehci_handle_intr_unlinks(ehci);
-       else if (ehci->intr_unlink == qh) {
+       else if (ehci->intr_unlink.next == &qh->unlink_node) {
                ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true);
                ++ehci->intr_unlink_cycle;
        }
@@ -649,7 +640,8 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)
        qh->qh_state = QH_STATE_IDLE;
        hw->hw_next = EHCI_LIST_END(ehci);
 
-       qh_completions(ehci, qh);
+       if (!list_empty(&qh->qtd_list))
+               qh_completions(ehci, qh);
 
        /* reschedule QH iff another request is queued */
        if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) {
@@ -792,7 +784,6 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
        unsigned        frame;          /* 0..(qh->period - 1), or NO_FRAME */
        struct ehci_qh_hw       *hw = qh->hw;
 
-       qh_refresh(ehci, qh);
        hw->hw_next = EHCI_LIST_END(ehci);
        frame = qh->start;
 
@@ -844,8 +835,6 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)
        } else
                ehci_dbg (ehci, "reused qh %p schedule\n", qh);
 
-       /* stuff into the periodic schedule */
-       qh_link_periodic(ehci, qh);
 done:
        return status;
 }
@@ -891,6 +880,12 @@ static int intr_submit (
        qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv);
        BUG_ON (qh == NULL);
 
+       /* stuff into the periodic schedule */
+       if (qh->qh_state == QH_STATE_IDLE) {
+               qh_refresh(ehci, qh);
+               qh_link_periodic(ehci, qh);
+       }
+
        /* ... update usbfs periodic stats */
        ehci_to_hcd(ehci)->self.bandwidth_int_reqs++;
 
@@ -911,7 +906,7 @@ static void scan_intr(struct ehci_hcd *ehci)
 
        list_for_each_entry_safe(qh, ehci->qh_scan_next, &ehci->intr_qh_list,
                        intr_node) {
- rescan:
+
                /* clean any finished work for this qh */
                if (!list_empty(&qh->qtd_list)) {
                        int temp;
@@ -924,12 +919,9 @@ static void scan_intr(struct ehci_hcd *ehci)
                         * in qh_unlink_periodic().
                         */
                        temp = qh_completions(ehci, qh);
-                       if (unlikely(qh->needs_rescan ||
-                                       (list_empty(&qh->qtd_list) &&
-                                               qh->qh_state == QH_STATE_LINKED)))
+                       if (unlikely(temp || (list_empty(&qh->qtd_list) &&
+                                       qh->qh_state == QH_STATE_LINKED)))
                                start_unlink_intr(ehci, qh);
-                       else if (temp != 0)
-                               goto rescan;
                }
        }
 }
index 3565a300f401347315b968b0c09131df294e317f..b44d716ddc825e1b5905e0f4cbf481f3e176e83a 100644 (file)
@@ -77,7 +77,6 @@ static const struct hc_driver ehci_sh_hc_driver = {
 
 static int ehci_hcd_sh_probe(struct platform_device *pdev)
 {
-       const struct hc_driver *driver = &ehci_sh_hc_driver;
        struct resource *res;
        struct ehci_sh_priv *priv;
        struct ehci_sh_platdata *pdata;
@@ -170,7 +169,7 @@ fail_create_hcd:
        return ret;
 }
 
-static int __exit ehci_hcd_sh_remove(struct platform_device *pdev)
+static int ehci_hcd_sh_remove(struct platform_device *pdev)
 {
        struct ehci_sh_priv *priv = platform_get_drvdata(pdev);
        struct usb_hcd *hcd = priv->hcd;
@@ -196,7 +195,7 @@ static void ehci_hcd_sh_shutdown(struct platform_device *pdev)
 
 static struct platform_driver ehci_hcd_sh_driver = {
        .probe          = ehci_hcd_sh_probe,
-       .remove         = __exit_p(ehci_hcd_sh_remove),
+       .remove         = ehci_hcd_sh_remove,
        .shutdown       = ehci_hcd_sh_shutdown,
        .driver         = {
                .name   = "sh_ehci",
index 466c1bb5b96728c6514ef45e7348a747868398f9..61ecfb3d52f5d102f78d058fa5c032d37e0e7742 100644 (file)
@@ -1,5 +1,5 @@
 /*
-* Driver for EHCI HCD on SPEAR SOC
+* Driver for EHCI HCD on SPEAr SOC
 *
 * Copyright (C) 2010 ST Micro Electronics,
 * Deepak Sikri <deepak.sikri@st.com>
 */
 
 #include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
 #include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
 
-struct spear_ehci {
-       struct ehci_hcd ehci;
-       struct clk *clk;
-};
-
-#define to_spear_ehci(hcd)     (struct spear_ehci *)hcd_to_ehci(hcd)
+#include "ehci.h"
 
-static void spear_start_ehci(struct spear_ehci *ehci)
-{
-       clk_prepare_enable(ehci->clk);
-}
+#define DRIVER_DESC "EHCI SPEAr driver"
 
-static void spear_stop_ehci(struct spear_ehci *ehci)
-{
-       clk_disable_unprepare(ehci->clk);
-}
+static const char hcd_name[] = "SPEAr-ehci";
 
-static int ehci_spear_setup(struct usb_hcd *hcd)
-{
-       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-
-       /* registers start at offset 0x0 */
-       ehci->caps = hcd->regs;
+struct spear_ehci {
+       struct clk *clk;
+};
 
-       return ehci_setup(hcd);
-}
+#define to_spear_ehci(hcd)     (struct spear_ehci *)(hcd_to_ehci(hcd)->priv)
 
-static const struct hc_driver ehci_spear_hc_driver = {
-       .description                    = hcd_name,
-       .product_desc                   = "SPEAr EHCI",
-       .hcd_priv_size                  = sizeof(struct spear_ehci),
-
-       /* generic hardware linkage */
-       .irq                            = ehci_irq,
-       .flags                          = HCD_MEMORY | HCD_USB2,
-
-       /* basic lifecycle operations */
-       .reset                          = ehci_spear_setup,
-       .start                          = ehci_run,
-       .stop                           = ehci_stop,
-       .shutdown                       = ehci_shutdown,
-
-       /* managing i/o requests and associated device resources */
-       .urb_enqueue                    = ehci_urb_enqueue,
-       .urb_dequeue                    = ehci_urb_dequeue,
-       .endpoint_disable               = ehci_endpoint_disable,
-       .endpoint_reset                 = ehci_endpoint_reset,
-
-       /* scheduling support */
-       .get_frame_number               = ehci_get_frame,
-
-       /* root hub support */
-       .hub_status_data                = ehci_hub_status_data,
-       .hub_control                    = ehci_hub_control,
-       .bus_suspend                    = ehci_bus_suspend,
-       .bus_resume                     = ehci_bus_resume,
-       .relinquish_port                = ehci_relinquish_port,
-       .port_handed_over               = ehci_port_handed_over,
-       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
-};
+static struct hc_driver __read_mostly ehci_spear_hc_driver;
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int ehci_spear_drv_suspend(struct device *dev)
 {
        struct usb_hcd *hcd = dev_get_drvdata(dev);
@@ -94,7 +53,7 @@ static int ehci_spear_drv_resume(struct device *dev)
        ehci_resume(hcd, false);
        return 0;
 }
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
 
 static SIMPLE_DEV_PM_OPS(ehci_spear_pm_ops, ehci_spear_drv_suspend,
                ehci_spear_drv_resume);
@@ -104,7 +63,7 @@ static u64 spear_ehci_dma_mask = DMA_BIT_MASK(32);
 static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
 {
        struct usb_hcd *hcd ;
-       struct spear_ehci *ehci;
+       struct spear_ehci *sehci;
        struct resource *res;
        struct clk *usbh_clk;
        const struct hc_driver *driver = &ehci_spear_hc_driver;
@@ -161,10 +120,13 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
                goto err_put_hcd;
        }
 
-       ehci = (struct spear_ehci *)hcd_to_ehci(hcd);
-       ehci->clk = usbh_clk;
+       sehci = to_spear_ehci(hcd);
+       sehci->clk = usbh_clk;
+
+       /* registers start at offset 0x0 */
+       hcd_to_ehci(hcd)->caps = hcd->regs;
 
-       spear_start_ehci(ehci);
+       clk_prepare_enable(sehci->clk);
        retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (retval)
                goto err_stop_ehci;
@@ -172,7 +134,7 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
        return retval;
 
 err_stop_ehci:
-       spear_stop_ehci(ehci);
+       clk_disable_unprepare(sehci->clk);
 err_put_hcd:
        usb_put_hcd(hcd);
 fail:
@@ -184,7 +146,7 @@ fail:
 static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)
 {
        struct usb_hcd *hcd = platform_get_drvdata(pdev);
-       struct spear_ehci *ehci_p = to_spear_ehci(hcd);
+       struct spear_ehci *sehci = to_spear_ehci(hcd);
 
        if (!hcd)
                return 0;
@@ -192,8 +154,8 @@ static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)
                BUG();
        usb_remove_hcd(hcd);
 
-       if (ehci_p->clk)
-               spear_stop_ehci(ehci_p);
+       if (sehci->clk)
+               clk_disable_unprepare(sehci->clk);
        usb_put_hcd(hcd);
 
        return 0;
@@ -216,4 +178,29 @@ static struct platform_driver spear_ehci_hcd_driver = {
        }
 };
 
+static const struct ehci_driver_overrides spear_overrides __initdata = {
+       .extra_priv_size = sizeof(struct spear_ehci),
+};
+
+static int __init ehci_spear_init(void)
+{
+       if (usb_disabled())
+               return -ENODEV;
+
+       pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+       ehci_init_driver(&ehci_spear_hc_driver, &spear_overrides);
+       return platform_driver_register(&spear_ehci_hcd_driver);
+}
+module_init(ehci_spear_init);
+
+static void __exit ehci_spear_cleanup(void)
+{
+       platform_driver_unregister(&spear_ehci_hcd_driver);
+}
+module_exit(ehci_spear_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_ALIAS("platform:spear-ehci");
+MODULE_AUTHOR("Deepak Sikri");
+MODULE_LICENSE("GPL");
index 568aecc7075b4d345bc59bb033570c6e034b9ebc..e3eddc31ac83fd4f2065a5815967700fa6932ef7 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/usb/ehci_def.h>
 #include <linux/usb/tegra_usb_phy.h>
+#include <linux/clk/tegra.h>
 
 #define TEGRA_USB_BASE                 0xC5000000
 #define TEGRA_USB2_BASE                        0xC5004000
@@ -610,7 +611,7 @@ static const struct dev_pm_ops tegra_ehci_pm_ops = {
 /* Bits of PORTSC1, which will get cleared by writing 1 into them */
 #define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
 
-void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val)
+static void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val)
 {
        unsigned long val;
        struct usb_hcd *hcd = bus_to_hcd(x->otg->host);
@@ -621,9 +622,8 @@ void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val)
        val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3);
        writel(val, base + TEGRA_USB_PORTSC1);
 }
-EXPORT_SYMBOL_GPL(tegra_ehci_set_pts);
 
-void tegra_ehci_set_phcd(struct usb_phy *x, bool enable)
+static void tegra_ehci_set_phcd(struct usb_phy *x, bool enable)
 {
        unsigned long val;
        struct usb_hcd *hcd = bus_to_hcd(x->otg->host);
@@ -636,7 +636,6 @@ void tegra_ehci_set_phcd(struct usb_phy *x, bool enable)
                val &= ~TEGRA_USB_PORTSC1_PHCD;
        writel(val, base + TEGRA_USB_PORTSC1);
 }
-EXPORT_SYMBOL_GPL(tegra_ehci_set_phcd);
 
 static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32);
 
@@ -691,6 +690,10 @@ static int tegra_ehci_probe(struct platform_device *pdev)
        if (err)
                goto fail_clk;
 
+       tegra_periph_reset_assert(tegra->clk);
+       udelay(1);
+       tegra_periph_reset_deassert(tegra->clk);
+
        tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node,
                "nvidia,needs-double-reset");
 
@@ -733,7 +736,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)
 
        tegra->phy = tegra_usb_phy_open(&pdev->dev, instance, hcd->regs,
                                        pdata->phy_config,
-                                       TEGRA_USB_PHY_MODE_HOST);
+                                       TEGRA_USB_PHY_MODE_HOST,
+                                       tegra_ehci_set_pts,
+                                       tegra_ehci_set_phcd);
        if (IS_ERR(tegra->phy)) {
                dev_err(&pdev->dev, "Failed to open USB phy\n");
                err = -ENXIO;
@@ -755,7 +760,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
        err = usb_phy_set_suspend(hcd->phy, 0);
        if (err) {
                dev_err(&pdev->dev, "Failed to power on the phy\n");
-               goto fail;
+               goto fail_phy;
        }
 
        tegra->host_resumed = 1;
@@ -765,17 +770,17 @@ static int tegra_ehci_probe(struct platform_device *pdev)
        if (!irq) {
                dev_err(&pdev->dev, "Failed to get IRQ\n");
                err = -ENODEV;
-               goto fail;
+               goto fail_phy;
        }
 
-#ifdef CONFIG_USB_OTG_UTILS
        if (pdata->operating_mode == TEGRA_USB_OTG) {
                tegra->transceiver =
                        devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-               if (!IS_ERR_OR_NULL(tegra->transceiver))
+               if (!IS_ERR(tegra->transceiver))
                        otg_set_host(tegra->transceiver->otg, &hcd->self);
+       } else {
+               tegra->transceiver = ERR_PTR(-ENODEV);
        }
-#endif
 
        err = usb_add_hcd(hcd, irq, IRQF_SHARED);
        if (err) {
@@ -794,10 +799,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)
        return err;
 
 fail:
-#ifdef CONFIG_USB_OTG_UTILS
-       if (!IS_ERR_OR_NULL(tegra->transceiver))
+       if (!IS_ERR(tegra->transceiver))
                otg_set_host(tegra->transceiver->otg, NULL);
-#endif
+fail_phy:
        usb_phy_shutdown(hcd->phy);
 fail_io:
        clk_disable_unprepare(tegra->clk);
@@ -815,10 +819,8 @@ static int tegra_ehci_remove(struct platform_device *pdev)
        pm_runtime_disable(&pdev->dev);
        pm_runtime_put_noidle(&pdev->dev);
 
-#ifdef CONFIG_USB_OTG_UTILS
-       if (!IS_ERR_OR_NULL(tegra->transceiver))
+       if (!IS_ERR(tegra->transceiver))
                otg_set_host(tegra->transceiver->otg, NULL);
-#endif
 
        usb_phy_shutdown(hcd->phy);
        usb_remove_hcd(hcd);
index c3fa1305f830bf53070a6553446428368553691d..11e5b32f73e943824ca262f3bb61462dacb82b15 100644 (file)
@@ -113,8 +113,8 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci)
 
        if (want != actual) {
 
-               /* Poll again later, but give up after about 20 ms */
-               if (ehci->ASS_poll_count++ < 20) {
+               /* Poll again later, but give up after about 2-4 ms */
+               if (ehci->ASS_poll_count++ < 2) {
                        ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);
                        return;
                }
@@ -159,8 +159,8 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)
 
        if (want != actual) {
 
-               /* Poll again later, but give up after about 20 ms */
-               if (ehci->PSS_poll_count++ < 20) {
+               /* Poll again later, but give up after about 2-4 ms */
+               if (ehci->PSS_poll_count++ < 2) {
                        ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);
                        return;
                }
@@ -229,18 +229,19 @@ static void ehci_handle_intr_unlinks(struct ehci_hcd *ehci)
         * process all the QHs on the list.
         */
        ehci->intr_unlinking = true;
-       while (ehci->intr_unlink) {
-               struct ehci_qh  *qh = ehci->intr_unlink;
+       while (!list_empty(&ehci->intr_unlink)) {
+               struct ehci_qh  *qh;
 
+               qh = list_first_entry(&ehci->intr_unlink, struct ehci_qh,
+                               unlink_node);
                if (!stopped && qh->unlink_cycle == ehci->intr_unlink_cycle)
                        break;
-               ehci->intr_unlink = qh->unlink_next;
-               qh->unlink_next = NULL;
+               list_del(&qh->unlink_node);
                end_unlink_intr(ehci, qh);
        }
 
        /* Handle remaining entries later */
-       if (ehci->intr_unlink) {
+       if (!list_empty(&ehci->intr_unlink)) {
                ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true);
                ++ehci->intr_unlink_cycle;
        }
@@ -295,8 +296,7 @@ static void end_free_itds(struct ehci_hcd *ehci)
 /* Handle lost (or very late) IAA interrupts */
 static void ehci_iaa_watchdog(struct ehci_hcd *ehci)
 {
-       if (ehci->rh_state != EHCI_RH_RUNNING)
-               return;
+       u32 cmd, status;
 
        /*
         * Lost IAA irqs wedge things badly; seen first with a vt8235.
@@ -304,34 +304,32 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci)
         * (a) SMP races against real IAA firing and retriggering, and
         * (b) clean HC shutdown, when IAA watchdog was pending.
         */
-       if (1) {
-               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 = ehci_readl(ehci, &ehci->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 = ehci_readl(ehci, &ehci->regs->status);
-               if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
-                       COUNT(ehci->stats.lost_iaa);
-                       ehci_writel(ehci, STS_IAA, &ehci->regs->status);
-               }
+       if (!ehci->iaa_in_progress || ehci->rh_state != EHCI_RH_RUNNING)
+               return;
+
+       /* 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 = ehci_readl(ehci, &ehci->regs->command);
 
-               ehci_vdbg(ehci, "IAA watchdog: status %x cmd %x\n",
-                               status, cmd);
-               end_unlink_async(ehci);
+       /*
+        * 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 = ehci_readl(ehci, &ehci->regs->status);
+       if ((status & STS_IAA) || !(cmd & CMD_IAAD)) {
+               COUNT(ehci->stats.lost_iaa);
+               ehci_writel(ehci, STS_IAA, &ehci->regs->status);
        }
+
+       ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd);
+       end_unlink_async(ehci);
 }
 
 
diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c
deleted file mode 100644 (file)
index 7ecf709..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * drivers/usb/host/ehci-vt8500.c
- *
- * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * Based on ehci-au1xxx.c
- *
- * 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 <linux/err.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-
-static const struct hc_driver vt8500_ehci_hc_driver = {
-       .description            = hcd_name,
-       .product_desc           = "VT8500 EHCI",
-       .hcd_priv_size          = sizeof(struct ehci_hcd),
-
-       /*
-        * generic hardware linkage
-        */
-       .irq                    = ehci_irq,
-       .flags                  = HCD_MEMORY | HCD_USB2,
-
-       /*
-        * basic lifecycle operations
-        */
-       .reset                  = ehci_setup,
-       .start                  = ehci_run,
-       .stop                   = ehci_stop,
-       .shutdown               = ehci_shutdown,
-
-       /*
-        * managing i/o requests and associated device resources
-        */
-       .urb_enqueue            = ehci_urb_enqueue,
-       .urb_dequeue            = ehci_urb_dequeue,
-       .endpoint_disable       = ehci_endpoint_disable,
-       .endpoint_reset         = ehci_endpoint_reset,
-
-       /*
-        * scheduling support
-        */
-       .get_frame_number       = ehci_get_frame,
-
-       /*
-        * root hub support
-        */
-       .hub_status_data        = ehci_hub_status_data,
-       .hub_control            = ehci_hub_control,
-       .bus_suspend            = ehci_bus_suspend,
-       .bus_resume             = ehci_bus_resume,
-       .relinquish_port        = ehci_relinquish_port,
-       .port_handed_over       = ehci_port_handed_over,
-
-       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
-};
-
-static u64 vt8500_ehci_dma_mask = DMA_BIT_MASK(32);
-
-static int vt8500_ehci_drv_probe(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd;
-       struct ehci_hcd *ehci;
-       struct resource *res;
-       int ret;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       /*
-        * Right now device-tree probed devices don't get dma_mask set.
-        * Since shared usb code relies on it, set it here for now.
-        * Once we have dma capability bindings this can go away.
-        */
-       if (!pdev->dev.dma_mask)
-               pdev->dev.dma_mask = &vt8500_ehci_dma_mask;
-
-       if (pdev->resource[1].flags != IORESOURCE_IRQ) {
-               pr_debug("resource[1] is not IORESOURCE_IRQ");
-               return -ENOMEM;
-       }
-       hcd = usb_create_hcd(&vt8500_ehci_hc_driver, &pdev->dev, "VT8500");
-       if (!hcd)
-               return -ENOMEM;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       hcd->rsrc_start = res->start;
-       hcd->rsrc_len = resource_size(res);
-
-       hcd->regs = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(hcd->regs)) {
-               ret = PTR_ERR(hcd->regs);
-               goto err1;
-       }
-
-       ehci = hcd_to_ehci(hcd);
-       ehci->caps = hcd->regs;
-
-       ret = usb_add_hcd(hcd, pdev->resource[1].start,
-                         IRQF_SHARED);
-       if (ret == 0) {
-               platform_set_drvdata(pdev, hcd);
-               return ret;
-       }
-
-err1:
-       usb_put_hcd(hcd);
-       return ret;
-}
-
-static int vt8500_ehci_drv_remove(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd = platform_get_drvdata(pdev);
-
-       usb_remove_hcd(hcd);
-       usb_put_hcd(hcd);
-       platform_set_drvdata(pdev, NULL);
-
-       return 0;
-}
-
-static const struct of_device_id vt8500_ehci_ids[] = {
-       { .compatible = "via,vt8500-ehci", },
-       { .compatible = "wm,prizm-ehci", },
-       {}
-};
-
-static struct platform_driver vt8500_ehci_driver = {
-       .probe          = vt8500_ehci_drv_probe,
-       .remove         = vt8500_ehci_drv_remove,
-       .shutdown       = usb_hcd_platform_shutdown,
-       .driver = {
-               .name   = "vt8500-ehci",
-               .owner  = THIS_MODULE,
-               .of_match_table = of_match_ptr(vt8500_ehci_ids),
-       }
-};
-
-MODULE_ALIAS("platform:vt8500-ehci");
-MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);
index 36c3a82105953ba2433d12845e7e02a293fa6d35..7c978b23520d07a871396db9626293fd352944ca 100644 (file)
@@ -121,6 +121,7 @@ struct ehci_hcd {                   /* one per controller */
        bool                    scanning:1;
        bool                    need_rescan:1;
        bool                    intr_unlinking:1;
+       bool                    iaa_in_progress:1;
        bool                    async_unlinking:1;
        bool                    shutdown:1;
        struct ehci_qh          *qh_scan_next;
@@ -128,9 +129,8 @@ struct ehci_hcd {                   /* one per controller */
        /* async schedule support */
        struct ehci_qh          *async;
        struct ehci_qh          *dummy;         /* For AMD quirk use */
-       struct ehci_qh          *async_unlink;
-       struct ehci_qh          *async_unlink_last;
-       struct ehci_qh          *async_iaa;
+       struct list_head        async_unlink;
+       struct list_head        async_idle;
        unsigned                async_unlink_cycle;
        unsigned                async_count;    /* async activity count */
 
@@ -143,8 +143,7 @@ struct ehci_hcd {                   /* one per controller */
        unsigned                i_thresh;       /* uframes HC might cache */
 
        union ehci_shadow       *pshadow;       /* mirror hw periodic table */
-       struct ehci_qh          *intr_unlink;
-       struct ehci_qh          *intr_unlink_last;
+       struct list_head        intr_unlink;
        unsigned                intr_unlink_cycle;
        unsigned                now_frame;      /* frame from HC hardware */
        unsigned                last_iso_frame; /* last frame scanned for iso */
@@ -200,6 +199,7 @@ struct ehci_hcd {                   /* one per controller */
        unsigned                use_dummy_qh:1; /* AMD Frame List table quirk*/
        unsigned                has_synopsys_hc_bug:1; /* Synopsys HC */
        unsigned                frame_index_bug:1; /* MosChip (AKA NetMos) */
+       unsigned                need_oc_pp_cycle:1; /* MPC834X port power */
 
        /* required for usb32 quirk */
        #define OHCI_CTRL_HCFS          (3 << 6)
@@ -380,11 +380,10 @@ struct ehci_qh {
        struct list_head        qtd_list;       /* sw qtd list */
        struct list_head        intr_node;      /* list of intr QHs */
        struct ehci_qtd         *dummy;
-       struct ehci_qh          *unlink_next;   /* next on unlink list */
+       struct list_head        unlink_node;
 
        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 */
@@ -407,6 +406,9 @@ struct ehci_qh {
        struct usb_device       *dev;           /* access to TT */
        unsigned                is_out:1;       /* bulk or intr OUT */
        unsigned                clearing_tt:1;  /* Clear-TT-Buf in progress */
+       unsigned                dequeue_during_giveback:1;
+       unsigned                exception:1;    /* got a fault, or an unlink
+                                                  was requested */
 };
 
 /*-------------------------------------------------------------------------*/
index e3b7e85120e44480ead256132098f7c7d3418710..114583a8e92b36dec178cf91afc7b9003aa37ddb 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/platform_data/usb-exynos.h>
 #include <linux/usb/phy.h>
 #include <linux/usb/samsung_usb_phy.h>
-#include <plat/usb-phy.h>
 
 struct exynos_ohci_hcd {
        struct device *dev;
@@ -34,7 +33,7 @@ static void exynos_ohci_phy_enable(struct exynos_ohci_hcd *exynos_ohci)
 
        if (exynos_ohci->phy)
                usb_phy_init(exynos_ohci->phy);
-       else if (exynos_ohci->pdata->phy_init)
+       else if (exynos_ohci->pdata && exynos_ohci->pdata->phy_init)
                exynos_ohci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
 }
 
@@ -44,7 +43,7 @@ static void exynos_ohci_phy_disable(struct exynos_ohci_hcd *exynos_ohci)
 
        if (exynos_ohci->phy)
                usb_phy_shutdown(exynos_ohci->phy);
-       else if (exynos_ohci->pdata->phy_exit)
+       else if (exynos_ohci->pdata && exynos_ohci->pdata->phy_exit)
                exynos_ohci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
 }
 
@@ -127,8 +126,12 @@ static int exynos_ohci_probe(struct platform_device *pdev)
        if (!exynos_ohci)
                return -ENOMEM;
 
+       if (of_device_is_compatible(pdev->dev.of_node,
+                                       "samsung,exynos5440-ohci"))
+               goto skip_phy;
+
        phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
-       if (IS_ERR_OR_NULL(phy)) {
+       if (IS_ERR(phy)) {
                /* Fallback to pdata */
                if (!pdata) {
                        dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
@@ -141,6 +144,8 @@ static int exynos_ohci_probe(struct platform_device *pdev)
                exynos_ohci->otg = phy->otg;
        }
 
+skip_phy:
+
        exynos_ohci->dev = &pdev->dev;
 
        hcd = usb_create_hcd(&exynos_ohci_hc_driver, &pdev->dev,
@@ -311,6 +316,7 @@ static const struct dev_pm_ops exynos_ohci_pm_ops = {
 #ifdef CONFIG_OF
 static const struct of_device_id exynos_ohci_match[] = {
        { .compatible = "samsung,exynos4210-ohci" },
+       { .compatible = "samsung,exynos5440-ohci" },
        {},
 };
 MODULE_DEVICE_TABLE(of, exynos_ohci_match);
index 180a2b01db56c9d496fb52388a324d2df2b4a931..9e6de9586ae4bf82afb01f4c70464ffbbcd01117 100644 (file)
@@ -1102,12 +1102,12 @@ MODULE_LICENSE ("GPL");
 
 #if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S3C64XX)
 #include "ohci-s3c2410.c"
-#define PLATFORM_DRIVER                ohci_hcd_s3c2410_driver
+#define S3C2410_PLATFORM_DRIVER        ohci_hcd_s3c2410_driver
 #endif
 
 #ifdef CONFIG_USB_OHCI_EXYNOS
 #include "ohci-exynos.c"
-#define PLATFORM_DRIVER                exynos_ohci_driver
+#define EXYNOS_PLATFORM_DRIVER exynos_ohci_driver
 #endif
 
 #ifdef CONFIG_USB_OHCI_HCD_OMAP1
@@ -1127,25 +1127,24 @@ MODULE_LICENSE ("GPL");
 
 #ifdef CONFIG_ARCH_EP93XX
 #include "ohci-ep93xx.c"
-#define PLATFORM_DRIVER                ohci_hcd_ep93xx_driver
+#define EP93XX_PLATFORM_DRIVER ohci_hcd_ep93xx_driver
 #endif
 
 #ifdef CONFIG_ARCH_AT91
 #include "ohci-at91.c"
-#define PLATFORM_DRIVER                ohci_hcd_at91_driver
+#define AT91_PLATFORM_DRIVER   ohci_hcd_at91_driver
 #endif
 
 #ifdef CONFIG_ARCH_LPC32XX
 #include "ohci-nxp.c"
-#define PLATFORM_DRIVER                usb_hcd_nxp_driver
+#define NXP_PLATFORM_DRIVER    usb_hcd_nxp_driver
 #endif
 
 #ifdef CONFIG_ARCH_DAVINCI_DA8XX
 #include "ohci-da8xx.c"
-#define PLATFORM_DRIVER                ohci_hcd_da8xx_driver
+#define DAVINCI_PLATFORM_DRIVER        ohci_hcd_da8xx_driver
 #endif
 
-
 #ifdef CONFIG_USB_OHCI_HCD_PPC_OF
 #include "ohci-ppc-of.c"
 #define OF_PLATFORM_DRIVER     ohci_hcd_ppc_of_driver
@@ -1153,7 +1152,7 @@ MODULE_LICENSE ("GPL");
 
 #ifdef CONFIG_PLAT_SPEAR
 #include "ohci-spear.c"
-#define PLATFORM_DRIVER                spear_ohci_hcd_driver
+#define SPEAR_PLATFORM_DRIVER  spear_ohci_hcd_driver
 #endif
 
 #ifdef CONFIG_PPC_PS3
@@ -1199,7 +1198,14 @@ MODULE_LICENSE ("GPL");
        !defined(SA1111_DRIVER) &&      \
        !defined(PS3_SYSTEM_BUS_DRIVER) && \
        !defined(SM501_OHCI_DRIVER) && \
-       !defined(TMIO_OHCI_DRIVER)
+       !defined(TMIO_OHCI_DRIVER) && \
+       !defined(S3C2410_PLATFORM_DRIVER) && \
+       !defined(EXYNOS_PLATFORM_DRIVER) && \
+       !defined(EP93XX_PLATFORM_DRIVER) && \
+       !defined(AT91_PLATFORM_DRIVER) && \
+       !defined(NXP_PLATFORM_DRIVER) && \
+       !defined(DAVINCI_PLATFORM_DRIVER) && \
+       !defined(SPEAR_PLATFORM_DRIVER)
 #error "missing bus glue for ohci-hcd"
 #endif
 
@@ -1277,9 +1283,79 @@ static int __init ohci_hcd_mod_init(void)
                goto error_tmio;
 #endif
 
+#ifdef S3C2410_PLATFORM_DRIVER
+       retval = platform_driver_register(&S3C2410_PLATFORM_DRIVER);
+       if (retval < 0)
+               goto error_s3c2410;
+#endif
+
+#ifdef EXYNOS_PLATFORM_DRIVER
+       retval = platform_driver_register(&EXYNOS_PLATFORM_DRIVER);
+       if (retval < 0)
+               goto error_exynos;
+#endif
+
+#ifdef EP93XX_PLATFORM_DRIVER
+       retval = platform_driver_register(&EP93XX_PLATFORM_DRIVER);
+       if (retval < 0)
+               goto error_ep93xx;
+#endif
+
+#ifdef AT91_PLATFORM_DRIVER
+       retval = platform_driver_register(&AT91_PLATFORM_DRIVER);
+       if (retval < 0)
+               goto error_at91;
+#endif
+
+#ifdef NXP_PLATFORM_DRIVER
+       retval = platform_driver_register(&NXP_PLATFORM_DRIVER);
+       if (retval < 0)
+               goto error_nxp;
+#endif
+
+#ifdef DAVINCI_PLATFORM_DRIVER
+       retval = platform_driver_register(&DAVINCI_PLATFORM_DRIVER);
+       if (retval < 0)
+               goto error_davinci;
+#endif
+
+#ifdef SPEAR_PLATFORM_DRIVER
+       retval = platform_driver_register(&SPEAR_PLATFORM_DRIVER);
+       if (retval < 0)
+               goto error_spear;
+#endif
+
        return retval;
 
        /* Error path */
+#ifdef SPEAR_PLATFORM_DRIVER
+       platform_driver_unregister(&SPEAR_PLATFORM_DRIVER);
+ error_spear:
+#endif
+#ifdef DAVINCI_PLATFORM_DRIVER
+       platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER);
+ error_davinci:
+#endif
+#ifdef NXP_PLATFORM_DRIVER
+       platform_driver_unregister(&NXP_PLATFORM_DRIVER);
+ error_nxp:
+#endif
+#ifdef AT91_PLATFORM_DRIVER
+       platform_driver_unregister(&AT91_PLATFORM_DRIVER);
+ error_at91:
+#endif
+#ifdef EP93XX_PLATFORM_DRIVER
+       platform_driver_unregister(&EP93XX_PLATFORM_DRIVER);
+ error_ep93xx:
+#endif
+#ifdef EXYNOS_PLATFORM_DRIVER
+       platform_driver_unregister(&EXYNOS_PLATFORM_DRIVER);
+ error_exynos:
+#endif
+#ifdef S3C2410_PLATFORM_DRIVER
+       platform_driver_unregister(&S3C2410_PLATFORM_DRIVER);
+ error_s3c2410:
+#endif
 #ifdef TMIO_OHCI_DRIVER
        platform_driver_unregister(&TMIO_OHCI_DRIVER);
  error_tmio:
@@ -1300,17 +1376,17 @@ static int __init ohci_hcd_mod_init(void)
        platform_driver_unregister(&OF_PLATFORM_DRIVER);
  error_of_platform:
 #endif
-#ifdef PLATFORM_DRIVER
-       platform_driver_unregister(&PLATFORM_DRIVER);
- error_platform:
+#ifdef OMAP3_PLATFORM_DRIVER
+       platform_driver_unregister(&OMAP3_PLATFORM_DRIVER);
+ error_omap3_platform:
 #endif
 #ifdef OMAP1_PLATFORM_DRIVER
        platform_driver_unregister(&OMAP1_PLATFORM_DRIVER);
  error_omap1_platform:
 #endif
-#ifdef OMAP3_PLATFORM_DRIVER
-       platform_driver_unregister(&OMAP3_PLATFORM_DRIVER);
- error_omap3_platform:
+#ifdef PLATFORM_DRIVER
+       platform_driver_unregister(&PLATFORM_DRIVER);
+ error_platform:
 #endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
        ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
@@ -1329,6 +1405,27 @@ module_init(ohci_hcd_mod_init);
 
 static void __exit ohci_hcd_mod_exit(void)
 {
+#ifdef SPEAR_PLATFORM_DRIVER
+       platform_driver_unregister(&SPEAR_PLATFORM_DRIVER);
+#endif
+#ifdef DAVINCI_PLATFORM_DRIVER
+       platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER);
+#endif
+#ifdef NXP_PLATFORM_DRIVER
+       platform_driver_unregister(&NXP_PLATFORM_DRIVER);
+#endif
+#ifdef AT91_PLATFORM_DRIVER
+       platform_driver_unregister(&AT91_PLATFORM_DRIVER);
+#endif
+#ifdef EP93XX_PLATFORM_DRIVER
+       platform_driver_unregister(&EP93XX_PLATFORM_DRIVER);
+#endif
+#ifdef EXYNOS_PLATFORM_DRIVER
+       platform_driver_unregister(&EXYNOS_PLATFORM_DRIVER);
+#endif
+#ifdef S3C2410_PLATFORM_DRIVER
+       platform_driver_unregister(&S3C2410_PLATFORM_DRIVER);
+#endif
 #ifdef TMIO_OHCI_DRIVER
        platform_driver_unregister(&TMIO_OHCI_DRIVER);
 #endif
@@ -1344,12 +1441,15 @@ static void __exit ohci_hcd_mod_exit(void)
 #ifdef OF_PLATFORM_DRIVER
        platform_driver_unregister(&OF_PLATFORM_DRIVER);
 #endif
-#ifdef PLATFORM_DRIVER
-       platform_driver_unregister(&PLATFORM_DRIVER);
-#endif
 #ifdef OMAP3_PLATFORM_DRIVER
        platform_driver_unregister(&OMAP3_PLATFORM_DRIVER);
 #endif
+#ifdef OMAP1_PLATFORM_DRIVER
+       platform_driver_unregister(&OMAP1_PLATFORM_DRIVER);
+#endif
+#ifdef PLATFORM_DRIVER
+       platform_driver_unregister(&PLATFORM_DRIVER);
+#endif
 #ifdef PS3_SYSTEM_BUS_DRIVER
        ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);
 #endif
index db09dae7b557a18063d424a3ffc58c1edb8ccca8..60ff4220e8b4fbe771857f5b1316e02663eccf68 100644 (file)
@@ -580,14 +580,8 @@ static int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port)
 
 /* See usb 7.1.7.5:  root hubs must issue at least 50 msec reset signaling,
  * not necessarily continuous ... to guard against resume signaling.
- * The short timeout is safe for non-root hubs, and is backward-compatible
- * with earlier Linux hosts.
  */
-#ifdef CONFIG_USB_SUSPEND
 #define        PORT_RESET_MSEC         50
-#else
-#define        PORT_RESET_MSEC         10
-#endif
 
 /* this timer value might be vendor-specific ... */
 #define        PORT_RESET_HW_MSEC      10
index eb35d96302373c7e9e2fa3345f7d81008aa802f9..ddfc31427bc09e1fc95c63ea40f006ad00631e66 100644 (file)
@@ -31,6 +31,8 @@
 
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/dma-mapping.h>
 
 /*-------------------------------------------------------------------------*/
 
@@ -112,6 +114,8 @@ static const struct hc_driver ohci_omap3_hc_driver = {
 
 /*-------------------------------------------------------------------------*/
 
+static u64 omap_ohci_dma_mask = DMA_BIT_MASK(32);
+
 /*
  * configure so an HC device and id are always provided
  * always called with process context; sleeping is OK
@@ -141,14 +145,13 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       irq = platform_get_irq_byname(pdev, "ohci-irq");
+       irq = platform_get_irq(pdev, 0);
        if (irq < 0) {
                dev_err(dev, "OHCI irq failed\n");
                return -ENODEV;
        }
 
-       res = platform_get_resource_byname(pdev,
-                               IORESOURCE_MEM, "ohci");
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(dev, "UHH OHCI get resource failed\n");
                return -ENOMEM;
@@ -160,6 +163,13 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
+       /*
+        * Right now device-tree probed devices don't get dma_mask set.
+        * Since shared usb code relies on it, set it here for now.
+        * Once we have dma capability bindings this can go away.
+        */
+       if (!pdev->dev.dma_mask)
+               pdev->dev.dma_mask = &omap_ohci_dma_mask;
 
        hcd = usb_create_hcd(&ohci_omap3_hc_driver, dev,
                        dev_name(dev));
@@ -229,12 +239,20 @@ static void ohci_hcd_omap3_shutdown(struct platform_device *pdev)
                hcd->driver->shutdown(hcd);
 }
 
+static const struct of_device_id omap_ohci_dt_ids[] = {
+       { .compatible = "ti,ohci-omap3" },
+       { }
+};
+
+MODULE_DEVICE_TABLE(of, omap_ohci_dt_ids);
+
 static struct platform_driver ohci_hcd_omap3_driver = {
        .probe          = ohci_hcd_omap3_probe,
        .remove         = ohci_hcd_omap3_remove,
        .shutdown       = ohci_hcd_omap3_shutdown,
        .driver         = {
                .name   = "ohci-omap3",
+               .of_match_table = of_match_ptr(omap_ohci_dt_ids),
        },
 };
 
index d62f0404baaa636d82e3b409edf4581c7e92ab03..15ed7e8d887f6897781715ca42a0b12018e0e99a 100644 (file)
@@ -1755,7 +1755,7 @@ sl811h_probe(struct platform_device *dev)
 
 /* for this device there's no useful distinction between the controller
  * and its root hub, except that the root hub only gets direct PM calls
- * when CONFIG_USB_SUSPEND is enabled.
+ * when CONFIG_PM_RUNTIME is enabled.
  */
 
 static int
index 5efdffe3236572e4f7b3141a6a8ab5f4fb95d721..5c124bf5d01869c727543b34240deace3d27d1cd 100644 (file)
@@ -3141,10 +3141,11 @@ static int u132_probe(struct platform_device *pdev)
 
 
 #ifdef CONFIG_PM
-/* for this device there's no useful distinction between the controller
-* and its root hub, except that the root hub only gets direct PM calls
-* when CONFIG_USB_SUSPEND is enabled.
-*/
+/*
+ * for this device there's no useful distinction between the controller
+ * and its root hub, except that the root hub only gets direct PM calls
+ * when CONFIG_PM_RUNTIME is enabled.
+ */
 static int u132_suspend(struct platform_device *pdev, pm_message_t state)
 {
        struct usb_hcd *hcd = platform_get_drvdata(pdev);
index 68914429482f30ff4afed47180aae563d07c5784..187a3ec1069ace87d28b888823e4c4e38053f80b 100644 (file)
@@ -1075,7 +1075,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
                        set_bit(port_index, &bus_state->bus_suspended);
                }
                /* USB core sets remote wake mask for USB 3.0 hubs,
-                * including the USB 3.0 roothub, but only if CONFIG_USB_SUSPEND
+                * including the USB 3.0 roothub, but only if CONFIG_PM_RUNTIME
                 * is enabled, so also enable remote wake here.
                 */
                if (hcd->self.root_hub->do_remote_wakeup) {
index 6dc238c592bc9aef5e3d8a564240b085e401cf6b..965b539bc47410721c9021f41eb7bf051dcc8feb 100644 (file)
@@ -51,7 +51,7 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci,
                return NULL;
        }
 
-       memset(seg->trbs, 0, SEGMENT_SIZE);
+       memset(seg->trbs, 0, TRB_SEGMENT_SIZE);
        /* If the cycle state is 0, set the cycle bit to 1 for all the TRBs */
        if (cycle_state == 0) {
                for (i = 0; i < TRBS_PER_SEGMENT; i++)
@@ -467,7 +467,7 @@ struct xhci_ring *xhci_dma_to_transfer_ring(
 {
        if (ep->ep_state & EP_HAS_STREAMS)
                return radix_tree_lookup(&ep->stream_info->trb_address_map,
-                               address >> SEGMENT_SHIFT);
+                               address >> TRB_SEGMENT_SHIFT);
        return ep->ring;
 }
 
@@ -478,7 +478,7 @@ static struct xhci_ring *dma_to_stream_ring(
                u64 address)
 {
        return radix_tree_lookup(&stream_info->trb_address_map,
-                       address >> SEGMENT_SHIFT);
+                       address >> TRB_SEGMENT_SHIFT);
 }
 #endif /* CONFIG_USB_XHCI_HCD_DEBUGGING */
 
@@ -514,7 +514,7 @@ static int xhci_test_radix_tree(struct xhci_hcd *xhci,
 
                cur_ring = stream_info->stream_rings[cur_stream];
                for (addr = cur_ring->first_seg->dma;
-                               addr < cur_ring->first_seg->dma + SEGMENT_SIZE;
+                               addr < cur_ring->first_seg->dma + TRB_SEGMENT_SIZE;
                                addr += trb_size) {
                        mapped_ring = dma_to_stream_ring(stream_info, addr);
                        if (cur_ring != mapped_ring) {
@@ -662,7 +662,7 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,
                                cur_stream, (unsigned long long) addr);
 
                key = (unsigned long)
-                       (cur_ring->first_seg->dma >> SEGMENT_SHIFT);
+                       (cur_ring->first_seg->dma >> TRB_SEGMENT_SHIFT);
                ret = radix_tree_insert(&stream_info->trb_address_map,
                                key, cur_ring);
                if (ret) {
@@ -693,7 +693,7 @@ cleanup_rings:
                if (cur_ring) {
                        addr = cur_ring->first_seg->dma;
                        radix_tree_delete(&stream_info->trb_address_map,
-                                       addr >> SEGMENT_SHIFT);
+                                       addr >> TRB_SEGMENT_SHIFT);
                        xhci_ring_free(xhci, cur_ring);
                        stream_info->stream_rings[cur_stream] = NULL;
                }
@@ -764,7 +764,7 @@ void xhci_free_stream_info(struct xhci_hcd *xhci,
                if (cur_ring) {
                        addr = cur_ring->first_seg->dma;
                        radix_tree_delete(&stream_info->trb_address_map,
-                                       addr >> SEGMENT_SHIFT);
+                                       addr >> TRB_SEGMENT_SHIFT);
                        xhci_ring_free(xhci, cur_ring);
                        stream_info->stream_rings[cur_stream] = NULL;
                }
@@ -2305,7 +2305,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
         * so we pick the greater alignment need.
         */
        xhci->segment_pool = dma_pool_create("xHCI ring segments", dev,
-                       SEGMENT_SIZE, 64, xhci->page_size);
+                       TRB_SEGMENT_SIZE, 64, xhci->page_size);
 
        /* See Table 46 and Note on Figure 55 */
        xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev,
index 53b8f89a0b1c7e6199c95672c85d3d27fb3e0b90..b4aa79d154b28b29db4b2a6509e974b74fdd4192 100644 (file)
@@ -417,9 +417,9 @@ static void compliance_mode_recovery(unsigned long arg)
                         * Compliance Mode Detected. Letting USB Core
                         * handle the Warm Reset
                         */
-                       xhci_dbg(xhci, "Compliance Mode Detected->Port %d!\n",
+                       xhci_dbg(xhci, "Compliance mode detected->port %d\n",
                                        i + 1);
-                       xhci_dbg(xhci, "Attempting Recovery routine!\n");
+                       xhci_dbg(xhci, "Attempting compliance mode recovery\n");
                        hcd = xhci->shared_hcd;
 
                        if (hcd->state == HC_STATE_SUSPENDED)
@@ -457,7 +457,7 @@ static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci)
        set_timer_slack(&xhci->comp_mode_recovery_timer,
                        msecs_to_jiffies(COMP_MODE_RCVRY_MSECS));
        add_timer(&xhci->comp_mode_recovery_timer);
-       xhci_dbg(xhci, "Compliance Mode Recovery Timer Initialized.\n");
+       xhci_dbg(xhci, "Compliance mode recovery timer initialized\n");
 }
 
 /*
@@ -733,8 +733,11 @@ void xhci_stop(struct usb_hcd *hcd)
 
        /* Deleting Compliance Mode Recovery Timer */
        if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
-                       (!(xhci_all_ports_seen_u0(xhci))))
+                       (!(xhci_all_ports_seen_u0(xhci)))) {
                del_timer_sync(&xhci->comp_mode_recovery_timer);
+               xhci_dbg(xhci, "%s: compliance mode recovery timer deleted\n",
+                               __func__);
+       }
 
        if (xhci->quirks & XHCI_AMD_PLL_FIX)
                usb_amd_dev_put();
@@ -930,7 +933,8 @@ int xhci_suspend(struct xhci_hcd *xhci)
        if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
                        (!(xhci_all_ports_seen_u0(xhci)))) {
                del_timer_sync(&xhci->comp_mode_recovery_timer);
-               xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted!\n");
+               xhci_dbg(xhci, "%s: compliance mode recovery timer deleted\n",
+                               __func__);
        }
 
        /* step 5: remove core well power */
@@ -3801,7 +3805,7 @@ int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1)
        return raw_port;
 }
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 
 /* BESL to HIRD Encoding array for USB2 LPM */
 static int xhci_besl_encoding[16] = {125, 150, 200, 300, 400, 500, 1000, 2000,
@@ -4051,7 +4055,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
        return 0;
 }
 
-#endif /* CONFIG_USB_SUSPEND */
+#endif /* CONFIG_PM_RUNTIME */
 
 /*---------------------- USB 3.0 Link PM functions ------------------------*/
 
index 63582719e0fb26cafb4d19f5248c2b5f9aa8a43a..29c978e37135a9c836808407907803f4770fadae 100644 (file)
@@ -1238,8 +1238,8 @@ union xhci_trb {
 #define TRBS_PER_SEGMENT       64
 /* Allow two commands + a link TRB, along with any reserved command TRBs */
 #define MAX_RSVD_CMD_TRBS      (TRBS_PER_SEGMENT - 3)
-#define SEGMENT_SIZE           (TRBS_PER_SEGMENT*16)
-#define SEGMENT_SHIFT          (__ffs(SEGMENT_SIZE))
+#define TRB_SEGMENT_SIZE       (TRBS_PER_SEGMENT*16)
+#define TRB_SEGMENT_SHIFT      (ilog2(TRB_SEGMENT_SIZE))
 /* TRB buffer pointers can't cross 64KB boundaries */
 #define TRB_MAX_BUFF_SHIFT             16
 #define TRB_MAX_BUFF_SIZE      (1 << TRB_MAX_BUFF_SHIFT)
index 33350f9dd34f302f86d916a40a0cb627c636bf1b..320d368c8dace716b9f6e4a52085efba50d552bd 100644 (file)
@@ -2,11 +2,9 @@
 # USB Imaging devices configuration
 #
 comment "USB Imaging devices"
-       depends on USB
 
 config USB_MDC800
        tristate "USB Mustek MDC800 Digital Camera support"
-       depends on USB
        ---help---
          Say Y here if you want to connect this type of still camera to
          your computer's USB port. This driver can be used with gphoto 0.4.3
@@ -19,7 +17,7 @@ config USB_MDC800
 
 config USB_MICROTEK
        tristate "Microtek X6USB scanner support"
-       depends on USB && SCSI
+       depends on SCSI
        help
          Say Y here if you want support for the Microtek X6USB and
          possibly the Phantom 336CX, Phantom C6 and ScanMaker V6U(S)L.
index 3b1a3f4ec5e9b7e42da55656560b70c14d5076d7..a51e7d6afda97ab9bbf28a46fd788ca9c43602c6 100644 (file)
@@ -2,11 +2,9 @@
 # USB Miscellaneous driver configuration
 #
 comment "USB Miscellaneous drivers"
-       depends on USB
 
 config USB_EMI62
        tristate "EMI 6|2m USB Audio interface support"
-       depends on USB
        ---help---
          This driver loads firmware to Emagic EMI 6|2m low latency USB
          Audio and Midi interface.
@@ -21,7 +19,6 @@ config USB_EMI62
 
 config USB_EMI26
        tristate "EMI 2|6 USB Audio interface support"
-       depends on USB
        ---help---
          This driver loads firmware to Emagic EMI 2|6 low latency USB
          Audio interface.
@@ -34,7 +31,6 @@ config USB_EMI26
 
 config USB_ADUTUX
        tristate "ADU devices from Ontrak Control Systems"
-       depends on USB
        help
          Say Y if you want to use an ADU device from Ontrak Control
          Systems.
@@ -44,7 +40,6 @@ config USB_ADUTUX
 
 config USB_SEVSEG
        tristate "USB 7-Segment LED Display"
-       depends on USB
        help
          Say Y here if you have a USB 7-Segment Display by Delcom
 
@@ -53,7 +48,6 @@ config USB_SEVSEG
 
 config USB_RIO500
        tristate "USB Diamond Rio500 support"
-       depends on USB
        help
          Say Y here if you want to connect a USB Rio500 mp3 player to your
          computer's USB port. Please read <file:Documentation/usb/rio.txt>
@@ -64,7 +58,6 @@ config USB_RIO500
 
 config USB_LEGOTOWER
        tristate "USB Lego Infrared Tower support"
-       depends on USB
        help
          Say Y here if you want to connect a USB Lego Infrared Tower to your
          computer's USB port.
@@ -77,7 +70,6 @@ config USB_LEGOTOWER
 
 config USB_LCD
        tristate "USB LCD driver support"
-       depends on USB
        help
          Say Y here if you want to connect an USBLCD to your computer's
          USB port. The USBLCD is a small USB interface board for
@@ -89,7 +81,6 @@ config USB_LCD
 
 config USB_LED
        tristate "USB LED driver support"
-       depends on USB
        help
          Say Y here if you want to connect an USBLED device to your 
          computer's USB port.
@@ -99,7 +90,6 @@ config USB_LED
 
 config USB_CYPRESS_CY7C63
        tristate "Cypress CY7C63xxx USB driver support"
-       depends on USB
        help
          Say Y here if you want to connect a Cypress CY7C63xxx
          micro controller to your computer's USB port. Currently this
@@ -113,7 +103,6 @@ config USB_CYPRESS_CY7C63
 
 config USB_CYTHERM
        tristate "Cypress USB thermometer driver support"
-       depends on USB
        help
          Say Y here if you want to connect a Cypress USB thermometer
          device to your computer's USB port. This device is also known
@@ -126,7 +115,6 @@ config USB_CYTHERM
 
 config USB_IDMOUSE
        tristate "Siemens ID USB Mouse Fingerprint sensor support"
-       depends on USB
        help
          Say Y here if you want to use the fingerprint sensor on
          the Siemens ID Mouse. There is also a Siemens ID Mouse
@@ -140,7 +128,6 @@ config USB_IDMOUSE
 
 config USB_FTDI_ELAN
        tristate "Elan PCMCIA CardBus Adapter USB Client"
-       depends on USB
        default M
        help
          ELAN's Uxxx series of adapters are USB to PCMCIA CardBus adapters.
@@ -164,7 +151,6 @@ config USB_FTDI_ELAN
 
 config USB_APPLEDISPLAY
        tristate "Apple Cinema Display support"
-       depends on USB
        select BACKLIGHT_LCD_SUPPORT
        select BACKLIGHT_CLASS_DEVICE
        help
@@ -175,7 +161,6 @@ source "drivers/usb/misc/sisusbvga/Kconfig"
 
 config USB_LD
        tristate "USB LD driver"
-       depends on USB
        help
          This driver is for generic USB devices that use interrupt transfers,
          like LD Didactic's USB devices.
@@ -185,7 +170,6 @@ config USB_LD
 
 config USB_TRANCEVIBRATOR
        tristate "PlayStation 2 Trance Vibrator driver support"
-       depends on USB
        help
          Say Y here if you want to connect a PlayStation 2 Trance Vibrator
          device to your computer's USB port.
@@ -195,7 +179,6 @@ config USB_TRANCEVIBRATOR
 
 config USB_IOWARRIOR
        tristate "IO Warrior driver support"
-       depends on USB
        help
          Say Y here if you want to support the IO Warrior devices from Code
          Mercenaries.  This includes support for the following devices:
@@ -209,7 +192,6 @@ config USB_IOWARRIOR
 
 config USB_TEST
        tristate "USB testing driver"
-       depends on USB
        help
          This driver is for testing host controller software.  It is used
          with specialized device firmware for regression and stress testing,
@@ -220,7 +202,6 @@ config USB_TEST
 
 config USB_ISIGHTFW
        tristate "iSight firmware loading support"
-       depends on USB
        select FW_LOADER
        help
          This driver loads firmware for USB Apple iSight cameras, allowing
@@ -233,7 +214,6 @@ config USB_ISIGHTFW
 
 config USB_YUREX
        tristate "USB YUREX driver support"
-       depends on USB
        help
          Say Y here if you want to connect a YUREX to your computer's
          USB port. The YUREX is a leg-shakes sensor. See
@@ -246,7 +226,6 @@ config USB_YUREX
 
 config USB_EZUSB_FX2
        tristate "Functions for loading firmware on EZUSB chips"
-       depends on USB
        help
          Say Y here if you need EZUSB device support.
          (Cypress FX/FX2/FX2LP microcontrollers)
index 0fc6e5fc745fbf0de60d97e7059d93dc6ad82348..ba6a5d6e618e20092842c0974b3e5788461b651d 100644 (file)
@@ -63,6 +63,7 @@ static const struct usb_device_id appledisplay_table[] = {
        { APPLEDISPLAY_DEVICE(0x9219) },
        { APPLEDISPLAY_DEVICE(0x921c) },
        { APPLEDISPLAY_DEVICE(0x921d) },
+       { APPLEDISPLAY_DEVICE(0x9236) },
 
        /* Terminating entry */
        { }
index 30ea7ca6846e2a9cd3c36ecf182b9b934ca2a338..0d03a52004822417c4daba49b5afc814af0314d2 100644 (file)
@@ -1,7 +1,7 @@
 
 config USB_SISUSBVGA
        tristate "USB 2.0 SVGA dongle support (Net2280/SiS315)"
-       depends on USB && (USB_MUSB_HDRC || USB_EHCI_HCD)
+       depends on (USB_MUSB_HDRC || USB_EHCI_HCD)
         ---help---
          Say Y here if you intend to attach a USB2VGA dongle based on a
          Net2280 and a SiS315 chip.
index dd573abd2d1edf9b32b0a97aa9def3d1abd9d967..c21386ec5d35d142b7d0d84abe2e3f3cb5be7125 100644 (file)
@@ -3084,7 +3084,7 @@ static int sisusb_probe(struct usb_interface *intf,
 
        /* Allocate memory for our private */
        if (!(sisusb = kzalloc(sizeof(*sisusb), GFP_KERNEL))) {
-               dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for private data\n");
+               dev_err(&dev->dev, "Failed to allocate memory for private data\n");
                return -ENOMEM;
        }
        kref_init(&sisusb->kref);
index f713f6aeb6e5508dc79302d067474e59c3eadade..d3a1cce1bf9c511710993002d83391f8f6a6fb35 100644 (file)
@@ -307,18 +307,7 @@ static struct i2c_driver usb3503_driver = {
        .id_table       = usb3503_id,
 };
 
-static int __init usb3503_init(void)
-{
-       return i2c_add_driver(&usb3503_driver);
-}
-
-static void __exit usb3503_exit(void)
-{
-       i2c_del_driver(&usb3503_driver);
-}
-
-module_init(usb3503_init);
-module_exit(usb3503_exit);
+module_i2c_driver(usb3503_driver);
 
 MODULE_AUTHOR("Dongjin Kim <tobetter@gmail.com>");
 MODULE_DESCRIPTION("USB3503 USB HUB driver");
index 635745f57fbdf4c8a1dafbdd01245c56ff75fc1d..5c6ffa2a612eff0223467c4bd08461fc7c11b7fa 100644 (file)
@@ -4,7 +4,6 @@
 
 config USB_MON
        tristate "USB Monitor"
-       depends on USB
        help
          If you select this option, a component which captures the USB traffic
          between peripheral-specific drivers and HC drivers will be built.
index 05e51432dd2f77eb08bda0b43293df5363425ef0..06f8d29af1ef7a74dfb0d2c0ae61ea58e36e2a74 100644 (file)
@@ -6,8 +6,7 @@
 # (M)HDRC = (Multipoint) Highspeed Dual-Role Controller
 config USB_MUSB_HDRC
        tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
-       depends on USB && USB_GADGET
-       select USB_OTG_UTILS
+       depends on USB_GADGET
        help
          Say Y here if your system has a dual role high speed USB
          controller based on the Mentor Graphics silicon IP.  Then
@@ -34,10 +33,12 @@ choice
 config USB_MUSB_DAVINCI
        tristate "DaVinci"
        depends on ARCH_DAVINCI_DMx
+       depends on BROKEN
 
 config USB_MUSB_DA8XX
        tristate "DA8xx/OMAP-L1x"
        depends on ARCH_DAVINCI_DA8XX
+       depends on BROKEN
 
 config USB_MUSB_TUSB6010
        tristate "TUSB6010"
@@ -53,7 +54,6 @@ config USB_MUSB_AM35X
 
 config USB_MUSB_DSPS
        tristate "TI DSPS platforms"
-       depends on SOC_TI81XX || SOC_AM33XX
 
 config USB_MUSB_BLACKFIN
        tristate "Blackfin"
@@ -61,12 +61,12 @@ config USB_MUSB_BLACKFIN
 
 config USB_MUSB_UX500
        tristate "U8500 and U5500"
-       depends on (ARCH_U8500 && AB8500_USB)
 
 endchoice
 
 choice
        prompt 'MUSB DMA mode'
+       default MUSB_PIO_ONLY if ARCH_MULTIPLATFORM
        default USB_UX500_DMA if USB_MUSB_UX500
        default USB_INVENTRA_DMA if USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN
        default USB_TI_CPPI_DMA if USB_MUSB_DAVINCI
index 59eea219034a0252420b1f2248d80d33753fa9b5..2231850c062530765f49b761bd711e83bcde9579 100644 (file)
@@ -149,7 +149,7 @@ static void otg_timer(unsigned long _musb)
         */
        devctl = musb_readb(mregs, MUSB_DEVCTL);
        dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
-               otg_state_string(musb->xceiv->state));
+               usb_otg_state_string(musb->xceiv->state));
 
        spin_lock_irqsave(&musb->lock, flags);
        switch (musb->xceiv->state) {
@@ -195,7 +195,7 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)
        if (musb->is_active || (musb->a_wait_bcon == 0 &&
                                musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
                dev_dbg(musb->controller, "%s active, deleting timer\n",
-                       otg_state_string(musb->xceiv->state));
+                       usb_otg_state_string(musb->xceiv->state));
                del_timer(&otg_workaround);
                last_timer = jiffies;
                return;
@@ -208,7 +208,7 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout)
        last_timer = timeout;
 
        dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
-               otg_state_string(musb->xceiv->state),
+               usb_otg_state_string(musb->xceiv->state),
                jiffies_to_msecs(timeout - jiffies));
        mod_timer(&otg_workaround, timeout);
 }
@@ -298,7 +298,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
                /* NOTE: this must complete power-on within 100 ms. */
                dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
                                drvvbus ? "on" : "off",
-                               otg_state_string(musb->xceiv->state),
+                               usb_otg_state_string(musb->xceiv->state),
                                err ? " ERROR" : "",
                                devctl);
                ret = IRQ_HANDLED;
index dbb31b30c7fa6505da81a065ebc499d824706dcd..5e63b160db0c10bd2087cbfcf21c611c5ce3a7af 100644 (file)
@@ -280,13 +280,13 @@ static void musb_conn_timer_handler(unsigned long _musb)
                break;
        default:
                dev_dbg(musb->controller, "%s state not handled\n",
-                       otg_state_string(musb->xceiv->state));
+                       usb_otg_state_string(musb->xceiv->state));
                break;
        }
        spin_unlock_irqrestore(&musb->lock, flags);
 
        dev_dbg(musb->controller, "state is %s\n",
-               otg_state_string(musb->xceiv->state));
+               usb_otg_state_string(musb->xceiv->state));
 }
 
 static void bfin_musb_enable(struct musb *musb)
@@ -307,7 +307,7 @@ static void bfin_musb_set_vbus(struct musb *musb, int is_on)
 
        dev_dbg(musb->controller, "VBUS %s, devctl %02x "
                /* otg %3x conf %08x prcm %08x */ "\n",
-               otg_state_string(musb->xceiv->state),
+               usb_otg_state_string(musb->xceiv->state),
                musb_readb(musb->mregs, MUSB_DEVCTL));
 }
 
index f522000e8f0659b11124f48ef94f6f0c1bdb104c..9db211ee15b5350467fb8808a80c9d0575a9c4ff 100644 (file)
@@ -435,7 +435,6 @@ cppi_rndis_update(struct cppi_channel *c, int is_rx,
        }
 }
 
-#ifdef CONFIG_USB_MUSB_DEBUG
 static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd)
 {
        pr_debug("RXBD/%s %08x: "
@@ -444,21 +443,16 @@ static void cppi_dump_rxbd(const char *tag, struct cppi_descriptor *bd)
                        bd->hw_next, bd->hw_bufp, bd->hw_off_len,
                        bd->hw_options);
 }
-#endif
 
 static void cppi_dump_rxq(int level, const char *tag, struct cppi_channel *rx)
 {
-#ifdef CONFIG_USB_MUSB_DEBUG
        struct cppi_descriptor  *bd;
 
-       if (!_dbg_level(level))
-               return;
        cppi_dump_rx(level, rx, tag);
        if (rx->last_processed)
                cppi_dump_rxbd("last", rx->last_processed);
        for (bd = rx->head; bd; bd = bd->next)
                cppi_dump_rxbd("active", bd);
-#endif
 }
 
 
@@ -784,6 +778,7 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)
        void __iomem            *tibase = musb->ctrl_base;
        int                     is_rndis = 0;
        struct cppi_rx_stateram __iomem *rx_ram = rx->state_ram;
+       struct cppi_descriptor  *d;
 
        if (onepacket) {
                /* almost every USB driver, host or peripheral side */
@@ -897,14 +892,8 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)
        bd->hw_options |= CPPI_SOP_SET;
        tail->hw_options |= CPPI_EOP_SET;
 
-#ifdef CONFIG_USB_MUSB_DEBUG
-       if (_dbg_level(5)) {
-               struct cppi_descriptor  *d;
-
-               for (d = rx->head; d; d = d->next)
-                       cppi_dump_rxbd("S", d);
-       }
-#endif
+       for (d = rx->head; d; d = d->next)
+               cppi_dump_rxbd("S", d);
 
        /* in case the preceding transfer left some state... */
        tail = rx->last_processed;
index 41613a2b35e8530d8278bd8e4191bafae5617828..b903b744a2249d59b1a2aa681dfb2b3b70b6b5c4 100644 (file)
@@ -198,7 +198,7 @@ static void otg_timer(unsigned long _musb)
         */
        devctl = musb_readb(mregs, MUSB_DEVCTL);
        dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
-               otg_state_string(musb->xceiv->state));
+               usb_otg_state_string(musb->xceiv->state));
 
        spin_lock_irqsave(&musb->lock, flags);
        switch (musb->xceiv->state) {
@@ -267,7 +267,7 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout)
        if (musb->is_active || (musb->a_wait_bcon == 0 &&
                                musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
                dev_dbg(musb->controller, "%s active, deleting timer\n",
-                       otg_state_string(musb->xceiv->state));
+                       usb_otg_state_string(musb->xceiv->state));
                del_timer(&otg_workaround);
                last_timer = jiffies;
                return;
@@ -280,7 +280,7 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout)
        last_timer = timeout;
 
        dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
-               otg_state_string(musb->xceiv->state),
+               usb_otg_state_string(musb->xceiv->state),
                jiffies_to_msecs(timeout - jiffies));
        mod_timer(&otg_workaround, timeout);
 }
@@ -360,7 +360,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)
 
                dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
                                drvvbus ? "on" : "off",
-                               otg_state_string(musb->xceiv->state),
+                               usb_otg_state_string(musb->xceiv->state),
                                err ? " ERROR" : "",
                                devctl);
                ret = IRQ_HANDLED;
index e040d9103735181aa03f4f7bd24eabbaf12f8b78..bea6cc35471c5f73bd5e26607e06d2087df08fe1 100644 (file)
@@ -215,7 +215,7 @@ static void otg_timer(unsigned long _musb)
         */
        devctl = musb_readb(mregs, MUSB_DEVCTL);
        dev_dbg(musb->controller, "poll devctl %02x (%s)\n", devctl,
-               otg_state_string(musb->xceiv->state));
+               usb_otg_state_string(musb->xceiv->state));
 
        spin_lock_irqsave(&musb->lock, flags);
        switch (musb->xceiv->state) {
@@ -349,7 +349,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci)
                davinci_musb_source_power(musb, drvvbus, 0);
                dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
                                drvvbus ? "on" : "off",
-                               otg_state_string(musb->xceiv->state),
+                               usb_otg_state_string(musb->xceiv->state),
                                err ? " ERROR" : "",
                                devctl);
                retval = IRQ_HANDLED;
index daec6e0f7e381e52750cffab9112488c3af1e01d..37a261a6bb6aa1d75d8e9a0b27e787d0cffeff41 100644 (file)
@@ -372,13 +372,13 @@ static void musb_otg_timer_func(unsigned long data)
        case OTG_STATE_A_SUSPEND:
        case OTG_STATE_A_WAIT_BCON:
                dev_dbg(musb->controller, "HNP: %s timeout\n",
-                       otg_state_string(musb->xceiv->state));
+                       usb_otg_state_string(musb->xceiv->state));
                musb_platform_set_vbus(musb, 0);
                musb->xceiv->state = OTG_STATE_A_WAIT_VFALL;
                break;
        default:
                dev_dbg(musb->controller, "HNP: Unhandled mode %s\n",
-                       otg_state_string(musb->xceiv->state));
+                       usb_otg_state_string(musb->xceiv->state));
        }
        musb->ignore_disconnect = 0;
        spin_unlock_irqrestore(&musb->lock, flags);
@@ -393,13 +393,14 @@ void musb_hnp_stop(struct musb *musb)
        void __iomem    *mbase = musb->mregs;
        u8      reg;
 
-       dev_dbg(musb->controller, "HNP: stop from %s\n", otg_state_string(musb->xceiv->state));
+       dev_dbg(musb->controller, "HNP: stop from %s\n",
+                       usb_otg_state_string(musb->xceiv->state));
 
        switch (musb->xceiv->state) {
        case OTG_STATE_A_PERIPHERAL:
                musb_g_disconnect(musb);
                dev_dbg(musb->controller, "HNP: back to %s\n",
-                       otg_state_string(musb->xceiv->state));
+                       usb_otg_state_string(musb->xceiv->state));
                break;
        case OTG_STATE_B_HOST:
                dev_dbg(musb->controller, "HNP: Disabling HR\n");
@@ -413,7 +414,7 @@ void musb_hnp_stop(struct musb *musb)
                break;
        default:
                dev_dbg(musb->controller, "HNP: Stopping in unknown state %s\n",
-                       otg_state_string(musb->xceiv->state));
+                       usb_otg_state_string(musb->xceiv->state));
        }
 
        /*
@@ -451,7 +452,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
         */
        if (int_usb & MUSB_INTR_RESUME) {
                handled = IRQ_HANDLED;
-               dev_dbg(musb->controller, "RESUME (%s)\n", otg_state_string(musb->xceiv->state));
+               dev_dbg(musb->controller, "RESUME (%s)\n", usb_otg_state_string(musb->xceiv->state));
 
                if (devctl & MUSB_DEVCTL_HM) {
                        void __iomem *mbase = musb->mregs;
@@ -493,7 +494,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                        default:
                                WARNING("bogus %s RESUME (%s)\n",
                                        "host",
-                                       otg_state_string(musb->xceiv->state));
+                                       usb_otg_state_string(musb->xceiv->state));
                        }
                } else {
                        switch (musb->xceiv->state) {
@@ -522,7 +523,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                        default:
                                WARNING("bogus %s RESUME (%s)\n",
                                        "peripheral",
-                                       otg_state_string(musb->xceiv->state));
+                                       usb_otg_state_string(musb->xceiv->state));
                        }
                }
        }
@@ -538,7 +539,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                }
 
                dev_dbg(musb->controller, "SESSION_REQUEST (%s)\n",
-                       otg_state_string(musb->xceiv->state));
+                       usb_otg_state_string(musb->xceiv->state));
 
                /* IRQ arrives from ID pin sense or (later, if VBUS power
                 * is removed) SRP.  responses are time critical:
@@ -602,8 +603,9 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
                        break;
                }
 
-               dev_dbg(musb->controller, "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n",
-                               otg_state_string(musb->xceiv->state),
+               dev_printk(ignore ? KERN_DEBUG : KERN_ERR, musb->controller,
+                               "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n",
+                               usb_otg_state_string(musb->xceiv->state),
                                devctl,
                                ({ char *s;
                                switch (devctl & MUSB_DEVCTL_VBUS) {
@@ -628,7 +630,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 
        if (int_usb & MUSB_INTR_SUSPEND) {
                dev_dbg(musb->controller, "SUSPEND (%s) devctl %02x\n",
-                       otg_state_string(musb->xceiv->state), devctl);
+                       usb_otg_state_string(musb->xceiv->state), devctl);
                handled = IRQ_HANDLED;
 
                switch (musb->xceiv->state) {
@@ -745,12 +747,12 @@ b_host:
                        usb_hcd_resume_root_hub(hcd);
 
                dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n",
-                               otg_state_string(musb->xceiv->state), devctl);
+                               usb_otg_state_string(musb->xceiv->state), devctl);
        }
 
        if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) {
                dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n",
-                               otg_state_string(musb->xceiv->state),
+                               usb_otg_state_string(musb->xceiv->state),
                                MUSB_MODE(musb), devctl);
                handled = IRQ_HANDLED;
 
@@ -787,7 +789,7 @@ b_host:
                        break;
                default:
                        WARNING("unhandled DISCONNECT transition (%s)\n",
-                               otg_state_string(musb->xceiv->state));
+                               usb_otg_state_string(musb->xceiv->state));
                        break;
                }
        }
@@ -813,7 +815,7 @@ b_host:
                        }
                } else {
                        dev_dbg(musb->controller, "BUS RESET as %s\n",
-                               otg_state_string(musb->xceiv->state));
+                               usb_otg_state_string(musb->xceiv->state));
                        switch (musb->xceiv->state) {
                        case OTG_STATE_A_SUSPEND:
                                /* We need to ignore disconnect on suspend
@@ -826,7 +828,7 @@ b_host:
                        case OTG_STATE_A_WAIT_BCON:     /* OPT TD.4.7-900ms */
                                /* never use invalid T(a_wait_bcon) */
                                dev_dbg(musb->controller, "HNP: in %s, %d msec timeout\n",
-                                       otg_state_string(musb->xceiv->state),
+                                       usb_otg_state_string(musb->xceiv->state),
                                        TA_WAIT_BCON(musb));
                                mod_timer(&musb->otg_timer, jiffies
                                        + msecs_to_jiffies(TA_WAIT_BCON(musb)));
@@ -838,7 +840,7 @@ b_host:
                                break;
                        case OTG_STATE_B_WAIT_ACON:
                                dev_dbg(musb->controller, "HNP: RESET (%s), to b_peripheral\n",
-                                       otg_state_string(musb->xceiv->state));
+                                       usb_otg_state_string(musb->xceiv->state));
                                musb->xceiv->state = OTG_STATE_B_PERIPHERAL;
                                musb_g_reset(musb);
                                break;
@@ -850,7 +852,7 @@ b_host:
                                break;
                        default:
                                dev_dbg(musb->controller, "Unhandled BUS RESET as %s\n",
-                                       otg_state_string(musb->xceiv->state));
+                                       usb_otg_state_string(musb->xceiv->state));
                        }
                }
        }
@@ -1632,7 +1634,7 @@ musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
        int ret = -EINVAL;
 
        spin_lock_irqsave(&musb->lock, flags);
-       ret = sprintf(buf, "%s\n", otg_state_string(musb->xceiv->state));
+       ret = sprintf(buf, "%s\n", usb_otg_state_string(musb->xceiv->state));
        spin_unlock_irqrestore(&musb->lock, flags);
 
        return ret;
@@ -1951,9 +1953,13 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
                musb_write_ulpi_buscontrol(musb->mregs, busctl);
        }
 
-       MUSB_DEV_MODE(musb);
-       musb->xceiv->otg->default_a = 0;
-       musb->xceiv->state = OTG_STATE_B_IDLE;
+       if (musb->xceiv->otg->default_a) {
+               MUSB_HST_MODE(musb);
+               musb->xceiv->state = OTG_STATE_A_IDLE;
+       } else {
+               MUSB_DEV_MODE(musb);
+               musb->xceiv->state = OTG_STATE_B_IDLE;
+       }
 
        status = musb_gadget_setup(musb);
 
@@ -2008,7 +2014,6 @@ static int musb_probe(struct platform_device *pdev)
 {
        struct device   *dev = &pdev->dev;
        int             irq = platform_get_irq_byname(pdev, "mc");
-       int             status;
        struct resource *iomem;
        void __iomem    *base;
 
@@ -2016,24 +2021,17 @@ static int musb_probe(struct platform_device *pdev)
        if (!iomem || irq <= 0)
                return -ENODEV;
 
-       base = ioremap(iomem->start, resource_size(iomem));
-       if (!base) {
-               dev_err(dev, "ioremap failed\n");
-               return -ENOMEM;
-       }
+       base = devm_ioremap_resource(dev, iomem);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
 
-       status = musb_init_controller(dev, irq, base);
-       if (status < 0)
-               iounmap(base);
-
-       return status;
+       return musb_init_controller(dev, irq, base);
 }
 
 static int musb_remove(struct platform_device *pdev)
 {
        struct device   *dev = &pdev->dev;
        struct musb     *musb = dev_to_musb(dev);
-       void __iomem    *ctrl_base = musb->ctrl_base;
 
        /* this gets called on rmmod.
         *  - Host mode: host may still be active
@@ -2044,7 +2042,6 @@ static int musb_remove(struct platform_device *pdev)
        musb_shutdown(pdev);
 
        musb_free(musb);
-       iounmap(ctrl_base);
        device_init_wakeup(dev, 0);
 #ifndef CONFIG_MUSB_PIO_ONLY
        dma_set_mask(dev, *dev->parent->dma_mask);
@@ -2293,8 +2290,6 @@ static int __init musb_init(void)
        if (usb_disabled())
                return 0;
 
-       pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n",
-               musb_driver_name);
        return platform_driver_register(&musb_driver);
 }
 module_init(musb_init);
index 6bb89715b63703a22a96419f88711d7dde665e49..3a18e44e9391850ab7f7ee7858cd6d134b59361e 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/module.h>
 #include <linux/usb/nop-usb-xceiv.h>
 #include <linux/platform_data/usb-omap.h>
+#include <linux/sizes.h>
 
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -224,7 +225,7 @@ static void otg_timer(unsigned long _musb)
         */
        devctl = dsps_readb(mregs, MUSB_DEVCTL);
        dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl,
-                               otg_state_string(musb->xceiv->state));
+                               usb_otg_state_string(musb->xceiv->state));
 
        spin_lock_irqsave(&musb->lock, flags);
        switch (musb->xceiv->state) {
@@ -273,7 +274,7 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
        if (musb->is_active || (musb->a_wait_bcon == 0 &&
                                musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) {
                dev_dbg(musb->controller, "%s active, deleting timer\n",
-                               otg_state_string(musb->xceiv->state));
+                               usb_otg_state_string(musb->xceiv->state));
                del_timer(&glue->timer[pdev->id]);
                glue->last_timer[pdev->id] = jiffies;
                return;
@@ -288,7 +289,7 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout)
        glue->last_timer[pdev->id] = timeout;
 
        dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n",
-               otg_state_string(musb->xceiv->state),
+               usb_otg_state_string(musb->xceiv->state),
                        jiffies_to_msecs(timeout - jiffies));
        mod_timer(&glue->timer[pdev->id], timeout);
 }
@@ -334,7 +335,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
         * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set.
         * Also, DRVVBUS pulses for SRP (but not at 5V) ...
         */
-       if (usbintr & MUSB_INTR_BABBLE)
+       if (is_host_active(musb) && usbintr & MUSB_INTR_BABBLE)
                pr_info("CAUTION: musb: Babble Interrupt Occurred\n");
 
        if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) {
@@ -377,7 +378,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci)
                /* NOTE: this must complete power-on within 100 ms. */
                dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n",
                                drvvbus ? "on" : "off",
-                               otg_state_string(musb->xceiv->state),
+                               usb_otg_state_string(musb->xceiv->state),
                                err ? " ERROR" : "",
                                devctl);
                ret = IRQ_HANDLED;
@@ -596,14 +597,13 @@ err0:
 
 static int dsps_probe(struct platform_device *pdev)
 {
-       struct device_node *np = pdev->dev.of_node;
        const struct of_device_id *match;
        const struct dsps_musb_wrapper *wrp;
        struct dsps_glue *glue;
        struct resource *iomem;
        int ret, i;
 
-       match = of_match_node(musb_dsps_of_match, np);
+       match = of_match_node(musb_dsps_of_match, pdev->dev.of_node);
        if (!match) {
                dev_err(&pdev->dev, "fail to get matching of_match struct\n");
                ret = -EINVAL;
index 83eddedcd9be5895908672b329ebf881d26d8f2f..ba7092349fa95507a24ac3dedb7c0256f93ab269 100644 (file)
 #include "musb_core.h"
 
 
-/* MUSB PERIPHERAL status 3-mar-2006:
- *
- * - EP0 seems solid.  It passes both USBCV and usbtest control cases.
- *   Minor glitches:
- *
- *     + remote wakeup to Linux hosts work, but saw USBCV failures;
- *       in one test run (operator error?)
- *     + endpoint halt tests -- in both usbtest and usbcv -- seem
- *       to break when dma is enabled ... is something wrongly
- *       clearing SENDSTALL?
- *
- * - Mass storage behaved ok when last tested.  Network traffic patterns
- *   (with lots of short transfers etc) need retesting; they turn up the
- *   worst cases of the DMA, since short packets are typical but are not
- *   required.
- *
- * - TX/IN
- *     + both pio and dma behave in with network and g_zero tests
- *     + no cppi throughput issues other than no-hw-queueing
- *     + failed with FLAT_REG (DaVinci)
- *     + seems to behave with double buffering, PIO -and- CPPI
- *     + with gadgetfs + AIO, requests got lost?
- *
- * - RX/OUT
- *     + both pio and dma behave in with network and g_zero tests
- *     + dma is slow in typical case (short_not_ok is clear)
- *     + double buffering ok with PIO
- *     + double buffering *FAILS* with CPPI, wrong data bytes sometimes
- *     + request lossage observed with gadgetfs
- *
- * - ISO not tested ... might work, but only weakly isochronous
- *
- * - Gadget driver disabling of softconnect during bind() is ignored; so
- *   drivers can't hold off host requests until userspace is ready.
- *   (Workaround:  they can turn it off later.)
- *
- * - PORTABILITY (assumes PIO works):
- *     + DaVinci, basically works with cppi dma
- *     + OMAP 2430, ditto with mentor dma
- *     + TUSB 6010, platform-specific dma in the works
- */
-
 /* ----------------------------------------------------------------------- */
 
 #define is_buffer_mapped(req) (is_dma_capable() && \
@@ -280,41 +238,6 @@ static inline int max_ep_writesize(struct musb *musb, struct musb_ep *ep)
                return ep->packet_sz;
 }
 
-
-#ifdef CONFIG_USB_INVENTRA_DMA
-
-/* Peripheral tx (IN) using Mentor DMA works as follows:
-       Only mode 0 is used for transfers <= wPktSize,
-       mode 1 is used for larger transfers,
-
-       One of the following happens:
-       - Host sends IN token which causes an endpoint interrupt
-               -> TxAvail
-                       -> if DMA is currently busy, exit.
-                       -> if queue is non-empty, txstate().
-
-       - Request is queued by the gadget driver.
-               -> if queue was previously empty, txstate()
-
-       txstate()
-               -> start
-                 /\    -> setup DMA
-                 |     (data is transferred to the FIFO, then sent out when
-                 |     IN token(s) are recd from Host.
-                 |             -> DMA interrupt on completion
-                 |                calls TxAvail.
-                 |                   -> stop DMA, ~DMAENAB,
-                 |                   -> set TxPktRdy for last short pkt or zlp
-                 |                   -> Complete Request
-                 |                   -> Continue next request (call txstate)
-                 |___________________________________|
-
- * Non-Mentor DMA engines can of course work differently, such as by
- * upleveling from irq-per-packet to irq-per-buffer.
- */
-
-#endif
-
 /*
  * An endpoint is transmitting data. This can be called either from
  * the IRQ routine or from ep.queue() to kickstart a request on an
@@ -621,37 +544,6 @@ void musb_g_tx(struct musb *musb, u8 epnum)
 
 /* ------------------------------------------------------------ */
 
-#ifdef CONFIG_USB_INVENTRA_DMA
-
-/* Peripheral rx (OUT) using Mentor DMA works as follows:
-       - Only mode 0 is used.
-
-       - Request is queued by the gadget class driver.
-               -> if queue was previously empty, rxstate()
-
-       - Host sends OUT token which causes an endpoint interrupt
-         /\      -> RxReady
-         |           -> if request queued, call rxstate
-         |             /\      -> setup DMA
-         |             |            -> DMA interrupt on completion
-         |             |               -> RxReady
-         |             |                     -> stop DMA
-         |             |                     -> ack the read
-         |             |                     -> if data recd = max expected
-         |             |                               by the request, or host
-         |             |                               sent a short packet,
-         |             |                               complete the request,
-         |             |                               and start the next one.
-         |             |_____________________________________|
-         |                                      else just wait for the host
-         |                                         to send the next OUT token.
-         |__________________________________________________|
-
- * Non-Mentor DMA engines can of course work differently.
- */
-
-#endif
-
 /*
  * Context: controller locked, IRQs blocked, endpoint selected
  */
@@ -740,7 +632,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
                                struct dma_controller   *c;
                                struct dma_channel      *channel;
                                int                     use_dma = 0;
-                               int transfer_size;
+                               unsigned int transfer_size;
 
                                c = musb->dma_controller;
                                channel = musb_ep->dma;
@@ -782,10 +674,11 @@ static void rxstate(struct musb *musb, struct musb_request *req)
                                                csr | MUSB_RXCSR_DMAMODE);
                                        musb_writew(epio, MUSB_RXCSR, csr);
 
-                                       transfer_size = min(request->length - request->actual,
+                                       transfer_size = min_t(unsigned int,
+                                                       request->length -
+                                                       request->actual,
                                                        channel->max_len);
                                        musb_ep->dma->desired_mode = 1;
-
                                } else {
                                        if (!musb_ep->hb_mult &&
                                                musb_ep->hw_ep->rx_double_buffered)
@@ -815,7 +708,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
 
                                struct dma_controller *c;
                                struct dma_channel *channel;
-                               int transfer_size = 0;
+                               unsigned int transfer_size = 0;
 
                                c = musb->dma_controller;
                                channel = musb_ep->dma;
@@ -824,11 +717,13 @@ static void rxstate(struct musb *musb, struct musb_request *req)
                                if (fifo_count < musb_ep->packet_sz)
                                        transfer_size = fifo_count;
                                else if (request->short_not_ok)
-                                       transfer_size = min(request->length -
+                                       transfer_size = min_t(unsigned int,
+                                                       request->length -
                                                        request->actual,
                                                        channel->max_len);
                                else
-                                       transfer_size = min(request->length -
+                                       transfer_size = min_t(unsigned int,
+                                                       request->length -
                                                        request->actual,
                                                        (unsigned)fifo_count);
 
@@ -1681,7 +1576,7 @@ static int musb_gadget_wakeup(struct usb_gadget *gadget)
                goto done;
        default:
                dev_dbg(musb->controller, "Unhandled wake: %s\n",
-                       otg_state_string(musb->xceiv->state));
+                       usb_otg_state_string(musb->xceiv->state));
                goto done;
        }
 
@@ -1801,13 +1696,6 @@ static const struct usb_gadget_ops musb_gadget_operations = {
  * all peripheral ports are external...
  */
 
-static void musb_gadget_release(struct device *dev)
-{
-       /* kref_put(WHAT) */
-       dev_dbg(dev, "%s\n", __func__);
-}
-
-
 static void
 init_peripheral_ep(struct musb *musb, struct musb_ep *ep, u8 epnum, int is_in)
 {
@@ -1892,12 +1780,7 @@ int musb_gadget_setup(struct musb *musb)
        musb->g.speed = USB_SPEED_UNKNOWN;
 
        /* this "gadget" abstracts/virtualizes the controller */
-       dev_set_name(&musb->g.dev, "gadget");
-       musb->g.dev.parent = musb->controller;
-       musb->g.dev.dma_mask = musb->controller->dma_mask;
-       musb->g.dev.release = musb_gadget_release;
        musb->g.name = musb_driver_name;
-
        musb->g.is_otg = 1;
 
        musb_g_init_endpoints(musb);
@@ -1905,11 +1788,6 @@ int musb_gadget_setup(struct musb *musb)
        musb->is_active = 0;
        musb_platform_try_idle(musb, 0);
 
-       status = device_register(&musb->g.dev);
-       if (status != 0) {
-               put_device(&musb->g.dev);
-               return status;
-       }
        status = usb_add_gadget_udc(musb->controller, &musb->g);
        if (status)
                goto err;
@@ -1924,8 +1802,6 @@ err:
 void musb_gadget_cleanup(struct musb *musb)
 {
        usb_del_gadget_udc(&musb->g);
-       if (musb->g.dev.parent)
-               device_unregister(&musb->g.dev);
 }
 
 /*
@@ -1977,9 +1853,8 @@ static int musb_gadget_start(struct usb_gadget *g,
                goto err;
        }
 
-       if ((musb->xceiv->last_event == USB_EVENT_ID)
-                               && otg->set_vbus)
-               otg_set_vbus(otg, 1);
+       if (musb->xceiv->last_event == USB_EVENT_ID)
+               musb_platform_set_vbus(musb, 1);
 
        hcd->self.uses_pio_for_control = 1;
 
@@ -2063,6 +1938,7 @@ static int musb_gadget_stop(struct usb_gadget *g,
        dev_dbg(musb->controller, "unregistering driver %s\n", driver->function);
 
        musb->is_active = 0;
+       musb->gadget_driver = NULL;
        musb_platform_try_idle(musb, 0);
        spin_unlock_irqrestore(&musb->lock, flags);
 
@@ -2099,7 +1975,7 @@ void musb_g_resume(struct musb *musb)
                break;
        default:
                WARNING("unhandled RESUME transition (%s)\n",
-                               otg_state_string(musb->xceiv->state));
+                               usb_otg_state_string(musb->xceiv->state));
        }
 }
 
@@ -2129,7 +2005,7 @@ void musb_g_suspend(struct musb *musb)
                 * A_PERIPHERAL may need care too
                 */
                WARNING("unhandled SUSPEND transition (%s)\n",
-                               otg_state_string(musb->xceiv->state));
+                               usb_otg_state_string(musb->xceiv->state));
        }
 }
 
@@ -2163,7 +2039,7 @@ void musb_g_disconnect(struct musb *musb)
        switch (musb->xceiv->state) {
        default:
                dev_dbg(musb->controller, "Unhandled disconnect %s, setting a_idle\n",
-                       otg_state_string(musb->xceiv->state));
+                       usb_otg_state_string(musb->xceiv->state));
                musb->xceiv->state = OTG_STATE_A_IDLE;
                MUSB_HST_MODE(musb);
                break;
index c9c1ac4e075f758ae01eaf0a79b738ee41da0611..2af45a0c8930b35ca645834c157291198c383aca 100644 (file)
@@ -505,8 +505,10 @@ static void ep0_rxstate(struct musb *musb)
                        req->status = -EOVERFLOW;
                        count = len;
                }
-               musb_read_fifo(&musb->endpoints[0], count, buf);
-               req->actual += count;
+               if (count > 0) {
+                       musb_read_fifo(&musb->endpoints[0], count, buf);
+                       req->actual += count;
+               }
                csr = MUSB_CSR0_P_SVDRXPKTRDY;
                if (count < 64 || req->actual == req->length) {
                        musb->ep0_state = MUSB_EP0_STAGE_STATUSIN;
index 1ce1fcf3f3e7bd19be87f8d02b4dcac13ca54f28..8914dec49f01cfc2e70a89d1e2de1c29a70ef08c 100644 (file)
@@ -2453,7 +2453,7 @@ static int musb_bus_suspend(struct usb_hcd *hcd)
 
        if (musb->is_active) {
                WARNING("trying to suspend as %s while active\n",
-                               otg_state_string(musb->xceiv->state));
+                               usb_otg_state_string(musb->xceiv->state));
                return -EBUSY;
        } else
                return 0;
@@ -2465,6 +2465,118 @@ static int musb_bus_resume(struct usb_hcd *hcd)
        return 0;
 }
 
+
+#ifndef CONFIG_MUSB_PIO_ONLY
+
+#define MUSB_USB_DMA_ALIGN 4
+
+struct musb_temp_buffer {
+       void *kmalloc_ptr;
+       void *old_xfer_buffer;
+       u8 data[0];
+};
+
+static void musb_free_temp_buffer(struct urb *urb)
+{
+       enum dma_data_direction dir;
+       struct musb_temp_buffer *temp;
+
+       if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER))
+               return;
+
+       dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+       temp = container_of(urb->transfer_buffer, struct musb_temp_buffer,
+                           data);
+
+       if (dir == DMA_FROM_DEVICE) {
+               memcpy(temp->old_xfer_buffer, temp->data,
+                      urb->transfer_buffer_length);
+       }
+       urb->transfer_buffer = temp->old_xfer_buffer;
+       kfree(temp->kmalloc_ptr);
+
+       urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
+}
+
+static int musb_alloc_temp_buffer(struct urb *urb, gfp_t mem_flags)
+{
+       enum dma_data_direction dir;
+       struct musb_temp_buffer *temp;
+       void *kmalloc_ptr;
+       size_t kmalloc_size;
+
+       if (urb->num_sgs || urb->sg ||
+           urb->transfer_buffer_length == 0 ||
+           !((uintptr_t)urb->transfer_buffer & (MUSB_USB_DMA_ALIGN - 1)))
+               return 0;
+
+       dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+       /* Allocate a buffer with enough padding for alignment */
+       kmalloc_size = urb->transfer_buffer_length +
+               sizeof(struct musb_temp_buffer) + MUSB_USB_DMA_ALIGN - 1;
+
+       kmalloc_ptr = kmalloc(kmalloc_size, mem_flags);
+       if (!kmalloc_ptr)
+               return -ENOMEM;
+
+       /* Position our struct temp_buffer such that data is aligned */
+       temp = PTR_ALIGN(kmalloc_ptr, MUSB_USB_DMA_ALIGN);
+
+
+       temp->kmalloc_ptr = kmalloc_ptr;
+       temp->old_xfer_buffer = urb->transfer_buffer;
+       if (dir == DMA_TO_DEVICE)
+               memcpy(temp->data, urb->transfer_buffer,
+                      urb->transfer_buffer_length);
+       urb->transfer_buffer = temp->data;
+
+       urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER;
+
+       return 0;
+}
+
+static int musb_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+                                     gfp_t mem_flags)
+{
+       struct musb     *musb = hcd_to_musb(hcd);
+       int ret;
+
+       /*
+        * The DMA engine in RTL1.8 and above cannot handle
+        * DMA addresses that are not aligned to a 4 byte boundary.
+        * For such engine implemented (un)map_urb_for_dma hooks.
+        * Do not use these hooks for RTL<1.8
+        */
+       if (musb->hwvers < MUSB_HWVERS_1800)
+               return usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
+
+       ret = musb_alloc_temp_buffer(urb, mem_flags);
+       if (ret)
+               return ret;
+
+       ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
+       if (ret)
+               musb_free_temp_buffer(urb);
+
+       return ret;
+}
+
+static void musb_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+{
+       struct musb     *musb = hcd_to_musb(hcd);
+
+       usb_hcd_unmap_urb_for_dma(hcd, urb);
+
+       /* Do not use this hook for RTL<1.8 (see description above) */
+       if (musb->hwvers < MUSB_HWVERS_1800)
+               return;
+
+       musb_free_temp_buffer(urb);
+}
+#endif /* !CONFIG_MUSB_PIO_ONLY */
+
 const struct hc_driver musb_hc_driver = {
        .description            = "musb-hcd",
        .product_desc           = "MUSB HDRC host driver",
@@ -2484,6 +2596,11 @@ const struct hc_driver musb_hc_driver = {
        .urb_dequeue            = musb_urb_dequeue,
        .endpoint_disable       = musb_h_disable,
 
+#ifndef CONFIG_MUSB_PIO_ONLY
+       .map_urb_for_dma        = musb_map_urb_for_dma,
+       .unmap_urb_for_dma      = musb_unmap_urb_for_dma,
+#endif
+
        .hub_status_data        = musb_hub_status_data,
        .hub_control            = musb_hub_control,
        .bus_suspend            = musb_bus_suspend,
index f70579154ded77467ed33976e357ef763b478149..ef7d11045f561cb69db73d57ee5a42777fd8a91e 100644 (file)
@@ -95,7 +95,7 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend)
                        break;
                default:
                        dev_dbg(musb->controller, "bogus rh suspend? %s\n",
-                               otg_state_string(musb->xceiv->state));
+                               usb_otg_state_string(musb->xceiv->state));
                }
        } else if (power & MUSB_POWER_SUSPENDM) {
                power &= ~MUSB_POWER_SUSPENDM;
@@ -203,7 +203,7 @@ void musb_root_disconnect(struct musb *musb)
                break;
        default:
                dev_dbg(musb->controller, "host disconnect (%s)\n",
-                       otg_state_string(musb->xceiv->state));
+                       usb_otg_state_string(musb->xceiv->state));
        }
 }
 
index 1a42a458f2c4ff64cb8e9e3492bf368cf79cf0c3..3551f1a30c655efdc2977556e9e4f6c540ea115a 100644 (file)
@@ -117,7 +117,7 @@ static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout)
        if (musb->is_active || ((musb->a_wait_bcon == 0)
                        && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
                dev_dbg(musb->controller, "%s active, deleting timer\n",
-                       otg_state_string(musb->xceiv->state));
+                       usb_otg_state_string(musb->xceiv->state));
                del_timer(&musb_idle_timer);
                last_timer = jiffies;
                return;
@@ -134,7 +134,7 @@ static void omap2430_musb_try_idle(struct musb *musb, unsigned long timeout)
        last_timer = timeout;
 
        dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n",
-               otg_state_string(musb->xceiv->state),
+               usb_otg_state_string(musb->xceiv->state),
                (unsigned long)jiffies_to_msecs(timeout - jiffies));
        mod_timer(&musb_idle_timer, timeout);
 }
@@ -174,8 +174,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
                                }
                        }
 
-                       if (otg->set_vbus)
-                               otg_set_vbus(otg, 1);
+                       otg_set_vbus(otg, 1);
                } else {
                        musb->is_active = 1;
                        otg->default_a = 1;
@@ -200,7 +199,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on)
 
        dev_dbg(musb->controller, "VBUS %s, devctl %02x "
                /* otg %3x conf %08x prcm %08x */ "\n",
-               otg_state_string(musb->xceiv->state),
+               usb_otg_state_string(musb->xceiv->state),
                musb_readb(musb->mregs, MUSB_DEVCTL));
 }
 
@@ -292,14 +291,14 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue)
 
                musb->xceiv->last_event = USB_EVENT_NONE;
                if (musb->gadget_driver) {
+                       omap2430_musb_set_vbus(musb, 0);
                        pm_runtime_mark_last_busy(dev);
                        pm_runtime_put_autosuspend(dev);
                }
 
-               if (data->interface_type == MUSB_INTERFACE_UTMI) {
-                       if (musb->xceiv->otg->set_vbus)
-                               otg_set_vbus(musb->xceiv->otg, 0);
-               }
+               if (data->interface_type == MUSB_INTERFACE_UTMI)
+                       otg_set_vbus(musb->xceiv->otg, 0);
+
                omap_control_usb_set_mode(glue->control_otghs,
                        USB_MODE_DISCONNECT);
                break;
@@ -355,7 +354,12 @@ static int omap2430_musb_init(struct musb *musb)
        else
                musb->xceiv = devm_usb_get_phy_dev(dev, 0);
 
-       if (IS_ERR_OR_NULL(musb->xceiv)) {
+       if (IS_ERR(musb->xceiv)) {
+               status = PTR_ERR(musb->xceiv);
+
+               if (status == -ENXIO)
+                       return status;
+
                pr_err("HS USB OTG: no transceiver configured\n");
                return -EPROBE_DEFER;
        }
@@ -393,6 +397,8 @@ static int omap2430_musb_init(struct musb *musb)
        if (glue->status != OMAP_MUSB_UNKNOWN)
                omap_musb_set_mailbox(glue);
 
+       usb_phy_init(musb->xceiv);
+
        pm_runtime_put_noidle(musb->controller);
        return 0;
 
@@ -526,10 +532,10 @@ static int omap2430_probe(struct platform_device *pdev)
                }
 
                of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
-               of_property_read_u32(np, "interface_type",
+               of_property_read_u32(np, "interface-type",
                                                (u32 *)&data->interface_type);
-               of_property_read_u32(np, "num_eps", (u32 *)&config->num_eps);
-               of_property_read_u32(np, "ram_bits", (u32 *)&config->ram_bits);
+               of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);
+               of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
                of_property_read_u32(np, "power", (u32 *)&pdata->power);
                config->multipoint = of_property_read_bool(np, "multipoint");
                pdata->has_mailbox = of_property_read_bool(np,
index 464bd23cccda0cf04bca5fe3e8d4e0d3bde56201..7369ba33c94f1edc529c93dd03444c99fae5c464 100644 (file)
@@ -423,7 +423,7 @@ static void musb_do_idle(unsigned long _musb)
                        && (musb->idle_timeout == 0
                                || time_after(jiffies, musb->idle_timeout))) {
                        dev_dbg(musb->controller, "Nothing connected %s, turning off VBUS\n",
-                                       otg_state_string(musb->xceiv->state));
+                                       usb_otg_state_string(musb->xceiv->state));
                }
                /* FALLTHROUGH */
        case OTG_STATE_A_IDLE:
@@ -478,7 +478,7 @@ static void tusb_musb_try_idle(struct musb *musb, unsigned long timeout)
        if (musb->is_active || ((musb->a_wait_bcon == 0)
                        && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
                dev_dbg(musb->controller, "%s active, deleting timer\n",
-                       otg_state_string(musb->xceiv->state));
+                       usb_otg_state_string(musb->xceiv->state));
                del_timer(&musb_idle_timer);
                last_timer = jiffies;
                return;
@@ -495,7 +495,7 @@ static void tusb_musb_try_idle(struct musb *musb, unsigned long timeout)
        last_timer = timeout;
 
        dev_dbg(musb->controller, "%s inactive, for idle timer for %lu ms\n",
-               otg_state_string(musb->xceiv->state),
+               usb_otg_state_string(musb->xceiv->state),
                (unsigned long)jiffies_to_msecs(timeout - jiffies));
        mod_timer(&musb_idle_timer, timeout);
 }
@@ -571,7 +571,7 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on)
        musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
 
        dev_dbg(musb->controller, "VBUS %s, devctl %02x otg %3x conf %08x prcm %08x\n",
-               otg_state_string(musb->xceiv->state),
+               usb_otg_state_string(musb->xceiv->state),
                musb_readb(musb->mregs, MUSB_DEVCTL),
                musb_readl(tbase, TUSB_DEV_OTG_STAT),
                conf, prcm);
@@ -678,13 +678,13 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
                                musb->is_active = 0;
                        }
                        dev_dbg(musb->controller, "vbus change, %s, otg %03x\n",
-                               otg_state_string(musb->xceiv->state), otg_stat);
+                               usb_otg_state_string(musb->xceiv->state), otg_stat);
                        idle_timeout = jiffies + (1 * HZ);
                        schedule_work(&musb->irq_work);
 
                } else /* A-dev state machine */ {
                        dev_dbg(musb->controller, "vbus change, %s, otg %03x\n",
-                               otg_state_string(musb->xceiv->state), otg_stat);
+                               usb_otg_state_string(musb->xceiv->state), otg_stat);
 
                        switch (musb->xceiv->state) {
                        case OTG_STATE_A_IDLE:
@@ -733,7 +733,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase)
                u8      devctl;
 
                dev_dbg(musb->controller, "%s timer, %03x\n",
-                       otg_state_string(musb->xceiv->state), otg_stat);
+                       usb_otg_state_string(musb->xceiv->state), otg_stat);
 
                switch (musb->xceiv->state) {
                case OTG_STATE_A_WAIT_VRISE:
index 13a392913769ad6e11ad36d5a24a7c0233eb10a9..2c80004e0a83029b52b7ea13f2d4c97194f40412 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
+#include <linux/usb/musb-ux500.h>
 
 #include "musb_core.h"
 
@@ -36,6 +37,98 @@ struct ux500_glue {
 };
 #define glue_to_musb(g)        platform_get_drvdata(g->musb)
 
+static void ux500_musb_set_vbus(struct musb *musb, int is_on)
+{
+       u8            devctl;
+       unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+       /* HDRC controls CPEN, but beware current surges during device
+        * connect.  They can trigger transient overcurrent conditions
+        * that must be ignored.
+        */
+
+       devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
+
+       if (is_on) {
+               if (musb->xceiv->state == OTG_STATE_A_IDLE) {
+                       /* start the session */
+                       devctl |= MUSB_DEVCTL_SESSION;
+                       musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+                       /*
+                        * Wait for the musb to set as A device to enable the
+                        * VBUS
+                        */
+                       while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) {
+
+                               if (time_after(jiffies, timeout)) {
+                                       dev_err(musb->controller,
+                                       "configured as A device timeout");
+                                       break;
+                               }
+                       }
+
+               } else {
+                       musb->is_active = 1;
+                       musb->xceiv->otg->default_a = 1;
+                       musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
+                       devctl |= MUSB_DEVCTL_SESSION;
+                       MUSB_HST_MODE(musb);
+               }
+       } else {
+               musb->is_active = 0;
+
+               /* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and jumping
+                * right to B_IDLE...
+                */
+               musb->xceiv->otg->default_a = 0;
+               devctl &= ~MUSB_DEVCTL_SESSION;
+               MUSB_DEV_MODE(musb);
+       }
+       musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
+
+       /*
+        * Devctl values will be updated after vbus goes below
+        * session_valid. The time taken depends on the capacitance
+        * on VBUS line. The max discharge time can be upto 1 sec
+        * as per the spec. Typically on our platform, it is 200ms
+        */
+       if (!is_on)
+               mdelay(200);
+
+       dev_dbg(musb->controller, "VBUS %s, devctl %02x\n",
+               usb_otg_state_string(musb->xceiv->state),
+               musb_readb(musb->mregs, MUSB_DEVCTL));
+}
+
+static int musb_otg_notifications(struct notifier_block *nb,
+               unsigned long event, void *unused)
+{
+       struct musb *musb = container_of(nb, struct musb, nb);
+
+       dev_dbg(musb->controller, "musb_otg_notifications %ld %s\n",
+                       event, usb_otg_state_string(musb->xceiv->state));
+
+       switch (event) {
+       case UX500_MUSB_ID:
+               dev_dbg(musb->controller, "ID GND\n");
+               ux500_musb_set_vbus(musb, 1);
+               break;
+       case UX500_MUSB_VBUS:
+               dev_dbg(musb->controller, "VBUS Connect\n");
+               break;
+       case UX500_MUSB_NONE:
+               dev_dbg(musb->controller, "VBUS Disconnect\n");
+               if (is_host_active(musb))
+                       ux500_musb_set_vbus(musb, 0);
+               else
+                       musb->xceiv->state = OTG_STATE_B_IDLE;
+               break;
+       default:
+               dev_dbg(musb->controller, "ID float\n");
+               return NOTIFY_DONE;
+       }
+       return NOTIFY_OK;
+}
+
 static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)
 {
        unsigned long   flags;
@@ -58,12 +151,21 @@ static irqreturn_t ux500_musb_interrupt(int irq, void *__hci)
 
 static int ux500_musb_init(struct musb *musb)
 {
+       int status;
+
        musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
        if (IS_ERR_OR_NULL(musb->xceiv)) {
                pr_err("HS USB OTG: no transceiver configured\n");
                return -EPROBE_DEFER;
        }
 
+       musb->nb.notifier_call = musb_otg_notifications;
+       status = usb_register_notifier(musb->xceiv, &musb->nb);
+       if (status < 0) {
+               dev_dbg(musb->controller, "notification register failed\n");
+               return status;
+       }
+
        musb->isr = ux500_musb_interrupt;
 
        return 0;
@@ -71,6 +173,8 @@ static int ux500_musb_init(struct musb *musb)
 
 static int ux500_musb_exit(struct musb *musb)
 {
+       usb_unregister_notifier(musb->xceiv, &musb->nb);
+
        usb_put_phy(musb->xceiv);
 
        return 0;
@@ -79,6 +183,8 @@ static int ux500_musb_exit(struct musb *musb)
 static const struct musb_platform_ops ux500_ops = {
        .init           = ux500_musb_init,
        .exit           = ux500_musb_exit,
+
+       .set_vbus       = ux500_musb_set_vbus,
 };
 
 static int ux500_probe(struct platform_device *pdev)
index 039e567dd3b68548310325fea4f9776240884888..33812064114557c58a2db3bc9166b1bbe7d57f61 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/usb/musb/ux500_dma.c
  *
- * U8500 and U5500 DMA support code
+ * U8500 DMA support code
  *
  * Copyright (C) 2009 STMicroelectronics
  * Copyright (C) 2011 ST-Ericsson SA
@@ -30,6 +30,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
 #include <linux/pfn.h>
+#include <linux/sizes.h>
 #include <linux/platform_data/usb-musb-ux500.h>
 #include "musb_core.h"
 
@@ -56,7 +57,7 @@ struct ux500_dma_controller {
 };
 
 /* Work function invoked from DMA callback to handle rx transfers. */
-void ux500_dma_callback(void *private_data)
+static void ux500_dma_callback(void *private_data)
 {
        struct dma_channel *channel = private_data;
        struct ux500_dma_channel *ux500_channel = channel->private_data;
@@ -93,8 +94,9 @@ static bool ux500_configure_channel(struct dma_channel *channel,
        struct musb *musb = ux500_channel->controller->private_data;
 
        dev_dbg(musb->controller,
-               "packet_sz=%d, mode=%d, dma_addr=0x%x, len=%d is_tx=%d\n",
-               packet_sz, mode, dma_addr, len, ux500_channel->is_tx);
+               "packet_sz=%d, mode=%d, dma_addr=0x%llu, len=%d is_tx=%d\n",
+               packet_sz, mode, (unsigned long long) dma_addr,
+               len, ux500_channel->is_tx);
 
        ux500_channel->cur_len = len;
 
@@ -191,7 +193,7 @@ static int ux500_dma_is_compatible(struct dma_channel *channel,
                u16 maxpacket, void *buf, u32 length)
 {
        if ((maxpacket & 0x3)           ||
-               ((int)buf & 0x3)        ||
+               ((unsigned long int) buf & 0x3) ||
                (length < 512)          ||
                (length & 0x3))
                return false;
@@ -372,12 +374,17 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba
 
        controller = kzalloc(sizeof(*controller), GFP_KERNEL);
        if (!controller)
-               return NULL;
+               goto kzalloc_fail;
 
        controller->private_data = musb;
 
        /* Save physical address for DMA controller. */
        iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!iomem) {
+               dev_err(musb->controller, "no memory resource defined\n");
+               goto plat_get_fail;
+       }
+
        controller->phy_base = (dma_addr_t) iomem->start;
 
        controller->controller.start = ux500_dma_controller_start;
@@ -389,4 +396,9 @@ struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *ba
        controller->controller.is_compatible = ux500_dma_is_compatible;
 
        return &controller->controller;
+
+plat_get_fail:
+       kfree(controller);
+kzalloc_fail:
+       return NULL;
 }
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
deleted file mode 100644 (file)
index 37962c9..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-#
-# USB OTG infrastructure may be needed for peripheral-only, host-only,
-# or OTG-capable configurations when OTG transceivers or controllers
-# are used.
-#
-
-comment "OTG and related infrastructure"
-
-config USB_OTG_UTILS
-       bool
-       help
-         Select this to make sure the build includes objects from
-         the OTG infrastructure directory.
-
-if USB || USB_GADGET
-
-#
-# USB Transceiver Drivers
-#
-config USB_GPIO_VBUS
-       tristate "GPIO based peripheral-only VBUS sensing 'transceiver'"
-       depends on GENERIC_GPIO
-       select USB_OTG_UTILS
-       help
-         Provides simple GPIO VBUS sensing for controllers with an
-         internal transceiver via the usb_phy interface, and
-         optionally control of a D+ pullup GPIO as well as a VBUS
-         current limit regulator.
-
-config ISP1301_OMAP
-       tristate "Philips ISP1301 with OMAP OTG"
-       depends on I2C && ARCH_OMAP_OTG
-       select USB_OTG_UTILS
-       help
-         If you say yes here you get support for the Philips ISP1301
-         USB-On-The-Go transceiver working with the OMAP OTG controller.
-         The ISP1301 is a full speed USB  transceiver which is used in
-         products including H2, H3, and H4 development boards for Texas
-         Instruments OMAP processors.
-
-         This driver can also be built as a module.  If so, the module
-         will be called isp1301_omap.
-
-config USB_ULPI
-       bool "Generic ULPI Transceiver Driver"
-       depends on ARM
-       select USB_OTG_UTILS
-       help
-         Enable this to support ULPI connected USB OTG transceivers which
-         are likely found on embedded boards.
-
-config USB_ULPI_VIEWPORT
-       bool
-       depends on USB_ULPI
-       help
-         Provides read/write operations to the ULPI phy register set for
-         controllers with a viewport register (e.g. Chipidea/ARC controllers).
-
-config TWL4030_USB
-       tristate "TWL4030 USB Transceiver Driver"
-       depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
-       select USB_OTG_UTILS
-       help
-         Enable this to support the USB OTG transceiver on TWL4030
-         family chips (including the TWL5030 and TPS659x0 devices).
-         This transceiver supports high and full speed devices plus,
-         in host mode, low speed.
-
-config TWL6030_USB
-       tristate "TWL6030 USB Transceiver Driver"
-       depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS
-       select USB_OTG_UTILS
-       help
-         Enable this to support the USB OTG transceiver on TWL6030
-         family chips. This TWL6030 transceiver has the VBUS and ID GND
-         and OTG SRP events capabilities. For all other transceiver functionality
-         UTMI PHY is embedded in OMAP4430. The internal PHY configurations APIs
-         are hooked to this driver through platform_data structure.
-         The definition of internal PHY APIs are in the mach-omap2 layer.
-
-config NOP_USB_XCEIV
-       tristate "NOP USB Transceiver Driver"
-       select USB_OTG_UTILS
-       help
-         This driver is to be used by all the usb transceiver which are either
-         built-in with usb ip or which are autonomous and doesn't require any
-         phy programming such as ISP1x04 etc.
-
-config USB_MSM_OTG
-       tristate "OTG support for Qualcomm on-chip USB controller"
-       depends on (USB || USB_GADGET) && ARCH_MSM
-       select USB_OTG_UTILS
-       help
-         Enable this to support the USB OTG transceiver on MSM chips. It
-         handles PHY initialization, clock management, and workarounds
-         required after resetting the hardware and power management.
-         This driver is required even for peripheral only or host only
-         mode configurations.
-         This driver is not supported on boards like trout which
-         has an external PHY.
-
-config AB8500_USB
-       tristate "AB8500 USB Transceiver Driver"
-       depends on AB8500_CORE
-       select USB_OTG_UTILS
-       help
-         Enable this to support the USB OTG transceiver in AB8500 chip.
-         This transceiver supports high and full speed devices plus,
-         in host mode, low speed.
-
-config FSL_USB2_OTG
-       bool "Freescale USB OTG Transceiver Driver"
-       depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_SUSPEND
-       select USB_OTG
-       select USB_OTG_UTILS
-       help
-         Enable this to support Freescale USB OTG transceiver.
-
-config USB_MXS_PHY
-       tristate "Freescale MXS USB PHY support"
-       depends on ARCH_MXC || ARCH_MXS
-       select STMP_DEVICE
-       select USB_OTG_UTILS
-       help
-         Enable this to support the Freescale MXS USB PHY.
-
-         MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x.
-
-config USB_MV_OTG
-       tristate "Marvell USB OTG support"
-       depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND
-       select USB_OTG
-       select USB_OTG_UTILS
-       help
-         Say Y here if you want to build Marvell USB OTG transciever
-         driver in kernel (including PXA and MMP series). This driver
-         implements role switch between EHCI host driver and gadget driver.
-
-         To compile this driver as a module, choose M here.
-
-endif # USB || OTG
diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile
deleted file mode 100644 (file)
index a844b8d..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# OTG infrastructure and transceiver drivers
-#
-
-ccflags-$(CONFIG_USB_DEBUG)            := -DDEBUG
-ccflags-$(CONFIG_USB_GADGET_DEBUG)     += -DDEBUG
-
-# infrastructure
-obj-$(CONFIG_USB_OTG_UTILS)    += otg.o
-
-# transceiver drivers
-obj-$(CONFIG_USB_GPIO_VBUS)    += gpio_vbus.o
-obj-$(CONFIG_ISP1301_OMAP)     += isp1301_omap.o
-obj-$(CONFIG_TWL4030_USB)      += twl4030-usb.o
-obj-$(CONFIG_TWL6030_USB)      += twl6030-usb.o
-obj-$(CONFIG_NOP_USB_XCEIV)    += nop-usb-xceiv.o
-obj-$(CONFIG_USB_ULPI)         += ulpi.o
-obj-$(CONFIG_USB_ULPI_VIEWPORT)        += ulpi_viewport.o
-obj-$(CONFIG_USB_MSM_OTG)      += msm_otg.o
-obj-$(CONFIG_AB8500_USB)       += ab8500-usb.o
-fsl_usb2_otg-objs              := fsl_otg.o otg_fsm.o
-obj-$(CONFIG_FSL_USB2_OTG)     += fsl_usb2_otg.o
-obj-$(CONFIG_USB_MXS_PHY)      += mxs-phy.o
-obj-$(CONFIG_USB_MV_OTG)       += mv_otg.o
diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c
deleted file mode 100644 (file)
index 2d86f26..0000000
+++ /dev/null
@@ -1,596 +0,0 @@
-/*
- * drivers/usb/otg/ab8500_usb.c
- *
- * USB transceiver driver for AB8500 chip
- *
- * Copyright (C) 2010 ST-Ericsson AB
- * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
- *
- * 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/platform_device.h>
-#include <linux/usb/otg.h>
-#include <linux/slab.h>
-#include <linux/notifier.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/mfd/abx500.h>
-#include <linux/mfd/abx500/ab8500.h>
-
-#define AB8500_MAIN_WD_CTRL_REG 0x01
-#define AB8500_USB_LINE_STAT_REG 0x80
-#define AB8500_USB_PHY_CTRL_REG 0x8A
-
-#define AB8500_BIT_OTG_STAT_ID (1 << 0)
-#define AB8500_BIT_PHY_CTRL_HOST_EN (1 << 0)
-#define AB8500_BIT_PHY_CTRL_DEVICE_EN (1 << 1)
-#define AB8500_BIT_WD_CTRL_ENABLE (1 << 0)
-#define AB8500_BIT_WD_CTRL_KICK (1 << 1)
-
-#define AB8500_V1x_LINK_STAT_WAIT (HZ/10)
-#define AB8500_WD_KICK_DELAY_US 100 /* usec */
-#define AB8500_WD_V11_DISABLE_DELAY_US 100 /* usec */
-#define AB8500_WD_V10_DISABLE_DELAY_MS 100 /* ms */
-
-/* Usb line status register */
-enum ab8500_usb_link_status {
-       USB_LINK_NOT_CONFIGURED = 0,
-       USB_LINK_STD_HOST_NC,
-       USB_LINK_STD_HOST_C_NS,
-       USB_LINK_STD_HOST_C_S,
-       USB_LINK_HOST_CHG_NM,
-       USB_LINK_HOST_CHG_HS,
-       USB_LINK_HOST_CHG_HS_CHIRP,
-       USB_LINK_DEDICATED_CHG,
-       USB_LINK_ACA_RID_A,
-       USB_LINK_ACA_RID_B,
-       USB_LINK_ACA_RID_C_NM,
-       USB_LINK_ACA_RID_C_HS,
-       USB_LINK_ACA_RID_C_HS_CHIRP,
-       USB_LINK_HM_IDGND,
-       USB_LINK_RESERVED,
-       USB_LINK_NOT_VALID_LINK
-};
-
-struct ab8500_usb {
-       struct usb_phy phy;
-       struct device *dev;
-       int irq_num_id_rise;
-       int irq_num_id_fall;
-       int irq_num_vbus_rise;
-       int irq_num_vbus_fall;
-       int irq_num_link_status;
-       unsigned vbus_draw;
-       struct delayed_work dwork;
-       struct work_struct phy_dis_work;
-       unsigned long link_status_wait;
-       int rev;
-};
-
-static inline struct ab8500_usb *phy_to_ab(struct usb_phy *x)
-{
-       return container_of(x, struct ab8500_usb, phy);
-}
-
-static void ab8500_usb_wd_workaround(struct ab8500_usb *ab)
-{
-       abx500_set_register_interruptible(ab->dev,
-               AB8500_SYS_CTRL2_BLOCK,
-               AB8500_MAIN_WD_CTRL_REG,
-               AB8500_BIT_WD_CTRL_ENABLE);
-
-       udelay(AB8500_WD_KICK_DELAY_US);
-
-       abx500_set_register_interruptible(ab->dev,
-               AB8500_SYS_CTRL2_BLOCK,
-               AB8500_MAIN_WD_CTRL_REG,
-               (AB8500_BIT_WD_CTRL_ENABLE
-               | AB8500_BIT_WD_CTRL_KICK));
-
-       if (ab->rev > 0x10) /* v1.1 v2.0 */
-               udelay(AB8500_WD_V11_DISABLE_DELAY_US);
-       else /* v1.0 */
-               msleep(AB8500_WD_V10_DISABLE_DELAY_MS);
-
-       abx500_set_register_interruptible(ab->dev,
-               AB8500_SYS_CTRL2_BLOCK,
-               AB8500_MAIN_WD_CTRL_REG,
-               0);
-}
-
-static void ab8500_usb_phy_ctrl(struct ab8500_usb *ab, bool sel_host,
-                                       bool enable)
-{
-       u8 ctrl_reg;
-       abx500_get_register_interruptible(ab->dev,
-                               AB8500_USB,
-                               AB8500_USB_PHY_CTRL_REG,
-                               &ctrl_reg);
-       if (sel_host) {
-               if (enable)
-                       ctrl_reg |= AB8500_BIT_PHY_CTRL_HOST_EN;
-               else
-                       ctrl_reg &= ~AB8500_BIT_PHY_CTRL_HOST_EN;
-       } else {
-               if (enable)
-                       ctrl_reg |= AB8500_BIT_PHY_CTRL_DEVICE_EN;
-               else
-                       ctrl_reg &= ~AB8500_BIT_PHY_CTRL_DEVICE_EN;
-       }
-
-       abx500_set_register_interruptible(ab->dev,
-                               AB8500_USB,
-                               AB8500_USB_PHY_CTRL_REG,
-                               ctrl_reg);
-
-       /* Needed to enable the phy.*/
-       if (enable)
-               ab8500_usb_wd_workaround(ab);
-}
-
-#define ab8500_usb_host_phy_en(ab)     ab8500_usb_phy_ctrl(ab, true, true)
-#define ab8500_usb_host_phy_dis(ab)    ab8500_usb_phy_ctrl(ab, true, false)
-#define ab8500_usb_peri_phy_en(ab)     ab8500_usb_phy_ctrl(ab, false, true)
-#define ab8500_usb_peri_phy_dis(ab)    ab8500_usb_phy_ctrl(ab, false, false)
-
-static int ab8500_usb_link_status_update(struct ab8500_usb *ab)
-{
-       u8 reg;
-       enum ab8500_usb_link_status lsts;
-       void *v = NULL;
-       enum usb_phy_events event;
-
-       abx500_get_register_interruptible(ab->dev,
-                       AB8500_USB,
-                       AB8500_USB_LINE_STAT_REG,
-                       &reg);
-
-       lsts = (reg >> 3) & 0x0F;
-
-       switch (lsts) {
-       case USB_LINK_NOT_CONFIGURED:
-       case USB_LINK_RESERVED:
-       case USB_LINK_NOT_VALID_LINK:
-               /* TODO: Disable regulators. */
-               ab8500_usb_host_phy_dis(ab);
-               ab8500_usb_peri_phy_dis(ab);
-               ab->phy.state = OTG_STATE_B_IDLE;
-               ab->phy.otg->default_a = false;
-               ab->vbus_draw = 0;
-               event = USB_EVENT_NONE;
-               break;
-
-       case USB_LINK_STD_HOST_NC:
-       case USB_LINK_STD_HOST_C_NS:
-       case USB_LINK_STD_HOST_C_S:
-       case USB_LINK_HOST_CHG_NM:
-       case USB_LINK_HOST_CHG_HS:
-       case USB_LINK_HOST_CHG_HS_CHIRP:
-               if (ab->phy.otg->gadget) {
-                       /* TODO: Enable regulators. */
-                       ab8500_usb_peri_phy_en(ab);
-                       v = ab->phy.otg->gadget;
-               }
-               event = USB_EVENT_VBUS;
-               break;
-
-       case USB_LINK_HM_IDGND:
-               if (ab->phy.otg->host) {
-                       /* TODO: Enable regulators. */
-                       ab8500_usb_host_phy_en(ab);
-                       v = ab->phy.otg->host;
-               }
-               ab->phy.state = OTG_STATE_A_IDLE;
-               ab->phy.otg->default_a = true;
-               event = USB_EVENT_ID;
-               break;
-
-       case USB_LINK_ACA_RID_A:
-       case USB_LINK_ACA_RID_B:
-               /* TODO */
-       case USB_LINK_ACA_RID_C_NM:
-       case USB_LINK_ACA_RID_C_HS:
-       case USB_LINK_ACA_RID_C_HS_CHIRP:
-       case USB_LINK_DEDICATED_CHG:
-               /* TODO: vbus_draw */
-               event = USB_EVENT_CHARGER;
-               break;
-       }
-
-       atomic_notifier_call_chain(&ab->phy.notifier, event, v);
-
-       return 0;
-}
-
-static void ab8500_usb_delayed_work(struct work_struct *work)
-{
-       struct ab8500_usb *ab = container_of(work, struct ab8500_usb,
-                                               dwork.work);
-
-       ab8500_usb_link_status_update(ab);
-}
-
-static irqreturn_t ab8500_usb_v1x_common_irq(int irq, void *data)
-{
-       struct ab8500_usb *ab = (struct ab8500_usb *) data;
-
-       /* Wait for link status to become stable. */
-       schedule_delayed_work(&ab->dwork, ab->link_status_wait);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t ab8500_usb_v1x_vbus_fall_irq(int irq, void *data)
-{
-       struct ab8500_usb *ab = (struct ab8500_usb *) data;
-
-       /* Link status will not be updated till phy is disabled. */
-       ab8500_usb_peri_phy_dis(ab);
-
-       /* Wait for link status to become stable. */
-       schedule_delayed_work(&ab->dwork, ab->link_status_wait);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t ab8500_usb_v20_irq(int irq, void *data)
-{
-       struct ab8500_usb *ab = (struct ab8500_usb *) data;
-
-       ab8500_usb_link_status_update(ab);
-
-       return IRQ_HANDLED;
-}
-
-static void ab8500_usb_phy_disable_work(struct work_struct *work)
-{
-       struct ab8500_usb *ab = container_of(work, struct ab8500_usb,
-                                               phy_dis_work);
-
-       if (!ab->phy.otg->host)
-               ab8500_usb_host_phy_dis(ab);
-
-       if (!ab->phy.otg->gadget)
-               ab8500_usb_peri_phy_dis(ab);
-}
-
-static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA)
-{
-       struct ab8500_usb *ab;
-
-       if (!phy)
-               return -ENODEV;
-
-       ab = phy_to_ab(phy);
-
-       ab->vbus_draw = mA;
-
-       if (mA)
-               atomic_notifier_call_chain(&ab->phy.notifier,
-                               USB_EVENT_ENUMERATED, ab->phy.otg->gadget);
-       return 0;
-}
-
-/* TODO: Implement some way for charging or other drivers to read
- * ab->vbus_draw.
- */
-
-static int ab8500_usb_set_suspend(struct usb_phy *x, int suspend)
-{
-       /* TODO */
-       return 0;
-}
-
-static int ab8500_usb_set_peripheral(struct usb_otg *otg,
-                                       struct usb_gadget *gadget)
-{
-       struct ab8500_usb *ab;
-
-       if (!otg)
-               return -ENODEV;
-
-       ab = phy_to_ab(otg->phy);
-
-       /* Some drivers call this function in atomic context.
-        * Do not update ab8500 registers directly till this
-        * is fixed.
-        */
-
-       if (!gadget) {
-               /* TODO: Disable regulators. */
-               otg->gadget = NULL;
-               schedule_work(&ab->phy_dis_work);
-       } else {
-               otg->gadget = gadget;
-               otg->phy->state = OTG_STATE_B_IDLE;
-
-               /* Phy will not be enabled if cable is already
-                * plugged-in. Schedule to enable phy.
-                * Use same delay to avoid any race condition.
-                */
-               schedule_delayed_work(&ab->dwork, ab->link_status_wait);
-       }
-
-       return 0;
-}
-
-static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-       struct ab8500_usb *ab;
-
-       if (!otg)
-               return -ENODEV;
-
-       ab = phy_to_ab(otg->phy);
-
-       /* Some drivers call this function in atomic context.
-        * Do not update ab8500 registers directly till this
-        * is fixed.
-        */
-
-       if (!host) {
-               /* TODO: Disable regulators. */
-               otg->host = NULL;
-               schedule_work(&ab->phy_dis_work);
-       } else {
-               otg->host = host;
-               /* Phy will not be enabled if cable is already
-                * plugged-in. Schedule to enable phy.
-                * Use same delay to avoid any race condition.
-                */
-               schedule_delayed_work(&ab->dwork, ab->link_status_wait);
-       }
-
-       return 0;
-}
-
-static void ab8500_usb_irq_free(struct ab8500_usb *ab)
-{
-       if (ab->rev < 0x20) {
-               free_irq(ab->irq_num_id_rise, ab);
-               free_irq(ab->irq_num_id_fall, ab);
-               free_irq(ab->irq_num_vbus_rise, ab);
-               free_irq(ab->irq_num_vbus_fall, ab);
-       } else {
-               free_irq(ab->irq_num_link_status, ab);
-       }
-}
-
-static int ab8500_usb_v1x_res_setup(struct platform_device *pdev,
-                               struct ab8500_usb *ab)
-{
-       int err;
-
-       ab->irq_num_id_rise = platform_get_irq_byname(pdev, "ID_WAKEUP_R");
-       if (ab->irq_num_id_rise < 0) {
-               dev_err(&pdev->dev, "ID rise irq not found\n");
-               return ab->irq_num_id_rise;
-       }
-       err = request_threaded_irq(ab->irq_num_id_rise, NULL,
-               ab8500_usb_v1x_common_irq,
-               IRQF_NO_SUSPEND | IRQF_SHARED,
-               "usb-id-rise", ab);
-       if (err < 0) {
-               dev_err(ab->dev, "request_irq failed for ID rise irq\n");
-               goto fail0;
-       }
-
-       ab->irq_num_id_fall = platform_get_irq_byname(pdev, "ID_WAKEUP_F");
-       if (ab->irq_num_id_fall < 0) {
-               dev_err(&pdev->dev, "ID fall irq not found\n");
-               return ab->irq_num_id_fall;
-       }
-       err = request_threaded_irq(ab->irq_num_id_fall, NULL,
-               ab8500_usb_v1x_common_irq,
-               IRQF_NO_SUSPEND | IRQF_SHARED,
-               "usb-id-fall", ab);
-       if (err < 0) {
-               dev_err(ab->dev, "request_irq failed for ID fall irq\n");
-               goto fail1;
-       }
-
-       ab->irq_num_vbus_rise = platform_get_irq_byname(pdev, "VBUS_DET_R");
-       if (ab->irq_num_vbus_rise < 0) {
-               dev_err(&pdev->dev, "VBUS rise irq not found\n");
-               return ab->irq_num_vbus_rise;
-       }
-       err = request_threaded_irq(ab->irq_num_vbus_rise, NULL,
-               ab8500_usb_v1x_common_irq,
-               IRQF_NO_SUSPEND | IRQF_SHARED,
-               "usb-vbus-rise", ab);
-       if (err < 0) {
-               dev_err(ab->dev, "request_irq failed for Vbus rise irq\n");
-               goto fail2;
-       }
-
-       ab->irq_num_vbus_fall = platform_get_irq_byname(pdev, "VBUS_DET_F");
-       if (ab->irq_num_vbus_fall < 0) {
-               dev_err(&pdev->dev, "VBUS fall irq not found\n");
-               return ab->irq_num_vbus_fall;
-       }
-       err = request_threaded_irq(ab->irq_num_vbus_fall, NULL,
-               ab8500_usb_v1x_vbus_fall_irq,
-               IRQF_NO_SUSPEND | IRQF_SHARED,
-               "usb-vbus-fall", ab);
-       if (err < 0) {
-               dev_err(ab->dev, "request_irq failed for Vbus fall irq\n");
-               goto fail3;
-       }
-
-       return 0;
-fail3:
-       free_irq(ab->irq_num_vbus_rise, ab);
-fail2:
-       free_irq(ab->irq_num_id_fall, ab);
-fail1:
-       free_irq(ab->irq_num_id_rise, ab);
-fail0:
-       return err;
-}
-
-static int ab8500_usb_v2_res_setup(struct platform_device *pdev,
-                               struct ab8500_usb *ab)
-{
-       int err;
-
-       ab->irq_num_link_status = platform_get_irq_byname(pdev,
-                                               "USB_LINK_STATUS");
-       if (ab->irq_num_link_status < 0) {
-               dev_err(&pdev->dev, "Link status irq not found\n");
-               return ab->irq_num_link_status;
-       }
-
-       err = request_threaded_irq(ab->irq_num_link_status, NULL,
-               ab8500_usb_v20_irq,
-               IRQF_NO_SUSPEND | IRQF_SHARED,
-               "usb-link-status", ab);
-       if (err < 0) {
-               dev_err(ab->dev,
-                       "request_irq failed for link status irq\n");
-               return err;
-       }
-
-       return 0;
-}
-
-static int ab8500_usb_probe(struct platform_device *pdev)
-{
-       struct ab8500_usb       *ab;
-       struct usb_otg          *otg;
-       int err;
-       int rev;
-
-       rev = abx500_get_chip_id(&pdev->dev);
-       if (rev < 0) {
-               dev_err(&pdev->dev, "Chip id read failed\n");
-               return rev;
-       } else if (rev < 0x10) {
-               dev_err(&pdev->dev, "Unsupported AB8500 chip\n");
-               return -ENODEV;
-       }
-
-       ab = kzalloc(sizeof *ab, GFP_KERNEL);
-       if (!ab)
-               return -ENOMEM;
-
-       otg = kzalloc(sizeof *otg, GFP_KERNEL);
-       if (!otg) {
-               kfree(ab);
-               return -ENOMEM;
-       }
-
-       ab->dev                 = &pdev->dev;
-       ab->rev                 = rev;
-       ab->phy.dev             = ab->dev;
-       ab->phy.otg             = otg;
-       ab->phy.label           = "ab8500";
-       ab->phy.set_suspend     = ab8500_usb_set_suspend;
-       ab->phy.set_power       = ab8500_usb_set_power;
-       ab->phy.state           = OTG_STATE_UNDEFINED;
-
-       otg->phy                = &ab->phy;
-       otg->set_host           = ab8500_usb_set_host;
-       otg->set_peripheral     = ab8500_usb_set_peripheral;
-
-       platform_set_drvdata(pdev, ab);
-
-       ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier);
-
-       /* v1: Wait for link status to become stable.
-        * all: Updates form set_host and set_peripheral as they are atomic.
-        */
-       INIT_DELAYED_WORK(&ab->dwork, ab8500_usb_delayed_work);
-
-       /* all: Disable phy when called from set_host and set_peripheral */
-       INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work);
-
-       if (ab->rev < 0x20) {
-               err = ab8500_usb_v1x_res_setup(pdev, ab);
-               ab->link_status_wait = AB8500_V1x_LINK_STAT_WAIT;
-       } else {
-               err = ab8500_usb_v2_res_setup(pdev, ab);
-       }
-
-       if (err < 0)
-               goto fail0;
-
-       err = usb_add_phy(&ab->phy, USB_PHY_TYPE_USB2);
-       if (err) {
-               dev_err(&pdev->dev, "Can't register transceiver\n");
-               goto fail1;
-       }
-
-       dev_info(&pdev->dev, "AB8500 usb driver initialized\n");
-
-       return 0;
-fail1:
-       ab8500_usb_irq_free(ab);
-fail0:
-       kfree(otg);
-       kfree(ab);
-       return err;
-}
-
-static int ab8500_usb_remove(struct platform_device *pdev)
-{
-       struct ab8500_usb *ab = platform_get_drvdata(pdev);
-
-       ab8500_usb_irq_free(ab);
-
-       cancel_delayed_work_sync(&ab->dwork);
-
-       cancel_work_sync(&ab->phy_dis_work);
-
-       usb_remove_phy(&ab->phy);
-
-       ab8500_usb_host_phy_dis(ab);
-       ab8500_usb_peri_phy_dis(ab);
-
-       platform_set_drvdata(pdev, NULL);
-
-       kfree(ab->phy.otg);
-       kfree(ab);
-
-       return 0;
-}
-
-static struct platform_driver ab8500_usb_driver = {
-       .probe          = ab8500_usb_probe,
-       .remove         = ab8500_usb_remove,
-       .driver         = {
-               .name   = "ab8500-usb",
-               .owner  = THIS_MODULE,
-       },
-};
-
-static int __init ab8500_usb_init(void)
-{
-       return platform_driver_register(&ab8500_usb_driver);
-}
-subsys_initcall(ab8500_usb_init);
-
-static void __exit ab8500_usb_exit(void)
-{
-       platform_driver_unregister(&ab8500_usb_driver);
-}
-module_exit(ab8500_usb_exit);
-
-MODULE_ALIAS("platform:ab8500_usb");
-MODULE_AUTHOR("ST-Ericsson AB");
-MODULE_DESCRIPTION("AB8500 usb transceiver driver");
-MODULE_LICENSE("GPL");
index 90549382eba5f139c6d54b7617319132189e6596..aab2ab2fbc90d050a474cb39df7563bbfedb8633 100644 (file)
@@ -1,13 +1,74 @@
 #
 # Physical Layer USB driver configuration
 #
-comment "USB Physical Layer drivers"
-       depends on USB || USB_GADGET
+menuconfig USB_PHY
+       bool "USB Physical Layer drivers"
+       help
+         USB controllers (those which are host, device or DRD) need a
+         device to handle the physical layer signalling, commonly called
+         a PHY.
+
+         The following drivers add support for such PHY devices.
+
+if USB_PHY
+
+#
+# USB Transceiver Drivers
+#
+config AB8500_USB
+       tristate "AB8500 USB Transceiver Driver"
+       depends on AB8500_CORE
+       help
+         Enable this to support the USB OTG transceiver in AB8500 chip.
+         This transceiver supports high and full speed devices plus,
+         in host mode, low speed.
+
+config FSL_USB2_OTG
+       bool "Freescale USB OTG Transceiver Driver"
+       depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_SUSPEND
+       select USB_OTG
+       help
+         Enable this to support Freescale USB OTG transceiver.
+
+config ISP1301_OMAP
+       tristate "Philips ISP1301 with OMAP OTG"
+       depends on I2C && ARCH_OMAP_OTG
+       help
+         If you say yes here you get support for the Philips ISP1301
+         USB-On-The-Go transceiver working with the OMAP OTG controller.
+         The ISP1301 is a full speed USB  transceiver which is used in
+         products including H2, H3, and H4 development boards for Texas
+         Instruments OMAP processors.
+
+         This driver can also be built as a module.  If so, the module
+         will be called isp1301_omap.
+
+config MV_U3D_PHY
+       bool "Marvell USB 3.0 PHY controller Driver"
+       depends on CPU_MMP3
+       help
+         Enable this to support Marvell USB 3.0 phy controller for Marvell
+         SoC.
+
+config NOP_USB_XCEIV
+       tristate "NOP USB Transceiver Driver"
+       help
+         This driver is to be used by all the usb transceiver which are either
+         built-in with usb ip or which are autonomous and doesn't require any
+         phy programming such as ISP1x04 etc.
+
+config OMAP_CONTROL_USB
+       tristate "OMAP CONTROL USB Driver"
+       help
+         Enable this to add support for the USB part present in the control
+         module. This driver has API to power on the USB2 PHY and to write to
+         the mailbox. The mailbox is present only in omap4 and the register to
+         power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an
+         additional register to power on USB3 PHY.
 
 config OMAP_USB2
        tristate "OMAP USB2 PHY Driver"
        depends on ARCH_OMAP2PLUS
-       select USB_OTG_UTILS
        select OMAP_CONTROL_USB
        help
          Enable this to support the transceiver that is part of SOC. This
@@ -17,7 +78,6 @@ config OMAP_USB2
 
 config OMAP_USB3
        tristate "OMAP USB3 PHY Driver"
-       select USB_OTG_UTILS
        select OMAP_CONTROL_USB
        help
          Enable this to support the USB3 PHY that is part of SOC. This
@@ -25,14 +85,55 @@ config OMAP_USB3
          This driver interacts with the "OMAP Control USB Driver" to power
          on/off the PHY.
 
-config OMAP_CONTROL_USB
-       tristate "OMAP CONTROL USB Driver"
+config SAMSUNG_USBPHY
+       tristate "Samsung USB PHY Driver"
        help
-         Enable this to add support for the USB part present in the control
-         module. This driver has API to power on the USB2 PHY and to write to
-         the mailbox. The mailbox is present only in omap4 and the register to
-         power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an
-         additional register to power on USB3 PHY.
+         Enable this to support Samsung USB phy helper driver for Samsung SoCs.
+         This driver provides common interface to interact, for Samsung USB 2.0 PHY
+         driver and later for Samsung USB 3.0 PHY driver.
+
+config SAMSUNG_USB2PHY
+       tristate "Samsung USB 2.0 PHY controller Driver"
+       select SAMSUNG_USBPHY
+       help
+         Enable this to support Samsung USB 2.0 (High Speed) PHY controller
+         driver for Samsung SoCs.
+
+config SAMSUNG_USB3PHY
+       tristate "Samsung USB 3.0 PHY controller Driver"
+       select SAMSUNG_USBPHY
+       help
+         Enable this to support Samsung USB 3.0 (Super Speed) phy controller
+         for samsung SoCs.
+
+config TWL4030_USB
+       tristate "TWL4030 USB Transceiver Driver"
+       depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
+       help
+         Enable this to support the USB OTG transceiver on TWL4030
+         family chips (including the TWL5030 and TPS659x0 devices).
+         This transceiver supports high and full speed devices plus,
+         in host mode, low speed.
+
+config TWL6030_USB
+       tristate "TWL6030 USB Transceiver Driver"
+       depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS
+       help
+         Enable this to support the USB OTG transceiver on TWL6030
+         family chips. This TWL6030 transceiver has the VBUS and ID GND
+         and OTG SRP events capabilities. For all other transceiver functionality
+         UTMI PHY is embedded in OMAP4430. The internal PHY configurations APIs
+         are hooked to this driver through platform_data structure.
+         The definition of internal PHY APIs are in the mach-omap2 layer.
+
+config USB_GPIO_VBUS
+       tristate "GPIO based peripheral-only VBUS sensing 'transceiver'"
+       depends on GENERIC_GPIO
+       help
+         Provides simple GPIO VBUS sensing for controllers with an
+         internal transceiver via the usb_phy interface, and
+         optionally control of a D+ pullup GPIO as well as a VBUS
+         current limit regulator.
 
 config USB_ISP1301
        tristate "NXP ISP1301 USB transceiver support"
@@ -47,18 +148,41 @@ config USB_ISP1301
          To compile this driver as a module, choose M here: the
          module will be called isp1301.
 
-config MV_U3D_PHY
-       bool "Marvell USB 3.0 PHY controller Driver"
-       depends on USB_MV_U3D
-       select USB_OTG_UTILS
+config USB_MSM_OTG
+       tristate "OTG support for Qualcomm on-chip USB controller"
+       depends on (USB || USB_GADGET) && ARCH_MSM
        help
-         Enable this to support Marvell USB 3.0 phy controller for Marvell
-         SoC.
+         Enable this to support the USB OTG transceiver on MSM chips. It
+         handles PHY initialization, clock management, and workarounds
+         required after resetting the hardware and power management.
+         This driver is required even for peripheral only or host only
+         mode configurations.
+         This driver is not supported on boards like trout which
+         has an external PHY.
+
+config USB_MV_OTG
+       tristate "Marvell USB OTG support"
+       depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND
+       select USB_OTG
+       help
+         Say Y here if you want to build Marvell USB OTG transciever
+         driver in kernel (including PXA and MMP series). This driver
+         implements role switch between EHCI host driver and gadget driver.
+
+         To compile this driver as a module, choose M here.
+
+config USB_MXS_PHY
+       tristate "Freescale MXS USB PHY support"
+       depends on ARCH_MXC || ARCH_MXS
+       select STMP_DEVICE
+       help
+         Enable this to support the Freescale MXS USB PHY.
+
+         MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x.
 
 config USB_RCAR_PHY
        tristate "Renesas R-Car USB phy support"
        depends on USB || USB_GADGET
-       select USB_OTG_UTILS
        help
          Say Y here to add support for the Renesas R-Car USB phy driver.
          This chip is typically used as USB phy for USB host, gadget.
@@ -67,10 +191,18 @@ config USB_RCAR_PHY
          To compile this driver as a module, choose M here: the
          module will be called rcar-phy.
 
-config SAMSUNG_USBPHY
-       bool "Samsung USB PHY controller Driver"
-       depends on USB_S3C_HSOTG || USB_EHCI_S5P || USB_OHCI_EXYNOS
-       select USB_OTG_UTILS
+config USB_ULPI
+       bool "Generic ULPI Transceiver Driver"
+       depends on ARM
+       help
+         Enable this to support ULPI connected USB OTG transceivers which
+         are likely found on embedded boards.
+
+config USB_ULPI_VIEWPORT
+       bool
+       depends on USB_ULPI
        help
-         Enable this to support Samsung USB phy controller for samsung
-         SoCs.
+         Provides read/write operations to the ULPI phy register set for
+         controllers with a viewport register (e.g. Chipidea/ARC controllers).
+
+endif # USB_PHY
index b13faa193e0cb89049d5ce304bbeb389e094570f..a9169cb1e6fcca8d85856b4414bb36d89df1239d 100644 (file)
@@ -4,11 +4,30 @@
 
 ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG
 
-obj-$(CONFIG_OMAP_USB2)                        += omap-usb2.o
-obj-$(CONFIG_OMAP_USB3)                        += omap-usb3.o
-obj-$(CONFIG_OMAP_CONTROL_USB)         += omap-control-usb.o
-obj-$(CONFIG_USB_ISP1301)              += isp1301.o
-obj-$(CONFIG_MV_U3D_PHY)               += mv_u3d_phy.o
-obj-$(CONFIG_USB_EHCI_TEGRA)   += tegra_usb_phy.o
-obj-$(CONFIG_USB_RCAR_PHY)             += rcar-phy.o
-obj-$(CONFIG_SAMSUNG_USBPHY)           += samsung-usbphy.o
+obj-$(CONFIG_USB_PHY)                  += phy.o
+
+# transceiver drivers, keep the list sorted
+
+obj-$(CONFIG_AB8500_USB)               += phy-ab8500-usb.o
+phy-fsl-usb2-objs                      := phy-fsl-usb.o phy-fsm-usb.o
+obj-$(CONFIG_FSL_USB2_OTG)             += phy-fsl-usb2.o
+obj-$(CONFIG_ISP1301_OMAP)             += phy-isp1301-omap.o
+obj-$(CONFIG_MV_U3D_PHY)               += phy-mv-u3d-usb.o
+obj-$(CONFIG_NOP_USB_XCEIV)            += phy-nop.o
+obj-$(CONFIG_OMAP_CONTROL_USB)         += phy-omap-control.o
+obj-$(CONFIG_OMAP_USB2)                        += phy-omap-usb2.o
+obj-$(CONFIG_OMAP_USB3)                        += phy-omap-usb3.o
+obj-$(CONFIG_SAMSUNG_USBPHY)           += phy-samsung-usb.o
+obj-$(CONFIG_SAMSUNG_USB2PHY)          += phy-samsung-usb2.o
+obj-$(CONFIG_SAMSUNG_USB3PHY)          += phy-samsung-usb3.o
+obj-$(CONFIG_TWL4030_USB)              += phy-twl4030-usb.o
+obj-$(CONFIG_TWL6030_USB)              += phy-twl6030-usb.o
+obj-$(CONFIG_USB_EHCI_TEGRA)           += phy-tegra-usb.o
+obj-$(CONFIG_USB_GPIO_VBUS)            += phy-gpio-vbus-usb.o
+obj-$(CONFIG_USB_ISP1301)              += phy-isp1301.o
+obj-$(CONFIG_USB_MSM_OTG)              += phy-msm-usb.o
+obj-$(CONFIG_USB_MV_OTG)               += phy-mv-usb.o
+obj-$(CONFIG_USB_MXS_PHY)              += phy-mxs-usb.o
+obj-$(CONFIG_USB_RCAR_PHY)             += phy-rcar-usb.o
+obj-$(CONFIG_USB_ULPI)                 += phy-ulpi.o
+obj-$(CONFIG_USB_ULPI_VIEWPORT)                += phy-ulpi-viewport.o
diff --git a/drivers/usb/phy/isp1301.c b/drivers/usb/phy/isp1301.c
deleted file mode 100644 (file)
index 18dbf7e..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * NXP ISP1301 USB transceiver driver
- *
- * Copyright (C) 2012 Roland Stigge
- *
- * Author: Roland Stigge <stigge@antcom.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/i2c.h>
-
-#define DRV_NAME               "isp1301"
-
-static const struct i2c_device_id isp1301_id[] = {
-       { "isp1301", 0 },
-       { }
-};
-
-static struct i2c_client *isp1301_i2c_client;
-
-static int isp1301_probe(struct i2c_client *client,
-                        const struct i2c_device_id *i2c_id)
-{
-       isp1301_i2c_client = client;
-       return 0;
-}
-
-static int isp1301_remove(struct i2c_client *client)
-{
-       return 0;
-}
-
-static struct i2c_driver isp1301_driver = {
-       .driver = {
-               .name = DRV_NAME,
-       },
-       .probe = isp1301_probe,
-       .remove = isp1301_remove,
-       .id_table = isp1301_id,
-};
-
-module_i2c_driver(isp1301_driver);
-
-static int match(struct device *dev, void *data)
-{
-       struct device_node *node = (struct device_node *)data;
-       return (dev->of_node == node) &&
-               (dev->driver == &isp1301_driver.driver);
-}
-
-struct i2c_client *isp1301_get_client(struct device_node *node)
-{
-       if (node) { /* reference of ISP1301 I2C node via DT */
-               struct device *dev = bus_find_device(&i2c_bus_type, NULL,
-                                                    node, match);
-               if (!dev)
-                       return NULL;
-               return to_i2c_client(dev);
-       } else { /* non-DT: only one ISP1301 chip supported */
-               return isp1301_i2c_client;
-       }
-}
-EXPORT_SYMBOL_GPL(isp1301_get_client);
-
-MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
-MODULE_DESCRIPTION("NXP ISP1301 USB transceiver driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
new file mode 100644 (file)
index 0000000..4acef26
--- /dev/null
@@ -0,0 +1,924 @@
+/*
+ * drivers/usb/otg/ab8500_usb.c
+ *
+ * USB transceiver driver for AB8500 chip
+ *
+ * Copyright (C) 2010 ST-Ericsson AB
+ * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
+ *
+ * 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/platform_device.h>
+#include <linux/usb/otg.h>
+#include <linux/slab.h>
+#include <linux/notifier.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/abx500/ab8500.h>
+#include <linux/usb/musb-ux500.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pinctrl/consumer.h>
+
+/* Bank AB8500_SYS_CTRL2_BLOCK */
+#define AB8500_MAIN_WD_CTRL_REG 0x01
+
+/* Bank AB8500_USB */
+#define AB8500_USB_LINE_STAT_REG 0x80
+#define AB8505_USB_LINE_STAT_REG 0x94
+#define AB8500_USB_PHY_CTRL_REG 0x8A
+
+/* Bank AB8500_DEVELOPMENT */
+#define AB8500_BANK12_ACCESS 0x00
+
+/* Bank AB8500_DEBUG */
+#define AB8500_USB_PHY_TUNE1 0x05
+#define AB8500_USB_PHY_TUNE2 0x06
+#define AB8500_USB_PHY_TUNE3 0x07
+
+#define AB8500_BIT_OTG_STAT_ID (1 << 0)
+#define AB8500_BIT_PHY_CTRL_HOST_EN (1 << 0)
+#define AB8500_BIT_PHY_CTRL_DEVICE_EN (1 << 1)
+#define AB8500_BIT_WD_CTRL_ENABLE (1 << 0)
+#define AB8500_BIT_WD_CTRL_KICK (1 << 1)
+
+#define AB8500_WD_KICK_DELAY_US 100 /* usec */
+#define AB8500_WD_V11_DISABLE_DELAY_US 100 /* usec */
+#define AB8500_V20_31952_DISABLE_DELAY_US 100 /* usec */
+
+/* Usb line status register */
+enum ab8500_usb_link_status {
+       USB_LINK_NOT_CONFIGURED_8500 = 0,
+       USB_LINK_STD_HOST_NC_8500,
+       USB_LINK_STD_HOST_C_NS_8500,
+       USB_LINK_STD_HOST_C_S_8500,
+       USB_LINK_HOST_CHG_NM_8500,
+       USB_LINK_HOST_CHG_HS_8500,
+       USB_LINK_HOST_CHG_HS_CHIRP_8500,
+       USB_LINK_DEDICATED_CHG_8500,
+       USB_LINK_ACA_RID_A_8500,
+       USB_LINK_ACA_RID_B_8500,
+       USB_LINK_ACA_RID_C_NM_8500,
+       USB_LINK_ACA_RID_C_HS_8500,
+       USB_LINK_ACA_RID_C_HS_CHIRP_8500,
+       USB_LINK_HM_IDGND_8500,
+       USB_LINK_RESERVED_8500,
+       USB_LINK_NOT_VALID_LINK_8500,
+};
+
+enum ab8505_usb_link_status {
+       USB_LINK_NOT_CONFIGURED_8505 = 0,
+       USB_LINK_STD_HOST_NC_8505,
+       USB_LINK_STD_HOST_C_NS_8505,
+       USB_LINK_STD_HOST_C_S_8505,
+       USB_LINK_CDP_8505,
+       USB_LINK_RESERVED0_8505,
+       USB_LINK_RESERVED1_8505,
+       USB_LINK_DEDICATED_CHG_8505,
+       USB_LINK_ACA_RID_A_8505,
+       USB_LINK_ACA_RID_B_8505,
+       USB_LINK_ACA_RID_C_NM_8505,
+       USB_LINK_RESERVED2_8505,
+       USB_LINK_RESERVED3_8505,
+       USB_LINK_HM_IDGND_8505,
+       USB_LINK_CHARGERPORT_NOT_OK_8505,
+       USB_LINK_CHARGER_DM_HIGH_8505,
+       USB_LINK_PHYEN_NO_VBUS_NO_IDGND_8505,
+       USB_LINK_STD_UPSTREAM_NO_IDGNG_NO_VBUS_8505,
+       USB_LINK_STD_UPSTREAM_8505,
+       USB_LINK_CHARGER_SE1_8505,
+       USB_LINK_CARKIT_CHGR_1_8505,
+       USB_LINK_CARKIT_CHGR_2_8505,
+       USB_LINK_ACA_DOCK_CHGR_8505,
+       USB_LINK_SAMSUNG_BOOT_CBL_PHY_EN_8505,
+       USB_LINK_SAMSUNG_BOOT_CBL_PHY_DISB_8505,
+       USB_LINK_SAMSUNG_UART_CBL_PHY_EN_8505,
+       USB_LINK_SAMSUNG_UART_CBL_PHY_DISB_8505,
+       USB_LINK_MOTOROLA_FACTORY_CBL_PHY_EN_8505,
+};
+
+enum ab8500_usb_mode {
+       USB_IDLE = 0,
+       USB_PERIPHERAL,
+       USB_HOST,
+       USB_DEDICATED_CHG
+};
+
+struct ab8500_usb {
+       struct usb_phy phy;
+       struct device *dev;
+       struct ab8500 *ab8500;
+       unsigned vbus_draw;
+       struct work_struct phy_dis_work;
+       enum ab8500_usb_mode mode;
+       struct regulator *v_ape;
+       struct regulator *v_musb;
+       struct regulator *v_ulpi;
+       int saved_v_ulpi;
+       int previous_link_status_state;
+       struct pinctrl *pinctrl;
+       struct pinctrl_state *pins_sleep;
+};
+
+static inline struct ab8500_usb *phy_to_ab(struct usb_phy *x)
+{
+       return container_of(x, struct ab8500_usb, phy);
+}
+
+static void ab8500_usb_wd_workaround(struct ab8500_usb *ab)
+{
+       abx500_set_register_interruptible(ab->dev,
+               AB8500_SYS_CTRL2_BLOCK,
+               AB8500_MAIN_WD_CTRL_REG,
+               AB8500_BIT_WD_CTRL_ENABLE);
+
+       udelay(AB8500_WD_KICK_DELAY_US);
+
+       abx500_set_register_interruptible(ab->dev,
+               AB8500_SYS_CTRL2_BLOCK,
+               AB8500_MAIN_WD_CTRL_REG,
+               (AB8500_BIT_WD_CTRL_ENABLE
+               | AB8500_BIT_WD_CTRL_KICK));
+
+       udelay(AB8500_WD_V11_DISABLE_DELAY_US);
+
+       abx500_set_register_interruptible(ab->dev,
+               AB8500_SYS_CTRL2_BLOCK,
+               AB8500_MAIN_WD_CTRL_REG,
+               0);
+}
+
+static void ab8500_usb_regulator_enable(struct ab8500_usb *ab)
+{
+       int ret, volt;
+
+       ret = regulator_enable(ab->v_ape);
+       if (ret)
+               dev_err(ab->dev, "Failed to enable v-ape\n");
+
+       if (!is_ab8500_2p0_or_earlier(ab->ab8500)) {
+               ab->saved_v_ulpi = regulator_get_voltage(ab->v_ulpi);
+               if (ab->saved_v_ulpi < 0)
+                       dev_err(ab->dev, "Failed to get v_ulpi voltage\n");
+
+               ret = regulator_set_voltage(ab->v_ulpi, 1300000, 1350000);
+               if (ret < 0)
+                       dev_err(ab->dev, "Failed to set the Vintcore to 1.3V, ret=%d\n",
+                                       ret);
+
+               ret = regulator_set_optimum_mode(ab->v_ulpi, 28000);
+               if (ret < 0)
+                       dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n",
+                                       ret);
+       }
+
+       ret = regulator_enable(ab->v_ulpi);
+       if (ret)
+               dev_err(ab->dev, "Failed to enable vddulpivio18\n");
+
+       if (!is_ab8500_2p0_or_earlier(ab->ab8500)) {
+               volt = regulator_get_voltage(ab->v_ulpi);
+               if ((volt != 1300000) && (volt != 1350000))
+                       dev_err(ab->dev, "Vintcore is not set to 1.3V volt=%d\n",
+                                       volt);
+       }
+
+       ret = regulator_enable(ab->v_musb);
+       if (ret)
+               dev_err(ab->dev, "Failed to enable musb_1v8\n");
+}
+
+static void ab8500_usb_regulator_disable(struct ab8500_usb *ab)
+{
+       int ret;
+
+       regulator_disable(ab->v_musb);
+
+       regulator_disable(ab->v_ulpi);
+
+       /* USB is not the only consumer of Vintcore, restore old settings */
+       if (!is_ab8500_2p0_or_earlier(ab->ab8500)) {
+               if (ab->saved_v_ulpi > 0) {
+                       ret = regulator_set_voltage(ab->v_ulpi,
+                                       ab->saved_v_ulpi, ab->saved_v_ulpi);
+                       if (ret < 0)
+                               dev_err(ab->dev, "Failed to set the Vintcore to %duV, ret=%d\n",
+                                               ab->saved_v_ulpi, ret);
+               }
+
+               ret = regulator_set_optimum_mode(ab->v_ulpi, 0);
+               if (ret < 0)
+                       dev_err(ab->dev, "Failed to set optimum mode (ret=%d)\n",
+                                       ret);
+       }
+
+       regulator_disable(ab->v_ape);
+}
+
+static void ab8500_usb_wd_linkstatus(struct ab8500_usb *ab, u8 bit)
+{
+       /* Workaround for v2.0 bug # 31952 */
+       if (is_ab8500_2p0(ab->ab8500)) {
+               abx500_mask_and_set_register_interruptible(ab->dev,
+                               AB8500_USB, AB8500_USB_PHY_CTRL_REG,
+                               bit, bit);
+               udelay(AB8500_V20_31952_DISABLE_DELAY_US);
+       }
+}
+
+static void ab8500_usb_phy_enable(struct ab8500_usb *ab, bool sel_host)
+{
+       u8 bit;
+       bit = sel_host ? AB8500_BIT_PHY_CTRL_HOST_EN :
+               AB8500_BIT_PHY_CTRL_DEVICE_EN;
+
+       /* mux and configure USB pins to DEFAULT state */
+       ab->pinctrl = pinctrl_get_select(ab->dev, PINCTRL_STATE_DEFAULT);
+       if (IS_ERR(ab->pinctrl))
+               dev_err(ab->dev, "could not get/set default pinstate\n");
+
+       ab8500_usb_regulator_enable(ab);
+
+       abx500_mask_and_set_register_interruptible(ab->dev,
+                       AB8500_USB, AB8500_USB_PHY_CTRL_REG,
+                       bit, bit);
+}
+
+static void ab8500_usb_phy_disable(struct ab8500_usb *ab, bool sel_host)
+{
+       u8 bit;
+       bit = sel_host ? AB8500_BIT_PHY_CTRL_HOST_EN :
+               AB8500_BIT_PHY_CTRL_DEVICE_EN;
+
+       ab8500_usb_wd_linkstatus(ab, bit);
+
+       abx500_mask_and_set_register_interruptible(ab->dev,
+                       AB8500_USB, AB8500_USB_PHY_CTRL_REG,
+                       bit, 0);
+
+       /* Needed to disable the phy.*/
+       ab8500_usb_wd_workaround(ab);
+
+       ab8500_usb_regulator_disable(ab);
+
+       if (!IS_ERR(ab->pinctrl)) {
+               /* configure USB pins to SLEEP state */
+               ab->pins_sleep = pinctrl_lookup_state(ab->pinctrl,
+                               PINCTRL_STATE_SLEEP);
+
+               if (IS_ERR(ab->pins_sleep))
+                       dev_dbg(ab->dev, "could not get sleep pinstate\n");
+               else if (pinctrl_select_state(ab->pinctrl, ab->pins_sleep))
+                       dev_err(ab->dev, "could not set pins to sleep state\n");
+
+               /* as USB pins are shared with idddet, release them to allow
+                * iddet to request them
+                */
+               pinctrl_put(ab->pinctrl);
+       }
+}
+
+#define ab8500_usb_host_phy_en(ab)     ab8500_usb_phy_enable(ab, true)
+#define ab8500_usb_host_phy_dis(ab)    ab8500_usb_phy_disable(ab, true)
+#define ab8500_usb_peri_phy_en(ab)     ab8500_usb_phy_enable(ab, false)
+#define ab8500_usb_peri_phy_dis(ab)    ab8500_usb_phy_disable(ab, false)
+
+static int ab8505_usb_link_status_update(struct ab8500_usb *ab,
+               enum ab8505_usb_link_status lsts)
+{
+       enum ux500_musb_vbus_id_status event = 0;
+
+       dev_dbg(ab->dev, "ab8505_usb_link_status_update %d\n", lsts);
+
+       /*
+        * Spurious link_status interrupts are seen at the time of
+        * disconnection of a device in RIDA state
+        */
+       if (ab->previous_link_status_state == USB_LINK_ACA_RID_A_8505 &&
+                       (lsts == USB_LINK_STD_HOST_NC_8505))
+               return 0;
+
+       ab->previous_link_status_state = lsts;
+
+       switch (lsts) {
+       case USB_LINK_ACA_RID_B_8505:
+               event = UX500_MUSB_RIDB;
+       case USB_LINK_NOT_CONFIGURED_8505:
+       case USB_LINK_RESERVED0_8505:
+       case USB_LINK_RESERVED1_8505:
+       case USB_LINK_RESERVED2_8505:
+       case USB_LINK_RESERVED3_8505:
+               ab->mode = USB_IDLE;
+               ab->phy.otg->default_a = false;
+               ab->vbus_draw = 0;
+               if (event != UX500_MUSB_RIDB)
+                       event = UX500_MUSB_NONE;
+               /*
+                * Fallback to default B_IDLE as nothing
+                * is connected
+                */
+               ab->phy.state = OTG_STATE_B_IDLE;
+               break;
+
+       case USB_LINK_ACA_RID_C_NM_8505:
+               event = UX500_MUSB_RIDC;
+       case USB_LINK_STD_HOST_NC_8505:
+       case USB_LINK_STD_HOST_C_NS_8505:
+       case USB_LINK_STD_HOST_C_S_8505:
+       case USB_LINK_CDP_8505:
+               if (ab->mode == USB_IDLE) {
+                       ab->mode = USB_PERIPHERAL;
+                       ab8500_usb_peri_phy_en(ab);
+                       atomic_notifier_call_chain(&ab->phy.notifier,
+                                       UX500_MUSB_PREPARE, &ab->vbus_draw);
+               }
+               if (event != UX500_MUSB_RIDC)
+                       event = UX500_MUSB_VBUS;
+               break;
+
+       case USB_LINK_ACA_RID_A_8505:
+       case USB_LINK_ACA_DOCK_CHGR_8505:
+               event = UX500_MUSB_RIDA;
+       case USB_LINK_HM_IDGND_8505:
+               if (ab->mode == USB_IDLE) {
+                       ab->mode = USB_HOST;
+                       ab8500_usb_host_phy_en(ab);
+                       atomic_notifier_call_chain(&ab->phy.notifier,
+                                       UX500_MUSB_PREPARE, &ab->vbus_draw);
+               }
+               ab->phy.otg->default_a = true;
+               if (event != UX500_MUSB_RIDA)
+                       event = UX500_MUSB_ID;
+               atomic_notifier_call_chain(&ab->phy.notifier,
+                               event, &ab->vbus_draw);
+               break;
+
+       case USB_LINK_DEDICATED_CHG_8505:
+               ab->mode = USB_DEDICATED_CHG;
+               event = UX500_MUSB_CHARGER;
+               atomic_notifier_call_chain(&ab->phy.notifier,
+                               event, &ab->vbus_draw);
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int ab8500_usb_link_status_update(struct ab8500_usb *ab,
+               enum ab8500_usb_link_status lsts)
+{
+       enum ux500_musb_vbus_id_status event = 0;
+
+       dev_dbg(ab->dev, "ab8500_usb_link_status_update %d\n", lsts);
+
+       /*
+        * Spurious link_status interrupts are seen in case of a
+        * disconnection of a device in IDGND and RIDA stage
+        */
+       if (ab->previous_link_status_state == USB_LINK_HM_IDGND_8500 &&
+                       (lsts == USB_LINK_STD_HOST_C_NS_8500 ||
+                        lsts == USB_LINK_STD_HOST_NC_8500))
+               return 0;
+
+       if (ab->previous_link_status_state == USB_LINK_ACA_RID_A_8500 &&
+                       lsts == USB_LINK_STD_HOST_NC_8500)
+               return 0;
+
+       ab->previous_link_status_state = lsts;
+
+       switch (lsts) {
+       case USB_LINK_ACA_RID_B_8500:
+               event = UX500_MUSB_RIDB;
+       case USB_LINK_NOT_CONFIGURED_8500:
+       case USB_LINK_NOT_VALID_LINK_8500:
+               ab->mode = USB_IDLE;
+               ab->phy.otg->default_a = false;
+               ab->vbus_draw = 0;
+               if (event != UX500_MUSB_RIDB)
+                       event = UX500_MUSB_NONE;
+               /* Fallback to default B_IDLE as nothing is connected */
+               ab->phy.state = OTG_STATE_B_IDLE;
+               break;
+
+       case USB_LINK_ACA_RID_C_NM_8500:
+       case USB_LINK_ACA_RID_C_HS_8500:
+       case USB_LINK_ACA_RID_C_HS_CHIRP_8500:
+               event = UX500_MUSB_RIDC;
+       case USB_LINK_STD_HOST_NC_8500:
+       case USB_LINK_STD_HOST_C_NS_8500:
+       case USB_LINK_STD_HOST_C_S_8500:
+       case USB_LINK_HOST_CHG_NM_8500:
+       case USB_LINK_HOST_CHG_HS_8500:
+       case USB_LINK_HOST_CHG_HS_CHIRP_8500:
+               if (ab->mode == USB_IDLE) {
+                       ab->mode = USB_PERIPHERAL;
+                       ab8500_usb_peri_phy_en(ab);
+                       atomic_notifier_call_chain(&ab->phy.notifier,
+                                       UX500_MUSB_PREPARE, &ab->vbus_draw);
+               }
+               if (event != UX500_MUSB_RIDC)
+                       event = UX500_MUSB_VBUS;
+               break;
+
+       case USB_LINK_ACA_RID_A_8500:
+               event = UX500_MUSB_RIDA;
+       case USB_LINK_HM_IDGND_8500:
+               if (ab->mode == USB_IDLE) {
+                       ab->mode = USB_HOST;
+                       ab8500_usb_host_phy_en(ab);
+                       atomic_notifier_call_chain(&ab->phy.notifier,
+                                       UX500_MUSB_PREPARE, &ab->vbus_draw);
+               }
+               ab->phy.otg->default_a = true;
+               if (event != UX500_MUSB_RIDA)
+                       event = UX500_MUSB_ID;
+               atomic_notifier_call_chain(&ab->phy.notifier,
+                               event, &ab->vbus_draw);
+               break;
+
+       case USB_LINK_DEDICATED_CHG_8500:
+               ab->mode = USB_DEDICATED_CHG;
+               event = UX500_MUSB_CHARGER;
+               atomic_notifier_call_chain(&ab->phy.notifier,
+                               event, &ab->vbus_draw);
+               break;
+
+       case USB_LINK_RESERVED_8500:
+               break;
+       }
+
+       return 0;
+}
+
+/*
+ * Connection Sequence:
+ *   1. Link Status Interrupt
+ *   2. Enable AB clock
+ *   3. Enable AB regulators
+ *   4. Enable USB phy
+ *   5. Reset the musb controller
+ *   6. Switch the ULPI GPIO pins to fucntion mode
+ *   7. Enable the musb Peripheral5 clock
+ *   8. Restore MUSB context
+ */
+static int abx500_usb_link_status_update(struct ab8500_usb *ab)
+{
+       u8 reg;
+       int ret = 0;
+
+       if (is_ab8500(ab->ab8500)) {
+               enum ab8500_usb_link_status lsts;
+
+               abx500_get_register_interruptible(ab->dev,
+                               AB8500_USB, AB8500_USB_LINE_STAT_REG, &reg);
+               lsts = (reg >> 3) & 0x0F;
+               ret = ab8500_usb_link_status_update(ab, lsts);
+       } else if (is_ab8505(ab->ab8500)) {
+               enum ab8505_usb_link_status lsts;
+
+               abx500_get_register_interruptible(ab->dev,
+                               AB8500_USB, AB8505_USB_LINE_STAT_REG, &reg);
+               lsts = (reg >> 3) & 0x1F;
+               ret = ab8505_usb_link_status_update(ab, lsts);
+       }
+
+       return ret;
+}
+
+/*
+ * Disconnection Sequence:
+ *   1. Disconect Interrupt
+ *   2. Disable regulators
+ *   3. Disable AB clock
+ *   4. Disable the Phy
+ *   5. Link Status Interrupt
+ *   6. Disable Musb Clock
+ */
+static irqreturn_t ab8500_usb_disconnect_irq(int irq, void *data)
+{
+       struct ab8500_usb *ab = (struct ab8500_usb *) data;
+       enum usb_phy_events event = UX500_MUSB_NONE;
+
+       /* Link status will not be updated till phy is disabled. */
+       if (ab->mode == USB_HOST) {
+               ab->phy.otg->default_a = false;
+               ab->vbus_draw = 0;
+               atomic_notifier_call_chain(&ab->phy.notifier,
+                               event, &ab->vbus_draw);
+               ab8500_usb_host_phy_dis(ab);
+               ab->mode = USB_IDLE;
+       }
+
+       if (ab->mode == USB_PERIPHERAL) {
+               atomic_notifier_call_chain(&ab->phy.notifier,
+                               event, &ab->vbus_draw);
+               ab8500_usb_peri_phy_dis(ab);
+               atomic_notifier_call_chain(&ab->phy.notifier,
+                               UX500_MUSB_CLEAN, &ab->vbus_draw);
+               ab->mode = USB_IDLE;
+               ab->phy.otg->default_a = false;
+               ab->vbus_draw = 0;
+       }
+
+       if (is_ab8500_2p0(ab->ab8500)) {
+               if (ab->mode == USB_DEDICATED_CHG) {
+                       ab8500_usb_wd_linkstatus(ab,
+                                       AB8500_BIT_PHY_CTRL_DEVICE_EN);
+                       abx500_mask_and_set_register_interruptible(ab->dev,
+                                       AB8500_USB, AB8500_USB_PHY_CTRL_REG,
+                                       AB8500_BIT_PHY_CTRL_DEVICE_EN, 0);
+               }
+       }
+
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t ab8500_usb_link_status_irq(int irq, void *data)
+{
+       struct ab8500_usb *ab = (struct ab8500_usb *) data;
+
+       abx500_usb_link_status_update(ab);
+
+       return IRQ_HANDLED;
+}
+
+static void ab8500_usb_phy_disable_work(struct work_struct *work)
+{
+       struct ab8500_usb *ab = container_of(work, struct ab8500_usb,
+                                               phy_dis_work);
+
+       if (!ab->phy.otg->host)
+               ab8500_usb_host_phy_dis(ab);
+
+       if (!ab->phy.otg->gadget)
+               ab8500_usb_peri_phy_dis(ab);
+}
+
+static unsigned ab8500_eyediagram_workaroud(struct ab8500_usb *ab, unsigned mA)
+{
+       /*
+        * AB8500 V2 has eye diagram issues when drawing more than 100mA from
+        * VBUS.  Set charging current to 100mA in case of standard host
+        */
+       if (is_ab8500_2p0_or_earlier(ab->ab8500))
+               if (mA > 100)
+                       mA = 100;
+
+       return mA;
+}
+
+static int ab8500_usb_set_power(struct usb_phy *phy, unsigned mA)
+{
+       struct ab8500_usb *ab;
+
+       if (!phy)
+               return -ENODEV;
+
+       ab = phy_to_ab(phy);
+
+       mA = ab8500_eyediagram_workaroud(ab, mA);
+
+       ab->vbus_draw = mA;
+
+       atomic_notifier_call_chain(&ab->phy.notifier,
+                       UX500_MUSB_VBUS, &ab->vbus_draw);
+
+       return 0;
+}
+
+static int ab8500_usb_set_suspend(struct usb_phy *x, int suspend)
+{
+       /* TODO */
+       return 0;
+}
+
+static int ab8500_usb_set_peripheral(struct usb_otg *otg,
+                                       struct usb_gadget *gadget)
+{
+       struct ab8500_usb *ab;
+
+       if (!otg)
+               return -ENODEV;
+
+       ab = phy_to_ab(otg->phy);
+
+       ab->phy.otg->gadget = gadget;
+
+       /* Some drivers call this function in atomic context.
+        * Do not update ab8500 registers directly till this
+        * is fixed.
+        */
+
+       if ((ab->mode != USB_IDLE) && (!gadget)) {
+               ab->mode = USB_IDLE;
+               schedule_work(&ab->phy_dis_work);
+       }
+
+       return 0;
+}
+
+static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+       struct ab8500_usb *ab;
+
+       if (!otg)
+               return -ENODEV;
+
+       ab = phy_to_ab(otg->phy);
+
+       ab->phy.otg->host = host;
+
+       /* Some drivers call this function in atomic context.
+        * Do not update ab8500 registers directly till this
+        * is fixed.
+        */
+
+       if ((ab->mode != USB_IDLE) && (!host)) {
+               ab->mode = USB_IDLE;
+               schedule_work(&ab->phy_dis_work);
+       }
+
+       return 0;
+}
+
+static int ab8500_usb_regulator_get(struct ab8500_usb *ab)
+{
+       int err;
+
+       ab->v_ape = devm_regulator_get(ab->dev, "v-ape");
+       if (IS_ERR(ab->v_ape)) {
+               dev_err(ab->dev, "Could not get v-ape supply\n");
+               err = PTR_ERR(ab->v_ape);
+               return err;
+       }
+
+       ab->v_ulpi = devm_regulator_get(ab->dev, "vddulpivio18");
+       if (IS_ERR(ab->v_ulpi)) {
+               dev_err(ab->dev, "Could not get vddulpivio18 supply\n");
+               err = PTR_ERR(ab->v_ulpi);
+               return err;
+       }
+
+       ab->v_musb = devm_regulator_get(ab->dev, "musb_1v8");
+       if (IS_ERR(ab->v_musb)) {
+               dev_err(ab->dev, "Could not get musb_1v8 supply\n");
+               err = PTR_ERR(ab->v_musb);
+               return err;
+       }
+
+       return 0;
+}
+
+static int ab8500_usb_irq_setup(struct platform_device *pdev,
+               struct ab8500_usb *ab)
+{
+       int err;
+       int irq;
+
+       irq = platform_get_irq_byname(pdev, "USB_LINK_STATUS");
+       if (irq < 0) {
+               dev_err(&pdev->dev, "Link status irq not found\n");
+               return irq;
+       }
+       err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                       ab8500_usb_link_status_irq,
+                       IRQF_NO_SUSPEND | IRQF_SHARED, "usb-link-status", ab);
+       if (err < 0) {
+               dev_err(ab->dev, "request_irq failed for link status irq\n");
+               return err;
+       }
+
+       irq = platform_get_irq_byname(pdev, "ID_WAKEUP_F");
+       if (irq < 0) {
+               dev_err(&pdev->dev, "ID fall irq not found\n");
+               return irq;
+       }
+       err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                       ab8500_usb_disconnect_irq,
+                       IRQF_NO_SUSPEND | IRQF_SHARED, "usb-id-fall", ab);
+       if (err < 0) {
+               dev_err(ab->dev, "request_irq failed for ID fall irq\n");
+               return err;
+       }
+
+       irq = platform_get_irq_byname(pdev, "VBUS_DET_F");
+       if (irq < 0) {
+               dev_err(&pdev->dev, "VBUS fall irq not found\n");
+               return irq;
+       }
+       err = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                       ab8500_usb_disconnect_irq,
+                       IRQF_NO_SUSPEND | IRQF_SHARED, "usb-vbus-fall", ab);
+       if (err < 0) {
+               dev_err(ab->dev, "request_irq failed for Vbus fall irq\n");
+               return err;
+       }
+
+       return 0;
+}
+
+static int ab8500_usb_probe(struct platform_device *pdev)
+{
+       struct ab8500_usb       *ab;
+       struct ab8500           *ab8500;
+       struct usb_otg          *otg;
+       int err;
+       int rev;
+
+       ab8500 = dev_get_drvdata(pdev->dev.parent);
+       rev = abx500_get_chip_id(&pdev->dev);
+
+       if (is_ab8500_1p1_or_earlier(ab8500)) {
+               dev_err(&pdev->dev, "Unsupported AB8500 chip rev=%d\n", rev);
+               return -ENODEV;
+       }
+
+       ab = devm_kzalloc(&pdev->dev, sizeof(*ab), GFP_KERNEL);
+       if (!ab)
+               return -ENOMEM;
+
+       otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+       if (!otg)
+               return -ENOMEM;
+
+       ab->dev                 = &pdev->dev;
+       ab->ab8500              = ab8500;
+       ab->phy.dev             = ab->dev;
+       ab->phy.otg             = otg;
+       ab->phy.label           = "ab8500";
+       ab->phy.set_suspend     = ab8500_usb_set_suspend;
+       ab->phy.set_power       = ab8500_usb_set_power;
+       ab->phy.state           = OTG_STATE_UNDEFINED;
+
+       otg->phy                = &ab->phy;
+       otg->set_host           = ab8500_usb_set_host;
+       otg->set_peripheral     = ab8500_usb_set_peripheral;
+
+       platform_set_drvdata(pdev, ab);
+
+       ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier);
+
+       /* all: Disable phy when called from set_host and set_peripheral */
+       INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work);
+
+       err = ab8500_usb_regulator_get(ab);
+       if (err)
+               return err;
+
+       err = ab8500_usb_irq_setup(pdev, ab);
+       if (err < 0)
+               return err;
+
+       err = usb_add_phy(&ab->phy, USB_PHY_TYPE_USB2);
+       if (err) {
+               dev_err(&pdev->dev, "Can't register transceiver\n");
+               return err;
+       }
+
+       /* Phy tuning values for AB8500 */
+       if (!is_ab8500_2p0_or_earlier(ab->ab8500)) {
+               /* Enable the PBT/Bank 0x12 access */
+               err = abx500_set_register_interruptible(ab->dev,
+                               AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x01);
+               if (err < 0)
+                       dev_err(ab->dev, "Failed to enable bank12 access err=%d\n",
+                                       err);
+
+               err = abx500_set_register_interruptible(ab->dev,
+                               AB8500_DEBUG, AB8500_USB_PHY_TUNE1, 0xC8);
+               if (err < 0)
+                       dev_err(ab->dev, "Failed to set PHY_TUNE1 register err=%d\n",
+                                       err);
+
+               err = abx500_set_register_interruptible(ab->dev,
+                               AB8500_DEBUG, AB8500_USB_PHY_TUNE2, 0x00);
+               if (err < 0)
+                       dev_err(ab->dev, "Failed to set PHY_TUNE2 register err=%d\n",
+                                       err);
+
+               err = abx500_set_register_interruptible(ab->dev,
+                               AB8500_DEBUG, AB8500_USB_PHY_TUNE3, 0x78);
+               if (err < 0)
+                       dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n",
+                                       err);
+
+               /* Switch to normal mode/disable Bank 0x12 access */
+               err = abx500_set_register_interruptible(ab->dev,
+                               AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x00);
+               if (err < 0)
+                       dev_err(ab->dev, "Failed to switch bank12 access err=%d\n",
+                                       err);
+       }
+
+       /* Phy tuning values for AB8505 */
+       if (is_ab8505(ab->ab8500)) {
+               /* Enable the PBT/Bank 0x12 access */
+               err = abx500_mask_and_set_register_interruptible(ab->dev,
+                               AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS,
+                               0x01, 0x01);
+               if (err < 0)
+                       dev_err(ab->dev, "Failed to enable bank12 access err=%d\n",
+                                       err);
+
+               err = abx500_mask_and_set_register_interruptible(ab->dev,
+                               AB8500_DEBUG, AB8500_USB_PHY_TUNE1,
+                               0xC8, 0xC8);
+               if (err < 0)
+                       dev_err(ab->dev, "Failed to set PHY_TUNE1 register err=%d\n",
+                                       err);
+
+               err = abx500_mask_and_set_register_interruptible(ab->dev,
+                               AB8500_DEBUG, AB8500_USB_PHY_TUNE2,
+                               0x60, 0x60);
+               if (err < 0)
+                       dev_err(ab->dev, "Failed to set PHY_TUNE2 register err=%d\n",
+                                       err);
+
+               err = abx500_mask_and_set_register_interruptible(ab->dev,
+                               AB8500_DEBUG, AB8500_USB_PHY_TUNE3,
+                               0xFC, 0x80);
+
+               if (err < 0)
+                       dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n",
+                                       err);
+
+               /* Switch to normal mode/disable Bank 0x12 access */
+               err = abx500_mask_and_set_register_interruptible(ab->dev,
+                               AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS,
+                               0x00, 0x00);
+               if (err < 0)
+                       dev_err(ab->dev, "Failed to switch bank12 access err=%d\n",
+                                       err);
+       }
+
+       /* Needed to enable ID detection. */
+       ab8500_usb_wd_workaround(ab);
+
+       abx500_usb_link_status_update(ab);
+
+       dev_info(&pdev->dev, "revision 0x%2x driver initialized\n", rev);
+
+       return 0;
+}
+
+static int ab8500_usb_remove(struct platform_device *pdev)
+{
+       struct ab8500_usb *ab = platform_get_drvdata(pdev);
+
+       cancel_work_sync(&ab->phy_dis_work);
+
+       usb_remove_phy(&ab->phy);
+
+       if (ab->mode == USB_HOST)
+               ab8500_usb_host_phy_dis(ab);
+       else if (ab->mode == USB_PERIPHERAL)
+               ab8500_usb_peri_phy_dis(ab);
+
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver ab8500_usb_driver = {
+       .probe          = ab8500_usb_probe,
+       .remove         = ab8500_usb_remove,
+       .driver         = {
+               .name   = "ab8500-usb",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init ab8500_usb_init(void)
+{
+       return platform_driver_register(&ab8500_usb_driver);
+}
+subsys_initcall(ab8500_usb_init);
+
+static void __exit ab8500_usb_exit(void)
+{
+       platform_driver_unregister(&ab8500_usb_driver);
+}
+module_exit(ab8500_usb_exit);
+
+MODULE_ALIAS("platform:ab8500_usb");
+MODULE_AUTHOR("ST-Ericsson AB");
+MODULE_DESCRIPTION("AB8500 usb transceiver driver");
+MODULE_LICENSE("GPL");
similarity index 97%
rename from drivers/usb/otg/fsl_otg.c
rename to drivers/usb/phy/phy-fsl-usb.c
index d16adb41eb21de144167fc3ad9d6acb5634f1508..97b9308507c3dae718828645a79069c6af2de46e 100644 (file)
@@ -43,7 +43,7 @@
 
 #include <asm/unaligned.h>
 
-#include "fsl_otg.h"
+#include "phy-fsl-usb.h"
 
 #define DRIVER_VERSION "Rev. 1.55"
 #define DRIVER_AUTHOR "Jerry Huang/Li Yang"
@@ -361,28 +361,18 @@ int fsl_otg_init_timers(struct otg_fsm *fsm)
 void fsl_otg_uninit_timers(void)
 {
        /* FSM used timers */
-       if (a_wait_vrise_tmr != NULL)
-               kfree(a_wait_vrise_tmr);
-       if (a_wait_bcon_tmr != NULL)
-               kfree(a_wait_bcon_tmr);
-       if (a_aidl_bdis_tmr != NULL)
-               kfree(a_aidl_bdis_tmr);
-       if (b_ase0_brst_tmr != NULL)
-               kfree(b_ase0_brst_tmr);
-       if (b_se0_srp_tmr != NULL)
-               kfree(b_se0_srp_tmr);
-       if (b_srp_fail_tmr != NULL)
-               kfree(b_srp_fail_tmr);
-       if (a_wait_enum_tmr != NULL)
-               kfree(a_wait_enum_tmr);
+       kfree(a_wait_vrise_tmr);
+       kfree(a_wait_bcon_tmr);
+       kfree(a_aidl_bdis_tmr);
+       kfree(b_ase0_brst_tmr);
+       kfree(b_se0_srp_tmr);
+       kfree(b_srp_fail_tmr);
+       kfree(a_wait_enum_tmr);
 
        /* device driver used timers */
-       if (b_srp_wait_tmr != NULL)
-               kfree(b_srp_wait_tmr);
-       if (b_data_pulse_tmr != NULL)
-               kfree(b_data_pulse_tmr);
-       if (b_vbus_pulse_tmr != NULL)
-               kfree(b_vbus_pulse_tmr);
+       kfree(b_srp_wait_tmr);
+       kfree(b_data_pulse_tmr);
+       kfree(b_vbus_pulse_tmr);
 }
 
 /* Add timer to timer list */
@@ -1002,7 +992,7 @@ static int show_fsl_usb2_otg_state(struct device *dev,
        /* State */
        t = scnprintf(next, size,
                      "OTG state: %s\n\n",
-                     otg_state_string(fsl_otg_dev->phy.state));
+                     usb_otg_state_string(fsl_otg_dev->phy.state));
        size -= t;
        next += t;
 
similarity index 99%
rename from drivers/usb/otg/otg_fsm.c
rename to drivers/usb/phy/phy-fsm-usb.c
index ade131a8ae5ee6e664ee707034951eaad2db757e..c520b3548e7cf59cd0058eda330cd2d7ac792197 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/usb/gadget.h>
 #include <linux/usb/otg.h>
 
-#include "otg_fsm.h"
+#include "phy-otg-fsm.h"
 
 /* Change USB protocol when there is a protocol change */
 static int otg_set_protocol(struct otg_fsm *fsm, int protocol)
@@ -119,7 +119,7 @@ int otg_set_state(struct otg_fsm *fsm, enum usb_otg_state new_state)
        state_changed = 1;
        if (fsm->otg->phy->state == new_state)
                return 0;
-       VDBG("Set state: %s\n", otg_state_string(new_state));
+       VDBG("Set state: %s\n", usb_otg_state_string(new_state));
        otg_leave_state(fsm, fsm->otg->phy->state);
        switch (new_state) {
        case OTG_STATE_B_IDLE:
similarity index 98%
rename from drivers/usb/otg/gpio_vbus.c
rename to drivers/usb/phy/phy-gpio-vbus-usb.c
index a7d4ac591982af09297f9fba882d4c143d320bb5..4c76074e518d56f60c192f560dfc7a3d049de301 100644 (file)
@@ -61,6 +61,7 @@ static void set_vbus_draw(struct gpio_vbus_data *gpio_vbus, unsigned mA)
 {
        struct regulator *vbus_draw = gpio_vbus->vbus_draw;
        int enabled;
+       int ret;
 
        if (!vbus_draw)
                return;
@@ -69,12 +70,16 @@ static void set_vbus_draw(struct gpio_vbus_data *gpio_vbus, unsigned mA)
        if (mA) {
                regulator_set_current_limit(vbus_draw, 0, 1000 * mA);
                if (!enabled) {
-                       regulator_enable(vbus_draw);
+                       ret = regulator_enable(vbus_draw);
+                       if (ret < 0)
+                               return;
                        gpio_vbus->vbus_draw_enabled = 1;
                }
        } else {
                if (enabled) {
-                       regulator_disable(vbus_draw);
+                       ret = regulator_disable(vbus_draw);
+                       if (ret < 0)
+                               return;
                        gpio_vbus->vbus_draw_enabled = 0;
                }
        }
similarity index 99%
rename from drivers/usb/otg/isp1301_omap.c
rename to drivers/usb/phy/phy-isp1301-omap.c
index af9cb11626b229a417b49189ff932c40f3587c13..ae481afcb3ece1358ffd8244ad6df9cbccb93081 100644 (file)
@@ -236,7 +236,7 @@ isp1301_clear_bits(struct isp1301 *isp, u8 reg, u8 bits)
 
 static inline const char *state_name(struct isp1301 *isp)
 {
-       return otg_state_string(isp->phy.state);
+       return usb_otg_state_string(isp->phy.state);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -481,7 +481,7 @@ static void check_state(struct isp1301 *isp, const char *tag)
        if (isp->phy.state == state && !extra)
                return;
        pr_debug("otg: %s FSM %s/%02x, %s, %06x\n", tag,
-               otg_state_string(state), fsm, state_name(isp),
+               usb_otg_state_string(state), fsm, state_name(isp),
                omap_readl(OTG_CTRL));
 }
 
@@ -1077,7 +1077,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat)
 
        if (state != isp->phy.state)
                pr_debug("  isp, %s -> %s\n",
-                               otg_state_string(state), state_name(isp));
+                               usb_otg_state_string(state), state_name(isp));
 
 #ifdef CONFIG_USB_OTG
        /* update the OTG controller state to match the isp1301; may
@@ -1212,7 +1212,7 @@ static void isp1301_release(struct device *dev)
 
 static struct isp1301 *the_transceiver;
 
-static int __exit isp1301_remove(struct i2c_client *i2c)
+static int isp1301_remove(struct i2c_client *i2c)
 {
        struct isp1301  *isp;
 
@@ -1634,7 +1634,7 @@ static struct i2c_driver isp1301_driver = {
                .name   = "isp1301_omap",
        },
        .probe          = isp1301_probe,
-       .remove         = __exit_p(isp1301_remove),
+       .remove         = isp1301_remove,
        .id_table       = isp1301_id,
 };
 
diff --git a/drivers/usb/phy/phy-isp1301.c b/drivers/usb/phy/phy-isp1301.c
new file mode 100644 (file)
index 0000000..225ae6c
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * NXP ISP1301 USB transceiver driver
+ *
+ * Copyright (C) 2012 Roland Stigge
+ *
+ * Author: Roland Stigge <stigge@antcom.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/usb/phy.h>
+#include <linux/usb/isp1301.h>
+
+#define DRV_NAME               "isp1301"
+
+struct isp1301 {
+       struct usb_phy          phy;
+       struct mutex            mutex;
+
+       struct i2c_client       *client;
+};
+
+#define phy_to_isp(p)          (container_of((p), struct isp1301, phy))
+
+static const struct i2c_device_id isp1301_id[] = {
+       { "isp1301", 0 },
+       { }
+};
+
+static struct i2c_client *isp1301_i2c_client;
+
+static int __isp1301_write(struct isp1301 *isp, u8 reg, u8 value, u8 clear)
+{
+       return i2c_smbus_write_byte_data(isp->client, reg | clear, value);
+}
+
+static int isp1301_write(struct isp1301 *isp, u8 reg, u8 value)
+{
+       return __isp1301_write(isp, reg, value, 0);
+}
+
+static int isp1301_clear(struct isp1301 *isp, u8 reg, u8 value)
+{
+       return __isp1301_write(isp, reg, value, ISP1301_I2C_REG_CLEAR_ADDR);
+}
+
+static int isp1301_phy_init(struct usb_phy *phy)
+{
+       struct isp1301 *isp = phy_to_isp(phy);
+
+       /* Disable transparent UART mode first */
+       isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_UART_EN);
+       isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_1, ~MC1_SPEED_REG);
+       isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_SPEED_REG);
+       isp1301_clear(isp, ISP1301_I2C_MODE_CONTROL_2, ~0);
+       isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_2, (MC2_BI_DI | MC2_PSW_EN
+                               | MC2_SPD_SUSP_CTRL));
+
+       isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, ~0);
+       isp1301_write(isp, ISP1301_I2C_MODE_CONTROL_1, MC1_DAT_SE0);
+       isp1301_write(isp, ISP1301_I2C_OTG_CONTROL_1, (OTG1_DM_PULLDOWN
+                               | OTG1_DP_PULLDOWN));
+       isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, (OTG1_DM_PULLUP
+                               | OTG1_DP_PULLUP));
+
+       /* mask all interrupts */
+       isp1301_clear(isp, ISP1301_I2C_INTERRUPT_LATCH, ~0);
+       isp1301_clear(isp, ISP1301_I2C_INTERRUPT_FALLING, ~0);
+       isp1301_clear(isp, ISP1301_I2C_INTERRUPT_RISING, ~0);
+
+       return 0;
+}
+
+static int isp1301_phy_set_vbus(struct usb_phy *phy, int on)
+{
+       struct isp1301 *isp = phy_to_isp(phy);
+
+       if (on)
+               isp1301_write(isp, ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV);
+       else
+               isp1301_clear(isp, ISP1301_I2C_OTG_CONTROL_1, OTG1_VBUS_DRV);
+
+       return 0;
+}
+
+static int isp1301_probe(struct i2c_client *client,
+                        const struct i2c_device_id *i2c_id)
+{
+       struct isp1301 *isp;
+       struct usb_phy *phy;
+
+       isp = devm_kzalloc(&client->dev, sizeof(*isp), GFP_KERNEL);
+       if (!isp)
+               return -ENOMEM;
+
+       isp->client = client;
+       mutex_init(&isp->mutex);
+
+       phy = &isp->phy;
+       phy->label = DRV_NAME;
+       phy->init = isp1301_phy_init;
+       phy->set_vbus = isp1301_phy_set_vbus;
+       phy->type = USB_PHY_TYPE_USB2;
+
+       i2c_set_clientdata(client, isp);
+       usb_add_phy_dev(phy);
+
+       isp1301_i2c_client = client;
+
+       return 0;
+}
+
+static int isp1301_remove(struct i2c_client *client)
+{
+       struct isp1301 *isp = i2c_get_clientdata(client);
+
+       usb_remove_phy(&isp->phy);
+       isp1301_i2c_client = NULL;
+
+       return 0;
+}
+
+static struct i2c_driver isp1301_driver = {
+       .driver = {
+               .name = DRV_NAME,
+       },
+       .probe = isp1301_probe,
+       .remove = isp1301_remove,
+       .id_table = isp1301_id,
+};
+
+module_i2c_driver(isp1301_driver);
+
+static int match(struct device *dev, void *data)
+{
+       struct device_node *node = (struct device_node *)data;
+       return (dev->of_node == node) &&
+               (dev->driver == &isp1301_driver.driver);
+}
+
+struct i2c_client *isp1301_get_client(struct device_node *node)
+{
+       if (node) { /* reference of ISP1301 I2C node via DT */
+               struct device *dev = bus_find_device(&i2c_bus_type, NULL,
+                                                    node, match);
+               if (!dev)
+                       return NULL;
+               return to_i2c_client(dev);
+       } else { /* non-DT: only one ISP1301 chip supported */
+               return isp1301_i2c_client;
+       }
+}
+EXPORT_SYMBOL_GPL(isp1301_get_client);
+
+MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
+MODULE_DESCRIPTION("NXP ISP1301 USB transceiver driver");
+MODULE_LICENSE("GPL");
similarity index 99%
rename from drivers/usb/phy/mv_u3d_phy.c
rename to drivers/usb/phy/phy-mv-u3d-usb.c
index 9d8599122aa9abb424d469747fb50c28d9893dbd..f7838a43347c64d855fe396c7da3ec2c81246a7b 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/usb/otg.h>
 #include <linux/platform_data/mv_usb.h>
 
-#include "mv_u3d_phy.h"
+#include "phy-mv-u3d-usb.h"
 
 /*
  * struct mv_u3d_phy - transceiver driver state
@@ -313,7 +313,7 @@ err:
        return ret;
 }
 
-static int __exit mv_u3d_phy_remove(struct platform_device *pdev)
+static int mv_u3d_phy_remove(struct platform_device *pdev)
 {
        struct mv_u3d_phy *mv_u3d_phy = platform_get_drvdata(pdev);
 
similarity index 97%
rename from drivers/usb/otg/mv_otg.c
rename to drivers/usb/phy/phy-mv-usb.c
index b6a9be31133b0dd15231c6b02ed05cbd10adade6..c987bbe278519c04bfc2e390dd59dd0ba6a8be60 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/usb/hcd.h>
 #include <linux/platform_data/mv_usb.h>
 
-#include "mv_otg.h"
+#include "phy-mv-usb.h"
 
 #define        DRIVER_DESC     "Marvell USB OTG transceiver driver"
 #define        DRIVER_VERSION  "Jan 20, 2010"
@@ -237,18 +237,12 @@ static void mv_otg_start_periphrals(struct mv_otg *mvotg, int on)
 
 static void otg_clock_enable(struct mv_otg *mvotg)
 {
-       unsigned int i;
-
-       for (i = 0; i < mvotg->clknum; i++)
-               clk_prepare_enable(mvotg->clk[i]);
+       clk_prepare_enable(mvotg->clk);
 }
 
 static void otg_clock_disable(struct mv_otg *mvotg)
 {
-       unsigned int i;
-
-       for (i = 0; i < mvotg->clknum; i++)
-               clk_disable_unprepare(mvotg->clk[i]);
+       clk_disable_unprepare(mvotg->clk);
 }
 
 static int mv_otg_enable_internal(struct mv_otg *mvotg)
@@ -684,16 +678,14 @@ static int mv_otg_probe(struct platform_device *pdev)
        struct mv_otg *mvotg;
        struct usb_otg *otg;
        struct resource *r;
-       int retval = 0, clk_i, i;
-       size_t size;
+       int retval = 0, i;
 
        if (pdata == NULL) {
                dev_err(&pdev->dev, "failed to get platform data\n");
                return -ENODEV;
        }
 
-       size = sizeof(*mvotg) + sizeof(struct clk *) * pdata->clknum;
-       mvotg = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+       mvotg = devm_kzalloc(&pdev->dev, sizeof(*mvotg), GFP_KERNEL);
        if (!mvotg) {
                dev_err(&pdev->dev, "failed to allocate memory!\n");
                return -ENOMEM;
@@ -708,15 +700,9 @@ static int mv_otg_probe(struct platform_device *pdev)
        mvotg->pdev = pdev;
        mvotg->pdata = pdata;
 
-       mvotg->clknum = pdata->clknum;
-       for (clk_i = 0; clk_i < mvotg->clknum; clk_i++) {
-               mvotg->clk[clk_i] = devm_clk_get(&pdev->dev,
-                                               pdata->clkname[clk_i]);
-               if (IS_ERR(mvotg->clk[clk_i])) {
-                       retval = PTR_ERR(mvotg->clk[clk_i]);
-                       return retval;
-               }
-       }
+       mvotg->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(mvotg->clk))
+               return PTR_ERR(mvotg->clk);
 
        mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");
        if (!mvotg->qwork) {
similarity index 99%
rename from drivers/usb/otg/mv_otg.h
rename to drivers/usb/phy/phy-mv-usb.h
index 8a9e351b36ba01ab28687be44340642f152c7ed2..551da6eb0ba83569ffd4dbe9728e98bb17aa5f5e 100644 (file)
@@ -158,8 +158,7 @@ struct mv_otg {
 
        unsigned int active;
        unsigned int clock_gating;
-       unsigned int clknum;
-       struct clk *clk[0];
+       struct clk *clk;
 };
 
 #endif
similarity index 84%
rename from drivers/usb/otg/mxs-phy.c
rename to drivers/usb/phy/phy-mxs-usb.c
index b0d9f119c74998e19354658a71cfe78c88b51436..9d4381e64d5126d086af1cbca806519e4813f602 100644 (file)
@@ -48,12 +48,12 @@ static void mxs_phy_hw_init(struct mxs_phy *mxs_phy)
        stmp_reset_block(base + HW_USBPHY_CTRL);
 
        /* Power up the PHY */
-       writel_relaxed(0, base + HW_USBPHY_PWD);
+       writel(0, base + HW_USBPHY_PWD);
 
        /* enable FS/LS device */
-       writel_relaxed(BM_USBPHY_CTRL_ENUTMILEVEL2 |
-                       BM_USBPHY_CTRL_ENUTMILEVEL3,
-                       base + HW_USBPHY_CTRL_SET);
+       writel(BM_USBPHY_CTRL_ENUTMILEVEL2 |
+              BM_USBPHY_CTRL_ENUTMILEVEL3,
+              base + HW_USBPHY_CTRL_SET);
 }
 
 static int mxs_phy_init(struct usb_phy *phy)
@@ -70,8 +70,8 @@ static void mxs_phy_shutdown(struct usb_phy *phy)
 {
        struct mxs_phy *mxs_phy = to_mxs_phy(phy);
 
-       writel_relaxed(BM_USBPHY_CTRL_CLKGATE,
-                       phy->io_priv + HW_USBPHY_CTRL_SET);
+       writel(BM_USBPHY_CTRL_CLKGATE,
+              phy->io_priv + HW_USBPHY_CTRL_SET);
 
        clk_disable_unprepare(mxs_phy->clk);
 }
@@ -81,15 +81,15 @@ static int mxs_phy_suspend(struct usb_phy *x, int suspend)
        struct mxs_phy *mxs_phy = to_mxs_phy(x);
 
        if (suspend) {
-               writel_relaxed(0xffffffff, x->io_priv + HW_USBPHY_PWD);
-               writel_relaxed(BM_USBPHY_CTRL_CLKGATE,
-                       x->io_priv + HW_USBPHY_CTRL_SET);
+               writel(0xffffffff, x->io_priv + HW_USBPHY_PWD);
+               writel(BM_USBPHY_CTRL_CLKGATE,
+                      x->io_priv + HW_USBPHY_CTRL_SET);
                clk_disable_unprepare(mxs_phy->clk);
        } else {
                clk_prepare_enable(mxs_phy->clk);
-               writel_relaxed(BM_USBPHY_CTRL_CLKGATE,
-                       x->io_priv + HW_USBPHY_CTRL_CLR);
-               writel_relaxed(0, x->io_priv + HW_USBPHY_PWD);
+               writel(BM_USBPHY_CTRL_CLKGATE,
+                      x->io_priv + HW_USBPHY_CTRL_CLR);
+               writel(0, x->io_priv + HW_USBPHY_PWD);
        }
 
        return 0;
@@ -102,8 +102,8 @@ static int mxs_phy_on_connect(struct usb_phy *phy,
                (speed == USB_SPEED_HIGH) ? "high" : "non-high");
 
        if (speed == USB_SPEED_HIGH)
-               writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
-                               phy->io_priv + HW_USBPHY_CTRL_SET);
+               writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+                      phy->io_priv + HW_USBPHY_CTRL_SET);
 
        return 0;
 }
@@ -115,8 +115,8 @@ static int mxs_phy_on_disconnect(struct usb_phy *phy,
                (speed == USB_SPEED_HIGH) ? "high" : "non-high");
 
        if (speed == USB_SPEED_HIGH)
-               writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
-                               phy->io_priv + HW_USBPHY_CTRL_CLR);
+               writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
+                      phy->io_priv + HW_USBPHY_CTRL_CLR);
 
        return 0;
 }
@@ -127,6 +127,7 @@ static int mxs_phy_probe(struct platform_device *pdev)
        void __iomem *base;
        struct clk *clk;
        struct mxs_phy *mxs_phy;
+       int ret;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
@@ -166,11 +167,19 @@ static int mxs_phy_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, &mxs_phy->phy);
 
+       ret = usb_add_phy_dev(&mxs_phy->phy);
+       if (ret)
+               return ret;
+
        return 0;
 }
 
 static int mxs_phy_remove(struct platform_device *pdev)
 {
+       struct mxs_phy *mxs_phy = platform_get_drvdata(pdev);
+
+       usb_remove_phy(&mxs_phy->phy);
+
        platform_set_drvdata(pdev, NULL);
 
        return 0;
similarity index 55%
rename from drivers/usb/otg/nop-usb-xceiv.c
rename to drivers/usb/phy/phy-nop.c
index a3ce24b94a73b1ee4bd43a1cbbcb2483c5bddeaf..2b10cc969bbb1f4457a463c2072508953a42fdc2 100644 (file)
 #include <linux/usb/otg.h>
 #include <linux/usb/nop-usb-xceiv.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of.h>
 
 struct nop_usb_xceiv {
-       struct usb_phy          phy;
-       struct device           *dev;
+       struct usb_phy phy;
+       struct device *dev;
+       struct clk *clk;
+       struct regulator *vcc;
+       struct regulator *reset;
 };
 
 static struct platform_device *pd;
@@ -64,6 +70,46 @@ static int nop_set_suspend(struct usb_phy *x, int suspend)
        return 0;
 }
 
+static int nop_init(struct usb_phy *phy)
+{
+       struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev);
+
+       if (!IS_ERR(nop->vcc)) {
+               if (regulator_enable(nop->vcc))
+                       dev_err(phy->dev, "Failed to enable power\n");
+       }
+
+       if (!IS_ERR(nop->clk))
+               clk_enable(nop->clk);
+
+       if (!IS_ERR(nop->reset)) {
+               /* De-assert RESET */
+               if (regulator_enable(nop->reset))
+                       dev_err(phy->dev, "Failed to de-assert reset\n");
+       }
+
+       return 0;
+}
+
+static void nop_shutdown(struct usb_phy *phy)
+{
+       struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev);
+
+       if (!IS_ERR(nop->reset)) {
+               /* Assert RESET */
+               if (regulator_disable(nop->reset))
+                       dev_err(phy->dev, "Failed to assert reset\n");
+       }
+
+       if (!IS_ERR(nop->clk))
+               clk_disable(nop->clk);
+
+       if (!IS_ERR(nop->vcc)) {
+               if (regulator_disable(nop->vcc))
+                       dev_err(phy->dev, "Failed to disable power\n");
+       }
+}
+
 static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget)
 {
        if (!otg)
@@ -95,39 +141,96 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host)
 
 static int nop_usb_xceiv_probe(struct platform_device *pdev)
 {
+       struct device *dev = &pdev->dev;
        struct nop_usb_xceiv_platform_data *pdata = pdev->dev.platform_data;
        struct nop_usb_xceiv    *nop;
        enum usb_phy_type       type = USB_PHY_TYPE_USB2;
        int err;
+       u32 clk_rate = 0;
+       bool needs_vcc = false;
+       bool needs_reset = false;
 
-       nop = kzalloc(sizeof *nop, GFP_KERNEL);
+       nop = devm_kzalloc(&pdev->dev, sizeof(*nop), GFP_KERNEL);
        if (!nop)
                return -ENOMEM;
 
-       nop->phy.otg = kzalloc(sizeof *nop->phy.otg, GFP_KERNEL);
-       if (!nop->phy.otg) {
-               kfree(nop);
+       nop->phy.otg = devm_kzalloc(&pdev->dev, sizeof(*nop->phy.otg),
+                                                       GFP_KERNEL);
+       if (!nop->phy.otg)
                return -ENOMEM;
-       }
 
-       if (pdata)
+       if (dev->of_node) {
+               struct device_node *node = dev->of_node;
+
+               if (of_property_read_u32(node, "clock-frequency", &clk_rate))
+                       clk_rate = 0;
+
+               needs_vcc = of_property_read_bool(node, "vcc-supply");
+               needs_reset = of_property_read_bool(node, "reset-supply");
+
+       } else if (pdata) {
                type = pdata->type;
+               clk_rate = pdata->clk_rate;
+               needs_vcc = pdata->needs_vcc;
+               needs_reset = pdata->needs_reset;
+       }
+
+       nop->clk = devm_clk_get(&pdev->dev, "main_clk");
+       if (IS_ERR(nop->clk)) {
+               dev_dbg(&pdev->dev, "Can't get phy clock: %ld\n",
+                                       PTR_ERR(nop->clk));
+       }
+
+       if (!IS_ERR(nop->clk) && clk_rate) {
+               err = clk_set_rate(nop->clk, clk_rate);
+               if (err) {
+                       dev_err(&pdev->dev, "Error setting clock rate\n");
+                       return err;
+               }
+       }
+
+       if (!IS_ERR(nop->clk)) {
+               err = clk_prepare(nop->clk);
+               if (err) {
+                       dev_err(&pdev->dev, "Error preparing clock\n");
+                       return err;
+               }
+       }
+
+       nop->vcc = devm_regulator_get(&pdev->dev, "vcc");
+       if (IS_ERR(nop->vcc)) {
+               dev_dbg(&pdev->dev, "Error getting vcc regulator: %ld\n",
+                                       PTR_ERR(nop->vcc));
+               if (needs_vcc)
+                       return -EPROBE_DEFER;
+       }
+
+       nop->reset = devm_regulator_get(&pdev->dev, "reset");
+       if (IS_ERR(nop->reset)) {
+               dev_dbg(&pdev->dev, "Error getting reset regulator: %ld\n",
+                                       PTR_ERR(nop->reset));
+               if (needs_reset)
+                       return -EPROBE_DEFER;
+       }
 
        nop->dev                = &pdev->dev;
        nop->phy.dev            = nop->dev;
        nop->phy.label          = "nop-xceiv";
        nop->phy.set_suspend    = nop_set_suspend;
+       nop->phy.init           = nop_init;
+       nop->phy.shutdown       = nop_shutdown;
        nop->phy.state          = OTG_STATE_UNDEFINED;
+       nop->phy.type           = type;
 
        nop->phy.otg->phy               = &nop->phy;
        nop->phy.otg->set_host          = nop_set_host;
        nop->phy.otg->set_peripheral    = nop_set_peripheral;
 
-       err = usb_add_phy(&nop->phy, type);
+       err = usb_add_phy_dev(&nop->phy);
        if (err) {
                dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
                        err);
-               goto exit;
+               goto err_add;
        }
 
        platform_set_drvdata(pdev, nop);
@@ -135,9 +238,10 @@ static int nop_usb_xceiv_probe(struct platform_device *pdev)
        ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier);
 
        return 0;
-exit:
-       kfree(nop->phy.otg);
-       kfree(nop);
+
+err_add:
+       if (!IS_ERR(nop->clk))
+               clk_unprepare(nop->clk);
        return err;
 }
 
@@ -145,21 +249,30 @@ static int nop_usb_xceiv_remove(struct platform_device *pdev)
 {
        struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
 
+       if (!IS_ERR(nop->clk))
+               clk_unprepare(nop->clk);
+
        usb_remove_phy(&nop->phy);
 
        platform_set_drvdata(pdev, NULL);
-       kfree(nop->phy.otg);
-       kfree(nop);
 
        return 0;
 }
 
+static const struct of_device_id nop_xceiv_dt_ids[] = {
+       { .compatible = "usb-nop-xceiv" },
+       { }
+};
+
+MODULE_DEVICE_TABLE(of, nop_xceiv_dt_ids);
+
 static struct platform_driver nop_usb_xceiv_driver = {
        .probe          = nop_usb_xceiv_probe,
        .remove         = nop_usb_xceiv_remove,
        .driver         = {
                .name   = "nop_usb_xceiv",
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(nop_xceiv_dt_ids),
        },
 };
 
diff --git a/drivers/usb/phy/phy-samsung-usb.c b/drivers/usb/phy/phy-samsung-usb.c
new file mode 100644 (file)
index 0000000..7b118ee
--- /dev/null
@@ -0,0 +1,236 @@
+/* linux/drivers/usb/phy/phy-samsung-usb.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com
+ *
+ * Author: Praveen Paneri <p.paneri@samsung.com>
+ *
+ * Samsung USB-PHY helper driver with common function calls;
+ * interacts with Samsung USB 2.0 PHY controller driver and later
+ * with Samsung USB 3.0 PHY driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This 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 <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/usb/samsung_usb_phy.h>
+
+#include "phy-samsung-usb.h"
+
+int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy)
+{
+       struct device_node *usbphy_sys;
+
+       /* Getting node for system controller interface for usb-phy */
+       usbphy_sys = of_get_child_by_name(sphy->dev->of_node, "usbphy-sys");
+       if (!usbphy_sys) {
+               dev_err(sphy->dev, "No sys-controller interface for usb-phy\n");
+               return -ENODEV;
+       }
+
+       sphy->pmuregs = of_iomap(usbphy_sys, 0);
+
+       if (sphy->pmuregs == NULL) {
+               dev_err(sphy->dev, "Can't get usb-phy pmu control register\n");
+               goto err0;
+       }
+
+       sphy->sysreg = of_iomap(usbphy_sys, 1);
+
+       /*
+        * Not returning error code here, since this situation is not fatal.
+        * Few SoCs may not have this switch available
+        */
+       if (sphy->sysreg == NULL)
+               dev_warn(sphy->dev, "Can't get usb-phy sysreg cfg register\n");
+
+       of_node_put(usbphy_sys);
+
+       return 0;
+
+err0:
+       of_node_put(usbphy_sys);
+       return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(samsung_usbphy_parse_dt);
+
+/*
+ * Set isolation here for phy.
+ * Here 'on = true' would mean USB PHY block is isolated, hence
+ * de-activated and vice-versa.
+ */
+void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
+{
+       void __iomem *reg = NULL;
+       u32 reg_val;
+       u32 en_mask = 0;
+
+       if (!sphy->pmuregs) {
+               dev_warn(sphy->dev, "Can't set pmu isolation\n");
+               return;
+       }
+
+       switch (sphy->drv_data->cpu_type) {
+       case TYPE_S3C64XX:
+               /*
+                * Do nothing: We will add here once S3C64xx goes for DT support
+                */
+               break;
+       case TYPE_EXYNOS4210:
+               /*
+                * Fall through since exynos4210 and exynos5250 have similar
+                * register architecture: two separate registers for host and
+                * device phy control with enable bit at position 0.
+                */
+       case TYPE_EXYNOS5250:
+               if (sphy->phy_type == USB_PHY_TYPE_DEVICE) {
+                       reg = sphy->pmuregs +
+                               sphy->drv_data->devphy_reg_offset;
+                       en_mask = sphy->drv_data->devphy_en_mask;
+               } else if (sphy->phy_type == USB_PHY_TYPE_HOST) {
+                       reg = sphy->pmuregs +
+                               sphy->drv_data->hostphy_reg_offset;
+                       en_mask = sphy->drv_data->hostphy_en_mask;
+               }
+               break;
+       default:
+               dev_err(sphy->dev, "Invalid SoC type\n");
+               return;
+       }
+
+       reg_val = readl(reg);
+
+       if (on)
+               reg_val &= ~en_mask;
+       else
+               reg_val |= en_mask;
+
+       writel(reg_val, reg);
+}
+EXPORT_SYMBOL_GPL(samsung_usbphy_set_isolation);
+
+/*
+ * Configure the mode of working of usb-phy here: HOST/DEVICE.
+ */
+void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy)
+{
+       u32 reg;
+
+       if (!sphy->sysreg) {
+               dev_warn(sphy->dev, "Can't configure specified phy mode\n");
+               return;
+       }
+
+       reg = readl(sphy->sysreg);
+
+       if (sphy->phy_type == USB_PHY_TYPE_DEVICE)
+               reg &= ~EXYNOS_USB20PHY_CFG_HOST_LINK;
+       else if (sphy->phy_type == USB_PHY_TYPE_HOST)
+               reg |= EXYNOS_USB20PHY_CFG_HOST_LINK;
+
+       writel(reg, sphy->sysreg);
+}
+EXPORT_SYMBOL_GPL(samsung_usbphy_cfg_sel);
+
+/*
+ * PHYs are different for USB Device and USB Host.
+ * This make sure that correct PHY type is selected before
+ * any operation on PHY.
+ */
+int samsung_usbphy_set_type(struct usb_phy *phy,
+                               enum samsung_usb_phy_type phy_type)
+{
+       struct samsung_usbphy *sphy = phy_to_sphy(phy);
+
+       sphy->phy_type = phy_type;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(samsung_usbphy_set_type);
+
+/*
+ * Returns reference clock frequency selection value
+ */
+int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
+{
+       struct clk *ref_clk;
+       int refclk_freq = 0;
+
+       /*
+        * In exynos5250 USB host and device PHY use
+        * external crystal clock XXTI
+        */
+       if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
+               ref_clk = devm_clk_get(sphy->dev, "ext_xtal");
+       else
+               ref_clk = devm_clk_get(sphy->dev, "xusbxti");
+       if (IS_ERR(ref_clk)) {
+               dev_err(sphy->dev, "Failed to get reference clock\n");
+               return PTR_ERR(ref_clk);
+       }
+
+       if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) {
+               /* set clock frequency for PLL */
+               switch (clk_get_rate(ref_clk)) {
+               case 9600 * KHZ:
+                       refclk_freq = FSEL_CLKSEL_9600K;
+                       break;
+               case 10 * MHZ:
+                       refclk_freq = FSEL_CLKSEL_10M;
+                       break;
+               case 12 * MHZ:
+                       refclk_freq = FSEL_CLKSEL_12M;
+                       break;
+               case 19200 * KHZ:
+                       refclk_freq = FSEL_CLKSEL_19200K;
+                       break;
+               case 20 * MHZ:
+                       refclk_freq = FSEL_CLKSEL_20M;
+                       break;
+               case 50 * MHZ:
+                       refclk_freq = FSEL_CLKSEL_50M;
+                       break;
+               case 24 * MHZ:
+               default:
+                       /* default reference clock */
+                       refclk_freq = FSEL_CLKSEL_24M;
+                       break;
+               }
+       } else {
+               switch (clk_get_rate(ref_clk)) {
+               case 12 * MHZ:
+                       refclk_freq = PHYCLK_CLKSEL_12M;
+                       break;
+               case 24 * MHZ:
+                       refclk_freq = PHYCLK_CLKSEL_24M;
+                       break;
+               case 48 * MHZ:
+                       refclk_freq = PHYCLK_CLKSEL_48M;
+                       break;
+               default:
+                       if (sphy->drv_data->cpu_type == TYPE_S3C64XX)
+                               refclk_freq = PHYCLK_CLKSEL_48M;
+                       else
+                               refclk_freq = PHYCLK_CLKSEL_24M;
+                       break;
+               }
+       }
+       clk_put(ref_clk);
+
+       return refclk_freq;
+}
+EXPORT_SYMBOL_GPL(samsung_usbphy_get_refclk_freq);
diff --git a/drivers/usb/phy/phy-samsung-usb.h b/drivers/usb/phy/phy-samsung-usb.h
new file mode 100644 (file)
index 0000000..70a9cae
--- /dev/null
@@ -0,0 +1,327 @@
+/* linux/drivers/usb/phy/phy-samsung-usb.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com
+ *
+ * Samsung USB-PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
+ * OHCI-EXYNOS controllers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This 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 <linux/usb/phy.h>
+
+/* Register definitions */
+
+#define SAMSUNG_PHYPWR                         (0x00)
+
+#define PHYPWR_NORMAL_MASK                     (0x19 << 0)
+#define PHYPWR_OTG_DISABLE                     (0x1 << 4)
+#define PHYPWR_ANALOG_POWERDOWN                        (0x1 << 3)
+#define PHYPWR_FORCE_SUSPEND                   (0x1 << 1)
+/* For Exynos4 */
+#define PHYPWR_NORMAL_MASK_PHY0                        (0x39 << 0)
+#define PHYPWR_SLEEP_PHY0                      (0x1 << 5)
+
+#define SAMSUNG_PHYCLK                         (0x04)
+
+#define PHYCLK_MODE_USB11                      (0x1 << 6)
+#define PHYCLK_EXT_OSC                         (0x1 << 5)
+#define PHYCLK_COMMON_ON_N                     (0x1 << 4)
+#define PHYCLK_ID_PULL                         (0x1 << 2)
+#define PHYCLK_CLKSEL_MASK                     (0x3 << 0)
+#define PHYCLK_CLKSEL_48M                      (0x0 << 0)
+#define PHYCLK_CLKSEL_12M                      (0x2 << 0)
+#define PHYCLK_CLKSEL_24M                      (0x3 << 0)
+
+#define SAMSUNG_RSTCON                         (0x08)
+
+#define RSTCON_PHYLINK_SWRST                   (0x1 << 2)
+#define RSTCON_HLINK_SWRST                     (0x1 << 1)
+#define RSTCON_SWRST                           (0x1 << 0)
+
+/* EXYNOS5 */
+#define EXYNOS5_PHY_HOST_CTRL0                 (0x00)
+
+#define HOST_CTRL0_PHYSWRSTALL                 (0x1 << 31)
+
+#define HOST_CTRL0_REFCLKSEL_MASK              (0x3 << 19)
+#define HOST_CTRL0_REFCLKSEL_XTAL              (0x0 << 19)
+#define HOST_CTRL0_REFCLKSEL_EXTL              (0x1 << 19)
+#define HOST_CTRL0_REFCLKSEL_CLKCORE           (0x2 << 19)
+
+#define HOST_CTRL0_FSEL_MASK                   (0x7 << 16)
+#define HOST_CTRL0_FSEL(_x)                    ((_x) << 16)
+
+#define FSEL_CLKSEL_50M                                (0x7)
+#define FSEL_CLKSEL_24M                                (0x5)
+#define FSEL_CLKSEL_20M                                (0x4)
+#define FSEL_CLKSEL_19200K                     (0x3)
+#define FSEL_CLKSEL_12M                                (0x2)
+#define FSEL_CLKSEL_10M                                (0x1)
+#define FSEL_CLKSEL_9600K                      (0x0)
+
+#define HOST_CTRL0_TESTBURNIN                  (0x1 << 11)
+#define HOST_CTRL0_RETENABLE                   (0x1 << 10)
+#define HOST_CTRL0_COMMONON_N                  (0x1 << 9)
+#define HOST_CTRL0_SIDDQ                       (0x1 << 6)
+#define HOST_CTRL0_FORCESLEEP                  (0x1 << 5)
+#define HOST_CTRL0_FORCESUSPEND                        (0x1 << 4)
+#define HOST_CTRL0_WORDINTERFACE               (0x1 << 3)
+#define HOST_CTRL0_UTMISWRST                   (0x1 << 2)
+#define HOST_CTRL0_LINKSWRST                   (0x1 << 1)
+#define HOST_CTRL0_PHYSWRST                    (0x1 << 0)
+
+#define EXYNOS5_PHY_HOST_TUNE0                 (0x04)
+
+#define EXYNOS5_PHY_HSIC_CTRL1                 (0x10)
+
+#define EXYNOS5_PHY_HSIC_TUNE1                 (0x14)
+
+#define EXYNOS5_PHY_HSIC_CTRL2                 (0x20)
+
+#define EXYNOS5_PHY_HSIC_TUNE2                 (0x24)
+
+#define HSIC_CTRL_REFCLKSEL_MASK               (0x3 << 23)
+#define HSIC_CTRL_REFCLKSEL                    (0x2 << 23)
+
+#define HSIC_CTRL_REFCLKDIV_MASK               (0x7f << 16)
+#define HSIC_CTRL_REFCLKDIV(_x)                        ((_x) << 16)
+#define HSIC_CTRL_REFCLKDIV_12                 (0x24 << 16)
+#define HSIC_CTRL_REFCLKDIV_15                 (0x1c << 16)
+#define HSIC_CTRL_REFCLKDIV_16                 (0x1a << 16)
+#define HSIC_CTRL_REFCLKDIV_19_2               (0x15 << 16)
+#define HSIC_CTRL_REFCLKDIV_20                 (0x14 << 16)
+
+#define HSIC_CTRL_SIDDQ                                (0x1 << 6)
+#define HSIC_CTRL_FORCESLEEP                   (0x1 << 5)
+#define HSIC_CTRL_FORCESUSPEND                 (0x1 << 4)
+#define HSIC_CTRL_WORDINTERFACE                        (0x1 << 3)
+#define HSIC_CTRL_UTMISWRST                    (0x1 << 2)
+#define HSIC_CTRL_PHYSWRST                     (0x1 << 0)
+
+#define EXYNOS5_PHY_HOST_EHCICTRL              (0x30)
+
+#define HOST_EHCICTRL_ENAINCRXALIGN            (0x1 << 29)
+#define HOST_EHCICTRL_ENAINCR4                 (0x1 << 28)
+#define HOST_EHCICTRL_ENAINCR8                 (0x1 << 27)
+#define HOST_EHCICTRL_ENAINCR16                        (0x1 << 26)
+
+#define EXYNOS5_PHY_HOST_OHCICTRL              (0x34)
+
+#define HOST_OHCICTRL_SUSPLGCY                 (0x1 << 3)
+#define HOST_OHCICTRL_APPSTARTCLK              (0x1 << 2)
+#define HOST_OHCICTRL_CNTSEL                   (0x1 << 1)
+#define HOST_OHCICTRL_CLKCKTRST                        (0x1 << 0)
+
+#define EXYNOS5_PHY_OTG_SYS                    (0x38)
+
+#define OTG_SYS_PHYLINK_SWRESET                        (0x1 << 14)
+#define OTG_SYS_LINKSWRST_UOTG                 (0x1 << 13)
+#define OTG_SYS_PHY0_SWRST                     (0x1 << 12)
+
+#define OTG_SYS_REFCLKSEL_MASK                 (0x3 << 9)
+#define OTG_SYS_REFCLKSEL_XTAL                 (0x0 << 9)
+#define OTG_SYS_REFCLKSEL_EXTL                 (0x1 << 9)
+#define OTG_SYS_REFCLKSEL_CLKCORE              (0x2 << 9)
+
+#define OTG_SYS_IDPULLUP_UOTG                  (0x1 << 8)
+#define OTG_SYS_COMMON_ON                      (0x1 << 7)
+
+#define OTG_SYS_FSEL_MASK                      (0x7 << 4)
+#define OTG_SYS_FSEL(_x)                       ((_x) << 4)
+
+#define OTG_SYS_FORCESLEEP                     (0x1 << 3)
+#define OTG_SYS_OTGDISABLE                     (0x1 << 2)
+#define OTG_SYS_SIDDQ_UOTG                     (0x1 << 1)
+#define OTG_SYS_FORCESUSPEND                   (0x1 << 0)
+
+#define EXYNOS5_PHY_OTG_TUNE                   (0x40)
+
+/* EXYNOS5: USB 3.0 DRD */
+#define EXYNOS5_DRD_LINKSYSTEM                 (0x04)
+
+#define LINKSYSTEM_FLADJ_MASK                  (0x3f << 1)
+#define LINKSYSTEM_FLADJ(_x)                   ((_x) << 1)
+#define LINKSYSTEM_XHCI_VERSION_CONTROL                (0x1 << 27)
+
+#define EXYNOS5_DRD_PHYUTMI                    (0x08)
+
+#define PHYUTMI_OTGDISABLE                     (0x1 << 6)
+#define PHYUTMI_FORCESUSPEND                   (0x1 << 1)
+#define PHYUTMI_FORCESLEEP                     (0x1 << 0)
+
+#define EXYNOS5_DRD_PHYPIPE                    (0x0c)
+
+#define EXYNOS5_DRD_PHYCLKRST                  (0x10)
+
+#define PHYCLKRST_SSC_REFCLKSEL_MASK           (0xff << 23)
+#define PHYCLKRST_SSC_REFCLKSEL(_x)            ((_x) << 23)
+
+#define PHYCLKRST_SSC_RANGE_MASK               (0x03 << 21)
+#define PHYCLKRST_SSC_RANGE(_x)                        ((_x) << 21)
+
+#define PHYCLKRST_SSC_EN                       (0x1 << 20)
+#define PHYCLKRST_REF_SSP_EN                   (0x1 << 19)
+#define PHYCLKRST_REF_CLKDIV2                  (0x1 << 18)
+
+#define PHYCLKRST_MPLL_MULTIPLIER_MASK         (0x7f << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF   (0x19 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF      (0x02 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF    (0x68 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF    (0x7d << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF (0x02 << 11)
+
+#define PHYCLKRST_FSEL_MASK                    (0x3f << 5)
+#define PHYCLKRST_FSEL(_x)                     ((_x) << 5)
+#define PHYCLKRST_FSEL_PAD_100MHZ              (0x27 << 5)
+#define PHYCLKRST_FSEL_PAD_24MHZ               (0x2a << 5)
+#define PHYCLKRST_FSEL_PAD_20MHZ               (0x31 << 5)
+#define PHYCLKRST_FSEL_PAD_19_2MHZ             (0x38 << 5)
+
+#define PHYCLKRST_RETENABLEN                   (0x1 << 4)
+
+#define PHYCLKRST_REFCLKSEL_MASK               (0x03 << 2)
+#define PHYCLKRST_REFCLKSEL_PAD_REFCLK         (0x2 << 2)
+#define PHYCLKRST_REFCLKSEL_EXT_REFCLK         (0x3 << 2)
+
+#define PHYCLKRST_PORTRESET                    (0x1 << 1)
+#define PHYCLKRST_COMMONONN                    (0x1 << 0)
+
+#define EXYNOS5_DRD_PHYREG0                    (0x14)
+#define EXYNOS5_DRD_PHYREG1                    (0x18)
+
+#define EXYNOS5_DRD_PHYPARAM0                  (0x1c)
+
+#define PHYPARAM0_REF_USE_PAD                  (0x1 << 31)
+#define PHYPARAM0_REF_LOSLEVEL_MASK            (0x1f << 26)
+#define PHYPARAM0_REF_LOSLEVEL                 (0x9 << 26)
+
+#define EXYNOS5_DRD_PHYPARAM1                  (0x20)
+
+#define PHYPARAM1_PCS_TXDEEMPH_MASK            (0x1f << 0)
+#define PHYPARAM1_PCS_TXDEEMPH                 (0x1c)
+
+#define EXYNOS5_DRD_PHYTERM                    (0x24)
+
+#define EXYNOS5_DRD_PHYTEST                    (0x28)
+
+#define PHYTEST_POWERDOWN_SSP                  (0x1 << 3)
+#define PHYTEST_POWERDOWN_HSP                  (0x1 << 2)
+
+#define EXYNOS5_DRD_PHYADP                     (0x2c)
+
+#define EXYNOS5_DRD_PHYBATCHG                  (0x30)
+
+#define PHYBATCHG_UTMI_CLKSEL                  (0x1 << 2)
+
+#define EXYNOS5_DRD_PHYRESUME                  (0x34)
+#define EXYNOS5_DRD_LINKPORT                   (0x44)
+
+#ifndef MHZ
+#define MHZ (1000*1000)
+#endif
+
+#ifndef KHZ
+#define KHZ (1000)
+#endif
+
+#define EXYNOS_USBHOST_PHY_CTRL_OFFSET         (0x4)
+#define S3C64XX_USBPHY_ENABLE                  (0x1 << 16)
+#define EXYNOS_USBPHY_ENABLE                   (0x1 << 0)
+#define EXYNOS_USB20PHY_CFG_HOST_LINK          (0x1 << 0)
+
+enum samsung_cpu_type {
+       TYPE_S3C64XX,
+       TYPE_EXYNOS4210,
+       TYPE_EXYNOS5250,
+};
+
+/*
+ * struct samsung_usbphy_drvdata - driver data for various SoC variants
+ * @cpu_type: machine identifier
+ * @devphy_en_mask: device phy enable mask for PHY CONTROL register
+ * @hostphy_en_mask: host phy enable mask for PHY CONTROL register
+ * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from
+ *                    mapped address of system controller.
+ * @hostphy_reg_offset: offset to HOST PHY CONTROL register from
+ *                    mapped address of system controller.
+ *
+ *     Here we have a separate mask for device type phy.
+ *     Having different masks for host and device type phy helps
+ *     in setting independent masks in case of SoCs like S5PV210,
+ *     in which PHY0 and PHY1 enable bits belong to same register
+ *     placed at position 0 and 1 respectively.
+ *     Although for newer SoCs like exynos these bits belong to
+ *     different registers altogether placed at position 0.
+ */
+struct samsung_usbphy_drvdata {
+       int cpu_type;
+       int devphy_en_mask;
+       int hostphy_en_mask;
+       u32 devphy_reg_offset;
+       u32 hostphy_reg_offset;
+};
+
+/*
+ * struct samsung_usbphy - transceiver driver state
+ * @phy: transceiver structure
+ * @plat: platform data
+ * @dev: The parent device supplied to the probe function
+ * @clk: usb phy clock
+ * @regs: usb phy controller registers memory base
+ * @pmuregs: USB device PHY_CONTROL register memory base
+ * @sysreg: USB2.0 PHY_CFG register memory base
+ * @ref_clk_freq: reference clock frequency selection
+ * @drv_data: driver data available for different SoCs
+ * @phy_type: Samsung SoCs specific phy types: #HOST
+ *                                             #DEVICE
+ * @phy_usage: usage count for phy
+ * @lock: lock for phy operations
+ */
+struct samsung_usbphy {
+       struct usb_phy  phy;
+       struct samsung_usbphy_data *plat;
+       struct device   *dev;
+       struct clk      *clk;
+       void __iomem    *regs;
+       void __iomem    *pmuregs;
+       void __iomem    *sysreg;
+       int             ref_clk_freq;
+       const struct samsung_usbphy_drvdata *drv_data;
+       enum samsung_usb_phy_type phy_type;
+       atomic_t        phy_usage;
+       spinlock_t      lock;
+};
+
+#define phy_to_sphy(x)         container_of((x), struct samsung_usbphy, phy)
+
+static const struct of_device_id samsung_usbphy_dt_match[];
+
+static inline const struct samsung_usbphy_drvdata
+*samsung_usbphy_get_driver_data(struct platform_device *pdev)
+{
+       if (pdev->dev.of_node) {
+               const struct of_device_id *match;
+               match = of_match_node(samsung_usbphy_dt_match,
+                                                       pdev->dev.of_node);
+               return match->data;
+       }
+
+       return (struct samsung_usbphy_drvdata *)
+                               platform_get_device_id(pdev)->driver_data;
+}
+
+extern int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy);
+extern void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on);
+extern void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy);
+extern int samsung_usbphy_set_type(struct usb_phy *phy,
+                                       enum samsung_usb_phy_type phy_type);
+extern int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy);
diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c
new file mode 100644 (file)
index 0000000..45ffe03
--- /dev/null
@@ -0,0 +1,509 @@
+/* linux/drivers/usb/phy/phy-samsung-usb2.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com
+ *
+ * Author: Praveen Paneri <p.paneri@samsung.com>
+ *
+ * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
+ * OHCI-EXYNOS controllers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This 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 <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/samsung_usb_phy.h>
+#include <linux/platform_data/samsung-usbphy.h>
+
+#include "phy-samsung-usb.h"
+
+static int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+       if (!otg)
+               return -ENODEV;
+
+       if (!otg->host)
+               otg->host = host;
+
+       return 0;
+}
+
+static bool exynos5_phyhost_is_on(void __iomem *regs)
+{
+       u32 reg;
+
+       reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
+
+       return !(reg & HOST_CTRL0_SIDDQ);
+}
+
+static void samsung_exynos5_usb2phy_enable(struct samsung_usbphy *sphy)
+{
+       void __iomem *regs = sphy->regs;
+       u32 phyclk = sphy->ref_clk_freq;
+       u32 phyhost;
+       u32 phyotg;
+       u32 phyhsic;
+       u32 ehcictrl;
+       u32 ohcictrl;
+
+       /*
+        * phy_usage helps in keeping usage count for phy
+        * so that the first consumer enabling the phy is also
+        * the last consumer to disable it.
+        */
+
+       atomic_inc(&sphy->phy_usage);
+
+       if (exynos5_phyhost_is_on(regs)) {
+               dev_info(sphy->dev, "Already power on PHY\n");
+               return;
+       }
+
+       /* Host configuration */
+       phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
+
+       /* phy reference clock configuration */
+       phyhost &= ~HOST_CTRL0_FSEL_MASK;
+       phyhost |= HOST_CTRL0_FSEL(phyclk);
+
+       /* host phy reset */
+       phyhost &= ~(HOST_CTRL0_PHYSWRST |
+                       HOST_CTRL0_PHYSWRSTALL |
+                       HOST_CTRL0_SIDDQ |
+                       /* Enable normal mode of operation */
+                       HOST_CTRL0_FORCESUSPEND |
+                       HOST_CTRL0_FORCESLEEP);
+
+       /* Link reset */
+       phyhost |= (HOST_CTRL0_LINKSWRST |
+                       HOST_CTRL0_UTMISWRST |
+                       /* COMMON Block configuration during suspend */
+                       HOST_CTRL0_COMMONON_N);
+       writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
+       udelay(10);
+       phyhost &= ~(HOST_CTRL0_LINKSWRST |
+                       HOST_CTRL0_UTMISWRST);
+       writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
+
+       /* OTG configuration */
+       phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
+
+       /* phy reference clock configuration */
+       phyotg &= ~OTG_SYS_FSEL_MASK;
+       phyotg |= OTG_SYS_FSEL(phyclk);
+
+       /* Enable normal mode of operation */
+       phyotg &= ~(OTG_SYS_FORCESUSPEND |
+                       OTG_SYS_SIDDQ_UOTG |
+                       OTG_SYS_FORCESLEEP |
+                       OTG_SYS_REFCLKSEL_MASK |
+                       /* COMMON Block configuration during suspend */
+                       OTG_SYS_COMMON_ON);
+
+       /* OTG phy & link reset */
+       phyotg |= (OTG_SYS_PHY0_SWRST |
+                       OTG_SYS_LINKSWRST_UOTG |
+                       OTG_SYS_PHYLINK_SWRESET |
+                       OTG_SYS_OTGDISABLE |
+                       /* Set phy refclk */
+                       OTG_SYS_REFCLKSEL_CLKCORE);
+
+       writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
+       udelay(10);
+       phyotg &= ~(OTG_SYS_PHY0_SWRST |
+                       OTG_SYS_LINKSWRST_UOTG |
+                       OTG_SYS_PHYLINK_SWRESET);
+       writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
+
+       /* HSIC phy configuration */
+       phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
+                       HSIC_CTRL_REFCLKSEL |
+                       HSIC_CTRL_PHYSWRST);
+       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
+       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
+       udelay(10);
+       phyhsic &= ~HSIC_CTRL_PHYSWRST;
+       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
+       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
+
+       udelay(80);
+
+       /* enable EHCI DMA burst */
+       ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL);
+       ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN |
+                               HOST_EHCICTRL_ENAINCR4 |
+                               HOST_EHCICTRL_ENAINCR8 |
+                               HOST_EHCICTRL_ENAINCR16);
+       writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL);
+
+       /* set ohci_suspend_on_n */
+       ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL);
+       ohcictrl |= HOST_OHCICTRL_SUSPLGCY;
+       writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL);
+}
+
+static void samsung_usb2phy_enable(struct samsung_usbphy *sphy)
+{
+       void __iomem *regs = sphy->regs;
+       u32 phypwr;
+       u32 phyclk;
+       u32 rstcon;
+
+       /* set clock frequency for PLL */
+       phyclk = sphy->ref_clk_freq;
+       phypwr = readl(regs + SAMSUNG_PHYPWR);
+       rstcon = readl(regs + SAMSUNG_RSTCON);
+
+       switch (sphy->drv_data->cpu_type) {
+       case TYPE_S3C64XX:
+               phyclk &= ~PHYCLK_COMMON_ON_N;
+               phypwr &= ~PHYPWR_NORMAL_MASK;
+               rstcon |= RSTCON_SWRST;
+               break;
+       case TYPE_EXYNOS4210:
+               phypwr &= ~PHYPWR_NORMAL_MASK_PHY0;
+               rstcon |= RSTCON_SWRST;
+       default:
+               break;
+       }
+
+       writel(phyclk, regs + SAMSUNG_PHYCLK);
+       /* Configure PHY0 for normal operation*/
+       writel(phypwr, regs + SAMSUNG_PHYPWR);
+       /* reset all ports of PHY and Link */
+       writel(rstcon, regs + SAMSUNG_RSTCON);
+       udelay(10);
+       rstcon &= ~RSTCON_SWRST;
+       writel(rstcon, regs + SAMSUNG_RSTCON);
+}
+
+static void samsung_exynos5_usb2phy_disable(struct samsung_usbphy *sphy)
+{
+       void __iomem *regs = sphy->regs;
+       u32 phyhost;
+       u32 phyotg;
+       u32 phyhsic;
+
+       if (atomic_dec_return(&sphy->phy_usage) > 0) {
+               dev_info(sphy->dev, "still being used\n");
+               return;
+       }
+
+       phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
+                       HSIC_CTRL_REFCLKSEL |
+                       HSIC_CTRL_SIDDQ |
+                       HSIC_CTRL_FORCESLEEP |
+                       HSIC_CTRL_FORCESUSPEND);
+       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
+       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
+
+       phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
+       phyhost |= (HOST_CTRL0_SIDDQ |
+                       HOST_CTRL0_FORCESUSPEND |
+                       HOST_CTRL0_FORCESLEEP |
+                       HOST_CTRL0_PHYSWRST |
+                       HOST_CTRL0_PHYSWRSTALL);
+       writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
+
+       phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
+       phyotg |= (OTG_SYS_FORCESUSPEND |
+                       OTG_SYS_SIDDQ_UOTG |
+                       OTG_SYS_FORCESLEEP);
+       writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
+}
+
+static void samsung_usb2phy_disable(struct samsung_usbphy *sphy)
+{
+       void __iomem *regs = sphy->regs;
+       u32 phypwr;
+
+       phypwr = readl(regs + SAMSUNG_PHYPWR);
+
+       switch (sphy->drv_data->cpu_type) {
+       case TYPE_S3C64XX:
+               phypwr |= PHYPWR_NORMAL_MASK;
+               break;
+       case TYPE_EXYNOS4210:
+               phypwr |= PHYPWR_NORMAL_MASK_PHY0;
+       default:
+               break;
+       }
+
+       /* Disable analog and otg block power */
+       writel(phypwr, regs + SAMSUNG_PHYPWR);
+}
+
+/*
+ * The function passed to the usb driver for phy initialization
+ */
+static int samsung_usb2phy_init(struct usb_phy *phy)
+{
+       struct samsung_usbphy *sphy;
+       struct usb_bus *host = NULL;
+       unsigned long flags;
+       int ret = 0;
+
+       sphy = phy_to_sphy(phy);
+
+       host = phy->otg->host;
+
+       /* Enable the phy clock */
+       ret = clk_prepare_enable(sphy->clk);
+       if (ret) {
+               dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+               return ret;
+       }
+
+       spin_lock_irqsave(&sphy->lock, flags);
+
+       if (host) {
+               /* setting default phy-type for USB 2.0 */
+               if (!strstr(dev_name(host->controller), "ehci") ||
+                               !strstr(dev_name(host->controller), "ohci"))
+                       samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
+       } else {
+               samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+       }
+
+       /* Disable phy isolation */
+       if (sphy->plat && sphy->plat->pmu_isolation)
+               sphy->plat->pmu_isolation(false);
+       else
+               samsung_usbphy_set_isolation(sphy, false);
+
+       /* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */
+       samsung_usbphy_cfg_sel(sphy);
+
+       /* Initialize usb phy registers */
+       if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
+               samsung_exynos5_usb2phy_enable(sphy);
+       else
+               samsung_usb2phy_enable(sphy);
+
+       spin_unlock_irqrestore(&sphy->lock, flags);
+
+       /* Disable the phy clock */
+       clk_disable_unprepare(sphy->clk);
+
+       return ret;
+}
+
+/*
+ * The function passed to the usb driver for phy shutdown
+ */
+static void samsung_usb2phy_shutdown(struct usb_phy *phy)
+{
+       struct samsung_usbphy *sphy;
+       struct usb_bus *host = NULL;
+       unsigned long flags;
+
+       sphy = phy_to_sphy(phy);
+
+       host = phy->otg->host;
+
+       if (clk_prepare_enable(sphy->clk)) {
+               dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+               return;
+       }
+
+       spin_lock_irqsave(&sphy->lock, flags);
+
+       if (host) {
+               /* setting default phy-type for USB 2.0 */
+               if (!strstr(dev_name(host->controller), "ehci") ||
+                               !strstr(dev_name(host->controller), "ohci"))
+                       samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
+       } else {
+               samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+       }
+
+       /* De-initialize usb phy registers */
+       if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
+               samsung_exynos5_usb2phy_disable(sphy);
+       else
+               samsung_usb2phy_disable(sphy);
+
+       /* Enable phy isolation */
+       if (sphy->plat && sphy->plat->pmu_isolation)
+               sphy->plat->pmu_isolation(true);
+       else
+               samsung_usbphy_set_isolation(sphy, true);
+
+       spin_unlock_irqrestore(&sphy->lock, flags);
+
+       clk_disable_unprepare(sphy->clk);
+}
+
+static int samsung_usb2phy_probe(struct platform_device *pdev)
+{
+       struct samsung_usbphy *sphy;
+       struct usb_otg *otg;
+       struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
+       const struct samsung_usbphy_drvdata *drv_data;
+       struct device *dev = &pdev->dev;
+       struct resource *phy_mem;
+       void __iomem    *phy_base;
+       struct clk *clk;
+       int ret;
+
+       phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!phy_mem) {
+               dev_err(dev, "%s: missing mem resource\n", __func__);
+               return -ENODEV;
+       }
+
+       phy_base = devm_ioremap_resource(dev, phy_mem);
+       if (IS_ERR(phy_base))
+               return PTR_ERR(phy_base);
+
+       sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
+       if (!sphy)
+               return -ENOMEM;
+
+       otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL);
+       if (!otg)
+               return -ENOMEM;
+
+       drv_data = samsung_usbphy_get_driver_data(pdev);
+
+       if (drv_data->cpu_type == TYPE_EXYNOS5250)
+               clk = devm_clk_get(dev, "usbhost");
+       else
+               clk = devm_clk_get(dev, "otg");
+
+       if (IS_ERR(clk)) {
+               dev_err(dev, "Failed to get otg clock\n");
+               return PTR_ERR(clk);
+       }
+
+       sphy->dev = dev;
+
+       if (dev->of_node) {
+               ret = samsung_usbphy_parse_dt(sphy);
+               if (ret < 0)
+                       return ret;
+       } else {
+               if (!pdata) {
+                       dev_err(dev, "no platform data specified\n");
+                       return -EINVAL;
+               }
+       }
+
+       sphy->plat              = pdata;
+       sphy->regs              = phy_base;
+       sphy->clk               = clk;
+       sphy->drv_data          = drv_data;
+       sphy->phy.dev           = sphy->dev;
+       sphy->phy.label         = "samsung-usb2phy";
+       sphy->phy.init          = samsung_usb2phy_init;
+       sphy->phy.shutdown      = samsung_usb2phy_shutdown;
+       sphy->ref_clk_freq      = samsung_usbphy_get_refclk_freq(sphy);
+
+       sphy->phy.otg           = otg;
+       sphy->phy.otg->phy      = &sphy->phy;
+       sphy->phy.otg->set_host = samsung_usbphy_set_host;
+
+       spin_lock_init(&sphy->lock);
+
+       platform_set_drvdata(pdev, sphy);
+
+       return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2);
+}
+
+static int samsung_usb2phy_remove(struct platform_device *pdev)
+{
+       struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
+
+       usb_remove_phy(&sphy->phy);
+
+       if (sphy->pmuregs)
+               iounmap(sphy->pmuregs);
+       if (sphy->sysreg)
+               iounmap(sphy->sysreg);
+
+       return 0;
+}
+
+static const struct samsung_usbphy_drvdata usb2phy_s3c64xx = {
+       .cpu_type               = TYPE_S3C64XX,
+       .devphy_en_mask         = S3C64XX_USBPHY_ENABLE,
+};
+
+static const struct samsung_usbphy_drvdata usb2phy_exynos4 = {
+       .cpu_type               = TYPE_EXYNOS4210,
+       .devphy_en_mask         = EXYNOS_USBPHY_ENABLE,
+       .hostphy_en_mask        = EXYNOS_USBPHY_ENABLE,
+};
+
+static struct samsung_usbphy_drvdata usb2phy_exynos5 = {
+       .cpu_type               = TYPE_EXYNOS5250,
+       .hostphy_en_mask        = EXYNOS_USBPHY_ENABLE,
+       .hostphy_reg_offset     = EXYNOS_USBHOST_PHY_CTRL_OFFSET,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id samsung_usbphy_dt_match[] = {
+       {
+               .compatible = "samsung,s3c64xx-usb2phy",
+               .data = &usb2phy_s3c64xx,
+       }, {
+               .compatible = "samsung,exynos4210-usb2phy",
+               .data = &usb2phy_exynos4,
+       }, {
+               .compatible = "samsung,exynos5250-usb2phy",
+               .data = &usb2phy_exynos5
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
+#endif
+
+static struct platform_device_id samsung_usbphy_driver_ids[] = {
+       {
+               .name           = "s3c64xx-usb2phy",
+               .driver_data    = (unsigned long)&usb2phy_s3c64xx,
+       }, {
+               .name           = "exynos4210-usb2phy",
+               .driver_data    = (unsigned long)&usb2phy_exynos4,
+       }, {
+               .name           = "exynos5250-usb2phy",
+               .driver_data    = (unsigned long)&usb2phy_exynos5,
+       },
+       {},
+};
+
+MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
+
+static struct platform_driver samsung_usb2phy_driver = {
+       .probe          = samsung_usb2phy_probe,
+       .remove         = samsung_usb2phy_remove,
+       .id_table       = samsung_usbphy_driver_ids,
+       .driver         = {
+               .name   = "samsung-usb2phy",
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(samsung_usbphy_dt_match),
+       },
+};
+
+module_platform_driver(samsung_usb2phy_driver);
+
+MODULE_DESCRIPTION("Samsung USB 2.0 phy controller");
+MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:samsung-usb2phy");
diff --git a/drivers/usb/phy/phy-samsung-usb3.c b/drivers/usb/phy/phy-samsung-usb3.c
new file mode 100644 (file)
index 0000000..133f3d0
--- /dev/null
@@ -0,0 +1,347 @@
+/* linux/drivers/usb/phy/phy-samsung-usb3.c
+ *
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com
+ *
+ * Author: Vivek Gautam <gautam.vivek@samsung.com>
+ *
+ * Samsung USB 3.0 PHY transceiver; talks to DWC3 controller.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This 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 <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/usb/samsung_usb_phy.h>
+#include <linux/platform_data/samsung-usbphy.h>
+
+#include "phy-samsung-usb.h"
+
+/*
+ * Sets the phy clk as EXTREFCLK (XXTI) which is internal clock from clock core.
+ */
+static u32 samsung_usb3phy_set_refclk(struct samsung_usbphy *sphy)
+{
+       u32 reg;
+       u32 refclk;
+
+       refclk = sphy->ref_clk_freq;
+
+       reg = PHYCLKRST_REFCLKSEL_EXT_REFCLK |
+               PHYCLKRST_FSEL(refclk);
+
+       switch (refclk) {
+       case FSEL_CLKSEL_50M:
+               reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
+                       PHYCLKRST_SSC_REFCLKSEL(0x00));
+               break;
+       case FSEL_CLKSEL_20M:
+               reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF |
+                       PHYCLKRST_SSC_REFCLKSEL(0x00));
+               break;
+       case FSEL_CLKSEL_19200K:
+               reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF |
+                       PHYCLKRST_SSC_REFCLKSEL(0x88));
+               break;
+       case FSEL_CLKSEL_24M:
+       default:
+               reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF |
+                       PHYCLKRST_SSC_REFCLKSEL(0x88));
+               break;
+       }
+
+       return reg;
+}
+
+static int samsung_exynos5_usb3phy_enable(struct samsung_usbphy *sphy)
+{
+       void __iomem *regs = sphy->regs;
+       u32 phyparam0;
+       u32 phyparam1;
+       u32 linksystem;
+       u32 phybatchg;
+       u32 phytest;
+       u32 phyclkrst;
+
+       /* Reset USB 3.0 PHY */
+       writel(0x0, regs + EXYNOS5_DRD_PHYREG0);
+
+       phyparam0 = readl(regs + EXYNOS5_DRD_PHYPARAM0);
+       /* Select PHY CLK source */
+       phyparam0 &= ~PHYPARAM0_REF_USE_PAD;
+       /* Set Loss-of-Signal Detector sensitivity */
+       phyparam0 &= ~PHYPARAM0_REF_LOSLEVEL_MASK;
+       phyparam0 |= PHYPARAM0_REF_LOSLEVEL;
+       writel(phyparam0, regs + EXYNOS5_DRD_PHYPARAM0);
+
+       writel(0x0, regs + EXYNOS5_DRD_PHYRESUME);
+
+       /*
+        * Setting the Frame length Adj value[6:1] to default 0x20
+        * See xHCI 1.0 spec, 5.2.4
+        */
+       linksystem = LINKSYSTEM_XHCI_VERSION_CONTROL |
+                       LINKSYSTEM_FLADJ(0x20);
+       writel(linksystem, regs + EXYNOS5_DRD_LINKSYSTEM);
+
+       phyparam1 = readl(regs + EXYNOS5_DRD_PHYPARAM1);
+       /* Set Tx De-Emphasis level */
+       phyparam1 &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
+       phyparam1 |= PHYPARAM1_PCS_TXDEEMPH;
+       writel(phyparam1, regs + EXYNOS5_DRD_PHYPARAM1);
+
+       phybatchg = readl(regs + EXYNOS5_DRD_PHYBATCHG);
+       phybatchg |= PHYBATCHG_UTMI_CLKSEL;
+       writel(phybatchg, regs + EXYNOS5_DRD_PHYBATCHG);
+
+       /* PHYTEST POWERDOWN Control */
+       phytest = readl(regs + EXYNOS5_DRD_PHYTEST);
+       phytest &= ~(PHYTEST_POWERDOWN_SSP |
+                       PHYTEST_POWERDOWN_HSP);
+       writel(phytest, regs + EXYNOS5_DRD_PHYTEST);
+
+       /* UTMI Power Control */
+       writel(PHYUTMI_OTGDISABLE, regs + EXYNOS5_DRD_PHYUTMI);
+
+       phyclkrst = samsung_usb3phy_set_refclk(sphy);
+
+       phyclkrst |= PHYCLKRST_PORTRESET |
+                       /* Digital power supply in normal operating mode */
+                       PHYCLKRST_RETENABLEN |
+                       /* Enable ref clock for SS function */
+                       PHYCLKRST_REF_SSP_EN |
+                       /* Enable spread spectrum */
+                       PHYCLKRST_SSC_EN |
+                       /* Power down HS Bias and PLL blocks in suspend mode */
+                       PHYCLKRST_COMMONONN;
+
+       writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST);
+
+       udelay(10);
+
+       phyclkrst &= ~(PHYCLKRST_PORTRESET);
+       writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST);
+
+       return 0;
+}
+
+static void samsung_exynos5_usb3phy_disable(struct samsung_usbphy *sphy)
+{
+       u32 phyutmi;
+       u32 phyclkrst;
+       u32 phytest;
+       void __iomem *regs = sphy->regs;
+
+       phyutmi = PHYUTMI_OTGDISABLE |
+                       PHYUTMI_FORCESUSPEND |
+                       PHYUTMI_FORCESLEEP;
+       writel(phyutmi, regs + EXYNOS5_DRD_PHYUTMI);
+
+       /* Resetting the PHYCLKRST enable bits to reduce leakage current */
+       phyclkrst = readl(regs + EXYNOS5_DRD_PHYCLKRST);
+       phyclkrst &= ~(PHYCLKRST_REF_SSP_EN |
+                       PHYCLKRST_SSC_EN |
+                       PHYCLKRST_COMMONONN);
+       writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST);
+
+       /* Control PHYTEST to remove leakage current */
+       phytest = readl(regs + EXYNOS5_DRD_PHYTEST);
+       phytest |= (PHYTEST_POWERDOWN_SSP |
+                       PHYTEST_POWERDOWN_HSP);
+       writel(phytest, regs + EXYNOS5_DRD_PHYTEST);
+}
+
+static int samsung_usb3phy_init(struct usb_phy *phy)
+{
+       struct samsung_usbphy *sphy;
+       unsigned long flags;
+       int ret = 0;
+
+       sphy = phy_to_sphy(phy);
+
+       /* Enable the phy clock */
+       ret = clk_prepare_enable(sphy->clk);
+       if (ret) {
+               dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+               return ret;
+       }
+
+       spin_lock_irqsave(&sphy->lock, flags);
+
+       /* setting default phy-type for USB 3.0 */
+       samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+
+       /* Disable phy isolation */
+       samsung_usbphy_set_isolation(sphy, false);
+
+       /* Initialize usb phy registers */
+       samsung_exynos5_usb3phy_enable(sphy);
+
+       spin_unlock_irqrestore(&sphy->lock, flags);
+
+       /* Disable the phy clock */
+       clk_disable_unprepare(sphy->clk);
+
+       return ret;
+}
+
+/*
+ * The function passed to the usb driver for phy shutdown
+ */
+static void samsung_usb3phy_shutdown(struct usb_phy *phy)
+{
+       struct samsung_usbphy *sphy;
+       unsigned long flags;
+
+       sphy = phy_to_sphy(phy);
+
+       if (clk_prepare_enable(sphy->clk)) {
+               dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+               return;
+       }
+
+       spin_lock_irqsave(&sphy->lock, flags);
+
+       /* setting default phy-type for USB 3.0 */
+       samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+
+       /* De-initialize usb phy registers */
+       samsung_exynos5_usb3phy_disable(sphy);
+
+       /* Enable phy isolation */
+       samsung_usbphy_set_isolation(sphy, true);
+
+       spin_unlock_irqrestore(&sphy->lock, flags);
+
+       clk_disable_unprepare(sphy->clk);
+}
+
+static int samsung_usb3phy_probe(struct platform_device *pdev)
+{
+       struct samsung_usbphy *sphy;
+       struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
+       struct device *dev = &pdev->dev;
+       struct resource *phy_mem;
+       void __iomem    *phy_base;
+       struct clk *clk;
+       int ret;
+
+       phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!phy_mem) {
+               dev_err(dev, "%s: missing mem resource\n", __func__);
+               return -ENODEV;
+       }
+
+       phy_base = devm_ioremap_resource(dev, phy_mem);
+       if (IS_ERR(phy_base))
+               return PTR_ERR(phy_base);
+
+       sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
+       if (!sphy)
+               return -ENOMEM;
+
+       clk = devm_clk_get(dev, "usbdrd30");
+       if (IS_ERR(clk)) {
+               dev_err(dev, "Failed to get device clock\n");
+               return PTR_ERR(clk);
+       }
+
+       sphy->dev = dev;
+
+       if (dev->of_node) {
+               ret = samsung_usbphy_parse_dt(sphy);
+               if (ret < 0)
+                       return ret;
+       } else {
+               if (!pdata) {
+                       dev_err(dev, "no platform data specified\n");
+                       return -EINVAL;
+               }
+       }
+
+       sphy->plat              = pdata;
+       sphy->regs              = phy_base;
+       sphy->clk               = clk;
+       sphy->phy.dev           = sphy->dev;
+       sphy->phy.label         = "samsung-usb3phy";
+       sphy->phy.init          = samsung_usb3phy_init;
+       sphy->phy.shutdown      = samsung_usb3phy_shutdown;
+       sphy->drv_data          = samsung_usbphy_get_driver_data(pdev);
+       sphy->ref_clk_freq      = samsung_usbphy_get_refclk_freq(sphy);
+
+       spin_lock_init(&sphy->lock);
+
+       platform_set_drvdata(pdev, sphy);
+
+       return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB3);
+}
+
+static int samsung_usb3phy_remove(struct platform_device *pdev)
+{
+       struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
+
+       usb_remove_phy(&sphy->phy);
+
+       if (sphy->pmuregs)
+               iounmap(sphy->pmuregs);
+       if (sphy->sysreg)
+               iounmap(sphy->sysreg);
+
+       return 0;
+}
+
+static struct samsung_usbphy_drvdata usb3phy_exynos5 = {
+       .cpu_type               = TYPE_EXYNOS5250,
+       .devphy_en_mask         = EXYNOS_USBPHY_ENABLE,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id samsung_usbphy_dt_match[] = {
+       {
+               .compatible = "samsung,exynos5250-usb3phy",
+               .data = &usb3phy_exynos5
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
+#endif
+
+static struct platform_device_id samsung_usbphy_driver_ids[] = {
+       {
+               .name           = "exynos5250-usb3phy",
+               .driver_data    = (unsigned long)&usb3phy_exynos5,
+       },
+       {},
+};
+
+MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
+
+static struct platform_driver samsung_usb3phy_driver = {
+       .probe          = samsung_usb3phy_probe,
+       .remove         = samsung_usb3phy_remove,
+       .id_table       = samsung_usbphy_driver_ids,
+       .driver         = {
+               .name   = "samsung-usb3phy",
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(samsung_usbphy_dt_match),
+       },
+};
+
+module_platform_driver(samsung_usb3phy_driver);
+
+MODULE_DESCRIPTION("Samsung USB 3.0 phy controller");
+MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:samsung-usb3phy");
similarity index 98%
rename from drivers/usb/phy/tegra_usb_phy.c
rename to drivers/usb/phy/phy-tegra-usb.c
index 5487d38481af38dead7dee1ed9b7cbc839a7ad22..17d811292f3a9316232569af657993d811173079 100644 (file)
@@ -299,7 +299,7 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
                val &= ~USB_SUSP_SET;
                writel(val, base + USB_SUSP_CTRL);
        } else
-               tegra_ehci_set_phcd(&phy->u_phy, true);
+               phy->set_phcd(&phy->u_phy, true);
 
        if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0)
                pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
@@ -321,7 +321,7 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
                val &= ~USB_SUSP_CLR;
                writel(val, base + USB_SUSP_CTRL);
        } else
-               tegra_ehci_set_phcd(&phy->u_phy, false);
+               phy->set_phcd(&phy->u_phy, false);
 
        if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
                                                     USB_PHY_CLK_VALID))
@@ -444,7 +444,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
        utmi_phy_clk_enable(phy);
 
        if (!phy->is_legacy_phy)
-               tegra_ehci_set_pts(&phy->u_phy, 0);
+               phy->set_pts(&phy->u_phy, 0);
 
        return 0;
 }
@@ -688,7 +688,10 @@ static int tegra_usb_phy_suspend(struct usb_phy *x, int suspend)
 }
 
 struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
-       void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode)
+       void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode,
+       void (*set_pts)(struct usb_phy *x, u8 pts_val),
+       void (*set_phcd)(struct usb_phy *x, bool enable))
+
 {
        struct tegra_usb_phy *phy;
        unsigned long parent_rate;
@@ -707,6 +710,8 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
        phy->dev = dev;
        phy->is_legacy_phy =
                of_property_read_bool(np, "nvidia,has-legacy-mode");
+       phy->set_pts = set_pts;
+       phy->set_phcd = set_phcd;
        err = of_property_match_string(np, "phy_type", "ulpi");
        if (err < 0)
                phy->is_ulpi_phy = false;
similarity index 84%
rename from drivers/usb/otg/twl4030-usb.c
rename to drivers/usb/phy/phy-twl4030-usb.c
index a994715a3101978a916bea3f4d3d1e1c38d72f7d..8f78d2d40722ebb2412415a33d369666a3c9167a 100644 (file)
@@ -163,6 +163,8 @@ struct twl4030_usb {
        bool                    vbus_supplied;
        u8                      asleep;
        bool                    irq_enabled;
+
+       struct delayed_work     id_workaround_work;
 };
 
 /* internal define on top of container_of */
@@ -246,6 +248,25 @@ twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits)
 
 /*-------------------------------------------------------------------------*/
 
+static bool twl4030_is_driving_vbus(struct twl4030_usb *twl)
+{
+       int ret;
+
+       ret = twl4030_usb_read(twl, PHY_CLK_CTRL_STS);
+       if (ret < 0 || !(ret & PHY_DPLL_CLK))
+               /*
+                * if clocks are off, registers are not updated,
+                * but we can assume we don't drive VBUS in this case
+                */
+               return false;
+
+       ret = twl4030_usb_read(twl, ULPI_OTG_CTRL);
+       if (ret < 0)
+               return false;
+
+       return (ret & (ULPI_OTG_DRVVBUS | ULPI_OTG_CHRGVBUS)) ? true : false;
+}
+
 static enum omap_musb_vbus_id_status
        twl4030_usb_linkstat(struct twl4030_usb *twl)
 {
@@ -268,13 +289,19 @@ static enum omap_musb_vbus_id_status
        if (status < 0)
                dev_err(twl->dev, "USB link status err %d\n", status);
        else if (status & (BIT(7) | BIT(2))) {
-               if (status & (BIT(7)))
-                        twl->vbus_supplied = true;
+               if (status & BIT(7)) {
+                       if (twl4030_is_driving_vbus(twl))
+                               status &= ~BIT(7);
+                       else
+                               twl->vbus_supplied = true;
+               }
 
                if (status & BIT(2))
                        linkstat = OMAP_MUSB_ID_GROUND;
-               else
+               else if (status & BIT(7))
                        linkstat = OMAP_MUSB_VBUS_VALID;
+               else
+                       linkstat = OMAP_MUSB_VBUS_OFF;
        } else {
                if (twl->linkstat != OMAP_MUSB_UNKNOWN)
                        linkstat = OMAP_MUSB_VBUS_OFF;
@@ -287,10 +314,6 @@ static enum omap_musb_vbus_id_status
         * are registered, and that both are active...
         */
 
-       spin_lock_irq(&twl->lock);
-       twl->linkstat = linkstat;
-       spin_unlock_irq(&twl->lock);
-
        return linkstat;
 }
 
@@ -361,9 +384,17 @@ static void __twl4030_phy_power(struct twl4030_usb *twl, int on)
 
 static void twl4030_phy_power(struct twl4030_usb *twl, int on)
 {
+       int ret;
+
        if (on) {
-               regulator_enable(twl->usb3v1);
-               regulator_enable(twl->usb1v8);
+               ret = regulator_enable(twl->usb3v1);
+               if (ret)
+                       dev_err(twl->dev, "Failed to enable usb3v1\n");
+
+               ret = regulator_enable(twl->usb1v8);
+               if (ret)
+                       dev_err(twl->dev, "Failed to enable usb1v8\n");
+
                /*
                 * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP
                 * in twl4030) resets the VUSB_DEDICATED2 register. This reset
@@ -372,7 +403,11 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on)
                 * is re-activated. This ensures that VUSB3V1 is really active.
                 */
                twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);
-               regulator_enable(twl->usb1v5);
+
+               ret = regulator_enable(twl->usb1v5);
+               if (ret)
+                       dev_err(twl->dev, "Failed to enable usb1v5\n");
+
                __twl4030_phy_power(twl, 1);
                twl4030_usb_write(twl, PHY_CLK_CTRL,
                                  twl4030_usb_read(twl, PHY_CLK_CTRL) |
@@ -412,6 +447,16 @@ static void twl4030_phy_resume(struct twl4030_usb *twl)
        __twl4030_phy_resume(twl);
        twl->asleep = 0;
        dev_dbg(twl->dev, "%s\n", __func__);
+
+       /*
+        * XXX When VBUS gets driven after musb goes to A mode,
+        * ID_PRES related interrupts no longer arrive, why?
+        * Register itself is updated fine though, so we must poll.
+        */
+       if (twl->linkstat == OMAP_MUSB_ID_GROUND) {
+               cancel_delayed_work(&twl->id_workaround_work);
+               schedule_delayed_work(&twl->id_workaround_work, HZ);
+       }
 }
 
 static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
@@ -432,7 +477,7 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
        /* Initialize 3.1V regulator */
        twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
 
-       twl->usb3v1 = regulator_get(twl->dev, "usb3v1");
+       twl->usb3v1 = devm_regulator_get(twl->dev, "usb3v1");
        if (IS_ERR(twl->usb3v1))
                return -ENODEV;
 
@@ -441,18 +486,18 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
        /* Initialize 1.5V regulator */
        twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);
 
-       twl->usb1v5 = regulator_get(twl->dev, "usb1v5");
+       twl->usb1v5 = devm_regulator_get(twl->dev, "usb1v5");
        if (IS_ERR(twl->usb1v5))
-               goto fail1;
+               return -ENODEV;
 
        twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE);
 
        /* Initialize 1.8V regulator */
        twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP);
 
-       twl->usb1v8 = regulator_get(twl->dev, "usb1v8");
+       twl->usb1v8 = devm_regulator_get(twl->dev, "usb1v8");
        if (IS_ERR(twl->usb1v8))
-               goto fail2;
+               return -ENODEV;
 
        twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE);
 
@@ -461,14 +506,6 @@ static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
                         TWL4030_PM_MASTER_PROTECT_KEY);
 
        return 0;
-
-fail2:
-       regulator_put(twl->usb1v5);
-       twl->usb1v5 = NULL;
-fail1:
-       regulator_put(twl->usb3v1);
-       twl->usb3v1 = NULL;
-       return -ENODEV;
 }
 
 static ssize_t twl4030_usb_vbus_show(struct device *dev,
@@ -491,9 +528,18 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
 {
        struct twl4030_usb *twl = _twl;
        enum omap_musb_vbus_id_status status;
+       bool status_changed = false;
 
        status = twl4030_usb_linkstat(twl);
-       if (status > 0) {
+
+       spin_lock_irq(&twl->lock);
+       if (status >= 0 && status != twl->linkstat) {
+               twl->linkstat = status;
+               status_changed = true;
+       }
+       spin_unlock_irq(&twl->lock);
+
+       if (status_changed) {
                /* FIXME add a set_power() method so that B-devices can
                 * configure the charger appropriately.  It's not always
                 * correct to consume VBUS power, and how much current to
@@ -505,37 +551,62 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
                 * USB_LINK_VBUS state.  musb_hdrc won't care until it
                 * starts to handle softconnect right.
                 */
-               if (status == OMAP_MUSB_VBUS_OFF ||
-                               status == OMAP_MUSB_ID_FLOAT)
-                       twl4030_phy_suspend(twl, 0);
-               else
-                       twl4030_phy_resume(twl);
-
-               omap_musb_mailbox(twl->linkstat);
+               omap_musb_mailbox(status);
        }
        sysfs_notify(&twl->dev->kobj, NULL, "vbus");
 
        return IRQ_HANDLED;
 }
 
-static void twl4030_usb_phy_init(struct twl4030_usb *twl)
+static void twl4030_id_workaround_work(struct work_struct *work)
 {
+       struct twl4030_usb *twl = container_of(work, struct twl4030_usb,
+               id_workaround_work.work);
        enum omap_musb_vbus_id_status status;
+       bool status_changed = false;
 
        status = twl4030_usb_linkstat(twl);
-       if (status > 0) {
-               if (status == OMAP_MUSB_VBUS_OFF ||
-                               status == OMAP_MUSB_ID_FLOAT) {
-                       __twl4030_phy_power(twl, 0);
-                       twl->asleep = 1;
-               } else {
-                       __twl4030_phy_resume(twl);
-                       twl->asleep = 0;
-               }
 
-               omap_musb_mailbox(twl->linkstat);
+       spin_lock_irq(&twl->lock);
+       if (status >= 0 && status != twl->linkstat) {
+               twl->linkstat = status;
+               status_changed = true;
+       }
+       spin_unlock_irq(&twl->lock);
+
+       if (status_changed) {
+               dev_dbg(twl->dev, "handle missing status change to %d\n",
+                               status);
+               omap_musb_mailbox(status);
        }
+
+       /* don't schedule during sleep - irq works right then */
+       if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) {
+               cancel_delayed_work(&twl->id_workaround_work);
+               schedule_delayed_work(&twl->id_workaround_work, HZ);
+       }
+}
+
+static int twl4030_usb_phy_init(struct usb_phy *phy)
+{
+       struct twl4030_usb *twl = phy_to_twl(phy);
+       enum omap_musb_vbus_id_status status;
+
+       /*
+        * Start in sleep state, we'll get called through set_suspend()
+        * callback when musb is runtime resumed and it's time to start.
+        */
+       __twl4030_phy_power(twl, 0);
+       twl->asleep = 1;
+
+       status = twl4030_usb_linkstat(twl);
+       twl->linkstat = status;
+
+       if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID)
+               omap_musb_mailbox(twl->linkstat);
+
        sysfs_notify(&twl->dev->kobj, NULL, "vbus");
+       return 0;
 }
 
 static int twl4030_set_suspend(struct usb_phy *x, int suspend)
@@ -612,6 +683,7 @@ static int twl4030_usb_probe(struct platform_device *pdev)
        twl->phy.otg            = otg;
        twl->phy.type           = USB_PHY_TYPE_USB2;
        twl->phy.set_suspend    = twl4030_set_suspend;
+       twl->phy.init           = twl4030_usb_phy_init;
 
        otg->phy                = &twl->phy;
        otg->set_host           = twl4030_set_host;
@@ -620,6 +692,8 @@ static int twl4030_usb_probe(struct platform_device *pdev)
        /* init spinlock for workqueue */
        spin_lock_init(&twl->lock);
 
+       INIT_DELAYED_WORK(&twl->id_workaround_work, twl4030_id_workaround_work);
+
        err = twl4030_usb_ldo_init(twl);
        if (err) {
                dev_err(&pdev->dev, "ldo init failed\n");
@@ -640,30 +714,25 @@ static int twl4030_usb_probe(struct platform_device *pdev)
         * need both handles, otherwise just one suffices.
         */
        twl->irq_enabled = true;
-       status = request_threaded_irq(twl->irq, NULL, twl4030_usb_irq,
-                       IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
-                       IRQF_ONESHOT, "twl4030_usb", twl);
+       status = devm_request_threaded_irq(twl->dev, twl->irq, NULL,
+                       twl4030_usb_irq, IRQF_TRIGGER_FALLING |
+                       IRQF_TRIGGER_RISING | IRQF_ONESHOT, "twl4030_usb", twl);
        if (status < 0) {
                dev_dbg(&pdev->dev, "can't get IRQ %d, err %d\n",
                        twl->irq, status);
                return status;
        }
 
-       /* Power down phy or make it work according to
-        * current link state.
-        */
-       twl4030_usb_phy_init(twl);
-
        dev_info(&pdev->dev, "Initialized TWL4030 USB module\n");
        return 0;
 }
 
-static int __exit twl4030_usb_remove(struct platform_device *pdev)
+static int twl4030_usb_remove(struct platform_device *pdev)
 {
        struct twl4030_usb *twl = platform_get_drvdata(pdev);
        int val;
 
-       free_irq(twl->irq, twl);
+       cancel_delayed_work(&twl->id_workaround_work);
        device_remove_file(twl->dev, &dev_attr_vbus);
 
        /* set transceiver mode to power on defaults */
@@ -685,9 +754,6 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev)
 
        if (!twl->asleep)
                twl4030_phy_power(twl, 0);
-       regulator_put(twl->usb1v5);
-       regulator_put(twl->usb1v8);
-       regulator_put(twl->usb3v1);
 
        return 0;
 }
@@ -702,7 +768,7 @@ MODULE_DEVICE_TABLE(of, twl4030_usb_id_table);
 
 static struct platform_driver twl4030_usb_driver = {
        .probe          = twl4030_usb_probe,
-       .remove         = __exit_p(twl4030_usb_remove),
+       .remove         = twl4030_usb_remove,
        .driver         = {
                .name   = "twl4030_usb",
                .owner  = THIS_MODULE,
similarity index 97%
rename from drivers/usb/otg/twl6030-usb.c
rename to drivers/usb/phy/phy-twl6030-usb.c
index 8cd6cf49bdbd12c987f871193e58be3f3df77853..9de7ada90a8b9717d096e3fb9852015dc1199ed4 100644 (file)
@@ -211,6 +211,7 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
        struct twl6030_usb *twl = _twl;
        enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
        u8 vbus_state, hw_state;
+       int ret;
 
        hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
 
@@ -218,7 +219,10 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl)
                                                CONTROLLER_STAT1);
        if (!(hw_state & STS_USB_ID)) {
                if (vbus_state & VBUS_DET) {
-                       regulator_enable(twl->usb3v3);
+                       ret = regulator_enable(twl->usb3v3);
+                       if (ret)
+                               dev_err(twl->dev, "Failed to enable usb3v3\n");
+
                        twl->asleep = 1;
                        status = OMAP_MUSB_VBUS_VALID;
                        twl->linkstat = status;
@@ -245,12 +249,15 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl)
        struct twl6030_usb *twl = _twl;
        enum omap_musb_vbus_id_status status = OMAP_MUSB_UNKNOWN;
        u8 hw_state;
+       int ret;
 
        hw_state = twl6030_readb(twl, TWL6030_MODULE_ID0, STS_HW_CONDITIONS);
 
        if (hw_state & STS_USB_ID) {
+               ret = regulator_enable(twl->usb3v3);
+               if (ret)
+                       dev_err(twl->dev, "Failed to enable usb3v3\n");
 
-               regulator_enable(twl->usb3v3);
                twl->asleep = 1;
                twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_CLR);
                twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET);
@@ -393,7 +400,7 @@ static int twl6030_usb_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __exit twl6030_usb_remove(struct platform_device *pdev)
+static int twl6030_usb_remove(struct platform_device *pdev)
 {
        struct twl6030_usb *twl = platform_get_drvdata(pdev);
 
@@ -420,7 +427,7 @@ MODULE_DEVICE_TABLE(of, twl6030_usb_id_table);
 
 static struct platform_driver twl6030_usb_driver = {
        .probe          = twl6030_usb_probe,
-       .remove         = __exit_p(twl6030_usb_remove),
+       .remove         = twl6030_usb_remove,
        .driver         = {
                .name   = "twl6030_usb",
                .owner  = THIS_MODULE,
similarity index 88%
rename from drivers/usb/otg/otg.c
rename to drivers/usb/phy/phy.c
index 2bd03d261a50f4f8f8df3583dcc57961c3b8ec34..a9984c700d2c428fd2e771a1d175c12009f94475 100644 (file)
@@ -1,14 +1,13 @@
 /*
- * otg.c -- USB OTG utility code
+ * phy.c -- USB phy handling
  *
- * Copyright (C) 2004 Texas Instruments
+ * Copyright (C) 2004-2013 Texas Instruments
  *
  * 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.
  */
-
 #include <linux/kernel.h>
 #include <linux/export.h>
 #include <linux/err.h>
@@ -17,7 +16,7 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 
-#include <linux/usb/otg.h>
+#include <linux/usb/phy.h>
 
 static LIST_HEAD(phy_list);
 static LIST_HEAD(phy_bind_list);
@@ -110,7 +109,7 @@ struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type)
 
        return phy;
 }
-EXPORT_SYMBOL(devm_usb_get_phy);
+EXPORT_SYMBOL_GPL(devm_usb_get_phy);
 
 /**
  * usb_get_phy - find the USB PHY
@@ -143,7 +142,7 @@ err0:
 
        return phy;
 }
-EXPORT_SYMBOL(usb_get_phy);
+EXPORT_SYMBOL_GPL(usb_get_phy);
 
  /**
  * devm_usb_get_phy_by_phandle - find the USB PHY by phandle
@@ -207,7 +206,7 @@ err0:
 
        return phy;
 }
-EXPORT_SYMBOL(devm_usb_get_phy_by_phandle);
+EXPORT_SYMBOL_GPL(devm_usb_get_phy_by_phandle);
 
 /**
  * usb_get_phy_dev - find the USB PHY
@@ -240,7 +239,7 @@ err0:
 
        return phy;
 }
-EXPORT_SYMBOL(usb_get_phy_dev);
+EXPORT_SYMBOL_GPL(usb_get_phy_dev);
 
 /**
  * devm_usb_get_phy_dev - find the USB PHY using device ptr and index
@@ -270,7 +269,7 @@ struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index)
 
        return phy;
 }
-EXPORT_SYMBOL(devm_usb_get_phy_dev);
+EXPORT_SYMBOL_GPL(devm_usb_get_phy_dev);
 
 /**
  * devm_usb_put_phy - release the USB PHY
@@ -289,7 +288,7 @@ void devm_usb_put_phy(struct device *dev, struct usb_phy *phy)
        r = devres_destroy(dev, devm_usb_phy_release, devm_usb_phy_match, phy);
        dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
 }
-EXPORT_SYMBOL(devm_usb_put_phy);
+EXPORT_SYMBOL_GPL(devm_usb_put_phy);
 
 /**
  * usb_put_phy - release the USB PHY
@@ -308,7 +307,7 @@ void usb_put_phy(struct usb_phy *x)
                module_put(owner);
        }
 }
-EXPORT_SYMBOL(usb_put_phy);
+EXPORT_SYMBOL_GPL(usb_put_phy);
 
 /**
  * usb_add_phy - declare the USB PHY
@@ -348,7 +347,7 @@ out:
        spin_unlock_irqrestore(&phy_lock, flags);
        return ret;
 }
-EXPORT_SYMBOL(usb_add_phy);
+EXPORT_SYMBOL_GPL(usb_add_phy);
 
 /**
  * usb_add_phy_dev - declare the USB PHY
@@ -378,7 +377,7 @@ int usb_add_phy_dev(struct usb_phy *x)
        spin_unlock_irqrestore(&phy_lock, flags);
        return 0;
 }
-EXPORT_SYMBOL(usb_add_phy_dev);
+EXPORT_SYMBOL_GPL(usb_add_phy_dev);
 
 /**
  * usb_remove_phy - remove the OTG PHY
@@ -400,7 +399,7 @@ void usb_remove_phy(struct usb_phy *x)
        }
        spin_unlock_irqrestore(&phy_lock, flags);
 }
-EXPORT_SYMBOL(usb_remove_phy);
+EXPORT_SYMBOL_GPL(usb_remove_phy);
 
 /**
  * usb_bind_phy - bind the phy and the controller that uses the phy
@@ -414,7 +413,7 @@ EXPORT_SYMBOL(usb_remove_phy);
  *
  * To be used by platform specific initialization code.
  */
-int __init usb_bind_phy(const char *dev_name, u8 index,
+int usb_bind_phy(const char *dev_name, u8 index,
                                const char *phy_dev_name)
 {
        struct usb_phy_bind *phy_bind;
@@ -437,38 +436,3 @@ int __init usb_bind_phy(const char *dev_name, u8 index,
        return 0;
 }
 EXPORT_SYMBOL_GPL(usb_bind_phy);
-
-const char *otg_state_string(enum usb_otg_state state)
-{
-       switch (state) {
-       case OTG_STATE_A_IDLE:
-               return "a_idle";
-       case OTG_STATE_A_WAIT_VRISE:
-               return "a_wait_vrise";
-       case OTG_STATE_A_WAIT_BCON:
-               return "a_wait_bcon";
-       case OTG_STATE_A_HOST:
-               return "a_host";
-       case OTG_STATE_A_SUSPEND:
-               return "a_suspend";
-       case OTG_STATE_A_PERIPHERAL:
-               return "a_peripheral";
-       case OTG_STATE_A_WAIT_VFALL:
-               return "a_wait_vfall";
-       case OTG_STATE_A_VBUS_ERR:
-               return "a_vbus_err";
-       case OTG_STATE_B_IDLE:
-               return "b_idle";
-       case OTG_STATE_B_SRP_INIT:
-               return "b_srp_init";
-       case OTG_STATE_B_PERIPHERAL:
-               return "b_peripheral";
-       case OTG_STATE_B_WAIT_ACON:
-               return "b_wait_acon";
-       case OTG_STATE_B_HOST:
-               return "b_host";
-       default:
-               return "UNDEFINED";
-       }
-}
-EXPORT_SYMBOL(otg_state_string);
diff --git a/drivers/usb/phy/samsung-usbphy.c b/drivers/usb/phy/samsung-usbphy.c
deleted file mode 100644 (file)
index 967101e..0000000
+++ /dev/null
@@ -1,928 +0,0 @@
-/* linux/drivers/usb/phy/samsung-usbphy.c
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *              http://www.samsung.com
- *
- * Author: Praveen Paneri <p.paneri@samsung.com>
- *
- * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
- * OHCI-EXYNOS controllers.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This 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 <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/usb/otg.h>
-#include <linux/usb/samsung_usb_phy.h>
-#include <linux/platform_data/samsung-usbphy.h>
-
-/* Register definitions */
-
-#define SAMSUNG_PHYPWR                         (0x00)
-
-#define PHYPWR_NORMAL_MASK                     (0x19 << 0)
-#define PHYPWR_OTG_DISABLE                     (0x1 << 4)
-#define PHYPWR_ANALOG_POWERDOWN                        (0x1 << 3)
-#define PHYPWR_FORCE_SUSPEND                   (0x1 << 1)
-/* For Exynos4 */
-#define PHYPWR_NORMAL_MASK_PHY0                        (0x39 << 0)
-#define PHYPWR_SLEEP_PHY0                      (0x1 << 5)
-
-#define SAMSUNG_PHYCLK                         (0x04)
-
-#define PHYCLK_MODE_USB11                      (0x1 << 6)
-#define PHYCLK_EXT_OSC                         (0x1 << 5)
-#define PHYCLK_COMMON_ON_N                     (0x1 << 4)
-#define PHYCLK_ID_PULL                         (0x1 << 2)
-#define PHYCLK_CLKSEL_MASK                     (0x3 << 0)
-#define PHYCLK_CLKSEL_48M                      (0x0 << 0)
-#define PHYCLK_CLKSEL_12M                      (0x2 << 0)
-#define PHYCLK_CLKSEL_24M                      (0x3 << 0)
-
-#define SAMSUNG_RSTCON                         (0x08)
-
-#define RSTCON_PHYLINK_SWRST                   (0x1 << 2)
-#define RSTCON_HLINK_SWRST                     (0x1 << 1)
-#define RSTCON_SWRST                           (0x1 << 0)
-
-/* EXYNOS5 */
-#define EXYNOS5_PHY_HOST_CTRL0                 (0x00)
-
-#define HOST_CTRL0_PHYSWRSTALL                 (0x1 << 31)
-
-#define HOST_CTRL0_REFCLKSEL_MASK              (0x3 << 19)
-#define HOST_CTRL0_REFCLKSEL_XTAL              (0x0 << 19)
-#define HOST_CTRL0_REFCLKSEL_EXTL              (0x1 << 19)
-#define HOST_CTRL0_REFCLKSEL_CLKCORE           (0x2 << 19)
-
-#define HOST_CTRL0_FSEL_MASK                   (0x7 << 16)
-#define HOST_CTRL0_FSEL(_x)                    ((_x) << 16)
-
-#define FSEL_CLKSEL_50M                                (0x7)
-#define FSEL_CLKSEL_24M                                (0x5)
-#define FSEL_CLKSEL_20M                                (0x4)
-#define FSEL_CLKSEL_19200K                     (0x3)
-#define FSEL_CLKSEL_12M                                (0x2)
-#define FSEL_CLKSEL_10M                                (0x1)
-#define FSEL_CLKSEL_9600K                      (0x0)
-
-#define HOST_CTRL0_TESTBURNIN                  (0x1 << 11)
-#define HOST_CTRL0_RETENABLE                   (0x1 << 10)
-#define HOST_CTRL0_COMMONON_N                  (0x1 << 9)
-#define HOST_CTRL0_SIDDQ                       (0x1 << 6)
-#define HOST_CTRL0_FORCESLEEP                  (0x1 << 5)
-#define HOST_CTRL0_FORCESUSPEND                        (0x1 << 4)
-#define HOST_CTRL0_WORDINTERFACE               (0x1 << 3)
-#define HOST_CTRL0_UTMISWRST                   (0x1 << 2)
-#define HOST_CTRL0_LINKSWRST                   (0x1 << 1)
-#define HOST_CTRL0_PHYSWRST                    (0x1 << 0)
-
-#define EXYNOS5_PHY_HOST_TUNE0                 (0x04)
-
-#define EXYNOS5_PHY_HSIC_CTRL1                 (0x10)
-
-#define EXYNOS5_PHY_HSIC_TUNE1                 (0x14)
-
-#define EXYNOS5_PHY_HSIC_CTRL2                 (0x20)
-
-#define EXYNOS5_PHY_HSIC_TUNE2                 (0x24)
-
-#define HSIC_CTRL_REFCLKSEL_MASK               (0x3 << 23)
-#define HSIC_CTRL_REFCLKSEL                    (0x2 << 23)
-
-#define HSIC_CTRL_REFCLKDIV_MASK               (0x7f << 16)
-#define HSIC_CTRL_REFCLKDIV(_x)                        ((_x) << 16)
-#define HSIC_CTRL_REFCLKDIV_12                 (0x24 << 16)
-#define HSIC_CTRL_REFCLKDIV_15                 (0x1c << 16)
-#define HSIC_CTRL_REFCLKDIV_16                 (0x1a << 16)
-#define HSIC_CTRL_REFCLKDIV_19_2               (0x15 << 16)
-#define HSIC_CTRL_REFCLKDIV_20                 (0x14 << 16)
-
-#define HSIC_CTRL_SIDDQ                                (0x1 << 6)
-#define HSIC_CTRL_FORCESLEEP                   (0x1 << 5)
-#define HSIC_CTRL_FORCESUSPEND                 (0x1 << 4)
-#define HSIC_CTRL_WORDINTERFACE                        (0x1 << 3)
-#define HSIC_CTRL_UTMISWRST                    (0x1 << 2)
-#define HSIC_CTRL_PHYSWRST                     (0x1 << 0)
-
-#define EXYNOS5_PHY_HOST_EHCICTRL              (0x30)
-
-#define HOST_EHCICTRL_ENAINCRXALIGN            (0x1 << 29)
-#define HOST_EHCICTRL_ENAINCR4                 (0x1 << 28)
-#define HOST_EHCICTRL_ENAINCR8                 (0x1 << 27)
-#define HOST_EHCICTRL_ENAINCR16                        (0x1 << 26)
-
-#define EXYNOS5_PHY_HOST_OHCICTRL              (0x34)
-
-#define HOST_OHCICTRL_SUSPLGCY                 (0x1 << 3)
-#define HOST_OHCICTRL_APPSTARTCLK              (0x1 << 2)
-#define HOST_OHCICTRL_CNTSEL                   (0x1 << 1)
-#define HOST_OHCICTRL_CLKCKTRST                        (0x1 << 0)
-
-#define EXYNOS5_PHY_OTG_SYS                    (0x38)
-
-#define OTG_SYS_PHYLINK_SWRESET                        (0x1 << 14)
-#define OTG_SYS_LINKSWRST_UOTG                 (0x1 << 13)
-#define OTG_SYS_PHY0_SWRST                     (0x1 << 12)
-
-#define OTG_SYS_REFCLKSEL_MASK                 (0x3 << 9)
-#define OTG_SYS_REFCLKSEL_XTAL                 (0x0 << 9)
-#define OTG_SYS_REFCLKSEL_EXTL                 (0x1 << 9)
-#define OTG_SYS_REFCLKSEL_CLKCORE              (0x2 << 9)
-
-#define OTG_SYS_IDPULLUP_UOTG                  (0x1 << 8)
-#define OTG_SYS_COMMON_ON                      (0x1 << 7)
-
-#define OTG_SYS_FSEL_MASK                      (0x7 << 4)
-#define OTG_SYS_FSEL(_x)                       ((_x) << 4)
-
-#define OTG_SYS_FORCESLEEP                     (0x1 << 3)
-#define OTG_SYS_OTGDISABLE                     (0x1 << 2)
-#define OTG_SYS_SIDDQ_UOTG                     (0x1 << 1)
-#define OTG_SYS_FORCESUSPEND                   (0x1 << 0)
-
-#define EXYNOS5_PHY_OTG_TUNE                   (0x40)
-
-#ifndef MHZ
-#define MHZ (1000*1000)
-#endif
-
-#ifndef KHZ
-#define KHZ (1000)
-#endif
-
-#define EXYNOS_USBHOST_PHY_CTRL_OFFSET         (0x4)
-#define S3C64XX_USBPHY_ENABLE                  (0x1 << 16)
-#define EXYNOS_USBPHY_ENABLE                   (0x1 << 0)
-#define EXYNOS_USB20PHY_CFG_HOST_LINK          (0x1 << 0)
-
-enum samsung_cpu_type {
-       TYPE_S3C64XX,
-       TYPE_EXYNOS4210,
-       TYPE_EXYNOS5250,
-};
-
-/*
- * struct samsung_usbphy_drvdata - driver data for various SoC variants
- * @cpu_type: machine identifier
- * @devphy_en_mask: device phy enable mask for PHY CONTROL register
- * @hostphy_en_mask: host phy enable mask for PHY CONTROL register
- * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from
- *                    mapped address of system controller.
- * @hostphy_reg_offset: offset to HOST PHY CONTROL register from
- *                    mapped address of system controller.
- *
- *     Here we have a separate mask for device type phy.
- *     Having different masks for host and device type phy helps
- *     in setting independent masks in case of SoCs like S5PV210,
- *     in which PHY0 and PHY1 enable bits belong to same register
- *     placed at position 0 and 1 respectively.
- *     Although for newer SoCs like exynos these bits belong to
- *     different registers altogether placed at position 0.
- */
-struct samsung_usbphy_drvdata {
-       int cpu_type;
-       int devphy_en_mask;
-       int hostphy_en_mask;
-       u32 devphy_reg_offset;
-       u32 hostphy_reg_offset;
-};
-
-/*
- * struct samsung_usbphy - transceiver driver state
- * @phy: transceiver structure
- * @plat: platform data
- * @dev: The parent device supplied to the probe function
- * @clk: usb phy clock
- * @regs: usb phy controller registers memory base
- * @pmuregs: USB device PHY_CONTROL register memory base
- * @sysreg: USB2.0 PHY_CFG register memory base
- * @ref_clk_freq: reference clock frequency selection
- * @drv_data: driver data available for different SoCs
- * @phy_type: Samsung SoCs specific phy types: #HOST
- *                                             #DEVICE
- * @phy_usage: usage count for phy
- * @lock: lock for phy operations
- */
-struct samsung_usbphy {
-       struct usb_phy  phy;
-       struct samsung_usbphy_data *plat;
-       struct device   *dev;
-       struct clk      *clk;
-       void __iomem    *regs;
-       void __iomem    *pmuregs;
-       void __iomem    *sysreg;
-       int             ref_clk_freq;
-       const struct samsung_usbphy_drvdata *drv_data;
-       enum samsung_usb_phy_type phy_type;
-       atomic_t        phy_usage;
-       spinlock_t      lock;
-};
-
-#define phy_to_sphy(x)         container_of((x), struct samsung_usbphy, phy)
-
-int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-       if (!otg)
-               return -ENODEV;
-
-       if (!otg->host)
-               otg->host = host;
-
-       return 0;
-}
-
-static int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy)
-{
-       struct device_node *usbphy_sys;
-
-       /* Getting node for system controller interface for usb-phy */
-       usbphy_sys = of_get_child_by_name(sphy->dev->of_node, "usbphy-sys");
-       if (!usbphy_sys) {
-               dev_err(sphy->dev, "No sys-controller interface for usb-phy\n");
-               return -ENODEV;
-       }
-
-       sphy->pmuregs = of_iomap(usbphy_sys, 0);
-
-       if (sphy->pmuregs == NULL) {
-               dev_err(sphy->dev, "Can't get usb-phy pmu control register\n");
-               goto err0;
-       }
-
-       sphy->sysreg = of_iomap(usbphy_sys, 1);
-
-       /*
-        * Not returning error code here, since this situation is not fatal.
-        * Few SoCs may not have this switch available
-        */
-       if (sphy->sysreg == NULL)
-               dev_warn(sphy->dev, "Can't get usb-phy sysreg cfg register\n");
-
-       of_node_put(usbphy_sys);
-
-       return 0;
-
-err0:
-       of_node_put(usbphy_sys);
-       return -ENXIO;
-}
-
-/*
- * Set isolation here for phy.
- * Here 'on = true' would mean USB PHY block is isolated, hence
- * de-activated and vice-versa.
- */
-static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
-{
-       void __iomem *reg = NULL;
-       u32 reg_val;
-       u32 en_mask = 0;
-
-       if (!sphy->pmuregs) {
-               dev_warn(sphy->dev, "Can't set pmu isolation\n");
-               return;
-       }
-
-       switch (sphy->drv_data->cpu_type) {
-       case TYPE_S3C64XX:
-               /*
-                * Do nothing: We will add here once S3C64xx goes for DT support
-                */
-               break;
-       case TYPE_EXYNOS4210:
-               /*
-                * Fall through since exynos4210 and exynos5250 have similar
-                * register architecture: two separate registers for host and
-                * device phy control with enable bit at position 0.
-                */
-       case TYPE_EXYNOS5250:
-               if (sphy->phy_type == USB_PHY_TYPE_DEVICE) {
-                       reg = sphy->pmuregs +
-                               sphy->drv_data->devphy_reg_offset;
-                       en_mask = sphy->drv_data->devphy_en_mask;
-               } else if (sphy->phy_type == USB_PHY_TYPE_HOST) {
-                       reg = sphy->pmuregs +
-                               sphy->drv_data->hostphy_reg_offset;
-                       en_mask = sphy->drv_data->hostphy_en_mask;
-               }
-               break;
-       default:
-               dev_err(sphy->dev, "Invalid SoC type\n");
-               return;
-       }
-
-       reg_val = readl(reg);
-
-       if (on)
-               reg_val &= ~en_mask;
-       else
-               reg_val |= en_mask;
-
-       writel(reg_val, reg);
-}
-
-/*
- * Configure the mode of working of usb-phy here: HOST/DEVICE.
- */
-static void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy)
-{
-       u32 reg;
-
-       if (!sphy->sysreg) {
-               dev_warn(sphy->dev, "Can't configure specified phy mode\n");
-               return;
-       }
-
-       reg = readl(sphy->sysreg);
-
-       if (sphy->phy_type == USB_PHY_TYPE_DEVICE)
-               reg &= ~EXYNOS_USB20PHY_CFG_HOST_LINK;
-       else if (sphy->phy_type == USB_PHY_TYPE_HOST)
-               reg |= EXYNOS_USB20PHY_CFG_HOST_LINK;
-
-       writel(reg, sphy->sysreg);
-}
-
-/*
- * PHYs are different for USB Device and USB Host.
- * This make sure that correct PHY type is selected before
- * any operation on PHY.
- */
-static int samsung_usbphy_set_type(struct usb_phy *phy,
-                               enum samsung_usb_phy_type phy_type)
-{
-       struct samsung_usbphy *sphy = phy_to_sphy(phy);
-
-       sphy->phy_type = phy_type;
-
-       return 0;
-}
-
-/*
- * Returns reference clock frequency selection value
- */
-static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
-{
-       struct clk *ref_clk;
-       int refclk_freq = 0;
-
-       /*
-        * In exynos5250 USB host and device PHY use
-        * external crystal clock XXTI
-        */
-       if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
-               ref_clk = clk_get(sphy->dev, "ext_xtal");
-       else
-               ref_clk = clk_get(sphy->dev, "xusbxti");
-       if (IS_ERR(ref_clk)) {
-               dev_err(sphy->dev, "Failed to get reference clock\n");
-               return PTR_ERR(ref_clk);
-       }
-
-       if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) {
-               /* set clock frequency for PLL */
-               switch (clk_get_rate(ref_clk)) {
-               case 9600 * KHZ:
-                       refclk_freq = FSEL_CLKSEL_9600K;
-                       break;
-               case 10 * MHZ:
-                       refclk_freq = FSEL_CLKSEL_10M;
-                       break;
-               case 12 * MHZ:
-                       refclk_freq = FSEL_CLKSEL_12M;
-                       break;
-               case 19200 * KHZ:
-                       refclk_freq = FSEL_CLKSEL_19200K;
-                       break;
-               case 20 * MHZ:
-                       refclk_freq = FSEL_CLKSEL_20M;
-                       break;
-               case 50 * MHZ:
-                       refclk_freq = FSEL_CLKSEL_50M;
-                       break;
-               case 24 * MHZ:
-               default:
-                       /* default reference clock */
-                       refclk_freq = FSEL_CLKSEL_24M;
-                       break;
-               }
-       } else {
-               switch (clk_get_rate(ref_clk)) {
-               case 12 * MHZ:
-                       refclk_freq = PHYCLK_CLKSEL_12M;
-                       break;
-               case 24 * MHZ:
-                       refclk_freq = PHYCLK_CLKSEL_24M;
-                       break;
-               case 48 * MHZ:
-                       refclk_freq = PHYCLK_CLKSEL_48M;
-                       break;
-               default:
-                       if (sphy->drv_data->cpu_type == TYPE_S3C64XX)
-                               refclk_freq = PHYCLK_CLKSEL_48M;
-                       else
-                               refclk_freq = PHYCLK_CLKSEL_24M;
-                       break;
-               }
-       }
-       clk_put(ref_clk);
-
-       return refclk_freq;
-}
-
-static bool exynos5_phyhost_is_on(void *regs)
-{
-       u32 reg;
-
-       reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
-
-       return !(reg & HOST_CTRL0_SIDDQ);
-}
-
-static void samsung_exynos5_usbphy_enable(struct samsung_usbphy *sphy)
-{
-       void __iomem *regs = sphy->regs;
-       u32 phyclk = sphy->ref_clk_freq;
-       u32 phyhost;
-       u32 phyotg;
-       u32 phyhsic;
-       u32 ehcictrl;
-       u32 ohcictrl;
-
-       /*
-        * phy_usage helps in keeping usage count for phy
-        * so that the first consumer enabling the phy is also
-        * the last consumer to disable it.
-        */
-
-       atomic_inc(&sphy->phy_usage);
-
-       if (exynos5_phyhost_is_on(regs)) {
-               dev_info(sphy->dev, "Already power on PHY\n");
-               return;
-       }
-
-       /* Host configuration */
-       phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
-
-       /* phy reference clock configuration */
-       phyhost &= ~HOST_CTRL0_FSEL_MASK;
-       phyhost |= HOST_CTRL0_FSEL(phyclk);
-
-       /* host phy reset */
-       phyhost &= ~(HOST_CTRL0_PHYSWRST |
-                       HOST_CTRL0_PHYSWRSTALL |
-                       HOST_CTRL0_SIDDQ |
-                       /* Enable normal mode of operation */
-                       HOST_CTRL0_FORCESUSPEND |
-                       HOST_CTRL0_FORCESLEEP);
-
-       /* Link reset */
-       phyhost |= (HOST_CTRL0_LINKSWRST |
-                       HOST_CTRL0_UTMISWRST |
-                       /* COMMON Block configuration during suspend */
-                       HOST_CTRL0_COMMONON_N);
-       writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
-       udelay(10);
-       phyhost &= ~(HOST_CTRL0_LINKSWRST |
-                       HOST_CTRL0_UTMISWRST);
-       writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
-
-       /* OTG configuration */
-       phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
-
-       /* phy reference clock configuration */
-       phyotg &= ~OTG_SYS_FSEL_MASK;
-       phyotg |= OTG_SYS_FSEL(phyclk);
-
-       /* Enable normal mode of operation */
-       phyotg &= ~(OTG_SYS_FORCESUSPEND |
-                       OTG_SYS_SIDDQ_UOTG |
-                       OTG_SYS_FORCESLEEP |
-                       OTG_SYS_REFCLKSEL_MASK |
-                       /* COMMON Block configuration during suspend */
-                       OTG_SYS_COMMON_ON);
-
-       /* OTG phy & link reset */
-       phyotg |= (OTG_SYS_PHY0_SWRST |
-                       OTG_SYS_LINKSWRST_UOTG |
-                       OTG_SYS_PHYLINK_SWRESET |
-                       OTG_SYS_OTGDISABLE |
-                       /* Set phy refclk */
-                       OTG_SYS_REFCLKSEL_CLKCORE);
-
-       writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
-       udelay(10);
-       phyotg &= ~(OTG_SYS_PHY0_SWRST |
-                       OTG_SYS_LINKSWRST_UOTG |
-                       OTG_SYS_PHYLINK_SWRESET);
-       writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
-
-       /* HSIC phy configuration */
-       phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
-                       HSIC_CTRL_REFCLKSEL |
-                       HSIC_CTRL_PHYSWRST);
-       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
-       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
-       udelay(10);
-       phyhsic &= ~HSIC_CTRL_PHYSWRST;
-       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
-       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
-
-       udelay(80);
-
-       /* enable EHCI DMA burst */
-       ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL);
-       ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN |
-                               HOST_EHCICTRL_ENAINCR4 |
-                               HOST_EHCICTRL_ENAINCR8 |
-                               HOST_EHCICTRL_ENAINCR16);
-       writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL);
-
-       /* set ohci_suspend_on_n */
-       ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL);
-       ohcictrl |= HOST_OHCICTRL_SUSPLGCY;
-       writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL);
-}
-
-static void samsung_usbphy_enable(struct samsung_usbphy *sphy)
-{
-       void __iomem *regs = sphy->regs;
-       u32 phypwr;
-       u32 phyclk;
-       u32 rstcon;
-
-       /* set clock frequency for PLL */
-       phyclk = sphy->ref_clk_freq;
-       phypwr = readl(regs + SAMSUNG_PHYPWR);
-       rstcon = readl(regs + SAMSUNG_RSTCON);
-
-       switch (sphy->drv_data->cpu_type) {
-       case TYPE_S3C64XX:
-               phyclk &= ~PHYCLK_COMMON_ON_N;
-               phypwr &= ~PHYPWR_NORMAL_MASK;
-               rstcon |= RSTCON_SWRST;
-               break;
-       case TYPE_EXYNOS4210:
-               phypwr &= ~PHYPWR_NORMAL_MASK_PHY0;
-               rstcon |= RSTCON_SWRST;
-       default:
-               break;
-       }
-
-       writel(phyclk, regs + SAMSUNG_PHYCLK);
-       /* Configure PHY0 for normal operation*/
-       writel(phypwr, regs + SAMSUNG_PHYPWR);
-       /* reset all ports of PHY and Link */
-       writel(rstcon, regs + SAMSUNG_RSTCON);
-       udelay(10);
-       rstcon &= ~RSTCON_SWRST;
-       writel(rstcon, regs + SAMSUNG_RSTCON);
-}
-
-static void samsung_exynos5_usbphy_disable(struct samsung_usbphy *sphy)
-{
-       void __iomem *regs = sphy->regs;
-       u32 phyhost;
-       u32 phyotg;
-       u32 phyhsic;
-
-       if (atomic_dec_return(&sphy->phy_usage) > 0) {
-               dev_info(sphy->dev, "still being used\n");
-               return;
-       }
-
-       phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
-                       HSIC_CTRL_REFCLKSEL |
-                       HSIC_CTRL_SIDDQ |
-                       HSIC_CTRL_FORCESLEEP |
-                       HSIC_CTRL_FORCESUSPEND);
-       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
-       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
-
-       phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
-       phyhost |= (HOST_CTRL0_SIDDQ |
-                       HOST_CTRL0_FORCESUSPEND |
-                       HOST_CTRL0_FORCESLEEP |
-                       HOST_CTRL0_PHYSWRST |
-                       HOST_CTRL0_PHYSWRSTALL);
-       writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
-
-       phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
-       phyotg |= (OTG_SYS_FORCESUSPEND |
-                       OTG_SYS_SIDDQ_UOTG |
-                       OTG_SYS_FORCESLEEP);
-       writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
-}
-
-static void samsung_usbphy_disable(struct samsung_usbphy *sphy)
-{
-       void __iomem *regs = sphy->regs;
-       u32 phypwr;
-
-       phypwr = readl(regs + SAMSUNG_PHYPWR);
-
-       switch (sphy->drv_data->cpu_type) {
-       case TYPE_S3C64XX:
-               phypwr |= PHYPWR_NORMAL_MASK;
-               break;
-       case TYPE_EXYNOS4210:
-               phypwr |= PHYPWR_NORMAL_MASK_PHY0;
-       default:
-               break;
-       }
-
-       /* Disable analog and otg block power */
-       writel(phypwr, regs + SAMSUNG_PHYPWR);
-}
-
-/*
- * The function passed to the usb driver for phy initialization
- */
-static int samsung_usbphy_init(struct usb_phy *phy)
-{
-       struct samsung_usbphy *sphy;
-       struct usb_bus *host = NULL;
-       unsigned long flags;
-       int ret = 0;
-
-       sphy = phy_to_sphy(phy);
-
-       host = phy->otg->host;
-
-       /* Enable the phy clock */
-       ret = clk_prepare_enable(sphy->clk);
-       if (ret) {
-               dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
-               return ret;
-       }
-
-       spin_lock_irqsave(&sphy->lock, flags);
-
-       if (host) {
-               /* setting default phy-type for USB 2.0 */
-               if (!strstr(dev_name(host->controller), "ehci") ||
-                               !strstr(dev_name(host->controller), "ohci"))
-                       samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
-       } else {
-               samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
-       }
-
-       /* Disable phy isolation */
-       if (sphy->plat && sphy->plat->pmu_isolation)
-               sphy->plat->pmu_isolation(false);
-       else
-               samsung_usbphy_set_isolation(sphy, false);
-
-       /* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */
-       samsung_usbphy_cfg_sel(sphy);
-
-       /* Initialize usb phy registers */
-       if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
-               samsung_exynos5_usbphy_enable(sphy);
-       else
-               samsung_usbphy_enable(sphy);
-
-       spin_unlock_irqrestore(&sphy->lock, flags);
-
-       /* Disable the phy clock */
-       clk_disable_unprepare(sphy->clk);
-
-       return ret;
-}
-
-/*
- * The function passed to the usb driver for phy shutdown
- */
-static void samsung_usbphy_shutdown(struct usb_phy *phy)
-{
-       struct samsung_usbphy *sphy;
-       struct usb_bus *host = NULL;
-       unsigned long flags;
-
-       sphy = phy_to_sphy(phy);
-
-       host = phy->otg->host;
-
-       if (clk_prepare_enable(sphy->clk)) {
-               dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
-               return;
-       }
-
-       spin_lock_irqsave(&sphy->lock, flags);
-
-       if (host) {
-               /* setting default phy-type for USB 2.0 */
-               if (!strstr(dev_name(host->controller), "ehci") ||
-                               !strstr(dev_name(host->controller), "ohci"))
-                       samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
-       } else {
-               samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
-       }
-
-       /* De-initialize usb phy registers */
-       if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
-               samsung_exynos5_usbphy_disable(sphy);
-       else
-               samsung_usbphy_disable(sphy);
-
-       /* Enable phy isolation */
-       if (sphy->plat && sphy->plat->pmu_isolation)
-               sphy->plat->pmu_isolation(true);
-       else
-               samsung_usbphy_set_isolation(sphy, true);
-
-       spin_unlock_irqrestore(&sphy->lock, flags);
-
-       clk_disable_unprepare(sphy->clk);
-}
-
-static const struct of_device_id samsung_usbphy_dt_match[];
-
-static inline const struct samsung_usbphy_drvdata
-*samsung_usbphy_get_driver_data(struct platform_device *pdev)
-{
-       if (pdev->dev.of_node) {
-               const struct of_device_id *match;
-               match = of_match_node(samsung_usbphy_dt_match,
-                                                       pdev->dev.of_node);
-               return match->data;
-       }
-
-       return (struct samsung_usbphy_drvdata *)
-                               platform_get_device_id(pdev)->driver_data;
-}
-
-static int samsung_usbphy_probe(struct platform_device *pdev)
-{
-       struct samsung_usbphy *sphy;
-       struct usb_otg *otg;
-       struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
-       const struct samsung_usbphy_drvdata *drv_data;
-       struct device *dev = &pdev->dev;
-       struct resource *phy_mem;
-       void __iomem    *phy_base;
-       struct clk *clk;
-       int ret;
-
-       phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!phy_mem) {
-               dev_err(dev, "%s: missing mem resource\n", __func__);
-               return -ENODEV;
-       }
-
-       phy_base = devm_ioremap_resource(dev, phy_mem);
-       if (IS_ERR(phy_base))
-               return PTR_ERR(phy_base);
-
-       sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
-       if (!sphy)
-               return -ENOMEM;
-
-       otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL);
-       if (!otg)
-               return -ENOMEM;
-
-       drv_data = samsung_usbphy_get_driver_data(pdev);
-
-       if (drv_data->cpu_type == TYPE_EXYNOS5250)
-               clk = devm_clk_get(dev, "usbhost");
-       else
-               clk = devm_clk_get(dev, "otg");
-
-       if (IS_ERR(clk)) {
-               dev_err(dev, "Failed to get otg clock\n");
-               return PTR_ERR(clk);
-       }
-
-       sphy->dev = dev;
-
-       if (dev->of_node) {
-               ret = samsung_usbphy_parse_dt(sphy);
-               if (ret < 0)
-                       return ret;
-       } else {
-               if (!pdata) {
-                       dev_err(dev, "no platform data specified\n");
-                       return -EINVAL;
-               }
-       }
-
-       sphy->plat              = pdata;
-       sphy->regs              = phy_base;
-       sphy->clk               = clk;
-       sphy->drv_data          = drv_data;
-       sphy->phy.dev           = sphy->dev;
-       sphy->phy.label         = "samsung-usbphy";
-       sphy->phy.init          = samsung_usbphy_init;
-       sphy->phy.shutdown      = samsung_usbphy_shutdown;
-       sphy->ref_clk_freq      = samsung_usbphy_get_refclk_freq(sphy);
-
-       sphy->phy.otg           = otg;
-       sphy->phy.otg->phy      = &sphy->phy;
-       sphy->phy.otg->set_host = samsung_usbphy_set_host;
-
-       spin_lock_init(&sphy->lock);
-
-       platform_set_drvdata(pdev, sphy);
-
-       return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2);
-}
-
-static int samsung_usbphy_remove(struct platform_device *pdev)
-{
-       struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
-
-       usb_remove_phy(&sphy->phy);
-
-       if (sphy->pmuregs)
-               iounmap(sphy->pmuregs);
-       if (sphy->sysreg)
-               iounmap(sphy->sysreg);
-
-       return 0;
-}
-
-static const struct samsung_usbphy_drvdata usbphy_s3c64xx = {
-       .cpu_type               = TYPE_S3C64XX,
-       .devphy_en_mask         = S3C64XX_USBPHY_ENABLE,
-};
-
-static const struct samsung_usbphy_drvdata usbphy_exynos4 = {
-       .cpu_type               = TYPE_EXYNOS4210,
-       .devphy_en_mask         = EXYNOS_USBPHY_ENABLE,
-       .hostphy_en_mask        = EXYNOS_USBPHY_ENABLE,
-};
-
-static struct samsung_usbphy_drvdata usbphy_exynos5 = {
-       .cpu_type               = TYPE_EXYNOS5250,
-       .hostphy_en_mask        = EXYNOS_USBPHY_ENABLE,
-       .hostphy_reg_offset     = EXYNOS_USBHOST_PHY_CTRL_OFFSET,
-};
-
-#ifdef CONFIG_OF
-static const struct of_device_id samsung_usbphy_dt_match[] = {
-       {
-               .compatible = "samsung,s3c64xx-usbphy",
-               .data = &usbphy_s3c64xx,
-       }, {
-               .compatible = "samsung,exynos4210-usbphy",
-               .data = &usbphy_exynos4,
-       }, {
-               .compatible = "samsung,exynos5250-usbphy",
-               .data = &usbphy_exynos5
-       },
-       {},
-};
-MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
-#endif
-
-static struct platform_device_id samsung_usbphy_driver_ids[] = {
-       {
-               .name           = "s3c64xx-usbphy",
-               .driver_data    = (unsigned long)&usbphy_s3c64xx,
-       }, {
-               .name           = "exynos4210-usbphy",
-               .driver_data    = (unsigned long)&usbphy_exynos4,
-       }, {
-               .name           = "exynos5250-usbphy",
-               .driver_data    = (unsigned long)&usbphy_exynos5,
-       },
-       {},
-};
-
-MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
-
-static struct platform_driver samsung_usbphy_driver = {
-       .probe          = samsung_usbphy_probe,
-       .remove         = samsung_usbphy_remove,
-       .id_table       = samsung_usbphy_driver_ids,
-       .driver         = {
-               .name   = "samsung-usbphy",
-               .owner  = THIS_MODULE,
-               .of_match_table = of_match_ptr(samsung_usbphy_dt_match),
-       },
-};
-
-module_platform_driver(samsung_usbphy_driver);
-
-MODULE_DESCRIPTION("Samsung USB phy controller");
-MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:samsung-usbphy");
index 29feb00d7f3913e33a315980ca47fd4d1b409bd3..019bf7e49ee6b1d2d64055326fdbf54589ff8b4f 100644 (file)
@@ -4,7 +4,7 @@
 
 config USB_RENESAS_USBHS
        tristate 'Renesas USBHS controller'
-       depends on USB && USB_GADGET && GENERIC_HARDIRQS
+       depends on USB_GADGET && GENERIC_HARDIRQS
        default n
        help
          Renesas USBHS is a discrete USB host and peripheral controller chip
index 9538f0feafe2c37f6b98f5598126fa8b75906af3..45b94019aec8f9aad1dc87385a7022262184803b 100644 (file)
@@ -32,7 +32,6 @@
  */
 void usbhs_pkt_init(struct usbhs_pkt *pkt)
 {
-       pkt->dma = DMA_ADDR_INVALID;
        INIT_LIST_HEAD(&pkt->node);
 }
 
index c31731a843d12cefa1214fe17dad4a31b97dee94..a168a1760fce87ca6e8747491a609e9ed2445b6f 100644 (file)
@@ -23,8 +23,6 @@
 #include <asm/dma.h>
 #include "pipe.h"
 
-#define        DMA_ADDR_INVALID        (~(dma_addr_t)0)
-
 struct usbhs_fifo {
        char *name;
        u32 port;       /* xFIFO */
index 78fca978b2d058a86bb4b9a178bb5336951e99cf..ed4949faa70d14502a6669a3fb35b6fb814b35c6 100644 (file)
@@ -230,7 +230,7 @@ static int usbhsg_recip_handler_std_clear_endpoint(struct usbhs_priv *priv,
        return 0;
 }
 
-struct usbhsg_recip_handle req_clear_feature = {
+static struct usbhsg_recip_handle req_clear_feature = {
        .name           = "clear feature",
        .device         = usbhsg_recip_handler_std_control_done,
        .interface      = usbhsg_recip_handler_std_control_done,
@@ -271,7 +271,7 @@ static int usbhsg_recip_handler_std_set_endpoint(struct usbhs_priv *priv,
        return 0;
 }
 
-struct usbhsg_recip_handle req_set_feature = {
+static struct usbhsg_recip_handle req_set_feature = {
        .name           = "set feature",
        .device         = usbhsg_recip_handler_std_set_device,
        .interface      = usbhsg_recip_handler_std_control_done,
@@ -372,7 +372,7 @@ static int usbhsg_recip_handler_std_get_endpoint(struct usbhs_priv *priv,
        return 0;
 }
 
-struct usbhsg_recip_handle req_get_status = {
+static struct usbhsg_recip_handle req_get_status = {
        .name           = "get status",
        .device         = usbhsg_recip_handler_std_get_device,
        .interface      = usbhsg_recip_handler_std_get_interface,
@@ -845,7 +845,6 @@ static int usbhsg_gadget_start(struct usb_gadget *gadget,
 
        /* first hook up the driver ... */
        gpriv->driver = driver;
-       gpriv->gadget.dev.driver = &driver->driver;
 
        return usbhsg_try_start(priv, USBHSG_STATUS_REGISTERD);
 }
@@ -861,7 +860,6 @@ static int usbhsg_gadget_stop(struct usb_gadget *gadget,
                return -EINVAL;
 
        usbhsg_try_stop(priv, USBHSG_STATUS_REGISTERD);
-       gpriv->gadget.dev.driver = NULL;
        gpriv->driver = NULL;
 
        return 0;
@@ -925,11 +923,6 @@ static int usbhsg_stop(struct usbhs_priv *priv)
        return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED);
 }
 
-static void usbhs_mod_gadget_release(struct device *pdev)
-{
-       /* do nothing */
-}
-
 int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 {
        struct usbhsg_gpriv *gpriv;
@@ -976,15 +969,10 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
        /*
         * init gadget
         */
-       dev_set_name(&gpriv->gadget.dev, "gadget");
        gpriv->gadget.dev.parent        = dev;
-       gpriv->gadget.dev.release       = usbhs_mod_gadget_release;
        gpriv->gadget.name              = "renesas_usbhs_udc";
        gpriv->gadget.ops               = &usbhsg_gadget_ops;
        gpriv->gadget.max_speed         = USB_SPEED_HIGH;
-       ret = device_register(&gpriv->gadget.dev);
-       if (ret < 0)
-               goto err_add_udc;
 
        INIT_LIST_HEAD(&gpriv->gadget.ep_list);
 
@@ -1014,15 +1002,13 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 
        ret = usb_add_gadget_udc(dev, &gpriv->gadget);
        if (ret)
-               goto err_register;
+               goto err_add_udc;
 
 
        dev_info(dev, "gadget probed\n");
 
        return 0;
 
-err_register:
-       device_unregister(&gpriv->gadget.dev);
 err_add_udc:
        kfree(gpriv->uep);
 
@@ -1038,8 +1024,6 @@ void usbhs_mod_gadget_remove(struct usbhs_priv *priv)
 
        usb_del_gadget_udc(&gpriv->gadget);
 
-       device_unregister(&gpriv->gadget.dev);
-
        kfree(gpriv->uep);
        kfree(gpriv);
 }
index 17b7f9ae36ad16eb183b3eb2cf7ec187ccadf7b5..1d55762afbb118bdb2d62fbb960490e02b4479cb 100644 (file)
@@ -4,7 +4,7 @@
 
 menuconfig USB_SERIAL
        tristate "USB Serial Converter support"
-       depends on USB && TTY
+       depends on TTY
        ---help---
          Say Y here if you have a USB device that provides normal serial
          ports, or acts like a serial device, and you want to connect it to
@@ -667,6 +667,23 @@ config USB_SERIAL_ZIO
          To compile this driver as a module, choose M here: the
          module will be called zio.
 
+config USB_SERIAL_WISHBONE
+       tristate "USB-Wishbone adapter interface driver"
+       help
+         Say Y here if you want to use a USB attached Wishbone bus.
+
+         Wishbone is an open hardware SoC bus commonly used in FPGA
+         designs. Bus access can be serialized using the Etherbone
+         protocol <http://www.ohwr.org/projects/etherbone-core>.
+
+         This driver is intended to be used with devices which attach
+         their internal Wishbone bus to a USB serial interface using
+         the Etherbone protocol. A userspace library is required to
+         speak the protocol made available by this driver as ttyUSBx.
+
+         To compile this driver as a module, choose M here: the
+         module will be called wishbone-serial.
+
 config USB_SERIAL_ZTE
        tristate "ZTE USB serial driver"
        help
index eaf5ca14dfeb4d1401abc8621ca2d45ec62a9572..cec63fa191046eda1e3b0d095186069f38f01a90 100644 (file)
@@ -58,6 +58,7 @@ obj-$(CONFIG_USB_SERIAL_SYMBOL)                       += symbolserial.o
 obj-$(CONFIG_USB_SERIAL_WWAN)                  += usb_wwan.o
 obj-$(CONFIG_USB_SERIAL_TI)                    += ti_usb_3410_5052.o
 obj-$(CONFIG_USB_SERIAL_VISOR)                 += visor.o
+obj-$(CONFIG_USB_SERIAL_WISHBONE)              += wishbone-serial.o
 obj-$(CONFIG_USB_SERIAL_WHITEHEAT)             += whiteheat.o
 obj-$(CONFIG_USB_SERIAL_XIRCOM)                        += keyspan_pda.o
 obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL)                += vivopay-serial.o
index 4775f8209e5502b7f893d0a00a8f51622746a138..3b16118cbf62d7d8be032f6a243a39fd5965a5be 100644 (file)
@@ -62,7 +62,6 @@ static int is_irda(struct usb_serial *serial)
 }
 
 struct ark3116_private {
-       struct async_icount     icount;
        int                     irda;   /* 1 for irda device */
 
        /* protects hw register updates */
@@ -341,18 +340,15 @@ static void ark3116_close(struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
 
-       if (serial->dev) {
-               /* disable DMA */
-               ark3116_write_reg(serial, UART_FCR, 0);
-
-               /* deactivate interrupts */
-               ark3116_write_reg(serial, UART_IER, 0);
+       /* disable DMA */
+       ark3116_write_reg(serial, UART_FCR, 0);
 
-               usb_serial_generic_close(port);
-               if (serial->num_interrupt_in)
-                       usb_kill_urb(port->interrupt_in_urb);
-       }
+       /* deactivate interrupts */
+       ark3116_write_reg(serial, UART_IER, 0);
 
+       usb_serial_generic_close(port);
+       if (serial->num_interrupt_in)
+               usb_kill_urb(port->interrupt_in_urb);
 }
 
 static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)
@@ -405,31 +401,10 @@ err_out:
        return result;
 }
 
-static int ark3116_get_icount(struct tty_struct *tty,
-                                       struct serial_icounter_struct *icount)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct ark3116_private *priv = usb_get_serial_port_data(port);
-       struct async_icount cnow = priv->icount;
-       icount->cts = cnow.cts;
-       icount->dsr = cnow.dsr;
-       icount->rng = cnow.rng;
-       icount->dcd = cnow.dcd;
-       icount->rx = cnow.rx;
-       icount->tx = cnow.tx;
-       icount->frame = cnow.frame;
-       icount->overrun = cnow.overrun;
-       icount->parity = cnow.parity;
-       icount->brk = cnow.brk;
-       icount->buf_overrun = cnow.buf_overrun;
-       return 0;
-}
-
 static int ark3116_ioctl(struct tty_struct *tty,
                         unsigned int cmd, unsigned long arg)
 {
        struct usb_serial_port *port = tty->driver_data;
-       struct ark3116_private *priv = usb_get_serial_port_data(port);
        struct serial_struct serstruct;
        void __user *user_arg = (void __user *)arg;
 
@@ -451,33 +426,6 @@ static int ark3116_ioctl(struct tty_struct *tty,
                if (copy_from_user(&serstruct, user_arg, sizeof(serstruct)))
                        return -EFAULT;
                return 0;
-       case TIOCMIWAIT:
-               for (;;) {
-                       struct async_icount prev = priv->icount;
-                       interruptible_sleep_on(&port->delta_msr_wait);
-                       /* see if a signal did it */
-                       if (signal_pending(current))
-                               return -ERESTARTSYS;
-
-                       if (port->serial->disconnected)
-                               return -EIO;
-
-                       if ((prev.rng == priv->icount.rng) &&
-                           (prev.dsr == priv->icount.dsr) &&
-                           (prev.dcd == priv->icount.dcd) &&
-                           (prev.cts == priv->icount.cts))
-                               return -EIO;
-                       if ((arg & TIOCM_RNG &&
-                            (prev.rng != priv->icount.rng)) ||
-                           (arg & TIOCM_DSR &&
-                            (prev.dsr != priv->icount.dsr)) ||
-                           (arg & TIOCM_CD  &&
-                            (prev.dcd != priv->icount.dcd)) ||
-                           (arg & TIOCM_CTS &&
-                            (prev.cts != priv->icount.cts)))
-                               return 0;
-               }
-               break;
        }
 
        return -ENOIOCTLCMD;
@@ -575,14 +523,14 @@ static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr)
        if (msr & UART_MSR_ANY_DELTA) {
                /* update input line counters */
                if (msr & UART_MSR_DCTS)
-                       priv->icount.cts++;
+                       port->icount.cts++;
                if (msr & UART_MSR_DDSR)
-                       priv->icount.dsr++;
+                       port->icount.dsr++;
                if (msr & UART_MSR_DDCD)
-                       priv->icount.dcd++;
+                       port->icount.dcd++;
                if (msr & UART_MSR_TERI)
-                       priv->icount.rng++;
-               wake_up_interruptible(&port->delta_msr_wait);
+                       port->icount.rng++;
+               wake_up_interruptible(&port->port.delta_msr_wait);
        }
 }
 
@@ -598,13 +546,13 @@ static void ark3116_update_lsr(struct usb_serial_port *port, __u8 lsr)
 
        if (lsr&UART_LSR_BRK_ERROR_BITS) {
                if (lsr & UART_LSR_BI)
-                       priv->icount.brk++;
+                       port->icount.brk++;
                if (lsr & UART_LSR_FE)
-                       priv->icount.frame++;
+                       port->icount.frame++;
                if (lsr & UART_LSR_PE)
-                       priv->icount.parity++;
+                       port->icount.parity++;
                if (lsr & UART_LSR_OE)
-                       priv->icount.overrun++;
+                       port->icount.overrun++;
        }
 }
 
@@ -722,7 +670,8 @@ static struct usb_serial_driver ark3116_device = {
        .ioctl =                ark3116_ioctl,
        .tiocmget =             ark3116_tiocmget,
        .tiocmset =             ark3116_tiocmset,
-       .get_icount =           ark3116_get_icount,
+       .tiocmiwait =           usb_serial_generic_tiocmiwait,
+       .get_icount =           usb_serial_generic_get_icount,
        .open =                 ark3116_open,
        .close =                ark3116_close,
        .break_ctl =            ark3116_break_ctl,
index 37decb13d7eb82a2f4486f3d17ca56fec73dc6f3..3c4db6d196c630257611883e9f8f7ec46f5c20b6 100644 (file)
@@ -106,14 +106,15 @@ static int usb_serial_device_remove(struct device *dev)
        /* make sure suspend/resume doesn't race against port_remove */
        usb_autopm_get_interface(port->serial->interface);
 
+       minor = port->number;
+       tty_unregister_device(usb_serial_tty_driver, minor);
+
        device_remove_file(&port->dev, &dev_attr_port_number);
 
        driver = port->serial->type;
        if (driver->port_remove)
                retval = driver->port_remove(port);
 
-       minor = port->number;
-       tty_unregister_device(usb_serial_tty_driver, minor);
        dev_info(dev, "%s converter now disconnected from ttyUSB%d\n",
                 driver->description, minor);
 
index 07d4650a32abe2d89149ef8fc2a22bc17bebe8b2..c2a4171ab9cb7f962ca32b07a85e8d2f37630d10 100644 (file)
@@ -296,7 +296,6 @@ static void ch341_dtr_rts(struct usb_serial_port *port, int on)
                priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);
        spin_unlock_irqrestore(&priv->lock, flags);
        ch341_set_handshake(port->serial->dev, priv->line_control);
-       wake_up_interruptible(&port->delta_msr_wait);
 }
 
 static void ch341_close(struct usb_serial_port *port)
@@ -489,7 +488,7 @@ static void ch341_read_int_callback(struct urb *urb)
                        tty_kref_put(tty);
                }
 
-               wake_up_interruptible(&port->delta_msr_wait);
+               wake_up_interruptible(&port->port.delta_msr_wait);
        }
 
 exit:
@@ -500,8 +499,9 @@ exit:
                        __func__, status);
 }
 
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+static int ch341_tiocmiwait(struct tty_struct *tty, unsigned long arg)
 {
+       struct usb_serial_port *port = tty->driver_data;
        struct ch341_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
        u8 prevstatus;
@@ -515,7 +515,7 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
        spin_unlock_irqrestore(&priv->lock, flags);
 
        while (!multi_change) {
-               interruptible_sleep_on(&port->delta_msr_wait);
+               interruptible_sleep_on(&port->port.delta_msr_wait);
                /* see if a signal did it */
                if (signal_pending(current))
                        return -ERESTARTSYS;
@@ -542,26 +542,6 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
        return 0;
 }
 
-static int ch341_ioctl(struct tty_struct *tty,
-                       unsigned int cmd, unsigned long arg)
-{
-       struct usb_serial_port *port = tty->driver_data;
-
-       dev_dbg(&port->dev, "%s (%d) cmd = 0x%04x\n", __func__, port->number, cmd);
-
-       switch (cmd) {
-       case TIOCMIWAIT:
-               dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,  port->number);
-               return wait_modem_info(port, arg);
-
-       default:
-               dev_dbg(&port->dev, "%s not supported = 0x%04x\n", __func__, cmd);
-               break;
-       }
-
-       return -ENOIOCTLCMD;
-}
-
 static int ch341_tiocmget(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
@@ -611,11 +591,11 @@ static struct usb_serial_driver ch341_device = {
        .dtr_rts           = ch341_dtr_rts,
        .carrier_raised    = ch341_carrier_raised,
        .close             = ch341_close,
-       .ioctl             = ch341_ioctl,
        .set_termios       = ch341_set_termios,
        .break_ctl         = ch341_break_ctl,
        .tiocmget          = ch341_tiocmget,
        .tiocmset          = ch341_tiocmset,
+       .tiocmiwait        = ch341_tiocmiwait,
        .read_int_callback = ch341_read_int_callback,
        .port_probe        = ch341_port_probe,
        .port_remove       = ch341_port_remove,
index 4747d1c328ffbdc13e1ca4337dc11a6c557711f5..2c659553c07c01df5dc1a65be8341809939fc6f4 100644 (file)
@@ -462,11 +462,7 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
 static void cp210x_close(struct usb_serial_port *port)
 {
        usb_serial_generic_close(port);
-
-       mutex_lock(&port->serial->disc_mutex);
-       if (!port->serial->disconnected)
-               cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE);
-       mutex_unlock(&port->serial->disc_mutex);
+       cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE);
 }
 
 /*
index 629bd2894506344e2177d4191d1b9e4a19a8b6f4..781426230d695a3f34544ab4b0a589a500a0063e 100644 (file)
@@ -51,7 +51,6 @@
 #define CYBERJACK_PRODUCT_ID   0x0100
 
 /* Function prototypes */
-static void cyberjack_disconnect(struct usb_serial *serial);
 static int cyberjack_port_probe(struct usb_serial_port *port);
 static int cyberjack_port_remove(struct usb_serial_port *port);
 static int  cyberjack_open(struct tty_struct *tty,
@@ -79,7 +78,6 @@ static struct usb_serial_driver cyberjack_device = {
        .description =          "Reiner SCT Cyberjack USB card reader",
        .id_table =             id_table,
        .num_ports =            1,
-       .disconnect =           cyberjack_disconnect,
        .port_probe =           cyberjack_port_probe,
        .port_remove =          cyberjack_port_remove,
        .open =                 cyberjack_open,
@@ -130,20 +128,14 @@ static int cyberjack_port_remove(struct usb_serial_port *port)
 {
        struct cyberjack_private *priv;
 
+       usb_kill_urb(port->interrupt_in_urb);
+
        priv = usb_get_serial_port_data(port);
        kfree(priv);
 
        return 0;
 }
 
-static void cyberjack_disconnect(struct usb_serial *serial)
-{
-       int i;
-
-       for (i = 0; i < serial->num_ports; ++i)
-               usb_kill_urb(serial->port[i]->interrupt_in_urb);
-}
-
 static int  cyberjack_open(struct tty_struct *tty,
                                        struct usb_serial_port *port)
 {
@@ -166,11 +158,8 @@ static int  cyberjack_open(struct tty_struct *tty,
 
 static void cyberjack_close(struct usb_serial_port *port)
 {
-       if (port->serial->dev) {
-               /* shutdown any bulk reads that might be going on */
-               usb_kill_urb(port->write_urb);
-               usb_kill_urb(port->read_urb);
-       }
+       usb_kill_urb(port->write_urb);
+       usb_kill_urb(port->read_urb);
 }
 
 static int cyberjack_write(struct tty_struct *tty,
index ba7352e4187efbd1ef73a09297d1cbb1825a4b08..d341555d37d8bbe85f719d782049806522d2a066 100644 (file)
@@ -129,13 +129,12 @@ static int  cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
                        const unsigned char *buf, int count);
 static void cypress_send(struct usb_serial_port *port);
 static int  cypress_write_room(struct tty_struct *tty);
-static int  cypress_ioctl(struct tty_struct *tty,
-                       unsigned int cmd, unsigned long arg);
 static void cypress_set_termios(struct tty_struct *tty,
                        struct usb_serial_port *port, struct ktermios *old);
 static int  cypress_tiocmget(struct tty_struct *tty);
 static int  cypress_tiocmset(struct tty_struct *tty,
                        unsigned int set, unsigned int clear);
+static int  cypress_tiocmiwait(struct tty_struct *tty, unsigned long arg);
 static int  cypress_chars_in_buffer(struct tty_struct *tty);
 static void cypress_throttle(struct tty_struct *tty);
 static void cypress_unthrottle(struct tty_struct *tty);
@@ -158,10 +157,10 @@ static struct usb_serial_driver cypress_earthmate_device = {
        .dtr_rts =                      cypress_dtr_rts,
        .write =                        cypress_write,
        .write_room =                   cypress_write_room,
-       .ioctl =                        cypress_ioctl,
        .set_termios =                  cypress_set_termios,
        .tiocmget =                     cypress_tiocmget,
        .tiocmset =                     cypress_tiocmset,
+       .tiocmiwait =                   cypress_tiocmiwait,
        .chars_in_buffer =              cypress_chars_in_buffer,
        .throttle =                     cypress_throttle,
        .unthrottle =                   cypress_unthrottle,
@@ -184,10 +183,10 @@ static struct usb_serial_driver cypress_hidcom_device = {
        .dtr_rts =                      cypress_dtr_rts,
        .write =                        cypress_write,
        .write_room =                   cypress_write_room,
-       .ioctl =                        cypress_ioctl,
        .set_termios =                  cypress_set_termios,
        .tiocmget =                     cypress_tiocmget,
        .tiocmset =                     cypress_tiocmset,
+       .tiocmiwait =                   cypress_tiocmiwait,
        .chars_in_buffer =              cypress_chars_in_buffer,
        .throttle =                     cypress_throttle,
        .unthrottle =                   cypress_unthrottle,
@@ -210,10 +209,10 @@ static struct usb_serial_driver cypress_ca42v2_device = {
        .dtr_rts =                      cypress_dtr_rts,
        .write =                        cypress_write,
        .write_room =                   cypress_write_room,
-       .ioctl =                        cypress_ioctl,
        .set_termios =                  cypress_set_termios,
        .tiocmget =                     cypress_tiocmget,
        .tiocmset =                     cypress_tiocmset,
+       .tiocmiwait =                   cypress_tiocmiwait,
        .chars_in_buffer =              cypress_chars_in_buffer,
        .throttle =                     cypress_throttle,
        .unthrottle =                   cypress_unthrottle,
@@ -633,12 +632,6 @@ static void cypress_close(struct usb_serial_port *port)
        struct cypress_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
 
-       /* writing is potentially harmful, lock must be taken */
-       mutex_lock(&port->serial->disc_mutex);
-       if (port->serial->disconnected) {
-               mutex_unlock(&port->serial->disc_mutex);
-               return;
-       }
        spin_lock_irqsave(&priv->lock, flags);
        kfifo_reset_out(&priv->write_fifo);
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -650,7 +643,6 @@ static void cypress_close(struct usb_serial_port *port)
        if (stats)
                dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
                        priv->bytes_in, priv->bytes_out, priv->cmd_count);
-       mutex_unlock(&port->serial->disc_mutex);
 } /* cypress_close */
 
 
@@ -855,55 +847,43 @@ static int cypress_tiocmset(struct tty_struct *tty,
 }
 
 
-static int cypress_ioctl(struct tty_struct *tty,
-                                       unsigned int cmd, unsigned long arg)
+static int cypress_tiocmiwait(struct tty_struct *tty, unsigned long arg)
 {
        struct usb_serial_port *port = tty->driver_data;
        struct cypress_private *priv = usb_get_serial_port_data(port);
-
-       dev_dbg(&port->dev, "%s - port %d, cmd 0x%.4x\n", __func__, port->number, cmd);
-
-       switch (cmd) {
-       /* This code comes from drivers/char/serial.c and ftdi_sio.c */
-       case TIOCMIWAIT:
-               for (;;) {
-                       interruptible_sleep_on(&port->delta_msr_wait);
-                       /* see if a signal did it */
-                       if (signal_pending(current))
-                               return -ERESTARTSYS;
-
-                       if (port->serial->disconnected)
-                               return -EIO;
-
-                       {
-                               char diff = priv->diff_status;
-                               if (diff == 0)
-                                       return -EIO; /* no change => error */
-
-                               /* consume all events */
-                               priv->diff_status = 0;
-
-                               /* return 0 if caller wanted to know about
-                                  these bits */
-                               if (((arg & TIOCM_RNG) && (diff & UART_RI)) ||
-                                   ((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
-                                   ((arg & TIOCM_CD) && (diff & UART_CD)) ||
-                                   ((arg & TIOCM_CTS) && (diff & UART_CTS)))
-                                       return 0;
-                               /* otherwise caller can't care less about what
-                                * happened, and so we continue to wait for
-                                * more events.
-                                */
-                       }
-               }
-               return 0;
-       default:
-               break;
+       char diff;
+
+       for (;;) {
+               interruptible_sleep_on(&port->port.delta_msr_wait);
+               /* see if a signal did it */
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
+
+               if (port->serial->disconnected)
+                       return -EIO;
+
+               diff = priv->diff_status;
+               if (diff == 0)
+                       return -EIO; /* no change => error */
+
+               /* consume all events */
+               priv->diff_status = 0;
+
+               /* return 0 if caller wanted to know about
+                  these bits */
+               if (((arg & TIOCM_RNG) && (diff & UART_RI))  ||
+                       ((arg & TIOCM_DSR) && (diff & UART_DSR)) ||
+                       ((arg & TIOCM_CD)  && (diff & UART_CD))  ||
+                       ((arg & TIOCM_CTS) && (diff & UART_CTS)))
+                       return 0;
+               /* otherwise caller can't care less about what
+                * happened, and so we continue to wait for
+                * more events.
+                */
        }
-       dev_dbg(&port->dev, "%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h\n", __func__, cmd);
-       return -ENOIOCTLCMD;
-} /* cypress_ioctl */
 
+       return 0;
+}
 
 static void cypress_set_termios(struct tty_struct *tty,
        struct usb_serial_port *port, struct ktermios *old_termios)
@@ -1189,7 +1169,7 @@ static void cypress_read_int_callback(struct urb *urb)
        if (priv->current_status != priv->prev_status) {
                priv->diff_status |= priv->current_status ^
                        priv->prev_status;
-               wake_up_interruptible(&port->delta_msr_wait);
+               wake_up_interruptible(&port->port.delta_msr_wait);
                priv->prev_status = priv->current_status;
        }
        spin_unlock_irqrestore(&priv->lock, flags);
index 31191581060c94762c7265eb031e224ccb227713..7b807d38952783b43854370590e0cc9db628ae49 100644 (file)
@@ -196,7 +196,6 @@ struct digi_port {
        unsigned char dp_out_buf[DIGI_OUT_BUF_SIZE];
        int dp_write_urb_in_use;
        unsigned int dp_modem_signals;
-       wait_queue_head_t dp_modem_change_wait;
        int dp_transmit_idle;
        wait_queue_head_t dp_transmit_idle_wait;
        int dp_throttled;
@@ -1138,53 +1137,51 @@ static void digi_close(struct usb_serial_port *port)
        if (port->serial->disconnected)
                goto exit;
 
-       if (port->serial->dev) {
-               /* FIXME: Transmit idle belongs in the wait_unti_sent path */
-               digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
-
-               /* disable input flow control */
-               buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
-               buf[1] = priv->dp_port_num;
-               buf[2] = DIGI_DISABLE;
-               buf[3] = 0;
-
-               /* disable output flow control */
-               buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL;
-               buf[5] = priv->dp_port_num;
-               buf[6] = DIGI_DISABLE;
-               buf[7] = 0;
-
-               /* disable reading modem signals automatically */
-               buf[8] = DIGI_CMD_READ_INPUT_SIGNALS;
-               buf[9] = priv->dp_port_num;
-               buf[10] = DIGI_DISABLE;
-               buf[11] = 0;
-
-               /* disable receive */
-               buf[12] = DIGI_CMD_RECEIVE_ENABLE;
-               buf[13] = priv->dp_port_num;
-               buf[14] = DIGI_DISABLE;
-               buf[15] = 0;
-
-               /* flush fifos */
-               buf[16] = DIGI_CMD_IFLUSH_FIFO;
-               buf[17] = priv->dp_port_num;
-               buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
-               buf[19] = 0;
-
-               ret = digi_write_oob_command(port, buf, 20, 0);
-               if (ret != 0)
-                       dev_dbg(&port->dev, "digi_close: write oob failed, ret=%d\n", ret);
-
-               /* wait for final commands on oob port to complete */
-               prepare_to_wait(&priv->dp_flush_wait, &wait,
-                                                       TASK_INTERRUPTIBLE);
-               schedule_timeout(DIGI_CLOSE_TIMEOUT);
-               finish_wait(&priv->dp_flush_wait, &wait);
-
-               /* shutdown any outstanding bulk writes */
-               usb_kill_urb(port->write_urb);
-       }
+       /* FIXME: Transmit idle belongs in the wait_unti_sent path */
+       digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
+
+       /* disable input flow control */
+       buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
+       buf[1] = priv->dp_port_num;
+       buf[2] = DIGI_DISABLE;
+       buf[3] = 0;
+
+       /* disable output flow control */
+       buf[4] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL;
+       buf[5] = priv->dp_port_num;
+       buf[6] = DIGI_DISABLE;
+       buf[7] = 0;
+
+       /* disable reading modem signals automatically */
+       buf[8] = DIGI_CMD_READ_INPUT_SIGNALS;
+       buf[9] = priv->dp_port_num;
+       buf[10] = DIGI_DISABLE;
+       buf[11] = 0;
+
+       /* disable receive */
+       buf[12] = DIGI_CMD_RECEIVE_ENABLE;
+       buf[13] = priv->dp_port_num;
+       buf[14] = DIGI_DISABLE;
+       buf[15] = 0;
+
+       /* flush fifos */
+       buf[16] = DIGI_CMD_IFLUSH_FIFO;
+       buf[17] = priv->dp_port_num;
+       buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
+       buf[19] = 0;
+
+       ret = digi_write_oob_command(port, buf, 20, 0);
+       if (ret != 0)
+               dev_dbg(&port->dev, "digi_close: write oob failed, ret=%d\n",
+                                                                       ret);
+       /* wait for final commands on oob port to complete */
+       prepare_to_wait(&priv->dp_flush_wait, &wait,
+                       TASK_INTERRUPTIBLE);
+       schedule_timeout(DIGI_CLOSE_TIMEOUT);
+       finish_wait(&priv->dp_flush_wait, &wait);
+
+       /* shutdown any outstanding bulk writes */
+       usb_kill_urb(port->write_urb);
 exit:
        spin_lock_irq(&priv->dp_port_lock);
        priv->dp_write_urb_in_use = 0;
@@ -1241,7 +1238,6 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
 
        spin_lock_init(&priv->dp_port_lock);
        priv->dp_port_num = port_num;
-       init_waitqueue_head(&priv->dp_modem_change_wait);
        init_waitqueue_head(&priv->dp_transmit_idle_wait);
        init_waitqueue_head(&priv->dp_flush_wait);
        init_waitqueue_head(&priv->dp_close_wait);
@@ -1532,7 +1528,6 @@ static int digi_read_oob_callback(struct urb *urb)
                        else
                                priv->dp_modem_signals &= ~TIOCM_CD;
 
-                       wake_up_interruptible(&priv->dp_modem_change_wait);
                        spin_unlock(&priv->dp_port_lock);
                } else if (opcode == DIGI_CMD_TRANSMIT_IDLE) {
                        spin_lock(&priv->dp_port_lock);
index a172ad5c5ce80c1c00983960a04339ac3c13fb24..090b411d893f8b957d816eb6b45bd599948ea055 100644 (file)
@@ -110,7 +110,7 @@ static void f81232_process_read_urb(struct urb *urb)
        line_status = priv->line_status;
        priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
        spin_unlock_irqrestore(&priv->lock, flags);
-       wake_up_interruptible(&port->delta_msr_wait);
+       wake_up_interruptible(&port->port.delta_msr_wait);
 
        if (!urb->actual_length)
                return;
@@ -242,8 +242,9 @@ static int f81232_carrier_raised(struct usb_serial_port *port)
        return 0;
 }
 
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+static int f81232_tiocmiwait(struct tty_struct *tty, unsigned long arg)
 {
+       struct usb_serial_port *port = tty->driver_data;
        struct f81232_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
        unsigned int prevstatus;
@@ -255,7 +256,7 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
        spin_unlock_irqrestore(&priv->lock, flags);
 
        while (1) {
-               interruptible_sleep_on(&port->delta_msr_wait);
+               interruptible_sleep_on(&port->port.delta_msr_wait);
                /* see if a signal did it */
                if (signal_pending(current))
                        return -ERESTARTSYS;
@@ -302,11 +303,6 @@ static int f81232_ioctl(struct tty_struct *tty,
                        return -EFAULT;
 
                return 0;
-
-       case TIOCMIWAIT:
-               dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,
-                       port->number);
-               return wait_modem_info(port, arg);
        default:
                dev_dbg(&port->dev, "%s not supported = 0x%04x\n",
                        __func__, cmd);
@@ -358,6 +354,7 @@ static struct usb_serial_driver f81232_device = {
        .set_termios =          f81232_set_termios,
        .tiocmget =             f81232_tiocmget,
        .tiocmset =             f81232_tiocmset,
+       .tiocmiwait =           f81232_tiocmiwait,
        .process_read_urb =     f81232_process_read_urb,
        .read_int_callback =    f81232_read_int_callback,
        .port_probe =           f81232_port_probe,
index 9886180e45f1b5d73ddc1903f2e13eecb6297013..242b5776648ab31c1e820bcc82dad0a48c629775 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * USB FTDI SIO driver
  *
- *     Copyright (C) 2009 - 2010
+ *     Copyright (C) 2009 - 2013
  *         Johan Hovold (jhovold@gmail.com)
  *     Copyright (C) 1999 - 2001
  *         Greg Kroah-Hartman (greg@kroah.com)
@@ -55,7 +55,6 @@ static __u16 vendor = FTDI_VID;
 static __u16 product;
 
 struct ftdi_private {
-       struct kref kref;
        enum ftdi_chip_type chip_type;
                                /* type of device, either SIO or FT8U232AM */
        int baud_base;          /* baud base clock for divisor setting */
@@ -68,7 +67,6 @@ struct ftdi_private {
                                 */
        int flags;              /* some ASYNC_xxxx flags are supported */
        unsigned long last_dtr_rts;     /* saved modem control outputs */
-       struct async_icount     icount;
        char prev_status;        /* Used for TIOCMIWAIT */
        char transmit_empty;    /* If transmitter is empty or not */
        __u16 interface;        /* FT2232C, FT2232H or FT4232H port interface
@@ -189,6 +187,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_BOOST_PID) },
        { USB_DEVICE(NEWPORT_VID, NEWPORT_AGILIS_PID) },
        { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
        { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
@@ -870,7 +869,9 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },
        { USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
-       { USB_DEVICE(ST_VID, ST_STMCLT1030_PID),
+       { USB_DEVICE(ST_VID, ST_STMCLT_2232_PID),
+               .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+       { USB_DEVICE(ST_VID, ST_STMCLT_4232_PID),
                .driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk },
        { USB_DEVICE(FTDI_VID, FTDI_RF_R106) },
        { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID),
@@ -911,7 +912,6 @@ static int  ftdi_sio_probe(struct usb_serial *serial,
 static int  ftdi_sio_port_probe(struct usb_serial_port *port);
 static int  ftdi_sio_port_remove(struct usb_serial_port *port);
 static int  ftdi_open(struct tty_struct *tty, struct usb_serial_port *port);
-static void ftdi_close(struct usb_serial_port *port);
 static void ftdi_dtr_rts(struct usb_serial_port *port, int on);
 static void ftdi_process_read_urb(struct urb *urb);
 static int ftdi_prepare_write_buffer(struct usb_serial_port *port,
@@ -921,8 +921,6 @@ static void ftdi_set_termios(struct tty_struct *tty,
 static int  ftdi_tiocmget(struct tty_struct *tty);
 static int  ftdi_tiocmset(struct tty_struct *tty,
                        unsigned int set, unsigned int clear);
-static int ftdi_get_icount(struct tty_struct *tty,
-                          struct serial_icounter_struct *icount);
 static int  ftdi_ioctl(struct tty_struct *tty,
                        unsigned int cmd, unsigned long arg);
 static void ftdi_break_ctl(struct tty_struct *tty, int break_state);
@@ -951,7 +949,6 @@ static struct usb_serial_driver ftdi_sio_device = {
        .port_probe =           ftdi_sio_port_probe,
        .port_remove =          ftdi_sio_port_remove,
        .open =                 ftdi_open,
-       .close =                ftdi_close,
        .dtr_rts =              ftdi_dtr_rts,
        .throttle =             usb_serial_generic_throttle,
        .unthrottle =           usb_serial_generic_unthrottle,
@@ -959,7 +956,8 @@ static struct usb_serial_driver ftdi_sio_device = {
        .prepare_write_buffer = ftdi_prepare_write_buffer,
        .tiocmget =             ftdi_tiocmget,
        .tiocmset =             ftdi_tiocmset,
-       .get_icount =           ftdi_get_icount,
+       .tiocmiwait =           usb_serial_generic_tiocmiwait,
+       .get_icount =           usb_serial_generic_get_icount,
        .ioctl =                ftdi_ioctl,
        .set_termios =          ftdi_set_termios,
        .break_ctl =            ftdi_break_ctl,
@@ -1688,7 +1686,6 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
                return -ENOMEM;
        }
 
-       kref_init(&priv->kref);
        mutex_init(&priv->cfg_lock);
 
        priv->flags = ASYNC_LOW_LATENCY;
@@ -1792,20 +1789,24 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial)
 }
 
 /*
- * First and second port on STMCLiteadaptors is reserved for JTAG interface
- * and the forth port for pio
+ * First two ports on JTAG adaptors using an FT4232 such as STMicroelectronics's
+ * ST Micro Connect Lite are reserved for JTAG or other non-UART interfaces and
+ * can be accessed from userspace.
+ * The next two ports are enabled as UARTs by default, where port 2 is
+ * a conventional RS-232 UART.
  */
 static int ftdi_stmclite_probe(struct usb_serial *serial)
 {
        struct usb_device *udev = serial->dev;
        struct usb_interface *interface = serial->interface;
 
-       if (interface == udev->actconfig->interface[2])
-               return 0;
-
-       dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n");
+       if (interface == udev->actconfig->interface[0] ||
+           interface == udev->actconfig->interface[1]) {
+               dev_info(&udev->dev, "Ignoring serial port reserved for JTAG\n");
+               return -ENODEV;
+       }
 
-       return -ENODEV;
+       return 0;
 }
 
 /*
@@ -1826,22 +1827,13 @@ static int ftdi_mtxorb_hack_setup(struct usb_serial *serial)
        return 0;
 }
 
-static void ftdi_sio_priv_release(struct kref *k)
-{
-       struct ftdi_private *priv = container_of(k, struct ftdi_private, kref);
-
-       kfree(priv);
-}
-
 static int ftdi_sio_port_remove(struct usb_serial_port *port)
 {
        struct ftdi_private *priv = usb_get_serial_port_data(port);
 
-       wake_up_interruptible(&port->delta_msr_wait);
-
        remove_sysfs_attrs(port);
 
-       kref_put(&priv->kref, ftdi_sio_priv_release);
+       kfree(priv);
 
        return 0;
 }
@@ -1851,7 +1843,6 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
        struct ktermios dummy;
        struct usb_device *dev = port->serial->dev;
        struct ftdi_private *priv = usb_get_serial_port_data(port);
-       int result;
 
        /* No error checking for this (will get errors later anyway) */
        /* See ftdi_sio.h for description of what is reset */
@@ -1870,12 +1861,7 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
                ftdi_set_termios(tty, port, &dummy);
        }
 
-       /* Start reading from the device */
-       result = usb_serial_generic_open(tty, port);
-       if (!result)
-               kref_get(&priv->kref);
-
-       return result;
+       return usb_serial_generic_open(tty, port);
 }
 
 static void ftdi_dtr_rts(struct usb_serial_port *port, int on)
@@ -1900,19 +1886,6 @@ static void ftdi_dtr_rts(struct usb_serial_port *port, int on)
                clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
 }
 
-/*
- * usbserial:__serial_close  only calls ftdi_close if the point is open
- *
- *   This only gets called when it is the last close
- */
-static void ftdi_close(struct usb_serial_port *port)
-{
-       struct ftdi_private *priv = usb_get_serial_port_data(port);
-
-       usb_serial_generic_close(port);
-       kref_put(&priv->kref, ftdi_sio_priv_release);
-}
-
 /* The SIO requires the first byte to have:
  *  B0 1
  *  B1 0
@@ -1940,7 +1913,7 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port,
                        c = kfifo_out(&port->write_fifo, &buffer[i + 1], len);
                        if (!c)
                                break;
-                       priv->icount.tx += c;
+                       port->icount.tx += c;
                        buffer[i] = (c << 2) + 1;
                        count += c + 1;
                }
@@ -1948,7 +1921,7 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port,
        } else {
                count = kfifo_out_locked(&port->write_fifo, dest, size,
                                                                &port->lock);
-               priv->icount.tx += count;
+               port->icount.tx += count;
        }
 
        return count;
@@ -1977,15 +1950,15 @@ static int ftdi_process_packet(struct usb_serial_port *port,
                char diff_status = status ^ priv->prev_status;
 
                if (diff_status & FTDI_RS0_CTS)
-                       priv->icount.cts++;
+                       port->icount.cts++;
                if (diff_status & FTDI_RS0_DSR)
-                       priv->icount.dsr++;
+                       port->icount.dsr++;
                if (diff_status & FTDI_RS0_RI)
-                       priv->icount.rng++;
+                       port->icount.rng++;
                if (diff_status & FTDI_RS0_RLSD)
-                       priv->icount.dcd++;
+                       port->icount.dcd++;
 
-               wake_up_interruptible(&port->delta_msr_wait);
+               wake_up_interruptible(&port->port.delta_msr_wait);
                priv->prev_status = status;
        }
 
@@ -1995,18 +1968,18 @@ static int ftdi_process_packet(struct usb_serial_port *port,
                 * over framing errors */
                if (packet[1] & FTDI_RS_BI) {
                        flag = TTY_BREAK;
-                       priv->icount.brk++;
+                       port->icount.brk++;
                        usb_serial_handle_break(port);
                } else if (packet[1] & FTDI_RS_PE) {
                        flag = TTY_PARITY;
-                       priv->icount.parity++;
+                       port->icount.parity++;
                } else if (packet[1] & FTDI_RS_FE) {
                        flag = TTY_FRAME;
-                       priv->icount.frame++;
+                       port->icount.frame++;
                }
                /* Overrun is special, not associated with a char */
                if (packet[1] & FTDI_RS_OE) {
-                       priv->icount.overrun++;
+                       port->icount.overrun++;
                        tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
                }
        }
@@ -2020,7 +1993,7 @@ static int ftdi_process_packet(struct usb_serial_port *port,
        len -= 2;
        if (!len)
                return 0;       /* status only */
-       priv->icount.rx += len;
+       port->icount.rx += len;
        ch = packet + 2;
 
        if (port->port.console && port->sysrq) {
@@ -2384,34 +2357,10 @@ static int ftdi_tiocmset(struct tty_struct *tty,
        return update_mctrl(port, set, clear);
 }
 
-static int ftdi_get_icount(struct tty_struct *tty,
-                               struct serial_icounter_struct *icount)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct ftdi_private *priv = usb_get_serial_port_data(port);
-       struct async_icount *ic = &priv->icount;
-
-       icount->cts = ic->cts;
-       icount->dsr = ic->dsr;
-       icount->rng = ic->rng;
-       icount->dcd = ic->dcd;
-       icount->tx = ic->tx;
-       icount->rx = ic->rx;
-       icount->frame = ic->frame;
-       icount->parity = ic->parity;
-       icount->overrun = ic->overrun;
-       icount->brk = ic->brk;
-       icount->buf_overrun = ic->buf_overrun;
-       return 0;
-}
-
 static int ftdi_ioctl(struct tty_struct *tty,
                                        unsigned int cmd, unsigned long arg)
 {
        struct usb_serial_port *port = tty->driver_data;
-       struct ftdi_private *priv = usb_get_serial_port_data(port);
-       struct async_icount cnow;
-       struct async_icount cprev;
 
        dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd);
 
@@ -2425,35 +2374,6 @@ static int ftdi_ioctl(struct tty_struct *tty,
        case TIOCSSERIAL: /* sets serial port data */
                return set_serial_info(tty, port,
                                        (struct serial_struct __user *) arg);
-
-       /*
-        * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
-        * - mask passed in arg for lines of interest
-        *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
-        * Caller should use TIOCGICOUNT to see which one it was.
-        *
-        * This code is borrowed from linux/drivers/char/serial.c
-        */
-       case TIOCMIWAIT:
-               cprev = priv->icount;
-               for (;;) {
-                       interruptible_sleep_on(&port->delta_msr_wait);
-                       /* see if a signal did it */
-                       if (signal_pending(current))
-                               return -ERESTARTSYS;
-
-                       if (port->serial->disconnected)
-                               return -EIO;
-
-                       cnow = priv->icount;
-                       if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-                           ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-                           ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-                           ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-                               return 0;
-                       }
-                       cprev = cnow;
-               }
        case TIOCSERGETLSR:
                return get_lsr_info(port, (struct serial_struct __user *)arg);
                break;
index e79861eeed4cca1471e4531ff727f0f8425e7892..98528270c43c21f5f8d66ccf594a269b32f0600f 100644 (file)
@@ -74,6 +74,7 @@
 #define FTDI_OPENDCC_THROTTLE_PID      0xBFDA
 #define FTDI_OPENDCC_GATEWAY_PID       0xBFDB
 #define FTDI_OPENDCC_GBM_PID   0xBFDC
+#define FTDI_OPENDCC_GBM_BOOST_PID     0xBFDD
 
 /* NZR SEM 16+ USB (http://www.nzr.de) */
 #define FTDI_NZR_SEM_USB_PID   0xC1E0  /* NZR SEM-LOG16+ */
  * STMicroelectonics
  */
 #define ST_VID                 0x0483
-#define ST_STMCLT1030_PID      0x3747 /* ST Micro Connect Lite STMCLT1030 */
+#define ST_STMCLT_2232_PID     0x3746
+#define ST_STMCLT_4232_PID     0x3747
 
 /*
  * Papouch products (http://www.papouch.com/)
index 81caf5623ee295d609acce00a1e06a20ef34c20f..b110c573ea85319490922d8f3c538d507913c060 100644 (file)
@@ -946,16 +946,12 @@ static int garmin_open(struct tty_struct *tty, struct usb_serial_port *port)
 
 static void garmin_close(struct usb_serial_port *port)
 {
-       struct usb_serial *serial = port->serial;
        struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 
        dev_dbg(&port->dev, "%s - port %d - mode=%d state=%d flags=0x%X\n",
                __func__, port->number, garmin_data_p->mode,
                garmin_data_p->state, garmin_data_p->flags);
 
-       if (!serial)
-               return;
-
        garmin_clear(garmin_data_p);
 
        /* shutdown our urbs */
@@ -1185,17 +1181,11 @@ static void garmin_read_bulk_callback(struct urb *urb)
 {
        unsigned long flags;
        struct usb_serial_port *port = urb->context;
-       struct usb_serial *serial =  port->serial;
        struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
        unsigned char *data = urb->transfer_buffer;
        int status = urb->status;
        int retval;
 
-       if (!serial) {
-               dev_dbg(&urb->dev->dev, "%s - bad serial pointer, exiting\n", __func__);
-               return;
-       }
-
        if (status) {
                dev_dbg(&urb->dev->dev, "%s - nonzero read bulk status received: %d\n",
                        __func__, status);
index 4c5c23f1cae5db8a5ff157cbe0277dfb4bc42e5d..297665fdd16d31993a5e95cddd313626453be6c7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * USB Serial Converter Generic functions
  *
- * Copyright (C) 2010 - 2011 Johan Hovold (jhovold@gmail.com)
+ * Copyright (C) 2010 - 2013 Johan Hovold (jhovold@gmail.com)
  * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
  *
  *     This program is free software; you can redistribute it and/or
@@ -45,8 +45,6 @@ struct usb_serial_driver usb_serial_generic_device = {
        },
        .id_table =             generic_device_ids,
        .num_ports =            1,
-       .disconnect =           usb_serial_generic_disconnect,
-       .release =              usb_serial_generic_release,
        .throttle =             usb_serial_generic_throttle,
        .unthrottle =           usb_serial_generic_unthrottle,
        .resume =               usb_serial_generic_resume,
@@ -102,32 +100,23 @@ int usb_serial_generic_open(struct tty_struct *tty, struct usb_serial_port *port
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_open);
 
-static void generic_cleanup(struct usb_serial_port *port)
+void usb_serial_generic_close(struct usb_serial_port *port)
 {
-       struct usb_serial *serial = port->serial;
        unsigned long flags;
        int i;
 
-       if (serial->dev) {
-               /* shutdown any bulk transfers that might be going on */
-               if (port->bulk_out_size) {
-                       for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
-                               usb_kill_urb(port->write_urbs[i]);
+       if (port->bulk_out_size) {
+               for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
+                       usb_kill_urb(port->write_urbs[i]);
 
-                       spin_lock_irqsave(&port->lock, flags);
-                       kfifo_reset_out(&port->write_fifo);
-                       spin_unlock_irqrestore(&port->lock, flags);
-               }
-               if (port->bulk_in_size) {
-                       for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
-                               usb_kill_urb(port->read_urbs[i]);
-               }
+               spin_lock_irqsave(&port->lock, flags);
+               kfifo_reset_out(&port->write_fifo);
+               spin_unlock_irqrestore(&port->lock, flags);
+       }
+       if (port->bulk_in_size) {
+               for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
+                       usb_kill_urb(port->read_urbs[i]);
        }
-}
-
-void usb_serial_generic_close(struct usb_serial_port *port)
-{
-       generic_cleanup(port);
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_close);
 
@@ -272,8 +261,7 @@ static int usb_serial_generic_submit_read_urb(struct usb_serial_port *port,
        if (!test_and_clear_bit(index, &port->read_urbs_free))
                return 0;
 
-       dev_dbg(&port->dev, "%s - port %d, urb %d\n", __func__,
-               port->number, index);
+       dev_dbg(&port->dev, "%s - urb %d\n", __func__, index);
 
        res = usb_submit_urb(port->read_urbs[index], mem_flags);
        if (res) {
@@ -347,8 +335,8 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb)
        }
        set_bit(i, &port->read_urbs_free);
 
-       dev_dbg(&port->dev, "%s - port %d, urb %d, len %d\n",
-               __func__, port->number, i, urb->actual_length);
+       dev_dbg(&port->dev, "%s - urb %d, len %d\n", __func__, i,
+                                                       urb->actual_length);
 
        if (urb->status) {
                dev_dbg(&port->dev, "%s - non-zero urb status: %d\n",
@@ -430,6 +418,91 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty)
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_unthrottle);
 
+static bool usb_serial_generic_msr_changed(struct tty_struct *tty,
+                               unsigned long arg, struct async_icount *cprev)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       struct async_icount cnow;
+       unsigned long flags;
+       bool ret;
+
+       /*
+        * Use tty-port initialised flag to detect all hangups including the
+        * one generated at USB-device disconnect.
+        *
+        * FIXME: Remove hupping check once tty_port_hangup calls shutdown
+        *        (which clears the initialised flag) before wake up.
+        */
+       if (test_bit(TTY_HUPPING, &tty->flags))
+               return true;
+       if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+               return true;
+
+       spin_lock_irqsave(&port->lock, flags);
+       cnow = port->icount;                            /* atomic copy*/
+       spin_unlock_irqrestore(&port->lock, flags);
+
+       ret =   ((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) ||
+               ((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) ||
+               ((arg & TIOCM_CD)  && (cnow.dcd != cprev->dcd)) ||
+               ((arg & TIOCM_CTS) && (cnow.cts != cprev->cts));
+
+       *cprev = cnow;
+
+       return ret;
+}
+
+int usb_serial_generic_tiocmiwait(struct tty_struct *tty, unsigned long arg)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       struct async_icount cnow;
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&port->lock, flags);
+       cnow = port->icount;                            /* atomic copy */
+       spin_unlock_irqrestore(&port->lock, flags);
+
+       ret = wait_event_interruptible(port->port.delta_msr_wait,
+                       usb_serial_generic_msr_changed(tty, arg, &cnow));
+       if (!ret) {
+               if (test_bit(TTY_HUPPING, &tty->flags))
+                       ret = -EIO;
+               if (!test_bit(ASYNCB_INITIALIZED, &port->port.flags))
+                       ret = -EIO;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(usb_serial_generic_tiocmiwait);
+
+int usb_serial_generic_get_icount(struct tty_struct *tty,
+                                       struct serial_icounter_struct *icount)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       struct async_icount cnow;
+       unsigned long flags;
+
+       spin_lock_irqsave(&port->lock, flags);
+       cnow = port->icount;                            /* atomic copy */
+       spin_unlock_irqrestore(&port->lock, flags);
+
+       icount->cts = cnow.cts;
+       icount->dsr = cnow.dsr;
+       icount->rng = cnow.rng;
+       icount->dcd = cnow.dcd;
+       icount->tx = cnow.tx;
+       icount->rx = cnow.rx;
+       icount->frame = cnow.frame;
+       icount->parity = cnow.parity;
+       icount->overrun = cnow.overrun;
+       icount->brk = cnow.brk;
+       icount->buf_overrun = cnow.buf_overrun;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(usb_serial_generic_get_icount);
+
 #ifdef CONFIG_MAGIC_SYSRQ
 int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch)
 {
@@ -473,8 +546,7 @@ void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port,
 {
        struct tty_port *port = &usb_port->port;
 
-       dev_dbg(&usb_port->dev, "%s - port %d, status %d\n", __func__,
-               usb_port->number, status);
+       dev_dbg(&usb_port->dev, "%s - status %d\n", __func__, status);
 
        if (status)
                wake_up_interruptible(&port->open_wait);
@@ -510,17 +582,3 @@ int usb_serial_generic_resume(struct usb_serial *serial)
        return c ? -EIO : 0;
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_resume);
-
-void usb_serial_generic_disconnect(struct usb_serial *serial)
-{
-       int i;
-
-       /* stop reads and writes on all ports */
-       for (i = 0; i < serial->num_ports; ++i)
-               generic_cleanup(serial->port[i]);
-}
-EXPORT_SYMBOL_GPL(usb_serial_generic_disconnect);
-
-void usb_serial_generic_release(struct usb_serial *serial)
-{
-}
index cf0b0a2f7b564ee854fa95fd30ced39e8d1a3d60..1477e8593476deb54a831e3169c00c42e705c50a 100644 (file)
@@ -111,7 +111,6 @@ struct edgeport_port {
        wait_queue_head_t       wait_open;              /* for handling sleeping while waiting for open to finish */
        wait_queue_head_t       wait_command;           /* for handling sleeping while waiting for command to finish */
 
-       struct async_icount     icount;
        struct usb_serial_port  *port;                  /* loop back to the owner of this object */
 };
 
@@ -215,8 +214,6 @@ static void edge_break(struct tty_struct *tty, int break_state);
 static int  edge_tiocmget(struct tty_struct *tty);
 static int  edge_tiocmset(struct tty_struct *tty,
                                        unsigned int set, unsigned int clear);
-static int  edge_get_icount(struct tty_struct *tty,
-                               struct serial_icounter_struct *icount);
 static int  edge_startup(struct usb_serial *serial);
 static void edge_disconnect(struct usb_serial *serial);
 static void edge_release(struct usb_serial *serial);
@@ -867,9 +864,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
        init_waitqueue_head(&edge_port->wait_chase);
        init_waitqueue_head(&edge_port->wait_command);
 
-       /* initialize our icount structure */
-       memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
-
        /* initialize our port settings */
        edge_port->txCredits = 0;       /* Can't send any data yet */
        /* Must always set this bit to enable ints! */
@@ -1296,7 +1290,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,
 
        /* decrement the number of credits we have by the number we just sent */
        edge_port->txCredits -= count;
-       edge_port->icount.tx += count;
+       edge_port->port->icount.tx += count;
 
        status = usb_submit_urb(urb, GFP_ATOMIC);
        if (status) {
@@ -1308,7 +1302,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial,
 
                /* revert the credits as something bad happened. */
                edge_port->txCredits += count;
-               edge_port->icount.tx -= count;
+               edge_port->port->icount.tx -= count;
        }
        dev_dbg(dev, "%s wrote %d byte(s) TxCredit %d, Fifo %d\n",
                __func__, count, edge_port->txCredits, fifo->count);
@@ -1570,31 +1564,6 @@ static int edge_tiocmget(struct tty_struct *tty)
        return result;
 }
 
-static int edge_get_icount(struct tty_struct *tty,
-                               struct serial_icounter_struct *icount)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct edgeport_port *edge_port = usb_get_serial_port_data(port);
-       struct async_icount cnow;
-       cnow = edge_port->icount;
-
-       icount->cts = cnow.cts;
-       icount->dsr = cnow.dsr;
-       icount->rng = cnow.rng;
-       icount->dcd = cnow.dcd;
-       icount->rx = cnow.rx;
-       icount->tx = cnow.tx;
-       icount->frame = cnow.frame;
-       icount->overrun = cnow.overrun;
-       icount->parity = cnow.parity;
-       icount->brk = cnow.brk;
-       icount->buf_overrun = cnow.buf_overrun;
-
-       dev_dbg(&port->dev, "%s (%d) TIOCGICOUNT RX=%d, TX=%d\n", __func__,
-               port->number, icount->rx, icount->tx);
-       return 0;
-}
-
 static int get_serial_info(struct edgeport_port *edge_port,
                                struct serial_struct __user *retinfo)
 {
@@ -1631,8 +1600,6 @@ static int edge_ioctl(struct tty_struct *tty,
        struct usb_serial_port *port = tty->driver_data;
        DEFINE_WAIT(wait);
        struct edgeport_port *edge_port = usb_get_serial_port_data(port);
-       struct async_icount cnow;
-       struct async_icount cprev;
 
        dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd);
 
@@ -1644,37 +1611,6 @@ static int edge_ioctl(struct tty_struct *tty,
        case TIOCGSERIAL:
                dev_dbg(&port->dev, "%s (%d) TIOCGSERIAL\n", __func__,  port->number);
                return get_serial_info(edge_port, (struct serial_struct __user *) arg);
-
-       case TIOCMIWAIT:
-               dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,  port->number);
-               cprev = edge_port->icount;
-               while (1) {
-                       prepare_to_wait(&port->delta_msr_wait,
-                                               &wait, TASK_INTERRUPTIBLE);
-                       schedule();
-                       finish_wait(&port->delta_msr_wait, &wait);
-                       /* see if a signal did it */
-                       if (signal_pending(current))
-                               return -ERESTARTSYS;
-
-                       if (port->serial->disconnected)
-                               return -EIO;
-
-                       cnow = edge_port->icount;
-                       if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-                           cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-                               return -EIO; /* no change => error */
-                       if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-                           ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-                           ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-                           ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-                               return 0;
-                       }
-                       cprev = cnow;
-               }
-               /* NOTREACHED */
-               break;
-
        }
        return -ENOIOCTLCMD;
 }
@@ -1848,7 +1784,7 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,
                                                edge_serial->rxPort);
                                        edge_tty_recv(edge_port->port, buffer,
                                                        rxLen);
-                                       edge_port->icount.rx += rxLen;
+                                       edge_port->port->icount.rx += rxLen;
                                }
                                buffer += rxLen;
                        }
@@ -2024,7 +1960,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
 
        if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR |
                        EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
-               icount = &edge_port->icount;
+               icount = &edge_port->port->icount;
 
                /* update input line counters */
                if (newMsr & EDGEPORT_MSR_DELTA_CTS)
@@ -2035,7 +1971,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
                        icount->dcd++;
                if (newMsr & EDGEPORT_MSR_DELTA_RI)
                        icount->rng++;
-               wake_up_interruptible(&edge_port->port->delta_msr_wait);
+               wake_up_interruptible(&edge_port->port->port.delta_msr_wait);
        }
 
        /* Save the new modem status */
@@ -2070,7 +2006,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData,
                edge_tty_recv(edge_port->port, &data, 1);
 
        /* update input line counters */
-       icount = &edge_port->icount;
+       icount = &edge_port->port->icount;
        if (newLsr & LSR_BREAK)
                icount->brk++;
        if (newLsr & LSR_OVER_ERR)
index 1511dd0ad3242650e6da605d316b2d7165b1fb2d..ae5fac5656c90f7d8e15d820c643c954de415242 100644 (file)
@@ -116,7 +116,8 @@ static struct usb_serial_driver edgeport_2port_device = {
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
        .tiocmset               = edge_tiocmset,
-       .get_icount             = edge_get_icount,
+       .tiocmiwait             = usb_serial_generic_tiocmiwait,
+       .get_icount             = usb_serial_generic_get_icount,
        .write                  = edge_write,
        .write_room             = edge_write_room,
        .chars_in_buffer        = edge_chars_in_buffer,
@@ -147,7 +148,8 @@ static struct usb_serial_driver edgeport_4port_device = {
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
        .tiocmset               = edge_tiocmset,
-       .get_icount             = edge_get_icount,
+       .tiocmiwait             = usb_serial_generic_tiocmiwait,
+       .get_icount             = usb_serial_generic_get_icount,
        .write                  = edge_write,
        .write_room             = edge_write_room,
        .chars_in_buffer        = edge_chars_in_buffer,
@@ -178,7 +180,8 @@ static struct usb_serial_driver edgeport_8port_device = {
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
        .tiocmset               = edge_tiocmset,
-       .get_icount             = edge_get_icount,
+       .tiocmiwait             = usb_serial_generic_tiocmiwait,
+       .get_icount             = usb_serial_generic_get_icount,
        .write                  = edge_write,
        .write_room             = edge_write_room,
        .chars_in_buffer        = edge_chars_in_buffer,
@@ -209,7 +212,8 @@ static struct usb_serial_driver epic_device = {
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
        .tiocmset               = edge_tiocmset,
-       .get_icount             = edge_get_icount,
+       .tiocmiwait             = usb_serial_generic_tiocmiwait,
+       .get_icount             = usb_serial_generic_get_icount,
        .write                  = edge_write,
        .write_room             = edge_write_room,
        .chars_in_buffer        = edge_chars_in_buffer,
index 7777172206de1b42a971acb0747d97180230d670..158bf4bc29cc2b6f60c7211ad0e9f8b75186bf04 100644 (file)
@@ -86,7 +86,7 @@ struct edgeport_port {
        int baud_rate;
        int close_pending;
        int lsr_event;
-       struct async_icount     icount;
+
        struct edgeport_serial  *edge_serial;
        struct usb_serial_port  *port;
        __u8 bUartMode;         /* Port type, 0: RS232, etc. */
@@ -206,7 +206,7 @@ static int restart_read(struct edgeport_port *edge_port);
 
 static void edge_set_termios(struct tty_struct *tty,
                struct usb_serial_port *port, struct ktermios *old_termios);
-static void edge_send(struct tty_struct *tty);
+static void edge_send(struct usb_serial_port *port, struct tty_struct *tty);
 
 /* sysfs attributes */
 static int edge_create_sysfs_attrs(struct usb_serial_port *port);
@@ -1445,7 +1445,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
 
        if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR |
                        EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) {
-               icount = &edge_port->icount;
+               icount = &edge_port->port->icount;
 
                /* update input line counters */
                if (msr & EDGEPORT_MSR_DELTA_CTS)
@@ -1456,7 +1456,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
                        icount->dcd++;
                if (msr & EDGEPORT_MSR_DELTA_RI)
                        icount->rng++;
-               wake_up_interruptible(&edge_port->port->delta_msr_wait);
+               wake_up_interruptible(&edge_port->port->port.delta_msr_wait);
        }
 
        /* Save the new modem status */
@@ -1498,7 +1498,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data,
                edge_tty_recv(edge_port->port, &data, 1);
 
        /* update input line counters */
-       icount = &edge_port->icount;
+       icount = &edge_port->port->icount;
        if (new_lsr & LSR_BREAK)
                icount->brk++;
        if (new_lsr & LSR_OVER_ERR)
@@ -1657,7 +1657,7 @@ static void edge_bulk_in_callback(struct urb *urb)
                else
                        edge_tty_recv(edge_port->port, data,
                                        urb->actual_length);
-               edge_port->icount.rx += urb->actual_length;
+               edge_port->port->icount.rx += urb->actual_length;
        }
 
 exit:
@@ -1712,7 +1712,7 @@ static void edge_bulk_out_callback(struct urb *urb)
 
        /* send any buffered data */
        tty = tty_port_tty_get(&port->port);
-       edge_send(tty);
+       edge_send(port, tty);
        tty_kref_put(tty);
 }
 
@@ -1750,8 +1750,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
 
        dev = port->serial->dev;
 
-       memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
-
        /* turn off loopback */
        status = ti_do_config(edge_port, UMPC_SET_CLR_LOOPBACK, 0);
        if (status) {
@@ -1909,21 +1907,10 @@ static void edge_close(struct usb_serial_port *port)
        kfifo_reset_out(&edge_port->write_fifo);
        spin_unlock_irqrestore(&edge_port->ep_lock, flags);
 
-       /* assuming we can still talk to the device,
-        * send a close port command to it */
        dev_dbg(&port->dev, "%s - send umpc_close_port\n", __func__);
        port_number = port->number - port->serial->minor;
-
-       mutex_lock(&serial->disc_mutex);
-       if (!serial->disconnected) {
-               send_cmd(serial->dev,
-                                    UMPC_CLOSE_PORT,
-                                    (__u8)(UMPM_UART1_PORT + port_number),
-                                    0,
-                                    NULL,
-                                    0);
-       }
-       mutex_unlock(&serial->disc_mutex);
+       send_cmd(serial->dev, UMPC_CLOSE_PORT,
+                    (__u8)(UMPM_UART1_PORT + port_number), 0, NULL, 0);
 
        mutex_lock(&edge_serial->es_lock);
        --edge_port->edge_serial->num_ports_open;
@@ -1953,14 +1940,13 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
 
        count = kfifo_in_locked(&edge_port->write_fifo, data, count,
                                                        &edge_port->ep_lock);
-       edge_send(tty);
+       edge_send(port, tty);
 
        return count;
 }
 
-static void edge_send(struct tty_struct *tty)
+static void edge_send(struct usb_serial_port *port, struct tty_struct *tty)
 {
-       struct usb_serial_port *port = tty->driver_data;
        int count, result;
        struct edgeport_port *edge_port = usb_get_serial_port_data(port);
        unsigned long flags;
@@ -1999,7 +1985,7 @@ static void edge_send(struct tty_struct *tty)
                edge_port->ep_write_urb_in_use = 0;
                /* TODO: reschedule edge_send */
        } else
-               edge_port->icount.tx += count;
+               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 */
@@ -2360,27 +2346,6 @@ static int edge_tiocmget(struct tty_struct *tty)
        return result;
 }
 
-static int edge_get_icount(struct tty_struct *tty,
-                               struct serial_icounter_struct *icount)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct edgeport_port *edge_port = usb_get_serial_port_data(port);
-       struct async_icount *ic = &edge_port->icount;
-
-       icount->cts = ic->cts;
-       icount->dsr = ic->dsr;
-       icount->rng = ic->rng;
-       icount->dcd = ic->dcd;
-       icount->tx = ic->tx;
-        icount->rx = ic->rx;
-        icount->frame = ic->frame;
-        icount->parity = ic->parity;
-        icount->overrun = ic->overrun;
-        icount->brk = ic->brk;
-        icount->buf_overrun = ic->buf_overrun;
-       return 0;
-}
-
 static int get_serial_info(struct edgeport_port *edge_port,
                                struct serial_struct __user *retinfo)
 {
@@ -2392,7 +2357,7 @@ static int get_serial_info(struct edgeport_port *edge_port,
 
        cwait = edge_port->port->port.closing_wait;
        if (cwait != ASYNC_CLOSING_WAIT_NONE)
-               cwait = jiffies_to_msecs(closing_wait) / 10;
+               cwait = jiffies_to_msecs(cwait) / 10;
 
        memset(&tmp, 0, sizeof(tmp));
 
@@ -2416,8 +2381,6 @@ static int edge_ioctl(struct tty_struct *tty,
 {
        struct usb_serial_port *port = tty->driver_data;
        struct edgeport_port *edge_port = usb_get_serial_port_data(port);
-       struct async_icount cnow;
-       struct async_icount cprev;
 
        dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd);
 
@@ -2426,32 +2389,6 @@ static int edge_ioctl(struct tty_struct *tty,
                dev_dbg(&port->dev, "%s - TIOCGSERIAL\n", __func__);
                return get_serial_info(edge_port,
                                (struct serial_struct __user *) arg);
-       case TIOCMIWAIT:
-               dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__);
-               cprev = edge_port->icount;
-               while (1) {
-                       interruptible_sleep_on(&port->delta_msr_wait);
-                       /* see if a signal did it */
-                       if (signal_pending(current))
-                               return -ERESTARTSYS;
-
-                       if (port->serial->disconnected)
-                               return -EIO;
-
-                       cnow = edge_port->icount;
-                       if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-                           cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-                               return -EIO; /* no change => error */
-                       if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-                           ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-                           ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-                           ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-                               return 0;
-                       }
-                       cprev = cnow;
-               }
-               /* not reached */
-               break;
        }
        return -ENOIOCTLCMD;
 }
@@ -2463,8 +2400,6 @@ static void edge_break(struct tty_struct *tty, int break_state)
        int status;
        int bv = 0;     /* Off */
 
-       tty_wait_until_sent(tty, 0);
-
        if (break_state == -1)
                bv = 1; /* On */
        status = ti_do_config(edge_port, UMPC_SET_CLR_BREAK, bv);
@@ -2546,7 +2481,6 @@ static int edge_port_remove(struct usb_serial_port *port)
        struct edgeport_port *edge_port;
 
        edge_port = usb_get_serial_port_data(port);
-
        edge_remove_sysfs_attrs(port);
        kfifo_free(&edge_port->write_fifo);
        kfree(edge_port);
@@ -2618,7 +2552,8 @@ static struct usb_serial_driver edgeport_1port_device = {
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
        .tiocmset               = edge_tiocmset,
-       .get_icount             = edge_get_icount,
+       .tiocmiwait             = usb_serial_generic_tiocmiwait,
+       .get_icount             = usb_serial_generic_get_icount,
        .write                  = edge_write,
        .write_room             = edge_write_room,
        .chars_in_buffer        = edge_chars_in_buffer,
@@ -2649,7 +2584,8 @@ static struct usb_serial_driver edgeport_2port_device = {
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
        .tiocmset               = edge_tiocmset,
-       .get_icount             = edge_get_icount,
+       .tiocmiwait             = usb_serial_generic_tiocmiwait,
+       .get_icount             = usb_serial_generic_get_icount,
        .write                  = edge_write,
        .write_room             = edge_write_room,
        .chars_in_buffer        = edge_chars_in_buffer,
index ff77027160aab7eca0ac78e4f78ae1c8e7f01877..9d74c278b7b58d5f9ce6878d35d5ff66d869a5cf 100644 (file)
@@ -55,7 +55,6 @@ static void read_rxcmd_callback(struct urb *urb);
 
 struct iuu_private {
        spinlock_t lock;        /* store irq state */
-       wait_queue_head_t delta_msr_wait;
        u8 line_status;
        int tiostatus;          /* store IUART SIGNAL for tiocmget call */
        u8 reset;               /* if 1 reset is needed */
@@ -94,7 +93,6 @@ static int iuu_port_probe(struct usb_serial_port *port)
 
        priv->vcc = vcc_default;
        spin_lock_init(&priv->lock);
-       init_waitqueue_head(&priv->delta_msr_wait);
 
        usb_set_serial_port_data(port, priv);
 
@@ -944,22 +942,13 @@ static void iuu_set_termios(struct tty_struct *tty,
 static void iuu_close(struct usb_serial_port *port)
 {
        /* iuu_led (port,255,0,0,0); */
-       struct usb_serial *serial;
-
-       serial = port->serial;
-       if (!serial)
-               return;
 
        iuu_uart_off(port);
-       if (serial->dev) {
-               /* free writebuf */
-               /* shutdown our urbs */
-               dev_dbg(&port->dev, "%s - shutting down urbs\n", __func__);
-               usb_kill_urb(port->write_urb);
-               usb_kill_urb(port->read_urb);
-               usb_kill_urb(port->interrupt_in_urb);
-               iuu_led(port, 0, 0, 0xF000, 0xFF);
-       }
+
+       usb_kill_urb(port->write_urb);
+       usb_kill_urb(port->read_urb);
+
+       iuu_led(port, 0, 0, 0xF000, 0xFF);
 }
 
 static void iuu_init_termios(struct tty_struct *tty)
index b011478d2e5f43cffc8923f3264d69d9a4facceb..eb30d7b01f3681bd00c7fe73827533a613f162b6 100644 (file)
@@ -712,45 +712,45 @@ static void usa49wg_indat_callback(struct urb *urb)
        i = 0;
        len = 0;
 
-       if (urb->actual_length) {
-               while (i < urb->actual_length) {
+       while (i < urb->actual_length) {
 
-                       /* Check port number from message*/
-                       if (data[i] >= serial->num_ports) {
-                               dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
-                                       __func__, data[i]);
-                               return;
-                       }
-                       port = serial->port[data[i++]];
-                       len = data[i++];
+               /* Check port number from message */
+               if (data[i] >= serial->num_ports) {
+                       dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n",
+                               __func__, data[i]);
+                       return;
+               }
+               port = serial->port[data[i++]];
+               len = data[i++];
 
-                       /* 0x80 bit is error flag */
-                       if ((data[i] & 0x80) == 0) {
-                               /* no error on any byte */
-                               i++;
-                               for (x = 1; x < len ; ++x)
-                                       tty_insert_flip_char(&port->port,
-                                                       data[i++], 0);
-                       } else {
-                               /*
-                                * some bytes had errors, every byte has status
-                                */
-                               for (x = 0; x + 1 < len; x += 2) {
-                                       int stat = data[i], flag = 0;
-                                       if (stat & RXERROR_OVERRUN)
-                                               flag |= TTY_OVERRUN;
-                                       if (stat & RXERROR_FRAMING)
-                                               flag |= TTY_FRAME;
-                                       if (stat & RXERROR_PARITY)
-                                               flag |= TTY_PARITY;
-                                       /* XXX should handle break (0x10) */
-                                       tty_insert_flip_char(&port->port,
-                                                       data[i+1], flag);
-                                       i += 2;
-                               }
+               /* 0x80 bit is error flag */
+               if ((data[i] & 0x80) == 0) {
+                       /* no error on any byte */
+                       i++;
+                       for (x = 1; x < len && i < urb->actual_length; ++x)
+                               tty_insert_flip_char(&port->port,
+                                               data[i++], 0);
+               } else {
+                       /*
+                        * some bytes had errors, every byte has status
+                        */
+                       for (x = 0; x + 1 < len &&
+                                   i + 1 < urb->actual_length; x += 2) {
+                               int stat = data[i], flag = 0;
+
+                               if (stat & RXERROR_OVERRUN)
+                                       flag |= TTY_OVERRUN;
+                               if (stat & RXERROR_FRAMING)
+                                       flag |= TTY_FRAME;
+                               if (stat & RXERROR_PARITY)
+                                       flag |= TTY_PARITY;
+                               /* XXX should handle break (0x10) */
+                               tty_insert_flip_char(&port->port, data[i+1],
+                                                    flag);
+                               i += 2;
                        }
-                       tty_flip_buffer_push(&port->port);
                }
+               tty_flip_buffer_push(&port->port);
        }
 
        /* Resubmit urb so we continue receiving */
@@ -1092,7 +1092,6 @@ static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
 static void keyspan_close(struct usb_serial_port *port)
 {
        int                     i;
-       struct usb_serial       *serial = port->serial;
        struct keyspan_port_private     *p_priv;
 
        p_priv = usb_get_serial_port_data(port);
@@ -1100,28 +1099,17 @@ static void keyspan_close(struct usb_serial_port *port)
        p_priv->rts_state = 0;
        p_priv->dtr_state = 0;
 
-       if (serial->dev) {
-               keyspan_send_setup(port, 2);
-               /* pilot-xfer seems to work best with this delay */
-               mdelay(100);
-               /* keyspan_set_termios(port, NULL); */
-       }
-
-       /*while (p_priv->outcont_urb->status == -EINPROGRESS) {
-               dev_dbg(&port->dev, "%s - urb in progress\n", __func__);
-       }*/
+       keyspan_send_setup(port, 2);
+       /* pilot-xfer seems to work best with this delay */
+       mdelay(100);
 
        p_priv->out_flip = 0;
        p_priv->in_flip = 0;
 
-       if (serial->dev) {
-               /* Stop reading/writing urbs */
-               stop_urb(p_priv->inack_urb);
-               /* stop_urb(p_priv->outcont_urb); */
-               for (i = 0; i < 2; i++) {
-                       stop_urb(p_priv->in_urbs[i]);
-                       stop_urb(p_priv->out_urbs[i]);
-               }
+       stop_urb(p_priv->inack_urb);
+       for (i = 0; i < 2; i++) {
+               stop_urb(p_priv->in_urbs[i]);
+               stop_urb(p_priv->out_urbs[i]);
        }
 }
 
index 2230223978ca731bef98ffb09b121ad974ff649f..5f1d382e55cfbd3b673c4b26dbf7863fbf0d4be2 100644 (file)
@@ -593,12 +593,10 @@ static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on)
 {
        struct usb_serial *serial = port->serial;
 
-       if (serial->dev) {
-               if (on)
-                       keyspan_pda_set_modem_info(serial, (1<<7) | (1<< 2));
-               else
-                       keyspan_pda_set_modem_info(serial, 0);
-       }
+       if (on)
+               keyspan_pda_set_modem_info(serial, (1 << 7) | (1 << 2));
+       else
+               keyspan_pda_set_modem_info(serial, 0);
 }
 
 
@@ -649,13 +647,8 @@ error:
 }
 static void keyspan_pda_close(struct usb_serial_port *port)
 {
-       struct usb_serial *serial = port->serial;
-
-       if (serial->dev) {
-               /* shutdown our bulk reads and writes */
-               usb_kill_urb(port->write_urb);
-               usb_kill_urb(port->interrupt_in_urb);
-       }
+       usb_kill_urb(port->write_urb);
+       usb_kill_urb(port->interrupt_in_urb);
 }
 
 
index 769d910ae0a5d789cf933659867fee715fc6be8a..1b4054fe52a5fccf85d4be4cbe4cbb3b30ff03b7 100644 (file)
@@ -341,28 +341,20 @@ static void klsi_105_close(struct usb_serial_port *port)
 {
        int rc;
 
-       mutex_lock(&port->serial->disc_mutex);
-       if (!port->serial->disconnected) {
-               /* send READ_OFF */
-               rc = usb_control_msg(port->serial->dev,
-                                    usb_sndctrlpipe(port->serial->dev, 0),
-                                    KL5KUSB105A_SIO_CONFIGURE,
-                                    USB_TYPE_VENDOR | USB_DIR_OUT,
-                                    KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
-                                    0, /* index */
-                                    NULL, 0,
-                                    KLSI_TIMEOUT);
-               if (rc < 0)
-                       dev_err(&port->dev,
-                               "Disabling read failed (error = %d)\n", rc);
-       }
-       mutex_unlock(&port->serial->disc_mutex);
+       /* send READ_OFF */
+       rc = usb_control_msg(port->serial->dev,
+                            usb_sndctrlpipe(port->serial->dev, 0),
+                            KL5KUSB105A_SIO_CONFIGURE,
+                            USB_TYPE_VENDOR | USB_DIR_OUT,
+                            KL5KUSB105A_SIO_CONFIGURE_READ_OFF,
+                            0, /* index */
+                            NULL, 0,
+                            KLSI_TIMEOUT);
+       if (rc < 0)
+               dev_err(&port->dev, "failed to disable read: %d\n", rc);
 
        /* shutdown our bulk reads and writes */
        usb_serial_generic_close(port);
-
-       /* wgg - do I need this? I think so. */
-       usb_kill_urb(port->interrupt_in_urb);
 }
 
 /* We need to write a complete 64-byte data block and encode the
index 903d938e174ba074d85ebeff36ba1a9da39a2074..78b48c31abf5cb335f24d822643a2003e80f43ee 100644 (file)
@@ -65,7 +65,7 @@ static int  kobil_tiocmget(struct tty_struct *tty);
 static int  kobil_tiocmset(struct tty_struct *tty,
                           unsigned int set, unsigned int clear);
 static void kobil_read_int_callback(struct urb *urb);
-static void kobil_write_callback(struct urb *purb);
+static void kobil_write_int_callback(struct urb *urb);
 static void kobil_set_termios(struct tty_struct *tty,
                        struct usb_serial_port *port, struct ktermios *old);
 static void kobil_init_termios(struct tty_struct *tty);
@@ -99,6 +99,7 @@ static struct usb_serial_driver kobil_device = {
        .write =                kobil_write,
        .write_room =           kobil_write_room,
        .read_int_callback =    kobil_read_int_callback,
+       .write_int_callback =   kobil_write_int_callback,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -106,8 +107,6 @@ static struct usb_serial_driver * const serial_drivers[] = {
 };
 
 struct kobil_private {
-       int write_int_endpoint_address;
-       int read_int_endpoint_address;
        unsigned char buf[KOBIL_BUF_LENGTH]; /* buffer for the APDU to send */
        int filled;  /* index of the last char in buf */
        int cur_pos; /* index of the next char to send in buf */
@@ -117,14 +116,8 @@ struct kobil_private {
 
 static int kobil_port_probe(struct usb_serial_port *port)
 {
-       int i;
        struct usb_serial *serial = port->serial;
        struct kobil_private *priv;
-       struct usb_device *pdev;
-       struct usb_host_config *actconfig;
-       struct usb_interface *interface;
-       struct usb_host_interface *altsetting;
-       struct usb_host_endpoint *endpoint;
 
        priv = kmalloc(sizeof(struct kobil_private), GFP_KERNEL);
        if (!priv)
@@ -150,30 +143,6 @@ static int kobil_port_probe(struct usb_serial_port *port)
        }
        usb_set_serial_port_data(port, priv);
 
-       /* search for the necessary endpoints */
-       pdev = serial->dev;
-       actconfig = pdev->actconfig;
-       interface = actconfig->interface[0];
-       altsetting = interface->cur_altsetting;
-       endpoint = altsetting->endpoint;
-
-       for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
-               endpoint = &altsetting->endpoint[i];
-               if (usb_endpoint_is_int_out(&endpoint->desc)) {
-                       dev_dbg(&serial->dev->dev,
-                               "%s Found interrupt out endpoint. Address: %d\n",
-                               __func__, endpoint->desc.bEndpointAddress);
-                       priv->write_int_endpoint_address =
-                               endpoint->desc.bEndpointAddress;
-               }
-               if (usb_endpoint_is_int_in(&endpoint->desc)) {
-                       dev_dbg(&serial->dev->dev,
-                               "%s Found interrupt in  endpoint. Address: %d\n",
-                               __func__, endpoint->desc.bEndpointAddress);
-                       priv->read_int_endpoint_address =
-                               endpoint->desc.bEndpointAddress;
-               }
-       }
        return 0;
 }
 
@@ -205,7 +174,6 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
        struct kobil_private *priv;
        unsigned char *transfer_buffer;
        int transfer_buffer_length = 8;
-       int write_urb_transfer_buffer_length = 8;
 
        priv = usb_get_serial_port_data(port);
 
@@ -214,27 +182,6 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
        if (!transfer_buffer)
                return -ENOMEM;
 
-       /* allocate write_urb */
-       if (!port->write_urb) {
-               dev_dbg(dev, "%s - Allocating port->write_urb\n", __func__);
-               port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
-               if (!port->write_urb) {
-                       dev_dbg(dev, "%s - usb_alloc_urb failed\n", __func__);
-                       kfree(transfer_buffer);
-                       return -ENOMEM;
-               }
-       }
-
-       /* allocate memory for write_urb transfer buffer */
-       port->write_urb->transfer_buffer =
-                       kmalloc(write_urb_transfer_buffer_length, GFP_KERNEL);
-       if (!port->write_urb->transfer_buffer) {
-               kfree(transfer_buffer);
-               usb_free_urb(port->write_urb);
-               port->write_urb = NULL;
-               return -ENOMEM;
-       }
-
        /* get hardware version */
        result = usb_control_msg(port->serial->dev,
                          usb_rcvctrlpipe(port->serial->dev, 0),
@@ -310,12 +257,7 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port)
 static void kobil_close(struct usb_serial_port *port)
 {
        /* FIXME: Add rts/dtr methods */
-       if (port->write_urb) {
-               usb_poison_urb(port->write_urb);
-               kfree(port->write_urb->transfer_buffer);
-               usb_free_urb(port->write_urb);
-               port->write_urb = NULL;
-       }
+       usb_kill_urb(port->interrupt_out_urb);
        usb_kill_urb(port->interrupt_in_urb);
 }
 
@@ -333,24 +275,8 @@ static void kobil_read_int_callback(struct urb *urb)
        }
 
        if (urb->actual_length) {
-
-               /* BEGIN DEBUG */
-               /*
-                 char *dbg_data;
-
-                 dbg_data = kzalloc((3 *  purb->actual_length + 10)
-                                               * sizeof(char), GFP_KERNEL);
-                 if (! dbg_data) {
-                         return;
-                 }
-                 for (i = 0; i < purb->actual_length; i++) {
-                         sprintf(dbg_data +3*i, "%02X ", data[i]);
-                 }
-                 dev_dbg(&port->dev, " <-- %s\n", dbg_data);
-                 kfree(dbg_data);
-               */
-               /* END DEBUG */
-
+               usb_serial_debug_data(&port->dev, __func__, urb->actual_length,
+                                                                       data);
                tty_insert_flip_string(&port->port, data, urb->actual_length);
                tty_flip_buffer_push(&port->port);
        }
@@ -360,7 +286,7 @@ static void kobil_read_int_callback(struct urb *urb)
 }
 
 
-static void kobil_write_callback(struct urb *purb)
+static void kobil_write_int_callback(struct urb *urb)
 {
 }
 
@@ -403,23 +329,14 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
 
                while (todo > 0) {
                        /* max 8 byte in one urb (endpoint size) */
-                       length = (todo < 8) ? todo : 8;
+                       length = min(todo, port->interrupt_out_size);
                        /* copy data to transfer buffer */
-                       memcpy(port->write_urb->transfer_buffer,
+                       memcpy(port->interrupt_out_buffer,
                                        priv->buf + priv->cur_pos, length);
-                       usb_fill_int_urb(port->write_urb,
-                                 port->serial->dev,
-                                 usb_sndintpipe(port->serial->dev,
-                                       priv->write_int_endpoint_address),
-                                 port->write_urb->transfer_buffer,
-                                 length,
-                                 kobil_write_callback,
-                                 port,
-                                 8
-                       );
+                       port->interrupt_out_urb->transfer_buffer_length = length;
 
                        priv->cur_pos = priv->cur_pos + length;
-                       result = usb_submit_urb(port->write_urb, GFP_NOIO);
+                       result = usb_submit_urb(port->interrupt_out_urb, GFP_NOIO);
                        dev_dbg(&port->dev, "%s - Send write URB returns: %i\n", __func__, result);
                        todo = priv->filled - priv->cur_pos;
 
index 06d5a60be2c4cb87279744372edef4a41864b74b..6a15adf53360f75994d9e7f3c62d2ac1ff04a461 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 #include <linux/serial.h>
-#include <linux/ioctl.h>
 #include "mct_u232.h"
 
 #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
@@ -44,7 +43,6 @@
 /*
  * Function prototypes
  */
-static int  mct_u232_startup(struct usb_serial *serial);
 static int  mct_u232_port_probe(struct usb_serial_port *port);
 static int  mct_u232_port_remove(struct usb_serial_port *remove);
 static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port);
@@ -57,10 +55,6 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state);
 static int  mct_u232_tiocmget(struct tty_struct *tty);
 static int  mct_u232_tiocmset(struct tty_struct *tty,
                        unsigned int set, unsigned int clear);
-static int  mct_u232_ioctl(struct tty_struct *tty,
-                       unsigned int cmd, unsigned long arg);
-static int  mct_u232_get_icount(struct tty_struct *tty,
-                       struct serial_icounter_struct *icount);
 static void mct_u232_throttle(struct tty_struct *tty);
 static void mct_u232_unthrottle(struct tty_struct *tty);
 
@@ -95,11 +89,10 @@ static struct usb_serial_driver mct_u232_device = {
        .break_ctl =         mct_u232_break_ctl,
        .tiocmget =          mct_u232_tiocmget,
        .tiocmset =          mct_u232_tiocmset,
-       .attach =            mct_u232_startup,
+       .tiocmiwait =        usb_serial_generic_tiocmiwait,
        .port_probe =        mct_u232_port_probe,
        .port_remove =       mct_u232_port_remove,
-       .ioctl =             mct_u232_ioctl,
-       .get_icount =        mct_u232_get_icount,
+       .get_icount =        usb_serial_generic_get_icount,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -107,13 +100,13 @@ static struct usb_serial_driver * const serial_drivers[] = {
 };
 
 struct mct_u232_private {
+       struct urb *read_urb;
        spinlock_t lock;
        unsigned int         control_state; /* Modem Line Setting (TIOCM) */
        unsigned char        last_lcr;      /* Line Control Register */
        unsigned char        last_lsr;      /* Line Status Register */
        unsigned char        last_msr;      /* Modem Status Register */
        unsigned int         rx_flags;      /* Throttling flags */
-       struct async_icount  icount;
 };
 
 #define THROTTLED              0x01
@@ -382,22 +375,6 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port,
  * Driver's tty interface functions
  */
 
-static int mct_u232_startup(struct usb_serial *serial)
-{
-       struct usb_serial_port *port, *rport;
-
-       /* Puh, that's dirty */
-       port = serial->port[0];
-       rport = serial->port[1];
-       /* No unlinking, it wasn't submitted yet. */
-       usb_free_urb(port->read_urb);
-       port->read_urb = rport->interrupt_in_urb;
-       rport->interrupt_in_urb = NULL;
-       port->read_urb->context = port;
-
-       return 0;
-} /* mct_u232_startup */
-
 static int mct_u232_port_probe(struct usb_serial_port *port)
 {
        struct mct_u232_private *priv;
@@ -406,6 +383,10 @@ static int mct_u232_port_probe(struct usb_serial_port *port)
        if (!priv)
                return -ENOMEM;
 
+       /* Use second interrupt-in endpoint for reading. */
+       priv->read_urb = port->serial->port[1]->interrupt_in_urb;
+       priv->read_urb->context = port;
+
        spin_lock_init(&priv->lock);
 
        usb_set_serial_port_data(port, priv);
@@ -469,17 +450,17 @@ static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)
        mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr);
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
+       retval = usb_submit_urb(priv->read_urb, GFP_KERNEL);
        if (retval) {
                dev_err(&port->dev,
-                       "usb_submit_urb(read bulk) failed pipe 0x%x err %d\n",
+                       "usb_submit_urb(read) failed pipe 0x%x err %d\n",
                        port->read_urb->pipe, retval);
                goto error;
        }
 
        retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
        if (retval) {
-               usb_kill_urb(port->read_urb);
+               usb_kill_urb(priv->read_urb);
                dev_err(&port->dev,
                        "usb_submit_urb(read int) failed pipe 0x%x err %d",
                        port->interrupt_in_urb->pipe, retval);
@@ -509,11 +490,9 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
 
 static void mct_u232_close(struct usb_serial_port *port)
 {
-       /*
-        * Must kill the read urb as it is actually an interrupt urb, which
-        * generic close thus fails to kill.
-        */
-       usb_kill_urb(port->read_urb);
+       struct mct_u232_private *priv = usb_get_serial_port_data(port);
+
+       usb_kill_urb(priv->read_urb);
        usb_kill_urb(port->interrupt_in_urb);
 
        usb_serial_generic_close(port);
@@ -570,7 +549,7 @@ static void mct_u232_read_int_callback(struct urb *urb)
        /* Record Control Line states */
        mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr);
 
-       mct_u232_msr_to_icount(&priv->icount, priv->last_msr);
+       mct_u232_msr_to_icount(&port->icount, priv->last_msr);
 
 #if 0
        /* Not yet handled. See belkin_sa.c for further information */
@@ -598,7 +577,7 @@ static void mct_u232_read_int_callback(struct urb *urb)
                tty_kref_put(tty);
        }
 #endif
-       wake_up_interruptible(&port->delta_msr_wait);
+       wake_up_interruptible(&port->port.delta_msr_wait);
        spin_unlock_irqrestore(&priv->lock, flags);
 exit:
        retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -786,86 +765,6 @@ static void mct_u232_unthrottle(struct tty_struct *tty)
        }
 }
 
-static int  mct_u232_ioctl(struct tty_struct *tty,
-                       unsigned int cmd, unsigned long arg)
-{
-       DEFINE_WAIT(wait);
-       struct usb_serial_port *port = tty->driver_data;
-       struct mct_u232_private *mct_u232_port = usb_get_serial_port_data(port);
-       struct async_icount cnow, cprev;
-       unsigned long flags;
-
-       dev_dbg(&port->dev, "%s - cmd = 0x%x\n", __func__, cmd);
-
-       switch (cmd) {
-
-       case TIOCMIWAIT:
-
-               dev_dbg(&port->dev, "%s TIOCMIWAIT", __func__);
-
-               spin_lock_irqsave(&mct_u232_port->lock, flags);
-               cprev = mct_u232_port->icount;
-               spin_unlock_irqrestore(&mct_u232_port->lock, flags);
-               for ( ; ; ) {
-                       prepare_to_wait(&port->delta_msr_wait,
-                                       &wait, TASK_INTERRUPTIBLE);
-                       schedule();
-                       finish_wait(&port->delta_msr_wait, &wait);
-                       /* see if a signal did it */
-                       if (signal_pending(current))
-                               return -ERESTARTSYS;
-
-                       if (port->serial->disconnected)
-                               return -EIO;
-
-                       spin_lock_irqsave(&mct_u232_port->lock, flags);
-                       cnow = mct_u232_port->icount;
-                       spin_unlock_irqrestore(&mct_u232_port->lock, flags);
-                       if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-                           cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-                               return -EIO; /* no change => error */
-                       if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-                           ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-                           ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-                           ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-                               return 0;
-                       }
-                       cprev = cnow;
-               }
-
-       }
-       return -ENOIOCTLCMD;
-}
-
-static int  mct_u232_get_icount(struct tty_struct *tty,
-                       struct serial_icounter_struct *icount)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct mct_u232_private *mct_u232_port = usb_get_serial_port_data(port);
-       struct async_icount *ic = &mct_u232_port->icount;
-       unsigned long flags;
-
-       spin_lock_irqsave(&mct_u232_port->lock, flags);
-
-       icount->cts = ic->cts;
-       icount->dsr = ic->dsr;
-       icount->rng = ic->rng;
-       icount->dcd = ic->dcd;
-       icount->rx = ic->rx;
-       icount->tx = ic->tx;
-       icount->frame = ic->frame;
-       icount->overrun = ic->overrun;
-       icount->parity = ic->parity;
-       icount->brk = ic->brk;
-       icount->buf_overrun = ic->buf_overrun;
-
-       spin_unlock_irqrestore(&mct_u232_port->lock, flags);
-
-       dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n",
-               __func__,  icount->rx, icount->tx);
-       return 0;
-}
-
 module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
index bf3c7a23553efbe73d1c12b4e7b910d506fed474..47e247759eb0ed975ddcca6482b34080525397d3 100644 (file)
@@ -177,10 +177,7 @@ static void metrousb_cleanup(struct usb_serial_port *port)
        usb_unlink_urb(port->interrupt_in_urb);
        usb_kill_urb(port->interrupt_in_urb);
 
-       mutex_lock(&port->serial->disc_mutex);
-       if (!port->serial->disconnected)
-               metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port);
-       mutex_unlock(&port->serial->disc_mutex);
+       metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port);
 }
 
 static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
index e956eae198fd6cfbb014fc727912953dee22d892..cc0e54345df98c03621949fab2bdc91b7a90af3e 100644 (file)
@@ -62,7 +62,6 @@ struct moschip_port {
        __u8    shadowMCR;              /* last MCR value received */
        __u8    shadowMSR;              /* last MSR value received */
        char                    open;
-       struct async_icount     icount;
        struct usb_serial_port  *port;  /* loop back to the owner */
        struct urb              *write_urb_pool[NUM_URBS];
 };
@@ -1071,9 +1070,6 @@ static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port)
                dev_err(&port->dev, "%s - Error %d submitting read urb\n",
                                                        __func__, response);
 
-       /* initialize our icount structure */
-       memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount));
-
        /* initialize our port settings */
        mos7720_port->shadowMCR = UART_MCR_OUT2; /* Must set to enable ints! */
 
@@ -1140,16 +1136,9 @@ static void mos7720_close(struct usb_serial_port *port)
        usb_kill_urb(port->write_urb);
        usb_kill_urb(port->read_urb);
 
-       mutex_lock(&serial->disc_mutex);
-       /* these commands must not be issued if the device has
-        * been disconnected */
-       if (!serial->disconnected) {
-               write_mos_reg(serial, port->number - port->serial->minor,
-                             MCR, 0x00);
-               write_mos_reg(serial, port->number - port->serial->minor,
-                             IER, 0x00);
-       }
-       mutex_unlock(&serial->disc_mutex);
+       write_mos_reg(serial, port->number - port->serial->minor, MCR, 0x00);
+       write_mos_reg(serial, port->number - port->serial->minor, IER, 0x00);
+
        mos7720_port->open = 0;
 }
 
@@ -1799,33 +1788,6 @@ static int mos7720_tiocmset(struct tty_struct *tty,
        return 0;
 }
 
-static int mos7720_get_icount(struct tty_struct *tty,
-                               struct serial_icounter_struct *icount)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct moschip_port *mos7720_port;
-       struct async_icount cnow;
-
-       mos7720_port = usb_get_serial_port_data(port);
-       cnow = mos7720_port->icount;
-
-       icount->cts = cnow.cts;
-       icount->dsr = cnow.dsr;
-       icount->rng = cnow.rng;
-       icount->dcd = cnow.dcd;
-       icount->rx = cnow.rx;
-       icount->tx = cnow.tx;
-       icount->frame = cnow.frame;
-       icount->overrun = cnow.overrun;
-       icount->parity = cnow.parity;
-       icount->brk = cnow.brk;
-       icount->buf_overrun = cnow.buf_overrun;
-
-       dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", __func__,
-               icount->rx, icount->tx);
-       return 0;
-}
-
 static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd,
                          unsigned int __user *value)
 {
@@ -1901,8 +1863,6 @@ static int mos7720_ioctl(struct tty_struct *tty,
 {
        struct usb_serial_port *port = tty->driver_data;
        struct moschip_port *mos7720_port;
-       struct async_icount cnow;
-       struct async_icount cprev;
 
        mos7720_port = usb_get_serial_port_data(port);
        if (mos7720_port == NULL)
@@ -1927,27 +1887,6 @@ static int mos7720_ioctl(struct tty_struct *tty,
                dev_dbg(&port->dev, "%s TIOCGSERIAL\n", __func__);
                return get_serial_info(mos7720_port,
                                       (struct serial_struct __user *)arg);
-
-       case TIOCMIWAIT:
-               dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__);
-               cprev = mos7720_port->icount;
-               while (1) {
-                       if (signal_pending(current))
-                               return -ERESTARTSYS;
-                       cnow = mos7720_port->icount;
-                       if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-                           cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-                               return -EIO; /* no change => error */
-                       if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-                           ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-                           ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-                           ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-                               return 0;
-                       }
-                       cprev = cnow;
-               }
-               /* NOTREACHED */
-               break;
        }
 
        return -ENOIOCTLCMD;
@@ -2103,7 +2042,6 @@ static struct usb_serial_driver moschip7720_2port_driver = {
        .ioctl                  = mos7720_ioctl,
        .tiocmget               = mos7720_tiocmget,
        .tiocmset               = mos7720_tiocmset,
-       .get_icount             = mos7720_get_icount,
        .set_termios            = mos7720_set_termios,
        .write                  = mos7720_write,
        .write_room             = mos7720_write_room,
index 2be376a2e0e3883dbb1c0bc5059580c8a7fe915a..a0d5ea5459823fbd528d83f5676120a8c456eca0 100644 (file)
@@ -219,8 +219,6 @@ struct moschip_port {
        char open;
        char open_ports;
        wait_queue_head_t wait_chase;   /* for handling sleeping while waiting for chase to finish */
-       int delta_msr_cond;
-       struct async_icount icount;
        struct usb_serial_port *port;   /* loop back to the owner of this object */
 
        /* Offsets */
@@ -399,32 +397,22 @@ static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)
        struct moschip_port *mos7840_port;
        struct async_icount *icount;
        mos7840_port = port;
-       icount = &mos7840_port->icount;
        if (new_msr &
            (MOS_MSR_DELTA_CTS | MOS_MSR_DELTA_DSR | MOS_MSR_DELTA_RI |
             MOS_MSR_DELTA_CD)) {
-               icount = &mos7840_port->icount;
+               icount = &mos7840_port->port->icount;
 
                /* update input line counters */
-               if (new_msr & MOS_MSR_DELTA_CTS) {
+               if (new_msr & MOS_MSR_DELTA_CTS)
                        icount->cts++;
-                       smp_wmb();
-               }
-               if (new_msr & MOS_MSR_DELTA_DSR) {
+               if (new_msr & MOS_MSR_DELTA_DSR)
                        icount->dsr++;
-                       smp_wmb();
-               }
-               if (new_msr & MOS_MSR_DELTA_CD) {
+               if (new_msr & MOS_MSR_DELTA_CD)
                        icount->dcd++;
-                       smp_wmb();
-               }
-               if (new_msr & MOS_MSR_DELTA_RI) {
+               if (new_msr & MOS_MSR_DELTA_RI)
                        icount->rng++;
-                       smp_wmb();
-               }
 
-               mos7840_port->delta_msr_cond = 1;
-               wake_up_interruptible(&port->port->delta_msr_wait);
+               wake_up_interruptible(&port->port->port.delta_msr_wait);
        }
 }
 
@@ -442,23 +430,15 @@ static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr)
        }
 
        /* update input line counters */
-       icount = &port->icount;
-       if (new_lsr & SERIAL_LSR_BI) {
+       icount = &port->port->icount;
+       if (new_lsr & SERIAL_LSR_BI)
                icount->brk++;
-               smp_wmb();
-       }
-       if (new_lsr & SERIAL_LSR_OE) {
+       if (new_lsr & SERIAL_LSR_OE)
                icount->overrun++;
-               smp_wmb();
-       }
-       if (new_lsr & SERIAL_LSR_PE) {
+       if (new_lsr & SERIAL_LSR_PE)
                icount->parity++;
-               smp_wmb();
-       }
-       if (new_lsr & SERIAL_LSR_FE) {
+       if (new_lsr & SERIAL_LSR_FE)
                icount->frame++;
-               smp_wmb();
-       }
 }
 
 /************************************************************************/
@@ -777,9 +757,8 @@ static void mos7840_bulk_in_callback(struct urb *urb)
                struct tty_port *tport = &mos7840_port->port->port;
                tty_insert_flip_string(tport, data, urb->actual_length);
                tty_flip_buffer_push(tport);
-               mos7840_port->icount.rx += urb->actual_length;
-               smp_wmb();
-               dev_dbg(&port->dev, "mos7840_port->icount.rx is %d:\n", mos7840_port->icount.rx);
+               port->icount.rx += urb->actual_length;
+               dev_dbg(&port->dev, "icount.rx is %d:\n", port->icount.rx);
        }
 
        if (!mos7840_port->read_urb) {
@@ -1127,17 +1106,12 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
        /* initialize our wait queues */
        init_waitqueue_head(&mos7840_port->wait_chase);
 
-       /* initialize our icount structure */
-       memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));
-
        /* initialize our port settings */
        /* Must set to enable ints! */
        mos7840_port->shadowMCR = MCR_MASTER_IE;
        /* send a open port command */
        mos7840_port->open = 1;
        /* mos7840_change_port_settings(mos7840_port,old_termios); */
-       mos7840_port->icount.tx = 0;
-       mos7840_port->icount.rx = 0;
 
        return 0;
 }
@@ -1220,25 +1194,10 @@ static void mos7840_close(struct usb_serial_port *port)
                }
        }
 
-       /* While closing port, shutdown all bulk read, write  *
-        * and interrupt read if they exists                  */
-       if (serial->dev) {
-               if (mos7840_port->write_urb) {
-                       dev_dbg(&port->dev, "%s", "Shutdown bulk write\n");
-                       usb_kill_urb(mos7840_port->write_urb);
-               }
-               if (mos7840_port->read_urb) {
-                       dev_dbg(&port->dev, "%s", "Shutdown bulk read\n");
-                       usb_kill_urb(mos7840_port->read_urb);
-                       mos7840_port->read_urb_busy = false;
-               }
-               if ((&mos7840_port->control_urb)) {
-                       dev_dbg(&port->dev, "%s", "Shutdown control read\n");
-                       /*/      usb_kill_urb (mos7840_port->control_urb); */
-               }
-       }
-/*      if(mos7840_port->ctrl_buf != NULL) */
-/*              kfree(mos7840_port->ctrl_buf); */
+       usb_kill_urb(mos7840_port->write_urb);
+       usb_kill_urb(mos7840_port->read_urb);
+       mos7840_port->read_urb_busy = false;
+
        port0->open_ports--;
        dev_dbg(&port->dev, "%s in close%d:in port%d\n", __func__, port0->open_ports, port->number);
        if (port0->open_ports == 0) {
@@ -1250,8 +1209,7 @@ static void mos7840_close(struct usb_serial_port *port)
 
        if (mos7840_port->write_urb) {
                /* if this urb had a transfer buffer already (old tx) free it */
-               if (mos7840_port->write_urb->transfer_buffer != NULL)
-                       kfree(mos7840_port->write_urb->transfer_buffer);
+               kfree(mos7840_port->write_urb->transfer_buffer);
                usb_free_urb(mos7840_port->write_urb);
        }
 
@@ -1328,9 +1286,8 @@ static void mos7840_break(struct tty_struct *tty, int break_state)
        if (mos7840_port == NULL)
                return;
 
-       if (serial->dev)
-               /* flush and block until tx is empty */
-               mos7840_block_until_chase_response(tty, mos7840_port);
+       /* flush and block until tx is empty */
+       mos7840_block_until_chase_response(tty, mos7840_port);
 
        if (break_state == -1)
                data = mos7840_port->shadowLCR | LCR_SET_BREAK;
@@ -1520,9 +1477,8 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
                goto exit;
        }
        bytes_sent = transfer_size;
-       mos7840_port->icount.tx += transfer_size;
-       smp_wmb();
-       dev_dbg(&port->dev, "mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx);
+       port->icount.tx += transfer_size;
+       dev_dbg(&port->dev, "icount.tx is %d:\n", port->icount.tx);
 exit:
        return bytes_sent;
 
@@ -2141,34 +2097,6 @@ static int mos7840_get_serial_info(struct moschip_port *mos7840_port,
        return 0;
 }
 
-static int mos7840_get_icount(struct tty_struct *tty,
-                       struct serial_icounter_struct *icount)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct moschip_port *mos7840_port;
-       struct async_icount cnow;
-
-       mos7840_port = mos7840_get_port_private(port);
-       cnow = mos7840_port->icount;
-
-       smp_rmb();
-       icount->cts = cnow.cts;
-       icount->dsr = cnow.dsr;
-       icount->rng = cnow.rng;
-       icount->dcd = cnow.dcd;
-       icount->rx = cnow.rx;
-       icount->tx = cnow.tx;
-       icount->frame = cnow.frame;
-       icount->overrun = cnow.overrun;
-       icount->parity = cnow.parity;
-       icount->brk = cnow.brk;
-       icount->buf_overrun = cnow.buf_overrun;
-
-       dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", __func__,
-               icount->rx, icount->tx);
-       return 0;
-}
-
 /*****************************************************************************
  * SerialIoctl
  *     this function handles any ioctl calls to the driver
@@ -2181,9 +2109,6 @@ static int mos7840_ioctl(struct tty_struct *tty,
        void __user *argp = (void __user *)arg;
        struct moschip_port *mos7840_port;
 
-       struct async_icount cnow;
-       struct async_icount cprev;
-
        if (mos7840_port_paranoia_check(port, __func__))
                return -1;
 
@@ -2208,41 +2133,6 @@ static int mos7840_ioctl(struct tty_struct *tty,
        case TIOCSSERIAL:
                dev_dbg(&port->dev, "%s TIOCSSERIAL\n", __func__);
                break;
-
-       case TIOCMIWAIT:
-               dev_dbg(&port->dev, "%s  TIOCMIWAIT\n", __func__);
-               cprev = mos7840_port->icount;
-               while (1) {
-                       /* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */
-                       mos7840_port->delta_msr_cond = 0;
-                       wait_event_interruptible(port->delta_msr_wait,
-                                                (port->serial->disconnected ||
-                                                 mos7840_port->
-                                                 delta_msr_cond == 1));
-
-                       /* see if a signal did it */
-                       if (signal_pending(current))
-                               return -ERESTARTSYS;
-
-                       if (port->serial->disconnected)
-                               return -EIO;
-
-                       cnow = mos7840_port->icount;
-                       smp_rmb();
-                       if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-                           cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-                               return -EIO;    /* no change => error */
-                       if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-                           ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-                           ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
-                           ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
-                               return 0;
-                       }
-                       cprev = cnow;
-               }
-               /* NOTREACHED */
-               break;
-
        default:
                break;
        }
@@ -2589,7 +2479,8 @@ static struct usb_serial_driver moschip7840_4port_device = {
        .break_ctl = mos7840_break,
        .tiocmget = mos7840_tiocmget,
        .tiocmset = mos7840_tiocmset,
-       .get_icount = mos7840_get_icount,
+       .tiocmiwait = usb_serial_generic_tiocmiwait,
+       .get_icount = usb_serial_generic_get_icount,
        .port_probe = mos7840_port_probe,
        .port_remove = mos7840_port_remove,
        .read_bulk_callback = mos7840_bulk_in_callback,
index 1e1cafe287e4e63f7b7c23a18fd9b66965228e2e..5739bf6f7200923afd280219572987a0d9b8f104 100644 (file)
@@ -33,8 +33,7 @@
 
 /* function prototypes */
 static int  omninet_open(struct tty_struct *tty, struct usb_serial_port *port);
-static void omninet_close(struct usb_serial_port *port);
-static void omninet_read_bulk_callback(struct urb *urb);
+static void omninet_process_read_urb(struct urb *urb);
 static void omninet_write_bulk_callback(struct urb *urb);
 static int  omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
                                const unsigned char *buf, int count);
@@ -61,11 +60,10 @@ static struct usb_serial_driver zyxel_omninet_device = {
        .port_probe =           omninet_port_probe,
        .port_remove =          omninet_port_remove,
        .open =                 omninet_open,
-       .close =                omninet_close,
        .write =                omninet_write,
        .write_room =           omninet_write_room,
-       .read_bulk_callback =   omninet_read_bulk_callback,
        .write_bulk_callback =  omninet_write_bulk_callback,
+       .process_read_urb =     omninet_process_read_urb,
        .disconnect =           omninet_disconnect,
 };
 
@@ -74,29 +72,28 @@ static struct usb_serial_driver * const serial_drivers[] = {
 };
 
 
-/* The protocol.
+/*
+ * The protocol.
  *
  * The omni.net always exchange 64 bytes of data with the host. The first
- * four bytes are the control header, you can see it in the above structure.
+ * four bytes are the control header.
  *
  * oh_seq is a sequence number. Don't know if/how it's used.
  * oh_len is the length of the data bytes in the packet.
  * oh_xxx Bit-mapped, related to handshaking and status info.
- *     I normally set it to 0x03 in trasmitted frames.
+ *     I normally set it to 0x03 in transmitted frames.
  *     7: Active when the TA is in a CONNECTed state.
  *     6: unknown
  *     5: handshaking, unknown
  *     4: handshaking, unknown
  *     3: unknown, usually 0
  *     2: unknown, usually 0
- *     1: handshaking, unknown, usually set to 1 in trasmitted frames
- *     0: handshaking, unknown, usually set to 1 in trasmitted frames
+ *     1: handshaking, unknown, usually set to 1 in transmitted frames
+ *     0: handshaking, unknown, usually set to 1 in transmitted frames
  * oh_pad Probably a pad byte.
  *
  * After the header you will find data bytes if oh_len was greater than zero.
- *
  */
-
 struct omninet_header {
        __u8    oh_seq;
        __u8    oh_len;
@@ -112,7 +109,7 @@ static int omninet_port_probe(struct usb_serial_port *port)
 {
        struct omninet_data *od;
 
-       od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL);
+       od = kzalloc(sizeof(*od), GFP_KERNEL);
        if (!od)
                return -ENOMEM;
 
@@ -135,56 +132,32 @@ static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
        struct usb_serial       *serial = port->serial;
        struct usb_serial_port  *wport;
-       int                     result = 0;
 
        wport = serial->port[1];
        tty_port_tty_set(&wport->port, tty);
 
-       /* Start reading from the device */
-       result = usb_submit_urb(port->read_urb, GFP_KERNEL);
-       if (result)
-               dev_err(&port->dev,
-                       "%s - failed submitting read urb, error %d\n",
-                       __func__, result);
-       return result;
-}
-
-static void omninet_close(struct usb_serial_port *port)
-{
-       usb_kill_urb(port->read_urb);
+       return usb_serial_generic_open(tty, port);
 }
 
+#define OMNINET_HEADERLEN      4
+#define OMNINET_BULKOUTSIZE    64
+#define OMNINET_PAYLOADSIZE    (OMNINET_BULKOUTSIZE - OMNINET_HEADERLEN)
 
-#define OMNINET_DATAOFFSET     0x04
-#define OMNINET_HEADERLEN      sizeof(struct omninet_header)
-#define OMNINET_BULKOUTSIZE    (64 - OMNINET_HEADERLEN)
-
-static void omninet_read_bulk_callback(struct urb *urb)
+static void omninet_process_read_urb(struct urb *urb)
 {
-       struct usb_serial_port  *port   = urb->context;
-       unsigned char           *data   = urb->transfer_buffer;
-       struct omninet_header   *header = (struct omninet_header *) &data[0];
-       int status = urb->status;
-       int result;
+       struct usb_serial_port *port = urb->context;
+       const struct omninet_header *hdr = urb->transfer_buffer;
+       const unsigned char *data;
+       size_t data_len;
 
-       if (status) {
-               dev_dbg(&port->dev, "%s - nonzero read bulk status received: %d\n",
-                       __func__, status);
+       if (urb->actual_length <= OMNINET_HEADERLEN || !hdr->oh_len)
                return;
-       }
-
-       if (urb->actual_length && header->oh_len) {
-               tty_insert_flip_string(&port->port, data + OMNINET_DATAOFFSET,
-                               header->oh_len);
-               tty_flip_buffer_push(&port->port);
-       }
 
-       /* Continue trying to always read  */
-       result = usb_submit_urb(urb, GFP_ATOMIC);
-       if (result)
-               dev_err(&port->dev,
-                       "%s - failed resubmitting read urb, error %d\n",
-                       __func__, result);
+       data = (char *)urb->transfer_buffer + OMNINET_HEADERLEN;
+       data_len = min_t(size_t, urb->actual_length - OMNINET_HEADERLEN,
+                                                               hdr->oh_len);
+       tty_insert_flip_string(&port->port, data, data_len);
+       tty_flip_buffer_push(&port->port);
 }
 
 static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -209,9 +182,9 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
                return 0;
        }
 
-       count = (count > OMNINET_BULKOUTSIZE) ? OMNINET_BULKOUTSIZE : count;
+       count = (count > OMNINET_PAYLOADSIZE) ? OMNINET_PAYLOADSIZE : count;
 
-       memcpy(wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET,
+       memcpy(wport->write_urb->transfer_buffer + OMNINET_HEADERLEN,
                                                                buf, count);
 
        usb_serial_debug_data(&port->dev, __func__, count,
@@ -223,7 +196,7 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
        header->oh_pad  = 0x00;
 
        /* send the data out the bulk port, always 64 bytes */
-       wport->write_urb->transfer_buffer_length = 64;
+       wport->write_urb->transfer_buffer_length = OMNINET_BULKOUTSIZE;
 
        result = usb_submit_urb(wport->write_urb, GFP_ATOMIC);
        if (result) {
index e13e1a4d3e1e0901d09195280ae6f7fd4cf386fc..5f4b0cd0f6e9734193dac84ba23373f13e301d65 100644 (file)
@@ -120,7 +120,10 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
                                0, 0, buffer, 1, 0);
        kfree(buffer);
 
-       return retval;
+       if (retval < 0)
+               return retval;
+
+       return 0;
 }
 
 static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port)
@@ -306,7 +309,6 @@ static int opticon_tiocmset(struct tty_struct *tty,
                           unsigned int set, unsigned int clear)
 {
        struct usb_serial_port *port = tty->driver_data;
-       struct usb_serial *serial = port->serial;
        struct opticon_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
        bool rts;
@@ -327,15 +329,11 @@ static int opticon_tiocmset(struct tty_struct *tty,
        if (!changed)
                return 0;
 
-       /* Send the new RTS state to the connected device */
-       mutex_lock(&serial->disc_mutex);
-       if (!serial->disconnected)
-               ret = send_control_msg(port, CONTROL_RTS, !rts);
-       else
-               ret = -ENODEV;
-       mutex_unlock(&serial->disc_mutex);
+       ret = send_control_msg(port, CONTROL_RTS, !rts);
+       if (ret)
+               return usb_translate_errors(ret);
 
-       return ret;
+       return 0;
 }
 
 static int get_serial_info(struct usb_serial_port *port,
index 09cd3967b8df777237d09819966350716cc2f7d0..734372846abbb31b1381841f4f144a09a4f0b2a0 100644 (file)
@@ -347,6 +347,7 @@ static void option_instat_callback(struct urb *urb);
 /* Olivetti products */
 #define OLIVETTI_VENDOR_ID                     0x0b3c
 #define OLIVETTI_PRODUCT_OLICARD100            0xc000
+#define OLIVETTI_PRODUCT_OLICARD145            0xc003
 
 /* Celot products */
 #define CELOT_VENDOR_ID                                0x211f
@@ -1273,6 +1274,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
 
        { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
+       { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD145) },
        { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
        { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
        { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/
@@ -1350,6 +1352,12 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180),
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) },
+       { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x02, 0x01) },    /* D-Link DWM-156 (variant) */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x00, 0x00) },    /* D-Link DWM-156 (variant) */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x02, 0x01) },
+       { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x00, 0x00) },
+       { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) },
+       { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) },
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index 87c71ccfee87bfd06d41034a52a6e5dc27a21c7f..7e3e0782e51fe48ccb91e3e9e28eb42a380a0932 100644 (file)
@@ -124,8 +124,6 @@ static void oti6858_close(struct usb_serial_port *port);
 static void oti6858_set_termios(struct tty_struct *tty,
                        struct usb_serial_port *port, struct ktermios *old);
 static void oti6858_init_termios(struct tty_struct *tty);
-static int oti6858_ioctl(struct tty_struct *tty,
-                       unsigned int cmd, unsigned long arg);
 static void oti6858_read_int_callback(struct urb *urb);
 static void oti6858_read_bulk_callback(struct urb *urb);
 static void oti6858_write_bulk_callback(struct urb *urb);
@@ -136,6 +134,7 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty);
 static int oti6858_tiocmget(struct tty_struct *tty);
 static int oti6858_tiocmset(struct tty_struct *tty,
                                unsigned int set, unsigned int clear);
+static int oti6858_tiocmiwait(struct tty_struct *tty, unsigned long arg);
 static int oti6858_port_probe(struct usb_serial_port *port);
 static int oti6858_port_remove(struct usb_serial_port *port);
 
@@ -150,11 +149,11 @@ static struct usb_serial_driver oti6858_device = {
        .open =                 oti6858_open,
        .close =                oti6858_close,
        .write =                oti6858_write,
-       .ioctl =                oti6858_ioctl,
        .set_termios =          oti6858_set_termios,
        .init_termios =         oti6858_init_termios,
        .tiocmget =             oti6858_tiocmget,
        .tiocmset =             oti6858_tiocmset,
+       .tiocmiwait =           oti6858_tiocmiwait,
        .read_bulk_callback =   oti6858_read_bulk_callback,
        .read_int_callback =    oti6858_read_int_callback,
        .write_bulk_callback =  oti6858_write_bulk_callback,
@@ -650,8 +649,9 @@ static int oti6858_tiocmget(struct tty_struct *tty)
        return result;
 }
 
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+static int oti6858_tiocmiwait(struct tty_struct *tty, unsigned long arg)
 {
+       struct usb_serial_port *port = tty->driver_data;
        struct oti6858_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
        unsigned int prev, status;
@@ -662,7 +662,7 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
        spin_unlock_irqrestore(&priv->lock, flags);
 
        while (1) {
-               wait_event_interruptible(port->delta_msr_wait,
+               wait_event_interruptible(port->port.delta_msr_wait,
                                        port->serial->disconnected ||
                                        priv->status.pin_state != prev);
                if (signal_pending(current))
@@ -689,24 +689,6 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
        return 0;
 }
 
-static int oti6858_ioctl(struct tty_struct *tty,
-                       unsigned int cmd, unsigned long arg)
-{
-       struct usb_serial_port *port = tty->driver_data;
-
-       dev_dbg(&port->dev, "%s(cmd = 0x%04x, arg = 0x%08lx)\n", __func__, cmd, arg);
-
-       switch (cmd) {
-       case TIOCMIWAIT:
-               dev_dbg(&port->dev, "%s(): TIOCMIWAIT\n", __func__);
-               return wait_modem_info(port, arg);
-       default:
-               dev_dbg(&port->dev, "%s(): 0x%04x not supported\n", __func__, cmd);
-               break;
-       }
-       return -ENOIOCTLCMD;
-}
-
 static void oti6858_read_int_callback(struct urb *urb)
 {
        struct usb_serial_port *port =  urb->context;
@@ -765,7 +747,7 @@ static void oti6858_read_int_callback(struct urb *urb)
 
                if (!priv->transient) {
                        if (xs->pin_state != priv->status.pin_state)
-                               wake_up_interruptible(&port->delta_msr_wait);
+                               wake_up_interruptible(&port->port.delta_msr_wait);
                        memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE);
                }
 
index 3b10018d89a34e44e03b5ffb5562c34c7e4e6b85..7151659367a0898cec3124e8ee328bf17f57d6bd 100644 (file)
@@ -149,7 +149,7 @@ static int pl2303_vendor_read(__u16 value, __u16 index,
        int res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
                        VENDOR_READ_REQUEST, VENDOR_READ_REQUEST_TYPE,
                        value, index, buf, 1, 100);
-       dev_dbg(&serial->dev->dev, "0x%x:0x%x:0x%x:0x%x  %d - %x\n",
+       dev_dbg(&serial->interface->dev, "0x%x:0x%x:0x%x:0x%x  %d - %x\n",
                VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, value, index,
                res, buf[0]);
        return res;
@@ -161,7 +161,7 @@ static int pl2303_vendor_write(__u16 value, __u16 index,
        int res = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                        VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE,
                        value, index, NULL, 0, 100);
-       dev_dbg(&serial->dev->dev, "0x%x:0x%x:0x%x:0x%x  %d\n",
+       dev_dbg(&serial->interface->dev, "0x%x:0x%x:0x%x:0x%x  %d\n",
                VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, value, index,
                res);
        return res;
@@ -248,14 +248,15 @@ static int pl2303_port_remove(struct usb_serial_port *port)
        return 0;
 }
 
-static int set_control_lines(struct usb_device *dev, u8 value)
+static int pl2303_set_control_lines(struct usb_serial_port *port, u8 value)
 {
+       struct usb_device *dev = port->serial->dev;
        int retval;
 
        retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                                 SET_CONTROL_REQUEST, SET_CONTROL_REQUEST_TYPE,
                                 value, 0, NULL, 0, 100);
-       dev_dbg(&dev->dev, "%s - value = %d, retval = %d\n", __func__,
+       dev_dbg(&port->dev, "%s - value = %d, retval = %d\n", __func__,
                value, retval);
        return retval;
 }
@@ -437,7 +438,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
        if (control != priv->line_control) {
                control = priv->line_control;
                spin_unlock_irqrestore(&priv->lock, flags);
-               set_control_lines(serial->dev, control);
+               pl2303_set_control_lines(port, control);
        } else {
                spin_unlock_irqrestore(&priv->lock, flags);
        }
@@ -480,7 +481,7 @@ static void pl2303_dtr_rts(struct usb_serial_port *port, int on)
                priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
        control = priv->line_control;
        spin_unlock_irqrestore(&priv->lock, flags);
-       set_control_lines(port->serial->dev, control);
+       pl2303_set_control_lines(port, control);
 }
 
 static void pl2303_close(struct usb_serial_port *port)
@@ -530,7 +531,6 @@ static int pl2303_tiocmset(struct tty_struct *tty,
                           unsigned int set, unsigned int clear)
 {
        struct usb_serial_port *port = tty->driver_data;
-       struct usb_serial *serial = port->serial;
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
        u8 control;
@@ -548,14 +548,11 @@ static int pl2303_tiocmset(struct tty_struct *tty,
        control = priv->line_control;
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       mutex_lock(&serial->disc_mutex);
-       if (!serial->disconnected)
-               ret = set_control_lines(serial->dev, control);
-       else
-               ret = -ENODEV;
-       mutex_unlock(&serial->disc_mutex);
+       ret = pl2303_set_control_lines(port, control);
+       if (ret)
+               return usb_translate_errors(ret);
 
-       return ret;
+       return 0;
 }
 
 static int pl2303_tiocmget(struct tty_struct *tty)
@@ -592,8 +589,9 @@ static int pl2303_carrier_raised(struct usb_serial_port *port)
        return 0;
 }
 
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+static int pl2303_tiocmiwait(struct tty_struct *tty, unsigned long arg)
 {
+       struct usb_serial_port *port = tty->driver_data;
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
        unsigned int prevstatus;
@@ -605,7 +603,7 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
        spin_unlock_irqrestore(&priv->lock, flags);
 
        while (1) {
-               interruptible_sleep_on(&port->delta_msr_wait);
+               interruptible_sleep_on(&port->port.delta_msr_wait);
                /* see if a signal did it */
                if (signal_pending(current))
                        return -ERESTARTSYS;
@@ -651,10 +649,6 @@ static int pl2303_ioctl(struct tty_struct *tty,
                        return -EFAULT;
 
                return 0;
-
-       case TIOCMIWAIT:
-               dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__);
-               return wait_modem_info(port, arg);
        default:
                dev_dbg(&port->dev, "%s not supported = 0x%04x\n", __func__, cmd);
                break;
@@ -720,7 +714,7 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
        spin_unlock_irqrestore(&priv->lock, flags);
        if (priv->line_status & UART_BREAK_ERROR)
                usb_serial_handle_break(port);
-       wake_up_interruptible(&port->delta_msr_wait);
+       wake_up_interruptible(&port->port.delta_msr_wait);
 
        tty = tty_port_tty_get(&port->port);
        if (!tty)
@@ -784,7 +778,7 @@ static void pl2303_process_read_urb(struct urb *urb)
        line_status = priv->line_status;
        priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
        spin_unlock_irqrestore(&priv->lock, flags);
-       wake_up_interruptible(&port->delta_msr_wait);
+       wake_up_interruptible(&port->port.delta_msr_wait);
 
        if (!urb->actual_length)
                return;
@@ -835,6 +829,7 @@ static struct usb_serial_driver pl2303_device = {
        .set_termios =          pl2303_set_termios,
        .tiocmget =             pl2303_tiocmget,
        .tiocmset =             pl2303_tiocmset,
+       .tiocmiwait =           pl2303_tiocmiwait,
        .process_read_urb =     pl2303_process_read_urb,
        .read_int_callback =    pl2303_read_int_callback,
        .attach =               pl2303_startup,
index ef3a7d5eaab4afa072daf8914b5db90040445fe6..02b0803425c5d01d82f4b8d498a78c128bdfd268 100644 (file)
@@ -127,8 +127,6 @@ struct qt2_port_private {
        u8          shadowLSR;
        u8          shadowMSR;
 
-       struct async_icount icount;
-
        struct usb_serial_port *port;
 };
 
@@ -420,12 +418,6 @@ static void qt2_close(struct usb_serial_port *port)
        port_priv->urb_in_use = false;
        spin_unlock_irqrestore(&port_priv->urb_lock, flags);
 
-       mutex_lock(&port->serial->disc_mutex);
-       if (port->serial->disconnected) {
-               mutex_unlock(&port->serial->disc_mutex);
-               return;
-       }
-
        /* flush the port transmit buffer */
        i = usb_control_msg(serial->dev,
                            usb_rcvctrlpipe(serial->dev, 0),
@@ -456,8 +448,6 @@ static void qt2_close(struct usb_serial_port *port)
        if (i < 0)
                dev_err(&port->dev, "%s - close port failed %i\n",
                        __func__, i);
-
-       mutex_unlock(&port->serial->disc_mutex);
 }
 
 static void qt2_disconnect(struct usb_serial *serial)
@@ -490,71 +480,6 @@ static int get_serial_info(struct usb_serial_port *port,
        return 0;
 }
 
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
-{
-       struct qt2_port_private *priv = usb_get_serial_port_data(port);
-       struct async_icount prev, cur;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->lock, flags);
-       prev = priv->icount;
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       while (1) {
-               wait_event_interruptible(port->delta_msr_wait,
-                                        (port->serial->disconnected ||
-                                         (priv->icount.rng != prev.rng) ||
-                                         (priv->icount.dsr != prev.dsr) ||
-                                         (priv->icount.dcd != prev.dcd) ||
-                                         (priv->icount.cts != prev.cts)));
-
-               if (signal_pending(current))
-                       return -ERESTARTSYS;
-
-               if (port->serial->disconnected)
-                       return -EIO;
-
-               spin_lock_irqsave(&priv->lock, flags);
-               cur = priv->icount;
-               spin_unlock_irqrestore(&priv->lock, flags);
-
-               if ((prev.rng == cur.rng) &&
-                   (prev.dsr == cur.dsr) &&
-                   (prev.dcd == cur.dcd) &&
-                   (prev.cts == cur.cts))
-                       return -EIO;
-
-               if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) ||
-                   (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) ||
-                   (arg & TIOCM_CD && (prev.dcd != cur.dcd)) ||
-                   (arg & TIOCM_CTS && (prev.cts != cur.cts)))
-                       return 0;
-       }
-       return 0;
-}
-
-static int qt2_get_icount(struct tty_struct *tty,
-                         struct serial_icounter_struct *icount)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct qt2_port_private *priv = usb_get_serial_port_data(port);
-       struct async_icount cnow = priv->icount;
-
-       icount->cts = cnow.cts;
-       icount->dsr = cnow.dsr;
-       icount->rng = cnow.rng;
-       icount->dcd = cnow.dcd;
-       icount->rx = cnow.rx;
-       icount->tx = cnow.tx;
-       icount->frame = cnow.frame;
-       icount->overrun = cnow.overrun;
-       icount->parity = cnow.parity;
-       icount->brk = cnow.brk;
-       icount->buf_overrun = cnow.buf_overrun;
-
-       return 0;
-}
-
 static int qt2_ioctl(struct tty_struct *tty,
                     unsigned int cmd, unsigned long arg)
 {
@@ -564,10 +489,6 @@ static int qt2_ioctl(struct tty_struct *tty,
        case TIOCGSERIAL:
                return get_serial_info(port,
                                       (struct serial_struct __user *)arg);
-
-       case TIOCMIWAIT:
-               return wait_modem_info(port, arg);
-
        default:
                break;
        }
@@ -948,18 +869,15 @@ static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch)
        if (newMSR & UART_MSR_ANY_DELTA) {
                /* update input line counters */
                if (newMSR & UART_MSR_DCTS)
-                       port_priv->icount.cts++;
-
+                       port->icount.cts++;
                if (newMSR & UART_MSR_DDSR)
-                       port_priv->icount.dsr++;
-
+                       port->icount.dsr++;
                if (newMSR & UART_MSR_DDCD)
-                       port_priv->icount.dcd++;
-
+                       port->icount.dcd++;
                if (newMSR & UART_MSR_TERI)
-                       port_priv->icount.rng++;
+                       port->icount.rng++;
 
-               wake_up_interruptible(&port->delta_msr_wait);
+               wake_up_interruptible(&port->port.delta_msr_wait);
        }
 }
 
@@ -979,7 +897,7 @@ static void qt2_update_lsr(struct usb_serial_port *port, unsigned char *ch)
        port_priv->shadowLSR = newLSR;
        spin_unlock_irqrestore(&port_priv->lock, flags);
 
-       icount = &port_priv->icount;
+       icount = &port->icount;
 
        if (newLSR & UART_LSR_BRK_ERROR_BITS) {
 
@@ -1089,7 +1007,8 @@ static struct usb_serial_driver qt2_device = {
        .break_ctl           = qt2_break_ctl,
        .tiocmget            = qt2_tiocmget,
        .tiocmset            = qt2_tiocmset,
-       .get_icount          = qt2_get_icount,
+       .tiocmiwait          = usb_serial_generic_tiocmiwait,
+       .get_icount          = usb_serial_generic_get_icount,
        .ioctl               = qt2_ioctl,
        .set_termios         = qt2_set_termios,
 };
index d66148a17fe36548e019c0b8b7b60aa563548a1a..8894665cd6102cfe756ea2a86f46176010483444 100644 (file)
@@ -774,30 +774,25 @@ static void sierra_close(struct usb_serial_port *port)
        portdata->rts_state = 0;
        portdata->dtr_state = 0;
 
-       if (serial->dev) {
-               mutex_lock(&serial->disc_mutex);
-               if (!serial->disconnected) {
-                       serial->interface->needs_remote_wakeup = 0;
-                       /* odd error handling due to pm counters */
-                       if (!usb_autopm_get_interface(serial->interface))
-                               sierra_send_setup(port);
-                       else
-                               usb_autopm_get_interface_no_resume(serial->interface);
-                               
-               }
-               mutex_unlock(&serial->disc_mutex);
-               spin_lock_irq(&intfdata->susp_lock);
-               portdata->opened = 0;
-               spin_unlock_irq(&intfdata->susp_lock);
+       mutex_lock(&serial->disc_mutex);
+       if (!serial->disconnected) {
+               serial->interface->needs_remote_wakeup = 0;
+               /* odd error handling due to pm counters */
+               if (!usb_autopm_get_interface(serial->interface))
+                       sierra_send_setup(port);
+               else
+                       usb_autopm_get_interface_no_resume(serial->interface);
 
+       }
+       mutex_unlock(&serial->disc_mutex);
+       spin_lock_irq(&intfdata->susp_lock);
+       portdata->opened = 0;
+       spin_unlock_irq(&intfdata->susp_lock);
 
-               /* Stop reading urbs */
-               sierra_stop_rx_urbs(port);
-               /* .. and release them */
-               for (i = 0; i < portdata->num_in_urbs; i++) {
-                       sierra_release_urb(portdata->in_urbs[i]);
-                       portdata->in_urbs[i] = NULL;
-               }
+       sierra_stop_rx_urbs(port);
+       for (i = 0; i < portdata->num_in_urbs; i++) {
+               sierra_release_urb(portdata->in_urbs[i]);
+               portdata->in_urbs[i] = NULL;
        }
 }
 
index 549ef68ff5fa2ea156fa31ea65f3b823353b1cfa..cf3df793c2b7a1a7781e908e0a5d2385e7056f5b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * spcp8x5 USB to serial adaptor driver
  *
- * Copyright (C) 2010 Johan Hovold (jhovold@gmail.com)
+ * Copyright (C) 2010-2013 Johan Hovold (jhovold@gmail.com)
  * Copyright (C) 2006 Linxb (xubin.lin@worldplus.com.cn)
  * Copyright (C) 2006 S1 Corp.
  *
@@ -13,8 +13,6 @@
  *     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.
- *
- *
  */
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/usb.h>
 #include <linux/usb/serial.h>
 
-#define DRIVER_DESC    "SPCP8x5 USB to serial adaptor driver"
+#define DRIVER_DESC    "SPCP8x5 USB to serial adaptor driver"
+
+#define SPCP825_QUIRK_NO_UART_STATUS   0x01
+#define SPCP825_QUIRK_NO_WORK_MODE     0x02
 
 #define SPCP8x5_007_VID                0x04FC
 #define SPCP8x5_007_PID                0x0201
@@ -46,13 +47,15 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(SPCP8x5_INTERMATIC_VID, SPCP8x5_INTERMATIC_PID)},
        { USB_DEVICE(SPCP8x5_835_VID, SPCP8x5_835_PID)},
        { USB_DEVICE(SPCP8x5_008_VID, SPCP8x5_008_PID)},
-       { USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID)},
+       { USB_DEVICE(SPCP8x5_007_VID, SPCP8x5_007_PID),
+         .driver_info = SPCP825_QUIRK_NO_UART_STATUS |
+                               SPCP825_QUIRK_NO_WORK_MODE },
        { }                                     /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, id_table);
 
 struct spcp8x5_usb_ctrl_arg {
-       u8      type;
+       u8      type;
        u8      cmd;
        u8      cmd_type;
        u16     value;
@@ -138,49 +141,33 @@ struct spcp8x5_usb_ctrl_arg {
 #define UART_OVERRUN_ERROR             0x40
 #define UART_CTS                       0x80
 
-enum spcp8x5_type {
-       SPCP825_007_TYPE,
-       SPCP825_008_TYPE,
-       SPCP825_PHILIP_TYPE,
-       SPCP825_INTERMATIC_TYPE,
-       SPCP835_TYPE,
-};
-
 struct spcp8x5_private {
-       spinlock_t      lock;
-       enum spcp8x5_type       type;
-       u8                      line_control;
-       u8                      line_status;
+       unsigned                quirks;
+       spinlock_t              lock;
+       u8                      line_control;
 };
 
+static int spcp8x5_probe(struct usb_serial *serial,
+                                               const struct usb_device_id *id)
+{
+       usb_set_serial_data(serial, (void *)id);
+
+       return 0;
+}
+
 static int spcp8x5_port_probe(struct usb_serial_port *port)
 {
-       struct usb_serial *serial = port->serial;
+       const struct usb_device_id *id = usb_get_serial_data(port->serial);
        struct spcp8x5_private *priv;
-       enum spcp8x5_type type = SPCP825_007_TYPE;
-       u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
-
-       if (product == 0x0201)
-               type = SPCP825_007_TYPE;
-       else if (product == 0x0231)
-               type = SPCP835_TYPE;
-       else if (product == 0x0235)
-               type = SPCP825_008_TYPE;
-       else if (product == 0x0204)
-               type = SPCP825_INTERMATIC_TYPE;
-       else if (product == 0x0471 &&
-                serial->dev->descriptor.idVendor == cpu_to_le16(0x081e))
-               type = SPCP825_PHILIP_TYPE;
-       dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type);
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
        spin_lock_init(&priv->lock);
-       priv->type = type;
+       priv->quirks = id->driver_info;
 
-       usb_set_serial_port_data(port , priv);
+       usb_set_serial_port_data(port, priv);
 
        return 0;
 }
@@ -195,86 +182,79 @@ static int spcp8x5_port_remove(struct usb_serial_port *port)
        return 0;
 }
 
-/* set the modem control line of the device.
- * NOTE spcp825-007 not supported this */
-static int spcp8x5_set_ctrlLine(struct usb_device *dev, u8 value,
-                               enum spcp8x5_type type)
+static int spcp8x5_set_ctrl_line(struct usb_serial_port *port, u8 mcr)
 {
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       struct usb_device *dev = port->serial->dev;
        int retval;
-       u8 mcr = 0 ;
 
-       if (type == SPCP825_007_TYPE)
+       if (priv->quirks & SPCP825_QUIRK_NO_UART_STATUS)
                return -EPERM;
 
-       mcr = (unsigned short)value;
        retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                                 SET_UART_STATUS_TYPE, SET_UART_STATUS,
                                 mcr, 0x04, NULL, 0, 100);
-       if (retval != 0)
-               dev_dbg(&dev->dev, "usb_control_msg return %#x\n", retval);
+       if (retval != 0) {
+               dev_err(&port->dev, "failed to set control lines: %d\n",
+                                                               retval);
+       }
        return retval;
 }
 
-/* get the modem status register of the device
- * NOTE spcp825-007 not supported this */
-static int spcp8x5_get_msr(struct usb_device *dev, u8 *status,
-                          enum spcp8x5_type type)
+static int spcp8x5_get_msr(struct usb_serial_port *port, u8 *status)
 {
-       u8 *status_buffer;
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       struct usb_device *dev = port->serial->dev;
+       u8 *buf;
        int ret;
 
-       /* I return Permited not support here but seem inval device
-        * is more fix */
-       if (type == SPCP825_007_TYPE)
+       if (priv->quirks & SPCP825_QUIRK_NO_UART_STATUS)
                return -EPERM;
-       if (status == NULL)
-               return -EINVAL;
 
-       status_buffer = kmalloc(1, GFP_KERNEL);
-       if (!status_buffer)
+       buf = kzalloc(1, GFP_KERNEL);
+       if (!buf)
                return -ENOMEM;
-       status_buffer[0] = status[0];
 
        ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
                              GET_UART_STATUS, GET_UART_STATUS_TYPE,
-                             0, GET_UART_STATUS_MSR, status_buffer, 1, 100);
+                             0, GET_UART_STATUS_MSR, buf, 1, 100);
        if (ret < 0)
-               dev_dbg(&dev->dev, "Get MSR = 0x%p failed (error = %d)",
-                       status_buffer, ret);
+               dev_err(&port->dev, "failed to get modem status: %d", ret);
 
-       dev_dbg(&dev->dev, "0xc0:0x22:0:6  %d - 0x%p ", ret, status_buffer);
-       status[0] = status_buffer[0];
-       kfree(status_buffer);
+       dev_dbg(&port->dev, "0xc0:0x22:0:6  %d - 0x02%x", ret, *buf);
+       *status = *buf;
+       kfree(buf);
 
        return ret;
 }
 
-/* select the work mode.
- * NOTE this function not supported by spcp825-007 */
-static void spcp8x5_set_workMode(struct usb_device *dev, u16 value,
-                                u16 index, enum spcp8x5_type type)
+static void spcp8x5_set_work_mode(struct usb_serial_port *port, u16 value,
+                                                                u16 index)
 {
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       struct usb_device *dev = port->serial->dev;
        int ret;
 
-       /* I return Permited not support here but seem inval device
-        * is more fix */
-       if (type == SPCP825_007_TYPE)
+       if (priv->quirks & SPCP825_QUIRK_NO_WORK_MODE)
                return;
 
        ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                              SET_WORKING_MODE_TYPE, SET_WORKING_MODE,
                              value, index, NULL, 0, 100);
-       dev_dbg(&dev->dev, "value = %#x , index = %#x\n", value, index);
+       dev_dbg(&port->dev, "value = %#x , index = %#x\n", value, index);
        if (ret < 0)
-               dev_dbg(&dev->dev,
-                       "RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret);
+               dev_err(&port->dev, "failed to set work mode: %d\n", ret);
 }
 
 static int spcp8x5_carrier_raised(struct usb_serial_port *port)
 {
-       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
-       if (priv->line_status & MSR_STATUS_LINE_DCD)
+       u8 msr;
+       int ret;
+
+       ret = spcp8x5_get_msr(port, &msr);
+       if (ret || msr & MSR_STATUS_LINE_DCD)
                return 1;
+
        return 0;
 }
 
@@ -293,20 +273,17 @@ static void spcp8x5_dtr_rts(struct usb_serial_port *port, int on)
                                                | MCR_CONTROL_LINE_RTS);
        control = priv->line_control;
        spin_unlock_irqrestore(&priv->lock, flags);
-       spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
+       spcp8x5_set_ctrl_line(port, control);
 }
 
 static void spcp8x5_init_termios(struct tty_struct *tty)
 {
-       /* for the 1st time call this function */
        tty->termios = tty_std_termios;
        tty->termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
        tty->termios.c_ispeed = 115200;
        tty->termios.c_ospeed = 115200;
 }
 
-/* set the serial param for transfer. we should check if we really need to
- * transfer. if we set flow control we should do this too. */
 static void spcp8x5_set_termios(struct tty_struct *tty,
                struct usb_serial_port *port, struct ktermios *old_termios)
 {
@@ -321,7 +298,6 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
        int i;
        u8 control;
 
-
        /* check that they really want us to change something */
        if (!tty_termios_hw_change(&tty->termios, old_termios))
                return;
@@ -337,7 +313,7 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
        if (control != priv->line_control) {
                control = priv->line_control;
                spin_unlock_irqrestore(&priv->lock, flags);
-               spcp8x5_set_ctrlLine(serial->dev, control , priv->type);
+               spcp8x5_set_ctrl_line(port, control);
        } else {
                spin_unlock_irqrestore(&priv->lock, flags);
        }
@@ -397,9 +373,9 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
        if (cflag & PARENB) {
                buf[1] |= (cflag & PARODD) ?
                SET_UART_FORMAT_PAR_ODD : SET_UART_FORMAT_PAR_EVEN ;
-       } else
+       } else {
                buf[1] |= SET_UART_FORMAT_PAR_NONE;
-
+       }
        uartdata = buf[0] | buf[1]<<8;
 
        i = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
@@ -412,22 +388,16 @@ static void spcp8x5_set_termios(struct tty_struct *tty,
 
        if (cflag & CRTSCTS) {
                /* enable hardware flow control */
-               spcp8x5_set_workMode(serial->dev, 0x000a,
-                                    SET_WORKING_MODE_U2C, priv->type);
+               spcp8x5_set_work_mode(port, 0x000a, SET_WORKING_MODE_U2C);
        }
 }
 
-/* open the serial port. do some usb system call. set termios and get the line
- * status of the device. */
 static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
        struct ktermios tmp_termios;
        struct usb_serial *serial = port->serial;
        struct spcp8x5_private *priv = usb_get_serial_port_data(port);
        int ret;
-       unsigned long flags;
-       u8 status = 0x30;
-       /* status 0x30 means DSR and CTS = 1 other CDC RI and delta = 0 */
 
        usb_clear_halt(serial->dev, port->write_urb->pipe);
        usb_clear_halt(serial->dev, port->read_urb->pipe);
@@ -438,142 +408,16 @@ static int spcp8x5_open(struct tty_struct *tty, struct usb_serial_port *port)
        if (ret)
                return ret;
 
-       spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type);
+       spcp8x5_set_ctrl_line(port, priv->line_control);
 
-       /* Setup termios */
        if (tty)
                spcp8x5_set_termios(tty, port, &tmp_termios);
 
-       spcp8x5_get_msr(serial->dev, &status, priv->type);
-
-       /* may be we should update uart status here but now we did not do */
-       spin_lock_irqsave(&priv->lock, flags);
-       priv->line_status = status & 0xf0 ;
-       spin_unlock_irqrestore(&priv->lock, flags);
-
        port->port.drain_delay = 256;
 
        return usb_serial_generic_open(tty, port);
 }
 
-static void spcp8x5_process_read_urb(struct urb *urb)
-{
-       struct usb_serial_port *port = urb->context;
-       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
-       unsigned char *data = urb->transfer_buffer;
-       unsigned long flags;
-       u8 status;
-       char tty_flag;
-
-       /* get tty_flag from status */
-       tty_flag = TTY_NORMAL;
-
-       spin_lock_irqsave(&priv->lock, flags);
-       status = priv->line_status;
-       priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
-       spin_unlock_irqrestore(&priv->lock, flags);
-       /* wake up the wait for termios */
-       wake_up_interruptible(&port->delta_msr_wait);
-
-       if (!urb->actual_length)
-               return;
-
-
-       if (status & UART_STATE_TRANSIENT_MASK) {
-               /* break takes precedence over parity, which takes precedence
-                * over framing errors */
-               if (status & UART_BREAK_ERROR)
-                       tty_flag = TTY_BREAK;
-               else if (status & UART_PARITY_ERROR)
-                       tty_flag = TTY_PARITY;
-               else if (status & UART_FRAME_ERROR)
-                       tty_flag = TTY_FRAME;
-               dev_dbg(&port->dev, "tty_flag = %d\n", tty_flag);
-
-               /* overrun is special, not associated with a char */
-               if (status & UART_OVERRUN_ERROR)
-                       tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
-
-               if (status & UART_DCD) {
-                       struct tty_struct *tty = tty_port_tty_get(&port->port);
-                       if (tty) {
-                               usb_serial_handle_dcd_change(port, tty,
-                                      priv->line_status & MSR_STATUS_LINE_DCD);
-                               tty_kref_put(tty);
-                       }
-               }
-       }
-
-       tty_insert_flip_string_fixed_flag(&port->port, data, tty_flag,
-                                                       urb->actual_length);
-       tty_flip_buffer_push(&port->port);
-}
-
-static int spcp8x5_wait_modem_info(struct usb_serial_port *port,
-                                  unsigned int arg)
-{
-       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
-       unsigned long flags;
-       unsigned int prevstatus;
-       unsigned int status;
-       unsigned int changed;
-
-       spin_lock_irqsave(&priv->lock, flags);
-       prevstatus = priv->line_status;
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       while (1) {
-               /* wake up in bulk read */
-               interruptible_sleep_on(&port->delta_msr_wait);
-
-               /* see if a signal did it */
-               if (signal_pending(current))
-                       return -ERESTARTSYS;
-
-               if (port->serial->disconnected)
-                       return -EIO;
-
-               spin_lock_irqsave(&priv->lock, flags);
-               status = priv->line_status;
-               spin_unlock_irqrestore(&priv->lock, flags);
-
-               changed = prevstatus^status;
-
-               if (((arg & TIOCM_RNG) && (changed & MSR_STATUS_LINE_RI)) ||
-                   ((arg & TIOCM_DSR) && (changed & MSR_STATUS_LINE_DSR)) ||
-                   ((arg & TIOCM_CD)  && (changed & MSR_STATUS_LINE_DCD)) ||
-                   ((arg & TIOCM_CTS) && (changed & MSR_STATUS_LINE_CTS)))
-                       return 0;
-
-               prevstatus = status;
-       }
-       /* NOTREACHED */
-       return 0;
-}
-
-static int spcp8x5_ioctl(struct tty_struct *tty,
-                        unsigned int cmd, unsigned long arg)
-{
-       struct usb_serial_port *port = tty->driver_data;
-
-       dev_dbg(&port->dev, "%s (%d) cmd = 0x%04x\n", __func__,
-               port->number, cmd);
-
-       switch (cmd) {
-       case TIOCMIWAIT:
-               dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,
-                       port->number);
-               return spcp8x5_wait_modem_info(port, arg);
-
-       default:
-               dev_dbg(&port->dev, "%s not supported = 0x%04x", __func__,
-                       cmd);
-               break;
-       }
-
-       return -ENOIOCTLCMD;
-}
-
 static int spcp8x5_tiocmset(struct tty_struct *tty,
                            unsigned int set, unsigned int clear)
 {
@@ -594,7 +438,7 @@ static int spcp8x5_tiocmset(struct tty_struct *tty,
        control = priv->line_control;
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       return spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
+       return spcp8x5_set_ctrl_line(port, control);
 }
 
 static int spcp8x5_tiocmget(struct tty_struct *tty)
@@ -603,12 +447,15 @@ static int spcp8x5_tiocmget(struct tty_struct *tty)
        struct spcp8x5_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
        unsigned int mcr;
-       unsigned int status;
+       u8 status;
        unsigned int result;
 
+       result = spcp8x5_get_msr(port, &status);
+       if (result)
+               return result;
+
        spin_lock_irqsave(&priv->lock, flags);
        mcr = priv->line_control;
-       status = priv->line_status;
        spin_unlock_irqrestore(&priv->lock, flags);
 
        result = ((mcr & MCR_DTR)                       ? TIOCM_DTR : 0)
@@ -621,7 +468,6 @@ static int spcp8x5_tiocmget(struct tty_struct *tty)
        return result;
 }
 
-/* All of the device info needed for the spcp8x5 SIO serial converter */
 static struct usb_serial_driver spcp8x5_device = {
        .driver = {
                .owner =        THIS_MODULE,
@@ -629,17 +475,16 @@ static struct usb_serial_driver spcp8x5_device = {
        },
        .id_table               = id_table,
        .num_ports              = 1,
-       .open                   = spcp8x5_open,
+       .open                   = spcp8x5_open,
        .dtr_rts                = spcp8x5_dtr_rts,
        .carrier_raised         = spcp8x5_carrier_raised,
-       .set_termios            = spcp8x5_set_termios,
+       .set_termios            = spcp8x5_set_termios,
        .init_termios           = spcp8x5_init_termios,
-       .ioctl                  = spcp8x5_ioctl,
-       .tiocmget               = spcp8x5_tiocmget,
-       .tiocmset               = spcp8x5_tiocmset,
+       .tiocmget               = spcp8x5_tiocmget,
+       .tiocmset               = spcp8x5_tiocmset,
+       .probe                  = spcp8x5_probe,
        .port_probe             = spcp8x5_port_probe,
        .port_remove            = spcp8x5_port_remove,
-       .process_read_urb       = spcp8x5_process_read_urb,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
index 4b2a19757b4d531baa8dfb48c8009517d2d21cb5..5b62dbbdf996b53bcb4f82ea6966dae7c2fa5801 100644 (file)
@@ -61,7 +61,6 @@ struct ssu100_port_private {
        spinlock_t status_lock;
        u8 shadowLSR;
        u8 shadowMSR;
-       struct async_icount icount;
 };
 
 static inline int ssu100_control_msg(struct usb_device *dev,
@@ -315,11 +314,6 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port)
        return usb_serial_generic_open(tty, port);
 }
 
-static void ssu100_close(struct usb_serial_port *port)
-{
-       usb_serial_generic_close(port);
-}
-
 static int get_serial_info(struct usb_serial_port *port,
                           struct serial_struct __user *retinfo)
 {
@@ -343,73 +337,6 @@ static int get_serial_info(struct usb_serial_port *port,
        return 0;
 }
 
-static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
-{
-       struct ssu100_port_private *priv = usb_get_serial_port_data(port);
-       struct async_icount prev, cur;
-       unsigned long flags;
-
-       spin_lock_irqsave(&priv->status_lock, flags);
-       prev = priv->icount;
-       spin_unlock_irqrestore(&priv->status_lock, flags);
-
-       while (1) {
-               wait_event_interruptible(port->delta_msr_wait,
-                                        (port->serial->disconnected ||
-                                         (priv->icount.rng != prev.rng) ||
-                                         (priv->icount.dsr != prev.dsr) ||
-                                         (priv->icount.dcd != prev.dcd) ||
-                                         (priv->icount.cts != prev.cts)));
-
-               if (signal_pending(current))
-                       return -ERESTARTSYS;
-
-               if (port->serial->disconnected)
-                       return -EIO;
-
-               spin_lock_irqsave(&priv->status_lock, flags);
-               cur = priv->icount;
-               spin_unlock_irqrestore(&priv->status_lock, flags);
-
-               if ((prev.rng == cur.rng) &&
-                   (prev.dsr == cur.dsr) &&
-                   (prev.dcd == cur.dcd) &&
-                   (prev.cts == cur.cts))
-                       return -EIO;
-
-               if ((arg & TIOCM_RNG && (prev.rng != cur.rng)) ||
-                   (arg & TIOCM_DSR && (prev.dsr != cur.dsr)) ||
-                   (arg & TIOCM_CD  && (prev.dcd != cur.dcd)) ||
-                   (arg & TIOCM_CTS && (prev.cts != cur.cts)))
-                       return 0;
-       }
-       return 0;
-}
-
-static int ssu100_get_icount(struct tty_struct *tty,
-                       struct serial_icounter_struct *icount)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct ssu100_port_private *priv = usb_get_serial_port_data(port);
-       struct async_icount cnow = priv->icount;
-
-       icount->cts = cnow.cts;
-       icount->dsr = cnow.dsr;
-       icount->rng = cnow.rng;
-       icount->dcd = cnow.dcd;
-       icount->rx = cnow.rx;
-       icount->tx = cnow.tx;
-       icount->frame = cnow.frame;
-       icount->overrun = cnow.overrun;
-       icount->parity = cnow.parity;
-       icount->brk = cnow.brk;
-       icount->buf_overrun = cnow.buf_overrun;
-
-       return 0;
-}
-
-
-
 static int ssu100_ioctl(struct tty_struct *tty,
                    unsigned int cmd, unsigned long arg)
 {
@@ -421,10 +348,6 @@ static int ssu100_ioctl(struct tty_struct *tty,
        case TIOCGSERIAL:
                return get_serial_info(port,
                                       (struct serial_struct __user *) arg);
-
-       case TIOCMIWAIT:
-               return wait_modem_info(port, arg);
-
        default:
                break;
        }
@@ -532,14 +455,14 @@ static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)
        if (msr & UART_MSR_ANY_DELTA) {
                /* update input line counters */
                if (msr & UART_MSR_DCTS)
-                       priv->icount.cts++;
+                       port->icount.cts++;
                if (msr & UART_MSR_DDSR)
-                       priv->icount.dsr++;
+                       port->icount.dsr++;
                if (msr & UART_MSR_DDCD)
-                       priv->icount.dcd++;
+                       port->icount.dcd++;
                if (msr & UART_MSR_TERI)
-                       priv->icount.rng++;
-               wake_up_interruptible(&port->delta_msr_wait);
+                       port->icount.rng++;
+               wake_up_interruptible(&port->port.delta_msr_wait);
        }
 }
 
@@ -558,22 +481,22 @@ static void ssu100_update_lsr(struct usb_serial_port *port, u8 lsr,
                /* we always want to update icount, but we only want to
                 * update tty_flag for one case */
                if (lsr & UART_LSR_BI) {
-                       priv->icount.brk++;
+                       port->icount.brk++;
                        *tty_flag = TTY_BREAK;
                        usb_serial_handle_break(port);
                }
                if (lsr & UART_LSR_PE) {
-                       priv->icount.parity++;
+                       port->icount.parity++;
                        if (*tty_flag == TTY_NORMAL)
                                *tty_flag = TTY_PARITY;
                }
                if (lsr & UART_LSR_FE) {
-                       priv->icount.frame++;
+                       port->icount.frame++;
                        if (*tty_flag == TTY_NORMAL)
                                *tty_flag = TTY_FRAME;
                }
                if (lsr & UART_LSR_OE){
-                       priv->icount.overrun++;
+                       port->icount.overrun++;
                        if (*tty_flag == TTY_NORMAL)
                                *tty_flag = TTY_OVERRUN;
                }
@@ -630,7 +553,6 @@ static struct usb_serial_driver ssu100_device = {
        .id_table            = id_table,
        .num_ports           = 1,
        .open                = ssu100_open,
-       .close               = ssu100_close,
        .attach              = ssu100_attach,
        .port_probe          = ssu100_port_probe,
        .port_remove         = ssu100_port_remove,
@@ -638,10 +560,10 @@ static struct usb_serial_driver ssu100_device = {
        .process_read_urb    = ssu100_process_read_urb,
        .tiocmget            = ssu100_tiocmget,
        .tiocmset            = ssu100_tiocmset,
-       .get_icount          = ssu100_get_icount,
+       .tiocmiwait          = usb_serial_generic_tiocmiwait,
+       .get_icount          = usb_serial_generic_get_icount,
        .ioctl               = ssu100_ioctl,
        .set_termios         = ssu100_set_termios,
-       .disconnect          = usb_serial_generic_disconnect,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
index be05e6caf9a3c501f617c92cee83a6ba84469a28..9b1648945e7a854151d260dd79815a8db90f4b12 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Symbol USB barcode to serial driver
  *
+ * Copyright (C) 2013 Johan Hovold <jhovold@gmail.com>
  * Copyright (C) 2009 Greg Kroah-Hartman <gregkh@suse.de>
  * Copyright (C) 2009 Novell Inc.
  *
@@ -26,27 +27,17 @@ static const struct usb_device_id id_table[] = {
 };
 MODULE_DEVICE_TABLE(usb, id_table);
 
-/* This structure holds all of the individual device information */
 struct symbol_private {
-       struct usb_device *udev;
-       struct usb_serial *serial;
-       struct usb_serial_port *port;
-       unsigned char *int_buffer;
-       struct urb *int_urb;
-       int buffer_size;
-       u8 bInterval;
-       u8 int_address;
        spinlock_t lock;        /* protects the following flags */
        bool throttled;
        bool actually_throttled;
-       bool rts;
 };
 
 static void symbol_int_callback(struct urb *urb)
 {
-       struct symbol_private *priv = urb->context;
+       struct usb_serial_port *port = urb->context;
+       struct symbol_private *priv = usb_get_serial_port_data(port);
        unsigned char *data = urb->transfer_buffer;
-       struct usb_serial_port *port = priv->port;
        int status = urb->status;
        int result;
        int data_length;
@@ -84,7 +75,7 @@ static void symbol_int_callback(struct urb *urb)
                tty_insert_flip_string(&port->port, &data[1], data_length);
                tty_flip_buffer_push(&port->port);
        } else {
-               dev_dbg(&priv->udev->dev,
+               dev_dbg(&port->dev,
                        "Improper amount of data received from the device, "
                        "%d bytes", urb->actual_length);
        }
@@ -94,12 +85,7 @@ exit:
 
        /* Continue trying to always read if we should */
        if (!priv->throttled) {
-               usb_fill_int_urb(priv->int_urb, priv->udev,
-                                usb_rcvintpipe(priv->udev,
-                                               priv->int_address),
-                                priv->int_buffer, priv->buffer_size,
-                                symbol_int_callback, priv, priv->bInterval);
-               result = usb_submit_urb(priv->int_urb, GFP_ATOMIC);
+               result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
                if (result)
                        dev_err(&port->dev,
                            "%s - failed resubmitting read urb, error %d\n",
@@ -118,15 +104,10 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port)
        spin_lock_irqsave(&priv->lock, flags);
        priv->throttled = false;
        priv->actually_throttled = false;
-       priv->port = port;
        spin_unlock_irqrestore(&priv->lock, flags);
 
        /* Start reading from the device */
-       usb_fill_int_urb(priv->int_urb, priv->udev,
-                        usb_rcvintpipe(priv->udev, priv->int_address),
-                        priv->int_buffer, priv->buffer_size,
-                        symbol_int_callback, priv, priv->bInterval);
-       result = usb_submit_urb(priv->int_urb, GFP_KERNEL);
+       result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
        if (result)
                dev_err(&port->dev,
                        "%s - failed resubmitting read urb, error %d\n",
@@ -136,10 +117,7 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port)
 
 static void symbol_close(struct usb_serial_port *port)
 {
-       struct symbol_private *priv = usb_get_serial_data(port->serial);
-
-       /* shutdown our urbs */
-       usb_kill_urb(priv->int_urb);
+       usb_kill_urb(port->interrupt_in_urb);
 }
 
 static void symbol_throttle(struct tty_struct *tty)
@@ -166,7 +144,7 @@ static void symbol_unthrottle(struct tty_struct *tty)
        spin_unlock_irq(&priv->lock);
 
        if (was_throttled) {
-               result = usb_submit_urb(priv->int_urb, GFP_KERNEL);
+               result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
                if (result)
                        dev_err(&port->dev,
                                "%s - failed submitting read urb, error %d\n",
@@ -175,90 +153,37 @@ static void symbol_unthrottle(struct tty_struct *tty)
 }
 
 static int symbol_startup(struct usb_serial *serial)
+{
+       if (!serial->num_interrupt_in) {
+               dev_err(&serial->dev->dev, "no interrupt-in endpoint\n");
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static int symbol_port_probe(struct usb_serial_port *port)
 {
        struct symbol_private *priv;
-       struct usb_host_interface *intf;
-       int i;
-       int retval = -ENOMEM;
-       bool int_in_found = false;
 
-       /* create our private serial structure */
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-       if (priv == NULL) {
-               dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__);
+       if (!priv)
                return -ENOMEM;
-       }
+
        spin_lock_init(&priv->lock);
-       priv->serial = serial;
-       priv->port = serial->port[0];
-       priv->udev = serial->dev;
-
-       /* find our interrupt endpoint */
-       intf = serial->interface->altsetting;
-       for (i = 0; i < intf->desc.bNumEndpoints; ++i) {
-               struct usb_endpoint_descriptor *endpoint;
-
-               endpoint = &intf->endpoint[i].desc;
-               if (!usb_endpoint_is_int_in(endpoint))
-                       continue;
-
-               priv->int_urb = usb_alloc_urb(0, GFP_KERNEL);
-               if (!priv->int_urb) {
-                       dev_err(&priv->udev->dev, "out of memory\n");
-                       goto error;
-               }
-
-               priv->buffer_size = usb_endpoint_maxp(endpoint) * 2;
-               priv->int_buffer = kmalloc(priv->buffer_size, GFP_KERNEL);
-               if (!priv->int_buffer) {
-                       dev_err(&priv->udev->dev, "out of memory\n");
-                       goto error;
-               }
-
-               priv->int_address = endpoint->bEndpointAddress;
-               priv->bInterval = endpoint->bInterval;
-
-               /* set up our int urb */
-               usb_fill_int_urb(priv->int_urb, priv->udev,
-                                usb_rcvintpipe(priv->udev,
-                                               endpoint->bEndpointAddress),
-                                priv->int_buffer, priv->buffer_size,
-                                symbol_int_callback, priv, priv->bInterval);
-
-               int_in_found = true;
-               break;
-               }
 
-       if (!int_in_found) {
-               dev_err(&priv->udev->dev,
-                       "Error - the proper endpoints were not found!\n");
-               goto error;
-       }
+       usb_set_serial_port_data(port, priv);
 
-       usb_set_serial_data(serial, priv);
        return 0;
-
-error:
-       usb_free_urb(priv->int_urb);
-       kfree(priv->int_buffer);
-       kfree(priv);
-       return retval;
-}
-
-static void symbol_disconnect(struct usb_serial *serial)
-{
-       struct symbol_private *priv = usb_get_serial_data(serial);
-
-       usb_kill_urb(priv->int_urb);
-       usb_free_urb(priv->int_urb);
 }
 
-static void symbol_release(struct usb_serial *serial)
+static int symbol_port_remove(struct usb_serial_port *port)
 {
-       struct symbol_private *priv = usb_get_serial_data(serial);
+       struct symbol_private *priv = usb_get_serial_port_data(port);
 
-       kfree(priv->int_buffer);
        kfree(priv);
+
+       return 0;
 }
 
 static struct usb_serial_driver symbol_device = {
@@ -269,12 +194,13 @@ static struct usb_serial_driver symbol_device = {
        .id_table =             id_table,
        .num_ports =            1,
        .attach =               symbol_startup,
+       .port_probe =           symbol_port_probe,
+       .port_remove =          symbol_port_remove,
        .open =                 symbol_open,
        .close =                symbol_close,
-       .disconnect =           symbol_disconnect,
-       .release =              symbol_release,
        .throttle =             symbol_throttle,
        .unthrottle =           symbol_unthrottle,
+       .read_int_callback =    symbol_int_callback,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
index 19a71a9eecf09130d196dc8131e00733c9e09f4e..cac47aef2918972ead4aeb01a43bd9166daec0ca 100644 (file)
 struct ti_port {
        int                     tp_is_open;
        __u8                    tp_msr;
-       __u8                    tp_lsr;
        __u8                    tp_shadow_mcr;
        __u8                    tp_uart_mode;   /* 232 or 485 modes */
        unsigned int            tp_uart_base_addr;
        int                     tp_flags;
-       int                     tp_closing_wait;/* in .01 secs */
-       struct async_icount     tp_icount;
        wait_queue_head_t       tp_write_wait;
        struct ti_device        *tp_tdev;
        struct usb_serial_port  *tp_port;
@@ -108,8 +105,6 @@ static void ti_throttle(struct tty_struct *tty);
 static void ti_unthrottle(struct tty_struct *tty);
 static int ti_ioctl(struct tty_struct *tty,
                unsigned int cmd, unsigned long arg);
-static int ti_get_icount(struct tty_struct *tty,
-               struct serial_icounter_struct *icount);
 static void ti_set_termios(struct tty_struct *tty,
                struct usb_serial_port *port, struct ktermios *old_termios);
 static int ti_tiocmget(struct tty_struct *tty);
@@ -124,15 +119,13 @@ static void ti_recv(struct usb_serial_port *port, unsigned char *data,
                int length);
 static void ti_send(struct ti_port *tport);
 static int ti_set_mcr(struct ti_port *tport, unsigned int mcr);
-static int ti_get_lsr(struct ti_port *tport);
+static int ti_get_lsr(struct ti_port *tport, u8 *lsr);
 static int ti_get_serial_info(struct ti_port *tport,
        struct serial_struct __user *ret_arg);
 static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport,
        struct serial_struct __user *new_arg);
 static void ti_handle_new_msr(struct ti_port *tport, __u8 msr);
 
-static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush);
-
 static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty);
 static int ti_restart_read(struct ti_port *tport, struct tty_struct *tty);
 
@@ -235,7 +228,8 @@ static struct usb_serial_driver ti_1port_device = {
        .set_termios            = ti_set_termios,
        .tiocmget               = ti_tiocmget,
        .tiocmset               = ti_tiocmset,
-       .get_icount             = ti_get_icount,
+       .tiocmiwait             = usb_serial_generic_tiocmiwait,
+       .get_icount             = usb_serial_generic_get_icount,
        .break_ctl              = ti_break,
        .read_int_callback      = ti_interrupt_callback,
        .read_bulk_callback     = ti_bulk_in_callback,
@@ -265,7 +259,8 @@ static struct usb_serial_driver ti_2port_device = {
        .set_termios            = ti_set_termios,
        .tiocmget               = ti_tiocmget,
        .tiocmset               = ti_tiocmset,
-       .get_icount             = ti_get_icount,
+       .tiocmiwait             = usb_serial_generic_tiocmiwait,
+       .get_icount             = usb_serial_generic_get_icount,
        .break_ctl              = ti_break,
        .read_int_callback      = ti_interrupt_callback,
        .read_bulk_callback     = ti_bulk_in_callback,
@@ -430,7 +425,7 @@ static int ti_port_probe(struct usb_serial_port *port)
                tport->tp_uart_base_addr = TI_UART1_BASE_ADDR;
        else
                tport->tp_uart_base_addr = TI_UART2_BASE_ADDR;
-       tport->tp_closing_wait = closing_wait;
+       port->port.closing_wait = msecs_to_jiffies(10 * closing_wait);
        init_waitqueue_head(&tport->tp_write_wait);
        if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) {
                kfree(tport);
@@ -480,8 +475,6 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
 
        port_number = port->number - port->serial->minor;
 
-       memset(&(tport->tp_icount), 0x00, sizeof(tport->tp_icount));
-
        tport->tp_msr = 0;
        tport->tp_shadow_mcr |= (TI_MCR_RTS | TI_MCR_DTR);
 
@@ -585,6 +578,8 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
        tport->tp_is_open = 1;
        ++tdev->td_open_port_count;
 
+       port->port.drain_delay = 3;
+
        goto release_lock;
 
 unlink_int_urb:
@@ -604,6 +599,7 @@ static void ti_close(struct usb_serial_port *port)
        int port_number;
        int status;
        int do_unlock;
+       unsigned long flags;
 
        tdev = usb_get_serial_data(port->serial);
        tport = usb_get_serial_port_data(port);
@@ -612,11 +608,12 @@ static void ti_close(struct usb_serial_port *port)
 
        tport->tp_is_open = 0;
 
-       ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 1);
-
        usb_kill_urb(port->read_urb);
        usb_kill_urb(port->write_urb);
        tport->tp_write_urb_in_use = 0;
+       spin_lock_irqsave(&tport->tp_lock, flags);
+       kfifo_reset_out(&tport->write_fifo);
+       spin_unlock_irqrestore(&tport->tp_lock, flags);
 
        port_number = port->number - port->serial->minor;
 
@@ -687,6 +684,8 @@ static int ti_chars_in_buffer(struct tty_struct *tty)
        struct ti_port *tport = usb_get_serial_port_data(port);
        int chars = 0;
        unsigned long flags;
+       int ret;
+       u8 lsr;
 
        if (tport == NULL)
                return 0;
@@ -695,6 +694,12 @@ static int ti_chars_in_buffer(struct tty_struct *tty)
        chars = kfifo_len(&tport->write_fifo);
        spin_unlock_irqrestore(&tport->tp_lock, flags);
 
+       if (!chars) {
+               ret = ti_get_lsr(tport, &lsr);
+               if (!ret && !(lsr & TI_LSR_TX_EMPTY))
+                       chars = 1;
+       }
+
        dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars);
        return chars;
 }
@@ -731,38 +736,11 @@ static void ti_unthrottle(struct tty_struct *tty)
        }
 }
 
-static int ti_get_icount(struct tty_struct *tty,
-               struct serial_icounter_struct *icount)
-{
-       struct usb_serial_port *port = tty->driver_data;
-       struct ti_port *tport = usb_get_serial_port_data(port);
-       struct async_icount cnow = tport->tp_icount;
-
-       dev_dbg(&port->dev, "%s - TIOCGICOUNT RX=%d, TX=%d\n", __func__,
-               cnow.rx, cnow.tx);
-
-       icount->cts = cnow.cts;
-       icount->dsr = cnow.dsr;
-       icount->rng = cnow.rng;
-       icount->dcd = cnow.dcd;
-       icount->rx = cnow.rx;
-       icount->tx = cnow.tx;
-       icount->frame = cnow.frame;
-       icount->overrun = cnow.overrun;
-       icount->parity = cnow.parity;
-       icount->brk = cnow.brk;
-       icount->buf_overrun = cnow.buf_overrun;
-
-       return 0;
-}
-
 static int ti_ioctl(struct tty_struct *tty,
        unsigned int cmd, unsigned long arg)
 {
        struct usb_serial_port *port = tty->driver_data;
        struct ti_port *tport = usb_get_serial_port_data(port);
-       struct async_icount cnow;
-       struct async_icount cprev;
 
        dev_dbg(&port->dev, "%s - cmd = 0x%04X\n", __func__, cmd);
 
@@ -778,29 +756,6 @@ static int ti_ioctl(struct tty_struct *tty,
                dev_dbg(&port->dev, "%s - TIOCSSERIAL\n", __func__);
                return ti_set_serial_info(tty, tport,
                                (struct serial_struct __user *)arg);
-       case TIOCMIWAIT:
-               dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__);
-               cprev = tport->tp_icount;
-               while (1) {
-                       interruptible_sleep_on(&port->delta_msr_wait);
-                       if (signal_pending(current))
-                               return -ERESTARTSYS;
-
-                       if (port->serial->disconnected)
-                               return -EIO;
-
-                       cnow = tport->tp_icount;
-                       if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-                           cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-                               return -EIO; /* no change => error */
-                       if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-                           ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-                           ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-                           ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)))
-                               return 0;
-                       cprev = cnow;
-               }
-               break;
        }
        return -ENOIOCTLCMD;
 }
@@ -1018,8 +973,6 @@ static void ti_break(struct tty_struct *tty, int break_state)
        if (tport == NULL)
                return;
 
-       ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 0);
-
        status = ti_write_byte(port, tport->tp_tdev,
                tport->tp_uart_base_addr + TI_UART_OFFSET_LCR,
                TI_LCR_BREAK, break_state == -1 ? TI_LCR_BREAK : 0);
@@ -1156,7 +1109,7 @@ static void ti_bulk_in_callback(struct urb *urb)
                else
                        ti_recv(port, urb->transfer_buffer, urb->actual_length);
                spin_lock(&tport->tp_lock);
-               tport->tp_icount.rx += urb->actual_length;
+               port->icount.rx += urb->actual_length;
                spin_unlock(&tport->tp_lock);
        }
 
@@ -1264,7 +1217,7 @@ static void ti_send(struct ti_port *tport)
                /* TODO: reschedule ti_send */
        } else {
                spin_lock_irqsave(&tport->tp_lock, flags);
-               tport->tp_icount.tx += count;
+               port->icount.tx += count;
                spin_unlock_irqrestore(&tport->tp_lock, flags);
        }
 
@@ -1297,7 +1250,7 @@ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr)
 }
 
 
-static int ti_get_lsr(struct ti_port *tport)
+static int ti_get_lsr(struct ti_port *tport, u8 *lsr)
 {
        int size, status;
        struct ti_device *tdev = tport->tp_tdev;
@@ -1323,7 +1276,7 @@ static int ti_get_lsr(struct ti_port *tport)
 
        dev_dbg(&port->dev, "%s - lsr 0x%02X\n", __func__, data->bLSR);
 
-       tport->tp_lsr = data->bLSR;
+       *lsr = data->bLSR;
 
 free_data:
        kfree(data);
@@ -1336,10 +1289,15 @@ static int ti_get_serial_info(struct ti_port *tport,
 {
        struct usb_serial_port *port = tport->tp_port;
        struct serial_struct ret_serial;
+       unsigned cwait;
 
        if (!ret_arg)
                return -EFAULT;
 
+       cwait = port->port.closing_wait;
+       if (cwait != ASYNC_CLOSING_WAIT_NONE)
+               cwait = jiffies_to_msecs(cwait) / 10;
+
        memset(&ret_serial, 0, sizeof(ret_serial));
 
        ret_serial.type = PORT_16550A;
@@ -1348,7 +1306,7 @@ static int ti_get_serial_info(struct ti_port *tport,
        ret_serial.flags = tport->tp_flags;
        ret_serial.xmit_fifo_size = TI_WRITE_BUF_SIZE;
        ret_serial.baud_base = tport->tp_tdev->td_is_3410 ? 921600 : 460800;
-       ret_serial.closing_wait = tport->tp_closing_wait;
+       ret_serial.closing_wait = cwait;
 
        if (copy_to_user(ret_arg, &ret_serial, sizeof(*ret_arg)))
                return -EFAULT;
@@ -1361,12 +1319,17 @@ static int ti_set_serial_info(struct tty_struct *tty, struct ti_port *tport,
        struct serial_struct __user *new_arg)
 {
        struct serial_struct new_serial;
+       unsigned cwait;
 
        if (copy_from_user(&new_serial, new_arg, sizeof(new_serial)))
                return -EFAULT;
 
+       cwait = new_serial.closing_wait;
+       if (cwait != ASYNC_CLOSING_WAIT_NONE)
+               cwait = msecs_to_jiffies(10 * new_serial.closing_wait);
+
        tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS;
-       tport->tp_closing_wait = new_serial.closing_wait;
+       tport->tp_port->port.closing_wait = cwait;
 
        return 0;
 }
@@ -1382,7 +1345,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
 
        if (msr & TI_MSR_DELTA_MASK) {
                spin_lock_irqsave(&tport->tp_lock, flags);
-               icount = &tport->tp_icount;
+               icount = &tport->tp_port->icount;
                if (msr & TI_MSR_DELTA_CTS)
                        icount->cts++;
                if (msr & TI_MSR_DELTA_DSR)
@@ -1391,7 +1354,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
                        icount->dcd++;
                if (msr & TI_MSR_DELTA_RI)
                        icount->rng++;
-               wake_up_interruptible(&tport->tp_port->delta_msr_wait);
+               wake_up_interruptible(&tport->tp_port->port.delta_msr_wait);
                spin_unlock_irqrestore(&tport->tp_lock, flags);
        }
 
@@ -1411,56 +1374,6 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
 }
 
 
-static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush)
-{
-       struct ti_device *tdev = tport->tp_tdev;
-       struct usb_serial_port *port = tport->tp_port;
-       wait_queue_t wait;
-
-       spin_lock_irq(&tport->tp_lock);
-
-       /* wait for data to drain from the buffer */
-       tdev->td_urb_error = 0;
-       init_waitqueue_entry(&wait, current);
-       add_wait_queue(&tport->tp_write_wait, &wait);
-       for (;;) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (kfifo_len(&tport->write_fifo) == 0
-               || timeout == 0 || signal_pending(current)
-               || tdev->td_urb_error
-               || port->serial->disconnected)  /* disconnect */
-                       break;
-               spin_unlock_irq(&tport->tp_lock);
-               timeout = schedule_timeout(timeout);
-               spin_lock_irq(&tport->tp_lock);
-       }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&tport->tp_write_wait, &wait);
-
-       /* flush any remaining data in the buffer */
-       if (flush)
-               kfifo_reset_out(&tport->write_fifo);
-
-       spin_unlock_irq(&tport->tp_lock);
-
-       mutex_lock(&port->serial->disc_mutex);
-       /* wait for data to drain from the device */
-       /* wait for empty tx register, plus 20 ms */
-       timeout += jiffies;
-       tport->tp_lsr &= ~TI_LSR_TX_EMPTY;
-       while ((long)(jiffies - timeout) < 0 && !signal_pending(current)
-       && !(tport->tp_lsr&TI_LSR_TX_EMPTY) && !tdev->td_urb_error
-       && !port->serial->disconnected) {
-               if (ti_get_lsr(tport))
-                       break;
-               mutex_unlock(&port->serial->disc_mutex);
-               msleep_interruptible(20);
-               mutex_lock(&port->serial->disc_mutex);
-       }
-       mutex_unlock(&port->serial->disc_mutex);
-}
-
-
 static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty)
 {
        unsigned long flags;
index 650be17a68f20993b4cf24489eafed109afa08a7..cf75beb1251bc85b3c709b989e1ddd5220094c7c 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * USB Serial Converter driver
  *
+ * Copyright (C) 2009 - 2013 Johan Hovold (jhovold@gmail.com)
  * Copyright (C) 1999 - 2012 Greg Kroah-Hartman (greg@kroah.com)
  * Copyright (C) 2000 Peter Berger (pberger@brimson.com)
  * Copyright (C) 2000 Al Borchers (borchers@steinerpoint.com)
@@ -14,7 +15,6 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this
  * driver
- *
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -49,7 +49,6 @@
    drivers depend on it.
 */
 
-/* initially all NULL */
 static struct usb_serial *serial_table[SERIAL_TTY_MINORS];
 static DEFINE_MUTEX(table_lock);
 static LIST_HEAD(usb_serial_driver_list);
@@ -139,7 +138,7 @@ static void destroy_serial(struct kref *kref)
        if (serial->minor != SERIAL_TTY_NO_MINOR)
                return_serial(serial);
 
-       if (serial->attached)
+       if (serial->attached && serial->type->release)
                serial->type->release(serial);
 
        /* Now that nothing is using the ports, they can be freed */
@@ -225,7 +224,7 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty)
        return retval;
 }
 
-static int serial_activate(struct tty_port *tport, struct tty_struct *tty)
+static int serial_port_activate(struct tty_port *tport, struct tty_struct *tty)
 {
        struct usb_serial_port *port =
                container_of(tport, struct usb_serial_port, port);
@@ -249,30 +248,27 @@ static int serial_open(struct tty_struct *tty, struct file *filp)
 {
        struct usb_serial_port *port = tty->driver_data;
 
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
+
        return tty_port_open(&port->port, tty, filp);
 }
 
 /**
- * serial_down - shut down hardware
+ * serial_port_shutdown - shut down hardware
  * @tport: tty port to shut down
  *
- * Shut down a USB serial port unless it is the console.  We never
- * shut down the console hardware as it will always be in use. Serialized
- * against activate by the tport mutex and kept to matching open/close pairs
+ * Shut down a USB serial port. Serialized against activate by the
+ * tport mutex and kept to matching open/close pairs
  * of calls by the ASYNCB_INITIALIZED flag.
+ *
+ * Not called if tty is console.
  */
-static void serial_down(struct tty_port *tport)
+static void serial_port_shutdown(struct tty_port *tport)
 {
        struct usb_serial_port *port =
                container_of(tport, struct usb_serial_port, port);
        struct usb_serial_driver *drv = port->serial->type;
-       /*
-        * The console is magical.  Do not hang up the console hardware
-        * or there will be tears.
-        */
-       if (port->port.console)
-               return;
+
        if (drv->close)
                drv->close(port);
 }
@@ -281,7 +277,8 @@ static void serial_hangup(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
 
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
+
        tty_port_hangup(&port->port);
 }
 
@@ -289,7 +286,8 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
 {
        struct usb_serial_port *port = tty->driver_data;
 
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
+
        tty_port_close(&port->port, tty, filp);
 }
 
@@ -308,14 +306,14 @@ static void serial_cleanup(struct tty_struct *tty)
        struct usb_serial *serial;
        struct module *owner;
 
+       dev_dbg(tty->dev, "%s\n", __func__);
+
        /* The console is magical.  Do not hang up the console hardware
         * or there will be tears.
         */
        if (port->port.console)
                return;
 
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
-
        tty->driver_data = NULL;
 
        serial = port->serial;
@@ -339,10 +337,8 @@ static int serial_write(struct tty_struct *tty, const unsigned char *buf,
        if (port->serial->dev->state == USB_STATE_NOTATTACHED)
                goto exit;
 
-       dev_dbg(tty->dev, "%s - port %d, %d byte(s)\n", __func__,
-               port->number, count);
+       dev_dbg(tty->dev, "%s - %d byte(s)\n", __func__, count);
 
-       /* pass on to the driver specific version of this function */
        retval = port->serial->type->write(tty, port, buf, count);
        if (retval < 0)
                retval = usb_translate_errors(retval);
@@ -354,8 +350,8 @@ static int serial_write_room(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
 
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
-       /* pass on to the driver specific version of this function */
+       dev_dbg(tty->dev, "%s\n", __func__);
+
        return port->serial->type->write_room(tty);
 }
 
@@ -365,7 +361,7 @@ static int serial_chars_in_buffer(struct tty_struct *tty)
        struct usb_serial *serial = port->serial;
        int count = 0;
 
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
 
        mutex_lock(&serial->disc_mutex);
        /* if the device was unplugged then any remaining characters
@@ -383,9 +379,8 @@ static void serial_throttle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
 
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
 
-       /* pass on to the driver specific version of this function */
        if (port->serial->type->throttle)
                port->serial->type->throttle(tty);
 }
@@ -394,9 +389,8 @@ static void serial_unthrottle(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
 
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
 
-       /* pass on to the driver specific version of this function */
        if (port->serial->type->unthrottle)
                port->serial->type->unthrottle(tty);
 }
@@ -407,15 +401,20 @@ static int serial_ioctl(struct tty_struct *tty,
        struct usb_serial_port *port = tty->driver_data;
        int retval = -ENODEV;
 
-       dev_dbg(tty->dev, "%s - port %d, cmd 0x%.4x\n", __func__,
-               port->number, cmd);
+       dev_dbg(tty->dev, "%s - cmd 0x%.4x\n", __func__, cmd);
+
+       switch (cmd) {
+       case TIOCMIWAIT:
+               if (port->serial->type->tiocmiwait)
+                       retval = port->serial->type->tiocmiwait(tty, arg);
+               break;
+       default:
+               if (port->serial->type->ioctl)
+                       retval = port->serial->type->ioctl(tty, cmd, arg);
+               else
+                       retval = -ENOIOCTLCMD;
+       }
 
-       /* pass on to the driver specific version of this function
-          if it is available */
-       if (port->serial->type->ioctl) {
-               retval = port->serial->type->ioctl(tty, cmd, arg);
-       } else
-               retval = -ENOIOCTLCMD;
        return retval;
 }
 
@@ -423,10 +422,8 @@ static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
 {
        struct usb_serial_port *port = tty->driver_data;
 
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
 
-       /* pass on to the driver specific version of this function
-          if it is available */
        if (port->serial->type->set_termios)
                port->serial->type->set_termios(tty, port, old);
        else
@@ -437,12 +434,11 @@ static int serial_break(struct tty_struct *tty, int break_state)
 {
        struct usb_serial_port *port = tty->driver_data;
 
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
 
-       /* pass on to the driver specific version of this function
-          if it is available */
        if (port->serial->type->break_ctl)
                port->serial->type->break_ctl(tty, break_state);
+
        return 0;
 }
 
@@ -496,7 +492,7 @@ static int serial_tiocmget(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
 
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
 
        if (port->serial->type->tiocmget)
                return port->serial->type->tiocmget(tty);
@@ -508,7 +504,7 @@ static int serial_tiocmset(struct tty_struct *tty,
 {
        struct usb_serial_port *port = tty->driver_data;
 
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
 
        if (port->serial->type->tiocmset)
                return port->serial->type->tiocmset(tty, set, clear);
@@ -520,7 +516,7 @@ static int serial_get_icount(struct tty_struct *tty,
 {
        struct usb_serial_port *port = tty->driver_data;
 
-       dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number);
+       dev_dbg(tty->dev, "%s\n", __func__);
 
        if (port->serial->type->get_icount)
                return port->serial->type->get_icount(tty, icount);
@@ -546,43 +542,39 @@ static void usb_serial_port_work(struct work_struct *work)
        tty_port_tty_wakeup(&port->port);
 }
 
-static void kill_traffic(struct usb_serial_port *port)
+static void usb_serial_port_poison_urbs(struct usb_serial_port *port)
 {
        int i;
 
        for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
-               usb_kill_urb(port->read_urbs[i]);
+               usb_poison_urb(port->read_urbs[i]);
        for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
-               usb_kill_urb(port->write_urbs[i]);
-       /*
-        * This is tricky.
-        * Some drivers submit the read_urb in the
-        * handler for the write_urb or vice versa
-        * this order determines the order in which
-        * usb_kill_urb() must be used to reliably
-        * kill the URBs. As it is unknown here,
-        * both orders must be used in turn.
-        * The call below is not redundant.
-        */
-       usb_kill_urb(port->read_urb);
-       usb_kill_urb(port->interrupt_in_urb);
-       usb_kill_urb(port->interrupt_out_urb);
+               usb_poison_urb(port->write_urbs[i]);
+
+       usb_poison_urb(port->interrupt_in_urb);
+       usb_poison_urb(port->interrupt_out_urb);
+}
+
+static void usb_serial_port_unpoison_urbs(struct usb_serial_port *port)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i)
+               usb_unpoison_urb(port->read_urbs[i]);
+       for (i = 0; i < ARRAY_SIZE(port->write_urbs); ++i)
+               usb_unpoison_urb(port->write_urbs[i]);
+
+       usb_unpoison_urb(port->interrupt_in_urb);
+       usb_unpoison_urb(port->interrupt_out_urb);
 }
 
-static void port_release(struct device *dev)
+static void usb_serial_port_release(struct device *dev)
 {
        struct usb_serial_port *port = to_usb_serial_port(dev);
        int i;
 
        dev_dbg(dev, "%s\n", __func__);
 
-       /*
-        * Stop all the traffic before cancelling the work, so that
-        * nobody will restart it by calling usb_serial_port_softint.
-        */
-       kill_traffic(port);
-       cancel_work_sync(&port->work);
-
        usb_free_urb(port->interrupt_in_urb);
        usb_free_urb(port->interrupt_out_urb);
        for (i = 0; i < ARRAY_SIZE(port->read_urbs); ++i) {
@@ -607,10 +599,8 @@ static struct usb_serial *create_serial(struct usb_device *dev,
        struct usb_serial *serial;
 
        serial = kzalloc(sizeof(*serial), GFP_KERNEL);
-       if (!serial) {
-               dev_err(&dev->dev, "%s - out of memory\n", __func__);
+       if (!serial)
                return NULL;
-       }
        serial->dev = usb_get_dev(dev);
        serial->type = driver;
        serial->interface = usb_get_intf(interface);
@@ -673,7 +663,7 @@ static struct usb_serial_driver *search_serial_device(
        return NULL;
 }
 
-static int serial_carrier_raised(struct tty_port *port)
+static int serial_port_carrier_raised(struct tty_port *port)
 {
        struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
        struct usb_serial_driver *drv = p->serial->type;
@@ -684,7 +674,7 @@ static int serial_carrier_raised(struct tty_port *port)
        return 1;
 }
 
-static void serial_dtr_rts(struct tty_port *port, int on)
+static void serial_port_dtr_rts(struct tty_port *port, int on)
 {
        struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
        struct usb_serial *serial = p->serial;
@@ -704,10 +694,10 @@ static void serial_dtr_rts(struct tty_port *port, int on)
 }
 
 static const struct tty_port_operations serial_port_ops = {
-       .carrier_raised = serial_carrier_raised,
-       .dtr_rts = serial_dtr_rts,
-       .activate = serial_activate,
-       .shutdown = serial_down,
+       .carrier_raised         = serial_port_carrier_raised,
+       .dtr_rts                = serial_port_dtr_rts,
+       .activate               = serial_port_activate,
+       .shutdown               = serial_port_shutdown,
 };
 
 static int usb_serial_probe(struct usb_interface *interface,
@@ -754,7 +744,6 @@ static int usb_serial_probe(struct usb_interface *interface,
        serial = create_serial(dev, interface, type);
        if (!serial) {
                module_put(type->driver.owner);
-               dev_err(ddev, "%s - out of memory\n", __func__);
                return -ENOMEM;
        }
 
@@ -895,7 +884,6 @@ static int usb_serial_probe(struct usb_interface *interface,
                port->port.ops = &serial_port_ops;
                port->serial = serial;
                spin_lock_init(&port->lock);
-               init_waitqueue_head(&port->delta_msr_wait);
                /* Keep this for private driver use for the moment but
                   should probably go away */
                INIT_WORK(&port->work, usb_serial_port_work);
@@ -903,7 +891,7 @@ static int usb_serial_probe(struct usb_interface *interface,
                port->dev.parent = &interface->dev;
                port->dev.driver = NULL;
                port->dev.bus = &usb_serial_bus_type;
-               port->dev.release = &port_release;
+               port->dev.release = &usb_serial_port_release;
                device_initialize(&port->dev);
        }
 
@@ -919,16 +907,12 @@ static int usb_serial_probe(struct usb_interface *interface,
                for (j = 0; j < ARRAY_SIZE(port->read_urbs); ++j) {
                        set_bit(j, &port->read_urbs_free);
                        port->read_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
-                       if (!port->read_urbs[j]) {
-                               dev_err(ddev, "No free urbs available\n");
+                       if (!port->read_urbs[j])
                                goto probe_error;
-                       }
                        port->bulk_in_buffers[j] = kmalloc(buffer_size,
                                                                GFP_KERNEL);
-                       if (!port->bulk_in_buffers[j]) {
-                               dev_err(ddev, "Couldn't allocate bulk_in_buffer\n");
+                       if (!port->bulk_in_buffers[j])
                                goto probe_error;
-                       }
                        usb_fill_bulk_urb(port->read_urbs[j], dev,
                                        usb_rcvbulkpipe(dev,
                                                endpoint->bEndpointAddress),
@@ -955,16 +939,12 @@ static int usb_serial_probe(struct usb_interface *interface,
                for (j = 0; j < ARRAY_SIZE(port->write_urbs); ++j) {
                        set_bit(j, &port->write_urbs_free);
                        port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL);
-                       if (!port->write_urbs[j]) {
-                               dev_err(ddev, "No free urbs available\n");
+                       if (!port->write_urbs[j])
                                goto probe_error;
-                       }
                        port->bulk_out_buffers[j] = kmalloc(buffer_size,
                                                                GFP_KERNEL);
-                       if (!port->bulk_out_buffers[j]) {
-                               dev_err(ddev, "Couldn't allocate bulk_out_buffer\n");
+                       if (!port->bulk_out_buffers[j])
                                goto probe_error;
-                       }
                        usb_fill_bulk_urb(port->write_urbs[j], dev,
                                        usb_sndbulkpipe(dev,
                                                endpoint->bEndpointAddress),
@@ -982,19 +962,15 @@ static int usb_serial_probe(struct usb_interface *interface,
                        endpoint = interrupt_in_endpoint[i];
                        port = serial->port[i];
                        port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
-                       if (!port->interrupt_in_urb) {
-                               dev_err(ddev, "No free urbs available\n");
+                       if (!port->interrupt_in_urb)
                                goto probe_error;
-                       }
                        buffer_size = usb_endpoint_maxp(endpoint);
                        port->interrupt_in_endpointAddress =
                                                endpoint->bEndpointAddress;
                        port->interrupt_in_buffer = kmalloc(buffer_size,
                                                                GFP_KERNEL);
-                       if (!port->interrupt_in_buffer) {
-                               dev_err(ddev, "Couldn't allocate interrupt_in_buffer\n");
+                       if (!port->interrupt_in_buffer)
                                goto probe_error;
-                       }
                        usb_fill_int_urb(port->interrupt_in_urb, dev,
                                usb_rcvintpipe(dev,
                                                endpoint->bEndpointAddress),
@@ -1011,20 +987,16 @@ static int usb_serial_probe(struct usb_interface *interface,
                        endpoint = interrupt_out_endpoint[i];
                        port = serial->port[i];
                        port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
-                       if (!port->interrupt_out_urb) {
-                               dev_err(ddev, "No free urbs available\n");
+                       if (!port->interrupt_out_urb)
                                goto probe_error;
-                       }
                        buffer_size = usb_endpoint_maxp(endpoint);
                        port->interrupt_out_size = buffer_size;
                        port->interrupt_out_endpointAddress =
                                                endpoint->bEndpointAddress;
                        port->interrupt_out_buffer = kmalloc(buffer_size,
                                                                GFP_KERNEL);
-                       if (!port->interrupt_out_buffer) {
-                               dev_err(ddev, "Couldn't allocate interrupt_out_buffer\n");
+                       if (!port->interrupt_out_buffer)
                                goto probe_error;
-                       }
                        usb_fill_int_urb(port->interrupt_out_urb, dev,
                                usb_sndintpipe(dev,
                                                  endpoint->bEndpointAddress),
@@ -1113,13 +1085,15 @@ static void usb_serial_disconnect(struct usb_interface *interface)
                                tty_vhangup(tty);
                                tty_kref_put(tty);
                        }
-                       kill_traffic(port);
+                       usb_serial_port_poison_urbs(port);
+                       wake_up_interruptible(&port->port.delta_msr_wait);
                        cancel_work_sync(&port->work);
                        if (device_is_registered(&port->dev))
                                device_del(&port->dev);
                }
        }
-       serial->type->disconnect(serial);
+       if (serial->type->disconnect)
+               serial->type->disconnect(serial);
 
        /* let the last holder of this object cause it to be cleaned up */
        usb_serial_put(serial);
@@ -1134,6 +1108,11 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
 
        serial->suspending = 1;
 
+       /*
+        * serial->type->suspend() MUST return 0 in system sleep context,
+        * otherwise, the resume callback has to recover device from
+        * previous suspend failure.
+        */
        if (serial->type->suspend) {
                r = serial->type->suspend(serial, message);
                if (r < 0) {
@@ -1145,7 +1124,7 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
        for (i = 0; i < serial->num_ports; ++i) {
                port = serial->port[i];
                if (port)
-                       kill_traffic(port);
+                       usb_serial_port_poison_urbs(port);
        }
 
 err_out:
@@ -1153,11 +1132,25 @@ err_out:
 }
 EXPORT_SYMBOL(usb_serial_suspend);
 
+static void usb_serial_unpoison_port_urbs(struct usb_serial *serial)
+{
+       struct usb_serial_port *port;
+       int i;
+
+       for (i = 0; i < serial->num_ports; ++i) {
+               port = serial->port[i];
+               if (port)
+                       usb_serial_port_unpoison_urbs(port);
+       }
+}
+
 int usb_serial_resume(struct usb_interface *intf)
 {
        struct usb_serial *serial = usb_get_intfdata(intf);
        int rv;
 
+       usb_serial_unpoison_port_urbs(serial);
+
        serial->suspending = 0;
        if (serial->type->resume)
                rv = serial->type->resume(serial);
@@ -1173,6 +1166,8 @@ static int usb_serial_reset_resume(struct usb_interface *intf)
        struct usb_serial *serial = usb_get_intfdata(intf);
        int rv;
 
+       usb_serial_unpoison_port_urbs(serial);
+
        serial->suspending = 0;
        if (serial->type->reset_resume)
                rv = serial->type->reset_resume(serial);
@@ -1309,12 +1304,12 @@ module_exit(usb_serial_exit);
        do {                                                            \
                if (!type->function) {                                  \
                        type->function = usb_serial_generic_##function; \
-                       pr_debug("Had to override the " #function       \
-                               " usb serial operation with the generic one.");\
-                       }                                               \
+                       pr_debug("%s: using generic " #function "\n",   \
+                                               type->driver.name);     \
+               }                                                       \
        } while (0)
 
-static void fixup_generic(struct usb_serial_driver *device)
+static void usb_serial_operations_init(struct usb_serial_driver *device)
 {
        set_to_generic_if_null(device, open);
        set_to_generic_if_null(device, write);
@@ -1323,8 +1318,6 @@ static void fixup_generic(struct usb_serial_driver *device)
        set_to_generic_if_null(device, chars_in_buffer);
        set_to_generic_if_null(device, read_bulk_callback);
        set_to_generic_if_null(device, write_bulk_callback);
-       set_to_generic_if_null(device, disconnect);
-       set_to_generic_if_null(device, release);
        set_to_generic_if_null(device, process_read_urb);
        set_to_generic_if_null(device, prepare_write_buffer);
 }
@@ -1336,8 +1329,6 @@ static int usb_serial_register(struct usb_serial_driver *driver)
        if (usb_disabled())
                return -ENODEV;
 
-       fixup_generic(driver);
-
        if (!driver->description)
                driver->description = driver->driver.name;
        if (!driver->usb_driver) {
@@ -1346,6 +1337,8 @@ static int usb_serial_register(struct usb_serial_driver *driver)
                return -EINVAL;
        }
 
+       usb_serial_operations_init(driver);
+
        /* Add this device to our list of devices */
        mutex_lock(&table_lock);
        list_add(&driver->driver_list, &usb_serial_driver_list);
@@ -1463,7 +1456,6 @@ void usb_serial_deregister_drivers(struct usb_serial_driver *const serial_driver
 }
 EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers);
 
-/* Module information */
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
index 571965aa1cc015257eaf4bde8316ce10045a82a0..ece326ef63a0b64c831e5f541b7171b95a9761f6 100644 (file)
@@ -421,20 +421,19 @@ void usb_wwan_close(struct usb_serial_port *port)
 
        portdata = usb_get_serial_port_data(port);
 
-       if (serial->dev) {
-               /* Stop reading/writing urbs */
-               spin_lock_irq(&intfdata->susp_lock);
-               portdata->opened = 0;
-               spin_unlock_irq(&intfdata->susp_lock);
+       /* Stop reading/writing urbs */
+       spin_lock_irq(&intfdata->susp_lock);
+       portdata->opened = 0;
+       spin_unlock_irq(&intfdata->susp_lock);
 
-               for (i = 0; i < N_IN_URB; i++)
-                       usb_kill_urb(portdata->in_urbs[i]);
-               for (i = 0; i < N_OUT_URB; i++)
-                       usb_kill_urb(portdata->out_urbs[i]);
-               /* balancing - important as an error cannot be handled*/
-               usb_autopm_get_interface_no_resume(serial->interface);
-               serial->interface->needs_remote_wakeup = 0;
-       }
+       for (i = 0; i < N_IN_URB; i++)
+               usb_kill_urb(portdata->in_urbs[i]);
+       for (i = 0; i < N_OUT_URB; i++)
+               usb_kill_urb(portdata->out_urbs[i]);
+
+       /* balancing - important as an error cannot be handled*/
+       usb_autopm_get_interface_no_resume(serial->interface);
+       serial->interface->needs_remote_wakeup = 0;
 }
 EXPORT_SYMBOL(usb_wwan_close);
 
index 1129aa73c23e93643ab273f578533ce85e04dc2c..7573ec8a084f3f55c1f2597c2f2b699e58790351 100644 (file)
@@ -257,24 +257,18 @@ static void visor_close(struct usb_serial_port *port)
 {
        unsigned char *transfer_buffer;
 
-       /* shutdown our urbs */
        usb_serial_generic_close(port);
        usb_kill_urb(port->interrupt_in_urb);
 
-       mutex_lock(&port->serial->disc_mutex);
-       if (!port->serial->disconnected) {
-               /* Try to send shutdown message, unless the device is gone */
-               transfer_buffer =  kmalloc(0x12, GFP_KERNEL);
-               if (transfer_buffer) {
-                       usb_control_msg(port->serial->dev,
+       transfer_buffer = kmalloc(0x12, GFP_KERNEL);
+       if (!transfer_buffer)
+               return;
+       usb_control_msg(port->serial->dev,
                                         usb_rcvctrlpipe(port->serial->dev, 0),
                                         VISOR_CLOSE_NOTIFICATION, 0xc2,
                                         0x0000, 0x0000,
                                         transfer_buffer, 0x12, 300);
-                       kfree(transfer_buffer);
-               }
-       }
-       mutex_unlock(&port->serial->disc_mutex);
+       kfree(transfer_buffer);
 }
 
 static void visor_read_int_callback(struct urb *urb)
diff --git a/drivers/usb/serial/wishbone-serial.c b/drivers/usb/serial/wishbone-serial.c
new file mode 100644 (file)
index 0000000..100573c
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * USB Wishbone-Serial adapter driver
+ *
+ * Copyright (C) 2013 Wesley W. Terpstra <w.terpstra@gsi.de>
+ * Copyright (C) 2013 GSI Helmholtz Centre for Heavy Ion Research GmbH
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/serial.h>
+#include <linux/uaccess.h>
+
+#define GSI_VENDOR_OPENCLOSE 0xB0
+
+static const struct usb_device_id id_table[] = {
+       { USB_DEVICE_AND_INTERFACE_INFO(0x1D50, 0x6062, 0xFF, 0xFF, 0xFF) },
+       { },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+/*
+ * Etherbone must be told that a new stream has begun before data arrives.
+ * This is necessary to restart the negotiation of Wishbone bus parameters.
+ * Similarly, when the stream ends, Etherbone must be told so that the cycle
+ * line can be driven low in the case that userspace failed to do so.
+ */
+static int usb_gsi_openclose(struct usb_serial_port *port, int value)
+{
+       struct usb_device *dev = port->serial->dev;
+
+       return usb_control_msg(
+               dev,
+               usb_sndctrlpipe(dev, 0), /* Send to EP0OUT */
+               GSI_VENDOR_OPENCLOSE,
+               USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
+               value, /* wValue = device is open(1) or closed(0) */
+               port->serial->interface->cur_altsetting->desc.bInterfaceNumber,
+               NULL, 0,  /* There is no data stage */
+               5000); /* Timeout till operation fails */
+}
+
+static int wishbone_serial_open(struct tty_struct *tty,
+                               struct usb_serial_port *port)
+{
+       int retval;
+
+       retval = usb_gsi_openclose(port, 1);
+       if (retval) {
+               dev_err(&port->serial->dev->dev,
+                      "Could not mark device as open (%d)\n",
+                      retval);
+               return retval;
+       }
+
+       retval = usb_serial_generic_open(tty, port);
+       if (retval)
+               usb_gsi_openclose(port, 0);
+
+       return retval;
+}
+
+static void wishbone_serial_close(struct usb_serial_port *port)
+{
+       usb_serial_generic_close(port);
+       usb_gsi_openclose(port, 0);
+}
+
+static struct usb_serial_driver wishbone_serial_device = {
+       .driver = {
+               .owner =        THIS_MODULE,
+               .name =         "wishbone_serial",
+       },
+       .id_table =             id_table,
+       .num_ports =            1,
+       .open =                 &wishbone_serial_open,
+       .close =                &wishbone_serial_close,
+};
+
+static struct usb_serial_driver * const serial_drivers[] = {
+       &wishbone_serial_device, NULL
+};
+
+module_usb_serial_driver(serial_drivers, id_table);
+
+MODULE_AUTHOR("Wesley W. Terpstra <w.terpstra@gsi.de>");
+MODULE_DESCRIPTION("USB Wishbone-Serial adapter");
+MODULE_LICENSE("GPL");
index eab04a6b5fbc91752f4caba31ac9c62dd9bfa1ad..8470e1b114f2bff5538d9f4134e4f6222ab47500 100644 (file)
@@ -4,11 +4,10 @@
 
 comment "NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may"
 comment "also be needed; see USB_STORAGE Help for more info"
-       depends on USB
 
 config USB_STORAGE
        tristate "USB Mass Storage support"
-       depends on USB && SCSI
+       depends on SCSI
        ---help---
          Say Y here if you want to connect USB mass storage devices to your
          computer's USB port. This is the driver you need for USB
@@ -188,7 +187,7 @@ config USB_STORAGE_CYPRESS_ATACB
 
 config USB_STORAGE_ENE_UB6250
        tristate "USB ENE card reader support"
-       depends on USB && SCSI
+       depends on SCSI
        depends on USB_STORAGE
        ---help---
          Say Y here if you wish to control a ENE SD/MS Card reader.
@@ -203,7 +202,7 @@ config USB_STORAGE_ENE_UB6250
 
 config USB_UAS
        tristate "USB Attached SCSI"
-       depends on USB && SCSI && BROKEN
+       depends on SCSI && BROKEN
        help
          The USB Attached SCSI protocol is supported by some USB
          storage devices.  It permits higher performance by supporting
index be5564cc8e0160c466c79558ec3a57f0994418f0..77a2ddfe64875ce83644db2a462ec17465e3ea2a 100644 (file)
@@ -326,8 +326,7 @@ static int alauda_get_media_status(struct us_data *us, unsigned char *data)
        rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe,
                command, 0xc0, 0, 1, data, 2);
 
-       US_DEBUGP("alauda_get_media_status: Media status %02X %02X\n",
-               data[0], data[1]);
+       usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]);
 
        return rc;
 }
@@ -402,7 +401,7 @@ static int alauda_init_media(struct us_data *us)
                        ready = 1;
        }
 
-       US_DEBUGP("alauda_init_media: We are ready for action!\n");
+       usb_stor_dbg(us, "We are ready for action!\n");
 
        if (alauda_ack_media(us) != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
@@ -413,15 +412,15 @@ static int alauda_init_media(struct us_data *us)
                return USB_STOR_TRANSPORT_ERROR;
 
        if (data[0] != 0x14) {
-               US_DEBUGP("alauda_init_media: Media not ready after ack\n");
+               usb_stor_dbg(us, "Media not ready after ack\n");
                return USB_STOR_TRANSPORT_ERROR;
        }
 
        if (alauda_get_media_signature(us, data) != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
-       US_DEBUGP("alauda_init_media: Media signature: %02X %02X %02X %02X\n",
-               data[0], data[1], data[2], data[3]);
+       usb_stor_dbg(us, "Media signature: %02X %02X %02X %02X\n",
+                    data[0], data[1], data[2], data[3]);
        media_info = alauda_card_find_id(data[1]);
        if (media_info == NULL) {
                printk(KERN_WARNING
@@ -432,8 +431,8 @@ static int alauda_init_media(struct us_data *us)
        }
 
        MEDIA_INFO(us).capacity = 1 << media_info->chipshift;
-       US_DEBUGP("Found media with capacity: %ldMB\n",
-               MEDIA_INFO(us).capacity >> 20);
+       usb_stor_dbg(us, "Found media with capacity: %ldMB\n",
+                    MEDIA_INFO(us).capacity >> 20);
 
        MEDIA_INFO(us).pageshift = media_info->pageshift;
        MEDIA_INFO(us).blockshift = media_info->blockshift;
@@ -472,7 +471,7 @@ static int alauda_check_media(struct us_data *us)
        /* Check for no media or door open */
        if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10)
                || ((status[1] & 0x01) == 0)) {
-               US_DEBUGP("alauda_check_media: No media, or door open\n");
+               usb_stor_dbg(us, "No media, or door open\n");
                alauda_free_maps(&MEDIA_INFO(us));
                info->sense_key = 0x02;
                info->sense_asc = 0x3A;
@@ -482,7 +481,7 @@ static int alauda_check_media(struct us_data *us)
 
        /* Check for media change */
        if (status[0] & 0x08) {
-               US_DEBUGP("alauda_check_media: Media change detected\n");
+               usb_stor_dbg(us, "Media change detected\n");
                alauda_free_maps(&MEDIA_INFO(us));
                alauda_init_media(us);
 
@@ -518,7 +517,7 @@ static int alauda_check_status2(struct us_data *us)
        if (rc != USB_STOR_XFER_GOOD)
                return rc;
 
-       US_DEBUGP("alauda_check_status2: %02X %02X %02X\n", data[0], data[1], data[2]);
+       usb_stor_dbg(us, "%02X %02X %02X\n", data[0], data[1], data[2]);
        if (data[0] & ALAUDA_STATUS_ERROR)
                return USB_STOR_XFER_ERROR;
 
@@ -584,7 +583,7 @@ static int alauda_read_map(struct us_data *us, unsigned int zone)
                goto error;
        }
 
-       US_DEBUGP("alauda_read_map: Mapping blocks for zone %d\n", zone);
+       usb_stor_dbg(us, "Mapping blocks for zone %d\n", zone);
 
        /* 1024 PBA's per zone */
        for (i = 0; i < zonesize; i++)
@@ -604,7 +603,7 @@ static int alauda_read_map(struct us_data *us, unsigned int zone)
                        if (data[j] != 0)
                                goto nonz;
                pba_to_lba[i] = UNUSABLE;
-               US_DEBUGP("alauda_read_map: PBA %d has no logical mapping\n", blocknum);
+               usb_stor_dbg(us, "PBA %d has no logical mapping\n", blocknum);
                continue;
 
        nonz:
@@ -617,19 +616,18 @@ static int alauda_read_map(struct us_data *us, unsigned int zone)
        nonff:
                /* normal PBAs start with six FFs */
                if (j < 6) {
-                       US_DEBUGP("alauda_read_map: PBA %d has no logical mapping: "
-                              "reserved area = %02X%02X%02X%02X "
-                              "data status %02X block status %02X\n",
-                              blocknum, data[0], data[1], data[2], data[3],
-                              data[4], data[5]);
+                       usb_stor_dbg(us, "PBA %d has no logical mapping: reserved area = %02X%02X%02X%02X data status %02X block status %02X\n",
+                                    blocknum,
+                                    data[0], data[1], data[2], data[3],
+                                    data[4], data[5]);
                        pba_to_lba[i] = UNUSABLE;
                        continue;
                }
 
                if ((data[6] >> 4) != 0x01) {
-                       US_DEBUGP("alauda_read_map: PBA %d has invalid address "
-                              "field %02X%02X/%02X%02X\n",
-                              blocknum, data[6], data[7], data[11], data[12]);
+                       usb_stor_dbg(us, "PBA %d has invalid address field %02X%02X/%02X%02X\n",
+                                    blocknum, data[6], data[7],
+                                    data[11], data[12]);
                        pba_to_lba[i] = UNUSABLE;
                        continue;
                }
@@ -711,7 +709,7 @@ static int alauda_erase_block(struct us_data *us, u16 pba)
        };
        unsigned char buf[2];
 
-       US_DEBUGP("alauda_erase_block: Erasing PBA %d\n", pba);
+       usb_stor_dbg(us, "Erasing PBA %d\n", pba);
 
        rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
                command, 9, NULL);
@@ -723,8 +721,7 @@ static int alauda_erase_block(struct us_data *us, u16 pba)
        if (rc != USB_STOR_XFER_GOOD)
                return rc;
 
-       US_DEBUGP("alauda_erase_block: Erase result: %02X %02X\n",
-               buf[0], buf[1]);
+       usb_stor_dbg(us, "Erase result: %02X %02X\n", buf[0], buf[1]);
        return rc;
 }
 
@@ -741,8 +738,7 @@ static int alauda_read_block_raw(struct us_data *us, u16 pba,
                PBA_ZONE(pba), 0, PBA_LO(pba) + page, pages, 0, MEDIA_PORT(us)
        };
 
-       US_DEBUGP("alauda_read_block: pba %d page %d count %d\n",
-               pba, page, pages);
+       usb_stor_dbg(us, "pba %d page %d count %d\n", pba, page, pages);
 
        rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
                command, 9, NULL);
@@ -793,7 +789,7 @@ static int alauda_write_block(struct us_data *us, u16 pba, unsigned char *data)
                PBA_ZONE(pba), 0, PBA_LO(pba), 32, 0, MEDIA_PORT(us)
        };
 
-       US_DEBUGP("alauda_write_block: pba %d\n", pba);
+       usb_stor_dbg(us, "pba %d\n", pba);
 
        rc = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
                command, 9, NULL);
@@ -866,14 +862,14 @@ static int alauda_write_lba(struct us_data *us, u16 lba,
                cptr = bptr + pagesize;
                nand_compute_ecc(bptr, ecc);
                if (!nand_compare_ecc(cptr+13, ecc)) {
-                       US_DEBUGP("Warning: bad ecc in page %d- of pba %d\n",
-                                 i, pba);
+                       usb_stor_dbg(us, "Warning: bad ecc in page %d- of pba %d\n",
+                                    i, pba);
                        nand_store_ecc(cptr+13, ecc);
                }
                nand_compute_ecc(bptr + (pagesize / 2), ecc);
                if (!nand_compare_ecc(cptr+8, ecc)) {
-                       US_DEBUGP("Warning: bad ecc in page %d+ of pba %d\n",
-                                 i, pba);
+                       usb_stor_dbg(us, "Warning: bad ecc in page %d+ of pba %d\n",
+                                    i, pba);
                        nand_store_ecc(cptr+8, ecc);
                }
                cptr[6] = cptr[11] = MSB_of(lbap);
@@ -900,8 +896,7 @@ static int alauda_write_lba(struct us_data *us, u16 lba,
        new_pba_offset = new_pba - (zone * zonesize);
        MEDIA_INFO(us).pba_to_lba[zone][new_pba_offset] = lba;
        MEDIA_INFO(us).lba_to_pba[zone][lba_offset] = new_pba;
-       US_DEBUGP("alauda_write_lba: Remapped LBA %d to PBA %d\n",
-               lba, new_pba);
+       usb_stor_dbg(us, "Remapped LBA %d to PBA %d\n", lba, new_pba);
 
        if (pba != UNDEF) {
                unsigned int pba_offset = pba - (zone * zonesize);
@@ -964,8 +959,8 @@ static int alauda_read_data(struct us_data *us, unsigned long address,
 
                /* Not overflowing capacity? */
                if (lba >= max_lba) {
-                       US_DEBUGP("Error: Requested lba %u exceeds "
-                                 "maximum %u\n", lba, max_lba);
+                       usb_stor_dbg(us, "Error: Requested lba %u exceeds maximum %u\n",
+                                    lba, max_lba);
                        result = USB_STOR_TRANSPORT_ERROR;
                        break;
                }
@@ -978,8 +973,8 @@ static int alauda_read_data(struct us_data *us, unsigned long address,
                pba = MEDIA_INFO(us).lba_to_pba[zone][lba_offset];
 
                if (pba == UNDEF) {     /* this lba was never written */
-                       US_DEBUGP("Read %d zero pages (LBA %d) page %d\n",
-                                 pages, lba, page);
+                       usb_stor_dbg(us, "Read %d zero pages (LBA %d) page %d\n",
+                                    pages, lba, page);
 
                        /* This is not really an error. It just means
                           that the block has never been written.
@@ -988,9 +983,8 @@ static int alauda_read_data(struct us_data *us, unsigned long address,
 
                        memset(buffer, 0, len);
                } else {
-                       US_DEBUGP("Read %d pages, from PBA %d"
-                                 " (LBA %d) page %d\n",
-                                 pages, pba, lba, page);
+                       usb_stor_dbg(us, "Read %d pages, from PBA %d (LBA %d) page %d\n",
+                                    pages, pba, lba, page);
 
                        result = alauda_read_block(us, pba, page, pages, buffer);
                        if (result != USB_STOR_TRANSPORT_GOOD)
@@ -1066,8 +1060,8 @@ static int alauda_write_data(struct us_data *us, unsigned long address,
 
                /* Not overflowing capacity? */
                if (lba >= max_lba) {
-                       US_DEBUGP("alauda_write_data: Requested lba %u exceeds "
-                                 "maximum %u\n", lba, max_lba);
+                       usb_stor_dbg(us, "Requested lba %u exceeds maximum %u\n",
+                                    lba, max_lba);
                        result = USB_STOR_TRANSPORT_ERROR;
                        break;
                }
@@ -1122,11 +1116,9 @@ static int init_alauda(struct us_data *us)
        nand_init_ecc();
 
        us->extra = kzalloc(sizeof(struct alauda_info), GFP_NOIO);
-       if (!us->extra) {
-               US_DEBUGP("init_alauda: Gah! Can't allocate storage for"
-                       "alauda info struct!\n");
+       if (!us->extra)
                return USB_STOR_TRANSPORT_ERROR;
-       }
+
        info = (struct alauda_info *) us->extra;
        us->extra_destructor = alauda_info_destructor;
 
@@ -1147,15 +1139,14 @@ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
        };
 
        if (srb->cmnd[0] == INQUIRY) {
-               US_DEBUGP("alauda_transport: INQUIRY. "
-                       "Returning bogus response.\n");
+               usb_stor_dbg(us, "INQUIRY - Returning bogus response\n");
                memcpy(ptr, inquiry_response, sizeof(inquiry_response));
                fill_inquiry_response(us, ptr, 36);
                return USB_STOR_TRANSPORT_GOOD;
        }
 
        if (srb->cmnd[0] == TEST_UNIT_READY) {
-               US_DEBUGP("alauda_transport: TEST_UNIT_READY.\n");
+               usb_stor_dbg(us, "TEST_UNIT_READY\n");
                return alauda_check_media(us);
        }
 
@@ -1193,8 +1184,7 @@ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
                page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
                pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
 
-               US_DEBUGP("alauda_transport: READ_10: page %d pagect %d\n",
-                         page, pages);
+               usb_stor_dbg(us, "READ_10: page %d pagect %d\n", page, pages);
 
                return alauda_read_data(us, page, pages);
        }
@@ -1211,14 +1201,13 @@ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
                page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
                pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
 
-               US_DEBUGP("alauda_transport: WRITE_10: page %d pagect %d\n",
-                         page, pages);
+               usb_stor_dbg(us, "WRITE_10: page %d pagect %d\n", page, pages);
 
                return alauda_write_data(us, page, pages);
        }
 
        if (srb->cmnd[0] == REQUEST_SENSE) {
-               US_DEBUGP("alauda_transport: REQUEST_SENSE.\n");
+               usb_stor_dbg(us, "REQUEST_SENSE\n");
 
                memset(ptr, 0, 18);
                ptr[0] = 0xF0;
@@ -1237,8 +1226,8 @@ static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us)
                return USB_STOR_TRANSPORT_GOOD;
        }
 
-       US_DEBUGP("alauda_transport: Gah! Unknown command: %d (0x%x)\n",
-               srb->cmnd[0], srb->cmnd[0]);
+       usb_stor_dbg(us, "Gah! Unknown command: %d (0x%x)\n",
+                    srb->cmnd[0], srb->cmnd[0]);
        info->sense_key = 0x05;
        info->sense_asc = 0x20;
        info->sense_ascq = 0x00;
index 070b5c0ebbf98d0d822723c4fe04b9ee984c5bf5..8514a2d82b72a2404420cd813f6aebff08e19f57 100644 (file)
@@ -159,7 +159,7 @@ static void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us)
        if (srb->result == SAM_STAT_CHECK_CONDITION &&
                        memcmp(srb->sense_buffer, usb_stor_sense_invalidCDB,
                                sizeof(usb_stor_sense_invalidCDB)) == 0) {
-               US_DEBUGP("cypress atacb not supported ???\n");
+               usb_stor_dbg(us, "cypress atacb not supported ???\n");
                goto end;
        }
 
@@ -248,14 +248,26 @@ static int cypress_probe(struct usb_interface *intf,
 {
        struct us_data *us;
        int result;
+       struct usb_device *device;
 
        result = usb_stor_probe1(&us, intf, id,
                        (id - cypress_usb_ids) + cypress_unusual_dev_list);
        if (result)
                return result;
 
-       us->protocol_name = "Transparent SCSI with Cypress ATACB";
-       us->proto_handler = cypress_atacb_passthrough;
+       /* Among CY7C68300 chips, the A revision does not support Cypress ATACB
+        * Filter out this revision from EEPROM default descriptor values
+        */
+       device = interface_to_usbdev(intf);
+       if (device->descriptor.iManufacturer != 0x38 ||
+           device->descriptor.iProduct != 0x4e ||
+           device->descriptor.iSerialNumber != 0x64) {
+               us->protocol_name = "Transparent SCSI with Cypress ATACB";
+               us->proto_handler = cypress_atacb_passthrough;
+       } else {
+               us->protocol_name = "Transparent SCSI";
+               us->proto_handler = usb_stor_transparent_scsi_command;
+       }
 
        result = usb_stor_probe2(us);
        return result;
index 494fee5af41d516c0a1e1e8a2b9b63e1faa6ecaf..7b17c2169812a64be584081ec7a9e960a8845786 100644 (file)
@@ -123,7 +123,7 @@ datafab_bulk_read(struct us_data *us, unsigned char *data, unsigned int len) {
        if (len == 0)
                return USB_STOR_XFER_GOOD;
 
-       US_DEBUGP("datafab_bulk_read:  len = %d\n", len);
+       usb_stor_dbg(us, "len = %d\n", len);
        return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
                        data, len, NULL);
 }
@@ -134,7 +134,7 @@ datafab_bulk_write(struct us_data *us, unsigned char *data, unsigned int len) {
        if (len == 0)
                return USB_STOR_XFER_GOOD;
 
-       US_DEBUGP("datafab_bulk_write:  len = %d\n", len);
+       usb_stor_dbg(us, "len = %d\n", len);
        return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
                        data, len, NULL);
 }
@@ -300,9 +300,8 @@ static int datafab_write_data(struct us_data *us,
                        goto leave;
 
                if (reply[0] != 0x50 && reply[1] != 0) {
-                       US_DEBUGP("datafab_write_data:  Gah! "
-                                 "write return code: %02x %02x\n",
-                                 reply[0], reply[1]);
+                       usb_stor_dbg(us, "Gah! write return code: %02x %02x\n",
+                                    reply[0], reply[1]);
                        result = USB_STOR_TRANSPORT_ERROR;
                        goto leave;
                }
@@ -342,7 +341,7 @@ static int datafab_determine_lun(struct us_data *us,
        if (!buf)
                return USB_STOR_TRANSPORT_ERROR;
 
-       US_DEBUGP("datafab_determine_lun:  locating...\n");
+       usb_stor_dbg(us, "locating...\n");
 
        // we'll try 3 times before giving up...
        //
@@ -474,16 +473,16 @@ static int datafab_handle_mode_sense(struct us_data *us,
 
        switch (pc) {
           case 0x0:
-               US_DEBUGP("datafab_handle_mode_sense:  Current values\n");
+                  usb_stor_dbg(us, "Current values\n");
                break;
           case 0x1:
-               US_DEBUGP("datafab_handle_mode_sense:  Changeable values\n");
+                  usb_stor_dbg(us, "Changeable values\n");
                break;
           case 0x2:
-               US_DEBUGP("datafab_handle_mode_sense:  Default values\n");
+                  usb_stor_dbg(us, "Default values\n");
                break;
           case 0x3:
-               US_DEBUGP("datafab_handle_mode_sense:  Saves values\n");
+                  usb_stor_dbg(us, "Saves values\n");
                break;
        }
 
@@ -566,11 +565,9 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
 
        if (!us->extra) {
                us->extra = kzalloc(sizeof(struct datafab_info), GFP_NOIO);
-               if (!us->extra) {
-                       US_DEBUGP("datafab_transport:  Gah! "
-                                 "Can't allocate storage for Datafab info struct!\n");
+               if (!us->extra)
                        return USB_STOR_TRANSPORT_ERROR;
-               }
+
                us->extra_destructor = datafab_info_destructor;
                ((struct datafab_info *)us->extra)->lun = -1;
        }
@@ -578,7 +575,7 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
        info = (struct datafab_info *) (us->extra);
 
        if (srb->cmnd[0] == INQUIRY) {
-               US_DEBUGP("datafab_transport:  INQUIRY.  Returning bogus response");
+               usb_stor_dbg(us, "INQUIRY - Returning bogus response\n");
                memcpy(ptr, inquiry_reply, sizeof(inquiry_reply));
                fill_inquiry_response(us, ptr, 36);
                return USB_STOR_TRANSPORT_GOOD;
@@ -590,8 +587,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
                if (rc != USB_STOR_TRANSPORT_GOOD)
                        return rc;
 
-               US_DEBUGP("datafab_transport:  READ_CAPACITY:  %ld sectors, %ld bytes per sector\n",
-                         info->sectors, info->ssize);
+               usb_stor_dbg(us, "READ_CAPACITY:  %ld sectors, %ld bytes per sector\n",
+                            info->sectors, info->ssize);
 
                // build the reply
                // we need the last sector, not the number of sectors
@@ -603,7 +600,7 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
        }
 
        if (srb->cmnd[0] == MODE_SELECT_10) {
-               US_DEBUGP("datafab_transport:  Gah! MODE_SELECT_10.\n");
+               usb_stor_dbg(us, "Gah! MODE_SELECT_10\n");
                return USB_STOR_TRANSPORT_ERROR;
        }
 
@@ -615,7 +612,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
 
                blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
 
-               US_DEBUGP("datafab_transport:  READ_10: read block 0x%04lx  count %ld\n", block, blocks);
+               usb_stor_dbg(us, "READ_10: read block 0x%04lx  count %ld\n",
+                            block, blocks);
                return datafab_read_data(us, info, block, blocks);
        }
 
@@ -628,7 +626,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
                blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
                         ((u32)(srb->cmnd[8]) <<  8) | ((u32)(srb->cmnd[9]));
 
-               US_DEBUGP("datafab_transport:  READ_12: read block 0x%04lx  count %ld\n", block, blocks);
+               usb_stor_dbg(us, "READ_12: read block 0x%04lx  count %ld\n",
+                            block, blocks);
                return datafab_read_data(us, info, block, blocks);
        }
 
@@ -638,7 +637,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
 
                blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
 
-               US_DEBUGP("datafab_transport:  WRITE_10: write block 0x%04lx  count %ld\n", block, blocks);
+               usb_stor_dbg(us, "WRITE_10: write block 0x%04lx count %ld\n",
+                            block, blocks);
                return datafab_write_data(us, info, block, blocks);
        }
 
@@ -651,17 +651,18 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
                blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
                         ((u32)(srb->cmnd[8]) <<  8) | ((u32)(srb->cmnd[9]));
 
-               US_DEBUGP("datafab_transport:  WRITE_12: write block 0x%04lx  count %ld\n", block, blocks);
+               usb_stor_dbg(us, "WRITE_12: write block 0x%04lx count %ld\n",
+                            block, blocks);
                return datafab_write_data(us, info, block, blocks);
        }
 
        if (srb->cmnd[0] == TEST_UNIT_READY) {
-               US_DEBUGP("datafab_transport:  TEST_UNIT_READY.\n");
+               usb_stor_dbg(us, "TEST_UNIT_READY\n");
                return datafab_id_device(us, info);
        }
 
        if (srb->cmnd[0] == REQUEST_SENSE) {
-               US_DEBUGP("datafab_transport:  REQUEST_SENSE.  Returning faked response\n");
+               usb_stor_dbg(us, "REQUEST_SENSE - Returning faked response\n");
 
                // this response is pretty bogus right now.  eventually if necessary
                // we can set the correct sense data.  so far though it hasn't been
@@ -679,12 +680,12 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
        }
 
        if (srb->cmnd[0] == MODE_SENSE) {
-               US_DEBUGP("datafab_transport:  MODE_SENSE_6 detected\n");
+               usb_stor_dbg(us, "MODE_SENSE_6 detected\n");
                return datafab_handle_mode_sense(us, srb, 1);
        }
 
        if (srb->cmnd[0] == MODE_SENSE_10) {
-               US_DEBUGP("datafab_transport:  MODE_SENSE_10 detected\n");
+               usb_stor_dbg(us, "MODE_SENSE_10 detected\n");
                return datafab_handle_mode_sense(us, srb, 0);
        }
 
@@ -698,7 +699,7 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
        if (srb->cmnd[0] == START_STOP) {
                /* this is used by sd.c'check_scsidisk_media_change to detect
                   media change */
-               US_DEBUGP("datafab_transport:  START_STOP.\n");
+               usb_stor_dbg(us, "START_STOP\n");
                /* the first datafab_id_device after a media change returns
                   an error (determined experimentally) */
                rc = datafab_id_device(us, info);
@@ -712,8 +713,8 @@ static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us)
                return rc;
        }
 
-       US_DEBUGP("datafab_transport:  Gah! Unknown command: %d (0x%x)\n",
-                 srb->cmnd[0], srb->cmnd[0]);
+       usb_stor_dbg(us, "Gah! Unknown command: %d (0x%x)\n",
+                    srb->cmnd[0], srb->cmnd[0]);
        info->sense_key = 0x05;
        info->sense_asc = 0x20;
        info->sense_ascq = 0x00;
index a2b5526c9fa09e742e6d34969326af6b3712214f..e08f64780e30fb3af660b7066cc14b1f6181417a 100644 (file)
  * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/device.h>
 #include <linux/cdrom.h>
+#include <linux/export.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_dbg.h>
 
+#include "usb.h"
 #include "debug.h"
 #include "scsi.h"
 
 
-void usb_stor_show_command(struct scsi_cmnd *srb)
+void usb_stor_show_command(const struct us_data *us, struct scsi_cmnd *srb)
 {
        char *what = NULL;
        int i;
@@ -149,18 +152,18 @@ void usb_stor_show_command(struct scsi_cmnd *srb)
        case WRITE_LONG_2: what = "WRITE_LONG_2"; break;
        default: what = "(unknown command)"; break;
        }
-       US_DEBUGP("Command %s (%d bytes)\n", what, srb->cmd_len);
-       US_DEBUGP("");
+       usb_stor_dbg(us, "Command %s (%d bytes)\n", what, srb->cmd_len);
+       usb_stor_dbg(us, "bytes: ");
        for (i = 0; i < srb->cmd_len && i < 16; i++)
                US_DEBUGPX(" %02x", srb->cmnd[i]);
        US_DEBUGPX("\n");
 }
 
-void usb_stor_show_sense(
-               unsigned char key,
-               unsigned char asc,
-               unsigned char ascq) {
-
+void usb_stor_show_sense(const struct us_data *us,
+                        unsigned char key,
+                        unsigned char asc,
+                        unsigned char ascq)
+{
        const char *what, *keystr;
 
        keystr = scsi_sense_key_string(key);
@@ -171,7 +174,22 @@ void usb_stor_show_sense(
        if (what == NULL)
                what = "(unknown ASC/ASCQ)";
 
-       US_DEBUGP("%s: ", keystr);
+       usb_stor_dbg(us, "%s: ", keystr);
        US_DEBUGPX(what, ascq);
        US_DEBUGPX("\n");
 }
+
+int usb_stor_dbg(const struct us_data *us, const char *fmt, ...)
+{
+       va_list args;
+       int r;
+
+       va_start(args, fmt);
+
+       r = dev_vprintk_emit(7, &us->pusb_dev->dev, fmt, args);
+
+       va_end(args);
+
+       return r;
+}
+EXPORT_SYMBOL_GPL(usb_stor_dbg);
index dbb985d52423f33d4a997ee2835ab8e93a9617a4..b1273f03e223f1cc265565276663524527828be3 100644 (file)
 #define USB_STORAGE "usb-storage: "
 
 #ifdef CONFIG_USB_STORAGE_DEBUG
-void usb_stor_show_command(struct scsi_cmnd *srb);
-void usb_stor_show_sense( unsigned char key,
-               unsigned char asc, unsigned char ascq );
-#define US_DEBUGP(x...) printk( KERN_DEBUG USB_STORAGE x )
-#define US_DEBUGPX(x...) printk( x )
-#define US_DEBUG(x) x 
+void usb_stor_show_command(const struct us_data *us, struct scsi_cmnd *srb);
+void usb_stor_show_sense(const struct us_data *us, unsigned char key,
+                        unsigned char asc, unsigned char ascq);
+__printf(2, 3) int usb_stor_dbg(const struct us_data *us,
+                               const char *fmt, ...);
+
+#define US_DEBUGPX(fmt, ...)   printk(fmt, ##__VA_ARGS__)
+#define US_DEBUG(x)            x
 #else
-#define US_DEBUGP(x...)
-#define US_DEBUGPX(x...)
+__printf(2, 3)
+static inline int _usb_stor_dbg(const struct us_data *us,
+                               const char *fmt, ...) {return 1;}
+#define usb_stor_dbg(us, fmt, ...)                             \
+       do { if (0) _usb_stor_dbg(us, fmt, ##__VA_ARGS__); } while (0)
+#define US_DEBUGPX(fmt, ...)                                   \
+       do { if (0) printk(fmt, ##__VA_ARGS__); } while (0)
 #define US_DEBUG(x)
 #endif
 
index 118b134a1dad38c970f3a459f9b8868c4002ee43..1bfc9a6cab5f7fad815b8f92feb5b50e7adceba8 100644 (file)
@@ -504,12 +504,12 @@ static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg)
        unsigned int cswlen = 0, partial = 0;
        unsigned int transfer_length = bcb->DataTransferLength;
 
-       /* US_DEBUGP("transport --- ene_send_scsi_cmd\n"); */
+       /* usb_stor_dbg(us, "transport --- ene_send_scsi_cmd\n"); */
        /* send cmd to out endpoint */
        result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
                                            bcb, US_BULK_CB_WRAP_LEN, NULL);
        if (result != USB_STOR_XFER_GOOD) {
-               US_DEBUGP("send cmd to out endpoint fail ---\n");
+               usb_stor_dbg(us, "send cmd to out endpoint fail ---\n");
                return USB_STOR_TRANSPORT_ERROR;
        }
 
@@ -529,7 +529,7 @@ static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg)
                                                transfer_length, 0, &partial);
                }
                if (result != USB_STOR_XFER_GOOD) {
-                       US_DEBUGP("data transfer fail ---\n");
+                       usb_stor_dbg(us, "data transfer fail ---\n");
                        return USB_STOR_TRANSPORT_ERROR;
                }
        }
@@ -539,14 +539,14 @@ static int ene_send_scsi_cmd(struct us_data *us, u8 fDir, void *buf, int use_sg)
                                            US_BULK_CS_WRAP_LEN, &cswlen);
 
        if (result == USB_STOR_XFER_SHORT && cswlen == 0) {
-               US_DEBUGP("Received 0-length CSW; retrying...\n");
+               usb_stor_dbg(us, "Received 0-length CSW; retrying...\n");
                result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
                                            bcs, US_BULK_CS_WRAP_LEN, &cswlen);
        }
 
        if (result == USB_STOR_XFER_STALLED) {
                /* get the status again */
-               US_DEBUGP("Attempting to get CSW (2nd try)...\n");
+               usb_stor_dbg(us, "Attempting to get CSW (2nd try)...\n");
                result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
                                                bcs, US_BULK_CS_WRAP_LEN, NULL);
        }
@@ -626,7 +626,7 @@ static int sd_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)
        struct scatterlist *sg = NULL;
        struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
 
-       US_DEBUGP("sd_scsi_read_capacity\n");
+       usb_stor_dbg(us, "sd_scsi_read_capacity\n");
        if (info->SD_Status.HiCapacity) {
                bl_len = 0x200;
                if (info->SD_Status.IsMMC)
@@ -639,8 +639,8 @@ static int sd_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)
                                * (1 << (info->SD_C_SIZE_MULT + 2)) - 1;
        }
        info->bl_num = bl_num;
-       US_DEBUGP("bl_len = %x\n", bl_len);
-       US_DEBUGP("bl_num = %x\n", bl_num);
+       usb_stor_dbg(us, "bl_len = %x\n", bl_len);
+       usb_stor_dbg(us, "bl_num = %x\n", bl_num);
 
        /*srb->request_bufflen = 8; */
        buf[0] = (bl_num >> 24) & 0xff;
@@ -675,7 +675,7 @@ static int sd_scsi_read(struct us_data *us, struct scsi_cmnd *srb)
 
        result = ene_load_bincode(us, SD_RW_PATTERN);
        if (result != USB_STOR_XFER_GOOD) {
-               US_DEBUGP("Load SD RW pattern Fail !!\n");
+               usb_stor_dbg(us, "Load SD RW pattern Fail !!\n");
                return USB_STOR_TRANSPORT_ERROR;
        }
 
@@ -715,7 +715,7 @@ static int sd_scsi_write(struct us_data *us, struct scsi_cmnd *srb)
 
        result = ene_load_bincode(us, SD_RW_PATTERN);
        if (result != USB_STOR_XFER_GOOD) {
-               US_DEBUGP("Load SD RW pattern Fail !!\n");
+               usb_stor_dbg(us, "Load SD RW pattern Fail !!\n");
                return USB_STOR_TRANSPORT_ERROR;
        }
 
@@ -1493,7 +1493,7 @@ static int ms_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)
        struct scatterlist *sg = NULL;
        struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
 
-       US_DEBUGP("ms_scsi_read_capacity\n");
+       usb_stor_dbg(us, "ms_scsi_read_capacity\n");
        bl_len = 0x200;
        if (info->MS_Status.IsMSPro)
                bl_num = info->MSP_TotalBlock - 1;
@@ -1501,8 +1501,8 @@ static int ms_scsi_read_capacity(struct us_data *us, struct scsi_cmnd *srb)
                bl_num = info->MS_Lib.NumberOfLogBlock * info->MS_Lib.blockSize * 2 - 1;
 
        info->bl_num = bl_num;
-       US_DEBUGP("bl_len = %x\n", bl_len);
-       US_DEBUGP("bl_num = %x\n", bl_num);
+       usb_stor_dbg(us, "bl_len = %x\n", bl_len);
+       usb_stor_dbg(us, "bl_num = %x\n", bl_num);
 
        /*srb->request_bufflen = 8; */
        buf[0] = (bl_num >> 24) & 0xff;
@@ -1654,7 +1654,7 @@ static int ms_scsi_read(struct us_data *us, struct scsi_cmnd *srb)
        if (info->MS_Status.IsMSPro) {
                result = ene_load_bincode(us, MSP_RW_PATTERN);
                if (result != USB_STOR_XFER_GOOD) {
-                       US_DEBUGP("Load MPS RW pattern Fail !!\n");
+                       usb_stor_dbg(us, "Load MPS RW pattern Fail !!\n");
                        return USB_STOR_TRANSPORT_ERROR;
                }
 
@@ -1854,7 +1854,7 @@ static int ene_get_card_status(struct us_data *us, u8 *buf)
        u32 reg4b;
        struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
 
-       /*US_DEBUGP("transport --- ENE_ReadSDReg\n");*/
+       /*usb_stor_dbg(us, "transport --- ENE_ReadSDReg\n");*/
        reg4b = *(u32 *)&buf[0x18];
        info->SD_READ_BL_LEN = (u8)((reg4b >> 8) & 0x0f);
 
@@ -1894,45 +1894,44 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag)
        switch (flag) {
        /* For SD */
        case SD_INIT1_PATTERN:
-               US_DEBUGP("SD_INIT1_PATTERN\n");
+               usb_stor_dbg(us, "SD_INIT1_PATTERN\n");
                fw_name = SD_INIT1_FIRMWARE;
                break;
        case SD_INIT2_PATTERN:
-               US_DEBUGP("SD_INIT2_PATTERN\n");
+               usb_stor_dbg(us, "SD_INIT2_PATTERN\n");
                fw_name = SD_INIT2_FIRMWARE;
                break;
        case SD_RW_PATTERN:
-               US_DEBUGP("SD_RW_PATTERN\n");
+               usb_stor_dbg(us, "SD_RW_PATTERN\n");
                fw_name = SD_RW_FIRMWARE;
                break;
        /* For MS */
        case MS_INIT_PATTERN:
-               US_DEBUGP("MS_INIT_PATTERN\n");
+               usb_stor_dbg(us, "MS_INIT_PATTERN\n");
                fw_name = MS_INIT_FIRMWARE;
                break;
        case MSP_RW_PATTERN:
-               US_DEBUGP("MSP_RW_PATTERN\n");
+               usb_stor_dbg(us, "MSP_RW_PATTERN\n");
                fw_name = MSP_RW_FIRMWARE;
                break;
        case MS_RW_PATTERN:
-               US_DEBUGP("MS_RW_PATTERN\n");
+               usb_stor_dbg(us, "MS_RW_PATTERN\n");
                fw_name = MS_RW_FIRMWARE;
                break;
        default:
-               US_DEBUGP("----------- Unknown PATTERN ----------\n");
+               usb_stor_dbg(us, "----------- Unknown PATTERN ----------\n");
                goto nofw;
        }
 
        err = request_firmware(&sd_fw, fw_name, &us->pusb_dev->dev);
        if (err) {
-               US_DEBUGP("load firmware %s failed\n", fw_name);
+               usb_stor_dbg(us, "load firmware %s failed\n", fw_name);
                goto nofw;
        }
        buf = kmalloc(sd_fw->size, GFP_KERNEL);
-       if (buf == NULL) {
-               US_DEBUGP("Malloc memory for fireware failed!\n");
+       if (buf == NULL)
                goto nofw;
-       }
+
        memcpy(buf, sd_fw->data, sd_fw->size);
        memset(bcb, 0, sizeof(struct bulk_cb_wrap));
        bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
@@ -2116,9 +2115,9 @@ static int ene_ms_init(struct us_data *us)
                } else {
                        ms_card_init(us); /* Card is MS (to ms.c)*/
                }
-               US_DEBUGP("MS Init Code OK !!\n");
+               usb_stor_dbg(us, "MS Init Code OK !!\n");
        } else {
-               US_DEBUGP("MS Card Not Ready --- %x\n", buf[0]);
+               usb_stor_dbg(us, "MS Card Not Ready --- %x\n", buf[0]);
                return USB_STOR_TRANSPORT_ERROR;
        }
 
@@ -2132,11 +2131,11 @@ static int ene_sd_init(struct us_data *us)
        struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
        struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
 
-       US_DEBUGP("transport --- ENE_SDInit\n");
+       usb_stor_dbg(us, "transport --- ENE_SDInit\n");
        /* SD Init Part-1 */
        result = ene_load_bincode(us, SD_INIT1_PATTERN);
        if (result != USB_STOR_XFER_GOOD) {
-               US_DEBUGP("Load SD Init Code Part-1 Fail !!\n");
+               usb_stor_dbg(us, "Load SD Init Code Part-1 Fail !!\n");
                return USB_STOR_TRANSPORT_ERROR;
        }
 
@@ -2147,14 +2146,14 @@ static int ene_sd_init(struct us_data *us)
 
        result = ene_send_scsi_cmd(us, FDIR_READ, NULL, 0);
        if (result != USB_STOR_XFER_GOOD) {
-               US_DEBUGP("Execution SD Init Code Fail !!\n");
+               usb_stor_dbg(us, "Execution SD Init Code Fail !!\n");
                return USB_STOR_TRANSPORT_ERROR;
        }
 
        /* SD Init Part-2 */
        result = ene_load_bincode(us, SD_INIT2_PATTERN);
        if (result != USB_STOR_XFER_GOOD) {
-               US_DEBUGP("Load SD Init Code Part-2 Fail !!\n");
+               usb_stor_dbg(us, "Load SD Init Code Part-2 Fail !!\n");
                return USB_STOR_TRANSPORT_ERROR;
        }
 
@@ -2166,21 +2165,23 @@ static int ene_sd_init(struct us_data *us)
 
        result = ene_send_scsi_cmd(us, FDIR_READ, &buf, 0);
        if (result != USB_STOR_XFER_GOOD) {
-               US_DEBUGP("Execution SD Init Code Fail !!\n");
+               usb_stor_dbg(us, "Execution SD Init Code Fail !!\n");
                return USB_STOR_TRANSPORT_ERROR;
        }
 
        info->SD_Status =  *(struct SD_STATUS *)&buf[0];
        if (info->SD_Status.Insert && info->SD_Status.Ready) {
+               struct SD_STATUS *s = &info->SD_Status;
+
                ene_get_card_status(us, (unsigned char *)&buf);
-               US_DEBUGP("Insert     = %x\n", info->SD_Status.Insert);
-               US_DEBUGP("Ready      = %x\n", info->SD_Status.Ready);
-               US_DEBUGP("IsMMC      = %x\n", info->SD_Status.IsMMC);
-               US_DEBUGP("HiCapacity = %x\n", info->SD_Status.HiCapacity);
-               US_DEBUGP("HiSpeed    = %x\n", info->SD_Status.HiSpeed);
-               US_DEBUGP("WtP        = %x\n", info->SD_Status.WtP);
+               usb_stor_dbg(us, "Insert     = %x\n", s->Insert);
+               usb_stor_dbg(us, "Ready      = %x\n", s->Ready);
+               usb_stor_dbg(us, "IsMMC      = %x\n", s->IsMMC);
+               usb_stor_dbg(us, "HiCapacity = %x\n", s->HiCapacity);
+               usb_stor_dbg(us, "HiSpeed    = %x\n", s->HiSpeed);
+               usb_stor_dbg(us, "WtP        = %x\n", s->WtP);
        } else {
-               US_DEBUGP("SD Card Not Ready --- %x\n", buf[0]);
+               usb_stor_dbg(us, "SD Card Not Ready --- %x\n", buf[0]);
                return USB_STOR_TRANSPORT_ERROR;
        }
        return USB_STOR_TRANSPORT_GOOD;
@@ -2293,7 +2294,7 @@ static int ene_transport(struct scsi_cmnd *srb, struct us_data *us)
        int result = 0;
        struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
 
-       /*US_DEBUG(usb_stor_show_command(srb)); */
+       /*US_DEBUG(usb_stor_show_command(us, srb)); */
        scsi_set_resid(srb, 0);
        if (unlikely(!(info->SD_Status.Ready || info->MS_Status.Ready))) {
                result = ene_init(us);
@@ -2362,7 +2363,6 @@ static int ene_ub6250_resume(struct usb_interface *iface)
 
        mutex_lock(&us->dev_mutex);
 
-       US_DEBUGP("%s\n", __func__);
        if (us->suspend_resume_hook)
                (us->suspend_resume_hook)(us, US_RESUME);
 
@@ -2382,7 +2382,7 @@ static int ene_ub6250_reset_resume(struct usb_interface *iface)
        u8 tmp = 0;
        struct us_data *us = usb_get_intfdata(iface);
        struct ene_ub6250_info *info = (struct ene_ub6250_info *)(us->extra);
-       US_DEBUGP("%s\n", __func__);
+
        /* Report the reset to the SCSI core */
        usb_stor_reset_resume(iface);
 
index e6df087dca9d39e0910962df2eb40b2573f94115..ef16068b708704dad1cd2abda3efee0a7754304b 100644 (file)
@@ -40,7 +40,7 @@ MODULE_AUTHOR("David Brown <usb-storage@davidb.org>");
 MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_USB_STORAGE_DEBUG
-static void pdump (void *, int);
+static void pdump(struct us_data *us, void *ibuffer, int length);
 #endif
 
 /* Bits of HD_STATUS */
@@ -161,20 +161,20 @@ freecom_readdata (struct scsi_cmnd *srb, struct us_data *us,
        fxfr->Count = cpu_to_le32 (count);
        memset (fxfr->Pad, 0, sizeof (fxfr->Pad));
 
-       US_DEBUGP("Read data Freecom! (c=%d)\n", count);
+       usb_stor_dbg(us, "Read data Freecom! (c=%d)\n", count);
 
        /* Issue the transfer command. */
        result = usb_stor_bulk_transfer_buf (us, opipe, fxfr,
                        FCM_PACKET_LENGTH, NULL);
        if (result != USB_STOR_XFER_GOOD) {
-               US_DEBUGP ("Freecom readdata transport error\n");
+               usb_stor_dbg(us, "Freecom readdata transport error\n");
                return USB_STOR_TRANSPORT_ERROR;
        }
 
        /* Now transfer all of our blocks. */
-       US_DEBUGP("Start of read\n");
+       usb_stor_dbg(us, "Start of read\n");
        result = usb_stor_bulk_srb(us, ipipe, srb);
-       US_DEBUGP("freecom_readdata done!\n");
+       usb_stor_dbg(us, "freecom_readdata done!\n");
 
        if (result > USB_STOR_XFER_SHORT)
                return USB_STOR_TRANSPORT_ERROR;
@@ -194,21 +194,21 @@ freecom_writedata (struct scsi_cmnd *srb, struct us_data *us,
        fxfr->Count = cpu_to_le32 (count);
        memset (fxfr->Pad, 0, sizeof (fxfr->Pad));
 
-       US_DEBUGP("Write data Freecom! (c=%d)\n", count);
+       usb_stor_dbg(us, "Write data Freecom! (c=%d)\n", count);
 
        /* Issue the transfer command. */
        result = usb_stor_bulk_transfer_buf (us, opipe, fxfr,
                        FCM_PACKET_LENGTH, NULL);
        if (result != USB_STOR_XFER_GOOD) {
-               US_DEBUGP ("Freecom writedata transport error\n");
+               usb_stor_dbg(us, "Freecom writedata transport error\n");
                return USB_STOR_TRANSPORT_ERROR;
        }
 
        /* Now transfer all of our blocks. */
-       US_DEBUGP("Start of write\n");
+       usb_stor_dbg(us, "Start of write\n");
        result = usb_stor_bulk_srb(us, opipe, srb);
 
-       US_DEBUGP("freecom_writedata done!\n");
+       usb_stor_dbg(us, "freecom_writedata done!\n");
        if (result > USB_STOR_XFER_SHORT)
                return USB_STOR_TRANSPORT_ERROR;
        return USB_STOR_TRANSPORT_GOOD;
@@ -230,7 +230,7 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
        fcb = (struct freecom_cb_wrap *) us->iobuf;
        fst = (struct freecom_status *) us->iobuf;
 
-       US_DEBUGP("Freecom TRANSPORT STARTED\n");
+       usb_stor_dbg(us, "Freecom TRANSPORT STARTED\n");
 
        /* Get handles for both transports. */
        opipe = us->send_bulk_pipe;
@@ -242,7 +242,7 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
        memcpy (fcb->Atapi, srb->cmnd, 12);
        memset (fcb->Filler, 0, sizeof (fcb->Filler));
 
-       US_DEBUG(pdump (srb->cmnd, 12));
+       US_DEBUG(pdump(us, srb->cmnd, 12));
 
        /* Send it out. */
        result = usb_stor_bulk_transfer_buf (us, opipe, fcb,
@@ -252,7 +252,7 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
         * USB land.  It returns the status in its own registers, which
         * come back in the bulk pipe. */
        if (result != USB_STOR_XFER_GOOD) {
-               US_DEBUGP ("freecom transport error\n");
+               usb_stor_dbg(us, "freecom transport error\n");
                return USB_STOR_TRANSPORT_ERROR;
        }
 
@@ -260,11 +260,11 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
         * doesn't hurt us to always do it now. */
        result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
                        FCM_STATUS_PACKET_LENGTH, &partial);
-       US_DEBUGP("foo Status result %d %u\n", result, partial);
+       usb_stor_dbg(us, "foo Status result %d %u\n", result, partial);
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
-       US_DEBUG(pdump ((void *) fst, partial));
+       US_DEBUG(pdump(us, (void *)fst, partial));
 
        /* The firmware will time-out commands after 20 seconds. Some commands
         * can legitimately take longer than this, so we use a different
@@ -275,8 +275,8 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
         * may not work, but that is a condition that should never happen.
         */
        while (fst->Status & FCM_STATUS_BUSY) {
-               US_DEBUGP("20 second USB/ATAPI bridge TIMEOUT occurred!\n");
-               US_DEBUGP("fst->Status is %x\n", fst->Status);
+               usb_stor_dbg(us, "20 second USB/ATAPI bridge TIMEOUT occurred!\n");
+               usb_stor_dbg(us, "fst->Status is %x\n", fst->Status);
 
                /* Get the status again */
                fcb->Type = FCM_PACKET_STATUS;
@@ -293,7 +293,7 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
                 * registers, which come back in the bulk pipe.
                 */
                if (result != USB_STOR_XFER_GOOD) {
-                       US_DEBUGP ("freecom transport error\n");
+                       usb_stor_dbg(us, "freecom transport error\n");
                        return USB_STOR_TRANSPORT_ERROR;
                }
 
@@ -301,26 +301,26 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
                result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
                                FCM_STATUS_PACKET_LENGTH, &partial);
 
-               US_DEBUGP("bar Status result %d %u\n", result, partial);
+               usb_stor_dbg(us, "bar Status result %d %u\n", result, partial);
                if (result != USB_STOR_XFER_GOOD)
                        return USB_STOR_TRANSPORT_ERROR;
 
-               US_DEBUG(pdump ((void *) fst, partial));
+               US_DEBUG(pdump(us, (void *)fst, partial));
        }
 
        if (partial != 4)
                return USB_STOR_TRANSPORT_ERROR;
        if ((fst->Status & 1) != 0) {
-               US_DEBUGP("operation failed\n");
+               usb_stor_dbg(us, "operation failed\n");
                return USB_STOR_TRANSPORT_FAILED;
        }
 
        /* The device might not have as much data available as we
         * requested.  If you ask for more than the device has, this reads
         * and such will hang. */
-       US_DEBUGP("Device indicates that it has %d bytes available\n",
-                       le16_to_cpu (fst->Count));
-       US_DEBUGP("SCSI requested %d\n", scsi_bufflen(srb));
+       usb_stor_dbg(us, "Device indicates that it has %d bytes available\n",
+                    le16_to_cpu(fst->Count));
+       usb_stor_dbg(us, "SCSI requested %d\n", scsi_bufflen(srb));
 
        /* Find the length we desire to read. */
        switch (srb->cmnd[0]) {
@@ -337,7 +337,8 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
        /* verify that this amount is legal */
        if (length > scsi_bufflen(srb)) {
                length = scsi_bufflen(srb);
-               US_DEBUGP("Truncating request to match buffer length: %d\n", length);
+               usb_stor_dbg(us, "Truncating request to match buffer length: %d\n",
+                            length);
        }
 
        /* What we do now depends on what direction the data is supposed to
@@ -351,29 +352,29 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
                /* Make sure that the status indicates that the device
                 * wants data as well. */
                if ((fst->Status & DRQ_STAT) == 0 || (fst->Reason & 3) != 2) {
-                       US_DEBUGP("SCSI wants data, drive doesn't have any\n");
+                       usb_stor_dbg(us, "SCSI wants data, drive doesn't have any\n");
                        return USB_STOR_TRANSPORT_FAILED;
                }
                result = freecom_readdata (srb, us, ipipe, opipe, length);
                if (result != USB_STOR_TRANSPORT_GOOD)
                        return result;
 
-               US_DEBUGP("FCM: Waiting for status\n");
+               usb_stor_dbg(us, "Waiting for status\n");
                result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
                                FCM_PACKET_LENGTH, &partial);
-               US_DEBUG(pdump ((void *) fst, partial));
+               US_DEBUG(pdump(us, (void *)fst, partial));
 
                if (partial != 4 || result > USB_STOR_XFER_SHORT)
                        return USB_STOR_TRANSPORT_ERROR;
                if ((fst->Status & ERR_STAT) != 0) {
-                       US_DEBUGP("operation failed\n");
+                       usb_stor_dbg(us, "operation failed\n");
                        return USB_STOR_TRANSPORT_FAILED;
                }
                if ((fst->Reason & 3) != 3) {
-                       US_DEBUGP("Drive seems still hungry\n");
+                       usb_stor_dbg(us, "Drive seems still hungry\n");
                        return USB_STOR_TRANSPORT_FAILED;
                }
-               US_DEBUGP("Transfer happy\n");
+               usb_stor_dbg(us, "Transfer happy\n");
                break;
 
        case DMA_TO_DEVICE:
@@ -387,22 +388,22 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
                if (result != USB_STOR_TRANSPORT_GOOD)
                        return result;
 
-               US_DEBUGP("FCM: Waiting for status\n");
+               usb_stor_dbg(us, "Waiting for status\n");
                result = usb_stor_bulk_transfer_buf (us, ipipe, fst,
                                FCM_PACKET_LENGTH, &partial);
 
                if (partial != 4 || result > USB_STOR_XFER_SHORT)
                        return USB_STOR_TRANSPORT_ERROR;
                if ((fst->Status & ERR_STAT) != 0) {
-                       US_DEBUGP("operation failed\n");
+                       usb_stor_dbg(us, "operation failed\n");
                        return USB_STOR_TRANSPORT_FAILED;
                }
                if ((fst->Reason & 3) != 3) {
-                       US_DEBUGP("Drive seems still hungry\n");
+                       usb_stor_dbg(us, "Drive seems still hungry\n");
                        return USB_STOR_TRANSPORT_FAILED;
                }
 
-               US_DEBUGP("Transfer happy\n");
+               usb_stor_dbg(us, "Transfer happy\n");
                break;
 
 
@@ -412,8 +413,8 @@ static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us)
 
        default:
                /* should never hit here -- filtered in usb.c */
-               US_DEBUGP ("freecom unimplemented direction: %d\n",
-                               us->srb->sc_data_direction);
+               usb_stor_dbg(us, "freecom unimplemented direction: %d\n",
+                            us->srb->sc_data_direction);
                /* Return fail, SCSI seems to handle this better. */
                return USB_STOR_TRANSPORT_FAILED;
                break;
@@ -434,7 +435,7 @@ static int init_freecom(struct us_data *us)
        result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
                        0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ);
        buffer[32] = '\0';
-       US_DEBUGP("String returned from FC init is: %s\n", buffer);
+       usb_stor_dbg(us, "String returned from FC init is: %s\n", buffer);
 
        /* Special thanks to the people at Freecom for providing me with
         * this "magic sequence", which they use in their Windows and MacOS
@@ -445,7 +446,7 @@ static int init_freecom(struct us_data *us)
        /* send reset */
        result = usb_stor_control_msg(us, us->send_ctrl_pipe,
                        0x4d, 0x40, 0x24d8, 0x0, NULL, 0x0, 3*HZ);
-       US_DEBUGP("result from activate reset is %d\n", result);
+       usb_stor_dbg(us, "result from activate reset is %d\n", result);
 
        /* wait 250ms */
        mdelay(250);
@@ -453,7 +454,7 @@ static int init_freecom(struct us_data *us)
        /* clear reset */
        result = usb_stor_control_msg(us, us->send_ctrl_pipe,
                        0x4d, 0x40, 0x24f8, 0x0, NULL, 0x0, 3*HZ);
-       US_DEBUGP("result from clear reset is %d\n", result);
+       usb_stor_dbg(us, "result from clear reset is %d\n", result);
 
        /* wait 3 seconds */
        mdelay(3 * 1000);
@@ -470,7 +471,7 @@ static int usb_stor_freecom_reset(struct us_data *us)
 }
 
 #ifdef CONFIG_USB_STORAGE_DEBUG
-static void pdump (void *ibuffer, int length)
+static void pdump(struct us_data *us, void *ibuffer, int length)
 {
        static char line[80];
        int offset = 0;
@@ -490,7 +491,7 @@ static void pdump (void *ibuffer, int length)
                                                line[offset++] = '.';
                                }
                                line[offset] = 0;
-                               US_DEBUGP("%s\n", line);
+                               usb_stor_dbg(us, "%s\n", line);
                                offset = 0;
                        }
                        offset += sprintf (line+offset, "%08x:", i);
@@ -517,7 +518,7 @@ static void pdump (void *ibuffer, int length)
                        line[offset++] = '.';
        }
        line[offset] = 0;
-       US_DEBUGP("%s\n", line);
+       usb_stor_dbg(us, "%s\n", line);
        offset = 0;
 }
 #endif
index 105d900150c1a80155c2afcec6a61f4fb07fd0b4..5a8b5ff1e45bf597d9028c80e585047b0148e838 100644 (file)
@@ -48,12 +48,12 @@ int usb_stor_euscsi_init(struct us_data *us)
 {
        int result;
 
-       US_DEBUGP("Attempting to init eUSCSI bridge...\n");
+       usb_stor_dbg(us, "Attempting to init eUSCSI bridge...\n");
        us->iobuf[0] = 0x1;
        result = usb_stor_control_msg(us, us->send_ctrl_pipe,
                        0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR,
                        0x01, 0x0, us->iobuf, 0x1, 5000);
-       US_DEBUGP("-- result is %d\n", result);
+       usb_stor_dbg(us, "-- result is %d\n", result);
 
        return 0;
 }
@@ -68,7 +68,7 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
        unsigned int partial;
        static char init_string[] = "\xec\x0a\x06\x00$PCCHIPS";
 
-       US_DEBUGP("Sending UCR-61S2B initialization packet...\n");
+       usb_stor_dbg(us, "Sending UCR-61S2B initialization packet...\n");
 
        bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
        bcb->Tag = 0;
@@ -83,7 +83,7 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
        if (res)
                return -EIO;
 
-       US_DEBUGP("Getting status packet...\n");
+       usb_stor_dbg(us, "Getting status packet...\n");
        res = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, bcs,
                        US_BULK_CS_WRAP_LEN, &partial);
        if (res)
@@ -101,6 +101,6 @@ int usb_stor_huawei_e220_init(struct us_data *us)
                                      USB_REQ_SET_FEATURE,
                                      USB_TYPE_STANDARD | USB_RECIP_DEVICE,
                                      0x01, 0x0, NULL, 0x0, 1000);
-       US_DEBUGP("Huawei mode set result is %d\n", result);
+       usb_stor_dbg(us, "Huawei mode set result is %d\n", result);
        return 0;
 }
index ecea4787736463ccda4d1a498749eed74c2c9136..599d8bff26c3f19164f5a79c428a11f3da4e3322 100644 (file)
@@ -503,7 +503,7 @@ static int isd200_action( struct us_data *us, int action,
 
        switch ( action ) {
        case ACTION_READ_STATUS:
-               US_DEBUGP("   isd200_action(READ_STATUS)\n");
+               usb_stor_dbg(us, "   isd200_action(READ_STATUS)\n");
                ata.generic.ActionSelect = ACTION_SELECT_0|ACTION_SELECT_2;
                ata.generic.RegisterSelect =
                  REG_CYLINDER_LOW | REG_CYLINDER_HIGH |
@@ -512,7 +512,7 @@ static int isd200_action( struct us_data *us, int action,
                break;
 
        case ACTION_ENUM:
-               US_DEBUGP("   isd200_action(ENUM,0x%02x)\n",value);
+               usb_stor_dbg(us, "   isd200_action(ENUM,0x%02x)\n", value);
                ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2|
                                           ACTION_SELECT_3|ACTION_SELECT_4|
                                           ACTION_SELECT_5;
@@ -522,7 +522,7 @@ static int isd200_action( struct us_data *us, int action,
                break;
 
        case ACTION_RESET:
-               US_DEBUGP("   isd200_action(RESET)\n");
+               usb_stor_dbg(us, "   isd200_action(RESET)\n");
                ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2|
                                           ACTION_SELECT_3|ACTION_SELECT_4;
                ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
@@ -531,7 +531,7 @@ static int isd200_action( struct us_data *us, int action,
                break;
 
        case ACTION_REENABLE:
-               US_DEBUGP("   isd200_action(REENABLE)\n");
+               usb_stor_dbg(us, "   isd200_action(REENABLE)\n");
                ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_2|
                                           ACTION_SELECT_3|ACTION_SELECT_4;
                ata.generic.RegisterSelect = REG_DEVICE_CONTROL;
@@ -540,7 +540,7 @@ static int isd200_action( struct us_data *us, int action,
                break;
 
        case ACTION_SOFT_RESET:
-               US_DEBUGP("   isd200_action(SOFT_RESET)\n");
+               usb_stor_dbg(us, "   isd200_action(SOFT_RESET)\n");
                ata.generic.ActionSelect = ACTION_SELECT_1|ACTION_SELECT_5;
                ata.generic.RegisterSelect = REG_DEVICE_HEAD | REG_COMMAND;
                ata.write.DeviceHeadByte = info->DeviceHead;
@@ -549,7 +549,7 @@ static int isd200_action( struct us_data *us, int action,
                break;
 
        case ACTION_IDENTIFY:
-               US_DEBUGP("   isd200_action(IDENTIFY)\n");
+               usb_stor_dbg(us, "   isd200_action(IDENTIFY)\n");
                ata.generic.RegisterSelect = REG_COMMAND;
                ata.write.CommandByte = ATA_CMD_ID_ATA;
                isd200_set_srb(info, DMA_FROM_DEVICE, info->id,
@@ -557,7 +557,7 @@ static int isd200_action( struct us_data *us, int action,
                break;
 
        default:
-               US_DEBUGP("Error: Undefined action %d\n",action);
+               usb_stor_dbg(us, "Error: Undefined action %d\n", action);
                return ISD200_ERROR;
        }
 
@@ -567,7 +567,8 @@ static int isd200_action( struct us_data *us, int action,
        if (status == USB_STOR_TRANSPORT_GOOD)
                status = ISD200_GOOD;
        else {
-               US_DEBUGP("   isd200_action(0x%02x) error: %d\n",action,status);
+               usb_stor_dbg(us, "   isd200_action(0x%02x) error: %d\n",
+                            action, status);
                status = ISD200_ERROR;
                /* need to reset device here */
        }
@@ -589,17 +590,17 @@ static int isd200_read_regs( struct us_data *us )
        int retStatus = ISD200_GOOD;
        int transferStatus;
 
-       US_DEBUGP("Entering isd200_IssueATAReadRegs\n");
+       usb_stor_dbg(us, "Entering isd200_IssueATAReadRegs\n");
 
        transferStatus = isd200_action( us, ACTION_READ_STATUS,
                                    info->RegsBuf, sizeof(info->ATARegs) );
        if (transferStatus != ISD200_TRANSPORT_GOOD) {
-               US_DEBUGP("   Error reading ATA registers\n");
+               usb_stor_dbg(us, "   Error reading ATA registers\n");
                retStatus = ISD200_ERROR;
        } else {
                memcpy(info->ATARegs, info->RegsBuf, sizeof(info->ATARegs));
-               US_DEBUGP("   Got ATA Register[ATA_REG_ERROR_OFFSET] = 0x%x\n",
-                         info->ATARegs[ATA_REG_ERROR_OFFSET]);
+               usb_stor_dbg(us, "   Got ATA Register[ATA_REG_ERROR_OFFSET] = 0x%x\n",
+                            info->ATARegs[ATA_REG_ERROR_OFFSET]);
        }
 
        return retStatus;
@@ -629,7 +630,7 @@ static void isd200_invoke_transport( struct us_data *us,
         * short-circuit all other processing
         */
        if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
-               US_DEBUGP("-- command was aborted\n");
+               usb_stor_dbg(us, "-- command was aborted\n");
                goto Handle_Abort;
        }
 
@@ -641,23 +642,23 @@ static void isd200_invoke_transport( struct us_data *us,
                break;
 
        case USB_STOR_TRANSPORT_NO_SENSE:
-               US_DEBUGP("-- transport indicates protocol failure\n");
+               usb_stor_dbg(us, "-- transport indicates protocol failure\n");
                srb->result = SAM_STAT_CHECK_CONDITION;
                return;
 
        case USB_STOR_TRANSPORT_FAILED:
-               US_DEBUGP("-- transport indicates command failure\n");
+               usb_stor_dbg(us, "-- transport indicates command failure\n");
                need_auto_sense = 1;
                break;
 
        case USB_STOR_TRANSPORT_ERROR:
-               US_DEBUGP("-- transport indicates transport error\n");
+               usb_stor_dbg(us, "-- transport indicates transport error\n");
                srb->result = DID_ERROR << 16;
                /* Need reset here */
                return;
     
        default:
-               US_DEBUGP("-- transport indicates unknown error\n");   
+               usb_stor_dbg(us, "-- transport indicates unknown error\n");
                srb->result = DID_ERROR << 16;
                /* Need reset here */
                return;
@@ -669,14 +670,14 @@ static void isd200_invoke_transport( struct us_data *us,
              (srb->cmnd[0] == MODE_SENSE) ||
              (srb->cmnd[0] == LOG_SENSE) ||
              (srb->cmnd[0] == MODE_SENSE_10))) {
-               US_DEBUGP("-- unexpectedly short transfer\n");
+               usb_stor_dbg(us, "-- unexpectedly short transfer\n");
                need_auto_sense = 1;
        }
 
        if (need_auto_sense) {
                result = isd200_read_regs(us);
                if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
-                       US_DEBUGP("-- auto-sense aborted\n");
+                       usb_stor_dbg(us, "-- auto-sense aborted\n");
                        goto Handle_Abort;
                }
                if (result == ISD200_GOOD) {
@@ -710,40 +711,40 @@ static void isd200_invoke_transport( struct us_data *us,
 }
 
 #ifdef CONFIG_USB_STORAGE_DEBUG
-static void isd200_log_config( struct isd200_info* info )
+static void isd200_log_config(struct us_data *us, struct isd200_info *info)
 {
-       US_DEBUGP("      Event Notification: 0x%x\n", 
-                 info->ConfigData.EventNotification);
-       US_DEBUGP("      External Clock: 0x%x\n", 
-                 info->ConfigData.ExternalClock);
-       US_DEBUGP("      ATA Init Timeout: 0x%x\n", 
-                 info->ConfigData.ATAInitTimeout);
-       US_DEBUGP("      ATAPI Command Block Size: 0x%x\n", 
-                 (info->ConfigData.ATAConfig & ATACFG_BLOCKSIZE) >> 6);
-       US_DEBUGP("      Master/Slave Selection: 0x%x\n", 
-                 info->ConfigData.ATAConfig & ATACFG_MASTER);
-       US_DEBUGP("      ATAPI Reset: 0x%x\n",
-                 info->ConfigData.ATAConfig & ATACFG_ATAPI_RESET);
-       US_DEBUGP("      ATA Timing: 0x%x\n",
-                 info->ConfigData.ATAConfig & ATACFG_TIMING);
-       US_DEBUGP("      ATA Major Command: 0x%x\n", 
-                 info->ConfigData.ATAMajorCommand);
-       US_DEBUGP("      ATA Minor Command: 0x%x\n", 
-                 info->ConfigData.ATAMinorCommand);
-       US_DEBUGP("      Init Status: 0x%x\n", 
-                 info->ConfigData.ATAExtraConfig & ATACFGE_INIT_STATUS);
-       US_DEBUGP("      Config Descriptor 2: 0x%x\n", 
-                 info->ConfigData.ATAExtraConfig & ATACFGE_CONF_DESC2);
-       US_DEBUGP("      Skip Device Boot: 0x%x\n",
-                 info->ConfigData.ATAExtraConfig & ATACFGE_SKIP_BOOT);
-       US_DEBUGP("      ATA 3 State Supsend: 0x%x\n",
-                 info->ConfigData.ATAExtraConfig & ATACFGE_STATE_SUSPEND);
-       US_DEBUGP("      Descriptor Override: 0x%x\n", 
-                 info->ConfigData.ATAExtraConfig & ATACFGE_DESC_OVERRIDE);
-       US_DEBUGP("      Last LUN Identifier: 0x%x\n",
-                 info->ConfigData.ATAExtraConfig & ATACFGE_LAST_LUN);
-       US_DEBUGP("      SRST Enable: 0x%x\n", 
-                 info->ConfigData.ATAExtraConfig & CFG_CAPABILITY_SRST);
+       usb_stor_dbg(us, "      Event Notification: 0x%x\n",
+                    info->ConfigData.EventNotification);
+       usb_stor_dbg(us, "      External Clock: 0x%x\n",
+                    info->ConfigData.ExternalClock);
+       usb_stor_dbg(us, "      ATA Init Timeout: 0x%x\n",
+                    info->ConfigData.ATAInitTimeout);
+       usb_stor_dbg(us, "      ATAPI Command Block Size: 0x%x\n",
+                    (info->ConfigData.ATAConfig & ATACFG_BLOCKSIZE) >> 6);
+       usb_stor_dbg(us, "      Master/Slave Selection: 0x%x\n",
+                    info->ConfigData.ATAConfig & ATACFG_MASTER);
+       usb_stor_dbg(us, "      ATAPI Reset: 0x%x\n",
+                    info->ConfigData.ATAConfig & ATACFG_ATAPI_RESET);
+       usb_stor_dbg(us, "      ATA Timing: 0x%x\n",
+                    info->ConfigData.ATAConfig & ATACFG_TIMING);
+       usb_stor_dbg(us, "      ATA Major Command: 0x%x\n",
+                    info->ConfigData.ATAMajorCommand);
+       usb_stor_dbg(us, "      ATA Minor Command: 0x%x\n",
+                    info->ConfigData.ATAMinorCommand);
+       usb_stor_dbg(us, "      Init Status: 0x%x\n",
+                    info->ConfigData.ATAExtraConfig & ATACFGE_INIT_STATUS);
+       usb_stor_dbg(us, "      Config Descriptor 2: 0x%x\n",
+                    info->ConfigData.ATAExtraConfig & ATACFGE_CONF_DESC2);
+       usb_stor_dbg(us, "      Skip Device Boot: 0x%x\n",
+                    info->ConfigData.ATAExtraConfig & ATACFGE_SKIP_BOOT);
+       usb_stor_dbg(us, "      ATA 3 State Supsend: 0x%x\n",
+                    info->ConfigData.ATAExtraConfig & ATACFGE_STATE_SUSPEND);
+       usb_stor_dbg(us, "      Descriptor Override: 0x%x\n",
+                    info->ConfigData.ATAExtraConfig & ATACFGE_DESC_OVERRIDE);
+       usb_stor_dbg(us, "      Last LUN Identifier: 0x%x\n",
+                    info->ConfigData.ATAExtraConfig & ATACFGE_LAST_LUN);
+       usb_stor_dbg(us, "      SRST Enable: 0x%x\n",
+                    info->ConfigData.ATAExtraConfig & CFG_CAPABILITY_SRST);
 }
 #endif
 
@@ -762,9 +763,9 @@ static int isd200_write_config( struct us_data *us )
        int result;
 
 #ifdef CONFIG_USB_STORAGE_DEBUG
-       US_DEBUGP("Entering isd200_write_config\n");
-       US_DEBUGP("   Writing the following ISD200 Config Data:\n");
-       isd200_log_config(info);
+       usb_stor_dbg(us, "Entering isd200_write_config\n");
+       usb_stor_dbg(us, "   Writing the following ISD200 Config Data:\n");
+       isd200_log_config(us, info);
 #endif
 
        /* let's send the command via the control pipe */
@@ -779,13 +780,13 @@ static int isd200_write_config( struct us_data *us )
                sizeof(info->ConfigData));
 
        if (result >= 0) {
-               US_DEBUGP("   ISD200 Config Data was written successfully\n");
+               usb_stor_dbg(us, "   ISD200 Config Data was written successfully\n");
        } else {
-               US_DEBUGP("   Request to write ISD200 Config Data failed!\n");
+               usb_stor_dbg(us, "   Request to write ISD200 Config Data failed!\n");
                retStatus = ISD200_ERROR;
        }
 
-       US_DEBUGP("Leaving isd200_write_config %08X\n", retStatus);
+       usb_stor_dbg(us, "Leaving isd200_write_config %08X\n", retStatus);
        return retStatus;
 }
 
@@ -804,7 +805,7 @@ static int isd200_read_config( struct us_data *us )
        int retStatus = ISD200_GOOD;
        int result;
 
-       US_DEBUGP("Entering isd200_read_config\n");
+       usb_stor_dbg(us, "Entering isd200_read_config\n");
 
        /* read the configuration information from ISD200.  Use this to */
        /* determine what the special ATA CDB bytes are.                */
@@ -821,16 +822,16 @@ static int isd200_read_config( struct us_data *us )
 
 
        if (result >= 0) {
-               US_DEBUGP("   Retrieved the following ISD200 Config Data:\n");
+               usb_stor_dbg(us, "   Retrieved the following ISD200 Config Data:\n");
 #ifdef CONFIG_USB_STORAGE_DEBUG
-               isd200_log_config(info);
+               isd200_log_config(us, info);
 #endif
        } else {
-               US_DEBUGP("   Request to get ISD200 Config Data failed!\n");
+               usb_stor_dbg(us, "   Request to get ISD200 Config Data failed!\n");
                retStatus = ISD200_ERROR;
        }
 
-       US_DEBUGP("Leaving isd200_read_config %08X\n", retStatus);
+       usb_stor_dbg(us, "Leaving isd200_read_config %08X\n", retStatus);
        return retStatus;
 }
 
@@ -848,15 +849,15 @@ static int isd200_atapi_soft_reset( struct us_data *us )
        int retStatus = ISD200_GOOD;
        int transferStatus;
 
-       US_DEBUGP("Entering isd200_atapi_soft_reset\n");
+       usb_stor_dbg(us, "Entering isd200_atapi_soft_reset\n");
 
        transferStatus = isd200_action( us, ACTION_SOFT_RESET, NULL, 0 );
        if (transferStatus != ISD200_TRANSPORT_GOOD) {
-               US_DEBUGP("   Error issuing Atapi Soft Reset\n");
+               usb_stor_dbg(us, "   Error issuing Atapi Soft Reset\n");
                retStatus = ISD200_ERROR;
        }
 
-       US_DEBUGP("Leaving isd200_atapi_soft_reset %08X\n", retStatus);
+       usb_stor_dbg(us, "Leaving isd200_atapi_soft_reset %08X\n", retStatus);
        return retStatus;
 }
 
@@ -874,13 +875,13 @@ static int isd200_srst( struct us_data *us )
        int retStatus = ISD200_GOOD;
        int transferStatus;
 
-       US_DEBUGP("Entering isd200_SRST\n");
+       usb_stor_dbg(us, "Entering isd200_SRST\n");
 
        transferStatus = isd200_action( us, ACTION_RESET, NULL, 0 );
 
        /* check to see if this request failed */
        if (transferStatus != ISD200_TRANSPORT_GOOD) {
-               US_DEBUGP("   Error issuing SRST\n");
+               usb_stor_dbg(us, "   Error issuing SRST\n");
                retStatus = ISD200_ERROR;
        } else {
                /* delay 10ms to give the drive a chance to see it */
@@ -888,7 +889,7 @@ static int isd200_srst( struct us_data *us )
 
                transferStatus = isd200_action( us, ACTION_REENABLE, NULL, 0 );
                if (transferStatus != ISD200_TRANSPORT_GOOD) {
-                       US_DEBUGP("   Error taking drive out of reset\n");
+                       usb_stor_dbg(us, "   Error taking drive out of reset\n");
                        retStatus = ISD200_ERROR;
                } else {
                        /* delay 50ms to give the drive a chance to recover after SRST */
@@ -896,7 +897,7 @@ static int isd200_srst( struct us_data *us )
                }
        }
 
-       US_DEBUGP("Leaving isd200_srst %08X\n", retStatus);
+       usb_stor_dbg(us, "Leaving isd200_srst %08X\n", retStatus);
        return retStatus;
 }
 
@@ -926,10 +927,6 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
 
        /* loop until we detect !BSY or timeout */
        while(1) {
-#ifdef CONFIG_USB_STORAGE_DEBUG
-               char* mstr = master_slave == ATA_ADDRESS_DEVHEAD_STD ?
-                       "Master" : "Slave";
-#endif
 
                status = isd200_action( us, ACTION_ENUM, NULL, master_slave );
                if ( status != ISD200_GOOD )
@@ -942,9 +939,13 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
 
                if (!detect) {
                        if (regs[ATA_REG_STATUS_OFFSET] & ATA_BUSY) {
-                               US_DEBUGP("   %s status is still BSY, try again...\n",mstr);
+                               usb_stor_dbg(us, "   %s status is still BSY, try again...\n",
+                                            master_slave == ATA_ADDRESS_DEVHEAD_STD ?
+                                            "Master" : "Slave");
                        } else {
-                               US_DEBUGP("   %s status !BSY, continue with next operation\n",mstr);
+                               usb_stor_dbg(us, "   %s status !BSY, continue with next operation\n",
+                                            master_slave == ATA_ADDRESS_DEVHEAD_STD ?
+                                            "Master" : "Slave");
                                break;
                        }
                }
@@ -953,11 +954,11 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
                /* ATA_ERR (workaround for Archos CD-ROM) */
                else if (regs[ATA_REG_STATUS_OFFSET] &
                         (ATA_BUSY | ATA_DF | ATA_ERR)) {
-                       US_DEBUGP("   Status indicates it is not ready, try again...\n");
+                       usb_stor_dbg(us, "   Status indicates it is not ready, try again...\n");
                }
                /* check for DRDY, ATA devices set DRDY after SRST */
                else if (regs[ATA_REG_STATUS_OFFSET] & ATA_DRDY) {
-                       US_DEBUGP("   Identified ATA device\n");
+                       usb_stor_dbg(us, "   Identified ATA device\n");
                        info->DeviceFlags |= DF_ATA_DEVICE;
                        info->DeviceHead = master_slave;
                        break;
@@ -978,27 +979,27 @@ static int isd200_try_enum(struct us_data *us, unsigned char master_slave,
                        */
                        if ((master_slave & ATA_ADDRESS_DEVHEAD_SLAVE) &&
                            !recheckAsMaster) {
-                               US_DEBUGP("   Identified ATAPI device as slave.  Rechecking again as master\n");
+                               usb_stor_dbg(us, "   Identified ATAPI device as slave.  Rechecking again as master\n");
                                recheckAsMaster = 1;
                                master_slave = ATA_ADDRESS_DEVHEAD_STD;
                        } else {
-                               US_DEBUGP("   Identified ATAPI device\n");
+                               usb_stor_dbg(us, "   Identified ATAPI device\n");
                                info->DeviceHead = master_slave;
                              
                                status = isd200_atapi_soft_reset(us);
                                break;
                        }
                } else {
-                       US_DEBUGP("   Not ATA, not ATAPI. Weird.\n");
+                       usb_stor_dbg(us, "   Not ATA, not ATAPI - Weird\n");
                        break;
                }
 
                /* check for timeout on this request */
                if (time_after_eq(jiffies, endTime)) {
                        if (!detect)
-                               US_DEBUGP("   BSY check timeout, just continue with next operation...\n");
+                               usb_stor_dbg(us, "   BSY check timeout, just continue with next operation...\n");
                        else
-                               US_DEBUGP("   Device detect timeout!\n");
+                               usb_stor_dbg(us, "   Device detect timeout!\n");
                        break;
                }
        }
@@ -1020,7 +1021,7 @@ static int isd200_manual_enum(struct us_data *us)
        struct isd200_info *info = (struct isd200_info *)us->extra;
        int retStatus = ISD200_GOOD;
 
-       US_DEBUGP("Entering isd200_manual_enum\n");
+       usb_stor_dbg(us, "Entering isd200_manual_enum\n");
 
        retStatus = isd200_read_config(us);
        if (retStatus == ISD200_GOOD) {
@@ -1039,14 +1040,15 @@ static int isd200_manual_enum(struct us_data *us)
 
                isslave = (info->DeviceHead & ATA_ADDRESS_DEVHEAD_SLAVE) ? 1 : 0;
                if (!(info->ConfigData.ATAConfig & ATACFG_MASTER)) {
-                       US_DEBUGP("   Setting Master/Slave selection to %d\n", isslave);
+                       usb_stor_dbg(us, "   Setting Master/Slave selection to %d\n",
+                                    isslave);
                        info->ConfigData.ATAConfig &= 0x3f;
                        info->ConfigData.ATAConfig |= (isslave<<6);
                        retStatus = isd200_write_config(us);
                }
        }
 
-       US_DEBUGP("Leaving isd200_manual_enum %08X\n", retStatus);
+       usb_stor_dbg(us, "Leaving isd200_manual_enum %08X\n", retStatus);
        return(retStatus);
 }
 
@@ -1064,35 +1066,35 @@ static void isd200_fix_driveid(u16 *id)
 #endif
 }
 
-static void isd200_dump_driveid(u16 *id)
+static void isd200_dump_driveid(struct us_data *us, u16 *id)
 {
-       US_DEBUGP("   Identify Data Structure:\n");
-       US_DEBUGP("      config = 0x%x\n",        id[ATA_ID_CONFIG]);
-       US_DEBUGP("      cyls = 0x%x\n",          id[ATA_ID_CYLS]);
-       US_DEBUGP("      heads = 0x%x\n",         id[ATA_ID_HEADS]);
-       US_DEBUGP("      track_bytes = 0x%x\n",   id[4]);
-       US_DEBUGP("      sector_bytes = 0x%x\n",  id[5]);
-       US_DEBUGP("      sectors = 0x%x\n",       id[ATA_ID_SECTORS]);
-       US_DEBUGP("      serial_no[0] = 0x%x\n",  *(char *)&id[ATA_ID_SERNO]);
-       US_DEBUGP("      buf_type = 0x%x\n",      id[20]);
-       US_DEBUGP("      buf_size = 0x%x\n",      id[ATA_ID_BUF_SIZE]);
-       US_DEBUGP("      ecc_bytes = 0x%x\n",     id[22]);
-       US_DEBUGP("      fw_rev[0] = 0x%x\n",     *(char *)&id[ATA_ID_FW_REV]);
-       US_DEBUGP("      model[0] = 0x%x\n",      *(char *)&id[ATA_ID_PROD]);
-       US_DEBUGP("      max_multsect = 0x%x\n",  id[ATA_ID_MAX_MULTSECT] & 0xff);
-       US_DEBUGP("      dword_io = 0x%x\n",      id[ATA_ID_DWORD_IO]);
-       US_DEBUGP("      capability = 0x%x\n",    id[ATA_ID_CAPABILITY] >> 8);
-       US_DEBUGP("      tPIO = 0x%x\n",          id[ATA_ID_OLD_PIO_MODES] >> 8);
-       US_DEBUGP("      tDMA = 0x%x\n",          id[ATA_ID_OLD_DMA_MODES] >> 8);
-       US_DEBUGP("      field_valid = 0x%x\n",   id[ATA_ID_FIELD_VALID]);
-       US_DEBUGP("      cur_cyls = 0x%x\n",      id[ATA_ID_CUR_CYLS]);
-       US_DEBUGP("      cur_heads = 0x%x\n",     id[ATA_ID_CUR_HEADS]);
-       US_DEBUGP("      cur_sectors = 0x%x\n",   id[ATA_ID_CUR_SECTORS]);
-       US_DEBUGP("      cur_capacity = 0x%x\n",  ata_id_u32(id, 57));
-       US_DEBUGP("      multsect = 0x%x\n",      id[ATA_ID_MULTSECT] & 0xff);
-       US_DEBUGP("      lba_capacity = 0x%x\n",  ata_id_u32(id, ATA_ID_LBA_CAPACITY));
-       US_DEBUGP("      command_set_1 = 0x%x\n", id[ATA_ID_COMMAND_SET_1]);
-       US_DEBUGP("      command_set_2 = 0x%x\n", id[ATA_ID_COMMAND_SET_2]);
+       usb_stor_dbg(us, "   Identify Data Structure:\n");
+       usb_stor_dbg(us, "      config = 0x%x\n",       id[ATA_ID_CONFIG]);
+       usb_stor_dbg(us, "      cyls = 0x%x\n",         id[ATA_ID_CYLS]);
+       usb_stor_dbg(us, "      heads = 0x%x\n",        id[ATA_ID_HEADS]);
+       usb_stor_dbg(us, "      track_bytes = 0x%x\n",  id[4]);
+       usb_stor_dbg(us, "      sector_bytes = 0x%x\n", id[5]);
+       usb_stor_dbg(us, "      sectors = 0x%x\n",      id[ATA_ID_SECTORS]);
+       usb_stor_dbg(us, "      serial_no[0] = 0x%x\n", *(char *)&id[ATA_ID_SERNO]);
+       usb_stor_dbg(us, "      buf_type = 0x%x\n",     id[20]);
+       usb_stor_dbg(us, "      buf_size = 0x%x\n",     id[ATA_ID_BUF_SIZE]);
+       usb_stor_dbg(us, "      ecc_bytes = 0x%x\n",    id[22]);
+       usb_stor_dbg(us, "      fw_rev[0] = 0x%x\n",    *(char *)&id[ATA_ID_FW_REV]);
+       usb_stor_dbg(us, "      model[0] = 0x%x\n",     *(char *)&id[ATA_ID_PROD]);
+       usb_stor_dbg(us, "      max_multsect = 0x%x\n", id[ATA_ID_MAX_MULTSECT] & 0xff);
+       usb_stor_dbg(us, "      dword_io = 0x%x\n",     id[ATA_ID_DWORD_IO]);
+       usb_stor_dbg(us, "      capability = 0x%x\n",   id[ATA_ID_CAPABILITY] >> 8);
+       usb_stor_dbg(us, "      tPIO = 0x%x\n",   id[ATA_ID_OLD_PIO_MODES] >> 8);
+       usb_stor_dbg(us, "      tDMA = 0x%x\n",   id[ATA_ID_OLD_DMA_MODES] >> 8);
+       usb_stor_dbg(us, "      field_valid = 0x%x\n",  id[ATA_ID_FIELD_VALID]);
+       usb_stor_dbg(us, "      cur_cyls = 0x%x\n",     id[ATA_ID_CUR_CYLS]);
+       usb_stor_dbg(us, "      cur_heads = 0x%x\n",    id[ATA_ID_CUR_HEADS]);
+       usb_stor_dbg(us, "      cur_sectors = 0x%x\n",  id[ATA_ID_CUR_SECTORS]);
+       usb_stor_dbg(us, "      cur_capacity = 0x%x\n", ata_id_u32(id, 57));
+       usb_stor_dbg(us, "      multsect = 0x%x\n",     id[ATA_ID_MULTSECT] & 0xff);
+       usb_stor_dbg(us, "      lba_capacity = 0x%x\n", ata_id_u32(id, ATA_ID_LBA_CAPACITY));
+       usb_stor_dbg(us, "      command_set_1 = 0x%x\n", id[ATA_ID_COMMAND_SET_1]);
+       usb_stor_dbg(us, "      command_set_2 = 0x%x\n", id[ATA_ID_COMMAND_SET_2]);
 }
 
 /**************************************************************************
@@ -1109,7 +1111,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
        int retStatus = ISD200_GOOD;
        u16 *id = info->id;
 
-       US_DEBUGP("Entering isd200_get_inquiry_data\n");
+       usb_stor_dbg(us, "Entering isd200_get_inquiry_data\n");
 
        /* set default to Master */
        info->DeviceHead = ATA_ADDRESS_DEVHEAD_STD;
@@ -1127,7 +1129,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
                                                        id, ATA_ID_WORDS * 2);
                        if (transferStatus != ISD200_TRANSPORT_GOOD) {
                                /* Error issuing ATA Command Identify */
-                               US_DEBUGP("   Error issuing ATA Command Identify\n");
+                               usb_stor_dbg(us, "   Error issuing ATA Command Identify\n");
                                retStatus = ISD200_ERROR;
                        } else {
                                /* ATA Command Identify successful */
@@ -1136,7 +1138,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
                                __u16 *dest;
 
                                isd200_fix_driveid(id);
-                               isd200_dump_driveid(id);
+                               isd200_dump_driveid(us, id);
 
                                memset(&info->InquiryData, 0, sizeof(info->InquiryData));
 
@@ -1170,7 +1172,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
 
                                /* determine if it supports Media Status Notification */
                                if (id[ATA_ID_COMMAND_SET_2] & COMMANDSET_MEDIA_STATUS) {
-                                       US_DEBUGP("   Device supports Media Status Notification\n");
+                                       usb_stor_dbg(us, "   Device supports Media Status Notification\n");
 
                                        /* Indicate that it is enabled, even though it is not
                                         * This allows the lock/unlock of the media to work
@@ -1190,7 +1192,8 @@ static int isd200_get_inquiry_data( struct us_data *us )
                        us->protocol_name = "Transparent SCSI";
                        us->proto_handler = usb_stor_transparent_scsi_command;
 
-                       US_DEBUGP("Protocol changed to: %s\n", us->protocol_name);
+                       usb_stor_dbg(us, "Protocol changed to: %s\n",
+                                    us->protocol_name);
            
                        /* Free driver structure */         
                        us->extra_destructor(info);
@@ -1200,7 +1203,7 @@ static int isd200_get_inquiry_data( struct us_data *us )
                }
        }
 
-       US_DEBUGP("Leaving isd200_get_inquiry_data %08X\n", retStatus);
+       usb_stor_dbg(us, "Leaving isd200_get_inquiry_data %08X\n", retStatus);
 
        return(retStatus);
 }
@@ -1231,7 +1234,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
        /* SCSI Command */
        switch (srb->cmnd[0]) {
        case INQUIRY:
-               US_DEBUGP("   ATA OUT - INQUIRY\n");
+               usb_stor_dbg(us, "   ATA OUT - INQUIRY\n");
 
                /* copy InquiryData */
                usb_stor_set_xfer_buf((unsigned char *) &info->InquiryData,
@@ -1241,7 +1244,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
                break;
 
        case MODE_SENSE:
-               US_DEBUGP("   ATA OUT - SCSIOP_MODE_SENSE\n");
+               usb_stor_dbg(us, "   ATA OUT - SCSIOP_MODE_SENSE\n");
 
                /* Initialize the return buffer */
                usb_stor_set_xfer_buf(senseData, sizeof(senseData), srb);
@@ -1255,14 +1258,14 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
                        ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
                        isd200_srb_set_bufflen(srb, 0);
                } else {
-                       US_DEBUGP("   Media Status not supported, just report okay\n");
+                       usb_stor_dbg(us, "   Media Status not supported, just report okay\n");
                        srb->result = SAM_STAT_GOOD;
                        sendToTransport = 0;
                }
                break;
 
        case TEST_UNIT_READY:
-               US_DEBUGP("   ATA OUT - SCSIOP_TEST_UNIT_READY\n");
+               usb_stor_dbg(us, "   ATA OUT - SCSIOP_TEST_UNIT_READY\n");
 
                if (info->DeviceFlags & DF_MEDIA_STATUS_ENABLED)
                {
@@ -1273,7 +1276,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
                        ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
                        isd200_srb_set_bufflen(srb, 0);
                } else {
-                       US_DEBUGP("   Media Status not supported, just report okay\n");
+                       usb_stor_dbg(us, "   Media Status not supported, just report okay\n");
                        srb->result = SAM_STAT_GOOD;
                        sendToTransport = 0;
                }
@@ -1284,7 +1287,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
                unsigned long capacity;
                struct read_capacity_data readCapacityData;
 
-               US_DEBUGP("   ATA OUT - SCSIOP_READ_CAPACITY\n");
+               usb_stor_dbg(us, "   ATA OUT - SCSIOP_READ_CAPACITY\n");
 
                if (ata_id_has_lba(id))
                        capacity = ata_id_u32(id, ATA_ID_LBA_CAPACITY) - 1;
@@ -1303,7 +1306,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
        break;
 
        case READ_10:
-               US_DEBUGP("   ATA OUT - SCSIOP_READ\n");
+               usb_stor_dbg(us, "   ATA OUT - SCSIOP_READ\n");
 
                lba = be32_to_cpu(*(__be32 *)&srb->cmnd[2]);
                blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8];
@@ -1335,7 +1338,7 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
                break;
 
        case WRITE_10:
-               US_DEBUGP("   ATA OUT - SCSIOP_WRITE\n");
+               usb_stor_dbg(us, "   ATA OUT - SCSIOP_WRITE\n");
 
                lba = be32_to_cpu(*(__be32 *)&srb->cmnd[2]);
                blockCount = (unsigned long)srb->cmnd[7]<<8 | (unsigned long)srb->cmnd[8];
@@ -1367,10 +1370,11 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
                break;
 
        case ALLOW_MEDIUM_REMOVAL:
-               US_DEBUGP("   ATA OUT - SCSIOP_MEDIUM_REMOVAL\n");
+               usb_stor_dbg(us, "   ATA OUT - SCSIOP_MEDIUM_REMOVAL\n");
 
                if (info->DeviceFlags & DF_REMOVABLE_MEDIA) {
-                       US_DEBUGP("   srb->cmnd[4] = 0x%X\n", srb->cmnd[4]);
+                       usb_stor_dbg(us, "   srb->cmnd[4] = 0x%X\n",
+                                    srb->cmnd[4]);
            
                        ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
                        ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
@@ -1380,25 +1384,25 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
                                ATA_CMD_MEDIA_LOCK : ATA_CMD_MEDIA_UNLOCK;
                        isd200_srb_set_bufflen(srb, 0);
                } else {
-                       US_DEBUGP("   Not removeable media, just report okay\n");
+                       usb_stor_dbg(us, "   Not removeable media, just report okay\n");
                        srb->result = SAM_STAT_GOOD;
                        sendToTransport = 0;
                }
                break;
 
        case START_STOP:    
-               US_DEBUGP("   ATA OUT - SCSIOP_START_STOP_UNIT\n");
-               US_DEBUGP("   srb->cmnd[4] = 0x%X\n", srb->cmnd[4]);
+               usb_stor_dbg(us, "   ATA OUT - SCSIOP_START_STOP_UNIT\n");
+               usb_stor_dbg(us, "   srb->cmnd[4] = 0x%X\n", srb->cmnd[4]);
 
                if ((srb->cmnd[4] & 0x3) == 0x2) {
-                       US_DEBUGP("   Media Eject\n");
+                       usb_stor_dbg(us, "   Media Eject\n");
                        ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
                        ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
                        ataCdb->generic.TransferBlockSize = 0;
                        ataCdb->generic.RegisterSelect = REG_COMMAND;
                        ataCdb->write.CommandByte = ATA_COMMAND_MEDIA_EJECT;
                } else if ((srb->cmnd[4] & 0x3) == 0x1) {
-                       US_DEBUGP("   Get Media Status\n");
+                       usb_stor_dbg(us, "   Get Media Status\n");
                        ataCdb->generic.SignatureByte0 = info->ConfigData.ATAMajorCommand;
                        ataCdb->generic.SignatureByte1 = info->ConfigData.ATAMinorCommand;
                        ataCdb->generic.TransferBlockSize = 1;
@@ -1406,14 +1410,15 @@ static int isd200_scsi_to_ata(struct scsi_cmnd *srb, struct us_data *us,
                        ataCdb->write.CommandByte = ATA_COMMAND_GET_MEDIA_STATUS;
                        isd200_srb_set_bufflen(srb, 0);
                } else {
-                       US_DEBUGP("   Nothing to do, just report okay\n");
+                       usb_stor_dbg(us, "   Nothing to do, just report okay\n");
                        srb->result = SAM_STAT_GOOD;
                        sendToTransport = 0;
                }
                break;
 
        default:
-               US_DEBUGP("Unsupported SCSI command - 0x%X\n", srb->cmnd[0]);
+               usb_stor_dbg(us, "Unsupported SCSI command - 0x%X\n",
+                            srb->cmnd[0]);
                srb->result = DID_ERROR << 16;
                sendToTransport = 0;
                break;
@@ -1457,8 +1462,7 @@ static int isd200_init_info(struct us_data *us)
                retStatus = ISD200_ERROR;
        else {
                info->id = kzalloc(ATA_ID_WORDS * 2, GFP_KERNEL);
-               info->RegsBuf = (unsigned char *)
-                               kmalloc(sizeof(info->ATARegs), 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) {
@@ -1471,8 +1475,7 @@ static int isd200_init_info(struct us_data *us)
        if (retStatus == ISD200_GOOD) {
                us->extra = info;
                us->extra_destructor = isd200_free_info_ptrs;
-       } else
-               US_DEBUGP("ERROR - kmalloc failure\n");
+       }
 
        return retStatus;
 }
@@ -1483,19 +1486,19 @@ static int isd200_init_info(struct us_data *us)
 
 static int isd200_Initialization(struct us_data *us)
 {
-       US_DEBUGP("ISD200 Initialization...\n");
+       usb_stor_dbg(us, "ISD200 Initialization...\n");
 
        /* Initialize ISD200 info struct */
 
        if (isd200_init_info(us) == ISD200_ERROR) {
-               US_DEBUGP("ERROR Initializing ISD200 Info struct\n");
+               usb_stor_dbg(us, "ERROR Initializing ISD200 Info struct\n");
        } else {
                /* Get device specific data */
 
                if (isd200_get_inquiry_data(us) != ISD200_GOOD)
-                       US_DEBUGP("ISD200 Initialization Failure\n");
+                       usb_stor_dbg(us, "ISD200 Initialization Failure\n");
                else
-                       US_DEBUGP("ISD200 Initialization complete\n");
+                       usb_stor_dbg(us, "ISD200 Initialization complete\n");
        }
 
        return 0;
@@ -1520,7 +1523,7 @@ static void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us)
        /* Make sure driver was initialized */
 
        if (us->extra == NULL)
-               US_DEBUGP("ERROR Driver not initialized\n");
+               usb_stor_dbg(us, "ERROR Driver not initialized\n");
 
        scsi_set_resid(srb, 0);
        /* scsi_bufflen might change in protocol translation to ata */
index ddc78780b1ad2a687a198281a181a57f5e0417a4..563078be6547844106e9927540d17e556d1971fc 100644 (file)
@@ -118,7 +118,7 @@ static inline int jumpshot_bulk_read(struct us_data *us,
        if (len == 0)
                return USB_STOR_XFER_GOOD;
 
-       US_DEBUGP("jumpshot_bulk_read:  len = %d\n", len);
+       usb_stor_dbg(us, "len = %d\n", len);
        return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
                        data, len, NULL);
 }
@@ -131,7 +131,7 @@ static inline int jumpshot_bulk_write(struct us_data *us,
        if (len == 0)
                return USB_STOR_XFER_GOOD;
 
-       US_DEBUGP("jumpshot_bulk_write:  len = %d\n", len);
+       usb_stor_dbg(us, "len = %d\n", len);
        return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
                        data, len, NULL);
 }
@@ -152,8 +152,7 @@ static int jumpshot_get_status(struct us_data  *us)
                return USB_STOR_TRANSPORT_ERROR;
 
        if (us->iobuf[0] != 0x50) {
-               US_DEBUGP("jumpshot_get_status:  0x%2x\n",
-                         us->iobuf[0]);
+               usb_stor_dbg(us, "0x%2x\n", us->iobuf[0]);
                return USB_STOR_TRANSPORT_ERROR;
        }
 
@@ -218,7 +217,7 @@ static int jumpshot_read_data(struct us_data *us,
                if (result != USB_STOR_XFER_GOOD)
                        goto leave;
 
-               US_DEBUGP("jumpshot_read_data:  %d bytes\n", len);
+               usb_stor_dbg(us, "%d bytes\n", len);
 
                // Store the data in the transfer buffer
                usb_stor_access_xfer_buf(buffer, len, us->srb,
@@ -314,7 +313,7 @@ static int jumpshot_write_data(struct us_data *us,
                } while ((result != USB_STOR_TRANSPORT_GOOD) && (waitcount < 10));
 
                if (result != USB_STOR_TRANSPORT_GOOD)
-                       US_DEBUGP("jumpshot_write_data:  Gah!  Waitcount = 10.  Bad write!?\n");
+                       usb_stor_dbg(us, "Gah!  Waitcount = 10.  Bad write!?\n");
 
                sector += thistime;
                totallen -= len;
@@ -349,8 +348,7 @@ static int jumpshot_id_device(struct us_data *us,
                                   0, 0x20, 0, 6, command, 2);
 
        if (rc != USB_STOR_XFER_GOOD) {
-               US_DEBUGP("jumpshot_id_device:  Gah! "
-                         "send_control for read_capacity failed\n");
+               usb_stor_dbg(us, "Gah! send_control for read_capacity failed\n");
                rc = USB_STOR_TRANSPORT_ERROR;
                goto leave;
        }
@@ -400,17 +398,17 @@ static int jumpshot_handle_mode_sense(struct us_data *us,
 
        switch (pc) {
           case 0x0:
-               US_DEBUGP("jumpshot_handle_mode_sense:  Current values\n");
-               break;
+                  usb_stor_dbg(us, "Current values\n");
+                  break;
           case 0x1:
-               US_DEBUGP("jumpshot_handle_mode_sense:  Changeable values\n");
-               break;
+                  usb_stor_dbg(us, "Changeable values\n");
+                  break;
           case 0x2:
-               US_DEBUGP("jumpshot_handle_mode_sense:  Default values\n");
-               break;
+                  usb_stor_dbg(us, "Default values\n");
+                  break;
           case 0x3:
-               US_DEBUGP("jumpshot_handle_mode_sense:  Saves values\n");
-               break;
+                  usb_stor_dbg(us, "Saves values\n");
+                  break;
        }
 
        memset(ptr, 0, 8);
@@ -494,17 +492,16 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
 
        if (!us->extra) {
                us->extra = kzalloc(sizeof(struct jumpshot_info), GFP_NOIO);
-               if (!us->extra) {
-                       US_DEBUGP("jumpshot_transport:  Gah! Can't allocate storage for jumpshot info struct!\n");
+               if (!us->extra)
                        return USB_STOR_TRANSPORT_ERROR;
-               }
+
                us->extra_destructor = jumpshot_info_destructor;
        }
 
        info = (struct jumpshot_info *) (us->extra);
 
        if (srb->cmnd[0] == INQUIRY) {
-               US_DEBUGP("jumpshot_transport:  INQUIRY.  Returning bogus response.\n");
+               usb_stor_dbg(us, "INQUIRY - Returning bogus response\n");
                memcpy(ptr, inquiry_response, sizeof(inquiry_response));
                fill_inquiry_response(us, ptr, 36);
                return USB_STOR_TRANSPORT_GOOD;
@@ -521,8 +518,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
                if (rc != USB_STOR_TRANSPORT_GOOD)
                        return rc;
 
-               US_DEBUGP("jumpshot_transport:  READ_CAPACITY:  %ld sectors, %ld bytes per sector\n",
-                         info->sectors, info->ssize);
+               usb_stor_dbg(us, "READ_CAPACITY:  %ld sectors, %ld bytes per sector\n",
+                            info->sectors, info->ssize);
 
                // build the reply
                //
@@ -534,7 +531,7 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
        }
 
        if (srb->cmnd[0] == MODE_SELECT_10) {
-               US_DEBUGP("jumpshot_transport:  Gah! MODE_SELECT_10.\n");
+               usb_stor_dbg(us, "Gah! MODE_SELECT_10\n");
                return USB_STOR_TRANSPORT_ERROR;
        }
 
@@ -544,7 +541,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
 
                blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
 
-               US_DEBUGP("jumpshot_transport:  READ_10: read block 0x%04lx  count %ld\n", block, blocks);
+               usb_stor_dbg(us, "READ_10: read block 0x%04lx  count %ld\n",
+                            block, blocks);
                return jumpshot_read_data(us, info, block, blocks);
        }
 
@@ -557,7 +555,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
                blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
                         ((u32)(srb->cmnd[8]) <<  8) | ((u32)(srb->cmnd[9]));
 
-               US_DEBUGP("jumpshot_transport:  READ_12: read block 0x%04lx  count %ld\n", block, blocks);
+               usb_stor_dbg(us, "READ_12: read block 0x%04lx  count %ld\n",
+                            block, blocks);
                return jumpshot_read_data(us, info, block, blocks);
        }
 
@@ -567,7 +566,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
 
                blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
 
-               US_DEBUGP("jumpshot_transport:  WRITE_10: write block 0x%04lx  count %ld\n", block, blocks);
+               usb_stor_dbg(us, "WRITE_10: write block 0x%04lx  count %ld\n",
+                            block, blocks);
                return jumpshot_write_data(us, info, block, blocks);
        }
 
@@ -580,18 +580,19 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
                blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
                         ((u32)(srb->cmnd[8]) <<  8) | ((u32)(srb->cmnd[9]));
 
-               US_DEBUGP("jumpshot_transport:  WRITE_12: write block 0x%04lx  count %ld\n", block, blocks);
+               usb_stor_dbg(us, "WRITE_12: write block 0x%04lx  count %ld\n",
+                            block, blocks);
                return jumpshot_write_data(us, info, block, blocks);
        }
 
 
        if (srb->cmnd[0] == TEST_UNIT_READY) {
-               US_DEBUGP("jumpshot_transport:  TEST_UNIT_READY.\n");
+               usb_stor_dbg(us, "TEST_UNIT_READY\n");
                return jumpshot_get_status(us);
        }
 
        if (srb->cmnd[0] == REQUEST_SENSE) {
-               US_DEBUGP("jumpshot_transport:  REQUEST_SENSE.\n");
+               usb_stor_dbg(us, "REQUEST_SENSE\n");
 
                memset(ptr, 0, 18);
                ptr[0] = 0xF0;
@@ -605,12 +606,12 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
        }
 
        if (srb->cmnd[0] == MODE_SENSE) {
-               US_DEBUGP("jumpshot_transport:  MODE_SENSE_6 detected\n");
+               usb_stor_dbg(us, "MODE_SENSE_6 detected\n");
                return jumpshot_handle_mode_sense(us, srb, 1);
        }
 
        if (srb->cmnd[0] == MODE_SENSE_10) {
-               US_DEBUGP("jumpshot_transport:  MODE_SENSE_10 detected\n");
+               usb_stor_dbg(us, "MODE_SENSE_10 detected\n");
                return jumpshot_handle_mode_sense(us, srb, 0);
        }
 
@@ -624,7 +625,7 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
        if (srb->cmnd[0] == START_STOP) {
                /* this is used by sd.c'check_scsidisk_media_change to detect
                   media change */
-               US_DEBUGP("jumpshot_transport:  START_STOP.\n");
+               usb_stor_dbg(us, "START_STOP\n");
                /* the first jumpshot_id_device after a media change returns
                   an error (determined experimentally) */
                rc = jumpshot_id_device(us, info);
@@ -638,8 +639,8 @@ static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us)
                return rc;
        }
 
-       US_DEBUGP("jumpshot_transport:  Gah! Unknown command: %d (0x%x)\n",
-                 srb->cmnd[0], srb->cmnd[0]);
+       usb_stor_dbg(us, "Gah! Unknown command: %d (0x%x)\n",
+                    srb->cmnd[0], srb->cmnd[0]);
        info->sense_key = 0x05;
        info->sense_asc = 0x20;
        info->sense_ascq = 0x00;
index f085ffb606c88e9c199dadb81448c2740c4f68a6..94d16ee5e84bcaab93afab0cf0b15e088f910c06 100644 (file)
@@ -106,7 +106,7 @@ static int rio_karma_send_command(char cmd, struct us_data *us)
        static unsigned char seq = 1;
        struct karma_data *data = (struct karma_data *) us->extra;
 
-       US_DEBUGP("karma: sending command %04x\n", cmd);
+       usb_stor_dbg(us, "sending command %04x\n", cmd);
        memset(us->iobuf, 0, RIO_SEND_LEN);
        memcpy(us->iobuf, RIO_PREFIX, RIO_PREFIX_LEN);
        us->iobuf[5] = cmd;
@@ -139,10 +139,10 @@ static int rio_karma_send_command(char cmd, struct us_data *us)
        if (seq == 0)
                seq = 1;
 
-       US_DEBUGP("karma: sent command %04x\n", cmd);
+       usb_stor_dbg(us, "sent command %04x\n", cmd);
        return 0;
 err:
-       US_DEBUGP("karma: command %04x failed\n", cmd);
+       usb_stor_dbg(us, "command %04x failed\n", cmd);
        return USB_STOR_TRANSPORT_FAILED;
 }
 
index cb79de61f4c837e191e1e8de0616e9b06d33d5fe..26964895c88b50ea0ce9bbc51a63e62bfda8f37c 100644 (file)
@@ -195,6 +195,7 @@ static int onetouch_connect_input(struct us_data *ss)
 
        pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
        maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
+       maxp = min(maxp, ONETOUCH_PKT_LEN);
 
        onetouch = kzalloc(sizeof(struct usb_onetouch), GFP_KERNEL);
        input_dev = input_allocate_device();
@@ -245,8 +246,7 @@ static int onetouch_connect_input(struct us_data *ss)
        input_dev->open = usb_onetouch_open;
        input_dev->close = usb_onetouch_close;
 
-       usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data,
-                        (maxp > 8 ? 8 : maxp),
+       usb_fill_int_urb(onetouch->irq, udev, pipe, onetouch->data, maxp,
                         usb_onetouch_irq, onetouch, endpoint->bInterval);
        onetouch->irq->transfer_dma = onetouch->data_dma;
        onetouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
index e0f76bb05915cb63647a5470c71714c61e0a52ce..b2b35b1d7de824b5724b107410098b2b7ef6b5c8 100644 (file)
@@ -50,7 +50,7 @@ static int option_rezero(struct us_data *us)
        char *buffer;
        int result;
 
-       US_DEBUGP("Option MS: %s", "DEVICE MODE SWITCH\n");
+       usb_stor_dbg(us, "Option MS: %s\n", "DEVICE MODE SWITCH");
 
        buffer = kzalloc(RESPONSE_LEN, GFP_KERNEL);
        if (buffer == NULL)
@@ -95,7 +95,7 @@ static int option_inquiry(struct us_data *us)
        char *buffer;
        int result;
 
-       US_DEBUGP("Option MS: %s", "device inquiry for vendor name\n");
+       usb_stor_dbg(us, "Option MS: %s\n", "device inquiry for vendor name");
 
        buffer = kzalloc(0x24, GFP_KERNEL);
        if (buffer == NULL)
@@ -138,31 +138,32 @@ int option_ms_init(struct us_data *us)
 {
        int result;
 
-       US_DEBUGP("Option MS: option_ms_init called\n");
+       usb_stor_dbg(us, "Option MS: %s\n", "option_ms_init called");
 
        /* Additional test for vendor information via INQUIRY,
         * because some vendor/product IDs are ambiguous
         */
        result = option_inquiry(us);
        if (result != 0) {
-               US_DEBUGP("Option MS: vendor is not Option or not determinable,"
-                         " no action taken\n");
+               usb_stor_dbg(us, "Option MS: %s\n",
+                            "vendor is not Option or not determinable, no action taken");
                return 0;
        } else
-               US_DEBUGP("Option MS: this is a genuine Option device,"
-                         " proceeding\n");
+               usb_stor_dbg(us, "Option MS: %s\n",
+                            "this is a genuine Option device, proceeding");
 
        /* Force Modem mode */
        if (option_zero_cd == ZCD_FORCE_MODEM) {
-               US_DEBUGP("Option MS: %s", "Forcing Modem Mode\n");
+               usb_stor_dbg(us, "Option MS: %s\n", "Forcing Modem Mode");
                result = option_rezero(us);
                if (result != USB_STOR_XFER_GOOD)
-                       US_DEBUGP("Option MS: Failed to switch to modem mode.\n");
+                       usb_stor_dbg(us, "Option MS: %s\n",
+                                    "Failed to switch to modem mode");
                return -EIO;
        } else if (option_zero_cd == ZCD_ALLOW_MS) {
                /* Allow Mass Storage mode (keep CD-Rom) */
-               US_DEBUGP("Option MS: %s", "Allowing Mass Storage Mode if device"
-                         " requests it\n");
+               usb_stor_dbg(us, "Option MS: %s\n",
+                            "Allowing Mass Storage Mode if device requests it");
        }
 
        return 0;
index 6c3586a4c95635780cc4adf7a8f14ed62cda6b24..4797228747fbfda5fb15d12aa589b63f2d453f1b 100644 (file)
@@ -254,8 +254,8 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun,
 
        /* check bulk status */
        if (bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN)) {
-               US_DEBUGP("Signature mismatch: got %08X, expecting %08X\n",
-                         le32_to_cpu(bcs->Signature), US_BULK_CS_SIGN);
+               usb_stor_dbg(us, "Signature mismatch: got %08X, expecting %08X\n",
+                            le32_to_cpu(bcs->Signature), US_BULK_CS_SIGN);
                return USB_STOR_TRANSPORT_ERROR;
        }
 
@@ -351,8 +351,8 @@ static int rts51x_get_max_lun(struct us_data *us)
                                      USB_RECIP_INTERFACE,
                                      0, us->ifnum, us->iobuf, 1, 10 * HZ);
 
-       US_DEBUGP("GetMaxLUN command result is %d, data is %d\n",
-                 result, us->iobuf[0]);
+       usb_stor_dbg(us, "GetMaxLUN command result is %d, data is %d\n",
+                    result, us->iobuf[0]);
 
        /* if we have a successful request, return the result */
        if (result > 0)
@@ -371,7 +371,7 @@ static int rts51x_read_mem(struct us_data *us, u16 addr, u8 *data, u16 len)
        if (buf == NULL)
                return USB_STOR_TRANSPORT_ERROR;
 
-       US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len);
+       usb_stor_dbg(us, "addr = 0x%x, len = %d\n", addr, len);
 
        cmnd[0] = 0xF0;
        cmnd[1] = 0x0D;
@@ -402,7 +402,7 @@ static int rts51x_write_mem(struct us_data *us, u16 addr, u8 *data, u16 len)
        if (buf == NULL)
                return USB_STOR_TRANSPORT_ERROR;
 
-       US_DEBUGP("%s, addr = 0x%x, len = %d\n", __func__, addr, len);
+       usb_stor_dbg(us, "addr = 0x%x, len = %d\n", addr, len);
 
        cmnd[0] = 0xF0;
        cmnd[1] = 0x0E;
@@ -431,7 +431,7 @@ static int rts51x_read_status(struct us_data *us,
        if (buf == NULL)
                return USB_STOR_TRANSPORT_ERROR;
 
-       US_DEBUGP("%s, lun = %d\n", __func__, lun);
+       usb_stor_dbg(us, "lun = %d\n", lun);
 
        cmnd[0] = 0xF0;
        cmnd[1] = 0x09;
@@ -458,7 +458,7 @@ static int rts51x_check_status(struct us_data *us, u8 lun)
        if (retval != STATUS_SUCCESS)
                return -EIO;
 
-       US_DEBUGP("chip->status_len = %d\n", chip->status_len);
+       usb_stor_dbg(us, "chip->status_len = %d\n", chip->status_len);
 
        chip->status[lun].vid = ((u16) buf[0] << 8) | buf[1];
        chip->status[lun].pid = ((u16) buf[2] << 8) | buf[3];
@@ -509,7 +509,7 @@ static int __do_config_autodelink(struct us_data *us, u8 *data, u16 len)
        u8 cmnd[12] = {0};
        u8 *buf;
 
-       US_DEBUGP("%s, addr = 0xfe47, len = %d\n", __FUNCTION__, len);
+       usb_stor_dbg(us, "addr = 0xfe47, len = %d\n", len);
 
        buf = kmemdup(data, len, GFP_NOIO);
        if (!buf)
@@ -549,7 +549,7 @@ static int do_config_autodelink(struct us_data *us, int enable, int force)
                value &= ~0x03;
        }
 
-       US_DEBUGP("In %s,set 0xfe47 to 0x%x\n", __func__, value);
+       usb_stor_dbg(us, "set 0xfe47 to 0x%x\n", value);
 
        /* retval = rts51x_write_mem(us, 0xFE47, &value, 1); */
        retval = __do_config_autodelink(us, &value, 1);
@@ -565,8 +565,6 @@ static int config_autodelink_after_power_on(struct us_data *us)
        int retval;
        u8 value;
 
-       US_DEBUGP("%s: <---\n", __func__);
-
        if (!CHK_AUTO_DELINK(chip))
                return 0;
 
@@ -624,8 +622,6 @@ static int config_autodelink_after_power_on(struct us_data *us)
                }
        }
 
-       US_DEBUGP("%s: --->\n", __func__);
-
        return 0;
 }
 
@@ -635,8 +631,6 @@ static int config_autodelink_before_power_down(struct us_data *us)
        int retval;
        u8 value;
 
-       US_DEBUGP("%s: <---\n", __func__);
-
        if (!CHK_AUTO_DELINK(chip))
                return 0;
 
@@ -698,8 +692,6 @@ static int config_autodelink_before_power_down(struct us_data *us)
                }
        }
 
-       US_DEBUGP("%s: --->\n", __func__);
-
        return 0;
 }
 
@@ -709,23 +701,19 @@ static void fw5895_init(struct us_data *us)
        int retval;
        u8 val;
 
-       US_DEBUGP("%s: <---\n", __func__);
-
        if ((PRODUCT_ID(chip) != 0x0158) || (FW_VERSION(chip) != 0x5895)) {
-               US_DEBUGP("Not the specified device, return immediately!\n");
+               usb_stor_dbg(us, "Not the specified device, return immediately!\n");
        } else {
                retval = rts51x_read_mem(us, 0xFD6F, &val, 1);
                if (retval == STATUS_SUCCESS && (val & 0x1F) == 0) {
                        val = 0x1F;
                        retval = rts51x_write_mem(us, 0xFD70, &val, 1);
                        if (retval != STATUS_SUCCESS)
-                               US_DEBUGP("Write memory fail\n");
+                               usb_stor_dbg(us, "Write memory fail\n");
                } else {
-                       US_DEBUGP("Read memory fail, OR (val & 0x1F) != 0\n");
+                       usb_stor_dbg(us, "Read memory fail, OR (val & 0x1F) != 0\n");
                }
        }
-
-       US_DEBUGP("%s: --->\n", __func__);
 }
 
 #ifdef CONFIG_REALTEK_AUTOPM
@@ -735,10 +723,8 @@ static void fw5895_set_mmc_wp(struct us_data *us)
        int retval;
        u8 buf[13];
 
-       US_DEBUGP("%s: <---\n", __func__);
-
        if ((PRODUCT_ID(chip) != 0x0158) || (FW_VERSION(chip) != 0x5895)) {
-               US_DEBUGP("Not the specified device, return immediately!\n");
+               usb_stor_dbg(us, "Not the specified device, return immediately!\n");
        } else {
                retval = rts51x_read_mem(us, 0xFD6F, buf, 1);
                if (retval == STATUS_SUCCESS && (buf[0] & 0x24) == 0x24) {
@@ -748,26 +734,24 @@ static void fw5895_set_mmc_wp(struct us_data *us)
                                buf[0] |= 0x04;
                                retval = rts51x_write_mem(us, 0xFD70, buf, 1);
                                if (retval != STATUS_SUCCESS)
-                                       US_DEBUGP("Write memory fail\n");
+                                       usb_stor_dbg(us, "Write memory fail\n");
                        } else {
-                               US_DEBUGP("Read memory fail\n");
+                               usb_stor_dbg(us, "Read memory fail\n");
                        }
                } else {
-                       US_DEBUGP("Read memory fail, OR (buf[0]&0x24)!=0x24\n");
+                       usb_stor_dbg(us, "Read memory fail, OR (buf[0]&0x24)!=0x24\n");
                }
        }
-
-       US_DEBUGP("%s: --->\n", __func__);
 }
 
 static void rts51x_modi_suspend_timer(struct rts51x_chip *chip)
 {
-       US_DEBUGP("%s: <---, state:%d\n", __func__, rts51x_get_stat(chip));
+       struct us_data *us = chip->us;
+
+       usb_stor_dbg(us, "state:%d\n", rts51x_get_stat(chip));
 
        chip->timer_expires = jiffies + msecs_to_jiffies(1000*ss_delay);
        mod_timer(&chip->rts51x_suspend_timer, chip->timer_expires);
-
-       US_DEBUGP("%s: --->\n", __func__);
 }
 
 static void rts51x_suspend_timer_fn(unsigned long data)
@@ -775,8 +759,6 @@ static void rts51x_suspend_timer_fn(unsigned long data)
        struct rts51x_chip *chip = (struct rts51x_chip *)data;
        struct us_data *us = chip->us;
 
-       US_DEBUGP("%s: <---\n", __func__);
-
        switch (rts51x_get_stat(chip)) {
        case RTS51X_STAT_INIT:
        case RTS51X_STAT_RUN:
@@ -784,32 +766,25 @@ static void rts51x_suspend_timer_fn(unsigned long data)
                break;
        case RTS51X_STAT_IDLE:
        case RTS51X_STAT_SS:
-               US_DEBUGP("%s: RTS51X_STAT_SS, intf->pm_usage_cnt:%d,"
-                       "power.usage:%d\n", __func__,
-                       atomic_read(&us->pusb_intf->pm_usage_cnt),
-                       atomic_read(&us->pusb_intf->dev.power.usage_count));
+               usb_stor_dbg(us, "RTS51X_STAT_SS, intf->pm_usage_cnt:%d, power.usage:%d\n",
+                            atomic_read(&us->pusb_intf->pm_usage_cnt),
+                            atomic_read(&us->pusb_intf->dev.power.usage_count));
 
                if (atomic_read(&us->pusb_intf->pm_usage_cnt) > 0) {
-                       US_DEBUGP("%s: Ready to enter SS state.\n",
-                                 __func__);
+                       usb_stor_dbg(us, "Ready to enter SS state\n");
                        rts51x_set_stat(chip, RTS51X_STAT_SS);
                        /* ignore mass storage interface's children */
                        pm_suspend_ignore_children(&us->pusb_intf->dev, true);
                        usb_autopm_put_interface_async(us->pusb_intf);
-                       US_DEBUGP("%s: RTS51X_STAT_SS 01,"
-                               "intf->pm_usage_cnt:%d, power.usage:%d\n",
-                               __func__,
-                               atomic_read(&us->pusb_intf->pm_usage_cnt),
-                               atomic_read(
-                                       &us->pusb_intf->dev.power.usage_count));
+                       usb_stor_dbg(us, "RTS51X_STAT_SS 01, intf->pm_usage_cnt:%d, power.usage:%d\n",
+                                    atomic_read(&us->pusb_intf->pm_usage_cnt),
+                                    atomic_read(&us->pusb_intf->dev.power.usage_count));
                }
                break;
        default:
-               US_DEBUGP("%s: Unknonwn state !!!\n", __func__);
+               usb_stor_dbg(us, "Unknown state !!!\n");
                break;
        }
-
-       US_DEBUGP("%s: --->\n", __func__);
 }
 
 static inline int working_scsi(struct scsi_cmnd *srb)
@@ -834,24 +809,21 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
        };
        int ret;
 
-       US_DEBUGP("%s: <---\n", __func__);
-
        if (working_scsi(srb)) {
-               US_DEBUGP("%s: working scsi, intf->pm_usage_cnt:%d,"
-                       "power.usage:%d\n", __func__,
-                       atomic_read(&us->pusb_intf->pm_usage_cnt),
-                       atomic_read(&us->pusb_intf->dev.power.usage_count));
+               usb_stor_dbg(us, "working scsi, intf->pm_usage_cnt:%d, power.usage:%d\n",
+                            atomic_read(&us->pusb_intf->pm_usage_cnt),
+                            atomic_read(&us->pusb_intf->dev.power.usage_count));
 
                if (atomic_read(&us->pusb_intf->pm_usage_cnt) <= 0) {
                        ret = usb_autopm_get_interface(us->pusb_intf);
-                       US_DEBUGP("%s: working scsi, ret=%d\n", __func__, ret);
+                       usb_stor_dbg(us, "working scsi, ret=%d\n", ret);
                }
                if (rts51x_get_stat(chip) != RTS51X_STAT_RUN)
                        rts51x_set_stat(chip, RTS51X_STAT_RUN);
                chip->proto_handler_backup(srb, us);
        } else {
                if (rts51x_get_stat(chip) == RTS51X_STAT_SS) {
-                       US_DEBUGP("%s: NOT working scsi\n", __func__);
+                       usb_stor_dbg(us, "NOT working scsi\n");
                        if ((srb->cmnd[0] == TEST_UNIT_READY) &&
                            (chip->pwr_state == US_SUSPEND)) {
                                if (TST_LUN_READY(chip, srb->device->lun)) {
@@ -862,8 +834,7 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
                                               media_not_present,
                                               US_SENSE_SIZE);
                                }
-                               US_DEBUGP("%s: TEST_UNIT_READY--->\n",
-                                         __func__);
+                               usb_stor_dbg(us, "TEST_UNIT_READY\n");
                                goto out;
                        }
                        if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
@@ -876,12 +847,11 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
                                } else {
                                        srb->result = SAM_STAT_GOOD;
                                }
-                               US_DEBUGP("%s: ALLOW_MEDIUM_REMOVAL--->\n",
-                                         __func__);
+                               usb_stor_dbg(us, "ALLOW_MEDIUM_REMOVAL\n");
                                goto out;
                        }
                } else {
-                       US_DEBUGP("%s: NOT working scsi, not SS\n", __func__);
+                       usb_stor_dbg(us, "NOT working scsi, not SS\n");
                        chip->proto_handler_backup(srb, us);
                        /* Check whether card is plugged in */
                        if (srb->cmnd[0] == TEST_UNIT_READY) {
@@ -901,11 +871,9 @@ static void rts51x_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
                }
        }
 out:
-       US_DEBUGP("%s: state:%d\n", __func__, rts51x_get_stat(chip));
+       usb_stor_dbg(us, "state:%d\n", rts51x_get_stat(chip));
        if (rts51x_get_stat(chip) == RTS51X_STAT_RUN)
                rts51x_modi_suspend_timer(chip);
-
-       US_DEBUGP("%s: --->\n", __func__);
 }
 
 static int realtek_cr_autosuspend_setup(struct us_data *us)
@@ -923,7 +891,7 @@ static int realtek_cr_autosuspend_setup(struct us_data *us)
 
        retval = rts51x_read_status(us, 0, buf, 16, &(chip->status_len));
        if (retval != STATUS_SUCCESS) {
-               US_DEBUGP("Read status fail\n");
+               usb_stor_dbg(us, "Read status fail\n");
                return -EIO;
        }
        status = chip->status;
@@ -966,11 +934,13 @@ static int realtek_cr_autosuspend_setup(struct us_data *us)
 static void realtek_cr_destructor(void *extra)
 {
        struct rts51x_chip *chip = (struct rts51x_chip *)extra;
-
-       US_DEBUGP("%s: <---\n", __func__);
+       struct us_data *us;
 
        if (!chip)
                return;
+
+       us = chip->us;
+
 #ifdef CONFIG_REALTEK_AUTOPM
        if (ss_en) {
                del_timer(&chip->rts51x_suspend_timer);
@@ -985,8 +955,6 @@ static int realtek_cr_suspend(struct usb_interface *iface, pm_message_t message)
 {
        struct us_data *us = usb_get_intfdata(iface);
 
-       US_DEBUGP("%s: <---\n", __func__);
-
        /* wait until no command is running */
        mutex_lock(&us->dev_mutex);
 
@@ -994,8 +962,6 @@ static int realtek_cr_suspend(struct usb_interface *iface, pm_message_t message)
 
        mutex_unlock(&us->dev_mutex);
 
-       US_DEBUGP("%s: --->\n", __func__);
-
        return 0;
 }
 
@@ -1003,13 +969,9 @@ static int realtek_cr_resume(struct usb_interface *iface)
 {
        struct us_data *us = usb_get_intfdata(iface);
 
-       US_DEBUGP("%s: <---\n", __func__);
-
        fw5895_init(us);
        config_autodelink_after_power_on(us);
 
-       US_DEBUGP("%s: --->\n", __func__);
-
        return 0;
 }
 #else
@@ -1030,7 +992,7 @@ static int init_realtek_cr(struct us_data *us)
        us->extra_destructor = realtek_cr_destructor;
        us->max_lun = chip->max_lun = rts51x_get_max_lun(us);
 
-       US_DEBUGP("chip->max_lun = %d\n", chip->max_lun);
+       usb_stor_dbg(us, "chip->max_lun = %d\n", chip->max_lun);
 
        size = (chip->max_lun + 1) * sizeof(struct rts51x_status);
        chip->status = kzalloc(size, GFP_KERNEL);
@@ -1057,7 +1019,7 @@ static int init_realtek_cr(struct us_data *us)
        }
 #endif
 
-       US_DEBUGP("chip->flag = 0x%x\n", chip->flag);
+       usb_stor_dbg(us, "chip->flag = 0x%x\n", chip->flag);
 
        (void)config_autodelink_after_power_on(us);
 
@@ -1079,7 +1041,7 @@ static int realtek_cr_probe(struct usb_interface *intf,
        struct us_data *us;
        int result;
 
-       US_DEBUGP("Probe Realtek Card Reader!\n");
+       dev_dbg(&intf->dev, "Probe Realtek Card Reader!\n");
 
        result = usb_stor_probe1(&us, intf, id,
                                 (id - realtek_cr_ids) +
index 92f35abee92d281990e17ccdb4f388d33ed67f0e..4faa982807f237c57183c68b307851629a51c376 100644 (file)
@@ -313,8 +313,6 @@ static int queuecommand_lck(struct scsi_cmnd *srb,
 {
        struct us_data *us = host_to_us(srb->device->host);
 
-       US_DEBUGP("%s called\n", __func__);
-
        /* check for state-transition errors */
        if (us->srb != NULL) {
                printk(KERN_ERR USB_STORAGE "Error in %s: us->srb = %p\n",
@@ -324,7 +322,7 @@ static int queuecommand_lck(struct scsi_cmnd *srb,
 
        /* fail the command if we are disconnecting */
        if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
-               US_DEBUGP("Fail command during disconnect\n");
+               usb_stor_dbg(us, "Fail command during disconnect\n");
                srb->result = DID_NO_CONNECT << 16;
                done(srb);
                return 0;
@@ -349,7 +347,7 @@ static int command_abort(struct scsi_cmnd *srb)
 {
        struct us_data *us = host_to_us(srb->device->host);
 
-       US_DEBUGP("%s called\n", __func__);
+       usb_stor_dbg(us, "%s called\n", __func__);
 
        /* us->srb together with the TIMED_OUT, RESETTING, and ABORTING
         * bits are protected by the host lock. */
@@ -358,7 +356,7 @@ static int command_abort(struct scsi_cmnd *srb)
        /* Is this command still active? */
        if (us->srb != srb) {
                scsi_unlock(us_to_host(us));
-               US_DEBUGP ("-- nothing to abort\n");
+               usb_stor_dbg(us, "-- nothing to abort\n");
                return FAILED;
        }
 
@@ -386,7 +384,7 @@ static int device_reset(struct scsi_cmnd *srb)
        struct us_data *us = host_to_us(srb->device->host);
        int result;
 
-       US_DEBUGP("%s called\n", __func__);
+       usb_stor_dbg(us, "%s called\n", __func__);
 
        /* lock the device pointers and do the reset */
        mutex_lock(&(us->dev_mutex));
@@ -402,7 +400,8 @@ static int bus_reset(struct scsi_cmnd *srb)
        struct us_data *us = host_to_us(srb->device->host);
        int result;
 
-       US_DEBUGP("%s called\n", __func__);
+       usb_stor_dbg(us, "%s called\n", __func__);
+
        result = usb_stor_port_reset(us);
        return result < 0 ? FAILED : SUCCESS;
 }
index 7bd54e0d5120cdaf0dba96fff1928c4380ba4631..732027f3320020ba88d6f3bc1a9c65accf717c39 100644 (file)
@@ -105,8 +105,6 @@ static struct us_unusual_dev sddr09_unusual_dev_list[] = {
 #define LSB_of(s) ((s)&0xFF)
 #define MSB_of(s) ((s)>>8)
 
-/* #define US_DEBUGP printk */
-
 /*
  * First some stuff that does not belong here:
  * data on SmartMedia and other cards, completely
@@ -347,7 +345,7 @@ sddr09_test_unit_ready(struct us_data *us) {
 
        result = sddr09_send_scsi_command(us, command, 6);
 
-       US_DEBUGP("sddr09_test_unit_ready returns %d\n", result);
+       usb_stor_dbg(us, "sddr09_test_unit_ready returns %d\n", result);
 
        return result;
 }
@@ -423,8 +421,8 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress,
        result = sddr09_send_scsi_command(us, command, 12);
 
        if (result) {
-               US_DEBUGP("Result for send_control in sddr09_read2%d %d\n",
-                         x, result);
+               usb_stor_dbg(us, "Result for send_control in sddr09_read2%d %d\n",
+                            x, result);
                return result;
        }
 
@@ -432,8 +430,8 @@ sddr09_readX(struct us_data *us, int x, unsigned long fromaddress,
                                       buf, bulklen, use_sg, NULL);
 
        if (result != USB_STOR_XFER_GOOD) {
-               US_DEBUGP("Result for bulk_transfer in sddr09_read2%d %d\n",
-                         x, result);
+               usb_stor_dbg(us, "Result for bulk_transfer in sddr09_read2%d %d\n",
+                            x, result);
                return -EIO;
        }
        return 0;
@@ -494,8 +492,7 @@ sddr09_read22(struct us_data *us, unsigned long fromaddress,
              int nr_of_pages, int pageshift, unsigned char *buf, int use_sg) {
 
        int bulklen = (nr_of_pages << pageshift) + (nr_of_pages << CONTROL_SHIFT);
-       US_DEBUGP("sddr09_read22: reading %d pages, %d bytes\n",
-                 nr_of_pages, bulklen);
+       usb_stor_dbg(us, "reading %d pages, %d bytes\n", nr_of_pages, bulklen);
        return sddr09_readX(us, 2, fromaddress, nr_of_pages, bulklen,
                            buf, use_sg);
 }
@@ -538,7 +535,7 @@ sddr09_erase(struct us_data *us, unsigned long Eaddress) {
        unsigned char *command = us->iobuf;
        int result;
 
-       US_DEBUGP("sddr09_erase: erase address %lu\n", Eaddress);
+       usb_stor_dbg(us, "erase address %lu\n", Eaddress);
 
        memset(command, 0, 12);
        command[0] = 0xEA;
@@ -551,8 +548,8 @@ sddr09_erase(struct us_data *us, unsigned long Eaddress) {
        result = sddr09_send_scsi_command(us, command, 12);
 
        if (result)
-               US_DEBUGP("Result for send_control in sddr09_erase %d\n",
-                         result);
+               usb_stor_dbg(us, "Result for send_control in sddr09_erase %d\n",
+                            result);
 
        return result;
 }
@@ -609,8 +606,8 @@ sddr09_writeX(struct us_data *us,
        result = sddr09_send_scsi_command(us, command, 12);
 
        if (result) {
-               US_DEBUGP("Result for send_control in sddr09_writeX %d\n",
-                         result);
+               usb_stor_dbg(us, "Result for send_control in sddr09_writeX %d\n",
+                            result);
                return result;
        }
 
@@ -618,8 +615,8 @@ sddr09_writeX(struct us_data *us,
                                       buf, bulklen, use_sg, NULL);
 
        if (result != USB_STOR_XFER_GOOD) {
-               US_DEBUGP("Result for bulk_transfer in sddr09_writeX %d\n",
-                         result);
+               usb_stor_dbg(us, "Result for bulk_transfer in sddr09_writeX %d\n",
+                            result);
                return -EIO;
        }
        return 0;
@@ -687,8 +684,8 @@ sddr09_read_sg_test_only(struct us_data *us) {
        result = sddr09_send_scsi_command(us, command, 4*nsg+3);
 
        if (result) {
-               US_DEBUGP("Result for send_control in sddr09_read_sg %d\n",
-                         result);
+               usb_stor_dbg(us, "Result for send_control in sddr09_read_sg %d\n",
+                            result);
                return result;
        }
 
@@ -700,8 +697,8 @@ sddr09_read_sg_test_only(struct us_data *us) {
                                       buf, bulklen, NULL);
        kfree(buf);
        if (result != USB_STOR_XFER_GOOD) {
-               US_DEBUGP("Result for bulk_transfer in sddr09_read_sg %d\n",
-                         result);
+               usb_stor_dbg(us, "Result for bulk_transfer in sddr09_read_sg %d\n",
+                            result);
                return -EIO;
        }
 
@@ -727,7 +724,7 @@ sddr09_read_status(struct us_data *us, unsigned char *status) {
        unsigned char *data = us->iobuf;
        int result;
 
-       US_DEBUGP("Reading status...\n");
+       usb_stor_dbg(us, "Reading status...\n");
 
        memset(command, 0, 12);
        command[0] = 0xEC;
@@ -789,8 +786,8 @@ sddr09_read_data(struct us_data *us,
 
                /* Not overflowing capacity? */
                if (lba >= maxlba) {
-                       US_DEBUGP("Error: Requested lba %u exceeds "
-                                 "maximum %u\n", lba, maxlba);
+                       usb_stor_dbg(us, "Error: Requested lba %u exceeds maximum %u\n",
+                                    lba, maxlba);
                        result = -EIO;
                        break;
                }
@@ -800,8 +797,8 @@ sddr09_read_data(struct us_data *us,
 
                if (pba == UNDEF) {     /* this lba was never written */
 
-                       US_DEBUGP("Read %d zero pages (LBA %d) page %d\n",
-                                 pages, lba, page);
+                       usb_stor_dbg(us, "Read %d zero pages (LBA %d) page %d\n",
+                                    pages, lba, page);
 
                        /* This is not really an error. It just means
                           that the block has never been written.
@@ -811,9 +808,8 @@ sddr09_read_data(struct us_data *us,
                        memset(buffer, 0, len);
 
                } else {
-                       US_DEBUGP("Read %d pages, from PBA %d"
-                                 " (LBA %d) page %d\n",
-                                 pages, pba, lba, page);
+                       usb_stor_dbg(us, "Read %d pages, from PBA %d (LBA %d) page %d\n",
+                                    pages, pba, lba, page);
 
                        address = ((pba << info->blockshift) + page) << 
                                info->pageshift;
@@ -916,14 +912,14 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,
                cptr = bptr + info->pagesize;
                nand_compute_ecc(bptr, ecc);
                if (!nand_compare_ecc(cptr+13, ecc)) {
-                       US_DEBUGP("Warning: bad ecc in page %d- of pba %d\n",
-                                 i, pba);
+                       usb_stor_dbg(us, "Warning: bad ecc in page %d- of pba %d\n",
+                                    i, pba);
                        nand_store_ecc(cptr+13, ecc);
                }
                nand_compute_ecc(bptr+(info->pagesize / 2), ecc);
                if (!nand_compare_ecc(cptr+8, ecc)) {
-                       US_DEBUGP("Warning: bad ecc in page %d+ of pba %d\n",
-                                 i, pba);
+                       usb_stor_dbg(us, "Warning: bad ecc in page %d+ of pba %d\n",
+                                    i, pba);
                        nand_store_ecc(cptr+8, ecc);
                }
                cptr[6] = cptr[11] = MSB_of(lbap);
@@ -943,22 +939,21 @@ sddr09_write_lba(struct us_data *us, unsigned int lba,
                nand_store_ecc(cptr+8, ecc);
        }
 
-       US_DEBUGP("Rewrite PBA %d (LBA %d)\n", pba, lba);
+       usb_stor_dbg(us, "Rewrite PBA %d (LBA %d)\n", pba, lba);
 
        result = sddr09_write_inplace(us, address>>1, info->blocksize,
                                      info->pageshift, blockbuffer, 0);
 
-       US_DEBUGP("sddr09_write_inplace returns %d\n", result);
+       usb_stor_dbg(us, "sddr09_write_inplace returns %d\n", result);
 
 #if 0
        {
                unsigned char status = 0;
                int result2 = sddr09_read_status(us, &status);
                if (result2)
-                       US_DEBUGP("sddr09_write_inplace: cannot read status\n");
+                       usb_stor_dbg(us, "cannot read status\n");
                else if (status != 0xc0)
-                       US_DEBUGP("sddr09_write_inplace: status after write: 0x%x\n",
-                                 status);
+                       usb_stor_dbg(us, "status after write: 0x%x\n", status);
        }
 #endif
 
@@ -1031,8 +1026,8 @@ sddr09_write_data(struct us_data *us,
 
                /* Not overflowing capacity? */
                if (lba >= maxlba) {
-                       US_DEBUGP("Error: Requested lba %u exceeds "
-                                 "maximum %u\n", lba, maxlba);
+                       usb_stor_dbg(us, "Error: Requested lba %u exceeds maximum %u\n",
+                                    lba, maxlba);
                        result = -EIO;
                        break;
                }
@@ -1064,8 +1059,8 @@ sddr09_read_control(struct us_data *us,
                unsigned char *content,
                int use_sg) {
 
-       US_DEBUGP("Read control address %lu, blocks %d\n",
-               address, blocks);
+       usb_stor_dbg(us, "Read control address %lu, blocks %d\n",
+                    address, blocks);
 
        return sddr09_read21(us, address, blocks,
                             CONTROL_SHIFT, content, use_sg);
@@ -1111,21 +1106,21 @@ sddr09_get_wp(struct us_data *us, struct sddr09_card_info *info) {
 
        result = sddr09_read_status(us, &status);
        if (result) {
-               US_DEBUGP("sddr09_get_wp: read_status fails\n");
+               usb_stor_dbg(us, "read_status fails\n");
                return result;
        }
-       US_DEBUGP("sddr09_get_wp: status 0x%02X", status);
+       usb_stor_dbg(us, "status 0x%02X", status);
        if ((status & 0x80) == 0) {
                info->flags |= SDDR09_WP;       /* write protected */
-               US_DEBUGP(" WP");
+               US_DEBUGPX(" WP");
        }
        if (status & 0x40)
-               US_DEBUGP(" Ready");
+               US_DEBUGPX(" Ready");
        if (status & LUNBITS)
-               US_DEBUGP(" Suspended");
+               US_DEBUGPX(" Suspended");
        if (status & 0x1)
-               US_DEBUGP(" Error");
-       US_DEBUGP("\n");
+               US_DEBUGPX(" Error");
+       US_DEBUGPX("\n");
        return 0;
 }
 
@@ -1154,12 +1149,12 @@ sddr09_get_cardinfo(struct us_data *us, unsigned char flags) {
        char blurbtxt[256];
        int result;
 
-       US_DEBUGP("Reading capacity...\n");
+       usb_stor_dbg(us, "Reading capacity...\n");
 
        result = sddr09_read_deviceID(us, deviceID);
 
        if (result) {
-               US_DEBUGP("Result of read_deviceID is %d\n", result);
+               usb_stor_dbg(us, "Result of read_deviceID is %d\n", result);
                printk(KERN_WARNING "sddr09: could not read card info\n");
                return NULL;
        }
@@ -1392,7 +1387,7 @@ sddr09_read_map(struct us_data *us) {
                lbact += ct;
        }
        info->lbact = lbact;
-       US_DEBUGP("Found %d LBA's\n", lbact);
+       usb_stor_dbg(us, "Found %d LBA's\n", lbact);
        result = 0;
 
  done:
@@ -1423,18 +1418,18 @@ sddr09_common_init(struct us_data *us) {
 
        /* set the configuration -- STALL is an acceptable response here */
        if (us->pusb_dev->actconfig->desc.bConfigurationValue != 1) {
-               US_DEBUGP("active config #%d != 1 ??\n", us->pusb_dev
-                               ->actconfig->desc.bConfigurationValue);
+               usb_stor_dbg(us, "active config #%d != 1 ??\n",
+                            us->pusb_dev->actconfig->desc.bConfigurationValue);
                return -EINVAL;
        }
 
        result = usb_reset_configuration(us->pusb_dev);
-       US_DEBUGP("Result of usb_reset_configuration is %d\n", result);
+       usb_stor_dbg(us, "Result of usb_reset_configuration is %d\n", result);
        if (result == -EPIPE) {
-               US_DEBUGP("-- stall on control interface\n");
+               usb_stor_dbg(us, "-- stall on control interface\n");
        } else if (result != 0) {
                /* it's not a stall, but another error -- time to bail */
-               US_DEBUGP("-- Unknown error.  Rejecting device\n");
+               usb_stor_dbg(us, "-- Unknown error.  Rejecting device\n");
                return -EINVAL;
        }
 
@@ -1464,20 +1459,20 @@ usb_stor_sddr09_dpcm_init(struct us_data *us) {
 
        result = sddr09_send_command(us, 0x01, USB_DIR_IN, data, 2);
        if (result) {
-               US_DEBUGP("sddr09_init: send_command fails\n");
+               usb_stor_dbg(us, "send_command fails\n");
                return result;
        }
 
-       US_DEBUGP("SDDR09init: %02X %02X\n", data[0], data[1]);
+       usb_stor_dbg(us, "%02X %02X\n", data[0], data[1]);
        // get 07 02
 
        result = sddr09_send_command(us, 0x08, USB_DIR_IN, data, 2);
        if (result) {
-               US_DEBUGP("sddr09_init: 2nd send_command fails\n");
+               usb_stor_dbg(us, "2nd send_command fails\n");
                return result;
        }
 
-       US_DEBUGP("SDDR09init: %02X %02X\n", data[0], data[1]);
+       usb_stor_dbg(us, "%02X %02X\n", data[0], data[1]);
        // get 07 00
 
        result = sddr09_request_sense(us, data, 18);
@@ -1507,7 +1502,7 @@ static int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
        int ret;
 
-       US_DEBUGP("dpcm_transport: LUN=%d\n", srb->device->lun);
+       usb_stor_dbg(us, "LUN=%d\n", srb->device->lun);
 
        switch (srb->device->lun) {
        case 0:
@@ -1533,8 +1528,7 @@ static int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us)
                break;
 
        default:
-               US_DEBUGP("dpcm_transport: Invalid LUN %d\n",
-                               srb->device->lun);
+               usb_stor_dbg(us, "Invalid LUN %d\n", srb->device->lun);
                ret = USB_STOR_TRANSPORT_ERROR;
                break;
        }
@@ -1640,8 +1634,8 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
                   or for all pages. */
                /* %% We should check DBD %% */
                if (modepage == 0x01 || modepage == 0x3F) {
-                       US_DEBUGP("SDDR09: Dummy up request for "
-                                 "mode page 0x%x\n", modepage);
+                       usb_stor_dbg(us, "Dummy up request for mode page 0x%x\n",
+                                    modepage);
 
                        memcpy(ptr, mode_page_01, sizeof(mode_page_01));
                        ((__be16*)ptr)[0] = cpu_to_be16(sizeof(mode_page_01) - 2);
@@ -1667,8 +1661,8 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
                page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
                pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
 
-               US_DEBUGP("READ_10: read page %d pagect %d\n",
-                         page, pages);
+               usb_stor_dbg(us, "READ_10: read page %d pagect %d\n",
+                            page, pages);
 
                result = sddr09_read_data(us, page, pages);
                return (result == 0 ? USB_STOR_TRANSPORT_GOOD :
@@ -1682,8 +1676,8 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
                page |= short_pack(srb->cmnd[5], srb->cmnd[4]);
                pages = short_pack(srb->cmnd[8], srb->cmnd[7]);
 
-               US_DEBUGP("WRITE_10: write page %d pagect %d\n",
-                         page, pages);
+               usb_stor_dbg(us, "WRITE_10: write page %d pagect %d\n",
+                            page, pages);
 
                result = sddr09_write_data(us, page, pages);
                return (result == 0 ? USB_STOR_TRANSPORT_GOOD :
@@ -1710,12 +1704,12 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
        for (i=0; i<12; i++)
                sprintf(ptr+strlen(ptr), "%02X ", srb->cmnd[i]);
 
-       US_DEBUGP("SDDR09: Send control for command %s\n", ptr);
+       usb_stor_dbg(us, "Send control for command %s\n", ptr);
 
        result = sddr09_send_scsi_command(us, srb->cmnd, 12);
        if (result) {
-               US_DEBUGP("sddr09_transport: sddr09_send_scsi_command "
-                         "returns %d\n", result);
+               usb_stor_dbg(us, "sddr09_send_scsi_command returns %d\n",
+                            result);
                return USB_STOR_TRANSPORT_ERROR;
        }
 
@@ -1727,10 +1721,10 @@ static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us)
                unsigned int pipe = (srb->sc_data_direction == DMA_TO_DEVICE)
                                ? us->send_bulk_pipe : us->recv_bulk_pipe;
 
-               US_DEBUGP("SDDR09: %s %d bytes\n",
-                         (srb->sc_data_direction == DMA_TO_DEVICE) ?
-                         "sending" : "receiving",
-                         scsi_bufflen(srb));
+               usb_stor_dbg(us, "%s %d bytes\n",
+                            (srb->sc_data_direction == DMA_TO_DEVICE) ?
+                            "sending" : "receiving",
+                            scsi_bufflen(srb));
 
                result = usb_stor_bulk_srb(us, pipe, srb);
 
index d278c5a99b7a253a49ba6b2d09ba2abac88bd5e4..aacedef9667cebcf0ef1992a5f05a0d600d0c9ff 100644 (file)
@@ -145,8 +145,7 @@ static int sddr55_status(struct us_data *us)
        result = sddr55_bulk_transport(us,
                DMA_TO_DEVICE, command, 8);
 
-       US_DEBUGP("Result for send_command in status %d\n",
-               result);
+       usb_stor_dbg(us, "Result for send_command in status %d\n", result);
 
        if (result != USB_STOR_XFER_GOOD) {
                set_sense_info (4, 0, 0);       /* hardware error */
@@ -236,9 +235,8 @@ static int sddr55_read_data(struct us_data *us,
                                info->blocksize - page);
                len = pages << info->pageshift;
 
-               US_DEBUGP("Read %02X pages, from PBA %04X"
-                       " (LBA %04X) page %02X\n",
-                       pages, pba, lba, page);
+               usb_stor_dbg(us, "Read %02X pages, from PBA %04X (LBA %04X) page %02X\n",
+                            pages, pba, lba, page);
 
                if (pba == NOT_ALLOCATED) {
                        /* no pba for this lba, fill with zeroes */
@@ -261,8 +259,8 @@ static int sddr55_read_data(struct us_data *us,
                        result = sddr55_bulk_transport(us,
                                DMA_TO_DEVICE, command, 8);
 
-                       US_DEBUGP("Result for send_command in read_data %d\n",
-                               result);
+                       usb_stor_dbg(us, "Result for send_command in read_data %d\n",
+                                    result);
 
                        if (result != USB_STOR_XFER_GOOD) {
                                result = USB_STOR_TRANSPORT_ERROR;
@@ -368,9 +366,8 @@ static int sddr55_write_data(struct us_data *us,
                usb_stor_access_xfer_buf(buffer, len, us->srb,
                                &sg, &offset, FROM_XFER_BUF);
 
-               US_DEBUGP("Write %02X pages, to PBA %04X"
-                       " (LBA %04X) page %02X\n",
-                       pages, pba, lba, page);
+               usb_stor_dbg(us, "Write %02X pages, to PBA %04X (LBA %04X) page %02X\n",
+                            pages, pba, lba, page);
                        
                command[4] = 0;
 
@@ -384,7 +381,7 @@ static int sddr55_write_data(struct us_data *us,
                        /* set pba to first block in zone lba is in */
                        pba = (lba / 1000) * 1024;
 
-                       US_DEBUGP("No PBA for LBA %04X\n",lba);
+                       usb_stor_dbg(us, "No PBA for LBA %04X\n", lba);
 
                        if (max_pba > 1024)
                                max_pba = 1024;
@@ -407,14 +404,15 @@ static int sddr55_write_data(struct us_data *us,
 
                        if (pba == -1) {
                                /* oh dear */
-                               US_DEBUGP("Couldn't find unallocated block\n");
+                               usb_stor_dbg(us, "Couldn't find unallocated block\n");
 
                                set_sense_info (3, 0x31, 0);    /* medium error */
                                result = USB_STOR_TRANSPORT_FAILED;
                                goto leave;
                        }
 
-                       US_DEBUGP("Allocating PBA %04X for LBA %04X\n", pba, lba);
+                       usb_stor_dbg(us, "Allocating PBA %04X for LBA %04X\n",
+                                    pba, lba);
 
                        /* set writing to unallocated block flag */
                        command[4] = 0x40;
@@ -439,8 +437,8 @@ static int sddr55_write_data(struct us_data *us,
                        DMA_TO_DEVICE, command, 8);
 
                if (result != USB_STOR_XFER_GOOD) {
-                       US_DEBUGP("Result for send_command in write_data %d\n",
-                       result);
+                       usb_stor_dbg(us, "Result for send_command in write_data %d\n",
+                                    result);
 
                        /* set_sense_info is superfluous here? */
                        set_sense_info (3, 0x3, 0);/* peripheral write error */
@@ -453,8 +451,8 @@ static int sddr55_write_data(struct us_data *us,
                        DMA_TO_DEVICE, buffer, len);
 
                if (result != USB_STOR_XFER_GOOD) {
-                       US_DEBUGP("Result for send_data in write_data %d\n",
-                                 result);
+                       usb_stor_dbg(us, "Result for send_data in write_data %d\n",
+                                    result);
 
                        /* set_sense_info is superfluous here? */
                        set_sense_info (3, 0x3, 0);/* peripheral write error */
@@ -466,8 +464,8 @@ static int sddr55_write_data(struct us_data *us,
                result = sddr55_bulk_transport(us, DMA_FROM_DEVICE, status, 6);
 
                if (result != USB_STOR_XFER_GOOD) {
-                       US_DEBUGP("Result for get_status in write_data %d\n",
-                                 result);
+                       usb_stor_dbg(us, "Result for get_status in write_data %d\n",
+                                    result);
 
                        /* set_sense_info is superfluous here? */
                        set_sense_info (3, 0x3, 0);/* peripheral write error */
@@ -487,8 +485,8 @@ static int sddr55_write_data(struct us_data *us,
                        goto leave;
                }
 
-               US_DEBUGP("Updating maps for LBA %04X: old PBA %04X, new PBA %04X\n",
-                       lba, pba, new_pba);
+               usb_stor_dbg(us, "Updating maps for LBA %04X: old PBA %04X, new PBA %04X\n",
+                            lba, pba, new_pba);
 
                /* update the lba<->pba maps, note new_pba might be the same as pba */
                info->lba_to_pba[lba] = new_pba;
@@ -531,8 +529,8 @@ static int sddr55_read_deviceID(struct us_data *us,
        command[7] = 0x84;
        result = sddr55_bulk_transport(us, DMA_TO_DEVICE, command, 8);
 
-       US_DEBUGP("Result of send_control for device ID is %d\n",
-               result);
+       usb_stor_dbg(us, "Result of send_control for device ID is %d\n",
+                    result);
 
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
@@ -568,20 +566,19 @@ static unsigned long sddr55_get_capacity(struct us_data *us) {
        int result;
        struct sddr55_card_info *info = (struct sddr55_card_info *)us->extra;
 
-       US_DEBUGP("Reading capacity...\n");
+       usb_stor_dbg(us, "Reading capacity...\n");
 
        result = sddr55_read_deviceID(us,
                &manufacturerID,
                &deviceID);
 
-       US_DEBUGP("Result of read_deviceID is %d\n",
-               result);
+       usb_stor_dbg(us, "Result of read_deviceID is %d\n", result);
 
        if (result != USB_STOR_XFER_GOOD)
                return 0;
 
-       US_DEBUGP("Device ID = %02X\n", deviceID);
-       US_DEBUGP("Manuf  ID = %02X\n", manufacturerID);
+       usb_stor_dbg(us, "Device ID = %02X\n", deviceID);
+       usb_stor_dbg(us, "Manuf  ID = %02X\n", manufacturerID);
 
        info->pageshift = 9;
        info->smallpageshift = 0;
@@ -753,7 +750,7 @@ static int sddr55_read_map(struct us_data *us) {
                }
 
                if (lba<0x10 || (lba>=0x3E0 && lba<0x3EF))
-                       US_DEBUGP("LBA %04X <-> PBA %04X\n", lba, i);
+                       usb_stor_dbg(us, "LBA %04X <-> PBA %04X\n", lba, i);
 
                info->lba_to_pba[lba + zone * 1000] = i;
        }
@@ -808,7 +805,10 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
        info = (struct sddr55_card_info *)(us->extra);
 
        if (srb->cmnd[0] == REQUEST_SENSE) {
-               US_DEBUGP("SDDR55: request sense %02x/%02x/%02x\n", info->sense_data[2], info->sense_data[12], info->sense_data[13]);
+               usb_stor_dbg(us, "request sense %02x/%02x/%02x\n",
+                            info->sense_data[2],
+                            info->sense_data[12],
+                            info->sense_data[13]);
 
                memcpy (ptr, info->sense_data, sizeof info->sense_data);
                ptr[0] = 0x70;
@@ -892,13 +892,11 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
                usb_stor_set_xfer_buf(ptr, sizeof(mode_page_01), srb);
 
                if ( (srb->cmnd[2] & 0x3F) == 0x01 ) {
-                       US_DEBUGP(
-                         "SDDR55: Dummy up request for mode page 1\n");
+                       usb_stor_dbg(us, "Dummy up request for mode page 1\n");
                        return USB_STOR_TRANSPORT_GOOD;
 
                } else if ( (srb->cmnd[2] & 0x3F) == 0x3F ) {
-                       US_DEBUGP(
-                         "SDDR55: Dummy up request for all mode pages\n");
+                       usb_stor_dbg(us, "Dummy up request for all mode pages\n");
                        return USB_STOR_TRANSPORT_GOOD;
                }
 
@@ -908,10 +906,8 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
 
        if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
 
-               US_DEBUGP(
-                 "SDDR55: %s medium removal. Not that I can do"
-                 " anything about it...\n",
-                 (srb->cmnd[4]&0x03) ? "Prevent" : "Allow");
+               usb_stor_dbg(us, "%s medium removal. Not that I can do anything about it...\n",
+                            (srb->cmnd[4]&0x03) ? "Prevent" : "Allow");
 
                return USB_STOR_TRANSPORT_GOOD;
 
@@ -935,8 +931,8 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
 
                if (lba >= info->max_log_blks) {
 
-                       US_DEBUGP("Error: Requested LBA %04X exceeds maximum "
-                         "block %04X\n", lba, info->max_log_blks-1);
+                       usb_stor_dbg(us, "Error: Requested LBA %04X exceeds maximum block %04X\n",
+                                    lba, info->max_log_blks - 1);
 
                        set_sense_info (5, 0x24, 0);    /* invalid field in command */
 
@@ -946,15 +942,13 @@ static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us)
                pba = info->lba_to_pba[lba];
 
                if (srb->cmnd[0] == WRITE_10) {
-                       US_DEBUGP("WRITE_10: write block %04X (LBA %04X) page %01X"
-                               " pages %d\n",
-                               pba, lba, page, pages);
+                       usb_stor_dbg(us, "WRITE_10: write block %04X (LBA %04X) page %01X pages %d\n",
+                                    pba, lba, page, pages);
 
                        return sddr55_write_data(us, lba, page, pages);
                } else {
-                       US_DEBUGP("READ_10: read block %04X (LBA %04X) page %01X"
-                               " pages %d\n",
-                               pba, lba, page, pages);
+                       usb_stor_dbg(us, "READ_10: read block %04X (LBA %04X) page %01X pages %d\n",
+                                    pba, lba, page, pages);
 
                        return sddr55_read_data(us, lba, page, pages);
                }
index daf2fc58ae0203857b5b198327d7f9a917214c98..4ef2a80728f74521d103dc8d33b1fed8735b1947 100644 (file)
@@ -271,7 +271,7 @@ static int usbat_bulk_read(struct us_data *us,
        if (len == 0)
                return USB_STOR_XFER_GOOD;
 
-       US_DEBUGP("usbat_bulk_read: len = %d\n", len);
+       usb_stor_dbg(us, "len = %d\n", len);
        return usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe, buf, len, use_sg, NULL);
 }
 
@@ -286,7 +286,7 @@ static int usbat_bulk_write(struct us_data *us,
        if (len == 0)
                return USB_STOR_XFER_GOOD;
 
-       US_DEBUGP("usbat_bulk_write:  len = %d\n", len);
+       usb_stor_dbg(us, "len = %d\n", len);
        return usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe, buf, len, use_sg, NULL);
 }
 
@@ -312,7 +312,7 @@ static int usbat_get_status(struct us_data *us, unsigned char *status)
        int rc;
        rc = usbat_read(us, USBAT_ATA, USBAT_ATA_STATUS, status);
 
-       US_DEBUGP("usbat_get_status: 0x%02X\n", (unsigned short) (*status));
+       usb_stor_dbg(us, "0x%02X\n", *status);
        return rc;
 }
 
@@ -425,7 +425,7 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes)
                        return USB_STOR_TRANSPORT_FAILED;
 
                if ((*status & 0x80)==0x00) { /* not busy */
-                       US_DEBUGP("Waited not busy for %d steps\n", i);
+                       usb_stor_dbg(us, "Waited not busy for %d steps\n", i);
                        return USB_STOR_TRANSPORT_GOOD;
                }
 
@@ -439,8 +439,8 @@ static int usbat_wait_not_busy(struct us_data *us, int minutes)
                        msleep(1000); /* X minutes */
        }
 
-       US_DEBUGP("Waited not busy for %d minutes, timing out.\n",
-               minutes);
+       usb_stor_dbg(us, "Waited not busy for %d minutes, timing out\n",
+                    minutes);
        return USB_STOR_TRANSPORT_FAILED;
 }
 
@@ -657,8 +657,9 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us,
                        if (*status & 0x20) /* device fault */
                                return USB_STOR_TRANSPORT_FAILED;
 
-                       US_DEBUGP("Redoing %s\n",
-                         direction==DMA_TO_DEVICE ? "write" : "read");
+                       usb_stor_dbg(us, "Redoing %s\n",
+                                    direction == DMA_TO_DEVICE
+                                    ? "write" : "read");
 
                } else if (result != USB_STOR_XFER_GOOD)
                        return USB_STOR_TRANSPORT_ERROR;
@@ -667,8 +668,8 @@ static int usbat_hp8200e_rw_block_test(struct us_data *us,
 
        }
 
-       US_DEBUGP("Bummer! %s bulk data 20 times failed.\n",
-               direction==DMA_TO_DEVICE ? "Writing" : "Reading");
+       usb_stor_dbg(us, "Bummer! %s bulk data 20 times failed\n",
+                    direction == DMA_TO_DEVICE ? "Writing" : "Reading");
 
        return USB_STOR_TRANSPORT_FAILED;
 }
@@ -827,7 +828,7 @@ static int usbat_read_user_io(struct us_data *us, unsigned char *data_flags)
                data_flags,
                USBAT_UIO_READ);
 
-       US_DEBUGP("usbat_read_user_io: UIO register reads %02X\n", (unsigned short) (*data_flags));
+       usb_stor_dbg(us, "UIO register reads %02X\n", *data_flags);
 
        return result;
 }
@@ -900,10 +901,11 @@ static int usbat_device_enable_cdt(struct us_data *us)
 /*
  * Determine if media is present.
  */
-static int usbat_flash_check_media_present(unsigned char *uio)
+static int usbat_flash_check_media_present(struct us_data *us,
+                                          unsigned char *uio)
 {
        if (*uio & USBAT_UIO_UI0) {
-               US_DEBUGP("usbat_flash_check_media_present: no media detected\n");
+               usb_stor_dbg(us, "no media detected\n");
                return USBAT_FLASH_MEDIA_NONE;
        }
 
@@ -913,10 +915,11 @@ static int usbat_flash_check_media_present(unsigned char *uio)
 /*
  * Determine if media has changed since last operation
  */
-static int usbat_flash_check_media_changed(unsigned char *uio)
+static int usbat_flash_check_media_changed(struct us_data *us,
+                                          unsigned char *uio)
 {
        if (*uio & USBAT_UIO_0) {
-               US_DEBUGP("usbat_flash_check_media_changed: media change detected\n");
+               usb_stor_dbg(us, "media change detected\n");
                return USBAT_FLASH_MEDIA_CHANGED;
        }
 
@@ -937,7 +940,7 @@ static int usbat_flash_check_media(struct us_data *us,
                return USB_STOR_TRANSPORT_ERROR;
 
        /* Check for media existence */
-       rc = usbat_flash_check_media_present(uio);
+       rc = usbat_flash_check_media_present(us, uio);
        if (rc == USBAT_FLASH_MEDIA_NONE) {
                info->sense_key = 0x02;
                info->sense_asc = 0x3A;
@@ -946,7 +949,7 @@ static int usbat_flash_check_media(struct us_data *us,
        }
 
        /* Check for media change */
-       rc = usbat_flash_check_media_changed(uio);
+       rc = usbat_flash_check_media_changed(us, uio);
        if (rc == USBAT_FLASH_MEDIA_CHANGED) {
 
                /* Reset and re-enable card detect */
@@ -1008,11 +1011,11 @@ static int usbat_identify_device(struct us_data *us,
        /* Check for error bit, or if the command 'fell through' */
        if (status == 0xA1 || !(status & 0x01)) {
                /* Device is HP 8200 */
-               US_DEBUGP("usbat_identify_device: Detected HP8200 CDRW\n");
+               usb_stor_dbg(us, "Detected HP8200 CDRW\n");
                info->devicetype = USBAT_DEV_HP8200;
        } else {
                /* Device is a CompactFlash reader/writer */
-               US_DEBUGP("usbat_identify_device: Detected Flash reader/writer\n");
+               usb_stor_dbg(us, "Detected Flash reader/writer\n");
                info->devicetype = USBAT_DEV_FLASH;
        }
 
@@ -1075,7 +1078,7 @@ static int usbat_flash_get_sector_count(struct us_data *us,
        /* ATA command : IDENTIFY DEVICE */
        rc = usbat_multiple_write(us, registers, command, 3);
        if (rc != USB_STOR_XFER_GOOD) {
-               US_DEBUGP("usbat_flash_get_sector_count: Gah! identify_device failed\n");
+               usb_stor_dbg(us, "Gah! identify_device failed\n");
                rc = USB_STOR_TRANSPORT_ERROR;
                goto leave;
        }
@@ -1178,7 +1181,7 @@ static int usbat_flash_read_data(struct us_data *us,
                if (result != USB_STOR_TRANSPORT_GOOD)
                        goto leave;
         
-               US_DEBUGP("usbat_flash_read_data:  %d bytes\n", len);
+               usb_stor_dbg(us, "%d bytes\n", len);
        
                /* Store the data in the transfer buffer */
                usb_stor_access_xfer_buf(buffer, len, us->srb,
@@ -1301,8 +1304,7 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,
        unsigned int sg_offset = 0;
        struct scatterlist *sg = NULL;
 
-       US_DEBUGP("handle_read10: transfersize %d\n",
-               srb->transfersize);
+       usb_stor_dbg(us, "transfersize %d\n", srb->transfersize);
 
        if (scsi_bufflen(srb) < 0x10000) {
 
@@ -1329,14 +1331,14 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,
                len = short_pack(data[7+9], data[7+8]);
                len <<= 16;
                len |= data[7+7];
-               US_DEBUGP("handle_read10: GPCMD_READ_CD: len %d\n", len);
+               usb_stor_dbg(us, "GPCMD_READ_CD: len %d\n", len);
                srb->transfersize = scsi_bufflen(srb)/len;
        }
 
        if (!srb->transfersize)  {
                srb->transfersize = 2048; /* A guess */
-               US_DEBUGP("handle_read10: transfersize 0, forcing %d\n",
-                       srb->transfersize);
+               usb_stor_dbg(us, "transfersize 0, forcing %d\n",
+                            srb->transfersize);
        }
 
        /*
@@ -1346,7 +1348,7 @@ static int usbat_hp8200e_handle_read10(struct us_data *us,
         */
 
        len = (65535/srb->transfersize) * srb->transfersize;
-       US_DEBUGP("Max read is %d bytes\n", len);
+       usb_stor_dbg(us, "Max read is %d bytes\n", len);
        len = min(len, scsi_bufflen(srb));
        buffer = kmalloc(len, GFP_NOIO);
        if (buffer == NULL) /* bloody hell! */
@@ -1460,10 +1462,9 @@ static int init_usbat(struct us_data *us, int devicetype)
        unsigned char *status = us->iobuf;
 
        us->extra = kzalloc(sizeof(struct usbat_info), GFP_NOIO);
-       if (!us->extra) {
-               US_DEBUGP("init_usbat: Gah! Can't allocate storage for usbat info struct!\n");
+       if (!us->extra)
                return 1;
-       }
+
        info = (struct usbat_info *) (us->extra);
 
        /* Enable peripheral control signals */
@@ -1473,7 +1474,7 @@ static int init_usbat(struct us_data *us, int devicetype)
        if (rc != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
-       US_DEBUGP("INIT 1\n");
+       usb_stor_dbg(us, "INIT 1\n");
 
        msleep(2000);
 
@@ -1481,7 +1482,7 @@ static int init_usbat(struct us_data *us, int devicetype)
        if (rc != USB_STOR_TRANSPORT_GOOD)
                return rc;
 
-       US_DEBUGP("INIT 2\n");
+       usb_stor_dbg(us, "INIT 2\n");
 
        rc = usbat_read_user_io(us, status);
        if (rc != USB_STOR_XFER_GOOD)
@@ -1491,32 +1492,32 @@ static int init_usbat(struct us_data *us, int devicetype)
        if (rc != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
-       US_DEBUGP("INIT 3\n");
+       usb_stor_dbg(us, "INIT 3\n");
 
        rc = usbat_select_and_test_registers(us);
        if (rc != USB_STOR_TRANSPORT_GOOD)
                return rc;
 
-       US_DEBUGP("INIT 4\n");
+       usb_stor_dbg(us, "INIT 4\n");
 
        rc = usbat_read_user_io(us, status);
        if (rc != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
-       US_DEBUGP("INIT 5\n");
+       usb_stor_dbg(us, "INIT 5\n");
 
        /* Enable peripheral control signals and card detect */
        rc = usbat_device_enable_cdt(us);
        if (rc != USB_STOR_TRANSPORT_GOOD)
                return rc;
 
-       US_DEBUGP("INIT 6\n");
+       usb_stor_dbg(us, "INIT 6\n");
 
        rc = usbat_read_user_io(us, status);
        if (rc != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
-       US_DEBUGP("INIT 7\n");
+       usb_stor_dbg(us, "INIT 7\n");
 
        msleep(1400);
 
@@ -1524,19 +1525,19 @@ static int init_usbat(struct us_data *us, int devicetype)
        if (rc != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
-       US_DEBUGP("INIT 8\n");
+       usb_stor_dbg(us, "INIT 8\n");
 
        rc = usbat_select_and_test_registers(us);
        if (rc != USB_STOR_TRANSPORT_GOOD)
                return rc;
 
-       US_DEBUGP("INIT 9\n");
+       usb_stor_dbg(us, "INIT 9\n");
 
        /* At this point, we need to detect which device we are using */
        if (usbat_set_transport(us, info, devicetype))
                return USB_STOR_TRANSPORT_ERROR;
 
-       US_DEBUGP("INIT 10\n");
+       usb_stor_dbg(us, "INIT 10\n");
 
        if (usbat_get_device_type(us) == USBAT_DEV_FLASH) { 
                subcountH = 0x02;
@@ -1547,7 +1548,7 @@ static int init_usbat(struct us_data *us, int devicetype)
        if (rc != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
-       US_DEBUGP("INIT 11\n");
+       usb_stor_dbg(us, "INIT 11\n");
 
        return USB_STOR_TRANSPORT_GOOD;
 }
@@ -1592,7 +1593,7 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
        }
 
        result = usbat_get_status(us, status);
-       US_DEBUGP("Status = %02X\n", *status);
+       usb_stor_dbg(us, "Status = %02X\n", *status);
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
        if (srb->cmnd[0] == TEST_UNIT_READY)
@@ -1610,7 +1611,7 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
 
                if (result == USB_STOR_TRANSPORT_GOOD) {
                        transferred += len;
-                       US_DEBUGP("Wrote %08X bytes\n", transferred);
+                       usb_stor_dbg(us, "Wrote %08X bytes\n", transferred);
                }
 
                return result;
@@ -1623,8 +1624,8 @@ static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
        }
 
        if (len > 0xFFFF) {
-               US_DEBUGP("Error: len = %08X... what do I do now?\n",
-                       len);
+               usb_stor_dbg(us, "Error: len = %08X... what do I do now?\n",
+                            len);
                return USB_STOR_TRANSPORT_ERROR;
        }
 
@@ -1693,7 +1694,7 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
        };
 
        if (srb->cmnd[0] == INQUIRY) {
-               US_DEBUGP("usbat_flash_transport: INQUIRY. Returning bogus response.\n");
+               usb_stor_dbg(us, "INQUIRY - Returning bogus response\n");
                memcpy(ptr, inquiry_response, sizeof(inquiry_response));
                fill_inquiry_response(us, ptr, 36);
                return USB_STOR_TRANSPORT_GOOD;
@@ -1710,8 +1711,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
 
                /* hard coded 512 byte sectors as per ATA spec */
                info->ssize = 0x200;
-               US_DEBUGP("usbat_flash_transport: READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
-                         info->sectors, info->ssize);
+               usb_stor_dbg(us, "READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
+                            info->sectors, info->ssize);
 
                /*
                 * build the reply
@@ -1726,7 +1727,7 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
        }
 
        if (srb->cmnd[0] == MODE_SELECT_10) {
-               US_DEBUGP("usbat_flash_transport:  Gah! MODE_SELECT_10.\n");
+               usb_stor_dbg(us, "Gah! MODE_SELECT_10\n");
                return USB_STOR_TRANSPORT_ERROR;
        }
 
@@ -1736,7 +1737,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
 
                blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
 
-               US_DEBUGP("usbat_flash_transport:  READ_10: read block 0x%04lx  count %ld\n", block, blocks);
+               usb_stor_dbg(us, "READ_10: read block 0x%04lx  count %ld\n",
+                            block, blocks);
                return usbat_flash_read_data(us, info, block, blocks);
        }
 
@@ -1750,7 +1752,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
                blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
                         ((u32)(srb->cmnd[8]) <<  8) | ((u32)(srb->cmnd[9]));
 
-               US_DEBUGP("usbat_flash_transport: READ_12: read block 0x%04lx  count %ld\n", block, blocks);
+               usb_stor_dbg(us, "READ_12: read block 0x%04lx  count %ld\n",
+                            block, blocks);
                return usbat_flash_read_data(us, info, block, blocks);
        }
 
@@ -1760,7 +1763,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
 
                blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
 
-               US_DEBUGP("usbat_flash_transport: WRITE_10: write block 0x%04lx  count %ld\n", block, blocks);
+               usb_stor_dbg(us, "WRITE_10: write block 0x%04lx  count %ld\n",
+                            block, blocks);
                return usbat_flash_write_data(us, info, block, blocks);
        }
 
@@ -1774,13 +1778,14 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
                blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
                         ((u32)(srb->cmnd[8]) <<  8) | ((u32)(srb->cmnd[9]));
 
-               US_DEBUGP("usbat_flash_transport: WRITE_12: write block 0x%04lx  count %ld\n", block, blocks);
+               usb_stor_dbg(us, "WRITE_12: write block 0x%04lx  count %ld\n",
+                            block, blocks);
                return usbat_flash_write_data(us, info, block, blocks);
        }
 
 
        if (srb->cmnd[0] == TEST_UNIT_READY) {
-               US_DEBUGP("usbat_flash_transport: TEST_UNIT_READY.\n");
+               usb_stor_dbg(us, "TEST_UNIT_READY\n");
 
                rc = usbat_flash_check_media(us, info);
                if (rc != USB_STOR_TRANSPORT_GOOD)
@@ -1790,7 +1795,7 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
        }
 
        if (srb->cmnd[0] == REQUEST_SENSE) {
-               US_DEBUGP("usbat_flash_transport: REQUEST_SENSE.\n");
+               usb_stor_dbg(us, "REQUEST_SENSE\n");
 
                memset(ptr, 0, 18);
                ptr[0] = 0xF0;
@@ -1811,8 +1816,8 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
                return USB_STOR_TRANSPORT_GOOD;
        }
 
-       US_DEBUGP("usbat_flash_transport: Gah! Unknown command: %d (0x%x)\n",
-                         srb->cmnd[0], srb->cmnd[0]);
+       usb_stor_dbg(us, "Gah! Unknown command: %d (0x%x)\n",
+                    srb->cmnd[0], srb->cmnd[0]);
        info->sense_key = 0x05;
        info->sense_asc = 0x20;
        info->sense_ascq = 0x00;
index 17e36952bcedc076dad8d6f7765e869fea5c53e0..2ea657be14c80e33a8d9303ce2043472b8ae33d5 100644 (file)
@@ -47,7 +47,7 @@ static bool containsFullLinuxPackage(struct swoc_info *swocInfo)
 static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSWocMode)
 {
        int result;
-       US_DEBUGP("SWIMS: %s", "DEVICE MODE SWITCH\n");
+       dev_dbg(&udev->dev, "SWIMS: %s", "DEVICE MODE SWITCH\n");
        result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                        SWIMS_USB_REQUEST_SetSwocMode,  /* __u8 request      */
                        USB_TYPE_VENDOR | USB_DIR_OUT,  /* __u8 request type */
@@ -65,7 +65,7 @@ static int sierra_get_swoc_info(struct usb_device *udev,
 {
        int result;
 
-       US_DEBUGP("SWIMS: Attempting to get TRU-Install info.\n");
+       dev_dbg(&udev->dev, "SWIMS: Attempting to get TRU-Install info\n");
 
        result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
                        SWIMS_USB_REQUEST_GetSwocInfo,  /* __u8 request      */
@@ -81,11 +81,11 @@ static int sierra_get_swoc_info(struct usb_device *udev,
        return result;
 }
 
-static void debug_swoc(struct swoc_info *swocInfo)
+static void debug_swoc(const struct device *dev, struct swoc_info *swocInfo)
 {
-       US_DEBUGP("SWIMS: SWoC Rev: %02d \n", swocInfo->rev);
-       US_DEBUGP("SWIMS: Linux SKU: %04X \n", swocInfo->LinuxSKU);
-       US_DEBUGP("SWIMS: Linux Version: %04X \n", swocInfo->LinuxVer);
+       dev_dbg(dev, "SWIMS: SWoC Rev: %02d\n", swocInfo->rev);
+       dev_dbg(dev, "SWIMS: Linux SKU: %04X\n", swocInfo->LinuxSKU);
+       dev_dbg(dev, "SWIMS: Linux Version: %04X\n", swocInfo->LinuxVer);
 }
 
 
@@ -101,18 +101,17 @@ static ssize_t show_truinst(struct device *dev, struct device_attribute *attr,
        } else {
                swocInfo = kmalloc(sizeof(struct swoc_info), GFP_KERNEL);
                if (!swocInfo) {
-                       US_DEBUGP("SWIMS: Allocation failure\n");
                        snprintf(buf, PAGE_SIZE, "Error\n");
                        return -ENOMEM;
                }
                result = sierra_get_swoc_info(udev, swocInfo);
                if (result < 0) {
-                       US_DEBUGP("SWIMS: failed SWoC query\n");
+                       dev_dbg(dev, "SWIMS: failed SWoC query\n");
                        kfree(swocInfo);
                        snprintf(buf, PAGE_SIZE, "Error\n");
                        return -EIO;
                }
-               debug_swoc(swocInfo);
+               debug_swoc(dev, swocInfo);
                result = snprintf(buf, PAGE_SIZE,
                        "REV=%02d SKU=%04X VER=%04X\n",
                        swocInfo->rev,
@@ -138,61 +137,55 @@ int sierra_ms_init(struct us_data *us)
        sh = us_to_host(us);
        scsi_get_host_dev(sh);
 
-       US_DEBUGP("SWIMS: sierra_ms_init called\n");
-
        /* Force Modem mode */
        if (swi_tru_install == TRU_FORCE_MODEM) {
-               US_DEBUGP("SWIMS: %s", "Forcing Modem Mode\n");
+               usb_stor_dbg(us, "SWIMS: Forcing Modem Mode\n");
                result = sierra_set_ms_mode(udev, SWIMS_SET_MODE_Modem);
                if (result < 0)
-                       US_DEBUGP("SWIMS: Failed to switch to modem mode.\n");
+                       usb_stor_dbg(us, "SWIMS: Failed to switch to modem mode\n");
                return -EIO;
        }
        /* Force Mass Storage mode (keep CD-Rom) */
        else if (swi_tru_install == TRU_FORCE_MS) {
-               US_DEBUGP("SWIMS: %s", "Forcing Mass Storage Mode\n");
+               usb_stor_dbg(us, "SWIMS: Forcing Mass Storage Mode\n");
                goto complete;
        }
        /* Normal TRU-Install Logic */
        else {
-               US_DEBUGP("SWIMS: %s", "Normal SWoC Logic\n");
+               usb_stor_dbg(us, "SWIMS: Normal SWoC Logic\n");
 
                swocInfo = kmalloc(sizeof(struct swoc_info),
                                GFP_KERNEL);
-               if (!swocInfo) {
-                       US_DEBUGP("SWIMS: %s", "Allocation failure\n");
+               if (!swocInfo)
                        return -ENOMEM;
-               }
 
                retries = 3;
                do {
                        retries--;
                        result = sierra_get_swoc_info(udev, swocInfo);
                        if (result < 0) {
-                               US_DEBUGP("SWIMS: %s", "Failed SWoC query\n");
+                               usb_stor_dbg(us, "SWIMS: Failed SWoC query\n");
                                schedule_timeout_uninterruptible(2*HZ);
                        }
                } while (retries && result < 0);
 
                if (result < 0) {
-                       US_DEBUGP("SWIMS: %s",
-                                 "Completely failed SWoC query\n");
+                       usb_stor_dbg(us, "SWIMS: Completely failed SWoC query\n");
                        kfree(swocInfo);
                        return -EIO;
                }
 
-               debug_swoc(swocInfo);
+               debug_swoc(&us->pusb_dev->dev, swocInfo);
 
                /* If there is not Linux software on the TRU-Install device
                 * then switch to modem mode
                 */
                if (!containsFullLinuxPackage(swocInfo)) {
-                       US_DEBUGP("SWIMS: %s",
-                               "Switching to Modem Mode\n");
+                       usb_stor_dbg(us, "SWIMS: Switching to Modem Mode\n");
                        result = sierra_set_ms_mode(udev,
                                SWIMS_SET_MODE_Modem);
                        if (result < 0)
-                               US_DEBUGP("SWIMS: Failed to switch modem\n");
+                               usb_stor_dbg(us, "SWIMS: Failed to switch modem\n");
                        kfree(swocInfo);
                        return -EIO;
                }
index c0543c83923e30fab82b82698471d200ec1be47d..22c7d4360fa222722369b6861da34bafdd4b5b96 100644 (file)
@@ -166,7 +166,7 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
 
                /* cancel the URB, if it hasn't been cancelled already */
                if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
-                       US_DEBUGP("-- cancelling URB\n");
+                       usb_stor_dbg(us, "-- cancelling URB\n");
                        usb_unlink_urb(us->current_urb);
                }
        }
@@ -178,8 +178,8 @@ static int usb_stor_msg_common(struct us_data *us, int timeout)
        clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags);
 
        if (timeleft <= 0) {
-               US_DEBUGP("%s -- cancelling URB\n",
-                         timeleft == 0 ? "Timeout" : "Signal");
+               usb_stor_dbg(us, "%s -- cancelling URB\n",
+                            timeleft == 0 ? "Timeout" : "Signal");
                usb_kill_urb(us->current_urb);
        }
 
@@ -197,9 +197,8 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
 {
        int status;
 
-       US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
-                       __func__, request, requesttype,
-                       value, index, size);
+       usb_stor_dbg(us, "rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
+                    request, requesttype, value, index, size);
 
        /* fill in the devrequest structure */
        us->cr->bRequestType = requesttype;
@@ -249,7 +248,7 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
        if (result >= 0)
                usb_reset_endpoint(us->pusb_dev, endp);
 
-       US_DEBUGP("%s: result = %d\n", __func__, result);
+       usb_stor_dbg(us, "result = %d\n", result);
        return result;
 }
 EXPORT_SYMBOL_GPL(usb_stor_clear_halt);
@@ -265,18 +264,18 @@ EXPORT_SYMBOL_GPL(usb_stor_clear_halt);
 static int interpret_urb_result(struct us_data *us, unsigned int pipe,
                unsigned int length, int result, unsigned int partial)
 {
-       US_DEBUGP("Status code %d; transferred %u/%u\n",
-                       result, partial, length);
+       usb_stor_dbg(us, "Status code %d; transferred %u/%u\n",
+                    result, partial, length);
        switch (result) {
 
        /* no error code; did we send all the data? */
        case 0:
                if (partial != length) {
-                       US_DEBUGP("-- short transfer\n");
+                       usb_stor_dbg(us, "-- short transfer\n");
                        return USB_STOR_XFER_SHORT;
                }
 
-               US_DEBUGP("-- transfer complete\n");
+               usb_stor_dbg(us, "-- transfer complete\n");
                return USB_STOR_XFER_GOOD;
 
        /* stalled */
@@ -284,39 +283,40 @@ static int interpret_urb_result(struct us_data *us, unsigned int pipe,
                /* for control endpoints, (used by CB[I]) a stall indicates
                 * a failed command */
                if (usb_pipecontrol(pipe)) {
-                       US_DEBUGP("-- stall on control pipe\n");
+                       usb_stor_dbg(us, "-- stall on control pipe\n");
                        return USB_STOR_XFER_STALLED;
                }
 
                /* for other sorts of endpoint, clear the stall */
-               US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
+               usb_stor_dbg(us, "clearing endpoint halt for pipe 0x%x\n",
+                            pipe);
                if (usb_stor_clear_halt(us, pipe) < 0)
                        return USB_STOR_XFER_ERROR;
                return USB_STOR_XFER_STALLED;
 
        /* babble - the device tried to send more than we wanted to read */
        case -EOVERFLOW:
-               US_DEBUGP("-- babble\n");
+               usb_stor_dbg(us, "-- babble\n");
                return USB_STOR_XFER_LONG;
 
        /* the transfer was cancelled by abort, disconnect, or timeout */
        case -ECONNRESET:
-               US_DEBUGP("-- transfer cancelled\n");
+               usb_stor_dbg(us, "-- transfer cancelled\n");
                return USB_STOR_XFER_ERROR;
 
        /* short scatter-gather read transfer */
        case -EREMOTEIO:
-               US_DEBUGP("-- short read transfer\n");
+               usb_stor_dbg(us, "-- short read transfer\n");
                return USB_STOR_XFER_SHORT;
 
        /* abort or disconnect in progress */
        case -EIO:
-               US_DEBUGP("-- abort or disconnect in progress\n");
+               usb_stor_dbg(us, "-- abort or disconnect in progress\n");
                return USB_STOR_XFER_ERROR;
 
        /* the catch-all error case */
        default:
-               US_DEBUGP("-- unknown error\n");
+               usb_stor_dbg(us, "-- unknown error\n");
                return USB_STOR_XFER_ERROR;
        }
 }
@@ -331,9 +331,8 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
 {
        int result;
 
-       US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
-                       __func__, request, requesttype,
-                       value, index, size);
+       usb_stor_dbg(us, "rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
+                    request, requesttype, value, index, size);
 
        /* fill in the devrequest structure */
        us->cr->bRequestType = requesttype;
@@ -367,7 +366,7 @@ static int usb_stor_intr_transfer(struct us_data *us, void *buf,
        unsigned int pipe = us->recv_intr_pipe;
        unsigned int maxp;
 
-       US_DEBUGP("%s: xfer %u bytes\n", __func__, length);
+       usb_stor_dbg(us, "xfer %u bytes\n", length);
 
        /* calculate the max packet size */
        maxp = usb_maxpacket(us->pusb_dev, pipe, usb_pipeout(pipe));
@@ -394,7 +393,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
 {
        int result;
 
-       US_DEBUGP("%s: xfer %u bytes\n", __func__, length);
+       usb_stor_dbg(us, "xfer %u bytes\n", length);
 
        /* fill and submit the URB */
        usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, buf, length,
@@ -426,12 +425,11 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
                return USB_STOR_XFER_ERROR;
 
        /* initialize the scatter-gather request block */
-       US_DEBUGP("%s: xfer %u bytes, %d entries\n", __func__,
-                       length, num_sg);
+       usb_stor_dbg(us, "xfer %u bytes, %d entries\n", length, num_sg);
        result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0,
                        sg, num_sg, length, GFP_NOIO);
        if (result) {
-               US_DEBUGP("usb_sg_init returned %d\n", result);
+               usb_stor_dbg(us, "usb_sg_init returned %d\n", result);
                return USB_STOR_XFER_ERROR;
        }
 
@@ -444,7 +442,7 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
 
                /* cancel the request, if it hasn't been cancelled already */
                if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
-                       US_DEBUGP("-- cancelling sg request\n");
+                       usb_stor_dbg(us, "-- cancelling sg request\n");
                        usb_sg_cancel(&us->current_sg);
                }
        }
@@ -609,14 +607,14 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
         * short-circuit all other processing
         */
        if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
-               US_DEBUGP("-- command was aborted\n");
+               usb_stor_dbg(us, "-- command was aborted\n");
                srb->result = DID_ABORT << 16;
                goto Handle_Errors;
        }
 
        /* if there is a transport error, reset and don't auto-sense */
        if (result == USB_STOR_TRANSPORT_ERROR) {
-               US_DEBUGP("-- transport indicates error, resetting\n");
+               usb_stor_dbg(us, "-- transport indicates error, resetting\n");
                srb->result = DID_ERROR << 16;
                goto Handle_Errors;
        }
@@ -645,7 +643,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
         */
        if ((us->protocol == USB_PR_CB || us->protocol == USB_PR_DPCM_USB) &&
                        srb->sc_data_direction != DMA_FROM_DEVICE) {
-               US_DEBUGP("-- CB transport device requiring auto-sense\n");
+               usb_stor_dbg(us, "-- CB transport device requiring auto-sense\n");
                need_auto_sense = 1;
        }
 
@@ -655,7 +653,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
         * "failure" and an "error" in the transport mechanism.
         */
        if (result == USB_STOR_TRANSPORT_FAILED) {
-               US_DEBUGP("-- transport indicates command failure\n");
+               usb_stor_dbg(us, "-- transport indicates command failure\n");
                need_auto_sense = 1;
        }
 
@@ -670,7 +668,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
            !(us->fflags & US_FL_SANE_SENSE) &&
            !(us->fflags & US_FL_BAD_SENSE) &&
            !(srb->cmnd[2] & 0x20))) {
-               US_DEBUGP("-- SAT supported, increasing auto-sense\n");
+               usb_stor_dbg(us, "-- SAT supported, increasing auto-sense\n");
                us->fflags |= US_FL_SANE_SENSE;
        }
 
@@ -684,7 +682,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
              (srb->cmnd[0] == MODE_SENSE) ||
              (srb->cmnd[0] == LOG_SENSE) ||
              (srb->cmnd[0] == MODE_SENSE_10))) {
-               US_DEBUGP("-- unexpectedly short transfer\n");
+               usb_stor_dbg(us, "-- unexpectedly short transfer\n");
        }
 
        /* Now, if we need to do the auto-sense, let's do it */
@@ -700,7 +698,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
                if (us->fflags & US_FL_SANE_SENSE)
                        sense_size = ~0;
 Retry_Sense:
-               US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
+               usb_stor_dbg(us, "Issuing auto-REQUEST_SENSE\n");
 
                scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sense_size);
 
@@ -719,7 +717,7 @@ Retry_Sense:
                scsi_eh_restore_cmnd(srb, &ses);
 
                if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
-                       US_DEBUGP("-- auto-sense aborted\n");
+                       usb_stor_dbg(us, "-- auto-sense aborted\n");
                        srb->result = DID_ABORT << 16;
 
                        /* If SANE_SENSE caused this problem, disable it */
@@ -737,7 +735,7 @@ Retry_Sense:
                 */
                if (temp_result == USB_STOR_TRANSPORT_FAILED &&
                                sense_size != US_SENSE_SIZE) {
-                       US_DEBUGP("-- auto-sense failure, retry small sense\n");
+                       usb_stor_dbg(us, "-- auto-sense failure, retry small sense\n");
                        sense_size = US_SENSE_SIZE;
                        us->fflags &= ~US_FL_SANE_SENSE;
                        us->fflags |= US_FL_BAD_SENSE;
@@ -746,7 +744,7 @@ Retry_Sense:
 
                /* Other failures */
                if (temp_result != USB_STOR_TRANSPORT_GOOD) {
-                       US_DEBUGP("-- auto-sense failure\n");
+                       usb_stor_dbg(us, "-- auto-sense failure\n");
 
                        /* we skip the reset if this happens to be a
                         * multi-target device, since failure of an
@@ -766,27 +764,28 @@ Retry_Sense:
                    !(us->fflags & US_FL_SANE_SENSE) &&
                    !(us->fflags & US_FL_BAD_SENSE) &&
                    (srb->sense_buffer[0] & 0x7C) == 0x70) {
-                       US_DEBUGP("-- SANE_SENSE support enabled\n");
+                       usb_stor_dbg(us, "-- SANE_SENSE support enabled\n");
                        us->fflags |= US_FL_SANE_SENSE;
 
                        /* Indicate to the user that we truncated their sense
                         * because we didn't know it supported larger sense.
                         */
-                       US_DEBUGP("-- Sense data truncated to %i from %i\n",
-                                 US_SENSE_SIZE,
-                                 srb->sense_buffer[7] + 8);
+                       usb_stor_dbg(us, "-- Sense data truncated to %i from %i\n",
+                                    US_SENSE_SIZE,
+                                    srb->sense_buffer[7] + 8);
                        srb->sense_buffer[7] = (US_SENSE_SIZE - 8);
                }
 
                scsi_normalize_sense(srb->sense_buffer, SCSI_SENSE_BUFFERSIZE,
                                     &sshdr);
 
-               US_DEBUGP("-- Result from auto-sense is %d\n", temp_result);
-               US_DEBUGP("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",
-                         sshdr.response_code, sshdr.sense_key,
-                         sshdr.asc, sshdr.ascq);
+               usb_stor_dbg(us, "-- Result from auto-sense is %d\n",
+                            temp_result);
+               usb_stor_dbg(us, "-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",
+                            sshdr.response_code, sshdr.sense_key,
+                            sshdr.asc, sshdr.ascq);
 #ifdef CONFIG_USB_STORAGE_DEBUG
-               usb_stor_show_sense(sshdr.sense_key, sshdr.asc, sshdr.ascq);
+               usb_stor_show_sense(us, sshdr.sense_key, sshdr.asc, sshdr.ascq);
 #endif
 
                /* set the result so the higher layers expect this data */
@@ -892,20 +891,18 @@ Retry_Sense:
 /* Stop the current URB transfer */
 void usb_stor_stop_transport(struct us_data *us)
 {
-       US_DEBUGP("%s called\n", __func__);
-
        /* If the state machine is blocked waiting for an URB,
         * let's wake it up.  The test_and_clear_bit() call
         * guarantees that if a URB has just been submitted,
         * it won't be cancelled more than once. */
        if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->dflags)) {
-               US_DEBUGP("-- cancelling URB\n");
+               usb_stor_dbg(us, "-- cancelling URB\n");
                usb_unlink_urb(us->current_urb);
        }
 
        /* If we are waiting for a scatter-gather operation, cancel it. */
        if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->dflags)) {
-               US_DEBUGP("-- cancelling sg request\n");
+               usb_stor_dbg(us, "-- cancelling sg request\n");
                usb_sg_cancel(&us->current_sg);
        }
 }
@@ -928,7 +925,8 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
                                      us->ifnum, srb->cmnd, srb->cmd_len);
 
        /* check the return code for the command */
-       US_DEBUGP("Call to usb_stor_ctrl_transfer() returned %d\n", result);
+       usb_stor_dbg(us, "Call to usb_stor_ctrl_transfer() returned %d\n",
+                    result);
 
        /* if we stalled the command, it means command failed */
        if (result == USB_STOR_XFER_STALLED) {
@@ -946,7 +944,7 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
                pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
                                us->recv_bulk_pipe : us->send_bulk_pipe;
                result = usb_stor_bulk_srb(us, pipe, srb);
-               US_DEBUGP("CBI data stage result is 0x%x\n", result);
+               usb_stor_dbg(us, "CBI data stage result is 0x%x\n", result);
 
                /* if we stalled the data transfer it means command failed */
                if (result == USB_STOR_XFER_STALLED)
@@ -964,8 +962,8 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
                return USB_STOR_TRANSPORT_GOOD;
 
        result = usb_stor_intr_transfer(us, us->iobuf, 2);
-       US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", 
-                       us->iobuf[0], us->iobuf[1]);
+       usb_stor_dbg(us, "Got interrupt data (0x%x, 0x%x)\n",
+                    us->iobuf[0], us->iobuf[1]);
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
@@ -992,8 +990,8 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us)
         * into the first byte -- so if it's non-zero, call it a failure.
         */
        if (us->iobuf[0]) {
-               US_DEBUGP("CBI IRQ data showed reserved bType 0x%x\n",
-                               us->iobuf[0]);
+               usb_stor_dbg(us, "CBI IRQ data showed reserved bType 0x%x\n",
+                            us->iobuf[0]);
                goto Failed;
 
        }
@@ -1034,8 +1032,8 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
                                 USB_RECIP_INTERFACE,
                                 0, us->ifnum, us->iobuf, 1, 10*HZ);
 
-       US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", 
-                 result, us->iobuf[0]);
+       usb_stor_dbg(us, "GetMaxLUN command result is %d, data is %d\n",
+                    result, us->iobuf[0]);
 
        /* if we have a successful request, return the result */
        if (result > 0)
@@ -1084,14 +1082,14 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
        memcpy(bcb->CDB, srb->cmnd, bcb->Length);
 
        /* send it to out endpoint */
-       US_DEBUGP("Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n",
-                       le32_to_cpu(bcb->Signature), bcb->Tag,
-                       le32_to_cpu(bcb->DataTransferLength), bcb->Flags,
-                       (bcb->Lun >> 4), (bcb->Lun & 0x0F), 
-                       bcb->Length);
+       usb_stor_dbg(us, "Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n",
+                    le32_to_cpu(bcb->Signature), bcb->Tag,
+                    le32_to_cpu(bcb->DataTransferLength), bcb->Flags,
+                    (bcb->Lun >> 4), (bcb->Lun & 0x0F),
+                    bcb->Length);
        result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
                                bcb, cbwlen, NULL);
-       US_DEBUGP("Bulk command transfer result=%d\n", result);
+       usb_stor_dbg(us, "Bulk command transfer result=%d\n", result);
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
@@ -1108,7 +1106,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
                unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ? 
                                us->recv_bulk_pipe : us->send_bulk_pipe;
                result = usb_stor_bulk_srb(us, pipe, srb);
-               US_DEBUGP("Bulk data transfer result 0x%x\n", result);
+               usb_stor_dbg(us, "Bulk data transfer result 0x%x\n", result);
                if (result == USB_STOR_XFER_ERROR)
                        return USB_STOR_TRANSPORT_ERROR;
 
@@ -1127,7 +1125,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
         */
 
        /* get CSW for device status */
-       US_DEBUGP("Attempting to get CSW...\n");
+       usb_stor_dbg(us, "Attempting to get CSW...\n");
        result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
                                bcs, US_BULK_CS_WRAP_LEN, &cswlen);
 
@@ -1136,7 +1134,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
         * CSWs.  If we encounter such a thing, try to read the CSW again.
         */
        if (result == USB_STOR_XFER_SHORT && cswlen == 0) {
-               US_DEBUGP("Received 0-length CSW; retrying...\n");
+               usb_stor_dbg(us, "Received 0-length CSW; retrying...\n");
                result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
                                bcs, US_BULK_CS_WRAP_LEN, &cswlen);
        }
@@ -1145,24 +1143,24 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
        if (result == USB_STOR_XFER_STALLED) {
 
                /* get the status again */
-               US_DEBUGP("Attempting to get CSW (2nd try)...\n");
+               usb_stor_dbg(us, "Attempting to get CSW (2nd try)...\n");
                result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
                                bcs, US_BULK_CS_WRAP_LEN, NULL);
        }
 
        /* if we still have a failure at this point, we're in trouble */
-       US_DEBUGP("Bulk status result = %d\n", result);
+       usb_stor_dbg(us, "Bulk status result = %d\n", result);
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
        /* check bulk status */
        residue = le32_to_cpu(bcs->Residue);
-       US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
-                       le32_to_cpu(bcs->Signature), bcs->Tag, 
-                       residue, bcs->Status);
+       usb_stor_dbg(us, "Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
+                    le32_to_cpu(bcs->Signature), bcs->Tag,
+                    residue, bcs->Status);
        if (!(bcs->Tag == us->tag || (us->fflags & US_FL_BULK_IGNORE_TAG)) ||
                bcs->Status > US_BULK_STAT_PHASE) {
-               US_DEBUGP("Bulk logical error\n");
+               usb_stor_dbg(us, "Bulk logical error\n");
                return USB_STOR_TRANSPORT_ERROR;
        }
 
@@ -1173,12 +1171,12 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
        if (!us->bcs_signature) {
                us->bcs_signature = bcs->Signature;
                if (us->bcs_signature != cpu_to_le32(US_BULK_CS_SIGN))
-                       US_DEBUGP("Learnt BCS signature 0x%08X\n",
-                                       le32_to_cpu(us->bcs_signature));
+                       usb_stor_dbg(us, "Learnt BCS signature 0x%08X\n",
+                                    le32_to_cpu(us->bcs_signature));
        } else if (bcs->Signature != us->bcs_signature) {
-               US_DEBUGP("Signature mismatch: got %08X, expecting %08X\n",
-                         le32_to_cpu(bcs->Signature),
-                         le32_to_cpu(us->bcs_signature));
+               usb_stor_dbg(us, "Signature mismatch: got %08X, expecting %08X\n",
+                            le32_to_cpu(bcs->Signature),
+                            le32_to_cpu(us->bcs_signature));
                return USB_STOR_TRANSPORT_ERROR;
        }
 
@@ -1255,7 +1253,7 @@ static int usb_stor_reset_common(struct us_data *us,
        int result2;
 
        if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
-               US_DEBUGP("No reset during disconnect\n");
+               usb_stor_dbg(us, "No reset during disconnect\n");
                return -EIO;
        }
 
@@ -1263,7 +1261,7 @@ static int usb_stor_reset_common(struct us_data *us,
                        request, requesttype, value, index, data, size,
                        5*HZ);
        if (result < 0) {
-               US_DEBUGP("Soft reset failed: %d\n", result);
+               usb_stor_dbg(us, "Soft reset failed: %d\n", result);
                return result;
        }
 
@@ -1273,23 +1271,23 @@ static int usb_stor_reset_common(struct us_data *us,
                        test_bit(US_FLIDX_DISCONNECTING, &us->dflags),
                        HZ*6);
        if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
-               US_DEBUGP("Reset interrupted by disconnect\n");
+               usb_stor_dbg(us, "Reset interrupted by disconnect\n");
                return -EIO;
        }
 
-       US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n");
+       usb_stor_dbg(us, "Soft reset: clearing bulk-in endpoint halt\n");
        result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
 
-       US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n");
+       usb_stor_dbg(us, "Soft reset: clearing bulk-out endpoint halt\n");
        result2 = usb_stor_clear_halt(us, us->send_bulk_pipe);
 
        /* return a result code based on the result of the clear-halts */
        if (result >= 0)
                result = result2;
        if (result < 0)
-               US_DEBUGP("Soft reset failed\n");
+               usb_stor_dbg(us, "Soft reset failed\n");
        else
-               US_DEBUGP("Soft reset done\n");
+               usb_stor_dbg(us, "Soft reset done\n");
        return result;
 }
 
@@ -1299,8 +1297,6 @@ static int usb_stor_reset_common(struct us_data *us,
 
 int usb_stor_CB_reset(struct us_data *us)
 {
-       US_DEBUGP("%s called\n", __func__);
-
        memset(us->iobuf, 0xFF, CB_RESET_CMD_SIZE);
        us->iobuf[0] = SEND_DIAGNOSTIC;
        us->iobuf[1] = 4;
@@ -1315,8 +1311,6 @@ EXPORT_SYMBOL_GPL(usb_stor_CB_reset);
  */
 int usb_stor_Bulk_reset(struct us_data *us)
 {
-       US_DEBUGP("%s called\n", __func__);
-
        return usb_stor_reset_common(us, US_BULK_RESET_REQUEST, 
                                 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
                                 0, us->ifnum, NULL, 0);
@@ -1336,16 +1330,17 @@ int usb_stor_port_reset(struct us_data *us)
 
        result = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf);
        if (result < 0)
-               US_DEBUGP("unable to lock device for reset: %d\n", result);
+               usb_stor_dbg(us, "unable to lock device for reset: %d\n",
+                            result);
        else {
                /* Were we disconnected while waiting for the lock? */
                if (test_bit(US_FLIDX_DISCONNECTING, &us->dflags)) {
                        result = -EIO;
-                       US_DEBUGP("No reset during disconnect\n");
+                       usb_stor_dbg(us, "No reset during disconnect\n");
                } else {
                        result = usb_reset_device(us->pusb_dev);
-                       US_DEBUGP("usb_reset_device returns %d\n",
-                                       result);
+                       usb_stor_dbg(us, "usb_reset_device returns %d\n",
+                                    result);
                }
                usb_unlock_device(us->pusb_dev);
        }
index d6bee407af025bfb386a19d9223e14f945527d0f..5c4fe0749af1f74ce007b2da09df558254f4465c 100644 (file)
@@ -183,7 +183,6 @@ int usb_stor_suspend(struct usb_interface *iface, pm_message_t message)
        /* Wait until no command is running */
        mutex_lock(&us->dev_mutex);
 
-       US_DEBUGP("%s\n", __func__);
        if (us->suspend_resume_hook)
                (us->suspend_resume_hook)(us, US_SUSPEND);
 
@@ -201,7 +200,6 @@ int usb_stor_resume(struct usb_interface *iface)
 
        mutex_lock(&us->dev_mutex);
 
-       US_DEBUGP("%s\n", __func__);
        if (us->suspend_resume_hook)
                (us->suspend_resume_hook)(us, US_RESUME);
 
@@ -214,8 +212,6 @@ int usb_stor_reset_resume(struct usb_interface *iface)
 {
        struct us_data *us = usb_get_intfdata(iface);
 
-       US_DEBUGP("%s\n", __func__);
-
        /* Report the reset to the SCSI core */
        usb_stor_report_bus_reset(us);
 
@@ -236,8 +232,6 @@ int usb_stor_pre_reset(struct usb_interface *iface)
 {
        struct us_data *us = usb_get_intfdata(iface);
 
-       US_DEBUGP("%s\n", __func__);
-
        /* Make sure no command runs during the reset */
        mutex_lock(&us->dev_mutex);
        return 0;
@@ -248,8 +242,6 @@ int usb_stor_post_reset(struct usb_interface *iface)
 {
        struct us_data *us = usb_get_intfdata(iface);
 
-       US_DEBUGP("%s\n", __func__);
-
        /* Report the reset to the SCSI core */
        usb_stor_report_bus_reset(us);
 
@@ -311,11 +303,11 @@ static int usb_stor_control_thread(void * __us)
        struct Scsi_Host *host = us_to_host(us);
 
        for (;;) {
-               US_DEBUGP("*** thread sleeping.\n");
+               usb_stor_dbg(us, "*** thread sleeping\n");
                if (wait_for_completion_interruptible(&us->cmnd_ready))
                        break;
 
-               US_DEBUGP("*** thread awakened.\n");
+               usb_stor_dbg(us, "*** thread awakened\n");
 
                /* lock the device pointers */
                mutex_lock(&(us->dev_mutex));
@@ -327,7 +319,7 @@ static int usb_stor_control_thread(void * __us)
                if (us->srb == NULL) {
                        scsi_unlock(host);
                        mutex_unlock(&us->dev_mutex);
-                       US_DEBUGP("-- exiting\n");
+                       usb_stor_dbg(us, "-- exiting\n");
                        break;
                }
 
@@ -343,7 +335,7 @@ static int usb_stor_control_thread(void * __us)
                 * is UNKNOWN
                 */
                if (us->srb->sc_data_direction == DMA_BIDIRECTIONAL) {
-                       US_DEBUGP("UNKNOWN data direction\n");
+                       usb_stor_dbg(us, "UNKNOWN data direction\n");
                        us->srb->result = DID_ERROR << 16;
                }
 
@@ -352,14 +344,14 @@ static int usb_stor_control_thread(void * __us)
                 */
                else if (us->srb->device->id &&
                                !(us->fflags & US_FL_SCM_MULT_TARG)) {
-                       US_DEBUGP("Bad target number (%d:%d)\n",
-                                 us->srb->device->id, us->srb->device->lun);
+                       usb_stor_dbg(us, "Bad target number (%d:%d)\n",
+                                    us->srb->device->id, us->srb->device->lun);
                        us->srb->result = DID_BAD_TARGET << 16;
                }
 
                else if (us->srb->device->lun > us->max_lun) {
-                       US_DEBUGP("Bad LUN (%d:%d)\n",
-                                 us->srb->device->id, us->srb->device->lun);
+                       usb_stor_dbg(us, "Bad LUN (%d:%d)\n",
+                                    us->srb->device->id, us->srb->device->lun);
                        us->srb->result = DID_BAD_TARGET << 16;
                }
 
@@ -371,14 +363,14 @@ static int usb_stor_control_thread(void * __us)
                            0x00, 0x80, 0x02, 0x02,
                            0x1F, 0x00, 0x00, 0x00};
 
-                       US_DEBUGP("Faking INQUIRY command\n");
+                       usb_stor_dbg(us, "Faking INQUIRY command\n");
                        fill_inquiry_response(us, data_ptr, 36);
                        us->srb->result = SAM_STAT_GOOD;
                }
 
                /* we've got a command, let's do it! */
                else {
-                       US_DEBUG(usb_stor_show_command(us->srb));
+                       US_DEBUG(usb_stor_show_command(us, us->srb));
                        us->proto_handler(us->srb, us);
                        usb_mark_last_busy(us->pusb_dev);
                }
@@ -388,12 +380,12 @@ static int usb_stor_control_thread(void * __us)
 
                /* indicate that the command is done */
                if (us->srb->result != DID_ABORT << 16) {
-                       US_DEBUGP("scsi cmd done, result=0x%x\n",
-                                  us->srb->result);
+                       usb_stor_dbg(us, "scsi cmd done, result=0x%x\n",
+                                    us->srb->result);
                        us->srb->scsi_done(us->srb);
                } else {
 SkipForAbort:
-                       US_DEBUGP("scsi command aborted\n");
+                       usb_stor_dbg(us, "scsi command aborted\n");
                }
 
                /* If an abort request was received we need to signal that
@@ -435,34 +427,30 @@ SkipForAbort:
 /* Associate our private data with the USB device */
 static int associate_dev(struct us_data *us, struct usb_interface *intf)
 {
-       US_DEBUGP("-- %s\n", __func__);
-
        /* Fill in the device-related fields */
        us->pusb_dev = interface_to_usbdev(intf);
        us->pusb_intf = intf;
        us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
-       US_DEBUGP("Vendor: 0x%04x, Product: 0x%04x, Revision: 0x%04x\n",
-                       le16_to_cpu(us->pusb_dev->descriptor.idVendor),
-                       le16_to_cpu(us->pusb_dev->descriptor.idProduct),
-                       le16_to_cpu(us->pusb_dev->descriptor.bcdDevice));
-       US_DEBUGP("Interface Subclass: 0x%02x, Protocol: 0x%02x\n",
-                       intf->cur_altsetting->desc.bInterfaceSubClass,
-                       intf->cur_altsetting->desc.bInterfaceProtocol);
+       usb_stor_dbg(us, "Vendor: 0x%04x, Product: 0x%04x, Revision: 0x%04x\n",
+                    le16_to_cpu(us->pusb_dev->descriptor.idVendor),
+                    le16_to_cpu(us->pusb_dev->descriptor.idProduct),
+                    le16_to_cpu(us->pusb_dev->descriptor.bcdDevice));
+       usb_stor_dbg(us, "Interface Subclass: 0x%02x, Protocol: 0x%02x\n",
+                    intf->cur_altsetting->desc.bInterfaceSubClass,
+                    intf->cur_altsetting->desc.bInterfaceProtocol);
 
        /* Store our private data in the interface */
        usb_set_intfdata(intf, us);
 
        /* Allocate the control/setup and DMA-mapped buffers */
        us->cr = kmalloc(sizeof(*us->cr), GFP_KERNEL);
-       if (!us->cr) {
-               US_DEBUGP("usb_ctrlrequest allocation failed\n");
+       if (!us->cr)
                return -ENOMEM;
-       }
 
        us->iobuf = usb_alloc_coherent(us->pusb_dev, US_IOBUF_SIZE,
                        GFP_KERNEL, &us->iobuf_dma);
        if (!us->iobuf) {
-               US_DEBUGP("I/O buffer allocation failed\n");
+               usb_stor_dbg(us, "I/O buffer allocation failed\n");
                return -ENOMEM;
        }
        return 0;
@@ -738,7 +726,7 @@ static int get_pipes(struct us_data *us)
        }
 
        if (!ep_in || !ep_out || (us->protocol == USB_PR_CBI && !ep_int)) {
-               US_DEBUGP("Endpoint sanity check failed! Rejecting dev.\n");
+               usb_stor_dbg(us, "Endpoint sanity check failed! Rejecting dev.\n");
                return -EIO;
        }
 
@@ -765,7 +753,7 @@ static int usb_stor_acquire_resources(struct us_data *us)
 
        us->current_urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!us->current_urb) {
-               US_DEBUGP("URB allocation failed\n");
+               usb_stor_dbg(us, "URB allocation failed\n");
                return -ENOMEM;
        }
 
@@ -792,20 +780,18 @@ static int usb_stor_acquire_resources(struct us_data *us)
 /* Release all our dynamic resources */
 static void usb_stor_release_resources(struct us_data *us)
 {
-       US_DEBUGP("-- %s\n", __func__);
-
        /* Tell the control thread to exit.  The SCSI host must
         * already have been removed and the DISCONNECTING flag set
         * so that we won't accept any more commands.
         */
-       US_DEBUGP("-- sending exit command to thread\n");
+       usb_stor_dbg(us, "-- sending exit command to thread\n");
        complete(&us->cmnd_ready);
        if (us->ctl_thread)
                kthread_stop(us->ctl_thread);
 
        /* Call the destructor routine, if it exists */
        if (us->extra_destructor) {
-               US_DEBUGP("-- calling extra_destructor()\n");
+               usb_stor_dbg(us, "-- calling extra_destructor()\n");
                us->extra_destructor(us->extra);
        }
 
@@ -817,8 +803,6 @@ static void usb_stor_release_resources(struct us_data *us)
 /* Dissociate from the USB device */
 static void dissociate_dev(struct us_data *us)
 {
-       US_DEBUGP("-- %s\n", __func__);
-
        /* Free the buffers */
        kfree(us->cr);
        usb_free_coherent(us->pusb_dev, US_IOBUF_SIZE, us->iobuf, us->iobuf_dma);
@@ -918,7 +902,7 @@ int usb_stor_probe1(struct us_data **pus,
        struct us_data *us;
        int result;
 
-       US_DEBUGP("USB Mass Storage device detected\n");
+       dev_info(&intf->dev, "USB Mass Storage device detected\n");
 
        /*
         * Ask the SCSI layer to allocate a host structure, with extra
@@ -926,8 +910,7 @@ int usb_stor_probe1(struct us_data **pus,
         */
        host = scsi_host_alloc(&usb_stor_host_template, sizeof(*us));
        if (!host) {
-               dev_warn(&intf->dev,
-                               "Unable to allocate the scsi host\n");
+               dev_warn(&intf->dev, "Unable to allocate the scsi host\n");
                return -ENOMEM;
        }
 
@@ -964,7 +947,7 @@ int usb_stor_probe1(struct us_data **pus,
        return 0;
 
 BadDevice:
-       US_DEBUGP("storage_probe() failed\n");
+       usb_stor_dbg(us, "storage_probe() failed\n");
        release_everything(us);
        return result;
 }
@@ -981,8 +964,8 @@ int usb_stor_probe2(struct us_data *us)
                result = -ENXIO;
                goto BadDevice;
        }
-       US_DEBUGP("Transport: %s\n", us->transport_name);
-       US_DEBUGP("Protocol: %s\n", us->protocol_name);
+       usb_stor_dbg(us, "Transport: %s\n", us->transport_name);
+       usb_stor_dbg(us, "Protocol: %s\n", us->protocol_name);
 
        /* fix for single-lun devices */
        if (us->fflags & US_FL_SINGLE_LUN)
@@ -1028,7 +1011,7 @@ int usb_stor_probe2(struct us_data *us)
 
        /* We come here if there are any problems */
 BadDevice:
-       US_DEBUGP("storage_probe() failed\n");
+       usb_stor_dbg(us, "storage_probe() failed\n");
        release_everything(us);
        return result;
 }
@@ -1039,7 +1022,6 @@ void usb_stor_disconnect(struct usb_interface *intf)
 {
        struct us_data *us = usb_get_intfdata(intf);
 
-       US_DEBUGP("storage_disconnect() called\n");
        quiesce_and_remove_host(us);
        release_everything(us);
 }
@@ -1075,8 +1057,7 @@ static int storage_probe(struct usb_interface *intf,
        } else {
                unusual_dev = &for_dynamic_ids;
 
-               US_DEBUGP("%s %s 0x%04x 0x%04x\n", "Use Bulk-Only transport",
-                       "with the Transparent SCSI protocol for dynamic id:",
+               dev_dbg(&intf->dev, "Use Bulk-Only transport with the Transparent SCSI protocol for dynamic id: 0x%04x 0x%04x\n",
                        id->idVendor, id->idProduct);
        }
 
@@ -1090,10 +1071,6 @@ static int storage_probe(struct usb_interface *intf,
        return result;
 }
 
-/***********************************************************************
- * Initialization and registration
- ***********************************************************************/
-
 static struct usb_driver usb_storage_driver = {
        .name =         "usb-storage",
        .probe =        storage_probe,
@@ -1108,30 +1085,4 @@ static struct usb_driver usb_storage_driver = {
        .soft_unbind =  1,
 };
 
-static int __init usb_stor_init(void)
-{
-       int retval;
-
-       pr_info("Initializing USB Mass Storage driver...\n");
-
-       /* register the driver, return usb_register return code if error */
-       retval = usb_register(&usb_storage_driver);
-       if (retval == 0)
-               pr_info("USB Mass Storage support registered.\n");
-       return retval;
-}
-
-static void __exit usb_stor_exit(void)
-{
-       US_DEBUGP("usb_stor_exit() called\n");
-
-       /* Deregister the driver
-        * This will cause disconnect() to be called for each
-        * attached unit
-        */
-       US_DEBUGP("-- calling usb_deregister()\n");
-       usb_deregister(&usb_storage_driver) ;
-}
-
-module_init(usb_stor_init);
-module_exit(usb_stor_exit);
+module_usb_driver(usb_storage_driver);
index d29503e954abf829c71e69f08ec995da39291481..0db0a919d72b2a0a7460f2e6fc7aeee639aebf5c 100644 (file)
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/usb/ch9.h>
+#include <linux/usb/otg.h>
+
+const char *usb_otg_state_string(enum usb_otg_state state)
+{
+       static const char *const names[] = {
+               [OTG_STATE_A_IDLE] = "a_idle",
+               [OTG_STATE_A_WAIT_VRISE] = "a_wait_vrise",
+               [OTG_STATE_A_WAIT_BCON] = "a_wait_bcon",
+               [OTG_STATE_A_HOST] = "a_host",
+               [OTG_STATE_A_SUSPEND] = "a_suspend",
+               [OTG_STATE_A_PERIPHERAL] = "a_peripheral",
+               [OTG_STATE_A_WAIT_VFALL] = "a_wait_vfall",
+               [OTG_STATE_A_VBUS_ERR] = "a_vbus_err",
+               [OTG_STATE_B_IDLE] = "b_idle",
+               [OTG_STATE_B_SRP_INIT] = "b_srp_init",
+               [OTG_STATE_B_PERIPHERAL] = "b_peripheral",
+               [OTG_STATE_B_WAIT_ACON] = "b_wait_acon",
+               [OTG_STATE_B_HOST] = "b_host",
+       };
+
+       if (state < 0 || state >= ARRAY_SIZE(names))
+               return "UNDEFINED";
+
+       return names[state];
+}
+EXPORT_SYMBOL_GPL(usb_otg_state_string);
 
 const char *usb_speed_string(enum usb_device_speed speed)
 {
@@ -32,4 +58,25 @@ const char *usb_speed_string(enum usb_device_speed speed)
 }
 EXPORT_SYMBOL_GPL(usb_speed_string);
 
+const char *usb_state_string(enum usb_device_state state)
+{
+       static const char *const names[] = {
+               [USB_STATE_NOTATTACHED] = "not attached",
+               [USB_STATE_ATTACHED] = "attached",
+               [USB_STATE_POWERED] = "powered",
+               [USB_STATE_RECONNECTING] = "reconnecting",
+               [USB_STATE_UNAUTHENTICATED] = "unauthenticated",
+               [USB_STATE_DEFAULT] = "default",
+               [USB_STATE_ADDRESS] = "addresssed",
+               [USB_STATE_CONFIGURED] = "configured",
+               [USB_STATE_SUSPENDED] = "suspended",
+       };
+
+       if (state < 0 || state >= ARRAY_SIZE(names))
+               return "UNKNOWN";
+
+       return names[state];
+}
+EXPORT_SYMBOL_GPL(usb_state_string);
+
 MODULE_LICENSE("GPL");
index ce310170829fdc66442a8c7b629fc028152c96af..7ed3b039dbe878a8a7c7db038e6150c3395e5bec 100644 (file)
@@ -61,11 +61,10 @@ struct usb_skel {
        __u8                    bulk_out_endpointAddr;  /* the address of the bulk out endpoint */
        int                     errors;                 /* the last request tanked */
        bool                    ongoing_read;           /* a read is going on */
-       bool                    processed_urb;          /* indicates we haven't processed the urb */
        spinlock_t              err_lock;               /* lock for errors */
        struct kref             kref;
        struct mutex            io_mutex;               /* synchronize I/O with disconnect */
-       struct completion       bulk_in_completion;     /* to wait for an ongoing read */
+       wait_queue_head_t       bulk_in_wait;           /* to wait for an ongoing read */
 };
 #define to_skel_dev(d) container_of(d, struct usb_skel, kref)
 
@@ -185,7 +184,7 @@ static void skel_read_bulk_callback(struct urb *urb)
        dev->ongoing_read = 0;
        spin_unlock(&dev->err_lock);
 
-       complete(&dev->bulk_in_completion);
+       wake_up_interruptible(&dev->bulk_in_wait);
 }
 
 static int skel_do_read_io(struct usb_skel *dev, size_t count)
@@ -206,13 +205,16 @@ static int skel_do_read_io(struct usb_skel *dev, size_t count)
        dev->ongoing_read = 1;
        spin_unlock_irq(&dev->err_lock);
 
+       /* submit bulk in urb, which means no data to deliver */
+       dev->bulk_in_filled = 0;
+       dev->bulk_in_copied = 0;
+
        /* do it */
        rv = usb_submit_urb(dev->bulk_in_urb, GFP_KERNEL);
        if (rv < 0) {
                dev_err(&dev->interface->dev,
                        "%s - failed submitting read urb, error %d\n",
                        __func__, rv);
-               dev->bulk_in_filled = 0;
                rv = (rv == -ENOMEM) ? rv : -EIO;
                spin_lock_irq(&dev->err_lock);
                dev->ongoing_read = 0;
@@ -261,25 +263,9 @@ retry:
                 * IO may take forever
                 * hence wait in an interruptible state
                 */
-               rv = wait_for_completion_interruptible(&dev->bulk_in_completion);
+               rv = wait_event_interruptible(dev->bulk_in_wait, (!dev->ongoing_read));
                if (rv < 0)
                        goto exit;
-               /*
-                * by waiting we also semiprocessed the urb
-                * we must finish now
-                */
-               dev->bulk_in_copied = 0;
-               dev->processed_urb = 1;
-       }
-
-       if (!dev->processed_urb) {
-               /*
-                * the URB hasn't been processed
-                * do it now
-                */
-               wait_for_completion(&dev->bulk_in_completion);
-               dev->bulk_in_copied = 0;
-               dev->processed_urb = 1;
        }
 
        /* errors must be reported */
@@ -289,8 +275,6 @@ retry:
                dev->errors = 0;
                /* to preserve notifications about reset */
                rv = (rv == -EPIPE) ? rv : -EIO;
-               /* no data to deliver */
-               dev->bulk_in_filled = 0;
                /* report it */
                goto exit;
        }
@@ -526,7 +510,7 @@ static int skel_probe(struct usb_interface *interface,
        mutex_init(&dev->io_mutex);
        spin_lock_init(&dev->err_lock);
        init_usb_anchor(&dev->submitted);
-       init_completion(&dev->bulk_in_completion);
+       init_waitqueue_head(&dev->bulk_in_wait);
 
        dev->udev = usb_get_dev(interface_to_usbdev(interface));
        dev->interface = interface;
index 8bf19760d4478d16257ab45b857680ae60a53451..0e17b966e1b45b792628f68c1282e5790e944f43 100644 (file)
@@ -3,7 +3,6 @@
 #
 config USB_WUSB
        tristate "Enable Wireless USB extensions"
-       depends on USB
        depends on PCI
        depends on UWB
         select CRYPTO
@@ -19,7 +18,6 @@ config USB_WUSB
 
 config USB_WUSB_CBAF
        tristate "Support WUSB Cable Based Association (CBA)"
-       depends on USB
        help
          Some WUSB devices support Cable Based Association. It's used to
          enable the secure communication between the host and the
index ada401244e0b636cff9fe9996312727d4e504022..1d36ca874cc86fb7b9ec82724277eee625a8478d 100644 (file)
@@ -41,7 +41,3 @@ enum dwc3_omap_utmi_mode {
        DWC3_OMAP_UTMI_MODE_HW,
        DWC3_OMAP_UTMI_MODE_SW,
 };
-
-struct dwc3_omap_data {
-       enum dwc3_omap_utmi_mode        utmi_mode;
-};
index 944b01dd103ef131b20784f6853524f9bd5812c2..98b7925f1a2d851a0da538f19c5a5a28d62de682 100644 (file)
@@ -34,8 +34,6 @@ struct mv_usb_addon_irq {
 };
 
 struct mv_usb_platform_data {
-       unsigned int            clknum;
-       char                    **clkname;
        struct mv_usb_addon_irq *id;    /* Only valid for OTG. ID pin change*/
        struct mv_usb_addon_irq *vbus;  /* valid for OTG/UDC. VBUS change*/
 
index 4d22d0f6167aa49b653c8d942c2e00d61be689b8..a0bee5a28d1a578a27829edd231968e1ff11ce1d 100644 (file)
@@ -469,14 +469,12 @@ struct usb3_lpm_parameters {
  * @lpm_capable: device supports LPM
  * @usb2_hw_lpm_capable: device can perform USB2 hardware LPM
  * @usb2_hw_lpm_enabled: USB2 hardware LPM enabled
+ * @usb3_lpm_enabled: USB3 hardware LPM enabled
  * @string_langid: language ID for strings
  * @product: iProduct string, if present (static)
  * @manufacturer: iManufacturer string, if present (static)
  * @serial: iSerialNumber string, if present (static)
  * @filelist: usbfs files that are open to this device
- * @usb_classdev: USB class device that was created for usbfs device
- *     access from userspace
- * @usbfs_dentry: usbfs dentry entry for the device
  * @maxchild: number of ports if hub
  * @quirks: quirks of the whole device
  * @urbnum: number of URBs submitted for the whole device
@@ -619,7 +617,7 @@ static inline bool usb_acpi_power_manageable(struct usb_device *hdev, int index)
 #endif
 
 /* USB autosuspend and autoresume */
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 extern void usb_enable_autosuspend(struct usb_device *udev);
 extern void usb_disable_autosuspend(struct usb_device *udev);
 
@@ -978,7 +976,12 @@ struct usbdrv_wrap {
  *     the "usbfs" filesystem.  This lets devices provide ways to
  *     expose information to user space regardless of where they
  *     do (or don't) show up otherwise in the filesystem.
- * @suspend: Called when the device is going to be suspended by the system.
+ * @suspend: Called when the device is going to be suspended by the
+ *     system either from system sleep or runtime suspend context. The
+ *     return value will be ignored in system sleep context, so do NOT
+ *     try to continue using the device if suspend fails in this case.
+ *     Instead, let the resume or reset-resume routine recover from
+ *     the failure.
  * @resume: Called when the device is being resumed by the system.
  * @reset_resume: Called when the suspended device has been reset instead
  *     of being resumed.
index 719c332620fa7688bfa440c0cc1fc3472ffd40d9..0b3f4295c0254ae4ecc0b4ae999a5fe363731875 100644 (file)
@@ -11,6 +11,8 @@
 #ifndef __LINUX_USB_CDC_WDM_H
 #define __LINUX_USB_CDC_WDM_H
 
+#include <uapi/linux/usb/cdc-wdm.h>
+
 extern struct usb_driver *usb_cdc_wdm_register(struct usb_interface *intf,
                                        struct usb_endpoint_descriptor *ep,
                                        int bufsize,
index 9c210f2283dfd0268e1e7e580b1b6b3091801429..27603bcbb9b99dccd86f9ac7f720e13fde4c8bd0 100644 (file)
  */
 extern const char *usb_speed_string(enum usb_device_speed speed);
 
+
+/**
+ * usb_state_string - Returns human readable name for the state.
+ * @state: The state to return a human-readable name for. If it's not
+ *     any of the states devices in usb_device_state_string enum,
+ *     the string UNKNOWN will be returned.
+ */
+extern const char *usb_state_string(enum usb_device_state state);
+
 #endif /* __LINUX_USB_CH9_H */
index 8860594d6364b30f4a5e1c2d4b64be63a28d2a9a..5e61589fc1669234e716b313e1b74090d9b192f6 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <linux/log2.h>
+#include <linux/configfs.h>
 
 /*
  * USB function drivers should return USB_GADGET_DELAYED_STATUS if they
@@ -464,6 +465,8 @@ struct usb_function_driver {
 };
 
 struct usb_function_instance {
+       struct config_group group;
+       struct list_head cfs_list;
        struct usb_function_driver *fd;
        void (*free_func_inst)(struct usb_function_instance *inst);
 };
index 51eae14477f72000dcbfbca7fdbc965cafc1c405..5615f4d8272499d4cbc5d1c9850d0cc06e9bf319 100644 (file)
@@ -19,11 +19,11 @@ enum omap_dwc3_vbus_id_status {
 };
 
 #if (defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_DWC3_MODULE))
-extern void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status);
+extern int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status);
 #else
-static inline void dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
+static inline int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status)
 {
-       return;
+       return -ENODEV;
 }
 #endif
 
index 2e297e80d59a81b0a42cf54098030b12e48125ad..c454a88abf2e6fed7adda903a7d2e0626613e29f 100644 (file)
@@ -482,6 +482,7 @@ struct usb_gadget_ops {
  * @speed: Speed of current connection to USB host.
  * @max_speed: Maximal speed the UDC can handle.  UDC must support this
  *      and all slower speeds.
+ * @state: the state we are now (attached, suspended, configured, etc)
  * @sg_supported: true if we can handle scatter-gather
  * @is_otg: True if the USB device port uses a Mini-AB jack, so that the
  *     gadget driver must provide a USB OTG descriptor.
@@ -525,6 +526,7 @@ struct usb_gadget {
        struct list_head                ep_list;        /* of usb_ep */
        enum usb_device_speed           speed;
        enum usb_device_speed           max_speed;
+       enum usb_device_state           state;
        unsigned                        sg_supported:1;
        unsigned                        is_otg:1;
        unsigned                        is_a_peripheral:1;
@@ -872,6 +874,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver);
  */
 int usb_gadget_unregister_driver(struct usb_gadget_driver *driver);
 
+extern int usb_add_gadget_udc_release(struct device *parent,
+               struct usb_gadget *gadget, void (*release)(struct device *dev));
 extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget);
 extern void usb_del_gadget_udc(struct usb_gadget *gadget);
 extern int udc_attach_driver(const char *name,
@@ -959,6 +963,13 @@ extern void usb_gadget_unmap_request(struct usb_gadget *gadget,
 
 /*-------------------------------------------------------------------------*/
 
+/* utility to set gadget state properly */
+
+extern void usb_gadget_set_state(struct usb_gadget *gadget,
+               enum usb_device_state state);
+
+/*-------------------------------------------------------------------------*/
+
 /* utility wrapping a simple endpoint selection policy */
 
 extern struct usb_ep *usb_ep_autoconfig(struct usb_gadget *,
diff --git a/include/linux/usb/gadget_configfs.h b/include/linux/usb/gadget_configfs.h
new file mode 100644 (file)
index 0000000..d74c0ae
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef __GADGET_CONFIGFS__
+#define __GADGET_CONFIGFS__
+
+#include <linux/configfs.h>
+
+int check_user_usb_string(const char *name,
+               struct usb_gadget_strings *stringtab_dev);
+
+#define GS_STRINGS_W(__struct, __name) \
+       static ssize_t __struct##_##__name##_store(struct __struct *gs, \
+               const char *page, size_t len)           \
+{                                                      \
+       int ret;                                        \
+                                                       \
+       ret = usb_string_copy(page, &gs->__name);       \
+       if (ret)                                        \
+               return ret;                             \
+       return len;                                     \
+}
+
+#define GS_STRINGS_R(__struct, __name) \
+       static ssize_t __struct##_##__name##_show(struct __struct *gs, \
+                       char *page)     \
+{      \
+       return sprintf(page, "%s\n", gs->__name ?: ""); \
+}
+
+#define GS_STRING_ITEM_ATTR(struct_name, name) \
+       static struct struct_name##_attribute struct_name##_##name = \
+               __CONFIGFS_ATTR(name,  S_IRUGO | S_IWUSR,               \
+                               struct_name##_##name##_show,            \
+                               struct_name##_##name##_store)
+
+#define GS_STRINGS_RW(struct_name, _name)      \
+       GS_STRINGS_R(struct_name, _name)        \
+       GS_STRINGS_W(struct_name, _name)        \
+       GS_STRING_ITEM_ATTR(struct_name, _name)
+
+#define USB_CONFIG_STRING_RW_OPS(struct_in)                            \
+       CONFIGFS_ATTR_OPS(struct_in);                                   \
+                                                                       \
+static struct configfs_item_operations struct_in##_langid_item_ops = { \
+       .release                = struct_in##_attr_release,             \
+       .show_attribute         = struct_in##_attr_show,                \
+       .store_attribute        = struct_in##_attr_store,               \
+};                                                                     \
+                                                                       \
+static struct config_item_type struct_in##_langid_type = {             \
+       .ct_item_ops    = &struct_in##_langid_item_ops,                 \
+       .ct_attrs       = struct_in##_langid_attrs,                     \
+       .ct_owner       = THIS_MODULE,                                  \
+}
+
+#define USB_CONFIG_STRINGS_LANG(struct_in, struct_member)      \
+       static struct config_group *struct_in##_strings_make(           \
+                       struct config_group *group,                     \
+                       const char *name)                               \
+       {                                                               \
+       struct struct_member *gi;                                       \
+       struct struct_in *gs;                                           \
+       struct struct_in *new;                                          \
+       int langs = 0;                                                  \
+       int ret;                                                        \
+                                                                       \
+       new = kzalloc(sizeof(*new), GFP_KERNEL);                        \
+       if (!new)                                                       \
+               return ERR_PTR(-ENOMEM);                                \
+                                                                       \
+       ret = check_user_usb_string(name, &new->stringtab_dev);         \
+       if (ret)                                                        \
+               goto err;                                               \
+       config_group_init_type_name(&new->group, name,                  \
+                       &struct_in##_langid_type);                      \
+                                                                       \
+       gi = container_of(group, struct struct_member, strings_group);  \
+       ret = -EEXIST;                                                  \
+       list_for_each_entry(gs, &gi->string_list, list) {               \
+               if (gs->stringtab_dev.language == new->stringtab_dev.language) \
+                       goto err;                                       \
+               langs++;                                                \
+       }                                                               \
+       ret = -EOVERFLOW;                                               \
+       if (langs >= MAX_USB_STRING_LANGS)                              \
+               goto err;                                               \
+                                                                       \
+       list_add_tail(&new->list, &gi->string_list);                    \
+       return &new->group;                                             \
+err:                                                                   \
+       kfree(new);                                                     \
+       return ERR_PTR(ret);                                            \
+}                                                                      \
+                                                                       \
+static void struct_in##_strings_drop(                                  \
+               struct config_group *group,                             \
+               struct config_item *item)                               \
+{                                                                      \
+       config_item_put(item);                                          \
+}                                                                      \
+                                                                       \
+static struct configfs_group_operations struct_in##_strings_ops = {    \
+       .make_group     = &struct_in##_strings_make,                    \
+       .drop_item      = &struct_in##_strings_drop,                    \
+};                                                                     \
+                                                                       \
+static struct config_item_type struct_in##_strings_type = {            \
+       .ct_group_ops   = &struct_in##_strings_ops,                     \
+       .ct_owner       = THIS_MODULE,                                  \
+}
+
+#endif
index 59694b5e5e906821a873d52a1a33b9c5d67af5d4..f5f5c7dfda90ebe2656176c058672b75854c3176 100644 (file)
@@ -84,7 +84,7 @@ struct usb_hcd {
 
        struct timer_list       rh_timer;       /* drives root-hub polling */
        struct urb              *status_urb;    /* the current status urb */
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
        struct work_struct      wakeup_work;    /* for remote wakeup */
 #endif
 
@@ -593,14 +593,14 @@ extern int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg);
 extern int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg);
 #endif /* CONFIG_PM */
 
-#ifdef CONFIG_USB_SUSPEND
+#ifdef CONFIG_PM_RUNTIME
 extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd);
 #else
 static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
 {
        return;
 }
-#endif /* CONFIG_USB_SUSPEND */
+#endif /* CONFIG_PM_RUNTIME */
 
 /*-------------------------------------------------------------------------*/
 
diff --git a/include/linux/usb/musb-ux500.h b/include/linux/usb/musb-ux500.h
new file mode 100644 (file)
index 0000000..1e2c713
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 ST-Ericsson AB
+ *
+ * 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.
+ */
+
+#ifndef __MUSB_UX500_H__
+#define __MUSB_UX500_H__
+
+enum ux500_musb_vbus_id_status {
+       UX500_MUSB_NONE = 0,
+       UX500_MUSB_VBUS,
+       UX500_MUSB_ID,
+       UX500_MUSB_CHARGER,
+       UX500_MUSB_ENUMERATED,
+       UX500_MUSB_RIDA,
+       UX500_MUSB_RIDB,
+       UX500_MUSB_RIDC,
+       UX500_MUSB_PREPARE,
+       UX500_MUSB_CLEAN,
+};
+
+#endif /* __MUSB_UX500_H__ */
index 28884c7174112d7ede78d0283d9cba35802eddaa..148d35171aac622ab215bb6520f3dc3f0c0b431f 100644 (file)
@@ -5,6 +5,11 @@
 
 struct nop_usb_xceiv_platform_data {
        enum usb_phy_type type;
+       unsigned long clk_rate;
+
+       /* if set fails with -EPROBE_DEFER if can't get regulator */
+       unsigned int needs_vcc:1;
+       unsigned int needs_reset:1;
 };
 
 #if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE))
index e8a5fe87c6bdeb0700310503defff73ee630864a..291e01ba32e5b80ba49be153ad98523fc220954e 100644 (file)
@@ -36,14 +36,7 @@ struct usb_otg {
 
 };
 
-#ifdef CONFIG_USB_OTG_UTILS
-extern const char *otg_state_string(enum usb_otg_state state);
-#else
-static inline const char *otg_state_string(enum usb_otg_state state)
-{
-       return NULL;
-}
-#endif
+extern const char *usb_otg_state_string(enum usb_otg_state state);
 
 /* Context: can sleep */
 static inline int
index 15847cbdb512b804347b3219d60c7b96563fd9bd..6b5978f576331bcfc9e9411211ab82b38f91f4a2 100644 (file)
@@ -91,6 +91,9 @@ struct usb_phy {
        int     (*init)(struct usb_phy *x);
        void    (*shutdown)(struct usb_phy *x);
 
+       /* enable/disable VBUS */
+       int     (*set_vbus)(struct usb_phy *x, int on);
+
        /* effective for B devices, ignored for A-peripheral */
        int     (*set_power)(struct usb_phy *x,
                                unsigned mA);
@@ -160,8 +163,26 @@ usb_phy_shutdown(struct usb_phy *x)
                x->shutdown(x);
 }
 
+static inline int
+usb_phy_vbus_on(struct usb_phy *x)
+{
+       if (!x->set_vbus)
+               return 0;
+
+       return x->set_vbus(x, true);
+}
+
+static inline int
+usb_phy_vbus_off(struct usb_phy *x)
+{
+       if (!x->set_vbus)
+               return 0;
+
+       return x->set_vbus(x, false);
+}
+
 /* for usb host and peripheral controller drivers */
-#ifdef CONFIG_USB_OTG_UTILS
+#if IS_ENABLED(CONFIG_USB_PHY)
 extern struct usb_phy *usb_get_phy(enum usb_phy_type type);
 extern struct usb_phy *devm_usb_get_phy(struct device *dev,
        enum usb_phy_type type);
@@ -176,29 +197,29 @@ extern int usb_bind_phy(const char *dev_name, u8 index,
 #else
 static inline struct usb_phy *usb_get_phy(enum usb_phy_type type)
 {
-       return NULL;
+       return ERR_PTR(-ENXIO);
 }
 
 static inline struct usb_phy *devm_usb_get_phy(struct device *dev,
        enum usb_phy_type type)
 {
-       return NULL;
+       return ERR_PTR(-ENXIO);
 }
 
 static inline struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index)
 {
-       return NULL;
+       return ERR_PTR(-ENXIO);
 }
 
 static inline struct usb_phy *devm_usb_get_phy_dev(struct device *dev, u8 index)
 {
-       return NULL;
+       return ERR_PTR(-ENXIO);
 }
 
 static inline struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev,
        const char *phandle, u8 index)
 {
-       return NULL;
+       return ERR_PTR(-ENXIO);
 }
 
 static inline void usb_put_phy(struct usb_phy *x)
index c5d36c65c33bfe7e77f6a984a66f7a06e1683f84..e452ba6ec6bd937a86f35f2495077c7a0420847a 100644 (file)
@@ -62,14 +62,14 @@ struct renesas_usbhs_platform_callback {
         * Hardware exit function for platform.
         * it is called when driver was removed
         */
-       void (*hardware_exit)(struct platform_device *pdev);
+       int (*hardware_exit)(struct platform_device *pdev);
 
        /*
         * option:
         *
         * for board specific clock control
         */
-       void (*power_ctrl)(struct platform_device *pdev,
+       int (*power_ctrl)(struct platform_device *pdev,
                           void __iomem *base, int enable);
 
        /*
@@ -77,7 +77,7 @@ struct renesas_usbhs_platform_callback {
         *
         * Phy reset for platform
         */
-       void (*phy_reset)(struct platform_device *pdev);
+       int (*phy_reset)(struct platform_device *pdev);
 
        /*
         * get USB ID function
index 1819b59aab2a697aa573cbf8fe4e1081292dc713..b9b0f7b4e43b81c4829802b5f0eea0cd0713974d 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/kref.h>
 #include <linux/mutex.h>
+#include <linux/serial.h>
 #include <linux/sysrq.h>
 #include <linux/kfifo.h>
 
  * @bulk_out_buffers: pointers to the bulk out buffers for this port
  * @write_urbs: pointers to the bulk out urbs for this port
  * @write_urbs_free: status bitmap the for bulk out urbs
+ * @icount: interrupt counters
  * @tx_bytes: number of bytes currently in host stack queues
  * @bulk_out_endpointAddress: endpoint address for the bulk out pipe for this
  *     port.
  * @flags: usb serial port flags
  * @write_wait: a wait_queue_head_t used by the port.
- * @delta_msr_wait: modem-status-change wait queue
  * @work: work queue entry for the line discipline waking up.
  * @throttled: nonzero if the read urb is inactive to throttle the device
  * @throttle_req: nonzero if the tty wants to throttle us
@@ -109,11 +110,11 @@ struct usb_serial_port {
        unsigned long           write_urbs_free;
        __u8                    bulk_out_endpointAddress;
 
+       struct async_icount     icount;
        int                     tx_bytes;
 
        unsigned long           flags;
        wait_queue_head_t       write_wait;
-       wait_queue_head_t       delta_msr_wait;
        struct work_struct      work;
        char                    throttled;
        char                    throttle_req;
@@ -272,6 +273,7 @@ struct usb_serial_driver {
        int  (*tiocmget)(struct tty_struct *tty);
        int  (*tiocmset)(struct tty_struct *tty,
                         unsigned int set, unsigned int clear);
+       int  (*tiocmiwait)(struct tty_struct *tty, unsigned long arg);
        int  (*get_icount)(struct tty_struct *tty,
                        struct serial_icounter_struct *icount);
        /* Called by the tty layer for port level work. There may or may not
@@ -329,8 +331,10 @@ extern void usb_serial_generic_read_bulk_callback(struct urb *urb);
 extern void usb_serial_generic_write_bulk_callback(struct urb *urb);
 extern void usb_serial_generic_throttle(struct tty_struct *tty);
 extern void usb_serial_generic_unthrottle(struct tty_struct *tty);
-extern void usb_serial_generic_disconnect(struct usb_serial *serial);
-extern void usb_serial_generic_release(struct usb_serial *serial);
+extern int usb_serial_generic_tiocmiwait(struct tty_struct *tty,
+                                                       unsigned long arg);
+extern int usb_serial_generic_get_icount(struct tty_struct *tty,
+                                       struct serial_icounter_struct *icount);
 extern int usb_serial_generic_register(void);
 extern void usb_serial_generic_deregister(void);
 extern int usb_serial_generic_submit_read_urbs(struct usb_serial_port *port,
index 9ebebe90692593c0e26b1f4a7bbbe6f2ce0f8661..1b7519a8c0bf5e509e90fa0b5827713b0aaf219a 100644 (file)
@@ -61,10 +61,14 @@ struct tegra_usb_phy {
        struct device *dev;
        bool is_legacy_phy;
        bool is_ulpi_phy;
+       void (*set_pts)(struct usb_phy *x, u8 pts_val);
+       void (*set_phcd)(struct usb_phy *x, bool enable);
 };
 
 struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
-       void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode);
+       void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode,
+       void (*set_pts)(struct usb_phy *x, u8 pts_val),
+       void (*set_phcd)(struct usb_phy *x, bool enable));
 
 void tegra_usb_phy_preresume(struct usb_phy *phy);
 
@@ -75,8 +79,4 @@ void tegra_ehci_phy_restore_start(struct usb_phy *phy,
 
 void tegra_ehci_phy_restore_end(struct usb_phy *phy);
 
-void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val);
-
-void tegra_ehci_set_phcd(struct usb_phy *x, bool enable);
-
 #endif /* __TEGRA_USB_PHY_H */
diff --git a/include/uapi/linux/usb/cdc-wdm.h b/include/uapi/linux/usb/cdc-wdm.h
new file mode 100644 (file)
index 0000000..f03134f
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * USB CDC Device Management userspace API definitions
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#ifndef _UAPI__LINUX_USB_CDC_WDM_H
+#define _UAPI__LINUX_USB_CDC_WDM_H
+
+/*
+ * This IOCTL is used to retrieve the wMaxCommand for the device,
+ * defining the message limit for both reading and writing.
+ *
+ * For CDC WDM functions this will be the wMaxCommand field of the
+ * Device Management Functional Descriptor.
+ */
+#define IOCTL_WDM_MAX_COMMAND _IOR('H', 0xA0, __u16)
+
+#endif /* _UAPI__LINUX_USB_CDC_WDM_H */
index f738e25377ffbc3ed8e794246f03f718bdb1bab4..aa33fd1b2d4f3a7575dc160d906907133119f1d5 100644 (file)
 
 /*
  * New Feature Selectors as added by USB 3.0
- * See USB 3.0 spec Table 9-6
+ * See USB 3.0 spec Table 9-7
  */
 #define USB_DEVICE_U1_ENABLE   48      /* dev may initiate U1 transition */
 #define USB_DEVICE_U2_ENABLE   49      /* dev may initiate U2 transition */
 
 #define USB_INTR_FUNC_SUSPEND_OPT_MASK 0xFF00
 /*
- * Suspend Options, Table 9-7 USB 3.0 spec
+ * Suspend Options, Table 9-8 USB 3.0 spec
  */
 #define USB_INTRF_FUNC_SUSPEND_LP      (1 << (8 + 0))
 #define USB_INTRF_FUNC_SUSPEND_RW      (1 << (8 + 1))