diff options
author | Martin Chi <mchi@nvidia.com> | 2014-01-11 10:42:41 +0800 |
---|---|---|
committer | Martin Chi <mchi@nvidia.com> | 2014-01-12 17:41:54 -0800 |
commit | 2afc8fda56f76e8809e09a7180729e8c18e8589c (patch) | |
tree | 902958a4253fe294f0a05110791f52f1971228b1 /arch | |
parent | 7376643a34952cd0807855c35a27d15c8449477d (diff) |
Arm: tegra: usb: set run bit after disabling PMC
Set run bit soon after disabling the PMC so that
the delay in releasing the pmc_lock is avoided.
Also add delay in phy_restore_end so that the resume
will driven for minimum of 20ms.
Bug 1264731
Bug 1382457
Bug 1438066
Change-Id: If4d53359d8a3f33898ed0663cbdf7d4c8310bcf9
Signed-off-by: Petlozu Pravareshwar <petlozup@nvidia.com>
Reviewed-on: http://git-master/r/309449
Reviewed-by: Riham Haidar <rhaidar@nvidia.com>
Tested-by: Riham Haidar <rhaidar@nvidia.com>
Signed-off-by: Martin Chi <mchi@nvidia.com>
Reviewed-on: http://git-master/r/354696
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-tegra/include/mach/tegra_usb_pmc.h | 10 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra11x_usb_phy.c | 66 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra_usb_pmc.c | 39 |
3 files changed, 58 insertions, 57 deletions
diff --git a/arch/arm/mach-tegra/include/mach/tegra_usb_pmc.h b/arch/arm/mach-tegra/include/mach/tegra_usb_pmc.h index 3d4558ecaa90..d28a5b5807e8 100644 --- a/arch/arm/mach-tegra/include/mach/tegra_usb_pmc.h +++ b/arch/arm/mach-tegra/include/mach/tegra_usb_pmc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -38,6 +38,10 @@ #define USB_PORTSC_LINE_DM_SET (1 << 0) #define USB_PORTSC_LINE_DP_SET (1 << 1) +#define USB_USBCMD 0x130 +#define USB_USBCMD_RS (1 << 0) +#define USB_CMD_RESET (1<<1) + #define HOSTPC1_DEVLC 0x1b4 #define HOSTPC1_DEVLC_PHCD (1 << 22) #define HOSTPC1_DEVLC_PTS(x) (((x) & 0x7) << 29) @@ -249,7 +253,8 @@ struct tegra_usb_pmc_ops { void (*setup_pmc_wake_detect)(struct tegra_usb_pmc_data *pmc_data); void (*powerup_pmc_wake_detect)(struct tegra_usb_pmc_data *pmc_data); void (*powerdown_pmc_wake_detect)(struct tegra_usb_pmc_data *pmc_data); - void (*disable_pmc_bus_ctrl)(struct tegra_usb_pmc_data *pmc_data); + void (*disable_pmc_bus_ctrl)(struct tegra_usb_pmc_data *pmc_data, + int enable_sof); void (*power_down_pmc)(struct tegra_usb_pmc_data *pmc_data); }; @@ -262,6 +267,7 @@ struct tegra_usb_pmc_data { enum tegra_usb_phy_interface phy_type; enum usb_pmc_port_speed port_speed; struct tegra_usb_pmc_ops *pmc_ops; + void __iomem *usb_base; }; void tegra_usb_pmc_init(struct tegra_usb_pmc_data *pmc_data); diff --git a/arch/arm/mach-tegra/tegra11x_usb_phy.c b/arch/arm/mach-tegra/tegra11x_usb_phy.c index 945a10e9de84..9e67dc5ed645 100644 --- a/arch/arm/mach-tegra/tegra11x_usb_phy.c +++ b/arch/arm/mach-tegra/tegra11x_usb_phy.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-tegra/tegra11x_usb_phy.c * - * Copyright (c) 2012-2013 NVIDIA Corporation. All rights reserved. + * Copyright (c) 2012-2014 NVIDIA Corporation. All rights reserved. * * * This software is licensed under the terms of the GNU General Public @@ -400,6 +400,7 @@ static void pmc_init(struct tegra_usb_phy *phy) pmc_data[phy->inst].instance = phy->inst; pmc_data[phy->inst].phy_type = phy->pdata->phy_intf; pmc_data[phy->inst].controller_type = TEGRA_USB_2_0; + pmc_data[phy->inst].usb_base = phy->regs; tegra_usb_pmc_init(&pmc_data[phy->inst]); } @@ -705,11 +706,7 @@ static void utmi_phy_close(struct tegra_usb_phy *phy) val = tegra_usb_pmc_reg_read(PMC_SLEEP_CFG); if (val & UTMIP_MASTER_ENABLE(phy->inst)) { - val = readl(base + UTMIP_PMC_WAKEUP0); - val &= ~EVENT_INT_ENB; - writel(val, base + UTMIP_PMC_WAKEUP0); - - pmc->pmc_ops->disable_pmc_bus_ctrl(pmc); + pmc->pmc_ops->disable_pmc_bus_ctrl(pmc, 0); phy->pmc_remote_wakeup = false; phy->pmc_hotplug_wakeup = false; @@ -783,18 +780,13 @@ static int utmi_phy_pre_resume(struct tegra_usb_phy *phy, bool remote_wakeup) { unsigned long val; unsigned int inst = phy->inst; - void __iomem *base = phy->regs; struct tegra_usb_pmc_data *pmc = &pmc_data[phy->inst]; DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst); val = tegra_usb_pmc_reg_read(PMC_SLEEP_CFG); if (val & UTMIP_MASTER_ENABLE(inst)) { if (!remote_wakeup) { - val = readl(base + UTMIP_PMC_WAKEUP0); - val &= ~EVENT_INT_ENB; - writel(val, base + UTMIP_PMC_WAKEUP0); - - pmc->pmc_ops->disable_pmc_bus_ctrl(pmc); + pmc->pmc_ops->disable_pmc_bus_ctrl(pmc, 0); phy->pmc_remote_wakeup = false; phy->pmc_hotplug_wakeup = false; @@ -1156,10 +1148,7 @@ static void utmi_phy_restore_end(struct tegra_usb_phy *phy) PHY_DBG("%s PMC FPR" \ "timeout val = 0x%x instance = %d\n", \ __func__, (u32)val, phy->inst); - val = readl(base + UTMIP_PMC_WAKEUP0); - val &= ~EVENT_INT_ENB; - writel(val, base + UTMIP_PMC_WAKEUP0); - pmc->pmc_ops->disable_pmc_bus_ctrl(pmc); + pmc->pmc_ops->disable_pmc_bus_ctrl(pmc, 0); phy->pmc_remote_wakeup = false; phy->pmc_hotplug_wakeup = false; return; @@ -1167,20 +1156,14 @@ static void utmi_phy_restore_end(struct tegra_usb_phy *phy) wait_time_us--; } while (val & (USB_PORTSC_RESUME | USB_PORTSC_SUSP)); + /* Add delay sothat resume will be driven for more than 20 ms */ + mdelay(10); local_irq_save(flags); - /* disable PMC master control */ - val = readl(base + UTMIP_PMC_WAKEUP0); - val &= ~EVENT_INT_ENB; - writel(val, base + UTMIP_PMC_WAKEUP0); - pmc->pmc_ops->disable_pmc_bus_ctrl(pmc); + pmc->pmc_ops->disable_pmc_bus_ctrl(pmc, 1); phy->pmc_remote_wakeup = false; phy->pmc_hotplug_wakeup = false; PHY_DBG("%s DISABLE_PMC inst = %d\n", __func__, phy->inst); - val = readl(base + USB_USBCMD); - val |= USB_USBCMD_RS; - writel(val, base + USB_USBCMD); - local_irq_restore(flags); if (usb_phy_reg_status_wait(base + USB_USBCMD, USB_USBCMD_RS, @@ -1198,10 +1181,7 @@ static void utmi_phy_restore_end(struct tegra_usb_phy *phy) pr_err("%s: timeout waiting for SOF\n", __func__); } } else { - val = readl(base + UTMIP_PMC_WAKEUP0); - val &= ~EVENT_INT_ENB; - writel(val, base + UTMIP_PMC_WAKEUP0); - pmc->pmc_ops->disable_pmc_bus_ctrl(pmc); + pmc->pmc_ops->disable_pmc_bus_ctrl(pmc, 0); phy->pmc_remote_wakeup = false; phy->pmc_hotplug_wakeup = false; PHY_DBG("%s DISABLE_PMC inst = %d\n", __func__, phy->inst); @@ -1233,10 +1213,7 @@ static int utmi_phy_resume(struct tegra_usb_phy *phy) usb_phy_bringup_host_controller(phy); utmi_phy_restore_end(phy); } else { - val = readl(base + UTMIP_PMC_WAKEUP0); - val &= ~EVENT_INT_ENB; - writel(val, base + UTMIP_PMC_WAKEUP0); - pmc->pmc_ops->disable_pmc_bus_ctrl(pmc); + pmc->pmc_ops->disable_pmc_bus_ctrl(pmc, 0); phy->pmc_remote_wakeup = false; phy->pmc_hotplug_wakeup = false; @@ -1458,7 +1435,7 @@ static void utmi_phy_pmc_disable(struct tegra_usb_phy *phy) struct tegra_usb_pmc_data *pmc = &pmc_data[phy->inst]; if (phy->pdata->u_data.host.turn_off_vbus_on_lp0 && phy->pdata->port_otg) { - pmc->pmc_ops->disable_pmc_bus_ctrl(pmc); + pmc->pmc_ops->disable_pmc_bus_ctrl(pmc, 0); pmc->pmc_ops->powerdown_pmc_wake_detect(pmc); } } @@ -1546,9 +1523,6 @@ static void uhsic_phy_restore_start(struct tegra_usb_phy *phy) DBG("%s: uhsic remote wakeup detected\n", __func__); } else { if (!((UHSIC_STROBE_VAL(inst) | UHSIC_DATA_VAL(inst)) & val)) { - val = readl(base + UHSIC_PMC_WAKEUP0); - val &= ~EVENT_INT_ENB; - writel(val, base + UHSIC_PMC_WAKEUP0); /* * If pmc wakeup is detected after putting controller @@ -1567,7 +1541,7 @@ static void uhsic_phy_restore_start(struct tegra_usb_phy *phy) phy->ctrlr_suspended = false; } - pmc->pmc_ops->disable_pmc_bus_ctrl(pmc); + pmc->pmc_ops->disable_pmc_bus_ctrl(pmc, 0); phy->pmc_remote_wakeup = false; } else { DBG("%s(%d): setting pretend connect\n", __func__, __LINE__); @@ -1602,10 +1576,6 @@ static void uhsic_phy_restore_end(struct tegra_usb_phy *phy) val = readl(base + USB_PORTSC); udelay(1); if (wait_time_us == 0) { - val = readl(base + UHSIC_PMC_WAKEUP0); - val &= ~EVENT_INT_ENB; - writel(val, base + UHSIC_PMC_WAKEUP0); - /* * If pmc wakeup is detected after putting controller * in suspend in usb_phy_bringup_host_cotroller, @@ -1623,7 +1593,7 @@ static void uhsic_phy_restore_end(struct tegra_usb_phy *phy) phy->ctrlr_suspended = false; } - pmc->pmc_ops->disable_pmc_bus_ctrl(pmc); + pmc->pmc_ops->disable_pmc_bus_ctrl(pmc, 0); phy->pmc_remote_wakeup = false; return; } @@ -1634,10 +1604,6 @@ static void uhsic_phy_restore_end(struct tegra_usb_phy *phy) local_irq_save(flags); irq_disabled = true; } - /* disable PMC master control */ - val = readl(base + UHSIC_PMC_WAKEUP0); - val &= ~EVENT_INT_ENB; - writel(val, base + UHSIC_PMC_WAKEUP0); /* * If pmc wakeup is detected after putting controller in suspend @@ -1654,13 +1620,9 @@ static void uhsic_phy_restore_end(struct tegra_usb_phy *phy) phy->ctrlr_suspended = false; } - pmc->pmc_ops->disable_pmc_bus_ctrl(pmc); + pmc->pmc_ops->disable_pmc_bus_ctrl(pmc, 1); phy->pmc_remote_wakeup = false; - /* Set RUN bit */ - val = readl(base + USB_USBCMD); - val |= USB_USBCMD_RS; - writel(val, base + USB_USBCMD); /* Restore local irq if disabled before */ if (irq_disabled) local_irq_restore(flags); diff --git a/arch/arm/mach-tegra/tegra_usb_pmc.c b/arch/arm/mach-tegra/tegra_usb_pmc.c index 71732197023f..3f37e0717656 100644 --- a/arch/arm/mach-tegra/tegra_usb_pmc.c +++ b/arch/arm/mach-tegra/tegra_usb_pmc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -337,15 +337,25 @@ static void utmip_setup_pmc_wake_detect(struct tegra_usb_pmc_data *pmc_data) spin_unlock_irqrestore(&pmc_lock, flags); } -static void utmip_phy_disable_pmc_bus_ctrl(struct tegra_usb_pmc_data *pmc_data) +static void utmip_phy_disable_pmc_bus_ctrl(struct tegra_usb_pmc_data *pmc_data, + int enable_sof) { unsigned long val; + void __iomem *usb_base; unsigned int inst = pmc_data->instance; + usb_base = pmc_data->usb_base; DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, pmc_data->instance); spin_lock_irqsave(&pmc_lock, flags); + if (pmc_data->controller_type == TEGRA_USB_2_0 && usb_base) { + /* disable PMC master control */ + val = readl(usb_base + UTMIP_PMC_WAKEUP0); + val &= ~EVENT_INT_ENB; + writel(val, usb_base + UTMIP_PMC_WAKEUP0); + } + val = readl(pmc_base + PMC_SLEEP_CFG); val &= ~UTMIP_WAKE_VAL(inst, 0xF); val |= UTMIP_WAKE_VAL(inst, WAKE_VAL_NONE); @@ -376,6 +386,12 @@ static void utmip_phy_disable_pmc_bus_ctrl(struct tegra_usb_pmc_data *pmc_data) val |= UTMIP_CLR_WAKE_ALARM(inst); writel(val, pmc_base + PMC_TRIGGERS); + if (pmc_data->controller_type == TEGRA_USB_2_0 && enable_sof == 1 && + usb_base) { + val = readl(usb_base + USB_USBCMD); + val |= USB_USBCMD_RS; + writel(val, usb_base + USB_USBCMD); + } spin_unlock_irqrestore(&pmc_lock, flags); } @@ -605,15 +621,25 @@ static void uhsic_setup_pmc_wake_detect(struct tegra_usb_pmc_data *pmc_data) DBG("%s:PMC enabled for HSIC remote wakeup\n", __func__); } -static void uhsic_phy_disable_pmc_bus_ctrl(struct tegra_usb_pmc_data *pmc_data) +static void uhsic_phy_disable_pmc_bus_ctrl(struct tegra_usb_pmc_data *pmc_data, + int enable_sof) { unsigned long val; + void __iomem *usb_base; unsigned int inst = pmc_data->instance; + usb_base = pmc_data->usb_base; DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, pmc_data->instance); spin_lock_irqsave(&pmc_lock, flags); + if (pmc_data->controller_type == TEGRA_USB_2_0 && usb_base) { + /* disable PMC master control */ + val = readl(usb_base + UHSIC_PMC_WAKEUP0); + val &= ~EVENT_INT_ENB; + writel(val, usb_base + UHSIC_PMC_WAKEUP0); + } + val = readl(pmc_base + PMC_UHSIC_SLEEP_CFG(inst)); val &= ~UHSIC_WAKE_VAL(inst, WAKE_VAL_ANY); val |= UHSIC_WAKE_VAL(inst, WAKE_VAL_NONE); @@ -633,6 +659,13 @@ static void uhsic_phy_disable_pmc_bus_ctrl(struct tegra_usb_pmc_data *pmc_data) val |= (UHSIC_CLR_WALK_PTR(inst) | UHSIC_CLR_WAKE_ALARM(inst)); writel(val, pmc_base + PMC_UHSIC_TRIGGERS(inst)); + if (pmc_data->controller_type == TEGRA_USB_2_0 && enable_sof == 1 && + usb_base) { + val = readl(usb_base + USB_USBCMD); + val |= USB_USBCMD_RS; + writel(val, usb_base + USB_USBCMD); + } + spin_unlock_irqrestore(&pmc_lock, flags); } |