aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Chen <peter.chen@freescale.com>2015-01-16 05:29:00 -0500
committerFelipe Balbi <balbi@ti.com>2015-01-27 10:40:46 -0500
commitefdbd3a5d6e6108f1565ab4dc4c53e77aba6fe0a (patch)
tree070e45a15a5fd11e65fa7a577e0c55bb591aeb5f
parent7b09e67639d6857439bae0d6276d443a7c2c9c40 (diff)
usb: phy: mxs: do not set PWD.RXPWD1PT1 for low speed connection
At very rare cases, the SoF will not send out after resume with low speed connection. The workaround is do not power down PWD.RXPWD1PT1 bit during the suspend. Signed-off-by: Peter Chen <peter.chen@freescale.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r--drivers/usb/phy/phy-mxs-usb.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
index eb746051eda4..c3177a1757ee 100644
--- a/drivers/usb/phy/phy-mxs-usb.c
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -70,6 +70,9 @@
70#define ANADIG_USB2_LOOPBACK_SET 0x244 70#define ANADIG_USB2_LOOPBACK_SET 0x244
71#define ANADIG_USB2_LOOPBACK_CLR 0x248 71#define ANADIG_USB2_LOOPBACK_CLR 0x248
72 72
73#define ANADIG_USB1_MISC 0x1f0
74#define ANADIG_USB2_MISC 0x250
75
73#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG BIT(12) 76#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG BIT(12)
74#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG_SL BIT(11) 77#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG_SL BIT(11)
75 78
@@ -81,6 +84,11 @@
81#define BM_ANADIG_USB2_LOOPBACK_UTMI_DIG_TST1 BIT(2) 84#define BM_ANADIG_USB2_LOOPBACK_UTMI_DIG_TST1 BIT(2)
82#define BM_ANADIG_USB2_LOOPBACK_TSTI_TX_EN BIT(5) 85#define BM_ANADIG_USB2_LOOPBACK_TSTI_TX_EN BIT(5)
83 86
87#define BM_ANADIG_USB1_MISC_RX_VPIN_FS BIT(29)
88#define BM_ANADIG_USB1_MISC_RX_VMIN_FS BIT(28)
89#define BM_ANADIG_USB2_MISC_RX_VPIN_FS BIT(29)
90#define BM_ANADIG_USB2_MISC_RX_VMIN_FS BIT(28)
91
84#define to_mxs_phy(p) container_of((p), struct mxs_phy, phy) 92#define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
85 93
86/* Do disconnection between PHY and controller without vbus */ 94/* Do disconnection between PHY and controller without vbus */
@@ -323,13 +331,50 @@ static void mxs_phy_shutdown(struct usb_phy *phy)
323 clk_disable_unprepare(mxs_phy->clk); 331 clk_disable_unprepare(mxs_phy->clk);
324} 332}
325 333
334static bool mxs_phy_is_low_speed_connection(struct mxs_phy *mxs_phy)
335{
336 unsigned int line_state;
337 /* bit definition is the same for all controllers */
338 unsigned int dp_bit = BM_ANADIG_USB1_MISC_RX_VPIN_FS,
339 dm_bit = BM_ANADIG_USB1_MISC_RX_VMIN_FS;
340 unsigned int reg = ANADIG_USB1_MISC;
341
342 /* If the SoCs don't have anatop, quit */
343 if (!mxs_phy->regmap_anatop)
344 return false;
345
346 if (mxs_phy->port_id == 0)
347 reg = ANADIG_USB1_MISC;
348 else if (mxs_phy->port_id == 1)
349 reg = ANADIG_USB2_MISC;
350
351 regmap_read(mxs_phy->regmap_anatop, reg, &line_state);
352
353 if ((line_state & (dp_bit | dm_bit)) == dm_bit)
354 return true;
355 else
356 return false;
357}
358
326static int mxs_phy_suspend(struct usb_phy *x, int suspend) 359static int mxs_phy_suspend(struct usb_phy *x, int suspend)
327{ 360{
328 int ret; 361 int ret;
329 struct mxs_phy *mxs_phy = to_mxs_phy(x); 362 struct mxs_phy *mxs_phy = to_mxs_phy(x);
363 bool low_speed_connection, vbus_is_on;
364
365 low_speed_connection = mxs_phy_is_low_speed_connection(mxs_phy);
366 vbus_is_on = mxs_phy_get_vbus_status(mxs_phy);
330 367
331 if (suspend) { 368 if (suspend) {
332 writel(0xffffffff, x->io_priv + HW_USBPHY_PWD); 369 /*
370 * FIXME: Do not power down RXPWD1PT1 bit for low speed
371 * connect. The low speed connection will have problem at
372 * very rare cases during usb suspend and resume process.
373 */
374 if (low_speed_connection & vbus_is_on)
375 writel(0xfffbffff, x->io_priv + HW_USBPHY_PWD);
376 else
377 writel(0xffffffff, x->io_priv + HW_USBPHY_PWD);
333 writel(BM_USBPHY_CTRL_CLKGATE, 378 writel(BM_USBPHY_CTRL_CLKGATE,
334 x->io_priv + HW_USBPHY_CTRL_SET); 379 x->io_priv + HW_USBPHY_CTRL_SET);
335 clk_disable_unprepare(mxs_phy->clk); 380 clk_disable_unprepare(mxs_phy->clk);