diff mbox

USB: EHCI: make ehci-tegra a separate driver

Message ID 1363167296-11851-1-git-send-email-manjunath.goudar@linaro.org
State New
Headers show

Commit Message

manjunath.goudar@linaro.org March 13, 2013, 9:34 a.m. UTC
Separate the Tegra on-chip host controller driver from
ehci-hcd host code so that it can be built as a separate driver module.
This work is part of enabling multi-platform kernels on ARM;
however, note that other changes are still needed before Tegra
can be booted with a multi-platform kernel.

Signed-off-by: Manjunath Goudar <manjunath.goudar@linaro.org>
Cc: Greg KH <greg@kroah.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Russell King <linux@arm.linux.org.uk>
CC: Felipe Balbi <balbi@ti.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-usb@vger.kernel.org
Cc: linux-tegra@vger.kernel.org
---
 drivers/usb/host/Kconfig        |    2 +-
 drivers/usb/host/Makefile       |    1 +
 drivers/usb/host/ehci-hcd.c     |   52 +++++++++-------
 drivers/usb/host/ehci-hub.c     |    9 +--
 drivers/usb/host/ehci-tegra.c   |  127 +++++++++++++++++++--------------------
 drivers/usb/host/ehci.h         |   23 +++++++
 drivers/usb/otg/ulpi_viewport.c |    2 +
 7 files changed, 125 insertions(+), 91 deletions(-)

Comments

manjunath.goudar@linaro.org March 13, 2013, 9:43 a.m. UTC | #1
Hi arnd,

I think I fixed all your review comments in this latest patch look ones
again,if any thing enhancement is required let me know.

after using below command, having 6 warning if have any comment on this let
me.I am confusing about how to remove WARNING: Avoid CamelCase: <typeReq>
errors.

#git show --format=email | scripts/checkpatch.pl -
WARNING: line over 80 characters
#199: FILE: drivers/usb/host/ehci-hcd.c:1245:
+ drv->unmap_urb_for_dma = over->unmap_urb_for_dma;

WARNING: Avoid CamelCase: <typeReq>
#528: FILE: drivers/usb/host/ehci.h:809:
+ int (*hub_control)(struct usb_hcd *hcd, u16 typeReq, u16 wValue,

WARNING: Avoid CamelCase: <wValue>
#528: FILE: drivers/usb/host/ehci.h:809:
+ int (*hub_control)(struct usb_hcd *hcd, u16 typeReq, u16 wValue,

WARNING: Avoid CamelCase: <wIndex>
#529: FILE: drivers/usb/host/ehci.h:810:
+ u16 wIndex, char *buf, u16 wLength);

WARNING: Avoid CamelCase: <wLength>
#529: FILE: drivers/usb/host/ehci.h:810:
+ u16 wIndex, char *buf, u16 wLength);

total: 0 errors, 5 warnings, 475 lines checked

Your patch has style problems, please review.

If any of these errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.



Thanks
Manjunath Goudar


On 13 March 2013 15:04, Manjunath Goudar <manjunath.goudar@linaro.org>wrote:

