diff mbox

[5/5,v7] mfd: omap: usb: Runtime PM support

Message ID 1314196260-9578-6-git-send-email-keshava_mgowda@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Munegowda, Keshava Aug. 24, 2011, 2:31 p.m. UTC
From: Keshava Munegowda <Keshava_mgowda@ti.com>

The usbhs core driver does not enable/disable the interface and
functional clocks; These clocks are handled by hwmod and runtime pm,
hence instead of the clock enable/disable, the runtime pm APIS are
used. however,the port clocks are handled by the usbhs core.

Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
---
 arch/arm/plat-omap/include/plat/usb.h |    3 -
 drivers/mfd/omap-usb-host.c           |  731 +++++++++++++--------------------
 drivers/usb/host/ehci-omap.c          |   17 +-
 drivers/usb/host/ohci-omap3.c         |   18 +-
 4 files changed, 295 insertions(+), 474 deletions(-)

Comments

Shubhrajyoti Datta Aug. 25, 2011, 6:33 a.m. UTC | #1
Hi Keshav,
Some minor comments

On Wednesday 24 August 2011 08:01 PM, Keshava Munegowda wrote:
> From: Keshava Munegowda<Keshava_mgowda@ti.com>
>
> The usbhs core driver does not enable/disable the interface and
> functional clocks; These clocks are handled by hwmod and runtime pm,
> hence instead of the clock enable/disable, the runtime pm APIS are
> used. however,the port clocks are handled by the usbhs core.
>
> Signed-off-by: Keshava Munegowda<keshava_mgowda@ti.com>
> ---
>   arch/arm/plat-omap/include/plat/usb.h |    3 -
>   drivers/mfd/omap-usb-host.c           |  731 +++++++++++++--------------------
>   drivers/usb/host/ehci-omap.c          |   17 +-
>   drivers/usb/host/ohci-omap3.c         |   18 +-
>   4 files changed, 295 insertions(+), 474 deletions(-)
>
> diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h
> index 17d3c93..2b66dc2 100644
> --- a/arch/arm/plat-omap/include/plat/usb.h
> +++ b/arch/arm/plat-omap/include/plat/usb.h
> @@ -100,9 +100,6 @@ extern void usb_musb_init(struct omap_musb_board_data *board_data);
>
>   extern void usbhs_init(const struct usbhs_omap_board_data *pdata);
>
> -extern int omap_usbhs_enable(struct device *dev);
> -extern void omap_usbhs_disable(struct device *dev);
> -
>   extern int omap4430_phy_power(struct device *dev, int ID, int on);
>   extern int omap4430_phy_set_clk(struct device *dev, int on);
>   extern int omap4430_phy_init(struct device *dev);
> diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
> index 9c2da29..e6f3b01 100644
> --- a/drivers/mfd/omap-usb-host.c
> +++ b/drivers/mfd/omap-usb-host.c
> @@ -26,6 +26,7 @@
>   #include<linux/spinlock.h>
>   #include<linux/gpio.h>
>   #include<plat/usb.h>
> +#include<linux/pm_runtime.h>
>
>   #define USBHS_DRIVER_NAME	"usbhs_omap"
>   #define OMAP_EHCI_DEVICE	"ehci-omap"
> @@ -146,9 +147,6 @@
>
>
>   struct usbhs_hcd_omap {
> -	struct clk			*usbhost_ick;
> -	struct clk			*usbhost_hs_fck;
> -	struct clk			*usbhost_fs_fck;
>   	struct clk			*xclk60mhsp1_ck;
>   	struct clk			*xclk60mhsp2_ck;
>   	struct clk			*utmi_p1_fck;
> @@ -158,8 +156,6 @@ struct usbhs_hcd_omap {
>   	struct clk			*usbhost_p2_fck;
>   	struct clk			*usbtll_p2_fck;
>   	struct clk			*init_60m_fclk;
> -	struct clk			*usbtll_fck;
> -	struct clk			*usbtll_ick;
>
>   	void __iomem			*uhh_base;
>   	void __iomem			*tll_base;
> @@ -168,7 +164,6 @@ struct usbhs_hcd_omap {
>
>   	u32				usbhs_rev;
>   	spinlock_t			lock;
> -	int				count;
>   };
>   /*-------------------------------------------------------------------------*/
>
> @@ -318,269 +313,6 @@ err_end:
>   	return ret;
>   }
>
> -/**
> - * usbhs_omap_probe - initialize TI-based HCDs
> - *
> - * Allocates basic resources for this USB host controller.
> - */
> -static int __devinit usbhs_omap_probe(struct platform_device *pdev)
> -{
> -	struct device			*dev =&pdev->dev;
> -	struct usbhs_omap_platform_data	*pdata = dev->platform_data;
> -	struct usbhs_hcd_omap		*omap;
> -	struct resource			*res;
> -	int				ret = 0;
> -	int				i;
> -
> -	if (!pdata) {
> -		dev_err(dev, "Missing platform data\n");
> -		ret = -ENOMEM;
> -		goto end_probe;
> -	}
> -
> -	omap = kzalloc(sizeof(*omap), GFP_KERNEL);
> -	if (!omap) {
> -		dev_err(dev, "Memory allocation failed\n");
> -		ret = -ENOMEM;
> -		goto end_probe;
> -	}
> -
> -	spin_lock_init(&omap->lock);
> -
> -	for (i = 0; i<  OMAP3_HS_USB_PORTS; i++)
> -		omap->platdata.port_mode[i] = pdata->port_mode[i];
> -
> -	omap->platdata.ehci_data = pdata->ehci_data;
> -	omap->platdata.ohci_data = pdata->ohci_data;
> -
> -	omap->usbhost_ick = clk_get(dev, "usbhost_ick");
> -	if (IS_ERR(omap->usbhost_ick)) {
> -		ret =  PTR_ERR(omap->usbhost_ick);
> -		dev_err(dev, "usbhost_ick failed error:%d\n", ret);
> -		goto err_end;
> -	}
> -
> -	omap->usbhost_hs_fck = clk_get(dev, "hs_fck");
> -	if (IS_ERR(omap->usbhost_hs_fck)) {
> -		ret = PTR_ERR(omap->usbhost_hs_fck);
> -		dev_err(dev, "usbhost_hs_fck failed error:%d\n", ret);
> -		goto err_usbhost_ick;
> -	}
> -
> -	omap->usbhost_fs_fck = clk_get(dev, "fs_fck");
> -	if (IS_ERR(omap->usbhost_fs_fck)) {
> -		ret = PTR_ERR(omap->usbhost_fs_fck);
> -		dev_err(dev, "usbhost_fs_fck failed error:%d\n", ret);
> -		goto err_usbhost_hs_fck;
> -	}
> -
> -	omap->usbtll_fck = clk_get(dev, "usbtll_fck");
> -	if (IS_ERR(omap->usbtll_fck)) {
> -		ret = PTR_ERR(omap->usbtll_fck);
> -		dev_err(dev, "usbtll_fck failed error:%d\n", ret);
> -		goto err_usbhost_fs_fck;
> -	}
> -
> -	omap->usbtll_ick = clk_get(dev, "usbtll_ick");
> -	if (IS_ERR(omap->usbtll_ick)) {
> -		ret = PTR_ERR(omap->usbtll_ick);
> -		dev_err(dev, "usbtll_ick failed error:%d\n", ret);
> -		goto err_usbtll_fck;
> -	}
> -
> -	omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
> -	if (IS_ERR(omap->utmi_p1_fck)) {
> -		ret = PTR_ERR(omap->utmi_p1_fck);
> -		dev_err(dev, "utmi_p1_gfclk failed error:%d\n",	ret);
> -		goto err_usbtll_ick;
> -	}
> -
> -	omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck");
> -	if (IS_ERR(omap->xclk60mhsp1_ck)) {
> -		ret = PTR_ERR(omap->xclk60mhsp1_ck);
> -		dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret);
> -		goto err_utmi_p1_fck;
> -	}
> -
> -	omap->utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk");
> -	if (IS_ERR(omap->utmi_p2_fck)) {
> -		ret = PTR_ERR(omap->utmi_p2_fck);
> -		dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret);
> -		goto err_xclk60mhsp1_ck;
> -	}
> -
> -	omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck");
> -	if (IS_ERR(omap->xclk60mhsp2_ck)) {
> -		ret = PTR_ERR(omap->xclk60mhsp2_ck);
> -		dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret);
> -		goto err_utmi_p2_fck;
> -	}
> -
> -	omap->usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk");
> -	if (IS_ERR(omap->usbhost_p1_fck)) {
> -		ret = PTR_ERR(omap->usbhost_p1_fck);
> -		dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret);
> -		goto err_xclk60mhsp2_ck;
> -	}
> -
> -	omap->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk");
> -	if (IS_ERR(omap->usbtll_p1_fck)) {
> -		ret = PTR_ERR(omap->usbtll_p1_fck);
> -		dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret);
> -		goto err_usbhost_p1_fck;
> -	}
> -
> -	omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk");
> -	if (IS_ERR(omap->usbhost_p2_fck)) {
> -		ret = PTR_ERR(omap->usbhost_p2_fck);
> -		dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret);
> -		goto err_usbtll_p1_fck;
> -	}
> -
> -	omap->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk");
> -	if (IS_ERR(omap->usbtll_p2_fck)) {
> -		ret = PTR_ERR(omap->usbtll_p2_fck);
> -		dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret);
> -		goto err_usbhost_p2_fck;
> -	}
> -
> -	omap->init_60m_fclk = clk_get(dev, "init_60m_fclk");
> -	if (IS_ERR(omap->init_60m_fclk)) {
> -		ret = PTR_ERR(omap->init_60m_fclk);
> -		dev_err(dev, "init_60m_fclk failed error:%d\n", ret);
> -		goto err_usbtll_p2_fck;
> -	}
> -
> -	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uhh");
> -	if (!res) {
> -		dev_err(dev, "UHH EHCI get resource failed\n");
> -		ret = -ENODEV;
> -		goto err_init_60m_fclk;
> -	}
> -
> -	omap->uhh_base = ioremap(res->start, resource_size(res));
> -	if (!omap->uhh_base) {
> -		dev_err(dev, "UHH ioremap failed\n");
> -		ret = -ENOMEM;
> -		goto err_init_60m_fclk;
> -	}
> -
> -	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tll");
> -	if (!res) {
> -		dev_err(dev, "UHH EHCI get resource failed\n");
> -		ret = -ENODEV;
> -		goto err_tll;
> -	}
> -
> -	omap->tll_base = ioremap(res->start, resource_size(res));
> -	if (!omap->tll_base) {
> -		dev_err(dev, "TLL ioremap failed\n");
> -		ret = -ENOMEM;
> -		goto err_tll;
> -	}
> -
> -	platform_set_drvdata(pdev, omap);
> -
> -	ret = omap_usbhs_alloc_children(pdev);
> -	if (ret) {
> -		dev_err(dev, "omap_usbhs_alloc_children failed\n");
> -		goto err_alloc;
> -	}
> -
> -	goto end_probe;
> -
> -err_alloc:
> -	iounmap(omap->tll_base);
> -
> -err_tll:
> -	iounmap(omap->uhh_base);
> -
> -err_init_60m_fclk:
> -	clk_put(omap->init_60m_fclk);
> -
> -err_usbtll_p2_fck:
> -	clk_put(omap->usbtll_p2_fck);
> -
> -err_usbhost_p2_fck:
> -	clk_put(omap->usbhost_p2_fck);
> -
> -err_usbtll_p1_fck:
> -	clk_put(omap->usbtll_p1_fck);
> -
> -err_usbhost_p1_fck:
> -	clk_put(omap->usbhost_p1_fck);
> -
> -err_xclk60mhsp2_ck:
> -	clk_put(omap->xclk60mhsp2_ck);
> -
> -err_utmi_p2_fck:
> -	clk_put(omap->utmi_p2_fck);
> -
> -err_xclk60mhsp1_ck:
> -	clk_put(omap->xclk60mhsp1_ck);
> -
> -err_utmi_p1_fck:
> -	clk_put(omap->utmi_p1_fck);
> -
> -err_usbtll_ick:
> -	clk_put(omap->usbtll_ick);
> -
> -err_usbtll_fck:
> -	clk_put(omap->usbtll_fck);
> -
> -err_usbhost_fs_fck:
> -	clk_put(omap->usbhost_fs_fck);
> -
> -err_usbhost_hs_fck:
> -	clk_put(omap->usbhost_hs_fck);
> -
> -err_usbhost_ick:
> -	clk_put(omap->usbhost_ick);
> -
> -err_end:
> -	kfree(omap);
> -
> -end_probe:
> -	return ret;
> -}
> -
> -/**
> - * usbhs_omap_remove - shutdown processing for UHH&  TLL HCDs
> - * @pdev: USB Host Controller being removed
> - *
> - * Reverses the effect of usbhs_omap_probe().
> - */
> -static int __devexit usbhs_omap_remove(struct platform_device *pdev)
> -{
> -	struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
> -
> -	if (omap->count != 0) {
> -		dev_err(&pdev->dev,
> -			"Either EHCI or OHCI is still using usbhs core\n");
> -		return -EBUSY;
> -	}
> -
> -	iounmap(omap->tll_base);
> -	iounmap(omap->uhh_base);
> -	clk_put(omap->init_60m_fclk);
> -	clk_put(omap->usbtll_p2_fck);
> -	clk_put(omap->usbhost_p2_fck);
> -	clk_put(omap->usbtll_p1_fck);
> -	clk_put(omap->usbhost_p1_fck);
> -	clk_put(omap->xclk60mhsp2_ck);
> -	clk_put(omap->utmi_p2_fck);
> -	clk_put(omap->xclk60mhsp1_ck);
> -	clk_put(omap->utmi_p1_fck);
> -	clk_put(omap->usbtll_ick);
> -	clk_put(omap->usbtll_fck);
> -	clk_put(omap->usbhost_fs_fck);
> -	clk_put(omap->usbhost_hs_fck);
> -	clk_put(omap->usbhost_ick);
> -	kfree(omap);
> -
> -	return 0;
> -}
> -
>   static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
>   {
>   	switch (pmode) {
> @@ -687,30 +419,79 @@ static void usbhs_omap_tll_init(struct device *dev, u8 tll_channel_count)
>   	}
>   }
>
> -static int usbhs_enable(struct device *dev)
> +static int usbhs_runtime_resume(struct device *dev)
>   {
>   	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
>   	struct usbhs_omap_platform_data	*pdata =&omap->platdata;
> -	unsigned long			flags = 0;
> -	int				ret = 0;
> -	unsigned long			timeout;
> -	unsigned			reg;
> +	unsigned long			flags;
> +
> +	dev_dbg(dev, "usbhs_runtime_resume\n");
> +
> +	if (!pdata) {
> +		dev_dbg(dev, "missing platform_data\n");
> +		return  -ENODEV;
> +	}
> +
> +	spin_lock_irqsave(&omap->lock, flags);
> +
> +	if (is_ehci_tll_mode(pdata->port_mode[0])) {
> +		clk_enable(omap->usbhost_p1_fck);
> +		clk_enable(omap->usbtll_p1_fck);
> +	}
> +	if (is_ehci_tll_mode(pdata->port_mode[1])) {
> +		clk_enable(omap->usbhost_p2_fck);
> +		clk_enable(omap->usbtll_p2_fck);
> +	}
> +	clk_enable(omap->utmi_p1_fck);
> +	clk_enable(omap->utmi_p2_fck);
> +
> +	spin_unlock_irqrestore(&omap->lock, flags);
> +
> +	return 0;
> +}
> +
> +static int usbhs_runtime_suspend(struct device *dev)
> +{
> +	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
> +	struct usbhs_omap_platform_data	*pdata =&omap->platdata;
> +	unsigned long			flags;
> +
> +	dev_dbg(dev, "usbhs_runtime_suspend\n");
>
> -	dev_dbg(dev, "starting TI HSUSB Controller\n");
>   	if (!pdata) {
>   		dev_dbg(dev, "missing platform_data\n");
>   		return  -ENODEV;
>   	}
>
>   	spin_lock_irqsave(&omap->lock, flags);
> -	if (omap->count>  0)
> -		goto end_count;
>
> -	clk_enable(omap->usbhost_ick);
> -	clk_enable(omap->usbhost_hs_fck);
> -	clk_enable(omap->usbhost_fs_fck);
> -	clk_enable(omap->usbtll_fck);
> -	clk_enable(omap->usbtll_ick);
> +	if (is_ehci_tll_mode(pdata->port_mode[0])) {
> +		clk_disable(omap->usbhost_p1_fck);
> +		clk_disable(omap->usbtll_p1_fck);
> +	}
> +	if (is_ehci_tll_mode(pdata->port_mode[1])) {
> +		clk_disable(omap->usbhost_p2_fck);
> +		clk_disable(omap->usbtll_p2_fck);
> +	}
> +	clk_disable(omap->utmi_p2_fck);
> +	clk_disable(omap->utmi_p1_fck);
> +
> +	spin_unlock_irqrestore(&omap->lock, flags);
> +
> +	return 0;
> +}
> +
> +static void omap_usbhs_init(struct device *dev)
Since it is called only at init the it could be placed in init section.
> +{
> +	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
> +	struct usbhs_omap_platform_data	*pdata =&omap->platdata;
> +	unsigned long			flags;
> +	unsigned			reg;
> +
> +	dev_dbg(dev, "starting TI HSUSB Controller\n");
> +
> +	pm_runtime_get_sync(dev);
> +	spin_lock_irqsave(&omap->lock, flags);
>
>   	if (pdata->ehci_data->phy_reset) {
>   		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) {
> @@ -734,50 +515,6 @@ static int usbhs_enable(struct device *dev)
>   	omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
>   	dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);
>
> -	/* perform TLL soft reset, and wait until reset is complete */
> -	usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
> -			OMAP_USBTLL_SYSCONFIG_SOFTRESET);
> -
> -	/* Wait for TLL reset to complete */
> -	timeout = jiffies + msecs_to_jiffies(1000);
> -	while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
> -			&  OMAP_USBTLL_SYSSTATUS_RESETDONE)) {
> -		cpu_relax();
> -
> -		if (time_after(jiffies, timeout)) {
> -			dev_dbg(dev, "operation timed out\n");
> -			ret = -EINVAL;
> -			goto err_tll;
> -		}
> -	}
> -
> -	dev_dbg(dev, "TLL RESET DONE\n");
> -
> -	/* (1<<3) = no idle mode only for initial debugging */
> -	usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
> -			OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
> -			OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
> -			OMAP_USBTLL_SYSCONFIG_AUTOIDLE);
> -
> -	/* Put UHH in NoIdle/NoStandby mode */
> -	reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG);
> -	if (is_omap_usbhs_rev1(omap)) {
> -		reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
> -				| OMAP_UHH_SYSCONFIG_SIDLEMODE
> -				| OMAP_UHH_SYSCONFIG_CACTIVITY
> -				| OMAP_UHH_SYSCONFIG_MIDLEMODE);
> -		reg&= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
> -
> -
> -	} else if (is_omap_usbhs_rev2(omap)) {
> -		reg&= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR;
> -		reg |= OMAP4_UHH_SYSCONFIG_NOIDLE;
> -		reg&= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR;
> -		reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY;
> -	}
> -
> -	usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
> -
>   	reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
>   	/* setup ULPI bypass and burst configurations */
>   	reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
> @@ -823,49 +560,6 @@ static int usbhs_enable(struct device *dev)
>   		reg&= ~OMAP4_P1_MODE_CLEAR;
>   		reg&= ~OMAP4_P2_MODE_CLEAR;
>
> -		if (is_ehci_phy_mode(pdata->port_mode[0])) {
> -			ret = clk_set_parent(omap->utmi_p1_fck,
> -						omap->xclk60mhsp1_ck);
> -			if (ret != 0) {
> -				dev_err(dev, "xclk60mhsp1_ck set parent"
> -				"failed error:%d\n", ret);
> -				goto err_tll;
> -			}
> -		} else if (is_ehci_tll_mode(pdata->port_mode[0])) {
> -			ret = clk_set_parent(omap->utmi_p1_fck,
> -						omap->init_60m_fclk);
> -			if (ret != 0) {
> -				dev_err(dev, "init_60m_fclk set parent"
> -				"failed error:%d\n", ret);
> -				goto err_tll;
> -			}
> -			clk_enable(omap->usbhost_p1_fck);
> -			clk_enable(omap->usbtll_p1_fck);
> -		}
> -
> -		if (is_ehci_phy_mode(pdata->port_mode[1])) {
> -			ret = clk_set_parent(omap->utmi_p2_fck,
> -						omap->xclk60mhsp2_ck);
> -			if (ret != 0) {
> -				dev_err(dev, "xclk60mhsp1_ck set parent"
> -					"failed error:%d\n", ret);
> -				goto err_tll;
> -			}
> -		} else if (is_ehci_tll_mode(pdata->port_mode[1])) {
> -			ret = clk_set_parent(omap->utmi_p2_fck,
> -						omap->init_60m_fclk);
> -			if (ret != 0) {
> -				dev_err(dev, "init_60m_fclk set parent"
> -				"failed error:%d\n", ret);
> -				goto err_tll;
> -			}
> -			clk_enable(omap->usbhost_p2_fck);
> -			clk_enable(omap->usbtll_p2_fck);
> -		}
> -
> -		clk_enable(omap->utmi_p1_fck);
> -		clk_enable(omap->utmi_p2_fck);
> -
>   		if (is_ehci_tll_mode(pdata->port_mode[0]) ||
>   			(is_ohci_port(pdata->port_mode[0])))
>   			reg |= OMAP4_P1_MODE_TLL;
> @@ -911,12 +605,15 @@ static int usbhs_enable(struct device *dev)
>   				(pdata->ehci_data->reset_gpio_port[1], 1);
>   	}
>
> -end_count:
> -	omap->count++;
>   	spin_unlock_irqrestore(&omap->lock, flags);
> -	return 0;
> +	pm_runtime_put_sync(dev);
> +}
> +
> +static void omap_usbhs_deinit(struct device *dev)
> +{
> +	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
> +	struct usbhs_omap_platform_data	*pdata =&omap->platdata;
>
> -err_tll:
>   	if (pdata->ehci_data->phy_reset) {
>   		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
>   			gpio_free(pdata->ehci_data->reset_gpio_port[0]);
> @@ -924,123 +621,257 @@ err_tll:
>   		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
>   			gpio_free(pdata->ehci_data->reset_gpio_port[1]);
>   	}
> -
> -	clk_disable(omap->usbtll_ick);
> -	clk_disable(omap->usbtll_fck);
> -	clk_disable(omap->usbhost_fs_fck);
> -	clk_disable(omap->usbhost_hs_fck);
> -	clk_disable(omap->usbhost_ick);
> -	spin_unlock_irqrestore(&omap->lock, flags);
> -	return ret;
>   }
>
> -static void usbhs_disable(struct device *dev)
> +
> +/**
> + * usbhs_omap_probe - initialize TI-based HCDs
> + *
> + * Allocates basic resources for this USB host controller.
> + */
> +static int __devinit usbhs_omap_probe(struct platform_device *pdev)
>   {
> -	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
> -	struct usbhs_omap_platform_data	*pdata =&omap->platdata;
> -	unsigned long			flags = 0;
> -	unsigned long			timeout;
> +	struct device			*dev =&pdev->dev;
> +	struct usbhs_omap_platform_data	*pdata = dev->platform_data;
> +	struct usbhs_hcd_omap		*omap;
> +	struct resource			*res;
> +	int				ret = 0;
> +	int				i;
>
> -	dev_dbg(dev, "stopping TI HSUSB Controller\n");
> +	if (!pdata) {
> +		dev_err(dev, "Missing platform data\n");
> +		ret = -ENOMEM;
> +		goto end_probe;
> +	}
>
> -	spin_lock_irqsave(&omap->lock, flags);
> +	omap = kzalloc(sizeof(*omap), GFP_KERNEL);
> +	if (!omap) {
> +		dev_err(dev, "Memory allocation failed\n");
> +		ret = -ENOMEM;
> +		goto end_probe;
> +	}
>
> -	if (omap->count == 0)
> -		goto end_disble;
> +	spin_lock_init(&omap->lock);
>
> -	omap->count--;
> +	for (i = 0; i<  OMAP3_HS_USB_PORTS; i++)
> +		omap->platdata.port_mode[i] = pdata->port_mode[i];
>
> -	if (omap->count != 0)
> -		goto end_disble;
> +	omap->platdata.ehci_data = pdata->ehci_data;
> +	omap->platdata.ohci_data = pdata->ohci_data;
>
> -	/* Reset OMAP modules for insmod/rmmod to work */
> -	usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG,
> -			is_omap_usbhs_rev2(omap) ?
> -			OMAP4_UHH_SYSCONFIG_SOFTRESET :
> -			OMAP_UHH_SYSCONFIG_SOFTRESET);
> +	pm_runtime_enable(dev);
>
> -	timeout = jiffies + msecs_to_jiffies(100);
> -	while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS)
> -				&  (1<<  0))) {
> -		cpu_relax();
> +	omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
> +	if (IS_ERR(omap->utmi_p1_fck)) {
> +		ret = PTR_ERR(omap->utmi_p1_fck);
> +		dev_err(dev, "utmi_p1_gfclk failed error:%d\n",	ret);
> +		goto err_end;
> +	}
>
> -		if (time_after(jiffies, timeout))
> -			dev_dbg(dev, "operation timed out\n");
> +	omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck");
> +	if (IS_ERR(omap->xclk60mhsp1_ck)) {
> +		ret = PTR_ERR(omap->xclk60mhsp1_ck);
> +		dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret);
> +		goto err_utmi_p1_fck;
> +	}
> +
> +	omap->utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk");
> +	if (IS_ERR(omap->utmi_p2_fck)) {
> +		ret = PTR_ERR(omap->utmi_p2_fck);
> +		dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret);
> +		goto err_xclk60mhsp1_ck;
> +	}
> +
> +	omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck");
> +	if (IS_ERR(omap->xclk60mhsp2_ck)) {
> +		ret = PTR_ERR(omap->xclk60mhsp2_ck);
> +		dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret);
> +		goto err_utmi_p2_fck;
>   	}
>
> -	while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS)
> -				&  (1<<  1))) {
> -		cpu_relax();
> +	omap->usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk");
> +	if (IS_ERR(omap->usbhost_p1_fck)) {
> +		ret = PTR_ERR(omap->usbhost_p1_fck);
> +		dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret);
> +		goto err_xclk60mhsp2_ck;
> +	}
>
> -		if (time_after(jiffies, timeout))
> -			dev_dbg(dev, "operation timed out\n");
> +	omap->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk");
> +	if (IS_ERR(omap->usbtll_p1_fck)) {
> +		ret = PTR_ERR(omap->usbtll_p1_fck);
> +		dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret);
> +		goto err_usbhost_p1_fck;
> +	}
> +
> +	omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk");
> +	if (IS_ERR(omap->usbhost_p2_fck)) {
> +		ret = PTR_ERR(omap->usbhost_p2_fck);
> +		dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret);
> +		goto err_usbtll_p1_fck;
>   	}
>
> -	while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS)
> -				&  (1<<  2))) {
> -		cpu_relax();
> +	omap->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk");
> +	if (IS_ERR(omap->usbtll_p2_fck)) {
> +		ret = PTR_ERR(omap->usbtll_p2_fck);
> +		dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret);
> +		goto err_usbhost_p2_fck;
> +	}
>
> -		if (time_after(jiffies, timeout))
> -			dev_dbg(dev, "operation timed out\n");
> +	omap->init_60m_fclk = clk_get(dev, "init_60m_fclk");
> +	if (IS_ERR(omap->init_60m_fclk)) {
> +		ret = PTR_ERR(omap->init_60m_fclk);
> +		dev_err(dev, "init_60m_fclk failed error:%d\n", ret);
> +		goto err_usbtll_p2_fck;
>   	}
>
> -	usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1<<  1));
> +	if (is_ehci_phy_mode(pdata->port_mode[0])) {
> +		/* for OMAP3 , the clk set paretn fails */
> +		ret = clk_set_parent(omap->utmi_p1_fck,
> +					omap->xclk60mhsp1_ck);
> +		if (ret != 0)
> +			dev_err(dev, "xclk60mhsp1_ck set parent"
> +				"failed error:%d\n", ret);
> +	} else if (is_ehci_tll_mode(pdata->port_mode[0])) {
> +		ret = clk_set_parent(omap->utmi_p1_fck,
> +					omap->init_60m_fclk);
> +		if (ret != 0)
> +			dev_err(dev, "init_60m_fclk set parent"
> +				"failed error:%d\n", ret);
> +	}
>
> -	while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
> -				&  (1<<  0))) {
> -		cpu_relax();
> +	if (is_ehci_phy_mode(pdata->port_mode[1])) {
> +		ret = clk_set_parent(omap->utmi_p2_fck,
> +					omap->xclk60mhsp2_ck);
> +		if (ret != 0)
> +			dev_err(dev, "xclk60mhsp2_ck set parent"
> +					"failed error:%d\n", ret);
> +	} else if (is_ehci_tll_mode(pdata->port_mode[1])) {
> +		ret = clk_set_parent(omap->utmi_p2_fck,
> +						omap->init_60m_fclk);
> +		if (ret != 0)
> +			dev_err(dev, "init_60m_fclk set parent"
> +				"failed error:%d\n", ret);
> +	}
>
> -		if (time_after(jiffies, timeout))
> -			dev_dbg(dev, "operation timed out\n");
> +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uhh");
> +	if (!res) {
> +		dev_err(dev, "UHH EHCI get resource failed\n");
> +		ret = -ENODEV;
> +		goto err_init_60m_fclk;
>   	}
>
> -	if (is_omap_usbhs_rev2(omap)) {
> -		if (is_ehci_tll_mode(pdata->port_mode[0]))
> -			clk_disable(omap->usbtll_p1_fck);
> -		if (is_ehci_tll_mode(pdata->port_mode[1]))
> -			clk_disable(omap->usbtll_p2_fck);
> -		clk_disable(omap->utmi_p2_fck);
> -		clk_disable(omap->utmi_p1_fck);
> +	omap->uhh_base = ioremap(res->start, resource_size(res));
> +	if (!omap->uhh_base) {
> +		dev_err(dev, "UHH ioremap failed\n");
> +		ret = -ENOMEM;
> +		goto err_init_60m_fclk;
>   	}
>
> -	clk_disable(omap->usbtll_ick);
> -	clk_disable(omap->usbtll_fck);
> -	clk_disable(omap->usbhost_fs_fck);
> -	clk_disable(omap->usbhost_hs_fck);
> -	clk_disable(omap->usbhost_ick);
> +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tll");
> +	if (!res) {
> +		dev_err(dev, "UHH EHCI get resource failed\n");
> +		ret = -ENODEV;
> +		goto err_tll;
> +	}
>
> -	/* The gpio_free migh sleep; so unlock the spinlock */
> -	spin_unlock_irqrestore(&omap->lock, flags);
> +	omap->tll_base = ioremap(res->start, resource_size(res));
> +	if (!omap->tll_base) {
> +		dev_err(dev, "TLL ioremap failed\n");
> +		ret = -ENOMEM;
> +		goto err_tll;
> +	}
>
> -	if (pdata->ehci_data->phy_reset) {
> -		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
> -			gpio_free(pdata->ehci_data->reset_gpio_port[0]);
> +	platform_set_drvdata(pdev, omap);
>
> -		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
> -			gpio_free(pdata->ehci_data->reset_gpio_port[1]);
> +	ret = omap_usbhs_alloc_children(pdev);
> +	if (ret) {
> +		dev_err(dev, "omap_usbhs_alloc_children failed\n");
> +		goto err_alloc;
>   	}
> -	return;
>
> -end_disble:
> -	spin_unlock_irqrestore(&omap->lock, flags);
> -}
> +	omap_usbhs_init(dev);
>
> -int omap_usbhs_enable(struct device *dev)
> -{
> -	return  usbhs_enable(dev->parent);
> +	goto end_probe;
> +
> +err_alloc:
> +	iounmap(omap->tll_base);
> +
> +err_tll:
> +	iounmap(omap->uhh_base);
> +
> +err_init_60m_fclk:
> +	clk_put(omap->init_60m_fclk);
> +
> +err_usbtll_p2_fck:
> +	clk_put(omap->usbtll_p2_fck);
> +
> +err_usbhost_p2_fck:
> +	clk_put(omap->usbhost_p2_fck);
> +
> +err_usbtll_p1_fck:
> +	clk_put(omap->usbtll_p1_fck);
> +
> +err_usbhost_p1_fck:
> +	clk_put(omap->usbhost_p1_fck);
> +
> +err_xclk60mhsp2_ck:
> +	clk_put(omap->xclk60mhsp2_ck);
> +
> +err_utmi_p2_fck:
> +	clk_put(omap->utmi_p2_fck);
> +
> +err_xclk60mhsp1_ck:
> +	clk_put(omap->xclk60mhsp1_ck);
> +
> +err_utmi_p1_fck:
> +	clk_put(omap->utmi_p1_fck);
> +
> +err_end:
> +	pm_runtime_disable(dev);
> +	kfree(omap);
> +
> +end_probe:
> +	return ret;
>   }
> -EXPORT_SYMBOL_GPL(omap_usbhs_enable);
>
> -void omap_usbhs_disable(struct device *dev)
> +/**
> + * usbhs_omap_remove - shutdown processing for UHH&  TLL HCDs
> + * @pdev: USB Host Controller being removed
> + *
> + * Reverses the effect of usbhs_omap_probe().
> + */
> +static int __devexit usbhs_omap_remove(struct platform_device *pdev)
>   {
> -	usbhs_disable(dev->parent);
> +	struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
> +
> +	omap_usbhs_deinit(&pdev->dev);
> +	iounmap(omap->tll_base);
> +	iounmap(omap->uhh_base);
> +	clk_put(omap->init_60m_fclk);
> +	clk_put(omap->usbtll_p2_fck);
> +	clk_put(omap->usbhost_p2_fck);
> +	clk_put(omap->usbtll_p1_fck);
> +	clk_put(omap->usbhost_p1_fck);
> +	clk_put(omap->xclk60mhsp2_ck);
> +	clk_put(omap->utmi_p2_fck);
> +	clk_put(omap->xclk60mhsp1_ck);
> +	clk_put(omap->utmi_p1_fck);
> +	pm_runtime_disable(&pdev->dev);
> +	kfree(omap);
> +
> +	return 0;
>   }
> -EXPORT_SYMBOL_GPL(omap_usbhs_disable);
> +
> +static const struct dev_pm_ops usbhsomap_dev_pm_ops = {
> +	.runtime_suspend	= usbhs_runtime_suspend,
> +	.runtime_resume		= usbhs_runtime_resume,
> +};
Could these be placed under a PM flag.

>
>   static struct platform_driver usbhs_omap_driver = {
>   	.driver = {
>   		.name		= (char *)usbhs_driver_name,
>   		.owner		= THIS_MODULE,
> +		.pm		=&usbhsomap_dev_pm_ops,
>   	},
>   	.remove		= __exit_p(usbhs_omap_remove),
>   };
> diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
> index 4524032..82cd3ea 100644
> --- a/drivers/usb/host/ehci-omap.c
> +++ b/drivers/usb/host/ehci-omap.c
> @@ -41,6 +41,7 @@
>   #include<linux/usb/ulpi.h>
>   #include<plat/usb.h>
>   #include<linux/regulator/consumer.h>
> +#include<linux/pm_runtime.h>
>
>   /* EHCI Register Set */
>   #define EHCI_INSNREG04					(0xA0)
> @@ -190,11 +191,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
>   		}
>   	}
>
> -	ret = omap_usbhs_enable(dev);
> -	if (ret) {
> -		dev_err(dev, "failed to start usbhs with err %d\n", ret);
> -		goto err_enable;
> -	}
> +	pm_runtime_enable(dev);
> +	pm_runtime_get_sync(dev);
>
>   	/*
>   	 * An undocumented "feature" in the OMAP3 EHCI controller,
> @@ -240,11 +238,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
>   	return 0;
>
>   err_add_hcd:
> -	omap_usbhs_disable(dev);
> -
> -err_enable:
>   	disable_put_regulator(pdata);
> -	usb_put_hcd(hcd);
> +	pm_runtime_put_sync(dev);
>
>   err_io:
>   	iounmap(regs);
> @@ -266,10 +261,12 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev)
>   	struct usb_hcd *hcd	= dev_get_drvdata(dev);
>
>   	usb_remove_hcd(hcd);
> -	omap_usbhs_disable(dev);
>   	disable_put_regulator(dev->platform_data);
>   	iounmap(hcd->regs);
>   	usb_put_hcd(hcd);
> +	pm_runtime_put_sync(dev);
> +	pm_runtime_disable(dev);
> +
>   	return 0;
>   }
>
> diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
> index 6048f2f..6cfedaf 100644
> --- a/drivers/usb/host/ohci-omap3.c
> +++ b/drivers/usb/host/ohci-omap3.c
> @@ -31,6 +31,7 @@
>
>   #include<linux/platform_device.h>
>   #include<plat/usb.h>
> +#include<linux/pm_runtime.h>
>
>   /*-------------------------------------------------------------------------*/
>
> @@ -134,7 +135,7 @@ static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev)
>   	int			irq;
>
>   	if (usb_disabled())
> -		goto err_end;
> +		return -ENODEV;
>
>   	if (!dev->parent) {
>   		dev_err(dev, "Missing parent device\n");
> @@ -172,11 +173,8 @@ static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev)
>   	hcd->rsrc_len = resource_size(res);
>   	hcd->regs =  regs;
>
> -	ret = omap_usbhs_enable(dev);
> -	if (ret) {
> -		dev_dbg(dev, "failed to start ohci\n");
> -		goto err_end;
> -	}
> +	pm_runtime_enable(dev);
> +	pm_runtime_get_sync(dev);
>
>   	ohci_hcd_init(hcd_to_ohci(hcd));
>
> @@ -189,9 +187,7 @@ static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev)
>   	return 0;
>
>   err_add_hcd:
> -	omap_usbhs_disable(dev);
> -
> -err_end:
> +	pm_runtime_put_sync(dev);
>   	usb_put_hcd(hcd);
>
>   err_io:
> @@ -220,9 +216,9 @@ static int __devexit ohci_hcd_omap3_remove(struct platform_device *pdev)
>
>   	iounmap(hcd->regs);
>   	usb_remove_hcd(hcd);
> -	omap_usbhs_disable(dev);
> +	pm_runtime_put_sync(dev);
> +	pm_runtime_disable(dev);
>   	usb_put_hcd(hcd);
> -
>   	return 0;
>   }
>

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Munegowda, Keshava Aug. 25, 2011, 6:38 a.m. UTC | #2
On Thu, Aug 25, 2011 at 12:03 PM, Shubhrajyoti <shubhrajyoti@ti.com> wrote:
> Hi Keshav,
> Some minor comments
>
> On Wednesday 24 August 2011 08:01 PM, Keshava Munegowda wrote:
>>
>> From: Keshava Munegowda<Keshava_mgowda@ti.com>
>>
>> The usbhs core driver does not enable/disable the interface and
>> functional clocks; These clocks are handled by hwmod and runtime pm,
>> hence instead of the clock enable/disable, the runtime pm APIS are
>> used. however,the port clocks are handled by the usbhs core.
>>
>> Signed-off-by: Keshava Munegowda<keshava_mgowda@ti.com>
>> ---
>>  arch/arm/plat-omap/include/plat/usb.h |    3 -
>>  drivers/mfd/omap-usb-host.c           |  731
>> +++++++++++++--------------------
>>  drivers/usb/host/ehci-omap.c          |   17 +-
>>  drivers/usb/host/ohci-omap3.c         |   18 +-
>>  4 files changed, 295 insertions(+), 474 deletions(-)
>>
>> diff --git a/arch/arm/plat-omap/include/plat/usb.h
>> b/arch/arm/plat-omap/include/plat/usb.h
>> index 17d3c93..2b66dc2 100644
>> --- a/arch/arm/plat-omap/include/plat/usb.h
>> +++ b/arch/arm/plat-omap/include/plat/usb.h
>> @@ -100,9 +100,6 @@ extern void usb_musb_init(struct omap_musb_board_data
>> *board_data);
>>
>>  extern void usbhs_init(const struct usbhs_omap_board_data *pdata);
>>
>> -extern int omap_usbhs_enable(struct device *dev);
>> -extern void omap_usbhs_disable(struct device *dev);
>> -
>>  extern int omap4430_phy_power(struct device *dev, int ID, int on);
>>  extern int omap4430_phy_set_clk(struct device *dev, int on);
>>  extern int omap4430_phy_init(struct device *dev);
>> diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
>> index 9c2da29..e6f3b01 100644
>> --- a/drivers/mfd/omap-usb-host.c
>> +++ b/drivers/mfd/omap-usb-host.c
>> @@ -26,6 +26,7 @@
>>  #include<linux/spinlock.h>
>>  #include<linux/gpio.h>
>>  #include<plat/usb.h>
>> +#include<linux/pm_runtime.h>
>>
>>  #define USBHS_DRIVER_NAME     "usbhs_omap"
>>  #define OMAP_EHCI_DEVICE      "ehci-omap"
>> @@ -146,9 +147,6 @@
>>
>>
>>  struct usbhs_hcd_omap {
>> -       struct clk                      *usbhost_ick;
>> -       struct clk                      *usbhost_hs_fck;
>> -       struct clk                      *usbhost_fs_fck;
>>        struct clk                      *xclk60mhsp1_ck;
>>        struct clk                      *xclk60mhsp2_ck;
>>        struct clk                      *utmi_p1_fck;
>> @@ -158,8 +156,6 @@ struct usbhs_hcd_omap {
>>        struct clk                      *usbhost_p2_fck;
>>        struct clk                      *usbtll_p2_fck;
>>        struct clk                      *init_60m_fclk;
>> -       struct clk                      *usbtll_fck;
>> -       struct clk                      *usbtll_ick;
>>
>>        void __iomem                    *uhh_base;
>>        void __iomem                    *tll_base;
>> @@ -168,7 +164,6 @@ struct usbhs_hcd_omap {
>>
>>        u32                             usbhs_rev;
>>        spinlock_t                      lock;
>> -       int                             count;
>>  };
>>
>>  /*-------------------------------------------------------------------------*/
>>
>> @@ -318,269 +313,6 @@ err_end:
>>        return ret;
>>  }
>>
>> -/**
>> - * usbhs_omap_probe - initialize TI-based HCDs
>> - *
>> - * Allocates basic resources for this USB host controller.
>> - */
>> -static int __devinit usbhs_omap_probe(struct platform_device *pdev)
>> -{
>> -       struct device                   *dev =&pdev->dev;
>> -       struct usbhs_omap_platform_data *pdata = dev->platform_data;
>> -       struct usbhs_hcd_omap           *omap;
>> -       struct resource                 *res;
>> -       int                             ret = 0;
>> -       int                             i;
>> -
>> -       if (!pdata) {
>> -               dev_err(dev, "Missing platform data\n");
>> -               ret = -ENOMEM;
>> -               goto end_probe;
>> -       }
>> -
>> -       omap = kzalloc(sizeof(*omap), GFP_KERNEL);
>> -       if (!omap) {
>> -               dev_err(dev, "Memory allocation failed\n");
>> -               ret = -ENOMEM;
>> -               goto end_probe;
>> -       }
>> -
>> -       spin_lock_init(&omap->lock);
>> -
>> -       for (i = 0; i<  OMAP3_HS_USB_PORTS; i++)
>> -               omap->platdata.port_mode[i] = pdata->port_mode[i];
>> -
>> -       omap->platdata.ehci_data = pdata->ehci_data;
>> -       omap->platdata.ohci_data = pdata->ohci_data;
>> -
>> -       omap->usbhost_ick = clk_get(dev, "usbhost_ick");
>> -       if (IS_ERR(omap->usbhost_ick)) {
>> -               ret =  PTR_ERR(omap->usbhost_ick);
>> -               dev_err(dev, "usbhost_ick failed error:%d\n", ret);
>> -               goto err_end;
>> -       }
>> -
>> -       omap->usbhost_hs_fck = clk_get(dev, "hs_fck");
>> -       if (IS_ERR(omap->usbhost_hs_fck)) {
>> -               ret = PTR_ERR(omap->usbhost_hs_fck);
>> -               dev_err(dev, "usbhost_hs_fck failed error:%d\n", ret);
>> -               goto err_usbhost_ick;
>> -       }
>> -
>> -       omap->usbhost_fs_fck = clk_get(dev, "fs_fck");
>> -       if (IS_ERR(omap->usbhost_fs_fck)) {
>> -               ret = PTR_ERR(omap->usbhost_fs_fck);
>> -               dev_err(dev, "usbhost_fs_fck failed error:%d\n", ret);
>> -               goto err_usbhost_hs_fck;
>> -       }
>> -
>> -       omap->usbtll_fck = clk_get(dev, "usbtll_fck");
>> -       if (IS_ERR(omap->usbtll_fck)) {
>> -               ret = PTR_ERR(omap->usbtll_fck);
>> -               dev_err(dev, "usbtll_fck failed error:%d\n", ret);
>> -               goto err_usbhost_fs_fck;
>> -       }
>> -
>> -       omap->usbtll_ick = clk_get(dev, "usbtll_ick");
>> -       if (IS_ERR(omap->usbtll_ick)) {
>> -               ret = PTR_ERR(omap->usbtll_ick);
>> -               dev_err(dev, "usbtll_ick failed error:%d\n", ret);
>> -               goto err_usbtll_fck;
>> -       }
>> -
>> -       omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
>> -       if (IS_ERR(omap->utmi_p1_fck)) {
>> -               ret = PTR_ERR(omap->utmi_p1_fck);
>> -               dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret);
>> -               goto err_usbtll_ick;
>> -       }
>> -
>> -       omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck");
>> -       if (IS_ERR(omap->xclk60mhsp1_ck)) {
>> -               ret = PTR_ERR(omap->xclk60mhsp1_ck);
>> -               dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret);
>> -               goto err_utmi_p1_fck;
>> -       }
>> -
>> -       omap->utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk");
>> -       if (IS_ERR(omap->utmi_p2_fck)) {
>> -               ret = PTR_ERR(omap->utmi_p2_fck);
>> -               dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret);
>> -               goto err_xclk60mhsp1_ck;
>> -       }
>> -
>> -       omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck");
>> -       if (IS_ERR(omap->xclk60mhsp2_ck)) {
>> -               ret = PTR_ERR(omap->xclk60mhsp2_ck);
>> -               dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret);
>> -               goto err_utmi_p2_fck;
>> -       }
>> -
>> -       omap->usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk");
>> -       if (IS_ERR(omap->usbhost_p1_fck)) {
>> -               ret = PTR_ERR(omap->usbhost_p1_fck);
>> -               dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret);
>> -               goto err_xclk60mhsp2_ck;
>> -       }
>> -
>> -       omap->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk");
>> -       if (IS_ERR(omap->usbtll_p1_fck)) {
>> -               ret = PTR_ERR(omap->usbtll_p1_fck);
>> -               dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret);
>> -               goto err_usbhost_p1_fck;
>> -       }
>> -
>> -       omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk");
>> -       if (IS_ERR(omap->usbhost_p2_fck)) {
>> -               ret = PTR_ERR(omap->usbhost_p2_fck);
>> -               dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret);
>> -               goto err_usbtll_p1_fck;
>> -       }
>> -
>> -       omap->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk");
>> -       if (IS_ERR(omap->usbtll_p2_fck)) {
>> -               ret = PTR_ERR(omap->usbtll_p2_fck);
>> -               dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret);
>> -               goto err_usbhost_p2_fck;
>> -       }
>> -
>> -       omap->init_60m_fclk = clk_get(dev, "init_60m_fclk");
>> -       if (IS_ERR(omap->init_60m_fclk)) {
>> -               ret = PTR_ERR(omap->init_60m_fclk);
>> -               dev_err(dev, "init_60m_fclk failed error:%d\n", ret);
>> -               goto err_usbtll_p2_fck;
>> -       }
>> -
>> -       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uhh");
>> -       if (!res) {
>> -               dev_err(dev, "UHH EHCI get resource failed\n");
>> -               ret = -ENODEV;
>> -               goto err_init_60m_fclk;
>> -       }
>> -
>> -       omap->uhh_base = ioremap(res->start, resource_size(res));
>> -       if (!omap->uhh_base) {
>> -               dev_err(dev, "UHH ioremap failed\n");
>> -               ret = -ENOMEM;
>> -               goto err_init_60m_fclk;
>> -       }
>> -
>> -       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tll");
>> -       if (!res) {
>> -               dev_err(dev, "UHH EHCI get resource failed\n");
>> -               ret = -ENODEV;
>> -               goto err_tll;
>> -       }
>> -
>> -       omap->tll_base = ioremap(res->start, resource_size(res));
>> -       if (!omap->tll_base) {
>> -               dev_err(dev, "TLL ioremap failed\n");
>> -               ret = -ENOMEM;
>> -               goto err_tll;
>> -       }
>> -
>> -       platform_set_drvdata(pdev, omap);
>> -
>> -       ret = omap_usbhs_alloc_children(pdev);
>> -       if (ret) {
>> -               dev_err(dev, "omap_usbhs_alloc_children failed\n");
>> -               goto err_alloc;
>> -       }
>> -
>> -       goto end_probe;
>> -
>> -err_alloc:
>> -       iounmap(omap->tll_base);
>> -
>> -err_tll:
>> -       iounmap(omap->uhh_base);
>> -
>> -err_init_60m_fclk:
>> -       clk_put(omap->init_60m_fclk);
>> -
>> -err_usbtll_p2_fck:
>> -       clk_put(omap->usbtll_p2_fck);
>> -
>> -err_usbhost_p2_fck:
>> -       clk_put(omap->usbhost_p2_fck);
>> -
>> -err_usbtll_p1_fck:
>> -       clk_put(omap->usbtll_p1_fck);
>> -
>> -err_usbhost_p1_fck:
>> -       clk_put(omap->usbhost_p1_fck);
>> -
>> -err_xclk60mhsp2_ck:
>> -       clk_put(omap->xclk60mhsp2_ck);
>> -
>> -err_utmi_p2_fck:
>> -       clk_put(omap->utmi_p2_fck);
>> -
>> -err_xclk60mhsp1_ck:
>> -       clk_put(omap->xclk60mhsp1_ck);
>> -
>> -err_utmi_p1_fck:
>> -       clk_put(omap->utmi_p1_fck);
>> -
>> -err_usbtll_ick:
>> -       clk_put(omap->usbtll_ick);
>> -
>> -err_usbtll_fck:
>> -       clk_put(omap->usbtll_fck);
>> -
>> -err_usbhost_fs_fck:
>> -       clk_put(omap->usbhost_fs_fck);
>> -
>> -err_usbhost_hs_fck:
>> -       clk_put(omap->usbhost_hs_fck);
>> -
>> -err_usbhost_ick:
>> -       clk_put(omap->usbhost_ick);
>> -
>> -err_end:
>> -       kfree(omap);
>> -
>> -end_probe:
>> -       return ret;
>> -}
>> -
>> -/**
>> - * usbhs_omap_remove - shutdown processing for UHH&  TLL HCDs
>> - * @pdev: USB Host Controller being removed
>> - *
>> - * Reverses the effect of usbhs_omap_probe().
>> - */
>> -static int __devexit usbhs_omap_remove(struct platform_device *pdev)
>> -{
>> -       struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
>> -
>> -       if (omap->count != 0) {
>> -               dev_err(&pdev->dev,
>> -                       "Either EHCI or OHCI is still using usbhs
>> core\n");
>> -               return -EBUSY;
>> -       }
>> -
>> -       iounmap(omap->tll_base);
>> -       iounmap(omap->uhh_base);
>> -       clk_put(omap->init_60m_fclk);
>> -       clk_put(omap->usbtll_p2_fck);
>> -       clk_put(omap->usbhost_p2_fck);
>> -       clk_put(omap->usbtll_p1_fck);
>> -       clk_put(omap->usbhost_p1_fck);
>> -       clk_put(omap->xclk60mhsp2_ck);
>> -       clk_put(omap->utmi_p2_fck);
>> -       clk_put(omap->xclk60mhsp1_ck);
>> -       clk_put(omap->utmi_p1_fck);
>> -       clk_put(omap->usbtll_ick);
>> -       clk_put(omap->usbtll_fck);
>> -       clk_put(omap->usbhost_fs_fck);
>> -       clk_put(omap->usbhost_hs_fck);
>> -       clk_put(omap->usbhost_ick);
>> -       kfree(omap);
>> -
>> -       return 0;
>> -}
>> -
>>  static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
>>  {
>>        switch (pmode) {
>> @@ -687,30 +419,79 @@ static void usbhs_omap_tll_init(struct device *dev,
>> u8 tll_channel_count)
>>        }
>>  }
>>
>> -static int usbhs_enable(struct device *dev)
>> +static int usbhs_runtime_resume(struct device *dev)
>>  {
>>        struct usbhs_hcd_omap           *omap = dev_get_drvdata(dev);
>>        struct usbhs_omap_platform_data *pdata =&omap->platdata;
>> -       unsigned long                   flags = 0;
>> -       int                             ret = 0;
>> -       unsigned long                   timeout;
>> -       unsigned                        reg;
>> +       unsigned long                   flags;
>> +
>> +       dev_dbg(dev, "usbhs_runtime_resume\n");
>> +
>> +       if (!pdata) {
>> +               dev_dbg(dev, "missing platform_data\n");
>> +               return  -ENODEV;
>> +       }
>> +
>> +       spin_lock_irqsave(&omap->lock, flags);
>> +
>> +       if (is_ehci_tll_mode(pdata->port_mode[0])) {
>> +               clk_enable(omap->usbhost_p1_fck);
>> +               clk_enable(omap->usbtll_p1_fck);
>> +       }
>> +       if (is_ehci_tll_mode(pdata->port_mode[1])) {
>> +               clk_enable(omap->usbhost_p2_fck);
>> +               clk_enable(omap->usbtll_p2_fck);
>> +       }
>> +       clk_enable(omap->utmi_p1_fck);
>> +       clk_enable(omap->utmi_p2_fck);
>> +
>> +       spin_unlock_irqrestore(&omap->lock, flags);
>> +
>> +       return 0;
>> +}
>> +
>> +static int usbhs_runtime_suspend(struct device *dev)
>> +{
>> +       struct usbhs_hcd_omap           *omap = dev_get_drvdata(dev);
>> +       struct usbhs_omap_platform_data *pdata =&omap->platdata;
>> +       unsigned long                   flags;
>> +
>> +       dev_dbg(dev, "usbhs_runtime_suspend\n");
>>
>> -       dev_dbg(dev, "starting TI HSUSB Controller\n");
>>        if (!pdata) {
>>                dev_dbg(dev, "missing platform_data\n");
>>                return  -ENODEV;
>>        }
>>
>>        spin_lock_irqsave(&omap->lock, flags);
>> -       if (omap->count>  0)
>> -               goto end_count;
>>
>> -       clk_enable(omap->usbhost_ick);
>> -       clk_enable(omap->usbhost_hs_fck);
>> -       clk_enable(omap->usbhost_fs_fck);
>> -       clk_enable(omap->usbtll_fck);
>> -       clk_enable(omap->usbtll_ick);
>> +       if (is_ehci_tll_mode(pdata->port_mode[0])) {
>> +               clk_disable(omap->usbhost_p1_fck);
>> +               clk_disable(omap->usbtll_p1_fck);
>> +       }
>> +       if (is_ehci_tll_mode(pdata->port_mode[1])) {
>> +               clk_disable(omap->usbhost_p2_fck);
>> +               clk_disable(omap->usbtll_p2_fck);
>> +       }
>> +       clk_disable(omap->utmi_p2_fck);
>> +       clk_disable(omap->utmi_p1_fck);
>> +
>> +       spin_unlock_irqrestore(&omap->lock, flags);
>> +
>> +       return 0;
>> +}
>> +
>> +static void omap_usbhs_init(struct device *dev)
>
> Since it is called only at init the it could be placed in init section.
>>
>> +{
>> +       struct usbhs_hcd_omap           *omap = dev_get_drvdata(dev);
>> +       struct usbhs_omap_platform_data *pdata =&omap->platdata;
>> +       unsigned long                   flags;
>> +       unsigned                        reg;
>> +
>> +       dev_dbg(dev, "starting TI HSUSB Controller\n");
>> +
>> +       pm_runtime_get_sync(dev);
>> +       spin_lock_irqsave(&omap->lock, flags);
>>
>>        if (pdata->ehci_data->phy_reset) {
>>                if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) {
>> @@ -734,50 +515,6 @@ static int usbhs_enable(struct device *dev)
>>        omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
>>        dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);
>>
>> -       /* perform TLL soft reset, and wait until reset is complete */
>> -       usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
>> -                       OMAP_USBTLL_SYSCONFIG_SOFTRESET);
>> -
>> -       /* Wait for TLL reset to complete */
>> -       timeout = jiffies + msecs_to_jiffies(1000);
>> -       while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
>> -                       &  OMAP_USBTLL_SYSSTATUS_RESETDONE)) {
>> -               cpu_relax();
>> -
>> -               if (time_after(jiffies, timeout)) {
>> -                       dev_dbg(dev, "operation timed out\n");
>> -                       ret = -EINVAL;
>> -                       goto err_tll;
>> -               }
>> -       }
>> -
>> -       dev_dbg(dev, "TLL RESET DONE\n");
>> -
>> -       /* (1<<3) = no idle mode only for initial debugging */
>> -       usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
>> -                       OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
>> -                       OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
>> -                       OMAP_USBTLL_SYSCONFIG_AUTOIDLE);
>> -
>> -       /* Put UHH in NoIdle/NoStandby mode */
>> -       reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG);
>> -       if (is_omap_usbhs_rev1(omap)) {
>> -               reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
>> -                               | OMAP_UHH_SYSCONFIG_SIDLEMODE
>> -                               | OMAP_UHH_SYSCONFIG_CACTIVITY
>> -                               | OMAP_UHH_SYSCONFIG_MIDLEMODE);
>> -               reg&= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
>> -
>> -
>> -       } else if (is_omap_usbhs_rev2(omap)) {
>> -               reg&= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR;
>> -               reg |= OMAP4_UHH_SYSCONFIG_NOIDLE;
>> -               reg&= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR;
>> -               reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY;
>> -       }
>> -
>> -       usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
>> -
>>        reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
>>        /* setup ULPI bypass and burst configurations */
>>        reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
>> @@ -823,49 +560,6 @@ static int usbhs_enable(struct device *dev)
>>                reg&= ~OMAP4_P1_MODE_CLEAR;
>>                reg&= ~OMAP4_P2_MODE_CLEAR;
>>
>> -               if (is_ehci_phy_mode(pdata->port_mode[0])) {
>> -                       ret = clk_set_parent(omap->utmi_p1_fck,
>> -                                               omap->xclk60mhsp1_ck);
>> -                       if (ret != 0) {
>> -                               dev_err(dev, "xclk60mhsp1_ck set parent"
>> -                               "failed error:%d\n", ret);
>> -                               goto err_tll;
>> -                       }
>> -               } else if (is_ehci_tll_mode(pdata->port_mode[0])) {
>> -                       ret = clk_set_parent(omap->utmi_p1_fck,
>> -                                               omap->init_60m_fclk);
>> -                       if (ret != 0) {
>> -                               dev_err(dev, "init_60m_fclk set parent"
>> -                               "failed error:%d\n", ret);
>> -                               goto err_tll;
>> -                       }
>> -                       clk_enable(omap->usbhost_p1_fck);
>> -                       clk_enable(omap->usbtll_p1_fck);
>> -               }
>> -
>> -               if (is_ehci_phy_mode(pdata->port_mode[1])) {
>> -                       ret = clk_set_parent(omap->utmi_p2_fck,
>> -                                               omap->xclk60mhsp2_ck);
>> -                       if (ret != 0) {
>> -                               dev_err(dev, "xclk60mhsp1_ck set parent"
>> -                                       "failed error:%d\n", ret);
>> -                               goto err_tll;
>> -                       }
>> -               } else if (is_ehci_tll_mode(pdata->port_mode[1])) {
>> -                       ret = clk_set_parent(omap->utmi_p2_fck,
>> -                                               omap->init_60m_fclk);
>> -                       if (ret != 0) {
>> -                               dev_err(dev, "init_60m_fclk set parent"
>> -                               "failed error:%d\n", ret);
>> -                               goto err_tll;
>> -                       }
>> -                       clk_enable(omap->usbhost_p2_fck);
>> -                       clk_enable(omap->usbtll_p2_fck);
>> -               }
>> -
>> -               clk_enable(omap->utmi_p1_fck);
>> -               clk_enable(omap->utmi_p2_fck);
>> -
>>                if (is_ehci_tll_mode(pdata->port_mode[0]) ||
>>                        (is_ohci_port(pdata->port_mode[0])))
>>                        reg |= OMAP4_P1_MODE_TLL;
>> @@ -911,12 +605,15 @@ static int usbhs_enable(struct device *dev)
>>                                (pdata->ehci_data->reset_gpio_port[1], 1);
>>        }
>>
>> -end_count:
>> -       omap->count++;
>>        spin_unlock_irqrestore(&omap->lock, flags);
>> -       return 0;
>> +       pm_runtime_put_sync(dev);
>> +}
>> +
>> +static void omap_usbhs_deinit(struct device *dev)
>> +{
>> +       struct usbhs_hcd_omap           *omap = dev_get_drvdata(dev);
>> +       struct usbhs_omap_platform_data *pdata =&omap->platdata;
>>
>> -err_tll:
>>        if (pdata->ehci_data->phy_reset) {
>>                if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
>>                        gpio_free(pdata->ehci_data->reset_gpio_port[0]);
>> @@ -924,123 +621,257 @@ err_tll:
>>                if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
>>                        gpio_free(pdata->ehci_data->reset_gpio_port[1]);
>>        }
>> -
>> -       clk_disable(omap->usbtll_ick);
>> -       clk_disable(omap->usbtll_fck);
>> -       clk_disable(omap->usbhost_fs_fck);
>> -       clk_disable(omap->usbhost_hs_fck);
>> -       clk_disable(omap->usbhost_ick);
>> -       spin_unlock_irqrestore(&omap->lock, flags);
>> -       return ret;
>>  }
>>
>> -static void usbhs_disable(struct device *dev)
>> +
>> +/**
>> + * usbhs_omap_probe - initialize TI-based HCDs
>> + *
>> + * Allocates basic resources for this USB host controller.
>> + */
>> +static int __devinit usbhs_omap_probe(struct platform_device *pdev)
>>  {
>> -       struct usbhs_hcd_omap           *omap = dev_get_drvdata(dev);
>> -       struct usbhs_omap_platform_data *pdata =&omap->platdata;
>> -       unsigned long                   flags = 0;
>> -       unsigned long                   timeout;
>> +       struct device                   *dev =&pdev->dev;
>> +       struct usbhs_omap_platform_data *pdata = dev->platform_data;
>> +       struct usbhs_hcd_omap           *omap;
>> +       struct resource                 *res;
>> +       int                             ret = 0;
>> +       int                             i;
>>
>> -       dev_dbg(dev, "stopping TI HSUSB Controller\n");
>> +       if (!pdata) {
>> +               dev_err(dev, "Missing platform data\n");
>> +               ret = -ENOMEM;
>> +               goto end_probe;
>> +       }
>>
>> -       spin_lock_irqsave(&omap->lock, flags);
>> +       omap = kzalloc(sizeof(*omap), GFP_KERNEL);
>> +       if (!omap) {
>> +               dev_err(dev, "Memory allocation failed\n");
>> +               ret = -ENOMEM;
>> +               goto end_probe;
>> +       }
>>
>> -       if (omap->count == 0)
>> -               goto end_disble;
>> +       spin_lock_init(&omap->lock);
>>
>> -       omap->count--;
>> +       for (i = 0; i<  OMAP3_HS_USB_PORTS; i++)
>> +               omap->platdata.port_mode[i] = pdata->port_mode[i];
>>
>> -       if (omap->count != 0)
>> -               goto end_disble;
>> +       omap->platdata.ehci_data = pdata->ehci_data;
>> +       omap->platdata.ohci_data = pdata->ohci_data;
>>
>> -       /* Reset OMAP modules for insmod/rmmod to work */
>> -       usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG,
>> -                       is_omap_usbhs_rev2(omap) ?
>> -                       OMAP4_UHH_SYSCONFIG_SOFTRESET :
>> -                       OMAP_UHH_SYSCONFIG_SOFTRESET);
>> +       pm_runtime_enable(dev);
>>
>> -       timeout = jiffies + msecs_to_jiffies(100);
>> -       while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS)
>> -                               &  (1<<  0))) {
>> -               cpu_relax();
>> +       omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
>> +       if (IS_ERR(omap->utmi_p1_fck)) {
>> +               ret = PTR_ERR(omap->utmi_p1_fck);
>> +               dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret);
>> +               goto err_end;
>> +       }
>>
>> -               if (time_after(jiffies, timeout))
>> -                       dev_dbg(dev, "operation timed out\n");
>> +       omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck");
>> +       if (IS_ERR(omap->xclk60mhsp1_ck)) {
>> +               ret = PTR_ERR(omap->xclk60mhsp1_ck);
>> +               dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret);
>> +               goto err_utmi_p1_fck;
>> +       }
>> +
>> +       omap->utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk");
>> +       if (IS_ERR(omap->utmi_p2_fck)) {
>> +               ret = PTR_ERR(omap->utmi_p2_fck);
>> +               dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret);
>> +               goto err_xclk60mhsp1_ck;
>> +       }
>> +
>> +       omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck");
>> +       if (IS_ERR(omap->xclk60mhsp2_ck)) {
>> +               ret = PTR_ERR(omap->xclk60mhsp2_ck);
>> +               dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret);
>> +               goto err_utmi_p2_fck;
>>        }
>>
>> -       while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS)
>> -                               &  (1<<  1))) {
>> -               cpu_relax();
>> +       omap->usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk");
>> +       if (IS_ERR(omap->usbhost_p1_fck)) {
>> +               ret = PTR_ERR(omap->usbhost_p1_fck);
>> +               dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret);
>> +               goto err_xclk60mhsp2_ck;
>> +       }
>>
>> -               if (time_after(jiffies, timeout))
>> -                       dev_dbg(dev, "operation timed out\n");
>> +       omap->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk");
>> +       if (IS_ERR(omap->usbtll_p1_fck)) {
>> +               ret = PTR_ERR(omap->usbtll_p1_fck);
>> +               dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret);
>> +               goto err_usbhost_p1_fck;
>> +       }
>> +
>> +       omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk");
>> +       if (IS_ERR(omap->usbhost_p2_fck)) {
>> +               ret = PTR_ERR(omap->usbhost_p2_fck);
>> +               dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret);
>> +               goto err_usbtll_p1_fck;
>>        }
>>
>> -       while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS)
>> -                               &  (1<<  2))) {
>> -               cpu_relax();
>> +       omap->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk");
>> +       if (IS_ERR(omap->usbtll_p2_fck)) {
>> +               ret = PTR_ERR(omap->usbtll_p2_fck);
>> +               dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret);
>> +               goto err_usbhost_p2_fck;
>> +       }
>>
>> -               if (time_after(jiffies, timeout))
>> -                       dev_dbg(dev, "operation timed out\n");
>> +       omap->init_60m_fclk = clk_get(dev, "init_60m_fclk");
>> +       if (IS_ERR(omap->init_60m_fclk)) {
>> +               ret = PTR_ERR(omap->init_60m_fclk);
>> +               dev_err(dev, "init_60m_fclk failed error:%d\n", ret);
>> +               goto err_usbtll_p2_fck;
>>        }
>>
>> -       usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1<<  1));
>> +       if (is_ehci_phy_mode(pdata->port_mode[0])) {
>> +               /* for OMAP3 , the clk set paretn fails */
>> +               ret = clk_set_parent(omap->utmi_p1_fck,
>> +                                       omap->xclk60mhsp1_ck);
>> +               if (ret != 0)
>> +                       dev_err(dev, "xclk60mhsp1_ck set parent"
>> +                               "failed error:%d\n", ret);
>> +       } else if (is_ehci_tll_mode(pdata->port_mode[0])) {
>> +               ret = clk_set_parent(omap->utmi_p1_fck,
>> +                                       omap->init_60m_fclk);
>> +               if (ret != 0)
>> +                       dev_err(dev, "init_60m_fclk set parent"
>> +                               "failed error:%d\n", ret);
>> +       }
>>
>> -       while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
>> -                               &  (1<<  0))) {
>> -               cpu_relax();
>> +       if (is_ehci_phy_mode(pdata->port_mode[1])) {
>> +               ret = clk_set_parent(omap->utmi_p2_fck,
>> +                                       omap->xclk60mhsp2_ck);
>> +               if (ret != 0)
>> +                       dev_err(dev, "xclk60mhsp2_ck set parent"
>> +                                       "failed error:%d\n", ret);
>> +       } else if (is_ehci_tll_mode(pdata->port_mode[1])) {
>> +               ret = clk_set_parent(omap->utmi_p2_fck,
>> +                                               omap->init_60m_fclk);
>> +               if (ret != 0)
>> +                       dev_err(dev, "init_60m_fclk set parent"
>> +                               "failed error:%d\n", ret);
>> +       }
>>
>> -               if (time_after(jiffies, timeout))
>> -                       dev_dbg(dev, "operation timed out\n");
>> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uhh");
>> +       if (!res) {
>> +               dev_err(dev, "UHH EHCI get resource failed\n");
>> +               ret = -ENODEV;
>> +               goto err_init_60m_fclk;
>>        }
>>
>> -       if (is_omap_usbhs_rev2(omap)) {
>> -               if (is_ehci_tll_mode(pdata->port_mode[0]))
>> -                       clk_disable(omap->usbtll_p1_fck);
>> -               if (is_ehci_tll_mode(pdata->port_mode[1]))
>> -                       clk_disable(omap->usbtll_p2_fck);
>> -               clk_disable(omap->utmi_p2_fck);
>> -               clk_disable(omap->utmi_p1_fck);
>> +       omap->uhh_base = ioremap(res->start, resource_size(res));
>> +       if (!omap->uhh_base) {
>> +               dev_err(dev, "UHH ioremap failed\n");
>> +               ret = -ENOMEM;
>> +               goto err_init_60m_fclk;
>>        }
>>
>> -       clk_disable(omap->usbtll_ick);
>> -       clk_disable(omap->usbtll_fck);
>> -       clk_disable(omap->usbhost_fs_fck);
>> -       clk_disable(omap->usbhost_hs_fck);
>> -       clk_disable(omap->usbhost_ick);
>> +       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tll");
>> +       if (!res) {
>> +               dev_err(dev, "UHH EHCI get resource failed\n");
>> +               ret = -ENODEV;
>> +               goto err_tll;
>> +       }
>>
>> -       /* The gpio_free migh sleep; so unlock the spinlock */
>> -       spin_unlock_irqrestore(&omap->lock, flags);
>> +       omap->tll_base = ioremap(res->start, resource_size(res));
>> +       if (!omap->tll_base) {
>> +               dev_err(dev, "TLL ioremap failed\n");
>> +               ret = -ENOMEM;
>> +               goto err_tll;
>> +       }
>>
>> -       if (pdata->ehci_data->phy_reset) {
>> -               if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
>> -                       gpio_free(pdata->ehci_data->reset_gpio_port[0]);
>> +       platform_set_drvdata(pdev, omap);
>>
>> -               if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
>> -                       gpio_free(pdata->ehci_data->reset_gpio_port[1]);
>> +       ret = omap_usbhs_alloc_children(pdev);
>> +       if (ret) {
>> +               dev_err(dev, "omap_usbhs_alloc_children failed\n");
>> +               goto err_alloc;
>>        }
>> -       return;
>>
>> -end_disble:
>> -       spin_unlock_irqrestore(&omap->lock, flags);
>> -}
>> +       omap_usbhs_init(dev);
>>
>> -int omap_usbhs_enable(struct device *dev)
>> -{
>> -       return  usbhs_enable(dev->parent);
>> +       goto end_probe;
>> +
>> +err_alloc:
>> +       iounmap(omap->tll_base);
>> +
>> +err_tll:
>> +       iounmap(omap->uhh_base);
>> +
>> +err_init_60m_fclk:
>> +       clk_put(omap->init_60m_fclk);
>> +
>> +err_usbtll_p2_fck:
>> +       clk_put(omap->usbtll_p2_fck);
>> +
>> +err_usbhost_p2_fck:
>> +       clk_put(omap->usbhost_p2_fck);
>> +
>> +err_usbtll_p1_fck:
>> +       clk_put(omap->usbtll_p1_fck);
>> +
>> +err_usbhost_p1_fck:
>> +       clk_put(omap->usbhost_p1_fck);
>> +
>> +err_xclk60mhsp2_ck:
>> +       clk_put(omap->xclk60mhsp2_ck);
>> +
>> +err_utmi_p2_fck:
>> +       clk_put(omap->utmi_p2_fck);
>> +
>> +err_xclk60mhsp1_ck:
>> +       clk_put(omap->xclk60mhsp1_ck);
>> +
>> +err_utmi_p1_fck:
>> +       clk_put(omap->utmi_p1_fck);
>> +
>> +err_end:
>> +       pm_runtime_disable(dev);
>> +       kfree(omap);
>> +
>> +end_probe:
>> +       return ret;
>>  }
>> -EXPORT_SYMBOL_GPL(omap_usbhs_enable);
>>
>> -void omap_usbhs_disable(struct device *dev)
>> +/**
>> + * usbhs_omap_remove - shutdown processing for UHH&  TLL HCDs
>> + * @pdev: USB Host Controller being removed
>> + *
>> + * Reverses the effect of usbhs_omap_probe().
>> + */
>> +static int __devexit usbhs_omap_remove(struct platform_device *pdev)
>>  {
>> -       usbhs_disable(dev->parent);
>> +       struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
>> +
>> +       omap_usbhs_deinit(&pdev->dev);
>> +       iounmap(omap->tll_base);
>> +       iounmap(omap->uhh_base);
>> +       clk_put(omap->init_60m_fclk);
>> +       clk_put(omap->usbtll_p2_fck);
>> +       clk_put(omap->usbhost_p2_fck);
>> +       clk_put(omap->usbtll_p1_fck);
>> +       clk_put(omap->usbhost_p1_fck);
>> +       clk_put(omap->xclk60mhsp2_ck);
>> +       clk_put(omap->utmi_p2_fck);
>> +       clk_put(omap->xclk60mhsp1_ck);
>> +       clk_put(omap->utmi_p1_fck);
>> +       pm_runtime_disable(&pdev->dev);
>> +       kfree(omap);
>> +
>> +       return 0;
>>  }
>> -EXPORT_SYMBOL_GPL(omap_usbhs_disable);
>> +
>> +static const struct dev_pm_ops usbhsomap_dev_pm_ops = {
>> +       .runtime_suspend        = usbhs_runtime_suspend,
>> +       .runtime_resume         = usbhs_runtime_resume,
>> +};
>
> Could these be placed under a PM flag.

No, you should not, these functions enable the port clocks for omap4 usbhs
so, it should be default.


>
>>
>>  static struct platform_driver usbhs_omap_driver = {
>>        .driver = {
>>                .name           = (char *)usbhs_driver_name,
>>                .owner          = THIS_MODULE,
>> +               .pm             =&usbhsomap_dev_pm_ops,
>>        },
>>        .remove         = __exit_p(usbhs_omap_remove),
>>  };
>> diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
>> index 4524032..82cd3ea 100644
>> --- a/drivers/usb/host/ehci-omap.c
>> +++ b/drivers/usb/host/ehci-omap.c
>> @@ -41,6 +41,7 @@
>>  #include<linux/usb/ulpi.h>
>>  #include<plat/usb.h>
>>  #include<linux/regulator/consumer.h>
>> +#include<linux/pm_runtime.h>
>>
>>  /* EHCI Register Set */
>>  #define EHCI_INSNREG04                                        (0xA0)
>> @@ -190,11 +191,8 @@ static int ehci_hcd_omap_probe(struct platform_device
>> *pdev)
>>                }
>>        }
>>
>> -       ret = omap_usbhs_enable(dev);
>> -       if (ret) {
>> -               dev_err(dev, "failed to start usbhs with err %d\n", ret);
>> -               goto err_enable;
>> -       }
>> +       pm_runtime_enable(dev);
>> +       pm_runtime_get_sync(dev);
>>
>>        /*
>>         * An undocumented "feature" in the OMAP3 EHCI controller,
>> @@ -240,11 +238,8 @@ static int ehci_hcd_omap_probe(struct platform_device
>> *pdev)
>>        return 0;
>>
>>  err_add_hcd:
>> -       omap_usbhs_disable(dev);
>> -
>> -err_enable:
>>        disable_put_regulator(pdata);
>> -       usb_put_hcd(hcd);
>> +       pm_runtime_put_sync(dev);
>>
>>  err_io:
>>        iounmap(regs);
>> @@ -266,10 +261,12 @@ static int ehci_hcd_omap_remove(struct
>> platform_device *pdev)
>>        struct usb_hcd *hcd     = dev_get_drvdata(dev);
>>
>>        usb_remove_hcd(hcd);
>> -       omap_usbhs_disable(dev);
>>        disable_put_regulator(dev->platform_data);
>>        iounmap(hcd->regs);
>>        usb_put_hcd(hcd);
>> +       pm_runtime_put_sync(dev);
>> +       pm_runtime_disable(dev);
>> +
>>        return 0;
>>  }
>>
>> diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
>> index 6048f2f..6cfedaf 100644
>> --- a/drivers/usb/host/ohci-omap3.c
>> +++ b/drivers/usb/host/ohci-omap3.c
>> @@ -31,6 +31,7 @@
>>
>>  #include<linux/platform_device.h>
>>  #include<plat/usb.h>
>> +#include<linux/pm_runtime.h>
>>
>>
>>  /*-------------------------------------------------------------------------*/
>>
>> @@ -134,7 +135,7 @@ static int __devinit ohci_hcd_omap3_probe(struct
>> platform_device *pdev)
>>        int                     irq;
>>
>>        if (usb_disabled())
>> -               goto err_end;
>> +               return -ENODEV;
>>
>>        if (!dev->parent) {
>>                dev_err(dev, "Missing parent device\n");
>> @@ -172,11 +173,8 @@ static int __devinit ohci_hcd_omap3_probe(struct
>> platform_device *pdev)
>>        hcd->rsrc_len = resource_size(res);
>>        hcd->regs =  regs;
>>
>> -       ret = omap_usbhs_enable(dev);
>> -       if (ret) {
>> -               dev_dbg(dev, "failed to start ohci\n");
>> -               goto err_end;
>> -       }
>> +       pm_runtime_enable(dev);
>> +       pm_runtime_get_sync(dev);
>>
>>        ohci_hcd_init(hcd_to_ohci(hcd));
>>
>> @@ -189,9 +187,7 @@ static int __devinit ohci_hcd_omap3_probe(struct
>> platform_device *pdev)
>>        return 0;
>>
>>  err_add_hcd:
>> -       omap_usbhs_disable(dev);
>> -
>> -err_end:
>> +       pm_runtime_put_sync(dev);
>>        usb_put_hcd(hcd);
>>
>>  err_io:
>> @@ -220,9 +216,9 @@ static int __devexit ohci_hcd_omap3_remove(struct
>> platform_device *pdev)
>>
>>        iounmap(hcd->regs);
>>        usb_remove_hcd(hcd);
>> -       omap_usbhs_disable(dev);
>> +       pm_runtime_put_sync(dev);
>> +       pm_runtime_disable(dev);
>>        usb_put_hcd(hcd);
>> -
>>        return 0;
>>  }
>>
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/arm/plat-omap/include/plat/usb.h b/arch/arm/plat-omap/include/plat/usb.h
index 17d3c93..2b66dc2 100644
--- a/arch/arm/plat-omap/include/plat/usb.h
+++ b/arch/arm/plat-omap/include/plat/usb.h
@@ -100,9 +100,6 @@  extern void usb_musb_init(struct omap_musb_board_data *board_data);
 
 extern void usbhs_init(const struct usbhs_omap_board_data *pdata);
 
