aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/otg/mxs-phy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/otg/mxs-phy.c')
-rw-r--r--drivers/usb/otg/mxs-phy.c59
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
44struct mxs_phy { 37struct 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
88static void mxs_phy_enhostdiscondetect_delay(struct work_struct *ws) 79static 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
99static 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
120static int mxs_phy_on_disconnect(struct usb_phy *phy, int port) 92static 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
179static int __devexit mxs_phy_remove(struct platform_device *pdev) 152static 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
192static struct platform_driver mxs_phy_driver = { 165static 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,