[ARM] tegra: usb_phy: Moved suspend/resume code to ehci driver
authorBenoit Goby <benoit@android.com>
Tue, 31 Aug 2010 22:38:09 +0000 (15:38 -0700)
committerColin Cross <ccross@android.com>
Wed, 6 Oct 2010 23:28:19 +0000 (16:28 -0700)
The suspend/resume methods should go to the ehci driver as they only
save/restore ehci registers.

Remove phy_init and initialize all phy registers in power_on as all the
registers need to be reinitialized after LP0.

Change-Id: I649d2cb66339aaff2d7db442a5441d2d3f06268b
Signed-off-by: Benoit Goby <benoit@android.com>
arch/arm/mach-tegra/include/mach/usb_phy.h
arch/arm/mach-tegra/usb_phy.c

index 8f6bd2a948f3d4dcf77f6014c5223db38abbd59a..2fe707070307d91097e3f7d9e57cb920fbf80d3f 100644 (file)
@@ -52,6 +52,7 @@ enum tegra_usb_phy_mode {
 
 struct tegra_usb_phy {
        int instance;
+       int freq_sel;
        void __iomem *regs;
        void __iomem *pad_regs;
        struct clk *pll_u;
@@ -67,10 +68,6 @@ struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
 
 int tegra_usb_phy_power_on(struct tegra_usb_phy *phy);
 
-int tegra_usb_phy_suspend(struct tegra_usb_phy *phy);
-
-int tegra_usb_phy_resume(struct tegra_usb_phy *phy);
-
 int tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy);
 
 int tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy);
index 50b099fedd099866209f4f11dc99bc50abd54777..fe3b7f8ecff2a48f36148c386c65c3ce338bcff5 100644 (file)
 #include <mach/usb_phy.h>
 #include <mach/iomap.h>
 
-#define USB_USBCMD             0x140
-
 #define USB_USBSTS             0x144
 #define   USB_USBSTS_PCI       (1 << 2)
 
-#define USB_USBINTR            0x148
-#define USB_PERIODICLISTBASE   0x154
-#define USB_ASYNCLISTADDR      0x158
-#define USB_TXFILLTUNING       0x164
-
 #define USB_PORTSC1            0x184
 #define   USB_PORTSC1_PTS(x)   (((x) & 0x3) << 30)
 #define   USB_PORTSC1_PSPD(x)  (((x) & 0x3) << 26)
@@ -48,9 +41,6 @@
 #define   USB_PORTSC1_PE       (1 << 2)
 #define   USB_PORTSC1_CCS      (1 << 0)
 
-#define USB_OTGSC              0x1a4
-#define USB_USBMODE            0x1a8
-
 #define USB_SUSP_CTRL          0x400
 #define   USB_WAKE_ON_CNNT_EN_DEV      (1 << 3)
 #define   USB_WAKE_ON_DISCON_EN_DEV    (1 << 4)
 #define   UTMIP_FORCE_PDDR_POWERDOWN   (1 << 4)
 #define   UTMIP_XCVR_TERM_RANGE_ADJ(x) (((x) & 0xf) << 18)
 
+#define UTMIP_BIAS_CFG1                0x83c
+#define   UTMIP_BIAS_PDTRK_COUNT(x)    (((x) & 0x1f) << 3)
+
 static DEFINE_SPINLOCK(utmip_pad_lock);
 static int utmip_pad_count;
 
@@ -208,6 +201,8 @@ static void utmip_pad_power_on(struct tegra_usb_phy *phy)
        }
 
        spin_unlock_irqrestore(&utmip_pad_lock, flags);
+
+       clk_disable(phy->pad_clk);
 }
 
 static int utmip_pad_power_off(struct tegra_usb_phy *phy)
@@ -220,6 +215,8 @@ static int utmip_pad_power_off(struct tegra_usb_phy *phy)
                return -1;
        }
 
+       clk_enable(phy->pad_clk);
+
        spin_lock_irqsave(&utmip_pad_lock, flags);
 
        if (--utmip_pad_count == 0) {
@@ -228,15 +225,16 @@ static int utmip_pad_power_off(struct tegra_usb_phy *phy)
                writel(val, base + UTMIP_BIAS_CFG0);
        }
 
+       spin_unlock_irqrestore(&utmip_pad_lock, flags);
+
        clk_disable(phy->pad_clk);
 