-extern int omap_usbhs_enable(struct device *dev);
-extern void omap_usbhs_disable(struct device *dev);
-
 extern int omap4430_phy_power(struct device *dev, int ID, int on);
 extern int omap4430_phy_set_clk(struct device *dev, int on);
 extern int omap4430_phy_init(struct device *dev);
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 9c2da29..e6f3b01 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -26,6 +26,7 @@ 
 #include <linux/spinlock.h>
 #include <linux/gpio.h>
 #include <plat/usb.h>
+#include <linux/pm_runtime.h>
 
 #define USBHS_DRIVER_NAME	"usbhs_omap"
 #define OMAP_EHCI_DEVICE	"ehci-omap"
@@ -146,9 +147,6 @@ 
 
 
 struct usbhs_hcd_omap {
-	struct clk			*usbhost_ick;
-	struct clk			*usbhost_hs_fck;
-	struct clk			*usbhost_fs_fck;
 	struct clk			*xclk60mhsp1_ck;
 	struct clk			*xclk60mhsp2_ck;
 	struct clk			*utmi_p1_fck;
@@ -158,8 +156,6 @@  struct usbhs_hcd_omap {
 	struct clk			*usbhost_p2_fck;
 	struct clk			*usbtll_p2_fck;
 	struct clk			*init_60m_fclk;
-	struct clk			*usbtll_fck;
-	struct clk			*usbtll_ick;
 
 	void __iomem			*uhh_base;
 	void __iomem			*tll_base;
@@ -168,7 +164,6 @@  struct usbhs_hcd_omap {
 
 	u32				usbhs_rev;
 	spinlock_t			lock;
-	int				count;
 };
 /*-------------------------------------------------------------------------*/
 
@@ -318,269 +313,6 @@  err_end:
 	return ret;
 }
 
-/**
- * usbhs_omap_probe - initialize TI-based HCDs
- *
- * Allocates basic resources for this USB host controller.
- */
-static int __devinit usbhs_omap_probe(struct platform_device *pdev)
-{
-	struct device			*dev =  &pdev->dev;
-	struct usbhs_omap_platform_data	*pdata = dev->platform_data;
-	struct usbhs_hcd_omap		*omap;
-	struct resource			*res;
-	int				ret = 0;
-	int				i;
-
-	if (!pdata) {
-		dev_err(dev, "Missing platform data\n");
-		ret = -ENOMEM;
-		goto end_probe;
-	}
-
-	omap = kzalloc(sizeof(*omap), GFP_KERNEL);
-	if (!omap) {
-		dev_err(dev, "Memory allocation failed\n");
-		ret = -ENOMEM;
-		goto end_probe;
-	}
-
-	spin_lock_init(&omap->lock);
-
-	for (i = 0; i < OMAP3_HS_USB_PORTS; i++)
-		omap->platdata.port_mode[i] = pdata->port_mode[i];
-
-	omap->platdata.ehci_data = pdata->ehci_data;
-	omap->platdata.ohci_data = pdata->ohci_data;
-
-	omap->usbhost_ick = clk_get(dev, "usbhost_ick");
-	if (IS_ERR(omap->usbhost_ick)) {
-		ret =  PTR_ERR(omap->usbhost_ick);
-		dev_err(dev, "usbhost_ick failed error:%d\n", ret);
-		goto err_end;
-	}
-
-	omap->usbhost_hs_fck = clk_get(dev, "hs_fck");
-	if (IS_ERR(omap->usbhost_hs_fck)) {
-		ret = PTR_ERR(omap->usbhost_hs_fck);
-		dev_err(dev, "usbhost_hs_fck failed error:%d\n", ret);
-		goto err_usbhost_ick;
-	}
-
-	omap->usbhost_fs_fck = clk_get(dev, "fs_fck");
-	if (IS_ERR(omap->usbhost_fs_fck)) {
-		ret = PTR_ERR(omap->usbhost_fs_fck);
-		dev_err(dev, "usbhost_fs_fck failed error:%d\n", ret);
-		goto err_usbhost_hs_fck;
-	}
-
-	omap->usbtll_fck = clk_get(dev, "usbtll_fck");
-	if (IS_ERR(omap->usbtll_fck)) {
-		ret = PTR_ERR(omap->usbtll_fck);
-		dev_err(dev, "usbtll_fck failed error:%d\n", ret);
-		goto err_usbhost_fs_fck;
-	}
-
-	omap->usbtll_ick = clk_get(dev, "usbtll_ick");
-	if (IS_ERR(omap->usbtll_ick)) {
-		ret = PTR_ERR(omap->usbtll_ick);
-		dev_err(dev, "usbtll_ick failed error:%d\n", ret);
-		goto err_usbtll_fck;
-	}
-
-	omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
-	if (IS_ERR(omap->utmi_p1_fck)) {
-		ret = PTR_ERR(omap->utmi_p1_fck);
-		dev_err(dev, "utmi_p1_gfclk failed error:%d\n",	ret);
-		goto err_usbtll_ick;
-	}
-
-	omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck");
-	if (IS_ERR(omap->xclk60mhsp1_ck)) {
-		ret = PTR_ERR(omap->xclk60mhsp1_ck);
-		dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret);
-		goto err_utmi_p1_fck;
-	}
-
-	omap->utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk");
-	if (IS_ERR(omap->utmi_p2_fck)) {
-		ret = PTR_ERR(omap->utmi_p2_fck);
-		dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret);
-		goto err_xclk60mhsp1_ck;
-	}
-
-	omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck");
-	if (IS_ERR(omap->xclk60mhsp2_ck)) {
-		ret = PTR_ERR(omap->xclk60mhsp2_ck);
-		dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret);
-		goto err_utmi_p2_fck;
-	}
-
-	omap->usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk");
-	if (IS_ERR(omap->usbhost_p1_fck)) {
-		ret = PTR_ERR(omap->usbhost_p1_fck);
-		dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret);
-		goto err_xclk60mhsp2_ck;
-	}
-
-	omap->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk");
-	if (IS_ERR(omap->usbtll_p1_fck)) {
-		ret = PTR_ERR(omap->usbtll_p1_fck);
-		dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret);
-		goto err_usbhost_p1_fck;
-	}
-
-	omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk");
-	if (IS_ERR(omap->usbhost_p2_fck)) {
-		ret = PTR_ERR(omap->usbhost_p2_fck);
-		dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret);
-		goto err_usbtll_p1_fck;
-	}
-
-	omap->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk");
-	if (IS_ERR(omap->usbtll_p2_fck)) {
-		ret = PTR_ERR(omap->usbtll_p2_fck);
-		dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret);
-		goto err_usbhost_p2_fck;
-	}
-
-	omap->init_60m_fclk = clk_get(dev, "init_60m_fclk");
-	if (IS_ERR(omap->init_60m_fclk)) {
-		ret = PTR_ERR(omap->init_60m_fclk);
-		dev_err(dev, "init_60m_fclk failed error:%d\n", ret);
-		goto err_usbtll_p2_fck;
-	}
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uhh");
-	if (!res) {
-		dev_err(dev, "UHH EHCI get resource failed\n");
-		ret = -ENODEV;
-		goto err_init_60m_fclk;
-	}
-
-	omap->uhh_base = ioremap(res->start, resource_size(res));
-	if (!omap->uhh_base) {
-		dev_err(dev, "UHH ioremap failed\n");
-		ret = -ENOMEM;
-		goto err_init_60m_fclk;
-	}
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tll");
-	if (!res) {
-		dev_err(dev, "UHH EHCI get resource failed\n");
-		ret = -ENODEV;
-		goto err_tll;
-	}
-
-	omap->tll_base = ioremap(res->start, resource_size(res));
-	if (!omap->tll_base) {
-		dev_err(dev, "TLL ioremap failed\n");
-		ret = -ENOMEM;
-		goto err_tll;
-	}
-
-	platform_set_drvdata(pdev, omap);
-
-	ret = omap_usbhs_alloc_children(pdev);
-	if (ret) {
-		dev_err(dev, "omap_usbhs_alloc_children failed\n");
-		goto err_alloc;
-	}
-
-	goto end_probe;
-
-err_alloc:
-	iounmap(omap->tll_base);
-
-err_tll:
-	iounmap(omap->uhh_base);
-
-err_init_60m_fclk:
-	clk_put(omap->init_60m_fclk);
-
-err_usbtll_p2_fck:
-	clk_put(omap->usbtll_p2_fck);
-
-err_usbhost_p2_fck:
-	clk_put(omap->usbhost_p2_fck);
-
-err_usbtll_p1_fck:
-	clk_put(omap->usbtll_p1_fck);
-
-err_usbhost_p1_fck:
-	clk_put(omap->usbhost_p1_fck);
-
-err_xclk60mhsp2_ck:
-	clk_put(omap->xclk60mhsp2_ck);
-
-err_utmi_p2_fck:
-	clk_put(omap->utmi_p2_fck);
-
-err_xclk60mhsp1_ck:
-	clk_put(omap->xclk60mhsp1_ck);
-
-err_utmi_p1_fck:
-	clk_put(omap->utmi_p1_fck);
-
-err_usbtll_ick:
-	clk_put(omap->usbtll_ick);
-
-err_usbtll_fck:
-	clk_put(omap->usbtll_fck);
-
-err_usbhost_fs_fck:
-	clk_put(omap->usbhost_fs_fck);
-
-err_usbhost_hs_fck:
-	clk_put(omap->usbhost_hs_fck);
-
-err_usbhost_ick:
-	clk_put(omap->usbhost_ick);
-
-err_end:
-	kfree(omap);
-
-end_probe:
-	return ret;
-}
-
-/**
- * usbhs_omap_remove - shutdown processing for UHH & TLL HCDs
- * @pdev: USB Host Controller being removed
- *
- * Reverses the effect of usbhs_omap_probe().
- */
-static int __devexit usbhs_omap_remove(struct platform_device *pdev)
-{
-	struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
-
-	if (omap->count != 0) {
-		dev_err(&pdev->dev,
-			"Either EHCI or OHCI is still using usbhs core\n");
-		return -EBUSY;
-	}
-
-	iounmap(omap->tll_base);
-	iounmap(omap->uhh_base);
-	clk_put(omap->init_60m_fclk);
-	clk_put(omap->usbtll_p2_fck);
-	clk_put(omap->usbhost_p2_fck);
-	clk_put(omap->usbtll_p1_fck);
-	clk_put(omap->usbhost_p1_fck);
-	clk_put(omap->xclk60mhsp2_ck);
-	clk_put(omap->utmi_p2_fck);
-	clk_put(omap->xclk60mhsp1_ck);
-	clk_put(omap->utmi_p1_fck);
-	clk_put(omap->usbtll_ick);
-	clk_put(omap->usbtll_fck);
-	clk_put(omap->usbhost_fs_fck);
-	clk_put(omap->usbhost_hs_fck);
-	clk_put(omap->usbhost_ick);
-	kfree(omap);
-
-	return 0;
-}
-
 static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
 {
 	switch (pmode) {
@@ -687,30 +419,79 @@  static void usbhs_omap_tll_init(struct device *dev, u8 tll_channel_count)
 	}
 }
 