> Separate the Tegra on-chip host controller driver from
> ehci-hcd host code so that it can be built as a separate driver module.
> This work is part of enabling multi-platform kernels on ARM;
> however, note that other changes are still needed before Tegra
> can be booted with a multi-platform kernel.
>
> Signed-off-by: Manjunath Goudar <manjunath.goudar@linaro.org>
> Cc: Greg KH <greg@kroah.com>
> Cc: Alan Stern <stern@rowland.harvard.edu>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: Stephen Warren <swarren@wwwdotorg.org>
> Cc: Russell King <linux@arm.linux.org.uk>
> CC: Felipe Balbi <balbi@ti.com>
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linux-usb@vger.kernel.org
> Cc: linux-tegra@vger.kernel.org
> ---
>  drivers/usb/host/Kconfig        |    2 +-
>  drivers/usb/host/Makefile       |    1 +
>  drivers/usb/host/ehci-hcd.c     |   52 +++++++++-------
>  drivers/usb/host/ehci-hub.c     |    9 +--
>  drivers/usb/host/ehci-tegra.c   |  127
> +++++++++++++++++++--------------------
>  drivers/usb/host/ehci.h         |   23 +++++++
>  drivers/usb/otg/ulpi_viewport.c |    2 +
>  7 files changed, 125 insertions(+), 91 deletions(-)
>
> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
> index 1c516c6..2d15cca 100644
> --- a/drivers/usb/host/Kconfig
> +++ b/drivers/usb/host/Kconfig
> @@ -210,7 +210,7 @@ config USB_EHCI_MSM
>           has an external PHY.
>
>  config USB_EHCI_TEGRA
> -       boolean "NVIDIA Tegra HCD support"
> +       tristate "NVIDIA Tegra HCD support"
>         depends on USB_EHCI_HCD && ARCH_TEGRA
>         select USB_EHCI_ROOT_HUB_TT
>         help
> diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
> index 1550a0e..67bea25 100644
> --- a/drivers/usb/host/Makefile
> +++ b/drivers/usb/host/Makefile
> @@ -35,6 +35,7 @@ obj-$(CONFIG_USB_EHCI_HCD_VT8500)     += ehci-vt8500.o
>  obj-$(CONFIG_USB_EHCI_MSM)     += ehci-msm.o
>  obj-$(CONFIG_USB_W90X900_EHCI) += ehci-w90x900.o
>  obj-$(CONFIG_USB_EHCI_HCD_ORION)       += ehci-orion.o
> +obj-$(CONFIG_USB_EHCI_TEGRA)    +=ehci-tegra.o
>
>
>  obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
> diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
> index a077323..8e2691b 100644
> --- a/drivers/usb/host/ehci-hcd.c
> +++ b/drivers/usb/host/ehci-hcd.c
> @@ -139,7 +139,7 @@ static inline unsigned ehci_read_frame_index(struct
> ehci_hcd *ehci)
>
>  /*-------------------------------------------------------------------------*/
>
>  /*
> - * handshake - spin reading hc until handshake completes or fails
> + * ehci_handshake - spin reading hc until handshake completes or fails
>   * @ptr: address of hc register to be read
>   * @mask: bits to look at in result of read
>   * @done: value of those bits when handshake succeeds
> @@ -155,7 +155,7 @@ static inline unsigned ehci_read_frame_index(struct
> ehci_hcd *ehci)
>   * before driver shutdown. But it also seems to be caused by bugs in
> cardbus
>   * bridge shutdown:  shutting down the bridge before the devices using it.
>   */
> -static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
> +int ehci_handshake(struct ehci_hcd *ehci, void __iomem *ptr,
>                       u32 mask, u32 done, int usec)
>  {
>         u32     result;
> @@ -172,9 +172,10 @@ static int handshake (struct ehci_hcd *ehci, void
> __iomem *ptr,
>         } while (usec > 0);
>         return -ETIMEDOUT;
>  }
> +EXPORT_SYMBOL_GPL(ehci_handshake);
>
>  /* check TDI/ARC silicon is in host mode */
> -static int tdi_in_host_mode (struct ehci_hcd *ehci)
> +static int tdi_in_host_mode(struct ehci_hcd *ehci)
>  {
>         u32             tmp;
>
> @@ -186,7 +187,7 @@ static int tdi_in_host_mode (struct ehci_hcd *ehci)
>   * Force HC to halt state from unknown (EHCI spec section 2.3).
>   * Must be called with interrupts enabled and the lock not held.
>   */
> -static int ehci_halt (struct ehci_hcd *ehci)
> +int ehci_halt(struct ehci_hcd *ehci)
>  {
>         u32     temp;
>
> @@ -212,12 +213,13 @@ static int ehci_halt (struct ehci_hcd *ehci)
>         spin_unlock_irq(&ehci->lock);
>         synchronize_irq(ehci_to_hcd(ehci)->irq);
>
> -       return handshake(ehci, &ehci->regs->status,
> +       return ehci_handshake(ehci, &ehci->regs->status,
>                           STS_HALT, STS_HALT, 16 * 125);
>  }
> +EXPORT_SYMBOL_GPL(ehci_halt);
>
>  /* put TDI/ARC silicon into EHCI mode */
> -static void tdi_reset (struct ehci_hcd *ehci)
> +void ehci_tdi_reset(struct ehci_hcd *ehci)
>  {
>         u32             tmp;
>
> @@ -231,12 +233,13 @@ static void tdi_reset (struct ehci_hcd *ehci)
>                 tmp |= USBMODE_BE;
>         ehci_writel(ehci, tmp, &ehci->regs->usbmode);
>  }
> +EXPORT_SYMBOL_GPL(ehci_tdi_reset);
>
>  /*
>   * Reset a non-running (STS_HALT == 1) controller.
>   * Must be called with interrupts enabled and the lock not held.
>   */
> -static int ehci_reset (struct ehci_hcd *ehci)
> +int ehci_reset(struct ehci_hcd *ehci)
>  {
>         int     retval;
>         u32     command = ehci_readl(ehci, &ehci->regs->command);
> @@ -251,7 +254,7 @@ static int ehci_reset (struct ehci_hcd *ehci)
>         ehci_writel(ehci, command, &ehci->regs->command);
>         ehci->rh_state = EHCI_RH_HALTED;
>         ehci->next_statechange = jiffies;
> -       retval = handshake (ehci, &ehci->regs->command,
> +       retval = ehci_handshake(ehci, &ehci->regs->command,
>                             CMD_RESET, 0, 250 * 1000);
>
>         if (ehci->has_hostpc) {
> @@ -263,7 +266,7 @@ static int ehci_reset (struct ehci_hcd *ehci)
>                 return retval;
>
>         if (ehci_is_TDI(ehci))
> -               tdi_reset (ehci);
> +               ehci_tdi_reset(ehci);
>
>         if (ehci->debug)
>                 dbgp_external_startup(ehci_to_hcd(ehci));
> @@ -272,12 +275,13 @@ static int ehci_reset (struct ehci_hcd *ehci)
>                         ehci->resuming_ports = 0;
>         return retval;
>  }
> +EXPORT_SYMBOL_GPL(ehci_reset);
>
>  /*
>   * Idle the controller (turn off the schedules).
>   * Must be called with interrupts enabled and the lock not held.
>   */
> -static void ehci_quiesce (struct ehci_hcd *ehci)
> +static void ehci_quiesce(struct ehci_hcd *ehci)
>  {
>         u32     temp;
>
> @@ -286,7 +290,8 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
>
>         /* wait for any schedule enables/disables to take effect */
>         temp = (ehci->command << 10) & (STS_ASS | STS_PSS);
> -       handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, temp, 16 *
> 125);
> +       ehci_handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, temp,
> +                       16 * 125);
>
>         /* then disable anything that's still active */
>         spin_lock_irq(&ehci->lock);
> @@ -295,7 +300,8 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
>         spin_unlock_irq(&ehci->lock);
>
>         /* hardware can take 16 microframes to turn off ... */
> -       handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, 0, 16 *
> 125);
> +       ehci_handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, 0,
> +                       16 * 125);
>  }
>
>
>  /*-------------------------------------------------------------------------*/
> @@ -671,7 +677,7 @@ int ehci_setup(struct usb_hcd *hcd)
>                 return retval;
>
>         if (ehci_is_TDI(ehci))
> -               tdi_reset(ehci);
> +               ehci_tdi_reset(ehci);
>
>         ehci_reset(ehci);
>
> @@ -1230,10 +1236,16 @@ void ehci_init_driver(struct hc_driver *drv,
>         *drv = ehci_hc_driver;
>
>         if (over) {
> -               drv->hcd_priv_size += over->extra_priv_size;
> -               if (over->reset)
> -                       drv->reset = over->reset;
> -       }
> +                       drv->hcd_priv_size += over->extra_priv_size;
> +                       if (over->reset)
> +                               drv->reset = over->reset;
> +                       if (over->map_urb_for_dma)
> +                               drv->map_urb_for_dma =
> over->map_urb_for_dma;
> +                       if (over->unmap_urb_for_dma)
> +                               drv->unmap_urb_for_dma =
> over->unmap_urb_for_dma;
> +                       if (over->hub_control)
> +                               drv->hub_control = over->hub_control;
> +               }
>  }
>  EXPORT_SYMBOL_GPL(ehci_init_driver);
>
> @@ -1288,11 +1300,6 @@ MODULE_LICENSE ("GPL");
>  #define        PLATFORM_DRIVER         ehci_hcd_msp_driver
>  #endif
>
> -#ifdef CONFIG_USB_EHCI_TEGRA
> -#include "ehci-tegra.c"
> -#define PLATFORM_DRIVER                tegra_ehci_driver
> -#endif
> -
>  #ifdef CONFIG_SPARC_LEON
>  #include "ehci-grlib.c"
>  #define PLATFORM_DRIVER                ehci_grlib_driver
> @@ -1315,6 +1322,7 @@ MODULE_LICENSE ("GPL");
>         !IS_ENABLED(CONFIG_USB_EHCI_MSM) && \
>         !IS_ENABLED(CONFIG_USB_W90X900_EHCI) && \
>         !IS_ENABLED(CONFIG_PLAT_ORION) && \
> +       !IS_ENABLED(CONFIG_USB_EHCI_TEGRA) && \
>         !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 4d3b294..c678a66 100644
> --- a/drivers/usb/host/ehci-hub.c
> +++ b/drivers/usb/host/ehci-hub.c
> @@ -33,7 +33,7 @@
>
>  #ifdef CONFIG_PM
>
> -static int ehci_hub_control(
> +int ehci_hub_control(
>         struct usb_hcd  *hcd,
>         u16             typeReq,
>         u16             wValue,
> @@ -695,7 +695,7 @@ ehci_hub_descriptor (
>
>
>  /*-------------------------------------------------------------------------*/
>
> -static int ehci_hub_control (
> +int ehci_hub_control(
>         struct usb_hcd  *hcd,
>         u16             typeReq,
>         u16             wValue,
> @@ -875,7 +875,7 @@ static int ehci_hub_control (
>                                         temp & ~(PORT_RWC_BITS |
> PORT_RESUME),
>                                         status_reg);
>                                 clear_bit(wIndex, &ehci->resuming_ports);
> -                               retval = handshake(ehci, status_reg,
> +                               retval = ehci_handshake(ehci, status_reg,
>                                            PORT_RESUME, 0, 2000 /* 2msec
> */);
>                                 if (retval != 0) {
>                                         ehci_err(ehci,
> @@ -901,7 +901,7 @@ static int ehci_hub_control (
>                         /* REVISIT:  some hardware needs 550+ usec to clear
>                          * this bit; seems too long to spin routinely...
>                          */
> -                       retval = handshake(ehci, status_reg,
> +                       retval = ehci_handshake(ehci, status_reg,
>                                         PORT_RESET, 0, 1000);
>                         if (retval != 0) {
>                                 ehci_err (ehci, "port %d reset error %d\n",
> @@ -1115,6 +1115,7 @@ error_exit:
>         spin_unlock_irqrestore (&ehci->lock, flags);
>         return retval;
>  }
> +EXPORT_SYMBOL_GPL(ehci_hub_control);
>
>  static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
>  {
> diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
> index 568aecc..55c908b 100644
> --- a/drivers/usb/host/ehci-tegra.c
> +++ b/drivers/usb/host/ehci-tegra.c
> @@ -17,18 +17,27 @@
>   */
>
>  #include <linux/clk.h>
> +#include <linux/dma-mapping.h>
>  #include <linux/err.h>
> -#include <linux/platform_device.h>
> -#include <linux/platform_data/tegra_usb.h>
> -#include <linux/irq.h>
> -#include <linux/usb/otg.h>
>  #include <linux/gpio.h>
> +#include <linux/io.h>
> +#include <linux/irq.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
>  #include <linux/of.h>
>  #include <linux/of_gpio.h>
> +#include <linux/platform_device.h>
> +#include <linux/platform_data/tegra_usb.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/slab.h>
> +#include <linux/usb/otg.h>
>  #include <linux/usb/ehci_def.h>
> +#include <linux/usb.h>
> +#include <linux/usb/hcd.h>
>  #include <linux/usb/tegra_usb_phy.h>
>
> +#include "ehci.h"
> +
>  #define TEGRA_USB_BASE                 0xC5000000
>  #define TEGRA_USB2_BASE                        0xC5004000
>  #define TEGRA_USB3_BASE                        0xC5008000
> @@ -37,9 +46,14 @@
>  #define TEGRA_USB_PORTSC1                      0x184
>  #define TEGRA_USB_PORTSC1_PTS(x)       (((x) & 0x3) << 30)
>  #define TEGRA_USB_PORTSC1_PHCD (1 << 23)
> +#define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
>
>  #define TEGRA_USB_DMA_ALIGN 32
>
> +#define DRIVER_DESC "EHCI Tegra driver"
> +
> +static const char hcd_name[] = "tegra-ehci";
> +
>  struct tegra_ehci_hcd {
>         struct ehci_hcd *ehci;
>         struct tegra_usb_phy *phy;
> @@ -178,7 +192,7 @@ static int tegra_ehci_hub_control(
>                  * If a transaction is in progress, there may be a delay in
>                  * suspending the port. Poll until the port is suspended.
>                  */
> -               if (handshake(ehci, status_reg, PORT_SUSPEND,
> +               if (ehci_handshake(ehci, status_reg, PORT_SUSPEND,
>                                                 PORT_SUSPEND, 5000))
>                         pr_err("%s: timeout waiting for SUSPEND\n",
> __func__);
>
> @@ -226,9 +240,9 @@ static int tegra_ehci_hub_control(
>                 spin_lock_irqsave(&ehci->lock, flags);
>
>                 /* Poll until the controller clears RESUME and SUSPEND */
> -               if (handshake(ehci, status_reg, PORT_RESUME, 0, 2000))
> +               if (ehci_handshake(ehci, status_reg, PORT_RESUME, 0, 2000))
>                         pr_err("%s: timeout waiting for RESUME\n",
> __func__);
> -               if (handshake(ehci, status_reg, PORT_SUSPEND, 0, 2000))
> +               if (ehci_handshake(ehci, status_reg, PORT_SUSPEND, 0,
> 2000))
>                         pr_err("%s: timeout waiting for SUSPEND\n",
> __func__);
>
>                 ehci->reset_done[wIndex-1] = 0;
> @@ -268,31 +282,6 @@ static void tegra_ehci_restart(struct usb_hcd *hcd)
>         up_write(&ehci_cf_port_reset_rwsem);
>  }
>
> -static void tegra_ehci_shutdown(struct usb_hcd *hcd)
> -{
> -       struct tegra_ehci_hcd *tegra =
> dev_get_drvdata(hcd->self.controller);
> -
> -       /* ehci_shutdown touches the USB controller registers, make sure
> -        * controller has clocks to it */
> -       if (!tegra->host_resumed)
> -               tegra_ehci_power_up(hcd);
> -
> -       ehci_shutdown(hcd);
> -}
> -
> -static int tegra_ehci_setup(struct usb_hcd *hcd)
> -{
> -       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
> -
> -       /* EHCI registers start at offset 0x100 */
> -       ehci->caps = hcd->regs + 0x100;
> -
> -       /* switch to host mode */
> -       hcd->has_tt = 1;
> -
> -       return ehci_setup(hcd);
> -}
> -
>  struct dma_aligned_buffer {
>         void *kmalloc_ptr;
>         void *old_xfer_buffer;
> @@ -372,36 +361,14 @@ static void tegra_ehci_unmap_urb_for_dma(struct
> usb_hcd *hcd, struct urb *urb)
>         free_dma_aligned_buffer(urb);
>  }
>
> -static const struct hc_driver tegra_ehci_hc_driver = {
> -       .description            = hcd_name,
> -       .product_desc           = "Tegra EHCI Host Controller",
> -       .hcd_priv_size          = sizeof(struct ehci_hcd),
> -       .flags                  = HCD_USB2 | HCD_MEMORY,
> -
> -       /* standard ehci functions */
> -       .irq                    = ehci_irq,
> -       .start                  = ehci_run,
> -       .stop                   = ehci_stop,
> -       .urb_enqueue            = ehci_urb_enqueue,
> -       .urb_dequeue            = ehci_urb_dequeue,
> -       .endpoint_disable       = ehci_endpoint_disable,
> -       .endpoint_reset         = ehci_endpoint_reset,
> -       .get_frame_number       = ehci_get_frame,
> -       .hub_status_data        = ehci_hub_status_data,
> -       .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
> -       .relinquish_port        = ehci_relinquish_port,
> -       .port_handed_over       = ehci_port_handed_over,
> -
> -       /* modified ehci functions for tegra */
> -       .reset                  = tegra_ehci_setup,
> -       .shutdown               = tegra_ehci_shutdown,
> +static struct hc_driver __read_mostly tegra_ehci_hc_driver;
> +
> +static struct ehci_driver_overrides tegra_overrides __initdata = {
> +       .extra_priv_size        = sizeof(struct tegra_ehci_hcd),
>         .map_urb_for_dma        = tegra_ehci_map_urb_for_dma,
>         .unmap_urb_for_dma      = tegra_ehci_unmap_urb_for_dma,
> -       .hub_control            = tegra_ehci_hub_control,
> -#ifdef CONFIG_PM
> -       .bus_suspend            = ehci_bus_suspend,
> -       .bus_resume             = ehci_bus_resume,
> -#endif
> +       .hub_control    = tegra_ehci_hub_control,
> +
>  };
>
>  static int setup_vbus_gpio(struct platform_device *pdev,
> @@ -479,7 +446,7 @@ static int controller_resume(struct device *dev)
>         tegra_ehci_phy_restore_start(hcd->phy, tegra->port_speed);
>
>         /* Enable host mode */
> -       tdi_reset(ehci);
> +       ehci_tdi_reset(ehci);
>
>         /* Enable Port Power */
>         val = readl(&hw->port_status[0]);
> @@ -510,14 +477,14 @@ static int controller_resume(struct device *dev)
>         }
>
>         /* Poll until CCS is enabled */
> -       if (handshake(ehci, &hw->port_status[0], PORT_CONNECT,
> +       if (ehci_handshake(ehci, &hw->port_status[0], PORT_CONNECT,
>                                                  PORT_CONNECT, 2000)) {
>                 pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__);
>                 goto restart;
>         }
>
>         /* Poll until PE is enabled */
> -       if (handshake(ehci, &hw->port_status[0], PORT_PE,
> +       if (ehci_handshake(ehci, &hw->port_status[0], PORT_PE,
>                                                  PORT_PE, 2000)) {
>                 pr_err("%s: timeout waiting for USB_PORTSC1_PE\n",
> __func__);
>                 goto restart;
> @@ -535,7 +502,7 @@ static int controller_resume(struct device *dev)
>                 writel(val, &hw->port_status[0]);
>
>                 /* Wait until port suspend completes */
> -               if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND,
> +               if (ehci_handshake(ehci, &hw->port_status[0], PORT_SUSPEND,
>                                                          PORT_SUSPEND,
> 1000)) {
>                         pr_err("%s: timeout waiting for PORT_SUSPEND\n",
>                                                                 __func__);
> @@ -758,7 +725,13 @@ static int tegra_ehci_probe(struct platform_device
> *pdev)
>                 goto fail;
>         }
>
> +       /* EHCI registers start at offset 0x100 */
> +       tegra->ehci->caps = hcd->regs + 0x100;
> +
>         tegra->host_resumed = 1;
> +
> +       /* switch to host mode */
> +       hcd->has_tt = 1;
>         tegra->ehci = hcd_to_ehci(hcd);
>
>         irq = platform_get_irq(pdev, 0);
> @@ -834,6 +807,10 @@ static void tegra_ehci_hcd_shutdown(struct
> platform_device *pdev)
>         struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
>         struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
>
> +       /* ehci_shutdown touches the USB controller registers, make sure
> +       * controller has clocks to it */
> +       if (!tegra->host_resumed)
> +               tegra_ehci_power_up(hcd);
>         if (hcd->driver->shutdown)
>                 hcd->driver->shutdown(hcd);
>  }
> @@ -855,3 +832,25 @@ static struct platform_driver tegra_ehci_driver = {
>  #endif
>         }
>  };
> +
> +static int __init ehci_tegra_init(void)
> +{
> +       if (usb_disabled())
> +               return -ENODEV;
> +
> +       pr_info("%s: " DRIVER_DESC "\n", hcd_name);
> +
> +       ehci_init_driver(&tegra_ehci_hc_driver, &tegra_overrides);
> +       return platform_driver_register(&tegra_ehci_driver);
> +}
> +module_init(ehci_tegra_init);
> +
> +static void __exit ehci_tegra_cleanup(void)
> +{
> +       platform_driver_unregister(&tegra_ehci_driver);
> +}
> +module_exit(ehci_tegra_cleanup);
> +
> +MODULE_DESCRIPTION(DRIVER_DESC);
> +MODULE_ALIAS("platform:tegra-ehci");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
> index 139c932..ca15529 100644
> --- a/drivers/usb/host/ehci.h
> +++ b/drivers/usb/host/ehci.h
> @@ -793,12 +793,35 @@ static inline u32 hc32_to_cpup (const struct
> ehci_hcd *ehci, const __hc32 *x)
>  struct ehci_driver_overrides {
>         size_t          extra_priv_size;
>         int             (*reset)(struct usb_hcd *hcd);
> +       /*
> +       * (optional) these hooks allow an HCD to override the default DMA
> +       * mapping and unmapping routines.  In general, they shouldn't be
> +       * necessary unless the host controller has special DMA
> requirements,
> +       * such as alignment contraints.  If these are not specified, the
> +       * general usb_hcd_(un)?map_urb_for_dma functions will be used
> instead
> +       * (and it may be a good idea to call these functions in your HCD
> +       * implementation)
> +       */
> +       int     (*map_urb_for_dma)(struct usb_hcd *hcd, struct urb *urb,
> +                                       gfp_t mem_flags);
> +       void    (*unmap_urb_for_dma)(struct usb_hcd *hcd, struct urb *urb);
> +       /* root hub support */
> +       int     (*hub_control)(struct usb_hcd *hcd, u16 typeReq, u16
> wValue,
> +                               u16 wIndex, char *buf, u16 wLength);
>  };
>
>  extern void    ehci_init_driver(struct hc_driver *drv,
>                                 const struct ehci_driver_overrides *over);
>  extern int     ehci_setup(struct usb_hcd *hcd);
>  extern void    ehci_shutdown(struct usb_hcd *hcd);
> +extern int     ehci_handshake(struct ehci_hcd *ehci, void __iomem *ptr,
> +                               u32 mask, u32 done, int usec);
> +extern int     ehci_hub_control(struct usb_hcd  *hcd, u16 typeReq,
> +                               u16 wValue, u16 wIndex, char *buf,
> +                               u16 wLength);
> +extern int     ehci_reset(struct ehci_hcd *ehci);
> +extern int     ehci_halt(struct ehci_hcd *ehci);
> +extern void    ehci_tdi_reset(struct ehci_hcd *ehci);
>
>  #ifdef CONFIG_PM
>  extern int     ehci_suspend(struct usb_hcd *hcd, bool do_wakeup);
> diff --git a/drivers/usb/otg/ulpi_viewport.c
> b/drivers/usb/otg/ulpi_viewport.c
> index c5ba7e5..4442425 100644
> --- a/drivers/usb/otg/ulpi_viewport.c
> +++ b/drivers/usb/otg/ulpi_viewport.c
> @@ -13,6 +13,7 @@
>   */
>
>  #include <linux/kernel.h>
> +#include <linux/module.h>
>  #include <linux/usb.h>
>  #include <linux/io.h>
>  #include <linux/usb/otg.h>
> @@ -78,3 +79,4 @@ struct usb_phy_io_ops ulpi_viewport_access_ops = {
>         .read   = ulpi_viewport_read,
>         .write  = ulpi_viewport_write,
>  };
> +EXPORT_SYMBOL_GPL(ulpi_viewport_access_ops);
> --
> 1.7.9.5
>
>
Arnd Bergmann March 14, 2013, 3:43 p.m. UTC | #2
On Wednesday 13 March 2013, Manjunath Goudar wrote:
> I think I fixed all your review comments in this latest patch look ones
> again,if any thing enhancement is required let me know.
> 
> after using below command, having 6 warning if have any comment on this let
> me.I am confusing about how to remove WARNING: Avoid CamelCase: <typeReq>
> errors.

I think you can ignore those in this case, since the CamelCase is
preexisting in the USB subsystem, you are just moving stuff around.

	Arnd
diff mbox

Patch

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 1c516c6..2d15cca 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -210,7 +210,7 @@  config USB_EHCI_MSM
 	  has an external PHY.
 
 config USB_EHCI_TEGRA
-       boolean "NVIDIA Tegra HCD support"
+       tristate "NVIDIA Tegra HCD support"
        depends on USB_EHCI_HCD && ARCH_TEGRA
        select USB_EHCI_ROOT_HUB_TT
        help
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 1550a0e..67bea25 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -35,6 +35,7 @@  obj-$(CONFIG_USB_EHCI_HCD_VT8500)	+= ehci-vt8500.o
 obj-$(CONFIG_USB_EHCI_MSM)	+= ehci-msm.o
 obj-$(CONFIG_USB_W90X900_EHCI)	+= ehci-w90x900.o
 obj-$(CONFIG_USB_EHCI_HCD_ORION)	+= ehci-orion.o
+obj-$(CONFIG_USB_EHCI_TEGRA)    +=ehci-tegra.o
 
 
 obj-$(CONFIG_USB_OXU210HP_HCD)	+= oxu210hp-hcd.o
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index a077323..8e2691b 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -139,7 +139,7 @@  static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
 /*-------------------------------------------------------------------------*/
 
 /*
- * handshake - spin reading hc until handshake completes or fails
+ * ehci_handshake - spin reading hc until handshake completes or fails
  * @ptr: address of hc register to be read
  * @mask: bits to look at in result of read
  * @done: value of those bits when handshake succeeds
@@ -155,7 +155,7 @@  static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci)
  * before driver shutdown. But it also seems to be caused by bugs in cardbus
  * bridge shutdown:  shutting down the bridge before the devices using it.
  */
-static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
+int ehci_handshake(struct ehci_hcd *ehci, void __iomem *ptr,
 		      u32 mask, u32 done, int usec)
 {
 	u32	result;
@@ -172,9 +172,10 @@  static int handshake (struct ehci_hcd *ehci, void __iomem *ptr,
 	} while (usec > 0);
 	return -ETIMEDOUT;
 }
+EXPORT_SYMBOL_GPL(ehci_handshake);
 
 /* check TDI/ARC silicon is in host mode */
-static int tdi_in_host_mode (struct ehci_hcd *ehci)
+static int tdi_in_host_mode(struct ehci_hcd *ehci)
 {
 	u32		tmp;
 
@@ -186,7 +187,7 @@  static int tdi_in_host_mode (struct ehci_hcd *ehci)
  * Force HC to halt state from unknown (EHCI spec section 2.3).
  * Must be called with interrupts enabled and the lock not held.
  */
-static int ehci_halt (struct ehci_hcd *ehci)
+int ehci_halt(struct ehci_hcd *ehci)
 {
 	u32	temp;
 
@@ -212,12 +213,13 @@  static int ehci_halt (struct ehci_hcd *ehci)
 	spin_unlock_irq(&ehci->lock);
 	synchronize_irq(ehci_to_hcd(ehci)->irq);
 
-	return handshake(ehci, &ehci->regs->status,
+	return ehci_handshake(ehci, &ehci->regs->status,
 			  STS_HALT, STS_HALT, 16 * 125);
 }
+EXPORT_SYMBOL_GPL(ehci_halt);
 
 /* put TDI/ARC silicon into EHCI mode */
-static void tdi_reset (struct ehci_hcd *ehci)
+void ehci_tdi_reset(struct ehci_hcd *ehci)
 {
 	u32		tmp;
 
@@ -231,12 +233,13 @@  static void tdi_reset (struct ehci_hcd *ehci)
 		tmp |= USBMODE_BE;
 	ehci_writel(ehci, tmp, &ehci->regs->usbmode);
 }
+EXPORT_SYMBOL_GPL(ehci_tdi_reset);
 
 /*
  * Reset a non-running (STS_HALT == 1) controller.
  * Must be called with interrupts enabled and the lock not held.
  */
-static int ehci_reset (struct ehci_hcd *ehci)
+int ehci_reset(struct ehci_hcd *ehci)
 {
 	int	retval;
 	u32	command = ehci_readl(ehci, &ehci->regs->command);
@@ -251,7 +254,7 @@  static int ehci_reset (struct ehci_hcd *ehci)
 	ehci_writel(ehci, command, &ehci->regs->command);
 	ehci->rh_state = EHCI_RH_HALTED;
 	ehci->next_statechange = jiffies;
-	retval = handshake (ehci, &ehci->regs->command,
+	retval = ehci_handshake(ehci, &ehci->regs->command,
 			    CMD_RESET, 0, 250 * 1000);
 
 	if (ehci->has_hostpc) {
@@ -263,7 +266,7 @@  static int ehci_reset (struct ehci_hcd *ehci)
 		return retval;
 
 	if (ehci_is_TDI(ehci))
-		tdi_reset (ehci);
+		ehci_tdi_reset(ehci);
 
 	if (ehci->debug)
 		dbgp_external_startup(ehci_to_hcd(ehci));
@@ -272,12 +275,13 @@  static int ehci_reset (struct ehci_hcd *ehci)
 			ehci->resuming_ports = 0;
 	return retval;
 }
+EXPORT_SYMBOL_GPL(ehci_reset);
 
 /*
  * Idle the controller (turn off the schedules).
  * Must be called with interrupts enabled and the lock not held.
  */
-static void ehci_quiesce (struct ehci_hcd *ehci)
+static void ehci_quiesce(struct ehci_hcd *ehci)
 {
 	u32	temp;
 
@@ -286,7 +290,8 @@  static void ehci_quiesce (struct ehci_hcd *ehci)
 
 	/* wait for any schedule enables/disables to take effect */
 	temp = (ehci->command << 10) & (STS_ASS | STS_PSS);
-	handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, temp, 16 * 125);
+	ehci_handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, temp,
+			16 * 125);
 
 	/* then disable anything that's still active */
 	spin_lock_irq(&ehci->lock);
@@ -295,7 +300,8 @@  static void ehci_quiesce (struct ehci_hcd *ehci)
 	spin_unlock_irq(&ehci->lock);
 
 	/* hardware can take 16 microframes to turn off ... */
-	handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, 0, 16 * 125);
+	ehci_handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, 0,
+			16 * 125);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -671,7 +677,7 @@  int ehci_setup(struct usb_hcd *hcd)
 		return retval;
 
 	if (ehci_is_TDI(ehci))
-		tdi_reset(ehci);
+		ehci_tdi_reset(ehci);
 
 	ehci_reset(ehci);
 
@@ -1230,10 +1236,16 @@  void ehci_init_driver(struct hc_driver *drv,
 	*drv = ehci_hc_driver;
 
 	if (over) {
-		drv->hcd_priv_size += over->extra_priv_size;
-		if (over->reset)
-			drv->reset = over->reset;
-	}
+			drv->hcd_priv_size += over->extra_priv_size;
+			if (over->reset)
+				drv->reset = over->reset;
+			if (over->map_urb_for_dma)
+				drv->map_urb_for_dma = over->map_urb_for_dma;
+			if (over->unmap_urb_for_dma)
+				drv->unmap_urb_for_dma = over->unmap_urb_for_dma;
+			if (over->hub_control)
+				drv->hub_control = over->hub_control;
+		}
 }
 EXPORT_SYMBOL_GPL(ehci_init_driver);
 
@@ -1288,11 +1300,6 @@  MODULE_LICENSE ("GPL");
 #define	PLATFORM_DRIVER		ehci_hcd_msp_driver
 #endif
 
-#ifdef CONFIG_USB_EHCI_TEGRA
-#include "ehci-tegra.c"
-#define PLATFORM_DRIVER		tegra_ehci_driver
-#endif
-
 #ifdef CONFIG_SPARC_LEON
 #include "ehci-grlib.c"
 #define PLATFORM_DRIVER		ehci_grlib_driver
@@ -1315,6 +1322,7 @@  MODULE_LICENSE ("GPL");
 	!IS_ENABLED(CONFIG_USB_EHCI_MSM) && \
 	!IS_ENABLED(CONFIG_USB_W90X900_EHCI) && \
 	!IS_ENABLED(CONFIG_PLAT_ORION) && \
+	!IS_ENABLED(CONFIG_USB_EHCI_TEGRA) && \
 	!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 4d3b294..c678a66 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -33,7 +33,7 @@ 
 
 #ifdef	CONFIG_PM
 
-static int ehci_hub_control(
+int ehci_hub_control(
 	struct usb_hcd	*hcd,
 	u16		typeReq,
 	u16		wValue,
@@ -695,7 +695,7 @@  ehci_hub_descriptor (
 
 /*-------------------------------------------------------------------------*/
 
-static int ehci_hub_control (
+int ehci_hub_control(
 	struct usb_hcd	*hcd,
 	u16		typeReq,
 	u16		wValue,
@@ -875,7 +875,7 @@  static int ehci_hub_control (
 					temp & ~(PORT_RWC_BITS | PORT_RESUME),
 					status_reg);
 				clear_bit(wIndex, &ehci->resuming_ports);
-				retval = handshake(ehci, status_reg,
+				retval = ehci_handshake(ehci, status_reg,
 					   PORT_RESUME, 0, 2000 /* 2msec */);
 				if (retval != 0) {
 					ehci_err(ehci,
@@ -901,7 +901,7 @@  static int ehci_hub_control (
 			/* REVISIT:  some hardware needs 550+ usec to clear
 			 * this bit; seems too long to spin routinely...
 			 */
-			retval = handshake(ehci, status_reg,
+			retval = ehci_handshake(ehci, status_reg,
 					PORT_RESET, 0, 1000);
 			if (retval != 0) {
 				ehci_err (ehci, "port %d reset error %d\n",
@@ -1115,6 +1115,7 @@  error_exit:
 	spin_unlock_irqrestore (&ehci->lock, flags);
 	return retval;
 }
+EXPORT_SYMBOL_GPL(ehci_hub_control);
 
 static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
 {
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 568aecc..55c908b 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -17,18 +17,27 @@ 
  */
 
 #include <linux/clk.h>
+#include <linux/dma-mapping.h>
 #include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/platform_data/tegra_usb.h>
-#include <linux/irq.h>
-#include <linux/usb/otg.h>
 #include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/tegra_usb.h>
 #include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/usb/otg.h>
 #include <linux/usb/ehci_def.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
 #include <linux/usb/tegra_usb_phy.h>
 
+#include "ehci.h"
+
 #define TEGRA_USB_BASE			0xC5000000
 #define TEGRA_USB2_BASE			0xC5004000
 #define TEGRA_USB3_BASE			0xC5008000
@@ -37,9 +46,14 @@ 
 #define TEGRA_USB_PORTSC1			0x184
 #define TEGRA_USB_PORTSC1_PTS(x)	(((x) & 0x3) << 30)
 #define TEGRA_USB_PORTSC1_PHCD	(1 << 23)
+#define PORT_WAKE_BITS	(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
 
 #define TEGRA_USB_DMA_ALIGN 32
 
+#define DRIVER_DESC "EHCI Tegra driver"
+
+static const char hcd_name[] = "tegra-ehci";
+
 struct tegra_ehci_hcd {
 	struct ehci_hcd *ehci;
 	struct tegra_usb_phy *phy;
@@ -178,7 +192,7 @@  static int tegra_ehci_hub_control(
 		 * If a transaction is in progress, there may be a delay in
 		 * suspending the port. Poll until the port is suspended.
 		 */
-		if (handshake(ehci, status_reg, PORT_SUSPEND,
+		if (ehci_handshake(ehci, status_reg, PORT_SUSPEND,
 						PORT_SUSPEND, 5000))
 			pr_err("%s: timeout waiting for SUSPEND\n", __func__);
 
@@ -226,9 +240,9 @@  static int tegra_ehci_hub_control(
 		spin_lock_irqsave(&ehci->lock, flags);
 
 		/* Poll until the controller clears RESUME and SUSPEND */
-		if (handshake(ehci, status_reg, PORT_RESUME, 0, 2000))
+		if (ehci_handshake(ehci, status_reg, PORT_RESUME, 0, 2000))
 			pr_err("%s: timeout waiting for RESUME\n", __func__);
-		if (handshake(ehci, status_reg, PORT_SUSPEND, 0, 2000))
+		if (ehci_handshake(ehci, status_reg, PORT_SUSPEND, 0, 2000))
 			pr_err("%s: timeout waiting for SUSPEND\n", __func__);
 
 		ehci->reset_done[wIndex-1] = 0;
@@ -268,31 +282,6 @@  static void tegra_ehci_restart(struct usb_hcd *hcd)
 	up_write(&ehci_cf_port_reset_rwsem);
 }
 
-static void tegra_ehci_shutdown(struct usb_hcd *hcd)
-{
-	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
-
-	/* ehci_shutdown touches the USB controller registers, make sure
-	 * controller has clocks to it */
-	if (!tegra->host_resumed)
-		tegra_ehci_power_up(hcd);
-
-	ehci_shutdown(hcd);
-}
-
-static int tegra_ehci_setup(struct usb_hcd *hcd)
-{
-	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
-
-	/* EHCI registers start at offset 0x100 */
-	ehci->caps = hcd->regs + 0x100;
-
-	/* switch to host mode */
-	hcd->has_tt = 1;
-
-	return ehci_setup(hcd);
-}
-
 struct dma_aligned_buffer {
 	void *kmalloc_ptr;
 	void *old_xfer_buffer;
@@ -372,36 +361,14 @@  static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
 	free_dma_aligned_buffer(urb);
 }
 
-static const struct hc_driver tegra_ehci_hc_driver = {
-	.description		= hcd_name,
-	.product_desc		= "Tegra EHCI Host Controller",
-	.hcd_priv_size		= sizeof(struct ehci_hcd),
-	.flags			= HCD_USB2 | HCD_MEMORY,
-
-	/* standard ehci functions */
-	.irq			= ehci_irq,
-	.start			= ehci_run,
-	.stop			= ehci_stop,
-	.urb_enqueue		= ehci_urb_enqueue,
-	.urb_dequeue		= ehci_urb_dequeue,
-	.endpoint_disable	= ehci_endpoint_disable,
-	.endpoint_reset		= ehci_endpoint_reset,
-	.get_frame_number	= ehci_get_frame,
-	.hub_status_data	= ehci_hub_status_data,
-	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
-	.relinquish_port	= ehci_relinquish_port,
-	.port_handed_over	= ehci_port_handed_over,
-
-	/* modified ehci functions for tegra */
-	.reset			= tegra_ehci_setup,
-	.shutdown		= tegra_ehci_shutdown,
+static struct hc_driver __read_mostly tegra_ehci_hc_driver;
+
+static struct ehci_driver_overrides tegra_overrides __initdata = {
+	.extra_priv_size	= sizeof(struct tegra_ehci_hcd),
 	.map_urb_for_dma	= tegra_ehci_map_urb_for_dma,
 	.unmap_urb_for_dma	= tegra_ehci_unmap_urb_for_dma,
-	.hub_control		= tegra_ehci_hub_control,
-#ifdef CONFIG_PM
-	.bus_suspend		= ehci_bus_suspend,
-	.bus_resume		= ehci_bus_resume,
-#endif
+	.hub_control	= tegra_ehci_hub_control,
+
 };
 
 static int setup_vbus_gpio(struct platform_device *pdev,
@@ -479,7 +446,7 @@  static int controller_resume(struct device *dev)
 	tegra_ehci_phy_restore_start(hcd->phy, tegra->port_speed);
 
 	/* Enable host mode */
-	tdi_reset(ehci);
+	ehci_tdi_reset(ehci);
 
 	/* Enable Port Power */
 	val = readl(&hw->port_status[0]);
@@ -510,14 +477,14 @@  static int controller_resume(struct device *dev)
 	}
 
 	/* Poll until CCS is enabled */
-	if (handshake(ehci, &hw->port_status[0], PORT_CONNECT,
+	if (ehci_handshake(ehci, &hw->port_status[0], PORT_CONNECT,
 						 PORT_CONNECT, 2000)) {
 		pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__);
 		goto restart;
 	}
 
 	/* Poll until PE is enabled */
-	if (handshake(ehci, &hw->port_status[0], PORT_PE,
+	if (ehci_handshake(ehci, &hw->port_status[0], PORT_PE,
 						 PORT_PE, 2000)) {
 		pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__);
 		goto restart;
@@ -535,7 +502,7 @@  static int controller_resume(struct device *dev)
 		writel(val, &hw->port_status[0]);
 
 		/* Wait until port suspend completes */
-		if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND,
+		if (ehci_handshake(ehci, &hw->port_status[0], PORT_SUSPEND,
 							 PORT_SUSPEND, 1000)) {
 			pr_err("%s: timeout waiting for PORT_SUSPEND\n",
 								__func__);
@@ -758,7 +725,13 @@  static int tegra_ehci_probe(struct platform_device *pdev)
 		goto fail;
 	}
 
+	/* EHCI registers start at offset 0x100 */
+	tegra->ehci->caps = hcd->regs + 0x100;
+
 	tegra->host_resumed = 1;
+
+	/* switch to host mode */
+	hcd->has_tt = 1;
 	tegra->ehci = hcd_to_ehci(hcd);
 
 	irq = platform_get_irq(pdev, 0);
@@ -834,6 +807,10 @@  static void tegra_ehci_hcd_shutdown(struct platform_device *pdev)
 	struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev);
 	struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci);
 
+	/* ehci_shutdown touches the USB controller registers, make sure
+	* controller has clocks to it */
+	if (!tegra->host_resumed)
+		tegra_ehci_power_up(hcd);
 	if (hcd->driver->shutdown)
 		hcd->driver->shutdown(hcd);
 }
@@ -855,3 +832,25 @@  static struct platform_driver tegra_ehci_driver = {
 #endif
 	}
 };
+
+static int __init ehci_tegra_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+	ehci_init_driver(&tegra_ehci_hc_driver, &tegra_overrides);
+	return platform_driver_register(&tegra_ehci_driver);
+}
+module_init(ehci_tegra_init);
+
+static void __exit ehci_tegra_cleanup(void)
+{
+	platform_driver_unregister(&tegra_ehci_driver);
+}
+module_exit(ehci_tegra_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_ALIAS("platform:tegra-ehci");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 139c932..ca15529 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -793,12 +793,35 @@  static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x)
 struct ehci_driver_overrides {
 	size_t		extra_priv_size;
 	int		(*reset)(struct usb_hcd *hcd);
+	/*
+	* (optional) these hooks allow an HCD to override the default DMA
+	* mapping and unmapping routines.  In general, they shouldn't be
+	* necessary unless the host controller has special DMA requirements,
+	* such as alignment contraints.  If these are not specified, the
+	* general usb_hcd_(un)?map_urb_for_dma functions will be used instead
+	* (and it may be a good idea to call these functions in your HCD
+	* implementation)
+	*/
+	int	(*map_urb_for_dma)(struct usb_hcd *hcd, struct urb *urb,
+					gfp_t mem_flags);
+	void	(*unmap_urb_for_dma)(struct usb_hcd *hcd, struct urb *urb);
+       /* root hub support */
+	int	(*hub_control)(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+				u16 wIndex, char *buf, u16 wLength);
 };
 
 extern void	ehci_init_driver(struct hc_driver *drv,
 				const struct ehci_driver_overrides *over);
 extern int	ehci_setup(struct usb_hcd *hcd);
 extern void	ehci_shutdown(struct usb_hcd *hcd);
+extern int	ehci_handshake(struct ehci_hcd *ehci, void __iomem *ptr,
+				u32 mask, u32 done, int usec);
+extern int	ehci_hub_control(struct usb_hcd  *hcd, u16 typeReq,
+				u16 wValue, u16 wIndex, char *buf,
+				u16 wLength);
+extern int	ehci_reset(struct ehci_hcd *ehci);
+extern int	ehci_halt(struct ehci_hcd *ehci);
+extern void	ehci_tdi_reset(struct ehci_hcd *ehci);
 
 #ifdef CONFIG_PM
 extern int	ehci_suspend(struct usb_hcd *hcd, bool do_wakeup);
diff --git a/drivers/usb/otg/ulpi_viewport.c b/drivers/usb/otg/ulpi_viewport.c
index c5ba7e5..4442425 100644
--- a/drivers/usb/otg/ulpi_viewport.c
+++ b/drivers/usb/otg/ulpi_viewport.c
@@ -13,6 +13,7 @@ 
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/usb.h>
 #include <linux/io.h>
 #include <linux/usb/otg.h>
@@ -78,3 +79,4 @@  struct usb_phy_io_ops ulpi_viewport_access_ops = {
 	.read	= ulpi_viewport_read,
 	.write	= ulpi_viewport_write,
 };
+EXPORT_SYMBOL_GPL(ulpi_viewport_access_ops);