diff options
Diffstat (limited to 'drivers/usb/host')
35 files changed, 1006 insertions, 1183 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index c59a1126926..de94f269906 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -2,11 +2,9 @@  # USB Host Controller Drivers  #  comment "USB Host Controller Drivers" -	depends on USB  config USB_C67X00_HCD  	tristate "Cypress C67x00 HCD support" -	depends on USB  	help  	  The Cypress C67x00 (EZ-Host/EZ-OTG) chips are dual-role  	  host/peripheral/OTG USB controllers. @@ -19,7 +17,7 @@ config USB_C67X00_HCD  config USB_XHCI_HCD  	tristate "xHCI HCD (USB 3.0) support" -	depends on USB && USB_ARCH_HAS_XHCI +	depends on USB_ARCH_HAS_XHCI  	---help---  	  The eXtensible Host Controller Interface (xHCI) is standard for USB 3.0  	  "SuperSpeed" host controller hardware. @@ -27,13 +25,13 @@ config USB_XHCI_HCD  	  To compile this driver as a module, choose M here: the  	  module will be called xhci-hcd. +if USB_XHCI_HCD +  config USB_XHCI_PLATFORM  	tristate -	depends on USB_XHCI_HCD  config USB_XHCI_HCD_DEBUGGING  	bool "Debugging for the xHCI host controller" -	depends on USB_XHCI_HCD  	---help---  	  Say 'Y' to turn on debugging for the xHCI host controller driver.  	  This will spew debugging output, even in interrupt context. @@ -41,9 +39,11 @@ config USB_XHCI_HCD_DEBUGGING  	  If unsure, say N. +endif # USB_XHCI_HCD +  config USB_EHCI_HCD  	tristate "EHCI HCD (USB 2.0) support" -	depends on USB && USB_ARCH_HAS_EHCI +	depends on USB_ARCH_HAS_EHCI  	---help---  	  The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0  	  "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. @@ -95,14 +95,19 @@ config USB_EHCI_TT_NEWSCHED  	  If unsure, say Y. +config USB_FSL_MPH_DR_OF +	tristate + +if USB_EHCI_HCD +  config USB_EHCI_PCI  	tristate -	depends on USB_EHCI_HCD && PCI +	depends on PCI  	default y  config USB_EHCI_HCD_PMC_MSP  	tristate "EHCI support for on-chip PMC MSP71xx USB controller" -	depends on USB_EHCI_HCD && MSP_HAS_USB +	depends on MSP_HAS_USB  	default n  	select USB_EHCI_BIG_ENDIAN_DESC  	select USB_EHCI_BIG_ENDIAN_MMIO @@ -112,22 +117,13 @@ config USB_EHCI_HCD_PMC_MSP  config USB_EHCI_BIG_ENDIAN_MMIO  	bool -	depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || \ -				    ARCH_IXP4XX || XPS_USB_HCD_XILINX || \ -				    PPC_MPC512x || CPU_CAVIUM_OCTEON || \ -				    PMC_MSP || SPARC_LEON || MIPS_SEAD3) -	default y  config USB_EHCI_BIG_ENDIAN_DESC  	bool -	depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \ -				    PPC_MPC512x || PMC_MSP || SPARC_LEON || \ -				    MIPS_SEAD3) -	default y  config XPS_USB_HCD_XILINX  	bool "Use Xilinx usb host EHCI controller core" -	depends on USB_EHCI_HCD && (PPC32 || MICROBLAZE) +	depends on (PPC32 || MICROBLAZE)  	select USB_EHCI_BIG_ENDIAN_DESC  	select USB_EHCI_BIG_ENDIAN_MMIO  	---help--- @@ -136,12 +132,9 @@ config XPS_USB_HCD_XILINX  		support both high speed and full speed devices, or high speed  		devices only. -config USB_FSL_MPH_DR_OF -	tristate -  config USB_EHCI_FSL  	bool "Support for Freescale PPC on-chip EHCI USB controller" -	depends on USB_EHCI_HCD && FSL_SOC +	depends on FSL_SOC  	select USB_EHCI_ROOT_HUB_TT  	select USB_FSL_MPH_DR_OF if OF  	---help--- @@ -149,22 +142,53 @@ config USB_EHCI_FSL  config USB_EHCI_MXC  	tristate "Support for Freescale i.MX on-chip EHCI USB controller" -	depends on USB_EHCI_HCD && ARCH_MXC +	depends on ARCH_MXC  	select USB_EHCI_ROOT_HUB_TT  	---help---  	  Variation of ARC USB block used in some Freescale chips.  config USB_EHCI_HCD_OMAP -	bool "EHCI support for OMAP3 and later chips" -	depends on USB_EHCI_HCD && ARCH_OMAP +	tristate "EHCI support for OMAP3 and later chips" +	depends on ARCH_OMAP  	default y  	---help---  	  Enables support for the on-chip EHCI controller on  	  OMAP3 and later chips. +	  If your system uses a PHY on the USB port, you will need to +	  enable USB_PHY and the appropriate PHY driver as well. Most +	  boards need the NOP_USB_XCEIV PHY driver. + +config USB_EHCI_HCD_ORION +	tristate  "Support for Marvell EBU on-chip EHCI USB controller" +	depends on USB_EHCI_HCD && PLAT_ORION +	default y +	---help--- +	  Enables support for the on-chip EHCI controller on Marvell's +	  embedded ARM SoCs, including Orion, Kirkwood, Dove, Armada XP, +	  Armada 370.  This is different from the EHCI implementation +	  on Marvell's mobile PXA and MMP SoC, see "EHCI support for +	  Marvell PXA/MMP USB controller" for those. + +config USB_EHCI_HCD_SPEAR +        tristate "Support for ST SPEAr on-chip EHCI USB controller" +        depends on USB_EHCI_HCD && PLAT_SPEAR +        default y +        ---help--- +          Enables support for the on-chip EHCI controller on +          ST SPEAr chips. + +config USB_EHCI_HCD_AT91 +        tristate  "Support for Atmel on-chip EHCI USB controller" +        depends on USB_EHCI_HCD && ARCH_AT91 +        default y +        ---help--- +          Enables support for the on-chip EHCI controller on +          Atmel chips.  config USB_EHCI_MSM -	bool "Support for MSM on-chip EHCI USB controller" -	depends on USB_EHCI_HCD && ARCH_MSM +	tristate "Support for Qualcomm QSD/MSM on-chip EHCI USB controller" +	depends on ARCH_MSM +	depends on USB_PHY  	select USB_EHCI_ROOT_HUB_TT  	select USB_MSM_OTG  	---help--- @@ -177,15 +201,16 @@ config USB_EHCI_MSM  config USB_EHCI_TEGRA         boolean "NVIDIA Tegra HCD support" -       depends on USB_EHCI_HCD && ARCH_TEGRA +       depends on ARCH_TEGRA         select USB_EHCI_ROOT_HUB_TT +       select USB_PHY         help           This driver enables support for the internal USB Host Controllers           found in NVIDIA Tegra SoCs. The controllers are EHCI compliant.  config USB_EHCI_HCD_PPC_OF  	bool "EHCI support for PPC USB controller on OF platform bus" -	depends on USB_EHCI_HCD && PPC_OF +	depends on PPC_OF  	default y  	---help---  	  Enables support for the USB controller present on the PowerPC @@ -193,35 +218,40 @@ config USB_EHCI_HCD_PPC_OF  config USB_EHCI_SH  	bool "EHCI support for SuperH USB controller" -	depends on USB_EHCI_HCD && SUPERH +	depends on SUPERH  	---help---  	  Enables support for the on-chip EHCI controller on the SuperH.  	  If you use the PCI EHCI controller, this option is not necessary.  config USB_EHCI_S5P -       boolean "S5P EHCI support" -       depends on USB_EHCI_HCD && PLAT_S5P +       tristate "EHCI support for Samsung S5P/EXYNOS SoC Series" +       depends on PLAT_S5P         help -	 Enable support for the S5P SOC's on-chip EHCI controller. +	Enable support for the Samsung S5Pxxxx and Exynos3/4/5 SOC's +	on-chip EHCI controller.  config USB_EHCI_MV -	bool "EHCI support for Marvell on-chip controller" -	depends on USB_EHCI_HCD && (ARCH_PXA || ARCH_MMP) +	bool "EHCI support for Marvell PXA/MMP USB controller" +	depends on (ARCH_PXA || ARCH_MMP)  	select USB_EHCI_ROOT_HUB_TT  	---help---  	  Enables support for Marvell (including PXA and MMP series) on-chip  	  USB SPH and OTG controller. SPH is a single port host, and it can  	  only be EHCI host. OTG is controller that can switch to host mode. +	  Note that this driver will not work on Marvell's other EHCI +	  controller used by the EBU-type SoCs including Orion, Kirkwood, +	  Dova, Armada 370 and Armada XP. See "Support for Marvell EBU +	  on-chip EHCI USB controller" for those.  config USB_W90X900_EHCI  	bool "W90X900(W90P910) EHCI support" -	depends on USB_EHCI_HCD && ARCH_W90X900 +	depends on ARCH_W90X900  	---help---  		Enables support for the W90X900 USB controller  config USB_CNS3XXX_EHCI  	bool "Cavium CNS3XXX EHCI Module (DEPRECATED)" -	depends on USB_EHCI_HCD && ARCH_CNS3XXX +	depends on ARCH_CNS3XXX  	select USB_EHCI_HCD_PLATFORM  	---help---  	  This option is deprecated now and the driver was removed, use @@ -233,7 +263,7 @@ config USB_CNS3XXX_EHCI  config USB_EHCI_ATH79  	bool "EHCI support for AR7XXX/AR9XXX SoCs (DEPRECATED)" -	depends on USB_EHCI_HCD && (SOC_AR71XX || SOC_AR724X || SOC_AR913X || SOC_AR933X) +	depends on (SOC_AR71XX || SOC_AR724X || SOC_AR913X || SOC_AR933X)  	select USB_EHCI_ROOT_HUB_TT  	select USB_EHCI_HCD_PLATFORM  	default y @@ -244,9 +274,31 @@ config USB_EHCI_ATH79  	  Enables support for the built-in EHCI controller present  	  on the Atheros AR7XXX/AR9XXX SoCs. +config USB_EHCI_HCD_PLATFORM +	tristate "Generic EHCI driver for a platform device" +	default n +	---help--- +	  Adds an EHCI host driver for a generic platform device, which +	  provides a memory space and an irq. + +	  If unsure, say N. + +config USB_OCTEON_EHCI +	bool "Octeon on-chip EHCI support" +	depends on CPU_CAVIUM_OCTEON +	default n +	select USB_EHCI_BIG_ENDIAN_MMIO +	help +	  Enable support for the Octeon II SOC's on-chip EHCI +	  controller.  It is needed for high-speed (480Mbit/sec) +	  USB 2.0 device support.  All CN6XXX based chips with USB are +	  supported. + +endif # USB_EHCI_HCD +  config USB_OXU210HP_HCD  	tristate "OXU210HP HCD support" -	depends on USB && GENERIC_HARDIRQS +	depends on GENERIC_HARDIRQS  	---help---  	  The OXU210HP is an USB host/OTG/device controller. Enable this  	  option if your board has this chip. If unsure, say N. @@ -259,7 +311,6 @@ config USB_OXU210HP_HCD  config USB_ISP116X_HCD  	tristate "ISP116X HCD support" -	depends on USB  	---help---  	  The ISP1160 and ISP1161 chips are USB host controllers. Enable this  	  option if your board has this chip. If unsure, say N. @@ -271,7 +322,6 @@ config USB_ISP116X_HCD  config USB_ISP1760_HCD  	tristate "ISP 1760 HCD support" -	depends on USB  	---help---  	  The ISP1760 chip is a USB 2.0 host controller. @@ -286,7 +336,6 @@ config USB_ISP1760_HCD  config USB_ISP1362_HCD  	tristate "ISP1362 HCD support" -	depends on USB  	default N  	---help---  	  Supports the Philips ISP1362 chip as a host controller @@ -298,9 +347,8 @@ config USB_ISP1362_HCD  config USB_OHCI_HCD  	tristate "OHCI HCD support" -	depends on USB && USB_ARCH_HAS_OHCI +	depends on USB_ARCH_HAS_OHCI  	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 -	select USB_OTG_UTILS if ARCH_OMAP  	depends on USB_ISP1301 || !ARCH_LPC32XX  	---help---  	  The Open Host Controller Interface (OHCI) is a standard for accessing @@ -315,16 +363,18 @@ config USB_OHCI_HCD  	  To compile this driver as a module, choose M here: the  	  module will be called ohci-hcd. +if USB_OHCI_HCD +  config USB_OHCI_HCD_OMAP1  	bool "OHCI support for OMAP1/2 chips" -	depends on USB_OHCI_HCD && ARCH_OMAP1 +	depends on ARCH_OMAP1  	default y  	---help---  	  Enables support for the OHCI controller on OMAP1/2 chips.  config USB_OHCI_HCD_OMAP3  	bool "OHCI support for OMAP3 and later chips" -	depends on USB_OHCI_HCD && (ARCH_OMAP3 || ARCH_OMAP4) +	depends on (ARCH_OMAP3 || ARCH_OMAP4)  	default y  	---help---  	  Enables support for the on-chip OHCI controller on @@ -332,7 +382,7 @@ config USB_OHCI_HCD_OMAP3  config USB_OHCI_ATH79  	bool "USB OHCI support for the Atheros AR71XX/AR7240 SoCs (DEPRECATED)" -	depends on USB_OHCI_HCD && (SOC_AR71XX || SOC_AR724X) +	depends on (SOC_AR71XX || SOC_AR724X)  	select USB_OHCI_HCD_PLATFORM  	default y  	help @@ -344,7 +394,7 @@ config USB_OHCI_ATH79  config USB_OHCI_HCD_PPC_OF_BE  	bool "OHCI support for OF platform bus (big endian)" -	depends on USB_OHCI_HCD && PPC_OF +	depends on PPC_OF  	select USB_OHCI_BIG_ENDIAN_DESC  	select USB_OHCI_BIG_ENDIAN_MMIO  	---help--- @@ -353,7 +403,7 @@ config USB_OHCI_HCD_PPC_OF_BE  config USB_OHCI_HCD_PPC_OF_LE  	bool "OHCI support for OF platform bus (little endian)" -	depends on USB_OHCI_HCD && PPC_OF +	depends on PPC_OF  	select USB_OHCI_LITTLE_ENDIAN  	---help---  	  Enables support for little-endian USB controllers present on the @@ -361,12 +411,12 @@ config USB_OHCI_HCD_PPC_OF_LE  config USB_OHCI_HCD_PPC_OF  	bool -	depends on USB_OHCI_HCD && PPC_OF +	depends on PPC_OF  	default USB_OHCI_HCD_PPC_OF_BE || USB_OHCI_HCD_PPC_OF_LE  config USB_OHCI_HCD_PCI  	bool "OHCI support for PCI-bus USB controllers" -	depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx || USB_OHCI_HCD_PPC_OF) +	depends on PCI && (STB03xxx || PPC_MPC52xx || USB_OHCI_HCD_PPC_OF)  	default y  	select USB_OHCI_LITTLE_ENDIAN  	---help--- @@ -375,7 +425,7 @@ config USB_OHCI_HCD_PCI  config USB_OHCI_HCD_SSB  	bool "OHCI support for Broadcom SSB OHCI core (DEPRECATED)" -	depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD) +	depends on (SSB = y || SSB = USB_OHCI_HCD)  	select USB_HCD_SSB  	select USB_OHCI_HCD_PLATFORM  	default n @@ -393,7 +443,7 @@ config USB_OHCI_HCD_SSB  config USB_OHCI_SH  	bool "OHCI support for SuperH USB controller (DEPRECATED)" -	depends on USB_OHCI_HCD && SUPERH +	depends on SUPERH  	select USB_OHCI_HCD_PLATFORM  	---help---  	  This option is deprecated now and the driver was removed, use @@ -404,13 +454,13 @@ config USB_OHCI_SH  config USB_OHCI_EXYNOS  	boolean "OHCI support for Samsung EXYNOS SoC Series" -	depends on USB_OHCI_HCD && ARCH_EXYNOS +	depends on ARCH_EXYNOS  	help  	 Enable support for the Samsung Exynos SOC's on-chip OHCI controller.  config USB_CNS3XXX_OHCI  	bool "Cavium CNS3XXX OHCI Module (DEPRECATED)" -	depends on USB_OHCI_HCD && ARCH_CNS3XXX +	depends on ARCH_CNS3XXX  	select USB_OHCI_HCD_PLATFORM  	---help---  	  This option is deprecated now and the driver was removed, use @@ -421,7 +471,6 @@ config USB_CNS3XXX_OHCI  config USB_OHCI_HCD_PLATFORM  	bool "Generic OHCI driver for a platform device" -	depends on USB_OHCI_HCD  	default n  	---help---  	  Adds an OHCI host driver for a generic platform device, which @@ -429,35 +478,36 @@ config USB_OHCI_HCD_PLATFORM  	  If unsure, say N. -config USB_EHCI_HCD_PLATFORM -	tristate "Generic EHCI driver for a platform device" -	depends on USB_EHCI_HCD -	default n -	---help--- -	  Adds an EHCI host driver for a generic platform device, which -	  provides a memory space and an irq. +config USB_OCTEON_OHCI +	bool "Octeon on-chip OHCI support" +	depends on CPU_CAVIUM_OCTEON +	default USB_OCTEON_EHCI +	select USB_OHCI_BIG_ENDIAN_MMIO +	select USB_OHCI_LITTLE_ENDIAN +	help +	  Enable support for the Octeon II SOC's on-chip OHCI +	  controller.  It is needed for low-speed USB 1.0 device +	  support.  All CN6XXX based chips with USB are supported. -	  If unsure, say N.  config USB_OHCI_BIG_ENDIAN_DESC  	bool -	depends on USB_OHCI_HCD  	default n  config USB_OHCI_BIG_ENDIAN_MMIO  	bool -	depends on USB_OHCI_HCD  	default n  config USB_OHCI_LITTLE_ENDIAN  	bool -	depends on USB_OHCI_HCD  	default n if STB03xxx || PPC_MPC52xx  	default y +endif # USB_OHCI_HCD +  config USB_UHCI_HCD  	tristate "UHCI HCD (most Intel and VIA) support" -	depends on USB && (PCI || SPARC_LEON || ARCH_VT8500) +	depends on PCI || SPARC_LEON || ARCH_VT8500  	---help---  	  The Universal Host Controller Interface is a standard by Intel for  	  accessing the USB hardware in the PC (which is also called the USB @@ -497,7 +547,7 @@ config USB_UHCI_BIG_ENDIAN_DESC  config USB_FHCI_HCD  	tristate "Freescale QE USB Host Controller support" -	depends on USB && OF_GPIO && QE_GPIO && QUICC_ENGINE +	depends on OF_GPIO && QE_GPIO && QUICC_ENGINE  	select FSL_GTM  	select QE_USB  	help @@ -514,7 +564,7 @@ config FHCI_DEBUG  config USB_U132_HCD  	tristate "Elan U132 Adapter Host Controller" -	depends on USB && USB_FTDI_ELAN +	depends on USB_FTDI_ELAN  	default M  	help  	  The U132 adapter is a USB to CardBus adapter specifically designed @@ -542,7 +592,6 @@ config USB_U132_HCD  config USB_SL811_HCD  	tristate "SL811HS HCD support" -	depends on USB  	help  	  The SL811HS is a single-port USB controller that supports either  	  host side or peripheral side roles.  Enable this option if your @@ -574,7 +623,6 @@ config USB_SL811_CS  config USB_R8A66597_HCD  	tristate "R8A66597 HCD support" -	depends on USB  	help  	  The R8A66597 is a USB 2.0 host and peripheral controller. @@ -586,7 +634,6 @@ config USB_R8A66597_HCD  config USB_RENESAS_USBHS_HCD  	tristate "Renesas USBHS HCD support" -	depends on USB  	depends on USB_RENESAS_USBHS  	help  	  The Renesas USBHS is a USB 2.0 host and peripheral controller. @@ -611,7 +658,7 @@ config USB_WHCI_HCD  config USB_HWA_HCD  	tristate "Host Wire Adapter (HWA) driver" -	depends on USB && UWB +	depends on UWB  	select USB_WUSB  	select UWB_HWA  	help @@ -625,7 +672,7 @@ config USB_HWA_HCD  config USB_IMX21_HCD         tristate "i.MX21 HCD support" -       depends on USB && ARM && ARCH_MXC +       depends on ARM && ARCH_MXC         help           This driver enables support for the on-chip USB host in the           i.MX21 processor. @@ -633,27 +680,7 @@ config USB_IMX21_HCD           To compile this driver as a module, choose M here: the           module will be called "imx21-hcd". -config USB_OCTEON_EHCI -	bool "Octeon on-chip EHCI support" -	depends on USB && USB_EHCI_HCD && CPU_CAVIUM_OCTEON -	default n -	select USB_EHCI_BIG_ENDIAN_MMIO -	help -	  Enable support for the Octeon II SOC's on-chip EHCI -	  controller.  It is needed for high-speed (480Mbit/sec) -	  USB 2.0 device support.  All CN6XXX based chips with USB are -	  supported. -config USB_OCTEON_OHCI -	bool "Octeon on-chip OHCI support" -	depends on USB && USB_OHCI_HCD && CPU_CAVIUM_OCTEON -	default USB_OCTEON_EHCI -	select USB_OHCI_BIG_ENDIAN_MMIO -	select USB_OHCI_LITTLE_ENDIAN -	help -	  Enable support for the Octeon II SOC's on-chip OHCI -	  controller.  It is needed for low-speed USB 1.0 device -	  support.  All CN6XXX based chips with USB are supported.  config USB_OCTEON2_COMMON  	bool diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 001fbff2fde..4fb73c156d7 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -27,6 +27,12 @@ obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o  obj-$(CONFIG_USB_EHCI_PCI)	+= ehci-pci.o  obj-$(CONFIG_USB_EHCI_HCD_PLATFORM)	+= ehci-platform.o  obj-$(CONFIG_USB_EHCI_MXC)	+= ehci-mxc.o +obj-$(CONFIG_USB_EHCI_HCD_OMAP)	+= ehci-omap.o +obj-$(CONFIG_USB_EHCI_HCD_ORION)	+= ehci-orion.o +obj-$(CONFIG_USB_EHCI_HCD_SPEAR)	+= ehci-spear.o +obj-$(CONFIG_USB_EHCI_S5P)	+= ehci-s5p.o +obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o +obj-$(CONFIG_USB_EHCI_MSM)	+= ehci-msm.o  obj-$(CONFIG_USB_OXU210HP_HCD)	+= oxu210hp-hcd.o  obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index f3beac4d06b..66420097c24 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -12,9 +12,22 @@   */  #include <linux/clk.h> -#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h>  #include <linux/of.h>  #include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> + +#include "ehci.h" + +#define DRIVER_DESC "EHCI Atmel driver" + +static const char hcd_name[] = "ehci-atmel"; +static struct hc_driver __read_mostly ehci_atmel_hc_driver;  /* interface and function clocks */  static struct clk *iclk, *fclk; @@ -50,51 +63,6 @@ static void atmel_stop_ehci(struct platform_device *pdev)  /*-------------------------------------------------------------------------*/ -static int ehci_atmel_setup(struct usb_hcd *hcd) -{ -	struct ehci_hcd *ehci = hcd_to_ehci(hcd); - -	/* registers start at offset 0x0 */ -	ehci->caps = hcd->regs; - -	return ehci_setup(hcd); -} - -static const struct hc_driver ehci_atmel_hc_driver = { -	.description		= hcd_name, -	.product_desc		= "Atmel EHCI UHP HS", -	.hcd_priv_size		= sizeof(struct ehci_hcd), - -	/* generic hardware linkage */ -	.irq			= ehci_irq, -	.flags			= HCD_MEMORY | HCD_USB2, - -	/* basic lifecycle operations */ -	.reset			= ehci_atmel_setup, -	.start			= ehci_run, -	.stop			= ehci_stop, -	.shutdown		= ehci_shutdown, - -	/* managing i/o requests and associated device resources */ -	.urb_enqueue		= ehci_urb_enqueue, -	.urb_dequeue		= ehci_urb_dequeue, -	.endpoint_disable	= ehci_endpoint_disable, -	.endpoint_reset		= ehci_endpoint_reset, - -	/* scheduling support */ -	.get_frame_number	= ehci_get_frame, - -	/* root hub support */ -	.hub_status_data	= ehci_hub_status_data, -	.hub_control		= ehci_hub_control, -	.bus_suspend		= ehci_bus_suspend, -	.bus_resume		= ehci_bus_resume, -	.relinquish_port	= ehci_relinquish_port, -	.port_handed_over	= ehci_port_handed_over, - -	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete, -}; -  static u64 at91_ehci_dma_mask = DMA_BIT_MASK(32);  static int ehci_atmel_drv_probe(struct platform_device *pdev) @@ -102,6 +70,7 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev)  	struct usb_hcd *hcd;  	const struct hc_driver *driver = &ehci_atmel_hc_driver;  	struct resource *res; +	struct ehci_hcd *ehci;  	int irq;  	int retval; @@ -162,6 +131,10 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev)  		goto fail_request_resource;  	} +	ehci = hcd_to_ehci(hcd); +	/* registers start at offset 0x0 */ +	ehci->caps = hcd->regs; +  	atmel_start_ehci(pdev);  	retval = usb_add_hcd(hcd, irq, IRQF_SHARED); @@ -185,7 +158,6 @@ static int ehci_atmel_drv_remove(struct platform_device *pdev)  {  	struct usb_hcd *hcd = platform_get_drvdata(pdev); -	ehci_shutdown(hcd);  	usb_remove_hcd(hcd);  	usb_put_hcd(hcd); @@ -213,3 +185,25 @@ static struct platform_driver ehci_atmel_driver = {  		.of_match_table	= of_match_ptr(atmel_ehci_dt_ids),  	},  }; + +static int __init ehci_atmel_init(void) +{ +	if (usb_disabled()) +		return -ENODEV; + +	pr_info("%s: " DRIVER_DESC "\n", hcd_name); +	ehci_init_driver(&ehci_atmel_hc_driver, NULL); +	return platform_driver_register(&ehci_atmel_driver); +} +module_init(ehci_atmel_init); + +static void __exit ehci_atmel_cleanup(void) +{ +	platform_driver_unregister(&ehci_atmel_driver); +} +module_exit(ehci_atmel_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_ALIAS("platform:atmel-ehci"); +MODULE_AUTHOR("Nicolas Ferre"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 70b496dc18a..5429d2645bb 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -510,14 +510,16 @@ static ssize_t fill_async_buffer(struct debug_buffer *buf)  	spin_lock_irqsave (&ehci->lock, flags);  	for (qh = ehci->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh)  		qh_lines (ehci, qh, &next, &size); -	if (ehci->async_unlink && size > 0) { +	if (!list_empty(&ehci->async_unlink) && size > 0) {  		temp = scnprintf(next, size, "\nunlink =\n");  		size -= temp;  		next += temp; -		for (qh = ehci->async_unlink; size > 0 && qh; -				qh = qh->unlink_next) -			qh_lines (ehci, qh, &next, &size); +		list_for_each_entry(qh, &ehci->async_unlink, unlink_node) { +			if (size <= 0) +				break; +			qh_lines(ehci, qh, &next, &size); +		}  	}  	spin_unlock_irqrestore (&ehci->lock, flags); @@ -814,9 +816,10 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)  		}  	} -	if (ehci->async_unlink) { +	if (!list_empty(&ehci->async_unlink)) {  		temp = scnprintf(next, size, "async unlink qh %p\n", -				ehci->async_unlink); +				list_first_entry(&ehci->async_unlink, +						struct ehci_qh, unlink_node));  		size -= temp;  		next += temp;  	} diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index d81d2fcbff1..3be3df233a0 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -370,6 +370,15 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)  	/* EHCI registers start at offset 0x100 */  	ehci->caps = hcd->regs + 0x100; +#ifdef CONFIG_PPC_83xx +	/* +	 * Deal with MPC834X that need port power to be cycled after the power +	 * fault condition is removed. Otherwise the state machine does not +	 * reflect PORTSC[CSC] correctly. +	 */ +	ehci->need_oc_pp_cycle = 1; +#endif +  	hcd->has_tt = 1;  	retval = ehci_setup(hcd); diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 416a6dce5e1..312fc10da3c 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -482,6 +482,9 @@ static int ehci_init(struct usb_hcd *hcd)  	 * periodic_size can shrink by USBCMD update if hcc_params allows.  	 */  	ehci->periodic_size = DEFAULT_I_TDPS; +	INIT_LIST_HEAD(&ehci->async_unlink); +	INIT_LIST_HEAD(&ehci->async_idle); +	INIT_LIST_HEAD(&ehci->intr_unlink);  	INIT_LIST_HEAD(&ehci->intr_qh_list);  	INIT_LIST_HEAD(&ehci->cached_itd_list);  	INIT_LIST_HEAD(&ehci->cached_sitd_list); @@ -670,9 +673,6 @@ int ehci_setup(struct usb_hcd *hcd)  	if (retval)  		return retval; -	if (ehci_is_TDI(ehci)) -		tdi_reset(ehci); -  	ehci_reset(ehci);  	return 0; @@ -749,7 +749,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)  		/* guard against (alleged) silicon errata */  		if (cmd & CMD_IAAD)  			ehci_dbg(ehci, "IAA with IAAD still set?\n"); -		if (ehci->async_iaa) +		if (ehci->iaa_in_progress)  			COUNT(ehci->stats.iaa);  		end_unlink_async(ehci);  	} @@ -757,7 +757,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)  	/* remote wakeup [4.3.1] */  	if (status & STS_PCD) {  		unsigned	i = HCS_N_PORTS (ehci->hcs_params); -		u32		ppcd = 0; +		u32		ppcd = ~0;  		/* kick root hub later */  		pcd_status = status; @@ -774,7 +774,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)  			int pstatus;  			/* leverage per-port change bits feature */ -			if (ehci->has_ppcd && !(ppcd & (1 << i))) +			if (!(ppcd & (1 << i)))  				continue;  			pstatus = ehci_readl(ehci,  					 &ehci->regs->port_status[i]); @@ -896,17 +896,24 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)  	if (rc)  		goto done; -	switch (usb_pipetype (urb->pipe)) { -	// case PIPE_CONTROL: -	// case PIPE_BULK: -	default: +	if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { +		/* +		 * We don't expedite dequeue for isochronous URBs. +		 * Just wait until they complete normally or their +		 * time slot expires. +		 */ +	} else {  		qh = (struct ehci_qh *) urb->hcpriv; -		if (!qh) -			break; +		qh->exception = 1;  		switch (qh->qh_state) {  		case QH_STATE_LINKED: +			if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) +				start_unlink_intr(ehci, qh); +			else +				start_unlink_async(ehci, qh); +			break;  		case QH_STATE_COMPLETING: -			start_unlink_async(ehci, qh); +			qh->dequeue_during_giveback = 1;  			break;  		case QH_STATE_UNLINK:  		case QH_STATE_UNLINK_WAIT: @@ -917,33 +924,6 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)  			qh_completions(ehci, qh);  			break;  		} -		break; - -	case PIPE_INTERRUPT: -		qh = (struct ehci_qh *) urb->hcpriv; -		if (!qh) -			break; -		switch (qh->qh_state) { -		case QH_STATE_LINKED: -		case QH_STATE_COMPLETING: -			start_unlink_intr(ehci, qh); -			break; -		case QH_STATE_IDLE: -			qh_completions (ehci, qh); -			break; -		default: -			ehci_dbg (ehci, "bogus qh %p state %d\n", -					qh, qh->qh_state); -			goto done; -		} -		break; - -	case PIPE_ISOCHRONOUS: -		// itd or sitd ... - -		// wait till next completion, do it then. -		// completion irqs can wait up to 1024 msec, -		break;  	}  done:  	spin_unlock_irqrestore (&ehci->lock, flags); @@ -984,6 +964,7 @@ rescan:  		goto done;  	} +	qh->exception = 1;  	if (ehci->rh_state < EHCI_RH_RUNNING)  		qh->qh_state = QH_STATE_IDLE;  	switch (qh->qh_state) { @@ -1052,13 +1033,12 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep)  		usb_settoggle(qh->dev, epnum, is_out, 0);  		if (!list_empty(&qh->qtd_list)) {  			WARN_ONCE(1, "clear_halt for a busy endpoint\n"); -		} else if (qh->qh_state == QH_STATE_LINKED || -				qh->qh_state == QH_STATE_COMPLETING) { - +		} else {  			/* The toggle value in the QH can't be updated  			 * while the QH is active.  Unlink it now;  			 * re-linking will call qh_refresh().  			 */ +			qh->exception = 1;  			if (eptype == USB_ENDPOINT_XFER_BULK)  				start_unlink_async(ehci, qh);  			else @@ -1251,11 +1231,6 @@ MODULE_LICENSE ("GPL");  #define PLATFORM_DRIVER		ehci_hcd_sh_driver  #endif -#ifdef CONFIG_USB_EHCI_HCD_OMAP -#include "ehci-omap.c" -#define        PLATFORM_DRIVER         ehci_hcd_omap_driver -#endif -  #ifdef CONFIG_PPC_PS3  #include "ehci-ps3.c"  #define	PS3_SYSTEM_BUS_DRIVER	ps3_ehci_driver @@ -1271,41 +1246,16 @@ MODULE_LICENSE ("GPL");  #define XILINX_OF_PLATFORM_DRIVER	ehci_hcd_xilinx_of_driver  #endif -#ifdef CONFIG_PLAT_ORION -#include "ehci-orion.c" -#define	PLATFORM_DRIVER		ehci_orion_driver -#endif -  #ifdef CONFIG_USB_W90X900_EHCI  #include "ehci-w90x900.c"  #define	PLATFORM_DRIVER		ehci_hcd_w90x900_driver  #endif -#ifdef CONFIG_ARCH_AT91 -#include "ehci-atmel.c" -#define	PLATFORM_DRIVER		ehci_atmel_driver -#endif -  #ifdef CONFIG_USB_OCTEON_EHCI  #include "ehci-octeon.c"  #define PLATFORM_DRIVER		ehci_octeon_driver  #endif -#ifdef CONFIG_ARCH_VT8500 -#include "ehci-vt8500.c" -#define	PLATFORM_DRIVER		vt8500_ehci_driver -#endif - -#ifdef CONFIG_PLAT_SPEAR -#include "ehci-spear.c" -#define PLATFORM_DRIVER		spear_ehci_hcd_driver -#endif - -#ifdef CONFIG_USB_EHCI_MSM -#include "ehci-msm.c" -#define PLATFORM_DRIVER		ehci_msm_driver -#endif -  #ifdef CONFIG_TILE_USB  #include "ehci-tilegx.c"  #define	PLATFORM_DRIVER		ehci_hcd_tilegx_driver @@ -1321,11 +1271,6 @@ MODULE_LICENSE ("GPL");  #define PLATFORM_DRIVER		tegra_ehci_driver  #endif -#ifdef CONFIG_USB_EHCI_S5P -#include "ehci-s5p.c" -#define PLATFORM_DRIVER		s5p_ehci_driver -#endif -  #ifdef CONFIG_SPARC_LEON  #include "ehci-grlib.c"  #define PLATFORM_DRIVER		ehci_grlib_driver @@ -1345,6 +1290,12 @@ MODULE_LICENSE ("GPL");  	!IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \  	!IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \  	!IS_ENABLED(CONFIG_USB_EHCI_MXC) && \ +	!IS_ENABLED(CONFIG_USB_EHCI_HCD_OMAP) && \ +	!IS_ENABLED(CONFIG_USB_EHCI_HCD_ORION) && \ +	!IS_ENABLED(CONFIG_USB_EHCI_HCD_SPEAR) && \ +	!IS_ENABLED(CONFIG_USB_EHCI_S5P) && \ +	!IS_ENABLED(CONFIG_USB_EHCI_HCD_AT91) && \ +	!IS_ENABLED(CONFIG_USB_EHCI_MSM) && \  	!defined(PLATFORM_DRIVER) && \  	!defined(PS3_SYSTEM_BUS_DRIVER) && \  	!defined(OF_PLATFORM_DRIVER) && \ diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 7d06e77f6c4..9ab4a4d9768 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -464,7 +464,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)  	while (i--) {  		temp = ehci_readl(ehci, &ehci->regs->port_status [i]);  		if (test_bit(i, &resume_needed)) { -			temp &= ~(PORT_RWC_BITS | PORT_RESUME); +			temp &= ~(PORT_RWC_BITS | PORT_SUSPEND | PORT_RESUME);  			ehci_writel(ehci, temp, &ehci->regs->port_status [i]);  			ehci_vdbg (ehci, "resumed port %d\n", i + 1);  		} @@ -590,7 +590,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)  	u32		mask;  	int		ports, i, retval = 1;  	unsigned long	flags; -	u32		ppcd = 0; +	u32		ppcd = ~0;  	/* init status to no-changes */  	buf [0] = 0; @@ -628,9 +628,10 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)  	for (i = 0; i < ports; i++) {  		/* leverage per-port change bits feature */ -		if (ehci->has_ppcd && !(ppcd & (1 << i))) -			continue; -		temp = ehci_readl(ehci, &ehci->regs->port_status [i]); +		if (ppcd & (1 << i)) +			temp = ehci_readl(ehci, &ehci->regs->port_status[i]); +		else +			temp = 0;  		/*  		 * Return status information even for ports with OWNER set. @@ -839,7 +840,8 @@ static int ehci_hub_control (  			 * power switching; they're allowed to just limit the  			 * current.  khubd will turn the power back on.  			 */ -			if ((temp & PORT_OC) && HCS_PPC(ehci->hcs_params)) { +			if (((temp & PORT_OC) || (ehci->need_oc_pp_cycle)) +					&& HCS_PPC(ehci->hcs_params)) {  				ehci_writel(ehci,  					temp & ~(PORT_RWC_BITS | PORT_POWER),  					status_reg); @@ -870,10 +872,9 @@ static int ehci_hub_control (  				usb_hcd_end_port_resume(&hcd->self, wIndex);  				/* stop resume signaling */ -				temp = ehci_readl(ehci, status_reg); -				ehci_writel(ehci, -					temp & ~(PORT_RWC_BITS | PORT_RESUME), -					status_reg); +				temp &= ~(PORT_RWC_BITS | +						PORT_SUSPEND | PORT_RESUME); +				ehci_writel(ehci, temp, status_reg);  				clear_bit(wIndex, &ehci->resuming_ports);  				retval = handshake(ehci, status_reg,  					   PORT_RESUME, 0, 2000 /* 2msec */); @@ -883,7 +884,7 @@ static int ehci_hub_control (  						wIndex + 1, retval);  					goto error;  				} -				temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10)); +				temp = ehci_readl(ehci, status_reg);  			}  		} diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index 88a49c87e74..0f717dc688b 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -22,16 +22,26 @@   * along with this program; if not, you can find it at http://www.fsf.org   */ -#include <linux/platform_device.h>  #include <linux/clk.h>  #include <linux/err.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h>  #include <linux/pm_runtime.h> -  #include <linux/usb/otg.h>  #include <linux/usb/msm_hsusb_hw.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> + +#include "ehci.h"  #define MSM_USB_BASE (hcd->regs) +#define DRIVER_DESC "Qualcomm On-Chip EHCI Host Controller" + +static const char hcd_name[] = "ehci-msm"; +static struct hc_driver __read_mostly msm_hc_driver;  static struct usb_phy *phy;  static int ehci_msm_reset(struct usb_hcd *hcd) @@ -56,52 +66,6 @@ static int ehci_msm_reset(struct usb_hcd *hcd)  	return 0;  } -static struct hc_driver msm_hc_driver = { -	.description		= hcd_name, -	.product_desc		= "Qualcomm On-Chip EHCI Host Controller", -	.hcd_priv_size		= sizeof(struct ehci_hcd), - -	/* -	 * generic hardware linkage -	 */ -	.irq			= ehci_irq, -	.flags			= HCD_USB2 | HCD_MEMORY, - -	.reset			= ehci_msm_reset, -	.start			= ehci_run, - -	.stop			= ehci_stop, -	.shutdown		= ehci_shutdown, - -	/* -	 * managing i/o requests and associated device resources -	 */ -	.urb_enqueue		= ehci_urb_enqueue, -	.urb_dequeue		= ehci_urb_dequeue, -	.endpoint_disable	= ehci_endpoint_disable, -	.endpoint_reset		= ehci_endpoint_reset, -	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, - -	/* -	 * scheduling support -	 */ -	.get_frame_number	= ehci_get_frame, - -	/* -	 * root hub support -	 */ -	.hub_status_data	= ehci_hub_status_data, -	.hub_control		= ehci_hub_control, -	.relinquish_port	= ehci_relinquish_port, -	.port_handed_over	= ehci_port_handed_over, - -	/* -	 * PM support -	 */ -	.bus_suspend		= ehci_bus_suspend, -	.bus_resume		= ehci_bus_resume, -}; -  static int ehci_msm_probe(struct platform_device *pdev)  {  	struct usb_hcd *hcd; @@ -145,7 +109,7 @@ static int ehci_msm_probe(struct platform_device *pdev)  	 * management.  	 */  	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); -	if (IS_ERR_OR_NULL(phy)) { +	if (IS_ERR(phy)) {  		dev_err(&pdev->dev, "unable to find transceiver\n");  		ret = -ENODEV;  		goto put_hcd; @@ -165,6 +129,8 @@ static int ehci_msm_probe(struct platform_device *pdev)  	pm_runtime_no_callbacks(&pdev->dev);  	pm_runtime_enable(&pdev->dev); +	/* FIXME: need to call usb_add_hcd() here? */ +  	return 0;  put_hcd: @@ -183,6 +149,8 @@ static int ehci_msm_remove(struct platform_device *pdev)  	otg_set_host(phy->otg, NULL); +	/* FIXME: need to call usb_remove_hcd() here? */ +  	usb_put_hcd(hcd);  	return 0; @@ -226,3 +194,28 @@ static struct platform_driver ehci_msm_driver = {  		   .pm = &ehci_msm_dev_pm_ops,  	},  }; + +static const struct ehci_driver_overrides msm_overrides __initdata = { +	.reset = ehci_msm_reset, +}; + +static int __init ehci_msm_init(void) +{ +	if (usb_disabled()) +		return -ENODEV; + +	pr_info("%s: " DRIVER_DESC "\n", hcd_name); +	ehci_init_driver(&msm_hc_driver, &msm_overrides); +	return platform_driver_register(&ehci_msm_driver); +} +module_init(ehci_msm_init); + +static void __exit ehci_msm_cleanup(void) +{ +	platform_driver_unregister(&ehci_msm_driver); +} +module_exit(ehci_msm_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_ALIAS("platform:msm-ehci"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index 3065809546b..402062973f0 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -33,25 +33,17 @@ struct ehci_hcd_mv {  	struct mv_usb_platform_data *pdata; -	/* clock source and total clock number */ -	unsigned int clknum; -	struct clk *clk[0]; +	struct clk *clk;  };  static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv)  { -	unsigned int i; - -	for (i = 0; i < ehci_mv->clknum; i++) -		clk_prepare_enable(ehci_mv->clk[i]); +	clk_prepare_enable(ehci_mv->clk);  }  static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv)  { -	unsigned int i; - -	for (i = 0; i < ehci_mv->clknum; i++) -		clk_disable_unprepare(ehci_mv->clk[i]); +	clk_disable_unprepare(ehci_mv->clk);  }  static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv) @@ -144,9 +136,8 @@ static int mv_ehci_probe(struct platform_device *pdev)  	struct ehci_hcd *ehci;  	struct ehci_hcd_mv *ehci_mv;  	struct resource *r; -	int clk_i, retval = -ENODEV; +	int retval = -ENODEV;  	u32 offset; -	size_t size;  	if (!pdata) {  		dev_err(&pdev->dev, "missing platform_data\n"); @@ -160,8 +151,7 @@ static int mv_ehci_probe(struct platform_device *pdev)  	if (!hcd)  		return -ENOMEM; -	size = sizeof(*ehci_mv) + sizeof(struct clk *) * pdata->clknum; -	ehci_mv = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); +	ehci_mv = devm_kzalloc(&pdev->dev, sizeof(*ehci_mv), GFP_KERNEL);  	if (ehci_mv == NULL) {  		dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n");  		retval = -ENOMEM; @@ -172,16 +162,11 @@ static int mv_ehci_probe(struct platform_device *pdev)  	ehci_mv->pdata = pdata;  	ehci_mv->hcd = hcd; -	ehci_mv->clknum = pdata->clknum; -	for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) { -		ehci_mv->clk[clk_i] = -		    devm_clk_get(&pdev->dev, pdata->clkname[clk_i]); -		if (IS_ERR(ehci_mv->clk[clk_i])) { -			dev_err(&pdev->dev, "error get clck \"%s\"\n", -				pdata->clkname[clk_i]); -			retval = PTR_ERR(ehci_mv->clk[clk_i]); -			goto err_clear_drvdata; -		} +	ehci_mv->clk = devm_clk_get(&pdev->dev, NULL); +	if (IS_ERR(ehci_mv->clk)) { +		dev_err(&pdev->dev, "error getting clock\n"); +		retval = PTR_ERR(ehci_mv->clk); +		goto err_clear_drvdata;  	}  	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phyregs"); @@ -225,7 +210,7 @@ static int mv_ehci_probe(struct platform_device *pdev)  		(void __iomem *) ((unsigned long) ehci_mv->cap_regs + offset);  	hcd->rsrc_start = r->start; -	hcd->rsrc_len = r->end - r->start + 1; +	hcd->rsrc_len = resource_size(r);  	hcd->regs = ehci_mv->op_regs;  	hcd->irq = platform_get_irq(pdev, 0); @@ -240,12 +225,16 @@ static int mv_ehci_probe(struct platform_device *pdev)  	ehci_mv->mode = pdata->mode;  	if (ehci_mv->mode == MV_USB_MODE_OTG) { -#ifdef CONFIG_USB_OTG_UTILS  		ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); -		if (IS_ERR_OR_NULL(ehci_mv->otg)) { -			dev_err(&pdev->dev, -				"unable to find transceiver\n"); -			retval = -ENODEV; +		if (IS_ERR(ehci_mv->otg)) { +			retval = PTR_ERR(ehci_mv->otg); + +			if (retval == -ENXIO) +				dev_info(&pdev->dev, "MV_USB_MODE_OTG " +						"must have CONFIG_USB_PHY enabled\n"); +			else +				dev_err(&pdev->dev, +						"unable to find transceiver\n");  			goto err_disable_clk;  		} @@ -258,11 +247,6 @@ static int mv_ehci_probe(struct platform_device *pdev)  		}  		/* otg will enable clock before use as host */  		mv_ehci_disable(ehci_mv); -#else -		dev_info(&pdev->dev, "MV_USB_MODE_OTG " -			 "must have CONFIG_USB_OTG_UTILS enabled\n"); -		goto err_disable_clk; -#endif  	} else {  		if (pdata->set_vbus)  			pdata->set_vbus(1); diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index e9301fb97ea..c369767b00e 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -28,11 +28,7 @@  #include <linux/slab.h>  #include <linux/usb.h>  #include <linux/usb/hcd.h> -  #include <linux/platform_data/usb-ehci-mxc.h> - -#include <asm/mach-types.h> -  #include "ehci.h"  #define DRIVER_DESC "Freescale On-Chip EHCI Host driver" @@ -47,7 +43,7 @@ struct ehci_mxc_priv {  static struct hc_driver __read_mostly ehci_mxc_hc_driver; -static const struct ehci_driver_overrides ehci_mxc_overrides __initdata = { +static const struct ehci_driver_overrides ehci_mxc_overrides __initconst = {  	.extra_priv_size =	sizeof(struct ehci_mxc_priv),  }; @@ -61,8 +57,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)  	struct device *dev = &pdev->dev;  	struct ehci_hcd *ehci; -	dev_info(&pdev->dev, "initializing i.MX USB Controller\n"); -  	if (!pdata) {  		dev_err(dev, "No platform data given, bailing out.\n");  		return -EINVAL; @@ -178,7 +172,7 @@ err_alloc:  	return ret;  } -static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) +static int ehci_mxc_drv_remove(struct platform_device *pdev)  {  	struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data;  	struct usb_hcd *hcd = platform_get_drvdata(pdev); diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 0555ee42d7c..3d1491b5f36 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -4,10 +4,11 @@   * Bus Glue for the EHCI controllers in OMAP3/4   * Tested on several OMAP3 boards, and OMAP4 Pandaboard   * - * Copyright (C) 2007-2011 Texas Instruments, Inc. + * Copyright (C) 2007-2013 Texas Instruments, Inc.   *	Author: Vikram Pandita <vikram.pandita@ti.com>   *	Author: Anand Gadiyar <gadiyar@ti.com>   *	Author: Keshava Munegowda <keshava_mgowda@ti.com> + *	Author: Roger Quadros <rogerq@ti.com>   *   * Copyright (C) 2009 Nokia Corporation   *	Contact: Felipe Balbi <felipe.balbi@nokia.com> @@ -28,21 +29,23 @@   * along with this program; if not, write to the Free Software   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA   * - * TODO (last updated Feb 27, 2010): - *	- add kernel-doc - *	- enable AUTOIDLE - *	- add suspend/resume - *	- add HSIC and TLL support - *	- convert to use hwmod and runtime PM   */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/io.h>  #include <linux/platform_device.h>  #include <linux/slab.h>  #include <linux/usb/ulpi.h> -#include <linux/regulator/consumer.h>  #include <linux/pm_runtime.h>  #include <linux/gpio.h>  #include <linux/clk.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> +#include <linux/of.h> +#include <linux/dma-mapping.h> + +#include "ehci.h"  #include <linux/platform_data/usb-omap.h> @@ -57,10 +60,16 @@  #define	EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT		8  #define	EHCI_INSNREG05_ULPI_WRDATA_SHIFT		0 -/*-------------------------------------------------------------------------*/ +#define DRIVER_DESC "OMAP-EHCI Host Controller driver" + +static const char hcd_name[] = "ehci-omap"; -static const struct hc_driver ehci_omap_hc_driver; +/*-------------------------------------------------------------------------*/ +struct omap_hcd { +	struct usb_phy *phy[OMAP3_HS_USB_PORTS]; /* one PHY for each port */ +	int nports; +};  static inline void ehci_write(void __iomem *base, u32 reg, u32 val)  { @@ -72,99 +81,16 @@ static inline u32 ehci_read(void __iomem *base, u32 reg)  	return __raw_readl(base + reg);  } +/* configure so an HC device and id are always provided */ +/* always called with process context; sleeping is OK */ -static void omap_ehci_soft_phy_reset(struct usb_hcd *hcd, u8 port) -{ -	unsigned long timeout = jiffies + msecs_to_jiffies(1000); -	unsigned reg = 0; - -	reg = ULPI_FUNC_CTRL_RESET -		/* FUNCTION_CTRL_SET register */ -		| (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT) -		/* Write */ -		| (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) -		/* PORTn */ -		| ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) -		/* start ULPI access*/ -		| (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT); - -	ehci_write(hcd->regs, EHCI_INSNREG05_ULPI, reg); - -	/* Wait for ULPI access completion */ -	while ((ehci_read(hcd->regs, EHCI_INSNREG05_ULPI) -			& (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) { -		cpu_relax(); - -		if (time_after(jiffies, timeout)) { -			dev_dbg(hcd->self.controller, -					"phy reset operation timed out\n"); -			break; -		} -	} -} - -static int omap_ehci_init(struct usb_hcd *hcd) -{ -	struct ehci_hcd		*ehci = hcd_to_ehci(hcd); -	int			rc; -	struct usbhs_omap_platform_data	*pdata; - -	pdata = hcd->self.controller->platform_data; - -	/* Hold PHYs in reset while initializing EHCI controller */ -	if (pdata->phy_reset) { -		if (gpio_is_valid(pdata->reset_gpio_port[0])) -			gpio_set_value_cansleep(pdata->reset_gpio_port[0], 0); - -		if (gpio_is_valid(pdata->reset_gpio_port[1])) -			gpio_set_value_cansleep(pdata->reset_gpio_port[1], 0); - -		/* Hold the PHY in RESET for enough time till DIR is high */ -		udelay(10); -	} - -	/* Soft reset the PHY using PHY reset command over ULPI */ -	if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY) -		omap_ehci_soft_phy_reset(hcd, 0); -	if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY) -		omap_ehci_soft_phy_reset(hcd, 1); - -	/* we know this is the memory we want, no need to ioremap again */ -	ehci->caps = hcd->regs; - -	rc = ehci_setup(hcd); - -	if (pdata->phy_reset) { -		/* Hold the PHY in RESET for enough time till -		 * PHY is settled and ready -		 */ -		udelay(10); - -		if (gpio_is_valid(pdata->reset_gpio_port[0])) -			gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1); - -		if (gpio_is_valid(pdata->reset_gpio_port[1])) -			gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1); -	} - -	return rc; -} - -static void disable_put_regulator( -		struct usbhs_omap_platform_data *pdata) -{ -	int i; +static struct hc_driver __read_mostly ehci_omap_hc_driver; -	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { -		if (pdata->regulator[i]) { -			regulator_disable(pdata->regulator[i]); -			regulator_put(pdata->regulator[i]); -		} -	} -} +static const struct ehci_driver_overrides ehci_omap_overrides __initdata = { +	.extra_priv_size = sizeof(struct omap_hcd), +}; -/* configure so an HC device and id are always provided */ -/* always called with process context; sleeping is OK */ +static u64 omap_ehci_dma_mask = DMA_BIT_MASK(32);  /**   * ehci_hcd_omap_probe - initialize TI-based HCDs @@ -175,15 +101,15 @@ static void disable_put_regulator(   */  static int ehci_hcd_omap_probe(struct platform_device *pdev)  { -	struct device				*dev = &pdev->dev; -	struct usbhs_omap_platform_data		*pdata = dev->platform_data; -	struct resource				*res; -	struct usb_hcd				*hcd; -	void __iomem				*regs; -	int					ret = -ENODEV; -	int					irq; -	int					i; -	char					supply[7]; +	struct device *dev = &pdev->dev; +	struct usbhs_omap_platform_data *pdata = dev->platform_data; +	struct resource	*res; +	struct usb_hcd	*hcd; +	void __iomem *regs; +	int ret = -ENODEV; +	int irq; +	int i; +	struct omap_hcd	*omap;  	if (usb_disabled())  		return -ENODEV; @@ -193,52 +119,74 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)  		return -ENODEV;  	} -	irq = platform_get_irq_byname(pdev, "ehci-irq"); -	if (irq < 0) { -		dev_err(dev, "EHCI irq failed\n"); -		return -ENODEV; +	/* For DT boot, get platform data from parent. i.e. usbhshost */ +	if (dev->of_node) { +		pdata = dev->parent->platform_data; +		dev->platform_data = pdata;  	} -	res =  platform_get_resource_byname(pdev, -				IORESOURCE_MEM, "ehci"); -	if (!res) { -		dev_err(dev, "UHH EHCI get resource failed\n"); +	if (!pdata) { +		dev_err(dev, "Missing platform data\n");  		return -ENODEV;  	} -	regs = ioremap(res->start, resource_size(res)); -	if (!regs) { -		dev_err(dev, "UHH EHCI ioremap failed\n"); -		return -ENOMEM; +	irq = platform_get_irq(pdev, 0); +	if (irq < 0) { +		dev_err(dev, "EHCI irq failed\n"); +		return -ENODEV;  	} +	res =  platform_get_resource(pdev, IORESOURCE_MEM, 0); +	regs = devm_ioremap_resource(dev, res); +	if (IS_ERR(regs)) +		return PTR_ERR(regs); + +	/* +	 * Right now device-tree probed devices don't get dma_mask set. +	 * Since shared usb code relies on it, set it here for now. +	 * Once we have dma capability bindings this can go away. +	 */ +	if (!pdev->dev.dma_mask) +		pdev->dev.dma_mask = &omap_ehci_dma_mask; +  	hcd = usb_create_hcd(&ehci_omap_hc_driver, dev,  			dev_name(dev));  	if (!hcd) { -		dev_err(dev, "failed to create hcd with err %d\n", ret); -		ret = -ENOMEM; -		goto err_io; +		dev_err(dev, "Failed to create HCD\n"); +		return -ENOMEM;  	}  	hcd->rsrc_start = res->start;  	hcd->rsrc_len = resource_size(res);  	hcd->regs = regs; +	hcd_to_ehci(hcd)->caps = regs; -	/* get ehci regulator and enable */ -	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { -		if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) { -			pdata->regulator[i] = NULL; -			continue; -		} -		snprintf(supply, sizeof(supply), "hsusb%d", i); -		pdata->regulator[i] = regulator_get(dev, supply); -		if (IS_ERR(pdata->regulator[i])) { -			pdata->regulator[i] = NULL; -			dev_dbg(dev, -			"failed to get ehci port%d regulator\n", i); -		} else { -			regulator_enable(pdata->regulator[i]); +	omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv; +	omap->nports = pdata->nports; + +	platform_set_drvdata(pdev, hcd); + +	/* get the PHY devices if needed */ +	for (i = 0 ; i < omap->nports ; i++) { +		struct usb_phy *phy; + +		/* get the PHY device */ +		if (dev->of_node) +			phy = devm_usb_get_phy_by_phandle(dev, "phys", i); +		else +			phy = devm_usb_get_phy_dev(dev, i); +		if (IS_ERR(phy)) { +			/* Don't bail out if PHY is not absolutely necessary */ +			if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) +				continue; + +			ret = PTR_ERR(phy); +			dev_err(dev, "Can't get PHY device for port %d: %d\n", +					i, ret); +			goto err_phy;  		} + +		omap->phy[i] = phy;  	}  	pm_runtime_enable(dev); @@ -262,16 +210,34 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)  		goto err_pm_runtime;  	} +	/* +	 * Bring PHYs out of reset. +	 * Even though HSIC mode is a PHY-less mode, the reset +	 * line exists between the chips and can be modelled +	 * as a PHY device for reset control. +	 */ +	for (i = 0; i < omap->nports; i++) { +		if (!omap->phy[i]) +			continue; + +		usb_phy_init(omap->phy[i]); +		/* bring PHY out of suspend */ +		usb_phy_set_suspend(omap->phy[i], 0); +	}  	return 0;  err_pm_runtime: -	disable_put_regulator(pdata);  	pm_runtime_put_sync(dev); + +err_phy: +	for (i = 0; i < omap->nports; i++) { +		if (omap->phy[i]) +			usb_phy_shutdown(omap->phy[i]); +	} +  	usb_put_hcd(hcd); -err_io: -	iounmap(regs);  	return ret;  } @@ -286,14 +252,19 @@ err_io:   */  static int ehci_hcd_omap_remove(struct platform_device *pdev)  { -	struct device *dev				= &pdev->dev; -	struct usb_hcd *hcd				= dev_get_drvdata(dev); +	struct device *dev = &pdev->dev; +	struct usb_hcd *hcd = dev_get_drvdata(dev); +	struct omap_hcd *omap = (struct omap_hcd *)hcd_to_ehci(hcd)->priv; +	int i;  	usb_remove_hcd(hcd); -	disable_put_regulator(dev->platform_data); -	iounmap(hcd->regs); -	usb_put_hcd(hcd); +	for (i = 0; i < omap->nports; i++) { +		if (omap->phy[i]) +			usb_phy_shutdown(omap->phy[i]); +	} + +	usb_put_hcd(hcd);  	pm_runtime_put_sync(dev);  	pm_runtime_disable(dev); @@ -308,6 +279,13 @@ static void ehci_hcd_omap_shutdown(struct platform_device *pdev)  		hcd->driver->shutdown(hcd);  } +static const struct of_device_id omap_ehci_dt_ids[] = { +	{ .compatible = "ti,ehci-omap" }, +	{ } +}; + +MODULE_DEVICE_TABLE(of, omap_ehci_dt_ids); +  static struct platform_driver ehci_hcd_omap_driver = {  	.probe			= ehci_hcd_omap_probe,  	.remove			= ehci_hcd_omap_remove, @@ -315,56 +293,35 @@ static struct platform_driver ehci_hcd_omap_driver = {  	/*.suspend		= ehci_hcd_omap_suspend, */  	/*.resume		= ehci_hcd_omap_resume, */  	.driver = { -		.name		= "ehci-omap", +		.name		= hcd_name, +		.of_match_table = of_match_ptr(omap_ehci_dt_ids),  	}  };  /*-------------------------------------------------------------------------*/ -static const struct hc_driver ehci_omap_hc_driver = { -	.description		= hcd_name, -	.product_desc		= "OMAP-EHCI Host Controller", -	.hcd_priv_size		= sizeof(struct ehci_hcd), - -	/* -	 * generic hardware linkage -	 */ -	.irq			= ehci_irq, -	.flags			= HCD_MEMORY | HCD_USB2, - -	/* -	 * basic lifecycle operations -	 */ -	.reset			= omap_ehci_init, -	.start			= ehci_run, -	.stop			= ehci_stop, -	.shutdown		= ehci_shutdown, - -	/* -	 * managing i/o requests and associated device resources -	 */ -	.urb_enqueue		= ehci_urb_enqueue, -	.urb_dequeue		= ehci_urb_dequeue, -	.endpoint_disable	= ehci_endpoint_disable, -	.endpoint_reset		= ehci_endpoint_reset, +static int __init ehci_omap_init(void) +{ +	if (usb_disabled()) +		return -ENODEV; -	/* -	 * scheduling support -	 */ -	.get_frame_number	= ehci_get_frame, +	pr_info("%s: " DRIVER_DESC "\n", hcd_name); -	/* -	 * root hub support -	 */ -	.hub_status_data	= ehci_hub_status_data, -	.hub_control		= ehci_hub_control, -	.bus_suspend		= ehci_bus_suspend, -	.bus_resume		= ehci_bus_resume, +	ehci_init_driver(&ehci_omap_hc_driver, &ehci_omap_overrides); +	return platform_driver_register(&ehci_hcd_omap_driver); +} +module_init(ehci_omap_init); -	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, -}; +static void __exit ehci_omap_cleanup(void) +{ +	platform_driver_unregister(&ehci_hcd_omap_driver); +} +module_exit(ehci_omap_cleanup);  MODULE_ALIAS("platform:ehci-omap");  MODULE_AUTHOR("Texas Instruments, Inc.");  MODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>"); +MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>"); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 914a3ecfb5d..54c57948515 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -17,6 +17,12 @@  #include <linux/of.h>  #include <linux/of_device.h>  #include <linux/of_irq.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> +#include <linux/io.h> +#include <linux/dma-mapping.h> + +#include "ehci.h"  #define rdl(off)	__raw_readl(hcd->regs + (off))  #define wrl(off, val)	__raw_writel((val), hcd->regs + (off)) @@ -34,6 +40,12 @@  #define USB_PHY_IVREF_CTRL	0x440  #define USB_PHY_TST_GRP_CTRL	0x450 +#define DRIVER_DESC "EHCI orion driver" + +static const char hcd_name[] = "ehci-orion"; + +static struct hc_driver __read_mostly ehci_orion_hc_driver; +  /*   * Implement Orion USB controller specification guidelines   */ @@ -104,51 +116,6 @@ static void orion_usb_phy_v1_setup(struct usb_hcd *hcd)  	wrl(USB_MODE, 0x13);  } -static const struct hc_driver ehci_orion_hc_driver = { -	.description = hcd_name, -	.product_desc = "Marvell Orion EHCI", -	.hcd_priv_size = sizeof(struct ehci_hcd), - -	/* -	 * generic hardware linkage -	 */ -	.irq = ehci_irq, -	.flags = HCD_MEMORY | HCD_USB2, - -	/* -	 * basic lifecycle operations -	 */ -	.reset = ehci_setup, -	.start = ehci_run, -	.stop = ehci_stop, -	.shutdown = ehci_shutdown, - -	/* -	 * managing i/o requests and associated device resources -	 */ -	.urb_enqueue = ehci_urb_enqueue, -	.urb_dequeue = ehci_urb_dequeue, -	.endpoint_disable = ehci_endpoint_disable, -	.endpoint_reset = ehci_endpoint_reset, - -	/* -	 * scheduling support -	 */ -	.get_frame_number = ehci_get_frame, - -	/* -	 * root hub support -	 */ -	.hub_status_data = ehci_hub_status_data, -	.hub_control = ehci_hub_control, -	.bus_suspend = ehci_bus_suspend, -	.bus_resume = ehci_bus_resume, -	.relinquish_port = ehci_relinquish_port, -	.port_handed_over = ehci_port_handed_over, - -	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, -}; -  static void  ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,  			     const struct mbus_dram_target_info *dram) @@ -305,7 +272,7 @@ err1:  	return err;  } -static int __exit ehci_orion_drv_remove(struct platform_device *pdev) +static int ehci_orion_drv_remove(struct platform_device *pdev)  {  	struct usb_hcd *hcd = platform_get_drvdata(pdev);  	struct clk *clk; @@ -323,8 +290,6 @@ static int __exit ehci_orion_drv_remove(struct platform_device *pdev)  	return 0;  } -MODULE_ALIAS("platform:orion-ehci"); -  static const struct of_device_id ehci_orion_dt_ids[] = {  	{ .compatible = "marvell,orion-ehci", },  	{}, @@ -333,7 +298,7 @@ MODULE_DEVICE_TABLE(of, ehci_orion_dt_ids);  static struct platform_driver ehci_orion_driver = {  	.probe		= ehci_orion_drv_probe, -	.remove		= __exit_p(ehci_orion_drv_remove), +	.remove		= ehci_orion_drv_remove,  	.shutdown	= usb_hcd_platform_shutdown,  	.driver = {  		.name	= "orion-ehci", @@ -341,3 +306,26 @@ static struct platform_driver ehci_orion_driver = {  		.of_match_table = of_match_ptr(ehci_orion_dt_ids),  	},  }; + +static int __init ehci_orion_init(void) +{ +	if (usb_disabled()) +		return -ENODEV; + +	pr_info("%s: " DRIVER_DESC "\n", hcd_name); + +	ehci_init_driver(&ehci_orion_hc_driver, NULL); +	return platform_driver_register(&ehci_orion_driver); +} +module_init(ehci_orion_init); + +static void __exit ehci_orion_cleanup(void) +{ +	platform_driver_unregister(&ehci_orion_driver); +} +module_exit(ehci_orion_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_ALIAS("platform:orion-ehci"); +MODULE_AUTHOR("Tzachi Perelstein"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 170b9399e09..595d210655b 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -292,17 +292,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)  		}  	} -#ifdef	CONFIG_USB_SUSPEND -	/* REVISIT: the controller works fine for wakeup iff the root hub -	 * itself is "globally" suspended, but usbcore currently doesn't -	 * understand such things. -	 * -	 * System suspend currently expects to be able to suspend the entire -	 * device tree, device-at-a-time.  If we failed selective suspend -	 * reports, system suspend would fail; so the root hub code must claim -	 * success.  That's lying to usbcore, and it matters for runtime -	 * PM scenarios with selective suspend and remote wakeup... -	 */ +#ifdef	CONFIG_PM_RUNTIME  	if (ehci->no_selective_suspend && device_can_wakeup(&pdev->dev))  		ehci_warn(ehci, "selective suspend/wakeup unavailable\n");  #endif @@ -385,7 +375,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)  static struct hc_driver __read_mostly ehci_pci_hc_driver; -static const struct ehci_driver_overrides pci_overrides __initdata = { +static const struct ehci_driver_overrides pci_overrides __initconst = {  	.reset =		ehci_pci_setup,  }; diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index ca750639054..f47f2594c9d 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -18,11 +18,13 @@   *   * Licensed under the GNU/GPL. See COPYING for details.   */ +#include <linux/dma-mapping.h>  #include <linux/err.h>  #include <linux/kernel.h>  #include <linux/hrtimer.h>  #include <linux/io.h>  #include <linux/module.h> +#include <linux/of.h>  #include <linux/platform_device.h>  #include <linux/usb.h>  #include <linux/usb/hcd.h> @@ -58,26 +60,36 @@ static int ehci_platform_reset(struct usb_hcd *hcd)  static struct hc_driver __read_mostly ehci_platform_hc_driver; -static const struct ehci_driver_overrides platform_overrides __initdata = { +static const struct ehci_driver_overrides platform_overrides __initconst = {  	.reset =	ehci_platform_reset,  }; +static struct usb_ehci_pdata ehci_platform_defaults; +  static int ehci_platform_probe(struct platform_device *dev)  {  	struct usb_hcd *hcd;  	struct resource *res_mem; -	struct usb_ehci_pdata *pdata = dev->dev.platform_data; +	struct usb_ehci_pdata *pdata;  	int irq;  	int err = -ENOMEM; -	if (!pdata) { -		WARN_ON(1); -		return -ENODEV; -	} -  	if (usb_disabled())  		return -ENODEV; +	/* +	 * use reasonable defaults so platforms don't have to provide these. +	 * with DT probing on ARM, none of these are set. +	 */ +	if (!dev->dev.platform_data) +		dev->dev.platform_data = &ehci_platform_defaults; +	if (!dev->dev.dma_mask) +		dev->dev.dma_mask = &dev->dev.coherent_dma_mask; +	if (!dev->dev.coherent_dma_mask) +		dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + +	pdata = dev->dev.platform_data; +  	irq = platform_get_irq(dev, 0);  	if (irq < 0) {  		dev_err(&dev->dev, "no irq provided"); @@ -139,6 +151,9 @@ static int ehci_platform_remove(struct platform_device *dev)  	if (pdata->power_off)  		pdata->power_off(dev); +	if (pdata == &ehci_platform_defaults) +		dev->dev.platform_data = NULL; +  	return 0;  } @@ -183,6 +198,12 @@ static int ehci_platform_resume(struct device *dev)  #define ehci_platform_resume	NULL  #endif /* CONFIG_PM */ +static const struct of_device_id vt8500_ehci_ids[] = { +	{ .compatible = "via,vt8500-ehci", }, +	{ .compatible = "wm,prizm-ehci", }, +	{} +}; +  static const struct platform_device_id ehci_platform_table[] = {  	{ "ehci-platform", 0 },  	{ } @@ -203,6 +224,7 @@ static struct platform_driver ehci_platform_driver = {  		.owner	= THIS_MODULE,  		.name	= "ehci-platform",  		.pm	= &ehci_platform_pm_ops, +		.of_match_table = of_match_ptr(vt8500_ehci_ids),  	}  }; diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index df5925a4f0d..fd983771b02 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c @@ -221,7 +221,6 @@ static int ps3_ehci_remove(struct ps3_system_bus_device *dev)  	tmp = hcd->irq; -	ehci_shutdown(hcd);  	usb_remove_hcd(hcd);  	ps3_system_bus_set_drvdata(dev, NULL); diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 23d13690428..d34b399b78e 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -90,7 +90,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd)  	struct ehci_qh_hw *hw = qh->hw;  	/* writes to an active overlay are unsafe */ -	BUG_ON(qh->qh_state != QH_STATE_IDLE); +	WARN_ON(qh->qh_state != QH_STATE_IDLE);  	hw->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma);  	hw->hw_alt_next = EHCI_LIST_END(ehci); @@ -123,26 +123,19 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)  {  	struct ehci_qtd *qtd; -	if (list_empty (&qh->qtd_list)) -		qtd = qh->dummy; -	else { -		qtd = list_entry (qh->qtd_list.next, -				struct ehci_qtd, qtd_list); -		/* -		 * first qtd may already be partially processed. -		 * If we come here during unlink, the QH overlay region -		 * might have reference to the just unlinked qtd. The -		 * qtd is updated in qh_completions(). Update the QH -		 * overlay here. -		 */ -		if (qh->hw->hw_token & ACTIVE_BIT(ehci)) { -			qh->hw->hw_qtd_next = qtd->hw_next; -			qtd = NULL; -		} -	} +	qtd = list_entry(qh->qtd_list.next, struct ehci_qtd, qtd_list); -	if (qtd) -		qh_update (ehci, qh, qtd); +	/* +	 * first qtd may already be partially processed. +	 * If we come here during unlink, the QH overlay region +	 * might have reference to the just unlinked qtd. The +	 * qtd is updated in qh_completions(). Update the QH +	 * overlay here. +	 */ +	if (qh->hw->hw_token & ACTIVE_BIT(ehci)) +		qh->hw->hw_qtd_next = qtd->hw_next; +	else +		qh_update(ehci, qh, qtd);  }  /*-------------------------------------------------------------------------*/ @@ -299,8 +292,8 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);  /*   * Process and free completed qtds for a qh, returning URBs to drivers. - * Chases up to qh->hw_current.  Returns number of completions called, - * indicating how much "real" work we did. + * Chases up to qh->hw_current.  Returns nonzero if the caller should + * unlink qh.   */  static unsigned  qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) @@ -309,13 +302,9 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)  	struct list_head	*entry, *tmp;  	int			last_status;  	int			stopped; -	unsigned		count = 0;  	u8			state;  	struct ehci_qh_hw	*hw = qh->hw; -	if (unlikely (list_empty (&qh->qtd_list))) -		return count; -  	/* completions (or tasks on other cpus) must never clobber HALT  	 * till we've gone through and cleaned everything up, even when  	 * they add urbs to this qh's queue or mark them for unlinking. @@ -333,7 +322,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)   rescan:  	last = NULL;  	last_status = -EINPROGRESS; -	qh->needs_rescan = 0; +	qh->dequeue_during_giveback = 0;  	/* remove de-activated QTDs from front of queue.  	 * after faults (including short reads), cleanup this urb @@ -352,7 +341,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)  		if (last) {  			if (likely (last->urb != urb)) {  				ehci_urb_done(ehci, last->urb, last_status); -				count++;  				last_status = -EINPROGRESS;  			}  			ehci_qtd_free (ehci, last); @@ -526,23 +514,16 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)  	/* last urb's completion might still need calling */  	if (likely (last != NULL)) {  		ehci_urb_done(ehci, last->urb, last_status); -		count++;  		ehci_qtd_free (ehci, last);  	}  	/* Do we need to rescan for URBs dequeued during a giveback? */ -	if (unlikely(qh->needs_rescan)) { +	if (unlikely(qh->dequeue_during_giveback)) {  		/* If the QH is already unlinked, do the rescan now. */  		if (state == QH_STATE_IDLE)  			goto rescan; -		/* Otherwise we have to wait until the QH is fully unlinked. -		 * Our caller will start an unlink if qh->needs_rescan is -		 * set.  But if an unlink has already started, nothing needs -		 * to be done. -		 */ -		if (state != QH_STATE_LINKED) -			qh->needs_rescan = 0; +		/* Otherwise the caller must unlink the QH. */  	}  	/* restore original state; caller must unlink or relink */ @@ -551,33 +532,23 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)  	/* be sure the hardware's done with the qh before refreshing  	 * it after fault cleanup, or recovering from silicon wrongly  	 * overlaying the dummy qtd (which reduces DMA chatter). +	 * +	 * We won't refresh a QH that's linked (after the HC +	 * stopped the queue).  That avoids a race: +	 *  - HC reads first part of QH; +	 *  - CPU updates that first part and the token; +	 *  - HC reads rest of that QH, including token +	 * Result:  HC gets an inconsistent image, and then +	 * DMAs to/from the wrong memory (corrupting it). +	 * +	 * That should be rare for interrupt transfers, +	 * except maybe high bandwidth ...  	 */ -	if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci)) { -		switch (state) { -		case QH_STATE_IDLE: -			qh_refresh(ehci, qh); -			break; -		case QH_STATE_LINKED: -			/* We won't refresh a QH that's linked (after the HC -			 * stopped the queue).  That avoids a race: -			 *  - HC reads first part of QH; -			 *  - CPU updates that first part and the token; -			 *  - HC reads rest of that QH, including token -			 * Result:  HC gets an inconsistent image, and then -			 * DMAs to/from the wrong memory (corrupting it). -			 * -			 * That should be rare for interrupt transfers, -			 * except maybe high bandwidth ... -			 */ +	if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci)) +		qh->exception = 1; -			/* Tell the caller to start an unlink */ -			qh->needs_rescan = 1; -			break; -		/* otherwise, unlink already started */ -		} -	} - -	return count; +	/* Let the caller know if the QH needs to be unlinked. */ +	return qh->exception;  }  /*-------------------------------------------------------------------------*/ @@ -957,14 +928,13 @@ done:  	/* NOTE:  if (PIPE_INTERRUPT) { scheduler sets s-mask } */ -	/* init as live, toggle clear, advance to dummy */ +	/* init as live, toggle clear */  	qh->qh_state = QH_STATE_IDLE;  	hw = qh->hw;  	hw->hw_info1 = cpu_to_hc32(ehci, info1);  	hw->hw_info2 = cpu_to_hc32(ehci, info2);  	qh->is_out = !is_input;  	usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); -	qh_refresh (ehci, qh);  	return qh;  } @@ -988,8 +958,9 @@ static void disable_async(struct ehci_hcd *ehci)  	if (--ehci->async_count)  		return; -	/* The async schedule and async_unlink list are supposed to be empty */ -	WARN_ON(ehci->async->qh_next.qh || ehci->async_unlink); +	/* The async schedule and unlink lists are supposed to be empty */ +	WARN_ON(ehci->async->qh_next.qh || !list_empty(&ehci->async_unlink) || +			!list_empty(&ehci->async_idle));  	/* Don't turn off the schedule until ASS is 1 */  	ehci_poll_ASS(ehci); @@ -1020,8 +991,9 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)  	head->qh_next.qh = qh;  	head->hw->hw_next = dma; -	qh->xacterrs = 0;  	qh->qh_state = QH_STATE_LINKED; +	qh->xacterrs = 0; +	qh->exception = 0;  	/* qtd completions reported later by interrupt */  	enable_async(ehci); @@ -1179,11 +1151,7 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)  	/* Add to the end of the list of QHs waiting for the next IAAD */  	qh->qh_state = QH_STATE_UNLINK_WAIT; -	if (ehci->async_unlink) -		ehci->async_unlink_last->unlink_next = qh; -	else -		ehci->async_unlink = qh; -	ehci->async_unlink_last = qh; +	list_add_tail(&qh->unlink_node, &ehci->async_unlink);  	/* Unlink it from the schedule */  	prev = ehci->async; @@ -1196,44 +1164,19 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)  		ehci->qh_scan_next = qh->qh_next.qh;  } -static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested) +static void start_iaa_cycle(struct ehci_hcd *ehci)  { -	/* -	 * Do nothing if an IAA cycle is already running or -	 * if one will be started shortly. -	 */ -	if (ehci->async_iaa || ehci->async_unlinking) +	/* Do nothing if an IAA cycle is already running */ +	if (ehci->iaa_in_progress)  		return; +	ehci->iaa_in_progress = true;  	/* If the controller isn't running, we don't have to wait for it */  	if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) { - -		/* Do all the waiting QHs */ -		ehci->async_iaa = ehci->async_unlink; -		ehci->async_unlink = NULL; - -		if (!nested)		/* Avoid recursion */ -			end_unlink_async(ehci); +		end_unlink_async(ehci);  	/* Otherwise start a new IAA cycle */  	} else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) { -		struct ehci_qh		*qh; - -		/* Do only the first waiting QH (nVidia bug?) */ -		qh = ehci->async_unlink; - -		/* -		 * Intel (?) bug: The HC can write back the overlay region -		 * even after the IAA interrupt occurs.  In self-defense, -		 * always go through two IAA cycles for each QH. -		 */ -		if (qh->qh_state == QH_STATE_UNLINK_WAIT) { -			qh->qh_state = QH_STATE_UNLINK; -		} else { -			ehci->async_iaa = qh; -			ehci->async_unlink = qh->unlink_next; -			qh->unlink_next = NULL; -		}  		/* Make sure the unlinks are all visible to the hardware */  		wmb(); @@ -1250,36 +1193,73 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)  static void end_unlink_async(struct ehci_hcd *ehci)  {  	struct ehci_qh		*qh; +	bool			early_exit;  	if (ehci->has_synopsys_hc_bug)  		ehci_writel(ehci, (u32) ehci->async->qh_dma,  			    &ehci->regs->async_next); +	/* The current IAA cycle has ended */ +	ehci->iaa_in_progress = false; + +	if (list_empty(&ehci->async_unlink)) +		return; +	qh = list_first_entry(&ehci->async_unlink, struct ehci_qh, +			unlink_node);	/* QH whose IAA cycle just ended */ + +	/* +	 * If async_unlinking is set then this routine is already running, +	 * either on the stack or on another CPU. +	 */ +	early_exit = ehci->async_unlinking; + +	/* If the controller isn't running, process all the waiting QHs */ +	if (ehci->rh_state < EHCI_RH_RUNNING) +		list_splice_tail_init(&ehci->async_unlink, &ehci->async_idle); + +	/* +	 * Intel (?) bug: The HC can write back the overlay region even +	 * after the IAA interrupt occurs.  In self-defense, always go +	 * through two IAA cycles for each QH. +	 */ +	else if (qh->qh_state == QH_STATE_UNLINK_WAIT) { +		qh->qh_state = QH_STATE_UNLINK; +		early_exit = true; +	} + +	/* Otherwise process only the first waiting QH (NVIDIA bug?) */ +	else +		list_move_tail(&qh->unlink_node, &ehci->async_idle); + +	/* Start a new IAA cycle if any QHs are waiting for it */ +	if (!list_empty(&ehci->async_unlink)) +		start_iaa_cycle(ehci); + +	/* +	 * Don't allow nesting or concurrent calls, +	 * or wait for the second IAA cycle for the next QH. +	 */ +	if (early_exit) +		return; +  	/* Process the idle QHs */ - restart:  	ehci->async_unlinking = true; -	while (ehci->async_iaa) { -		qh = ehci->async_iaa; -		ehci->async_iaa = qh->unlink_next; -		qh->unlink_next = NULL; +	while (!list_empty(&ehci->async_idle)) { +		qh = list_first_entry(&ehci->async_idle, struct ehci_qh, +				unlink_node); +		list_del(&qh->unlink_node);  		qh->qh_state = QH_STATE_IDLE;  		qh->qh_next.qh = NULL; -		qh_completions(ehci, qh); +		if (!list_empty(&qh->qtd_list)) +			qh_completions(ehci, qh);  		if (!list_empty(&qh->qtd_list) &&  				ehci->rh_state == EHCI_RH_RUNNING)  			qh_link_async(ehci, qh);  		disable_async(ehci);  	}  	ehci->async_unlinking = false; - -	/* Start a new IAA cycle if any QHs are waiting for it */ -	if (ehci->async_unlink) { -		start_iaa_cycle(ehci, true); -		if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) -			goto restart; -	}  }  static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh); @@ -1288,7 +1268,6 @@ static void unlink_empty_async(struct ehci_hcd *ehci)  {  	struct ehci_qh		*qh;  	struct ehci_qh		*qh_to_unlink = NULL; -	bool			check_unlinks_later = false;  	int			count = 0;  	/* Find the last async QH which has been empty for a timer cycle */ @@ -1296,15 +1275,13 @@ static void unlink_empty_async(struct ehci_hcd *ehci)  		if (list_empty(&qh->qtd_list) &&  				qh->qh_state == QH_STATE_LINKED) {  			++count; -			if (qh->unlink_cycle == ehci->async_unlink_cycle) -				check_unlinks_later = true; -			else +			if (qh->unlink_cycle != ehci->async_unlink_cycle)  				qh_to_unlink = qh;  		}  	}  	/* If nothing else is being unlinked, unlink the last empty QH */ -	if (!ehci->async_iaa && !ehci->async_unlink && qh_to_unlink) { +	if (list_empty(&ehci->async_unlink) && qh_to_unlink) {  		start_unlink_async(ehci, qh_to_unlink);  		--count;  	} @@ -1317,7 +1294,7 @@ static void unlink_empty_async(struct ehci_hcd *ehci)  }  /* The root hub is suspended; unlink all the async QHs */ -static void unlink_empty_async_suspended(struct ehci_hcd *ehci) +static void __maybe_unused unlink_empty_async_suspended(struct ehci_hcd *ehci)  {  	struct ehci_qh		*qh; @@ -1326,7 +1303,7 @@ static void unlink_empty_async_suspended(struct ehci_hcd *ehci)  		WARN_ON(!list_empty(&qh->qtd_list));  		single_unlink_async(ehci, qh);  	} -	start_iaa_cycle(ehci, false); +	start_iaa_cycle(ehci);  }  /* makes sure the async qh will become idle */ @@ -1334,19 +1311,12 @@ static void unlink_empty_async_suspended(struct ehci_hcd *ehci)  static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)  { -	/* -	 * If the QH isn't linked then there's nothing we can do -	 * unless we were called during a giveback, in which case -	 * qh_completions() has to deal with it. -	 */ -	if (qh->qh_state != QH_STATE_LINKED) { -		if (qh->qh_state == QH_STATE_COMPLETING) -			qh->needs_rescan = 1; +	/* If the QH isn't linked then there's nothing we can do. */ +	if (qh->qh_state != QH_STATE_LINKED)  		return; -	}  	single_unlink_async(ehci, qh); -	start_iaa_cycle(ehci, false); +	start_iaa_cycle(ehci);  }  /*-------------------------------------------------------------------------*/ @@ -1360,7 +1330,7 @@ static void scan_async (struct ehci_hcd *ehci)  	while (ehci->qh_scan_next) {  		qh = ehci->qh_scan_next;  		ehci->qh_scan_next = qh->qh_next.qh; - rescan: +  		/* clean any finished work for this qh */  		if (!list_empty(&qh->qtd_list)) {  			int temp; @@ -1373,14 +1343,13 @@ static void scan_async (struct ehci_hcd *ehci)  			 * in single_unlink_async().  			 */  			temp = qh_completions(ehci, qh); -			if (qh->needs_rescan) { +			if (unlikely(temp)) {  				start_unlink_async(ehci, qh);  			} else if (list_empty(&qh->qtd_list)  					&& qh->qh_state == QH_STATE_LINKED) {  				qh->unlink_cycle = ehci->async_unlink_cycle;  				check_unlinks_later = true; -			} else if (temp != 0) -				goto rescan; +			}  		}  	} diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c index 20ebf6a8b7f..635775278c7 100644 --- a/drivers/usb/host/ehci-s5p.c +++ b/drivers/usb/host/ehci-s5p.c @@ -13,13 +13,23 @@   */  #include <linux/clk.h> +#include <linux/dma-mapping.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h>  #include <linux/of.h> -#include <linux/platform_device.h>  #include <linux/of_gpio.h> +#include <linux/platform_device.h>  #include <linux/platform_data/usb-ehci-s5p.h>  #include <linux/usb/phy.h>  #include <linux/usb/samsung_usb_phy.h> -#include <plat/usb-phy.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> +#include <linux/usb/otg.h> + +#include "ehci.h" + +#define DRIVER_DESC "EHCI s5p driver"  #define EHCI_INSNREG00(base)			(base + 0x90)  #define EHCI_INSNREG00_ENA_INCR16		(0x1 << 25) @@ -30,82 +40,35 @@  	(EHCI_INSNREG00_ENA_INCR16 | EHCI_INSNREG00_ENA_INCR8 |	\  	 EHCI_INSNREG00_ENA_INCR4 | EHCI_INSNREG00_ENA_INCRX_ALIGN) +static const char hcd_name[] = "ehci-s5p"; +static struct hc_driver __read_mostly s5p_ehci_hc_driver; +  struct s5p_ehci_hcd { -	struct device *dev; -	struct usb_hcd *hcd;  	struct clk *clk;  	struct usb_phy *phy;  	struct usb_otg *otg;  	struct s5p_ehci_platdata *pdata;  }; -static const struct hc_driver s5p_ehci_hc_driver = { -	.description		= hcd_name, -	.product_desc		= "S5P EHCI Host Controller", -	.hcd_priv_size		= sizeof(struct ehci_hcd), - -	.irq			= ehci_irq, -	.flags			= HCD_MEMORY | HCD_USB2, - -	.reset			= ehci_setup, -	.start			= ehci_run, -	.stop			= ehci_stop, -	.shutdown		= ehci_shutdown, - -	.get_frame_number	= ehci_get_frame, - -	.urb_enqueue		= ehci_urb_enqueue, -	.urb_dequeue		= ehci_urb_dequeue, -	.endpoint_disable	= ehci_endpoint_disable, -	.endpoint_reset		= ehci_endpoint_reset, - -	.hub_status_data	= ehci_hub_status_data, -	.hub_control		= ehci_hub_control, -	.bus_suspend		= ehci_bus_suspend, -	.bus_resume		= ehci_bus_resume, - -	.relinquish_port	= ehci_relinquish_port, -	.port_handed_over	= ehci_port_handed_over, - -	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete, -}; - -static void s5p_ehci_phy_enable(struct s5p_ehci_hcd *s5p_ehci) -{ -	struct platform_device *pdev = to_platform_device(s5p_ehci->dev); - -	if (s5p_ehci->phy) -		usb_phy_init(s5p_ehci->phy); -	else if (s5p_ehci->pdata->phy_init) -		s5p_ehci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST); -} - -static void s5p_ehci_phy_disable(struct s5p_ehci_hcd *s5p_ehci) -{ -	struct platform_device *pdev = to_platform_device(s5p_ehci->dev); - -	if (s5p_ehci->phy) -		usb_phy_shutdown(s5p_ehci->phy); -	else if (s5p_ehci->pdata->phy_exit) -		s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST); -} +#define to_s5p_ehci(hcd)      (struct s5p_ehci_hcd *)(hcd_to_ehci(hcd)->priv)  static void s5p_setup_vbus_gpio(struct platform_device *pdev)  { +	struct device *dev = &pdev->dev;  	int err;  	int gpio; -	if (!pdev->dev.of_node) +	if (!dev->of_node)  		return; -	gpio = of_get_named_gpio(pdev->dev.of_node, -			"samsung,vbus-gpio", 0); +	gpio = of_get_named_gpio(dev->of_node, "samsung,vbus-gpio", 0);  	if (!gpio_is_valid(gpio))  		return; -	err = gpio_request_one(gpio, GPIOF_OUT_INIT_HIGH, "ehci_vbus_gpio"); +	err = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_HIGH, +				    "ehci_vbus_gpio");  	if (err) -		dev_err(&pdev->dev, "can't request ehci vbus gpio %d", gpio); +		dev_err(dev, "can't request ehci vbus gpio %d", gpio);  }  static u64 ehci_s5p_dma_mask = DMA_BIT_MASK(32); @@ -133,13 +96,15 @@ static int s5p_ehci_probe(struct platform_device *pdev)  	s5p_setup_vbus_gpio(pdev); -	s5p_ehci = devm_kzalloc(&pdev->dev, sizeof(struct s5p_ehci_hcd), -				GFP_KERNEL); -	if (!s5p_ehci) +	hcd = usb_create_hcd(&s5p_ehci_hc_driver, +			     &pdev->dev, dev_name(&pdev->dev)); +	if (!hcd) { +		dev_err(&pdev->dev, "Unable to create HCD\n");  		return -ENOMEM; - +	} +	s5p_ehci = to_s5p_ehci(hcd);  	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); -	if (IS_ERR_OR_NULL(phy)) { +	if (IS_ERR(phy)) {  		/* Fallback to pdata */  		if (!pdata) {  			dev_warn(&pdev->dev, "no platform data or transceiver defined\n"); @@ -152,16 +117,6 @@ static int s5p_ehci_probe(struct platform_device *pdev)  		s5p_ehci->otg = phy->otg;  	} -	s5p_ehci->dev = &pdev->dev; - -	hcd = usb_create_hcd(&s5p_ehci_hc_driver, &pdev->dev, -					dev_name(&pdev->dev)); -	if (!hcd) { -		dev_err(&pdev->dev, "Unable to create HCD\n"); -		return -ENOMEM; -	} - -	s5p_ehci->hcd = hcd;  	s5p_ehci->clk = devm_clk_get(&pdev->dev, "usbhost");  	if (IS_ERR(s5p_ehci->clk)) { @@ -198,9 +153,12 @@ static int s5p_ehci_probe(struct platform_device *pdev)  	}  	if (s5p_ehci->otg) -		s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self); +		s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self); -	s5p_ehci_phy_enable(s5p_ehci); +	if (s5p_ehci->phy) +		usb_phy_init(s5p_ehci->phy); +	else if (s5p_ehci->pdata->phy_init) +		s5p_ehci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);  	ehci = hcd_to_ehci(hcd);  	ehci->caps = hcd->regs; @@ -214,12 +172,15 @@ static int s5p_ehci_probe(struct platform_device *pdev)  		goto fail_add_hcd;  	} -	platform_set_drvdata(pdev, s5p_ehci); +	platform_set_drvdata(pdev, hcd);  	return 0;  fail_add_hcd: -	s5p_ehci_phy_disable(s5p_ehci); +	if (s5p_ehci->phy) +		usb_phy_shutdown(s5p_ehci->phy); +	else if (s5p_ehci->pdata->phy_exit) +		s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);  fail_io:  	clk_disable_unprepare(s5p_ehci->clk);  fail_clk: @@ -229,15 +190,18 @@ fail_clk:  static int s5p_ehci_remove(struct platform_device *pdev)  { -	struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev); -	struct usb_hcd *hcd = s5p_ehci->hcd; +	struct usb_hcd *hcd = platform_get_drvdata(pdev); +	struct s5p_ehci_hcd *s5p_ehci = to_s5p_ehci(hcd);  	usb_remove_hcd(hcd);  	if (s5p_ehci->otg) -		s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self); +		s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self); -	s5p_ehci_phy_disable(s5p_ehci); +	if (s5p_ehci->phy) +		usb_phy_shutdown(s5p_ehci->phy); +	else if (s5p_ehci->pdata->phy_exit) +		s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);  	clk_disable_unprepare(s5p_ehci->clk); @@ -248,8 +212,7 @@ static int s5p_ehci_remove(struct platform_device *pdev)  static void s5p_ehci_shutdown(struct platform_device *pdev)  { -	struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev); -	struct usb_hcd *hcd = s5p_ehci->hcd; +	struct usb_hcd *hcd = platform_get_drvdata(pdev);  	if (hcd->driver->shutdown)  		hcd->driver->shutdown(hcd); @@ -258,17 +221,22 @@ static void s5p_ehci_shutdown(struct platform_device *pdev)  #ifdef CONFIG_PM  static int s5p_ehci_suspend(struct device *dev)  { -	struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev); -	struct usb_hcd *hcd = s5p_ehci->hcd; +	struct usb_hcd *hcd = dev_get_drvdata(dev); +	struct s5p_ehci_hcd *s5p_ehci = to_s5p_ehci(hcd); +	struct platform_device *pdev = to_platform_device(dev); +  	bool do_wakeup = device_may_wakeup(dev);  	int rc;  	rc = ehci_suspend(hcd, do_wakeup);  	if (s5p_ehci->otg) -		s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self); +		s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self); -	s5p_ehci_phy_disable(s5p_ehci); +	if (s5p_ehci->phy) +		usb_phy_shutdown(s5p_ehci->phy); +	else if (s5p_ehci->pdata->phy_exit) +		s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);  	clk_disable_unprepare(s5p_ehci->clk); @@ -277,15 +245,19 @@ static int s5p_ehci_suspend(struct device *dev)  static int s5p_ehci_resume(struct device *dev)  { -	struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev); -	struct usb_hcd *hcd = s5p_ehci->hcd; +	struct usb_hcd *hcd = dev_get_drvdata(dev); +	struct  s5p_ehci_hcd *s5p_ehci = to_s5p_ehci(hcd); +	struct platform_device *pdev = to_platform_device(dev);  	clk_prepare_enable(s5p_ehci->clk);  	if (s5p_ehci->otg) -		s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self); +		s5p_ehci->otg->set_host(s5p_ehci->otg, &hcd->self); -	s5p_ehci_phy_enable(s5p_ehci); +	if (s5p_ehci->phy) +		usb_phy_init(s5p_ehci->phy); +	else if (s5p_ehci->pdata->phy_init) +		s5p_ehci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);  	/* DMA burst Enable */  	writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); @@ -322,5 +294,29 @@ static struct platform_driver s5p_ehci_driver = {  		.of_match_table = of_match_ptr(exynos_ehci_match),  	}  }; +static const struct ehci_driver_overrides s5p_overrides __initdata = { +	.extra_priv_size = sizeof(struct s5p_ehci_hcd), +}; + +static int __init ehci_s5p_init(void) +{ +	if (usb_disabled()) +		return -ENODEV; + +	pr_info("%s: " DRIVER_DESC "\n", hcd_name); +	ehci_init_driver(&s5p_ehci_hc_driver, &s5p_overrides); +	return platform_driver_register(&s5p_ehci_driver); +} +module_init(ehci_s5p_init); + +static void __exit ehci_s5p_cleanup(void) +{ +	platform_driver_unregister(&s5p_ehci_driver); +} +module_exit(ehci_s5p_cleanup); +MODULE_DESCRIPTION(DRIVER_DESC);  MODULE_ALIAS("platform:s5p-ehci"); +MODULE_AUTHOR("Jingoo Han"); +MODULE_AUTHOR("Joonyoung Shim"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 010f686d888..acff5b8f6e8 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -539,6 +539,7 @@ static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)  	}  	qh->qh_state = QH_STATE_LINKED;  	qh->xacterrs = 0; +	qh->exception = 0;  	/* update per-qh bandwidth for usbfs */  	ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->period @@ -602,15 +603,9 @@ static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh)  static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)  { -	/* If the QH isn't linked then there's nothing we can do -	 * unless we were called during a giveback, in which case -	 * qh_completions() has to deal with it. -	 */ -	if (qh->qh_state != QH_STATE_LINKED) { -		if (qh->qh_state == QH_STATE_COMPLETING) -			qh->needs_rescan = 1; +	/* If the QH isn't linked then there's nothing we can do. */ +	if (qh->qh_state != QH_STATE_LINKED)  		return; -	}  	qh_unlink_periodic (ehci, qh); @@ -625,17 +620,13 @@ static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)  	qh->unlink_cycle = ehci->intr_unlink_cycle;  	/* New entries go at the end of the intr_unlink list */ -	if (ehci->intr_unlink) -		ehci->intr_unlink_last->unlink_next = qh; -	else -		ehci->intr_unlink = qh; -	ehci->intr_unlink_last = qh; +	list_add_tail(&qh->unlink_node, &ehci->intr_unlink);  	if (ehci->intr_unlinking)  		;	/* Avoid recursive calls */  	else if (ehci->rh_state < EHCI_RH_RUNNING)  		ehci_handle_intr_unlinks(ehci); -	else if (ehci->intr_unlink == qh) { +	else if (ehci->intr_unlink.next == &qh->unlink_node) {  		ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true);  		++ehci->intr_unlink_cycle;  	} @@ -649,7 +640,8 @@ static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh)  	qh->qh_state = QH_STATE_IDLE;  	hw->hw_next = EHCI_LIST_END(ehci); -	qh_completions(ehci, qh); +	if (!list_empty(&qh->qtd_list)) +		qh_completions(ehci, qh);  	/* reschedule QH iff another request is queued */  	if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) { @@ -792,7 +784,6 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)  	unsigned	frame;		/* 0..(qh->period - 1), or NO_FRAME */  	struct ehci_qh_hw	*hw = qh->hw; -	qh_refresh(ehci, qh);  	hw->hw_next = EHCI_LIST_END(ehci);  	frame = qh->start; @@ -844,8 +835,6 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh)  	} else  		ehci_dbg (ehci, "reused qh %p schedule\n", qh); -	/* stuff into the periodic schedule */ -	qh_link_periodic(ehci, qh);  done:  	return status;  } @@ -891,6 +880,12 @@ static int intr_submit (  	qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv);  	BUG_ON (qh == NULL); +	/* stuff into the periodic schedule */ +	if (qh->qh_state == QH_STATE_IDLE) { +		qh_refresh(ehci, qh); +		qh_link_periodic(ehci, qh); +	} +  	/* ... update usbfs periodic stats */  	ehci_to_hcd(ehci)->self.bandwidth_int_reqs++; @@ -911,7 +906,7 @@ static void scan_intr(struct ehci_hcd *ehci)  	list_for_each_entry_safe(qh, ehci->qh_scan_next, &ehci->intr_qh_list,  			intr_node) { - rescan: +  		/* clean any finished work for this qh */  		if (!list_empty(&qh->qtd_list)) {  			int temp; @@ -924,12 +919,9 @@ static void scan_intr(struct ehci_hcd *ehci)  			 * in qh_unlink_periodic().  			 */  			temp = qh_completions(ehci, qh); -			if (unlikely(qh->needs_rescan || -					(list_empty(&qh->qtd_list) && -						qh->qh_state == QH_STATE_LINKED))) +			if (unlikely(temp || (list_empty(&qh->qtd_list) && +					qh->qh_state == QH_STATE_LINKED)))  				start_unlink_intr(ehci, qh); -			else if (temp != 0) -				goto rescan;  		}  	}  } diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c index 3565a300f40..b44d716ddc8 100644 --- a/drivers/usb/host/ehci-sh.c +++ b/drivers/usb/host/ehci-sh.c @@ -77,7 +77,6 @@ static const struct hc_driver ehci_sh_hc_driver = {  static int ehci_hcd_sh_probe(struct platform_device *pdev)  { -	const struct hc_driver *driver = &ehci_sh_hc_driver;  	struct resource *res;  	struct ehci_sh_priv *priv;  	struct ehci_sh_platdata *pdata; @@ -170,7 +169,7 @@ fail_create_hcd:  	return ret;  } -static int __exit ehci_hcd_sh_remove(struct platform_device *pdev) +static int ehci_hcd_sh_remove(struct platform_device *pdev)  {  	struct ehci_sh_priv *priv = platform_get_drvdata(pdev);  	struct usb_hcd *hcd = priv->hcd; @@ -196,7 +195,7 @@ static void ehci_hcd_sh_shutdown(struct platform_device *pdev)  static struct platform_driver ehci_hcd_sh_driver = {  	.probe		= ehci_hcd_sh_probe, -	.remove		= __exit_p(ehci_hcd_sh_remove), +	.remove		= ehci_hcd_sh_remove,  	.shutdown	= ehci_hcd_sh_shutdown,  	.driver		= {  		.name	= "sh_ehci", diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c index 466c1bb5b96..61ecfb3d52f 100644 --- a/drivers/usb/host/ehci-spear.c +++ b/drivers/usb/host/ehci-spear.c @@ -1,5 +1,5 @@  /* -* Driver for EHCI HCD on SPEAR SOC +* Driver for EHCI HCD on SPEAr SOC  *  * Copyright (C) 2010 ST Micro Electronics,  * Deepak Sikri <deepak.sikri@st.com> @@ -12,73 +12,32 @@  */  #include <linux/clk.h> +#include <linux/dma-mapping.h> +#include <linux/io.h>  #include <linux/jiffies.h> +#include <linux/kernel.h> +#include <linux/module.h>  #include <linux/of.h>  #include <linux/platform_device.h>  #include <linux/pm.h> +#include <linux/usb.h> +#include <linux/usb/hcd.h> -struct spear_ehci { -	struct ehci_hcd ehci; -	struct clk *clk; -}; - -#define to_spear_ehci(hcd)	(struct spear_ehci *)hcd_to_ehci(hcd) - -static void spear_start_ehci(struct spear_ehci *ehci) -{ -	clk_prepare_enable(ehci->clk); -} - -static void spear_stop_ehci(struct spear_ehci *ehci) -{ -	clk_disable_unprepare(ehci->clk); -} +#include "ehci.h" -static int ehci_spear_setup(struct usb_hcd *hcd) -{ -	struct ehci_hcd *ehci = hcd_to_ehci(hcd); +#define DRIVER_DESC "EHCI SPEAr driver" -	/* registers start at offset 0x0 */ -	ehci->caps = hcd->regs; - -	return ehci_setup(hcd); -} +static const char hcd_name[] = "SPEAr-ehci"; -static const struct hc_driver ehci_spear_hc_driver = { -	.description			= hcd_name, -	.product_desc			= "SPEAr EHCI", -	.hcd_priv_size			= sizeof(struct spear_ehci), - -	/* generic hardware linkage */ -	.irq				= ehci_irq, -	.flags				= HCD_MEMORY | HCD_USB2, - -	/* basic lifecycle operations */ -	.reset				= ehci_spear_setup, -	.start				= ehci_run, -	.stop				= ehci_stop, -	.shutdown			= ehci_shutdown, - -	/* managing i/o requests and associated device resources */ -	.urb_enqueue			= ehci_urb_enqueue, -	.urb_dequeue			= ehci_urb_dequeue, -	.endpoint_disable		= ehci_endpoint_disable, -	.endpoint_reset			= ehci_endpoint_reset, +struct spear_ehci { +	struct clk *clk; +}; -	/* scheduling support */ -	.get_frame_number		= ehci_get_frame, +#define to_spear_ehci(hcd)	(struct spear_ehci *)(hcd_to_ehci(hcd)->priv) -	/* root hub support */ -	.hub_status_data		= ehci_hub_status_data, -	.hub_control			= ehci_hub_control, -	.bus_suspend			= ehci_bus_suspend, -	.bus_resume			= ehci_bus_resume, -	.relinquish_port		= ehci_relinquish_port, -	.port_handed_over		= ehci_port_handed_over, -	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete, -}; +static struct hc_driver __read_mostly ehci_spear_hc_driver; -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP  static int ehci_spear_drv_suspend(struct device *dev)  {  	struct usb_hcd *hcd = dev_get_drvdata(dev); @@ -94,7 +53,7 @@ static int ehci_spear_drv_resume(struct device *dev)  	ehci_resume(hcd, false);  	return 0;  } -#endif /* CONFIG_PM */ +#endif /* CONFIG_PM_SLEEP */  static SIMPLE_DEV_PM_OPS(ehci_spear_pm_ops, ehci_spear_drv_suspend,  		ehci_spear_drv_resume); @@ -104,7 +63,7 @@ static u64 spear_ehci_dma_mask = DMA_BIT_MASK(32);  static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)  {  	struct usb_hcd *hcd ; -	struct spear_ehci *ehci; +	struct spear_ehci *sehci;  	struct resource *res;  	struct clk *usbh_clk;  	const struct hc_driver *driver = &ehci_spear_hc_driver; @@ -161,10 +120,13 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)  		goto err_put_hcd;  	} -	ehci = (struct spear_ehci *)hcd_to_ehci(hcd); -	ehci->clk = usbh_clk; +	sehci = to_spear_ehci(hcd); +	sehci->clk = usbh_clk; + +	/* registers start at offset 0x0 */ +	hcd_to_ehci(hcd)->caps = hcd->regs; -	spear_start_ehci(ehci); +	clk_prepare_enable(sehci->clk);  	retval = usb_add_hcd(hcd, irq, IRQF_SHARED);  	if (retval)  		goto err_stop_ehci; @@ -172,7 +134,7 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)  	return retval;  err_stop_ehci: -	spear_stop_ehci(ehci); +	clk_disable_unprepare(sehci->clk);  err_put_hcd:  	usb_put_hcd(hcd);  fail: @@ -184,7 +146,7 @@ fail:  static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)  {  	struct usb_hcd *hcd = platform_get_drvdata(pdev); -	struct spear_ehci *ehci_p = to_spear_ehci(hcd); +	struct spear_ehci *sehci = to_spear_ehci(hcd);  	if (!hcd)  		return 0; @@ -192,8 +154,8 @@ static int spear_ehci_hcd_drv_remove(struct platform_device *pdev)  		BUG();  	usb_remove_hcd(hcd); -	if (ehci_p->clk) -		spear_stop_ehci(ehci_p); +	if (sehci->clk) +		clk_disable_unprepare(sehci->clk);  	usb_put_hcd(hcd);  	return 0; @@ -216,4 +178,29 @@ static struct platform_driver spear_ehci_hcd_driver = {  	}  }; +static const struct ehci_driver_overrides spear_overrides __initdata = { +	.extra_priv_size = sizeof(struct spear_ehci), +}; + +static int __init ehci_spear_init(void) +{ +	if (usb_disabled()) +		return -ENODEV; + +	pr_info("%s: " DRIVER_DESC "\n", hcd_name); + +	ehci_init_driver(&ehci_spear_hc_driver, &spear_overrides); +	return platform_driver_register(&spear_ehci_hcd_driver); +} +module_init(ehci_spear_init); + +static void __exit ehci_spear_cleanup(void) +{ +	platform_driver_unregister(&spear_ehci_hcd_driver); +} +module_exit(ehci_spear_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC);  MODULE_ALIAS("platform:spear-ehci"); +MODULE_AUTHOR("Deepak Sikri"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 568aecc7075..e3eddc31ac8 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -28,6 +28,7 @@  #include <linux/pm_runtime.h>  #include <linux/usb/ehci_def.h>  #include <linux/usb/tegra_usb_phy.h> +#include <linux/clk/tegra.h>  #define TEGRA_USB_BASE			0xC5000000  #define TEGRA_USB2_BASE			0xC5004000 @@ -610,7 +611,7 @@ static const struct dev_pm_ops tegra_ehci_pm_ops = {  /* Bits of PORTSC1, which will get cleared by writing 1 into them */  #define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) -void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val) +static void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val)  {  	unsigned long val;  	struct usb_hcd *hcd = bus_to_hcd(x->otg->host); @@ -621,9 +622,8 @@ void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val)  	val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3);  	writel(val, base + TEGRA_USB_PORTSC1);  } -EXPORT_SYMBOL_GPL(tegra_ehci_set_pts); -void tegra_ehci_set_phcd(struct usb_phy *x, bool enable) +static void tegra_ehci_set_phcd(struct usb_phy *x, bool enable)  {  	unsigned long val;  	struct usb_hcd *hcd = bus_to_hcd(x->otg->host); @@ -636,7 +636,6 @@ void tegra_ehci_set_phcd(struct usb_phy *x, bool enable)  		val &= ~TEGRA_USB_PORTSC1_PHCD;  	writel(val, base + TEGRA_USB_PORTSC1);  } -EXPORT_SYMBOL_GPL(tegra_ehci_set_phcd);  static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32); @@ -691,6 +690,10 @@ static int tegra_ehci_probe(struct platform_device *pdev)  	if (err)  		goto fail_clk; +	tegra_periph_reset_assert(tegra->clk); +	udelay(1); +	tegra_periph_reset_deassert(tegra->clk); +  	tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node,  		"nvidia,needs-double-reset"); @@ -733,7 +736,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)  	tegra->phy = tegra_usb_phy_open(&pdev->dev, instance, hcd->regs,  					pdata->phy_config, -					TEGRA_USB_PHY_MODE_HOST); +					TEGRA_USB_PHY_MODE_HOST, +					tegra_ehci_set_pts, +					tegra_ehci_set_phcd);  	if (IS_ERR(tegra->phy)) {  		dev_err(&pdev->dev, "Failed to open USB phy\n");  		err = -ENXIO; @@ -755,7 +760,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)  	err = usb_phy_set_suspend(hcd->phy, 0);  	if (err) {  		dev_err(&pdev->dev, "Failed to power on the phy\n"); -		goto fail; +		goto fail_phy;  	}  	tegra->host_resumed = 1; @@ -765,17 +770,17 @@ static int tegra_ehci_probe(struct platform_device *pdev)  	if (!irq) {  		dev_err(&pdev->dev, "Failed to get IRQ\n");  		err = -ENODEV; -		goto fail; +		goto fail_phy;  	} -#ifdef CONFIG_USB_OTG_UTILS  	if (pdata->operating_mode == TEGRA_USB_OTG) {  		tegra->transceiver =  			devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); -		if (!IS_ERR_OR_NULL(tegra->transceiver)) +		if (!IS_ERR(tegra->transceiver))  			otg_set_host(tegra->transceiver->otg, &hcd->self); +	} else { +		tegra->transceiver = ERR_PTR(-ENODEV);  	} -#endif  	err = usb_add_hcd(hcd, irq, IRQF_SHARED);  	if (err) { @@ -794,10 +799,9 @@ static int tegra_ehci_probe(struct platform_device *pdev)  	return err;  fail: -#ifdef CONFIG_USB_OTG_UTILS -	if (!IS_ERR_OR_NULL(tegra->transceiver)) +	if (!IS_ERR(tegra->transceiver))  		otg_set_host(tegra->transceiver->otg, NULL); -#endif +fail_phy:  	usb_phy_shutdown(hcd->phy);  fail_io:  	clk_disable_unprepare(tegra->clk); @@ -815,10 +819,8 @@ static int tegra_ehci_remove(struct platform_device *pdev)  	pm_runtime_disable(&pdev->dev);  	pm_runtime_put_noidle(&pdev->dev); -#ifdef CONFIG_USB_OTG_UTILS -	if (!IS_ERR_OR_NULL(tegra->transceiver)) +	if (!IS_ERR(tegra->transceiver))  		otg_set_host(tegra->transceiver->otg, NULL); -#endif  	usb_phy_shutdown(hcd->phy);  	usb_remove_hcd(hcd); diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c index c3fa1305f83..11e5b32f73e 100644 --- a/drivers/usb/host/ehci-timer.c +++ b/drivers/usb/host/ehci-timer.c @@ -113,8 +113,8 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci)  	if (want != actual) { -		/* Poll again later, but give up after about 20 ms */ -		if (ehci->ASS_poll_count++ < 20) { +		/* Poll again later, but give up after about 2-4 ms */ +		if (ehci->ASS_poll_count++ < 2) {  			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true);  			return;  		} @@ -159,8 +159,8 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci)  	if (want != actual) { -		/* Poll again later, but give up after about 20 ms */ -		if (ehci->PSS_poll_count++ < 20) { +		/* Poll again later, but give up after about 2-4 ms */ +		if (ehci->PSS_poll_count++ < 2) {  			ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true);  			return;  		} @@ -229,18 +229,19 @@ static void ehci_handle_intr_unlinks(struct ehci_hcd *ehci)  	 * process all the QHs on the list.  	 */  	ehci->intr_unlinking = true; -	while (ehci->intr_unlink) { -		struct ehci_qh	*qh = ehci->intr_unlink; +	while (!list_empty(&ehci->intr_unlink)) { +		struct ehci_qh	*qh; +		qh = list_first_entry(&ehci->intr_unlink, struct ehci_qh, +				unlink_node);  		if (!stopped && qh->unlink_cycle == ehci->intr_unlink_cycle)  			break; -		ehci->intr_unlink = qh->unlink_next; -		qh->unlink_next = NULL; +		list_del(&qh->unlink_node);  		end_unlink_intr(ehci, qh);  	}  	/* Handle remaining entries later */ -	if (ehci->intr_unlink) { +	if (!list_empty(&ehci->intr_unlink)) {  		ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true);  		++ehci->intr_unlink_cycle;  	} @@ -295,8 +296,7 @@ static void end_free_itds(struct ehci_hcd *ehci)  /* Handle lost (or very late) IAA interrupts */  static void ehci_iaa_watchdog(struct ehci_hcd *ehci)  { -	if (ehci->rh_state != EHCI_RH_RUNNING) -		return; +	u32 cmd, status;  	/*  	 * Lost IAA irqs wedge things badly; seen first with a vt8235. @@ -304,34 +304,32 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci)  	 * (a) SMP races against real IAA firing and retriggering, and  	 * (b) clean HC shutdown, when IAA watchdog was pending.  	 */ -	if (1) { -		u32 cmd, status; - -		/* If we get here, IAA is *REALLY* late.  It's barely -		 * conceivable that the system is so busy that CMD_IAAD -		 * is still legitimately set, so let's be sure it's -		 * clear before we read STS_IAA.  (The HC should clear -		 * CMD_IAAD when it sets STS_IAA.) -		 */ -		cmd = ehci_readl(ehci, &ehci->regs->command); +	if (!ehci->iaa_in_progress || ehci->rh_state != EHCI_RH_RUNNING) +		return; -		/* -		 * If IAA is set here it either legitimately triggered -		 * after the watchdog timer expired (_way_ late, so we'll -		 * still count it as lost) ... or a silicon erratum: -		 * - VIA seems to set IAA without triggering the IRQ; -		 * - IAAD potentially cleared without setting IAA. -		 */ -		status = ehci_readl(ehci, &ehci->regs->status); -		if ((status & STS_IAA) || !(cmd & CMD_IAAD)) { -			COUNT(ehci->stats.lost_iaa); -			ehci_writel(ehci, STS_IAA, &ehci->regs->status); -		} +	/* If we get here, IAA is *REALLY* late.  It's barely +	 * conceivable that the system is so busy that CMD_IAAD +	 * is still legitimately set, so let's be sure it's +	 * clear before we read STS_IAA.  (The HC should clear +	 * CMD_IAAD when it sets STS_IAA.) +	 */ +	cmd = ehci_readl(ehci, &ehci->regs->command); -		ehci_vdbg(ehci, "IAA watchdog: status %x cmd %x\n", -				status, cmd); -		end_unlink_async(ehci); +	/* +	 * If IAA is set here it either legitimately triggered +	 * after the watchdog timer expired (_way_ late, so we'll +	 * still count it as lost) ... or a silicon erratum: +	 * - VIA seems to set IAA without triggering the IRQ; +	 * - IAAD potentially cleared without setting IAA. +	 */ +	status = ehci_readl(ehci, &ehci->regs->status); +	if ((status & STS_IAA) || !(cmd & CMD_IAAD)) { +		COUNT(ehci->stats.lost_iaa); +		ehci_writel(ehci, STS_IAA, &ehci->regs->status);  	} + +	ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd); +	end_unlink_async(ehci);  } diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c deleted file mode 100644 index 7ecf709610b..00000000000 --- a/drivers/usb/host/ehci-vt8500.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * drivers/usb/host/ehci-vt8500.c - * - * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> - * - * Based on ehci-au1xxx.c - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - */ - -#include <linux/err.h> -#include <linux/of.h> -#include <linux/platform_device.h> - -static const struct hc_driver vt8500_ehci_hc_driver = { -	.description		= hcd_name, -	.product_desc		= "VT8500 EHCI", -	.hcd_priv_size		= sizeof(struct ehci_hcd), - -	/* -	 * generic hardware linkage -	 */ -	.irq			= ehci_irq, -	.flags			= HCD_MEMORY | HCD_USB2, - -	/* -	 * basic lifecycle operations -	 */ -	.reset			= ehci_setup, -	.start			= ehci_run, -	.stop			= ehci_stop, -	.shutdown		= ehci_shutdown, - -	/* -	 * managing i/o requests and associated device resources -	 */ -	.urb_enqueue		= ehci_urb_enqueue, -	.urb_dequeue		= ehci_urb_dequeue, -	.endpoint_disable	= ehci_endpoint_disable, -	.endpoint_reset		= ehci_endpoint_reset, - -	/* -	 * scheduling support -	 */ -	.get_frame_number	= ehci_get_frame, - -	/* -	 * root hub support -	 */ -	.hub_status_data	= ehci_hub_status_data, -	.hub_control		= ehci_hub_control, -	.bus_suspend		= ehci_bus_suspend, -	.bus_resume		= ehci_bus_resume, -	.relinquish_port	= ehci_relinquish_port, -	.port_handed_over	= ehci_port_handed_over, - -	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete, -}; - -static u64 vt8500_ehci_dma_mask = DMA_BIT_MASK(32); - -static int vt8500_ehci_drv_probe(struct platform_device *pdev) -{ -	struct usb_hcd *hcd; -	struct ehci_hcd *ehci; -	struct resource *res; -	int ret; - -	if (usb_disabled()) -		return -ENODEV; - -	/* -	 * Right now device-tree probed devices don't get dma_mask set. -	 * Since shared usb code relies on it, set it here for now. -	 * Once we have dma capability bindings this can go away. -	 */ -	if (!pdev->dev.dma_mask) -		pdev->dev.dma_mask = &vt8500_ehci_dma_mask; - -	if (pdev->resource[1].flags != IORESOURCE_IRQ) { -		pr_debug("resource[1] is not IORESOURCE_IRQ"); -		return -ENOMEM; -	} -	hcd = usb_create_hcd(&vt8500_ehci_hc_driver, &pdev->dev, "VT8500"); -	if (!hcd) -		return -ENOMEM; - -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	hcd->rsrc_start = res->start; -	hcd->rsrc_len = resource_size(res); - -	hcd->regs = devm_ioremap_resource(&pdev->dev, res); -	if (IS_ERR(hcd->regs)) { -		ret = PTR_ERR(hcd->regs); -		goto err1; -	} - -	ehci = hcd_to_ehci(hcd); -	ehci->caps = hcd->regs; - -	ret = usb_add_hcd(hcd, pdev->resource[1].start, -			  IRQF_SHARED); -	if (ret == 0) { -		platform_set_drvdata(pdev, hcd); -		return ret; -	} - -err1: -	usb_put_hcd(hcd); -	return ret; -} - -static int vt8500_ehci_drv_remove(struct platform_device *pdev) -{ -	struct usb_hcd *hcd = platform_get_drvdata(pdev); - -	usb_remove_hcd(hcd); -	usb_put_hcd(hcd); -	platform_set_drvdata(pdev, NULL); - -	return 0; -} - -static const struct of_device_id vt8500_ehci_ids[] = { -	{ .compatible = "via,vt8500-ehci", }, -	{ .compatible = "wm,prizm-ehci", }, -	{} -}; - -static struct platform_driver vt8500_ehci_driver = { -	.probe		= vt8500_ehci_drv_probe, -	.remove		= vt8500_ehci_drv_remove, -	.shutdown	= usb_hcd_platform_shutdown, -	.driver = { -		.name	= "vt8500-ehci", -		.owner	= THIS_MODULE, -		.of_match_table = of_match_ptr(vt8500_ehci_ids), -	} -}; - -MODULE_ALIAS("platform:vt8500-ehci"); -MODULE_DEVICE_TABLE(of, vt8500_ehci_ids); diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 36c3a821059..7c978b23520 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -121,6 +121,7 @@ struct ehci_hcd {			/* one per controller */  	bool			scanning:1;  	bool			need_rescan:1;  	bool			intr_unlinking:1; +	bool			iaa_in_progress:1;  	bool			async_unlinking:1;  	bool			shutdown:1;  	struct ehci_qh		*qh_scan_next; @@ -128,9 +129,8 @@ struct ehci_hcd {			/* one per controller */  	/* async schedule support */  	struct ehci_qh		*async;  	struct ehci_qh		*dummy;		/* For AMD quirk use */ -	struct ehci_qh		*async_unlink; -	struct ehci_qh		*async_unlink_last; -	struct ehci_qh		*async_iaa; +	struct list_head	async_unlink; +	struct list_head	async_idle;  	unsigned		async_unlink_cycle;  	unsigned		async_count;	/* async activity count */ @@ -143,8 +143,7 @@ struct ehci_hcd {			/* one per controller */  	unsigned		i_thresh;	/* uframes HC might cache */  	union ehci_shadow	*pshadow;	/* mirror hw periodic table */ -	struct ehci_qh		*intr_unlink; -	struct ehci_qh		*intr_unlink_last; +	struct list_head	intr_unlink;  	unsigned		intr_unlink_cycle;  	unsigned		now_frame;	/* frame from HC hardware */  	unsigned		last_iso_frame;	/* last frame scanned for iso */ @@ -200,6 +199,7 @@ struct ehci_hcd {			/* one per controller */  	unsigned		use_dummy_qh:1;	/* AMD Frame List table quirk*/  	unsigned		has_synopsys_hc_bug:1; /* Synopsys HC */  	unsigned		frame_index_bug:1; /* MosChip (AKA NetMos) */ +	unsigned		need_oc_pp_cycle:1; /* MPC834X port power */  	/* required for usb32 quirk */  	#define OHCI_CTRL_HCFS          (3 << 6) @@ -380,11 +380,10 @@ struct ehci_qh {  	struct list_head	qtd_list;	/* sw qtd list */  	struct list_head	intr_node;	/* list of intr QHs */  	struct ehci_qtd		*dummy; -	struct ehci_qh		*unlink_next;	/* next on unlink list */ +	struct list_head	unlink_node;  	unsigned		unlink_cycle; -	u8			needs_rescan;	/* Dequeue during giveback */  	u8			qh_state;  #define	QH_STATE_LINKED		1		/* HC sees this */  #define	QH_STATE_UNLINK		2		/* HC may still see this */ @@ -407,6 +406,9 @@ struct ehci_qh {  	struct usb_device	*dev;		/* access to TT */  	unsigned		is_out:1;	/* bulk or intr OUT */  	unsigned		clearing_tt:1;	/* Clear-TT-Buf in progress */ +	unsigned		dequeue_during_giveback:1; +	unsigned		exception:1;	/* got a fault, or an unlink +						   was requested */  };  /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index e3b7e85120e..114583a8e92 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -17,7 +17,6 @@  #include <linux/platform_data/usb-exynos.h>  #include <linux/usb/phy.h>  #include <linux/usb/samsung_usb_phy.h> -#include <plat/usb-phy.h>  struct exynos_ohci_hcd {  	struct device *dev; @@ -34,7 +33,7 @@ static void exynos_ohci_phy_enable(struct exynos_ohci_hcd *exynos_ohci)  	if (exynos_ohci->phy)  		usb_phy_init(exynos_ohci->phy); -	else if (exynos_ohci->pdata->phy_init) +	else if (exynos_ohci->pdata && exynos_ohci->pdata->phy_init)  		exynos_ohci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);  } @@ -44,7 +43,7 @@ static void exynos_ohci_phy_disable(struct exynos_ohci_hcd *exynos_ohci)  	if (exynos_ohci->phy)  		usb_phy_shutdown(exynos_ohci->phy); -	else if (exynos_ohci->pdata->phy_exit) +	else if (exynos_ohci->pdata && exynos_ohci->pdata->phy_exit)  		exynos_ohci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);  } @@ -127,8 +126,12 @@ static int exynos_ohci_probe(struct platform_device *pdev)  	if (!exynos_ohci)  		return -ENOMEM; +	if (of_device_is_compatible(pdev->dev.of_node, +					"samsung,exynos5440-ohci")) +		goto skip_phy; +  	phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); -	if (IS_ERR_OR_NULL(phy)) { +	if (IS_ERR(phy)) {  		/* Fallback to pdata */  		if (!pdata) {  			dev_warn(&pdev->dev, "no platform data or transceiver defined\n"); @@ -141,6 +144,8 @@ static int exynos_ohci_probe(struct platform_device *pdev)  		exynos_ohci->otg = phy->otg;  	} +skip_phy: +  	exynos_ohci->dev = &pdev->dev;  	hcd = usb_create_hcd(&exynos_ohci_hc_driver, &pdev->dev, @@ -311,6 +316,7 @@ static const struct dev_pm_ops exynos_ohci_pm_ops = {  #ifdef CONFIG_OF  static const struct of_device_id exynos_ohci_match[] = {  	{ .compatible = "samsung,exynos4210-ohci" }, +	{ .compatible = "samsung,exynos5440-ohci" },  	{},  };  MODULE_DEVICE_TABLE(of, exynos_ohci_match); diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 180a2b01db5..9e6de9586ae 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1102,12 +1102,12 @@ MODULE_LICENSE ("GPL");  #if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S3C64XX)  #include "ohci-s3c2410.c" -#define PLATFORM_DRIVER		ohci_hcd_s3c2410_driver +#define S3C2410_PLATFORM_DRIVER	ohci_hcd_s3c2410_driver  #endif  #ifdef CONFIG_USB_OHCI_EXYNOS  #include "ohci-exynos.c" -#define PLATFORM_DRIVER		exynos_ohci_driver +#define EXYNOS_PLATFORM_DRIVER	exynos_ohci_driver  #endif  #ifdef CONFIG_USB_OHCI_HCD_OMAP1 @@ -1127,25 +1127,24 @@ MODULE_LICENSE ("GPL");  #ifdef CONFIG_ARCH_EP93XX  #include "ohci-ep93xx.c" -#define PLATFORM_DRIVER		ohci_hcd_ep93xx_driver +#define EP93XX_PLATFORM_DRIVER	ohci_hcd_ep93xx_driver  #endif  #ifdef CONFIG_ARCH_AT91  #include "ohci-at91.c" -#define PLATFORM_DRIVER		ohci_hcd_at91_driver +#define AT91_PLATFORM_DRIVER	ohci_hcd_at91_driver  #endif  #ifdef CONFIG_ARCH_LPC32XX  #include "ohci-nxp.c" -#define PLATFORM_DRIVER		usb_hcd_nxp_driver +#define NXP_PLATFORM_DRIVER	usb_hcd_nxp_driver  #endif  #ifdef CONFIG_ARCH_DAVINCI_DA8XX  #include "ohci-da8xx.c" -#define PLATFORM_DRIVER		ohci_hcd_da8xx_driver +#define DAVINCI_PLATFORM_DRIVER	ohci_hcd_da8xx_driver  #endif -  #ifdef CONFIG_USB_OHCI_HCD_PPC_OF  #include "ohci-ppc-of.c"  #define OF_PLATFORM_DRIVER	ohci_hcd_ppc_of_driver @@ -1153,7 +1152,7 @@ MODULE_LICENSE ("GPL");  #ifdef CONFIG_PLAT_SPEAR  #include "ohci-spear.c" -#define PLATFORM_DRIVER		spear_ohci_hcd_driver +#define SPEAR_PLATFORM_DRIVER	spear_ohci_hcd_driver  #endif  #ifdef CONFIG_PPC_PS3 @@ -1199,7 +1198,14 @@ MODULE_LICENSE ("GPL");  	!defined(SA1111_DRIVER) &&	\  	!defined(PS3_SYSTEM_BUS_DRIVER) && \  	!defined(SM501_OHCI_DRIVER) && \ -	!defined(TMIO_OHCI_DRIVER) +	!defined(TMIO_OHCI_DRIVER) && \ +	!defined(S3C2410_PLATFORM_DRIVER) && \ +	!defined(EXYNOS_PLATFORM_DRIVER) && \ +	!defined(EP93XX_PLATFORM_DRIVER) && \ +	!defined(AT91_PLATFORM_DRIVER) && \ +	!defined(NXP_PLATFORM_DRIVER) && \ +	!defined(DAVINCI_PLATFORM_DRIVER) && \ +	!defined(SPEAR_PLATFORM_DRIVER)  #error "missing bus glue for ohci-hcd"  #endif @@ -1277,9 +1283,79 @@ static int __init ohci_hcd_mod_init(void)  		goto error_tmio;  #endif +#ifdef S3C2410_PLATFORM_DRIVER +	retval = platform_driver_register(&S3C2410_PLATFORM_DRIVER); +	if (retval < 0) +		goto error_s3c2410; +#endif + +#ifdef EXYNOS_PLATFORM_DRIVER +	retval = platform_driver_register(&EXYNOS_PLATFORM_DRIVER); +	if (retval < 0) +		goto error_exynos; +#endif + +#ifdef EP93XX_PLATFORM_DRIVER +	retval = platform_driver_register(&EP93XX_PLATFORM_DRIVER); +	if (retval < 0) +		goto error_ep93xx; +#endif + +#ifdef AT91_PLATFORM_DRIVER +	retval = platform_driver_register(&AT91_PLATFORM_DRIVER); +	if (retval < 0) +		goto error_at91; +#endif + +#ifdef NXP_PLATFORM_DRIVER +	retval = platform_driver_register(&NXP_PLATFORM_DRIVER); +	if (retval < 0) +		goto error_nxp; +#endif + +#ifdef DAVINCI_PLATFORM_DRIVER +	retval = platform_driver_register(&DAVINCI_PLATFORM_DRIVER); +	if (retval < 0) +		goto error_davinci; +#endif + +#ifdef SPEAR_PLATFORM_DRIVER +	retval = platform_driver_register(&SPEAR_PLATFORM_DRIVER); +	if (retval < 0) +		goto error_spear; +#endif +  	return retval;  	/* Error path */ +#ifdef SPEAR_PLATFORM_DRIVER +	platform_driver_unregister(&SPEAR_PLATFORM_DRIVER); + error_spear: +#endif +#ifdef DAVINCI_PLATFORM_DRIVER +	platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER); + error_davinci: +#endif +#ifdef NXP_PLATFORM_DRIVER +	platform_driver_unregister(&NXP_PLATFORM_DRIVER); + error_nxp: +#endif +#ifdef AT91_PLATFORM_DRIVER +	platform_driver_unregister(&AT91_PLATFORM_DRIVER); + error_at91: +#endif +#ifdef EP93XX_PLATFORM_DRIVER +	platform_driver_unregister(&EP93XX_PLATFORM_DRIVER); + error_ep93xx: +#endif +#ifdef EXYNOS_PLATFORM_DRIVER +	platform_driver_unregister(&EXYNOS_PLATFORM_DRIVER); + error_exynos: +#endif +#ifdef S3C2410_PLATFORM_DRIVER +	platform_driver_unregister(&S3C2410_PLATFORM_DRIVER); + error_s3c2410: +#endif  #ifdef TMIO_OHCI_DRIVER  	platform_driver_unregister(&TMIO_OHCI_DRIVER);   error_tmio: @@ -1300,17 +1376,17 @@ static int __init ohci_hcd_mod_init(void)  	platform_driver_unregister(&OF_PLATFORM_DRIVER);   error_of_platform:  #endif -#ifdef PLATFORM_DRIVER -	platform_driver_unregister(&PLATFORM_DRIVER); - error_platform: +#ifdef OMAP3_PLATFORM_DRIVER +	platform_driver_unregister(&OMAP3_PLATFORM_DRIVER); + error_omap3_platform:  #endif  #ifdef OMAP1_PLATFORM_DRIVER  	platform_driver_unregister(&OMAP1_PLATFORM_DRIVER);   error_omap1_platform:  #endif -#ifdef OMAP3_PLATFORM_DRIVER -	platform_driver_unregister(&OMAP3_PLATFORM_DRIVER); - error_omap3_platform: +#ifdef PLATFORM_DRIVER +	platform_driver_unregister(&PLATFORM_DRIVER); + error_platform:  #endif  #ifdef PS3_SYSTEM_BUS_DRIVER  	ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); @@ -1329,6 +1405,27 @@ module_init(ohci_hcd_mod_init);  static void __exit ohci_hcd_mod_exit(void)  { +#ifdef SPEAR_PLATFORM_DRIVER +	platform_driver_unregister(&SPEAR_PLATFORM_DRIVER); +#endif +#ifdef DAVINCI_PLATFORM_DRIVER +	platform_driver_unregister(&DAVINCI_PLATFORM_DRIVER); +#endif +#ifdef NXP_PLATFORM_DRIVER +	platform_driver_unregister(&NXP_PLATFORM_DRIVER); +#endif +#ifdef AT91_PLATFORM_DRIVER +	platform_driver_unregister(&AT91_PLATFORM_DRIVER); +#endif +#ifdef EP93XX_PLATFORM_DRIVER +	platform_driver_unregister(&EP93XX_PLATFORM_DRIVER); +#endif +#ifdef EXYNOS_PLATFORM_DRIVER +	platform_driver_unregister(&EXYNOS_PLATFORM_DRIVER); +#endif +#ifdef S3C2410_PLATFORM_DRIVER +	platform_driver_unregister(&S3C2410_PLATFORM_DRIVER); +#endif  #ifdef TMIO_OHCI_DRIVER  	platform_driver_unregister(&TMIO_OHCI_DRIVER);  #endif @@ -1344,12 +1441,15 @@ static void __exit ohci_hcd_mod_exit(void)  #ifdef OF_PLATFORM_DRIVER  	platform_driver_unregister(&OF_PLATFORM_DRIVER);  #endif -#ifdef PLATFORM_DRIVER -	platform_driver_unregister(&PLATFORM_DRIVER); -#endif  #ifdef OMAP3_PLATFORM_DRIVER  	platform_driver_unregister(&OMAP3_PLATFORM_DRIVER);  #endif +#ifdef OMAP1_PLATFORM_DRIVER +	platform_driver_unregister(&OMAP1_PLATFORM_DRIVER); +#endif +#ifdef PLATFORM_DRIVER +	platform_driver_unregister(&PLATFORM_DRIVER); +#endif  #ifdef PS3_SYSTEM_BUS_DRIVER  	ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER);  #endif diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index db09dae7b55..60ff4220e8b 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -580,14 +580,8 @@ static int ohci_start_port_reset (struct usb_hcd *hcd, unsigned port)  /* See usb 7.1.7.5:  root hubs must issue at least 50 msec reset signaling,   * not necessarily continuous ... to guard against resume signaling. - * The short timeout is safe for non-root hubs, and is backward-compatible - * with earlier Linux hosts.   */ -#ifdef	CONFIG_USB_SUSPEND  #define	PORT_RESET_MSEC		50 -#else -#define	PORT_RESET_MSEC		10 -#endif  /* this timer value might be vendor-specific ... */  #define	PORT_RESET_HW_MSEC	10 diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c index eb35d963023..ddfc31427bc 100644 --- a/drivers/usb/host/ohci-omap3.c +++ b/drivers/usb/host/ohci-omap3.c @@ -31,6 +31,8 @@  #include <linux/platform_device.h>  #include <linux/pm_runtime.h> +#include <linux/of.h> +#include <linux/dma-mapping.h>  /*-------------------------------------------------------------------------*/ @@ -112,6 +114,8 @@ static const struct hc_driver ohci_omap3_hc_driver = {  /*-------------------------------------------------------------------------*/ +static u64 omap_ohci_dma_mask = DMA_BIT_MASK(32); +  /*   * configure so an HC device and id are always provided   * always called with process context; sleeping is OK @@ -141,14 +145,13 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)  		return -ENODEV;  	} -	irq = platform_get_irq_byname(pdev, "ohci-irq"); +	irq = platform_get_irq(pdev, 0);  	if (irq < 0) {  		dev_err(dev, "OHCI irq failed\n");  		return -ENODEV;  	} -	res = platform_get_resource_byname(pdev, -				IORESOURCE_MEM, "ohci"); +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (!res) {  		dev_err(dev, "UHH OHCI get resource failed\n");  		return -ENOMEM; @@ -160,6 +163,13 @@ static int ohci_hcd_omap3_probe(struct platform_device *pdev)  		return -ENOMEM;  	} +	/* +	 * Right now device-tree probed devices don't get dma_mask set. +	 * Since shared usb code relies on it, set it here for now. +	 * Once we have dma capability bindings this can go away. +	 */ +	if (!pdev->dev.dma_mask) +		pdev->dev.dma_mask = &omap_ohci_dma_mask;  	hcd = usb_create_hcd(&ohci_omap3_hc_driver, dev,  			dev_name(dev)); @@ -229,12 +239,20 @@ static void ohci_hcd_omap3_shutdown(struct platform_device *pdev)  		hcd->driver->shutdown(hcd);  } +static const struct of_device_id omap_ohci_dt_ids[] = { +	{ .compatible = "ti,ohci-omap3" }, +	{ } +}; + +MODULE_DEVICE_TABLE(of, omap_ohci_dt_ids); +  static struct platform_driver ohci_hcd_omap3_driver = {  	.probe		= ohci_hcd_omap3_probe,  	.remove		= ohci_hcd_omap3_remove,  	.shutdown	= ohci_hcd_omap3_shutdown,  	.driver		= {  		.name	= "ohci-omap3", +		.of_match_table = of_match_ptr(omap_ohci_dt_ids),  	},  }; diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index d62f0404baa..15ed7e8d887 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -1755,7 +1755,7 @@ sl811h_probe(struct platform_device *dev)  /* for this device there's no useful distinction between the controller   * and its root hub, except that the root hub only gets direct PM calls - * when CONFIG_USB_SUSPEND is enabled. + * when CONFIG_PM_RUNTIME is enabled.   */  static int diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 3b6f50eaec9..469564e57a5 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -200,17 +200,4 @@ static struct pcmcia_driver sl811_cs_driver = {  	.remove		= sl811_cs_detach,  	.id_table	= sl811_ids,  }; - -/*====================================================================*/ - -static int __init init_sl811_cs(void) -{ -	return pcmcia_register_driver(&sl811_cs_driver); -} -module_init(init_sl811_cs); - -static void __exit exit_sl811_cs(void) -{ -	pcmcia_unregister_driver(&sl811_cs_driver); -} -module_exit(exit_sl811_cs); +module_pcmcia_driver(sl811_cs_driver); diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 5efdffe3236..5c124bf5d01 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -3141,10 +3141,11 @@ static int u132_probe(struct platform_device *pdev)  #ifdef CONFIG_PM -/* for this device there's no useful distinction between the controller -* and its root hub, except that the root hub only gets direct PM calls -* when CONFIG_USB_SUSPEND is enabled. -*/ +/* + * for this device there's no useful distinction between the controller + * and its root hub, except that the root hub only gets direct PM calls + * when CONFIG_PM_RUNTIME is enabled. + */  static int u132_suspend(struct platform_device *pdev, pm_message_t state)  {  	struct usb_hcd *hcd = platform_get_drvdata(pdev); diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 68914429482..187a3ec1069 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -1075,7 +1075,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)  			set_bit(port_index, &bus_state->bus_suspended);  		}  		/* USB core sets remote wake mask for USB 3.0 hubs, -		 * including the USB 3.0 roothub, but only if CONFIG_USB_SUSPEND +		 * including the USB 3.0 roothub, but only if CONFIG_PM_RUNTIME  		 * is enabled, so also enable remote wake here.  		 */  		if (hcd->self.root_hub->do_remote_wakeup) { diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 6dc238c592b..965b539bc47 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -51,7 +51,7 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci,  		return NULL;  	} -	memset(seg->trbs, 0, SEGMENT_SIZE); +	memset(seg->trbs, 0, TRB_SEGMENT_SIZE);  	/* If the cycle state is 0, set the cycle bit to 1 for all the TRBs */  	if (cycle_state == 0) {  		for (i = 0; i < TRBS_PER_SEGMENT; i++) @@ -467,7 +467,7 @@ struct xhci_ring *xhci_dma_to_transfer_ring(  {  	if (ep->ep_state & EP_HAS_STREAMS)  		return radix_tree_lookup(&ep->stream_info->trb_address_map, -				address >> SEGMENT_SHIFT); +				address >> TRB_SEGMENT_SHIFT);  	return ep->ring;  } @@ -478,7 +478,7 @@ static struct xhci_ring *dma_to_stream_ring(  		u64 address)  {  	return radix_tree_lookup(&stream_info->trb_address_map, -			address >> SEGMENT_SHIFT); +			address >> TRB_SEGMENT_SHIFT);  }  #endif	/* CONFIG_USB_XHCI_HCD_DEBUGGING */ @@ -514,7 +514,7 @@ static int xhci_test_radix_tree(struct xhci_hcd *xhci,  		cur_ring = stream_info->stream_rings[cur_stream];  		for (addr = cur_ring->first_seg->dma; -				addr < cur_ring->first_seg->dma + SEGMENT_SIZE; +				addr < cur_ring->first_seg->dma + TRB_SEGMENT_SIZE;  				addr += trb_size) {  			mapped_ring = dma_to_stream_ring(stream_info, addr);  			if (cur_ring != mapped_ring) { @@ -662,7 +662,7 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,  				cur_stream, (unsigned long long) addr);  		key = (unsigned long) -			(cur_ring->first_seg->dma >> SEGMENT_SHIFT); +			(cur_ring->first_seg->dma >> TRB_SEGMENT_SHIFT);  		ret = radix_tree_insert(&stream_info->trb_address_map,  				key, cur_ring);  		if (ret) { @@ -693,7 +693,7 @@ cleanup_rings:  		if (cur_ring) {  			addr = cur_ring->first_seg->dma;  			radix_tree_delete(&stream_info->trb_address_map, -					addr >> SEGMENT_SHIFT); +					addr >> TRB_SEGMENT_SHIFT);  			xhci_ring_free(xhci, cur_ring);  			stream_info->stream_rings[cur_stream] = NULL;  		} @@ -764,7 +764,7 @@ void xhci_free_stream_info(struct xhci_hcd *xhci,  		if (cur_ring) {  			addr = cur_ring->first_seg->dma;  			radix_tree_delete(&stream_info->trb_address_map, -					addr >> SEGMENT_SHIFT); +					addr >> TRB_SEGMENT_SHIFT);  			xhci_ring_free(xhci, cur_ring);  			stream_info->stream_rings[cur_stream] = NULL;  		} @@ -2305,7 +2305,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)  	 * so we pick the greater alignment need.  	 */  	xhci->segment_pool = dma_pool_create("xHCI ring segments", dev, -			SEGMENT_SIZE, 64, xhci->page_size); +			TRB_SEGMENT_SIZE, 64, xhci->page_size);  	/* See Table 46 and Note on Figure 55 */  	xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev, diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 53b8f89a0b1..b4aa79d154b 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -417,9 +417,9 @@ static void compliance_mode_recovery(unsigned long arg)  			 * Compliance Mode Detected. Letting USB Core  			 * handle the Warm Reset  			 */ -			xhci_dbg(xhci, "Compliance Mode Detected->Port %d!\n", +			xhci_dbg(xhci, "Compliance mode detected->port %d\n",  					i + 1); -			xhci_dbg(xhci, "Attempting Recovery routine!\n"); +			xhci_dbg(xhci, "Attempting compliance mode recovery\n");  			hcd = xhci->shared_hcd;  			if (hcd->state == HC_STATE_SUSPENDED) @@ -457,7 +457,7 @@ static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci)  	set_timer_slack(&xhci->comp_mode_recovery_timer,  			msecs_to_jiffies(COMP_MODE_RCVRY_MSECS));  	add_timer(&xhci->comp_mode_recovery_timer); -	xhci_dbg(xhci, "Compliance Mode Recovery Timer Initialized.\n"); +	xhci_dbg(xhci, "Compliance mode recovery timer initialized\n");  }  /* @@ -733,8 +733,11 @@ void xhci_stop(struct usb_hcd *hcd)  	/* Deleting Compliance Mode Recovery Timer */  	if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && -			(!(xhci_all_ports_seen_u0(xhci)))) +			(!(xhci_all_ports_seen_u0(xhci)))) {  		del_timer_sync(&xhci->comp_mode_recovery_timer); +		xhci_dbg(xhci, "%s: compliance mode recovery timer deleted\n", +				__func__); +	}  	if (xhci->quirks & XHCI_AMD_PLL_FIX)  		usb_amd_dev_put(); @@ -930,7 +933,8 @@ int xhci_suspend(struct xhci_hcd *xhci)  	if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&  			(!(xhci_all_ports_seen_u0(xhci)))) {  		del_timer_sync(&xhci->comp_mode_recovery_timer); -		xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted!\n"); +		xhci_dbg(xhci, "%s: compliance mode recovery timer deleted\n", +				__func__);  	}  	/* step 5: remove core well power */ @@ -3801,7 +3805,7 @@ int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1)  	return raw_port;  } -#ifdef CONFIG_USB_SUSPEND +#ifdef CONFIG_PM_RUNTIME  /* BESL to HIRD Encoding array for USB2 LPM */  static int xhci_besl_encoding[16] = {125, 150, 200, 300, 400, 500, 1000, 2000, @@ -4051,7 +4055,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)  	return 0;  } -#endif /* CONFIG_USB_SUSPEND */ +#endif /* CONFIG_PM_RUNTIME */  /*---------------------- USB 3.0 Link PM functions ------------------------*/ diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 63582719e0f..29c978e3713 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1238,8 +1238,8 @@ union xhci_trb {  #define TRBS_PER_SEGMENT	64  /* Allow two commands + a link TRB, along with any reserved command TRBs */  #define MAX_RSVD_CMD_TRBS	(TRBS_PER_SEGMENT - 3) -#define SEGMENT_SIZE		(TRBS_PER_SEGMENT*16) -#define SEGMENT_SHIFT		(__ffs(SEGMENT_SIZE)) +#define TRB_SEGMENT_SIZE	(TRBS_PER_SEGMENT*16) +#define TRB_SEGMENT_SHIFT	(ilog2(TRB_SEGMENT_SIZE))  /* TRB buffer pointers can't cross 64KB boundaries */  #define TRB_MAX_BUFF_SHIFT		16  #define TRB_MAX_BUFF_SIZE	(1 << TRB_MAX_BUFF_SHIFT)  |