usb: pmc: set utmip tracking data with snps
Krishna Yarlagadda [Thu, 5 Sep 2013 17:18:53 +0000 (22:18 +0530)]
provide api to read tracking data from snps register space

Bug 1334159

Change-Id: Ieb46f178226678295ce5ec03701209b11422bf43
Signed-off-by: Krishna Yarlagadda <kyarlagadda@nvidia.com>
Reviewed-on: http://git-master/r/270908
Reviewed-on: http://git-master/r/272749
Reviewed-by: Ajay Gupta <ajayg@nvidia.com>
Tested-by: Ajay Gupta <ajayg@nvidia.com>
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Joy Wang <joyw@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
Reviewed-by: Henry Lin <henryl@nvidia.com>

arch/arm/mach-tegra/include/mach/tegra_usb_pmc.h
arch/arm/mach-tegra/tegra_usb_pmc.c
drivers/usb/host/xhci-tegra.c

index 1886e0b..3d4558e 100644 (file)
 #define PMC_UTMIP_BIAS_MASTER_CNTRL 0x270
 #define BIAS_MASTER_PROG_VAL           (1 << 1)
 
+#define UTMIP_BIAS_CFG1                0x83c
+#define   UTMIP_BIAS_PDTRK_COUNT(x) (((x) & 0x1f) << 3)
+#define   UTMIP_BIAS_PDTRK_POWERDOWN   (1 << 0)
+#define   UTMIP_BIAS_PDTRK_POWERUP     (1 << 1)
+
+#define UTMIP_BIAS_STS0                        0x840
+#define   UTMIP_RCTRL_VAL(x)           (((x) & 0xffff) << 0)
+#define   UTMIP_TCTRL_VAL(x)           (((x) & (0xffff << 16)) >> 16)
+
 #define PMC_UTMIP_MASTER_CONFIG                0x274
 #define UTMIP_PWR(inst)                (1 << (inst))
 
@@ -253,11 +262,11 @@ 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;
-       u32 utmip_rctrl_val;
-       u32 utmip_tctrl_val;
 };
 
 void tegra_usb_pmc_init(struct tegra_usb_pmc_data *pmc_data);
+int utmi_phy_set_snps_trking_data(void);
+void utmi_phy_update_trking_data(u32 tctrl, u32 rctrl);
 void tegra_usb_pmc_reg_update(u32 reg_offset, u32 mask, u32 val);
 u32 tegra_usb_pmc_reg_read(u32 reg_offset);
 void tegra_usb_pmc_reg_write(u32 reg_offset, u32 val);
index 8d9e783..7173219 100644 (file)
@@ -35,6 +35,8 @@
 static void __iomem *pmc_base;
 static unsigned long flags;
 static DEFINE_SPINLOCK(pmc_lock);
+static u32 utmip_rctrl_val;
+static u32 utmip_tctrl_val;
 
 #ifdef KERNEL_WARNING
 static void usb_phy_power_down_pmc(struct tegra_usb_pmc_data *pmc_data)
@@ -92,6 +94,91 @@ static void usb_phy_power_down_pmc(struct tegra_usb_pmc_data *pmc_data)
 }
 #endif
 