-static int usbhs_enable(struct device *dev)
+static int usbhs_runtime_resume(struct device *dev)
 {
 	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
 	struct usbhs_omap_platform_data	*pdata = &omap->platdata;
-	unsigned long			flags = 0;
-	int				ret = 0;
-	unsigned long			timeout;
-	unsigned			reg;
+	unsigned long			flags;
+
+	dev_dbg(dev, "usbhs_runtime_resume\n");
+
+	if (!pdata) {
+		dev_dbg(dev, "missing platform_data\n");
+		return  -ENODEV;
+	}
+
+	spin_lock_irqsave(&omap->lock, flags);
+
+	if (is_ehci_tll_mode(pdata->port_mode[0])) {
+		clk_enable(omap->usbhost_p1_fck);
+		clk_enable(omap->usbtll_p1_fck);
+	}
+	if (is_ehci_tll_mode(pdata->port_mode[1])) {
+		clk_enable(omap->usbhost_p2_fck);
+		clk_enable(omap->usbtll_p2_fck);
+	}
+	clk_enable(omap->utmi_p1_fck);
+	clk_enable(omap->utmi_p2_fck);
+
+	spin_unlock_irqrestore(&omap->lock, flags);
+
+	return 0;
+}
+
+static int usbhs_runtime_suspend(struct device *dev)
+{
+	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
+	struct usbhs_omap_platform_data	*pdata = &omap->platdata;
+	unsigned long			flags;
+
+	dev_dbg(dev, "usbhs_runtime_suspend\n");
 
-	dev_dbg(dev, "starting TI HSUSB Controller\n");
 	if (!pdata) {
 		dev_dbg(dev, "missing platform_data\n");
 		return  -ENODEV;
 	}
 
 	spin_lock_irqsave(&omap->lock, flags);
-	if (omap->count > 0)
-		goto end_count;
 
-	clk_enable(omap->usbhost_ick);
-	clk_enable(omap->usbhost_hs_fck);
-	clk_enable(omap->usbhost_fs_fck);
-	clk_enable(omap->usbtll_fck);
-	clk_enable(omap->usbtll_ick);
+	if (is_ehci_tll_mode(pdata->port_mode[0])) {
+		clk_disable(omap->usbhost_p1_fck);
+		clk_disable(omap->usbtll_p1_fck);
+	}
+	if (is_ehci_tll_mode(pdata->port_mode[1])) {
+		clk_disable(omap->usbhost_p2_fck);
+		clk_disable(omap->usbtll_p2_fck);
+	}
+	clk_disable(omap->utmi_p2_fck);
+	clk_disable(omap->utmi_p1_fck);
+
+	spin_unlock_irqrestore(&omap->lock, flags);
+
+	return 0;
+}
+
+static void omap_usbhs_init(struct device *dev)
+{
+	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
+	struct usbhs_omap_platform_data	*pdata = &omap->platdata;
+	unsigned long			flags;
+	unsigned			reg;
+
+	dev_dbg(dev, "starting TI HSUSB Controller\n");
+
+	pm_runtime_get_sync(dev);
+	spin_lock_irqsave(&omap->lock, flags);
 
 	if (pdata->ehci_data->phy_reset) {
 		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) {
@@ -734,50 +515,6 @@  static int usbhs_enable(struct device *dev)
 	omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
 	dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);
 
-	/* perform TLL soft reset, and wait until reset is complete */
-	usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
-			OMAP_USBTLL_SYSCONFIG_SOFTRESET);
-
-	/* Wait for TLL reset to complete */
-	timeout = jiffies + msecs_to_jiffies(1000);
-	while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
-			& OMAP_USBTLL_SYSSTATUS_RESETDONE)) {
-		cpu_relax();
-
-		if (time_after(jiffies, timeout)) {
-			dev_dbg(dev, "operation timed out\n");
-			ret = -EINVAL;
-			goto err_tll;
-		}
-	}
-
-	dev_dbg(dev, "TLL RESET DONE\n");
-
-	/* (1<<3) = no idle mode only for initial debugging */
-	usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
-			OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
-			OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
-			OMAP_USBTLL_SYSCONFIG_AUTOIDLE);
-
-	/* Put UHH in NoIdle/NoStandby mode */
-	reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG);
-	if (is_omap_usbhs_rev1(omap)) {
-		reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
-				| OMAP_UHH_SYSCONFIG_SIDLEMODE
-				| OMAP_UHH_SYSCONFIG_CACTIVITY
-				| OMAP_UHH_SYSCONFIG_MIDLEMODE);
-		reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
-
-
-	} else if (is_omap_usbhs_rev2(omap)) {
-		reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR;
-		reg |= OMAP4_UHH_SYSCONFIG_NOIDLE;
-		reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR;
-		reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY;
-	}
-
-	usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
-
 	reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
 	/* setup ULPI bypass and burst configurations */
 	reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