-       spin_unlock_irqrestore(&utmip_pad_lock, flags);
        return 0;
 }
 
 static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
 {
-       unsigned long timeout = 1000000;
+       unsigned long timeout = 2000;
        do {
                if ((readl(reg) & mask) == result)
                        return 0;
@@ -246,134 +244,62 @@ static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
        return -1;
 }
 
-static int utmi_phy_restore_context(struct tegra_usb_phy *phy)
+static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
 {
+       unsigned long val;
        void __iomem *base = phy->regs;
-       unsigned long val = 0;
-       int count = 0;
-
-       /* If any saved context is present, restore it */
-       if (!phy->context.valid)
-               return -1;
-
-       /* Restore register context */
-       count = phy->context.regs_count;
-       count--;
-       writel(phy->context.regs[count--], base + USB_USBMODE);
-       writel(phy->context.regs[count--], base + USB_OTGSC);
-       writel(phy->context.regs[count--], base + USB_TXFILLTUNING);
-       writel(phy->context.regs[count--], base + USB_ASYNCLISTADDR);
-       writel(phy->context.regs[count--], base + USB_PERIODICLISTBASE);
-       /* Restore interrupt context later */
-       count--;
-       writel(phy->context.regs[count--], base + USB_USBCMD);
-
-       /* Enable Port Power */
-       val = readl(base + USB_PORTSC1);
-       val |= USB_PORTSC1_PP;
-       writel(val, base + USB_PORTSC1);
-       udelay(10);
-
-       /* Program the field PTC in PORTSC based on the saved speed mode */
-       if (phy->context.port_speed == TEGRA_USB_PHY_PORT_HIGH) {
-               val = readl(base + USB_PORTSC1);
-               val &= ~(USB_PORTSC1_PTC(~0));
-               val |= USB_PORTSC1_PTC(5);
-               writel(val, base + USB_PORTSC1);
-       } else if (phy->context.port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL) {
-               val = readl(base + USB_PORTSC1);
-               val &= ~(USB_PORTSC1_PTC(~0));
-               val |= USB_PORTSC1_PTC(6);
-               writel(val, base + USB_PORTSC1);
-       } else if (phy->context.port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) {
-               val = readl(base + USB_PORTSC1);
-               val &= ~(USB_PORTSC1_PTC(~0));
-               val |= USB_PORTSC1_PTC(7);
-               writel(val, base + USB_PORTSC1);
-       } else {
-               pr_err("%s: speed is not configureed properly\n", __func__);
-               return -1;
-       }
-       udelay(10);
-
-       /* Disable test mode by setting PTC field to NORMAL_OP */
-       val = readl(base + USB_PORTSC1);
-       val &= ~(USB_PORTSC1_PTC(~0));
-       writel(val, base + USB_PORTSC1);
 
-       /* Poll until CCS is enabled */
-       if (utmi_wait_register(base + USB_PORTSC1, USB_PORTSC1_CCS,
-                                                  USB_PORTSC1_CCS)) {
-               pr_err("%s: timeout waiting for USB_PORTSC1_CCS\n", __func__);
-               return -1;
-       }
+       if (phy->instance == 0) {
+               val = readl(base + USB_SUSP_CTRL);
+               val |= USB_SUSP_SET;
+               writel(val, base + USB_SUSP_CTRL);
 
-       /* Poll until PE is enabled */
-       if (utmi_wait_register(base + USB_PORTSC1, USB_PORTSC1_PE,
-                                                  USB_PORTSC1_PE)) {
-               pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__);
-               return -1;
-       }
+               udelay(10);
 
-       /* Clear the PCI status, to avoid an interrupt taken upon resume */
-       val = readl(base + USB_USBSTS);
-       val |= USB_USBSTS_PCI;
-       writel(val, base + USB_USBSTS);
-       if (utmi_wait_register(base + USB_USBSTS, USB_USBSTS_PCI, 0) < 0) {
-               pr_err("%s: timeout waiting for USB_USBSTS_PCI\n", __func__);
-               return -1;
+               val = readl(base + USB_SUSP_CTRL);
+               val &= ~USB_SUSP_SET;
+               writel(val, base + USB_SUSP_CTRL);
        }
 
-       /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */
-       val = readl(base + USB_PORTSC1);
-       if ((val & USB_PORTSC1_PP) && (val & USB_PORTSC1_PE)) {
-               val |= USB_PORTSC1_SUSP;
+       if (phy->instance == 2) {
+               val = readl(base + USB_PORTSC1);
+               val |= USB_PORTSC1_PHCD;
                writel(val, base + USB_PORTSC1);
-
-               /* Wait until port suspend completes */
-               if (utmi_wait_register(base + USB_PORTSC1, USB_PORTSC1_SUSP,
-                                                          USB_PORTSC1_SUSP)) {
-                       pr_err("%s: timeout waiting for USB_PORTSC1_SUSP\n",
-                                                               __func__);
-                       return -1;
-               }
        }
 
-       /* Restore interrupt register */
-       writel(phy->context.regs[1], base + USB_USBINTR);
-       udelay(10);
-
-       return 0;
+       if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0)
+               pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
 }
 
-static int utmi_phy_save_context(struct tegra_usb_phy *phy)
+static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
 {
+       unsigned long val;
        void __iomem *base = phy->regs;
-       int count = 0;
 
-       phy->context.port_speed = (readl(base + USB_PORTSC1)
-                                       & USB_PORTSC1_PSPD(3)) >> 26;
+       if (phy->instance == 0) {
+               val = readl(base + USB_SUSP_CTRL);
+               val |= USB_SUSP_CLR;
+               writel(val, base + USB_SUSP_CTRL);
+
+               udelay(10);
 
-       /* If no device connection or invalid speeds just return */
-       if (phy->context.port_speed > TEGRA_USB_PHY_PORT_HIGH) {
-               phy->context.valid = false;
-               return 0;
+               val = readl(base + USB_SUSP_CTRL);
+               val &= ~USB_SUSP_CLR;
+               writel(val, base + USB_SUSP_CTRL);
        }
 
-       phy->context.regs[count++] = readl(base + USB_USBCMD);
-       phy->context.regs[count++] = readl(base + USB_USBINTR);
-       phy->context.regs[count++] = readl(base + USB_PERIODICLISTBASE);
-       phy->context.regs[count++] = readl(base + USB_ASYNCLISTADDR);
-       phy->context.regs[count++] = readl(base + USB_TXFILLTUNING);
-       phy->context.regs[count++] = readl(base + USB_OTGSC);
-       phy->context.regs[count++] = readl(base + USB_USBMODE);
-       phy->context.regs_count = count;
-       phy->context.valid = true;
+       if (phy->instance == 2) {
+               val = readl(base + USB_PORTSC1);
+               val &= ~USB_PORTSC1_PHCD;
+               writel(val, base + USB_PORTSC1);
+       }
 
-       return 0;
+       if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
+                                                    USB_PHY_CLK_VALID))
+               pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
 }
 
