ARM: tegra: usb_phy: Fix T11x OverCurrent selection bit
Suresh Mangipudi [Mon, 17 Dec 2012 10:49:11 +0000 (15:49 +0530)]
The OCA bit in PORTSC is being set by default, this results in PORTSC
register reporting false status for over current.
Update the programming sequence such that the over_current bit is
cleared.

Bug 1199299

Change-Id: I17b2e6c48719986a87683da9ff52ff8874d7671d
Signed-off-by: Suresh Mangipudi <smangipudi@nvidia.com>
Reviewed-on: http://git-master/r/171886
(cherry picked from commit 4de2cc7c70ab9cd4f2790901b0535ffbd67f80da)
Reviewed-on: http://git-master/r/173091
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>

arch/arm/mach-tegra/board-dalmore.c
arch/arm/mach-tegra/board-pluto.c
arch/arm/mach-tegra/board-roth.c
arch/arm/mach-tegra/tegra11x_usb_phy.c
include/linux/platform_data/tegra_usb.h

index 3926b44..5b1c2e3 100644 (file)
@@ -490,6 +490,7 @@ static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = {
                .xcvr_lsrslew = 2,
                .xcvr_setup_offset = 0,
                .xcvr_use_fuses = 1,
+               .vbus_oc_map = 0x4,
        },
 };
 
@@ -515,6 +516,7 @@ static struct tegra_usb_platform_data tegra_ehci3_utmi_pdata = {
                .xcvr_lsrslew = 2,
                .xcvr_setup_offset = 0,
                .xcvr_use_fuses = 1,
+               .vbus_oc_map = 0x5,
        },
 };
 
index 2171ace..d9d63f5 100644 (file)
@@ -564,6 +564,7 @@ static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = {
                .xcvr_lsrslew = 2,
                .xcvr_setup_offset = 0,
                .xcvr_use_fuses = 1,
+               .vbus_oc_map = 0x7,
        },
 };
 
index cde2006..aed676d 100644 (file)
@@ -482,6 +482,7 @@ static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = {
                .xcvr_lsrslew = 2,
                .xcvr_setup_offset = 0,
                .xcvr_use_fuses = 1,
+               .vbus_oc_map = 0x4,
        },
 };
 
@@ -507,6 +508,7 @@ static struct tegra_usb_platform_data tegra_ehci3_utmi_pdata = {
                .xcvr_lsrslew = 2,
                .xcvr_setup_offset = 0,
                .xcvr_use_fuses = 1,
+               .vbus_oc_map = 0x5,
        },
 };
 
index 1363faa..7aeff1e 100644 (file)
 #define APB_MISC_GP_OBSCTRL_0  0x818
 #define APB_MISC_GP_OBSDATA_0  0x81c
 
+#define PADCTL_SNPS_OC_MAP     0xC
+#define   CONTROLLER_OC(inst, x)       (((x) & 0x7) << (3 * (inst)))
+#define   CONTROLLER_OC_P0(x)  (((x) & 0x7) << 0)
+#define   CONTROLLER_OC_P1(x)  (((x) & 0x7) << 3)
+#define   CONTROLLER_OC_P2(x)  (((x) & 0x7) << 6)
+
+#define PADCTL_OC_DET          0x18
+#define   ENABLE0_OC_MAP(x)    (((x) & 0x7) << 10)
+#define   ENABLE1_OC_MAP(x)    (((x) & 0x7) << 13)
+
 /* ULPI GPIO */
 #define ULPI_STP       TEGRA_GPIO_PY3
 #define ULPI_DIR       TEGRA_GPIO_PY1
@@ -1468,6 +1478,9 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
 {
        unsigned long val;
        void __iomem *base = phy->regs;
+#ifdef CONFIG_ARCH_TEGRA_11x_SOC
+       void __iomem *padctl_base = IO_ADDRESS(TEGRA_XUSB_PADCTL_BASE);
+#endif
        struct tegra_utmi_config *config = &phy->pdata->u_cfg.utmi;
 
        PHY_DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
@@ -1595,6 +1608,20 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy)
                utmip_powerup_pmc_wake_detect(phy);
        phy->phy_clk_on = true;
        phy->hw_accessible = true;
+
+#ifdef CONFIG_ARCH_TEGRA_11x_SOC
+       val = readl(padctl_base + PADCTL_SNPS_OC_MAP);
+       val |= CONTROLLER_OC(phy->inst, 0x4);
+       writel(val, padctl_base + PADCTL_SNPS_OC_MAP);
+
+       val = readl(padctl_base + PADCTL_OC_DET);
+       if (phy->inst == 0)
+               val |= ENABLE0_OC_MAP(config->vbus_oc_map);
+       if (phy->inst == 2)
+               val |= ENABLE1_OC_MAP(config->vbus_oc_map);
+       writel(val, padctl_base + PADCTL_OC_DET);
+#endif
+
        PHY_DBG("%s(%d) End inst:[%d]\n", __func__, __LINE__, phy->inst);
        return 0;
 }
@@ -2204,6 +2231,9 @@ static int uhsic_phy_power_on(struct tegra_usb_phy *phy)
 {
        unsigned long val;
        void __iomem *base = phy->regs;
+#ifdef CONFIG_ARCH_TEGRA_11x_SOC
+       void __iomem *padctl_base = IO_ADDRESS(TEGRA_XUSB_PADCTL_BASE);
+#endif
 
        DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, phy->inst);
 
@@ -2338,6 +2368,12 @@ static int uhsic_phy_power_on(struct tegra_usb_phy *phy)
                writel(val, base + USB_TXFILLTUNING);
        }
 
+#ifdef CONFIG_ARCH_TEGRA_11x_SOC
+       val = readl(padctl_base + PADCTL_SNPS_OC_MAP);
+       val |= CONTROLLER_OC(phy->inst, 0x7);
+       writel(val, padctl_base + PADCTL_SNPS_OC_MAP);
+#endif
+
        return 0;
 }
 
index a37ceae..5d9281c 100644 (file)
@@ -49,6 +49,7 @@ struct tegra_utmi_config {
        signed char xcvr_setup_offset;
        u8 xcvr_use_lsb;
        u8 xcvr_use_fuses;
+       u8 vbus_oc_map;
 };
 
 /**