@@ -823,49 +560,6 @@  static int usbhs_enable(struct device *dev)
 		reg &= ~OMAP4_P1_MODE_CLEAR;
 		reg &= ~OMAP4_P2_MODE_CLEAR;
 
-		if (is_ehci_phy_mode(pdata->port_mode[0])) {
-			ret = clk_set_parent(omap->utmi_p1_fck,
-						omap->xclk60mhsp1_ck);
-			if (ret != 0) {
-				dev_err(dev, "xclk60mhsp1_ck set parent"
-				"failed error:%d\n", ret);
-				goto err_tll;
-			}
-		} else if (is_ehci_tll_mode(pdata->port_mode[0])) {
-			ret = clk_set_parent(omap->utmi_p1_fck,
-						omap->init_60m_fclk);
-			if (ret != 0) {
-				dev_err(dev, "init_60m_fclk set parent"
-				"failed error:%d\n", ret);
-				goto err_tll;
-			}
-			clk_enable(omap->usbhost_p1_fck);
-			clk_enable(omap->usbtll_p1_fck);
-		}
-
-		if (is_ehci_phy_mode(pdata->port_mode[1])) {
-			ret = clk_set_parent(omap->utmi_p2_fck,
-						omap->xclk60mhsp2_ck);
-			if (ret != 0) {
-				dev_err(dev, "xclk60mhsp1_ck set parent"
-					"failed error:%d\n", ret);
-				goto err_tll;
-			}
-		} else if (is_ehci_tll_mode(pdata->port_mode[1])) {
-			ret = clk_set_parent(omap->utmi_p2_fck,
-						omap->init_60m_fclk);
-			if (ret != 0) {
-				dev_err(dev, "init_60m_fclk set parent"
-				"failed error:%d\n", ret);
-				goto err_tll;
-			}
-			clk_enable(omap->usbhost_p2_fck);
-			clk_enable(omap->usbtll_p2_fck);
-		}
-
-		clk_enable(omap->utmi_p1_fck);
-		clk_enable(omap->utmi_p2_fck);
-
 		if (is_ehci_tll_mode(pdata->port_mode[0]) ||
 			(is_ohci_port(pdata->port_mode[0])))
 			reg |= OMAP4_P1_MODE_TLL;
