diff options
Diffstat (limited to 'drivers/usb/otg/mxs-phy.c')
-rw-r--r-- | drivers/usb/otg/mxs-phy.c | 59 |
1 files changed, 16 insertions, 43 deletions
diff --git a/drivers/usb/otg/mxs-phy.c b/drivers/usb/otg/mxs-phy.c index 88db976647cf..76302720055a 100644 --- a/drivers/usb/otg/mxs-phy.c +++ b/drivers/usb/otg/mxs-phy.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/workqueue.h> | ||
24 | 23 | ||
25 | #define DRIVER_NAME "mxs_phy" | 24 | #define DRIVER_NAME "mxs_phy" |
26 | 25 | ||
@@ -35,16 +34,9 @@ | |||
35 | #define BM_USBPHY_CTRL_ENUTMILEVEL2 BIT(14) | 34 | #define BM_USBPHY_CTRL_ENUTMILEVEL2 BIT(14) |
36 | #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT BIT(1) | 35 | #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT BIT(1) |
37 | 36 | ||
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 | |||
44 | struct mxs_phy { | 37 | struct mxs_phy { |
45 | struct usb_phy phy; | 38 | struct usb_phy phy; |
46 | struct clk *clk; | 39 | struct clk *clk; |
47 | struct delayed_work enhostdiscondetect_work; | ||
48 | }; | 40 | }; |
49 | 41 | ||
50 | #define to_mxs_phy(p) container_of((p), struct mxs_phy, phy) | 42 | #define to_mxs_phy(p) container_of((p), struct mxs_phy, phy) |
@@ -70,7 +62,6 @@ static int mxs_phy_init(struct usb_phy *phy) | |||
70 | 62 | ||
71 | clk_prepare_enable(mxs_phy->clk); | 63 | clk_prepare_enable(mxs_phy->clk); |
72 | mxs_phy_hw_init(mxs_phy); | 64 | mxs_phy_hw_init(mxs_phy); |
73 | INIT_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work, NULL); | ||
74 | 65 | ||
75 | return 0; | 66 | return 0; |
76 | } | 67 | } |
@@ -85,46 +76,28 @@ static void mxs_phy_shutdown(struct usb_phy *phy) | |||
85 | clk_disable_unprepare(mxs_phy->clk); | 76 | clk_disable_unprepare(mxs_phy->clk); |
86 | } | 77 | } |
87 | 78 | ||
88 | static void mxs_phy_enhostdiscondetect_delay(struct work_struct *ws) | 79 | static int mxs_phy_on_connect(struct usb_phy *phy, |
80 | enum usb_device_speed speed) | ||
89 | { | 81 | { |
90 | struct mxs_phy *mxs_phy = container_of(ws, struct mxs_phy, | 82 | dev_dbg(phy->dev, "%s speed device has connected\n", |
91 | enhostdiscondetect_work.work); | 83 | (speed == USB_SPEED_HIGH) ? "high" : "non-high"); |
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 | |||
99 | static int mxs_phy_on_connect(struct usb_phy *phy, int port) | ||
100 | { | ||
101 | struct mxs_phy *mxs_phy = to_mxs_phy(phy); | ||
102 | |||
103 | dev_dbg(phy->dev, "Connect on port %d\n", port); | ||
104 | |||
105 | mxs_phy_hw_init(mxs_phy); | ||
106 | 84 | ||
107 | /* | 85 | if (speed == USB_SPEED_HIGH) |
108 | * Delay enabling ENHOSTDISCONDETECT so that connection and | 86 | writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, |
109 | * reset processing can be completed for the root hub. | 87 | phy->io_priv + HW_USBPHY_CTRL_SET); |
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)); | ||
116 | 88 | ||
117 | return 0; | 89 | return 0; |
118 | } | 90 | } |
119 | 91 | ||
120 | static int mxs_phy_on_disconnect(struct usb_phy *phy, int port) | 92 | static int mxs_phy_on_disconnect(struct usb_phy *phy, |
93 | enum usb_device_speed speed) | ||
121 | { | 94 | { |
122 | dev_dbg(phy->dev, "Disconnect on port %d\n", port); | 95 | dev_dbg(phy->dev, "%s speed device has disconnected\n", |
96 | (speed == USB_SPEED_HIGH) ? "high" : "non-high"); | ||
123 | 97 | ||
124 | /* No need to delay before clearing ENHOSTDISCONDETECT. */ | 98 | if (speed == USB_SPEED_HIGH) |
125 | dev_dbg(phy->dev, "Clearing ENHOSTDISCONDETECT\n"); | 99 | writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, |
126 | writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, | 100 | phy->io_priv + HW_USBPHY_CTRL_CLR); |
127 | phy->io_priv + HW_USBPHY_CTRL_CLR); | ||
128 | 101 | ||
129 | return 0; | 102 | return 0; |
130 | } | 103 | } |
@@ -176,7 +149,7 @@ static int mxs_phy_probe(struct platform_device *pdev) | |||
176 | return 0; | 149 | return 0; |
177 | } | 150 | } |
178 | 151 | ||
179 | static int __devexit mxs_phy_remove(struct platform_device *pdev) | 152 | static int mxs_phy_remove(struct platform_device *pdev) |
180 | { | 153 | { |
181 | platform_set_drvdata(pdev, NULL); | 154 | platform_set_drvdata(pdev, NULL); |
182 | 155 | ||
@@ -191,7 +164,7 @@ MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids); | |||
191 | 164 | ||
192 | static struct platform_driver mxs_phy_driver = { | 165 | static struct platform_driver mxs_phy_driver = { |
193 | .probe = mxs_phy_probe, | 166 | .probe = mxs_phy_probe, |
194 | .remove = __devexit_p(mxs_phy_remove), | 167 | .remove = mxs_phy_remove, |
195 | .driver = { | 168 | .driver = { |
196 | .name = DRIVER_NAME, | 169 | .name = DRIVER_NAME, |
197 | .owner = THIS_MODULE, | 170 | .owner = THIS_MODULE, |