+void utmi_phy_update_trking_data(u32 tctrl, u32 rctrl)
+{
+       spin_lock_irqsave(&pmc_lock, flags);
+       utmip_tctrl_val = tctrl;
+       utmip_rctrl_val = rctrl;
+       spin_unlock_irqrestore(&pmc_lock, flags);
+}
+EXPORT_SYMBOL_GPL(utmi_phy_update_trking_data);
+
+int utmi_phy_set_snps_trking_data(void)
+{
+       void __iomem *base = IO_ADDRESS(TEGRA_USB_BASE);
+       u32 val;
+       struct clk *utmi_pad_clk;
+
+       utmi_pad_clk = clk_get_sys("utmip-pad", NULL);
+       if (IS_ERR(utmi_pad_clk)) {
+               pr_err("%s: can't get utmip pad clock\n", __func__);
+               return PTR_ERR(utmi_pad_clk);
+       }
+
+       if (!pmc_base)
+               pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+
+       clk_enable(utmi_pad_clk);
+       spin_lock_irqsave(&pmc_lock, flags);
+       /* Bias pad MASTER_ENABLE=1 */
+       val = readl(pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
+       val |= BIAS_MASTER_PROG_VAL;
+       writel(val, pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
+
+       /* Setting the tracking length time */
+       val = readl(base + UTMIP_BIAS_CFG1);
+       val &= ~UTMIP_BIAS_PDTRK_COUNT(~0);
+       val |= UTMIP_BIAS_PDTRK_COUNT(5);
+       writel(val, base + UTMIP_BIAS_CFG1);
+
+       /* Bias PDTRK is Shared and MUST be done from USB1 ONLY, PD_TRK=0 */
+       val = readl(base + UTMIP_BIAS_CFG1);
+       val &= ~UTMIP_BIAS_PDTRK_POWERDOWN;
+       writel(val, base + UTMIP_BIAS_CFG1);
+
+       val = readl(base + UTMIP_BIAS_CFG1);
+       val |= UTMIP_BIAS_PDTRK_POWERUP;
+       writel(val, base + UTMIP_BIAS_CFG1);
+
+       /* Wait for 25usec */
+       udelay(25);
+
+       /* Bias pad MASTER_ENABLE=0 */
+       val = readl(pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
+       val &= ~BIAS_MASTER_PROG_VAL;
+       writel(val, pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
+
+       /* Wait for 1usec */
+       udelay(1);
+
+       /* Bias pad MASTER_ENABLE=1 */
+       val = readl(pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
+       val |= BIAS_MASTER_PROG_VAL;
+       writel(val, pmc_base + PMC_UTMIP_BIAS_MASTER_CNTRL);
+
+       /* Read RCTRL and TCTRL from UTMIP space */
+       val = readl(base + UTMIP_BIAS_STS0);
+       utmip_rctrl_val = 0xf + ffz(UTMIP_RCTRL_VAL(val));
+       utmip_tctrl_val = 0xf + ffz(UTMIP_TCTRL_VAL(val));
+
+       /* PD_TRK=1 */
+       val = readl(base + UTMIP_BIAS_CFG1);
+       val |= UTMIP_BIAS_PDTRK_POWERDOWN;
+       writel(val, base + UTMIP_BIAS_CFG1);
+
+       /* Program thermally encoded RCTRL_VAL, TCTRL_VAL into PMC space */
+       val = readl(pmc_base + PMC_UTMIP_TERM_PAD_CFG);
+       val = PMC_TCTRL_VAL(utmip_tctrl_val) |
+               PMC_RCTRL_VAL(utmip_rctrl_val);
+       writel(val, pmc_base + PMC_UTMIP_TERM_PAD_CFG);
+       spin_unlock_irqrestore(&pmc_lock, flags);
+       clk_disable(utmi_pad_clk);
+       clk_put(utmi_pad_clk);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(utmi_phy_set_snps_trking_data);
+
 static void utmip_setup_pmc_wake_detect(struct tegra_usb_pmc_data *pmc_data)
 {
        unsigned long val, pmc_pad_cfg_val;
@@ -232,10 +319,10 @@ static void utmip_setup_pmc_wake_detect(struct tegra_usb_pmc_data *pmc_data)
        spin_lock_irqsave(&pmc_lock, flags);
 
        /* Program thermally encoded RCTRL_VAL, TCTRL_VAL into PMC space */
-       if (pmc_data->utmip_tctrl_val | pmc_data->utmip_rctrl_val) {
+       if (utmip_tctrl_val | utmip_rctrl_val) {
                val = readl(pmc_base + PMC_UTMIP_TERM_PAD_CFG);
-               val = PMC_TCTRL_VAL(pmc_data->utmip_tctrl_val) |
-                       PMC_RCTRL_VAL(pmc_data->utmip_rctrl_val);
+               val = PMC_TCTRL_VAL(utmip_tctrl_val) |
+                       PMC_RCTRL_VAL(utmip_rctrl_val);
                writel(val, pmc_base + PMC_UTMIP_TERM_PAD_CFG);
        }
 
@@ -315,10 +402,10 @@ static void utmip_powerdown_pmc_wake_detect(struct tegra_usb_pmc_data *pmc_data)
        writel(val, pmc_base + PMC_SLEEPWALK_REG(inst));
 
        /* Program thermally encoded RCTRL_VAL, TCTRL_VAL into PMC space */
-       if (pmc_data->utmip_tctrl_val | pmc_data->utmip_rctrl_val) {
+       if (utmip_tctrl_val | utmip_rctrl_val) {
                val = readl(pmc_base + PMC_UTMIP_TERM_PAD_CFG);
-               val = PMC_TCTRL_VAL(pmc_data->utmip_tctrl_val) |
-                       PMC_RCTRL_VAL(pmc_data->utmip_rctrl_val);
+               val = PMC_TCTRL_VAL(utmip_tctrl_val) |
+                       PMC_RCTRL_VAL(utmip_rctrl_val);
                writel(val, pmc_base + PMC_UTMIP_TERM_PAD_CFG);
        }
 
@@ -570,9 +657,6 @@ static struct tegra_usb_pmc_ops *pmc_ops[] = {
 
 void tegra_usb_pmc_init(struct tegra_usb_pmc_data *pmc_data)
 {
-       static u32 utmip_rctrl_val;
-       static u32 utmip_tctrl_val;
-
        DBG("%s(%d) inst:[%d]\n", __func__, __LINE__, pmc_data->instance);
 
        if (!pmc_base)
@@ -581,10 +665,6 @@ void tegra_usb_pmc_init(struct tegra_usb_pmc_data *pmc_data)
 #ifdef KERNEL_WARNING
        pmc_data->pmc_ops.power_down_pmc = usb_phy_power_down_pmc;
 #endif
-       if (pmc_data->phy_type == TEGRA_USB_PHY_INTF_UTMI) {
-               utmip_rctrl_val = pmc_data->utmip_rctrl_val;
-               utmip_tctrl_val = pmc_data->utmip_tctrl_val;
-       }
        pmc_data->pmc_ops = pmc_ops[pmc_data->phy_type];
 }
 EXPORT_SYMBOL_GPL(tegra_usb_pmc_init);
index 2ff1387..c5dcbd6 100644 (file)
@@ -2383,11 +2383,12 @@ static void tegra_xhci_war_for_tctrl_rctrl(struct tegra_xhci_hcd *tegra)
                 * tctrl_val = 0x1f - (16 - ffz(utmip_tctrl_val)
                 * rctrl_val = 0x1f - (16 - ffz(utmip_rctrl_val)
                 */
-               pmc_data.utmip_rctrl_val = 0xf + ffz(utmip_rctrl_val);
-               pmc_data.utmip_tctrl_val = 0xf + ffz(utmip_tctrl_val);
+               utmip_rctrl_val = 0xf + ffz(utmip_rctrl_val);
+               utmip_tctrl_val = 0xf + ffz(utmip_tctrl_val);
 
+               utmi_phy_update_trking_data(utmip_tctrl_val, utmip_rctrl_val);
                xhci_dbg(tegra->xhci, "rctrl_val = 0x%x, tctrl_val = 0x%x\n",
-                       pmc_data.utmip_rctrl_val, pmc_data.utmip_tctrl_val);
+                       utmip_rctrl_val, utmip_tctrl_val);
 
                /* XUSB_PADCTL_USB2_BIAS_PAD_CTL_0_0::PD = 1 and
                 * XUSB_PADCTL_USB2_BIAS_PAD_CTL_0_0::PD_TRK = 1
@@ -2399,8 +2400,8 @@ static void tegra_xhci_war_for_tctrl_rctrl(struct tegra_xhci_hcd *tegra)
                /* Program these values into PMC regiseter and program the
                 * PMC override
                 */
-               reg = PMC_TCTRL_VAL(pmc_data.utmip_tctrl_val) |
-                       PMC_RCTRL_VAL(pmc_data.utmip_rctrl_val);
+               reg = PMC_TCTRL_VAL(utmip_tctrl_val) |
+                       PMC_RCTRL_VAL(utmip_rctrl_val);
                tegra_usb_pmc_reg_update(PMC_UTMIP_TERM_PAD_CFG,
                        0xffffffff, reg);