@@ -911,12 +605,15 @@  static int usbhs_enable(struct device *dev)
 				(pdata->ehci_data->reset_gpio_port[1], 1);
 	}
 
-end_count:
-	omap->count++;
 	spin_unlock_irqrestore(&omap->lock, flags);
-	return 0;
+	pm_runtime_put_sync(dev);
+}
+
+static void omap_usbhs_deinit(struct device *dev)
+{
+	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
+	struct usbhs_omap_platform_data	*pdata = &omap->platdata;
 
-err_tll:
 	if (pdata->ehci_data->phy_reset) {
 		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
 			gpio_free(pdata->ehci_data->reset_gpio_port[0]);
@@ -924,123 +621,257 @@  err_tll:
 		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
 			gpio_free(pdata->ehci_data->reset_gpio_port[1]);
 	}
-
-	clk_disable(omap->usbtll_ick);
-	clk_disable(omap->usbtll_fck);
-	clk_disable(omap->usbhost_fs_fck);
-	clk_disable(omap->usbhost_hs_fck);
-	clk_disable(omap->usbhost_ick);
-	spin_unlock_irqrestore(&omap->lock, flags);
-	return ret;
 }
 
-static void usbhs_disable(struct device *dev)
+
+/**
+ * usbhs_omap_probe - initialize TI-based HCDs
+ *
+ * Allocates basic resources for this USB host controller.
+ */
+static int __devinit usbhs_omap_probe(struct platform_device *pdev)
 {
-	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
-	struct usbhs_omap_platform_data	*pdata = &omap->platdata;
-	unsigned long			flags = 0;
-	unsigned long			timeout;
+	struct device			*dev =  &pdev->dev;
+	struct usbhs_omap_platform_data	*pdata = dev->platform_data;
+	struct usbhs_hcd_omap		*omap;
+	struct resource			*res;
+	int				ret = 0;
+	int				i;
 
-	dev_dbg(dev, "stopping TI HSUSB Controller\n");
+	if (!pdata) {
+		dev_err(dev, "Missing platform data\n");
+		ret = -ENOMEM;
+		goto end_probe;
+	}
 
-	spin_lock_irqsave(&omap->lock, flags);
+	omap = kzalloc(sizeof(*omap), GFP_KERNEL);
+	if (!omap) {
+		dev_err(dev, "Memory allocation failed\n");
+		ret = -ENOMEM;
+		goto end_probe;
+	}
 
-	if (omap->count == 0)
-		goto end_disble;
+	spin_lock_init(&omap->lock);
 
-	omap->count--;
+	for (i = 0; i < OMAP3_HS_USB_PORTS; i++)
+		omap->platdata.port_mode[i] = pdata->port_mode[i];
 
-	if (omap->count != 0)
-		goto end_disble;
+	omap->platdata.ehci_data = pdata->ehci_data;
+	omap->platdata.ohci_data = pdata->ohci_data;
 
-	/* Reset OMAP modules for insmod/rmmod to work */
-	usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG,
-			is_omap_usbhs_rev2(omap) ?
-			OMAP4_UHH_SYSCONFIG_SOFTRESET :
-			OMAP_UHH_SYSCONFIG_SOFTRESET);
+	pm_runtime_enable(dev);
 
