diff options
author | Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org> | 2010-12-20 10:48:58 -0500 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2011-01-03 04:20:23 -0500 |
commit | 711669e5b80b6f2d88f61ed8a9681f83d8cbd201 (patch) | |
tree | bfb50f071e2d539e310aeb3767bfbce54267420f /drivers/usb/host | |
parent | 8305ed75d1418f02933a48bcabdbb5032d885628 (diff) |
mx51: fix usb clock support
Current code doesn't really enable the usb clocks so if they're disabled
when booting linux, the kernel/machine will hang as soon as someone is trying
to read a usb register
Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/ehci-mxc.c | 44 |
1 files changed, 32 insertions, 12 deletions
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index bce85055019a..a22d2df769a9 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #define ULPI_VIEWPORT_OFFSET 0x170 | 28 | #define ULPI_VIEWPORT_OFFSET 0x170 |
29 | 29 | ||
30 | struct ehci_mxc_priv { | 30 | struct ehci_mxc_priv { |
31 | struct clk *usbclk, *ahbclk; | 31 | struct clk *usbclk, *ahbclk, *phy1clk; |
32 | struct usb_hcd *hcd; | 32 | struct usb_hcd *hcd; |
33 | }; | 33 | }; |
34 | 34 | ||
@@ -168,17 +168,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) | |||
168 | goto err_ioremap; | 168 | goto err_ioremap; |
169 | } | 169 | } |
170 | 170 | ||
171 | /* call platform specific init function */ | ||
172 | if (pdata->init) { | ||
173 | ret = pdata->init(pdev); | ||
174 | if (ret) { | ||
175 | dev_err(dev, "platform init failed\n"); | ||
176 | goto err_init; | ||
177 | } | ||
178 | /* platforms need some time to settle changed IO settings */ | ||
179 | mdelay(10); | ||
180 | } | ||
181 | |||
182 | /* enable clocks */ | 171 | /* enable clocks */ |
183 | priv->usbclk = clk_get(dev, "usb"); | 172 | priv->usbclk = clk_get(dev, "usb"); |
184 | if (IS_ERR(priv->usbclk)) { | 173 | if (IS_ERR(priv->usbclk)) { |
@@ -196,6 +185,28 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) | |||
196 | clk_enable(priv->ahbclk); | 185 | clk_enable(priv->ahbclk); |
197 | } | 186 | } |
198 | 187 | ||
188 | /* "dr" device has its own clock */ | ||
189 | if (pdev->id == 0) { | ||
190 | priv->phy1clk = clk_get(dev, "usb_phy1"); | ||
191 | if (IS_ERR(priv->phy1clk)) { | ||
192 | ret = PTR_ERR(priv->phy1clk); | ||
193 | goto err_clk_phy; | ||
194 | } | ||
195 | clk_enable(priv->phy1clk); | ||
196 | } | ||
197 | |||
198 | |||
199 | /* call platform specific init function */ | ||
200 | if (pdata->init) { | ||
201 | ret = pdata->init(pdev); | ||
202 | if (ret) { | ||
203 | dev_err(dev, "platform init failed\n"); | ||
204 | goto err_init; | ||
205 | } | ||
206 | /* platforms need some time to settle changed IO settings */ | ||
207 | mdelay(10); | ||
208 | } | ||
209 | |||
199 | /* setup specific usb hw */ | 210 | /* setup specific usb hw */ |
200 | ret = mxc_initialize_usb_hw(pdev->id, pdata->flags); | 211 | ret = mxc_initialize_usb_hw(pdev->id, pdata->flags); |
201 | if (ret < 0) | 212 | if (ret < 0) |
@@ -230,6 +241,11 @@ err_add: | |||
230 | if (pdata && pdata->exit) | 241 | if (pdata && pdata->exit) |
231 | pdata->exit(pdev); | 242 | pdata->exit(pdev); |
232 | err_init: | 243 | err_init: |
244 | if (priv->phy1clk) { | ||
245 | clk_disable(priv->phy1clk); | ||
246 | clk_put(priv->phy1clk); | ||
247 | } | ||
248 | err_clk_phy: | ||
233 | if (priv->ahbclk) { | 249 | if (priv->ahbclk) { |
234 | clk_disable(priv->ahbclk); | 250 | clk_disable(priv->ahbclk); |
235 | clk_put(priv->ahbclk); | 251 | clk_put(priv->ahbclk); |
@@ -273,6 +289,10 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) | |||
273 | clk_disable(priv->ahbclk); | 289 | clk_disable(priv->ahbclk); |
274 | clk_put(priv->ahbclk); | 290 | clk_put(priv->ahbclk); |
275 | } | 291 | } |
292 | if (priv->phy1clk) { | ||
293 | clk_disable(priv->phy1clk); | ||
294 | clk_put(priv->phy1clk); | ||
295 | } | ||
276 | 296 | ||
277 | kfree(priv); | 297 | kfree(priv); |
278 | 298 | ||