aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/configfs-usb-gadget45
-rw-r--r--Documentation/ABI/testing/sysfs-platform-chipidea-usb-otg56
-rw-r--r--Documentation/DocBook/Makefile3
-rw-r--r--Documentation/DocBook/writing_musb_glue_layer.tmpl873
-rw-r--r--Documentation/devicetree/bindings/phy/samsung-phy.txt47
-rw-r--r--Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt23
-rw-r--r--Documentation/devicetree/bindings/phy/ti-phy.txt7
-rw-r--r--Documentation/devicetree/bindings/usb/ci-hdrc-qcom.txt17
-rw-r--r--Documentation/devicetree/bindings/usb/ehci-orion.txt5
-rw-r--r--Documentation/devicetree/bindings/usb/exynos-usb.txt31
-rw-r--r--Documentation/devicetree/bindings/usb/gr-udc.txt22
-rw-r--r--Documentation/devicetree/bindings/usb/msm-hsusb.txt78
-rw-r--r--Documentation/devicetree/bindings/usb/usb-ehci.txt1
-rw-r--r--Documentation/devicetree/bindings/usb/usb-ohci.txt1
-rw-r--r--Documentation/devicetree/bindings/usb/usb-xhci.txt8
-rw-r--r--Documentation/devicetree/bindings/usb/usb3503.txt8
-rw-r--r--Documentation/usb/chipidea.txt71
-rw-r--r--arch/arm/configs/badge4_defconfig2
-rw-r--r--arch/arm/configs/cm_x2xx_defconfig1
-rw-r--r--arch/arm/configs/cm_x300_defconfig1
-rw-r--r--arch/arm/configs/colibri_pxa270_defconfig1
-rw-r--r--arch/arm/configs/colibri_pxa300_defconfig2
-rw-r--r--arch/arm/configs/corgi_defconfig1
-rw-r--r--arch/arm/configs/davinci_all_defconfig1
-rw-r--r--arch/arm/configs/em_x270_defconfig1
-rw-r--r--arch/arm/configs/ep93xx_defconfig1
-rw-r--r--arch/arm/configs/footbridge_defconfig2
-rw-r--r--arch/arm/configs/ixp4xx_defconfig1
-rw-r--r--arch/arm/configs/keystone_defconfig1
-rw-r--r--arch/arm/configs/kzm9g_defconfig1
-rw-r--r--arch/arm/configs/mini2440_defconfig1
-rw-r--r--arch/arm/configs/mv78xx0_defconfig1
-rw-r--r--arch/arm/configs/neponset_defconfig2
-rw-r--r--arch/arm/configs/omap1_defconfig2
-rw-r--r--arch/arm/configs/omap2plus_defconfig1
-rw-r--r--arch/arm/configs/pcm027_defconfig1
-rw-r--r--arch/arm/configs/raumfeld_defconfig1
-rw-r--r--arch/arm/configs/s3c2410_defconfig1
-rw-r--r--arch/arm/configs/s3c6400_defconfig1
-rw-r--r--arch/arm/configs/spitz_defconfig1
-rw-r--r--arch/arm/configs/tct_hammer_defconfig1
-rw-r--r--arch/arm/configs/trizeps4_defconfig1
-rw-r--r--arch/arm/configs/viper_defconfig1
-rw-r--r--arch/arm/configs/zeus_defconfig1
-rw-r--r--arch/arm/mach-msm/board-msm7x30.c2
-rw-r--r--arch/arm/mach-msm/board-qsd8x50.c2
-rw-r--r--arch/arm/mach-omap2/board-omap3beagle.c1
-rw-r--r--arch/arm/mach-omap2/usb-host.c10
-rw-r--r--arch/arm/mach-pxa/zeus.c89
-rw-r--r--arch/avr32/configs/hammerhead_defconfig1
-rw-r--r--arch/blackfin/configs/BF526-EZBRD_defconfig1
-rw-r--r--arch/blackfin/configs/BF527-EZKIT-V2_defconfig1
-rw-r--r--arch/blackfin/configs/BF527-EZKIT_defconfig1
-rw-r--r--arch/blackfin/configs/BF548-EZKIT_defconfig1
-rw-r--r--arch/blackfin/configs/CM-BF527_defconfig1
-rw-r--r--arch/blackfin/configs/CM-BF548_defconfig1
-rw-r--r--arch/blackfin/configs/IP0X_defconfig1
-rw-r--r--arch/ia64/configs/bigsur_defconfig1
-rw-r--r--arch/ia64/configs/generic_defconfig1
-rw-r--r--arch/ia64/configs/gensparse_defconfig1
-rw-r--r--arch/ia64/configs/tiger_defconfig1
-rw-r--r--arch/mips/configs/fuloong2e_defconfig1
-rw-r--r--arch/mips/configs/lemote2f_defconfig1
-rw-r--r--arch/mips/configs/mpc30x_defconfig1
-rw-r--r--arch/mips/configs/msp71xx_defconfig1
-rw-r--r--arch/mips/configs/mtx1_defconfig1
-rw-r--r--arch/mips/configs/rm200_defconfig1
-rw-r--r--arch/mips/configs/sb1250_swarm_defconfig1
-rw-r--r--arch/mips/configs/tb0219_defconfig1
-rw-r--r--arch/mips/configs/tb0226_defconfig1
-rw-r--r--arch/parisc/configs/c3000_defconfig2
-rw-r--r--arch/parisc/configs/default_defconfig1
-rw-r--r--arch/parisc/configs/generic-64bit_defconfig1
-rw-r--r--arch/powerpc/configs/40x/ep405_defconfig1
-rw-r--r--arch/powerpc/configs/44x/canyonlands_defconfig1
-rw-r--r--arch/powerpc/configs/44x/currituck_defconfig1
-rw-r--r--arch/powerpc/configs/44x/sam440ep_defconfig1
-rw-r--r--arch/powerpc/configs/52xx/cm5200_defconfig1
-rw-r--r--arch/powerpc/configs/52xx/pcm030_defconfig1
-rw-r--r--arch/powerpc/configs/52xx/tqm5200_defconfig1
-rw-r--r--arch/powerpc/configs/83xx/mpc8313_rdb_defconfig1
-rw-r--r--arch/powerpc/configs/83xx/mpc8315_rdb_defconfig1
-rw-r--r--arch/powerpc/configs/83xx/mpc832x_rdb_defconfig1
-rw-r--r--arch/powerpc/configs/83xx/mpc834x_itx_defconfig1
-rw-r--r--arch/powerpc/configs/83xx/sbc834x_defconfig1
-rw-r--r--arch/powerpc/configs/85xx/ge_imp3a_defconfig1
-rw-r--r--arch/powerpc/configs/85xx/socrates_defconfig1
-rw-r--r--arch/powerpc/configs/85xx/xes_mpc85xx_defconfig1
-rw-r--r--arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig1
-rw-r--r--arch/powerpc/configs/amigaone_defconfig1
-rw-r--r--arch/powerpc/configs/c2k_defconfig1
-rw-r--r--arch/powerpc/configs/cell_defconfig1
-rw-r--r--arch/powerpc/configs/celleb_defconfig1
-rw-r--r--arch/powerpc/configs/chrp32_defconfig1
-rw-r--r--arch/powerpc/configs/g5_defconfig1
-rw-r--r--arch/powerpc/configs/linkstation_defconfig1
-rw-r--r--arch/powerpc/configs/maple_defconfig1
-rw-r--r--arch/powerpc/configs/mpc5200_defconfig1
-rw-r--r--arch/powerpc/configs/mpc86xx_defconfig1
-rw-r--r--arch/powerpc/configs/pmac32_defconfig1
-rw-r--r--arch/powerpc/configs/ppc6xx_defconfig2
-rw-r--r--arch/powerpc/configs/storcenter_defconfig1
-rw-r--r--arch/sh/configs/apsh4ad0a_defconfig1
-rw-r--r--arch/sh/configs/ecovec24_defconfig1
-rw-r--r--arch/sh/configs/landisk_defconfig1
-rw-r--r--arch/sh/configs/rsk7203_defconfig1
-rw-r--r--arch/sh/configs/rsk7264_defconfig1
-rw-r--r--arch/sh/configs/rsk7269_defconfig1
-rw-r--r--arch/sh/configs/sdk7780_defconfig2
-rw-r--r--arch/sh/configs/se7343_defconfig2
-rw-r--r--arch/sh/configs/se7780_defconfig1
-rw-r--r--arch/sh/configs/sh2007_defconfig1
-rw-r--r--arch/sh/configs/sh7785lcr_defconfig1
-rw-r--r--arch/sh/configs/titan_defconfig1
-rw-r--r--arch/sh/configs/urquell_defconfig1
-rw-r--r--arch/unicore32/configs/unicore32_defconfig1
-rw-r--r--arch/x86/configs/i386_defconfig1
-rw-r--r--arch/x86/configs/x86_64_defconfig1
-rw-r--r--drivers/gpu/drm/udl/udl_main.c3
-rw-r--r--drivers/media/rc/redrat3.c102
-rw-r--r--drivers/media/rc/streamzap.c9
-rw-r--r--drivers/net/wireless/orinoco/orinoco_usb.c50
-rw-r--r--drivers/phy/Kconfig13
-rw-r--r--drivers/phy/Makefile1
-rw-r--r--drivers/phy/phy-exynos-mipi-video.c2
-rw-r--r--drivers/phy/phy-exynos5-usbdrd.c676
-rw-r--r--drivers/phy/phy-exynos5250-sata.c2
-rw-r--r--drivers/phy/phy-omap-usb2.c30
-rw-r--r--drivers/phy/phy-sun4i-usb.c75
-rw-r--r--drivers/staging/media/lirc/lirc_igorplugusb.c30
-rw-r--r--drivers/staging/usbip/userspace/README1
-rw-r--r--drivers/usb/Makefile3
-rw-r--r--drivers/usb/chipidea/Makefile1
-rw-r--r--drivers/usb/chipidea/bits.h10
-rw-r--r--drivers/usb/chipidea/ci.h23
-rw-r--r--drivers/usb/chipidea/ci_hdrc_msm.c24
-rw-r--r--drivers/usb/chipidea/core.c92
-rw-r--r--drivers/usb/chipidea/debug.c135
-rw-r--r--drivers/usb/chipidea/host.c21
-rw-r--r--drivers/usb/chipidea/otg.c48
-rw-r--r--drivers/usb/chipidea/otg.h23
-rw-r--r--drivers/usb/chipidea/otg_fsm.c842
-rw-r--r--drivers/usb/chipidea/otg_fsm.h129
-rw-r--r--drivers/usb/chipidea/udc.c69
-rw-r--r--drivers/usb/chipidea/usbmisc_imx.c68
-rw-r--r--drivers/usb/class/cdc-acm.c177
-rw-r--r--drivers/usb/class/cdc-acm.h14
-rw-r--r--drivers/usb/class/usbtmc.c6
-rw-r--r--drivers/usb/common/Makefile6
-rw-r--r--drivers/usb/common/usb-common.c (renamed from drivers/usb/usb-common.c)0
-rw-r--r--drivers/usb/common/usb-otg-fsm.c (renamed from drivers/usb/phy/phy-fsm-usb.c)1
-rw-r--r--drivers/usb/core/Kconfig16
-rw-r--r--drivers/usb/core/hcd-pci.c1
-rw-r--r--drivers/usb/core/hcd.c49
-rw-r--r--drivers/usb/core/hub.c956
-rw-r--r--drivers/usb/core/hub.h41
-rw-r--r--drivers/usb/core/port.c289
-rw-r--r--drivers/usb/core/usb-acpi.c107
-rw-r--r--drivers/usb/core/usb.h16
-rw-r--r--drivers/usb/dwc2/Kconfig61
-rw-r--r--drivers/usb/dwc2/Makefile37
-rw-r--r--drivers/usb/dwc2/core.c68
-rw-r--r--drivers/usb/dwc2/core.h182
-rw-r--r--drivers/usb/dwc2/gadget.c (renamed from drivers/usb/gadget/s3c-hsotg.c)598
-rw-r--r--drivers/usb/dwc2/hw.h12
-rw-r--r--drivers/usb/dwc2/platform.c6
-rw-r--r--drivers/usb/dwc3/Kconfig4
-rw-r--r--drivers/usb/dwc3/core.c253
-rw-r--r--drivers/usb/dwc3/dwc3-exynos.c71
-rw-r--r--drivers/usb/dwc3/dwc3-omap.c2
-rw-r--r--drivers/usb/dwc3/dwc3-pci.c21
-rw-r--r--drivers/usb/dwc3/gadget.c83
-rw-r--r--drivers/usb/gadget/Kconfig10
-rw-r--r--drivers/usb/gadget/Makefile1
-rw-r--r--drivers/usb/gadget/atmel_usba_udc.c2
-rw-r--r--drivers/usb/gadget/composite.c316
-rw-r--r--drivers/usb/gadget/configfs.c556
-rw-r--r--drivers/usb/gadget/configfs.h12
-rw-r--r--drivers/usb/gadget/dummy_hcd.c4
-rw-r--r--drivers/usb/gadget/f_fs.c33
-rw-r--r--drivers/usb/gadget/f_rndis.c33
-rw-r--r--drivers/usb/gadget/f_subset.c2
-rw-r--r--drivers/usb/gadget/f_uac2.c10
-rw-r--r--drivers/usb/gadget/fotg210-udc.c8
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c8
-rw-r--r--drivers/usb/gadget/fusb300_udc.c8
-rw-r--r--drivers/usb/gadget/gr_udc.c55
-rw-r--r--drivers/usb/gadget/inode.c3
-rw-r--r--drivers/usb/gadget/m66592-udc.c1
-rw-r--r--drivers/usb/gadget/mv_u3d_core.c14
-rw-r--r--drivers/usb/gadget/net2280.c4
-rw-r--r--drivers/usb/gadget/r8a66597-udc.c1
-rw-r--r--drivers/usb/gadget/rndis.c28
-rw-r--r--drivers/usb/gadget/s3c-hsotg.h378
-rw-r--r--drivers/usb/gadget/s3c2410_udc.c3
-rw-r--r--drivers/usb/gadget/storage_common.c52
-rw-r--r--drivers/usb/gadget/tcm_usb_gadget.c16
-rw-r--r--drivers/usb/gadget/u_ether.c32
-rw-r--r--drivers/usb/gadget/u_f.c2
-rw-r--r--drivers/usb/gadget/u_f.h26
-rw-r--r--drivers/usb/gadget/u_os_desc.h90
-rw-r--r--drivers/usb/gadget/u_rndis.h3
-rw-r--r--drivers/usb/gadget/udc-core.c2
-rw-r--r--drivers/usb/gadget/uvc_queue.c12
-rw-r--r--drivers/usb/host/Kconfig34
-rw-r--r--drivers/usb/host/Makefile4
-rw-r--r--drivers/usb/host/ehci-exynos.c141
-rw-r--r--drivers/usb/host/ehci-hub.c12
-rw-r--r--drivers/usb/host/ehci-msm.c7
-rw-r--r--drivers/usb/host/ehci-mv.c16
-rw-r--r--drivers/usb/host/ehci-orion.c92
-rw-r--r--drivers/usb/host/ehci-platform.c26
-rw-r--r--drivers/usb/host/ehci-spear.c13
-rw-r--r--drivers/usb/host/ehci-tegra.c15
-rw-r--r--drivers/usb/host/ehci.h3
-rw-r--r--drivers/usb/host/max3421-hcd.c1957
-rw-r--r--drivers/usb/host/ohci-at91.c11
-rw-r--r--drivers/usb/host/ohci-exynos.c145
-rw-r--r--drivers/usb/host/ohci-hcd.c2
-rw-r--r--drivers/usb/host/ohci-hub.c8
-rw-r--r--drivers/usb/host/ohci-platform.c27
-rw-r--r--drivers/usb/host/ohci-pxa27x.c68
-rw-r--r--drivers/usb/host/ohci-s3c2410.c13
-rw-r--r--drivers/usb/host/ohci.h3
-rw-r--r--drivers/usb/host/pci-quirks.h1
-rw-r--r--drivers/usb/host/xhci-hub.c43
-rw-r--r--drivers/usb/host/xhci-mem.c17
-rw-r--r--drivers/usb/host/xhci-mvebu.c72
-rw-r--r--drivers/usb/host/xhci-mvebu.h21
-rw-r--r--drivers/usb/host/xhci-pci.c10
-rw-r--r--drivers/usb/host/xhci-plat.c51
-rw-r--r--drivers/usb/host/xhci-ring.c587
-rw-r--r--drivers/usb/host/xhci.c271
-rw-r--r--drivers/usb/host/xhci.h49
-rw-r--r--drivers/usb/misc/appledisplay.c15
-rw-r--r--drivers/usb/misc/ftdi-elan.c4878
-rw-r--r--drivers/usb/misc/iowarrior.c38
-rw-r--r--drivers/usb/misc/usb3503.c59
-rw-r--r--drivers/usb/misc/usbtest.c13
-rw-r--r--drivers/usb/misc/yurex.c3
-rw-r--r--drivers/usb/musb/Kconfig5
-rw-r--r--drivers/usb/musb/am35x.c14
-rw-r--r--drivers/usb/musb/blackfin.c14
-rw-r--r--drivers/usb/musb/da8xx.c16
-rw-r--r--drivers/usb/musb/davinci.c8
-rw-r--r--drivers/usb/musb/musb_core.c35
-rw-r--r--drivers/usb/musb/musb_core.h9
-rw-r--r--drivers/usb/musb/musb_dsps.c29
-rw-r--r--drivers/usb/musb/tusb6010.c28
-rw-r--r--drivers/usb/musb/tusb6010.h8
-rw-r--r--drivers/usb/musb/tusb6010_omap.c2
-rw-r--r--drivers/usb/phy/Kconfig27
-rw-r--r--drivers/usb/phy/Makefile2
-rw-r--r--drivers/usb/phy/phy-am335x.c4
-rw-r--r--drivers/usb/phy/phy-generic.c65
-rw-r--r--drivers/usb/phy/phy-generic.h8
-rw-r--r--drivers/usb/phy/phy-keystone.c4
-rw-r--r--drivers/usb/phy/phy-msm-usb.c702
-rw-r--r--drivers/usb/phy/phy-mv-u3d-usb.c338
-rw-r--r--drivers/usb/phy/phy-mv-u3d-usb.h105
-rw-r--r--drivers/usb/phy/phy-ulpi.c1
-rw-r--r--drivers/usb/serial/bus.c14
-rw-r--r--drivers/usb/serial/keyspan.c4
-rw-r--r--drivers/usb/serial/kobil_sct.c22
-rw-r--r--drivers/usb/serial/option.c13
-rw-r--r--drivers/usb/serial/qcserial.c143
-rw-r--r--drivers/usb/serial/sierra.c198
-rw-r--r--drivers/usb/serial/usb-serial.c38
-rw-r--r--drivers/usb/serial/usb-wwan.h6
-rw-r--r--drivers/usb/serial/usb_wwan.c234
-rw-r--r--drivers/usb/storage/ene_ub6250.c3
-rw-r--r--drivers/usb/wusbcore/wa-rpipe.c4
-rw-r--r--drivers/uwb/beacon.c7
-rw-r--r--drivers/uwb/drp.c294
-rw-r--r--drivers/uwb/est.c2
-rw-r--r--drivers/uwb/ie-rcv.c2
-rw-r--r--drivers/uwb/radio.c2
-rw-r--r--drivers/uwb/rsv.c21
-rw-r--r--include/linux/mfd/syscon/exynos5-pmu.h44
-rw-r--r--include/linux/platform_data/max3421-hcd.h24
-rw-r--r--include/linux/usb.h2
-rw-r--r--include/linux/usb/composite.h79
-rw-r--r--include/linux/usb/msm_hsusb.h39
-rw-r--r--include/linux/usb/msm_hsusb_hw.h14
-rw-r--r--include/linux/usb/usb_phy_generic.h (renamed from include/linux/usb/usb_phy_gen_xceiv.h)13
-rw-r--r--tools/usb/ffs-aio-example/multibuff/device_app/aio_multibuff.c349
-rw-r--r--tools/usb/ffs-aio-example/multibuff/host_app/Makefile13
-rw-r--r--tools/usb/ffs-aio-example/multibuff/host_app/test.c146
-rw-r--r--tools/usb/ffs-aio-example/simple/device_app/aio_simple.c335
-rw-r--r--tools/usb/ffs-aio-example/simple/host_app/Makefile13
-rw-r--r--tools/usb/ffs-aio-example/simple/host_app/test.c148
291 files changed, 14364 insertions, 6800 deletions
diff --git a/Documentation/ABI/testing/configfs-usb-gadget b/Documentation/ABI/testing/configfs-usb-gadget
index 37559a06393b..95a36589a66b 100644
--- a/Documentation/ABI/testing/configfs-usb-gadget
+++ b/Documentation/ABI/testing/configfs-usb-gadget
@@ -62,6 +62,40 @@ KernelVersion: 3.11
Description:
This group contains functions available to this USB gadget.
+What: /config/usb-gadget/gadget/functions/<func>.<inst>/interface.<n>
+Date: May 2014
+KernelVersion: 3.16
+Description:
+ This group contains "Feature Descriptors" specific for one
+ gadget's USB interface or one interface group described
+ by an IAD.
+
+ The attributes:
+
+ compatible_id - 8-byte string for "Compatible ID"
+ sub_compatible_id - 8-byte string for "Sub Compatible ID"
+
+What: /config/usb-gadget/gadget/functions/<func>.<inst>/interface.<n>/<property>
+Date: May 2014
+KernelVersion: 3.16
+Description:
+ This group contains "Extended Property Descriptors" specific for one
+ gadget's USB interface or one interface group described
+ by an IAD.
+
+ The attributes:
+
+ type - value 1..7 for interpreting the data
+ 1: unicode string
+ 2: unicode string with environment variable
+ 3: binary
+ 4: little-endian 32-bit
+ 5: big-endian 32-bit
+ 6: unicode string with a symbolic link
+ 7: multiple unicode strings
+ data - blob of data to be interpreted depending on
+ type
+
What: /config/usb-gadget/gadget/strings
Date: Jun 2013
KernelVersion: 3.11
@@ -79,3 +113,14 @@ Description:
product - gadget's product description
manufacturer - gadget's manufacturer description
+What: /config/usb-gadget/gadget/os_desc
+Date: May 2014
+KernelVersion: 3.16
+Description:
+ This group contains "OS String" extension handling attributes.
+
+ use - flag turning "OS Desctiptors" support on/off
+ b_vendor_code - one-byte value used for custom per-device and
+ per-interface requests
+ qw_sign - an identifier to be reported as "OS String"
+ proper
diff --git a/Documentation/ABI/testing/sysfs-platform-chipidea-usb-otg b/Documentation/ABI/testing/sysfs-platform-chipidea-usb-otg
new file mode 100644
index 000000000000..151c59578db4
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-chipidea-usb-otg
@@ -0,0 +1,56 @@
+What: /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_req
+Date: Feb 2014
+Contact: Li Jun <b47624@freescale.com>
+Description:
+ Can be set and read.
+ Set a_bus_req(A-device bus request) input to be 1 if
+ the application running on the A-device wants to use the bus,
+ and to be 0 when the application no longer wants to use
+ the bus(or wants to work as peripheral). a_bus_req can also
+ be set to 1 by kernel in response to remote wakeup signaling
+ from the B-device, the A-device should decide to resume the bus.
+
+ Valid values are "1" and "0".
+
+ Reading: returns 1 if the application running on the A-device
+ is using the bus as host role, otherwise 0.
+
+What: /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_drop
+Date: Feb 2014
+Contact: Li Jun <b47624@freescale.com>
+Description:
+ Can be set and read
+ The a_bus_drop(A-device bus drop) input is 1 when the
+ application running on the A-device wants to power down
+ the bus, and is 0 otherwise, When a_bus_drop is 1, then
+ the a_bus_req shall be 0.
+
+ Valid values are "1" and "0".
+
+ Reading: returns 1 if the bus is off(vbus is turned off) by
+ A-device, otherwise 0.
+
+What: /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req
+Date: Feb 2014
+Contact: Li Jun <b47624@freescale.com>
+Description:
+ Can be set and read.
+ The b_bus_req(B-device bus request) input is 1 during the time
+ that the application running on the B-device wants to use the
+ bus as host, and is 0 when the application no longer wants to
+ work as host and decides to switch back to be peripheral.
+
+ Valid values are "1" and "0".
+
+ Reading: returns if the application running on the B device
+ is using the bus as host role, otherwise 0.
+
+What: /sys/bus/platform/devices/ci_hdrc.0/inputs/a_clr_err
+Date: Feb 2014
+Contact: Li Jun <b47624@freescale.com>
+Description:
+ Only can be set.
+ The a_clr_err(A-device Vbus error clear) input is used to clear
+ vbus error, then A-device will power down the bus.
+
+ Valid value is "1"
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index b444f2e8fe32..bec06659e0eb 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -14,7 +14,8 @@ DOCBOOKS := z8530book.xml device-drivers.xml \
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
80211.xml debugobjects.xml sh.xml regulator.xml \
alsa-driver-api.xml writing-an-alsa-driver.xml \
- tracepoint.xml drm.xml media_api.xml w1.xml
+ tracepoint.xml drm.xml media_api.xml w1.xml \
+ writing_musb_glue_layer.xml
include Documentation/DocBook/media/Makefile
diff --git a/Documentation/DocBook/writing_musb_glue_layer.tmpl b/Documentation/DocBook/writing_musb_glue_layer.tmpl
new file mode 100644
index 000000000000..837eca77f274
--- /dev/null
+++ b/Documentation/DocBook/writing_musb_glue_layer.tmpl
@@ -0,0 +1,873 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="Writing-MUSB-Glue-Layer">
+ <bookinfo>
+ <title>Writing an MUSB Glue Layer</title>
+
+ <authorgroup>
+ <author>
+ <firstname>Apelete</firstname>
+ <surname>Seketeli</surname>
+ <affiliation>
+ <address>
+ <email>apelete at seketeli.net</email>
+ </address>
+ </affiliation>
+ </author>
+ </authorgroup>
+
+ <copyright>
+ <year>2014</year>
+ <holder>Apelete Seketeli</holder>
+ </copyright>
+
+ <legalnotice>
+ <para>
+ This documentation 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.
+ </para>
+
+ <para>
+ This documentation 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.
+ </para>
+
+ <para>
+ You should have received a copy of the GNU General Public License
+ along with this documentation; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA
+ </para>
+
+ <para>
+ For more details see the file COPYING in the Linux kernel source
+ tree.
+ </para>
+ </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+ <chapter id="introduction">
+ <title>Introduction</title>
+ <para>
+ The Linux MUSB subsystem is part of the larger Linux USB
+ subsystem. It provides support for embedded USB Device Controllers
+ (UDC) that do not use Universal Host Controller Interface (UHCI)
+ or Open Host Controller Interface (OHCI).
+ </para>
+ <para>
+ Instead, these embedded UDC rely on the USB On-the-Go (OTG)
+ specification which they implement at least partially. The silicon
+ reference design used in most cases is the Multipoint USB
+ Highspeed Dual-Role Controller (MUSB HDRC) found in the Mentor
+ Graphics Inventra™ design.
+ </para>
+ <para>
+ As a self-taught exercise I have written an MUSB glue layer for
+ the Ingenic JZ4740 SoC, modelled after the many MUSB glue layers
+ in the kernel source tree. This layer can be found at
+ drivers/usb/musb/jz4740.c. In this documentation I will walk
+ through the basics of the jz4740.c glue layer, explaining the
+ different pieces and what needs to be done in order to write your
+ own device glue layer.
+ </para>
+ </chapter>
+
+ <chapter id="linux-musb-basics">
+ <title>Linux MUSB Basics</title>
+ <para>
+ To get started on the topic, please read USB On-the-Go Basics (see
+ Resources) which provides an introduction of USB OTG operation at
+ the hardware level. A couple of wiki pages by Texas Instruments
+ and Analog Devices also provide an overview of the Linux kernel
+ MUSB configuration, albeit focused on some specific devices
+ provided by these companies. Finally, getting acquainted with the
+ USB specification at USB home page may come in handy, with
+ practical instance provided through the Writing USB Device Drivers
+ documentation (again, see Resources).
+ </para>
+ <para>
+ Linux USB stack is a layered architecture in which the MUSB
+ controller hardware sits at the lowest. The MUSB controller driver
+ abstract the MUSB controller hardware to the Linux USB stack.
+ </para>
+ <programlisting>
+ ------------------------
+ | | &lt;------- drivers/usb/gadget
+ | Linux USB Core Stack | &lt;------- drivers/usb/host
+ | | &lt;------- drivers/usb/core
+ ------------------------
+ ⬍
+ --------------------------
+ | | &lt;------ drivers/usb/musb/musb_gadget.c
+ | MUSB Controller driver | &lt;------ drivers/usb/musb/musb_host.c
+ | | &lt;------ drivers/usb/musb/musb_core.c
+ --------------------------
+ ⬍
+ ---------------------------------
+ | MUSB Platform Specific Driver |
+ | | &lt;-- drivers/usb/musb/jz4740.c
+ | aka &quot;Glue Layer&quot; |
+ ---------------------------------
+ ⬍
+ ---------------------------------
+ | MUSB Controller Hardware |
+ ---------------------------------
+ </programlisting>
+ <para>
+ As outlined above, the glue layer is actually the platform
+ specific code sitting in between the controller driver and the
+ controller hardware.
+ </para>
+ <para>
+ Just like a Linux USB driver needs to register itself with the
+ Linux USB subsystem, the MUSB glue layer needs first to register
+ itself with the MUSB controller driver. This will allow the
+ controller driver to know about which device the glue layer
+ supports and which functions to call when a supported device is
+ detected or released; remember we are talking about an embedded
+ controller chip here, so no insertion or removal at run-time.
+ </para>
+ <para>
+ All of this information is passed to the MUSB controller driver
+ through a platform_driver structure defined in the glue layer as:
+ </para>
+ <programlisting linenumbering="numbered">
+static struct platform_driver jz4740_driver = {
+ .probe = jz4740_probe,
+ .remove = jz4740_remove,
+ .driver = {
+ .name = "musb-jz4740",
+ },
+};
+ </programlisting>
+ <para>
+ The probe and remove function pointers are called when a matching
+ device is detected and, respectively, released. The name string
+ describes the device supported by this glue layer. In the current
+ case it matches a platform_device structure declared in
+ arch/mips/jz4740/platform.c. Note that we are not using device
+ tree bindings here.
+ </para>
+ <para>
+ In order to register itself to the controller driver, the glue
+ layer goes through a few steps, basically allocating the
+ controller hardware resources and initialising a couple of
+ circuits. To do so, it needs to keep track of the information used
+ throughout these steps. This is done by defining a private
+ jz4740_glue structure:
+ </para>
+ <programlisting linenumbering="numbered">
+struct jz4740_glue {
+ struct device *dev;
+ struct platform_device *musb;
+ struct clk *clk;
+};
+ </programlisting>
+ <para>
+ The dev and musb members are both device structure variables. The
+ first one holds generic information about the device, since it's
+ the basic device structure, and the latter holds information more
+ closely related to the subsystem the device is registered to. The
+ clk variable keeps information related to the device clock
+ operation.
+ </para>
+ <para>
+ Let's go through the steps of the probe function that leads the
+ glue layer to register itself to the controller driver.
+ </para>
+ <para>
+ N.B.: For the sake of readability each function will be split in
+ logical parts, each part being shown as if it was independent from
+ the others.
+ </para>
+ <programlisting linenumbering="numbered">
+static int jz4740_probe(struct platform_device *pdev)
+{
+ struct platform_device *musb;
+ struct jz4740_glue *glue;
+ struct clk *clk;
+ int ret;
+
+ glue = devm_kzalloc(&amp;pdev->dev, sizeof(*glue), GFP_KERNEL);
+ if (!glue)
+ return -ENOMEM;
+
+ musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
+ if (!musb) {
+ dev_err(&amp;pdev->dev, "failed to allocate musb device\n");
+ return -ENOMEM;
+ }
+
+ clk = devm_clk_get(&amp;pdev->dev, "udc");
+ if (IS_ERR(clk)) {
+ dev_err(&amp;pdev->dev, "failed to get clock\n");
+ ret = PTR_ERR(clk);
+ goto err_platform_device_put;
+ }
+
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ dev_err(&amp;pdev->dev, "failed to enable clock\n");
+ goto err_platform_device_put;
+ }
+
+ musb->dev.parent = &amp;pdev->dev;
+
+ glue->dev = &amp;pdev->dev;
+ glue->musb = musb;
+ glue->clk = clk;
+
+ return 0;
+
+err_platform_device_put:
+ platform_device_put(musb);
+ return ret;
+}
+ </programlisting>
+ <para>
+ The first few lines of the probe function allocate and assign the
+ glue, musb and clk variables. The GFP_KERNEL flag (line 8) allows
+ the allocation process to sleep and wait for memory, thus being
+ usable in a blocking situation. The PLATFORM_DEVID_AUTO flag (line
+ 12) allows automatic allocation and management of device IDs in
+ order to avoid device namespace collisions with explicit IDs. With
+ devm_clk_get() (line 18) the glue layer allocates the clock -- the
+ <literal>devm_</literal> prefix indicates that clk_get() is
+ managed: it automatically frees the allocated clock resource data
+ when the device is released -- and enable it.
+ </para>
+ <para>
+ Then comes the registration steps:
+ </para>
+ <programlisting linenumbering="numbered">
+static int jz4740_probe(struct platform_device *pdev)
+{
+ struct musb_hdrc_platform_data *pdata = &amp;jz4740_musb_platform_data;
+
+ pdata->platform_ops = &amp;jz4740_musb_ops;
+
+ platform_set_drvdata(pdev, glue);
+
+ ret = platform_device_add_resources(musb, pdev->resource,
+ pdev->num_resources);
+ if (ret) {
+ dev_err(&amp;pdev->dev, "failed to add resources\n");
+ goto err_clk_disable;
+ }
+
+ ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+ if (ret) {
+ dev_err(&amp;pdev->dev, "failed to add platform_data\n");
+ goto err_clk_disable;
+ }
+
+ return 0;
+
+err_clk_disable:
+ clk_disable_unprepare(clk);
+err_platform_device_put:
+ platform_device_put(musb);
+ return ret;
+}
+ </programlisting>
+ <para>
+ The first step is to pass the device data privately held by the
+ glue layer on to the controller driver through
+ platform_set_drvdata() (line 7). Next is passing on the device
+ resources information, also privately held at that point, through
+ platform_device_add_resources() (line 9).
+ </para>
+ <para>
+ Finally comes passing on the platform specific data to the
+ controller driver (line 16). Platform data will be discussed in
+ <link linkend="device-platform-data">Chapter 4</link>, but here
+ we are looking at the platform_ops function pointer (line 5) in
+ musb_hdrc_platform_data structure (line 3). This function
+ pointer allows the MUSB controller driver to know which function
+ to call for device operation:
+ </para>
+ <programlisting linenumbering="numbered">
+static const struct musb_platform_ops jz4740_musb_ops = {
+ .init = jz4740_musb_init,
+ .exit = jz4740_musb_exit,
+};
+ </programlisting>
+ <para>
+ Here we have the minimal case where only init and exit functions
+ are called by the controller driver when needed. Fact is the
+ JZ4740 MUSB controller is a basic controller, lacking some
+ features found in other controllers, otherwise we may also have
+ pointers to a few other functions like a power management function
+ or a function to switch between OTG and non-OTG modes, for
+ instance.
+ </para>
+ <para>
+ At that point of the registration process, the controller driver
+ actually calls the init function:
+ </para>
+ <programlisting linenumbering="numbered">
+static int jz4740_musb_init(struct musb *musb)
+{
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (!musb->xceiv) {
+ pr_err("HS UDC: no transceiver configured\n");
+ return -ENODEV;
+ }
+
+ /* Silicon does not implement ConfigData register.
+ * Set dyn_fifo to avoid reading EP config from hardware.
+ */
+ musb->dyn_fifo = true;
+
+ musb->isr = jz4740_musb_interrupt;
+
+ return 0;
+}
+ </programlisting>
+ <para>
+ The goal of jz4740_musb_init() is to get hold of the transceiver
+ driver data of the MUSB controller hardware and pass it on to the
+ MUSB controller driver, as usual. The transceiver is the circuitry
+ inside the controller hardware responsible for sending/receiving
+ the USB data. Since it is an implementation of the physical layer
+ of the OSI model, the transceiver is also referred to as PHY.
+ </para>
+ <para>
+ Getting hold of the MUSB PHY driver data is done with
+ usb_get_phy() which returns a pointer to the structure
+ containing the driver instance data. The next couple of
+ instructions (line 12 and 14) are used as a quirk and to setup
+ IRQ handling respectively. Quirks and IRQ handling will be
+ discussed later in <link linkend="device-quirks">Chapter
+ 5</link> and <link linkend="handling-irqs">Chapter 3</link>.
+ </para>
+ <programlisting linenumbering="numbered">
+static int jz4740_musb_exit(struct musb *musb)
+{
+ usb_put_phy(musb->xceiv);
+
+ return 0;
+}
+ </programlisting>
+ <para>
+ Acting as the counterpart of init, the exit function releases the
+ MUSB PHY driver when the controller hardware itself is about to be
+ released.
+ </para>
+ <para>
+ Again, note that init and exit are fairly simple in this case due
+ to the basic set of features of the JZ4740 controller hardware.
+ When writing an musb glue layer for a more complex controller
+ hardware, you might need to take care of more processing in those
+ two functions.
+ </para>
+ <para>
+ Returning from the init function, the MUSB controller driver jumps
+ back into the probe function:
+ </para>
+ <programlisting linenumbering="numbered">
+static int jz4740_probe(struct platform_device *pdev)
+{
+ ret = platform_device_add(musb);
+ if (ret) {
+ dev_err(&amp;pdev->dev, "failed to register musb device\n");
+ goto err_clk_disable;
+ }
+
+ return 0;
+
+err_clk_disable:
+ clk_disable_unprepare(clk);
+err_platform_device_put:
+ platform_device_put(musb);
+ return ret;
+}
+ </programlisting>
+ <para>
+ This is the last part of the device registration process where the
+ glue layer adds the controller hardware device to Linux kernel
+ device hierarchy: at this stage, all known information about the
+ device is passed on to the Linux USB core stack.
+ </para>
+ <programlisting linenumbering="numbered">
+static int jz4740_remove(struct platform_device *pdev)
+{
+ struct jz4740_glue *glue = platform_get_drvdata(pdev);
+
+ platform_device_unregister(glue->musb);
+ clk_disable_unprepare(glue->clk);
+
+ return 0;
+}
+ </programlisting>
+ <para>
+ Acting as the counterpart of probe, the remove function unregister
+ the MUSB controller hardware (line 5) and disable the clock (line
+ 6), allowing it to be gated.
+ </para>
+ </chapter>
+
+ <chapter id="handling-irqs">
+ <title>Handling IRQs</title>
+ <para>
+ Additionally to the MUSB controller hardware basic setup and
+ registration, the glue layer is also responsible for handling the
+ IRQs:
+ </para>
+ <programlisting linenumbering="numbered">
+static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci)
+{
+ unsigned long flags;
+ irqreturn_t retval = IRQ_NONE;
+ struct musb *musb = __hci;
+
+ spin_lock_irqsave(&amp;musb->lock, flags);
+
+ musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
+ musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
+ musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
+
+ /*
+ * The controller is gadget only, the state of the host mode IRQ bits is
+ * undefined. Mask them to make sure that the musb driver core will
+ * never see them set
+ */
+ musb->int_usb &amp;= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME |
+ MUSB_INTR_RESET | MUSB_INTR_SOF;
+
+ if (musb->int_usb || musb->int_tx || musb->int_rx)
+ retval = musb_interrupt(musb);
+
+ spin_unlock_irqrestore(&amp;musb->lock, flags);
+
+ return retval;
+}
+ </programlisting>
+ <para>
+ Here the glue layer mostly has to read the relevant hardware
+ registers and pass their values on to the controller driver which
+ will handle the actual event that triggered the IRQ.
+ </para>
+ <para>
+ The interrupt handler critical section is protected by the
+ spin_lock_irqsave() and counterpart spin_unlock_irqrestore()
+ functions (line 7 and 24 respectively), which prevent the
+ interrupt handler code to be run by two different threads at the
+ same time.
+ </para>
+ <para>
+ Then the relevant interrupt registers are read (line 9 to 11):
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ MUSB_INTRUSB: indicates which USB interrupts are currently
+ active,
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ MUSB_INTRTX: indicates which of the interrupts for TX
+ endpoints are currently active,
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ MUSB_INTRRX: indicates which of the interrupts for TX
+ endpoints are currently active.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Note that musb_readb() is used to read 8-bit registers at most,
+ while musb_readw() allows us to read at most 16-bit registers.
+ There are other functions that can be used depending on the size
+ of your device registers. See musb_io.h for more information.
+ </para>
+ <para>
+ Instruction on line 18 is another quirk specific to the JZ4740
+ USB device controller, which will be discussed later in <link
+ linkend="device-quirks">Chapter 5</link>.
+ </para>
+ <para>
+ The glue layer still needs to register the IRQ handler though.
+ Remember the instruction on line 14 of the init function:
+ </para>
+ <programlisting linenumbering="numbered">
+static int jz4740_musb_init(struct musb *musb)
+{
+ musb->isr = jz4740_musb_interrupt;
+
+ return 0;
+}
+ </programlisting>
+ <para>
+ This instruction sets a pointer to the glue layer IRQ handler
+ function, in order for the controller hardware to call the handler
+ back when an IRQ comes from the controller hardware. The interrupt
+ handler is now implemented and registered.
+ </para>
+ </chapter>
+
+ <chapter id="device-platform-data">
+ <title>Device Platform Data</title>
+ <para>
+ In order to write an MUSB glue layer, you need to have some data
+ describing the hardware capabilities of your controller hardware,
+ which is called the platform data.
+ </para>
+ <para>
+ Platform data is specific to your hardware, though it may cover a
+ broad range of devices, and is generally found somewhere in the
+ arch/ directory, depending on your device architecture.
+ </para>
+ <para>
+ For instance, platform data for the JZ4740 SoC is found in
+ arch/mips/jz4740/platform.c. In the platform.c file each device of
+ the JZ4740 SoC is described through a set of structures.
+ </para>
+ <para>
+ Here is the part of arch/mips/jz4740/platform.c that covers the
+ USB Device Controller (UDC):
+ </para>
+ <programlisting linenumbering="numbered">
+/* USB Device Controller */
+struct platform_device jz4740_udc_xceiv_device = {
+ .name = "usb_phy_gen_xceiv",
+ .id = 0,
+};
+
+static struct resource jz4740_udc_resources[] = {
+ [0] = {
+ .start = JZ4740_UDC_BASE_ADDR,
+ .end = JZ4740_UDC_BASE_ADDR + 0x10000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = JZ4740_IRQ_UDC,
+ .end = JZ4740_IRQ_UDC,
+ .flags = IORESOURCE_IRQ,
+ .name = "mc",
+ },
+};
+
+struct platform_device jz4740_udc_device = {
+ .name = "musb-jz4740",
+ .id = -1,
+ .dev = {
+ .dma_mask = &amp;jz4740_udc_device.dev.coherent_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = ARRAY_SIZE(jz4740_udc_resources),
+ .resource = jz4740_udc_resources,
+};
+ </programlisting>
+ <para>
+ The jz4740_udc_xceiv_device platform device structure (line 2)
+ describes the UDC transceiver with a name and id number.
+ </para>
+ <para>
+ At the time of this writing, note that
+ &quot;usb_phy_gen_xceiv&quot; is the specific name to be used for
+ all transceivers that are either built-in with reference USB IP or
+ autonomous and doesn't require any PHY programming. You will need
+ to set CONFIG_NOP_USB_XCEIV=y in the kernel configuration to make
+ use of the corresponding transceiver driver. The id field could be
+ set to -1 (equivalent to PLATFORM_DEVID_NONE), -2 (equivalent to
+ PLATFORM_DEVID_AUTO) or start with 0 for the first device of this
+ kind if we want a specific id number.
+ </para>
+ <para>
+ The jz4740_udc_resources resource structure (line 7) defines the
+ UDC registers base addresses.
+ </para>
+ <para>
+ The first array (line 9 to 11) defines the UDC registers base
+ memory addresses: start points to the first register memory
+ address, end points to the last register memory address and the
+ flags member defines the type of resource we are dealing with. So
+ IORESOURCE_MEM is used to define the registers memory addresses.
+ The second array (line 14 to 17) defines the UDC IRQ registers
+ addresses. Since there is only one IRQ register available for the
+ JZ4740 UDC, start and end point at the same address. The
+ IORESOURCE_IRQ flag tells that we are dealing with IRQ resources,
+ and the name &quot;mc&quot; is in fact hard-coded in the MUSB core
+ in order for the controller driver to retrieve this IRQ resource
+ by querying it by its name.
+ </para>
+ <para>
+ Finally, the jz4740_udc_device platform device structure (line 21)
+ describes the UDC itself.
+ </para>
+ <para>
+ The &quot;musb-jz4740&quot; name (line 22) defines the MUSB
+ driver that is used for this device; remember this is in fact
+ the name that we used in the jz4740_driver platform driver
+ structure in <link linkend="linux-musb-basics">Chapter
+ 2</link>. The id field (line 23) is set to -1 (equivalent to
+ PLATFORM_DEVID_NONE) since we do not need an id for the device:
+ the MUSB controller driver was already set to allocate an
+ automatic id in <link linkend="linux-musb-basics">Chapter
+ 2</link>. In the dev field we care for DMA related information
+ here. The dma_mask field (line 25) defines the width of the DMA
+ mask that is going to be used, and coherent_dma_mask (line 26)
+ has the same purpose but for the alloc_coherent DMA mappings: in
+ both cases we are using a 32 bits mask. Then the resource field
+ (line 29) is simply a pointer to the resource structure defined
+ before, while the num_resources field (line 28) keeps track of
+ the number of arrays defined in the resource structure (in this
+ case there were two resource arrays defined before).
+ </para>
+ <para>
+ With this quick overview of the UDC platform data at the arch/
+ level now done, let's get back to the MUSB glue layer specific
+ platform data in drivers/usb/musb/jz4740.c:
+ </para>
+ <programlisting linenumbering="numbered">
+static struct musb_hdrc_config jz4740_musb_config = {
+ /* Silicon does not implement USB OTG. */
+ .multipoint = 0,
+ /* Max EPs scanned, driver will decide which EP can be used. */
+ .num_eps = 4,
+ /* RAMbits needed to configure EPs from table */
+ .ram_bits = 9,
+ .fifo_cfg = jz4740_musb_fifo_cfg,
+ .fifo_cfg_size = ARRAY_SIZE(jz4740_musb_fifo_cfg),
+};
+
+static struct musb_hdrc_platform_data jz4740_musb_platform_data = {
+ .mode = MUSB_PERIPHERAL,
+ .config = &amp;jz4740_musb_config,
+};
+ </programlisting>
+ <para>
+ First the glue layer configures some aspects of the controller
+ driver operation related to the controller hardware specifics.
+ This is done through the jz4740_musb_config musb_hdrc_config
+ structure.
+ </para>
+ <para>
+ Defining the OTG capability of the controller hardware, the
+ multipoint member (line 3) is set to 0 (equivalent to false)
+ since the JZ4740 UDC is not OTG compatible. Then num_eps (line
+ 5) defines the number of USB endpoints of the controller
+ hardware, including endpoint 0: here we have 3 endpoints +
+ endpoint 0. Next is ram_bits (line 7) which is the width of the
+ RAM address bus for the MUSB controller hardware. This
+ information is needed when the controller driver cannot
+ automatically configure endpoints by reading the relevant
+ controller hardware registers. This issue will be discussed when
+ we get to device quirks in <link linkend="device-quirks">Chapter
+ 5</link>. Last two fields (line 8 and 9) are also about device
+ quirks: fifo_cfg points to the USB endpoints configuration table
+ and fifo_cfg_size keeps track of the size of the number of
+ entries in that configuration table. More on that later in <link
+ linkend="device-quirks">Chapter 5</link>.
+ </para>
+ <para>
+ Then this configuration is embedded inside
+ jz4740_musb_platform_data musb_hdrc_platform_data structure (line
+ 11): config is a pointer to the configuration structure itself,
+ and mode tells the controller driver if the controller hardware
+ may be used as MUSB_HOST only, MUSB_PERIPHERAL only or MUSB_OTG
+ which is a dual mode.
+ </para>
+ <para>
+ Remember that jz4740_musb_platform_data is then used to convey
+ platform data information as we have seen in the probe function
+ in <link linkend="linux-musb-basics">Chapter 2</link>
+ </para>
+ </chapter>
+
+ <chapter id="device-quirks">
+ <title>Device Quirks</title>
+ <para>
+ Completing the platform data specific to your device, you may also
+ need to write some code in the glue layer to work around some
+ device specific limitations. These quirks may be due to some
+ hardware bugs, or simply be the result of an incomplete
+ implementation of the USB On-the-Go specification.
+ </para>
+ <para>
+ The JZ4740 UDC exhibits such quirks, some of which we will discuss
+ here for the sake of insight even though these might not be found
+ in the controller hardware you are working on.
+ </para>
+ <para>
+ Let's get back to the init function first:
+ </para>
+ <programlisting linenumbering="numbered">
+static int jz4740_musb_init(struct musb *musb)
+{
+ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
+ if (!musb->xceiv) {
+ pr_err("HS UDC: no transceiver configured\n");
+ return -ENODEV;
+ }
+
+ /* Silicon does not implement ConfigData register.
+ * Set dyn_fifo to avoid reading EP config from hardware.
+ */
+ musb->dyn_fifo = true;
+
+ musb->isr = jz4740_musb_interrupt;
+
+ return 0;
+}
+ </programlisting>
+ <para>
+ Instruction on line 12 helps the MUSB controller driver to work
+ around the fact that the controller hardware is missing registers
+ that are used for USB endpoints configuration.
+ </para>
+ <para>
+ Without these registers, the controller driver is unable to read
+ the endpoints configuration from the hardware, so we use line 12
+ instruction to bypass reading the configuration from silicon, and
+ rely on a hard-coded table that describes the endpoints
+ configuration instead:
+ </para>
+ <programlisting linenumbering="numbered">
+static struct musb_fifo_cfg jz4740_musb_fifo_cfg[] = {
+{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
+{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
+{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 64, },
+};
+ </programlisting>
+ <para>
+ Looking at the configuration table above, we see that each
+ endpoints is described by three fields: hw_ep_num is the endpoint
+ number, style is its direction (either FIFO_TX for the controller
+ driver to send packets in the controller hardware, or FIFO_RX to
+ receive packets from hardware), and maxpacket defines the maximum
+ size of each data packet that can be transmitted over that
+ endpoint. Reading from the table, the controller driver knows that
+ endpoint 1 can be used to send and receive USB data packets of 512
+ bytes at once (this is in fact a bulk in/out endpoint), and
+ endpoint 2 can be used to send data packets of 64 bytes at once
+ (this is in fact an interrupt endpoint).
+ </para>
+ <para>
+ Note that there is no information about endpoint 0 here: that one
+ is implemented by default in every silicon design, with a
+ predefined configuration according to the USB specification. For
+ more examples of endpoint configuration tables, see musb_core.c.
+ </para>
+ <para>
+ Let's now get back to the interrupt handler function:
+ </para>
+ <programlisting linenumbering="numbered">
+static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci)
+{
+ unsigned long flags;
+ irqreturn_t retval = IRQ_NONE;
+ struct musb *musb = __hci;
+
+ spin_lock_irqsave(&amp;musb->lock, flags);
+
+ musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
+ musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
+ musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
+
+ /*
+ * The controller is gadget only, the state of the host mode IRQ bits is
+ * undefined. Mask them to make sure that the musb driver core will
+ * never see them set
+ */
+ musb->int_usb &amp;= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME |
+ MUSB_INTR_RESET | MUSB_INTR_SOF;
+
+ if (musb->int_usb || musb->int_tx || musb->int_rx)
+ retval = musb_interrupt(musb);
+
+ spin_unlock_irqrestore(&amp;musb->lock, flags);
+
+ return retval;
+}
+ </programlisting>
+ <para>
+ Instruction on line 18 above is a way for the controller driver to
+ work around the fact that some interrupt bits used for USB host
+ mode operation are missing in the MUSB_INTRUSB register, thus left
+ in an undefined hardware state, since this MUSB controller
+ hardware is used in peripheral mode only. As a consequence, the
+ glue layer masks these missing bits out to avoid parasite
+ interrupts by doing a logical AND operation between the value read
+ from MUSB_INTRUSB and the bits that are actually implemented in
+ the register.
+ </para>
+ <para>
+ These are only a couple of the quirks found in the JZ4740 USB
+ device controller. Some others were directly addressed in the MUSB
+ core since the fixes were generic enough to provide a better
+ handling of the issues for others controller hardware eventually.
+ </para>
+ </chapter>
+
+ <chapter id="conclusion">
+ <title>Conclusion</title>
+ <para>
+ Writing a Linux MUSB glue layer should be a more accessible task,
+ as this documentation tries to show the ins and outs of this
+ exercise.
+ </para>
+ <para>
+ The JZ4740 USB device controller being fairly simple, I hope its
+ glue layer serves as a good example for the curious mind. Used
+ with the current MUSB glue layers, this documentation should
+ provide enough guidance to get started; should anything gets out
+ of hand, the linux-usb mailing list archive is another helpful
+ resource to browse through.
+ </para>
+ </chapter>
+
+ <chapter id="acknowledgements">
+ <title>Acknowledgements</title>
+ <para>
+ Many thanks to Lars-Peter Clausen and Maarten ter Huurne for
+ answering my questions while I was writing the JZ4740 glue layer
+ and for helping me out getting the code in good shape.
+ </para>
+ <para>
+ I would also like to thank the Qi-Hardware community at large for
+ its cheerful guidance and support.
+ </para>
+ </chapter>
+
+ <chapter id="resources">
+ <title>Resources</title>
+ <para>
+ USB Home Page:
+ <ulink url="http://www.usb.org">http://www.usb.org</ulink>
+ </para>
+ <para>
+ linux-usb Mailing List Archives:
+ <ulink url="http://marc.info/?l=linux-usb">http://marc.info/?l=linux-usb</ulink>
+ </para>
+ <para>
+ USB On-the-Go Basics:
+ <ulink url="http://www.maximintegrated.com/app-notes/index.mvp/id/1822">http://www.maximintegrated.com/app-notes/index.mvp/id/1822</ulink>
+ </para>
+ <para>
+ Writing USB Device Drivers:
+ <ulink url="https://www.kernel.org/doc/htmldocs/writing_usb_driver/index.html">https://www.kernel.org/doc/htmldocs/writing_usb_driver/index.html</ulink>
+ </para>
+ <para>
+ Texas Instruments USB Configuration Wiki Page:
+ <ulink url="http://processors.wiki.ti.com/index.php/Usbgeneralpage">http://processors.wiki.ti.com/index.php/Usbgeneralpage</ulink>
+ </para>
+ <para>
+ Analog Devices Blackfin MUSB Configuration:
+ <ulink url="http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:drivers:musb">http://docs.blackfin.uclinux.org/doku.php?id=linux-kernel:drivers:musb</ulink>
+ </para>
+ </chapter>
+
+</book>
diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt
index b422e38946d7..2049261d8c31 100644
--- a/Documentation/devicetree/bindings/phy/samsung-phy.txt
+++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt
@@ -114,3 +114,50 @@ Example:
compatible = "samsung,exynos-sataphy-i2c";
reg = <0x38>;
};
+
+Samsung Exynos5 SoC series USB DRD PHY controller
+--------------------------------------------------
+
+Required properties:
+- compatible : Should be set to one of the following supported values:
+ - "samsung,exynos5250-usbdrd-phy" - for exynos5250 SoC,
+ - "samsung,exynos5420-usbdrd-phy" - for exynos5420 SoC.
+- reg : Register offset and length of USB DRD PHY register set;
+- clocks: Clock IDs array as required by the controller
+- clock-names: names of clocks correseponding to IDs in the clock property;
+ Required clocks:
+ - phy: main PHY clock (same as USB DRD controller i.e. DWC3 IP clock),
+ used for register access.
+ - ref: PHY's reference clock (usually crystal clock), used for
+ PHY operations, associated by phy name. It is used to
+ determine bit values for clock settings register.
+ For Exynos5420 this is given as 'sclk_usbphy30' in CMU.
+- samsung,pmu-syscon: phandle for PMU system controller interface, used to
+ control pmu registers for power isolation.
+- #phy-cells : from the generic PHY bindings, must be 1;
+
+For "samsung,exynos5250-usbdrd-phy" and "samsung,exynos5420-usbdrd-phy"
+compatible PHYs, the second cell in the PHY specifier identifies the
+PHY id, which is interpreted as follows:
+ 0 - UTMI+ type phy,
+ 1 - PIPE3 type phy,
+
+Example:
+ usbdrd_phy: usbphy@12100000 {
+ compatible = "samsung,exynos5250-usbdrd-phy";
+ reg = <0x12100000 0x100>;
+ clocks = <&clock 286>, <&clock 1>;
+ clock-names = "phy", "ref";
+ samsung,pmu-syscon = <&pmu_system_controller>;
+ #phy-cells = <1>;
+ };
+
+- aliases: For SoCs like Exynos5420 having multiple USB 3.0 DRD PHY controllers,
+ 'usbdrd_phy' nodes should have numbered alias in the aliases node,
+ in the form of usbdrdphyN, N = 0, 1... (depending on number of
+ controllers).
+Example:
+ aliases {
+ usbdrdphy0 = &usb3_phy0;
+ usbdrdphy1 = &usb3_phy1;
+ };
diff --git a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
index a82361b62015..16528b9eb561 100644
--- a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
+++ b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
@@ -2,15 +2,26 @@ Allwinner sun4i USB PHY
-----------------------
Required properties:
-- compatible : should be one of "allwinner,sun4i-a10-usb-phy",
- "allwinner,sun5i-a13-usb-phy" or "allwinner,sun7i-a20-usb-phy"
+- compatible : should be one of
+ * allwinner,sun4i-a10-usb-phy
+ * allwinner,sun5i-a13-usb-phy
+ * allwinner,sun6i-a31-usb-phy
+ * allwinner,sun7i-a20-usb-phy
- reg : a list of offset + length pairs
-- reg-names : "phy_ctrl", "pmu1" and for sun4i or sun7i "pmu2"
+- reg-names :
+ * "phy_ctrl"
+ * "pmu1"
+ * "pmu2" for sun4i, sun6i or sun7i
- #phy-cells : from the generic phy bindings, must be 1
-- clocks : phandle + clock specifier for the phy clock
-- clock-names : "usb_phy"
+- clocks : phandle + clock specifier for the phy clocks
+- clock-names :
+ * "usb_phy" for sun4i, sun5i or sun7i
+ * "usb0_phy", "usb1_phy" and "usb2_phy" for sun6i
- resets : a list of phandle + reset specifier pairs
-- reset-names : "usb0_reset", "usb1_reset" and for sun4i or sun7i "usb2_reset"
+- reset-names :
+ * "usb0_reset"
+ * "usb1_reset"
+ * "usb2_reset" for sun4i, sun6i or sun7i
Example:
usbphy: phy@0x01c13400 {
diff --git a/Documentation/devicetree/bindings/phy/ti-phy.txt b/Documentation/devicetree/bindings/phy/ti-phy.txt
index 788fb0fa3762..9ce458f32945 100644
--- a/Documentation/devicetree/bindings/phy/ti-phy.txt
+++ b/Documentation/devicetree/bindings/phy/ti-phy.txt
@@ -32,6 +32,11 @@ Required properties:
- reg : Address and length of the register set for the device.
- #phy-cells: determine the number of cells that should be given in the
phandle while referencing this phy.
+ - clocks: a list of phandles and clock-specifier pairs, one for each entry in
+ clock-names.
+ - clock-names: should include:
+ * "wkupclk" - wakeup clock.
+ * "refclk" - reference clock (optional).
Optional properties:
- ctrl-module : phandle of the control module used by PHY driver to power on
@@ -44,6 +49,8 @@ usb2phy@4a0ad080 {
reg = <0x4a0ad080 0x58>;
ctrl-module = <&omap_control_usb>;
#phy-cells = <0>;
+ clocks = <&usb_phy_cm_clk32k>, <&usb_otg_ss_refclk960m>;
+ clock-names = "wkupclk", "refclk";
};
TI PIPE3 PHY
diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-qcom.txt b/Documentation/devicetree/bindings/usb/ci-hdrc-qcom.txt
new file mode 100644
index 000000000000..f2899b550939
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/ci-hdrc-qcom.txt
@@ -0,0 +1,17 @@
+Qualcomm CI13xxx (Chipidea) USB controllers
+
+Required properties:
+- compatible: should contain "qcom,ci-hdrc"
+- reg: offset and length of the register set in the memory map
+- interrupts: interrupt-specifier for the controller interrupt.
+- usb-phy: phandle for the PHY device
+- dr_mode: Should be "peripheral"
+
+Examples:
+ gadget@f9a55000 {
+ compatible = "qcom,ci-hdrc";
+ reg = <0xf9a55000 0x400>;
+ dr_mode = "peripheral";
+ interrupts = <0 134 0>;
+ usb-phy = <&usbphy0>;
+ };
diff --git a/Documentation/devicetree/bindings/usb/ehci-orion.txt b/Documentation/devicetree/bindings/usb/ehci-orion.txt
index 6bc09ec14c4d..17c3bc858b86 100644
--- a/Documentation/devicetree/bindings/usb/ehci-orion.txt
+++ b/Documentation/devicetree/bindings/usb/ehci-orion.txt
@@ -6,6 +6,11 @@ Required properties:
region.
- interrupts: The EHCI interrupt
+Optional properties:
+- clocks: reference to the clock
+- phys: reference to the USB PHY
+- phy-names: name of the USB PHY, should be "usb"
+
Example:
ehci@50000 {
diff --git a/Documentation/devicetree/bindings/usb/exynos-usb.txt b/Documentation/devicetree/bindings/usb/exynos-usb.txt
index d967ba16de60..a3b5990d0f2c 100644
--- a/Documentation/devicetree/bindings/usb/exynos-usb.txt
+++ b/Documentation/devicetree/bindings/usb/exynos-usb.txt
@@ -12,6 +12,13 @@ Required properties:
- interrupts: interrupt number to the cpu.
- clocks: from common clock binding: handle to usb clock.
- clock-names: from common clock binding: Shall be "usbhost".
+ - port: if in the SoC there are EHCI phys, they should be listed here.
+ One phy per port. Each port should have following entries:
+ - reg: port number on EHCI controller, e.g
+ On Exynos5250, port 0 is USB2.0 otg phy
+ port 1 is HSIC phy0
+ port 2 is HSIC phy1
+ - phys: from the *Generic PHY* bindings; specifying phy used by port.
Optional properties:
- samsung,vbus-gpio: if present, specifies the GPIO that
@@ -27,6 +34,14 @@ Example:
clocks = <&clock 285>;
clock-names = "usbhost";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ phys = <&usb2phy 1>;
+ status = "disabled";
+ };
};
OHCI
@@ -38,6 +53,13 @@ Required properties:
- interrupts: interrupt number to the cpu.
- clocks: from common clock binding: handle to usb clock.
- clock-names: from common clock binding: Shall be "usbhost".
+ - port: if in the SoC there are OHCI phys, they should be listed here.
+ One phy per port. Each port should have following entries:
+ - reg: port number on OHCI controller, e.g
+ On Exynos5250, port 0 is USB2.0 otg phy
+ port 1 is HSIC phy0
+ port 2 is HSIC phy1
+ - phys: from the *Generic PHY* bindings, specifying phy used by port.
Example:
usb@12120000 {
@@ -47,6 +69,15 @@ Example:
clocks = <&clock 285>;
clock-names = "usbhost";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ phys = <&usb2phy 1>;
+ status = "disabled";
+ };
+
};
DWC3
diff --git a/Documentation/devicetree/bindings/usb/gr-udc.txt b/Documentation/devicetree/bindings/usb/gr-udc.txt
index 0c5118f7a916..e9445224fabd 100644
--- a/Documentation/devicetree/bindings/usb/gr-udc.txt
+++ b/Documentation/devicetree/bindings/usb/gr-udc.txt
@@ -12,17 +12,23 @@ Required properties:
- reg : Address and length of the register set for the device
-- interrupts : Interrupt numbers for this device
+- interrupts : Interrupt numbers for this device. Either one interrupt number
+ for all interrupts, or one for status related interrupts, one for IN
+ endpoint related interrupts and one for OUT endpoint related interrupts.
Optional properties:
-- epobufsizes : An array of buffer sizes for OUT endpoints. If the property is
- not present, or for endpoints outside of the array, 1024 is assumed by
- the driver.
-
-- epibufsizes : An array of buffer sizes for IN endpoints. If the property is
- not present, or for endpoints outside of the array, 1024 is assumed by
- the driver.
+- epobufsizes : Array of buffer sizes for OUT endpoints when they differ
+ from the default size of 1024. The array is indexed by the OUT endpoint
+ number. If the property is present it typically contains one entry for
+ each OUT endpoint of the core. Fewer entries overrides the default sizes
+ only for as many endpoints as the array contains.
+
+- epibufsizes : Array of buffer sizes for IN endpoints when they differ
+ from the default size of 1024. The array is indexed by the IN endpoint
+ number. If the property is present it typically contains one entry for
+ each IN endpoint of the core. Fewer entries overrides the default sizes
+ only for as many endpoints as the array contains.
For further information look in the documentation for the GLIB IP core library:
http://www.gaisler.com/products/grlib/grip.pdf
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 5ea26c631e3a..2826f2af503a 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -15,3 +15,81 @@ Example EHCI controller device node:
usb-phy = <&usb_otg>;
};
+USB PHY with optional OTG:
+
+Required properties:
+- compatible: Should contain:
+ "qcom,usb-otg-ci" for chipsets with ChipIdea 45nm PHY
+ "qcom,usb-otg-snps" for chipsets with Synopsys 28nm PHY
+
+- regs: Offset and length of the register set in the memory map
+- interrupts: interrupt-specifier for the OTG interrupt.
+
+- clocks: A list of phandle + clock-specifier pairs for the
+ clocks listed in clock-names
+- clock-names: Should contain the following:
+ "phy" USB PHY reference clock
+ "core" Protocol engine clock
+ "iface" Interface bus clock
+ "alt_core" Protocol engine clock for targets with asynchronous
+ reset methodology. (optional)
+
+- vdccx-supply: phandle to the regulator for the vdd supply for
+ digital circuit operation.
+- v1p8-supply: phandle to the regulator for the 1.8V supply
+- v3p3-supply: phandle to the regulator for the 3.3V supply
+
+- resets: A list of phandle + reset-specifier pairs for the
+ resets listed in reset-names
+- reset-names: Should contain the following:
+ "phy" USB PHY controller reset
+ "link" USB LINK controller reset
+
+- qcom,otg-control: OTG control (VBUS and ID notifications) can be one of
+ 1 - PHY control
+ 2 - PMIC control
+
+Optional properties:
+- dr_mode: One of "host", "peripheral" or "otg". Defaults to "otg"
+
+- qcom,phy-init-sequence: PHY configuration sequence values. This is related to Device
+ Mode Eye Diagram test. Start address at which these values will be
+ written is ULPI_EXT_VENDOR_SPECIFIC. Value of -1 is reserved as
+ "do not overwrite default value at this address".
+ For example: qcom,phy-init-sequence = < -1 0x63 >;
+ Will update only value at address ULPI_EXT_VENDOR_SPECIFIC + 1.
+
+- qcom,phy-num: Select number of pyco-phy to use, can be one of
+ 0 - PHY one, default
+ 1 - Second PHY
+ Some platforms may have configuration to allow USB
+ controller work with any of the two HSPHYs present.
+
+- qcom,vdd-levels: This property must be a list of three integer values
+ (no, min, max) where each value represents either a voltage
+ in microvolts or a value corresponding to voltage corner.
+
+Example HSUSB OTG controller device node:
+
+ usb@f9a55000 {
+ compatible = "qcom,usb-otg-snps";
+ reg = <0xf9a55000 0x400>;
+ interrupts = <0 134 0>;
+ dr_mode = "peripheral";
+
+ clocks = <&gcc GCC_XO_CLK>, <&gcc GCC_USB_HS_SYSTEM_CLK>,
+ <&gcc GCC_USB_HS_AHB_CLK>;
+
+ clock-names = "phy", "core", "iface";
+
+ vddcx-supply = <&pm8841_s2_corner>;
+ v1p8-supply = <&pm8941_l6>;
+ v3p3-supply = <&pm8941_l24>;
+
+ resets = <&gcc GCC_USB2A_PHY_BCR>, <&gcc GCC_USB_HS_BCR>;
+ reset-names = "phy", "link";
+
+ qcom,otg-control = <1>;
+ qcom,phy-init-sequence = < -1 0x63 >;
+ qcom,vdd-levels = <1 5 7>;
+ };
diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt
index ff151ec084c4..43c1a4e06767 100644
--- a/Documentation/devicetree/bindings/usb/usb-ehci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt
@@ -15,6 +15,7 @@ Optional properties:
- clocks : a list of phandle + clock specifier pairs
- phys : phandle + phy specifier pair
- phy-names : "usb"
+ - resets : phandle + reset specifier pair
Example (Sequoia 440EPx):
ehci@e0000300 {
diff --git a/Documentation/devicetree/bindings/usb/usb-ohci.txt b/Documentation/devicetree/bindings/usb/usb-ohci.txt
index 45f67d91e888..b968a1aea995 100644
--- a/Documentation/devicetree/bindings/usb/usb-ohci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-ohci.txt
@@ -12,6 +12,7 @@ Optional properties:
- clocks : a list of phandle + clock specifier pairs
- phys : phandle + phy specifier pair
- phy-names : "usb"
+- resets : phandle + reset specifier pair
Example:
diff --git a/Documentation/devicetree/bindings/usb/usb-xhci.txt b/Documentation/devicetree/bindings/usb/usb-xhci.txt
index 90f8f607d125..5a79377c6a96 100644
--- a/Documentation/devicetree/bindings/usb/usb-xhci.txt
+++ b/Documentation/devicetree/bindings/usb/usb-xhci.txt
@@ -1,11 +1,17 @@
USB xHCI controllers
Required properties:
- - compatible: should be "generic-xhci" (deprecated: "xhci-platform").
+ - compatible: should be one of "generic-xhci",
+ "marvell,armada-375-xhci", "marvell,armada-380-xhci",
+ "renesas,xhci-r8a7790", "renesas,xhci-r8a7791" (deprecated:
+ "xhci-platform").
- reg: should contain address and length of the standard XHCI
register set for the device.
- interrupts: one XHCI interrupt should be described here.
+Optional property:
+ - clocks: reference to a clock
+
Example:
usb@f0931000 {
compatible = "generic-xhci";
diff --git a/Documentation/devicetree/bindings/usb/usb3503.txt b/Documentation/devicetree/bindings/usb/usb3503.txt
index a018da4a7ad7..221ac0dbc678 100644
--- a/Documentation/devicetree/bindings/usb/usb3503.txt
+++ b/Documentation/devicetree/bindings/usb/usb3503.txt
@@ -15,6 +15,14 @@ Optional properties:
- reset-gpios: Should specify GPIO for reset.
- initial-mode: Should specify initial mode.
(1 for HUB mode, 2 for STANDBY mode)
+- refclk: Clock used for driving REFCLK signal (optional, if not provided
+ the driver assumes that clock signal is always available, its
+ rate is specified by REF_SEL pins and a value from the primary
+ reference clock frequencies table is used)
+- refclk-frequency: Frequency of the REFCLK signal as defined by REF_SEL
+ pins (optional, if not provided, driver will not set rate of the
+ REFCLK signal and assume that a value from the primary reference
+ clock frequencies table is used)
Examples:
usb3503@08 {
diff --git a/Documentation/usb/chipidea.txt b/Documentation/usb/chipidea.txt
new file mode 100644
index 000000000000..995c8bca40e2
--- /dev/null
+++ b/Documentation/usb/chipidea.txt
@@ -0,0 +1,71 @@
+1. How to test OTG FSM(HNP and SRP)
+-----------------------------------
+To show how to demo OTG HNP and SRP functions via sys input files
+with 2 Freescale i.MX6Q sabre SD boards.
+
+1.1 How to enable OTG FSM in menuconfig
+---------------------------------------
+Select CONFIG_USB_OTG_FSM, rebuild kernel Image and modules.
+If you want to check some internal variables for otg fsm,
+select CONFIG_USB_CHIPIDEA_DEBUG, there are 2 files which
+can show otg fsm variables and some controller registers value:
+cat /sys/kernel/debug/ci_hdrc.0/otg
+cat /sys/kernel/debug/ci_hdrc.0/registers
+
+1.2 Test operations
+-------------------
+1) Power up 2 Freescale i.MX6Q sabre SD boards with gadget class driver loaded
+ (e.g. g_mass_storage).
+
+2) Connect 2 boards with usb cable with one end is micro A plug, the other end
+ is micro B plug.
+
+ The A-device(with micro A plug inserted) should enumrate B-device.
+
+3) Role switch
+ On B-device:
+ echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req
+
+ if HNP polling is not supported, also need:
+ On A-device:
+ echo 0 > /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_req
+
+ B-device should take host role and enumrate A-device.
+
+4) A-device switch back to host.
+ On B-device:
+ echo 0 > /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req
+
+ A-device should switch back to host and enumrate B-device.
+
+5) Remove B-device(unplug micro B plug) and insert again in 10 seconds,
+ A-device should enumrate B-device again.
+
+6) Remove B-device(unplug micro B plug) and insert again after 10 seconds,
+ A-device should NOT enumrate B-device.
+
+ if A-device wants to use bus:
+ On A-device:
+ echo 0 > /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_drop
+ echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_req
+
+ if B-device wants to use bus:
+ On B-device:
+ echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req
+
+7) A-device power down the bus.
+ On A-device:
+ echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_drop
+
+ A-device should disconnect with B-device and power down the bus.
+
+8) B-device does data pulse for SRP.
+ On B-device:
+ echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req
+
+ A-device should resume usb bus and enumrate B-device.
+
+1.3 Reference document
+----------------------
+"On-The-Go and Embedded Host Supplement to the USB Revision 2.0 Specification
+July 27, 2012 Revision 2.0 version 1.1a"
diff --git a/arch/arm/configs/badge4_defconfig b/arch/arm/configs/badge4_defconfig
index 5b54abbeb0b3..0494c8f229a2 100644
--- a/arch/arm/configs/badge4_defconfig
+++ b/arch/arm/configs/badge4_defconfig
@@ -73,8 +73,6 @@ CONFIG_SA1100_WATCHDOG=m
CONFIG_SOUND=y
CONFIG_SOUND_PRIME=y
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_ACM=m
CONFIG_USB_PRINTER=m
diff --git a/arch/arm/configs/cm_x2xx_defconfig b/arch/arm/configs/cm_x2xx_defconfig
index a93ff8da5bab..dc01c049a520 100644
--- a/arch/arm/configs/cm_x2xx_defconfig
+++ b/arch/arm/configs/cm_x2xx_defconfig
@@ -144,7 +144,6 @@ CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_MON=y
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/arm/configs/cm_x300_defconfig b/arch/arm/configs/cm_x300_defconfig
index f4b767256f95..7df040e91c1c 100644
--- a/arch/arm/configs/cm_x300_defconfig
+++ b/arch/arm/configs/cm_x300_defconfig
@@ -129,7 +129,6 @@ CONFIG_HID_TOPSEED=y
CONFIG_HID_THRUSTMASTER=y
CONFIG_HID_ZEROPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_MON=y
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig
index 2ef2c5e8aaec..18c311ae1113 100644
--- a/arch/arm/configs/colibri_pxa270_defconfig
+++ b/arch/arm/configs/colibri_pxa270_defconfig
@@ -124,7 +124,6 @@ CONFIG_FONT_8x16=y
CONFIG_LOGO=y
# CONFIG_USB_HID is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_SERIAL=m
CONFIG_USB_GADGET=m
diff --git a/arch/arm/configs/colibri_pxa300_defconfig b/arch/arm/configs/colibri_pxa300_defconfig
index b985334e42dd..be02fe2b14cb 100644
--- a/arch/arm/configs/colibri_pxa300_defconfig
+++ b/arch/arm/configs/colibri_pxa300_defconfig
@@ -47,9 +47,7 @@ CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_LOGO=y
# CONFIG_HID_SUPPORT is not set
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_STORAGE=y
CONFIG_MMC=y
diff --git a/arch/arm/configs/corgi_defconfig b/arch/arm/configs/corgi_defconfig
index 1fd1d1de3220..c1470a00f55a 100644
--- a/arch/arm/configs/corgi_defconfig
+++ b/arch/arm/configs/corgi_defconfig
@@ -172,7 +172,6 @@ CONFIG_HID_SAMSUNG=m
CONFIG_HID_SONY=m
CONFIG_HID_SUNPLUS=m
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=m
CONFIG_USB_SL811_HCD=m
CONFIG_USB_SL811_CS=m
diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig
index 2f8ff65e3ef1..f95f72d62db7 100644
--- a/arch/arm/configs/davinci_all_defconfig
+++ b/arch/arm/configs/davinci_all_defconfig
@@ -157,7 +157,6 @@ CONFIG_HID_SAMSUNG=m
CONFIG_HID_SONY=m
CONFIG_HID_SUNPLUS=m
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=m
CONFIG_USB_MUSB_HDRC=m
CONFIG_USB_GADGET_MUSB_HDRC=y
diff --git a/arch/arm/configs/em_x270_defconfig b/arch/arm/configs/em_x270_defconfig
index 60a21e01eb70..4560c9ca6636 100644
--- a/arch/arm/configs/em_x270_defconfig
+++ b/arch/arm/configs/em_x270_defconfig
@@ -144,7 +144,6 @@ CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_MON=y
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/arm/configs/ep93xx_defconfig b/arch/arm/configs/ep93xx_defconfig
index 6ac5ea73bd0a..1b650c85bdd0 100644
--- a/arch/arm/configs/ep93xx_defconfig
+++ b/arch/arm/configs/ep93xx_defconfig
@@ -80,7 +80,6 @@ CONFIG_I2C_DEBUG_BUS=y
CONFIG_WATCHDOG=y
CONFIG_EP93XX_WATCHDOG=y
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
CONFIG_USB_DYNAMIC_MINORS=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PLATFORM=y
diff --git a/arch/arm/configs/footbridge_defconfig b/arch/arm/configs/footbridge_defconfig
index 038518ab39a8..87e020f303ab 100644
--- a/arch/arm/configs/footbridge_defconfig
+++ b/arch/arm/configs/footbridge_defconfig
@@ -100,8 +100,6 @@ CONFIG_FB_CYBER2000=y
CONFIG_SOUND=m
# CONFIG_USB_HID is not set
CONFIG_USB=m
-CONFIG_USB_DEBUG=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=m
CONFIG_USB_PRINTER=m
CONFIG_EXT2_FS=y
diff --git a/arch/arm/configs/ixp4xx_defconfig b/arch/arm/configs/ixp4xx_defconfig
index 063e2ab2c8f1..1af665e847d1 100644
--- a/arch/arm/configs/ixp4xx_defconfig
+++ b/arch/arm/configs/ixp4xx_defconfig
@@ -169,7 +169,6 @@ CONFIG_SENSORS_W83781D=y
CONFIG_WATCHDOG=y
CONFIG_IXP4XX_WATCHDOG=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/arm/configs/keystone_defconfig b/arch/arm/configs/keystone_defconfig
index ec9a41d50680..095bb52671f6 100644
--- a/arch/arm/configs/keystone_defconfig
+++ b/arch/arm/configs/keystone_defconfig
@@ -135,7 +135,6 @@ CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_CORE=y
CONFIG_DAVINCI_WATCHDOG=y
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_MON=y
CONFIG_USB_XHCI_HCD=y
diff --git a/arch/arm/configs/kzm9g_defconfig b/arch/arm/configs/kzm9g_defconfig
index 12bd1f63c399..bd097d455f87 100644
--- a/arch/arm/configs/kzm9g_defconfig
+++ b/arch/arm/configs/kzm9g_defconfig
@@ -106,7 +106,6 @@ CONFIG_SND_SOC=y
CONFIG_SND_SOC_SH4_FSI=y
# CONFIG_HID_SUPPORT is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_R8A66597_HCD=y
CONFIG_USB_RENESAS_USBHS=y
CONFIG_USB_STORAGE=y
diff --git a/arch/arm/configs/mini2440_defconfig b/arch/arm/configs/mini2440_defconfig
index a07948a87caa..9c93f5655248 100644
--- a/arch/arm/configs/mini2440_defconfig
+++ b/arch/arm/configs/mini2440_defconfig
@@ -217,7 +217,6 @@ CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_HID_TOPSEED=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_ACM=m
diff --git a/arch/arm/configs/mv78xx0_defconfig b/arch/arm/configs/mv78xx0_defconfig
index 1f08219c1b3c..0dae1c1f007a 100644
--- a/arch/arm/configs/mv78xx0_defconfig
+++ b/arch/arm/configs/mv78xx0_defconfig
@@ -80,7 +80,6 @@ CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MV64XXX=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_EHCI_TT_NEWSCHED=y
diff --git a/arch/arm/configs/neponset_defconfig b/arch/arm/configs/neponset_defconfig
index d7dc9922cfff..460dca4a4f98 100644
--- a/arch/arm/configs/neponset_defconfig
+++ b/arch/arm/configs/neponset_defconfig
@@ -68,8 +68,6 @@ CONFIG_SOUND=y
CONFIG_SOUND_PRIME=y
# CONFIG_USB_HID is not set
CONFIG_USB=m
-CONFIG_USB_DEBUG=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=m
CONFIG_USB_OHCI_HCD=m
CONFIG_USB_STORAGE=m
diff --git a/arch/arm/configs/omap1_defconfig b/arch/arm/configs/omap1_defconfig
index d74edbad18fc..ce541bb3c2de 100644
--- a/arch/arm/configs/omap1_defconfig
+++ b/arch/arm/configs/omap1_defconfig
@@ -197,8 +197,6 @@ 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
CONFIG_USB_MON=y
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
index 28f3b6e3b589..59066cf0271a 100644
--- a/arch/arm/configs/omap2plus_defconfig
+++ b/arch/arm/configs/omap2plus_defconfig
@@ -224,7 +224,6 @@ CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m
CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m
CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_MON=y
CONFIG_USB_WDM=y
diff --git a/arch/arm/configs/pcm027_defconfig b/arch/arm/configs/pcm027_defconfig
index 2f136c30a989..0a847d04ddc1 100644
--- a/arch/arm/configs/pcm027_defconfig
+++ b/arch/arm/configs/pcm027_defconfig
@@ -76,7 +76,6 @@ CONFIG_SND_PCM_OSS=y
CONFIG_SND_PXA2XX_AC97=y
# CONFIG_HID_SUPPORT is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_STORAGE=y
CONFIG_MMC=y
diff --git a/arch/arm/configs/raumfeld_defconfig b/arch/arm/configs/raumfeld_defconfig
index f7caa909b40d..3d833aea545a 100644
--- a/arch/arm/configs/raumfeld_defconfig
+++ b/arch/arm/configs/raumfeld_defconfig
@@ -122,7 +122,6 @@ CONFIG_HID_TOPSEED=y
CONFIG_HID_THRUSTMASTER=y
CONFIG_HID_ZEROPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_MON=y
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index 193448f31284..eb4d204bff47 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -324,7 +324,6 @@ CONFIG_SND_USB_CAIAQ=m
CONFIG_SND_SOC=y
# CONFIG_USB_HID is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_ACM=m
diff --git a/arch/arm/configs/s3c6400_defconfig b/arch/arm/configs/s3c6400_defconfig
index 3a186d653dac..e2f9fa5bb54b 100644
--- a/arch/arm/configs/s3c6400_defconfig
+++ b/arch/arm/configs/s3c6400_defconfig
@@ -56,7 +56,6 @@ CONFIG_SND_S3C24XX_SOC=m
CONFIG_SND_SOC_SMDK_WM9713=m
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_ACM=m
CONFIG_USB_PRINTER=m
diff --git a/arch/arm/configs/spitz_defconfig b/arch/arm/configs/spitz_defconfig
index 2e0419d1b964..a1ede1966baf 100644
--- a/arch/arm/configs/spitz_defconfig
+++ b/arch/arm/configs/spitz_defconfig
@@ -166,7 +166,6 @@ CONFIG_HID_SAMSUNG=m
CONFIG_HID_SONY=m
CONFIG_HID_SUNPLUS=m
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=m
CONFIG_USB_OHCI_HCD=m
CONFIG_USB_SL811_HCD=m
diff --git a/arch/arm/configs/tct_hammer_defconfig b/arch/arm/configs/tct_hammer_defconfig
index 71277a1591ba..7209a2caefcf 100644
--- a/arch/arm/configs/tct_hammer_defconfig
+++ b/arch/arm/configs/tct_hammer_defconfig
@@ -47,7 +47,6 @@ CONFIG_BLK_DEV_RAM_SIZE=10240
# CONFIG_VGA_CONSOLE is not set
# CONFIG_HID_SUPPORT is not set
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_MON=y
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig
index 3162173fa75a..932ee4e4a13a 100644
--- a/arch/arm/configs/trizeps4_defconfig
+++ b/arch/arm/configs/trizeps4_defconfig
@@ -165,7 +165,6 @@ CONFIG_SND_PXA2XX_AC97=y
CONFIG_SND_USB_AUDIO=m
# CONFIG_USB_HID is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_STORAGE=m
diff --git a/arch/arm/configs/viper_defconfig b/arch/arm/configs/viper_defconfig
index d36e0d3c86ec..0d717a5eff29 100644
--- a/arch/arm/configs/viper_defconfig
+++ b/arch/arm/configs/viper_defconfig
@@ -127,7 +127,6 @@ CONFIG_SND_MIXER_OSS=m
CONFIG_SND_PCM_OSS=m
CONFIG_SND_PXA2XX_AC97=m
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_ISP116X_HCD=m
CONFIG_USB_SL811_HCD=m
CONFIG_USB_R8A66597_HCD=m
diff --git a/arch/arm/configs/zeus_defconfig b/arch/arm/configs/zeus_defconfig
index 731d4f985310..cd11da8b5123 100644
--- a/arch/arm/configs/zeus_defconfig
+++ b/arch/arm/configs/zeus_defconfig
@@ -132,7 +132,6 @@ CONFIG_SND_SOC=m
CONFIG_SND_PXA2XX_SOC=m
# CONFIG_HID_SUPPORT is not set
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_OHCI_HCD=m
CONFIG_USB_ACM=m
CONFIG_USB_STORAGE=m
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 46de789ad3ae..0c4c200e1221 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -95,7 +95,7 @@ static int hsusb_phy_clk_reset(struct clk *phy_clk)
static struct msm_otg_platform_data msm_otg_pdata = {
.phy_init_seq = hsusb_phy_init_seq,
- .mode = USB_PERIPHERAL,
+ .mode = USB_DR_MODE_PERIPHERAL,
.otg_control = OTG_PHY_CONTROL,
.link_clk_reset = hsusb_link_clk_reset,
.phy_clk_reset = hsusb_phy_clk_reset,
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index 9169ec324a43..4c748616ef47 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -116,7 +116,7 @@ static int hsusb_phy_clk_reset(struct clk *phy_clk)
static struct msm_otg_platform_data msm_otg_pdata = {
.phy_init_seq = hsusb_phy_init_seq,
- .mode = USB_PERIPHERAL,
+ .mode = USB_DR_MODE_PERIPHERAL,
.otg_control = OTG_PHY_CONTROL,
.link_clk_reset = hsusb_link_clk_reset,
.phy_clk_reset = hsusb_phy_clk_reset,
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index d6ed819ff15c..660bfc5a70d7 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -33,7 +33,6 @@
#include <linux/mtd/nand.h>
#include <linux/mmc/host.h>
#include <linux/usb/phy.h>
-#include <linux/usb/usb_phy_gen_xceiv.h>
#include <linux/regulator/machine.h>
#include <linux/i2c/twl.h>
diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c
index 10855eb4ccc1..745367c0c2bb 100644
--- a/arch/arm/mach-omap2/usb-host.c
+++ b/arch/arm/mach-omap2/usb-host.c
@@ -28,7 +28,7 @@
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/usb/phy.h>
-#include <linux/usb/usb_phy_gen_xceiv.h>
+#include <linux/usb/usb_phy_generic.h>
#include "soc.h"
#include "omap_device.h"
@@ -349,7 +349,7 @@ static struct fixed_voltage_config hsusb_reg_config = {
/* .init_data filled later */
};
-static const char *nop_name = "usb_phy_gen_xceiv"; /* NOP PHY driver */
+static const char *nop_name = "usb_phy_generic"; /* NOP PHY driver */
static const char *reg_name = "reg-fixed-voltage"; /* Regulator driver */
/**
@@ -435,7 +435,7 @@ int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys)
struct platform_device *pdev;
char *phy_id;
struct platform_device_info pdevinfo;
- struct usb_phy_gen_xceiv_platform_data nop_pdata;
+ struct usb_phy_generic_platform_data nop_pdata;
for (i = 0; i < num_phys; i++) {
@@ -469,8 +469,8 @@ int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys)
pdevinfo.id = phy->port;
pdevinfo.data = &nop_pdata;
pdevinfo.size_data =
- sizeof(struct usb_phy_gen_xceiv_platform_data);
- scnprintf(phy_id, MAX_STR, "usb_phy_gen_xceiv.%d",
+ sizeof(struct usb_phy_generic_platform_data);
+ scnprintf(phy_id, MAX_STR, "usb_phy_generic.%d",
phy->port);
pdev = platform_device_register_full(&pdevinfo);
if (IS_ERR(pdev)) {
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index b19d1c361cab..205f9bf3821e 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -413,7 +413,7 @@ static struct fixed_voltage_config can_regulator_pdata = {
static struct platform_device can_regulator_device = {
.name = "reg-fixed-volage",
- .id = -1,
+ .id = 0,
.dev = {
.platform_data = &can_regulator_pdata,
},
@@ -510,18 +510,6 @@ struct platform_device zeus_max6369_device = {
.num_resources = 1,
};
-static struct platform_device *zeus_devices[] __initdata = {
- &zeus_serial_device,
- &zeus_mtd_devices[0],
- &zeus_dm9k0_device,
- &zeus_dm9k1_device,
- &zeus_sram_device,
- &zeus_leds_device,
- &zeus_pcmcia_device,
- &zeus_max6369_device,
- &can_regulator_device,
-};
-
/* AC'97 */
static pxa2xx_audio_ops_t zeus_ac97_info = {
.reset_gpio = 95,
@@ -532,44 +520,50 @@ static pxa2xx_audio_ops_t zeus_ac97_info = {
* USB host
*/
-static int zeus_ohci_init(struct device *dev)
-{
- int err;
-
- /* Switch on port 2. */
- if ((err = gpio_request(ZEUS_USB2_PWREN_GPIO, "USB2_PWREN"))) {
- dev_err(dev, "Can't request USB2_PWREN\n");
- return err;
- }
-
- if ((err = gpio_direction_output(ZEUS_USB2_PWREN_GPIO, 1))) {
- gpio_free(ZEUS_USB2_PWREN_GPIO);
- dev_err(dev, "Can't enable USB2_PWREN\n");
- return err;
- }
+static struct regulator_consumer_supply zeus_ohci_regulator_supplies[] = {
+ REGULATOR_SUPPLY("vbus2", "pxa27x-ohci"),
+};
- /* Port 2 is shared between host and client interface. */
- UP2OCR = UP2OCR_HXOE | UP2OCR_HXS | UP2OCR_DMPDE | UP2OCR_DPPDE;
+static struct regulator_init_data zeus_ohci_regulator_data = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(zeus_ohci_regulator_supplies),
+ .consumer_supplies = zeus_ohci_regulator_supplies,
+};
- return 0;
-}
+static struct fixed_voltage_config zeus_ohci_regulator_config = {
+ .supply_name = "vbus2",
+ .microvolts = 5000000, /* 5.0V */
+ .gpio = ZEUS_USB2_PWREN_GPIO,
+ .enable_high = 1,
+ .startup_delay = 0,
+ .init_data = &zeus_ohci_regulator_data,
+};
-static void zeus_ohci_exit(struct device *dev)
-{
- /* Power-off port 2 */
- gpio_direction_output(ZEUS_USB2_PWREN_GPIO, 0);
- gpio_free(ZEUS_USB2_PWREN_GPIO);
-}
+static struct platform_device zeus_ohci_regulator_device = {
+ .name = "reg-fixed-voltage",
+ .id = 1,
+ .dev = {
+ .platform_data = &zeus_ohci_regulator_config,
+ },
+};
static struct pxaohci_platform_data zeus_ohci_platform_data = {
.port_mode = PMM_NPS_MODE,
/* Clear Power Control Polarity Low and set Power Sense
* Polarity Low. Supply power to USB ports. */
.flags = ENABLE_PORT_ALL | POWER_SENSE_LOW,
- .init = zeus_ohci_init,
- .exit = zeus_ohci_exit,
};
+static void zeus_register_ohci(void)
+{
+ /* Port 2 is shared between host and client interface. */
+ UP2OCR = UP2OCR_HXOE | UP2OCR_HXS | UP2OCR_DMPDE | UP2OCR_DPPDE;
+
+ pxa_set_ohci_info(&zeus_ohci_platform_data);
+}
+
/*
* Flat Panel
*/
@@ -677,6 +671,19 @@ static struct pxa2xx_udc_mach_info zeus_udc_info = {
.udc_command = zeus_udc_command,
};
+static struct platform_device *zeus_devices[] __initdata = {
+ &zeus_serial_device,
+ &zeus_mtd_devices[0],
+ &zeus_dm9k0_device,
+ &zeus_dm9k1_device,
+ &zeus_sram_device,
+ &zeus_leds_device,
+ &zeus_pcmcia_device,
+ &zeus_max6369_device,
+ &can_regulator_device,
+ &zeus_ohci_regulator_device,
+};
+
#ifdef CONFIG_PM
static void zeus_power_off(void)
{
@@ -847,7 +854,7 @@ static void __init zeus_init(void)
platform_add_devices(zeus_devices, ARRAY_SIZE(zeus_devices));
- pxa_set_ohci_info(&zeus_ohci_platform_data);
+ zeus_register_ohci();
if (zeus_setup_fb_gpios())
pr_err("Failed to setup fb gpios\n");
diff --git a/arch/avr32/configs/hammerhead_defconfig b/arch/avr32/configs/hammerhead_defconfig
index 18db853386c8..4912f0aadaa1 100644
--- a/arch/avr32/configs/hammerhead_defconfig
+++ b/arch/avr32/configs/hammerhead_defconfig
@@ -117,7 +117,6 @@ CONFIG_HID_SAMSUNG=m
CONFIG_HID_SONY=m
CONFIG_HID_SUNPLUS=m
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_MON=m
CONFIG_USB_ISP116X_HCD=m
diff --git a/arch/blackfin/configs/BF526-EZBRD_defconfig b/arch/blackfin/configs/BF526-EZBRD_defconfig
index 2f2c6acf210c..1759fad54017 100644
--- a/arch/blackfin/configs/BF526-EZBRD_defconfig
+++ b/arch/blackfin/configs/BF526-EZBRD_defconfig
@@ -123,7 +123,6 @@ CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_OTG_BLACKLIST_HUB=y
CONFIG_USB_MON=y
diff --git a/arch/blackfin/configs/BF527-EZKIT-V2_defconfig b/arch/blackfin/configs/BF527-EZKIT-V2_defconfig
index 91535c38e7f2..357729682c00 100644
--- a/arch/blackfin/configs/BF527-EZKIT-V2_defconfig
+++ b/arch/blackfin/configs/BF527-EZKIT-V2_defconfig
@@ -147,7 +147,6 @@ CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_OTG_BLACKLIST_HUB=y
CONFIG_USB_MON=y
diff --git a/arch/blackfin/configs/BF527-EZKIT_defconfig b/arch/blackfin/configs/BF527-EZKIT_defconfig
index af2738c7441b..2e73a5d33da8 100644
--- a/arch/blackfin/configs/BF527-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF527-EZKIT_defconfig
@@ -141,7 +141,6 @@ CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_OTG_BLACKLIST_HUB=y
CONFIG_USB_MON=y
diff --git a/arch/blackfin/configs/BF548-EZKIT_defconfig b/arch/blackfin/configs/BF548-EZKIT_defconfig
index e716fdfd2cf2..f0a2ddf5de46 100644
--- a/arch/blackfin/configs/BF548-EZKIT_defconfig
+++ b/arch/blackfin/configs/BF548-EZKIT_defconfig
@@ -159,7 +159,6 @@ CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_OTG_BLACKLIST_HUB=y
CONFIG_USB_MON=y
diff --git a/arch/blackfin/configs/CM-BF527_defconfig b/arch/blackfin/configs/CM-BF527_defconfig
index f59c80ee78e3..05108b85ab12 100644
--- a/arch/blackfin/configs/CM-BF527_defconfig
+++ b/arch/blackfin/configs/CM-BF527_defconfig
@@ -95,7 +95,6 @@ CONFIG_WATCHDOG=y
CONFIG_BFIN_WDT=y
CONFIG_USB=m
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_OTG_BLACKLIST_HUB=y
CONFIG_USB_MON=m
diff --git a/arch/blackfin/configs/CM-BF548_defconfig b/arch/blackfin/configs/CM-BF548_defconfig
index b9af4fa69984..9ff79df6825c 100644
--- a/arch/blackfin/configs/CM-BF548_defconfig
+++ b/arch/blackfin/configs/CM-BF548_defconfig
@@ -94,7 +94,6 @@ CONFIG_WATCHDOG=y
CONFIG_BFIN_WDT=y
# CONFIG_HID_SUPPORT is not set
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_MON=m
CONFIG_USB_MUSB_HDRC=m
diff --git a/arch/blackfin/configs/IP0X_defconfig b/arch/blackfin/configs/IP0X_defconfig
index 629516578760..5adf0da58499 100644
--- a/arch/blackfin/configs/IP0X_defconfig
+++ b/arch/blackfin/configs/IP0X_defconfig
@@ -73,7 +73,6 @@ CONFIG_SPI_BFIN5XX=y
# CONFIG_HWMON is not set
CONFIG_WATCHDOG=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_OTG_WHITELIST=y
CONFIG_USB_MON=y
CONFIG_USB_ISP1362_HCD=y
diff --git a/arch/ia64/configs/bigsur_defconfig b/arch/ia64/configs/bigsur_defconfig
index cf5993f05d4f..4c4ac163c600 100644
--- a/arch/ia64/configs/bigsur_defconfig
+++ b/arch/ia64/configs/bigsur_defconfig
@@ -75,7 +75,6 @@ CONFIG_SND_PCM_OSS=m
CONFIG_SND_CS4281=m
CONFIG_USB_HIDDEV=y
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=m
CONFIG_USB_UHCI_HCD=m
CONFIG_USB_ACM=m
diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig
index b4efaf2bc13e..e8ed3ae70aae 100644
--- a/arch/ia64/configs/generic_defconfig
+++ b/arch/ia64/configs/generic_defconfig
@@ -143,7 +143,6 @@ CONFIG_HID_SAMSUNG=m
CONFIG_HID_SONY=m
CONFIG_HID_SUNPLUS=m
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=m
CONFIG_USB_EHCI_HCD=m
CONFIG_USB_OHCI_HCD=m
diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig
index f64980dd20c3..d663efd1e4db 100644
--- a/arch/ia64/configs/gensparse_defconfig
+++ b/arch/ia64/configs/gensparse_defconfig
@@ -126,7 +126,6 @@ CONFIG_SND_CS46XX=m
CONFIG_SND_EMU10K1=m
CONFIG_SND_FM801=m
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=m
CONFIG_USB_EHCI_HCD=m
CONFIG_USB_OHCI_HCD=m
diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig
index 0fed9ae5a42a..c8a3f40e77f6 100644
--- a/arch/ia64/configs/tiger_defconfig
+++ b/arch/ia64/configs/tiger_defconfig
@@ -102,7 +102,6 @@ CONFIG_DRM_RADEON=m
CONFIG_DRM_MGA=m
CONFIG_DRM_SIS=m
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_EHCI_HCD=m
CONFIG_USB_OHCI_HCD=m
CONFIG_USB_UHCI_HCD=y
diff --git a/arch/mips/configs/fuloong2e_defconfig b/arch/mips/configs/fuloong2e_defconfig
index e5b73de08fc5..002680648dcb 100644
--- a/arch/mips/configs/fuloong2e_defconfig
+++ b/arch/mips/configs/fuloong2e_defconfig
@@ -188,7 +188,6 @@ CONFIG_USB_KBD=y
CONFIG_USB_MOUSE=y
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_OTG_WHITELIST=y
CONFIG_USB_WUSB_CBAF=m
diff --git a/arch/mips/configs/lemote2f_defconfig b/arch/mips/configs/lemote2f_defconfig
index 343bebc4b63b..227a9de32246 100644
--- a/arch/mips/configs/lemote2f_defconfig
+++ b/arch/mips/configs/lemote2f_defconfig
@@ -297,7 +297,6 @@ CONFIG_HID_WACOM=m
CONFIG_HID_ZEROPLUS=m
CONFIG_ZEROPLUS_FF=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_DYNAMIC_MINORS=y
CONFIG_USB_OTG_WHITELIST=y
diff --git a/arch/mips/configs/mpc30x_defconfig b/arch/mips/configs/mpc30x_defconfig
index c16de9812920..7a346605c498 100644
--- a/arch/mips/configs/mpc30x_defconfig
+++ b/arch/mips/configs/mpc30x_defconfig
@@ -47,7 +47,6 @@ CONFIG_GPIO_VR41XX=y
# CONFIG_VGA_CONSOLE is not set
# CONFIG_HID_SUPPORT is not set
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_OHCI_HCD=m
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_VR41XX=y
diff --git a/arch/mips/configs/msp71xx_defconfig b/arch/mips/configs/msp71xx_defconfig
index d1142e9cd9a1..201edfb2637d 100644
--- a/arch/mips/configs/msp71xx_defconfig
+++ b/arch/mips/configs/msp71xx_defconfig
@@ -67,7 +67,6 @@ CONFIG_I2C_CHARDEV=y
CONFIG_I2C_PMCMSP=y
# CONFIG_USB_HID is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
diff --git a/arch/mips/configs/mtx1_defconfig b/arch/mips/configs/mtx1_defconfig
index 593946afc483..d269a5326a30 100644
--- a/arch/mips/configs/mtx1_defconfig
+++ b/arch/mips/configs/mtx1_defconfig
@@ -575,7 +575,6 @@ CONFIG_USB_HIDDEV=y
CONFIG_USB_KBD=m
CONFIG_USB_MOUSE=m
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=m
CONFIG_USB_EHCI_HCD=m
CONFIG_USB_EHCI_ROOT_HUB_TT=y
diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig
index 59d9d2fdcd48..73e7bf49461c 100644
--- a/arch/mips/configs/rm200_defconfig
+++ b/arch/mips/configs/rm200_defconfig
@@ -301,7 +301,6 @@ CONFIG_USB_HIDDEV=y
CONFIG_USB_KBD=m
CONFIG_USB_MOUSE=m
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=m
CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
diff --git a/arch/mips/configs/sb1250_swarm_defconfig b/arch/mips/configs/sb1250_swarm_defconfig
index 5b0463ef9389..51bab13ef6f8 100644
--- a/arch/mips/configs/sb1250_swarm_defconfig
+++ b/arch/mips/configs/sb1250_swarm_defconfig
@@ -72,7 +72,6 @@ CONFIG_SERIO_RAW=m
# CONFIG_HW_RANDOM is not set
# CONFIG_HWMON is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_OHCI_HCD=y
CONFIG_EXT2_FS=y
diff --git a/arch/mips/configs/tb0219_defconfig b/arch/mips/configs/tb0219_defconfig
index 30036b4cbeb1..11f51505d562 100644
--- a/arch/mips/configs/tb0219_defconfig
+++ b/arch/mips/configs/tb0219_defconfig
@@ -72,7 +72,6 @@ CONFIG_GPIO_TB0219=y
# CONFIG_VGA_CONSOLE is not set
# CONFIG_HID_SUPPORT is not set
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=m
CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
diff --git a/arch/mips/configs/tb0226_defconfig b/arch/mips/configs/tb0226_defconfig
index 81bfa1d4d8e3..d99b1905a1ba 100644
--- a/arch/mips/configs/tb0226_defconfig
+++ b/arch/mips/configs/tb0226_defconfig
@@ -69,7 +69,6 @@ CONFIG_SERIAL_VR41XX_CONSOLE=y
# CONFIG_VGA_CONSOLE is not set
# CONFIG_HID_SUPPORT is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/parisc/configs/c3000_defconfig b/arch/parisc/configs/c3000_defconfig
index acacd348df89..fb92b8920785 100644
--- a/arch/parisc/configs/c3000_defconfig
+++ b/arch/parisc/configs/c3000_defconfig
@@ -127,8 +127,6 @@ CONFIG_SND_SEQUENCER_OSS=y
CONFIG_SND_AD1889=y
CONFIG_USB_HIDDEV=y
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_PRINTER=m
CONFIG_USB_STORAGE=m
diff --git a/arch/parisc/configs/default_defconfig b/arch/parisc/configs/default_defconfig
index ba61495e1fa4..4d8127e8428a 100644
--- a/arch/parisc/configs/default_defconfig
+++ b/arch/parisc/configs/default_defconfig
@@ -145,7 +145,6 @@ CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_HID_TOPSEED=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_UHCI_HCD=y
diff --git a/arch/parisc/configs/generic-64bit_defconfig b/arch/parisc/configs/generic-64bit_defconfig
index 28c1b5de044e..dc0d7ce71ea7 100644
--- a/arch/parisc/configs/generic-64bit_defconfig
+++ b/arch/parisc/configs/generic-64bit_defconfig
@@ -219,7 +219,6 @@ CONFIG_HIDRAW=y
CONFIG_HID_PID=y
CONFIG_USB_HIDDEV=y
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_DYNAMIC_MINORS=y
CONFIG_USB_MON=m
diff --git a/arch/powerpc/configs/40x/ep405_defconfig b/arch/powerpc/configs/40x/ep405_defconfig
index cf06d42f2c03..e9d84b5d0ab6 100644
--- a/arch/powerpc/configs/40x/ep405_defconfig
+++ b/arch/powerpc/configs/40x/ep405_defconfig
@@ -57,7 +57,6 @@ CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_THERMAL=y
CONFIG_VIDEO_OUTPUT_CONTROL=m
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
diff --git a/arch/powerpc/configs/44x/canyonlands_defconfig b/arch/powerpc/configs/44x/canyonlands_defconfig
index 7b8abd1b88b0..9919a91add12 100644
--- a/arch/powerpc/configs/44x/canyonlands_defconfig
+++ b/arch/powerpc/configs/44x/canyonlands_defconfig
@@ -71,7 +71,6 @@ CONFIG_I2C_IBM_IIC=y
CONFIG_SENSORS_AD7414=y
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=m
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/powerpc/configs/44x/currituck_defconfig b/arch/powerpc/configs/44x/currituck_defconfig
index 4192322f8a7f..47de68261443 100644
--- a/arch/powerpc/configs/44x/currituck_defconfig
+++ b/arch/powerpc/configs/44x/currituck_defconfig
@@ -71,7 +71,6 @@ CONFIG_I2C_IBM_IIC=y
# CONFIG_HWMON is not set
CONFIG_THERMAL=y
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
CONFIG_RTC_CLASS=y
diff --git a/arch/powerpc/configs/44x/sam440ep_defconfig b/arch/powerpc/configs/44x/sam440ep_defconfig
index ca088cd581af..9622eb2a3e37 100644
--- a/arch/powerpc/configs/44x/sam440ep_defconfig
+++ b/arch/powerpc/configs/44x/sam440ep_defconfig
@@ -83,7 +83,6 @@ CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_EHCI_HCD=m
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/powerpc/configs/52xx/cm5200_defconfig b/arch/powerpc/configs/52xx/cm5200_defconfig
index 4f84a0b2fbf3..0dc99e141035 100644
--- a/arch/powerpc/configs/52xx/cm5200_defconfig
+++ b/arch/powerpc/configs/52xx/cm5200_defconfig
@@ -64,7 +64,6 @@ CONFIG_I2C_MPC=y
# CONFIG_HWMON is not set
CONFIG_WATCHDOG=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
diff --git a/arch/powerpc/configs/52xx/pcm030_defconfig b/arch/powerpc/configs/52xx/pcm030_defconfig
index 2401e2554329..1d03c35540c7 100644
--- a/arch/powerpc/configs/52xx/pcm030_defconfig
+++ b/arch/powerpc/configs/52xx/pcm030_defconfig
@@ -76,7 +76,6 @@ CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MPC=y
# CONFIG_HWMON is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_OHCI_HCD=m
# CONFIG_USB_OHCI_HCD_PPC_SOC is not set
diff --git a/arch/powerpc/configs/52xx/tqm5200_defconfig b/arch/powerpc/configs/52xx/tqm5200_defconfig
index 21c841e0f482..ca83ec88b114 100644
--- a/arch/powerpc/configs/52xx/tqm5200_defconfig
+++ b/arch/powerpc/configs/52xx/tqm5200_defconfig
@@ -75,7 +75,6 @@ CONFIG_FB_FOREIGN_ENDIAN=y
CONFIG_FB_SM501=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_MON=y
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig b/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
index 0b73b7f9d112..4b4a2a9133a5 100644
--- a/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
+++ b/arch/powerpc/configs/83xx/mpc8313_rdb_defconfig
@@ -74,7 +74,6 @@ CONFIG_WATCHDOG=y
CONFIG_VIDEO_OUTPUT_CONTROL=m
# CONFIG_USB_HID is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_FSL=y
diff --git a/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig b/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
index 97ac3b993cb6..5871395573c5 100644
--- a/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
+++ b/arch/powerpc/configs/83xx/mpc8315_rdb_defconfig
@@ -71,7 +71,6 @@ CONFIG_WATCHDOG=y
CONFIG_VIDEO_OUTPUT_CONTROL=m
# CONFIG_USB_HID is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_FSL=y
diff --git a/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig b/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
index b4da1a7e6449..5adc4cea42d3 100644
--- a/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
+++ b/arch/powerpc/configs/83xx/mpc832x_rdb_defconfig
@@ -61,7 +61,6 @@ CONFIG_WATCHDOG=y
CONFIG_VIDEO_OUTPUT_CONTROL=m
# CONFIG_USB_HID is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/powerpc/configs/83xx/mpc834x_itx_defconfig b/arch/powerpc/configs/83xx/mpc834x_itx_defconfig
index 291f8221d5a6..82b6b6c88d6a 100644
--- a/arch/powerpc/configs/83xx/mpc834x_itx_defconfig
+++ b/arch/powerpc/configs/83xx/mpc834x_itx_defconfig
@@ -71,7 +71,6 @@ CONFIG_SPI_BITBANG=y
CONFIG_WATCHDOG=y
CONFIG_VIDEO_OUTPUT_CONTROL=m
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_FSL=y
diff --git a/arch/powerpc/configs/83xx/sbc834x_defconfig b/arch/powerpc/configs/83xx/sbc834x_defconfig
index a3bcda67d2d9..4ae385894c64 100644
--- a/arch/powerpc/configs/83xx/sbc834x_defconfig
+++ b/arch/powerpc/configs/83xx/sbc834x_defconfig
@@ -70,7 +70,6 @@ CONFIG_I2C_MPC=y
CONFIG_WATCHDOG=y
# CONFIG_USB_HID is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_FSL=y
diff --git a/arch/powerpc/configs/85xx/ge_imp3a_defconfig b/arch/powerpc/configs/85xx/ge_imp3a_defconfig
index c9765b54dd1a..dc939de9b5b0 100644
--- a/arch/powerpc/configs/85xx/ge_imp3a_defconfig
+++ b/arch/powerpc/configs/85xx/ge_imp3a_defconfig
@@ -158,7 +158,6 @@ CONFIG_HID_TOPSEED=y
CONFIG_HID_THRUSTMASTER=y
CONFIG_HID_ZEROPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_EHCI_FSL=y
diff --git a/arch/powerpc/configs/85xx/socrates_defconfig b/arch/powerpc/configs/85xx/socrates_defconfig
index e5147488c000..435fd408eef1 100644
--- a/arch/powerpc/configs/85xx/socrates_defconfig
+++ b/arch/powerpc/configs/85xx/socrates_defconfig
@@ -86,7 +86,6 @@ CONFIG_FONTS=y
CONFIG_FONT_8x16=y
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig b/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig
index 07bb81df27e0..72df8ab8449e 100644
--- a/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig
+++ b/arch/powerpc/configs/85xx/xes_mpc85xx_defconfig
@@ -125,7 +125,6 @@ CONFIG_SENSORS_LM90=y
CONFIG_WATCHDOG=y
CONFIG_VIDEO_OUTPUT_CONTROL=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_MON=y
CONFIG_USB_ISP1760_HCD=y
diff --git a/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig b/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig
index f51c7ebc181e..76f43df3dec7 100644
--- a/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig
+++ b/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig
@@ -123,7 +123,6 @@ CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/powerpc/configs/amigaone_defconfig b/arch/powerpc/configs/amigaone_defconfig
index b6d49da9c82c..8c66b13e59fc 100644
--- a/arch/powerpc/configs/amigaone_defconfig
+++ b/arch/powerpc/configs/amigaone_defconfig
@@ -108,7 +108,6 @@ CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_HID_TOPSEED=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_UHCI_HCD=y
diff --git a/arch/powerpc/configs/c2k_defconfig b/arch/powerpc/configs/c2k_defconfig
index c69f61620908..5e2aa43562b5 100644
--- a/arch/powerpc/configs/c2k_defconfig
+++ b/arch/powerpc/configs/c2k_defconfig
@@ -261,7 +261,6 @@ CONFIG_USBPCWATCHDOG=m
# CONFIG_VGA_CONSOLE is not set
# CONFIG_HID_SUPPORT is not set
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_MON=m
CONFIG_USB_EHCI_HCD=m
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index 22a403d78d34..4bee1a6d41d0 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -179,7 +179,6 @@ CONFIG_VIDEO_OUTPUT_CONTROL=m
CONFIG_HID=m
# CONFIG_USB_HID is not set
CONFIG_USB=m
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=m
CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_HCD_PPC_OF is not set
diff --git a/arch/powerpc/configs/celleb_defconfig b/arch/powerpc/configs/celleb_defconfig
index 895449ed971e..6d7b22f41b50 100644
--- a/arch/powerpc/configs/celleb_defconfig
+++ b/arch/powerpc/configs/celleb_defconfig
@@ -87,7 +87,6 @@ CONFIG_WATCHDOG=y
# CONFIG_VGA_CONSOLE is not set
CONFIG_USB_HIDDEV=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=m
diff --git a/arch/powerpc/configs/chrp32_defconfig b/arch/powerpc/configs/chrp32_defconfig
index b20554efddcc..db5b30857e1c 100644
--- a/arch/powerpc/configs/chrp32_defconfig
+++ b/arch/powerpc/configs/chrp32_defconfig
@@ -111,7 +111,6 @@ CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_HCD_PPC_OF is not set
diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig
index 1ea22fc24ea8..3c72fa615bd9 100644
--- a/arch/powerpc/configs/g5_defconfig
+++ b/arch/powerpc/configs/g5_defconfig
@@ -175,7 +175,6 @@ CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_HCD_PPC_OF is not set
diff --git a/arch/powerpc/configs/linkstation_defconfig b/arch/powerpc/configs/linkstation_defconfig
index 353435256f4c..b5e684640fdf 100644
--- a/arch/powerpc/configs/linkstation_defconfig
+++ b/arch/powerpc/configs/linkstation_defconfig
@@ -111,7 +111,6 @@ CONFIG_VIDEO_OUTPUT_CONTROL=m
CONFIG_HID=m
# CONFIG_USB_HID is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig
index 2a5afac29861..95e545d9f25c 100644
--- a/arch/powerpc/configs/maple_defconfig
+++ b/arch/powerpc/configs/maple_defconfig
@@ -79,7 +79,6 @@ CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
diff --git a/arch/powerpc/configs/mpc5200_defconfig b/arch/powerpc/configs/mpc5200_defconfig
index 8b682d1cf4d6..530601e8ccfe 100644
--- a/arch/powerpc/configs/mpc5200_defconfig
+++ b/arch/powerpc/configs/mpc5200_defconfig
@@ -113,7 +113,6 @@ CONFIG_HID_TOPSEED=y
CONFIG_HID_THRUSTMASTER=y
CONFIG_HID_ZEROPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_MON=y
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/powerpc/configs/mpc86xx_defconfig b/arch/powerpc/configs/mpc86xx_defconfig
index a1cc8179e9fd..35595ea74ff4 100644
--- a/arch/powerpc/configs/mpc86xx_defconfig
+++ b/arch/powerpc/configs/mpc86xx_defconfig
@@ -126,7 +126,6 @@ CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig
index a73626b09051..553e66278010 100644
--- a/arch/powerpc/configs/pmac32_defconfig
+++ b/arch/powerpc/configs/pmac32_defconfig
@@ -279,7 +279,6 @@ CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_HID_TOPSEED=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_DYNAMIC_MINORS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=m
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig
index 175a8b99c196..c91066944842 100644
--- a/arch/powerpc/configs/ppc6xx_defconfig
+++ b/arch/powerpc/configs/ppc6xx_defconfig
@@ -964,9 +964,7 @@ CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=m
diff --git a/arch/powerpc/configs/storcenter_defconfig b/arch/powerpc/configs/storcenter_defconfig
index ba39c785445d..60ad2c08caa6 100644
--- a/arch/powerpc/configs/storcenter_defconfig
+++ b/arch/powerpc/configs/storcenter_defconfig
@@ -72,7 +72,6 @@ CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MPC=y
# CONFIG_HWMON is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_STORAGE=y
diff --git a/arch/sh/configs/apsh4ad0a_defconfig b/arch/sh/configs/apsh4ad0a_defconfig
index 95ae23fcfdd6..ec70475da890 100644
--- a/arch/sh/configs/apsh4ad0a_defconfig
+++ b/arch/sh/configs/apsh4ad0a_defconfig
@@ -93,7 +93,6 @@ CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
CONFIG_LOGO=y
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
CONFIG_USB_MON=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_STORAGE=y
diff --git a/arch/sh/configs/ecovec24_defconfig b/arch/sh/configs/ecovec24_defconfig
index c6c2becdc8ab..0b364e3b0ff8 100644
--- a/arch/sh/configs/ecovec24_defconfig
+++ b/arch/sh/configs/ecovec24_defconfig
@@ -107,7 +107,6 @@ CONFIG_SND_SOC=y
CONFIG_SND_SOC_SH4_FSI=y
CONFIG_SND_FSI_DA7210=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_R8A66597_HCD=y
CONFIG_USB_STORAGE=y
diff --git a/arch/sh/configs/landisk_defconfig b/arch/sh/configs/landisk_defconfig
index 3670e937f2b7..6783f31315c7 100644
--- a/arch/sh/configs/landisk_defconfig
+++ b/arch/sh/configs/landisk_defconfig
@@ -80,7 +80,6 @@ CONFIG_HID_SAMSUNG=m
CONFIG_HID_SONY=m
CONFIG_HID_SUNPLUS=m
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
diff --git a/arch/sh/configs/rsk7203_defconfig b/arch/sh/configs/rsk7203_defconfig
index 47236573db83..3c4f6f4d52b0 100644
--- a/arch/sh/configs/rsk7203_defconfig
+++ b/arch/sh/configs/rsk7203_defconfig
@@ -100,7 +100,6 @@ CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_R8A66597_HCD=y
CONFIG_NEW_LEDS=y
diff --git a/arch/sh/configs/rsk7264_defconfig b/arch/sh/configs/rsk7264_defconfig
index 1600426224c2..eecdf65bb789 100644
--- a/arch/sh/configs/rsk7264_defconfig
+++ b/arch/sh/configs/rsk7264_defconfig
@@ -60,7 +60,6 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=8
CONFIG_SERIAL_SH_SCI_CONSOLE=y
# CONFIG_HWMON is not set
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_R8A66597_HCD=y
diff --git a/arch/sh/configs/rsk7269_defconfig b/arch/sh/configs/rsk7269_defconfig
index 9f062b5837d7..8370b10df357 100644
--- a/arch/sh/configs/rsk7269_defconfig
+++ b/arch/sh/configs/rsk7269_defconfig
@@ -43,7 +43,6 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=8
CONFIG_SERIAL_SH_SCI_CONSOLE=y
# CONFIG_HWMON is not set
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_R8A66597_HCD=y
diff --git a/arch/sh/configs/sdk7780_defconfig b/arch/sh/configs/sdk7780_defconfig
index ae1115849dda..6a96b9a2f7a5 100644
--- a/arch/sh/configs/sdk7780_defconfig
+++ b/arch/sh/configs/sdk7780_defconfig
@@ -100,8 +100,6 @@ CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
diff --git a/arch/sh/configs/se7343_defconfig b/arch/sh/configs/se7343_defconfig
index be9c474197b3..201acb4652f7 100644
--- a/arch/sh/configs/se7343_defconfig
+++ b/arch/sh/configs/se7343_defconfig
@@ -92,9 +92,7 @@ CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_ISP116X_HCD=y
CONFIG_UIO=y
CONFIG_EXT2_FS=y
diff --git a/arch/sh/configs/se7780_defconfig b/arch/sh/configs/se7780_defconfig
index c8c5e7f7a68d..b0ef63ce525a 100644
--- a/arch/sh/configs/se7780_defconfig
+++ b/arch/sh/configs/se7780_defconfig
@@ -94,7 +94,6 @@ CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
diff --git a/arch/sh/configs/sh2007_defconfig b/arch/sh/configs/sh2007_defconfig
index 0d2f41472a19..0c08d9244c97 100644
--- a/arch/sh/configs/sh2007_defconfig
+++ b/arch/sh/configs/sh2007_defconfig
@@ -97,7 +97,6 @@ CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
CONFIG_LOGO=y
# CONFIG_HID_SUPPORT is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DEVICE_CLASS is not set
CONFIG_USB_MON=y
CONFIG_NEW_LEDS=y
diff --git a/arch/sh/configs/sh7785lcr_defconfig b/arch/sh/configs/sh7785lcr_defconfig
index 51561f5677d8..d29da4a0f6c2 100644
--- a/arch/sh/configs/sh7785lcr_defconfig
+++ b/arch/sh/configs/sh7785lcr_defconfig
@@ -88,7 +88,6 @@ CONFIG_HID_SAMSUNG=y
CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
diff --git a/arch/sh/configs/titan_defconfig b/arch/sh/configs/titan_defconfig
index e2cbd92d520b..a77b778c745b 100644
--- a/arch/sh/configs/titan_defconfig
+++ b/arch/sh/configs/titan_defconfig
@@ -215,7 +215,6 @@ CONFIG_WATCHDOG=y
CONFIG_SH_WDT=m
# CONFIG_USB_HID is not set
CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
diff --git a/arch/sh/configs/urquell_defconfig b/arch/sh/configs/urquell_defconfig
index d7f89be9f474..1e843dbed5f0 100644
--- a/arch/sh/configs/urquell_defconfig
+++ b/arch/sh/configs/urquell_defconfig
@@ -117,7 +117,6 @@ CONFIG_HID_SONY=y
CONFIG_HID_SUNPLUS=y
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
CONFIG_USB_MON=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_STORAGE=y
diff --git a/arch/unicore32/configs/unicore32_defconfig b/arch/unicore32/configs/unicore32_defconfig
index c9dd3198b6f7..45f47f88d86a 100644
--- a/arch/unicore32/configs/unicore32_defconfig
+++ b/arch/unicore32/configs/unicore32_defconfig
@@ -149,7 +149,6 @@ CONFIG_SND_PCM_OSS=m
# USB support
CONFIG_USB_ARCH_HAS_HCD=n
CONFIG_USB=n
-CONFIG_USB_DEVICEFS=n
CONFIG_USB_PRINTER=n
CONFIG_USB_STORAGE=n
# Inventra Highspeed Dual Role Controller
diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig
index 619e7f7426c6..32d2e7056c87 100644
--- a/arch/x86/configs/i386_defconfig
+++ b/arch/x86/configs/i386_defconfig
@@ -244,7 +244,6 @@ CONFIG_HID_TOPSEED=y
CONFIG_HID_PID=y
CONFIG_USB_HIDDEV=y
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
index 6181c69b786b..a481dd4755d5 100644
--- a/arch/x86/configs/x86_64_defconfig
+++ b/arch/x86/configs/x86_64_defconfig
@@ -239,7 +239,6 @@ CONFIG_HID_TOPSEED=y
CONFIG_HID_PID=y
CONFIG_USB_HIDDEV=y
CONFIG_USB=y
-CONFIG_USB_DEBUG=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_MON=y
CONFIG_USB_EHCI_HCD=y
diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c
index f5ae57406f34..afdf383f630a 100644
--- a/drivers/gpu/drm/udl/udl_main.c
+++ b/drivers/gpu/drm/udl/udl_main.c
@@ -283,7 +283,7 @@ int udl_submit_urb(struct drm_device *dev, struct urb *urb, size_t len)
int udl_driver_load(struct drm_device *dev, unsigned long flags)
{
struct udl_device *udl;
- int ret;
+ int ret = -ENOMEM;
DRM_DEBUG("\n");
udl = kzalloc(sizeof(struct udl_device), GFP_KERNEL);
@@ -299,7 +299,6 @@ int udl_driver_load(struct drm_device *dev, unsigned long flags)
}
if (!udl_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
- ret = -ENOMEM;
DRM_ERROR("udl_alloc_urb_list failed\n");
goto err;
}
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index 47cd373e2295..79abbc8d9600 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -60,28 +60,6 @@
#define DRIVER_DESC "RedRat3 USB IR Transceiver Driver"
#define DRIVER_NAME "redrat3"
-/* module parameters */
-#ifdef CONFIG_USB_DEBUG
-static int debug = 1;
-#else
-static int debug;
-#endif
-
-#define RR3_DEBUG_STANDARD 0x1
-#define RR3_DEBUG_FUNCTION_TRACE 0x2
-
-#define rr3_dbg(dev, fmt, ...) \
- do { \
- if (debug & RR3_DEBUG_STANDARD) \
- dev_info(dev, fmt, ## __VA_ARGS__); \
- } while (0)
-
-#define rr3_ftr(dev, fmt, ...) \
- do { \
- if (debug & RR3_DEBUG_FUNCTION_TRACE) \
- dev_info(dev, fmt, ## __VA_ARGS__); \
- } while (0)
-
/* bulk data transfer types */
#define RR3_ERROR 0x01
#define RR3_MOD_SIGNAL_IN 0x20
@@ -237,13 +215,11 @@ static void redrat3_issue_async(struct redrat3_dev *rr3)
{
int res;
- rr3_ftr(rr3->dev, "Entering %s\n", __func__);
-
res = usb_submit_urb(rr3->read_urb, GFP_ATOMIC);
if (res)
- rr3_dbg(rr3->dev, "%s: receive request FAILED! "
- "(res %d, len %d)\n", __func__, res,
- rr3->read_urb->transfer_buffer_length);
+ dev_dbg(rr3->dev,
+ "%s: receive request FAILED! (res %d, len %d)\n",
+ __func__, res, rr3->read_urb->transfer_buffer_length);
}
static void redrat3_dump_fw_error(struct redrat3_dev *rr3, int code)
@@ -359,7 +335,7 @@ static void redrat3_rx_timeout(unsigned long data)
{
struct redrat3_dev *rr3 = (struct redrat3_dev *)data;
- rr3_dbg(rr3->dev, "calling ir_raw_event_reset\n");
+ dev_dbg(rr3->dev, "calling ir_raw_event_reset\n");
ir_raw_event_reset(rr3->rc);
}
@@ -377,8 +353,6 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)
return;
}
- rr3_ftr(rr3->dev, "Entered %s\n", __func__);
-
dev = rr3->dev;
/* Make sure we reset the IR kfifo after a bit of inactivity */
@@ -386,7 +360,7 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)
mod_timer(&rr3->rx_timeout, jiffies + delay);
mod_freq = redrat3_val_to_mod_freq(&rr3->irdata);
- rr3_dbg(dev, "Got mod_freq of %u\n", mod_freq);
+ dev_dbg(dev, "Got mod_freq of %u\n", mod_freq);
/* process each rr3 encoded byte into an int */
sig_size = be16_to_cpu(rr3->irdata.sig_size);
@@ -408,7 +382,7 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)
/* cap the value to IR_MAX_DURATION */
rawir.duration &= IR_MAX_DURATION;
- rr3_dbg(dev, "storing %s with duration %d (i: %d)\n",
+ dev_dbg(dev, "storing %s with duration %d (i: %d)\n",
rawir.pulse ? "pulse" : "space", rawir.duration, i);
ir_raw_event_store_with_filter(rr3->rc, &rawir);
}
@@ -421,12 +395,12 @@ static void redrat3_process_ir_data(struct redrat3_dev *rr3)
rawir.duration = US_TO_NS(2800);
else
rawir.duration = trailer;
- rr3_dbg(dev, "storing trailing space with duration %d\n",
+ dev_dbg(dev, "storing trailing space with duration %d\n",
rawir.duration);
ir_raw_event_store_with_filter(rr3->rc, &rawir);
}
- rr3_dbg(dev, "calling ir_raw_event_handle\n");
+ dev_dbg(dev, "calling ir_raw_event_handle\n");
ir_raw_event_handle(rr3->rc);
}
@@ -464,8 +438,6 @@ static int redrat3_enable_detector(struct redrat3_dev *rr3)
struct device *dev = rr3->dev;
u8 ret;
- rr3_ftr(dev, "Entering %s\n", __func__);
-
ret = redrat3_send_cmd(RR3_RC_DET_ENABLE, rr3);
if (ret != 0)
dev_dbg(dev, "%s: unexpected ret of %d\n",
@@ -486,7 +458,6 @@ static int redrat3_enable_detector(struct redrat3_dev *rr3)
static inline void redrat3_delete(struct redrat3_dev *rr3,
struct usb_device *udev)
{
- rr3_ftr(rr3->dev, "%s cleaning up\n", __func__);
usb_kill_urb(rr3->read_urb);
usb_kill_urb(rr3->flash_urb);
usb_free_urb(rr3->read_urb);
@@ -519,7 +490,7 @@ static u32 redrat3_get_timeout(struct redrat3_dev *rr3)
else {
timeout = redrat3_len_to_us(be32_to_cpup(tmp));
- rr3_dbg(rr3->dev, "Got timeout of %d ms\n", timeout / 1000);
+ dev_dbg(rr3->dev, "Got timeout of %d ms\n", timeout / 1000);
}
kfree(tmp);
@@ -535,8 +506,6 @@ static void redrat3_reset(struct redrat3_dev *rr3)
u8 *val;
int len = sizeof(u8);
- rr3_ftr(dev, "Entering %s\n", __func__);
-
rxpipe = usb_rcvctrlpipe(udev, 0);
txpipe = usb_sndctrlpipe(udev, 0);
@@ -550,19 +519,19 @@ static void redrat3_reset(struct redrat3_dev *rr3)
rc = usb_control_msg(udev, rxpipe, RR3_RESET,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
RR3_CPUCS_REG_ADDR, 0, val, len, HZ * 25);
- rr3_dbg(dev, "reset returned 0x%02x\n", rc);
+ dev_dbg(dev, "reset returned 0x%02x\n", rc);
*val = 5;
rc = usb_control_msg(udev, txpipe, RR3_SET_IR_PARAM,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
RR3_IR_IO_LENGTH_FUZZ, 0, val, len, HZ * 25);
- rr3_dbg(dev, "set ir parm len fuzz %d rc 0x%02x\n", *val, rc);
+ dev_dbg(dev, "set ir parm len fuzz %d rc 0x%02x\n", *val, rc);
*val = RR3_DRIVER_MAXLENS;
rc = usb_control_msg(udev, txpipe, RR3_SET_IR_PARAM,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
RR3_IR_IO_MAX_LENGTHS, 0, val, len, HZ * 25);
- rr3_dbg(dev, "set ir parm max lens %d rc 0x%02x\n", *val, rc);
+ dev_dbg(dev, "set ir parm max lens %d rc 0x%02x\n", *val, rc);
kfree(val);
}
@@ -572,8 +541,6 @@ static void redrat3_get_firmware_rev(struct redrat3_dev *rr3)
int rc = 0;
char *buffer;
- rr3_ftr(rr3->dev, "Entering %s\n", __func__);
-
buffer = kzalloc(sizeof(char) * (RR3_FW_VERSION_LEN + 1), GFP_KERNEL);
if (!buffer) {
dev_err(rr3->dev, "Memory allocation failure\n");
@@ -591,7 +558,6 @@ static void redrat3_get_firmware_rev(struct redrat3_dev *rr3)
dev_err(rr3->dev, "Problem fetching firmware ID\n");
kfree(buffer);
- rr3_ftr(rr3->dev, "Exiting %s\n", __func__);
}
static void redrat3_read_packet_start(struct redrat3_dev *rr3, unsigned len)
@@ -599,8 +565,6 @@ static void redrat3_read_packet_start(struct redrat3_dev *rr3, unsigned len)
struct redrat3_header *header = rr3->bulk_in_buf;
unsigned pktlen, pkttype;
- rr3_ftr(rr3->dev, "Entering %s\n", __func__);
-
/* grab the Length and type of transfer */
pktlen = be16_to_cpu(header->length);
pkttype = be16_to_cpu(header->transfer_type);
@@ -622,12 +586,12 @@ static void redrat3_read_packet_start(struct redrat3_dev *rr3, unsigned len)
case RR3_MOD_SIGNAL_IN:
memcpy(&rr3->irdata, rr3->bulk_in_buf, len);
rr3->bytes_read = len;
- rr3_dbg(rr3->dev, "bytes_read %d, pktlen %d\n",
+ dev_dbg(rr3->dev, "bytes_read %d, pktlen %d\n",
rr3->bytes_read, pktlen);
break;
default:
- rr3_dbg(rr3->dev, "ignoring packet with type 0x%02x, len of %d, 0x%02x\n",
+ dev_dbg(rr3->dev, "ignoring packet with type 0x%02x, len of %d, 0x%02x\n",
pkttype, len, pktlen);
break;
}
@@ -637,8 +601,6 @@ static void redrat3_read_packet_continue(struct redrat3_dev *rr3, unsigned len)
{
void *irdata = &rr3->irdata;
- rr3_ftr(rr3->dev, "Entering %s\n", __func__);
-
if (len + rr3->bytes_read > sizeof(rr3->irdata)) {
dev_warn(rr3->dev, "too much data for packet\n");
rr3->bytes_read = 0;
@@ -648,7 +610,7 @@ static void redrat3_read_packet_continue(struct redrat3_dev *rr3, unsigned len)
memcpy(irdata + rr3->bytes_read, rr3->bulk_in_buf, len);
rr3->bytes_read += len;
- rr3_dbg(rr3->dev, "bytes_read %d, pktlen %d\n", rr3->bytes_read,
+ dev_dbg(rr3->dev, "bytes_read %d, pktlen %d\n", rr3->bytes_read,
be16_to_cpu(rr3->irdata.header.length));
}
@@ -659,8 +621,6 @@ static int redrat3_get_ir_data(struct redrat3_dev *rr3, unsigned len)
unsigned pkttype;
int ret = 0;
- rr3_ftr(dev, "Entering %s\n", __func__);
-
if (rr3->bytes_read == 0 && len >= sizeof(struct redrat3_header)) {
redrat3_read_packet_start(rr3, len);
} else if (rr3->bytes_read != 0) {
@@ -681,7 +641,7 @@ static int redrat3_get_ir_data(struct redrat3_dev *rr3, unsigned len)
if (pkttype == RR3_MOD_SIGNAL_IN)
redrat3_process_ir_data(rr3);
else
- rr3_dbg(dev, "discarding non-signal data packet (type 0x%02x)\n",
+ dev_dbg(dev, "discarding non-signal data packet (type 0x%02x)\n",
pkttype);
out:
@@ -705,8 +665,6 @@ static void redrat3_handle_async(struct urb *urb)
return;
}
- rr3_ftr(rr3->dev, "Entering %s\n", __func__);
-
switch (urb->status) {
case 0:
ret = redrat3_get_ir_data(rr3, urb->actual_length);
@@ -743,7 +701,7 @@ static int redrat3_set_tx_carrier(struct rc_dev *rcdev, u32 carrier)
struct redrat3_dev *rr3 = rcdev->priv;
struct device *dev = rr3->dev;
- rr3_dbg(dev, "Setting modulation frequency to %u", carrier);
+ dev_dbg(dev, "Setting modulation frequency to %u", carrier);
if (carrier == 0)
return -EINVAL;
@@ -764,8 +722,6 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf,
u8 curlencheck = 0;
unsigned i, sendbuf_len;
- rr3_ftr(dev, "Entering %s\n", __func__);
-
if (rr3->transmitting) {
dev_warn(dev, "%s: transmitter already in use\n", __func__);
return -EAGAIN;
@@ -801,7 +757,7 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf,
break;
}
if (lencheck == curlencheck) {
- rr3_dbg(dev, "txbuf[%d]=%u, pos %d, enc %u\n",
+ dev_dbg(dev, "txbuf[%d]=%u, pos %d, enc %u\n",
i, txbuf[i], curlencheck, cur_sample_len);
if (curlencheck < RR3_DRIVER_MAXLENS) {
/* now convert the value to a proper
@@ -835,7 +791,7 @@ static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf,
pipe = usb_sndbulkpipe(rr3->udev, rr3->ep_out->bEndpointAddress);
ret = usb_bulk_msg(rr3->udev, pipe, irdata,
sendbuf_len, &ret_len, 10 * HZ);
- rr3_dbg(dev, "sent %d bytes, (ret %d)\n", ret_len, ret);
+ dev_dbg(dev, "sent %d bytes, (ret %d)\n", ret_len, ret);
/* now tell the hardware to transmit what we sent it */
pipe = usb_rcvctrlpipe(rr3->udev, 0);
@@ -957,8 +913,6 @@ static int redrat3_dev_probe(struct usb_interface *intf,
int pipe, i;
int retval = -ENOMEM;
- rr3_ftr(dev, "%s called\n", __func__);
-
uhi = intf->cur_altsetting;
/* find our bulk-in and bulk-out endpoints */
@@ -971,7 +925,7 @@ static int redrat3_dev_probe(struct usb_interface *intf,
((addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
((attrs & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK)) {
- rr3_dbg(dev, "found bulk-in endpoint at 0x%02x\n",
+ dev_dbg(dev, "found bulk-in endpoint at 0x%02x\n",
ep->bEndpointAddress);
/* data comes in on 0x82, 0x81 is for other data... */
if (ep->bEndpointAddress == RR3_BULK_IN_EP_ADDR)
@@ -982,7 +936,7 @@ static int redrat3_dev_probe(struct usb_interface *intf,
((addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) &&
((attrs & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK)) {
- rr3_dbg(dev, "found bulk-out endpoint at 0x%02x\n",
+ dev_dbg(dev, "found bulk-out endpoint at 0x%02x\n",
ep->bEndpointAddress);
ep_out = ep;
}
@@ -1074,7 +1028,6 @@ static int redrat3_dev_probe(struct usb_interface *intf,
/* we can register the device now, as it is ready */
usb_set_intfdata(intf, rr3);
- rr3_ftr(dev, "Exiting %s\n", __func__);
return 0;
led_free_error:
@@ -1093,8 +1046,6 @@ static void redrat3_dev_disconnect(struct usb_interface *intf)
struct usb_device *udev = interface_to_usbdev(intf);
struct redrat3_dev *rr3 = usb_get_intfdata(intf);
- rr3_ftr(&intf->dev, "Entering %s\n", __func__);
-
if (!rr3)
return;
@@ -1103,14 +1054,12 @@ static void redrat3_dev_disconnect(struct usb_interface *intf)
led_classdev_unregister(&rr3->led);
del_timer_sync(&rr3->rx_timeout);
redrat3_delete(rr3, udev);
-
- rr3_ftr(&intf->dev, "RedRat3 IR Transceiver now disconnected\n");
}
static int redrat3_dev_suspend(struct usb_interface *intf, pm_message_t message)
{
struct redrat3_dev *rr3 = usb_get_intfdata(intf);
- rr3_ftr(rr3->dev, "suspend\n");
+
led_classdev_suspend(&rr3->led);
usb_kill_urb(rr3->read_urb);
usb_kill_urb(rr3->flash_urb);
@@ -1120,7 +1069,7 @@ static int redrat3_dev_suspend(struct usb_interface *intf, pm_message_t message)
static int redrat3_dev_resume(struct usb_interface *intf)
{
struct redrat3_dev *rr3 = usb_get_intfdata(intf);
- rr3_ftr(rr3->dev, "resume\n");
+
if (usb_submit_urb(rr3->read_urb, GFP_ATOMIC))
return -EIO;
led_classdev_resume(&rr3->led);
@@ -1144,8 +1093,3 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_AUTHOR(DRIVER_AUTHOR2);
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(usb, redrat3_dev_table);
-
-module_param(debug, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable module debug spew. 0 = no debugging (default) "
- "0x1 = standard debug messages, 0x2 = function tracing debug. "
- "Flag bits are addative (i.e., 0x3 for both debug types).");
diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
index f4e0bc3d382c..bd5e4ff9e0ba 100644
--- a/drivers/media/rc/streamzap.c
+++ b/drivers/media/rc/streamzap.c
@@ -42,12 +42,6 @@
#define DRIVER_NAME "streamzap"
#define DRIVER_DESC "Streamzap Remote Control driver"
-#ifdef CONFIG_USB_DEBUG
-static bool debug = 1;
-#else
-static bool debug;
-#endif
-
#define USB_STREAMZAP_VENDOR_ID 0x0e9c
#define USB_STREAMZAP_PRODUCT_ID 0x0000
@@ -528,6 +522,3 @@ module_usb_driver(streamzap_driver);
MODULE_AUTHOR("Jarod Wilson <jarod@wilsonet.com>");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Enable debugging messages");
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c
index f9805c9353d2..3ac71339d040 100644
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
@@ -100,25 +100,11 @@ static struct ez_usb_fw firmware = {
.code = NULL,
};
-#ifdef CONFIG_USB_DEBUG
-static int debug = 1;
-#else
-static int debug;
-#endif
-
/* Debugging macros */
-#undef dbg
-#define dbg(format, arg...) \
- do { if (debug) printk(KERN_DEBUG PFX "%s: " format "\n", \
- __func__ , ## arg); } while (0)
#undef err
#define err(format, arg...) \
do { printk(KERN_ERR PFX format "\n", ## arg); } while (0)
-/* Module paramaters */
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
MODULE_FIRMWARE("orinoco_ezusb_fw");
/*
@@ -341,7 +327,7 @@ static void ezusb_request_timerfn(u_long _ctx)
ctx->state = EZUSB_CTX_REQ_TIMEOUT;
} else {
ctx->state = EZUSB_CTX_RESP_TIMEOUT;
- dbg("couldn't unlink");
+ dev_dbg(&ctx->outurb->dev->dev, "couldn't unlink\n");
atomic_inc(&ctx->refcount);
ctx->killed = 1;
ezusb_ctx_complete(ctx);
@@ -634,9 +620,9 @@ static void ezusb_request_in_callback(struct ezusb_priv *upriv,
ctx = c;
break;
}
- dbg("Skipped (0x%x/0x%x) (%d/%d)",
- le16_to_cpu(ans->hermes_rid),
- c->in_rid, ans->ans_reply_count, reply_count);
+ netdev_dbg(upriv->dev, "Skipped (0x%x/0x%x) (%d/%d)\n",
+ le16_to_cpu(ans->hermes_rid), c->in_rid,
+ ans->ans_reply_count, reply_count);
}
}
@@ -768,7 +754,7 @@ static int ezusb_submit_in_urb(struct ezusb_priv *upriv)
void *cur_buf = upriv->read_urb->transfer_buffer;
if (upriv->read_urb->status == -EINPROGRESS) {
- dbg("urb busy, not resubmiting");
+ netdev_dbg(upriv->dev, "urb busy, not resubmiting\n");
retval = -EBUSY;
goto exit;
}
@@ -838,8 +824,9 @@ static int ezusb_firmware_download(struct ezusb_priv *upriv,
memcpy(fw_buffer, &fw->code[addr], FW_BUF_SIZE);
if (variant_offset >= addr &&
variant_offset < addr + FW_BUF_SIZE) {
- dbg("Patching card_variant byte at 0x%04X",
- variant_offset);
+ netdev_dbg(upriv->dev,
+ "Patching card_variant byte at 0x%04X\n",
+ variant_offset);
fw_buffer[variant_offset - addr] = FW_VAR_VALUE;
}
retval = usb_control_msg(upriv->udev,
@@ -879,7 +866,6 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv,
BUG_ON(in_irq());
if (!upriv->udev) {
- dbg("Device disconnected");
retval = -ENODEV;
goto exit;
}
@@ -1023,8 +1009,9 @@ static int ezusb_doicmd_wait(struct hermes *hw, u16 cmd, u16 parm0, u16 parm1,
cpu_to_le16(parm1),
cpu_to_le16(parm2),
};
- dbg("0x%04X, parm0 0x%04X, parm1 0x%04X, parm2 0x%04X",
- cmd, parm0, parm1, parm2);
+ netdev_dbg(upriv->dev,
+ "0x%04X, parm0 0x%04X, parm1 0x%04X, parm2 0x%04X\n", cmd,
+ parm0, parm1, parm2);
ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_DOCMD, EZUSB_RID_ACK);
if (!ctx)
return -ENOMEM;
@@ -1045,7 +1032,7 @@ static int ezusb_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
0,
0,
};
- dbg("0x%04X, parm0 0x%04X", cmd, parm0);
+ netdev_dbg(upriv->dev, "0x%04X, parm0 0x%04X\n", cmd, parm0);
ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_DOCMD, EZUSB_RID_ACK);
if (!ctx)
return -ENOMEM;
@@ -1332,7 +1319,7 @@ static int ezusb_hard_reset(struct orinoco_private *priv)
return retval;
}
- dbg("sending control message");
+ netdev_dbg(upriv->dev, "sending control message\n");
retval = usb_control_msg(upriv->udev,
usb_sndctrlpipe(upriv->udev, 0),
EZUSB_REQUEST_TRIGER,
@@ -1401,10 +1388,8 @@ static void ezusb_bulk_in_callback(struct urb *urb)
u16 crc;
u16 hermes_rid;
- if (upriv->udev == NULL) {
- dbg("disconnected");
+ if (upriv->udev == NULL)
return;
- }
if (urb->status == -ETIMEDOUT) {
/* When a device gets unplugged we get this every time
@@ -1421,12 +1406,13 @@ static void ezusb_bulk_in_callback(struct urb *urb)
if ((urb->status == -EILSEQ)
|| (urb->status == -ENOENT)
|| (urb->status == -ECONNRESET)) {
- dbg("status %d, not resubmiting", urb->status);
+ netdev_dbg(upriv->dev, "status %d, not resubmiting\n",
+ urb->status);
return;
}
if (urb->status)
- dbg("status: %d length: %d",
- urb->status, urb->actual_length);
+ netdev_dbg(upriv->dev, "status: %d length: %d\n",
+ urb->status, urb->actual_length);
if (urb->actual_length < sizeof(*ans)) {
err("%s: short read, ignoring", __func__);
goto resubmit;
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 4906c27fa3bd..16a2f067c242 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -89,8 +89,8 @@ config PHY_EXYNOS_DP_VIDEO
config BCM_KONA_USB2_PHY
tristate "Broadcom Kona USB2 PHY Driver"
- depends on GENERIC_PHY
depends on HAS_IOMEM
+ select GENERIC_PHY
help
Enable this to support the Broadcom Kona USB 2.0 PHY.
@@ -160,6 +160,17 @@ config PHY_EXYNOS5250_USB2
particular SoC is compiled in the driver. In case of Exynos 5250 four
phys are available - device, host, HSIC0 and HSIC.
+config PHY_EXYNOS5_USBDRD
+ tristate "Exynos5 SoC series USB DRD PHY driver"
+ depends on ARCH_EXYNOS5 && OF
+ depends on HAS_IOMEM
+ select GENERIC_PHY
+ select MFD_SYSCON
+ help
+ Enable USB DRD PHY support for Exynos 5 SoC series.
+ This driver provides PHY interface for USB 3.0 DRD controller
+ present on Exynos5 SoC series.
+
config PHY_XGENE
tristate "APM X-Gene 15Gbps PHY support"
depends on HAS_IOMEM && OF && (ARM64 || COMPILE_TEST)
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 7728518572a4..b4f1d5770601 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -18,4 +18,5 @@ phy-exynos-usb2-y += phy-samsung-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o
phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o
+obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o
obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c
index 7f139326a642..ff026689358c 100644
--- a/drivers/phy/phy-exynos-mipi-video.c
+++ b/drivers/phy/phy-exynos-mipi-video.c
@@ -101,7 +101,7 @@ static struct phy *exynos_mipi_video_phy_xlate(struct device *dev,
{
struct exynos_mipi_video_phy *state = dev_get_drvdata(dev);
- if (WARN_ON(args->args[0] > EXYNOS_MIPI_PHYS_NUM))
+ if (WARN_ON(args->args[0] >= EXYNOS_MIPI_PHYS_NUM))
return ERR_PTR(-ENODEV);
return state->phys[args->args[0]].phy;
diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c
new file mode 100644
index 000000000000..76d862b2202f
--- /dev/null
+++ b/drivers/phy/phy-exynos5-usbdrd.c
@@ -0,0 +1,676 @@
+/*
+ * Samsung EXYNOS5 SoC series USB DRD PHY driver
+ *
+ * Phy provider for USB 3.0 DRD controller on Exynos5 SoC series
+ *
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd.
+ * Author: Vivek Gautam <gautam.vivek@samsung.com>
+ *
+ * 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/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/exynos5-pmu.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+/* Exynos USB PHY registers */
+#define EXYNOS5_FSEL_9MHZ6 0x0
+#define EXYNOS5_FSEL_10MHZ 0x1
+#define EXYNOS5_FSEL_12MHZ 0x2
+#define EXYNOS5_FSEL_19MHZ2 0x3
+#define EXYNOS5_FSEL_20MHZ 0x4
+#define EXYNOS5_FSEL_24MHZ 0x5
+#define EXYNOS5_FSEL_50MHZ 0x7
+
+/* EXYNOS5: USB 3.0 DRD PHY registers */
+#define EXYNOS5_DRD_LINKSYSTEM 0x04
+
+#define LINKSYSTEM_FLADJ_MASK (0x3f << 1)
+#define LINKSYSTEM_FLADJ(_x) ((_x) << 1)
+#define LINKSYSTEM_XHCI_VERSION_CONTROL BIT(27)
+
+#define EXYNOS5_DRD_PHYUTMI 0x08
+
+#define PHYUTMI_OTGDISABLE BIT(6)
+#define PHYUTMI_FORCESUSPEND BIT(1)
+#define PHYUTMI_FORCESLEEP BIT(0)
+
+#define EXYNOS5_DRD_PHYPIPE 0x0c
+
+#define EXYNOS5_DRD_PHYCLKRST 0x10
+
+#define PHYCLKRST_EN_UTMISUSPEND BIT(31)
+
+#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 BIT(20)
+#define PHYCLKRST_REF_SSP_EN BIT(19)
+#define PHYCLKRST_REF_CLKDIV2 BIT(18)
+
+#define PHYCLKRST_MPLL_MULTIPLIER_MASK (0x7f << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF (0x19 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF (0x32 << 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_UTMI_MASK (0x7 << 5)
+#define PHYCLKRST_FSEL_PIPE_MASK (0x7 << 8)
+#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 BIT(4)
+
+#define PHYCLKRST_REFCLKSEL_MASK (0x03 << 2)
+#define PHYCLKRST_REFCLKSEL_PAD_REFCLK (0x2 << 2)
+#define PHYCLKRST_REFCLKSEL_EXT_REFCLK (0x3 << 2)
+
+#define PHYCLKRST_PORTRESET BIT(1)
+#define PHYCLKRST_COMMONONN BIT(0)
+
+#define EXYNOS5_DRD_PHYREG0 0x14
+#define EXYNOS5_DRD_PHYREG1 0x18
+
+#define EXYNOS5_DRD_PHYPARAM0 0x1c
+
+#define PHYPARAM0_REF_USE_PAD BIT(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 BIT(3)
+#define PHYTEST_POWERDOWN_HSP BIT(2)
+
+#define EXYNOS5_DRD_PHYADP 0x2c
+
+#define EXYNOS5_DRD_PHYUTMICLKSEL 0x30
+
+#define PHYUTMICLKSEL_UTMI_CLKSEL BIT(2)
+
+#define EXYNOS5_DRD_PHYRESUME 0x34
+#define EXYNOS5_DRD_LINKPORT 0x44
+
+#define KHZ 1000
+#define MHZ (KHZ * KHZ)
+
+enum exynos5_usbdrd_phy_id {
+ EXYNOS5_DRDPHY_UTMI,
+ EXYNOS5_DRDPHY_PIPE3,
+ EXYNOS5_DRDPHYS_NUM,
+};
+
+struct phy_usb_instance;
+struct exynos5_usbdrd_phy;
+
+struct exynos5_usbdrd_phy_config {
+ u32 id;
+ void (*phy_isol)(struct phy_usb_instance *inst, u32 on);
+ void (*phy_init)(struct exynos5_usbdrd_phy *phy_drd);
+ unsigned int (*set_refclk)(struct phy_usb_instance *inst);
+};
+
+struct exynos5_usbdrd_phy_drvdata {
+ const struct exynos5_usbdrd_phy_config *phy_cfg;
+ u32 pmu_offset_usbdrd0_phy;
+ u32 pmu_offset_usbdrd1_phy;
+};
+
+/**
+ * struct exynos5_usbdrd_phy - driver data for USB 3.0 PHY
+ * @dev: pointer to device instance of this platform device
+ * @reg_phy: usb phy controller register memory base
+ * @clk: phy clock for register access
+ * @drv_data: pointer to SoC level driver data structure
+ * @phys[]: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY
+ * instances each with its 'phy' and 'phy_cfg'.
+ * @extrefclk: frequency select settings when using 'separate
+ * reference clocks' for SS and HS operations
+ * @ref_clk: reference clock to PHY block from which PHY's
+ * operational clocks are derived
+ * @ref_rate: rate of above reference clock
+ */
+struct exynos5_usbdrd_phy {
+ struct device *dev;
+ void __iomem *reg_phy;
+ struct clk *clk;
+ const struct exynos5_usbdrd_phy_drvdata *drv_data;
+ struct phy_usb_instance {
+ struct phy *phy;
+ u32 index;
+ struct regmap *reg_pmu;
+ u32 pmu_offset;
+ const struct exynos5_usbdrd_phy_config *phy_cfg;
+ } phys[EXYNOS5_DRDPHYS_NUM];
+ u32 extrefclk;
+ struct clk *ref_clk;
+ struct regulator *vbus;
+};
+
+static inline
+struct exynos5_usbdrd_phy *to_usbdrd_phy(struct phy_usb_instance *inst)
+{
+ return container_of((inst), struct exynos5_usbdrd_phy,
+ phys[(inst)->index]);
+}
+
+/*
+ * exynos5_rate_to_clk() converts the supplied clock rate to the value that
+ * can be written to the phy register.
+ */
+static unsigned int exynos5_rate_to_clk(unsigned long rate, u32 *reg)
+{
+ /* EXYNOS5_FSEL_MASK */
+
+ switch (rate) {
+ case 9600 * KHZ:
+ *reg = EXYNOS5_FSEL_9MHZ6;
+ break;
+ case 10 * MHZ:
+ *reg = EXYNOS5_FSEL_10MHZ;
+ break;
+ case 12 * MHZ:
+ *reg = EXYNOS5_FSEL_12MHZ;
+ break;
+ case 19200 * KHZ:
+ *reg = EXYNOS5_FSEL_19MHZ2;
+ break;
+ case 20 * MHZ:
+ *reg = EXYNOS5_FSEL_20MHZ;
+ break;
+ case 24 * MHZ:
+ *reg = EXYNOS5_FSEL_24MHZ;
+ break;
+ case 50 * MHZ:
+ *reg = EXYNOS5_FSEL_50MHZ;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void exynos5_usbdrd_phy_isol(struct phy_usb_instance *inst,
+ unsigned int on)
+{
+ unsigned int val;
+
+ if (!inst->reg_pmu)
+ return;
+
+ val = on ? 0 : EXYNOS5_PHY_ENABLE;
+
+ regmap_update_bits(inst->reg_pmu, inst->pmu_offset,
+ EXYNOS5_PHY_ENABLE, val);
+}
+
+/*
+ * Sets the pipe3 phy's clk as EXTREFCLK (XXTI) which is internal clock
+ * from clock core. Further sets multiplier values and spread spectrum
+ * clock settings for SuperSpeed operations.
+ */
+static unsigned int
+exynos5_usbdrd_pipe3_set_refclk(struct phy_usb_instance *inst)
+{
+ static u32 reg;
+ struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+
+ /* restore any previous reference clock settings */
+ reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
+
+ /* Use EXTREFCLK as ref clock */
+ reg &= ~PHYCLKRST_REFCLKSEL_MASK;
+ reg |= PHYCLKRST_REFCLKSEL_EXT_REFCLK;
+
+ /* FSEL settings corresponding to reference clock */
+ reg &= ~PHYCLKRST_FSEL_PIPE_MASK |
+ PHYCLKRST_MPLL_MULTIPLIER_MASK |
+ PHYCLKRST_SSC_REFCLKSEL_MASK;
+ switch (phy_drd->extrefclk) {
+ case EXYNOS5_FSEL_50MHZ:
+ reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
+ PHYCLKRST_SSC_REFCLKSEL(0x00));
+ break;
+ case EXYNOS5_FSEL_24MHZ:
+ reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF |
+ PHYCLKRST_SSC_REFCLKSEL(0x88));
+ break;
+ case EXYNOS5_FSEL_20MHZ:
+ reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF |
+ PHYCLKRST_SSC_REFCLKSEL(0x00));
+ break;
+ case EXYNOS5_FSEL_19MHZ2:
+ reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF |
+ PHYCLKRST_SSC_REFCLKSEL(0x88));
+ break;
+ default:
+ dev_dbg(phy_drd->dev, "unsupported ref clk\n");
+ break;
+ }
+
+ return reg;
+}
+
+/*
+ * Sets the utmi phy's clk as EXTREFCLK (XXTI) which is internal clock
+ * from clock core. Further sets the FSEL values for HighSpeed operations.
+ */
+static unsigned int
+exynos5_usbdrd_utmi_set_refclk(struct phy_usb_instance *inst)
+{
+ static u32 reg;
+ struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+
+ /* restore any previous reference clock settings */
+ reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
+
+ reg &= ~PHYCLKRST_REFCLKSEL_MASK;
+ reg |= PHYCLKRST_REFCLKSEL_EXT_REFCLK;
+
+ reg &= ~PHYCLKRST_FSEL_UTMI_MASK |
+ PHYCLKRST_MPLL_MULTIPLIER_MASK |
+ PHYCLKRST_SSC_REFCLKSEL_MASK;
+ reg |= PHYCLKRST_FSEL(phy_drd->extrefclk);
+
+ return reg;
+}
+
+static void exynos5_usbdrd_pipe3_init(struct exynos5_usbdrd_phy *phy_drd)
+{
+ u32 reg;
+
+ reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
+ /* Set Tx De-Emphasis level */
+ reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
+ reg |= PHYPARAM1_PCS_TXDEEMPH;
+ writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
+
+ reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
+ reg &= ~PHYTEST_POWERDOWN_SSP;
+ writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
+}
+
+static void exynos5_usbdrd_utmi_init(struct exynos5_usbdrd_phy *phy_drd)
+{
+ u32 reg;
+
+ reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
+ /* Set Loss-of-Signal Detector sensitivity */
+ reg &= ~PHYPARAM0_REF_LOSLEVEL_MASK;
+ reg |= PHYPARAM0_REF_LOSLEVEL;
+ writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
+
+ reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
+ /* Set Tx De-Emphasis level */
+ reg &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
+ reg |= PHYPARAM1_PCS_TXDEEMPH;
+ writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM1);
+
+ /* UTMI Power Control */
+ writel(PHYUTMI_OTGDISABLE, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
+
+ reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
+ reg &= ~PHYTEST_POWERDOWN_HSP;
+ writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
+}
+
+static int exynos5_usbdrd_phy_init(struct phy *phy)
+{
+ int ret;
+ u32 reg;
+ struct phy_usb_instance *inst = phy_get_drvdata(phy);
+ struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+
+ ret = clk_prepare_enable(phy_drd->clk);
+ if (ret)
+ return ret;
+
+ /* Reset USB 3.0 PHY */
+ writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYREG0);
+ writel(0x0, phy_drd->reg_phy + EXYNOS5_DRD_PHYRESUME);
+
+ /*
+ * Setting the Frame length Adj value[6:1] to default 0x20
+ * See xHCI 1.0 spec, 5.2.4
+ */
+ reg = LINKSYSTEM_XHCI_VERSION_CONTROL |
+ LINKSYSTEM_FLADJ(0x20);
+ writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_LINKSYSTEM);
+
+ reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
+ /* Select PHY CLK source */
+ reg &= ~PHYPARAM0_REF_USE_PAD;
+ writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYPARAM0);
+
+ /* This bit must be set for both HS and SS operations */
+ reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);
+ reg |= PHYUTMICLKSEL_UTMI_CLKSEL;
+ writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMICLKSEL);
+
+ /* UTMI or PIPE3 specific init */
+ inst->phy_cfg->phy_init(phy_drd);
+
+ /* reference clock settings */
+ reg = inst->phy_cfg->set_refclk(inst);
+
+ /* Digital power supply in normal operating mode */
+ reg |= 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 |
+ /* Reset the port */
+ PHYCLKRST_PORTRESET;
+
+ writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
+
+ udelay(10);
+
+ reg &= ~PHYCLKRST_PORTRESET;
+ writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
+
+ clk_disable_unprepare(phy_drd->clk);
+
+ return 0;
+}
+
+static int exynos5_usbdrd_phy_exit(struct phy *phy)
+{
+ int ret;
+ u32 reg;
+ struct phy_usb_instance *inst = phy_get_drvdata(phy);
+ struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+
+ ret = clk_prepare_enable(phy_drd->clk);
+ if (ret)
+ return ret;
+
+ reg = PHYUTMI_OTGDISABLE |
+ PHYUTMI_FORCESUSPEND |
+ PHYUTMI_FORCESLEEP;
+ writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYUTMI);
+
+ /* Resetting the PHYCLKRST enable bits to reduce leakage current */
+ reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
+ reg &= ~(PHYCLKRST_REF_SSP_EN |
+ PHYCLKRST_SSC_EN |
+ PHYCLKRST_COMMONONN);
+ writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYCLKRST);
+
+ /* Control PHYTEST to remove leakage current */
+ reg = readl(phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
+ reg |= PHYTEST_POWERDOWN_SSP |
+ PHYTEST_POWERDOWN_HSP;
+ writel(reg, phy_drd->reg_phy + EXYNOS5_DRD_PHYTEST);
+
+ clk_disable_unprepare(phy_drd->clk);
+
+ return 0;
+}
+
+static int exynos5_usbdrd_phy_power_on(struct phy *phy)
+{
+ int ret;
+ struct phy_usb_instance *inst = phy_get_drvdata(phy);
+ struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+
+ dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n");
+
+ clk_prepare_enable(phy_drd->ref_clk);
+
+ /* Enable VBUS supply */
+ if (phy_drd->vbus) {
+ ret = regulator_enable(phy_drd->vbus);
+ if (ret) {
+ dev_err(phy_drd->dev, "Failed to enable VBUS supply\n");
+ goto fail_vbus;
+ }
+ }
+
+ /* Power-on PHY*/
+ inst->phy_cfg->phy_isol(inst, 0);
+
+ return 0;
+
+fail_vbus:
+ clk_disable_unprepare(phy_drd->ref_clk);
+
+ return ret;
+}
+
+static int exynos5_usbdrd_phy_power_off(struct phy *phy)
+{
+ struct phy_usb_instance *inst = phy_get_drvdata(phy);
+ struct exynos5_usbdrd_phy *phy_drd = to_usbdrd_phy(inst);
+
+ dev_dbg(phy_drd->dev, "Request to power_off usbdrd_phy phy\n");
+
+ /* Power-off the PHY */
+ inst->phy_cfg->phy_isol(inst, 1);
+
+ /* Disable VBUS supply */
+ if (phy_drd->vbus)
+ regulator_disable(phy_drd->vbus);
+
+ clk_disable_unprepare(phy_drd->ref_clk);
+
+ return 0;
+}
+
+static struct phy *exynos5_usbdrd_phy_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ struct exynos5_usbdrd_phy *phy_drd = dev_get_drvdata(dev);
+
+ if (WARN_ON(args->args[0] > EXYNOS5_DRDPHYS_NUM))
+ return ERR_PTR(-ENODEV);
+
+ return phy_drd->phys[args->args[0]].phy;
+}
+
+static struct phy_ops exynos5_usbdrd_phy_ops = {
+ .init = exynos5_usbdrd_phy_init,
+ .exit = exynos5_usbdrd_phy_exit,
+ .power_on = exynos5_usbdrd_phy_power_on,
+ .power_off = exynos5_usbdrd_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
+ {
+ .id = EXYNOS5_DRDPHY_UTMI,
+ .phy_isol = exynos5_usbdrd_phy_isol,
+ .phy_init = exynos5_usbdrd_utmi_init,
+ .set_refclk = exynos5_usbdrd_utmi_set_refclk,
+ },
+ {
+ .id = EXYNOS5_DRDPHY_PIPE3,
+ .phy_isol = exynos5_usbdrd_phy_isol,
+ .phy_init = exynos5_usbdrd_pipe3_init,
+ .set_refclk = exynos5_usbdrd_pipe3_set_refclk,
+ },
+};
+
+const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
+ .phy_cfg = phy_cfg_exynos5,
+ .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
+ .pmu_offset_usbdrd1_phy = EXYNOS5420_USBDRD1_PHY_CONTROL,
+};
+
+const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
+ .phy_cfg = phy_cfg_exynos5,
+ .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
+};
+
+static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
+ {
+ .compatible = "samsung,exynos5250-usbdrd-phy",
+ .data = &exynos5250_usbdrd_phy
+ }, {
+ .compatible = "samsung,exynos5420-usbdrd-phy",
+ .data = &exynos5420_usbdrd_phy
+ },
+ { },
+};
+
+static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
+ struct exynos5_usbdrd_phy *phy_drd;
+ struct phy_provider *phy_provider;
+ struct resource *res;
+ const struct of_device_id *match;
+ const struct exynos5_usbdrd_phy_drvdata *drv_data;
+ struct regmap *reg_pmu;
+ u32 pmu_offset;
+ unsigned long ref_rate;
+ int i, ret;
+ int channel;
+
+ phy_drd = devm_kzalloc(dev, sizeof(*phy_drd), GFP_KERNEL);
+ if (!phy_drd)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, phy_drd);
+ phy_drd->dev = dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ phy_drd->reg_phy = devm_ioremap_resource(dev, res);
+ if (IS_ERR(phy_drd->reg_phy))
+ return PTR_ERR(phy_drd->reg_phy);
+
+ match = of_match_node(exynos5_usbdrd_phy_of_match, pdev->dev.of_node);
+
+ drv_data = match->data;
+ phy_drd->drv_data = drv_data;
+
+ phy_drd->clk = devm_clk_get(dev, "phy");
+ if (IS_ERR(phy_drd->clk)) {
+ dev_err(dev, "Failed to get clock of phy controller\n");
+ return PTR_ERR(phy_drd->clk);
+ }
+
+ phy_drd->ref_clk = devm_clk_get(dev, "ref");
+ if (IS_ERR(phy_drd->ref_clk)) {
+ dev_err(dev, "Failed to get reference clock of usbdrd phy\n");
+ return PTR_ERR(phy_drd->ref_clk);
+ }
+ ref_rate = clk_get_rate(phy_drd->ref_clk);
+
+ ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);
+ if (ret) {
+ dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n",
+ ref_rate);
+ return ret;
+ }
+
+ reg_pmu = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "samsung,pmu-syscon");
+ if (IS_ERR(reg_pmu)) {
+ dev_err(dev, "Failed to lookup PMU regmap\n");
+ return PTR_ERR(reg_pmu);
+ }
+
+ /*
+ * Exynos5420 SoC has multiple channels for USB 3.0 PHY, with
+ * each having separate power control registers.
+ * 'channel' facilitates to set such registers.
+ */
+ channel = of_alias_get_id(node, "usbdrdphy");
+ if (channel < 0)
+ dev_dbg(dev, "Not a multi-controller usbdrd phy\n");
+
+ switch (channel) {
+ case 1:
+ pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd1_phy;
+ break;
+ case 0:
+ default:
+ pmu_offset = phy_drd->drv_data->pmu_offset_usbdrd0_phy;
+ break;
+ }
+
+ /* Get Vbus regulator */
+ phy_drd->vbus = devm_regulator_get(dev, "vbus");
+ if (IS_ERR(phy_drd->vbus)) {
+ ret = PTR_ERR(phy_drd->vbus);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+
+ dev_warn(dev, "Failed to get VBUS supply regulator\n");
+ phy_drd->vbus = NULL;
+ }
+
+ dev_vdbg(dev, "Creating usbdrd_phy phy\n");
+
+ for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {
+ struct phy *phy = devm_phy_create(dev, &exynos5_usbdrd_phy_ops,
+ NULL);
+ if (IS_ERR(phy)) {
+ dev_err(dev, "Failed to create usbdrd_phy phy\n");
+ return PTR_ERR(phy);
+ }
+
+ phy_drd->phys[i].phy = phy;
+ phy_drd->phys[i].index = i;
+ phy_drd->phys[i].reg_pmu = reg_pmu;
+ phy_drd->phys[i].pmu_offset = pmu_offset;
+ phy_drd->phys[i].phy_cfg = &drv_data->phy_cfg[i];
+ phy_set_drvdata(phy, &phy_drd->phys[i]);
+ }
+
+ phy_provider = devm_of_phy_provider_register(dev,
+ exynos5_usbdrd_phy_xlate);
+ if (IS_ERR(phy_provider)) {
+ dev_err(phy_drd->dev, "Failed to register phy provider\n");
+ return PTR_ERR(phy_provider);
+ }
+
+ return 0;
+}
+
+static struct platform_driver exynos5_usb3drd_phy = {
+ .probe = exynos5_usbdrd_phy_probe,
+ .driver = {
+ .of_match_table = exynos5_usbdrd_phy_of_match,
+ .name = "exynos5_usb3drd_phy",
+ .owner = THIS_MODULE,
+ }
+};
+
+module_platform_driver(exynos5_usb3drd_phy);
+MODULE_DESCRIPTION("Samsung EXYNOS5 SoCs USB 3.0 DRD controller PHY driver");
+MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:exynos5_usb3drd_phy");
diff --git a/drivers/phy/phy-exynos5250-sata.c b/drivers/phy/phy-exynos5250-sata.c
index c9361b731fa6..05689450f93b 100644
--- a/drivers/phy/phy-exynos5250-sata.c
+++ b/drivers/phy/phy-exynos5250-sata.c
@@ -246,6 +246,6 @@ static struct platform_driver exynos_sata_phy_driver = {
module_platform_driver(exynos_sata_phy_driver);
MODULE_DESCRIPTION("Samsung SerDes PHY driver");
-MODULE_LICENSE("GPL V2");
+MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Girish K S <ks.giri@samsung.com>");
MODULE_AUTHOR("Yuvaraj C D <yuvaraj.cd@samsung.com>");
diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c
index a2205a841e5e..7007c11fe07d 100644
--- a/drivers/phy/phy-omap-usb2.c
+++ b/drivers/phy/phy-omap-usb2.c
@@ -275,18 +275,34 @@ static int omap_usb2_probe(struct platform_device *pdev)
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);
- phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
+ phy->wkupclk = devm_clk_get(phy->dev, "wkupclk");
if (IS_ERR(phy->wkupclk)) {
- dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
- return PTR_ERR(phy->wkupclk);
+ dev_warn(&pdev->dev, "unable to get wkupclk, trying old name\n");
+ phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
+ if (IS_ERR(phy->wkupclk)) {
+ dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
+ return PTR_ERR(phy->wkupclk);
+ } else {
+ dev_warn(&pdev->dev,
+ "found usb_phy_cm_clk32k, please fix DTS\n");
+ }
}
clk_prepare(phy->wkupclk);
- phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");
- if (IS_ERR(phy->optclk))
- dev_vdbg(&pdev->dev, "unable to get refclk960m\n");
- else
+ phy->optclk = devm_clk_get(phy->dev, "refclk");
+ if (IS_ERR(phy->optclk)) {
+ dev_dbg(&pdev->dev, "unable to get refclk, trying old name\n");
+ phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");
+ if (IS_ERR(phy->optclk)) {
+ dev_dbg(&pdev->dev,
+ "unable to get usb_otg_ss_refclk960m\n");
+ } else {
+ dev_warn(&pdev->dev,
+ "found usb_otg_ss_refclk960m, please fix DTS\n");
+ }
+ } else {
clk_prepare(phy->optclk);
+ }
usb_add_phy_dev(&phy->phy);
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index e6e6c4ba7145..115d8d5190d5 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -61,7 +61,6 @@
#define MAX_PHYS 3
struct sun4i_usb_phy_data {
- struct clk *clk;
void __iomem *base;
struct mutex mutex;
int num_phys;
@@ -71,6 +70,7 @@ struct sun4i_usb_phy_data {
void __iomem *pmu;
struct regulator *vbus;
struct reset_control *reset;
+ struct clk *clk;
int index;
} phys[MAX_PHYS];
};
@@ -146,13 +146,13 @@ static int sun4i_usb_phy_init(struct phy *_phy)
struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
int ret;
- ret = clk_prepare_enable(data->clk);
+ ret = clk_prepare_enable(phy->clk);
if (ret)
return ret;
ret = reset_control_deassert(phy->reset);
if (ret) {
- clk_disable_unprepare(data->clk);
+ clk_disable_unprepare(phy->clk);
return ret;
}
@@ -170,11 +170,10 @@ static int sun4i_usb_phy_init(struct phy *_phy)
static int sun4i_usb_phy_exit(struct phy *_phy)
{
struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
- struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
sun4i_usb_phy_passby(phy, 0);
reset_control_assert(phy->reset);
- clk_disable_unprepare(data->clk);
+ clk_disable_unprepare(phy->clk);
return 0;
}
@@ -224,13 +223,9 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
struct sun4i_usb_phy_data *data;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
- void __iomem *pmu = NULL;
struct phy_provider *phy_provider;
- struct reset_control *reset;
- struct regulator *vbus;
+ bool dedicated_clocks;
struct resource *res;
- struct phy *phy;
- char name[16];
int i;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
@@ -249,55 +244,64 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
else
data->disc_thresh = 2;
+ if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy"))
+ dedicated_clocks = true;
+ else
+ dedicated_clocks = false;
+
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
data->base = devm_ioremap_resource(dev, res);
if (IS_ERR(data->base))
return PTR_ERR(data->base);
- data->clk = devm_clk_get(dev, "usb_phy");
- if (IS_ERR(data->clk)) {
- dev_err(dev, "could not get usb_phy clock\n");
- return PTR_ERR(data->clk);
- }
-
/* Skip 0, 0 is the phy for otg which is not yet supported. */
for (i = 1; i < data->num_phys; i++) {
+ struct sun4i_usb_phy *phy = data->phys + i;
+ char name[16];
+
snprintf(name, sizeof(name), "usb%d_vbus", i);
- vbus = devm_regulator_get_optional(dev, name);
- if (IS_ERR(vbus)) {
- if (PTR_ERR(vbus) == -EPROBE_DEFER)
+ phy->vbus = devm_regulator_get_optional(dev, name);
+ if (IS_ERR(phy->vbus)) {
+ if (PTR_ERR(phy->vbus) == -EPROBE_DEFER)
return -EPROBE_DEFER;
- vbus = NULL;
+ phy->vbus = NULL;
+ }
+
+ if (dedicated_clocks)
+ snprintf(name, sizeof(name), "usb%d_phy", i);
+ else
+ strlcpy(name, "usb_phy", sizeof(name));
+
+ phy->clk = devm_clk_get(dev, name);
+ if (IS_ERR(phy->clk)) {
+ dev_err(dev, "failed to get clock %s\n", name);
+ return PTR_ERR(phy->clk);
}
snprintf(name, sizeof(name), "usb%d_reset", i);
- reset = devm_reset_control_get(dev, name);
- if (IS_ERR(reset)) {
+ phy->reset = devm_reset_control_get(dev, name);
+ if (IS_ERR(phy->reset)) {
dev_err(dev, "failed to get reset %s\n", name);
- return PTR_ERR(reset);
+ return PTR_ERR(phy->reset);
}
if (i) { /* No pmu for usbc0 */
snprintf(name, sizeof(name), "pmu%d", i);
res = platform_get_resource_byname(pdev,
IORESOURCE_MEM, name);
- pmu = devm_ioremap_resource(dev, res);
- if (IS_ERR(pmu))
- return PTR_ERR(pmu);
+ phy->pmu = devm_ioremap_resource(dev, res);
+ if (IS_ERR(phy->pmu))
+ return PTR_ERR(phy->pmu);
}
- phy = devm_phy_create(dev, &sun4i_usb_phy_ops, NULL);
- if (IS_ERR(phy)) {
+ phy->phy = devm_phy_create(dev, &sun4i_usb_phy_ops, NULL);
+ if (IS_ERR(phy->phy)) {
dev_err(dev, "failed to create PHY %d\n", i);
- return PTR_ERR(phy);
+ return PTR_ERR(phy->phy);
}
- data->phys[i].phy = phy;
- data->phys[i].pmu = pmu;
- data->phys[i].vbus = vbus;
- data->phys[i].reset = reset;
- data->phys[i].index = i;
- phy_set_drvdata(phy, &data->phys[i]);
+ phy->index = i;
+ phy_set_drvdata(phy->phy, &data->phys[i]);
}
dev_set_drvdata(dev, data);
@@ -311,6 +315,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
static const struct of_device_id sun4i_usb_phy_of_match[] = {
{ .compatible = "allwinner,sun4i-a10-usb-phy" },
{ .compatible = "allwinner,sun5i-a13-usb-phy" },
+ { .compatible = "allwinner,sun6i-a31-usb-phy" },
{ .compatible = "allwinner,sun7i-a20-usb-phy" },
{ },
};
diff --git a/drivers/staging/media/lirc/lirc_igorplugusb.c b/drivers/staging/media/lirc/lirc_igorplugusb.c
index f508a1372ad8..44b0d0766084 100644
--- a/drivers/staging/media/lirc/lirc_igorplugusb.c
+++ b/drivers/staging/media/lirc/lirc_igorplugusb.c
@@ -60,19 +60,6 @@
#define DRIVER_DESC "Igorplug USB remote driver for LIRC"
#define DRIVER_NAME "lirc_igorplugusb"
-/* debugging support */
-#ifdef CONFIG_USB_DEBUG
-static bool debug = true;
-#else
-static bool debug;
-#endif
-
-#define dprintk(fmt, args...) \
- do { \
- if (debug) \
- printk(KERN_DEBUG fmt, ## args); \
- } while (0)
-
/* One mode2 pulse/space has 4 bytes. */
#define CODE_LENGTH sizeof(int)
@@ -237,7 +224,7 @@ static int unregister_from_lirc(struct igorplug *ir)
return -EINVAL;
}
- dprintk(DRIVER_NAME "[%d]: calling lirc_unregister_driver\n", devnum);
+ dev_dbg(&ir->usbdev->dev, "calling lirc_unregister_driver\n");
lirc_unregister_driver(d->minor);
return devnum;
@@ -252,7 +239,7 @@ static int set_use_inc(void *data)
return -EIO;
}
- dprintk(DRIVER_NAME "[%d]: set use inc\n", ir->devnum);
+ dev_dbg(&ir->usbdev->dev, "set use inc\n");
if (!ir->usbdev)
return -ENODEV;
@@ -269,7 +256,7 @@ static void set_use_dec(void *data)
return;
}
- dprintk(DRIVER_NAME "[%d]: set use dec\n", ir->devnum);
+ dev_dbg(&ir->usbdev->dev, "set use dec\n");
}
static void send_fragment(struct igorplug *ir, struct lirc_buffer *buf,
@@ -321,7 +308,7 @@ static int igorplugusb_remote_poll(void *data, struct lirc_buffer *buf)
if (ret < DEVICE_HEADERLEN)
return -ENODATA;
- dprintk(DRIVER_NAME ": Got %d bytes. Header: %*ph\n",
+ dev_dbg(&ir->usbdev->dev, "Got %d bytes. Header: %*ph\n",
ret, 3, ir->buf_in);
do_gettimeofday(&now);
@@ -385,7 +372,7 @@ static int igorplugusb_remote_probe(struct usb_interface *intf,
char buf[63], name[128] = "";
int ret;
- dprintk(DRIVER_NAME ": usb probe called.\n");
+ dev_dbg(&intf->dev, "%s: usb probe called.\n", __func__);
dev = interface_to_usbdev(intf);
@@ -405,8 +392,8 @@ static int igorplugusb_remote_probe(struct usb_interface *intf,
devnum = dev->devnum;
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
- dprintk(DRIVER_NAME "[%d]: bytes_in_key=%zu maxp=%d\n",
- devnum, CODE_LENGTH, maxp);
+ dev_dbg(&intf->dev, "%s: bytes_in_key=%zu maxp=%d\n",
+ __func__, CODE_LENGTH, maxp);
ir = devm_kzalloc(&intf->dev, sizeof(*ir), GFP_KERNEL);
if (!ir)
@@ -525,6 +512,3 @@ MODULE_DEVICE_TABLE(usb, igorplugusb_remote_id_table);
module_param(sample_rate, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(sample_rate, "Sampling rate in Hz (default: 100)");
-
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
diff --git a/drivers/staging/usbip/userspace/README b/drivers/staging/usbip/userspace/README
index f528ba462b5f..831f49fea3ce 100644
--- a/drivers/staging/usbip/userspace/README
+++ b/drivers/staging/usbip/userspace/README
@@ -195,7 +195,6 @@ Detach the imported device:
- Shutdown firewall.
- usbip now uses TCP port 3240.
- Disable SELinux.
- - If possible, compile your kernel with CONFIG_USB_DEBUG flag and try again.
- Check the kernel and daemon messages.
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 1ae2bf39d84b..3cba892b83a2 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_USB_IMX21_HCD) += host/
obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/
obj-$(CONFIG_USB_FUSBH200_HCD) += host/
obj-$(CONFIG_USB_FOTG210_HCD) += host/
+obj-$(CONFIG_USB_MAX3421_HCD) += host/
obj-$(CONFIG_USB_C67X00_HCD) += c67x00/
@@ -58,4 +59,4 @@ obj-$(CONFIG_USB_CHIPIDEA) += chipidea/
obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs/
obj-$(CONFIG_USB_GADGET) += gadget/
-obj-$(CONFIG_USB_COMMON) += usb-common.o
+obj-$(CONFIG_USB_COMMON) += common/
diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile
index 480bd4d5710a..2f099c7df7b5 100644
--- a/drivers/usb/chipidea/Makefile
+++ b/drivers/usb/chipidea/Makefile
@@ -6,6 +6,7 @@ ci_hdrc-y := core.o otg.o
ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC) += udc.o
ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST) += host.o
ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG) += debug.o
+ci_hdrc-$(CONFIG_USB_OTG_FSM) += otg_fsm.o
# Glue/Bridge layers go here
diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
index 83d06c1455b7..ca57e3dcd3d5 100644
--- a/drivers/usb/chipidea/bits.h
+++ b/drivers/usb/chipidea/bits.h
@@ -44,9 +44,14 @@
#define DEVICEADDR_USBADR (0x7FUL << 25)
/* PORTSC */
+#define PORTSC_CCS BIT(0)
+#define PORTSC_CSC BIT(1)
+#define PORTSC_PEC BIT(3)
+#define PORTSC_OCC BIT(5)
#define PORTSC_FPR BIT(6)
#define PORTSC_SUSP BIT(7)
#define PORTSC_HSP BIT(9)
+#define PORTSC_PP BIT(12)
#define PORTSC_PTC (0x0FUL << 16)
#define PORTSC_PHCD(d) ((d) ? BIT(22) : BIT(23))
/* PTS and PTW for non lpm version only */
@@ -56,6 +61,9 @@
#define PORTSC_PTW BIT(28)
#define PORTSC_STS BIT(29)
+#define PORTSC_W1C_BITS \
+ (PORTSC_CSC | PORTSC_PEC | PORTSC_OCC)
+
/* DEVLC */
#define DEVLC_PFSC BIT(23)
#define DEVLC_PSPD (0x03UL << 25)
@@ -72,6 +80,8 @@
/* OTGSC */
#define OTGSC_IDPU BIT(5)
+#define OTGSC_HADP BIT(6)
+#define OTGSC_HABA BIT(7)
#define OTGSC_ID BIT(8)
#define OTGSC_AVV BIT(9)
#define OTGSC_ASV BIT(10)
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index e206406ae1d9..9563cb56d564 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -17,6 +17,7 @@
#include <linux/irqreturn.h>
#include <linux/usb.h>
#include <linux/usb/gadget.h>
+#include <linux/usb/otg-fsm.h>
/******************************************************************************
* DEFINE
@@ -139,6 +140,8 @@ struct hw_bank {
* @roles: array of supported roles for this controller
* @role: current role
* @is_otg: if the device is otg-capable
+ * @fsm: otg finite state machine
+ * @fsm_timer: pointer to timer list of otg fsm
* @work: work for role changing
* @wq: workqueue thread
* @qh_pool: allocation pool for queue heads
@@ -174,6 +177,8 @@ struct ci_hdrc {
struct ci_role_driver *roles[CI_ROLE_END];
enum ci_role role;
bool is_otg;
+ struct otg_fsm fsm;
+ struct ci_otg_fsm_timer_list *fsm_timer;
struct work_struct work;
struct workqueue_struct *wq;
@@ -319,6 +324,24 @@ static inline u32 hw_test_and_write(struct ci_hdrc *ci, enum ci_hw_regs reg,
return (val & mask) >> __ffs(mask);
}
+/**
+ * ci_otg_is_fsm_mode: runtime check if otg controller
+ * is in otg fsm mode.
+ */
+static inline bool ci_otg_is_fsm_mode(struct ci_hdrc *ci)
+{
+#ifdef CONFIG_USB_OTG_FSM
+ return ci->is_otg && ci->roles[CI_ROLE_HOST] &&
+ ci->roles[CI_ROLE_GADGET];
+#else
+ return false;
+#endif
+}
+
+u32 hw_read_intr_enable(struct ci_hdrc *ci);
+
+u32 hw_read_intr_status(struct ci_hdrc *ci);
+
int hw_device_reset(struct ci_hdrc *ci, u32 mode);
int hw_port_test_set(struct ci_hdrc *ci, u8 mode);
diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
index 2d51d852b474..d72b9d2de2c5 100644
--- a/drivers/usb/chipidea/ci_hdrc_msm.c
+++ b/drivers/usb/chipidea/ci_hdrc_msm.c
@@ -47,6 +47,7 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
.name = "ci_hdrc_msm",
+ .capoffset = DEF_CAPOFFSET,
.flags = CI_HDRC_REGS_SHARED |
CI_HDRC_REQUIRE_TRANSCEIVER |
CI_HDRC_DISABLE_STREAMING,
@@ -57,9 +58,21 @@ static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
static int ci_hdrc_msm_probe(struct platform_device *pdev)
{
struct platform_device *plat_ci;
+ struct usb_phy *phy;
dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n");
+ /*
+ * OTG(PHY) driver takes care of PHY initialization, clock management,
+ * powering up VBUS, mapping of registers address space and power
+ * management.
+ */
+ phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0);
+ if (IS_ERR(phy))
+ return PTR_ERR(phy);
+
+ ci_hdrc_msm_platdata.phy = phy;
+
plat_ci = ci_hdrc_add_device(&pdev->dev,
pdev->resource, pdev->num_resources,
&ci_hdrc_msm_platdata);
@@ -86,10 +99,19 @@ static int ci_hdrc_msm_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id msm_ci_dt_match[] = {
+ { .compatible = "qcom,ci-hdrc", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, msm_ci_dt_match);
+
static struct platform_driver ci_hdrc_msm_driver = {
.probe = ci_hdrc_msm_probe,
.remove = ci_hdrc_msm_remove,
- .driver = { .name = "msm_hsusb", },
+ .driver = {
+ .name = "msm_hsusb",
+ .of_match_table = msm_ci_dt_match,
+ },
};
module_platform_driver(ci_hdrc_msm_driver);
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 1cd5d0ba587c..619d13e29995 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -23,7 +23,7 @@
* - BUS: bus glue code, bus abstraction layer
*
* Compile Options
- * - CONFIG_USB_GADGET_DEBUG_FILES: enable debug facilities
+ * - CONFIG_USB_CHIPIDEA_DEBUG: enable debug facilities
* - STALL_IN: non-empty bulk-in pipes cannot be halted
* if defined mass storage compliance succeeds but with warnings
* => case 4: Hi > Dn
@@ -42,10 +42,6 @@
* - Not Supported: 15 & 16 (ISO)
*
* TODO List
- * - OTG
- * - Interrupt Traffic
- * - GET_STATUS(device) - always reports 0
- * - Gadget API (majority of optional features)
* - Suspend & Remote Wakeup
*/
#include <linux/delay.h>
@@ -74,6 +70,7 @@
#include "host.h"
#include "debug.h"
#include "otg.h"
+#include "otg_fsm.h"
/* Controller register map */
static const u8 ci_regs_nolpm[] = {
@@ -140,6 +137,26 @@ static int hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm)
}
/**
+ * hw_read_intr_enable: returns interrupt enable register
+ *
+ * This function returns register data
+ */
+u32 hw_read_intr_enable(struct ci_hdrc *ci)
+{
+ return hw_read(ci, OP_USBINTR, ~0);
+}
+
+/**
+ * hw_read_intr_status: returns interrupt status register
+ *
+ * This function returns register data
+ */
+u32 hw_read_intr_status(struct ci_hdrc *ci)
+{
+ return hw_read(ci, OP_USBSTS, ~0);
+}
+
+/**
* hw_port_test_set: writes port test mode (execute without interruption)
* @mode: new value
*
@@ -179,11 +196,10 @@ static void ci_hdrc_enter_lpm(struct ci_hdrc *ci, bool enable)
hw_write(ci, reg, PORTSC_PHCD(ci->hw_bank.lpm),
0);
/*
- * The controller needs at least 1ms to reflect
- * PHY's status, the PHY also needs some time (less
+ * the PHY needs some time (less
* than 1ms) to leave low power mode.
*/
- usleep_range(1500, 2000);
+ usleep_range(1000, 1100);
}
}
@@ -392,8 +408,14 @@ static irqreturn_t ci_irq(int irq, void *data)
irqreturn_t ret = IRQ_NONE;
u32 otgsc = 0;
- if (ci->is_otg)
- otgsc = hw_read(ci, OP_OTGSC, ~0);
+ if (ci->is_otg) {
+ otgsc = hw_read_otgsc(ci, ~0);
+ if (ci_otg_is_fsm_mode(ci)) {
+ ret = ci_otg_fsm_irq(ci);
+ if (ret == IRQ_HANDLED)
+ return ret;
+ }
+ }
/*
* Handle id change interrupt, it indicates device/host function
@@ -401,9 +423,9 @@ static irqreturn_t ci_irq(int irq, void *data)
*/
if (ci->is_otg && (otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS)) {
ci->id_event = true;
- ci_clear_otg_interrupt(ci, OTGSC_IDIS);
- disable_irq_nosync(ci->irq);
- queue_work(ci->wq, &ci->work);
+ /* Clear ID change irq status */
+ hw_write_otgsc(ci, OTGSC_IDIS, OTGSC_IDIS);
+ ci_otg_queue_work(ci);
return IRQ_HANDLED;
}
@@ -413,9 +435,9 @@ static irqreturn_t ci_irq(int irq, void *data)
*/
if (ci->is_otg && (otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS)) {
ci->b_sess_valid_event = true;
- ci_clear_otg_interrupt(ci, OTGSC_BSVIS);
- disable_irq_nosync(ci->irq);
- queue_work(ci->wq, &ci->work);
+ /* Clear BSV irq */
+ hw_write_otgsc(ci, OTGSC_BSVIS, OTGSC_BSVIS);
+ ci_otg_queue_work(ci);
return IRQ_HANDLED;
}
@@ -533,11 +555,8 @@ static void ci_get_otg_capable(struct ci_hdrc *ci)
ci->is_otg = (hw_read(ci, CAP_DCCPARAMS,
DCCPARAMS_DC | DCCPARAMS_HC)
== (DCCPARAMS_DC | DCCPARAMS_HC));
- if (ci->is_otg) {
+ if (ci->is_otg)
dev_dbg(ci->dev, "It is OTG capable controller\n");
- ci_disable_otg_interrupt(ci, OTGSC_INT_EN_BITS);
- ci_clear_otg_interrupt(ci, OTGSC_INT_STATUS_BITS);
- }
}
static int ci_hdrc_probe(struct platform_device *pdev)
@@ -599,6 +618,13 @@ static int ci_hdrc_probe(struct platform_device *pdev)
if (ret) {
dev_err(dev, "unable to init phy: %d\n", ret);
return ret;
+ } else {
+ /*
+ * The delay to sync PHY's status, the maximum delay is
+ * 2ms since the otgsc uses 1ms timer to debounce the
+ * PHY's input
+ */
+ usleep_range(2000, 2500);
}
ci->hw_bank.phys = res->start;
@@ -633,6 +659,9 @@ static int ci_hdrc_probe(struct platform_device *pdev)
}
if (ci->is_otg) {
+ /* Disable and clear all OTG irq */
+ hw_write_otgsc(ci, OTGSC_INT_EN_BITS | OTGSC_INT_STATUS_BITS,
+ OTGSC_INT_STATUS_BITS);
ret = ci_hdrc_otg_init(ci);
if (ret) {
dev_err(dev, "init otg fails, ret = %d\n", ret);
@@ -642,13 +671,9 @@ static int ci_hdrc_probe(struct platform_device *pdev)
if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) {
if (ci->is_otg) {
- /*
- * ID pin needs 1ms debouce time,
- * we delay 2ms for safe.
- */
- mdelay(2);
ci->role = ci_otg_role(ci);
- ci_enable_otg_interrupt(ci, OTGSC_IDIE);
+ /* Enable ID change irq */
+ hw_write_otgsc(ci, OTGSC_IDIE, OTGSC_IDIE);
} else {
/*
* If the controller is not OTG capable, but support
@@ -667,10 +692,13 @@ static int ci_hdrc_probe(struct platform_device *pdev)
if (ci->role == CI_ROLE_GADGET)
ci_handle_vbus_change(ci);
- ret = ci_role_start(ci, ci->role);
- if (ret) {
- dev_err(dev, "can't start %s role\n", ci_role(ci)->name);
- goto stop;
+ if (!ci_otg_is_fsm_mode(ci)) {
+ ret = ci_role_start(ci, ci->role);
+ if (ret) {
+ dev_err(dev, "can't start %s role\n",
+ ci_role(ci)->name);
+ goto stop;
+ }
}
platform_set_drvdata(pdev, ci);
@@ -679,6 +707,9 @@ static int ci_hdrc_probe(struct platform_device *pdev)
if (ret)
goto stop;
+ if (ci_otg_is_fsm_mode(ci))
+ ci_hdrc_otg_fsm_start(ci);
+
ret = dbg_create_files(ci);
if (!ret)
return 0;
@@ -711,6 +742,7 @@ static struct platform_driver ci_hdrc_driver = {
.remove = ci_hdrc_remove,
.driver = {
.name = "ci_hdrc",
+ .owner = THIS_MODULE,
},
};
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c
index 96d899aee473..7cccab6ff308 100644
--- a/drivers/usb/chipidea/debug.c
+++ b/drivers/usb/chipidea/debug.c
@@ -7,11 +7,15 @@
#include <linux/uaccess.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
+#include <linux/usb/phy.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/otg-fsm.h>
#include "ci.h"
#include "udc.h"
#include "bits.h"
#include "debug.h"
+#include "otg.h"
/**
* ci_device_show: prints information about device capabilities and status
@@ -204,6 +208,80 @@ static const struct file_operations ci_requests_fops = {
.release = single_release,
};
+int ci_otg_show(struct seq_file *s, void *unused)
+{
+ struct ci_hdrc *ci = s->private;
+ struct otg_fsm *fsm;
+
+ if (!ci || !ci_otg_is_fsm_mode(ci))
+ return 0;
+
+ fsm = &ci->fsm;
+
+ /* ------ State ----- */
+ seq_printf(s, "OTG state: %s\n\n",
+ usb_otg_state_string(ci->transceiver->state));
+
+ /* ------ State Machine Variables ----- */
+ seq_printf(s, "a_bus_drop: %d\n", fsm->a_bus_drop);
+
+ seq_printf(s, "a_bus_req: %d\n", fsm->a_bus_req);
+
+ seq_printf(s, "a_srp_det: %d\n", fsm->a_srp_det);
+
+ seq_printf(s, "a_vbus_vld: %d\n", fsm->a_vbus_vld);
+
+ seq_printf(s, "b_conn: %d\n", fsm->b_conn);
+
+ seq_printf(s, "adp_change: %d\n", fsm->adp_change);
+
+ seq_printf(s, "power_up: %d\n", fsm->power_up);
+
+ seq_printf(s, "a_bus_resume: %d\n", fsm->a_bus_resume);
+
+ seq_printf(s, "a_bus_suspend: %d\n", fsm->a_bus_suspend);
+
+ seq_printf(s, "a_conn: %d\n", fsm->a_conn);
+
+ seq_printf(s, "b_bus_req: %d\n", fsm->b_bus_req);
+
+ seq_printf(s, "b_bus_suspend: %d\n", fsm->b_bus_suspend);
+
+ seq_printf(s, "b_se0_srp: %d\n", fsm->b_se0_srp);
+
+ seq_printf(s, "b_ssend_srp: %d\n", fsm->b_ssend_srp);
+
+ seq_printf(s, "b_sess_vld: %d\n", fsm->b_sess_vld);
+
+ seq_printf(s, "b_srp_done: %d\n", fsm->b_srp_done);
+
+ seq_printf(s, "drv_vbus: %d\n", fsm->drv_vbus);
+
+ seq_printf(s, "loc_conn: %d\n", fsm->loc_conn);
+
+ seq_printf(s, "loc_sof: %d\n", fsm->loc_sof);
+
+ seq_printf(s, "adp_prb: %d\n", fsm->adp_prb);
+
+ seq_printf(s, "id: %d\n", fsm->id);
+
+ seq_printf(s, "protocol: %d\n", fsm->protocol);
+
+ return 0;
+}
+
+static int ci_otg_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ci_otg_show, inode->i_private);
+}
+
+static const struct file_operations ci_otg_fops = {
+ .open = ci_otg_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static int ci_role_show(struct seq_file *s, void *data)
{
struct ci_hdrc *ci = s->private;
@@ -253,6 +331,50 @@ static const struct file_operations ci_role_fops = {
.release = single_release,
};
+int ci_registers_show(struct seq_file *s, void *unused)
+{
+ struct ci_hdrc *ci = s->private;
+ u32 tmp_reg;
+
+ if (!ci)
+ return 0;
+
+ /* ------ Registers ----- */
+ tmp_reg = hw_read_intr_enable(ci);
+ seq_printf(s, "USBINTR reg: %08x\n", tmp_reg);
+
+ tmp_reg = hw_read_intr_status(ci);
+ seq_printf(s, "USBSTS reg: %08x\n", tmp_reg);
+
+ tmp_reg = hw_read(ci, OP_USBMODE, ~0);
+ seq_printf(s, "USBMODE reg: %08x\n", tmp_reg);
+
+ tmp_reg = hw_read(ci, OP_USBCMD, ~0);
+ seq_printf(s, "USBCMD reg: %08x\n", tmp_reg);
+
+ tmp_reg = hw_read(ci, OP_PORTSC, ~0);
+ seq_printf(s, "PORTSC reg: %08x\n", tmp_reg);
+
+ if (ci->is_otg) {
+ tmp_reg = hw_read_otgsc(ci, ~0);
+ seq_printf(s, "OTGSC reg: %08x\n", tmp_reg);
+ }
+
+ return 0;
+}
+
+static int ci_registers_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ci_registers_show, inode->i_private);
+}
+
+static const struct file_operations ci_registers_fops = {
+ .open = ci_registers_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
/**
* dbg_create_files: initializes the attribute interface
* @ci: device
@@ -287,8 +409,21 @@ int dbg_create_files(struct ci_hdrc *ci)
if (!dent)
goto err;
+ if (ci_otg_is_fsm_mode(ci)) {
+ dent = debugfs_create_file("otg", S_IRUGO, ci->debugfs, ci,
+ &ci_otg_fops);
+ if (!dent)
+ goto err;
+ }
+
dent = debugfs_create_file("role", S_IRUGO | S_IWUSR, ci->debugfs, ci,
&ci_role_fops);
+ if (!dent)
+ goto err;
+
+ dent = debugfs_create_file("registers", S_IRUGO, ci->debugfs, ci,
+ &ci_registers_fops);
+
if (dent)
return 0;
err:
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index a8ac6c16dac9..a93d950e9468 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -67,7 +67,11 @@ static int host_start(struct ci_hdrc *ci)
ehci->has_tdi_phy_lpm = ci->hw_bank.lpm;
ehci->imx28_write_fix = ci->imx28_write_fix;
- if (ci->platdata->reg_vbus) {
+ /*
+ * vbus is always on if host is not in OTG FSM mode,
+ * otherwise should be controlled by OTG FSM
+ */
+ if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci)) {
ret = regulator_enable(ci->platdata->reg_vbus);
if (ret) {
dev_err(ci->dev,
@@ -78,10 +82,17 @@ static int host_start(struct ci_hdrc *ci)
}
ret = usb_add_hcd(hcd, 0, 0);
- if (ret)
+ if (ret) {
goto disable_reg;
- else
+ } else {
+ struct usb_otg *otg = ci->transceiver->otg;
+
ci->hcd = hcd;
+ if (otg) {
+ otg->host = &hcd->self;
+ hcd->self.otg_port = 1;
+ }
+ }
if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING)
hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
@@ -89,7 +100,7 @@ static int host_start(struct ci_hdrc *ci)
return ret;
disable_reg:
- if (ci->platdata->reg_vbus)
+ if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci))
regulator_disable(ci->platdata->reg_vbus);
put_hcd:
@@ -105,7 +116,7 @@ static void host_stop(struct ci_hdrc *ci)
if (hcd) {
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
- if (ci->platdata->reg_vbus)
+ if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci))
regulator_disable(ci->platdata->reg_vbus);
}
}
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
index 39bd7ec8bf75..a048b08b9d4d 100644
--- a/drivers/usb/chipidea/otg.c
+++ b/drivers/usb/chipidea/otg.c
@@ -11,8 +11,8 @@
*/
/*
- * This file mainly handles otgsc register, it may include OTG operation
- * in the future.
+ * This file mainly handles otgsc register, OTG fsm operations for HNP and SRP
+ * are also included.
*/
#include <linux/usb/otg.h>
@@ -22,6 +22,26 @@
#include "ci.h"
#include "bits.h"
#include "otg.h"
+#include "otg_fsm.h"
+
+/**
+ * hw_read_otgsc returns otgsc register bits value.
+ * @mask: bitfield mask
+ */
+u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask)
+{
+ return hw_read(ci, OP_OTGSC, mask);
+}
+
+/**
+ * hw_write_otgsc updates target bits of OTGSC register.
+ * @mask: bitfield mask
+ * @data: to be written
+ */
+void hw_write_otgsc(struct ci_hdrc *ci, u32 mask, u32 data)
+{
+ hw_write(ci, OP_OTGSC, mask | OTGSC_INT_STATUS_BITS, data);
+}
/**
* ci_otg_role - pick role based on ID pin state
@@ -29,8 +49,7 @@
*/
enum ci_role ci_otg_role(struct ci_hdrc *ci)
{
- u32 sts = hw_read(ci, OP_OTGSC, ~0);
- enum ci_role role = sts & OTGSC_ID
+ enum ci_role role = hw_read_otgsc(ci, OTGSC_ID)
? CI_ROLE_GADGET
: CI_ROLE_HOST;
@@ -39,14 +58,10 @@ enum ci_role ci_otg_role(struct ci_hdrc *ci)
void ci_handle_vbus_change(struct ci_hdrc *ci)
{
- u32 otgsc;
-
if (!ci->is_otg)
return;
- otgsc = hw_read(ci, OP_OTGSC, ~0);
-
- if (otgsc & OTGSC_BSV)
+ if (hw_read_otgsc(ci, OTGSC_BSV))
usb_gadget_vbus_connect(&ci->gadget);
else
usb_gadget_vbus_disconnect(&ci->gadget);
@@ -76,6 +91,11 @@ static void ci_otg_work(struct work_struct *work)
{
struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work);
+ if (ci_otg_is_fsm_mode(ci) && !ci_otg_fsm_work(ci)) {
+ enable_irq(ci->irq);
+ return;
+ }
+
if (ci->id_event) {
ci->id_event = false;
ci_handle_id_switch(ci);
@@ -102,6 +122,9 @@ int ci_hdrc_otg_init(struct ci_hdrc *ci)
return -ENODEV;
}
+ if (ci_otg_is_fsm_mode(ci))
+ return ci_hdrc_otg_fsm_init(ci);
+
return 0;
}
@@ -115,6 +138,9 @@ void ci_hdrc_otg_destroy(struct ci_hdrc *ci)
flush_workqueue(ci->wq);
destroy_workqueue(ci->wq);
}
- ci_disable_otg_interrupt(ci, OTGSC_INT_EN_BITS);
- ci_clear_otg_interrupt(ci, OTGSC_INT_STATUS_BITS);
+ /* Disable all OTG irq and clear status */
+ hw_write_otgsc(ci, OTGSC_INT_EN_BITS | OTGSC_INT_STATUS_BITS,
+ OTGSC_INT_STATUS_BITS);
+ if (ci_otg_is_fsm_mode(ci))
+ ci_hdrc_otg_fsm_remove(ci);
}
diff --git a/drivers/usb/chipidea/otg.h b/drivers/usb/chipidea/otg.h
index 449bee07f4fe..9ecb598e48f0 100644
--- a/drivers/usb/chipidea/otg.h
+++ b/drivers/usb/chipidea/otg.h
@@ -11,25 +11,16 @@
#ifndef __DRIVERS_USB_CHIPIDEA_OTG_H
#define __DRIVERS_USB_CHIPIDEA_OTG_H
-static inline void ci_clear_otg_interrupt(struct ci_hdrc *ci, u32 bits)
-{
- /* Only clear request bits */
- hw_write(ci, OP_OTGSC, OTGSC_INT_STATUS_BITS, bits);
-}
-
-static inline void ci_enable_otg_interrupt(struct ci_hdrc *ci, u32 bits)
-{
- hw_write(ci, OP_OTGSC, bits | OTGSC_INT_STATUS_BITS, bits);
-}
-
-static inline void ci_disable_otg_interrupt(struct ci_hdrc *ci, u32 bits)
-{
- hw_write(ci, OP_OTGSC, bits | OTGSC_INT_STATUS_BITS, 0);
-}
-
+u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask);
+void hw_write_otgsc(struct ci_hdrc *ci, u32 mask, u32 data);
int ci_hdrc_otg_init(struct ci_hdrc *ci);
void ci_hdrc_otg_destroy(struct ci_hdrc *ci);
enum ci_role ci_otg_role(struct ci_hdrc *ci);
void ci_handle_vbus_change(struct ci_hdrc *ci);
+static inline void ci_otg_queue_work(struct ci_hdrc *ci)
+{
+ disable_irq_nosync(ci->irq);
+ queue_work(ci->wq, &ci->work);
+}
#endif /* __DRIVERS_USB_CHIPIDEA_OTG_H */
diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c
new file mode 100644
index 000000000000..caaabc58021e
--- /dev/null
+++ b/drivers/usb/chipidea/otg_fsm.c
@@ -0,0 +1,842 @@
+/*
+ * otg_fsm.c - ChipIdea USB IP core OTG FSM driver
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * Author: Jun Li
+ *
+ * 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 file mainly handles OTG fsm, it includes OTG fsm operations
+ * for HNP and SRP.
+ *
+ * TODO List
+ * - ADP
+ * - OTG test device
+ */
+
+#include <linux/usb/otg.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/hcd.h>
+#include <linux/usb/chipidea.h>
+#include <linux/regulator/consumer.h>
+
+#include "ci.h"
+#include "bits.h"
+#include "otg.h"
+#include "otg_fsm.h"
+
+static struct ci_otg_fsm_timer *otg_timer_initializer
+(struct ci_hdrc *ci, void (*function)(void *, unsigned long),
+ unsigned long expires, unsigned long data)
+{
+ struct ci_otg_fsm_timer *timer;
+
+ timer = devm_kzalloc(ci->dev, sizeof(struct ci_otg_fsm_timer),
+ GFP_KERNEL);
+ if (!timer)
+ return NULL;
+ timer->function = function;
+ timer->expires = expires;
+ timer->data = data;
+ return timer;
+}
+
+/* Add for otg: interact with user space app */
+static ssize_t
+get_a_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ char *next;
+ unsigned size, t;
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
+
+ next = buf;
+ size = PAGE_SIZE;
+ t = scnprintf(next, size, "%d\n", ci->fsm.a_bus_req);
+ size -= t;
+ next += t;
+
+ return PAGE_SIZE - size;
+}
+
+static ssize_t
+set_a_bus_req(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
+
+ if (count > 2)
+ return -1;
+
+ mutex_lock(&ci->fsm.lock);
+ if (buf[0] == '0') {
+ ci->fsm.a_bus_req = 0;
+ } else if (buf[0] == '1') {
+ /* If a_bus_drop is TRUE, a_bus_req can't be set */
+ if (ci->fsm.a_bus_drop) {
+ mutex_unlock(&ci->fsm.lock);
+ return count;
+ }
+ ci->fsm.a_bus_req = 1;
+ }
+
+ ci_otg_queue_work(ci);
+ mutex_unlock(&ci->fsm.lock);
+
+ return count;
+}
+static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR, get_a_bus_req, set_a_bus_req);
+
+static ssize_t
+get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ char *next;
+ unsigned size, t;
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
+
+ next = buf;
+ size = PAGE_SIZE;
+ t = scnprintf(next, size, "%d\n", ci->fsm.a_bus_drop);
+ size -= t;
+ next += t;
+
+ return PAGE_SIZE - size;
+}
+
+static ssize_t
+set_a_bus_drop(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
+
+ if (count > 2)
+ return -1;
+
+ mutex_lock(&ci->fsm.lock);
+ if (buf[0] == '0') {
+ ci->fsm.a_bus_drop = 0;
+ } else if (buf[0] == '1') {
+ ci->fsm.a_bus_drop = 1;
+ ci->fsm.a_bus_req = 0;
+ }
+
+ ci_otg_queue_work(ci);
+ mutex_unlock(&ci->fsm.lock);
+
+ return count;
+}
+static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR, get_a_bus_drop,
+ set_a_bus_drop);
+
+static ssize_t
+get_b_bus_req(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ char *next;
+ unsigned size, t;
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
+
+ next = buf;
+ size = PAGE_SIZE;
+ t = scnprintf(next, size, "%d\n", ci->fsm.b_bus_req);
+ size -= t;
+ next += t;
+
+ return PAGE_SIZE - size;
+}
+
+static ssize_t
+set_b_bus_req(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
+
+ if (count > 2)
+ return -1;
+
+ mutex_lock(&ci->fsm.lock);
+ if (buf[0] == '0')
+ ci->fsm.b_bus_req = 0;
+ else if (buf[0] == '1')
+ ci->fsm.b_bus_req = 1;
+
+ ci_otg_queue_work(ci);
+ mutex_unlock(&ci->fsm.lock);
+
+ return count;
+}
+static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUSR, get_b_bus_req, set_b_bus_req);
+
+static ssize_t
+set_a_clr_err(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
+
+ if (count > 2)
+ return -1;
+
+ mutex_lock(&ci->fsm.lock);
+ if (buf[0] == '1')
+ ci->fsm.a_clr_err = 1;
+
+ ci_otg_queue_work(ci);
+ mutex_unlock(&ci->fsm.lock);
+
+ return count;
+}
+static DEVICE_ATTR(a_clr_err, S_IWUSR, NULL, set_a_clr_err);
+
+static struct attribute *inputs_attrs[] = {
+ &dev_attr_a_bus_req.attr,
+ &dev_attr_a_bus_drop.attr,
+ &dev_attr_b_bus_req.attr,
+ &dev_attr_a_clr_err.attr,
+ NULL,
+};
+
+static struct attribute_group inputs_attr_group = {
+ .name = "inputs",
+ .attrs = inputs_attrs,
+};
+
+/*
+ * Add timer to active timer list
+ */
+static void ci_otg_add_timer(struct ci_hdrc *ci, enum ci_otg_fsm_timer_index t)
+{
+ struct ci_otg_fsm_timer *tmp_timer;
+ struct ci_otg_fsm_timer *timer = ci->fsm_timer->timer_list[t];
+ struct list_head *active_timers = &ci->fsm_timer->active_timers;
+
+ if (t >= NUM_CI_OTG_FSM_TIMERS)
+ return;
+
+ /*
+ * Check if the timer is already in the active list,
+ * if so update timer count
+ */
+ list_for_each_entry(tmp_timer, active_timers, list)
+ if (tmp_timer == timer) {
+ timer->count = timer->expires;
+ return;
+ }
+
+ timer->count = timer->expires;
+ list_add_tail(&timer->list, active_timers);
+
+ /* Enable 1ms irq */
+ if (!(hw_read_otgsc(ci, OTGSC_1MSIE)))
+ hw_write_otgsc(ci, OTGSC_1MSIE, OTGSC_1MSIE);
+}
+
+/*
+ * Remove timer from active timer list
+ */
+static void ci_otg_del_timer(struct ci_hdrc *ci, enum ci_otg_fsm_timer_index t)
+{
+ struct ci_otg_fsm_timer *tmp_timer, *del_tmp;
+ struct ci_otg_fsm_timer *timer = ci->fsm_timer->timer_list[t];
+ struct list_head *active_timers = &ci->fsm_timer->active_timers;
+
+ if (t >= NUM_CI_OTG_FSM_TIMERS)
+ return;
+
+ list_for_each_entry_safe(tmp_timer, del_tmp, active_timers, list)
+ if (tmp_timer == timer)
+ list_del(&timer->list);
+
+ /* Disable 1ms irq if there is no any active timer */
+ if (list_empty(active_timers))
+ hw_write_otgsc(ci, OTGSC_1MSIE, 0);
+}
+
+/*
+ * Reduce timer count by 1, and find timeout conditions.
+ * Called by otg 1ms timer interrupt
+ */
+static inline int ci_otg_tick_timer(struct ci_hdrc *ci)
+{
+ struct ci_otg_fsm_timer *tmp_timer, *del_tmp;
+ struct list_head *active_timers = &ci->fsm_timer->active_timers;
+ int expired = 0;
+
+ list_for_each_entry_safe(tmp_timer, del_tmp, active_timers, list) {
+ tmp_timer->count--;
+ /* check if timer expires */
+ if (!tmp_timer->count) {
+ list_del(&tmp_timer->list);
+ tmp_timer->function(ci, tmp_timer->data);
+ expired = 1;
+ }
+ }
+
+ /* disable 1ms irq if there is no any timer active */
+ if ((expired == 1) && list_empty(active_timers))
+ hw_write_otgsc(ci, OTGSC_1MSIE, 0);
+
+ return expired;
+}
+
+/* The timeout callback function to set time out bit */
+static void set_tmout(void *ptr, unsigned long indicator)
+{
+ *(int *)indicator = 1;
+}
+
+static void set_tmout_and_fsm(void *ptr, unsigned long indicator)
+{
+ struct ci_hdrc *ci = (struct ci_hdrc *)ptr;
+
+ set_tmout(ci, indicator);
+
+ ci_otg_queue_work(ci);
+}
+
+static void a_wait_vfall_tmout_func(void *ptr, unsigned long indicator)
+{
+ struct ci_hdrc *ci = (struct ci_hdrc *)ptr;
+
+ set_tmout(ci, indicator);
+ /* Disable port power */
+ hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | PORTSC_PP, 0);
+ /* Clear exsiting DP irq */
+ hw_write_otgsc(ci, OTGSC_DPIS, OTGSC_DPIS);
+ /* Enable data pulse irq */
+ hw_write_otgsc(ci, OTGSC_DPIE, OTGSC_DPIE);
+ ci_otg_queue_work(ci);
+}
+
+static void b_ase0_brst_tmout_func(void *ptr, unsigned long indicator)
+{
+ struct ci_hdrc *ci = (struct ci_hdrc *)ptr;
+
+ set_tmout(ci, indicator);
+ if (!hw_read_otgsc(ci, OTGSC_BSV))
+ ci->fsm.b_sess_vld = 0;
+
+ ci_otg_queue_work(ci);
+}
+
+static void b_ssend_srp_tmout_func(void *ptr, unsigned long indicator)
+{
+ struct ci_hdrc *ci = (struct ci_hdrc *)ptr;
+
+ set_tmout(ci, indicator);
+
+ /* only vbus fall below B_sess_vld in b_idle state */
+ if (ci->transceiver->state == OTG_STATE_B_IDLE)
+ ci_otg_queue_work(ci);
+}
+
+static void b_sess_vld_tmout_func(void *ptr, unsigned long indicator)
+{
+ struct ci_hdrc *ci = (struct ci_hdrc *)ptr;
+
+ /* Check if A detached */
+ if (!(hw_read_otgsc(ci, OTGSC_BSV))) {
+ ci->fsm.b_sess_vld = 0;
+ ci_otg_add_timer(ci, B_SSEND_SRP);
+ ci_otg_queue_work(ci);
+ }
+}
+
+static void b_data_pulse_end(void *ptr, unsigned long indicator)
+{
+ struct ci_hdrc *ci = (struct ci_hdrc *)ptr;
+
+ ci->fsm.b_srp_done = 1;
+ ci->fsm.b_bus_req = 0;
+ if (ci->fsm.power_up)
+ ci->fsm.power_up = 0;
+
+ hw_write_otgsc(ci, OTGSC_HABA, 0);
+
+ ci_otg_queue_work(ci);
+}
+
+/* Initialize timers */
+static int ci_otg_init_timers(struct ci_hdrc *ci)
+{
+ struct otg_fsm *fsm = &ci->fsm;
+
+ /* FSM used timers */
+ ci->fsm_timer->timer_list[A_WAIT_VRISE] =
+ otg_timer_initializer(ci, &set_tmout_and_fsm, TA_WAIT_VRISE,
+ (unsigned long)&fsm->a_wait_vrise_tmout);
+ if (ci->fsm_timer->timer_list[A_WAIT_VRISE] == NULL)
+ return -ENOMEM;
+
+ ci->fsm_timer->timer_list[A_WAIT_VFALL] =
+ otg_timer_initializer(ci, &a_wait_vfall_tmout_func,
+ TA_WAIT_VFALL, (unsigned long)&fsm->a_wait_vfall_tmout);
+ if (ci->fsm_timer->timer_list[A_WAIT_VFALL] == NULL)
+ return -ENOMEM;
+
+ ci->fsm_timer->timer_list[A_WAIT_BCON] =
+ otg_timer_initializer(ci, &set_tmout_and_fsm, TA_WAIT_BCON,
+ (unsigned long)&fsm->a_wait_bcon_tmout);
+ if (ci->fsm_timer->timer_list[A_WAIT_BCON] == NULL)
+ return -ENOMEM;
+
+ ci->fsm_timer->timer_list[A_AIDL_BDIS] =
+ otg_timer_initializer(ci, &set_tmout_and_fsm, TA_AIDL_BDIS,
+ (unsigned long)&fsm->a_aidl_bdis_tmout);
+ if (ci->fsm_timer->timer_list[A_AIDL_BDIS] == NULL)
+ return -ENOMEM;
+
+ ci->fsm_timer->timer_list[A_BIDL_ADIS] =
+ otg_timer_initializer(ci, &set_tmout_and_fsm, TA_BIDL_ADIS,
+ (unsigned long)&fsm->a_bidl_adis_tmout);
+ if (ci->fsm_timer->timer_list[A_BIDL_ADIS] == NULL)
+ return -ENOMEM;
+
+ ci->fsm_timer->timer_list[B_ASE0_BRST] =
+ otg_timer_initializer(ci, &b_ase0_brst_tmout_func, TB_ASE0_BRST,
+ (unsigned long)&fsm->b_ase0_brst_tmout);
+ if (ci->fsm_timer->timer_list[B_ASE0_BRST] == NULL)
+ return -ENOMEM;
+
+ ci->fsm_timer->timer_list[B_SE0_SRP] =
+ otg_timer_initializer(ci, &set_tmout_and_fsm, TB_SE0_SRP,
+ (unsigned long)&fsm->b_se0_srp);
+ if (ci->fsm_timer->timer_list[B_SE0_SRP] == NULL)
+ return -ENOMEM;
+
+ ci->fsm_timer->timer_list[B_SSEND_SRP] =
+ otg_timer_initializer(ci, &b_ssend_srp_tmout_func, TB_SSEND_SRP,
+ (unsigned long)&fsm->b_ssend_srp);
+ if (ci->fsm_timer->timer_list[B_SSEND_SRP] == NULL)
+ return -ENOMEM;
+
+ ci->fsm_timer->timer_list[B_SRP_FAIL] =
+ otg_timer_initializer(ci, &set_tmout, TB_SRP_FAIL,
+ (unsigned long)&fsm->b_srp_done);
+ if (ci->fsm_timer->timer_list[B_SRP_FAIL] == NULL)
+ return -ENOMEM;
+
+ ci->fsm_timer->timer_list[B_DATA_PLS] =
+ otg_timer_initializer(ci, &b_data_pulse_end, TB_DATA_PLS, 0);
+ if (ci->fsm_timer->timer_list[B_DATA_PLS] == NULL)
+ return -ENOMEM;
+
+ ci->fsm_timer->timer_list[B_SESS_VLD] = otg_timer_initializer(ci,
+ &b_sess_vld_tmout_func, TB_SESS_VLD, 0);
+ if (ci->fsm_timer->timer_list[B_SESS_VLD] == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
+/* -------------------------------------------------------------*/
+/* Operations that will be called from OTG Finite State Machine */
+/* -------------------------------------------------------------*/
+static void ci_otg_fsm_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer t)
+{
+ struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm);
+
+ if (t < NUM_OTG_FSM_TIMERS)
+ ci_otg_add_timer(ci, t);
+ return;
+}
+
+static void ci_otg_fsm_del_timer(struct otg_fsm *fsm, enum otg_fsm_timer t)
+{
+ struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm);
+
+ if (t < NUM_OTG_FSM_TIMERS)
+ ci_otg_del_timer(ci, t);
+ return;
+}
+
+/*
+ * A-device drive vbus: turn on vbus regulator and enable port power
+ * Data pulse irq should be disabled while vbus is on.
+ */
+static void ci_otg_drv_vbus(struct otg_fsm *fsm, int on)
+{
+ int ret;
+ struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm);
+
+ if (on) {
+ /* Enable power power */
+ hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | PORTSC_PP,
+ PORTSC_PP);
+ if (ci->platdata->reg_vbus) {
+ ret = regulator_enable(ci->platdata->reg_vbus);
+ if (ret) {
+ dev_err(ci->dev,
+ "Failed to enable vbus regulator, ret=%d\n",
+ ret);
+ return;
+ }
+ }
+ /* Disable data pulse irq */
+ hw_write_otgsc(ci, OTGSC_DPIE, 0);
+
+ fsm->a_srp_det = 0;
+ fsm->power_up = 0;
+ } else {
+ if (ci->platdata->reg_vbus)
+ regulator_disable(ci->platdata->reg_vbus);
+
+ fsm->a_bus_drop = 1;
+ fsm->a_bus_req = 0;
+ }
+}
+
+/*
+ * Control data line by Run Stop bit.
+ */
+static void ci_otg_loc_conn(struct otg_fsm *fsm, int on)
+{
+ struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm);
+
+ if (on)
+ hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
+ else
+ hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
+}
+
+/*
+ * Generate SOF by host.
+ * This is controlled through suspend/resume the port.
+ * In host mode, controller will automatically send SOF.
+ * Suspend will block the data on the port.
+ */
+static void ci_otg_loc_sof(struct otg_fsm *fsm, int on)
+{
+ struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm);
+
+ if (on)
+ hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | PORTSC_FPR,
+ PORTSC_FPR);
+ else
+ hw_write(ci, OP_PORTSC, PORTSC_W1C_BITS | PORTSC_SUSP,
+ PORTSC_SUSP);
+}
+
+/*
+ * Start SRP pulsing by data-line pulsing,
+ * no v-bus pulsing followed
+ */
+static void ci_otg_start_pulse(struct otg_fsm *fsm)
+{
+ struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm);
+
+ /* Hardware Assistant Data pulse */
+ hw_write_otgsc(ci, OTGSC_HADP, OTGSC_HADP);
+
+ ci_otg_add_timer(ci, B_DATA_PLS);
+}
+
+static int ci_otg_start_host(struct otg_fsm *fsm, int on)
+{
+ struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm);
+
+ mutex_unlock(&fsm->lock);
+ if (on) {
+ ci_role_stop(ci);
+ ci_role_start(ci, CI_ROLE_HOST);
+ } else {
+ ci_role_stop(ci);
+ hw_device_reset(ci, USBMODE_CM_DC);
+ ci_role_start(ci, CI_ROLE_GADGET);
+ }
+ mutex_lock(&fsm->lock);
+ return 0;
+}
+
+static int ci_otg_start_gadget(struct otg_fsm *fsm, int on)
+{
+ struct ci_hdrc *ci = container_of(fsm, struct ci_hdrc, fsm);
+
+ mutex_unlock(&fsm->lock);
+ if (on)
+ usb_gadget_vbus_connect(&ci->gadget);
+ else
+ usb_gadget_vbus_disconnect(&ci->gadget);
+ mutex_lock(&fsm->lock);
+
+ return 0;
+}
+
+static struct otg_fsm_ops ci_otg_ops = {
+ .drv_vbus = ci_otg_drv_vbus,
+ .loc_conn = ci_otg_loc_conn,
+ .loc_sof = ci_otg_loc_sof,
+ .start_pulse = ci_otg_start_pulse,
+ .add_timer = ci_otg_fsm_add_timer,
+ .del_timer = ci_otg_fsm_del_timer,
+ .start_host = ci_otg_start_host,
+ .start_gadget = ci_otg_start_gadget,
+};
+
+int ci_otg_fsm_work(struct ci_hdrc *ci)
+{
+ /*
+ * Don't do fsm transition for B device
+ * when there is no gadget class driver
+ */
+ if (ci->fsm.id && !(ci->driver) &&
+ ci->transceiver->state < OTG_STATE_A_IDLE)
+ return 0;
+
+ if (otg_statemachine(&ci->fsm)) {
+ if (ci->transceiver->state == OTG_STATE_A_IDLE) {
+ /*
+ * Further state change for cases:
+ * a_idle to b_idle; or
+ * a_idle to a_wait_vrise due to ID change(1->0), so
+ * B-dev becomes A-dev can try to start new session
+ * consequently; or
+ * a_idle to a_wait_vrise when power up
+ */
+ if ((ci->fsm.id) || (ci->id_event) ||
+ (ci->fsm.power_up))
+ ci_otg_queue_work(ci);
+ if (ci->id_event)
+ ci->id_event = false;
+ } else if (ci->transceiver->state == OTG_STATE_B_IDLE) {
+ if (ci->fsm.b_sess_vld) {
+ ci->fsm.power_up = 0;
+ /*
+ * Further transite to b_periphearl state
+ * when register gadget driver with vbus on
+ */
+ ci_otg_queue_work(ci);
+ }
+ }
+ }
+ return 0;
+}
+
+/*
+ * Update fsm variables in each state if catching expected interrupts,
+ * called by otg fsm isr.
+ */
+static void ci_otg_fsm_event(struct ci_hdrc *ci)
+{
+ u32 intr_sts, otg_bsess_vld, port_conn;
+ struct otg_fsm *fsm = &ci->fsm;
+
+ intr_sts = hw_read_intr_status(ci);
+ otg_bsess_vld = hw_read_otgsc(ci, OTGSC_BSV);
+ port_conn = hw_read(ci, OP_PORTSC, PORTSC_CCS);
+
+ switch (ci->transceiver->state) {
+ case OTG_STATE_A_WAIT_BCON:
+ if (port_conn) {
+ fsm->b_conn = 1;
+ fsm->a_bus_req = 1;
+ ci_otg_queue_work(ci);
+ }
+ break;
+ case OTG_STATE_B_IDLE:
+ if (otg_bsess_vld && (intr_sts & USBi_PCI) && port_conn) {
+ fsm->b_sess_vld = 1;
+ ci_otg_queue_work(ci);
+ }
+ break;
+ case OTG_STATE_B_PERIPHERAL:
+ if ((intr_sts & USBi_SLI) && port_conn && otg_bsess_vld) {
+ fsm->a_bus_suspend = 1;
+ ci_otg_queue_work(ci);
+ } else if (intr_sts & USBi_PCI) {
+ if (fsm->a_bus_suspend == 1)
+ fsm->a_bus_suspend = 0;
+ }
+ break;
+ case OTG_STATE_B_HOST:
+ if ((intr_sts & USBi_PCI) && !port_conn) {
+ fsm->a_conn = 0;
+ fsm->b_bus_req = 0;
+ ci_otg_queue_work(ci);
+ ci_otg_add_timer(ci, B_SESS_VLD);
+ }
+ break;
+ case OTG_STATE_A_PERIPHERAL:
+ if (intr_sts & USBi_SLI) {
+ fsm->b_bus_suspend = 1;
+ /*
+ * Init a timer to know how long this suspend
+ * will contine, if time out, indicates B no longer
+ * wants to be host role
+ */
+ ci_otg_add_timer(ci, A_BIDL_ADIS);
+ }
+
+ if (intr_sts & USBi_URI)
+ ci_otg_del_timer(ci, A_BIDL_ADIS);
+
+ if (intr_sts & USBi_PCI) {
+ if (fsm->b_bus_suspend == 1) {
+ ci_otg_del_timer(ci, A_BIDL_ADIS);
+ fsm->b_bus_suspend = 0;
+ }
+ }
+ break;
+ case OTG_STATE_A_SUSPEND:
+ if ((intr_sts & USBi_PCI) && !port_conn) {
+ fsm->b_conn = 0;
+
+ /* if gadget driver is binded */
+ if (ci->driver) {
+ /* A device to be peripheral mode */
+ ci->gadget.is_a_peripheral = 1;
+ }
+ ci_otg_queue_work(ci);
+ }
+ break;
+ case OTG_STATE_A_HOST:
+ if ((intr_sts & USBi_PCI) && !port_conn) {
+ fsm->b_conn = 0;
+ ci_otg_queue_work(ci);
+ }
+ break;
+ case OTG_STATE_B_WAIT_ACON:
+ if ((intr_sts & USBi_PCI) && port_conn) {
+ fsm->a_conn = 1;
+ ci_otg_queue_work(ci);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/*
+ * ci_otg_irq - otg fsm related irq handling
+ * and also update otg fsm variable by monitoring usb host and udc
+ * state change interrupts.
+ * @ci: ci_hdrc
+ */
+irqreturn_t ci_otg_fsm_irq(struct ci_hdrc *ci)
+{
+ irqreturn_t retval = IRQ_NONE;
+ u32 otgsc, otg_int_src = 0;
+ struct otg_fsm *fsm = &ci->fsm;
+
+ otgsc = hw_read_otgsc(ci, ~0);
+ otg_int_src = otgsc & OTGSC_INT_STATUS_BITS & (otgsc >> 8);
+ fsm->id = (otgsc & OTGSC_ID) ? 1 : 0;
+
+ if (otg_int_src) {
+ if (otg_int_src & OTGSC_1MSIS) {
+ hw_write_otgsc(ci, OTGSC_1MSIS, OTGSC_1MSIS);
+ retval = ci_otg_tick_timer(ci);
+ return IRQ_HANDLED;
+ } else if (otg_int_src & OTGSC_DPIS) {
+ hw_write_otgsc(ci, OTGSC_DPIS, OTGSC_DPIS);
+ fsm->a_srp_det = 1;
+ fsm->a_bus_drop = 0;
+ } else if (otg_int_src & OTGSC_IDIS) {
+ hw_write_otgsc(ci, OTGSC_IDIS, OTGSC_IDIS);
+ if (fsm->id == 0) {
+ fsm->a_bus_drop = 0;
+ fsm->a_bus_req = 1;
+ ci->id_event = true;
+ }
+ } else if (otg_int_src & OTGSC_BSVIS) {
+ hw_write_otgsc(ci, OTGSC_BSVIS, OTGSC_BSVIS);
+ if (otgsc & OTGSC_BSV) {
+ fsm->b_sess_vld = 1;
+ ci_otg_del_timer(ci, B_SSEND_SRP);
+ ci_otg_del_timer(ci, B_SRP_FAIL);
+ fsm->b_ssend_srp = 0;
+ } else {
+ fsm->b_sess_vld = 0;
+ if (fsm->id)
+ ci_otg_add_timer(ci, B_SSEND_SRP);
+ }
+ } else if (otg_int_src & OTGSC_AVVIS) {
+ hw_write_otgsc(ci, OTGSC_AVVIS, OTGSC_AVVIS);
+ if (otgsc & OTGSC_AVV) {
+ fsm->a_vbus_vld = 1;
+ } else {
+ fsm->a_vbus_vld = 0;
+ fsm->b_conn = 0;
+ }
+ }
+ ci_otg_queue_work(ci);
+ return IRQ_HANDLED;
+ }
+
+ ci_otg_fsm_event(ci);
+
+ return retval;
+}
+
+void ci_hdrc_otg_fsm_start(struct ci_hdrc *ci)
+{
+ ci_otg_queue_work(ci);
+}
+
+int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci)
+{
+ int retval = 0;
+ struct usb_otg *otg;
+
+ otg = devm_kzalloc(ci->dev,
+ sizeof(struct usb_otg), GFP_KERNEL);
+ if (!otg) {
+ dev_err(ci->dev,
+ "Failed to allocate usb_otg structure for ci hdrc otg!\n");
+ return -ENOMEM;
+ }
+
+ otg->phy = ci->transceiver;
+ otg->gadget = &ci->gadget;
+ ci->fsm.otg = otg;
+ ci->transceiver->otg = ci->fsm.otg;
+ ci->fsm.power_up = 1;
+ ci->fsm.id = hw_read_otgsc(ci, OTGSC_ID) ? 1 : 0;
+ ci->transceiver->state = OTG_STATE_UNDEFINED;
+ ci->fsm.ops = &ci_otg_ops;
+
+ mutex_init(&ci->fsm.lock);
+
+ ci->fsm_timer = devm_kzalloc(ci->dev,
+ sizeof(struct ci_otg_fsm_timer_list), GFP_KERNEL);
+ if (!ci->fsm_timer) {
+ dev_err(ci->dev,
+ "Failed to allocate timer structure for ci hdrc otg!\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&ci->fsm_timer->active_timers);
+ retval = ci_otg_init_timers(ci);
+ if (retval) {
+ dev_err(ci->dev, "Couldn't init OTG timers\n");
+ return retval;
+ }
+
+ retval = sysfs_create_group(&ci->dev->kobj, &inputs_attr_group);
+ if (retval < 0) {
+ dev_dbg(ci->dev,
+ "Can't register sysfs attr group: %d\n", retval);
+ return retval;
+ }
+
+ /* Enable A vbus valid irq */
+ hw_write_otgsc(ci, OTGSC_AVVIE, OTGSC_AVVIE);
+
+ if (ci->fsm.id) {
+ ci->fsm.b_ssend_srp =
+ hw_read_otgsc(ci, OTGSC_BSV) ? 0 : 1;
+ ci->fsm.b_sess_vld =
+ hw_read_otgsc(ci, OTGSC_BSV) ? 1 : 0;
+ /* Enable BSV irq */
+ hw_write_otgsc(ci, OTGSC_BSVIE, OTGSC_BSVIE);
+ }
+
+ return 0;
+}
+
+void ci_hdrc_otg_fsm_remove(struct ci_hdrc *ci)
+{
+ sysfs_remove_group(&ci->dev->kobj, &inputs_attr_group);
+}
diff --git a/drivers/usb/chipidea/otg_fsm.h b/drivers/usb/chipidea/otg_fsm.h
new file mode 100644
index 000000000000..94c085f456a9
--- /dev/null
+++ b/drivers/usb/chipidea/otg_fsm.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * Author: Jun Li
+ *
+ * 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 __DRIVERS_USB_CHIPIDEA_OTG_FSM_H
+#define __DRIVERS_USB_CHIPIDEA_OTG_FSM_H
+
+#include <linux/usb/otg-fsm.h>
+
+/*
+ * A-DEVICE timing constants
+ */
+
+/* Wait for VBUS Rise */
+#define TA_WAIT_VRISE (100) /* a_wait_vrise: section 7.1.2
+ * a_wait_vrise_tmr: section 7.4.5.1
+ * TA_VBUS_RISE <= 100ms, section 4.4
+ * Table 4-1: Electrical Characteristics
+ * ->DC Electrical Timing
+ */
+/* Wait for VBUS Fall */
+#define TA_WAIT_VFALL (1000) /* a_wait_vfall: section 7.1.7
+ * a_wait_vfall_tmr: section: 7.4.5.2
+ */
+/* Wait for B-Connect */
+#define TA_WAIT_BCON (10000) /* a_wait_bcon: section 7.1.3
+ * TA_WAIT_BCON: should be between 1100
+ * and 30000 ms, section 5.5, Table 5-1
+ */
+/* A-Idle to B-Disconnect */
+#define TA_AIDL_BDIS (5000) /* a_suspend min 200 ms, section 5.2.1
+ * TA_AIDL_BDIS: section 5.5, Table 5-1
+ */
+/* B-Idle to A-Disconnect */
+#define TA_BIDL_ADIS (500) /* TA_BIDL_ADIS: section 5.2.1
+ * 500ms is used for B switch to host
+ * for safe
+ */
+
+/*
+ * B-device timing constants
+ */
+
+/* Data-Line Pulse Time*/
+#define TB_DATA_PLS (10) /* b_srp_init,continue 5~10ms
+ * section:5.1.3
+ */
+/* SRP Fail Time */
+#define TB_SRP_FAIL (6000) /* b_srp_init,fail time 5~6s
+ * section:5.1.6
+ */
+/* A-SE0 to B-Reset */
+#define TB_ASE0_BRST (155) /* minimum 155 ms, section:5.3.1 */
+/* SE0 Time Before SRP */
+#define TB_SE0_SRP (1000) /* b_idle,minimum 1s, section:5.1.2 */
+/* SSEND time before SRP */
+#define TB_SSEND_SRP (1500) /* minimum 1.5 sec, section:5.1.2 */
+
+#define TB_SESS_VLD (1000)
+
+enum ci_otg_fsm_timer_index {
+ /*
+ * CI specific timers, start from the end
+ * of standard and auxiliary OTG timers
+ */
+ B_DATA_PLS = NUM_OTG_FSM_TIMERS,
+ B_SSEND_SRP,
+ B_SESS_VLD,
+
+ NUM_CI_OTG_FSM_TIMERS,
+};
+
+struct ci_otg_fsm_timer {
+ unsigned long expires; /* Number of count increase to timeout */
+ unsigned long count; /* Tick counter */
+ void (*function)(void *, unsigned long); /* Timeout function */
+ unsigned long data; /* Data passed to function */
+ struct list_head list;
+};
+
+struct ci_otg_fsm_timer_list {
+ struct ci_otg_fsm_timer *timer_list[NUM_CI_OTG_FSM_TIMERS];
+ struct list_head active_timers;
+};
+
+#ifdef CONFIG_USB_OTG_FSM
+
+int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci);
+int ci_otg_fsm_work(struct ci_hdrc *ci);
+irqreturn_t ci_otg_fsm_irq(struct ci_hdrc *ci);
+void ci_hdrc_otg_fsm_start(struct ci_hdrc *ci);
+void ci_hdrc_otg_fsm_remove(struct ci_hdrc *ci);
+
+#else
+
+static inline int ci_hdrc_otg_fsm_init(struct ci_hdrc *ci)
+{
+ return 0;
+}
+
+static inline int ci_otg_fsm_work(struct ci_hdrc *ci)
+{
+ return -ENXIO;
+}
+
+static inline irqreturn_t ci_otg_fsm_irq(struct ci_hdrc *ci)
+{
+ return IRQ_NONE;
+}
+
+static inline void ci_hdrc_otg_fsm_start(struct ci_hdrc *ci)
+{
+
+}
+
+static inline void ci_hdrc_otg_fsm_remove(struct ci_hdrc *ci)
+{
+
+}
+
+#endif
+
+#endif /* __DRIVERS_USB_CHIPIDEA_OTG_FSM_H */
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 7739c64ef259..69425b3cb6b7 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -20,6 +20,7 @@
#include <linux/pm_runtime.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
+#include <linux/usb/otg-fsm.h>
#include <linux/usb/chipidea.h>
#include "ci.h"
@@ -27,6 +28,7 @@
#include "bits.h"
#include "debug.h"
#include "otg.h"
+#include "otg_fsm.h"
/* control endpoint description */
static const struct usb_endpoint_descriptor
@@ -242,26 +244,6 @@ static int hw_port_is_high_speed(struct ci_hdrc *ci)
}
/**
- * hw_read_intr_enable: returns interrupt enable register
- *
- * This function returns register data
- */
-static u32 hw_read_intr_enable(struct ci_hdrc *ci)
-{
- return hw_read(ci, OP_USBINTR, ~0);
-}
-
-/**
- * hw_read_intr_status: returns interrupt status register
- *
- * This function returns register data
- */
-static u32 hw_read_intr_status(struct ci_hdrc *ci)
-{
- return hw_read(ci, OP_USBSTS, ~0);
-}
-
-/**
* hw_test_and_clear_complete: test & clear complete status (execute without
* interruption)
* @n: endpoint number
@@ -727,6 +709,8 @@ __acquires(ci->lock)
if (ci->status == NULL)
retval = -ENOMEM;
+ usb_gadget_set_state(&ci->gadget, USB_STATE_DEFAULT);
+
done:
spin_lock(&ci->lock);
@@ -841,7 +825,6 @@ __acquires(hwep->lock)
if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
/* Assume that device is bus powered for now. */
*(u16 *)req->buf = ci->remote_wakeup << 1;
- retval = 0;
} else if ((setup->bRequestType & USB_RECIP_MASK) \
== USB_RECIP_ENDPOINT) {
dir = (le16_to_cpu(setup->wIndex) & USB_ENDPOINT_DIR_MASK) ?
@@ -883,6 +866,8 @@ isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
if (ci->setaddr) {
hw_usb_set_address(ci, ci->address);
ci->setaddr = false;
+ if (ci->address)
+ usb_gadget_set_state(&ci->gadget, USB_STATE_ADDRESS);
}
spin_lock_irqsave(&ci->lock, flags);
@@ -1072,6 +1057,14 @@ __acquires(ci->lock)
default:
break;
}
+ break;
+ case USB_DEVICE_B_HNP_ENABLE:
+ if (ci_otg_is_fsm_mode(ci)) {
+ ci->gadget.b_hnp_enable = 1;
+ err = isr_setup_status_phase(
+ ci);
+ }
+ break;
default:
goto delegate;
}
@@ -1477,7 +1470,7 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
pm_runtime_get_sync(&_gadget->dev);
hw_device_reset(ci, USBMODE_CM_DC);
hw_device_state(ci, ci->ep0out->qh.dma);
- dev_dbg(ci->dev, "Connected to host\n");
+ usb_gadget_set_state(_gadget, USB_STATE_POWERED);
} else {
if (ci->driver)
ci->driver->disconnect(&ci->gadget);
@@ -1487,7 +1480,7 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
CI_HDRC_CONTROLLER_STOPPED_EVENT);
_gadget_stop_activity(&ci->gadget);
pm_runtime_put_sync(&_gadget->dev);
- dev_dbg(ci->dev, "Disconnected from host\n");
+ usb_gadget_set_state(_gadget, USB_STATE_NOTATTACHED);
}
}
@@ -1655,6 +1648,13 @@ static int ci_udc_start(struct usb_gadget *gadget,
return retval;
ci->driver = driver;
+
+ /* Start otg fsm for B-device */
+ if (ci_otg_is_fsm_mode(ci) && ci->fsm.id) {
+ ci_hdrc_otg_fsm_start(ci);
+ return retval;
+ }
+
pm_runtime_get_sync(&ci->gadget.dev);
if (ci->vbus_active) {
spin_lock_irqsave(&ci->lock, flags);
@@ -1753,6 +1753,8 @@ static irqreturn_t udc_irq(struct ci_hdrc *ci)
ci->suspended = 1;
spin_unlock(&ci->lock);
ci->driver->suspend(&ci->gadget);
+ usb_gadget_set_state(&ci->gadget,
+ USB_STATE_SUSPENDED);
spin_lock(&ci->lock);
}
}
@@ -1779,7 +1781,7 @@ static int udc_start(struct ci_hdrc *ci)
ci->gadget.ops = &usb_gadget_ops;
ci->gadget.speed = USB_SPEED_UNKNOWN;
ci->gadget.max_speed = USB_SPEED_HIGH;
- ci->gadget.is_otg = 0;
+ ci->gadget.is_otg = ci->is_otg ? 1 : 0;
ci->gadget.name = ci->platdata->name;
INIT_LIST_HEAD(&ci->gadget.ep_list);
@@ -1843,21 +1845,22 @@ void ci_hdrc_gadget_destroy(struct ci_hdrc *ci)
static int udc_id_switch_for_device(struct ci_hdrc *ci)
{
- if (ci->is_otg) {
- ci_clear_otg_interrupt(ci, OTGSC_BSVIS);
- ci_enable_otg_interrupt(ci, OTGSC_BSVIE);
- }
+ if (ci->is_otg)
+ /* Clear and enable BSV irq */
+ hw_write_otgsc(ci, OTGSC_BSVIS | OTGSC_BSVIE,
+ OTGSC_BSVIS | OTGSC_BSVIE);
return 0;
}
static void udc_id_switch_for_host(struct ci_hdrc *ci)
{
- if (ci->is_otg) {
- /* host doesn't care B_SESSION_VALID event */
- ci_clear_otg_interrupt(ci, OTGSC_BSVIS);
- ci_disable_otg_interrupt(ci, OTGSC_BSVIE);
- }
+ /*
+ * host doesn't care B_SESSION_VALID event
+ * so clear and disbale BSV irq
+ */
+ if (ci->is_otg)
+ hw_write_otgsc(ci, OTGSC_BSVIE | OTGSC_BSVIS, OTGSC_BSVIS);
}
/**
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index cd061abe3507..85293b8b1df9 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -21,16 +21,39 @@
#define MX25_USB_PHY_CTRL_OFFSET 0x08
#define MX25_BM_EXTERNAL_VBUS_DIVIDER BIT(23)
+#define MX25_EHCI_INTERFACE_SINGLE_UNI (2 << 0)
+#define MX25_EHCI_INTERFACE_DIFF_UNI (0 << 0)
+#define MX25_EHCI_INTERFACE_MASK (0xf)
+
+#define MX25_OTG_SIC_SHIFT 29
+#define MX25_OTG_SIC_MASK (0x3 << MX25_OTG_SIC_SHIFT)
+#define MX25_OTG_PM_BIT BIT(24)
+#define MX25_OTG_PP_BIT BIT(11)
+#define MX25_OTG_OCPOL_BIT BIT(3)
+
+#define MX25_H1_SIC_SHIFT 21
+#define MX25_H1_SIC_MASK (0x3 << MX25_H1_SIC_SHIFT)
+#define MX25_H1_PP_BIT BIT(18)
+#define MX25_H1_PM_BIT BIT(16)
+#define MX25_H1_IPPUE_UP_BIT BIT(7)
+#define MX25_H1_IPPUE_DOWN_BIT BIT(6)
+#define MX25_H1_TLL_BIT BIT(5)
+#define MX25_H1_USBTE_BIT BIT(4)
+#define MX25_H1_OCPOL_BIT BIT(2)
+
#define MX27_H1_PM_BIT BIT(8)
#define MX27_H2_PM_BIT BIT(16)
#define MX27_OTG_PM_BIT BIT(24)
#define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08
+#define MX53_USB_OTG_PHY_CTRL_1_OFFSET 0x0c
#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 MX53_USB_PHYCTRL1_PLLDIV_MASK 0x3
+#define MX53_USB_PLL_DIV_24_MHZ 0x01
#define MX6_BM_OVER_CUR_DIS BIT(7)
@@ -50,6 +73,39 @@ struct imx_usbmisc {
static struct imx_usbmisc *usbmisc;
+static int usbmisc_imx25_init(struct imx_usbmisc_data *data)
+{
+ unsigned long flags;
+ u32 val = 0;
+
+ if (data->index > 1)
+ return -EINVAL;
+
+ spin_lock_irqsave(&usbmisc->lock, flags);
+ switch (data->index) {
+ case 0:
+ val = readl(usbmisc->base);
+ val &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PP_BIT);
+ val |= (MX25_EHCI_INTERFACE_DIFF_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT;
+ val |= (MX25_OTG_PM_BIT | MX25_OTG_OCPOL_BIT);
+ writel(val, usbmisc->base);
+ break;
+ case 1:
+ val = readl(usbmisc->base);
+ val &= ~(MX25_H1_SIC_MASK | MX25_H1_PP_BIT | MX25_H1_IPPUE_UP_BIT);
+ val |= (MX25_EHCI_INTERFACE_SINGLE_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT;
+ val |= (MX25_H1_PM_BIT | MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT |
+ MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT);
+
+ writel(val, usbmisc->base);
+
+ break;
+ }
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+
+ return 0;
+}
+
static int usbmisc_imx25_post(struct imx_usbmisc_data *data)
{
void __iomem *reg;
@@ -111,6 +167,13 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data *data)
if (data->index > 3)
return -EINVAL;
+ /* Select a 24 MHz reference clock for the PHY */
+ reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET;
+ val = readl(reg);
+ val &= ~MX53_USB_PHYCTRL1_PLLDIV_MASK;
+ val |= MX53_USB_PLL_DIV_24_MHZ;
+ writel(val, usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
+
if (data->disable_oc) {
spin_lock_irqsave(&usbmisc->lock, flags);
switch (data->index) {
@@ -159,6 +222,7 @@ static int usbmisc_imx6q_init(struct imx_usbmisc_data *data)
}
static const struct usbmisc_ops imx25_usbmisc_ops = {
+ .init = usbmisc_imx25_init,
.post = usbmisc_imx25_post,
};
@@ -200,6 +264,10 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = {
.data = &imx25_usbmisc_ops,
},
{
+ .compatible = "fsl,imx35-usbmisc",
+ .data = &imx25_usbmisc_ops,
+ },
+ {
.compatible = "fsl,imx27-usbmisc",
.data = &imx27_usbmisc_ops,
},
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 904efb6035b0..e934e19f49f5 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -122,13 +122,23 @@ static void acm_release_minor(struct acm *acm)
static int acm_ctrl_msg(struct acm *acm, int request, int value,
void *buf, int len)
{
- int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
+ int retval;
+
+ retval = usb_autopm_get_interface(acm->control);
+ if (retval)
+ return retval;
+
+ retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
request, USB_RT_ACM, value,
acm->control->altsetting[0].desc.bInterfaceNumber,
buf, len, 5000);
+
dev_dbg(&acm->control->dev,
"%s - rq 0x%02x, val %#x, len %#x, result %d\n",
__func__, request, value, len, retval);
+
+ usb_autopm_put_interface(acm->control);
+
return retval < 0 ? retval : 0;
}
@@ -406,19 +416,21 @@ static void acm_read_bulk_callback(struct urb *urb)
dev_dbg(&acm->data->dev, "%s - disconnected\n", __func__);
return;
}
- usb_mark_last_busy(acm->dev);
if (urb->status) {
dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n",
__func__, urb->status);
return;
}
+
+ usb_mark_last_busy(acm->dev);
+
acm_process_read_urb(acm, urb);
/* throttle device if requested by tty */
spin_lock_irqsave(&acm->read_lock, flags);
acm->throttled = acm->throttle_req;
- if (!acm->throttled && !acm->susp_count) {
+ if (!acm->throttled) {
spin_unlock_irqrestore(&acm->read_lock, flags);
acm_submit_read_urb(acm, rb->index, GFP_ATOMIC);
} else {
@@ -492,10 +504,30 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
return tty_port_open(&acm->port, tty, filp);
}
+static void acm_port_dtr_rts(struct tty_port *port, int raise)
+{
+ struct acm *acm = container_of(port, struct acm, port);
+ int val;
+ int res;
+
+ if (raise)
+ val = ACM_CTRL_DTR | ACM_CTRL_RTS;
+ else
+ val = 0;
+
+ /* FIXME: add missing ctrlout locking throughout driver */
+ acm->ctrlout = val;
+
+ res = acm_set_control(acm, val);
+ if (res && (acm->ctrl_caps & USB_CDC_CAP_LINE))
+ dev_err(&acm->control->dev, "failed to set dtr/rts\n");
+}
+
static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
{
struct acm *acm = container_of(port, struct acm, port);
int retval = -ENODEV;
+ int i;
dev_dbg(&acm->control->dev, "%s\n", __func__);
@@ -515,22 +547,13 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
acm->control->needs_remote_wakeup = 1;
acm->ctrlurb->dev = acm->dev;
- if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) {
+ retval = usb_submit_urb(acm->ctrlurb, GFP_KERNEL);
+ if (retval) {
dev_err(&acm->control->dev,
"%s - usb_submit_urb(ctrl irq) failed\n", __func__);
- usb_autopm_put_interface(acm->control);
goto error_submit_urb;
}
- acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS;
- if (acm_set_control(acm, acm->ctrlout) < 0 &&
- (acm->ctrl_caps & USB_CDC_CAP_LINE)) {
- usb_autopm_put_interface(acm->control);
- goto error_set_control;
- }
-
- usb_autopm_put_interface(acm->control);
-
/*
* Unthrottle device in case the TTY was closed while throttled.
*/
@@ -539,23 +562,27 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
acm->throttle_req = 0;
spin_unlock_irq(&acm->read_lock);
- if (acm_submit_read_urbs(acm, GFP_KERNEL))
+ retval = acm_submit_read_urbs(acm, GFP_KERNEL);
+ if (retval)
goto error_submit_read_urbs;
+ usb_autopm_put_interface(acm->control);
+
mutex_unlock(&acm->mutex);
return 0;
error_submit_read_urbs:
- acm->ctrlout = 0;
- acm_set_control(acm, acm->ctrlout);
-error_set_control:
+ for (i = 0; i < acm->rx_buflimit; i++)
+ usb_kill_urb(acm->read_urbs[i]);
usb_kill_urb(acm->ctrlurb);
error_submit_urb:
+ usb_autopm_put_interface(acm->control);
error_get_interface:
disconnected:
mutex_unlock(&acm->mutex);
- return retval;
+
+ return usb_translate_errors(retval);
}
static void acm_port_destruct(struct tty_port *port)
@@ -573,23 +600,37 @@ static void acm_port_destruct(struct tty_port *port)
static void acm_port_shutdown(struct tty_port *port)
{
struct acm *acm = container_of(port, struct acm, port);
+ struct urb *urb;
+ struct acm_wb *wb;
int i;
dev_dbg(&acm->control->dev, "%s\n", __func__);
- mutex_lock(&acm->mutex);
- if (!acm->disconnected) {
- usb_autopm_get_interface(acm->control);
- acm_set_control(acm, acm->ctrlout = 0);
- usb_kill_urb(acm->ctrlurb);
- for (i = 0; i < ACM_NW; i++)
- usb_kill_urb(acm->wb[i].urb);
- for (i = 0; i < acm->rx_buflimit; i++)
- usb_kill_urb(acm->read_urbs[i]);
- acm->control->needs_remote_wakeup = 0;
- usb_autopm_put_interface(acm->control);
+ /*
+ * Need to grab write_lock to prevent race with resume, but no need to
+ * hold it due to the tty-port initialised flag.
+ */
+ spin_lock_irq(&acm->write_lock);
+ spin_unlock_irq(&acm->write_lock);
+
+ usb_autopm_get_interface_no_resume(acm->control);
+ acm->control->needs_remote_wakeup = 0;
+ usb_autopm_put_interface(acm->control);
+
+ for (;;) {
+ urb = usb_get_from_anchor(&acm->delayed);
+ if (!urb)
+ break;
+ wb = urb->context;
+ wb->use = 0;
+ usb_autopm_put_interface_async(acm->control);
}
- mutex_unlock(&acm->mutex);
+
+ usb_kill_urb(acm->ctrlurb);
+ for (i = 0; i < ACM_NW; i++)
+ usb_kill_urb(acm->wb[i].urb);
+ for (i = 0; i < acm->rx_buflimit; i++)
+ usb_kill_urb(acm->read_urbs[i]);
}
static void acm_tty_cleanup(struct tty_struct *tty)
@@ -646,16 +687,18 @@ static int acm_tty_write(struct tty_struct *tty,
memcpy(wb->buf, buf, count);
wb->len = count;
- usb_autopm_get_interface_async(acm->control);
+ stat = usb_autopm_get_interface_async(acm->control);
+ if (stat) {
+ wb->use = 0;
+ spin_unlock_irqrestore(&acm->write_lock, flags);
+ return stat;
+ }
+
if (acm->susp_count) {
- if (!acm->delayed_wb)
- acm->delayed_wb = wb;
- else
- usb_autopm_put_interface_async(acm->control);
+ usb_anchor_urb(wb->urb, &acm->delayed);
spin_unlock_irqrestore(&acm->write_lock, flags);
- return count; /* A white lie */
+ return count;
}
- usb_mark_last_busy(acm->dev);
stat = acm_start_wb(acm, wb);
spin_unlock_irqrestore(&acm->write_lock, flags);
@@ -958,6 +1001,7 @@ static void acm_tty_set_termios(struct tty_struct *tty,
}
static const struct tty_port_operations acm_port_ops = {
+ .dtr_rts = acm_port_dtr_rts,
.shutdown = acm_port_shutdown,
.activate = acm_port_activate,
.destruct = acm_port_destruct,
@@ -1269,6 +1313,7 @@ made_compressed_probe:
acm->bInterval = epread->bInterval;
tty_port_init(&acm->port);
acm->port.ops = &acm_port_ops;
+ init_usb_anchor(&acm->delayed);
buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
if (!buf) {
@@ -1394,8 +1439,6 @@ skip_countries:
dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
- acm_set_control(acm, acm->ctrlout);
-
acm->line.dwDTERate = cpu_to_le32(9600);
acm->line.bDataBits = 8;
acm_set_line(acm, &acm->line);
@@ -1514,27 +1557,20 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message)
struct acm *acm = usb_get_intfdata(intf);
int cnt;
+ spin_lock_irq(&acm->write_lock);
if (PMSG_IS_AUTO(message)) {
- int b;
-
- spin_lock_irq(&acm->write_lock);
- b = acm->transmitting;
- spin_unlock_irq(&acm->write_lock);
- if (b)
+ if (acm->transmitting) {
+ spin_unlock_irq(&acm->write_lock);
return -EBUSY;
+ }
}
-
- spin_lock_irq(&acm->read_lock);
- spin_lock(&acm->write_lock);
cnt = acm->susp_count++;
- spin_unlock(&acm->write_lock);
- spin_unlock_irq(&acm->read_lock);
+ spin_unlock_irq(&acm->write_lock);
if (cnt)
return 0;
- if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags))
- stop_data_traffic(acm);
+ stop_data_traffic(acm);
return 0;
}
@@ -1542,29 +1578,23 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message)
static int acm_resume(struct usb_interface *intf)
{
struct acm *acm = usb_get_intfdata(intf);
- struct acm_wb *wb;
+ struct urb *urb;
int rv = 0;
- int cnt;
- spin_lock_irq(&acm->read_lock);
- acm->susp_count -= 1;
- cnt = acm->susp_count;
- spin_unlock_irq(&acm->read_lock);
+ spin_lock_irq(&acm->write_lock);
- if (cnt)
- return 0;
+ if (--acm->susp_count)
+ goto out;
if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags)) {
- rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);
+ rv = usb_submit_urb(acm->ctrlurb, GFP_ATOMIC);
- spin_lock_irq(&acm->write_lock);
- if (acm->delayed_wb) {
- wb = acm->delayed_wb;
- acm->delayed_wb = NULL;
- spin_unlock_irq(&acm->write_lock);
- acm_start_wb(acm, wb);
- } else {
- spin_unlock_irq(&acm->write_lock);
+ for (;;) {
+ urb = usb_get_from_anchor(&acm->delayed);
+ if (!urb)
+ break;
+
+ acm_start_wb(acm, urb->context);
}
/*
@@ -1572,12 +1602,13 @@ static int acm_resume(struct usb_interface *intf)
* do the write path at all cost
*/
if (rv < 0)
- goto err_out;
+ goto out;
- rv = acm_submit_read_urbs(acm, GFP_NOIO);
+ rv = acm_submit_read_urbs(acm, GFP_ATOMIC);
}
+out:
+ spin_unlock_irq(&acm->write_lock);
-err_out:
return rv;
}
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index e38dc785808f..fc75651afe1c 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -120,15 +120,15 @@ struct acm {
unsigned int throttled:1; /* actually throttled */
unsigned int throttle_req:1; /* throttle requested */
u8 bInterval;
- struct acm_wb *delayed_wb; /* write queued for a device about to be woken */
+ struct usb_anchor delayed; /* writes queued for a device about to be woken */
};
#define CDC_DATA_INTERFACE_TYPE 0x0a
/* constants describing various quirks and errors */
-#define NO_UNION_NORMAL 1
-#define SINGLE_RX_URB 2
-#define NO_CAP_LINE 4
-#define NOT_A_MODEM 8
-#define NO_DATA_INTERFACE 16
-#define IGNORE_DEVICE 32
+#define NO_UNION_NORMAL BIT(0)
+#define SINGLE_RX_URB BIT(1)
+#define NO_CAP_LINE BIT(2)
+#define NOT_A_MODEM BIT(3)
+#define NO_DATA_INTERFACE BIT(4)
+#define IGNORE_DEVICE BIT(5)
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c
index cfbec9c7e09e..103a6e9ee49d 100644
--- a/drivers/usb/class/usbtmc.c
+++ b/drivers/usb/class/usbtmc.c
@@ -383,9 +383,12 @@ exit:
static int send_request_dev_dep_msg_in(struct usbtmc_device_data *data, size_t transfer_size)
{
int retval;
- u8 buffer[USBTMC_HEADER_SIZE];
+ u8 *buffer;
int actual;
+ buffer = kmalloc(USBTMC_HEADER_SIZE, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
/* Setup IO buffer for REQUEST_DEV_DEP_MSG_IN message
* Refer to class specs for details
*/
@@ -417,6 +420,7 @@ static int send_request_dev_dep_msg_in(struct usbtmc_device_data *data, size_t t
if (!data->bTag)
data->bTag++;
+ kfree(buffer);
if (retval < 0) {
dev_err(&data->intf->dev, "usb_bulk_msg in send_request_dev_dep_msg_in() returned %d\n", retval);
return retval;
diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile
new file mode 100644
index 000000000000..752646167e1e
--- /dev/null
+++ b/drivers/usb/common/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the usb common parts.
+#
+
+obj-$(CONFIG_USB_COMMON) += usb-common.o
+obj-$(CONFIG_USB_OTG_FSM) += usb-otg-fsm.o
diff --git a/drivers/usb/usb-common.c b/drivers/usb/common/usb-common.c
index 6dfd30a863c7..6dfd30a863c7 100644
--- a/drivers/usb/usb-common.c
+++ b/drivers/usb/common/usb-common.c
diff --git a/drivers/usb/phy/phy-fsm-usb.c b/drivers/usb/common/usb-otg-fsm.c
index d03fadd2629f..98e8340a5bb1 100644
--- a/drivers/usb/phy/phy-fsm-usb.c
+++ b/drivers/usb/common/usb-otg-fsm.c
@@ -364,3 +364,4 @@ int otg_statemachine(struct otg_fsm *fsm)
VDBG("quit statemachine, changed = %d\n", state_changed);
return state_changed;
}
+EXPORT_SYMBOL_GPL(otg_statemachine);
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index cb8e99156f5a..1060657ca1b0 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -1,13 +1,6 @@
#
# USB Core configuration
#
-config USB_DEBUG
- bool "USB verbose debug messages"
- 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
- problem with USB support and want to see more of what is going on.
-
config USB_ANNOUNCE_NEW_DEVICES
bool "USB announce new devices"
help
@@ -88,3 +81,12 @@ config USB_OTG_BLACKLIST_HUB
and software costs by not supporting external hubs. So
are "Embedded Hosts" that don't offer OTG support.
+config USB_OTG_FSM
+ tristate "USB 2.0 OTG FSM implementation"
+ depends on USB
+ select USB_OTG
+ select USB_PHY
+ help
+ Implements OTG Finite State Machine as specified in On-The-Go
+ and Embedded Host Supplement to the USB Revision 2.0 Specification.
+
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 1f02e65fe305..82044b5d6113 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -192,7 +192,6 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
if (pci_enable_device(dev) < 0)
return -ENODEV;
- dev->current_state = PCI_D0;
/*
* The xHCI driver has its own irq management
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 9c4e2922b04d..bec31e2efb88 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -918,6 +918,7 @@ static void usb_bus_init (struct usb_bus *bus)
bus->bandwidth_allocated = 0;
bus->bandwidth_int_reqs = 0;
bus->bandwidth_isoc_reqs = 0;
+ mutex_init(&bus->usb_address0_mutex);
INIT_LIST_HEAD (&bus->bus_list);
}
@@ -1502,6 +1503,9 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
ret = -EAGAIN;
else
urb->transfer_flags |= URB_DMA_MAP_PAGE;
+ } else if (is_vmalloc_addr(urb->transfer_buffer)) {
+ WARN_ONCE(1, "transfer buffer not dma capable\n");
+ ret = -EAGAIN;
} else {
urb->transfer_dma = dma_map_single(
hcd->self.controller,
@@ -2263,9 +2267,7 @@ static void hcd_resume_work(struct work_struct *work)
struct usb_hcd *hcd = container_of(work, struct usb_hcd, wakeup_work);
struct usb_device *udev = hcd->self.root_hub;
- usb_lock_device(udev);
usb_remote_wakeup(udev);
- usb_unlock_device(udev);
}
/**
@@ -2454,11 +2456,13 @@ struct usb_hcd *usb_create_shared_hcd(const struct hc_driver *driver,
mutex_init(hcd->bandwidth_mutex);
dev_set_drvdata(dev, hcd);
} else {
+ mutex_lock(&usb_port_peer_mutex);
hcd->bandwidth_mutex = primary_hcd->bandwidth_mutex;
hcd->primary_hcd = primary_hcd;
primary_hcd->primary_hcd = primary_hcd;
hcd->shared_hcd = primary_hcd;
primary_hcd->shared_hcd = hcd;
+ mutex_unlock(&usb_port_peer_mutex);
}
kref_init(&hcd->kref);
@@ -2510,18 +2514,25 @@ EXPORT_SYMBOL_GPL(usb_create_hcd);
* deallocated.
*
* Make sure to only deallocate the bandwidth_mutex when the primary HCD is
- * freed. When hcd_release() is called for the non-primary HCD, set the
- * primary_hcd's shared_hcd pointer to null (since the non-primary HCD will be
- * freed shortly).
+ * freed. When hcd_release() is called for either hcd in a peer set
+ * invalidate the peer's ->shared_hcd and ->primary_hcd pointers to
+ * block new peering attempts
*/
-static void hcd_release (struct kref *kref)
+static void hcd_release(struct kref *kref)
{
struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref);
+ mutex_lock(&usb_port_peer_mutex);
if (usb_hcd_is_primary_hcd(hcd))
kfree(hcd->bandwidth_mutex);
- else
- hcd->shared_hcd->shared_hcd = NULL;
+ if (hcd->shared_hcd) {
+ struct usb_hcd *peer = hcd->shared_hcd;
+
+ peer->shared_hcd = NULL;
+ if (peer->primary_hcd == hcd)
+ peer->primary_hcd = NULL;
+ }
+ mutex_unlock(&usb_port_peer_mutex);
kfree(hcd);
}
@@ -2589,6 +2600,21 @@ static int usb_hcd_request_irqs(struct usb_hcd *hcd,
return 0;
}
+/*
+ * Before we free this root hub, flush in-flight peering attempts
+ * and disable peer lookups
+ */
+static void usb_put_invalidate_rhdev(struct usb_hcd *hcd)
+{
+ struct usb_device *rhdev;
+
+ mutex_lock(&usb_port_peer_mutex);
+ rhdev = hcd->self.root_hub;
+ hcd->self.root_hub = NULL;
+ mutex_unlock(&usb_port_peer_mutex);
+ usb_put_dev(rhdev);
+}
+
/**
* usb_add_hcd - finish generic HCD structure initialization and register
* @hcd: the usb_hcd structure to initialize
@@ -2649,7 +2675,9 @@ int usb_add_hcd(struct usb_hcd *hcd,
retval = -ENOMEM;
goto err_allocate_root_hub;
}
+ mutex_lock(&usb_port_peer_mutex);
hcd->self.root_hub = rhdev;
+ mutex_unlock(&usb_port_peer_mutex);
switch (hcd->speed) {
case HCD_USB11:
@@ -2758,7 +2786,7 @@ err_hcd_driver_start:
err_request_irq:
err_hcd_driver_setup:
err_set_rh_speed:
- usb_put_dev(hcd->self.root_hub);
+ usb_put_invalidate_rhdev(hcd);
err_allocate_root_hub:
usb_deregister_bus(&hcd->self);
err_register_bus:
@@ -2838,7 +2866,6 @@ void usb_remove_hcd(struct usb_hcd *hcd)
free_irq(hcd->irq, hcd);
}
- usb_put_dev(hcd->self.root_hub);
usb_deregister_bus(&hcd->self);
hcd_buffer_destroy(hcd);
if (hcd->remove_phy && hcd->phy) {
@@ -2846,6 +2873,8 @@ void usb_remove_hcd(struct usb_hcd *hcd)
usb_put_phy(hcd->phy);
hcd->phy = NULL;
}
+
+ usb_put_invalidate_rhdev(hcd);
}
EXPORT_SYMBOL_GPL(usb_remove_hcd);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 090469ebfcff..db6287025c06 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -36,11 +36,6 @@
#define USB_VENDOR_GENESYS_LOGIC 0x05e3
#define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01
-static inline int hub_is_superspeed(struct usb_device *hdev)
-{
- return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS);
-}
-
/* Protect struct usb_device->state and ->children members
* Note: Both are also protected by ->dev.sem, except that ->state can
* change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
@@ -55,6 +50,9 @@ static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);
static struct task_struct *khubd_task;
+/* synchronize hub-port add/remove and peering operations */
+DEFINE_MUTEX(usb_port_peer_mutex);
+
/* cycle leds on hubs that aren't blinking for attention */
static bool blinkenlights = 0;
module_param (blinkenlights, bool, S_IRUGO);
@@ -412,30 +410,35 @@ static int set_port_feature(struct usb_device *hdev, int port1, int feature)
NULL, 0, 1000);
}
+static char *to_led_name(int selector)
+{
+ switch (selector) {
+ case HUB_LED_AMBER:
+ return "amber";
+ case HUB_LED_GREEN:
+ return "green";
+ case HUB_LED_OFF:
+ return "off";
+ case HUB_LED_AUTO:
+ return "auto";
+ default:
+ return "??";
+ }
+}
+
/*
* USB 2.0 spec Section 11.24.2.7.1.10 and table 11-7
* for info about using port indicators
*/
-static void set_port_led(
- struct usb_hub *hub,
- int port1,
- int selector
-)
+static void set_port_led(struct usb_hub *hub, int port1, int selector)
{
- int status = set_port_feature(hub->hdev, (selector << 8) | port1,
+ struct usb_port *port_dev = hub->ports[port1 - 1];
+ int status;
+
+ status = set_port_feature(hub->hdev, (selector << 8) | port1,
USB_PORT_FEAT_INDICATOR);
- if (status < 0)
- dev_dbg (hub->intfdev,
- "port %d indicator %s status %d\n",
- port1,
- ({ char *s; switch (selector) {
- case HUB_LED_AMBER: s = "amber"; break;
- case HUB_LED_GREEN: s = "green"; break;
- case HUB_LED_OFF: s = "off"; break;
- case HUB_LED_AUTO: s = "auto"; break;
- default: s = "??"; break;
- } s; }),
- status);
+ dev_dbg(&port_dev->dev, "indicator %s status %d\n",
+ to_led_name(selector), status);
}
#define LED_CYCLE_PERIOD ((2*HZ)/3)
@@ -743,16 +746,20 @@ int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
int port1, bool set)
{
int ret;
- struct usb_port *port_dev = hub->ports[port1 - 1];
if (set)
ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
else
ret = usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
- if (!ret)
- port_dev->power_is_on = set;
- return ret;
+ if (ret)
+ return ret;
+
+ if (set)
+ set_bit(port1, hub->power_bits);
+ else
+ clear_bit(port1, hub->power_bits);
+ return 0;
}
/**
@@ -810,16 +817,9 @@ int usb_hub_clear_tt_buffer(struct urb *urb)
}
EXPORT_SYMBOL_GPL(usb_hub_clear_tt_buffer);
-/* If do_delay is false, return the number of milliseconds the caller
- * needs to delay.
- */
-static unsigned hub_power_on(struct usb_hub *hub, bool do_delay)
+static void hub_power_on(struct usb_hub *hub, bool do_delay)
{
int port1;
- unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2;
- unsigned delay;
- u16 wHubCharacteristics =
- le16_to_cpu(hub->descriptor->wHubCharacteristics);
/* Enable power on each port. Some hubs have reserved values
* of LPSM (> 2) in their descriptors, even though they are
@@ -827,23 +827,19 @@ static unsigned hub_power_on(struct usb_hub *hub, bool do_delay)
* but only emulate it. In all cases, the ports won't work
* unless we send these messages to the hub.
*/
- if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2)
+ if (hub_is_port_power_switchable(hub))
dev_dbg(hub->intfdev, "enabling power on all ports\n");
else
dev_dbg(hub->intfdev, "trying to enable port power on "
"non-switchable hub\n");
for (port1 = 1; port1 <= hub->hdev->maxchild; port1++)
- if (hub->ports[port1 - 1]->power_is_on)
+ if (test_bit(port1, hub->power_bits))
set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER);
else
usb_clear_port_feature(hub->hdev, port1,
USB_PORT_FEAT_POWER);
-
- /* Wait at least 100 msec for power to become stable */
- delay = max(pgood_delay, (unsigned) 100);
if (do_delay)
- msleep(delay);
- return delay;
+ msleep(hub_power_on_good_delay(hub));
}
static int hub_hub_status(struct usb_hub *hub,
@@ -911,20 +907,20 @@ static int hub_usb3_port_disable(struct usb_hub *hub, int port1)
msleep(HUB_DEBOUNCE_STEP);
}
if (total_time >= HUB_DEBOUNCE_TIMEOUT)
- dev_warn(hub->intfdev, "Could not disable port %d after %d ms\n",
- port1, total_time);
+ dev_warn(&hub->ports[port1 - 1]->dev,
+ "Could not disable after %d ms\n", total_time);
return hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_RX_DETECT);
}
static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
{
+ struct usb_port *port_dev = hub->ports[port1 - 1];
struct usb_device *hdev = hub->hdev;
int ret = 0;
- if (hub->ports[port1 - 1]->child && set_state)
- usb_set_device_state(hub->ports[port1 - 1]->child,
- USB_STATE_NOTATTACHED);
+ if (port_dev->child && set_state)
+ usb_set_device_state(port_dev->child, USB_STATE_NOTATTACHED);
if (!hub->error) {
if (hub_is_superspeed(hub->hdev))
ret = hub_usb3_port_disable(hub, port1);
@@ -933,8 +929,7 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
USB_PORT_FEAT_ENABLE);
}
if (ret && ret != -ENODEV)
- dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
- port1, ret);
+ dev_err(&port_dev->dev, "cannot disable (err = %d)\n", ret);
return ret;
}
@@ -945,7 +940,7 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
*/
static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
{
- dev_dbg(hub->intfdev, "logical disconnect on port %d\n", port1);
+ dev_dbg(&hub->ports[port1 - 1]->dev, "logical disconnect\n");
hub_port_disable(hub, port1, 1);
/* FIXME let caller ask to power down the port:
@@ -1048,7 +1043,9 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
* for HUB_POST_RESET, but it's easier not to.
*/
if (type == HUB_INIT) {
- delay = hub_power_on(hub, false);
+ unsigned delay = hub_power_on_good_delay(hub);
+
+ hub_power_on(hub, false);
INIT_DELAYED_WORK(&hub->init_work, hub_init_func2);
queue_delayed_work(system_power_efficient_wq,
&hub->init_work,
@@ -1083,21 +1080,23 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
}
init2:
- /* Check each port and set hub->change_bits to let khubd know
+ /*
+ * Check each port and set hub->change_bits to let khubd know
* which ports need attention.
*/
for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
- struct usb_device *udev = hub->ports[port1 - 1]->child;
+ struct usb_port *port_dev = hub->ports[port1 - 1];
+ struct usb_device *udev = port_dev->child;
u16 portstatus, portchange;
portstatus = portchange = 0;
status = hub_port_status(hub, port1, &portstatus, &portchange);
if (udev || (portstatus & USB_PORT_STAT_CONNECTION))
- dev_dbg(hub->intfdev,
- "port %d: status %04x change %04x\n",
- port1, portstatus, portchange);
+ dev_dbg(&port_dev->dev, "status %04x change %04x\n",
+ portstatus, portchange);
- /* After anything other than HUB_RESUME (i.e., initialization
+ /*
+ * After anything other than HUB_RESUME (i.e., initialization
* or any sort of reset), every port should be disabled.
* Unconnected ports should likewise be disabled (paranoia),
* and so should ports for which we have no usb_device.
@@ -1173,15 +1172,13 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
set_bit(port1, hub->change_bits);
} else if (udev->persist_enabled) {
- struct usb_port *port_dev = hub->ports[port1 - 1];
-
#ifdef CONFIG_PM
udev->reset_resume = 1;
#endif
/* Don't set the change_bits when the device
* was powered off.
*/
- if (port_dev->power_is_on)
+ if (test_bit(port1, hub->power_bits))
set_bit(port1, hub->change_bits);
} else {
@@ -1276,12 +1273,22 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
flush_work(&hub->tt.clear_work);
}
+static void hub_pm_barrier_for_all_ports(struct usb_hub *hub)
+{
+ int i;
+
+ for (i = 0; i < hub->hdev->maxchild; ++i)
+ pm_runtime_barrier(&hub->ports[i]->dev);
+}
+
/* caller has locked the hub device */
static int hub_pre_reset(struct usb_interface *intf)
{
struct usb_hub *hub = usb_get_intfdata(intf);
hub_quiesce(hub, HUB_PRE_RESET);
+ hub->in_reset = 1;
+ hub_pm_barrier_for_all_ports(hub);
return 0;
}
@@ -1290,6 +1297,8 @@ static int hub_post_reset(struct usb_interface *intf)
{
struct usb_hub *hub = usb_get_intfdata(intf);
+ hub->in_reset = 0;
+ hub_pm_barrier_for_all_ports(hub);
hub_activate(hub, HUB_POST_RESET);
return 0;
}
@@ -1307,6 +1316,7 @@ static int hub_configure(struct usb_hub *hub,
char *message = "out of memory";
unsigned unit_load;
unsigned full_load;
+ unsigned maxchild;
hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL);
if (!hub->buffer) {
@@ -1345,12 +1355,11 @@ static int hub_configure(struct usb_hub *hub,
goto fail;
}
- hdev->maxchild = hub->descriptor->bNbrPorts;
- dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild,
- (hdev->maxchild == 1) ? "" : "s");
+ maxchild = hub->descriptor->bNbrPorts;
+ dev_info(hub_dev, "%d port%s detected\n", maxchild,
+ (maxchild == 1) ? "" : "s");
- hub->ports = kzalloc(hdev->maxchild * sizeof(struct usb_port *),
- GFP_KERNEL);
+ hub->ports = kzalloc(maxchild * sizeof(struct usb_port *), GFP_KERNEL);
if (!hub->ports) {
ret = -ENOMEM;
goto fail;
@@ -1371,11 +1380,11 @@ static int hub_configure(struct usb_hub *hub,
int i;
char portstr[USB_MAXCHILDREN + 1];
- for (i = 0; i < hdev->maxchild; i++)
+ for (i = 0; i < maxchild; i++)
portstr[i] = hub->descriptor->u.hs.DeviceRemovable
[((i + 1) / 8)] & (1 << ((i + 1) % 8))
? 'F' : 'R';
- portstr[hdev->maxchild] = 0;
+ portstr[maxchild] = 0;
dev_dbg(hub_dev, "compound device; port removable status: %s\n", portstr);
} else
dev_dbg(hub_dev, "standalone hub\n");
@@ -1487,7 +1496,7 @@ static int hub_configure(struct usb_hub *hub,
if (hcd->power_budget > 0)
hdev->bus_mA = hcd->power_budget;
else
- hdev->bus_mA = full_load * hdev->maxchild;
+ hdev->bus_mA = full_load * maxchild;
if (hdev->bus_mA >= full_load)
hub->mA_per_port = full_load;
else {
@@ -1502,7 +1511,7 @@ static int hub_configure(struct usb_hub *hub,
hub->descriptor->bHubContrCurrent);
hub->limited_power = 1;
- if (remaining < hdev->maxchild * unit_load)
+ if (remaining < maxchild * unit_load)
dev_warn(hub_dev,
"insufficient power available "
"to use all downstream ports\n");
@@ -1570,15 +1579,19 @@ static int hub_configure(struct usb_hub *hub,
if (hub->has_indicators && blinkenlights)
hub->indicator[0] = INDICATOR_CYCLE;
- for (i = 0; i < hdev->maxchild; i++) {
+ mutex_lock(&usb_port_peer_mutex);
+ for (i = 0; i < maxchild; i++) {
ret = usb_hub_create_port_device(hub, i + 1);
if (ret < 0) {
dev_err(hub->intfdev,
"couldn't create port%d device.\n", i + 1);
- hdev->maxchild = i;
- goto fail_keep_maxchild;
+ break;
}
}
+ hdev->maxchild = i;
+ mutex_unlock(&usb_port_peer_mutex);
+ if (ret < 0)
+ goto fail;
usb_hub_adjust_deviceremovable(hdev, hub->descriptor);
@@ -1586,8 +1599,6 @@ static int hub_configure(struct usb_hub *hub,
return 0;
fail:
- hdev->maxchild = 0;
-fail_keep_maxchild:
dev_err (hub_dev, "config failed, %s (err %d)\n",
message, ret);
/* hub_disconnect() frees urb and descriptor */
@@ -1623,6 +1634,8 @@ static void hub_disconnect(struct usb_interface *intf)
hub->error = 0;
hub_quiesce(hub, HUB_DISCONNECT);
+ mutex_lock(&usb_port_peer_mutex);
+
/* Avoid races with recursively_mark_NOTATTACHED() */
spin_lock_irq(&device_state_lock);
port1 = hdev->maxchild;
@@ -1633,6 +1646,8 @@ static void hub_disconnect(struct usb_interface *intf)
for (; port1 > 0; --port1)
usb_hub_remove_port_device(hub, port1);
+ mutex_unlock(&usb_port_peer_mutex);
+
if (hub->hdev->speed == USB_SPEED_HIGH)
highspeed_hubs--;
@@ -2024,6 +2039,18 @@ static void hub_free_dev(struct usb_device *udev)
hcd->driver->free_dev(hcd, udev);
}
+static void hub_disconnect_children(struct usb_device *udev)
+{
+ struct usb_hub *hub = usb_hub_to_struct_hub(udev);
+ int i;
+
+ /* Free up all the children before we remove this device */
+ for (i = 0; i < udev->maxchild; i++) {
+ if (hub->ports[i]->child)
+ usb_disconnect(&hub->ports[i]->child);
+ }
+}
+
/**
* usb_disconnect - disconnect a device (usbcore-internal)
* @pdev: pointer to device being disconnected
@@ -2042,9 +2069,10 @@ static void hub_free_dev(struct usb_device *udev)
*/
void usb_disconnect(struct usb_device **pdev)
{
- struct usb_device *udev = *pdev;
- struct usb_hub *hub = usb_hub_to_struct_hub(udev);
- int i;
+ struct usb_port *port_dev = NULL;
+ struct usb_device *udev = *pdev;
+ struct usb_hub *hub;
+ int port1;
/* mark the device as inactive, so any further urb submissions for
* this device (and any of its children) will fail immediately.
@@ -2056,11 +2084,7 @@ void usb_disconnect(struct usb_device **pdev)
usb_lock_device(udev);
- /* Free up all the children before we remove this device */
- for (i = 0; i < udev->maxchild; i++) {
- if (hub->ports[i]->child)
- usb_disconnect(&hub->ports[i]->child);
- }
+ hub_disconnect_children(udev);
/* deallocate hcd/hardware state ... nuking all pending urbs and
* cleaning up all state associated with the current configuration
@@ -2071,16 +2095,19 @@ void usb_disconnect(struct usb_device **pdev)
usb_hcd_synchronize_unlinks(udev);
if (udev->parent) {
- struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent);
- struct usb_port *port_dev = hub->ports[udev->portnum - 1];
+ port1 = udev->portnum;
+ hub = usb_hub_to_struct_hub(udev->parent);
+ port_dev = hub->ports[port1 - 1];
sysfs_remove_link(&udev->dev.kobj, "port");
sysfs_remove_link(&port_dev->dev.kobj, "device");
- if (!port_dev->did_runtime_put)
- pm_runtime_put(&port_dev->dev);
- else
- port_dev->did_runtime_put = false;
+ /*
+ * As usb_port_runtime_resume() de-references udev, make
+ * sure no resumes occur during removal
+ */
+ if (!test_and_set_bit(port1, hub->child_usage_bits))
+ pm_runtime_get_sync(&port_dev->dev);
}
usb_remove_ep_devs(&udev->ep0);
@@ -2102,6 +2129,9 @@ void usb_disconnect(struct usb_device **pdev)
*pdev = NULL;
spin_unlock_irq(&device_state_lock);
+ if (port_dev && test_and_clear_bit(port1, hub->child_usage_bits))
+ pm_runtime_put(&port_dev->dev);
+
hub_free_dev(udev);
put_device(&udev->dev);
@@ -2289,6 +2319,22 @@ static void set_usb_port_removable(struct usb_device *udev)
udev->removable = USB_DEVICE_REMOVABLE;
else
udev->removable = USB_DEVICE_FIXED;
+
+ /*
+ * Platform firmware may have populated an alternative value for
+ * removable. If the parent port has a known connect_type use
+ * that instead.
+ */
+ switch (hub->ports[udev->portnum - 1]->connect_type) {
+ case USB_PORT_CONNECT_TYPE_HOT_PLUG:
+ udev->removable = USB_DEVICE_REMOVABLE;
+ break;
+ case USB_PORT_CONNECT_TYPE_HARD_WIRED:
+ udev->removable = USB_DEVICE_FIXED;
+ break;
+ default: /* use what was set above */
+ break;
+ }
}
/**
@@ -2358,11 +2404,7 @@ int usb_new_device(struct usb_device *udev)
device_enable_async_suspend(&udev->dev);
- /*
- * check whether the hub marks this port as non-removable. Do it
- * now so that platform-specific data can override it in
- * device_add()
- */
+ /* check whether the hub or firmware marks this port as non-removable */
if (udev->parent)
set_usb_port_removable(udev);
@@ -2379,7 +2421,8 @@ int usb_new_device(struct usb_device *udev)
/* Create link files between child device and usb port device. */
if (udev->parent) {
struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent);
- struct usb_port *port_dev = hub->ports[udev->portnum - 1];
+ int port1 = udev->portnum;
+ struct usb_port *port_dev = hub->ports[port1 - 1];
err = sysfs_create_link(&udev->dev.kobj,
&port_dev->dev.kobj, "port");
@@ -2393,7 +2436,8 @@ int usb_new_device(struct usb_device *udev)
goto fail;
}
- pm_runtime_get_sync(&port_dev->dev);
+ if (!test_and_set_bit(port1, hub->child_usage_bits))
+ pm_runtime_get_sync(&port_dev->dev);
}
(void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev);
@@ -2561,9 +2605,9 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
if (delay_time >= 2 * HUB_SHORT_RESET_TIME)
delay = HUB_LONG_RESET_TIME;
- dev_dbg (hub->intfdev,
- "port %d not %sreset yet, waiting %dms\n",
- port1, warm ? "warm " : "", delay);
+ dev_dbg(&hub->ports[port1 - 1]->dev,
+ "not %sreset yet, waiting %dms\n",
+ warm ? "warm " : "", delay);
}
if ((portstatus & USB_PORT_STAT_RESET))
@@ -2647,6 +2691,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
{
int i, status;
u16 portchange, portstatus;
+ struct usb_port *port_dev = hub->ports[port1 - 1];
if (!hub_is_superspeed(hub->hdev)) {
if (warm) {
@@ -2680,9 +2725,9 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
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);
+ dev_err(&port_dev->dev,
+ "cannot %sreset (err = %d)\n",
+ warm ? "warm " : "", status);
} else {
status = hub_port_wait_reset(hub, port1, udev, delay,
warm);
@@ -2715,21 +2760,19 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
* hot or warm reset failed. Try another warm reset.
*/
if (!warm) {
- dev_dbg(hub->intfdev, "hot reset failed, warm reset port %d\n",
- port1);
+ dev_dbg(&port_dev->dev,
+ "hot reset failed, warm reset\n");
warm = true;
}
}
- dev_dbg (hub->intfdev,
- "port %d not enabled, trying %sreset again...\n",
- port1, warm ? "warm " : "");
+ dev_dbg(&port_dev->dev,
+ "not enabled, trying %sreset again...\n",
+ warm ? "warm " : "");
delay = HUB_LONG_RESET_TIME;
}
- dev_err (hub->intfdev,
- "Cannot enable port %i. Maybe the USB cable is bad?\n",
- port1);
+ dev_err(&port_dev->dev, "Cannot enable. Maybe the USB cable is bad?\n");
done:
if (!hub_is_superspeed(hub->hdev))
@@ -2754,6 +2797,20 @@ static int port_is_power_on(struct usb_hub *hub, unsigned portstatus)
return ret;
}
+static void usb_lock_port(struct usb_port *port_dev)
+ __acquires(&port_dev->status_lock)
+{
+ mutex_lock(&port_dev->status_lock);
+ __acquire(&port_dev->status_lock);
+}
+
+static void usb_unlock_port(struct usb_port *port_dev)
+ __releases(&port_dev->status_lock)
+{
+ mutex_unlock(&port_dev->status_lock);
+ __release(&port_dev->status_lock);
+}
+
#ifdef CONFIG_PM
/* Check if a port is suspended(USB2.0 port) or in U3 state(USB3.0 port) */
@@ -2780,6 +2837,8 @@ static int check_port_resume_type(struct usb_device *udev,
struct usb_hub *hub, int port1,
int status, unsigned portchange, unsigned portstatus)
{
+ struct usb_port *port_dev = hub->ports[port1 - 1];
+
/* Is the device still present? */
if (status || port_is_suspended(hub, portstatus) ||
!port_is_power_on(hub, portstatus) ||
@@ -2799,9 +2858,8 @@ static int check_port_resume_type(struct usb_device *udev,
}
if (status) {
- dev_dbg(hub->intfdev,
- "port %d status %04x.%04x after resume, %d\n",
- port1, portchange, portstatus, status);
+ dev_dbg(&port_dev->dev, "status %04x.%04x after resume, %d\n",
+ portchange, portstatus, status);
} else if (udev->reset_resume) {
/* Late port handoff can set status-change bits */
@@ -2975,6 +3033,8 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
int status;
bool really_suspend = true;
+ usb_lock_port(port_dev);
+
/* enable remote wakeup when appropriate; this lets the device
* wake up the upstream hub (including maybe the root hub).
*
@@ -3032,8 +3092,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
status = 0;
}
if (status) {
- dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
- port1, status);
+ dev_dbg(&port_dev->dev, "can't suspend, status %d\n", status);
/* Try to enable USB3 LPM and LTM again */
usb_unlocked_enable_lpm(udev);
@@ -3064,12 +3123,13 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
usb_set_device_state(udev, USB_STATE_SUSPENDED);
}
- if (status == 0 && !udev->do_remote_wakeup && udev->persist_enabled) {
+ if (status == 0 && !udev->do_remote_wakeup && udev->persist_enabled
+ && test_and_clear_bit(port1, hub->child_usage_bits))
pm_runtime_put_sync(&port_dev->dev);
- port_dev->did_runtime_put = true;
- }
usb_mark_last_busy(hub->hdev);
+
+ usb_unlock_port(port_dev);
return status;
}
@@ -3209,9 +3269,8 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
int status;
u16 portchange, portstatus;
- if (port_dev->did_runtime_put) {
+ if (!test_and_set_bit(port1, hub->child_usage_bits)) {
status = pm_runtime_get_sync(&port_dev->dev);
- port_dev->did_runtime_put = false;
if (status < 0) {
dev_dbg(&udev->dev, "can't resume usb port, status %d\n",
status);
@@ -3219,15 +3278,13 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
}
}
+ usb_lock_port(port_dev);
+
/* Skip the initial Clear-Suspend step for a remote wakeup */
status = hub_port_status(hub, port1, &portstatus, &portchange);
if (status == 0 && !port_is_suspended(hub, portstatus))
goto SuspendCleared;
- /* dev_dbg(hub->intfdev, "resume port %d\n", port1); */
-
- set_bit(port1, hub->busy_bits);
-
/* see 7.1.7.7; affects power usage, but not budgeting */
if (hub_is_superspeed(hub->hdev))
status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U0);
@@ -3235,8 +3292,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
status = usb_clear_port_feature(hub->hdev,
port1, USB_PORT_FEAT_SUSPEND);
if (status) {
- dev_dbg(hub->intfdev, "can't resume port %d, status %d\n",
- port1, status);
+ dev_dbg(&port_dev->dev, "can't resume, status %d\n", status);
} else {
/* drive resume for at least 20 msec */
dev_dbg(&udev->dev, "usb %sresume\n",
@@ -3267,8 +3323,6 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
}
}
- clear_bit(port1, hub->busy_bits);
-
status = check_port_resume_type(udev,
hub, port1, status, portchange, portstatus);
if (status == 0)
@@ -3286,16 +3340,18 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
usb_unlocked_enable_lpm(udev);
}
+ usb_unlock_port(port_dev);
+
return status;
}
#ifdef CONFIG_PM_RUNTIME
-/* caller has locked udev */
int usb_remote_wakeup(struct usb_device *udev)
{
int status = 0;
+ usb_lock_device(udev);
if (udev->state == USB_STATE_SUSPENDED) {
dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
status = usb_autoresume_device(udev);
@@ -3304,9 +3360,59 @@ int usb_remote_wakeup(struct usb_device *udev)
usb_autosuspend_device(udev);
}
}
+ usb_unlock_device(udev);
return status;
}
+/* Returns 1 if there was a remote wakeup and a connect status change. */
+static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port,
+ u16 portstatus, u16 portchange)
+ __must_hold(&port_dev->status_lock)
+{
+ struct usb_port *port_dev = hub->ports[port - 1];
+ struct usb_device *hdev;
+ struct usb_device *udev;
+ int connect_change = 0;
+ int ret;
+
+ hdev = hub->hdev;
+ udev = port_dev->child;
+ if (!hub_is_superspeed(hdev)) {
+ if (!(portchange & USB_PORT_STAT_C_SUSPEND))
+ return 0;
+ usb_clear_port_feature(hdev, port, USB_PORT_FEAT_C_SUSPEND);
+ } else {
+ if (!udev || udev->state != USB_STATE_SUSPENDED ||
+ (portstatus & USB_PORT_STAT_LINK_STATE) !=
+ USB_SS_PORT_LS_U0)
+ return 0;
+ }
+
+ if (udev) {
+ /* TRSMRCY = 10 msec */
+ msleep(10);
+
+ usb_unlock_port(port_dev);
+ ret = usb_remote_wakeup(udev);
+ usb_lock_port(port_dev);
+ if (ret < 0)
+ connect_change = 1;
+ } else {
+ ret = -ENODEV;
+ hub_port_disable(hub, port, 1);
+ }
+ dev_dbg(&port_dev->dev, "resume, status %d\n", ret);
+ return connect_change;
+}
+
+#else
+
+static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port,
+ u16 portstatus, u16 portchange)
+{
+ return 0;
+}
+
#endif
static int check_ports_changed(struct usb_hub *hub)
@@ -3337,12 +3443,11 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
*/
hub->wakeup_enabled_descendants = 0;
for (port1 = 1; port1 <= hdev->maxchild; port1++) {
- struct usb_device *udev;
+ struct usb_port *port_dev = hub->ports[port1 - 1];
+ struct usb_device *udev = port_dev->child;
- udev = hub->ports[port1 - 1]->child;
if (udev && udev->can_submit) {
- dev_warn(&intf->dev, "port %d not suspended yet\n",
- port1);
+ dev_warn(&port_dev->dev, "not suspended yet\n");
if (PMSG_IS_AUTO(msg))
return -EBUSY;
}
@@ -3861,6 +3966,12 @@ EXPORT_SYMBOL_GPL(usb_disable_ltm);
void usb_enable_ltm(struct usb_device *udev) { }
EXPORT_SYMBOL_GPL(usb_enable_ltm);
+static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port,
+ u16 portstatus, u16 portchange)
+{
+ return 0;
+}
+
#endif /* CONFIG_PM */
@@ -3882,9 +3993,10 @@ EXPORT_SYMBOL_GPL(usb_enable_ltm);
int hub_port_debounce(struct usb_hub *hub, int port1, bool must_be_connected)
{
int ret;
- int total_time, stable_time = 0;
u16 portchange, portstatus;
unsigned connection = 0xffff;
+ int total_time, stable_time = 0;
+ struct usb_port *port_dev = hub->ports[port1 - 1];
for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) {
ret = hub_port_status(hub, port1, &portstatus, &portchange);
@@ -3913,9 +4025,8 @@ int hub_port_debounce(struct usb_hub *hub, int port1, bool must_be_connected)
msleep(HUB_DEBOUNCE_STEP);
}
- dev_dbg (hub->intfdev,
- "debounce: port %d: total %dms stable %dms status 0x%x\n",
- port1, total_time, stable_time, portstatus);
+ dev_dbg(&port_dev->dev, "debounce total %dms stable %dms status 0x%x\n",
+ total_time, stable_time, portstatus);
if (stable_time < HUB_DEBOUNCE_STABLE)
return -ETIMEDOUT;
@@ -3974,13 +4085,14 @@ static int hub_set_address(struct usb_device *udev, int devnum)
*/
static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev)
{
- int connect_type;
+ struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent);
+ int connect_type = USB_PORT_CONNECT_TYPE_UNKNOWN;
if (!udev->usb2_hw_lpm_capable)
return;
- connect_type = usb_get_hub_port_connect_type(udev->parent,
- udev->portnum);
+ if (hub)
+ connect_type = hub->ports[udev->portnum - 1]->connect_type;
if ((udev->bos->ext_cap->bmAttributes & cpu_to_le32(USB_BESL_SUPPORT)) ||
connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) {
@@ -4008,16 +4120,15 @@ static int hub_enable_device(struct usb_device *udev)
* Returns device in USB_STATE_ADDRESS, except on error.
*
* If this is called for an already-existing device (as part of
- * usb_reset_and_verify_device), the caller must own the device lock. For a
- * newly detected device that is not accessible through any global
- * pointers, it's not necessary to lock the device.
+ * usb_reset_and_verify_device), the caller must own the device lock and
+ * the port lock. For a newly detected device that is not accessible
+ * through any global pointers, it's not necessary to lock the device,
+ * but it is still necessary to lock the port.
*/
static int
hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
int retry_counter)
{
- static DEFINE_MUTEX(usb_address0_mutex);
-
struct usb_device *hdev = hub->hdev;
struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
int i, j, retval;
@@ -4040,7 +4151,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
if (oldspeed == USB_SPEED_LOW)
delay = HUB_LONG_RESET_TIME;
- mutex_lock(&usb_address0_mutex);
+ mutex_lock(&hdev->bus->usb_address0_mutex);
/* Reset the device; full speed may morph to high speed */
/* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */
@@ -4317,7 +4428,7 @@ fail:
hub_port_disable(hub, port1, 0);
update_devnum(udev, devnum); /* for disconnect processing */
}
- mutex_unlock(&usb_address0_mutex);
+ mutex_unlock(&hdev->bus->usb_address0_mutex);
return retval;
}
@@ -4358,9 +4469,10 @@ hub_power_remaining (struct usb_hub *hub)
remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent;
for (port1 = 1; port1 <= hdev->maxchild; ++port1) {
- struct usb_device *udev = hub->ports[port1 - 1]->child;
- int delta;
- unsigned unit_load;
+ struct usb_port *port_dev = hub->ports[port1 - 1];
+ struct usb_device *udev = port_dev->child;
+ unsigned unit_load;
+ int delta;
if (!udev)
continue;
@@ -4380,9 +4492,8 @@ hub_power_remaining (struct usb_hub *hub)
else
delta = 8;
if (delta > hub->mA_per_port)
- dev_warn(&udev->dev,
- "%dmA is over %umA budget for port %d!\n",
- delta, hub->mA_per_port, port1);
+ dev_warn(&port_dev->dev, "%dmA is over %umA budget!\n",
+ delta, hub->mA_per_port);
remaining -= delta;
}
if (remaining < 0) {
@@ -4393,78 +4504,23 @@ hub_power_remaining (struct usb_hub *hub)
return remaining;
}
-/* Handle physical or logical connection change events.
- * This routine is called when:
- * a port connection-change occurs;
- * a port enable-change occurs (often caused by EMI);
- * usb_reset_and_verify_device() encounters changed descriptors (as from
- * a firmware download)
- * caller already locked the hub
- */
-static void hub_port_connect_change(struct usb_hub *hub, int port1,
- u16 portstatus, u16 portchange)
+static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
+ u16 portchange)
{
- struct usb_device *hdev = hub->hdev;
- struct device *hub_dev = hub->intfdev;
- struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
- unsigned wHubCharacteristics =
- le16_to_cpu(hub->descriptor->wHubCharacteristics);
- struct usb_device *udev;
int status, i;
unsigned unit_load;
-
- dev_dbg (hub_dev,
- "port %d, status %04x, change %04x, %s\n",
- port1, portstatus, portchange, portspeed(hub, portstatus));
-
- if (hub->has_indicators) {
- set_port_led(hub, port1, HUB_LED_AUTO);
- hub->indicator[port1-1] = INDICATOR_AUTO;
- }
-
-#ifdef CONFIG_USB_OTG
- /* during HNP, don't repeat the debounce */
- if (hdev->bus->is_b_host)
- portchange &= ~(USB_PORT_STAT_C_CONNECTION |
- USB_PORT_STAT_C_ENABLE);
-#endif
-
- /* Try to resuscitate an existing device */
- udev = hub->ports[port1 - 1]->child;
- if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
- udev->state != USB_STATE_NOTATTACHED) {
- usb_lock_device(udev);
- if (portstatus & USB_PORT_STAT_ENABLE) {
- status = 0; /* Nothing to do */
-
-#ifdef CONFIG_PM_RUNTIME
- } else if (udev->state == USB_STATE_SUSPENDED &&
- udev->persist_enabled) {
- /* For a suspended device, treat this as a
- * remote wakeup event.
- */
- status = usb_remote_wakeup(udev);
-#endif
-
- } else {
- status = -ENODEV; /* Don't resuscitate */
- }
- usb_unlock_device(udev);
-
- if (status == 0) {
- clear_bit(port1, hub->change_bits);
- return;
- }
- }
+ struct usb_device *hdev = hub->hdev;
+ struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
+ struct usb_port *port_dev = hub->ports[port1 - 1];
+ struct usb_device *udev = port_dev->child;
/* Disconnect any existing devices under this port */
if (udev) {
if (hcd->phy && !hdev->parent &&
!(portstatus & USB_PORT_STAT_CONNECTION))
usb_phy_notify_disconnect(hcd->phy, udev->speed);
- usb_disconnect(&hub->ports[port1 - 1]->child);
+ usb_disconnect(&port_dev->child);
}
- clear_bit(port1, hub->change_bits);
/* We can forget about a "removed" device when there's a physical
* disconnect or the connect status changes.
@@ -4478,8 +4534,8 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
status = hub_port_debounce_be_stable(hub, port1);
if (status < 0) {
if (status != -ENODEV && printk_ratelimit())
- dev_err(hub_dev, "connect-debounce failed, "
- "port %d disabled\n", port1);
+ dev_err(&port_dev->dev,
+ "connect-debounce failed\n");
portstatus &= ~USB_PORT_STAT_CONNECTION;
} else {
portstatus = status;
@@ -4493,7 +4549,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
test_bit(port1, hub->removed_bits)) {
/* maybe switch power back on (e.g. root hub was reset) */
- if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2
+ if (hub_is_port_power_switchable(hub)
&& !port_is_power_on(hub, portstatus))
set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
@@ -4514,9 +4570,8 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
*/
udev = usb_alloc_dev(hdev, hdev->bus, port1);
if (!udev) {
- dev_err (hub_dev,
- "couldn't allocate port %d usb_device\n",
- port1);
+ dev_err(&port_dev->dev,
+ "couldn't allocate usb_device\n");
goto done;
}
@@ -4538,7 +4593,9 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
}
/* reset (non-USB 3.0 devices) and get descriptor */
+ usb_lock_port(port_dev);
status = hub_port_init(hub, udev, port1, i);
+ usb_unlock_port(port_dev);
if (status < 0)
goto loop;
@@ -4590,6 +4647,8 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
*/
status = 0;
+ mutex_lock(&usb_port_peer_mutex);
+
/* We mustn't add new devices if the parent hub has
* been disconnected; we would race with the
* recursively_mark_NOTATTACHED() routine.
@@ -4598,16 +4657,19 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
if (hdev->state == USB_STATE_NOTATTACHED)
status = -ENOTCONN;
else
- hub->ports[port1 - 1]->child = udev;
+ port_dev->child = udev;
spin_unlock_irq(&device_state_lock);
+ mutex_unlock(&usb_port_peer_mutex);
/* Run it through the hoops (find a driver, etc) */
if (!status) {
status = usb_new_device(udev);
if (status) {
+ mutex_lock(&usb_port_peer_mutex);
spin_lock_irq(&device_state_lock);
- hub->ports[port1 - 1]->child = NULL;
+ port_dev->child = NULL;
spin_unlock_irq(&device_state_lock);
+ mutex_unlock(&usb_port_peer_mutex);
}
}
@@ -4616,7 +4678,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
status = hub_power_remaining(hub);
if (status)
- dev_dbg(hub_dev, "%dmA power budget left\n", status);
+ dev_dbg(hub->intfdev, "%dmA power budget left\n", status);
return;
@@ -4634,56 +4696,200 @@ loop:
!hcd->driver->port_handed_over ||
!(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);
+ dev_err(&port_dev->dev,
+ "unable to enumerate USB device\n");
}
done:
hub_port_disable(hub, port1, 1);
if (hcd->driver->relinquish_port && !hub->hdev->parent)
hcd->driver->relinquish_port(hcd, port1);
+
}
-/* Returns 1 if there was a remote wakeup and a connect status change. */
-static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port,
- u16 portstatus, u16 portchange)
+/* Handle physical or logical connection change events.
+ * This routine is called when:
+ * a port connection-change occurs;
+ * a port enable-change occurs (often caused by EMI);
+ * usb_reset_and_verify_device() encounters changed descriptors (as from
+ * a firmware download)
+ * caller already locked the hub
+ */
+static void hub_port_connect_change(struct usb_hub *hub, int port1,
+ u16 portstatus, u16 portchange)
+ __must_hold(&port_dev->status_lock)
{
- struct usb_device *hdev;
- struct usb_device *udev;
- int connect_change = 0;
- int ret;
+ struct usb_port *port_dev = hub->ports[port1 - 1];
+ struct usb_device *udev = port_dev->child;
+ int status = -ENODEV;
- hdev = hub->hdev;
- udev = hub->ports[port - 1]->child;
- if (!hub_is_superspeed(hdev)) {
- if (!(portchange & USB_PORT_STAT_C_SUSPEND))
- return 0;
- usb_clear_port_feature(hdev, port, USB_PORT_FEAT_C_SUSPEND);
- } else {
- if (!udev || udev->state != USB_STATE_SUSPENDED ||
- (portstatus & USB_PORT_STAT_LINK_STATE) !=
- USB_SS_PORT_LS_U0)
- return 0;
+ dev_dbg(&port_dev->dev, "status %04x, change %04x, %s\n", portstatus,
+ portchange, portspeed(hub, portstatus));
+
+ if (hub->has_indicators) {
+ set_port_led(hub, port1, HUB_LED_AUTO);
+ hub->indicator[port1-1] = INDICATOR_AUTO;
}
- if (udev) {
- /* TRSMRCY = 10 msec */
- msleep(10);
+#ifdef CONFIG_USB_OTG
+ /* during HNP, don't repeat the debounce */
+ if (hub->hdev->bus->is_b_host)
+ portchange &= ~(USB_PORT_STAT_C_CONNECTION |
+ USB_PORT_STAT_C_ENABLE);
+#endif
+
+ /* Try to resuscitate an existing device */
+ if ((portstatus & USB_PORT_STAT_CONNECTION) && udev &&
+ udev->state != USB_STATE_NOTATTACHED) {
+ if (portstatus & USB_PORT_STAT_ENABLE) {
+ status = 0; /* Nothing to do */
+#ifdef CONFIG_PM_RUNTIME
+ } else if (udev->state == USB_STATE_SUSPENDED &&
+ udev->persist_enabled) {
+ /* For a suspended device, treat this as a
+ * remote wakeup event.
+ */
+ usb_unlock_port(port_dev);
+ status = usb_remote_wakeup(udev);
+ usb_lock_port(port_dev);
+#endif
+ } else {
+ /* Don't resuscitate */;
+ }
+ }
+ clear_bit(port1, hub->change_bits);
+
+ /* successfully revalidated the connection */
+ if (status == 0)
+ return;
+
+ usb_unlock_port(port_dev);
+ hub_port_connect(hub, port1, portstatus, portchange);
+ usb_lock_port(port_dev);
+}
+
+static void port_event(struct usb_hub *hub, int port1)
+ __must_hold(&port_dev->status_lock)
+{
+ int connect_change, reset_device = 0;
+ struct usb_port *port_dev = hub->ports[port1 - 1];
+ struct usb_device *udev = port_dev->child;
+ struct usb_device *hdev = hub->hdev;
+ u16 portstatus, portchange;
+
+ connect_change = test_bit(port1, hub->change_bits);
+ clear_bit(port1, hub->event_bits);
+ clear_bit(port1, hub->wakeup_bits);
+
+ if (hub_port_status(hub, port1, &portstatus, &portchange) < 0)
+ return;
+
+ if (portchange & USB_PORT_STAT_C_CONNECTION) {
+ usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION);
+ connect_change = 1;
+ }
+
+ if (portchange & USB_PORT_STAT_C_ENABLE) {
+ if (!connect_change)
+ dev_dbg(&port_dev->dev, "enable change, status %08x\n",
+ portstatus);
+ usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE);
+
+ /*
+ * EM interference sometimes causes badly shielded USB devices
+ * to be shutdown by the hub, this hack enables them again.
+ * Works at least with mouse driver.
+ */
+ if (!(portstatus & USB_PORT_STAT_ENABLE)
+ && !connect_change && udev) {
+ dev_err(&port_dev->dev, "disabled by hub (EMI?), re-enabling...\n");
+ connect_change = 1;
+ }
+ }
+
+ if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
+ u16 status = 0, unused;
+
+ dev_dbg(&port_dev->dev, "over-current change\n");
+ usb_clear_port_feature(hdev, port1,
+ USB_PORT_FEAT_C_OVER_CURRENT);
+ msleep(100); /* Cool down */
+ hub_power_on(hub, true);
+ hub_port_status(hub, port1, &status, &unused);
+ if (status & USB_PORT_STAT_OVERCURRENT)
+ dev_err(&port_dev->dev, "over-current condition\n");
+ }
+
+ if (portchange & USB_PORT_STAT_C_RESET) {
+ dev_dbg(&port_dev->dev, "reset change\n");
+ usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_RESET);
+ }
+ if ((portchange & USB_PORT_STAT_C_BH_RESET)
+ && hub_is_superspeed(hdev)) {
+ dev_dbg(&port_dev->dev, "warm reset change\n");
+ usb_clear_port_feature(hdev, port1,
+ USB_PORT_FEAT_C_BH_PORT_RESET);
+ }
+ if (portchange & USB_PORT_STAT_C_LINK_STATE) {
+ dev_dbg(&port_dev->dev, "link state change\n");
+ usb_clear_port_feature(hdev, port1,
+ USB_PORT_FEAT_C_PORT_LINK_STATE);
+ }
+ if (portchange & USB_PORT_STAT_C_CONFIG_ERROR) {
+ dev_warn(&port_dev->dev, "config error\n");
+ usb_clear_port_feature(hdev, port1,
+ USB_PORT_FEAT_C_PORT_CONFIG_ERROR);
+ }
+
+ /* skip port actions that require the port to be powered on */
+ if (!pm_runtime_active(&port_dev->dev))
+ return;
+ if (hub_handle_remote_wakeup(hub, port1, portstatus, portchange))
+ connect_change = 1;
+
+ /*
+ * Warm reset a USB3 protocol port if it's in
+ * SS.Inactive state.
+ */
+ if (hub_port_warm_reset_required(hub, portstatus)) {
+ dev_dbg(&port_dev->dev, "do warm reset\n");
+ if (!udev || !(portstatus & USB_PORT_STAT_CONNECTION)
+ || udev->state == USB_STATE_NOTATTACHED) {
+ if (hub_port_reset(hub, port1, NULL,
+ HUB_BH_RESET_TIME, true) < 0)
+ hub_port_disable(hub, port1, 1);
+ } else
+ reset_device = 1;
+ }
+
+ /*
+ * On disconnect USB3 protocol ports transit from U0 to
+ * SS.Inactive to Rx.Detect. If this happens a warm-
+ * reset is not needed, but a (re)connect may happen
+ * before khubd runs and sees the disconnect, and the
+ * device may be an unknown state.
+ *
+ * If the port went through SS.Inactive without khubd
+ * seeing it the C_LINK_STATE change flag will be set,
+ * and we reset the dev to put it in a known state.
+ */
+ if (reset_device || (udev && hub_is_superspeed(hub->hdev)
+ && (portchange & USB_PORT_STAT_C_LINK_STATE)
+ && (portstatus & USB_PORT_STAT_CONNECTION))) {
+ usb_unlock_port(port_dev);
usb_lock_device(udev);
- ret = usb_remote_wakeup(udev);
+ usb_reset_device(udev);
usb_unlock_device(udev);
- if (ret < 0)
- connect_change = 1;
- } else {
- ret = -ENODEV;
- hub_port_disable(hub, port, 1);
+ usb_lock_port(port_dev);
+ connect_change = 0;
}
- dev_dbg(hub->intfdev, "resume on port %d, status %d\n",
- port, ret);
- return connect_change;
+
+ if (connect_change)
+ hub_port_connect_change(hub, port1, portstatus, portchange);
}
+
static void hub_events(void)
{
struct list_head *tmp;
@@ -4693,10 +4899,7 @@ static void hub_events(void)
struct device *hub_dev;
u16 hubstatus;
u16 hubchange;
- u16 portstatus;
- u16 portchange;
int i, ret;
- int connect_change, wakeup_change;
/*
* We restart the list every time to avoid a deadlock with
@@ -4770,146 +4973,28 @@ static void hub_events(void)
/* deal with port status changes */
for (i = 1; i <= hdev->maxchild; i++) {
- struct usb_device *udev = hub->ports[i - 1]->child;
-
- if (test_bit(i, hub->busy_bits))
- continue;
- connect_change = test_bit(i, hub->change_bits);
- wakeup_change = test_and_clear_bit(i, hub->wakeup_bits);
- if (!test_and_clear_bit(i, hub->event_bits) &&
- !connect_change && !wakeup_change)
- continue;
-
- ret = hub_port_status(hub, i,
- &portstatus, &portchange);
- if (ret < 0)
- continue;
-
- if (portchange & USB_PORT_STAT_C_CONNECTION) {
- usb_clear_port_feature(hdev, i,
- USB_PORT_FEAT_C_CONNECTION);
- connect_change = 1;
- }
-
- if (portchange & USB_PORT_STAT_C_ENABLE) {
- if (!connect_change)
- dev_dbg (hub_dev,
- "port %d enable change, "
- "status %08x\n",
- i, portstatus);
- usb_clear_port_feature(hdev, i,
- USB_PORT_FEAT_C_ENABLE);
+ struct usb_port *port_dev = hub->ports[i - 1];
+ if (test_bit(i, hub->event_bits)
+ || test_bit(i, hub->change_bits)
+ || test_bit(i, hub->wakeup_bits)) {
/*
- * EM interference sometimes causes badly
- * shielded USB devices to be shutdown by
- * the hub, this hack enables them again.
- * Works at least with mouse driver.
+ * The get_noresume and barrier ensure that if
+ * the port was in the process of resuming, we
+ * flush that work and keep the port active for
+ * the duration of the port_event(). However,
+ * if the port is runtime pm suspended
+ * (powered-off), we leave it in that state, run
+ * an abbreviated port_event(), and move on.
*/
- if (!(portstatus & USB_PORT_STAT_ENABLE)
- && !connect_change
- && hub->ports[i - 1]->child) {
- dev_err (hub_dev,
- "port %i "
- "disabled by hub (EMI?), "
- "re-enabling...\n",
- i);
- connect_change = 1;
- }
- }
-
- if (hub_handle_remote_wakeup(hub, i,
- portstatus, portchange))
- connect_change = 1;
-
- if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
- u16 status = 0;
- u16 unused;
-
- dev_dbg(hub_dev, "over-current change on port "
- "%d\n", i);
- usb_clear_port_feature(hdev, i,
- USB_PORT_FEAT_C_OVER_CURRENT);
- msleep(100); /* Cool down */
- hub_power_on(hub, true);
- hub_port_status(hub, i, &status, &unused);
- if (status & USB_PORT_STAT_OVERCURRENT)
- dev_err(hub_dev, "over-current "
- "condition on port %d\n", i);
- }
-
- if (portchange & USB_PORT_STAT_C_RESET) {
- dev_dbg (hub_dev,
- "reset change on port %d\n",
- i);
- usb_clear_port_feature(hdev, i,
- USB_PORT_FEAT_C_RESET);
- }
- if ((portchange & USB_PORT_STAT_C_BH_RESET) &&
- hub_is_superspeed(hub->hdev)) {
- dev_dbg(hub_dev,
- "warm reset change on port %d\n",
- i);
- usb_clear_port_feature(hdev, i,
- USB_PORT_FEAT_C_BH_PORT_RESET);
- }
- if (portchange & USB_PORT_STAT_C_LINK_STATE) {
- usb_clear_port_feature(hub->hdev, i,
- USB_PORT_FEAT_C_PORT_LINK_STATE);
- }
- if (portchange & USB_PORT_STAT_C_CONFIG_ERROR) {
- dev_warn(hub_dev,
- "config error on port %d\n",
- i);
- usb_clear_port_feature(hub->hdev, i,
- USB_PORT_FEAT_C_PORT_CONFIG_ERROR);
+ pm_runtime_get_noresume(&port_dev->dev);
+ pm_runtime_barrier(&port_dev->dev);
+ usb_lock_port(port_dev);
+ port_event(hub, i);
+ usb_unlock_port(port_dev);
+ pm_runtime_put_sync(&port_dev->dev);
}
-
- /* Warm reset a USB3 protocol port if it's in
- * SS.Inactive state.
- */
- if (hub_port_warm_reset_required(hub, portstatus)) {
- int status;
-
- dev_dbg(hub_dev, "warm reset port %d\n", i);
- if (!udev ||
- !(portstatus & USB_PORT_STAT_CONNECTION) ||
- udev->state == USB_STATE_NOTATTACHED) {
- status = hub_port_reset(hub, i,
- NULL, HUB_BH_RESET_TIME,
- true);
- if (status < 0)
- hub_port_disable(hub, i, 1);
- } else {
- usb_lock_device(udev);
- status = usb_reset_device(udev);
- usb_unlock_device(udev);
- connect_change = 0;
- }
- /*
- * On disconnect USB3 protocol ports transit from U0 to
- * SS.Inactive to Rx.Detect. If this happens a warm-
- * reset is not needed, but a (re)connect may happen
- * before khubd runs and sees the disconnect, and the
- * device may be an unknown state.
- *
- * If the port went through SS.Inactive without khubd
- * seeing it the C_LINK_STATE change flag will be set,
- * and we reset the dev to put it in a known state.
- */
- } else if (udev && hub_is_superspeed(hub->hdev) &&
- (portchange & USB_PORT_STAT_C_LINK_STATE) &&
- (portstatus & USB_PORT_STAT_CONNECTION)) {
- usb_lock_device(udev);
- usb_reset_device(udev);
- usb_unlock_device(udev);
- connect_change = 0;
- }
-
- if (connect_change)
- hub_port_connect_change(hub, i,
- portstatus, portchange);
- } /* end for i */
+ }
/* deal with hub status changes */
if (test_and_clear_bit(0, hub->event_bits) == 0)
@@ -5144,15 +5229,18 @@ static int descriptors_changed(struct usb_device *udev,
* if the reset wasn't even attempted.
*
* Note:
- * The caller must own the device lock. For example, it's safe to use
- * this from a driver probe() routine after downloading new firmware.
- * For calls that might not occur during probe(), drivers should lock
- * the device using usb_lock_device_for_reset().
+ * The caller must own the device lock and the port lock, the latter is
+ * taken by usb_reset_device(). For example, it's safe to use
+ * usb_reset_device() from a driver probe() routine after downloading
+ * new firmware. For calls that might not occur during probe(), drivers
+ * should lock the device using usb_lock_device_for_reset().
*
* Locking exception: This routine may also be called from within an
* autoresume handler. Such usage won't conflict with other tasks
* holding the device lock because these tasks should always call
- * usb_autopm_resume_device(), thereby preventing any unwanted autoresume.
+ * usb_autopm_resume_device(), thereby preventing any unwanted
+ * autoresume. The autoresume handler is expected to have already
+ * acquired the port lock before calling this routine.
*/
static int usb_reset_and_verify_device(struct usb_device *udev)
{
@@ -5171,11 +5259,9 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
return -EINVAL;
}
- if (!parent_hdev) {
- /* this requires hcd-specific logic; see ohci_restart() */
- dev_dbg(&udev->dev, "%s for root hub!\n", __func__);
+ if (!parent_hdev)
return -EISDIR;
- }
+
parent_hub = usb_hub_to_struct_hub(parent_hdev);
/* Disable USB2 hardware LPM.
@@ -5204,7 +5290,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
goto re_enumerate;
}
- set_bit(port1, parent_hub->busy_bits);
for (i = 0; i < SET_CONFIG_TRIES; ++i) {
/* ep0 maxpacket size may change; let the HCD know about it.
@@ -5214,7 +5299,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV)
break;
}
- clear_bit(port1, parent_hub->busy_bits);
if (ret < 0)
goto re_enumerate;
@@ -5335,7 +5419,9 @@ int usb_reset_device(struct usb_device *udev)
int ret;
int i;
unsigned int noio_flag;
+ struct usb_port *port_dev;
struct usb_host_config *config = udev->actconfig;
+ struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent);
if (udev->state == USB_STATE_NOTATTACHED ||
udev->state == USB_STATE_SUSPENDED) {
@@ -5344,6 +5430,14 @@ int usb_reset_device(struct usb_device *udev)
return -EINVAL;
}
+ if (!udev->parent) {
+ /* this requires hcd-specific logic; see ohci_restart() */
+ dev_dbg(&udev->dev, "%s for root hub!\n", __func__);
+ return -EISDIR;
+ }
+
+ port_dev = hub->ports[udev->portnum - 1];
+
/*
* Don't allocate memory with GFP_KERNEL in current
* context to avoid possible deadlock if usb mass
@@ -5377,7 +5471,9 @@ int usb_reset_device(struct usb_device *udev)
}
}
+ usb_lock_port(port_dev);
ret = usb_reset_and_verify_device(udev);
+ usb_unlock_port(port_dev);
if (config) {
for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) {
@@ -5472,56 +5568,26 @@ struct usb_device *usb_hub_find_child(struct usb_device *hdev,
}
EXPORT_SYMBOL_GPL(usb_hub_find_child);
-/**
- * usb_set_hub_port_connect_type - set hub port connect type.
- * @hdev: USB device belonging to the usb hub
- * @port1: port num of the port
- * @type: connect type of the port
- */
-void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1,
- enum usb_port_connect_type type)
-{
- struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
-
- if (hub)
- hub->ports[port1 - 1]->connect_type = type;
-}
-
-/**
- * usb_get_hub_port_connect_type - Get the port's connect type
- * @hdev: USB device belonging to the usb hub
- * @port1: port num of the port
- *
- * Return: The connect type of the port if successful. Or
- * USB_PORT_CONNECT_TYPE_UNKNOWN if input params are invalid.
- */
-enum usb_port_connect_type
-usb_get_hub_port_connect_type(struct usb_device *hdev, int port1)
-{
- struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
-
- if (!hub)
- return USB_PORT_CONNECT_TYPE_UNKNOWN;
-
- return hub->ports[port1 - 1]->connect_type;
-}
-
void usb_hub_adjust_deviceremovable(struct usb_device *hdev,
struct usb_hub_descriptor *desc)
{
+ struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
enum usb_port_connect_type connect_type;
int i;
+ if (!hub)
+ return;
+
if (!hub_is_superspeed(hdev)) {
for (i = 1; i <= hdev->maxchild; i++) {
- connect_type = usb_get_hub_port_connect_type(hdev, i);
+ struct usb_port *port_dev = hub->ports[i - 1];
+ connect_type = port_dev->connect_type;
if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) {
u8 mask = 1 << (i%8);
if (!(desc->u.hs.DeviceRemovable[i/8] & mask)) {
- dev_dbg(&hdev->dev, "usb port%d's DeviceRemovable is changed to 1 according to platform information.\n",
- i);
+ dev_dbg(&port_dev->dev, "DeviceRemovable is changed to 1 according to platform information.\n");
desc->u.hs.DeviceRemovable[i/8] |= mask;
}
}
@@ -5530,14 +5596,14 @@ void usb_hub_adjust_deviceremovable(struct usb_device *hdev,
u16 port_removable = le16_to_cpu(desc->u.ss.DeviceRemovable);
for (i = 1; i <= hdev->maxchild; i++) {
- connect_type = usb_get_hub_port_connect_type(hdev, i);
+ struct usb_port *port_dev = hub->ports[i - 1];
+ connect_type = port_dev->connect_type;
if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) {
u16 mask = 1 << i;
if (!(port_removable & mask)) {
- dev_dbg(&hdev->dev, "usb port%d's DeviceRemovable is changed to 1 according to platform information.\n",
- i);
+ dev_dbg(&port_dev->dev, "DeviceRemovable is changed to 1 according to platform information.\n");
port_removable |= mask;
}
}
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 33bcb2c6f90a..0a7cdc0ef0a9 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -45,12 +45,13 @@ struct usb_hub {
unsigned long event_bits[1]; /* status change bitmask */
unsigned long change_bits[1]; /* ports with logical connect
status change */
- unsigned long busy_bits[1]; /* ports being reset or
- resumed */
unsigned long removed_bits[1]; /* ports with a "removed"
device present */
unsigned long wakeup_bits[1]; /* ports that have signaled
remote wakeup */
+ unsigned long power_bits[1]; /* ports that are powered */
+ unsigned long child_usage_bits[1]; /* ports powered on for
+ children */
#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
#error event_bits[] is too short!
#endif
@@ -66,6 +67,7 @@ struct usb_hub {
unsigned limited_power:1;
unsigned quiescing:1;
unsigned disconnected:1;
+ unsigned in_reset:1;
unsigned quirk_check_port_auto_suspend:1;
@@ -81,19 +83,23 @@ struct usb_hub {
* @child: usb device attached to the port
* @dev: generic device interface
* @port_owner: port's owner
+ * @peer: related usb2 and usb3 ports (share the same connector)
* @connect_type: port's connect type
+ * @location: opaque representation of platform connector location
+ * @status_lock: synchronize port_event() vs usb_port_{suspend|resume}
* @portnum: port index num based one
- * @power_is_on: port's power state
- * @did_runtime_put: port has done pm_runtime_put().
+ * @is_superspeed cache super-speed status
*/
struct usb_port {
struct usb_device *child;
struct device dev;
struct usb_dev_state *port_owner;
+ struct usb_port *peer;
enum usb_port_connect_type connect_type;
+ usb_port_location_t location;
+ struct mutex status_lock;
u8 portnum;
- unsigned power_is_on:1;
- unsigned did_runtime_put:1;
+ unsigned int is_superspeed:1;
};
#define to_usb_port(_dev) \
@@ -111,6 +117,29 @@ extern int hub_port_debounce(struct usb_hub *hub, int port1,
extern int usb_clear_port_feature(struct usb_device *hdev,
int port1, int feature);
+static inline bool hub_is_port_power_switchable(struct usb_hub *hub)
+{
+ __le16 hcs;
+
+ if (!hub)
+ return false;
+ hcs = hub->descriptor->wHubCharacteristics;
+ return (le16_to_cpu(hcs) & HUB_CHAR_LPSM) < HUB_CHAR_NO_LPSM;
+}
+
+static inline int hub_is_superspeed(struct usb_device *hdev)
+{
+ return hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS;
+}
+
+static inline unsigned hub_power_on_good_delay(struct usb_hub *hub)
+{
+ unsigned delay = hub->descriptor->bPwrOn2PwrGood * 2;
+
+ /* Wait at least 100 msec for power to become stable */
+ return max(delay, 100U);
+}
+
static inline int hub_port_debounce_be_connected(struct usb_hub *hub,
int port1)
{
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index 51542f852393..62036faf56c0 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -76,17 +76,29 @@ static int usb_port_runtime_resume(struct device *dev)
struct usb_device *hdev = to_usb_device(dev->parent->parent);
struct usb_interface *intf = to_usb_interface(dev->parent);
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
+ struct usb_device *udev = port_dev->child;
+ struct usb_port *peer = port_dev->peer;
int port1 = port_dev->portnum;
int retval;
if (!hub)
return -EINVAL;
+ if (hub->in_reset) {
+ set_bit(port1, hub->power_bits);
+ return 0;
+ }
- usb_autopm_get_interface(intf);
- set_bit(port1, hub->busy_bits);
+ /*
+ * Power on our usb3 peer before this usb2 port to prevent a usb3
+ * device from degrading to its usb2 connection
+ */
+ if (!port_dev->is_superspeed && peer)
+ pm_runtime_get_sync(&peer->dev);
+ usb_autopm_get_interface(intf);
retval = usb_hub_set_port_power(hdev, hub, port1, true);
- if (port_dev->child && !retval) {
+ msleep(hub_power_on_good_delay(hub));
+ if (udev && !retval) {
/*
* Attempt to wait for usb hub port to be reconnected in order
* to make the resume procedure successful. The device may have
@@ -97,12 +109,17 @@ static int usb_port_runtime_resume(struct device *dev)
if (retval < 0)
dev_dbg(&port_dev->dev, "can't get reconnection after setting port power on, status %d\n",
retval);
- usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE);
retval = 0;
+
+ /* Force the child awake to revalidate after the power loss. */
+ if (!test_and_set_bit(port1, hub->child_usage_bits)) {
+ pm_runtime_get_noresume(&port_dev->dev);
+ pm_request_resume(&udev->dev);
+ }
}
- clear_bit(port1, hub->busy_bits);
usb_autopm_put_interface(intf);
+
return retval;
}
@@ -112,23 +129,34 @@ static int usb_port_runtime_suspend(struct device *dev)
struct usb_device *hdev = to_usb_device(dev->parent->parent);
struct usb_interface *intf = to_usb_interface(dev->parent);
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
+ struct usb_port *peer = port_dev->peer;
int port1 = port_dev->portnum;
int retval;
if (!hub)
return -EINVAL;
+ if (hub->in_reset)
+ return -EBUSY;
if (dev_pm_qos_flags(&port_dev->dev, PM_QOS_FLAG_NO_POWER_OFF)
== PM_QOS_FLAGS_ALL)
return -EAGAIN;
usb_autopm_get_interface(intf);
- set_bit(port1, hub->busy_bits);
retval = usb_hub_set_port_power(hdev, hub, port1, false);
usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION);
- usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE);
- clear_bit(port1, hub->busy_bits);
+ if (!port_dev->is_superspeed)
+ usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE);
usb_autopm_put_interface(intf);
+
+ /*
+ * Our peer usb3 port may now be able to suspend, so
+ * asynchronously queue a suspend request to observe that this
+ * usb2 port is now off.
+ */
+ if (!port_dev->is_superspeed && peer)
+ pm_runtime_put(&peer->dev);
+
return retval;
}
#endif
@@ -146,9 +174,215 @@ struct device_type usb_port_device_type = {
.pm = &usb_port_pm_ops,
};
+static struct device_driver usb_port_driver = {
+ .name = "usb",
+ .owner = THIS_MODULE,
+};
+
+static int link_peers(struct usb_port *left, struct usb_port *right)
+{
+ struct usb_port *ss_port, *hs_port;
+ int rc;
+
+ if (left->peer == right && right->peer == left)
+ return 0;
+
+ if (left->peer || right->peer) {
+ struct usb_port *lpeer = left->peer;
+ struct usb_port *rpeer = right->peer;
+
+ WARN(1, "failed to peer %s and %s (%s -> %p) (%s -> %p)\n",
+ dev_name(&left->dev), dev_name(&right->dev),
+ dev_name(&left->dev), lpeer,
+ dev_name(&right->dev), rpeer);
+ return -EBUSY;
+ }
+
+ rc = sysfs_create_link(&left->dev.kobj, &right->dev.kobj, "peer");
+ if (rc)
+ return rc;
+ rc = sysfs_create_link(&right->dev.kobj, &left->dev.kobj, "peer");
+ if (rc) {
+ sysfs_remove_link(&left->dev.kobj, "peer");
+ return rc;
+ }
+
+ /*
+ * We need to wake the HiSpeed port to make sure we don't race
+ * setting ->peer with usb_port_runtime_suspend(). Otherwise we
+ * may miss a suspend event for the SuperSpeed port.
+ */
+ if (left->is_superspeed) {
+ ss_port = left;
+ WARN_ON(right->is_superspeed);
+ hs_port = right;
+ } else {
+ ss_port = right;
+ WARN_ON(!right->is_superspeed);
+ hs_port = left;
+ }
+ pm_runtime_get_sync(&hs_port->dev);
+
+ left->peer = right;
+ right->peer = left;
+
+ /*
+ * The SuperSpeed reference is dropped when the HiSpeed port in
+ * this relationship suspends, i.e. when it is safe to allow a
+ * SuperSpeed connection to drop since there is no risk of a
+ * device degrading to its powered-off HiSpeed connection.
+ *
+ * Also, drop the HiSpeed ref taken above.
+ */
+ pm_runtime_get_sync(&ss_port->dev);
+ pm_runtime_put(&hs_port->dev);
+
+ return 0;
+}
+
+static void link_peers_report(struct usb_port *left, struct usb_port *right)
+{
+ int rc;
+
+ rc = link_peers(left, right);
+ if (rc == 0) {
+ dev_dbg(&left->dev, "peered to %s\n", dev_name(&right->dev));
+ } else {
+ dev_warn(&left->dev, "failed to peer to %s (%d)\n",
+ dev_name(&right->dev), rc);
+ pr_warn_once("usb: port power management may be unreliable\n");
+ }
+}
+
+static void unlink_peers(struct usb_port *left, struct usb_port *right)
+{
+ struct usb_port *ss_port, *hs_port;
+
+ WARN(right->peer != left || left->peer != right,
+ "%s and %s are not peers?\n",
+ dev_name(&left->dev), dev_name(&right->dev));
+
+ /*
+ * We wake the HiSpeed port to make sure we don't race its
+ * usb_port_runtime_resume() event which takes a SuperSpeed ref
+ * when ->peer is !NULL.
+ */
+ if (left->is_superspeed) {
+ ss_port = left;
+ hs_port = right;
+ } else {
+ ss_port = right;
+ hs_port = left;
+ }
+
+ pm_runtime_get_sync(&hs_port->dev);
+
+ sysfs_remove_link(&left->dev.kobj, "peer");
+ right->peer = NULL;
+ sysfs_remove_link(&right->dev.kobj, "peer");
+ left->peer = NULL;
+
+ /* Drop the SuperSpeed ref held on behalf of the active HiSpeed port */
+ pm_runtime_put(&ss_port->dev);
+
+ /* Drop the ref taken above */
+ pm_runtime_put(&hs_port->dev);
+}
+
+/*
+ * For each usb hub device in the system check to see if it is in the
+ * peer domain of the given port_dev, and if it is check to see if it
+ * has a port that matches the given port by location
+ */
+static int match_location(struct usb_device *peer_hdev, void *p)
+{
+ int port1;
+ struct usb_hcd *hcd, *peer_hcd;
+ struct usb_port *port_dev = p, *peer;
+ struct usb_hub *peer_hub = usb_hub_to_struct_hub(peer_hdev);
+ struct usb_device *hdev = to_usb_device(port_dev->dev.parent->parent);
+
+ if (!peer_hub)
+ return 0;
+
+ hcd = bus_to_hcd(hdev->bus);
+ peer_hcd = bus_to_hcd(peer_hdev->bus);
+ /* peer_hcd is provisional until we verify it against the known peer */
+ if (peer_hcd != hcd->shared_hcd)
+ return 0;
+
+ for (port1 = 1; port1 <= peer_hdev->maxchild; port1++) {
+ peer = peer_hub->ports[port1 - 1];
+ if (peer && peer->location == port_dev->location) {
+ link_peers_report(port_dev, peer);
+ return 1; /* done */
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Find the peer port either via explicit platform firmware "location"
+ * data, the peer hcd for root hubs, or the upstream peer relationship
+ * for all other hubs.
+ */
+static void find_and_link_peer(struct usb_hub *hub, int port1)
+{
+ struct usb_port *port_dev = hub->ports[port1 - 1], *peer;
+ struct usb_device *hdev = hub->hdev;
+ struct usb_device *peer_hdev;
+ struct usb_hub *peer_hub;
+
+ /*
+ * If location data is available then we can only peer this port
+ * by a location match, not the default peer (lest we create a
+ * situation where we need to go back and undo a default peering
+ * when the port is later peered by location data)
+ */
+ if (port_dev->location) {
+ /* we link the peer in match_location() if found */
+ usb_for_each_dev(port_dev, match_location);
+ return;
+ } else if (!hdev->parent) {
+ struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
+ struct usb_hcd *peer_hcd = hcd->shared_hcd;
+
+ if (!peer_hcd)
+ return;
+
+ peer_hdev = peer_hcd->self.root_hub;
+ } else {
+ struct usb_port *upstream;
+ struct usb_device *parent = hdev->parent;
+ struct usb_hub *parent_hub = usb_hub_to_struct_hub(parent);
+
+ if (!parent_hub)
+ return;
+
+ upstream = parent_hub->ports[hdev->portnum - 1];
+ if (!upstream || !upstream->peer)
+ return;
+
+ peer_hdev = upstream->peer->child;
+ }
+
+ peer_hub = usb_hub_to_struct_hub(peer_hdev);
+ if (!peer_hub || port1 > peer_hdev->maxchild)
+ return;
+
+ /*
+ * we found a valid default peer, last check is to make sure it
+ * does not have location data
+ */
+ peer = peer_hub->ports[port1 - 1];
+ if (peer && peer->location == 0)
+ link_peers_report(port_dev, peer);
+}
+
int usb_hub_create_port_device(struct usb_hub *hub, int port1)
{
- struct usb_port *port_dev = NULL;
+ struct usb_port *port_dev;
int retval;
port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL);
@@ -159,24 +393,33 @@ int usb_hub_create_port_device(struct usb_hub *hub, int port1)
hub->ports[port1 - 1] = port_dev;
port_dev->portnum = port1;
- port_dev->power_is_on = true;
+ set_bit(port1, hub->power_bits);
port_dev->dev.parent = hub->intfdev;
port_dev->dev.groups = port_dev_group;
port_dev->dev.type = &usb_port_device_type;
- dev_set_name(&port_dev->dev, "port%d", port1);
-
+ port_dev->dev.driver = &usb_port_driver;
+ if (hub_is_superspeed(hub->hdev))
+ port_dev->is_superspeed = 1;
+ dev_set_name(&port_dev->dev, "%s-port%d", dev_name(&hub->hdev->dev),
+ port1);
+ mutex_init(&port_dev->status_lock);
retval = device_register(&port_dev->dev);
if (retval)
goto error_register;
+ find_and_link_peer(hub, port1);
+
pm_runtime_set_active(&port_dev->dev);
- /* It would be dangerous if user space couldn't
- * prevent usb device from being powered off. So don't
- * enable port runtime pm if failed to expose port's pm qos.
+ /*
+ * Do not enable port runtime pm if the hub does not support
+ * power switching. Also, userspace must have final say of
+ * whether a port is permitted to power-off. Do not enable
+ * runtime pm if we fail to expose pm_qos_no_power_off.
*/
- if (!dev_pm_qos_expose_flags(&port_dev->dev,
- PM_QOS_FLAG_NO_POWER_OFF))
+ if (hub_is_port_power_switchable(hub)
+ && dev_pm_qos_expose_flags(&port_dev->dev,
+ PM_QOS_FLAG_NO_POWER_OFF) == 0)
pm_runtime_enable(&port_dev->dev);
device_enable_async_suspend(&port_dev->dev);
@@ -188,9 +431,13 @@ exit:
return retval;
}
-void usb_hub_remove_port_device(struct usb_hub *hub,
- int port1)
+void usb_hub_remove_port_device(struct usb_hub *hub, int port1)
{
- device_unregister(&hub->ports[port1 - 1]->dev);
-}
+ struct usb_port *port_dev = hub->ports[port1 - 1];
+ struct usb_port *peer;
+ peer = port_dev->peer;
+ if (peer)
+ unlink_peers(port_dev, peer);
+ device_unregister(&port_dev->dev);
+}
diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c
index 5ca4070b1f38..2776cfe64c09 100644
--- a/drivers/usb/core/usb-acpi.c
+++ b/drivers/usb/core/usb-acpi.c
@@ -17,7 +17,7 @@
#include <linux/pci.h>
#include <linux/usb/hcd.h>
-#include "usb.h"
+#include "hub.h"
/**
* usb_acpi_power_manageable - check whether usb port has
@@ -55,13 +55,18 @@ EXPORT_SYMBOL_GPL(usb_acpi_power_manageable);
*/
int usb_acpi_set_power_state(struct usb_device *hdev, int index, bool enable)
{
+ struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
+ struct usb_port *port_dev;
acpi_handle port_handle;
unsigned char state;
int port1 = index + 1;
int error = -EINVAL;
- port_handle = (acpi_handle)usb_get_hub_port_acpi_handle(hdev,
- port1);
+ if (!hub)
+ return -ENODEV;
+ port_dev = hub->ports[port1 - 1];
+
+ port_handle = (acpi_handle) usb_get_hub_port_acpi_handle(hdev, port1);
if (!port_handle)
return error;
@@ -72,23 +77,21 @@ int usb_acpi_set_power_state(struct usb_device *hdev, int index, bool enable)
error = acpi_bus_set_power(port_handle, state);
if (!error)
- dev_dbg(&hdev->dev, "The power of hub port %d was set to %d\n",
- port1, enable);
+ dev_dbg(&port_dev->dev, "acpi: power was set to %d\n", enable);
else
- dev_dbg(&hdev->dev, "The power of hub port failed to be set\n");
+ dev_dbg(&port_dev->dev, "acpi: power failed to be set\n");
return error;
}
EXPORT_SYMBOL_GPL(usb_acpi_set_power_state);
-static int usb_acpi_check_port_connect_type(struct usb_device *hdev,
- acpi_handle handle, int port1)
+static enum usb_port_connect_type usb_acpi_get_connect_type(acpi_handle handle,
+ struct acpi_pld_info *pld)
{
- acpi_status status;
+ enum usb_port_connect_type connect_type = USB_PORT_CONNECT_TYPE_UNKNOWN;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *upc;
- struct acpi_pld_info *pld;
- int ret = 0;
+ acpi_status status;
/*
* According to ACPI Spec 9.13. PLD indicates whether usb port is
@@ -98,39 +101,37 @@ static int usb_acpi_check_port_connect_type(struct usb_device *hdev,
* a usb device is directly hard-wired to the port. If no visible and
* no connectable, the port would be not used.
*/
- status = acpi_get_physical_device_location(handle, &pld);
- if (ACPI_FAILURE(status))
- return -ENODEV;
-
status = acpi_evaluate_object(handle, "_UPC", NULL, &buffer);
upc = buffer.pointer;
if (!upc || (upc->type != ACPI_TYPE_PACKAGE)
|| upc->package.count != 4) {
- ret = -EINVAL;
goto out;
}
if (upc->package.elements[0].integer.value)
if (pld->user_visible)
- usb_set_hub_port_connect_type(hdev, port1,
- USB_PORT_CONNECT_TYPE_HOT_PLUG);
+ connect_type = USB_PORT_CONNECT_TYPE_HOT_PLUG;
else
- usb_set_hub_port_connect_type(hdev, port1,
- USB_PORT_CONNECT_TYPE_HARD_WIRED);
+ connect_type = USB_PORT_CONNECT_TYPE_HARD_WIRED;
else if (!pld->user_visible)
- usb_set_hub_port_connect_type(hdev, port1, USB_PORT_NOT_USED);
-
+ connect_type = USB_PORT_NOT_USED;
out:
- ACPI_FREE(pld);
kfree(upc);
- return ret;
+ return connect_type;
}
+
+/*
+ * Private to usb-acpi, all the core needs to know is that
+ * port_dev->location is non-zero when it has been set by the firmware.
+ */
+#define USB_ACPI_LOCATION_VALID (1 << 31)
+
static struct acpi_device *usb_acpi_find_companion(struct device *dev)
{
struct usb_device *udev;
+ struct acpi_device *adev;
acpi_handle *parent_handle;
- int port_num;
/*
* In the ACPI DSDT table, only usb root hub and usb ports are
@@ -147,37 +148,19 @@ static struct acpi_device *usb_acpi_find_companion(struct device *dev)
*/
if (is_usb_device(dev)) {
udev = to_usb_device(dev);
- if (udev->parent) {
- enum usb_port_connect_type type;
-
- /*
- * According usb port's connect type to set usb device's
- * removability.
- */
- type = usb_get_hub_port_connect_type(udev->parent,
- udev->portnum);
- switch (type) {
- case USB_PORT_CONNECT_TYPE_HOT_PLUG:
- udev->removable = USB_DEVICE_REMOVABLE;
- break;
- case USB_PORT_CONNECT_TYPE_HARD_WIRED:
- udev->removable = USB_DEVICE_FIXED;
- break;
- default:
- udev->removable = USB_DEVICE_REMOVABLE_UNKNOWN;
- break;
- }
-
+ if (udev->parent)
return NULL;
- }
- /* root hub's parent is the usb hcd. */
- return acpi_find_child_device(ACPI_COMPANION(dev->parent),
- udev->portnum, false);
+ /* root hub is only child (_ADR=0) under its parent, the HC */
+ adev = ACPI_COMPANION(dev->parent);
+ return acpi_find_child_device(adev, 0, false);
} else if (is_usb_port(dev)) {
- struct acpi_device *adev = NULL;
+ struct usb_port *port_dev = to_usb_port(dev);
+ int port1 = port_dev->portnum;
+ struct acpi_pld_info *pld;
+ acpi_handle *handle;
+ acpi_status status;
- sscanf(dev_name(dev), "port%d", &port_num);
/* Get the struct usb_device point of port's hub */
udev = to_usb_device(dev->parent->parent);
@@ -188,12 +171,11 @@ static struct acpi_device *usb_acpi_find_companion(struct device *dev)
*/
if (!udev->parent) {
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
- int raw_port_num;
+ int raw;
- raw_port_num = usb_hcd_find_raw_port_number(hcd,
- port_num);
+ raw = usb_hcd_find_raw_port_number(hcd, port1);
adev = acpi_find_child_device(ACPI_COMPANION(&udev->dev),
- raw_port_num, false);
+ raw, false);
if (!adev)
return NULL;
} else {
@@ -204,11 +186,20 @@ static struct acpi_device *usb_acpi_find_companion(struct device *dev)
return NULL;
acpi_bus_get_device(parent_handle, &adev);
- adev = acpi_find_child_device(adev, port_num, false);
+ adev = acpi_find_child_device(adev, port1, false);
if (!adev)
return NULL;
}
- usb_acpi_check_port_connect_type(udev, adev->handle, port_num);
+ handle = adev->handle;
+ status = acpi_get_physical_device_location(handle, &pld);
+ if (ACPI_FAILURE(status) || !pld)
+ return adev;
+
+ port_dev->location = USB_ACPI_LOCATION_VALID
+ | pld->group_token << 8 | pld->group_position;
+ port_dev->connect_type = usb_acpi_get_connect_type(handle, pld);
+ ACPI_FREE(pld);
+
return adev;
}
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 75bf649da82d..d9d08720c386 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -107,11 +107,6 @@ static inline int usb_autoresume_device(struct usb_device *udev)
return 0;
}
-static inline int usb_remote_wakeup(struct usb_device *udev)
-{
- return 0;
-}
-
static inline int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
{
return 0;
@@ -119,6 +114,7 @@ static inline int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
#endif
extern struct bus_type usb_bus_type;
+extern struct mutex usb_port_peer_mutex;
extern struct device_type usb_device_type;
extern struct device_type usb_if_device_type;
extern struct device_type usb_ep_device_type;
@@ -170,15 +166,17 @@ extern void usbfs_conn_disc_event(void);
extern int usb_devio_init(void);
extern void usb_devio_cleanup(void);
+/*
+ * Firmware specific cookie identifying a port's location. '0' == no location
+ * data available
+ */
+typedef u32 usb_port_location_t;
+
/* internal notify stuff */
extern void usb_notify_add_device(struct usb_device *udev);
extern void usb_notify_remove_device(struct usb_device *udev);
extern void usb_notify_add_bus(struct usb_bus *ubus);
extern void usb_notify_remove_bus(struct usb_bus *ubus);
-extern enum usb_port_connect_type
- usb_get_hub_port_connect_type(struct usb_device *hdev, int port1);
-extern void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1,
- enum usb_port_connect_type type);
extern void usb_hub_adjust_deviceremovable(struct usb_device *hdev,
struct usb_hub_descriptor *desc);
diff --git a/drivers/usb/dwc2/Kconfig b/drivers/usb/dwc2/Kconfig
index be947d673844..f93807b3631a 100644
--- a/drivers/usb/dwc2/Kconfig
+++ b/drivers/usb/dwc2/Kconfig
@@ -1,25 +1,58 @@
config USB_DWC2
- tristate "DesignWare USB2 DRD Core Support"
+ bool "DesignWare USB2 DRD Core Support"
depends on USB
help
- Say Y or M here if your system has a Dual Role HighSpeed
- USB controller based on the DesignWare HSOTG IP Core.
+ Say Y here if your system has a Dual Role Hi-Speed USB
+ controller based on the DesignWare HSOTG IP Core.
- If you choose to build this driver as dynamically linked
- modules, the core module will be called dwc2.ko, the
- PCI bus interface module (if you have a PCI bus system)
- will be called dwc2_pci.ko and the platform interface module
- (for controllers directly connected to the CPU) will be called
- dwc2_platform.ko.
+ For host mode, if you choose to build the driver as dynamically
+ linked modules, the core module will be called dwc2.ko, the PCI
+ bus interface module (if you have a PCI bus system) will be
+ called dwc2_pci.ko, and the platform interface module (for
+ controllers directly connected to the CPU) will be called
+ dwc2_platform.ko. For gadget mode, there will be a single
+ module called dwc2_gadget.ko.
- NOTE: This driver at present only implements the Host mode
- of the controller. The existing s3c-hsotg driver supports
- Peripheral mode, but only for the Samsung S3C platforms.
- There are plans to merge the s3c-hsotg driver with this
- driver in the near future to create a dual-role driver.
+ NOTE: The s3c-hsotg driver is now renamed to dwc2_gadget. The
+ host and gadget drivers are still currently separate drivers.
+ There are plans to merge the dwc2_gadget driver with the dwc2
+ host driver in the near future to create a dual-role driver.
if USB_DWC2
+config USB_DWC2_HOST
+ tristate "Host only mode"
+ depends on USB
+ help
+ The Designware USB2.0 high-speed host controller
+ integrated into many SoCs.
+
+config USB_DWC2_PLATFORM
+ bool "DWC2 Platform"
+ depends on USB_DWC2_HOST
+ default USB_DWC2_HOST
+ help
+ The Designware USB2.0 platform interface module for
+ controllers directly connected to the CPU. This is only
+ used for host mode.
+
+config USB_DWC2_PCI
+ bool "DWC2 PCI"
+ depends on USB_DWC2_HOST && PCI
+ default USB_DWC2_HOST
+ help
+ The Designware USB2.0 PCI interface module for controllers
+ connected to a PCI bus. This is only used for host mode.
+
+comment "Gadget mode requires USB Gadget support to be enabled"
+
+config USB_DWC2_PERIPHERAL
+ tristate "Gadget only mode"
+ depends on USB_GADGET
+ help
+ The Designware USB2.0 high-speed gadget controller
+ integrated into many SoCs.
+
config USB_DWC2_DEBUG
bool "Enable Debugging Messages"
help
diff --git a/drivers/usb/dwc2/Makefile b/drivers/usb/dwc2/Makefile
index 11529d3439b0..b73d2a527970 100644
--- a/drivers/usb/dwc2/Makefile
+++ b/drivers/usb/dwc2/Makefile
@@ -1,25 +1,28 @@
ccflags-$(CONFIG_USB_DWC2_DEBUG) += -DDEBUG
ccflags-$(CONFIG_USB_DWC2_VERBOSE) += -DVERBOSE_DEBUG
-obj-$(CONFIG_USB_DWC2) += dwc2.o
-
-dwc2-y += core.o core_intr.o
-
-# NOTE: This driver at present only implements the Host mode
-# of the controller. The existing s3c-hsotg driver supports
-# Peripheral mode, but only for the Samsung S3C platforms.
-# There are plans to merge the s3c-hsotg driver with this
-# driver in the near future to create a dual-role driver. Once
-# that is done, Host mode will become an optional feature that
-# is selected with a config option.
-
+obj-$(CONFIG_USB_DWC2_HOST) += dwc2.o
+dwc2-y := core.o core_intr.o
dwc2-y += hcd.o hcd_intr.o
dwc2-y += hcd_queue.o hcd_ddma.o
-ifneq ($(CONFIG_PCI),)
- obj-$(CONFIG_USB_DWC2) += dwc2_pci.o
+# NOTE: The previous s3c-hsotg peripheral mode only driver has been moved to
+# this location and renamed gadget.c. When building for dynamically linked
+# modules, dwc2_gadget.ko will get built for peripheral mode. For host mode,
+# the core module will be dwc2.ko, the PCI bus interface module will called
+# dwc2_pci.ko and the platform interface module will be called dwc2_platform.ko.
+# At present the host and gadget driver will be separate drivers, but there
+# are plans in the near future to create a dual-role driver.
+
+ifneq ($(CONFIG_USB_DWC2_PCI),)
+ obj-$(CONFIG_USB_DWC2_HOST) += dwc2_pci.o
+ dwc2_pci-y := pci.o
+endif
+
+ifneq ($(CONFIG_USB_DWC2_PLATFORM),)
+ obj-$(CONFIG_USB_DWC2_HOST) += dwc2_platform.o
+ dwc2_platform-y := platform.o
endif
-obj-$(CONFIG_USB_DWC2) += dwc2_platform.o
-dwc2_pci-y += pci.o
-dwc2_platform-y += platform.o
+obj-$(CONFIG_USB_DWC2_PERIPHERAL) += dwc2_gadget.o
+dwc2_gadget-y := gadget.o
diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 1d129884cc39..27d2c9b8a034 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -507,6 +507,72 @@ void dwc2_disable_host_interrupts(struct dwc2_hsotg *hsotg)
writel(intmsk, hsotg->regs + GINTMSK);
}
+/*
+ * dwc2_calculate_dynamic_fifo() - Calculates the default fifo size
+ * For system that have a total fifo depth that is smaller than the default
+ * RX + TX fifo size.
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ */
+static void dwc2_calculate_dynamic_fifo(struct dwc2_hsotg *hsotg)
+{
+ struct dwc2_core_params *params = hsotg->core_params;
+ struct dwc2_hw_params *hw = &hsotg->hw_params;
+ u32 rxfsiz, nptxfsiz, ptxfsiz, total_fifo_size;
+
+ total_fifo_size = hw->total_fifo_size;
+ rxfsiz = params->host_rx_fifo_size;
+ nptxfsiz = params->host_nperio_tx_fifo_size;
+ ptxfsiz = params->host_perio_tx_fifo_size;
+
+ /*
+ * Will use Method 2 defined in the DWC2 spec: minimum FIFO depth
+ * allocation with support for high bandwidth endpoints. Synopsys
+ * defines MPS(Max Packet size) for a periodic EP=1024, and for
+ * non-periodic as 512.
+ */
+ if (total_fifo_size < (rxfsiz + nptxfsiz + ptxfsiz)) {
+ /*
+ * For Buffer DMA mode/Scatter Gather DMA mode
+ * 2 * ((Largest Packet size / 4) + 1 + 1) + n
+ * with n = number of host channel.
+ * 2 * ((1024/4) + 2) = 516
+ */
+ rxfsiz = 516 + hw->host_channels;
+
+ /*
+ * min non-periodic tx fifo depth
+ * 2 * (largest non-periodic USB packet used / 4)
+ * 2 * (512/4) = 256
+ */
+ nptxfsiz = 256;
+
+ /*
+ * min periodic tx fifo depth
+ * (largest packet size*MC)/4
+ * (1024 * 3)/4 = 768
+ */
+ ptxfsiz = 768;
+
+ params->host_rx_fifo_size = rxfsiz;
+ params->host_nperio_tx_fifo_size = nptxfsiz;
+ params->host_perio_tx_fifo_size = ptxfsiz;
+ }
+
+ /*
+ * If the summation of RX, NPTX and PTX fifo sizes is still
+ * bigger than the total_fifo_size, then we have a problem.
+ *
+ * We won't be able to allocate as many endpoints. Right now,
+ * we're just printing an error message, but ideally this FIFO
+ * allocation algorithm would be improved in the future.
+ *
+ * FIXME improve this FIFO allocation algorithm.
+ */
+ if (unlikely(total_fifo_size < (rxfsiz + nptxfsiz + ptxfsiz)))
+ dev_err(hsotg->dev, "invalid fifo sizes\n");
+}
+
static void dwc2_config_fifos(struct dwc2_hsotg *hsotg)
{
struct dwc2_core_params *params = hsotg->core_params;
@@ -515,6 +581,8 @@ static void dwc2_config_fifos(struct dwc2_hsotg *hsotg)
if (!params->enable_dynamic_fifo)
return;
+ dwc2_calculate_dynamic_fifo(hsotg);
+
/* Rx FIFO */
grxfsiz = readl(hsotg->regs + GRXFSIZ);
dev_dbg(hsotg->dev, "initial grxfsiz=%08x\n", grxfsiz);
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 648519c024b5..1efd10cc9629 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -37,6 +37,10 @@
#ifndef __DWC2_CORE_H__
#define __DWC2_CORE_H__
+#include <linux/phy/phy.h>
+#include <linux/regulator/consumer.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
#include <linux/usb/phy.h>
#include "hw.h"
@@ -54,6 +58,184 @@ static inline void do_write(u32 value, void *addr)
/* Maximum number of Endpoints/HostChannels */
#define MAX_EPS_CHANNELS 16
+/* s3c-hsotg declarations */
+static const char * const s3c_hsotg_supply_names[] = {
+ "vusb_d", /* digital USB supply, 1.2V */
+ "vusb_a", /* analog USB supply, 1.1V */
+};
+
+/*
+ * EP0_MPS_LIMIT
+ *
+ * Unfortunately there seems to be a limit of the amount of data that can
+ * be transferred by IN transactions on EP0. This is either 127 bytes or 3
+ * packets (which practically means 1 packet and 63 bytes of data) when the
+ * MPS is set to 64.
+ *
+ * This means if we are wanting to move >127 bytes of data, we need to
+ * split the transactions up, but just doing one packet at a time does
+ * not work (this may be an implicit DATA0 PID on first packet of the
+ * transaction) and doing 2 packets is outside the controller's limits.
+ *
+ * If we try to lower the MPS size for EP0, then no transfers work properly
+ * for EP0, and the system will fail basic enumeration. As no cause for this
+ * has currently been found, we cannot support any large IN transfers for
+ * EP0.
+ */
+#define EP0_MPS_LIMIT 64
+
+struct s3c_hsotg;
+struct s3c_hsotg_req;
+
+/**
+ * struct s3c_hsotg_ep - driver endpoint definition.
+ * @ep: The gadget layer representation of the endpoint.
+ * @name: The driver generated name for the endpoint.
+ * @queue: Queue of requests for this endpoint.
+ * @parent: Reference back to the parent device structure.
+ * @req: The current request that the endpoint is processing. This is
+ * used to indicate an request has been loaded onto the endpoint
+ * and has yet to be completed (maybe due to data move, or simply
+ * awaiting an ack from the core all the data has been completed).
+ * @debugfs: File entry for debugfs file for this endpoint.
+ * @lock: State lock to protect contents of endpoint.
+ * @dir_in: Set to true if this endpoint is of the IN direction, which
+ * means that it is sending data to the Host.
+ * @index: The index for the endpoint registers.
+ * @mc: Multi Count - number of transactions per microframe
+ * @interval - Interval for periodic endpoints
+ * @name: The name array passed to the USB core.
+ * @halted: Set if the endpoint has been halted.
+ * @periodic: Set if this is a periodic ep, such as Interrupt
+ * @isochronous: Set if this is a isochronous ep
+ * @sent_zlp: Set if we've sent a zero-length packet.
+ * @total_data: The total number of data bytes done.
+ * @fifo_size: The size of the FIFO (for periodic IN endpoints)
+ * @fifo_load: The amount of data loaded into the FIFO (periodic IN)
+ * @last_load: The offset of data for the last start of request.
+ * @size_loaded: The last loaded size for DxEPTSIZE for periodic IN
+ *
+ * This is the driver's state for each registered enpoint, allowing it
+ * to keep track of transactions that need doing. Each endpoint has a
+ * lock to protect the state, to try and avoid using an overall lock
+ * for the host controller as much as possible.
+ *
+ * For periodic IN endpoints, we have fifo_size and fifo_load to try
+ * and keep track of the amount of data in the periodic FIFO for each
+ * of these as we don't have a status register that tells us how much
+ * is in each of them. (note, this may actually be useless information
+ * as in shared-fifo mode periodic in acts like a single-frame packet
+ * buffer than a fifo)
+ */
+struct s3c_hsotg_ep {
+ struct usb_ep ep;
+ struct list_head queue;
+ struct s3c_hsotg *parent;
+ struct s3c_hsotg_req *req;
+ struct dentry *debugfs;
+
+ unsigned long total_data;
+ unsigned int size_loaded;
+ unsigned int last_load;
+ unsigned int fifo_load;
+ unsigned short fifo_size;
+
+ unsigned char dir_in;
+ unsigned char index;
+ unsigned char mc;
+ unsigned char interval;
+
+ unsigned int halted:1;
+ unsigned int periodic:1;
+ unsigned int isochronous:1;
+ unsigned int sent_zlp:1;
+
+ char name[10];
+};
+
+/**
+ * struct s3c_hsotg - driver state.
+ * @dev: The parent device supplied to the probe function
+ * @driver: USB gadget driver
+ * @phy: The otg phy transceiver structure for phy control.
+ * @uphy: The otg phy transceiver structure for old USB phy control.
+ * @plat: The platform specific configuration data. This can be removed once
+ * all SoCs support usb transceiver.
+ * @regs: The memory area mapped for accessing registers.
+ * @irq: The IRQ number we are using
+ * @supplies: Definition of USB power supplies
+ * @phyif: PHY interface width
+ * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos.
+ * @num_of_eps: Number of available EPs (excluding EP0)
+ * @debug_root: root directrory for debugfs.
+ * @debug_file: main status file for debugfs.
+ * @debug_fifo: FIFO status file for debugfs.
+ * @ep0_reply: Request used for ep0 reply.
+ * @ep0_buff: Buffer for EP0 reply data, if needed.
+ * @ctrl_buff: Buffer for EP0 control requests.
+ * @ctrl_req: Request for EP0 control packets.
+ * @setup: NAK management for EP0 SETUP
+ * @last_rst: Time of last reset
+ * @eps: The endpoints being supplied to the gadget framework
+ */
+struct s3c_hsotg {
+ struct device *dev;
+ struct usb_gadget_driver *driver;
+ struct phy *phy;
+ struct usb_phy *uphy;
+ struct s3c_hsotg_plat *plat;
+
+ spinlock_t lock;
+
+ void __iomem *regs;
+ int irq;
+ struct clk *clk;
+
+ struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsotg_supply_names)];
+
+ u32 phyif;
+ unsigned int dedicated_fifos:1;
+ unsigned char num_of_eps;
+
+ struct dentry *debug_root;
+ struct dentry *debug_file;
+ struct dentry *debug_fifo;
+
+ struct usb_request *ep0_reply;
+ struct usb_request *ctrl_req;
+ u8 ep0_buff[8];
+ u8 ctrl_buff[8];
+
+ struct usb_gadget gadget;
+ unsigned int setup;
+ unsigned long last_rst;
+ struct s3c_hsotg_ep *eps;
+};
+
+/**
+ * struct s3c_hsotg_req - data transfer request
+ * @req: The USB gadget request
+ * @queue: The list of requests for the endpoint this is queued for.
+ * @in_progress: Has already had size/packets written to core
+ * @mapped: DMA buffer for this request has been mapped via dma_map_single().
+ */
+struct s3c_hsotg_req {
+ struct usb_request req;
+ struct list_head queue;
+ unsigned char in_progress;
+ unsigned char mapped;
+};
+
+#define call_gadget(_hs, _entry) \
+do { \
+ if ((_hs)->gadget.speed != USB_SPEED_UNKNOWN && \
+ (_hs)->driver && (_hs)->driver->_entry) { \
+ spin_unlock(&_hs->lock); \
+ (_hs)->driver->_entry(&(_hs)->gadget); \
+ spin_lock(&_hs->lock); \
+ } \
+} while (0)
+
struct dwc2_hsotg;
struct dwc2_host_chan;
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/dwc2/gadget.c
index 2a9cb674926a..f3c56a2fed5b 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -37,175 +37,7 @@
#include <linux/usb/phy.h>
#include <linux/platform_data/s3c-hsotg.h>
-#include "s3c-hsotg.h"
-
-static const char * const s3c_hsotg_supply_names[] = {
- "vusb_d", /* digital USB supply, 1.2V */
- "vusb_a", /* analog USB supply, 1.1V */
-};
-
-/*
- * EP0_MPS_LIMIT
- *
- * Unfortunately there seems to be a limit of the amount of data that can
- * be transferred by IN transactions on EP0. This is either 127 bytes or 3
- * packets (which practically means 1 packet and 63 bytes of data) when the
- * MPS is set to 64.
- *
- * This means if we are wanting to move >127 bytes of data, we need to
- * split the transactions up, but just doing one packet at a time does
- * not work (this may be an implicit DATA0 PID on first packet of the
- * transaction) and doing 2 packets is outside the controller's limits.
- *
- * If we try to lower the MPS size for EP0, then no transfers work properly
- * for EP0, and the system will fail basic enumeration. As no cause for this
- * has currently been found, we cannot support any large IN transfers for
- * EP0.
- */
-#define EP0_MPS_LIMIT 64
-
-struct s3c_hsotg;
-struct s3c_hsotg_req;
-
-/**
- * struct s3c_hsotg_ep - driver endpoint definition.
- * @ep: The gadget layer representation of the endpoint.
- * @name: The driver generated name for the endpoint.
- * @queue: Queue of requests for this endpoint.
- * @parent: Reference back to the parent device structure.
- * @req: The current request that the endpoint is processing. This is
- * used to indicate an request has been loaded onto the endpoint
- * and has yet to be completed (maybe due to data move, or simply
- * awaiting an ack from the core all the data has been completed).
- * @debugfs: File entry for debugfs file for this endpoint.
- * @lock: State lock to protect contents of endpoint.
- * @dir_in: Set to true if this endpoint is of the IN direction, which
- * means that it is sending data to the Host.
- * @index: The index for the endpoint registers.
- * @mc: Multi Count - number of transactions per microframe
- * @interval - Interval for periodic endpoints
- * @name: The name array passed to the USB core.
- * @halted: Set if the endpoint has been halted.
- * @periodic: Set if this is a periodic ep, such as Interrupt
- * @isochronous: Set if this is a isochronous ep
- * @sent_zlp: Set if we've sent a zero-length packet.
- * @total_data: The total number of data bytes done.
- * @fifo_size: The size of the FIFO (for periodic IN endpoints)
- * @fifo_load: The amount of data loaded into the FIFO (periodic IN)
- * @last_load: The offset of data for the last start of request.
- * @size_loaded: The last loaded size for DxEPTSIZE for periodic IN
- *
- * This is the driver's state for each registered enpoint, allowing it
- * to keep track of transactions that need doing. Each endpoint has a
- * lock to protect the state, to try and avoid using an overall lock
- * for the host controller as much as possible.
- *
- * For periodic IN endpoints, we have fifo_size and fifo_load to try
- * and keep track of the amount of data in the periodic FIFO for each
- * of these as we don't have a status register that tells us how much
- * is in each of them. (note, this may actually be useless information
- * as in shared-fifo mode periodic in acts like a single-frame packet
- * buffer than a fifo)
- */
-struct s3c_hsotg_ep {
- struct usb_ep ep;
- struct list_head queue;
- struct s3c_hsotg *parent;
- struct s3c_hsotg_req *req;
- struct dentry *debugfs;
-
-
- unsigned long total_data;
- unsigned int size_loaded;
- unsigned int last_load;
- unsigned int fifo_load;
- unsigned short fifo_size;
-
- unsigned char dir_in;
- unsigned char index;
- unsigned char mc;
- unsigned char interval;
-
- unsigned int halted:1;
- unsigned int periodic:1;
- unsigned int isochronous:1;
- unsigned int sent_zlp:1;
-
- char name[10];
-};
-
-/**
- * struct s3c_hsotg - driver state.
- * @dev: The parent device supplied to the probe function
- * @driver: USB gadget driver
- * @phy: The otg phy transceiver structure for phy control.
- * @uphy: The otg phy transceiver structure for old USB phy control.
- * @plat: The platform specific configuration data. This can be removed once
- * all SoCs support usb transceiver.
- * @regs: The memory area mapped for accessing registers.
- * @irq: The IRQ number we are using
- * @supplies: Definition of USB power supplies
- * @phyif: PHY interface width
- * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos.
- * @num_of_eps: Number of available EPs (excluding EP0)
- * @debug_root: root directrory for debugfs.
- * @debug_file: main status file for debugfs.
- * @debug_fifo: FIFO status file for debugfs.
- * @ep0_reply: Request used for ep0 reply.
- * @ep0_buff: Buffer for EP0 reply data, if needed.
- * @ctrl_buff: Buffer for EP0 control requests.
- * @ctrl_req: Request for EP0 control packets.
- * @setup: NAK management for EP0 SETUP
- * @last_rst: Time of last reset
- * @eps: The endpoints being supplied to the gadget framework
- */
-struct s3c_hsotg {
- struct device *dev;
- struct usb_gadget_driver *driver;
- struct phy *phy;
- struct usb_phy *uphy;
- struct s3c_hsotg_plat *plat;
-
- spinlock_t lock;
-
- void __iomem *regs;
- int irq;
- struct clk *clk;
-
- struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsotg_supply_names)];
-
- u32 phyif;
- unsigned int dedicated_fifos:1;
- unsigned char num_of_eps;
-
- struct dentry *debug_root;
- struct dentry *debug_file;
- struct dentry *debug_fifo;
-
- struct usb_request *ep0_reply;
- struct usb_request *ctrl_req;
- u8 ep0_buff[8];
- u8 ctrl_buff[8];
-
- struct usb_gadget gadget;
- unsigned int setup;
- unsigned long last_rst;
- struct s3c_hsotg_ep *eps;
-};
-
-/**
- * struct s3c_hsotg_req - data transfer request
- * @req: The USB gadget request
- * @queue: The list of requests for the endpoint this is queued for.
- * @in_progress: Has already had size/packets written to core
- * @mapped: DMA buffer for this request has been mapped via dma_map_single().
- */
-struct s3c_hsotg_req {
- struct usb_request req;
- struct list_head queue;
- unsigned char in_progress;
- unsigned char mapped;
-};
+#include "core.h"
/* conversion functions */
static inline struct s3c_hsotg_req *our_req(struct usb_request *req)
@@ -340,9 +172,8 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg)
/* set FIFO sizes to 2048/1024 */
writel(2048, hsotg->regs + GRXFSIZ);
- writel(GNPTXFSIZ_NPTxFStAddr(2048) |
- GNPTXFSIZ_NPTxFDep(1024),
- hsotg->regs + GNPTXFSIZ);
+ writel((2048 << FIFOSIZE_STARTADDR_SHIFT) |
+ (1024 << FIFOSIZE_DEPTH_SHIFT), hsotg->regs + GNPTXFSIZ);
/*
* arange all the rest of the TX FIFOs, as some versions of this
@@ -362,10 +193,10 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg)
for (ep = 1; ep <= 15; ep++) {
val = addr;
- val |= size << DPTXFSIZn_DPTxFSize_SHIFT;
+ val |= size << FIFOSIZE_DEPTH_SHIFT;
addr += size;
- writel(val, hsotg->regs + DPTXFSIZn(ep));
+ writel(val, hsotg->regs + DPTXFSIZN(ep));
}
/*
@@ -373,15 +204,15 @@ static void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg)
* all fifos are flushed before continuing
*/
- writel(GRSTCTL_TxFNum(0x10) | GRSTCTL_TxFFlsh |
- GRSTCTL_RxFFlsh, hsotg->regs + GRSTCTL);
+ writel(GRSTCTL_TXFNUM(0x10) | GRSTCTL_TXFFLSH |
+ GRSTCTL_RXFFLSH, hsotg->regs + GRSTCTL);
/* wait until the fifos are both flushed */
timeout = 100;
while (1) {
val = readl(hsotg->regs + GRSTCTL);
- if ((val & (GRSTCTL_TxFFlsh | GRSTCTL_RxFFlsh)) == 0)
+ if ((val & (GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH)) == 0)
break;
if (--timeout == 0) {
@@ -495,14 +326,14 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
* how much data is left in the fifo.
*/
- size_left = DxEPTSIZ_XferSize_GET(epsize);
+ size_left = DXEPTSIZ_XFERSIZE_GET(epsize);
/*
* if shared fifo, we cannot write anything until the
* previous data has been completely sent.
*/
if (hs_ep->fifo_load != 0) {
- s3c_hsotg_en_gsint(hsotg, GINTSTS_PTxFEmp);
+ s3c_hsotg_en_gsint(hsotg, GINTSTS_PTXFEMP);
return -ENOSPC;
}
@@ -523,7 +354,7 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
__func__, can_write);
if (can_write <= 0) {
- s3c_hsotg_en_gsint(hsotg, GINTSTS_PTxFEmp);
+ s3c_hsotg_en_gsint(hsotg, GINTSTS_PTXFEMP);
return -ENOSPC;
}
} else if (hsotg->dedicated_fifos && hs_ep->index != 0) {
@@ -532,16 +363,16 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
can_write &= 0xffff;
can_write *= 4;
} else {
- if (GNPTXSTS_NPTxQSpcAvail_GET(gnptxsts) == 0) {
+ if (GNPTXSTS_NP_TXQ_SPC_AVAIL_GET(gnptxsts) == 0) {
dev_dbg(hsotg->dev,
"%s: no queue slots available (0x%08x)\n",
__func__, gnptxsts);
- s3c_hsotg_en_gsint(hsotg, GINTSTS_NPTxFEmp);
+ s3c_hsotg_en_gsint(hsotg, GINTSTS_NPTXFEMP);
return -ENOSPC;
}
- can_write = GNPTXSTS_NPTxFSpcAvail_GET(gnptxsts);
+ can_write = GNPTXSTS_NP_TXF_SPC_AVAIL_GET(gnptxsts);
can_write *= 4; /* fifo size is in 32bit quantities. */
}
@@ -569,8 +400,8 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
/* it's needed only when we do not use dedicated fifos */
if (!hsotg->dedicated_fifos)
s3c_hsotg_en_gsint(hsotg,
- periodic ? GINTSTS_PTxFEmp :
- GINTSTS_NPTxFEmp);
+ periodic ? GINTSTS_PTXFEMP :
+ GINTSTS_NPTXFEMP);
}
/* see if we can write data */
@@ -598,8 +429,8 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
/* it's needed only when we do not use dedicated fifos */
if (!hsotg->dedicated_fifos)
s3c_hsotg_en_gsint(hsotg,
- periodic ? GINTSTS_PTxFEmp :
- GINTSTS_NPTxFEmp);
+ periodic ? GINTSTS_PTXFEMP :
+ GINTSTS_NPTXFEMP);
}
dev_dbg(hsotg->dev, "write %d/%d, can_write %d, done %d\n",
@@ -636,12 +467,12 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep)
unsigned maxpkt;
if (index != 0) {
- maxsize = DxEPTSIZ_XferSize_LIMIT + 1;
- maxpkt = DxEPTSIZ_PktCnt_LIMIT + 1;
+ maxsize = DXEPTSIZ_XFERSIZE_LIMIT + 1;
+ maxpkt = DXEPTSIZ_PKTCNT_LIMIT + 1;
} else {
maxsize = 64+64;
if (hs_ep->dir_in)
- maxpkt = DIEPTSIZ0_PktCnt_LIMIT + 1;
+ maxpkt = DIEPTSIZ0_PKTCNT_LIMIT + 1;
else
maxpkt = 2;
}
@@ -710,7 +541,7 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
/* If endpoint is stalled, we will restart request later */
ctrl = readl(hsotg->regs + epctrl_reg);
- if (ctrl & DxEPCTL_Stall) {
+ if (ctrl & DXEPCTL_STALL) {
dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index);
return;
}
@@ -720,7 +551,7 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
ureq->length, ureq->actual);
if (0)
dev_dbg(hsotg->dev,
- "REQ buf %p len %d dma 0x%pad noi=%d zp=%d snok=%d\n",
+ "REQ buf %p len %d dma %pad noi=%d zp=%d snok=%d\n",
ureq->buf, length, &ureq->dma,
ureq->no_interrupt, ureq->zero, ureq->short_not_ok);
@@ -750,9 +581,9 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
if (dir_in && index != 0)
if (hs_ep->isochronous)
- epsize = DxEPTSIZ_MC(packets);
+ epsize = DXEPTSIZ_MC(packets);
else
- epsize = DxEPTSIZ_MC(1);
+ epsize = DXEPTSIZ_MC(1);
else
epsize = 0;
@@ -766,8 +597,8 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
packets++;
}
- epsize |= DxEPTSIZ_PktCnt(packets);
- epsize |= DxEPTSIZ_XferSize(length);
+ epsize |= DXEPTSIZ_PKTCNT(packets);
+ epsize |= DXEPTSIZ_XFERSIZE(length);
dev_dbg(hsotg->dev, "%s: %d@%d/%d, 0x%08x => 0x%08x\n",
__func__, packets, length, ureq->length, epsize, epsize_reg);
@@ -789,12 +620,12 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
dma_reg = dir_in ? DIEPDMA(index) : DOEPDMA(index);
writel(ureq->dma, hsotg->regs + dma_reg);
- dev_dbg(hsotg->dev, "%s: 0x%pad => 0x%08x\n",
+ dev_dbg(hsotg->dev, "%s: %pad => 0x%08x\n",
__func__, &ureq->dma, dma_reg);
}
- ctrl |= DxEPCTL_EPEna; /* ensure ep enabled */
- ctrl |= DxEPCTL_USBActEp;
+ ctrl |= DXEPCTL_EPENA; /* ensure ep enabled */
+ ctrl |= DXEPCTL_USBACTEP;
dev_dbg(hsotg->dev, "setup req:%d\n", hsotg->setup);
@@ -802,7 +633,7 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
if (hsotg->setup && index == 0)
hsotg->setup = 0;
else
- ctrl |= DxEPCTL_CNAK; /* clear NAK set by core */
+ ctrl |= DXEPCTL_CNAK; /* clear NAK set by core */
dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl);
@@ -828,7 +659,7 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
* to debugging to see what is going on.
*/
if (dir_in)
- writel(DIEPMSK_INTknTXFEmpMsk,
+ writel(DIEPMSK_INTKNTXFEMPMSK,
hsotg->regs + DIEPINT(index));
/*
@@ -837,12 +668,12 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
*/
/* check ep is enabled */
- if (!(readl(hsotg->regs + epctrl_reg) & DxEPCTL_EPEna))
+ if (!(readl(hsotg->regs + epctrl_reg) & DXEPCTL_EPENA))
dev_warn(hsotg->dev,
- "ep%d: failed to become enabled (DxEPCTL=0x%08x)?\n",
+ "ep%d: failed to become enabled (DXEPCTL=0x%08x)?\n",
index, readl(hsotg->regs + epctrl_reg));
- dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n",
+ dev_dbg(hsotg->dev, "%s: DXEPCTL=0x%08x\n",
__func__, readl(hsotg->regs + epctrl_reg));
/* enable ep interrupts */
@@ -1205,12 +1036,12 @@ static void s3c_hsotg_stall_ep0(struct s3c_hsotg *hsotg) {
*/
ctrl = readl(hsotg->regs + reg);
- ctrl |= DxEPCTL_Stall;
- ctrl |= DxEPCTL_CNAK;
+ ctrl |= DXEPCTL_STALL;
+ ctrl |= DXEPCTL_CNAK;
writel(ctrl, hsotg->regs + reg);
dev_dbg(hsotg->dev,
- "written DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n",
+ "written DXEPCTL=0x%08x to %08x (DXEPCTL=0x%08x)\n",
ctrl, reg, readl(hsotg->regs + reg));
/*
@@ -1262,8 +1093,9 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
case USB_REQ_SET_ADDRESS:
s3c_hsotg_disconnect(hsotg);
dcfg = readl(hsotg->regs + DCFG);
- dcfg &= ~DCFG_DevAddr_MASK;
- dcfg |= ctrl->wValue << DCFG_DevAddr_SHIFT;
+ dcfg &= ~DCFG_DEVADDR_MASK;
+ dcfg |= (le16_to_cpu(ctrl->wValue) <<
+ DCFG_DEVADDR_SHIFT) & DCFG_DEVADDR_MASK;
writel(dcfg, hsotg->regs + DCFG);
dev_info(hsotg->dev, "new address %d\n", ctrl->wValue);
@@ -1458,7 +1290,7 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
int ptr;
dev_warn(hsotg->dev,
- "%s: FIFO %d bytes on ep%d but no req (DxEPCTl=0x%08x)\n",
+ "%s: FIFO %d bytes on ep%d but no req (DXEPCTl=0x%08x)\n",
__func__, size, ep_idx, epctl);
/* dump the data from the FIFO, we've nothing we can do */
@@ -1530,13 +1362,13 @@ static void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg,
dev_dbg(hsotg->dev, "sending zero-length packet\n");
/* issue a zero-sized packet to terminate this */
- writel(DxEPTSIZ_MC(1) | DxEPTSIZ_PktCnt(1) |
- DxEPTSIZ_XferSize(0), hsotg->regs + DIEPTSIZ(0));
+ writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
+ DXEPTSIZ_XFERSIZE(0), hsotg->regs + DIEPTSIZ(0));
ctrl = readl(hsotg->regs + DIEPCTL0);
- ctrl |= DxEPCTL_CNAK; /* clear NAK set by core */
- ctrl |= DxEPCTL_EPEna; /* ensure ep enabled */
- ctrl |= DxEPCTL_USBActEp;
+ ctrl |= DXEPCTL_CNAK; /* clear NAK set by core */
+ ctrl |= DXEPCTL_EPENA; /* ensure ep enabled */
+ ctrl |= DXEPCTL_USBACTEP;
writel(ctrl, hsotg->regs + DIEPCTL0);
}
@@ -1557,7 +1389,7 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep = &hsotg->eps[epnum];
struct s3c_hsotg_req *hs_req = hs_ep->req;
struct usb_request *req = &hs_req->req;
- unsigned size_left = DxEPTSIZ_XferSize_GET(epsize);
+ unsigned size_left = DXEPTSIZ_XFERSIZE_GET(epsize);
int result = 0;
if (!hs_req) {
@@ -1657,24 +1489,22 @@ static void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg)
WARN_ON(using_dma(hsotg));
- epnum = grxstsr & GRXSTS_EPNum_MASK;
- status = grxstsr & GRXSTS_PktSts_MASK;
+ epnum = grxstsr & GRXSTS_EPNUM_MASK;
+ status = grxstsr & GRXSTS_PKTSTS_MASK;
- size = grxstsr & GRXSTS_ByteCnt_MASK;
- size >>= GRXSTS_ByteCnt_SHIFT;
+ size = grxstsr & GRXSTS_BYTECNT_MASK;
+ size >>= GRXSTS_BYTECNT_SHIFT;
if (1)
dev_dbg(hsotg->dev, "%s: GRXSTSP=0x%08x (%d@%d)\n",
__func__, grxstsr, size, epnum);
-#define __status(x) ((x) >> GRXSTS_PktSts_SHIFT)
-
- switch (status >> GRXSTS_PktSts_SHIFT) {
- case __status(GRXSTS_PktSts_GlobalOutNAK):
- dev_dbg(hsotg->dev, "GlobalOutNAK\n");
+ switch ((status & GRXSTS_PKTSTS_MASK) >> GRXSTS_PKTSTS_SHIFT) {
+ case GRXSTS_PKTSTS_GLOBALOUTNAK:
+ dev_dbg(hsotg->dev, "GLOBALOUTNAK\n");
break;
- case __status(GRXSTS_PktSts_OutDone):
+ case GRXSTS_PKTSTS_OUTDONE:
dev_dbg(hsotg->dev, "OutDone (Frame=0x%08x)\n",
s3c_hsotg_read_frameno(hsotg));
@@ -1682,7 +1512,7 @@ static void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg)
s3c_hsotg_handle_outdone(hsotg, epnum, false);
break;
- case __status(GRXSTS_PktSts_SetupDone):
+ case GRXSTS_PKTSTS_SETUPDONE:
dev_dbg(hsotg->dev,
"SetupDone (Frame=0x%08x, DOPEPCTL=0x%08x)\n",
s3c_hsotg_read_frameno(hsotg),
@@ -1691,11 +1521,11 @@ static void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg)
s3c_hsotg_handle_outdone(hsotg, epnum, true);
break;
- case __status(GRXSTS_PktSts_OutRX):
+ case GRXSTS_PKTSTS_OUTRX:
s3c_hsotg_rx_data(hsotg, epnum, size);
break;
- case __status(GRXSTS_PktSts_SetupRX):
+ case GRXSTS_PKTSTS_SETUPRX:
dev_dbg(hsotg->dev,
"SetupRX (Frame=0x%08x, DOPEPCTL=0x%08x)\n",
s3c_hsotg_read_frameno(hsotg),
@@ -1761,7 +1591,7 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg,
hs_ep->ep.maxpacket = mps;
hs_ep->mc = 1;
} else {
- mpsval = mps & DxEPCTL_MPS_MASK;
+ mpsval = mps & DXEPCTL_MPS_MASK;
if (mpsval > 1024)
goto bad_mps;
mcval = ((mps >> 11) & 0x3) + 1;
@@ -1777,13 +1607,13 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg,
*/
reg = readl(regs + DIEPCTL(ep));
- reg &= ~DxEPCTL_MPS_MASK;
+ reg &= ~DXEPCTL_MPS_MASK;
reg |= mpsval;
writel(reg, regs + DIEPCTL(ep));
if (ep) {
reg = readl(regs + DOEPCTL(ep));
- reg &= ~DxEPCTL_MPS_MASK;
+ reg &= ~DXEPCTL_MPS_MASK;
reg |= mpsval;
writel(reg, regs + DOEPCTL(ep));
}
@@ -1804,7 +1634,7 @@ static void s3c_hsotg_txfifo_flush(struct s3c_hsotg *hsotg, unsigned int idx)
int timeout;
int val;
- writel(GRSTCTL_TxFNum(idx) | GRSTCTL_TxFFlsh,
+ writel(GRSTCTL_TXFNUM(idx) | GRSTCTL_TXFFLSH,
hsotg->regs + GRSTCTL);
/* wait until the fifo is flushed */
@@ -1813,7 +1643,7 @@ static void s3c_hsotg_txfifo_flush(struct s3c_hsotg *hsotg, unsigned int idx)
while (1) {
val = readl(hsotg->regs + GRSTCTL);
- if ((val & (GRSTCTL_TxFFlsh)) == 0)
+ if ((val & (GRSTCTL_TXFFLSH)) == 0)
break;
if (--timeout == 0) {
@@ -1896,7 +1726,7 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg,
* aligned).
*/
- size_left = DxEPTSIZ_XferSize_GET(epsize);
+ size_left = DXEPTSIZ_XFERSIZE_GET(epsize);
size_done = hs_ep->size_loaded - size_left;
size_done += hs_ep->last_load;
@@ -1963,17 +1793,17 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
dev_dbg(hsotg->dev, "%s: ep%d(%s) DxEPINT=0x%08x\n",
__func__, idx, dir_in ? "in" : "out", ints);
- if (ints & DxEPINT_XferCompl) {
+ if (ints & DXEPINT_XFERCOMPL) {
if (hs_ep->isochronous && hs_ep->interval == 1) {
- if (ctrl & DxEPCTL_EOFrNum)
- ctrl |= DxEPCTL_SetEvenFr;
+ if (ctrl & DXEPCTL_EOFRNUM)
+ ctrl |= DXEPCTL_SETEVENFR;
else
- ctrl |= DxEPCTL_SetOddFr;
+ ctrl |= DXEPCTL_SETODDFR;
writel(ctrl, hsotg->regs + epctl_reg);
}
dev_dbg(hsotg->dev,
- "%s: XferCompl: DxEPCTL=0x%08x, DxEPTSIZ=%08x\n",
+ "%s: XferCompl: DxEPCTL=0x%08x, DXEPTSIZ=%08x\n",
__func__, readl(hsotg->regs + epctl_reg),
readl(hsotg->regs + epsiz_reg));
@@ -1996,7 +1826,7 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
}
}
- if (ints & DxEPINT_EPDisbld) {
+ if (ints & DXEPINT_EPDISBLD) {
dev_dbg(hsotg->dev, "%s: EPDisbld\n", __func__);
if (dir_in) {
@@ -2004,20 +1834,20 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
s3c_hsotg_txfifo_flush(hsotg, idx);
- if ((epctl & DxEPCTL_Stall) &&
- (epctl & DxEPCTL_EPType_Bulk)) {
+ if ((epctl & DXEPCTL_STALL) &&
+ (epctl & DXEPCTL_EPTYPE_BULK)) {
int dctl = readl(hsotg->regs + DCTL);
- dctl |= DCTL_CGNPInNAK;
+ dctl |= DCTL_CGNPINNAK;
writel(dctl, hsotg->regs + DCTL);
}
}
}
- if (ints & DxEPINT_AHBErr)
+ if (ints & DXEPINT_AHBERR)
dev_dbg(hsotg->dev, "%s: AHBErr\n", __func__);
- if (ints & DxEPINT_Setup) { /* Setup or Timeout */
+ if (ints & DXEPINT_SETUP) { /* Setup or Timeout */
dev_dbg(hsotg->dev, "%s: Setup/Timeout\n", __func__);
if (using_dma(hsotg) && idx == 0) {
@@ -2035,25 +1865,25 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
}
}
- if (ints & DxEPINT_Back2BackSetup)
+ if (ints & DXEPINT_BACK2BACKSETUP)
dev_dbg(hsotg->dev, "%s: B2BSetup/INEPNakEff\n", __func__);
if (dir_in && !hs_ep->isochronous) {
/* not sure if this is important, but we'll clear it anyway */
- if (ints & DIEPMSK_INTknTXFEmpMsk) {
+ if (ints & DIEPMSK_INTKNTXFEMPMSK) {
dev_dbg(hsotg->dev, "%s: ep%d: INTknTXFEmpMsk\n",
__func__, idx);
}
/* this probably means something bad is happening */
- if (ints & DIEPMSK_INTknEPMisMsk) {
+ if (ints & DIEPMSK_INTKNEPMISMSK) {
dev_warn(hsotg->dev, "%s: ep%d: INTknEP\n",
__func__, idx);
}
/* FIFO has space or is empty (see GAHBCFG) */
if (hsotg->dedicated_fifos &&
- ints & DIEPMSK_TxFIFOEmpty) {
+ ints & DIEPMSK_TXFIFOEMPTY) {
dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n",
__func__, idx);
if (!using_dma(hsotg))
@@ -2089,21 +1919,21 @@ static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg)
*/
/* catch both EnumSpd_FS and EnumSpd_FS48 */
- switch (dsts & DSTS_EnumSpd_MASK) {
- case DSTS_EnumSpd_FS:
- case DSTS_EnumSpd_FS48:
+ switch (dsts & DSTS_ENUMSPD_MASK) {
+ case DSTS_ENUMSPD_FS:
+ case DSTS_ENUMSPD_FS48:
hsotg->gadget.speed = USB_SPEED_FULL;
ep0_mps = EP0_MPS_LIMIT;
ep_mps = 1023;
break;
- case DSTS_EnumSpd_HS:
+ case DSTS_ENUMSPD_HS:
hsotg->gadget.speed = USB_SPEED_HIGH;
ep0_mps = EP0_MPS_LIMIT;
ep_mps = 1024;
break;
- case DSTS_EnumSpd_LS:
+ case DSTS_ENUMSPD_LS:
hsotg->gadget.speed = USB_SPEED_LOW;
/*
* note, we don't actually support LS in this driver at the
@@ -2169,16 +1999,6 @@ static void kill_all_requests(struct s3c_hsotg *hsotg,
s3c_hsotg_txfifo_flush(hsotg, ep->index);
}
-#define call_gadget(_hs, _entry) \
-do { \
- if ((_hs)->gadget.speed != USB_SPEED_UNKNOWN && \
- (_hs)->driver && (_hs)->driver->_entry) { \
- spin_unlock(&_hs->lock); \
- (_hs)->driver->_entry(&(_hs)->gadget); \
- spin_lock(&_hs->lock); \
- } \
-} while (0)
-
/**
* s3c_hsotg_disconnect - disconnect service
* @hsotg: The device state.
@@ -2226,9 +2046,9 @@ static void s3c_hsotg_irq_fifoempty(struct s3c_hsotg *hsotg, bool periodic)
}
/* IRQ flags which will trigger a retry around the IRQ loop */
-#define IRQ_RETRY_MASK (GINTSTS_NPTxFEmp | \
- GINTSTS_PTxFEmp | \
- GINTSTS_RxFLvl)
+#define IRQ_RETRY_MASK (GINTSTS_NPTXFEMP | \
+ GINTSTS_PTXFEMP | \
+ GINTSTS_RXFLVL)
/**
* s3c_hsotg_corereset - issue softreset to the core
@@ -2244,14 +2064,14 @@ static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg)
dev_dbg(hsotg->dev, "resetting core\n");
/* issue soft reset */
- writel(GRSTCTL_CSftRst, hsotg->regs + GRSTCTL);
+ writel(GRSTCTL_CSFTRST, hsotg->regs + GRSTCTL);
timeout = 10000;
do {
grstctl = readl(hsotg->regs + GRSTCTL);
- } while ((grstctl & GRSTCTL_CSftRst) && timeout-- > 0);
+ } while ((grstctl & GRSTCTL_CSFTRST) && timeout-- > 0);
- if (grstctl & GRSTCTL_CSftRst) {
+ if (grstctl & GRSTCTL_CSFTRST) {
dev_err(hsotg->dev, "Failed to get CSftRst asserted\n");
return -EINVAL;
}
@@ -2268,7 +2088,7 @@ static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg)
return -ETIMEDOUT;
}
- if (!(grstctl & GRSTCTL_AHBIdle))
+ if (!(grstctl & GRSTCTL_AHBIDLE))
continue;
break; /* reset done */
@@ -2294,14 +2114,14 @@ static void s3c_hsotg_core_init(struct s3c_hsotg *hsotg)
*/
/* set the PLL on, remove the HNP/SRP and set the PHY */
- writel(hsotg->phyif | GUSBCFG_TOutCal(7) |
+ writel(hsotg->phyif | GUSBCFG_TOUTCAL(7) |
(0x5 << 10), hsotg->regs + GUSBCFG);
s3c_hsotg_init_fifo(hsotg);
- __orr32(hsotg->regs + DCTL, DCTL_SftDiscon);
+ __orr32(hsotg->regs + DCTL, DCTL_SFTDISCON);
- writel(1 << 18 | DCFG_DevSpd_HS, hsotg->regs + DCFG);
+ writel(1 << 18 | DCFG_DEVSPD_HS, hsotg->regs + DCFG);
/* Clear any pending OTG interrupts */
writel(0xffffffff, hsotg->regs + GOTGINT);
@@ -2309,21 +2129,21 @@ static void s3c_hsotg_core_init(struct s3c_hsotg *hsotg)
/* Clear any pending interrupts */
writel(0xffffffff, hsotg->regs + GINTSTS);
- writel(GINTSTS_ErlySusp | GINTSTS_SessReqInt |
- GINTSTS_GOUTNakEff | GINTSTS_GINNakEff |
- GINTSTS_ConIDStsChng | GINTSTS_USBRst |
- GINTSTS_EnumDone | GINTSTS_OTGInt |
- GINTSTS_USBSusp | GINTSTS_WkUpInt,
- hsotg->regs + GINTMSK);
+ writel(GINTSTS_ERLYSUSP | GINTSTS_SESSREQINT |
+ GINTSTS_GOUTNAKEFF | GINTSTS_GINNAKEFF |
+ GINTSTS_CONIDSTSCHNG | GINTSTS_USBRST |
+ GINTSTS_ENUMDONE | GINTSTS_OTGINT |
+ GINTSTS_USBSUSP | GINTSTS_WKUPINT,
+ hsotg->regs + GINTMSK);
if (using_dma(hsotg))
- writel(GAHBCFG_GlblIntrEn | GAHBCFG_DMAEn |
- GAHBCFG_HBstLen_Incr4,
+ writel(GAHBCFG_GLBL_INTR_EN | GAHBCFG_DMA_EN |
+ GAHBCFG_HBSTLEN_INCR4,
hsotg->regs + GAHBCFG);
else
- writel(((hsotg->dedicated_fifos) ? (GAHBCFG_NPTxFEmpLvl |
- GAHBCFG_PTxFEmpLvl) : 0) |
- GAHBCFG_GlblIntrEn,
+ writel(((hsotg->dedicated_fifos) ? (GAHBCFG_NP_TXF_EMP_LVL |
+ GAHBCFG_P_TXF_EMP_LVL) : 0) |
+ GAHBCFG_GLBL_INTR_EN,
hsotg->regs + GAHBCFG);
/*
@@ -2332,22 +2152,22 @@ static void s3c_hsotg_core_init(struct s3c_hsotg *hsotg)
* interrupts.
*/
- writel(((hsotg->dedicated_fifos) ? DIEPMSK_TxFIFOEmpty |
- DIEPMSK_INTknTXFEmpMsk : 0) |
- DIEPMSK_EPDisbldMsk | DIEPMSK_XferComplMsk |
- DIEPMSK_TimeOUTMsk | DIEPMSK_AHBErrMsk |
- DIEPMSK_INTknEPMisMsk,
- hsotg->regs + DIEPMSK);
+ writel(((hsotg->dedicated_fifos) ? DIEPMSK_TXFIFOEMPTY |
+ DIEPMSK_INTKNTXFEMPMSK : 0) |
+ DIEPMSK_EPDISBLDMSK | DIEPMSK_XFERCOMPLMSK |
+ DIEPMSK_TIMEOUTMSK | DIEPMSK_AHBERRMSK |
+ DIEPMSK_INTKNEPMISMSK,
+ hsotg->regs + DIEPMSK);
/*
* don't need XferCompl, we get that from RXFIFO in slave mode. In
* DMA mode we may need this.
*/
- writel((using_dma(hsotg) ? (DIEPMSK_XferComplMsk |
- DIEPMSK_TimeOUTMsk) : 0) |
- DOEPMSK_EPDisbldMsk | DOEPMSK_AHBErrMsk |
- DOEPMSK_SetupMsk,
- hsotg->regs + DOEPMSK);
+ writel((using_dma(hsotg) ? (DIEPMSK_XFERCOMPLMSK |
+ DIEPMSK_TIMEOUTMSK) : 0) |
+ DOEPMSK_EPDISBLDMSK | DOEPMSK_AHBERRMSK |
+ DOEPMSK_SETUPMSK,
+ hsotg->regs + DOEPMSK);
writel(0, hsotg->regs + DAINTMSK);
@@ -2356,7 +2176,7 @@ static void s3c_hsotg_core_init(struct s3c_hsotg *hsotg)
readl(hsotg->regs + DOEPCTL0));
/* enable in and out endpoint interrupts */
- s3c_hsotg_en_gsint(hsotg, GINTSTS_OEPInt | GINTSTS_IEPInt);
+ s3c_hsotg_en_gsint(hsotg, GINTSTS_OEPINT | GINTSTS_IEPINT);
/*
* Enable the RXFIFO when in slave mode, as this is how we collect
@@ -2364,15 +2184,15 @@ static void s3c_hsotg_core_init(struct s3c_hsotg *hsotg)
* things we cannot process, so do not use it.
*/
if (!using_dma(hsotg))
- s3c_hsotg_en_gsint(hsotg, GINTSTS_RxFLvl);
+ s3c_hsotg_en_gsint(hsotg, GINTSTS_RXFLVL);
/* Enable interrupts for EP0 in and out */
s3c_hsotg_ctrl_epint(hsotg, 0, 0, 1);
s3c_hsotg_ctrl_epint(hsotg, 0, 1, 1);
- __orr32(hsotg->regs + DCTL, DCTL_PWROnPrgDone);
+ __orr32(hsotg->regs + DCTL, DCTL_PWRONPRGDONE);
udelay(10); /* see openiboot */
- __bic32(hsotg->regs + DCTL, DCTL_PWROnPrgDone);
+ __bic32(hsotg->regs + DCTL, DCTL_PWRONPRGDONE);
dev_dbg(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + DCTL));
@@ -2382,17 +2202,17 @@ static void s3c_hsotg_core_init(struct s3c_hsotg *hsotg)
*/
/* set to read 1 8byte packet */
- writel(DxEPTSIZ_MC(1) | DxEPTSIZ_PktCnt(1) |
- DxEPTSIZ_XferSize(8), hsotg->regs + DOEPTSIZ0);
+ writel(DXEPTSIZ_MC(1) | DXEPTSIZ_PKTCNT(1) |
+ DXEPTSIZ_XFERSIZE(8), hsotg->regs + DOEPTSIZ0);
writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) |
- DxEPCTL_CNAK | DxEPCTL_EPEna |
- DxEPCTL_USBActEp,
+ DXEPCTL_CNAK | DXEPCTL_EPENA |
+ DXEPCTL_USBACTEP,
hsotg->regs + DOEPCTL0);
/* enable, but don't activate EP0in */
writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) |
- DxEPCTL_USBActEp, hsotg->regs + DIEPCTL0);
+ DXEPCTL_USBACTEP, hsotg->regs + DIEPCTL0);
s3c_hsotg_enqueue_setup(hsotg);
@@ -2401,14 +2221,14 @@ static void s3c_hsotg_core_init(struct s3c_hsotg *hsotg)
readl(hsotg->regs + DOEPCTL0));
/* clear global NAKs */
- writel(DCTL_CGOUTNak | DCTL_CGNPInNAK,
+ writel(DCTL_CGOUTNAK | DCTL_CGNPINNAK,
hsotg->regs + DCTL);
/* must be at-least 3ms to allow bus to see disconnect */
mdelay(3);
/* remove the soft-disconnect and let's go */
- __bic32(hsotg->regs + DCTL, DCTL_SftDiscon);
+ __bic32(hsotg->regs + DCTL, DCTL_SFTDISCON);
}
/**
@@ -2433,7 +2253,7 @@ irq_retry:
gintsts &= gintmsk;
- if (gintsts & GINTSTS_OTGInt) {
+ if (gintsts & GINTSTS_OTGINT) {
u32 otgint = readl(hsotg->regs + GOTGINT);
dev_info(hsotg->dev, "OTGInt: %08x\n", otgint);
@@ -2441,34 +2261,34 @@ irq_retry:
writel(otgint, hsotg->regs + GOTGINT);
}
- if (gintsts & GINTSTS_SessReqInt) {
+ if (gintsts & GINTSTS_SESSREQINT) {
dev_dbg(hsotg->dev, "%s: SessReqInt\n", __func__);
- writel(GINTSTS_SessReqInt, hsotg->regs + GINTSTS);
+ writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
}
- if (gintsts & GINTSTS_EnumDone) {
- writel(GINTSTS_EnumDone, hsotg->regs + GINTSTS);
+ if (gintsts & GINTSTS_ENUMDONE) {
+ writel(GINTSTS_ENUMDONE, hsotg->regs + GINTSTS);
s3c_hsotg_irq_enumdone(hsotg);
}
- if (gintsts & GINTSTS_ConIDStsChng) {
+ if (gintsts & GINTSTS_CONIDSTSCHNG) {
dev_dbg(hsotg->dev, "ConIDStsChg (DSTS=0x%08x, GOTCTL=%08x)\n",
readl(hsotg->regs + DSTS),
readl(hsotg->regs + GOTGCTL));
- writel(GINTSTS_ConIDStsChng, hsotg->regs + GINTSTS);
+ writel(GINTSTS_CONIDSTSCHNG, hsotg->regs + GINTSTS);
}
- if (gintsts & (GINTSTS_OEPInt | GINTSTS_IEPInt)) {
+ if (gintsts & (GINTSTS_OEPINT | GINTSTS_IEPINT)) {
u32 daint = readl(hsotg->regs + DAINT);
u32 daintmsk = readl(hsotg->regs + DAINTMSK);
u32 daint_out, daint_in;
int ep;
daint &= daintmsk;
- daint_out = daint >> DAINT_OutEP_SHIFT;
- daint_in = daint & ~(daint_out << DAINT_OutEP_SHIFT);
+ daint_out = daint >> DAINT_OUTEP_SHIFT;
+ daint_in = daint & ~(daint_out << DAINT_OUTEP_SHIFT);
dev_dbg(hsotg->dev, "%s: daint=%08x\n", __func__, daint);
@@ -2483,7 +2303,7 @@ irq_retry:
}
}
- if (gintsts & GINTSTS_USBRst) {
+ if (gintsts & GINTSTS_USBRST) {
u32 usb_status = readl(hsotg->regs + GOTGCTL);
@@ -2491,7 +2311,7 @@ irq_retry:
dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
readl(hsotg->regs + GNPTXSTS));
- writel(GINTSTS_USBRst, hsotg->regs + GINTSTS);
+ writel(GINTSTS_USBRST, hsotg->regs + GINTSTS);
if (usb_status & GOTGCTL_BSESVLD) {
if (time_after(jiffies, hsotg->last_rst +
@@ -2508,7 +2328,7 @@ irq_retry:
/* check both FIFOs */
- if (gintsts & GINTSTS_NPTxFEmp) {
+ if (gintsts & GINTSTS_NPTXFEMP) {
dev_dbg(hsotg->dev, "NPTxFEmp\n");
/*
@@ -2517,20 +2337,20 @@ irq_retry:
* it needs re-enabling
*/
- s3c_hsotg_disable_gsint(hsotg, GINTSTS_NPTxFEmp);
+ s3c_hsotg_disable_gsint(hsotg, GINTSTS_NPTXFEMP);
s3c_hsotg_irq_fifoempty(hsotg, false);
}
- if (gintsts & GINTSTS_PTxFEmp) {
+ if (gintsts & GINTSTS_PTXFEMP) {
dev_dbg(hsotg->dev, "PTxFEmp\n");
/* See note in GINTSTS_NPTxFEmp */
- s3c_hsotg_disable_gsint(hsotg, GINTSTS_PTxFEmp);
+ s3c_hsotg_disable_gsint(hsotg, GINTSTS_PTXFEMP);
s3c_hsotg_irq_fifoempty(hsotg, true);
}
- if (gintsts & GINTSTS_RxFLvl) {
+ if (gintsts & GINTSTS_RXFLVL) {
/*
* note, since GINTSTS_RxFLvl doubles as FIFO-not-empty,
* we need to retry s3c_hsotg_handle_rx if this is still
@@ -2540,28 +2360,28 @@ irq_retry:
s3c_hsotg_handle_rx(hsotg);
}
- if (gintsts & GINTSTS_ModeMis) {
+ if (gintsts & GINTSTS_MODEMIS) {
dev_warn(hsotg->dev, "warning, mode mismatch triggered\n");
- writel(GINTSTS_ModeMis, hsotg->regs + GINTSTS);
+ writel(GINTSTS_MODEMIS, hsotg->regs + GINTSTS);
}
- if (gintsts & GINTSTS_USBSusp) {
+ if (gintsts & GINTSTS_USBSUSP) {
dev_info(hsotg->dev, "GINTSTS_USBSusp\n");
- writel(GINTSTS_USBSusp, hsotg->regs + GINTSTS);
+ writel(GINTSTS_USBSUSP, hsotg->regs + GINTSTS);
call_gadget(hsotg, suspend);
}
- if (gintsts & GINTSTS_WkUpInt) {
+ if (gintsts & GINTSTS_WKUPINT) {
dev_info(hsotg->dev, "GINTSTS_WkUpIn\n");
- writel(GINTSTS_WkUpInt, hsotg->regs + GINTSTS);
+ writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS);
call_gadget(hsotg, resume);
}
- if (gintsts & GINTSTS_ErlySusp) {
+ if (gintsts & GINTSTS_ERLYSUSP) {
dev_dbg(hsotg->dev, "GINTSTS_ErlySusp\n");
- writel(GINTSTS_ErlySusp, hsotg->regs + GINTSTS);
+ writel(GINTSTS_ERLYSUSP, hsotg->regs + GINTSTS);
}
/*
@@ -2570,18 +2390,18 @@ irq_retry:
* the occurrence.
*/
- if (gintsts & GINTSTS_GOUTNakEff) {
+ if (gintsts & GINTSTS_GOUTNAKEFF) {
dev_info(hsotg->dev, "GOUTNakEff triggered\n");
- writel(DCTL_CGOUTNak, hsotg->regs + DCTL);
+ writel(DCTL_CGOUTNAK, hsotg->regs + DCTL);
s3c_hsotg_dump(hsotg);
}
- if (gintsts & GINTSTS_GINNakEff) {
+ if (gintsts & GINTSTS_GINNAKEFF) {
dev_info(hsotg->dev, "GINNakEff triggered\n");
- writel(DCTL_CGNPInNAK, hsotg->regs + DCTL);
+ writel(DCTL_CGNPINNAK, hsotg->regs + DCTL);
s3c_hsotg_dump(hsotg);
}
@@ -2645,14 +2465,14 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
spin_lock_irqsave(&hsotg->lock, flags);
- epctrl &= ~(DxEPCTL_EPType_MASK | DxEPCTL_MPS_MASK);
- epctrl |= DxEPCTL_MPS(mps);
+ epctrl &= ~(DXEPCTL_EPTYPE_MASK | DXEPCTL_MPS_MASK);
+ epctrl |= DXEPCTL_MPS(mps);
/*
* mark the endpoint as active, otherwise the core may ignore
* transactions entirely for this endpoint
*/
- epctrl |= DxEPCTL_USBActEp;
+ epctrl |= DXEPCTL_USBACTEP;
/*
* set the NAK status on the endpoint, otherwise we might try and
@@ -2661,7 +2481,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
* size register hasn't been set.
*/
- epctrl |= DxEPCTL_SNAK;
+ epctrl |= DXEPCTL_SNAK;
/* update the endpoint state */
s3c_hsotg_set_ep_maxpacket(hsotg, hs_ep->index, mps);
@@ -2677,15 +2497,15 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
case USB_ENDPOINT_XFER_ISOC:
- epctrl |= DxEPCTL_EPType_Iso;
- epctrl |= DxEPCTL_SetEvenFr;
+ epctrl |= DXEPCTL_EPTYPE_ISO;
+ epctrl |= DXEPCTL_SETEVENFR;
hs_ep->isochronous = 1;
if (dir_in)
hs_ep->periodic = 1;
break;
case USB_ENDPOINT_XFER_BULK:
- epctrl |= DxEPCTL_EPType_Bulk;
+ epctrl |= DXEPCTL_EPTYPE_BULK;
break;
case USB_ENDPOINT_XFER_INT:
@@ -2698,14 +2518,14 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
*/
hs_ep->periodic = 1;
- epctrl |= DxEPCTL_TxFNum(index);
+ epctrl |= DXEPCTL_TXFNUM(index);
}
- epctrl |= DxEPCTL_EPType_Intterupt;
+ epctrl |= DXEPCTL_EPTYPE_INTERRUPT;
break;
case USB_ENDPOINT_XFER_CONTROL:
- epctrl |= DxEPCTL_EPType_Control;
+ epctrl |= DXEPCTL_EPTYPE_CONTROL;
break;
}
@@ -2714,11 +2534,11 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
* a unique tx-fifo even if it is non-periodic.
*/
if (dir_in && hsotg->dedicated_fifos)
- epctrl |= DxEPCTL_TxFNum(index);
+ epctrl |= DXEPCTL_TXFNUM(index);
/* for non control endpoints, set PID to D0 */
if (index)
- epctrl |= DxEPCTL_SetD0PID;
+ epctrl |= DXEPCTL_SETD0PID;
dev_dbg(hsotg->dev, "%s: write DxEPCTL=0x%08x\n",
__func__, epctrl);
@@ -2763,9 +2583,9 @@ static int s3c_hsotg_ep_disable(struct usb_ep *ep)
ctrl = readl(hsotg->regs + epctrl_reg);
- ctrl &= ~DxEPCTL_EPEna;
- ctrl &= ~DxEPCTL_USBActEp;
- ctrl |= DxEPCTL_SNAK;
+ ctrl &= ~DXEPCTL_EPENA;
+ ctrl &= ~DXEPCTL_USBACTEP;
+ ctrl |= DXEPCTL_SNAK;
dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl);
writel(ctrl, hsotg->regs + epctrl_reg);
@@ -2852,15 +2672,15 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
epctl = readl(hs->regs + epreg);
if (value) {
- epctl |= DxEPCTL_Stall + DxEPCTL_SNAK;
- if (epctl & DxEPCTL_EPEna)
- epctl |= DxEPCTL_EPDis;
+ epctl |= DXEPCTL_STALL + DXEPCTL_SNAK;
+ if (epctl & DXEPCTL_EPENA)
+ epctl |= DXEPCTL_EPDIS;
} else {
- epctl &= ~DxEPCTL_Stall;
- xfertype = epctl & DxEPCTL_EPType_MASK;
- if (xfertype == DxEPCTL_EPType_Bulk ||
- xfertype == DxEPCTL_EPType_Intterupt)
- epctl |= DxEPCTL_SetD0PID;
+ epctl &= ~DXEPCTL_STALL;
+ xfertype = epctl & DXEPCTL_EPTYPE_MASK;
+ if (xfertype == DXEPCTL_EPTYPE_BULK ||
+ xfertype == DXEPCTL_EPTYPE_INTERRUPT)
+ epctl |= DXEPCTL_SETD0PID;
}
writel(epctl, hs->regs + epreg);
@@ -2869,13 +2689,13 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
epctl = readl(hs->regs + epreg);
if (value)
- epctl |= DxEPCTL_Stall;
+ epctl |= DXEPCTL_STALL;
else {
- epctl &= ~DxEPCTL_Stall;
- xfertype = epctl & DxEPCTL_EPType_MASK;
- if (xfertype == DxEPCTL_EPType_Bulk ||
- xfertype == DxEPCTL_EPType_Intterupt)
- epctl |= DxEPCTL_SetD0PID;
+ epctl &= ~DXEPCTL_STALL;
+ xfertype = epctl & DXEPCTL_EPTYPE_MASK;
+ if (xfertype == DXEPCTL_EPTYPE_BULK ||
+ xfertype == DXEPCTL_EPTYPE_INTERRUPT)
+ epctl |= DXEPCTL_SETD0PID;
}
writel(epctl, hs->regs + epreg);
@@ -2965,22 +2785,22 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
{
/* unmask subset of endpoint interrupts */
- writel(DIEPMSK_TimeOUTMsk | DIEPMSK_AHBErrMsk |
- DIEPMSK_EPDisbldMsk | DIEPMSK_XferComplMsk,
- hsotg->regs + DIEPMSK);
+ writel(DIEPMSK_TIMEOUTMSK | DIEPMSK_AHBERRMSK |
+ DIEPMSK_EPDISBLDMSK | DIEPMSK_XFERCOMPLMSK,
+ hsotg->regs + DIEPMSK);
- writel(DOEPMSK_SetupMsk | DOEPMSK_AHBErrMsk |
- DOEPMSK_EPDisbldMsk | DOEPMSK_XferComplMsk,
- hsotg->regs + DOEPMSK);
+ writel(DOEPMSK_SETUPMSK | DOEPMSK_AHBERRMSK |
+ DOEPMSK_EPDISBLDMSK | DOEPMSK_XFERCOMPLMSK,
+ hsotg->regs + DOEPMSK);
writel(0, hsotg->regs + DAINTMSK);
/* Be in disconnected state until gadget is registered */
- __orr32(hsotg->regs + DCTL, DCTL_SftDiscon);
+ __orr32(hsotg->regs + DCTL, DCTL_SFTDISCON);
if (0) {
/* post global nak until we're ready */
- writel(DCTL_SGNPInNAK | DCTL_SGOUTNak,
+ writel(DCTL_SGNPINNAK | DCTL_SGOUTNAK,
hsotg->regs + DCTL);
}
@@ -2993,10 +2813,10 @@ static void s3c_hsotg_init(struct s3c_hsotg *hsotg)
s3c_hsotg_init_fifo(hsotg);
/* set the PLL on, remove the HNP/SRP and set the PHY */
- writel(GUSBCFG_PHYIf16 | GUSBCFG_TOutCal(7) | (0x5 << 10),
+ writel(GUSBCFG_PHYIF16 | GUSBCFG_TOUTCAL(7) | (0x5 << 10),
hsotg->regs + GUSBCFG);
- writel(using_dma(hsotg) ? GAHBCFG_DMAEn : 0x0,
+ writel(using_dma(hsotg) ? GAHBCFG_DMA_EN : 0x0,
hsotg->regs + GAHBCFG);
}
@@ -3187,8 +3007,8 @@ static void s3c_hsotg_initep(struct s3c_hsotg *hsotg,
* code is changed to make each endpoint's direction changeable.
*/
- ptxfifo = readl(hsotg->regs + DPTXFSIZn(epnum));
- hs_ep->fifo_size = DPTXFSIZn_DPTxFSize_GET(ptxfifo) * 4;
+ ptxfifo = readl(hsotg->regs + DPTXFSIZN(epnum));
+ hs_ep->fifo_size = FIFOSIZE_DEPTH_GET(ptxfifo) * 4;
/*
* if we're using dma, we need to set the next-endpoint pointer
@@ -3196,7 +3016,7 @@ static void s3c_hsotg_initep(struct s3c_hsotg *hsotg,
*/
if (using_dma(hsotg)) {
- u32 next = DxEPCTL_NextEp((epnum + 1) % 15);
+ u32 next = DXEPCTL_NEXTEP((epnum + 1) % 15);
writel(next, hsotg->regs + DIEPCTL(epnum));
writel(next, hsotg->regs + DOEPCTL(epnum));
}
@@ -3250,10 +3070,10 @@ static void s3c_hsotg_dump(struct s3c_hsotg *hsotg)
/* show periodic fifo settings */
for (idx = 1; idx <= 15; idx++) {
- val = readl(regs + DPTXFSIZn(idx));
+ val = readl(regs + DPTXFSIZN(idx));
dev_info(dev, "DPTx[%d] FSize=%d, StAddr=0x%08x\n", idx,
- val >> DPTXFSIZn_DPTxFSize_SHIFT,
- val & DPTXFSIZn_DPTxFStAddr_MASK);
+ val >> FIFOSIZE_DEPTH_SHIFT,
+ val & FIFOSIZE_STARTADDR_MASK);
}
for (idx = 0; idx < 15; idx++) {
@@ -3368,17 +3188,17 @@ static int fifo_show(struct seq_file *seq, void *v)
val = readl(regs + GNPTXFSIZ);
seq_printf(seq, "NPTXFIFO: Size %d, Start 0x%08x\n",
- val >> GNPTXFSIZ_NPTxFDep_SHIFT,
- val & GNPTXFSIZ_NPTxFStAddr_MASK);
+ val >> FIFOSIZE_DEPTH_SHIFT,
+ val & FIFOSIZE_DEPTH_MASK);
seq_puts(seq, "\nPeriodic TXFIFOs:\n");
for (idx = 1; idx <= 15; idx++) {
- val = readl(regs + DPTXFSIZn(idx));
+ val = readl(regs + DPTXFSIZN(idx));
seq_printf(seq, "\tDPTXFIFO%2d: Size %d, Start 0x%08x\n", idx,
- val >> DPTXFSIZn_DPTxFSize_SHIFT,
- val & DPTXFSIZn_DPTxFStAddr_MASK);
+ val >> FIFOSIZE_DEPTH_SHIFT,
+ val & FIFOSIZE_STARTADDR_MASK);
}
return 0;
@@ -3662,14 +3482,14 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
}
/* Set default UTMI width */
- hsotg->phyif = GUSBCFG_PHYIf16;
+ hsotg->phyif = GUSBCFG_PHYIF16;
/*
* If using the generic PHY framework, check if the PHY bus
* width is 8-bit and set the phyif appropriately.
*/
if (hsotg->phy && (phy_get_bus_width(phy) == 8))
- hsotg->phyif = GUSBCFG_PHYIf8;
+ hsotg->phyif = GUSBCFG_PHYIF8;
if (hsotg->phy)
phy_init(hsotg->phy);
diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h
index 9c92a3c7588a..51248b935493 100644
--- a/drivers/usb/dwc2/hw.h
+++ b/drivers/usb/dwc2/hw.h
@@ -109,6 +109,7 @@
#define GUSBCFG_FSINTF (1 << 5)
#define GUSBCFG_ULPI_UTMI_SEL (1 << 4)
#define GUSBCFG_PHYIF16 (1 << 3)
+#define GUSBCFG_PHYIF8 (0 << 3)
#define GUSBCFG_TOUTCAL_MASK (0x7 << 0)
#define GUSBCFG_TOUTCAL_SHIFT 0
#define GUSBCFG_TOUTCAL_LIMIT 0x7
@@ -403,6 +404,7 @@
#define FIFOSIZE_DEPTH_SHIFT 16
#define FIFOSIZE_STARTADDR_MASK (0xffff << 0)
#define FIFOSIZE_STARTADDR_SHIFT 0
+#define FIFOSIZE_DEPTH_GET(_x) (((_x) >> 16) & 0xffff)
/* Device mode registers */
@@ -519,11 +521,11 @@
#define DXEPCTL_STALL (1 << 21)
#define DXEPCTL_SNP (1 << 20)
#define DXEPCTL_EPTYPE_MASK (0x3 << 18)
-#define DXEPCTL_EPTYPE_SHIFT 18
-#define DXEPCTL_EPTYPE_CONTROL 0
-#define DXEPCTL_EPTYPE_ISO 1
-#define DXEPCTL_EPTYPE_BULK 2
-#define DXEPCTL_EPTYPE_INTTERUPT 3
+#define DXEPCTL_EPTYPE_CONTROL (0x0 << 18)
+#define DXEPCTL_EPTYPE_ISO (0x1 << 18)
+#define DXEPCTL_EPTYPE_BULK (0x2 << 18)
+#define DXEPCTL_EPTYPE_INTERRUPT (0x3 << 18)
+
#define DXEPCTL_NAKSTS (1 << 17)
#define DXEPCTL_DPID (1 << 16)
#define DXEPCTL_EOFRNUM (1 << 16)
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index eaba547ce26b..a10e7a353576 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -134,6 +134,12 @@ static int dwc2_driver_probe(struct platform_device *dev)
/* Default all params to autodetect */
dwc2_set_all_params(&defparams, -1);
params = &defparams;
+
+ /*
+ * Disable descriptor dma mode by default as the HW can support
+ * it, but does not support it for SPLIT transactions.
+ */
+ defparams.dma_desc_enable = 0;
}
hsotg = devm_kzalloc(&dev->dev, sizeof(*hsotg), GFP_KERNEL);
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index e2c730fc9a90..8eb996e4f058 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -44,7 +44,7 @@ comment "Platform Glue Driver Support"
config USB_DWC3_OMAP
tristate "Texas Instruments OMAP5 and similar Platforms"
- depends on EXTCON
+ depends on EXTCON && (ARCH_OMAP2PLUS || COMPILE_TEST)
default USB_DWC3
help
Some platforms from Texas Instruments like OMAP5, DRA7xxx and
@@ -54,6 +54,7 @@ config USB_DWC3_OMAP
config USB_DWC3_EXYNOS
tristate "Samsung Exynos Platform"
+ depends on ARCH_EXYNOS || COMPILE_TEST
default USB_DWC3
help
Recent Exynos5 SoCs ship with one DesignWare Core USB3 IP inside,
@@ -72,6 +73,7 @@ config USB_DWC3_PCI
config USB_DWC3_KEYSTONE
tristate "Texas Instruments Keystone2 Platforms"
+ depends on ARCH_KEYSTONE || COMPILE_TEST
default USB_DWC3
help
Support of USB2/3 functionality in TI Keystone2 platforms.
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 10aaaae9af25..eb69eb9f06c8 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -486,70 +486,20 @@ static void dwc3_core_exit(struct dwc3 *dwc)
phy_exit(dwc->usb3_generic_phy);
}
-#define DWC3_ALIGN_MASK (16 - 1)
-
-static int dwc3_probe(struct platform_device *pdev)
+static int dwc3_core_get_phy(struct dwc3 *dwc)
{
- struct device *dev = &pdev->dev;
- struct dwc3_platform_data *pdata = dev_get_platdata(dev);
+ struct device *dev = dwc->dev;
struct device_node *node = dev->of_node;
- struct resource *res;
- struct dwc3 *dwc;
-
- int ret = -ENOMEM;
-
- void __iomem *regs;
- void *mem;
-
- mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
- if (!mem) {
- dev_err(dev, "not enough memory\n");
- return -ENOMEM;
- }
- dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
- dwc->mem = mem;
-
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!res) {
- dev_err(dev, "missing IRQ\n");
- return -ENODEV;
- }
- dwc->xhci_resources[1].start = res->start;
- dwc->xhci_resources[1].end = res->end;
- dwc->xhci_resources[1].flags = res->flags;
- dwc->xhci_resources[1].name = res->name;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(dev, "missing memory resource\n");
- return -ENODEV;
- }
+ int ret;
if (node) {
- dwc->maximum_speed = of_usb_get_maximum_speed(node);
-
dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
-
- dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
- dwc->dr_mode = of_usb_get_dr_mode(node);
- } else if (pdata) {
- dwc->maximum_speed = pdata->maximum_speed;
-
- dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
- dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
-
- dwc->needs_fifo_resize = pdata->tx_fifo_resize;
- dwc->dr_mode = pdata->dr_mode;
} else {
dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
}
- /* default to superspeed if no maximum_speed passed */
- if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
- dwc->maximum_speed = USB_SPEED_SUPER;
-
if (IS_ERR(dwc->usb2_phy)) {
ret = PTR_ERR(dwc->usb2_phy);
if (ret == -ENXIO || ret == -ENODEV) {
@@ -600,6 +550,132 @@ static int dwc3_probe(struct platform_device *pdev)
}
}
+ return 0;
+}
+
+static int dwc3_core_init_mode(struct dwc3 *dwc)
+{
+ struct device *dev = dwc->dev;
+ int ret;
+
+ switch (dwc->dr_mode) {
+ case USB_DR_MODE_PERIPHERAL:
+ dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
+ ret = dwc3_gadget_init(dwc);
+ if (ret) {
+ dev_err(dev, "failed to initialize gadget\n");
+ return ret;
+ }
+ break;
+ case USB_DR_MODE_HOST:
+ dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
+ ret = dwc3_host_init(dwc);
+ if (ret) {
+ dev_err(dev, "failed to initialize host\n");
+ return ret;
+ }
+ break;
+ case USB_DR_MODE_OTG:
+ dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
+ ret = dwc3_host_init(dwc);
+ if (ret) {
+ dev_err(dev, "failed to initialize host\n");
+ return ret;
+ }
+
+ ret = dwc3_gadget_init(dwc);
+ if (ret) {
+ dev_err(dev, "failed to initialize gadget\n");
+ return ret;
+ }
+ break;
+ default:
+ dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void dwc3_core_exit_mode(struct dwc3 *dwc)
+{
+ switch (dwc->dr_mode) {
+ case USB_DR_MODE_PERIPHERAL:
+ dwc3_gadget_exit(dwc);
+ break;
+ case USB_DR_MODE_HOST:
+ dwc3_host_exit(dwc);
+ break;
+ case USB_DR_MODE_OTG:
+ dwc3_host_exit(dwc);
+ dwc3_gadget_exit(dwc);
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+}
+
+#define DWC3_ALIGN_MASK (16 - 1)
+
+static int dwc3_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct dwc3_platform_data *pdata = dev_get_platdata(dev);
+ struct device_node *node = dev->of_node;
+ struct resource *res;
+ struct dwc3 *dwc;
+
+ int ret;
+
+ void __iomem *regs;
+ void *mem;
+
+ mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL);
+ if (!mem) {
+ dev_err(dev, "not enough memory\n");
+ return -ENOMEM;
+ }
+ dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
+ dwc->mem = mem;
+ dwc->dev = dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev_err(dev, "missing IRQ\n");
+ return -ENODEV;
+ }
+ dwc->xhci_resources[1].start = res->start;
+ dwc->xhci_resources[1].end = res->end;
+ dwc->xhci_resources[1].flags = res->flags;
+ dwc->xhci_resources[1].name = res->name;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(dev, "missing memory resource\n");
+ return -ENODEV;
+ }
+
+ if (node) {
+ dwc->maximum_speed = of_usb_get_maximum_speed(node);
+
+ dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
+ dwc->dr_mode = of_usb_get_dr_mode(node);
+ } else if (pdata) {
+ dwc->maximum_speed = pdata->maximum_speed;
+
+ dwc->needs_fifo_resize = pdata->tx_fifo_resize;
+ dwc->dr_mode = pdata->dr_mode;
+ }
+
+ /* default to superspeed if no maximum_speed passed */
+ if (dwc->maximum_speed == USB_SPEED_UNKNOWN)
+ dwc->maximum_speed = USB_SPEED_SUPER;
+
+ ret = dwc3_core_get_phy(dwc);
+ if (ret)
+ return ret;
+
dwc->xhci_resources[0].start = res->start;
dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
DWC3_XHCI_REGS_END;
@@ -621,7 +697,6 @@ static int dwc3_probe(struct platform_device *pdev)
dwc->regs = regs;
dwc->regs_size = resource_size(res);
- dwc->dev = dev;
dev->dma_mask = dev->parent->dma_mask;
dev->dma_parms = dev->parent->dma_parms;
@@ -670,41 +745,9 @@ static int dwc3_probe(struct platform_device *pdev)
goto err_usb3phy_power;
}
- switch (dwc->dr_mode) {
- case USB_DR_MODE_PERIPHERAL:
- dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
- ret = dwc3_gadget_init(dwc);
- if (ret) {
- dev_err(dev, "failed to initialize gadget\n");
- goto err2;
- }
- break;
- case USB_DR_MODE_HOST:
- dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST);
- ret = dwc3_host_init(dwc);
- if (ret) {
- dev_err(dev, "failed to initialize host\n");
- goto err2;
- }
- break;
- case USB_DR_MODE_OTG:
- dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
- ret = dwc3_host_init(dwc);
- if (ret) {
- dev_err(dev, "failed to initialize host\n");
- goto err2;
- }
-
- ret = dwc3_gadget_init(dwc);
- if (ret) {
- dev_err(dev, "failed to initialize gadget\n");
- goto err2;
- }
- break;
- default:
- dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode);
+ ret = dwc3_core_init_mode(dwc);
+ if (ret)
goto err2;
- }
ret = dwc3_debugfs_init(dwc);
if (ret) {
@@ -717,21 +760,7 @@ static int dwc3_probe(struct platform_device *pdev)
return 0;
err3:
- switch (dwc->dr_mode) {
- case USB_DR_MODE_PERIPHERAL:
- dwc3_gadget_exit(dwc);
- break;
- case USB_DR_MODE_HOST:
- dwc3_host_exit(dwc);
- break;
- case USB_DR_MODE_OTG:
- dwc3_host_exit(dwc);
- dwc3_gadget_exit(dwc);
- break;
- default:
- /* do nothing */
- break;
- }
+ dwc3_core_exit_mode(dwc);
err2:
dwc3_event_buffers_cleanup(dwc);
@@ -766,23 +795,7 @@ static int dwc3_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
dwc3_debugfs_exit(dwc);
-
- switch (dwc->dr_mode) {
- case USB_DR_MODE_PERIPHERAL:
- dwc3_gadget_exit(dwc);
- break;
- case USB_DR_MODE_HOST:
- dwc3_host_exit(dwc);
- break;
- case USB_DR_MODE_OTG:
- dwc3_host_exit(dwc);
- dwc3_gadget_exit(dwc);
- break;
- default:
- /* do nothing */
- break;
- }
-
+ dwc3_core_exit_mode(dwc);
dwc3_event_buffers_cleanup(dwc);
dwc3_free_event_buffers(dwc);
dwc3_core_exit(dwc);
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index 28c8ad79f5e6..f9fb8adb785b 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -24,9 +24,10 @@
#include <linux/dma-mapping.h>
#include <linux/clk.h>
#include <linux/usb/otg.h>
-#include <linux/usb/usb_phy_gen_xceiv.h>
+#include <linux/usb/usb_phy_generic.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/regulator/consumer.h>
struct dwc3_exynos {
struct platform_device *usb2_phy;
@@ -34,17 +35,19 @@ struct dwc3_exynos {
struct device *dev;
struct clk *clk;
+ struct regulator *vdd33;
+ struct regulator *vdd10;
};
static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
{
- struct usb_phy_gen_xceiv_platform_data pdata;
+ struct usb_phy_generic_platform_data pdata;
struct platform_device *pdev;
int ret;
memset(&pdata, 0x00, sizeof(pdata));
- pdev = platform_device_alloc("usb_phy_gen_xceiv", PLATFORM_DEVID_AUTO);
+ pdev = platform_device_alloc("usb_phy_generic", PLATFORM_DEVID_AUTO);
if (!pdev)
return -ENOMEM;
@@ -56,7 +59,7 @@ static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos)
if (ret)
goto err1;
- pdev = platform_device_alloc("usb_phy_gen_xceiv", PLATFORM_DEVID_AUTO);
+ pdev = platform_device_alloc("usb_phy_generic", PLATFORM_DEVID_AUTO);
if (!pdev) {
ret = -ENOMEM;
goto err1;
@@ -107,12 +110,12 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
- int ret = -ENOMEM;
+ int ret;
exynos = devm_kzalloc(dev, sizeof(*exynos), GFP_KERNEL);
if (!exynos) {
dev_err(dev, "not enough memory\n");
- goto err1;
+ return -ENOMEM;
}
/*
@@ -122,21 +125,20 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
*/
ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
if (ret)
- goto err1;
+ return ret;
platform_set_drvdata(pdev, exynos);
ret = dwc3_exynos_register_phys(exynos);
if (ret) {
dev_err(dev, "couldn't register PHYs\n");
- goto err1;
+ return ret;
}
clk = devm_clk_get(dev, "usbdrd30");
if (IS_ERR(clk)) {
dev_err(dev, "couldn't get clock\n");
- ret = -EINVAL;
- goto err1;
+ return -EINVAL;
}
exynos->dev = dev;
@@ -144,23 +146,48 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
clk_prepare_enable(exynos->clk);
+ exynos->vdd33 = devm_regulator_get(dev, "vdd33");
+ if (IS_ERR(exynos->vdd33)) {
+ ret = PTR_ERR(exynos->vdd33);
+ goto err2;
+ }
+ ret = regulator_enable(exynos->vdd33);
+ if (ret) {
+ dev_err(dev, "Failed to enable VDD33 supply\n");
+ goto err2;
+ }
+
+ exynos->vdd10 = devm_regulator_get(dev, "vdd10");
+ if (IS_ERR(exynos->vdd10)) {
+ ret = PTR_ERR(exynos->vdd10);
+ goto err3;
+ }
+ ret = regulator_enable(exynos->vdd10);
+ if (ret) {
+ dev_err(dev, "Failed to enable VDD10 supply\n");
+ goto err3;
+ }
+
if (node) {
ret = of_platform_populate(node, NULL, NULL, dev);
if (ret) {
dev_err(dev, "failed to add dwc3 core\n");
- goto err2;
+ goto err4;
}
} else {
dev_err(dev, "no device node, failed to add dwc3 core\n");
ret = -ENODEV;
- goto err2;
+ goto err4;
}
return 0;
+err4:
+ regulator_disable(exynos->vdd10);
+err3:
+ regulator_disable(exynos->vdd33);
err2:
clk_disable_unprepare(clk);
-err1:
return ret;
}
@@ -174,6 +201,9 @@ static int dwc3_exynos_remove(struct platform_device *pdev)
clk_disable_unprepare(exynos->clk);
+ regulator_disable(exynos->vdd33);
+ regulator_disable(exynos->vdd10);
+
return 0;
}
@@ -192,12 +222,27 @@ static int dwc3_exynos_suspend(struct device *dev)
clk_disable(exynos->clk);
+ regulator_disable(exynos->vdd33);
+ regulator_disable(exynos->vdd10);
+
return 0;
}
static int dwc3_exynos_resume(struct device *dev)
{
struct dwc3_exynos *exynos = dev_get_drvdata(dev);
+ int ret;
+
+ ret = regulator_enable(exynos->vdd33);
+ if (ret) {
+ dev_err(dev, "Failed to enable VDD33 supply\n");
+ return ret;
+ }
+ ret = regulator_enable(exynos->vdd10);
+ if (ret) {
+ dev_err(dev, "Failed to enable VDD10 supply\n");
+ return ret;
+ }
clk_enable(exynos->clk);
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index 1160ff41bed4..4af4c3567656 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -393,7 +393,7 @@ static int dwc3_omap_probe(struct platform_device *pdev)
struct extcon_dev *edev;
struct regulator *vbus_reg = NULL;
- int ret = -ENOMEM;
+ int ret;
int irq;
int utmi_mode = 0;
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index f393c183cc69..a60bab7dfa0a 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -23,7 +23,7 @@
#include <linux/platform_device.h>
#include <linux/usb/otg.h>
-#include <linux/usb/usb_phy_gen_xceiv.h>
+#include <linux/usb/usb_phy_generic.h>
/* FIXME define these in <linux/pci_ids.h> */
#define PCI_VENDOR_ID_SYNOPSYS 0x16c3
@@ -40,13 +40,13 @@ struct dwc3_pci {
static int dwc3_pci_register_phys(struct dwc3_pci *glue)
{
- struct usb_phy_gen_xceiv_platform_data pdata;
+ struct usb_phy_generic_platform_data pdata;
struct platform_device *pdev;
int ret;
memset(&pdata, 0x00, sizeof(pdata));
- pdev = platform_device_alloc("usb_phy_gen_xceiv", 0);
+ pdev = platform_device_alloc("usb_phy_generic", 0);
if (!pdev)
return -ENOMEM;
@@ -58,7 +58,7 @@ static int dwc3_pci_register_phys(struct dwc3_pci *glue)
if (ret)
goto err1;
- pdev = platform_device_alloc("usb_phy_gen_xceiv", 1);
+ pdev = platform_device_alloc("usb_phy_generic", 1);
if (!pdev) {
ret = -ENOMEM;
goto err1;
@@ -99,7 +99,7 @@ static int dwc3_pci_probe(struct pci_dev *pci,
struct resource res[2];
struct platform_device *dwc3;
struct dwc3_pci *glue;
- int ret = -ENOMEM;
+ int ret;
struct device *dev = &pci->dev;
glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL);
@@ -110,7 +110,7 @@ static int dwc3_pci_probe(struct pci_dev *pci,
glue->dev = dev;
- ret = pci_enable_device(pci);
+ ret = pcim_enable_device(pci);
if (ret) {
dev_err(dev, "failed to enable pci device\n");
return -ENODEV;
@@ -127,8 +127,7 @@ static int dwc3_pci_probe(struct pci_dev *pci,
dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO);
if (!dwc3) {
dev_err(dev, "couldn't allocate dwc3 device\n");
- ret = -ENOMEM;
- goto err1;
+ return -ENOMEM;
}
memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res));
@@ -145,7 +144,7 @@ static int dwc3_pci_probe(struct pci_dev *pci,
ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res));
if (ret) {
dev_err(dev, "couldn't add resources to dwc3 device\n");
- goto err1;
+ return ret;
}
pci_set_drvdata(pci, glue);
@@ -167,9 +166,6 @@ static int dwc3_pci_probe(struct pci_dev *pci,
err3:
platform_device_put(dwc3);
-err1:
- pci_disable_device(pci);
-
return ret;
}
@@ -180,7 +176,6 @@ static void dwc3_pci_remove(struct pci_dev *pci)
platform_device_unregister(glue->dwc3);
platform_device_unregister(glue->usb2_phy);
platform_device_unregister(glue->usb3_phy);
- pci_disable_device(pci);
}
static const struct pci_device_id dwc3_pci_id_table[] = {
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 70715eeededd..9d64dd02c57e 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -298,11 +298,76 @@ static const char *dwc3_gadget_ep_cmd_string(u8 cmd)
}
}
+static const char *dwc3_gadget_generic_cmd_string(u8 cmd)
+{
+ switch (cmd) {
+ case DWC3_DGCMD_SET_LMP:
+ return "Set LMP";
+ case DWC3_DGCMD_SET_PERIODIC_PAR:
+ return "Set Periodic Parameters";
+ case DWC3_DGCMD_XMIT_FUNCTION:
+ return "Transmit Function Wake Device Notification";
+ case DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO:
+ return "Set Scratchpad Buffer Array Address Lo";
+ case DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI:
+ return "Set Scratchpad Buffer Array Address Hi";
+ case DWC3_DGCMD_SELECTED_FIFO_FLUSH:
+ return "Selected FIFO Flush";
+ case DWC3_DGCMD_ALL_FIFO_FLUSH:
+ return "All FIFO Flush";
+ case DWC3_DGCMD_SET_ENDPOINT_NRDY:
+ return "Set Endpoint NRDY";
+ case DWC3_DGCMD_RUN_SOC_BUS_LOOPBACK:
+ return "Run SoC Bus Loopback Test";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static const char *dwc3_gadget_link_string(enum dwc3_link_state link_state)
+{
+ switch (link_state) {
+ case DWC3_LINK_STATE_U0:
+ return "U0";
+ case DWC3_LINK_STATE_U1:
+ return "U1";
+ case DWC3_LINK_STATE_U2:
+ return "U2";
+ case DWC3_LINK_STATE_U3:
+ return "U3";
+ case DWC3_LINK_STATE_SS_DIS:
+ return "SS.Disabled";
+ case DWC3_LINK_STATE_RX_DET:
+ return "RX.Detect";
+ case DWC3_LINK_STATE_SS_INACT:
+ return "SS.Inactive";
+ case DWC3_LINK_STATE_POLL:
+ return "Polling";
+ case DWC3_LINK_STATE_RECOV:
+ return "Recovery";
+ case DWC3_LINK_STATE_HRESET:
+ return "Hot Reset";
+ case DWC3_LINK_STATE_CMPLY:
+ return "Compliance";
+ case DWC3_LINK_STATE_LPBK:
+ return "Loopback";
+ case DWC3_LINK_STATE_RESET:
+ return "Reset";
+ case DWC3_LINK_STATE_RESUME:
+ return "Resume";
+ default:
+ return "UNKNOWN link state\n";
+ }
+}
+
int dwc3_send_gadget_generic_command(struct dwc3 *dwc, int cmd, u32 param)
{
u32 timeout = 500;
u32 reg;
+ dev_vdbg(dwc->dev, "generic cmd '%s' [%d] param %08x\n",
+ dwc3_gadget_generic_cmd_string(cmd), cmd, param);
+
dwc3_writel(dwc->regs, DWC3_DGCMDPAR, param);
dwc3_writel(dwc->regs, DWC3_DGCMD, cmd | DWC3_DGCMD_CMDACT);
@@ -332,9 +397,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep,
u32 timeout = 500;
u32 reg;
- dev_vdbg(dwc->dev, "%s: cmd '%s' params %08x %08x %08x\n",
+ dev_vdbg(dwc->dev, "%s: cmd '%s' [%d] params %08x %08x %08x\n",
dep->name,
- dwc3_gadget_ep_cmd_string(cmd), params->param0,
+ dwc3_gadget_ep_cmd_string(cmd), cmd, params->param0,
params->param1, params->param2);
dwc3_writel(dwc->regs, DWC3_DEPCMDPAR0(ep), params->param0);
@@ -515,7 +580,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
{
struct dwc3 *dwc = dep->dwc;
u32 reg;
- int ret = -ENOMEM;
+ int ret;
dev_vdbg(dwc->dev, "Enabling %s\n", dep->name);
@@ -604,6 +669,10 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
dwc3_remove_requests(dwc, dep);
+ /* make sure HW endpoint isn't stalled */
+ if (dep->flags & DWC3_EP_STALL)
+ __dwc3_gadget_ep_set_halt(dep, 0);
+
reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
reg &= ~DWC3_DALEPENA_EP(dep->number);
dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
@@ -2441,8 +2510,6 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
}
}
- dwc->link_state = next;
-
switch (next) {
case DWC3_LINK_STATE_U1:
if (dwc->speed == USB_SPEED_SUPER)
@@ -2460,7 +2527,11 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc,
break;
}
- dev_vdbg(dwc->dev, "%s link %d\n", __func__, dwc->link_state);
+ dev_vdbg(dwc->dev, "link change: %s [%d] -> %s [%d]\n",
+ dwc3_gadget_link_string(dwc->link_state),
+ dwc->link_state, dwc3_gadget_link_string(next), next);
+
+ dwc->link_state = next;
}
static void dwc3_gadget_hibernation_interrupt(struct dwc3 *dwc,
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 3557c7e5040d..ba18e9c110cc 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -157,7 +157,7 @@ config USB_AT91
config USB_LPC32XX
tristate "LPC32XX USB Peripheral Controller"
- depends on ARCH_LPC32XX
+ depends on ARCH_LPC32XX && I2C
select USB_ISP1301
help
This option selects the USB device controller in the LPC32xx SoC.
@@ -226,7 +226,7 @@ config USB_GR_UDC
config USB_OMAP
tristate "OMAP USB Device Controller"
depends on ARCH_OMAP1
- select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
+ depends on ISP1301_OMAP || !(MACH_OMAP_H2 || MACH_OMAP_H3)
help
Many Texas Instruments OMAP processors have flexible full
speed USB device controllers, with support for up to 30
@@ -300,12 +300,6 @@ config USB_PXA27X
dynamically linked module called "pxa27x_udc" and force all
gadget drivers to also be dynamically linked.
-config USB_S3C_HSOTG
- tristate "Designware/S3C HS/OtG USB Device controller"
- help
- The Designware USB2.0 high-speed gadget controller
- integrated into many SoCs.
-
config USB_S3C2410
tristate "S3C2410 USB Device Controller"
depends on ARCH_S3C24XX
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 5f150bc1b4bc..49514ea60a98 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -26,7 +26,6 @@ fsl_usb2_udc-$(CONFIG_ARCH_MXC) += fsl_mxc_udc.o
obj-$(CONFIG_USB_M66592) += m66592-udc.o
obj-$(CONFIG_USB_R8A66597) += r8a66597-udc.o
obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o
-obj-$(CONFIG_USB_S3C_HSOTG) += s3c-hsotg.o
obj-$(CONFIG_USB_S3C_HSUDC) += s3c-hsudc.o
obj-$(CONFIG_USB_LPC32XX) += lpc32xx_udc.o
obj-$(CONFIG_USB_EG20T) += pch_udc.o
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c
index 9f65324f9ae0..76023ce449a3 100644
--- a/drivers/usb/gadget/atmel_usba_udc.c
+++ b/drivers/usb/gadget/atmel_usba_udc.c
@@ -1686,7 +1686,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
reset_all_endpoints(udc);
if (udc->gadget.speed != USB_SPEED_UNKNOWN
- && udc->driver->disconnect) {
+ && udc->driver && udc->driver->disconnect) {
udc->gadget.speed = USB_SPEED_UNKNOWN;
spin_unlock(&udc->lock);
udc->driver->disconnect(&udc->gadget);
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index fab906429b80..f80151932053 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -21,6 +21,24 @@
#include <linux/usb/composite.h>
#include <asm/unaligned.h>
+#include "u_os_desc.h"
+
+/**
+ * struct usb_os_string - represents OS String to be reported by a gadget
+ * @bLength: total length of the entire descritor, always 0x12
+ * @bDescriptorType: USB_DT_STRING
+ * @qwSignature: the OS String proper
+ * @bMS_VendorCode: code used by the host for subsequent requests
+ * @bPad: not used, must be zero
+ */
+struct usb_os_string {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 qwSignature[OS_STRING_QW_SIGN_LEN];
+ __u8 bMS_VendorCode;
+ __u8 bPad;
+} __packed;
+
/*
* The code in this file is utility code, used to build a gadget driver
* from one or more "function" drivers, one or more "configuration"
@@ -422,6 +440,7 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
{
struct usb_gadget *gadget = cdev->gadget;
struct usb_configuration *c;
+ struct list_head *pos;
u8 type = w_value >> 8;
enum usb_device_speed speed = USB_SPEED_UNKNOWN;
@@ -440,7 +459,20 @@ static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
/* This is a lookup by config *INDEX* */
w_value &= 0xff;
- list_for_each_entry(c, &cdev->configs, list) {
+
+ pos = &cdev->configs;
+ c = cdev->os_desc_config;
+ if (c)
+ goto check_config;
+
+ while ((pos = pos->next) != &cdev->configs) {
+ c = list_entry(pos, typeof(*c), list);
+
+ /* skip OS Descriptors config which is handled separately */
+ if (c == cdev->os_desc_config)
+ continue;
+
+check_config:
/* ignore configs that won't work at this speed */
switch (speed) {
case USB_SPEED_SUPER:
@@ -634,6 +666,7 @@ static int set_config(struct usb_composite_dev *cdev,
if (!c)
goto done;
+ usb_gadget_set_state(gadget, USB_STATE_CONFIGURED);
cdev->config = c;
/* Initialize all interfaces by setting them to altsetting zero. */
@@ -960,6 +993,19 @@ static int get_string(struct usb_composite_dev *cdev,
return s->bLength;
}
+ if (cdev->use_os_string && language == 0 && id == OS_STRING_IDX) {
+ struct usb_os_string *b = buf;
+ b->bLength = sizeof(*b);
+ b->bDescriptorType = USB_DT_STRING;
+ compiletime_assert(
+ sizeof(b->qwSignature) == sizeof(cdev->qw_sign),
+ "qwSignature size must be equal to qw_sign");
+ memcpy(&b->qwSignature, cdev->qw_sign, sizeof(b->qwSignature));
+ b->bMS_VendorCode = cdev->b_vendor_code;
+ b->bPad = 0;
+ return sizeof(*b);
+ }
+
list_for_each_entry(uc, &cdev->gstrings, list) {
struct usb_gadget_strings **sp;
@@ -1206,6 +1252,156 @@ static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req)
req->status, req->actual, req->length);
}
+static int count_ext_compat(struct usb_configuration *c)
+{
+ int i, res;
+
+ res = 0;
+ for (i = 0; i < c->next_interface_id; ++i) {
+ struct usb_function *f;
+ int j;
+
+ f = c->interface[i];
+ for (j = 0; j < f->os_desc_n; ++j) {
+ struct usb_os_desc *d;
+
+ if (i != f->os_desc_table[j].if_id)
+ continue;
+ d = f->os_desc_table[j].os_desc;
+ if (d && d->ext_compat_id)
+ ++res;
+ }
+ }
+ BUG_ON(res > 255);
+ return res;
+}
+
+static void fill_ext_compat(struct usb_configuration *c, u8 *buf)
+{
+ int i, count;
+
+ count = 16;
+ for (i = 0; i < c->next_interface_id; ++i) {
+ struct usb_function *f;
+ int j;
+
+ f = c->interface[i];
+ for (j = 0; j < f->os_desc_n; ++j) {
+ struct usb_os_desc *d;
+
+ if (i != f->os_desc_table[j].if_id)
+ continue;
+ d = f->os_desc_table[j].os_desc;
+ if (d && d->ext_compat_id) {
+ *buf++ = i;
+ *buf++ = 0x01;
+ memcpy(buf, d->ext_compat_id, 16);
+ buf += 22;
+ } else {
+ ++buf;
+ *buf = 0x01;
+ buf += 23;
+ }
+ count += 24;
+ if (count >= 4096)
+ return;
+ }
+ }
+}
+
+static int count_ext_prop(struct usb_configuration *c, int interface)
+{
+ struct usb_function *f;
+ int j;
+
+ f = c->interface[interface];
+ for (j = 0; j < f->os_desc_n; ++j) {
+ struct usb_os_desc *d;
+
+ if (interface != f->os_desc_table[j].if_id)
+ continue;
+ d = f->os_desc_table[j].os_desc;
+ if (d && d->ext_compat_id)
+ return d->ext_prop_count;
+ }
+ return 0;
+}
+
+static int len_ext_prop(struct usb_configuration *c, int interface)
+{
+ struct usb_function *f;
+ struct usb_os_desc *d;
+ int j, res;
+
+ res = 10; /* header length */
+ f = c->interface[interface];
+ for (j = 0; j < f->os_desc_n; ++j) {
+ if (interface != f->os_desc_table[j].if_id)
+ continue;
+ d = f->os_desc_table[j].os_desc;
+ if (d)
+ return min(res + d->ext_prop_len, 4096);
+ }
+ return res;
+}
+
+static int fill_ext_prop(struct usb_configuration *c, int interface, u8 *buf)
+{
+ struct usb_function *f;
+ struct usb_os_desc *d;
+ struct usb_os_desc_ext_prop *ext_prop;
+ int j, count, n, ret;
+ u8 *start = buf;
+
+ f = c->interface[interface];
+ for (j = 0; j < f->os_desc_n; ++j) {
+ if (interface != f->os_desc_table[j].if_id)
+ continue;
+ d = f->os_desc_table[j].os_desc;
+ if (d)
+ list_for_each_entry(ext_prop, &d->ext_prop, entry) {
+ /* 4kB minus header length */
+ n = buf - start;
+ if (n >= 4086)
+ return 0;
+
+ count = ext_prop->data_len +
+ ext_prop->name_len + 14;
+ if (count > 4086 - n)
+ return -EINVAL;
+ usb_ext_prop_put_size(buf, count);
+ usb_ext_prop_put_type(buf, ext_prop->type);
+ ret = usb_ext_prop_put_name(buf, ext_prop->name,
+ ext_prop->name_len);
+ if (ret < 0)
+ return ret;
+ switch (ext_prop->type) {
+ case USB_EXT_PROP_UNICODE:
+ case USB_EXT_PROP_UNICODE_ENV:
+ case USB_EXT_PROP_UNICODE_LINK:
+ usb_ext_prop_put_unicode(buf, ret,
+ ext_prop->data,
+ ext_prop->data_len);
+ break;
+ case USB_EXT_PROP_BINARY:
+ usb_ext_prop_put_binary(buf, ret,
+ ext_prop->data,
+ ext_prop->data_len);
+ break;
+ case USB_EXT_PROP_LE32:
+ /* not implemented */
+ case USB_EXT_PROP_BE32:
+ /* not implemented */
+ default:
+ return -EINVAL;
+ }
+ buf += count;
+ }
+ }
+
+ return 0;
+}
+
/*
* The setup() callback implements all the ep0 functionality that's
* not handled lower down, in hardware or the hardware driver(like
@@ -1415,6 +1611,91 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
break;
default:
unknown:
+ /*
+ * OS descriptors handling
+ */
+ if (cdev->use_os_string && cdev->os_desc_config &&
+ (ctrl->bRequest & USB_TYPE_VENDOR) &&
+ ctrl->bRequest == cdev->b_vendor_code) {
+ struct usb_request *req;
+ struct usb_configuration *os_desc_cfg;
+ u8 *buf;
+ int interface;
+ int count = 0;
+
+ req = cdev->os_desc_req;
+ req->complete = composite_setup_complete;
+ buf = req->buf;
+ os_desc_cfg = cdev->os_desc_config;
+ memset(buf, 0, w_length);
+ buf[5] = 0x01;
+ switch (ctrl->bRequestType & USB_RECIP_MASK) {
+ case USB_RECIP_DEVICE:
+ if (w_index != 0x4 || (w_value >> 8))
+ break;
+ buf[6] = w_index;
+ if (w_length == 0x10) {
+ /* Number of ext compat interfaces */
+ count = count_ext_compat(os_desc_cfg);
+ buf[8] = count;
+ count *= 24; /* 24 B/ext compat desc */
+ count += 16; /* header */
+ put_unaligned_le32(count, buf);
+ value = w_length;
+ } else {
+ /* "extended compatibility ID"s */
+ count = count_ext_compat(os_desc_cfg);
+ buf[8] = count;
+ count *= 24; /* 24 B/ext compat desc */
+ count += 16; /* header */
+ put_unaligned_le32(count, buf);
+ buf += 16;
+ fill_ext_compat(os_desc_cfg, buf);
+ value = w_length;
+ }
+ break;
+ case USB_RECIP_INTERFACE:
+ if (w_index != 0x5 || (w_value >> 8))
+ break;
+ interface = w_value & 0xFF;
+ buf[6] = w_index;
+ if (w_length == 0x0A) {
+ count = count_ext_prop(os_desc_cfg,
+ interface);
+ put_unaligned_le16(count, buf + 8);
+ count = len_ext_prop(os_desc_cfg,
+ interface);
+ put_unaligned_le32(count, buf);
+
+ value = w_length;
+ } else {
+ count = count_ext_prop(os_desc_cfg,
+ interface);
+ put_unaligned_le16(count, buf + 8);
+ count = len_ext_prop(os_desc_cfg,
+ interface);
+ put_unaligned_le32(count, buf);
+ buf += 10;
+ value = fill_ext_prop(os_desc_cfg,
+ interface, buf);
+ if (value < 0)
+ return value;
+
+ value = w_length;
+ }
+ break;
+ }
+ req->length = value;
+ req->zero = value < w_length;
+ value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
+ if (value < 0) {
+ DBG(cdev, "ep_queue --> %d\n", value);
+ req->status = 0;
+ composite_setup_complete(gadget->ep0, req);
+ }
+ return value;
+ }
+
VDBG(cdev,
"non-core control req%02x.%02x v%04x i%04x l%d\n",
ctrl->bRequestType, ctrl->bRequest,
@@ -1638,6 +1919,29 @@ fail:
return ret;
}
+int composite_os_desc_req_prepare(struct usb_composite_dev *cdev,
+ struct usb_ep *ep0)
+{
+ int ret = 0;
+
+ cdev->os_desc_req = usb_ep_alloc_request(ep0, GFP_KERNEL);
+ if (!cdev->os_desc_req) {
+ ret = PTR_ERR(cdev->os_desc_req);
+ goto end;
+ }
+
+ /* OS feature descriptor length <= 4kB */
+ cdev->os_desc_req->buf = kmalloc(4096, GFP_KERNEL);
+ if (!cdev->os_desc_req->buf) {
+ ret = PTR_ERR(cdev->os_desc_req->buf);
+ kfree(cdev->os_desc_req);
+ goto end;
+ }
+ cdev->os_desc_req->complete = composite_setup_complete;
+end:
+ return ret;
+}
+
void composite_dev_cleanup(struct usb_composite_dev *cdev)
{
struct usb_gadget_string_container *uc, *tmp;
@@ -1646,6 +1950,10 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev)
list_del(&uc->list);
kfree(uc);
}
+ if (cdev->os_desc_req) {
+ kfree(cdev->os_desc_req->buf);
+ usb_ep_free_request(cdev->gadget->ep0, cdev->os_desc_req);
+ }
if (cdev->req) {
kfree(cdev->req->buf);
usb_ep_free_request(cdev->gadget->ep0, cdev->req);
@@ -1683,6 +1991,12 @@ static int composite_bind(struct usb_gadget *gadget,
if (status < 0)
goto fail;
+ if (cdev->use_os_string) {
+ status = composite_os_desc_req_prepare(cdev, gadget->ep0);
+ if (status)
+ goto fail;
+ }
+
update_unchanged_dev_desc(&cdev->desc, composite->dev);
/* has userspace failed to provide a serial number? */
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 7d1cc01796b6..2ddcd635ca2a 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -2,9 +2,12 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/device.h>
+#include <linux/nls.h>
#include <linux/usb/composite.h>
#include <linux/usb/gadget_configfs.h>
#include "configfs.h"
+#include "u_f.h"
+#include "u_os_desc.h"
int check_user_usb_string(const char *name,
struct usb_gadget_strings *stringtab_dev)
@@ -43,7 +46,8 @@ struct gadget_info {
struct config_group functions_group;
struct config_group configs_group;
struct config_group strings_group;
- struct config_group *default_groups[4];
+ struct config_group os_desc_group;
+ struct config_group *default_groups[5];
struct mutex lock;
struct usb_gadget_strings *gstrings[MAX_USB_STRING_LANGS + 1];
@@ -56,6 +60,9 @@ struct gadget_info {
#endif
struct usb_composite_driver composite;
struct usb_composite_dev cdev;
+ bool use_os_desc;
+ char b_vendor_code;
+ char qw_sign[OS_STRING_QW_SIGN_LEN];
};
struct config_usb_cfg {
@@ -79,6 +86,10 @@ struct gadget_strings {
struct list_head list;
};
+struct os_desc {
+ struct config_group group;
+};
+
struct gadget_config_name {
struct usb_gadget_strings stringtab_dev;
struct usb_string strings;
@@ -736,6 +747,525 @@ static void gadget_strings_attr_release(struct config_item *item)
USB_CONFIG_STRING_RW_OPS(gadget_strings);
USB_CONFIG_STRINGS_LANG(gadget_strings, gadget_info);
+static inline struct os_desc *to_os_desc(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct os_desc, group);
+}
+
+CONFIGFS_ATTR_STRUCT(os_desc);
+CONFIGFS_ATTR_OPS(os_desc);
+
+static ssize_t os_desc_use_show(struct os_desc *os_desc, char *page)
+{
+ struct gadget_info *gi;
+
+ gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
+
+ return sprintf(page, "%d", gi->use_os_desc);
+}
+
+static ssize_t os_desc_use_store(struct os_desc *os_desc, const char *page,
+ size_t len)
+{
+ struct gadget_info *gi;
+ int ret;
+ bool use;
+
+ gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
+
+ mutex_lock(&gi->lock);
+ ret = strtobool(page, &use);
+ if (!ret) {
+ gi->use_os_desc = use;
+ ret = len;
+ }
+ mutex_unlock(&gi->lock);
+
+ return ret;
+}
+
+static struct os_desc_attribute os_desc_use =
+ __CONFIGFS_ATTR(use, S_IRUGO | S_IWUSR,
+ os_desc_use_show,
+ os_desc_use_store);
+
+static ssize_t os_desc_b_vendor_code_show(struct os_desc *os_desc, char *page)
+{
+ struct gadget_info *gi;
+
+ gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
+
+ return sprintf(page, "%d", gi->b_vendor_code);
+}
+
+static ssize_t os_desc_b_vendor_code_store(struct os_desc *os_desc,
+ const char *page, size_t len)
+{
+ struct gadget_info *gi;
+ int ret;
+ u8 b_vendor_code;
+
+ gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
+
+ mutex_lock(&gi->lock);
+ ret = kstrtou8(page, 0, &b_vendor_code);
+ if (!ret) {
+ gi->b_vendor_code = b_vendor_code;
+ ret = len;
+ }
+ mutex_unlock(&gi->lock);
+
+ return ret;
+}
+
+static struct os_desc_attribute os_desc_b_vendor_code =
+ __CONFIGFS_ATTR(b_vendor_code, S_IRUGO | S_IWUSR,
+ os_desc_b_vendor_code_show,
+ os_desc_b_vendor_code_store);
+
+static ssize_t os_desc_qw_sign_show(struct os_desc *os_desc, char *page)
+{
+ struct gadget_info *gi;
+
+ gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
+
+ memcpy(page, gi->qw_sign, OS_STRING_QW_SIGN_LEN);
+
+ return OS_STRING_QW_SIGN_LEN;
+}
+
+static ssize_t os_desc_qw_sign_store(struct os_desc *os_desc, const char *page,
+ size_t len)
+{
+ struct gadget_info *gi;
+ int res, l;
+
+ gi = to_gadget_info(os_desc->group.cg_item.ci_parent);
+ l = min((int)len, OS_STRING_QW_SIGN_LEN >> 1);
+ if (page[l - 1] == '\n')
+ --l;
+
+ mutex_lock(&gi->lock);
+ res = utf8s_to_utf16s(page, l,
+ UTF16_LITTLE_ENDIAN, (wchar_t *) gi->qw_sign,
+ OS_STRING_QW_SIGN_LEN);
+ if (res > 0)
+ res = len;
+ mutex_unlock(&gi->lock);
+
+ return res;
+}
+
+static struct os_desc_attribute os_desc_qw_sign =
+ __CONFIGFS_ATTR(qw_sign, S_IRUGO | S_IWUSR,
+ os_desc_qw_sign_show,
+ os_desc_qw_sign_store);
+
+static struct configfs_attribute *os_desc_attrs[] = {
+ &os_desc_use.attr,
+ &os_desc_b_vendor_code.attr,
+ &os_desc_qw_sign.attr,
+ NULL,
+};
+
+static void os_desc_attr_release(struct config_item *item)
+{
+ struct os_desc *os_desc = to_os_desc(item);
+ kfree(os_desc);
+}
+
+static int os_desc_link(struct config_item *os_desc_ci,
+ struct config_item *usb_cfg_ci)
+{
+ struct gadget_info *gi = container_of(to_config_group(os_desc_ci),
+ struct gadget_info, os_desc_group);
+ struct usb_composite_dev *cdev = &gi->cdev;
+ struct config_usb_cfg *c_target =
+ container_of(to_config_group(usb_cfg_ci),
+ struct config_usb_cfg, group);
+ struct usb_configuration *c;
+ int ret;
+
+ mutex_lock(&gi->lock);
+ list_for_each_entry(c, &cdev->configs, list) {
+ if (c == &c_target->c)
+ break;
+ }
+ if (c != &c_target->c) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (cdev->os_desc_config) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ cdev->os_desc_config = &c_target->c;
+ ret = 0;
+
+out:
+ mutex_unlock(&gi->lock);
+ return ret;
+}
+
+static int os_desc_unlink(struct config_item *os_desc_ci,
+ struct config_item *usb_cfg_ci)
+{
+ struct gadget_info *gi = container_of(to_config_group(os_desc_ci),
+ struct gadget_info, os_desc_group);
+ struct usb_composite_dev *cdev = &gi->cdev;
+
+ mutex_lock(&gi->lock);
+ if (gi->udc_name)
+ unregister_gadget(gi);
+ cdev->os_desc_config = NULL;
+ WARN_ON(gi->udc_name);
+ mutex_unlock(&gi->lock);
+ return 0;
+}
+
+static struct configfs_item_operations os_desc_ops = {
+ .release = os_desc_attr_release,
+ .show_attribute = os_desc_attr_show,
+ .store_attribute = os_desc_attr_store,
+ .allow_link = os_desc_link,
+ .drop_link = os_desc_unlink,
+};
+
+static struct config_item_type os_desc_type = {
+ .ct_item_ops = &os_desc_ops,
+ .ct_attrs = os_desc_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+CONFIGFS_ATTR_STRUCT(usb_os_desc);
+CONFIGFS_ATTR_OPS(usb_os_desc);
+
+
+static inline struct usb_os_desc_ext_prop
+*to_usb_os_desc_ext_prop(struct config_item *item)
+{
+ return container_of(item, struct usb_os_desc_ext_prop, item);
+}
+
+CONFIGFS_ATTR_STRUCT(usb_os_desc_ext_prop);
+CONFIGFS_ATTR_OPS(usb_os_desc_ext_prop);
+
+static ssize_t ext_prop_type_show(struct usb_os_desc_ext_prop *ext_prop,
+ char *page)
+{
+ return sprintf(page, "%d", ext_prop->type);
+}
+
+static ssize_t ext_prop_type_store(struct usb_os_desc_ext_prop *ext_prop,
+ const char *page, size_t len)
+{
+ struct usb_os_desc *desc = to_usb_os_desc(ext_prop->item.ci_parent);
+ u8 type;
+ int ret;
+
+ if (desc->opts_mutex)
+ mutex_lock(desc->opts_mutex);
+ ret = kstrtou8(page, 0, &type);
+ if (ret)
+ goto end;
+ if (type < USB_EXT_PROP_UNICODE || type > USB_EXT_PROP_UNICODE_MULTI) {
+ ret = -EINVAL;
+ goto end;
+ }
+
+ if ((ext_prop->type == USB_EXT_PROP_BINARY ||
+ ext_prop->type == USB_EXT_PROP_LE32 ||
+ ext_prop->type == USB_EXT_PROP_BE32) &&
+ (type == USB_EXT_PROP_UNICODE ||
+ type == USB_EXT_PROP_UNICODE_ENV ||
+ type == USB_EXT_PROP_UNICODE_LINK))
+ ext_prop->data_len <<= 1;
+ else if ((ext_prop->type == USB_EXT_PROP_UNICODE ||
+ ext_prop->type == USB_EXT_PROP_UNICODE_ENV ||
+ ext_prop->type == USB_EXT_PROP_UNICODE_LINK) &&
+ (type == USB_EXT_PROP_BINARY ||
+ type == USB_EXT_PROP_LE32 ||
+ type == USB_EXT_PROP_BE32))
+ ext_prop->data_len >>= 1;
+ ext_prop->type = type;
+ ret = len;
+
+end:
+ if (desc->opts_mutex)
+ mutex_unlock(desc->opts_mutex);
+ return ret;
+}
+
+static ssize_t ext_prop_data_show(struct usb_os_desc_ext_prop *ext_prop,
+ char *page)
+{
+ int len = ext_prop->data_len;
+
+ if (ext_prop->type == USB_EXT_PROP_UNICODE ||
+ ext_prop->type == USB_EXT_PROP_UNICODE_ENV ||
+ ext_prop->type == USB_EXT_PROP_UNICODE_LINK)
+ len >>= 1;
+ memcpy(page, ext_prop->data, len);
+
+ return len;
+}
+
+static ssize_t ext_prop_data_store(struct usb_os_desc_ext_prop *ext_prop,
+ const char *page, size_t len)
+{
+ struct usb_os_desc *desc = to_usb_os_desc(ext_prop->item.ci_parent);
+ char *new_data;
+ size_t ret_len = len;
+
+ if (page[len - 1] == '\n' || page[len - 1] == '\0')
+ --len;
+ new_data = kzalloc(len, GFP_KERNEL);
+ if (!new_data)
+ return -ENOMEM;
+
+ memcpy(new_data, page, len);
+
+ if (desc->opts_mutex)
+ mutex_lock(desc->opts_mutex);
+ kfree(ext_prop->data);
+ ext_prop->data = new_data;
+ desc->ext_prop_len -= ext_prop->data_len;
+ ext_prop->data_len = len;
+ desc->ext_prop_len += ext_prop->data_len;
+ if (ext_prop->type == USB_EXT_PROP_UNICODE ||
+ ext_prop->type == USB_EXT_PROP_UNICODE_ENV ||
+ ext_prop->type == USB_EXT_PROP_UNICODE_LINK) {
+ desc->ext_prop_len -= ext_prop->data_len;
+ ext_prop->data_len <<= 1;
+ ext_prop->data_len += 2;
+ desc->ext_prop_len += ext_prop->data_len;
+ }
+ if (desc->opts_mutex)
+ mutex_unlock(desc->opts_mutex);
+ return ret_len;
+}
+
+static struct usb_os_desc_ext_prop_attribute ext_prop_type =
+ __CONFIGFS_ATTR(type, S_IRUGO | S_IWUSR,
+ ext_prop_type_show, ext_prop_type_store);
+
+static struct usb_os_desc_ext_prop_attribute ext_prop_data =
+ __CONFIGFS_ATTR(data, S_IRUGO | S_IWUSR,
+ ext_prop_data_show, ext_prop_data_store);
+
+static struct configfs_attribute *ext_prop_attrs[] = {
+ &ext_prop_type.attr,
+ &ext_prop_data.attr,
+ NULL,
+};
+
+static void usb_os_desc_ext_prop_release(struct config_item *item)
+{
+ struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item);
+
+ kfree(ext_prop); /* frees a whole chunk */
+}
+
+static struct configfs_item_operations ext_prop_ops = {
+ .release = usb_os_desc_ext_prop_release,
+ .show_attribute = usb_os_desc_ext_prop_attr_show,
+ .store_attribute = usb_os_desc_ext_prop_attr_store,
+};
+
+static struct config_item *ext_prop_make(
+ struct config_group *group,
+ const char *name)
+{
+ struct usb_os_desc_ext_prop *ext_prop;
+ struct config_item_type *ext_prop_type;
+ struct usb_os_desc *desc;
+ char *vlabuf;
+
+ vla_group(data_chunk);
+ vla_item(data_chunk, struct usb_os_desc_ext_prop, ext_prop, 1);
+ vla_item(data_chunk, struct config_item_type, ext_prop_type, 1);
+
+ vlabuf = kzalloc(vla_group_size(data_chunk), GFP_KERNEL);
+ if (!vlabuf)
+ return ERR_PTR(-ENOMEM);
+
+ ext_prop = vla_ptr(vlabuf, data_chunk, ext_prop);
+ ext_prop_type = vla_ptr(vlabuf, data_chunk, ext_prop_type);
+
+ desc = container_of(group, struct usb_os_desc, group);
+ ext_prop_type->ct_item_ops = &ext_prop_ops;
+ ext_prop_type->ct_attrs = ext_prop_attrs;
+ ext_prop_type->ct_owner = desc->owner;
+
+ config_item_init_type_name(&ext_prop->item, name, ext_prop_type);
+
+ ext_prop->name = kstrdup(name, GFP_KERNEL);
+ if (!ext_prop->name) {
+ kfree(vlabuf);
+ return ERR_PTR(-ENOMEM);
+ }
+ desc->ext_prop_len += 14;
+ ext_prop->name_len = 2 * strlen(ext_prop->name) + 2;
+ if (desc->opts_mutex)
+ mutex_lock(desc->opts_mutex);
+ desc->ext_prop_len += ext_prop->name_len;
+ list_add_tail(&ext_prop->entry, &desc->ext_prop);
+ ++desc->ext_prop_count;
+ if (desc->opts_mutex)
+ mutex_unlock(desc->opts_mutex);
+
+ return &ext_prop->item;
+}
+
+static void ext_prop_drop(struct config_group *group, struct config_item *item)
+{
+ struct usb_os_desc_ext_prop *ext_prop = to_usb_os_desc_ext_prop(item);
+ struct usb_os_desc *desc = to_usb_os_desc(&group->cg_item);
+
+ if (desc->opts_mutex)
+ mutex_lock(desc->opts_mutex);
+ list_del(&ext_prop->entry);
+ --desc->ext_prop_count;
+ kfree(ext_prop->name);
+ desc->ext_prop_len -= (ext_prop->name_len + ext_prop->data_len + 14);
+ if (desc->opts_mutex)
+ mutex_unlock(desc->opts_mutex);
+ config_item_put(item);
+}
+
+static struct configfs_group_operations interf_grp_ops = {
+ .make_item = &ext_prop_make,
+ .drop_item = &ext_prop_drop,
+};
+
+static struct configfs_item_operations interf_item_ops = {
+ .show_attribute = usb_os_desc_attr_show,
+ .store_attribute = usb_os_desc_attr_store,
+};
+
+static ssize_t rndis_grp_compatible_id_show(struct usb_os_desc *desc,
+ char *page)
+{
+ memcpy(page, desc->ext_compat_id, 8);
+ return 8;
+}
+
+static ssize_t rndis_grp_compatible_id_store(struct usb_os_desc *desc,
+ const char *page, size_t len)
+{
+ int l;
+
+ l = min_t(int, 8, len);
+ if (page[l - 1] == '\n')
+ --l;
+ if (desc->opts_mutex)
+ mutex_lock(desc->opts_mutex);
+ memcpy(desc->ext_compat_id, page, l);
+ desc->ext_compat_id[l] = '\0';
+
+ if (desc->opts_mutex)
+ mutex_unlock(desc->opts_mutex);
+
+ return len;
+}
+
+static struct usb_os_desc_attribute rndis_grp_attr_compatible_id =
+ __CONFIGFS_ATTR(compatible_id, S_IRUGO | S_IWUSR,
+ rndis_grp_compatible_id_show,
+ rndis_grp_compatible_id_store);
+
+static ssize_t rndis_grp_sub_compatible_id_show(struct usb_os_desc *desc,
+ char *page)
+{
+ memcpy(page, desc->ext_compat_id + 8, 8);
+ return 8;
+}
+
+static ssize_t rndis_grp_sub_compatible_id_store(struct usb_os_desc *desc,
+ const char *page, size_t len)
+{
+ int l;
+
+ l = min_t(int, 8, len);
+ if (page[l - 1] == '\n')
+ --l;
+ if (desc->opts_mutex)
+ mutex_lock(desc->opts_mutex);
+ memcpy(desc->ext_compat_id + 8, page, l);
+ desc->ext_compat_id[l + 8] = '\0';
+
+ if (desc->opts_mutex)
+ mutex_unlock(desc->opts_mutex);
+
+ return len;
+}
+
+static struct usb_os_desc_attribute rndis_grp_attr_sub_compatible_id =
+ __CONFIGFS_ATTR(sub_compatible_id, S_IRUGO | S_IWUSR,
+ rndis_grp_sub_compatible_id_show,
+ rndis_grp_sub_compatible_id_store);
+
+static struct configfs_attribute *interf_grp_attrs[] = {
+ &rndis_grp_attr_compatible_id.attr,
+ &rndis_grp_attr_sub_compatible_id.attr,
+ NULL
+};
+
+int usb_os_desc_prepare_interf_dir(struct config_group *parent,
+ int n_interf,
+ struct usb_os_desc **desc,
+ struct module *owner)
+{
+ struct config_group **f_default_groups, *os_desc_group,
+ **interface_groups;
+ struct config_item_type *os_desc_type, *interface_type;
+
+ vla_group(data_chunk);
+ vla_item(data_chunk, struct config_group *, f_default_groups, 2);
+ vla_item(data_chunk, struct config_group, os_desc_group, 1);
+ vla_item(data_chunk, struct config_group *, interface_groups,
+ n_interf + 1);
+ vla_item(data_chunk, struct config_item_type, os_desc_type, 1);
+ vla_item(data_chunk, struct config_item_type, interface_type, 1);
+
+ char *vlabuf = kzalloc(vla_group_size(data_chunk), GFP_KERNEL);
+ if (!vlabuf)
+ return -ENOMEM;
+
+ f_default_groups = vla_ptr(vlabuf, data_chunk, f_default_groups);
+ os_desc_group = vla_ptr(vlabuf, data_chunk, os_desc_group);
+ os_desc_type = vla_ptr(vlabuf, data_chunk, os_desc_type);
+ interface_groups = vla_ptr(vlabuf, data_chunk, interface_groups);
+ interface_type = vla_ptr(vlabuf, data_chunk, interface_type);
+
+ parent->default_groups = f_default_groups;
+ os_desc_type->ct_owner = owner;
+ config_group_init_type_name(os_desc_group, "os_desc", os_desc_type);
+ f_default_groups[0] = os_desc_group;
+
+ os_desc_group->default_groups = interface_groups;
+ interface_type->ct_item_ops = &interf_item_ops;
+ interface_type->ct_group_ops = &interf_grp_ops;
+ interface_type->ct_attrs = interf_grp_attrs;
+ interface_type->ct_owner = owner;
+
+ while (n_interf--) {
+ struct usb_os_desc *d;
+
+ d = desc[n_interf];
+ d->owner = owner;
+ config_group_init_type_name(&d->group, "", interface_type);
+ config_item_set_name(&d->group.cg_item, "interface.%d",
+ n_interf);
+ interface_groups[n_interf] = &d->group;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(usb_os_desc_prepare_interf_dir);
+
static int configfs_do_nothing(struct usb_composite_dev *cdev)
{
WARN_ON(1);
@@ -745,6 +1275,9 @@ static int configfs_do_nothing(struct usb_composite_dev *cdev)
int composite_dev_prepare(struct usb_composite_driver *composite,
struct usb_composite_dev *dev);
+int composite_os_desc_req_prepare(struct usb_composite_dev *cdev,
+ struct usb_ep *ep0);
+
static void purge_configs_funcs(struct gadget_info *gi)
{
struct usb_configuration *c;
@@ -793,7 +1326,7 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
ret = -EINVAL;
if (list_empty(&gi->cdev.configs)) {
- pr_err("Need atleast one configuration in %s.\n",
+ pr_err("Need at least one configuration in %s.\n",
gi->composite.name);
goto err_comp_cleanup;
}
@@ -804,7 +1337,7 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
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",
+ pr_err("Config %s/%d of %s needs at least one function.\n",
c->label, c->bConfigurationValue,
gi->composite.name);
goto err_comp_cleanup;
@@ -839,6 +1372,12 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
gi->cdev.desc.iSerialNumber = s[USB_GADGET_SERIAL_IDX].id;
}
+ if (gi->use_os_desc) {
+ cdev->use_os_string = true;
+ cdev->b_vendor_code = gi->b_vendor_code;
+ memcpy(cdev->qw_sign, gi->qw_sign, OS_STRING_QW_SIGN_LEN);
+ }
+
/* Go through all configs, attach all functions */
list_for_each_entry(c, &gi->cdev.configs, list) {
struct config_usb_cfg *cfg;
@@ -874,6 +1413,12 @@ static int configfs_composite_bind(struct usb_gadget *gadget,
}
usb_ep_autoconfig_reset(cdev->gadget);
}
+ if (cdev->use_os_string) {
+ ret = composite_os_desc_req_prepare(cdev, gadget->ep0);
+ if (ret)
+ goto err_purge_funcs;
+ }
+
usb_ep_autoconfig_reset(cdev->gadget);
return 0;
@@ -929,6 +1474,7 @@ static struct config_group *gadgets_make(
gi->group.default_groups[0] = &gi->functions_group;
gi->group.default_groups[1] = &gi->configs_group;
gi->group.default_groups[2] = &gi->strings_group;
+ gi->group.default_groups[3] = &gi->os_desc_group;
config_group_init_type_name(&gi->functions_group, "functions",
&functions_type);
@@ -936,6 +1482,8 @@ static struct config_group *gadgets_make(
&config_desc_type);
config_group_init_type_name(&gi->strings_group, "strings",
&gadget_strings_strings_type);
+ config_group_init_type_name(&gi->os_desc_group, "os_desc",
+ &os_desc_type);
gi->composite.bind = configfs_do_nothing;
gi->composite.unbind = configfs_do_nothing;
@@ -1005,7 +1553,7 @@ void unregister_gadget_item(struct config_item *item)
unregister_gadget(gi);
}
-EXPORT_SYMBOL(unregister_gadget_item);
+EXPORT_SYMBOL_GPL(unregister_gadget_item);
static int __init gadget_cfs_init(void)
{
diff --git a/drivers/usb/gadget/configfs.h b/drivers/usb/gadget/configfs.h
index a7b564a913d1..a14ac792c698 100644
--- a/drivers/usb/gadget/configfs.h
+++ b/drivers/usb/gadget/configfs.h
@@ -1,6 +1,18 @@
#ifndef USB__GADGET__CONFIGFS__H
#define USB__GADGET__CONFIGFS__H
+#include <linux/configfs.h>
+
void unregister_gadget_item(struct config_item *item);
+int usb_os_desc_prepare_interf_dir(struct config_group *parent,
+ int n_interf,
+ struct usb_os_desc **desc,
+ struct module *owner);
+
+static inline struct usb_os_desc *to_usb_os_desc(struct config_item *item)
+{
+ return container_of(to_config_group(item), struct usb_os_desc, group);
+}
+
#endif /* USB__GADGET__CONFIGFS__H */
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 8c06430dcc47..2b54955d3166 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -561,7 +561,6 @@ static int dummy_disable(struct usb_ep *_ep)
struct dummy_ep *ep;
struct dummy *dum;
unsigned long flags;
- int retval;
ep = usb_ep_to_dummy_ep(_ep);
if (!_ep || !ep->desc || _ep->name == ep0name)
@@ -571,12 +570,11 @@ static int dummy_disable(struct usb_ep *_ep)
spin_lock_irqsave(&dum->lock, flags);
ep->desc = NULL;
ep->stream_en = 0;
- retval = 0;
nuke(dum, ep);
spin_unlock_irqrestore(&dum->lock, flags);
dev_dbg(udc_dev(dum), "disabled %s\n", _ep->name);
- return retval;
+ return 0;
}
static struct usb_request *dummy_alloc_request(struct usb_ep *_ep,
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 1e12b3ee56fd..74202d67f911 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -33,36 +33,11 @@
#include <linux/poll.h>
#include "u_fs.h"
+#include "u_f.h"
#include "configfs.h"
#define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */
-/* Variable Length Array Macros **********************************************/
-#define vla_group(groupname) size_t groupname##__next = 0
-#define vla_group_size(groupname) groupname##__next
-
-#define vla_item(groupname, type, name, n) \
- size_t groupname##_##name##__offset = ({ \
- size_t align_mask = __alignof__(type) - 1; \
- size_t offset = (groupname##__next + align_mask) & ~align_mask;\
- size_t size = (n) * sizeof(type); \
- groupname##__next = offset + size; \
- offset; \
- })
-
-#define vla_item_with_sz(groupname, type, name, n) \
- size_t groupname##_##name##__sz = (n) * sizeof(type); \
- size_t groupname##_##name##__offset = ({ \
- size_t align_mask = __alignof__(type) - 1; \
- size_t offset = (groupname##__next + align_mask) & ~align_mask;\
- size_t size = groupname##_##name##__sz; \
- groupname##__next = offset + size; \
- offset; \
- })
-
-#define vla_ptr(ptr, groupname, name) \
- ((void *) ((char *)ptr + groupname##_##name##__offset))
-
/* Reference counter handling */
static void ffs_data_get(struct ffs_data *ffs);
static void ffs_data_put(struct ffs_data *ffs);
@@ -190,7 +165,7 @@ ffs_sb_create_file(struct super_block *sb, const char *name, void *data,
/* Devices management *******************************************************/
DEFINE_MUTEX(ffs_lock);
-EXPORT_SYMBOL(ffs_lock);
+EXPORT_SYMBOL_GPL(ffs_lock);
static struct ffs_dev *_ffs_find_dev(const char *name);
static struct ffs_dev *_ffs_alloc_dev(void);
@@ -2883,7 +2858,7 @@ int ffs_name_dev(struct ffs_dev *dev, const char *name)
return ret;
}
-EXPORT_SYMBOL(ffs_name_dev);
+EXPORT_SYMBOL_GPL(ffs_name_dev);
int ffs_single_dev(struct ffs_dev *dev)
{
@@ -2900,7 +2875,7 @@ int ffs_single_dev(struct ffs_dev *dev)
ffs_dev_unlock();
return ret;
}
-EXPORT_SYMBOL(ffs_single_dev);
+EXPORT_SYMBOL_GPL(ffs_single_dev);
/*
* ffs_lock must be taken by the caller of this function
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
index 9a4f49dc6ac4..eed3ad878047 100644
--- a/drivers/usb/gadget/f_rndis.c
+++ b/drivers/usb/gadget/f_rndis.c
@@ -27,6 +27,7 @@
#include "u_ether_configfs.h"
#include "u_rndis.h"
#include "rndis.h"
+#include "configfs.h"
/*
* This function is an RNDIS Ethernet port -- a Microsoft protocol that's
@@ -682,6 +683,15 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
rndis_opts = container_of(f->fi, struct f_rndis_opts, func_inst);
+ if (cdev->use_os_string) {
+ f->os_desc_table = kzalloc(sizeof(*f->os_desc_table),
+ GFP_KERNEL);
+ if (!f->os_desc_table)
+ return PTR_ERR(f->os_desc_table);
+ f->os_desc_n = 1;
+ f->os_desc_table[0].os_desc = &rndis_opts->rndis_os_desc;
+ }
+
/*
* in drivers/usb/gadget/configfs.c:configfs_composite_bind()
* configurations are bound in sequence with list_for_each_entry,
@@ -693,14 +703,16 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
gether_set_gadget(rndis_opts->net, cdev->gadget);
status = gether_register_netdev(rndis_opts->net);
if (status)
- return status;
+ goto fail;
rndis_opts->bound = true;
}
us = usb_gstrings_attach(cdev, rndis_strings,
ARRAY_SIZE(rndis_string_defs));
- if (IS_ERR(us))
- return PTR_ERR(us);
+ if (IS_ERR(us)) {
+ status = PTR_ERR(us);
+ goto fail;
+ }
rndis_control_intf.iInterface = us[0].id;
rndis_data_intf.iInterface = us[1].id;
rndis_iad_descriptor.iFunction = us[2].id;
@@ -802,6 +814,8 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
return 0;
fail:
+ kfree(f->os_desc_table);
+ f->os_desc_n = 0;
usb_free_all_descriptors(f);
if (rndis->notify_req) {
@@ -834,7 +848,7 @@ void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net)
opts->borrowed_net = opts->bound = true;
opts->net = net;
}
-EXPORT_SYMBOL(rndis_borrow_net);
+EXPORT_SYMBOL_GPL(rndis_borrow_net);
static inline struct f_rndis_opts *to_f_rndis_opts(struct config_item *item)
{
@@ -882,16 +896,21 @@ static void rndis_free_inst(struct usb_function_instance *f)
else
free_netdev(opts->net);
}
+
+ kfree(opts->rndis_os_desc.group.default_groups); /* single VLA chunk */
kfree(opts);
}
static struct usb_function_instance *rndis_alloc_inst(void)
{
struct f_rndis_opts *opts;
+ struct usb_os_desc *descs[1];
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
if (!opts)
return ERR_PTR(-ENOMEM);
+ opts->rndis_os_desc.ext_compat_id = opts->rndis_ext_compat_id;
+
mutex_init(&opts->lock);
opts->func_inst.free_func_inst = rndis_free_inst;
opts->net = gether_setup_default();
@@ -900,7 +919,11 @@ static struct usb_function_instance *rndis_alloc_inst(void)
kfree(opts);
return ERR_CAST(net);
}
+ INIT_LIST_HEAD(&opts->rndis_os_desc.ext_prop);
+ descs[0] = &opts->rndis_os_desc;
+ usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs,
+ THIS_MODULE);
config_group_init_type_name(&opts->func_inst.group, "",
&rndis_func_type);
@@ -925,6 +948,8 @@ static void rndis_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct f_rndis *rndis = func_to_rndis(f);
+ kfree(f->os_desc_table);
+ f->os_desc_n = 0;
usb_free_all_descriptors(f);
kfree(rndis->notify_req->buf);
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c
index df4a0dcbc993..1ea8baf33333 100644
--- a/drivers/usb/gadget/f_subset.c
+++ b/drivers/usb/gadget/f_subset.c
@@ -276,7 +276,7 @@ static int geth_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
}
net = gether_connect(&geth->port);
- return PTR_RET(net);
+ return PTR_ERR_OR_ZERO(net);
}
static void geth_disable(struct usb_function *f)
diff --git a/drivers/usb/gadget/f_uac2.c b/drivers/usb/gadget/f_uac2.c
index bc23040c7790..6261db4a9910 100644
--- a/drivers/usb/gadget/f_uac2.c
+++ b/drivers/usb/gadget/f_uac2.c
@@ -196,7 +196,7 @@ agdev_iso_complete(struct usb_ep *ep, struct usb_request *req)
struct snd_uac2_chip *uac2 = prm->uac2;
/* i/f shutting down */
- if (!prm->ep_enabled)
+ if (!prm->ep_enabled || req->status == -ESHUTDOWN)
return;
/*
@@ -974,8 +974,6 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
if (!prm->rbuf) {
prm->max_psize = 0;
- dev_err(&uac2->pdev.dev,
- "%s:%d Error!\n", __func__, __LINE__);
goto err;
}
@@ -984,8 +982,6 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL);
if (!prm->rbuf) {
prm->max_psize = 0;
- dev_err(&uac2->pdev.dev,
- "%s:%d Error!\n", __func__, __LINE__);
goto err;
}
@@ -1298,10 +1294,8 @@ static int audio_bind_config(struct usb_configuration *cfg)
int res;
agdev_g = kzalloc(sizeof *agdev_g, GFP_KERNEL);
- if (agdev_g == NULL) {
- printk(KERN_ERR "Unable to allocate audio gadget\n");
+ if (agdev_g == NULL)
return -ENOMEM;
- }
res = usb_string_ids_tab(cfg->cdev, strings_fn);
if (res)
diff --git a/drivers/usb/gadget/fotg210-udc.c b/drivers/usb/gadget/fotg210-udc.c
index 2d0305280e8c..e143d69f6017 100644
--- a/drivers/usb/gadget/fotg210-udc.c
+++ b/drivers/usb/gadget/fotg210-udc.c
@@ -1112,17 +1112,13 @@ static int fotg210_udc_probe(struct platform_device *pdev)
/* initialize udc */
fotg210 = kzalloc(sizeof(struct fotg210_udc), GFP_KERNEL);
- if (fotg210 == NULL) {
- pr_err("kzalloc error\n");
+ if (fotg210 == NULL)
goto err_alloc;
- }
for (i = 0; i < FOTG210_MAX_NUM_EP; i++) {
_ep[i] = kzalloc(sizeof(struct fotg210_ep), GFP_KERNEL);
- if (_ep[i] == NULL) {
- pr_err("_ep kzalloc error\n");
+ if (_ep[i] == NULL)
goto err_alloc;
- }
fotg210->ep[i] = _ep[i];
}
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index a2f26cdb56fe..28e4fc957026 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -2256,10 +2256,8 @@ static int __init struct_udc_setup(struct fsl_udc *udc,
udc->phy_mode = pdata->phy_mode;
udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL);
- if (!udc->eps) {
- ERR("malloc fsl_ep failed\n");
+ if (!udc->eps)
return -1;
- }
/* initialized QHs, take care of alignment */
size = udc->max_ep * sizeof(struct ep_queue_head);
@@ -2342,10 +2340,8 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
u32 dccparams;
udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);
- if (udc_controller == NULL) {
- ERR("malloc udc failed\n");
+ if (udc_controller == NULL)
return -ENOMEM;
- }
pdata = dev_get_platdata(&pdev->dev);
udc_controller->pdata = pdata;
diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c
index 6423f1840ed9..3deb4e938071 100644
--- a/drivers/usb/gadget/fusb300_udc.c
+++ b/drivers/usb/gadget/fusb300_udc.c
@@ -1400,17 +1400,13 @@ static int __init fusb300_probe(struct platform_device *pdev)
/* initialize udc */
fusb300 = kzalloc(sizeof(struct fusb300), GFP_KERNEL);
- if (fusb300 == NULL) {
- pr_err("kzalloc error\n");
+ if (fusb300 == NULL)
goto clean_up;
- }
for (i = 0; i < FUSB300_MAX_NUM_EP; i++) {
_ep[i] = kzalloc(sizeof(struct fusb300_ep), GFP_KERNEL);
- if (_ep[i] == NULL) {
- pr_err("_ep kzalloc error\n");
+ if (_ep[i] == NULL)
goto clean_up;
- }
fusb300->ep[i] = _ep[i];
}
diff --git a/drivers/usb/gadget/gr_udc.c b/drivers/usb/gadget/gr_udc.c
index f984ee75324d..99a37ed03e27 100644
--- a/drivers/usb/gadget/gr_udc.c
+++ b/drivers/usb/gadget/gr_udc.c
@@ -143,6 +143,7 @@ static void gr_seq_ep_show(struct seq_file *seq, struct gr_ep *ep)
seq_printf(seq, " wedged = %d\n", ep->wedged);
seq_printf(seq, " callback = %d\n", ep->callback);
seq_printf(seq, " maxpacket = %d\n", ep->ep.maxpacket);
+ seq_printf(seq, " maxpacket_limit = %d\n", ep->ep.maxpacket_limit);
seq_printf(seq, " bytes_per_buffer = %d\n", ep->bytes_per_buffer);
if (mode == 1 || mode == 3)
seq_printf(seq, " nt = %d\n",
@@ -1541,6 +1542,10 @@ static int gr_ep_enable(struct usb_ep *_ep,
} else if (max == 0) {
dev_err(dev->dev, "Max payload cannot be set to 0\n");
return -EINVAL;
+ } else if (max > ep->ep.maxpacket_limit) {
+ dev_err(dev->dev, "Requested max payload %d > limit %d\n",
+ max, ep->ep.maxpacket_limit);
+ return -EINVAL;
}
spin_lock(&ep->dev->lock);
@@ -1679,7 +1684,7 @@ static int gr_queue_ext(struct usb_ep *_ep, struct usb_request *_req,
if (ep->is_in)
gr_dbgprint_request("EXTERN", ep, req);
- ret = gr_queue(ep, req, gfp_flags);
+ ret = gr_queue(ep, req, GFP_ATOMIC);
spin_unlock(&ep->dev->lock);
@@ -1985,8 +1990,8 @@ static int gr_ep_init(struct gr_udc *dev, int num, int is_in, u32 maxplimit)
INIT_LIST_HEAD(&ep->queue);
if (num == 0) {
- _req = gr_alloc_request(&ep->ep, GFP_KERNEL);
- buf = devm_kzalloc(dev->dev, PAGE_SIZE, GFP_DMA | GFP_KERNEL);
+ _req = gr_alloc_request(&ep->ep, GFP_ATOMIC);
+ buf = devm_kzalloc(dev->dev, PAGE_SIZE, GFP_DMA | GFP_ATOMIC);
if (!_req || !buf) {
/* possible _req freed by gr_probe via gr_remove */
return -ENOMEM;
@@ -2020,9 +2025,7 @@ static int gr_udc_init(struct gr_udc *dev)
u32 dmactrl_val;
int i;
int ret = 0;
- u32 *bufsizes;
u32 bufsize;
- int len;
gr_set_address(dev, 0);
@@ -2033,19 +2036,17 @@ static int gr_udc_init(struct gr_udc *dev)
INIT_LIST_HEAD(&dev->ep_list);
gr_set_ep0state(dev, GR_EP0_DISCONNECT);
- bufsizes = (u32 *)of_get_property(np, "epobufsizes", &len);
- len /= sizeof(u32);
for (i = 0; i < dev->nepo; i++) {
- bufsize = (bufsizes && i < len) ? bufsizes[i] : 1024;
+ if (of_property_read_u32_index(np, "epobufsizes", i, &bufsize))
+ bufsize = 1024;
ret = gr_ep_init(dev, i, 0, bufsize);
if (ret)
return ret;
}
- bufsizes = (u32 *)of_get_property(np, "epibufsizes", &len);
- len /= sizeof(u32);
for (i = 0; i < dev->nepi; i++) {
- bufsize = (bufsizes && i < len) ? bufsizes[i] : 1024;
+ if (of_property_read_u32_index(np, "epibufsizes", i, &bufsize))
+ bufsize = 1024;
ret = gr_ep_init(dev, i, 1, bufsize);
if (ret)
return ret;
@@ -2065,9 +2066,9 @@ static int gr_udc_init(struct gr_udc *dev)
return 0;
}
-static int gr_remove(struct platform_device *ofdev)
+static int gr_remove(struct platform_device *pdev)
{
- struct gr_udc *dev = dev_get_drvdata(&ofdev->dev);
+ struct gr_udc *dev = platform_get_drvdata(pdev);
if (dev->added)
usb_del_gadget_udc(&dev->gadget); /* Shuts everything down */
@@ -2077,7 +2078,7 @@ static int gr_remove(struct platform_device *ofdev)
gr_dfs_delete(dev);
if (dev->desc_pool)
dma_pool_destroy(dev->desc_pool);
- dev_set_drvdata(&ofdev->dev, NULL);
+ platform_set_drvdata(pdev, NULL);
gr_free_request(&dev->epi[0].ep, &dev->ep0reqi->req);
gr_free_request(&dev->epo[0].ep, &dev->ep0reqo->req);
@@ -2090,7 +2091,7 @@ static int gr_request_irq(struct gr_udc *dev, int irq)
IRQF_SHARED, driver_name, dev);
}
-static int gr_probe(struct platform_device *ofdev)
+static int gr_probe(struct platform_device *pdev)
{
struct gr_udc *dev;
struct resource *res;
@@ -2098,30 +2099,32 @@ static int gr_probe(struct platform_device *ofdev)
int retval;
u32 status;
- dev = devm_kzalloc(&ofdev->dev, sizeof(*dev), GFP_KERNEL);
+ dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
- dev->dev = &ofdev->dev;
+ dev->dev = &pdev->dev;
- res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
regs = devm_ioremap_resource(dev->dev, res);
if (IS_ERR(regs))
return PTR_ERR(regs);
- dev->irq = irq_of_parse_and_map(dev->dev->of_node, 0);
- if (!dev->irq) {
+ dev->irq = platform_get_irq(pdev, 0);
+ if (dev->irq <= 0) {
dev_err(dev->dev, "No irq found\n");
return -ENODEV;
}
/* Some core configurations has separate irqs for IN and OUT events */
- dev->irqi = irq_of_parse_and_map(dev->dev->of_node, 1);
- if (dev->irqi) {
- dev->irqo = irq_of_parse_and_map(dev->dev->of_node, 2);
- if (!dev->irqo) {
+ dev->irqi = platform_get_irq(pdev, 1);
+ if (dev->irqi > 0) {
+ dev->irqo = platform_get_irq(pdev, 2);
+ if (dev->irqo <= 0) {
dev_err(dev->dev, "Found irqi but not irqo\n");
return -ENODEV;
}
+ } else {
+ dev->irqi = 0;
}
dev->gadget.name = driver_name;
@@ -2132,7 +2135,7 @@ static int gr_probe(struct platform_device *ofdev)
spin_lock_init(&dev->lock);
dev->regs = regs;
- dev_set_drvdata(&ofdev->dev, dev);
+ platform_set_drvdata(pdev, dev);
/* Determine number of endpoints and data interface mode */
status = gr_read32(&dev->regs->status);
@@ -2204,7 +2207,7 @@ out:
spin_unlock(&dev->lock);
if (retval)
- gr_remove(ofdev);
+ gr_remove(pdev);
return retval;
}
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index a925d0cbcd41..ee6c16416c30 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1494,6 +1494,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
*/
if (value == 0) {
INFO (dev, "configuration #%d\n", dev->current_config);
+ usb_gadget_set_state(gadget, USB_STATE_CONFIGURED);
if (dev->usermode_setup) {
dev->setup_can_stall = 0;
goto delegate;
@@ -1501,7 +1502,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
}
break;
-#ifndef CONFIG_USB_GADGET_PXA25X
+#ifndef CONFIG_USB_PXA25X
/* PXA automagically handles this request too */
case USB_REQ_GET_CONFIGURATION:
if (ctrl->bRequestType != 0x80)
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c
index 8cae01d88597..0d17174b86f8 100644
--- a/drivers/usb/gadget/m66592-udc.c
+++ b/drivers/usb/gadget/m66592-udc.c
@@ -1594,7 +1594,6 @@ static int __init m66592_probe(struct platform_device *pdev)
m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
if (m66592 == NULL) {
ret = -ENOMEM;
- pr_err("kzalloc error\n");
goto clean_up;
}
diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c
index d2ca59e7b477..16248711c152 100644
--- a/drivers/usb/gadget/mv_u3d_core.c
+++ b/drivers/usb/gadget/mv_u3d_core.c
@@ -297,10 +297,8 @@ static struct mv_u3d_trb *mv_u3d_build_trb_one(struct mv_u3d_req *req,
u3d = req->ep->u3d;
trb = kzalloc(sizeof(*trb), GFP_ATOMIC);
- if (!trb) {
- dev_err(u3d->dev, "%s, trb alloc fail\n", __func__);
+ if (!trb)
return NULL;
- }
/*
* Be careful that no _GFP_HIGHMEM is set,
@@ -446,17 +444,12 @@ static int mv_u3d_req_to_trb(struct mv_u3d_req *req)
trb_num++;
trb = kcalloc(trb_num, sizeof(*trb), GFP_ATOMIC);
- if (!trb) {
- dev_err(u3d->dev,
- "%s, trb alloc fail\n", __func__);
+ if (!trb)
return -ENOMEM;
- }
trb_hw = kcalloc(trb_num, sizeof(*trb_hw), GFP_ATOMIC);
if (!trb_hw) {
kfree(trb);
- dev_err(u3d->dev,
- "%s, trb_hw alloc fail\n", __func__);
return -ENOMEM;
}
@@ -1811,7 +1804,6 @@ static int mv_u3d_probe(struct platform_device *dev)
u3d = kzalloc(sizeof(*u3d), GFP_KERNEL);
if (!u3d) {
- dev_err(&dev->dev, "failed to allocate memory for u3d\n");
retval = -ENOMEM;
goto err_alloc_private;
}
@@ -1905,7 +1897,6 @@ static int mv_u3d_probe(struct platform_device *dev)
size = u3d->max_eps * sizeof(struct mv_u3d_ep) * 2;
u3d->eps = kzalloc(size, GFP_KERNEL);
if (!u3d->eps) {
- dev_err(&dev->dev, "allocate ep memory failed\n");
retval = -ENOMEM;
goto err_alloc_eps;
}
@@ -1913,7 +1904,6 @@ static int mv_u3d_probe(struct platform_device *dev)
/* initialize ep0 status request structure */
u3d->status_req = kzalloc(sizeof(struct mv_u3d_req) + 8, GFP_KERNEL);
if (!u3d->status_req) {
- dev_err(&dev->dev, "allocate status_req memory failed\n");
retval = -ENOMEM;
goto err_alloc_status_req;
}
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 43e5e2f9888f..300b3a71383b 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -1972,7 +1972,9 @@ static int net2280_stop(struct usb_gadget *_gadget,
device_remove_file (&dev->pdev->dev, &dev_attr_function);
device_remove_file (&dev->pdev->dev, &dev_attr_queues);
- DEBUG (dev, "unregistered driver '%s'\n", driver->driver.name);
+ DEBUG(dev, "unregistered driver '%s'\n",
+ driver ? driver->driver.name : "");
+
return 0;
}
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
index aff0a6718bc6..b698a490cc7d 100644
--- a/drivers/usb/gadget/r8a66597-udc.c
+++ b/drivers/usb/gadget/r8a66597-udc.c
@@ -1904,7 +1904,6 @@ static int __init r8a66597_probe(struct platform_device *pdev)
r8a66597 = kzalloc(sizeof(struct r8a66597), GFP_KERNEL);
if (r8a66597 == NULL) {
ret = -ENOMEM;
- dev_err(&pdev->dev, "kzalloc error\n");
goto clean_up;
}
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 7ed452d90f4d..95d2324f6977 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -761,7 +761,7 @@ int rndis_signal_connect(int configNr)
return rndis_indicate_status_msg(configNr,
RNDIS_STATUS_MEDIA_CONNECT);
}
-EXPORT_SYMBOL(rndis_signal_connect);
+EXPORT_SYMBOL_GPL(rndis_signal_connect);
int rndis_signal_disconnect(int configNr)
{
@@ -770,7 +770,7 @@ int rndis_signal_disconnect(int configNr)
return rndis_indicate_status_msg(configNr,
RNDIS_STATUS_MEDIA_DISCONNECT);
}
-EXPORT_SYMBOL(rndis_signal_disconnect);
+EXPORT_SYMBOL_GPL(rndis_signal_disconnect);
void rndis_uninit(int configNr)
{
@@ -785,13 +785,13 @@ void rndis_uninit(int configNr)
while ((buf = rndis_get_next_response(configNr, &length)))
rndis_free_response(configNr, buf);
}
-EXPORT_SYMBOL(rndis_uninit);
+EXPORT_SYMBOL_GPL(rndis_uninit);
void rndis_set_host_mac(int configNr, const u8 *addr)
{
rndis_per_dev_params[configNr].host_mac = addr;
}
-EXPORT_SYMBOL(rndis_set_host_mac);
+EXPORT_SYMBOL_GPL(rndis_set_host_mac);
/*
* Message Parser
@@ -874,7 +874,7 @@ int rndis_msg_parser(u8 configNr, u8 *buf)
return -ENOTSUPP;
}
-EXPORT_SYMBOL(rndis_msg_parser);
+EXPORT_SYMBOL_GPL(rndis_msg_parser);
int rndis_register(void (*resp_avail)(void *v), void *v)
{
@@ -896,7 +896,7 @@ int rndis_register(void (*resp_avail)(void *v), void *v)
return -ENODEV;
}
-EXPORT_SYMBOL(rndis_register);
+EXPORT_SYMBOL_GPL(rndis_register);
void rndis_deregister(int configNr)
{
@@ -905,7 +905,7 @@ void rndis_deregister(int configNr)
if (configNr >= RNDIS_MAX_CONFIGS) return;
rndis_per_dev_params[configNr].used = 0;
}
-EXPORT_SYMBOL(rndis_deregister);
+EXPORT_SYMBOL_GPL(rndis_deregister);
int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter)
{
@@ -919,7 +919,7 @@ int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter)
return 0;
}
-EXPORT_SYMBOL(rndis_set_param_dev);
+EXPORT_SYMBOL_GPL(rndis_set_param_dev);
int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr)
{
@@ -932,7 +932,7 @@ int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr)
return 0;
}
-EXPORT_SYMBOL(rndis_set_param_vendor);
+EXPORT_SYMBOL_GPL(rndis_set_param_vendor);
int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed)
{
@@ -944,7 +944,7 @@ int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed)
return 0;
}
-EXPORT_SYMBOL(rndis_set_param_medium);
+EXPORT_SYMBOL_GPL(rndis_set_param_medium);
void rndis_add_hdr(struct sk_buff *skb)
{
@@ -959,7 +959,7 @@ void rndis_add_hdr(struct sk_buff *skb)
header->DataOffset = cpu_to_le32(36);
header->DataLength = cpu_to_le32(skb->len - sizeof(*header));
}
-EXPORT_SYMBOL(rndis_add_hdr);
+EXPORT_SYMBOL_GPL(rndis_add_hdr);
void rndis_free_response(int configNr, u8 *buf)
{
@@ -976,7 +976,7 @@ void rndis_free_response(int configNr, u8 *buf)
}
}
}
-EXPORT_SYMBOL(rndis_free_response);
+EXPORT_SYMBOL_GPL(rndis_free_response);
u8 *rndis_get_next_response(int configNr, u32 *length)
{
@@ -998,7 +998,7 @@ u8 *rndis_get_next_response(int configNr, u32 *length)
return NULL;
}
-EXPORT_SYMBOL(rndis_get_next_response);
+EXPORT_SYMBOL_GPL(rndis_get_next_response);
static rndis_resp_t *rndis_add_response(int configNr, u32 length)
{
@@ -1042,7 +1042,7 @@ int rndis_rm_hdr(struct gether *port,
skb_queue_tail(list, skb);
return 0;
}
-EXPORT_SYMBOL(rndis_rm_hdr);
+EXPORT_SYMBOL_GPL(rndis_rm_hdr);
#ifdef CONFIG_USB_GADGET_DEBUG_FILES
diff --git a/drivers/usb/gadget/s3c-hsotg.h b/drivers/usb/gadget/s3c-hsotg.h
deleted file mode 100644
index 85f549ff8c1f..000000000000
--- a/drivers/usb/gadget/s3c-hsotg.h
+++ /dev/null
@@ -1,378 +0,0 @@
-/* drivers/usb/gadget/s3c-hsotg.h
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- * http://armlinux.simtec.co.uk/
- * Ben Dooks <ben@simtec.co.uk>
- *
- * USB2.0 Highspeed/OtG Synopsis DWC2 device block registers
- *
- * 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 __REGS_USB_HSOTG_H
-#define __REGS_USB_HSOTG_H __FILE__
-
-#define HSOTG_REG(x) (x)
-
-#define GOTGCTL HSOTG_REG(0x000)
-#define GOTGCTL_BSESVLD (1 << 19)
-#define GOTGCTL_ASESVLD (1 << 18)
-#define GOTGCTL_DBNC_SHORT (1 << 17)
-#define GOTGCTL_CONID_B (1 << 16)
-#define GOTGCTL_DEVHNPEN (1 << 11)
-#define GOTGCTL_HSSETHNPEN (1 << 10)
-#define GOTGCTL_HNPREQ (1 << 9)
-#define GOTGCTL_HSTNEGSCS (1 << 8)
-#define GOTGCTL_SESREQ (1 << 1)
-#define GOTGCTL_SESREQSCS (1 << 0)
-
-#define GOTGINT HSOTG_REG(0x004)
-#define GOTGINT_DbnceDone (1 << 19)
-#define GOTGINT_ADevTOUTChg (1 << 18)
-#define GOTGINT_HstNegDet (1 << 17)
-#define GOTGINT_HstnegSucStsChng (1 << 9)
-#define GOTGINT_SesReqSucStsChng (1 << 8)
-#define GOTGINT_SesEndDet (1 << 2)
-
-#define GAHBCFG HSOTG_REG(0x008)
-#define GAHBCFG_PTxFEmpLvl (1 << 8)
-#define GAHBCFG_NPTxFEmpLvl (1 << 7)
-#define GAHBCFG_DMAEn (1 << 5)
-#define GAHBCFG_HBstLen_MASK (0xf << 1)
-#define GAHBCFG_HBstLen_SHIFT (1)
-#define GAHBCFG_HBstLen_Single (0x0 << 1)
-#define GAHBCFG_HBstLen_Incr (0x1 << 1)
-#define GAHBCFG_HBstLen_Incr4 (0x3 << 1)
-#define GAHBCFG_HBstLen_Incr8 (0x5 << 1)
-#define GAHBCFG_HBstLen_Incr16 (0x7 << 1)
-#define GAHBCFG_GlblIntrEn (1 << 0)
-
-#define GUSBCFG HSOTG_REG(0x00C)
-#define GUSBCFG_PHYLPClkSel (1 << 15)
-#define GUSBCFG_HNPCap (1 << 9)
-#define GUSBCFG_SRPCap (1 << 8)
-#define GUSBCFG_PHYIf16 (1 << 3)
-#define GUSBCFG_PHYIf8 (0 << 3)
-#define GUSBCFG_TOutCal_MASK (0x7 << 0)
-#define GUSBCFG_TOutCal_SHIFT (0)
-#define GUSBCFG_TOutCal_LIMIT (0x7)
-#define GUSBCFG_TOutCal(_x) ((_x) << 0)
-
-#define GRSTCTL HSOTG_REG(0x010)
-
-#define GRSTCTL_AHBIdle (1 << 31)
-#define GRSTCTL_DMAReq (1 << 30)
-#define GRSTCTL_TxFNum_MASK (0x1f << 6)
-#define GRSTCTL_TxFNum_SHIFT (6)
-#define GRSTCTL_TxFNum_LIMIT (0x1f)
-#define GRSTCTL_TxFNum(_x) ((_x) << 6)
-#define GRSTCTL_TxFFlsh (1 << 5)
-#define GRSTCTL_RxFFlsh (1 << 4)
-#define GRSTCTL_INTknQFlsh (1 << 3)
-#define GRSTCTL_FrmCntrRst (1 << 2)
-#define GRSTCTL_HSftRst (1 << 1)
-#define GRSTCTL_CSftRst (1 << 0)
-
-#define GINTSTS HSOTG_REG(0x014)
-#define GINTMSK HSOTG_REG(0x018)
-
-#define GINTSTS_WkUpInt (1 << 31)
-#define GINTSTS_SessReqInt (1 << 30)
-#define GINTSTS_DisconnInt (1 << 29)
-#define GINTSTS_ConIDStsChng (1 << 28)
-#define GINTSTS_PTxFEmp (1 << 26)
-#define GINTSTS_HChInt (1 << 25)
-#define GINTSTS_PrtInt (1 << 24)
-#define GINTSTS_FetSusp (1 << 22)
-#define GINTSTS_incompIP (1 << 21)
-#define GINTSTS_IncomplSOIN (1 << 20)
-#define GINTSTS_OEPInt (1 << 19)
-#define GINTSTS_IEPInt (1 << 18)
-#define GINTSTS_EPMis (1 << 17)
-#define GINTSTS_EOPF (1 << 15)
-#define GINTSTS_ISOutDrop (1 << 14)
-#define GINTSTS_EnumDone (1 << 13)
-#define GINTSTS_USBRst (1 << 12)
-#define GINTSTS_USBSusp (1 << 11)
-#define GINTSTS_ErlySusp (1 << 10)
-#define GINTSTS_GOUTNakEff (1 << 7)
-#define GINTSTS_GINNakEff (1 << 6)
-#define GINTSTS_NPTxFEmp (1 << 5)
-#define GINTSTS_RxFLvl (1 << 4)
-#define GINTSTS_SOF (1 << 3)
-#define GINTSTS_OTGInt (1 << 2)
-#define GINTSTS_ModeMis (1 << 1)
-#define GINTSTS_CurMod_Host (1 << 0)
-
-#define GRXSTSR HSOTG_REG(0x01C)
-#define GRXSTSP HSOTG_REG(0x020)
-
-#define GRXSTS_FN_MASK (0x7f << 25)
-#define GRXSTS_FN_SHIFT (25)
-
-#define GRXSTS_PktSts_MASK (0xf << 17)
-#define GRXSTS_PktSts_SHIFT (17)
-#define GRXSTS_PktSts_GlobalOutNAK (0x1 << 17)
-#define GRXSTS_PktSts_OutRX (0x2 << 17)
-#define GRXSTS_PktSts_OutDone (0x3 << 17)
-#define GRXSTS_PktSts_SetupDone (0x4 << 17)
-#define GRXSTS_PktSts_SetupRX (0x6 << 17)
-
-#define GRXSTS_DPID_MASK (0x3 << 15)
-#define GRXSTS_DPID_SHIFT (15)
-#define GRXSTS_ByteCnt_MASK (0x7ff << 4)
-#define GRXSTS_ByteCnt_SHIFT (4)
-#define GRXSTS_EPNum_MASK (0xf << 0)
-#define GRXSTS_EPNum_SHIFT (0)
-
-#define GRXFSIZ HSOTG_REG(0x024)
-
-#define GNPTXFSIZ HSOTG_REG(0x028)
-
-#define GNPTXFSIZ_NPTxFDep_MASK (0xffff << 16)
-#define GNPTXFSIZ_NPTxFDep_SHIFT (16)
-#define GNPTXFSIZ_NPTxFDep_LIMIT (0xffff)
-#define GNPTXFSIZ_NPTxFDep(_x) ((_x) << 16)
-#define GNPTXFSIZ_NPTxFStAddr_MASK (0xffff << 0)
-#define GNPTXFSIZ_NPTxFStAddr_SHIFT (0)
-#define GNPTXFSIZ_NPTxFStAddr_LIMIT (0xffff)
-#define GNPTXFSIZ_NPTxFStAddr(_x) ((_x) << 0)
-
-#define GNPTXSTS HSOTG_REG(0x02C)
-
-#define GNPTXSTS_NPtxQTop_MASK (0x7f << 24)
-#define GNPTXSTS_NPtxQTop_SHIFT (24)
-
-#define GNPTXSTS_NPTxQSpcAvail_MASK (0xff << 16)
-#define GNPTXSTS_NPTxQSpcAvail_SHIFT (16)
-#define GNPTXSTS_NPTxQSpcAvail_GET(_v) (((_v) >> 16) & 0xff)
-
-#define GNPTXSTS_NPTxFSpcAvail_MASK (0xffff << 0)
-#define GNPTXSTS_NPTxFSpcAvail_SHIFT (0)
-#define GNPTXSTS_NPTxFSpcAvail_GET(_v) (((_v) >> 0) & 0xffff)
-
-
-#define HPTXFSIZ HSOTG_REG(0x100)
-
-#define DPTXFSIZn(_a) HSOTG_REG(0x104 + (((_a) - 1) * 4))
-
-#define DPTXFSIZn_DPTxFSize_MASK (0xffff << 16)
-#define DPTXFSIZn_DPTxFSize_SHIFT (16)
-#define DPTXFSIZn_DPTxFSize_GET(_v) (((_v) >> 16) & 0xffff)
-#define DPTXFSIZn_DPTxFSize_LIMIT (0xffff)
-#define DPTXFSIZn_DPTxFSize(_x) ((_x) << 16)
-
-#define DPTXFSIZn_DPTxFStAddr_MASK (0xffff << 0)
-#define DPTXFSIZn_DPTxFStAddr_SHIFT (0)
-
-/* Device mode registers */
-#define DCFG HSOTG_REG(0x800)
-
-#define DCFG_EPMisCnt_MASK (0x1f << 18)
-#define DCFG_EPMisCnt_SHIFT (18)
-#define DCFG_EPMisCnt_LIMIT (0x1f)
-#define DCFG_EPMisCnt(_x) ((_x) << 18)
-
-#define DCFG_PerFrInt_MASK (0x3 << 11)
-#define DCFG_PerFrInt_SHIFT (11)
-#define DCFG_PerFrInt_LIMIT (0x3)
-#define DCFG_PerFrInt(_x) ((_x) << 11)
-
-#define DCFG_DevAddr_MASK (0x7f << 4)
-#define DCFG_DevAddr_SHIFT (4)
-#define DCFG_DevAddr_LIMIT (0x7f)
-#define DCFG_DevAddr(_x) ((_x) << 4)
-
-#define DCFG_NZStsOUTHShk (1 << 2)
-
-#define DCFG_DevSpd_MASK (0x3 << 0)
-#define DCFG_DevSpd_SHIFT (0)
-#define DCFG_DevSpd_HS (0x0 << 0)
-#define DCFG_DevSpd_FS (0x1 << 0)
-#define DCFG_DevSpd_LS (0x2 << 0)
-#define DCFG_DevSpd_FS48 (0x3 << 0)
-
-#define DCTL HSOTG_REG(0x804)
-
-#define DCTL_PWROnPrgDone (1 << 11)
-#define DCTL_CGOUTNak (1 << 10)
-#define DCTL_SGOUTNak (1 << 9)
-#define DCTL_CGNPInNAK (1 << 8)
-#define DCTL_SGNPInNAK (1 << 7)
-#define DCTL_TstCtl_MASK (0x7 << 4)
-#define DCTL_TstCtl_SHIFT (4)
-#define DCTL_GOUTNakSts (1 << 3)
-#define DCTL_GNPINNakSts (1 << 2)
-#define DCTL_SftDiscon (1 << 1)
-#define DCTL_RmtWkUpSig (1 << 0)
-
-#define DSTS HSOTG_REG(0x808)
-
-#define DSTS_SOFFN_MASK (0x3fff << 8)
-#define DSTS_SOFFN_SHIFT (8)
-#define DSTS_SOFFN_LIMIT (0x3fff)
-#define DSTS_SOFFN(_x) ((_x) << 8)
-#define DSTS_ErraticErr (1 << 3)
-#define DSTS_EnumSpd_MASK (0x3 << 1)
-#define DSTS_EnumSpd_SHIFT (1)
-#define DSTS_EnumSpd_HS (0x0 << 1)
-#define DSTS_EnumSpd_FS (0x1 << 1)
-#define DSTS_EnumSpd_LS (0x2 << 1)
-#define DSTS_EnumSpd_FS48 (0x3 << 1)
-
-#define DSTS_SuspSts (1 << 0)
-
-#define DIEPMSK HSOTG_REG(0x810)
-
-#define DIEPMSK_TxFIFOEmpty (1 << 7)
-#define DIEPMSK_INEPNakEffMsk (1 << 6)
-#define DIEPMSK_INTknEPMisMsk (1 << 5)
-#define DIEPMSK_INTknTXFEmpMsk (1 << 4)
-#define DIEPMSK_TimeOUTMsk (1 << 3)
-#define DIEPMSK_AHBErrMsk (1 << 2)
-#define DIEPMSK_EPDisbldMsk (1 << 1)
-#define DIEPMSK_XferComplMsk (1 << 0)
-
-#define DOEPMSK HSOTG_REG(0x814)
-
-#define DOEPMSK_Back2BackSetup (1 << 6)
-#define DOEPMSK_OUTTknEPdisMsk (1 << 4)
-#define DOEPMSK_SetupMsk (1 << 3)
-#define DOEPMSK_AHBErrMsk (1 << 2)
-#define DOEPMSK_EPDisbldMsk (1 << 1)
-#define DOEPMSK_XferComplMsk (1 << 0)
-
-#define DAINT HSOTG_REG(0x818)
-#define DAINTMSK HSOTG_REG(0x81C)
-
-#define DAINT_OutEP_SHIFT (16)
-#define DAINT_OutEP(x) (1 << ((x) + 16))
-#define DAINT_InEP(x) (1 << (x))
-
-#define DTKNQR1 HSOTG_REG(0x820)
-#define DTKNQR2 HSOTG_REG(0x824)
-#define DTKNQR3 HSOTG_REG(0x830)
-#define DTKNQR4 HSOTG_REG(0x834)
-
-#define DVBUSDIS HSOTG_REG(0x828)
-#define DVBUSPULSE HSOTG_REG(0x82C)
-
-#define DIEPCTL0 HSOTG_REG(0x900)
-#define DOEPCTL0 HSOTG_REG(0xB00)
-#define DIEPCTL(_a) HSOTG_REG(0x900 + ((_a) * 0x20))
-#define DOEPCTL(_a) HSOTG_REG(0xB00 + ((_a) * 0x20))
-
-/* EP0 specialness:
- * bits[29..28] - reserved (no SetD0PID, SetD1PID)
- * bits[25..22] - should always be zero, this isn't a periodic endpoint
- * bits[10..0] - MPS setting differenct for EP0
- */
-#define D0EPCTL_MPS_MASK (0x3 << 0)
-#define D0EPCTL_MPS_SHIFT (0)
-#define D0EPCTL_MPS_64 (0x0 << 0)
-#define D0EPCTL_MPS_32 (0x1 << 0)
-#define D0EPCTL_MPS_16 (0x2 << 0)
-#define D0EPCTL_MPS_8 (0x3 << 0)
-
-#define DxEPCTL_EPEna (1 << 31)
-#define DxEPCTL_EPDis (1 << 30)
-#define DxEPCTL_SetD1PID (1 << 29)
-#define DxEPCTL_SetOddFr (1 << 29)
-#define DxEPCTL_SetD0PID (1 << 28)
-#define DxEPCTL_SetEvenFr (1 << 28)
-#define DxEPCTL_SNAK (1 << 27)
-#define DxEPCTL_CNAK (1 << 26)
-#define DxEPCTL_TxFNum_MASK (0xf << 22)
-#define DxEPCTL_TxFNum_SHIFT (22)
-#define DxEPCTL_TxFNum_LIMIT (0xf)
-#define DxEPCTL_TxFNum(_x) ((_x) << 22)
-
-#define DxEPCTL_Stall (1 << 21)
-#define DxEPCTL_Snp (1 << 20)
-#define DxEPCTL_EPType_MASK (0x3 << 18)
-#define DxEPCTL_EPType_SHIFT (18)
-#define DxEPCTL_EPType_Control (0x0 << 18)
-#define DxEPCTL_EPType_Iso (0x1 << 18)
-#define DxEPCTL_EPType_Bulk (0x2 << 18)
-#define DxEPCTL_EPType_Intterupt (0x3 << 18)
-
-#define DxEPCTL_NAKsts (1 << 17)
-#define DxEPCTL_DPID (1 << 16)
-#define DxEPCTL_EOFrNum (1 << 16)
-#define DxEPCTL_USBActEp (1 << 15)
-#define DxEPCTL_NextEp_MASK (0xf << 11)
-#define DxEPCTL_NextEp_SHIFT (11)
-#define DxEPCTL_NextEp_LIMIT (0xf)
-#define DxEPCTL_NextEp(_x) ((_x) << 11)
-
-#define DxEPCTL_MPS_MASK (0x7ff << 0)
-#define DxEPCTL_MPS_SHIFT (0)
-#define DxEPCTL_MPS_LIMIT (0x7ff)
-#define DxEPCTL_MPS(_x) ((_x) << 0)
-
-#define DIEPINT(_a) HSOTG_REG(0x908 + ((_a) * 0x20))
-#define DOEPINT(_a) HSOTG_REG(0xB08 + ((_a) * 0x20))
-
-#define DxEPINT_INEPNakEff (1 << 6)
-#define DxEPINT_Back2BackSetup (1 << 6)
-#define DxEPINT_INTknEPMis (1 << 5)
-#define DxEPINT_INTknTXFEmp (1 << 4)
-#define DxEPINT_OUTTknEPdis (1 << 4)
-#define DxEPINT_Timeout (1 << 3)
-#define DxEPINT_Setup (1 << 3)
-#define DxEPINT_AHBErr (1 << 2)
-#define DxEPINT_EPDisbld (1 << 1)
-#define DxEPINT_XferCompl (1 << 0)
-
-#define DIEPTSIZ0 HSOTG_REG(0x910)
-
-#define DIEPTSIZ0_PktCnt_MASK (0x3 << 19)
-#define DIEPTSIZ0_PktCnt_SHIFT (19)
-#define DIEPTSIZ0_PktCnt_LIMIT (0x3)
-#define DIEPTSIZ0_PktCnt(_x) ((_x) << 19)
-
-#define DIEPTSIZ0_XferSize_MASK (0x7f << 0)
-#define DIEPTSIZ0_XferSize_SHIFT (0)
-#define DIEPTSIZ0_XferSize_LIMIT (0x7f)
-#define DIEPTSIZ0_XferSize(_x) ((_x) << 0)
-
-#define DOEPTSIZ0 HSOTG_REG(0xB10)
-#define DOEPTSIZ0_SUPCnt_MASK (0x3 << 29)
-#define DOEPTSIZ0_SUPCnt_SHIFT (29)
-#define DOEPTSIZ0_SUPCnt_LIMIT (0x3)
-#define DOEPTSIZ0_SUPCnt(_x) ((_x) << 29)
-
-#define DOEPTSIZ0_PktCnt (1 << 19)
-#define DOEPTSIZ0_XferSize_MASK (0x7f << 0)
-#define DOEPTSIZ0_XferSize_SHIFT (0)
-
-#define DIEPTSIZ(_a) HSOTG_REG(0x910 + ((_a) * 0x20))
-#define DOEPTSIZ(_a) HSOTG_REG(0xB10 + ((_a) * 0x20))
-
-#define DxEPTSIZ_MC_MASK (0x3 << 29)
-#define DxEPTSIZ_MC_SHIFT (29)
-#define DxEPTSIZ_MC_LIMIT (0x3)
-#define DxEPTSIZ_MC(_x) ((_x) << 29)
-
-#define DxEPTSIZ_PktCnt_MASK (0x3ff << 19)
-#define DxEPTSIZ_PktCnt_SHIFT (19)
-#define DxEPTSIZ_PktCnt_GET(_v) (((_v) >> 19) & 0x3ff)
-#define DxEPTSIZ_PktCnt_LIMIT (0x3ff)
-#define DxEPTSIZ_PktCnt(_x) ((_x) << 19)
-
-#define DxEPTSIZ_XferSize_MASK (0x7ffff << 0)
-#define DxEPTSIZ_XferSize_SHIFT (0)
-#define DxEPTSIZ_XferSize_GET(_v) (((_v) >> 0) & 0x7ffff)
-#define DxEPTSIZ_XferSize_LIMIT (0x7ffff)
-#define DxEPTSIZ_XferSize(_x) ((_x) << 0)
-
-#define DIEPDMA(_a) HSOTG_REG(0x914 + ((_a) * 0x20))
-#define DOEPDMA(_a) HSOTG_REG(0xB14 + ((_a) * 0x20))
-#define DTXFSTS(_a) HSOTG_REG(0x918 + ((_a) * 0x20))
-
-#define EPFIFO(_a) HSOTG_REG(0x1000 + ((_a) * 0x1000))
-
-#endif /* __REGS_USB_HSOTG_H */
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c
index dd9678f85c58..7987aa049fab 100644
--- a/drivers/usb/gadget/s3c2410_udc.c
+++ b/drivers/usb/gadget/s3c2410_udc.c
@@ -117,7 +117,8 @@ static int dprintk(int level, const char *fmt, ...)
sizeof(printk_buf)-len, fmt, args);
va_end(args);
- return pr_debug("%s", printk_buf);
+ pr_debug("%s", printk_buf);
+ return len;
}
#else
static int dprintk(int level, const char *fmt, ...)
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index ec20a1f50c2d..ff205a7bc55c 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -43,7 +43,7 @@ struct usb_interface_descriptor fsg_intf_desc = {
.bInterfaceProtocol = USB_PR_BULK, /* Adjusted during fsg_bind() */
.iInterface = FSG_STRING_INTERFACE,
};
-EXPORT_SYMBOL(fsg_intf_desc);
+EXPORT_SYMBOL_GPL(fsg_intf_desc);
/*
* Three full-speed endpoint descriptors: bulk-in, bulk-out, and
@@ -58,7 +58,7 @@ struct usb_endpoint_descriptor fsg_fs_bulk_in_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
/* wMaxPacketSize set by autoconfiguration */
};
-EXPORT_SYMBOL(fsg_fs_bulk_in_desc);
+EXPORT_SYMBOL_GPL(fsg_fs_bulk_in_desc);
struct usb_endpoint_descriptor fsg_fs_bulk_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
@@ -68,7 +68,7 @@ struct usb_endpoint_descriptor fsg_fs_bulk_out_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
/* wMaxPacketSize set by autoconfiguration */
};
-EXPORT_SYMBOL(fsg_fs_bulk_out_desc);
+EXPORT_SYMBOL_GPL(fsg_fs_bulk_out_desc);
struct usb_descriptor_header *fsg_fs_function[] = {
(struct usb_descriptor_header *) &fsg_intf_desc,
@@ -76,7 +76,7 @@ struct usb_descriptor_header *fsg_fs_function[] = {
(struct usb_descriptor_header *) &fsg_fs_bulk_out_desc,
NULL,
};
-EXPORT_SYMBOL(fsg_fs_function);
+EXPORT_SYMBOL_GPL(fsg_fs_function);
/*
@@ -95,7 +95,7 @@ struct usb_endpoint_descriptor fsg_hs_bulk_in_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(512),
};
-EXPORT_SYMBOL(fsg_hs_bulk_in_desc);
+EXPORT_SYMBOL_GPL(fsg_hs_bulk_in_desc);
struct usb_endpoint_descriptor fsg_hs_bulk_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
@@ -106,7 +106,7 @@ struct usb_endpoint_descriptor fsg_hs_bulk_out_desc = {
.wMaxPacketSize = cpu_to_le16(512),
.bInterval = 1, /* NAK every 1 uframe */
};
-EXPORT_SYMBOL(fsg_hs_bulk_out_desc);
+EXPORT_SYMBOL_GPL(fsg_hs_bulk_out_desc);
struct usb_descriptor_header *fsg_hs_function[] = {
@@ -115,7 +115,7 @@ struct usb_descriptor_header *fsg_hs_function[] = {
(struct usb_descriptor_header *) &fsg_hs_bulk_out_desc,
NULL,
};
-EXPORT_SYMBOL(fsg_hs_function);
+EXPORT_SYMBOL_GPL(fsg_hs_function);
struct usb_endpoint_descriptor fsg_ss_bulk_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
@@ -125,7 +125,7 @@ struct usb_endpoint_descriptor fsg_ss_bulk_in_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
-EXPORT_SYMBOL(fsg_ss_bulk_in_desc);
+EXPORT_SYMBOL_GPL(fsg_ss_bulk_in_desc);
struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = {
.bLength = sizeof(fsg_ss_bulk_in_comp_desc),
@@ -133,7 +133,7 @@ struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = {
/*.bMaxBurst = DYNAMIC, */
};
-EXPORT_SYMBOL(fsg_ss_bulk_in_comp_desc);
+EXPORT_SYMBOL_GPL(fsg_ss_bulk_in_comp_desc);
struct usb_endpoint_descriptor fsg_ss_bulk_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
@@ -143,7 +143,7 @@ struct usb_endpoint_descriptor fsg_ss_bulk_out_desc = {
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(1024),
};
-EXPORT_SYMBOL(fsg_ss_bulk_out_desc);
+EXPORT_SYMBOL_GPL(fsg_ss_bulk_out_desc);
struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {
.bLength = sizeof(fsg_ss_bulk_in_comp_desc),
@@ -151,7 +151,7 @@ struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = {
/*.bMaxBurst = DYNAMIC, */
};
-EXPORT_SYMBOL(fsg_ss_bulk_out_comp_desc);
+EXPORT_SYMBOL_GPL(fsg_ss_bulk_out_comp_desc);
struct usb_descriptor_header *fsg_ss_function[] = {
(struct usb_descriptor_header *) &fsg_intf_desc,
@@ -161,7 +161,7 @@ struct usb_descriptor_header *fsg_ss_function[] = {
(struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc,
NULL,
};
-EXPORT_SYMBOL(fsg_ss_function);
+EXPORT_SYMBOL_GPL(fsg_ss_function);
/*-------------------------------------------------------------------------*/
@@ -179,7 +179,7 @@ void fsg_lun_close(struct fsg_lun *curlun)
curlun->filp = NULL;
}
}
-EXPORT_SYMBOL(fsg_lun_close);
+EXPORT_SYMBOL_GPL(fsg_lun_close);
int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
{
@@ -278,7 +278,7 @@ out:
fput(filp);
return rc;
}
-EXPORT_SYMBOL(fsg_lun_open);
+EXPORT_SYMBOL_GPL(fsg_lun_open);
/*-------------------------------------------------------------------------*/
@@ -295,7 +295,7 @@ int fsg_lun_fsync_sub(struct fsg_lun *curlun)
return 0;
return vfs_fsync(filp, 1);
}
-EXPORT_SYMBOL(fsg_lun_fsync_sub);
+EXPORT_SYMBOL_GPL(fsg_lun_fsync_sub);
void store_cdrom_address(u8 *dest, int msf, u32 addr)
{
@@ -314,7 +314,7 @@ void store_cdrom_address(u8 *dest, int msf, u32 addr)
put_unaligned_be32(addr, dest);
}
}
-EXPORT_SYMBOL(store_cdrom_address);
+EXPORT_SYMBOL_GPL(store_cdrom_address);
/*-------------------------------------------------------------------------*/
@@ -325,13 +325,13 @@ ssize_t fsg_show_ro(struct fsg_lun *curlun, char *buf)
? curlun->ro
: curlun->initially_ro);
}
-EXPORT_SYMBOL(fsg_show_ro);
+EXPORT_SYMBOL_GPL(fsg_show_ro);
ssize_t fsg_show_nofua(struct fsg_lun *curlun, char *buf)
{
return sprintf(buf, "%u\n", curlun->nofua);
}
-EXPORT_SYMBOL(fsg_show_nofua);
+EXPORT_SYMBOL_GPL(fsg_show_nofua);
ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
char *buf)
@@ -357,19 +357,19 @@ ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
up_read(filesem);
return rc;
}
-EXPORT_SYMBOL(fsg_show_file);
+EXPORT_SYMBOL_GPL(fsg_show_file);
ssize_t fsg_show_cdrom(struct fsg_lun *curlun, char *buf)
{
return sprintf(buf, "%u\n", curlun->cdrom);
}
-EXPORT_SYMBOL(fsg_show_cdrom);
+EXPORT_SYMBOL_GPL(fsg_show_cdrom);
ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf)
{
return sprintf(buf, "%u\n", curlun->removable);
}
-EXPORT_SYMBOL(fsg_show_removable);
+EXPORT_SYMBOL_GPL(fsg_show_removable);
/*
* The caller must hold fsg->filesem for reading when calling this function.
@@ -410,7 +410,7 @@ ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem,
return rc;
}
-EXPORT_SYMBOL(fsg_store_ro);
+EXPORT_SYMBOL_GPL(fsg_store_ro);
ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count)
{
@@ -429,7 +429,7 @@ ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count)
return count;
}
-EXPORT_SYMBOL(fsg_store_nofua);
+EXPORT_SYMBOL_GPL(fsg_store_nofua);
ssize_t fsg_store_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
const char *buf, size_t count)
@@ -460,7 +460,7 @@ ssize_t fsg_store_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
up_write(filesem);
return (rc < 0 ? rc : count);
}
-EXPORT_SYMBOL(fsg_store_file);
+EXPORT_SYMBOL_GPL(fsg_store_file);
ssize_t fsg_store_cdrom(struct fsg_lun *curlun, struct rw_semaphore *filesem,
const char *buf, size_t count)
@@ -483,7 +483,7 @@ ssize_t fsg_store_cdrom(struct fsg_lun *curlun, struct rw_semaphore *filesem,
return ret;
}
-EXPORT_SYMBOL(fsg_store_cdrom);
+EXPORT_SYMBOL_GPL(fsg_store_cdrom);
ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf,
size_t count)
@@ -499,6 +499,6 @@ ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf,
return count;
}
-EXPORT_SYMBOL(fsg_store_removable);
+EXPORT_SYMBOL_GPL(fsg_store_removable);
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c
index f058c0368d61..49481e0a3382 100644
--- a/drivers/usb/gadget/tcm_usb_gadget.c
+++ b/drivers/usb/gadget/tcm_usb_gadget.c
@@ -1383,10 +1383,8 @@ static struct se_node_acl *usbg_alloc_fabric_acl(struct se_portal_group *se_tpg)
struct usbg_nacl *nacl;
nacl = kzalloc(sizeof(struct usbg_nacl), GFP_KERNEL);
- if (!nacl) {
- printk(KERN_ERR "Unable to allocate struct usbg_nacl\n");
+ if (!nacl)
return NULL;
- }
return &nacl->se_node_acl;
}
@@ -1561,10 +1559,8 @@ static struct se_portal_group *usbg_make_tpg(
}
tpg = kzalloc(sizeof(struct usbg_tpg), GFP_KERNEL);
- if (!tpg) {
- printk(KERN_ERR "Unable to allocate struct usbg_tpg");
+ if (!tpg)
return ERR_PTR(-ENOMEM);
- }
mutex_init(&tpg->tpg_mutex);
atomic_set(&tpg->tpg_port_count, 0);
tpg->workqueue = alloc_workqueue("tcm_usb_gadget", 0, 1);
@@ -1613,10 +1609,8 @@ static struct se_wwn *usbg_make_tport(
return ERR_PTR(-EINVAL);
tport = kzalloc(sizeof(struct usbg_tport), GFP_KERNEL);
- if (!(tport)) {
- printk(KERN_ERR "Unable to allocate struct usbg_tport");
+ if (!(tport))
return ERR_PTR(-ENOMEM);
- }
tport->tport_wwpn = wwpn;
snprintf(tport->tport_name, sizeof(tport->tport_name), "%s", wnn_name);
return &tport->tport_wwn;
@@ -1727,10 +1721,8 @@ static int tcm_usbg_make_nexus(struct usbg_tpg *tpg, char *name)
ret = -ENOMEM;
tv_nexus = kzalloc(sizeof(*tv_nexus), GFP_KERNEL);
- if (!tv_nexus) {
- pr_err("Unable to allocate struct tcm_vhost_nexus\n");
+ if (!tv_nexus)
goto err_unlock;
- }
tv_nexus->tvn_se_sess = transport_init_session(TARGET_PROT_NORMAL);
if (IS_ERR(tv_nexus->tvn_se_sess))
goto err_free;
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c
index b7d4f82872b7..fe0880d0873e 100644
--- a/drivers/usb/gadget/u_ether.c
+++ b/drivers/usb/gadget/u_ether.c
@@ -818,7 +818,7 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g,
return dev;
}
-EXPORT_SYMBOL(gether_setup_name);
+EXPORT_SYMBOL_GPL(gether_setup_name);
struct net_device *gether_setup_name_default(const char *netname)
{
@@ -855,7 +855,7 @@ struct net_device *gether_setup_name_default(const char *netname)
return net;
}
-EXPORT_SYMBOL(gether_setup_name_default);
+EXPORT_SYMBOL_GPL(gether_setup_name_default);
int gether_register_netdev(struct net_device *net)
{
@@ -893,7 +893,7 @@ int gether_register_netdev(struct net_device *net)
return status;
}
-EXPORT_SYMBOL(gether_register_netdev);
+EXPORT_SYMBOL_GPL(gether_register_netdev);
void gether_set_gadget(struct net_device *net, struct usb_gadget *g)
{
@@ -903,7 +903,7 @@ void gether_set_gadget(struct net_device *net, struct usb_gadget *g)
dev->gadget = g;
SET_NETDEV_DEV(net, &g->dev);
}
-EXPORT_SYMBOL(gether_set_gadget);
+EXPORT_SYMBOL_GPL(gether_set_gadget);
int gether_set_dev_addr(struct net_device *net, const char *dev_addr)
{
@@ -916,7 +916,7 @@ int gether_set_dev_addr(struct net_device *net, const char *dev_addr)
memcpy(dev->dev_mac, new_addr, ETH_ALEN);
return 0;
}
-EXPORT_SYMBOL(gether_set_dev_addr);
+EXPORT_SYMBOL_GPL(gether_set_dev_addr);
int gether_get_dev_addr(struct net_device *net, char *dev_addr, int len)
{
@@ -925,7 +925,7 @@ int gether_get_dev_addr(struct net_device *net, char *dev_addr, int len)
dev = netdev_priv(net);
return get_ether_addr_str(dev->dev_mac, dev_addr, len);
}
-EXPORT_SYMBOL(gether_get_dev_addr);
+EXPORT_SYMBOL_GPL(gether_get_dev_addr);
int gether_set_host_addr(struct net_device *net, const char *host_addr)
{
@@ -938,7 +938,7 @@ int gether_set_host_addr(struct net_device *net, const char *host_addr)
memcpy(dev->host_mac, new_addr, ETH_ALEN);
return 0;
}
-EXPORT_SYMBOL(gether_set_host_addr);
+EXPORT_SYMBOL_GPL(gether_set_host_addr);
int gether_get_host_addr(struct net_device *net, char *host_addr, int len)
{
@@ -947,7 +947,7 @@ int gether_get_host_addr(struct net_device *net, char *host_addr, int len)
dev = netdev_priv(net);
return get_ether_addr_str(dev->host_mac, host_addr, len);
}
-EXPORT_SYMBOL(gether_get_host_addr);
+EXPORT_SYMBOL_GPL(gether_get_host_addr);
int gether_get_host_addr_cdc(struct net_device *net, char *host_addr, int len)
{
@@ -961,7 +961,7 @@ int gether_get_host_addr_cdc(struct net_device *net, char *host_addr, int len)
return strlen(host_addr);
}
-EXPORT_SYMBOL(gether_get_host_addr_cdc);
+EXPORT_SYMBOL_GPL(gether_get_host_addr_cdc);
void gether_get_host_addr_u8(struct net_device *net, u8 host_mac[ETH_ALEN])
{
@@ -970,7 +970,7 @@ void gether_get_host_addr_u8(struct net_device *net, u8 host_mac[ETH_ALEN])
dev = netdev_priv(net);
memcpy(host_mac, dev->host_mac, ETH_ALEN);
}
-EXPORT_SYMBOL(gether_get_host_addr_u8);
+EXPORT_SYMBOL_GPL(gether_get_host_addr_u8);
void gether_set_qmult(struct net_device *net, unsigned qmult)
{
@@ -979,7 +979,7 @@ void gether_set_qmult(struct net_device *net, unsigned qmult)
dev = netdev_priv(net);
dev->qmult = qmult;
}
-EXPORT_SYMBOL(gether_set_qmult);
+EXPORT_SYMBOL_GPL(gether_set_qmult);
unsigned gether_get_qmult(struct net_device *net)
{
@@ -988,7 +988,7 @@ unsigned gether_get_qmult(struct net_device *net)
dev = netdev_priv(net);
return dev->qmult;
}
-EXPORT_SYMBOL(gether_get_qmult);
+EXPORT_SYMBOL_GPL(gether_get_qmult);
int gether_get_ifname(struct net_device *net, char *name, int len)
{
@@ -997,7 +997,7 @@ int gether_get_ifname(struct net_device *net, char *name, int len)
rtnl_unlock();
return strlen(name);
}
-EXPORT_SYMBOL(gether_get_ifname);
+EXPORT_SYMBOL_GPL(gether_get_ifname);
/**
* gether_cleanup - remove Ethernet-over-USB device
@@ -1014,7 +1014,7 @@ void gether_cleanup(struct eth_dev *dev)
flush_work(&dev->work);
free_netdev(dev->net);
}
-EXPORT_SYMBOL(gether_cleanup);
+EXPORT_SYMBOL_GPL(gether_cleanup);
/**
* gether_connect - notify network layer that USB link is active
@@ -1095,7 +1095,7 @@ fail0:
return ERR_PTR(result);
return dev->net;
}
-EXPORT_SYMBOL(gether_connect);
+EXPORT_SYMBOL_GPL(gether_connect);
/**
* gether_disconnect - notify network layer that USB link is inactive
@@ -1166,7 +1166,7 @@ void gether_disconnect(struct gether *link)
dev->port_usb = NULL;
spin_unlock(&dev->lock);
}
-EXPORT_SYMBOL(gether_disconnect);
+EXPORT_SYMBOL_GPL(gether_disconnect);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Brownell");
diff --git a/drivers/usb/gadget/u_f.c b/drivers/usb/gadget/u_f.c
index 63b6642c162b..c6276f0268ae 100644
--- a/drivers/usb/gadget/u_f.c
+++ b/drivers/usb/gadget/u_f.c
@@ -29,4 +29,4 @@ struct usb_request *alloc_ep_req(struct usb_ep *ep, int len, int default_len)
}
return req;
}
-EXPORT_SYMBOL(alloc_ep_req);
+EXPORT_SYMBOL_GPL(alloc_ep_req);
diff --git a/drivers/usb/gadget/u_f.h b/drivers/usb/gadget/u_f.h
index 71034c061fca..1d5f0eb68552 100644
--- a/drivers/usb/gadget/u_f.h
+++ b/drivers/usb/gadget/u_f.h
@@ -16,6 +16,32 @@
#ifndef __U_F_H__
#define __U_F_H__
+/* Variable Length Array Macros **********************************************/
+#define vla_group(groupname) size_t groupname##__next = 0
+#define vla_group_size(groupname) groupname##__next
+
+#define vla_item(groupname, type, name, n) \
+ size_t groupname##_##name##__offset = ({ \
+ size_t align_mask = __alignof__(type) - 1; \
+ size_t offset = (groupname##__next + align_mask) & ~align_mask;\
+ size_t size = (n) * sizeof(type); \
+ groupname##__next = offset + size; \
+ offset; \
+ })
+
+#define vla_item_with_sz(groupname, type, name, n) \
+ size_t groupname##_##name##__sz = (n) * sizeof(type); \
+ size_t groupname##_##name##__offset = ({ \
+ size_t align_mask = __alignof__(type) - 1; \
+ size_t offset = (groupname##__next + align_mask) & ~align_mask;\
+ size_t size = groupname##_##name##__sz; \
+ groupname##__next = offset + size; \
+ offset; \
+ })
+
+#define vla_ptr(ptr, groupname, name) \
+ ((void *) ((char *)ptr + groupname##_##name##__offset))
+
struct usb_ep;
struct usb_request;
diff --git a/drivers/usb/gadget/u_os_desc.h b/drivers/usb/gadget/u_os_desc.h
new file mode 100644
index 000000000000..ea5cf8c2da28
--- /dev/null
+++ b/drivers/usb/gadget/u_os_desc.h
@@ -0,0 +1,90 @@
+/*
+ * u_os_desc.h
+ *
+ * Utility definitions for "OS Descriptors" support
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * 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 __U_OS_DESC_H__
+#define __U_OS_DESC_H__
+
+#include <asm/unaligned.h>
+#include <linux/nls.h>
+
+#define USB_EXT_PROP_DW_SIZE 0
+#define USB_EXT_PROP_DW_PROPERTY_DATA_TYPE 4
+#define USB_EXT_PROP_W_PROPERTY_NAME_LENGTH 8
+#define USB_EXT_PROP_B_PROPERTY_NAME 10
+#define USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH 10
+#define USB_EXT_PROP_B_PROPERTY_DATA 14
+
+#define USB_EXT_PROP_RESERVED 0
+#define USB_EXT_PROP_UNICODE 1
+#define USB_EXT_PROP_UNICODE_ENV 2
+#define USB_EXT_PROP_BINARY 3
+#define USB_EXT_PROP_LE32 4
+#define USB_EXT_PROP_BE32 5
+#define USB_EXT_PROP_UNICODE_LINK 6
+#define USB_EXT_PROP_UNICODE_MULTI 7
+
+static inline void usb_ext_prop_put_size(u8 *buf, int dw_size)
+{
+ put_unaligned_le32(dw_size, &buf[USB_EXT_PROP_DW_SIZE]);
+}
+
+static inline void usb_ext_prop_put_type(u8 *buf, int type)
+{
+ put_unaligned_le32(type, &buf[USB_EXT_PROP_DW_PROPERTY_DATA_TYPE]);
+}
+
+static inline int usb_ext_prop_put_name(u8 *buf, const char *name, int pnl)
+{
+ int result;
+
+ put_unaligned_le16(pnl, &buf[USB_EXT_PROP_W_PROPERTY_NAME_LENGTH]);
+ result = utf8s_to_utf16s(name, strlen(name), UTF16_LITTLE_ENDIAN,
+ (wchar_t *) &buf[USB_EXT_PROP_B_PROPERTY_NAME], pnl - 2);
+ if (result < 0)
+ return result;
+
+ put_unaligned_le16(0, &buf[USB_EXT_PROP_B_PROPERTY_NAME + pnl]);
+
+ return pnl;
+}
+
+static inline void usb_ext_prop_put_binary(u8 *buf, int pnl, const u8 *data,
+ int data_len)
+{
+ put_unaligned_le32(data_len,
+ &buf[USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + pnl]);
+ memcpy(&buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl], data, data_len);
+}
+
+static inline int usb_ext_prop_put_unicode(u8 *buf, int pnl, const char *string,
+ int data_len)
+{
+ int result;
+ put_unaligned_le32(data_len,
+ &buf[USB_EXT_PROP_DW_PROPERTY_DATA_LENGTH + pnl]);
+
+ result = utf8s_to_utf16s(string, data_len >> 1, UTF16_LITTLE_ENDIAN,
+ (wchar_t *) &buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl],
+ data_len - 2);
+ if (result < 0)
+ return result;
+
+ put_unaligned_le16(0,
+ &buf[USB_EXT_PROP_B_PROPERTY_DATA + pnl + data_len]);
+
+ return data_len;
+}
+
+#endif /* __U_OS_DESC_H__ */
diff --git a/drivers/usb/gadget/u_rndis.h b/drivers/usb/gadget/u_rndis.h
index 7291b15c9dce..e902aa42a297 100644
--- a/drivers/usb/gadget/u_rndis.h
+++ b/drivers/usb/gadget/u_rndis.h
@@ -26,6 +26,9 @@ struct f_rndis_opts {
bool bound;
bool borrowed_net;
+ struct usb_os_desc rndis_os_desc;
+ char rndis_ext_compat_id[16];
+
/*
* Read/write access to configfs attributes is handled by configfs.
*
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index 27768a7d986a..b0d98172bc07 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc-core.c
@@ -428,6 +428,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
list_for_each_entry(udc, &udc_list, list)
if (udc->driver == driver) {
usb_gadget_remove_driver(udc);
+ usb_gadget_set_state(udc->gadget,
+ USB_STATE_NOTATTACHED);
ret = 0;
break;
}
diff --git a/drivers/usb/gadget/uvc_queue.c b/drivers/usb/gadget/uvc_queue.c
index 0bb5d50075de..1c29bc954db9 100644
--- a/drivers/usb/gadget/uvc_queue.c
+++ b/drivers/usb/gadget/uvc_queue.c
@@ -20,6 +20,7 @@
#include <linux/vmalloc.h>
#include <linux/wait.h>
+#include <media/v4l2-common.h>
#include <media/videobuf2-vmalloc.h>
#include "uvc.h"
@@ -136,6 +137,8 @@ static int uvc_queue_init(struct uvc_video_queue *queue,
queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
queue->queue.ops = &uvc_queue_qops;
queue->queue.mem_ops = &vb2_vmalloc_memops;
+ queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
+ | V4L2_BUF_FLAG_TSTAMP_SRC_EOF;
ret = vb2_queue_init(&queue->queue);
if (ret)
return ret;
@@ -379,14 +382,9 @@ static struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
else
nextbuf = NULL;
- /*
- * 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.field = V4L2_FIELD_NONE;
buf->buf.v4l2_buf.sequence = queue->sequence++;
- do_gettimeofday(&buf->buf.v4l2_buf.timestamp);
+ v4l2_get_timestamp(&buf->buf.v4l2_buf.timestamp);
vb2_set_plane_payload(&buf->buf, 0, buf->bytesused);
vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE);
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 3d9e54062d62..61b7817bd66b 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -29,6 +29,14 @@ if USB_XHCI_HCD
config USB_XHCI_PLATFORM
tristate
+config USB_XHCI_MVEBU
+ tristate "xHCI support for Marvell Armada 375/38x"
+ select USB_XHCI_PLATFORM
+ depends on ARCH_MVEBU || COMPILE_TEST
+ ---help---
+ Say 'Y' to enable the support for the xHCI host controller
+ found in Marvell Armada 375/38x ARM SOCs.
+
endif # USB_XHCI_HCD
config USB_EHCI_HCD
@@ -170,7 +178,6 @@ config USB_EHCI_MSM
tristate "Support for Qualcomm QSD/MSM on-chip EHCI USB controller"
depends on ARCH_MSM
select USB_EHCI_ROOT_HUB_TT
- select USB_MSM_OTG
---help---
Enables support for the USB Host controller present on the
Qualcomm chipsets. Root Hub has inbuilt TT.
@@ -343,10 +350,19 @@ config USB_FOTG210_HCD
To compile this driver as a module, choose M here: the
module will be called fotg210-hcd.
+config USB_MAX3421_HCD
+ tristate "MAX3421 HCD (USB-over-SPI) support"
+ depends on USB && SPI
+ ---help---
+ The Maxim MAX3421E chip supports standard USB 2.0-compliant
+ full-speed devices either in host or peripheral mode. This
+ driver supports the host-mode of the MAX3421E only.
+
+ To compile this driver as a module, choose M here: the module will
+ be called max3421-hcd.
+
config USB_OHCI_HCD
tristate "OHCI HCD (USB 1.1) support"
- select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
- depends on USB_ISP1301 || !ARCH_LPC32XX
---help---
The Open Host Controller Interface (OHCI) is a standard for accessing
USB 1.1 host controller hardware. It does more in hardware than Intel's
@@ -365,6 +381,7 @@ if USB_OHCI_HCD
config USB_OHCI_HCD_OMAP1
tristate "OHCI support for OMAP1/2 chips"
depends on ARCH_OMAP1
+ depends on ISP1301_OMAP || !(MACH_OMAP_H2 || MACH_OMAP_H3)
default y
---help---
Enables support for the OHCI controller on OMAP1/2 chips.
@@ -388,6 +405,7 @@ config USB_OHCI_HCD_S3C2410
config USB_OHCI_HCD_LPC32XX
tristate "Support for LPC on-chip OHCI USB controller"
depends on USB_OHCI_HCD && ARCH_LPC32XX
+ depends on USB_ISP1301
default y
---help---
Enables support for the on-chip OHCI controller on
@@ -417,6 +435,16 @@ config USB_OHCI_HCD_OMAP3
Enables support for the on-chip OHCI controller on
OMAP3 and later chips.
+config USB_OHCI_HCD_DAVINCI
+ bool "OHCI support for TI DaVinci DA8xx"
+ depends on ARCH_DAVINCI_DA8XX
+ depends on USB_OHCI_HCD=y
+ default y
+ help
+ Enables support for the DaVinci DA8xx integrated OHCI
+ controller. This driver cannot currently be a loadable
+ module because it lacks a proper PHY abstraction.
+
config USB_OHCI_ATH79
bool "USB OHCI support for the Atheros AR71XX/AR7240 SoCs (DEPRECATED)"
depends on (SOC_AR71XX || SOC_AR724X)
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 7530468c9a4f..af89a903d97e 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -19,6 +19,9 @@ xhci-hcd-$(CONFIG_PCI) += xhci-pci.o
ifneq ($(CONFIG_USB_XHCI_PLATFORM), )
xhci-hcd-y += xhci-plat.o
+ifneq ($(CONFIG_USB_XHCI_MVEBU), )
+ xhci-hcd-y += xhci-mvebu.o
+endif
endif
obj-$(CONFIG_USB_WHCI_HCD) += whci/
@@ -70,3 +73,4 @@ obj-$(CONFIG_USB_HCD_BCMA) += bcma-hcd.o
obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o
obj-$(CONFIG_USB_FUSBH200_HCD) += fusbh200-hcd.o
obj-$(CONFIG_USB_FOTG210_HCD) += fotg210-hcd.o
+obj-$(CONFIG_USB_MAX3421_HCD) += max3421-hcd.o
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index 7f425acd9be5..d1c76216350f 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
+#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/usb/phy.h>
#include <linux/usb/samsung_usb_phy.h>
@@ -42,17 +43,106 @@
static const char hcd_name[] = "ehci-exynos";
static struct hc_driver __read_mostly exynos_ehci_hc_driver;
+#define PHY_NUMBER 3
+
struct exynos_ehci_hcd {
struct clk *clk;
struct usb_phy *phy;
struct usb_otg *otg;
+ struct phy *phy_g[PHY_NUMBER];
};
#define to_exynos_ehci(hcd) (struct exynos_ehci_hcd *)(hcd_to_ehci(hcd)->priv)
-static void exynos_setup_vbus_gpio(struct platform_device *pdev)
+static int exynos_ehci_get_phy(struct device *dev,
+ struct exynos_ehci_hcd *exynos_ehci)
+{
+ struct device_node *child;
+ struct phy *phy;
+ int phy_number;
+ int ret = 0;
+
+ exynos_ehci->phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+ if (IS_ERR(exynos_ehci->phy)) {
+ ret = PTR_ERR(exynos_ehci->phy);
+ if (ret != -ENXIO && ret != -ENODEV) {
+ dev_err(dev, "no usb2 phy configured\n");
+ return ret;
+ }
+ dev_dbg(dev, "Failed to get usb2 phy\n");
+ } else {
+ exynos_ehci->otg = exynos_ehci->phy->otg;
+ }
+
+ for_each_available_child_of_node(dev->of_node, child) {
+ ret = of_property_read_u32(child, "reg", &phy_number);
+ if (ret) {
+ dev_err(dev, "Failed to parse device tree\n");
+ of_node_put(child);
+ return ret;
+ }
+
+ if (phy_number >= PHY_NUMBER) {
+ dev_err(dev, "Invalid number of PHYs\n");
+ of_node_put(child);
+ return -EINVAL;
+ }
+
+ phy = devm_of_phy_get(dev, child, 0);
+ of_node_put(child);
+ if (IS_ERR(phy)) {
+ ret = PTR_ERR(phy);
+ if (ret != -ENOSYS && ret != -ENODEV) {
+ dev_err(dev, "no usb2 phy configured\n");
+ return ret;
+ }
+ dev_dbg(dev, "Failed to get usb2 phy\n");
+ }
+ exynos_ehci->phy_g[phy_number] = phy;
+ }
+
+ return ret;
+}
+
+static int exynos_ehci_phy_enable(struct device *dev)
+{
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd);
+ int i;
+ int ret = 0;
+
+ if (!IS_ERR(exynos_ehci->phy))
+ return usb_phy_init(exynos_ehci->phy);
+
+ for (i = 0; ret == 0 && i < PHY_NUMBER; i++)
+ if (!IS_ERR(exynos_ehci->phy_g[i]))
+ ret = phy_power_on(exynos_ehci->phy_g[i]);
+ if (ret)
+ for (i--; i >= 0; i--)
+ if (!IS_ERR(exynos_ehci->phy_g[i]))
+ phy_power_off(exynos_ehci->phy_g[i]);
+
+ return ret;
+}
+
+static void exynos_ehci_phy_disable(struct device *dev)
+{
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd);
+ int i;
+
+ if (!IS_ERR(exynos_ehci->phy)) {
+ usb_phy_shutdown(exynos_ehci->phy);
+ return;
+ }
+
+ for (i = 0; i < PHY_NUMBER; i++)
+ if (!IS_ERR(exynos_ehci->phy_g[i]))
+ phy_power_off(exynos_ehci->phy_g[i]);
+}
+
+static void exynos_setup_vbus_gpio(struct device *dev)
{
- struct device *dev = &pdev->dev;
int err;
int gpio;
@@ -75,7 +165,6 @@ static int exynos_ehci_probe(struct platform_device *pdev)
struct usb_hcd *hcd;
struct ehci_hcd *ehci;
struct resource *res;
- struct usb_phy *phy;
int irq;
int err;
@@ -88,7 +177,7 @@ static int exynos_ehci_probe(struct platform_device *pdev)
if (err)
return err;
- exynos_setup_vbus_gpio(pdev);
+ exynos_setup_vbus_gpio(&pdev->dev);
hcd = usb_create_hcd(&exynos_ehci_hc_driver,
&pdev->dev, dev_name(&pdev->dev));
@@ -102,15 +191,9 @@ static int exynos_ehci_probe(struct platform_device *pdev)
"samsung,exynos5440-ehci"))
goto skip_phy;
- phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
- if (IS_ERR(phy)) {
- usb_put_hcd(hcd);
- dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
- return -EPROBE_DEFER;
- } else {
- exynos_ehci->phy = phy;
- exynos_ehci->otg = phy->otg;
- }
+ err = exynos_ehci_get_phy(&pdev->dev, exynos_ehci);
+ if (err)
+ goto fail_clk;
skip_phy:
@@ -135,10 +218,9 @@ skip_phy:
hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_size(res);
- hcd->regs = devm_ioremap(&pdev->dev, res->start, hcd->rsrc_len);
- if (!hcd->regs) {
- dev_err(&pdev->dev, "Failed to remap I/O memory\n");
- err = -ENOMEM;
+ hcd->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(hcd->regs)) {
+ err = PTR_ERR(hcd->regs);
goto fail_io;
}
@@ -152,8 +234,11 @@ skip_phy:
if (exynos_ehci->otg)
exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self);
- if (exynos_ehci->phy)
- usb_phy_init(exynos_ehci->phy);
+ err = exynos_ehci_phy_enable(&pdev->dev);
+ if (err) {
+ dev_err(&pdev->dev, "Failed to enable USB phy\n");
+ goto fail_io;
+ }
ehci = hcd_to_ehci(hcd);
ehci->caps = hcd->regs;
@@ -173,8 +258,7 @@ skip_phy:
return 0;
fail_add_hcd:
- if (exynos_ehci->phy)
- usb_phy_shutdown(exynos_ehci->phy);
+ exynos_ehci_phy_disable(&pdev->dev);
fail_io:
clk_disable_unprepare(exynos_ehci->clk);
fail_clk:
@@ -192,8 +276,7 @@ static int exynos_ehci_remove(struct platform_device *pdev)
if (exynos_ehci->otg)
exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self);
- if (exynos_ehci->phy)
- usb_phy_shutdown(exynos_ehci->phy);
+ exynos_ehci_phy_disable(&pdev->dev);
clk_disable_unprepare(exynos_ehci->clk);
@@ -218,8 +301,7 @@ static int exynos_ehci_suspend(struct device *dev)
if (exynos_ehci->otg)
exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self);
- if (exynos_ehci->phy)
- usb_phy_shutdown(exynos_ehci->phy);
+ exynos_ehci_phy_disable(dev);
clk_disable_unprepare(exynos_ehci->clk);
@@ -230,14 +312,19 @@ static int exynos_ehci_resume(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct exynos_ehci_hcd *exynos_ehci = to_exynos_ehci(hcd);
+ int ret;
clk_prepare_enable(exynos_ehci->clk);
if (exynos_ehci->otg)
exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self);
- if (exynos_ehci->phy)
- usb_phy_init(exynos_ehci->phy);
+ ret = exynos_ehci_phy_enable(dev);
+ if (ret) {
+ dev_err(dev, "Failed to enable USB phy\n");
+ clk_disable_unprepare(exynos_ehci->clk);
+ return ret;
+ }
/* DMA burst Enable */
writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 7ae0c4d51741..cc305c71ac3d 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -33,15 +33,6 @@
#ifdef CONFIG_PM
-static int ehci_hub_control(
- struct usb_hcd *hcd,
- u16 typeReq,
- u16 wValue,
- u16 wIndex,
- char *buf,
- u16 wLength
-);
-
static int persist_enabled_on_companion(struct usb_device *udev, void *unused)
{
return !udev->maxchild && udev->persist_enabled &&
@@ -865,7 +856,7 @@ cleanup:
#endif /* CONFIG_USB_HCD_TEST_MODE */
/*-------------------------------------------------------------------------*/
-static int ehci_hub_control (
+int ehci_hub_control(
struct usb_hcd *hcd,
u16 typeReq,
u16 wValue,
@@ -1285,6 +1276,7 @@ error_exit:
spin_unlock_irqrestore (&ehci->lock, flags);
return retval;
}
+EXPORT_SYMBOL_GPL(ehci_hub_control);
static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
{
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index f341651d6f6c..982c09bebe0f 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -96,10 +96,9 @@ static int ehci_msm_probe(struct platform_device *pdev)
hcd->rsrc_start = res->start;
hcd->rsrc_len = resource_size(res);
- hcd->regs = devm_ioremap(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len);
- if (!hcd->regs) {
- dev_err(&pdev->dev, "ioremap failed\n");
- ret = -ENOMEM;
+ hcd->regs = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(hcd->regs)) {
+ ret = PTR_ERR(hcd->regs);
goto put_hcd;
}
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index bd61612a7251..08147c35f836 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -176,11 +176,9 @@ static int mv_ehci_probe(struct platform_device *pdev)
goto err_put_hcd;
}
- ehci_mv->phy_regs = devm_ioremap(&pdev->dev, r->start,
- resource_size(r));
- if (!ehci_mv->phy_regs) {
- dev_err(&pdev->dev, "failed to map phy I/O memory\n");
- retval = -EFAULT;
+ ehci_mv->phy_regs = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(ehci_mv->phy_regs)) {
+ retval = PTR_ERR(ehci_mv->phy_regs);
goto err_put_hcd;
}
@@ -191,11 +189,9 @@ static int mv_ehci_probe(struct platform_device *pdev)
goto err_put_hcd;
}
- ehci_mv->cap_regs = devm_ioremap(&pdev->dev, r->start,
- resource_size(r));
- if (ehci_mv->cap_regs == NULL) {
- dev_err(&pdev->dev, "failed to map I/O memory\n");
- retval = -EFAULT;
+ ehci_mv->cap_regs = devm_ioremap_resource(&pdev->dev, r);
+ if (IS_ERR(ehci_mv->cap_regs)) {
+ retval = PTR_ERR(ehci_mv->cap_regs);
goto err_put_hcd;
}
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index 30d35e5e503a..22e15cab8ea5 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -15,6 +15,7 @@
#include <linux/clk.h>
#include <linux/platform_data/usb-ehci-orion.h>
#include <linux/of.h>
+#include <linux/phy/phy.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/usb.h>
@@ -42,6 +43,13 @@
#define DRIVER_DESC "EHCI orion driver"
+#define hcd_to_orion_priv(h) ((struct orion_ehci_hcd *)hcd_to_ehci(h)->priv)
+
+struct orion_ehci_hcd {
+ struct clk *clk;
+ struct phy *phy;
+};
+
static const char hcd_name[] = "ehci-orion";
static struct hc_driver __read_mostly ehci_orion_hc_driver;
@@ -137,6 +145,10 @@ ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
}
}
+static const struct ehci_driver_overrides orion_overrides __initconst = {
+ .extra_priv_size = sizeof(struct orion_ehci_hcd),
+};
+
static int ehci_orion_drv_probe(struct platform_device *pdev)
{
struct orion_ehci_data *pd = dev_get_platdata(&pdev->dev);
@@ -144,26 +156,23 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)
struct resource *res;
struct usb_hcd *hcd;
struct ehci_hcd *ehci;
- struct clk *clk;
void __iomem *regs;
int irq, err;
enum orion_ehci_phy_ver phy_version;
+ struct orion_ehci_hcd *priv;
if (usb_disabled())
return -ENODEV;
pr_debug("Initializing Orion-SoC USB Host Controller\n");
- if (pdev->dev.of_node)
- irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
- else
- irq = platform_get_irq(pdev, 0);
+ irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
dev_err(&pdev->dev,
"Found HC with no IRQ. Check %s setup!\n",
dev_name(&pdev->dev));
err = -ENODEV;
- goto err1;
+ goto err;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -172,7 +181,7 @@ static int ehci_orion_drv_probe(struct platform_device *pdev)