Skip to content

Commit 2f710e1

Browse files
mpthompsongregkh
authored andcommitted
usb: otg: mxs-phy: Fix mx23 operation
commit 363366c upstream. Currently mx23 fails to enumerate a USB device: [ 1.300000] hub 1-0:1.0: unable to enumerate USB device on port 1 [ 1.520000] hub 1-0:1.0: unable to enumerate USB device on port 1 [ 1.740000] hub 1-0:1.0: unable to enumerate USB device on port 1 [ 1.960000] hub 1-0:1.0: unable to enumerate USB device on port 1 [ 2.180000] hub 1-0:1.0: unable to enumerate USB device on port 1 Use a kernel workqueue to asynchronously delay the setting of ENHOSTDISCONDETECT bit until after higher level hub connect/reset processing is complete. Prematurely setting the bit prevents the connection processing from completing and not setting it prevents disconnect from being detected. No delay is needed for clearing of ENHOSTDISCONDETECT. Successfully tested on mx23-olinuxino (micro, mini and maxi variants) and mx28evk. Signed-off-by: Mike Thompson <[email protected]> Signed-off-by: Fabio Estevam <[email protected]> Signed-off-by: Felipe Balbi <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent cd46958 commit 2f710e1

File tree

1 file changed

+35
-3
lines changed

1 file changed

+35
-3
lines changed

drivers/usb/otg/mxs-phy.c

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/delay.h>
2121
#include <linux/err.h>
2222
#include <linux/io.h>
23+
#include <linux/workqueue.h>
2324

2425
#define DRIVER_NAME "mxs_phy"
2526

@@ -34,9 +35,16 @@
3435
#define BM_USBPHY_CTRL_ENUTMILEVEL2 BIT(14)
3536
#define BM_USBPHY_CTRL_ENHOSTDISCONDETECT BIT(1)
3637

38+
/*
39+
* Amount of delay in miliseconds to safely enable ENHOSTDISCONDETECT bit
40+
* so that connection and reset processing can be completed for the root hub.
41+
*/
42+
#define MXY_PHY_ENHOSTDISCONDETECT_DELAY 250
43+
3744
struct mxs_phy {
3845
struct usb_phy phy;
3946
struct clk *clk;
47+
struct delayed_work enhostdiscondetect_work;
4048
};
4149

4250
#define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
@@ -62,6 +70,7 @@ static int mxs_phy_init(struct usb_phy *phy)
6270

6371
clk_prepare_enable(mxs_phy->clk);
6472
mxs_phy_hw_init(mxs_phy);
73+
INIT_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work, NULL);
6574

6675
return 0;
6776
}
@@ -76,13 +85,34 @@ static void mxs_phy_shutdown(struct usb_phy *phy)
7685
clk_disable_unprepare(mxs_phy->clk);
7786
}
7887

88+
static void mxs_phy_enhostdiscondetect_delay(struct work_struct *ws)
89+
{
90+
struct mxs_phy *mxs_phy = container_of(ws, struct mxs_phy,
91+
enhostdiscondetect_work.work);
92+
93+
/* Enable HOSTDISCONDETECT after delay. */
94+
dev_dbg(mxs_phy->phy.dev, "Setting ENHOSTDISCONDETECT\n");
95+
writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
96+
mxs_phy->phy.io_priv + HW_USBPHY_CTRL_SET);
97+
}
98+
7999
static int mxs_phy_on_connect(struct usb_phy *phy, int port)
80100
{
101+
struct mxs_phy *mxs_phy = to_mxs_phy(phy);
102+
81103
dev_dbg(phy->dev, "Connect on port %d\n", port);
82104

83-
mxs_phy_hw_init(to_mxs_phy(phy));
84-
writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
85-
phy->io_priv + HW_USBPHY_CTRL_SET);
105+
mxs_phy_hw_init(mxs_phy);
106+
107+
/*
108+
* Delay enabling ENHOSTDISCONDETECT so that connection and
109+
* reset processing can be completed for the root hub.
110+
*/
111+
dev_dbg(phy->dev, "Delaying setting ENHOSTDISCONDETECT\n");
112+
PREPARE_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work,
113+
mxs_phy_enhostdiscondetect_delay);
114+
schedule_delayed_work(&mxs_phy->enhostdiscondetect_work,
115+
msecs_to_jiffies(MXY_PHY_ENHOSTDISCONDETECT_DELAY));
86116

87117
return 0;
88118
}
@@ -91,6 +121,8 @@ static int mxs_phy_on_disconnect(struct usb_phy *phy, int port)
91121
{
92122
dev_dbg(phy->dev, "Disconnect on port %d\n", port);
93123

124+
/* No need to delay before clearing ENHOSTDISCONDETECT. */
125+
dev_dbg(phy->dev, "Clearing ENHOSTDISCONDETECT\n");
94126
writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
95127
phy->io_priv + HW_USBPHY_CTRL_CLR);
96128

0 commit comments

Comments
 (0)