Message ID | 1314196260-9578-6-git-send-email-keshava_mgowda@ti.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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
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 --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; }