summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjoyw <joyw@nvidia.com>2013-09-06 12:55:48 +0800
committerHarry Hong <hhong@nvidia.com>2014-01-21 20:40:16 -0800
commit55932e69bf25963dcb400e031a9b0c85b20fdaab (patch)
tree33d3c49584187cb2a5aec815407618a6d83af7a3
parenta059003298f9474ef6a54179bb133002736f3c78 (diff)
xhci: tegra: fix DFE/CTLE control sequence
According to PG to adjust DEF and CTLE context save/restore programming sequence on T114 rel17 branch. Bug 1345950 Change-Id: Ie7ef0385ea70616ab69dd251d0b383cd9c62afa8 Signed-off-by: joyw <joyw@nvidia.com> Reviewed-on: http://git-master/r/271323 (cherry picked from commit 107b3dc2c5feb25e14cf29328323a0dfdec717ce) Reviewed-on: http://git-master/r/358118 Reviewed-by: Harry Hong <hhong@nvidia.com> Tested-by: Harry Hong <hhong@nvidia.com>
-rw-r--r--arch/arm/mach-tegra/include/mach/xusb.h3
-rw-r--r--drivers/usb/host/xhci-tegra.c83
-rw-r--r--drivers/usb/host/xhci-tegra.h14
3 files changed, 40 insertions, 60 deletions
diff --git a/arch/arm/mach-tegra/include/mach/xusb.h b/arch/arm/mach-tegra/include/mach/xusb.h
index b06ddb522534..e304bb47ce8a 100644
--- a/arch/arm/mach-tegra/include/mach/xusb.h
+++ b/arch/arm/mach-tegra/include/mach/xusb.h
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/include/mach/xusb.h
*
- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
*
* Author:
* Ajay Gupta <ajayg@nvidia.com>
@@ -29,6 +29,7 @@
*/
#define TEGRA_XUSB_SS_P0 (1 << 0)
#define TEGRA_XUSB_SS_P1 (1 << 1)
+#define XUSB_SS_PORT_COUNT (2)
#define TEGRA_XUSB_USB2_P0 (1 << 8)
#define TEGRA_XUSB_USB2_P1 (1 << 9)
#define TEGRA_XUSB_HSIC_P0 (1 << 16)
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index 47257b39a0d3..f7efbce73077 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -235,7 +235,7 @@ struct tegra_xhci_hcd {
bool hs_wake_event;
bool host_resume_req;
bool lp0_exit;
- bool dfe_ctle_ctx_saved;
+ bool dfe_ctx_saved[XUSB_SS_PORT_COUNT];
unsigned long last_jiffies;
unsigned long host_phy_base;
@@ -1423,84 +1423,61 @@ static void tegra_xusb_set_bw(struct tegra_xhci_hcd *tegra, unsigned int bw)
clk_set_rate(tegra->emc_clk, freq_khz * 1000);
}
-static void tegra_xhci_save_dfe_ctle_context(struct tegra_xhci_hcd *tegra,
+static void tegra_xhci_save_dfe_context(struct tegra_xhci_hcd *tegra,
u8 port)
{
struct xhci_hcd *xhci = tegra->xhci;
u32 offset;
u32 reg;
- xhci_info(xhci, "saving dfe_cntl and ctle context for port %d\n", port);
+ xhci_info(xhci, "saving dfe_cntl context for port %d\n", port);
- offset = port ? IOPHY_MISC_PAD1_CTL_6_0 : IOPHY_MISC_PAD0_CTL_6_0;
+ offset = MISC_PAD_CTL_6_0(port);
- /* save tap1_val[] for the port for dfe_cntl */
+ /*
+ * Value set to IOPHY_MISC_PAD_x_CTL_6 where x P0/P1/S0/ is from,
+ * T114 refer PG USB3_FW_Programming_Guide_Host.doc section 14.3.10
+ */
reg = readl(tegra->padctl_base + offset);
- reg &= ~(0xff << 16);
- reg |= (0x32 << 16);
+ reg &= ~MISC_OUT_SEL(~0);
+ reg |= MISC_OUT_SEL(0x32);
writel(reg, tegra->padctl_base + offset);
reg = readl(tegra->padctl_base + offset);
- tegra->sregs.tap1_val[port] = ((reg & (0x1f << 24)) >> 24);
+ tegra->sregs.tap1_val[port] = MISC_OUT_TAP_VAL(reg);
/* save amp_val[] for the port for dfe_cntl */
reg = readl(tegra->padctl_base + offset);
- reg &= ~(0xff << 16);
- reg |= (0x33 << 16);
+ reg &= ~MISC_OUT_SEL(~0);
+ reg |= MISC_OUT_SEL(0x33);
writel(reg, tegra->padctl_base + offset);
reg = readl(tegra->padctl_base + offset);
- tegra->sregs.amp_val[port] = ((reg & (0x7f << 24)) >> 24);
-
- /* save ctle_z_val[] for the port for ctle */
- reg = readl(tegra->padctl_base + offset);
- reg &= ~(0xff << 16);
- reg |= (0x20 << 16);
- writel(reg, tegra->padctl_base + offset);
+ tegra->sregs.amp_val[port] = MISC_OUT_AMP_VAL(reg);
- reg = readl(tegra->padctl_base + offset);
- tegra->sregs.ctle_z_val[port] = ((reg & (0x3f << 24)) >> 24);
-
- /* save ctle_g_val[] for the port for ctle */
- reg = readl(tegra->padctl_base + offset);
- reg &= ~(0xff << 16);
- reg |= (0x21 << 16);
- writel(reg, tegra->padctl_base + offset);
-
- reg = readl(tegra->padctl_base + offset);
- tegra->sregs.ctle_g_val[port] = ((reg & (0x3f << 24)) >> 24);
- tegra->dfe_ctle_ctx_saved = true;
+ tegra->dfe_ctx_saved[port] = true;
}
-static void tegra_xhci_restore_dfe_ctle_context(struct tegra_xhci_hcd *tegra,
+static void tegra_xhci_restore_dfe_context(struct tegra_xhci_hcd *tegra,
u8 port)
{
struct xhci_hcd *xhci = tegra->xhci;
- u32 ctl4_offset, ctl2_offset;
u32 reg;
/* don't restore if not saved */
- if (tegra->dfe_ctle_ctx_saved == false)
+ if (tegra->dfe_ctx_saved[port] == false)
return;
- ctl4_offset = port ? IOPHY_USB3_PAD1_CTL_4_0 : IOPHY_USB3_PAD0_CTL_4_0;
- ctl2_offset = port ? IOPHY_USB3_PAD1_CTL_2_0 : IOPHY_USB3_PAD0_CTL_2_0;
-
- xhci_info(xhci, "restoring dfe_cntl/ctle context of port %d\n", port);
+ xhci_info(xhci, "restoring dfe_cntl context of port %d\n", port);
/* restore dfe_cntl for the port */
- reg = readl(tegra->padctl_base + ctl4_offset);
- reg &= ~((0x7f << 16) | (0x1f << 24));
- reg |= ((tegra->sregs.amp_val[port] << 16) |
- (tegra->sregs.tap1_val[port] << 24));
- writel(reg, tegra->padctl_base + ctl4_offset);
+ reg = readl(tegra->padctl_base + USB3_PAD_CTL_4_0(port));
+ reg &= ~(DFE_CNTL_AMP_VAL(~0) |
+ DFE_CNTL_TAP_VAL(~0));
+ reg |= DFE_CNTL_AMP_VAL(tegra->sregs.amp_val[port]) |
+ DFE_CNTL_TAP_VAL(tegra->sregs.tap1_val[port]);
+ writel(reg, tegra->padctl_base + USB3_PAD_CTL_4_0(port));
- /* restore ctle for the port */
- reg = readl(tegra->padctl_base + ctl2_offset);
- reg &= ~((0x3f << 8) | (0x3f << 16));
- reg |= ((tegra->sregs.ctle_g_val[port] << 8) |
- (tegra->sregs.ctle_z_val[port] << 16));
- writel(reg, tegra->padctl_base + ctl2_offset);
}
static void tegra_xhci_program_ulpi_pad(struct tegra_xhci_hcd *tegra,
@@ -1625,7 +1602,7 @@ static void tegra_xhci_program_ss_pad(struct tegra_xhci_hcd *tegra,
u32 reg;
ctl2_offset = port ? IOPHY_USB3_PAD1_CTL_2_0 : IOPHY_USB3_PAD0_CTL_2_0;
- ctl4_offset = port ? IOPHY_USB3_PAD1_CTL_4_0 : IOPHY_USB3_PAD0_CTL_4_0;
+ ctl4_offset = USB3_PAD_CTL_4_0(port);
ctl5_offset = port ? IOPHY_MISC_PAD1_CTL_5_0 : IOPHY_MISC_PAD0_CTL_5_0;
reg = readl(tegra->padctl_base + ctl2_offset);
@@ -1649,7 +1626,7 @@ static void tegra_xhci_program_ss_pad(struct tegra_xhci_hcd *tegra,
(port ? TEGRA_XUSB_SS1_PORT_MAP : TEGRA_XUSB_SS0_PORT_MAP));
writel(reg, tegra->padctl_base + SS_PORT_MAP_0);
- tegra_xhci_restore_dfe_ctle_context(tegra, port);
+ tegra_xhci_restore_dfe_context(tegra, port);
}
/* This function assigns the USB ports to the controllers,
@@ -2626,8 +2603,8 @@ tegra_xhci_process_mbox_message(struct work_struct *work)
writel(0, tegra->fpci_base + XUSB_CFG_ARU_MBOX_OWNER);
break;
case MBOX_CMD_SAVE_DFE_CTLE_CTX:
- tegra_xhci_save_dfe_ctle_context(tegra, tegra->cmd_data);
- tegra_xhci_restore_dfe_ctle_context(tegra, tegra->cmd_data);
+ tegra_xhci_save_dfe_context(tegra, tegra->cmd_data);
+ tegra_xhci_restore_dfe_context(tegra, tegra->cmd_data);
sw_resp |= (MBOX_CMD_ACK << MBOX_CMD_SHIFT);
goto send_sw_response;
case MBOX_CMD_ACK:
@@ -3325,6 +3302,7 @@ static int tegra_xhci_probe(struct platform_device *pdev)
struct tegra_xhci_hcd *tegra;
struct resource *res;
struct usb_hcd *hcd;
+ unsigned port;
u32 pmc_reg;
int ret;
int irq;
@@ -3555,8 +3533,9 @@ static int tegra_xhci_probe(struct platform_device *pdev)
tegra->hs_wake_event = false;
tegra->host_resume_req = false;
tegra->lp0_exit = false;
- tegra->dfe_ctle_ctx_saved = false;
tegra->no_of_oc_retries = 0;
+ for (port = 0; port < XUSB_SS_PORT_COUNT; port++)
+ tegra->dfe_ctx_saved[port] = false;
/* reset wake event to NONE */
pmc_reg = tegra_usb_pmc_reg_read(PMC_UTMIP_UHSIC_SLEEP_CFG_0);
diff --git a/drivers/usb/host/xhci-tegra.h b/drivers/usb/host/xhci-tegra.h
index 2b527f5aee90..0d1ce21b6ba5 100644
--- a/drivers/usb/host/xhci-tegra.h
+++ b/drivers/usb/host/xhci-tegra.h
@@ -1,7 +1,7 @@
/*
* xhci-tegra.h - Nvidia xHCI host controller related data
*
- * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
+ * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -439,11 +439,10 @@
#define IOPHY_USB3_PAD1_CTL_3_0 0x54
#define EOM_CNTL(x) (((x) & 0xffff) << 0)
-#define IOPHY_USB3_PAD0_CTL_4_0 0x58
-#define DFE_CNTL(x) (((x) & 0xffffffff) << 0)
-
-#define IOPHY_USB3_PAD1_CTL_4_0 0x5c
+#define USB3_PAD_CTL_4_0(_p) (0x58 + _p * 4)
#define DFE_CNTL(x) (((x) & 0xffffffff) << 0)
+#define DFE_CNTL_TAP_VAL(x) ((x & 0x1F) << 24)
+#define DFE_CNTL_AMP_VAL(x) ((x & 0x7F) << 16)
#define IOPHY_MISC_PAD0_CTL_1_0 0x60
#define IOPHY_MISC_PAD1_CTL_1_0 0x64
@@ -534,11 +533,12 @@
#define RX_QEYE_EN (1 << 8)
#define RX_QEYE_OUT(x) (((x) & 0xf) << 12)
-#define IOPHY_MISC_PAD0_CTL_6_0 0x88
-#define IOPHY_MISC_PAD1_CTL_6_0 0x8c
+#define MISC_PAD_CTL_6_0(_p) (0x88 + _p * 4)
#define MISC_TEST(x) (((x) & 0xffff) << 0)
#define MISC_OUT_SEL(x) (((x) & 0xff) << 16)
#define MISC_OUT(x) (((x) & 0xff) << 24)
+#define MISC_OUT_TAP_VAL(reg) ((reg & (0x1F << 24)) >> 24)
+#define MISC_OUT_AMP_VAL(reg) ((reg & (0x7F << 24)) >> 24)
#define USB2_OTG_PAD0_CTL_0_0 0x90
#define USB2_OTG_PAD1_CTL_0_0 0x94