-static void utmi_phy_init(struct tegra_usb_phy *phy, int freq_sel)
+static void utmi_phy_power_on(struct tegra_usb_phy *phy)
 {
        unsigned long val;
        void __iomem *base = phy->regs;
@@ -389,6 +315,10 @@ static void utmi_phy_init(struct tegra_usb_phy *phy, int freq_sel)
                writel(val, base + USB1_LEGACY_CTRL);
        }
 
+       val = readl(base + UTMIP_TX_CFG0);
+       val &= ~UTMIP_FS_PREABMLE_J;
+       writel(val, base + UTMIP_TX_CFG0);
+
        val = readl(base + UTMIP_HSRX_CFG0);
        val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0));
        val |= UTMIP_IDLE_WAIT(config->idle_wait_delay);
@@ -402,7 +332,7 @@ static void utmi_phy_init(struct tegra_usb_phy *phy, int freq_sel)
 
        val = readl(base + UTMIP_DEBOUNCE_CFG0);
        val &= ~UTMIP_BIAS_DEBOUNCE_A(~0);
-       val |= UTMIP_BIAS_DEBOUNCE_A(udc_debounce_table[freq_sel]);
+       val |= UTMIP_BIAS_DEBOUNCE_A(udc_debounce_table[phy->freq_sel]);
        writel(val, base + UTMIP_DEBOUNCE_CFG0);
 
        val = readl(base + UTMIP_MISC_CFG0);
@@ -411,77 +341,15 @@ static void utmi_phy_init(struct tegra_usb_phy *phy, int freq_sel)
 
        val = readl(base + UTMIP_MISC_CFG1);
        val &= ~(UTMIP_PLL_ACTIVE_DLY_COUNT(~0) | UTMIP_PLLU_STABLE_COUNT(~0));
-       val |= UTMIP_PLL_ACTIVE_DLY_COUNT(udc_delay_table[freq_sel][2]) |
-               UTMIP_PLLU_STABLE_COUNT(udc_delay_table[freq_sel][1]);
+       val |= UTMIP_PLL_ACTIVE_DLY_COUNT(udc_delay_table[phy->freq_sel][2]) |
+               UTMIP_PLLU_STABLE_COUNT(udc_delay_table[phy->freq_sel][1]);
        writel(val, base + UTMIP_MISC_CFG1);
 
        val = readl(base + UTMIP_PLL_CFG1);
        val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) | UTMIP_PLLU_ENABLE_DLY_COUNT(~0));
