diff options
author | Suresh Mangipudi <smangipudi@nvidia.com> | 2011-05-06 13:57:20 +0530 |
---|---|---|
committer | Niket Sirsi <nsirsi@nvidia.com> | 2011-05-19 17:49:40 -0700 |
commit | c20a54d503e859b8b9c62c6fb446fcfe273d433b (patch) | |
tree | cd62bf6bf64f77c482f560c67b902889e0773827 | |
parent | ee550c20967fccfae7b13f2fac6271ae17339f53 (diff) |
usb: host: tegra: hotplug detection of device
Add support for usb hotplug, this change will add the following:
vbus is left enabled.
Bug 796158
Change-Id: I3c3cfa0bf8858b3be2351fe753ceb2a0229ed15d
Reviewed-on: http://git-master/r/30686
Reviewed-by: Suresh Mangipudi <smangipudi@nvidia.com>
Tested-by: Suresh Mangipudi <smangipudi@nvidia.com>
Reviewed-by: Hanumanth Venkateswa Moganty <vmoganty@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Reviewed-by: Prashant Gaikwad <pgaikwad@nvidia.com>
-rw-r--r-- | arch/arm/mach-tegra/include/mach/usb_phy.h | 8 | ||||
-rw-r--r-- | arch/arm/mach-tegra/usb_phy.c | 107 | ||||
-rw-r--r-- | drivers/usb/gadget/fsl_tegra_udc.c | 11 | ||||
-rw-r--r-- | drivers/usb/gadget/fsl_udc_core.c | 16 | ||||
-rw-r--r-- | drivers/usb/gadget/fsl_usb2_udc.h | 8 | ||||
-rw-r--r-- | drivers/usb/host/ehci-tegra.c | 74 | ||||
-rw-r--r-- | drivers/usb/otg/tegra-otg.c | 1 |
7 files changed, 123 insertions, 102 deletions
diff --git a/arch/arm/mach-tegra/include/mach/usb_phy.h b/arch/arm/mach-tegra/include/mach/usb_phy.h index f805ca5d0795..0ff8f5545d31 100644 --- a/arch/arm/mach-tegra/include/mach/usb_phy.h +++ b/arch/arm/mach-tegra/include/mach/usb_phy.h @@ -99,17 +99,17 @@ struct tegra_usb_phy { struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode); -int tegra_usb_phy_power_on(struct tegra_usb_phy *phy); +int tegra_usb_phy_power_on(struct tegra_usb_phy *phy, bool is_dpd); void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy); void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy); -void tegra_usb_phy_power_off(struct tegra_usb_phy *phy); +void tegra_usb_phy_power_off(struct tegra_usb_phy *phy, bool is_dpd); -void tegra_usb_phy_preresume(struct tegra_usb_phy *phy); +void tegra_usb_phy_preresume(struct tegra_usb_phy *phy, bool is_dpd); -void tegra_usb_phy_postresume(struct tegra_usb_phy *phy); +void tegra_usb_phy_postresume(struct tegra_usb_phy *phy, bool is_dpd); void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy, enum tegra_usb_phy_port_speed port_speed); diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c index 47e0155cc80a..371f5f72dd0f 100644 --- a/arch/arm/mach-tegra/usb_phy.c +++ b/arch/arm/mach-tegra/usb_phy.c @@ -67,6 +67,7 @@ #define USB_WAKE_ON_DISCON_EN_DEV (1 << 4) #define USB_SUSP_CLR (1 << 5) #define USB_PHY_CLK_VALID (1 << 7) +#define USB_PHY_CLK_VALID_INT_ENB (1 << 9) #define UTMIP_RESET (1 << 11) #define UHSIC_RESET (1 << 11) #define UTMIP_PHY_ENABLE (1 << 12) @@ -395,7 +396,7 @@ static void utmip_pad_power_on(struct tegra_usb_phy *phy) clk_disable(phy->pad_clk); } -static int utmip_pad_power_off(struct tegra_usb_phy *phy) +static int utmip_pad_power_off(struct tegra_usb_phy *phy, bool is_dpd) { unsigned long val, flags; void __iomem *base = phy->pad_regs; @@ -409,7 +410,7 @@ static int utmip_pad_power_off(struct tegra_usb_phy *phy) spin_lock_irqsave(&utmip_pad_lock, flags); - if (--utmip_pad_count == 0) { + if (--utmip_pad_count == 0 && is_dpd) { val = readl(base + UTMIP_BIAS_CFG0); val |= UTMIP_OTGPD | UTMIP_BIASPD; writel(val, base + UTMIP_BIAS_CFG0); @@ -521,7 +522,7 @@ static void vbus_disable(int gpio) gpio_free(gpio); } -static int utmi_phy_power_on(struct tegra_usb_phy *phy) +static int utmi_phy_power_on(struct tegra_usb_phy *phy, bool is_dpd) { unsigned long val; void __iomem *base = phy->regs; @@ -650,24 +651,15 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy) val &= ~USB_PORTSC1_PTS(~0); writel(val, base + USB_PORTSC1); } - if (phy->mode == TEGRA_USB_PHY_MODE_HOST) { - vbus_enable(usb_phy_data[phy->instance].vbus_gpio); - } return 0; } -static void utmi_phy_power_off(struct tegra_usb_phy *phy) +static void utmi_phy_power_off(struct tegra_usb_phy *phy, bool is_dpd) { unsigned long val; void __iomem *base = phy->regs; - utmi_phy_clk_disable(phy); - - if (phy->mode == TEGRA_USB_PHY_MODE_HOST) { - vbus_disable(usb_phy_data[phy->instance].vbus_gpio); - } - if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) { val = readl(base + USB_SUSP_CTRL); val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0); @@ -675,30 +667,32 @@ static void utmi_phy_power_off(struct tegra_usb_phy *phy) writel(val, base + USB_SUSP_CTRL); } - val = readl(base + USB_SUSP_CTRL); - val |= UTMIP_RESET; - writel(val, base + USB_SUSP_CTRL); - - if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) { - val = readl(base + UTMIP_BAT_CHRG_CFG0); - val |= UTMIP_PD_CHRG; - writel(val, base + UTMIP_BAT_CHRG_CFG0); - } - - val = readl(base + UTMIP_XCVR_CFG0); - val |= UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN | - UTMIP_FORCE_PDZI_POWERDOWN; - writel(val, base + UTMIP_XCVR_CFG0); + val = readl(base + UTMIP_BAT_CHRG_CFG0); + val |= UTMIP_PD_CHRG; + writel(val, base + UTMIP_BAT_CHRG_CFG0); val = readl(base + UTMIP_XCVR_CFG1); val |= UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN | UTMIP_FORCE_PDDR_POWERDOWN; writel(val, base + UTMIP_XCVR_CFG1); - utmip_pad_power_off(phy); + if (phy->instance == 2) { + val = readl(base + USB_PORTSC1); + val |= USB_PORTSC1_WKCN; + writel(val, base + USB_PORTSC1); + } + + utmi_phy_clk_disable(phy); + + if (phy->instance == 2) { + val = readl(base + USB_SUSP_CTRL); + val |= USB_PHY_CLK_VALID_INT_ENB; + writel(val, base + USB_SUSP_CTRL); + } + utmip_pad_power_off(phy, is_dpd); } -static void utmi_phy_preresume(struct tegra_usb_phy *phy) +static void utmi_phy_preresume(struct tegra_usb_phy *phy, bool is_dpd) { unsigned long val; void __iomem *base = phy->regs; @@ -708,7 +702,7 @@ static void utmi_phy_preresume(struct tegra_usb_phy *phy) writel(val, base + UTMIP_TX_CFG0); } -static void utmi_phy_postresume(struct tegra_usb_phy *phy) +static void utmi_phy_postresume(struct tegra_usb_phy *phy, bool is_dpd) { unsigned long val; void __iomem *base = phy->regs; @@ -718,7 +712,7 @@ static void utmi_phy_postresume(struct tegra_usb_phy *phy) writel(val, base + UTMIP_TX_CFG0); } -static void uhsic_phy_postresume(struct tegra_usb_phy *phy) +static void uhsic_phy_postresume(struct tegra_usb_phy *phy, bool is_dpd) { unsigned long val; void __iomem *base = phy->regs; @@ -763,7 +757,7 @@ static void utmi_phy_restore_end(struct tegra_usb_phy *phy) udelay(10); } -static int ulpi_phy_power_on(struct tegra_usb_phy *phy) +static int ulpi_phy_power_on(struct tegra_usb_phy *phy, bool is_dpd) { int ret; unsigned long val; @@ -832,7 +826,7 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) return 0; } -static void ulpi_phy_power_off(struct tegra_usb_phy *phy) +static void ulpi_phy_power_off(struct tegra_usb_phy *phy, bool is_dpd) { unsigned long val; void __iomem *base = phy->regs; @@ -849,7 +843,7 @@ static void ulpi_phy_power_off(struct tegra_usb_phy *phy) clk_disable(phy->clk); } -static int null_phy_power_on(struct tegra_usb_phy *phy) +static int null_phy_power_on(struct tegra_usb_phy *phy, bool is_dpd) { const struct tegra_ulpi_trimmer default_trimmer = {0, 0, 4, 4}; unsigned long val; @@ -943,7 +937,7 @@ static int null_phy_power_on(struct tegra_usb_phy *phy) return 0; } -static void null_phy_power_off(struct tegra_usb_phy *phy) +static void null_phy_power_off(struct tegra_usb_phy *phy, bool is_dpd) { unsigned long val; void __iomem *base = phy->regs; @@ -953,7 +947,7 @@ static void null_phy_power_off(struct tegra_usb_phy *phy) writel(val, base + ULPI_TIMING_CTRL_0); } -static int uhsic_phy_power_on(struct tegra_usb_phy *phy) +static int uhsic_phy_power_on(struct tegra_usb_phy *phy, bool is_dpd) { unsigned long val; void __iomem *base = phy->regs; @@ -1035,7 +1029,7 @@ static int uhsic_phy_power_on(struct tegra_usb_phy *phy) return 0; } -static void uhsic_phy_power_off(struct tegra_usb_phy *phy) +static void uhsic_phy_power_off(struct tegra_usb_phy *phy, bool is_dpd) { unsigned long val; void __iomem *base = phy->regs; @@ -1184,6 +1178,10 @@ struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs, goto err1; } } + if (((phy->instance == 0) || (phy->instance == 2)) && + (phy->mode == TEGRA_USB_PHY_MODE_HOST)) { + vbus_enable(usb_phy_data[phy->instance].vbus_gpio); + } return phy; @@ -1195,7 +1193,7 @@ err0: return ERR_PTR(err); } -int tegra_usb_phy_power_on(struct tegra_usb_phy *phy) +int tegra_usb_phy_power_on(struct tegra_usb_phy *phy, bool is_dpd) { if (!phy->regulator_on) { regulator_enable(phy->reg_vdd); @@ -1204,27 +1202,27 @@ int tegra_usb_phy_power_on(struct tegra_usb_phy *phy) if (phy_is_ulpi(phy)) { struct tegra_ulpi_config *ulpi_config = phy->config; if (ulpi_config->inf_type == TEGRA_USB_LINK_ULPI) - return ulpi_phy_power_on(phy); + return ulpi_phy_power_on(phy, is_dpd); else if (ulpi_config->inf_type == TEGRA_USB_UHSIC) - return uhsic_phy_power_on(phy); + return uhsic_phy_power_on(phy, is_dpd); else - return null_phy_power_on(phy); + return null_phy_power_on(phy, is_dpd); } else - return utmi_phy_power_on(phy); + return utmi_phy_power_on(phy, is_dpd); } -void tegra_usb_phy_power_off(struct tegra_usb_phy *phy) +void tegra_usb_phy_power_off(struct tegra_usb_phy *phy, bool is_dpd) { if (phy_is_ulpi(phy)) { struct tegra_ulpi_config *ulpi_config = phy->config; if (ulpi_config->inf_type == TEGRA_USB_LINK_ULPI) - ulpi_phy_power_off(phy); + ulpi_phy_power_off(phy, is_dpd); else if (ulpi_config->inf_type == TEGRA_USB_UHSIC) - uhsic_phy_power_off(phy); + uhsic_phy_power_off(phy, is_dpd); else - null_phy_power_off(phy); + null_phy_power_off(phy, is_dpd); } else - utmi_phy_power_off(phy); + utmi_phy_power_off(phy, is_dpd); if (phy->regulator_on && (tegra_get_revision() >= TEGRA_REVISION_A03)) { regulator_disable(phy->reg_vdd); @@ -1232,23 +1230,21 @@ void tegra_usb_phy_power_off(struct tegra_usb_phy *phy) } } -void tegra_usb_phy_preresume(struct tegra_usb_phy *phy) +void tegra_usb_phy_preresume(struct tegra_usb_phy *phy, bool is_dpd) { if (!phy_is_ulpi(phy)) - utmi_phy_preresume(phy); + utmi_phy_preresume(phy, is_dpd); } -void tegra_usb_phy_postresume(struct tegra_usb_phy *phy) +void tegra_usb_phy_postresume(struct tegra_usb_phy *phy, bool is_dpd) { struct tegra_ulpi_config *config = phy->config; if ((phy->instance == 1) && (config->inf_type == TEGRA_USB_UHSIC)) - uhsic_phy_postresume(phy); + uhsic_phy_postresume(phy, is_dpd); else if (!phy_is_ulpi(phy)) - utmi_phy_postresume(phy); - - return 0; + utmi_phy_postresume(phy, is_dpd); } void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy, @@ -1285,6 +1281,9 @@ void tegra_usb_phy_close(struct tegra_usb_phy *phy) clk_put(phy->clk); } else utmip_pad_close(phy); + if (phy->mode == TEGRA_USB_PHY_MODE_HOST) { + vbus_disable(usb_phy_data[phy->instance].vbus_gpio); + } clk_disable(phy->pll_u); clk_put(phy->pll_u); regulator_put(phy->reg_vdd); diff --git a/drivers/usb/gadget/fsl_tegra_udc.c b/drivers/usb/gadget/fsl_tegra_udc.c index 8589ef781039..712636d8ee8e 100644 --- a/drivers/usb/gadget/fsl_tegra_udc.c +++ b/drivers/usb/gadget/fsl_tegra_udc.c @@ -80,8 +80,7 @@ int fsl_udc_clk_init(struct platform_device *pdev) err = PTR_ERR(phy); goto err1; } - - tegra_usb_phy_power_on(phy); + tegra_usb_phy_power_on(phy, true); return 0; err1: @@ -118,18 +117,18 @@ void fsl_udc_clk_release(void) clk_put(emc_clk); } -void fsl_udc_clk_suspend(void) +void fsl_udc_clk_suspend(bool is_dpd) { - tegra_usb_phy_power_off(phy); + tegra_usb_phy_power_off(phy, is_dpd); clk_disable(udc_clk); clk_disable(sclk_clk); clk_disable(emc_clk); } -void fsl_udc_clk_resume(void) +void fsl_udc_clk_resume(bool is_dpd) { clk_enable(emc_clk); clk_enable(sclk_clk); clk_enable(udc_clk); - tegra_usb_phy_power_on(phy); + tegra_usb_phy_power_on(phy, is_dpd); } diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 74ebe55a1ca0..c67230db46eb 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1216,9 +1216,9 @@ static int fsl_vbus_session(struct usb_gadget *gadget, int is_active) udc->vbus_active = 0; udc->usb_state = USB_STATE_DEFAULT; spin_unlock_irqrestore(&udc->lock, flags); - fsl_udc_clk_suspend(); + fsl_udc_clk_suspend(false); } else if (!udc->vbus_active && is_active) { - fsl_udc_clk_resume(); + fsl_udc_clk_resume(false); /* setup the controller in the device mode */ dr_controller_setup(udc); /* setup EP0 for setup packet */ @@ -2751,7 +2751,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) if (udc_controller->transceiver) { dr_controller_stop(udc_controller); dr_controller_reset(udc_controller); - fsl_udc_clk_suspend(); + fsl_udc_clk_suspend(false); udc_controller->vbus_active = 0; udc_controller->usb_state = USB_STATE_DEFAULT; otg_set_peripheral(udc_controller->transceiver, &udc_controller->gadget); @@ -2760,7 +2760,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev) #ifdef CONFIG_ARCH_TEGRA /* Power down the phy if cable is not connected */ if (!(fsl_readl(&usb_sys_regs->vbus_wakeup) & USB_SYS_VBUS_STATUS)) - fsl_udc_clk_suspend(); + fsl_udc_clk_suspend(false); #endif #endif @@ -2847,7 +2847,7 @@ static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state) if (udc_controller->transceiver) { udc_controller->transceiver->state = OTG_STATE_UNDEFINED; } - fsl_udc_clk_suspend(); + fsl_udc_clk_suspend(true); return 0; } @@ -2868,13 +2868,13 @@ static int fsl_udc_resume(struct platform_device *pdev) /* if there is no VBUS then power down the clocks and return */ return 0; } else { - fsl_udc_clk_resume(); + fsl_udc_clk_resume(true); /* Detected VBUS set the transceiver state to device mode */ udc_controller->transceiver->state = OTG_STATE_B_PERIPHERAL; } } else { /* enable the clocks to the controller */ - fsl_udc_clk_resume(); + fsl_udc_clk_resume(true); } #if defined(CONFIG_ARCH_TEGRA) @@ -2891,7 +2891,7 @@ static int fsl_udc_resume(struct platform_device *pdev) #endif /* Power down the phy if cable is not connected */ if (!(fsl_readl(&usb_sys_regs->vbus_wakeup) & USB_SYS_VBUS_STATUS)) - fsl_udc_clk_suspend(); + fsl_udc_clk_suspend(false); return 0; } diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index 99c36054e66c..19d113c03af6 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h @@ -587,8 +587,8 @@ struct platform_device; int fsl_udc_clk_init(struct platform_device *pdev); void fsl_udc_clk_finalize(struct platform_device *pdev); void fsl_udc_clk_release(void); -void fsl_udc_clk_suspend(void); -void fsl_udc_clk_resume(void); +void fsl_udc_clk_suspend(bool is_dpd); +void fsl_udc_clk_resume(bool is_dpd); #else static inline int fsl_udc_clk_init(struct platform_device *pdev) { @@ -600,10 +600,10 @@ static inline void fsl_udc_clk_finalize(struct platform_device *pdev) static inline void fsl_udc_clk_release(void) { } -static inline void fsl_udc_clk_suspend(void) +static inline void fsl_udc_clk_suspend(bool is_dpd) { } -static inline void fsl_udc_clk_resume(void) +static inline void fsl_udc_clk_resume(bool is_dpd) { } #endif diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index fab9edb4cc99..3a28122b451a 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -30,6 +30,10 @@ #define TEGRA_USB_SUSP_CLR (1 << 5) #define TEGRA_USB_PHY_CLK_VALID (1 << 7) #define TEGRA_USB_SRT (1 << 25) +#define TEGRA_USB_PHY_CLK_VALID_INT_ENB (1 << 9) + +#define TEGRA_USB_PORTSC1_OFFSET 0x184 +#define TEGRA_USB_PORTSC1_WKCN (1 << 20) #define TEGRA_LVL2_CLK_GATE_OVRB 0xfc #define TEGRA_USB2_CLK_OVR_ON (1 << 10) @@ -53,26 +57,43 @@ struct tegra_ehci_hcd { enum tegra_usb_phy_port_speed port_speed; }; -static void tegra_ehci_power_up(struct usb_hcd *hcd) +static void tegra_ehci_power_up(struct usb_hcd *hcd, bool is_dpd) { struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); clk_enable(tegra->emc_clk); clk_enable(tegra->sclk_clk); - clk_enable(tegra->clk); - tegra_usb_phy_power_on(tegra->phy); + tegra_usb_phy_power_on(tegra->phy, is_dpd); tegra->host_resumed = 1; } -static void tegra_ehci_power_down(struct usb_hcd *hcd) +static void tegra_ehci_power_down(struct usb_hcd *hcd, bool is_dpd) { struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); tegra->host_resumed = 0; - tegra_usb_phy_power_off(tegra->phy); - clk_disable(tegra->clk); - clk_disable(tegra->sclk_clk); + tegra_usb_phy_power_off(tegra->phy, is_dpd); clk_disable(tegra->emc_clk); + clk_disable(tegra->sclk_clk); +} + +static irqreturn_t tegra_ehci_irq (struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + u32 val; + + spin_lock (&ehci->lock); + val = readl(hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET); + val &= ~TEGRA_USB_PHY_CLK_VALID_INT_ENB; + writel(val , (hcd->regs + TEGRA_USB_SUSP_CTRL_OFFSET)); + + val = readl(hcd->regs + TEGRA_USB_PORTSC1_OFFSET); + val &= ~TEGRA_USB_PORTSC1_WKCN; + writel(val , (hcd->regs + TEGRA_USB_PORTSC1_OFFSET)); + + spin_unlock (&ehci->lock); + + return ehci_irq(hcd); } static int tegra_ehci_hub_control( @@ -94,7 +115,11 @@ static int tegra_ehci_hub_control( unsigned selector; struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); bool hsic = false; - + if (!tegra->host_resumed) { + if (buf) + memset (buf, 0, wLength); + return retval; + } if (tegra->phy->instance == 1) { struct tegra_ulpi_config *config = tegra->phy->config; hsic = (config->inf_type == TEGRA_USB_UHSIC); @@ -118,7 +143,7 @@ static int tegra_ehci_hub_control( if (tegra->port_resuming && !(temp & PORT_SUSPEND)) { /* Resume completed, re-enable disconnect detection */ tegra->port_resuming = 0; - tegra_usb_phy_postresume(tegra->phy); + tegra_usb_phy_postresume(tegra->phy, false); } } else if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) { temp = ehci_readl(ehci, status_reg); @@ -164,7 +189,7 @@ static int tegra_ehci_hub_control( goto done; /* Disable disconnect detection during port resume */ - tegra_usb_phy_preresume(tegra->phy); + tegra_usb_phy_preresume(tegra->phy, false); ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25); @@ -308,7 +333,7 @@ static void tegra_ehci_restart(struct usb_hcd *hcd) ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); } -static int tegra_usb_suspend(struct usb_hcd *hcd) +static int tegra_usb_suspend(struct usb_hcd *hcd, bool is_dpd) { struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); struct ehci_regs __iomem *hw = tegra->ehci->regs; @@ -325,15 +350,14 @@ static int tegra_usb_suspend(struct usb_hcd *hcd) tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3; ehci_halt(tegra->ehci); - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); spin_unlock_irqrestore(&tegra->ehci->lock, flags); - tegra_ehci_power_down(hcd); + tegra_ehci_power_down(hcd, is_dpd); return 0; } -static int tegra_usb_resume(struct usb_hcd *hcd) +static int tegra_usb_resume(struct usb_hcd *hcd, bool is_dpd) { struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); struct usb_device *udev = hcd->self.root_hub; @@ -349,7 +373,7 @@ static int tegra_usb_resume(struct usb_hcd *hcd) } set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - tegra_ehci_power_up(hcd); + tegra_ehci_power_up(hcd, is_dpd); if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) { /* Wait for the phy to detect new devices @@ -457,12 +481,12 @@ static void tegra_ehci_shutdown(struct usb_hcd *hcd) /* ehci_shutdown touches the USB controller registers, make sure * controller has clocks to it */ if (!tegra->host_resumed) - tegra_ehci_power_up(hcd); + tegra_ehci_power_up(hcd, false); ehci_shutdown(hcd); /* we are ready to shut down, powerdown the phy */ - tegra_ehci_power_down(hcd); + tegra_ehci_power_down(hcd, false); } static int tegra_ehci_setup(struct usb_hcd *hcd) @@ -508,7 +532,7 @@ static int tegra_ehci_bus_suspend(struct usb_hcd *hcd) error_status = ehci_bus_suspend(hcd); if (!error_status && tegra->power_down_on_bus_suspend) { - tegra_usb_suspend(hcd); + tegra_usb_suspend(hcd, false); tegra->bus_suspended = 1; } return error_status; @@ -519,11 +543,11 @@ static int tegra_ehci_bus_resume(struct usb_hcd *hcd) struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); if (tegra->bus_suspended && tegra->power_down_on_bus_suspend) { - tegra_usb_resume(hcd); + tegra_usb_resume(hcd, false); tegra->bus_suspended = 0; } - tegra_usb_phy_preresume(tegra->phy); + tegra_usb_phy_preresume(tegra->phy, false); tegra->port_resuming = 1; return ehci_bus_resume(hcd); } @@ -775,7 +799,7 @@ static const struct hc_driver tegra_ehci_hc_driver = { .flags = HCD_USB2 | HCD_MEMORY, .reset = tegra_ehci_setup, - .irq = ehci_irq, + .irq = tegra_ehci_irq, .start = ehci_run, .stop = ehci_stop, @@ -885,7 +909,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) goto fail_phy; } - err = tegra_usb_phy_power_on(tegra->phy); + err = tegra_usb_phy_power_on(tegra->phy, true); if (err) { dev_err(&pdev->dev, "Failed to power on the phy\n"); goto fail; @@ -966,7 +990,7 @@ static int tegra_ehci_resume(struct platform_device *pdev) if ((tegra->bus_suspended) && (tegra->power_down_on_bus_suspend)) return 0; - return tegra_usb_resume(hcd); + return tegra_usb_resume(hcd, true); } static int tegra_ehci_suspend(struct platform_device *pdev, pm_message_t state) @@ -980,7 +1004,7 @@ static int tegra_ehci_suspend(struct platform_device *pdev, pm_message_t state) if (time_before(jiffies, tegra->ehci->next_statechange)) msleep(10); - return tegra_usb_suspend(hcd); + return tegra_usb_suspend(hcd, true); } #endif @@ -1012,7 +1036,7 @@ static int tegra_ehci_remove(struct platform_device *pdev) usb_remove_hcd(hcd); usb_put_hcd(hcd); cancel_delayed_work(&tegra->work); - tegra_usb_phy_power_off(tegra->phy); + tegra_usb_phy_power_off(tegra->phy, true); tegra_usb_phy_close(tegra->phy); iounmap(hcd->regs); diff --git a/drivers/usb/otg/tegra-otg.c b/drivers/usb/otg/tegra-otg.c index 386bb8b922da..893b897f5957 100644 --- a/drivers/usb/otg/tegra-otg.c +++ b/drivers/usb/otg/tegra-otg.c @@ -342,7 +342,6 @@ static int tegra_otg_probe(struct platform_device *pdev) INIT_WORK (&tegra->work, irq_work); dev_info(&pdev->dev, "otg transceiver registered\n"); - clk_disable(tegra->clk); return 0; err_irq: |