On Thu, Aug 25, 2011 at 12:03 PM, Shubhrajyoti <shubhrajyoti@xxxxxx> wrote: > Hi Keshav, > Some minor comments > > On Wednesday 24 August 2011 08:01 PM, Keshava Munegowda wrote: >> >> From: Keshava Munegowda<Keshava_mgowda@xxxxxx> >> >> 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@xxxxxx> >> --- >> 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-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html