-	timeout = jiffies + msecs_to_jiffies(100);
-	while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS)
-				& (1 << 0))) {
-		cpu_relax();
+	omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
+	if (IS_ERR(omap->utmi_p1_fck)) {
+		ret = PTR_ERR(omap->utmi_p1_fck);
+		dev_err(dev, "utmi_p1_gfclk failed error:%d\n",	ret);
+		goto err_end;
+	}
 
-		if (time_after(jiffies, timeout))
-			dev_dbg(dev, "operation timed out\n");
+	omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck");
+	if (IS_ERR(omap->xclk60mhsp1_ck)) {
+		ret = PTR_ERR(omap->xclk60mhsp1_ck);
+		dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret);
+		goto err_utmi_p1_fck;
+	}
+
+	omap->utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk");
+	if (IS_ERR(omap->utmi_p2_fck)) {
+		ret = PTR_ERR(omap->utmi_p2_fck);
+		dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret);
+		goto err_xclk60mhsp1_ck;
+	}
+
+	omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck");
+	if (IS_ERR(omap->xclk60mhsp2_ck)) {
+		ret = PTR_ERR(omap->xclk60mhsp2_ck);
+		dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret);
+		goto err_utmi_p2_fck;
 	}
 
-	while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS)
-				& (1 << 1))) {
-		cpu_relax();
+	omap->usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk");
+	if (IS_ERR(omap->usbhost_p1_fck)) {
+		ret = PTR_ERR(omap->usbhost_p1_fck);
+		dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret);
+		goto err_xclk60mhsp2_ck;
+	}
 