-       val |= UTMIP_XTAL_FREQ_COUNT(udc_delay_table[freq_sel][3]) |
-               UTMIP_PLLU_ENABLE_DLY_COUNT(udc_delay_table[freq_sel][0]);
+       val |= UTMIP_XTAL_FREQ_COUNT(udc_delay_table[phy->freq_sel][3]) |
+               UTMIP_PLLU_ENABLE_DLY_COUNT(udc_delay_table[phy->freq_sel][0]);
        writel(val, base + UTMIP_PLL_CFG1);
-}
-
-static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
-{
-       unsigned long val;
-       void __iomem *base = phy->regs;
-
-       if (phy->instance == 0) {
-               val = readl(base + USB_SUSP_CTRL);
-               val |= USB_SUSP_SET;
-               writel(val, base + USB_SUSP_CTRL);
-
-               udelay(10);
-
-               val = readl(base + USB_SUSP_CTRL);
-               val &= ~USB_SUSP_SET;
-               writel(val, base + USB_SUSP_CTRL);
-       }
-
-       if (phy->instance == 2) {
-               val = readl(base + USB_PORTSC1);
-               val |= USB_PORTSC1_PHCD;
-               writel(val, base + USB_PORTSC1);
-       }
-
-       if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0)
-               pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
-}
-
-static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
-{
-       unsigned long val;
-       void __iomem *base = phy->regs;
-
-       if (phy->instance == 0) {
-               val = readl(base + USB_SUSP_CTRL);
-               val |= USB_SUSP_CLR;
-               writel(val, base + USB_SUSP_CTRL);
-
-               udelay(10);
-
-               val = readl(base + USB_SUSP_CTRL);
-               val &= ~USB_SUSP_CLR;
-               writel(val, base + USB_SUSP_CTRL);
-       }
-
-       if (phy->instance == 2) {
-               val = readl(base + USB_PORTSC1);
-               val &= ~USB_PORTSC1_PHCD;
-               writel(val, base + USB_PORTSC1);
-       }
-
-       if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
-                                                    USB_PHY_CLK_VALID))
-               pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
-}
-
-static void utmi_phy_power_on(struct tegra_usb_phy *phy)
-{
-       unsigned long val;
-       void __iomem *base = phy->regs;
-       struct tegra_utmip_config *config = phy->config;
 
        if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
                val = readl(base + USB_SUSP_CTRL);
@@ -511,6 +379,11 @@ static void utmi_phy_power_on(struct tegra_usb_phy *phy)
        val &= ~UTMIP_PD_CHRG;
        writel(val, base + UTMIP_BAT_CHRG_CFG0);
 
+       val = readl(base + UTMIP_BIAS_CFG1);
+       val &= ~UTMIP_BIAS_PDTRK_COUNT(~0);
+       val |= UTMIP_BIAS_PDTRK_COUNT(0x5);
+       writel(val, base + UTMIP_BIAS_CFG1);
+
        if (phy->instance == 2) {
                val = readl(base + USB_SUSP_CTRL);
                val |= UTMIP_PHY_ENABLE;
@@ -613,13 +486,13 @@ struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
                err = -EINVAL;
                goto err1;
        }
+       phy->freq_sel = freq_sel;
 
        /* TODO usb2 ulpi */
        if (phy->instance != 1) {
                err = utmip_pad_open(phy);
                if (err < 0)
                        goto err1;
-               utmi_phy_init(phy, freq_sel);
        }
 
        return phy;
@@ -666,26 +539,6 @@ int tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy)
        return 0;
 }
 
-int tegra_usb_phy_suspend(struct tegra_usb_phy *phy)
-{
-       if (phy->instance != 1) {
-               utmi_phy_save_context(phy);
-               utmi_phy_power_off(phy);
-       }
-
-       return 0;
-}
-
-int tegra_usb_phy_resume(struct tegra_usb_phy *phy)
-{
-       if (phy->instance != 1) {
-               utmi_phy_power_on(phy);
-               return utmi_phy_restore_context(phy);
-       }
-
-       return 0;
-}
-
 int tegra_usb_phy_close(struct tegra_usb_phy *phy)
 {
        if (phy->instance != 1)