summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorMartin Chi <mchi@nvidia.com>2014-01-11 10:42:41 +0800
committerMartin Chi <mchi@nvidia.com>2014-01-12 17:41:54 -0800
commit2afc8fda56f76e8809e09a7180729e8c18e8589c (patch)
tree902958a4253fe294f0a05110791f52f1971228b1 /arch
parent7376643a34952cd0807855c35a27d15c8449477d (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.h10
-rw-r--r--arch/arm/mach-tegra/tegra11x_usb_phy.c66
-rw-r--r--arch/arm/mach-tegra/tegra_usb_pmc.c39
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);
}