-		if (time_after(jiffies, timeout))
-			dev_dbg(dev, "operation timed out\n");
+	omap->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk");
+	if (IS_ERR(omap->usbtll_p1_fck)) {
+		ret = PTR_ERR(omap->usbtll_p1_fck);
+		dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret);
+		goto err_usbhost_p1_fck;
+	}
+
+	omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk");
+	if (IS_ERR(omap->usbhost_p2_fck)) {
+		ret = PTR_ERR(omap->usbhost_p2_fck);
+		dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret);
+		goto err_usbtll_p1_fck;
 	}
 
-	while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS)
-				& (1 << 2))) {
-		cpu_relax();
+	omap->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk");
+	if (IS_ERR(omap->usbtll_p2_fck)) {
+		ret = PTR_ERR(omap->usbtll_p2_fck);
+		dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret);
+		goto err_usbhost_p2_fck;
+	}
 
-		if (time_after(jiffies, timeout))
-			dev_dbg(dev, "operation timed out\n");
+	omap->init_60m_fclk = clk_get(dev, "init_60m_fclk");
+	if (IS_ERR(omap->init_60m_fclk)) {
+		ret = PTR_ERR(omap->init_60m_fclk);
+		dev_err(dev, "init_60m_fclk failed error:%d\n", ret);
+		goto err_usbtll_p2_fck;
 	}
 
