aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/phy/phy-mxs-usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/phy/phy-mxs-usb.c')
-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);