-	usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1 << 1));
+	if (is_ehci_phy_mode(pdata->port_mode[0])) {
+		/* for OMAP3 , the clk set paretn fails */
+		ret = clk_set_parent(omap->utmi_p1_fck,
+					omap->xclk60mhsp1_ck);
+		if (ret != 0)
+			dev_err(dev, "xclk60mhsp1_ck set parent"
+				"failed error:%d\n", ret);
+	} else if (is_ehci_tll_mode(pdata->port_mode[0])) {
+		ret = clk_set_parent(omap->utmi_p1_fck,
+					omap->init_60m_fclk);
+		if (ret != 0)
+			dev_err(dev, "init_60m_fclk set parent"
+				"failed error:%d\n", ret);
+	}
 
-	while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
-				& (1 << 0))) {
-		cpu_relax();
+	if (is_ehci_phy_mode(pdata->port_mode[1])) {
+		ret = clk_set_parent(omap->utmi_p2_fck,
+					omap->xclk60mhsp2_ck);
+		if (ret != 0)
+			dev_err(dev, "xclk60mhsp2_ck set parent"
+					"failed error:%d\n", ret);
+	} else if (is_ehci_tll_mode(pdata->port_mode[1])) {
+		ret = clk_set_parent(omap->utmi_p2_fck,
+						omap->init_60m_fclk);
+		if (ret != 0)
+			dev_err(dev, "init_60m_fclk set parent"
+				"failed error:%d\n", ret);
+	}
 
-		if (time_after(jiffies, timeout))
-			dev_dbg(dev, "operation timed out\n");
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uhh");
+	if (!res) {
+		dev_err(dev, "UHH EHCI get resource failed\n");
+		ret = -ENODEV;
+		goto err_init_60m_fclk;
 	}
 
-	if (is_omap_usbhs_rev2(omap)) {
-		if (is_ehci_tll_mode(pdata->port_mode[0]))
-			clk_disable(omap->usbtll_p1_fck);
-		if (is_ehci_tll_mode(pdata->port_mode[1]))
-			clk_disable(omap->usbtll_p2_fck);
-		clk_disable(omap->utmi_p2_fck);
-		clk_disable(omap->utmi_p1_fck);
+	omap->uhh_base = ioremap(res->start, resource_size(res));
+	if (!omap->uhh_base) {
+		dev_err(dev, "UHH ioremap failed\n");
+		ret = -ENOMEM;
+		goto err_init_60m_fclk;
 	}
 
-	clk_disable(omap->usbtll_ick);
-	clk_disable(omap->usbtll_fck);
-	clk_disable(omap->usbhost_fs_fck);
-	clk_disable(omap->usbhost_hs_fck);
-	clk_disable(omap->usbhost_ick);
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tll");
+	if (!res) {
+		dev_err(dev, "UHH EHCI get resource failed\n");
+		ret = -ENODEV;
+		goto err_tll;
+	}
 
-	/* The gpio_free migh sleep; so unlock the spinlock */
-	spin_unlock_irqrestore(&omap->lock, flags);
+	omap->tll_base = ioremap(res->start, resource_size(res));
+	if (!omap->tll_base) {
+		dev_err(dev, "TLL ioremap failed\n");
+		ret = -ENOMEM;
+		goto err_tll;
+	}
 
-	if (pdata->ehci_data->phy_reset) {
-		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
-			gpio_free(pdata->ehci_data->reset_gpio_port[0]);
+	platform_set_drvdata(pdev, omap);
 
-		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
-			gpio_free(pdata->ehci_data->reset_gpio_port[1]);
+	ret = omap_usbhs_alloc_children(pdev);
+	if (ret) {
+		dev_err(dev, "omap_usbhs_alloc_children failed\n");
+		goto err_alloc;
 	}
-	return;
 
-end_disble:
-	spin_unlock_irqrestore(&omap->lock, flags);
-}
+	omap_usbhs_init(dev);
 
-int omap_usbhs_enable(struct device *dev)
-{
-	return  usbhs_enable(dev->parent);
+	goto end_probe;
+
+err_alloc:
+	iounmap(omap->tll_base);
+
+err_tll:
+	iounmap(omap->uhh_base);
+
+err_init_60m_fclk:
+	clk_put(omap->init_60m_fclk);
+
+err_usbtll_p2_fck:
+	clk_put(omap->usbtll_p2_fck);
+
+err_usbhost_p2_fck:
+	clk_put(omap->usbhost_p2_fck);
+
+err_usbtll_p1_fck:
+	clk_put(omap->usbtll_p1_fck);
+
+err_usbhost_p1_fck:
+	clk_put(omap->usbhost_p1_fck);
+
+err_xclk60mhsp2_ck:
+	clk_put(omap->xclk60mhsp2_ck);
+
+err_utmi_p2_fck:
+	clk_put(omap->utmi_p2_fck);
+
+err_xclk60mhsp1_ck:
+	clk_put(omap->xclk60mhsp1_ck);
+
+err_utmi_p1_fck:
+	clk_put(omap->utmi_p1_fck);
+
+err_end:
+	pm_runtime_disable(dev);
+	kfree(omap);
+
+end_probe:
+	return ret;
 }
-EXPORT_SYMBOL_GPL(omap_usbhs_enable);
 
-void omap_usbhs_disable(struct device *dev)
+/**
+ * usbhs_omap_remove - shutdown processing for UHH & TLL HCDs
+ * @pdev: USB Host Controller being removed
+ *
+ * Reverses the effect of usbhs_omap_probe().
+ */
+static int __devexit usbhs_omap_remove(struct platform_device *pdev)
 {
-	usbhs_disable(dev->parent);
+	struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
+
+	omap_usbhs_deinit(&pdev->dev);
+	iounmap(omap->tll_base);
+	iounmap(omap->uhh_base);
+	clk_put(omap->init_60m_fclk);
+	clk_put(omap->usbtll_p2_fck);
+	clk_put(omap->usbhost_p2_fck);
+	clk_put(omap->usbtll_p1_fck);
+	clk_put(omap->usbhost_p1_fck);
+	clk_put(omap->xclk60mhsp2_ck);
+	clk_put(omap->utmi_p2_fck);
+	clk_put(omap->xclk60mhsp1_ck);
+	clk_put(omap->utmi_p1_fck);
+	pm_runtime_disable(&pdev->dev);
+	kfree(omap);
+
+	return 0;
 }
-EXPORT_SYMBOL_GPL(omap_usbhs_disable);
+
+static const struct dev_pm_ops usbhsomap_dev_pm_ops = {
+	.runtime_suspend	= usbhs_runtime_suspend,
+	.runtime_resume		= usbhs_runtime_resume,
+};
 
 static struct platform_driver usbhs_omap_driver = {
 	.driver = {
 		.name		= (char *)usbhs_driver_name,
 		.owner		= THIS_MODULE,
+		.pm		= &usbhsomap_dev_pm_ops,
 	},
 	.remove		= __exit_p(usbhs_omap_remove),
 };
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 4524032..82cd3ea 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -41,6 +41,7 @@ 
 #include <linux/usb/ulpi.h>
 #include <plat/usb.h>
 #include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
 
 /* EHCI Register Set */
 #define EHCI_INSNREG04					(0xA0)
@@ -190,11 +191,8 @@  static int ehci_hcd_omap_probe(struct platform_device *pdev)
 		}
 	}
 
-	ret = omap_usbhs_enable(dev);
-	if (ret) {
-		dev_err(dev, "failed to start usbhs with err %d\n", ret);
-		goto err_enable;
-	}
+	pm_runtime_enable(dev);
+	pm_runtime_get_sync(dev);
 
 	/*
 	 * An undocumented "feature" in the OMAP3 EHCI controller,
@@ -240,11 +238,8 @@  static int ehci_hcd_omap_probe(struct platform_device *pdev)
 	return 0;
 
 err_add_hcd:
-	omap_usbhs_disable(dev);
-
-err_enable:
 	disable_put_regulator(pdata);
-	usb_put_hcd(hcd);
+	pm_runtime_put_sync(dev);
 
 err_io:
 	iounmap(regs);
@@ -266,10 +261,12 @@  static int ehci_hcd_omap_remove(struct platform_device *pdev)
 	struct usb_hcd *hcd	= dev_get_drvdata(dev);
 
 	usb_remove_hcd(hcd);
-	omap_usbhs_disable(dev);
 	disable_put_regulator(dev->platform_data);
 	iounmap(hcd->regs);
 	usb_put_hcd(hcd);
+	pm_runtime_put_sync(dev);
+	pm_runtime_disable(dev);
+
 	return 0;
 }
 
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
index 6048f2f..6cfedaf 100644
--- a/drivers/usb/host/ohci-omap3.c
+++ b/drivers/usb/host/ohci-omap3.c
@@ -31,6 +31,7 @@ 
 
 #include <linux/platform_device.h>
 #include <plat/usb.h>
+#include <linux/pm_runtime.h>
 
 /*-------------------------------------------------------------------------*/
 
@@ -134,7 +135,7 @@  static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev)
 	int			irq;
 
 	if (usb_disabled())
-		goto err_end;
+		return -ENODEV;
 
 	if (!dev->parent) {
 		dev_err(dev, "Missing parent device\n");
@@ -172,11 +173,8 @@  static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev)
 	hcd->rsrc_len = resource_size(res);
 	hcd->regs =  regs;
 
-	ret = omap_usbhs_enable(dev);
-	if (ret) {
-		dev_dbg(dev, "failed to start ohci\n");
-		goto err_end;
-	}
+	pm_runtime_enable(dev);
+	pm_runtime_get_sync(dev);
 
 	ohci_hcd_init(hcd_to_ohci(hcd));
 
@@ -189,9 +187,7 @@  static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev)
 	return 0;
 
 err_add_hcd:
-	omap_usbhs_disable(dev);
-
-err_end:
+	pm_runtime_put_sync(dev);
 	usb_put_hcd(hcd);
 
 err_io:
@@ -220,9 +216,9 @@  static int __devexit ohci_hcd_omap3_remove(struct platform_device *pdev)
 
 	iounmap(hcd->regs);
 	usb_remove_hcd(hcd);
-	omap_usbhs_disable(dev);
+	pm_runtime_put_sync(dev);
+	pm_runtime_disable(dev);
 	usb_put_hcd(hcd);
-
 	return 0;
 }