diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/ehci-orion.c | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 9298be7c0f9b..9c98bac0a5bc 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c | |||
@@ -42,6 +42,12 @@ | |||
42 | 42 | ||
43 | #define DRIVER_DESC "EHCI orion driver" | 43 | #define DRIVER_DESC "EHCI orion driver" |
44 | 44 | ||
45 | #define hcd_to_orion_priv(h) ((struct orion_ehci_hcd *)hcd_to_ehci(h)->priv) | ||
46 | |||
47 | struct orion_ehci_hcd { | ||
48 | struct clk *clk; | ||
49 | }; | ||
50 | |||
45 | static const char hcd_name[] = "ehci-orion"; | 51 | static const char hcd_name[] = "ehci-orion"; |
46 | 52 | ||
47 | static struct hc_driver __read_mostly ehci_orion_hc_driver; | 53 | static struct hc_driver __read_mostly ehci_orion_hc_driver; |
@@ -137,6 +143,10 @@ ehci_orion_conf_mbus_windows(struct usb_hcd *hcd, | |||
137 | } | 143 | } |
138 | } | 144 | } |
139 | 145 | ||
146 | static const struct ehci_driver_overrides orion_overrides __initconst = { | ||
147 | .extra_priv_size = sizeof(struct orion_ehci_hcd), | ||
148 | }; | ||
149 | |||
140 | static int ehci_orion_drv_probe(struct platform_device *pdev) | 150 | static int ehci_orion_drv_probe(struct platform_device *pdev) |
141 | { | 151 | { |
142 | struct orion_ehci_data *pd = dev_get_platdata(&pdev->dev); | 152 | struct orion_ehci_data *pd = dev_get_platdata(&pdev->dev); |
@@ -144,10 +154,10 @@ static int ehci_orion_drv_probe(struct platform_device *pdev) | |||
144 | struct resource *res; | 154 | struct resource *res; |
145 | struct usb_hcd *hcd; | 155 | struct usb_hcd *hcd; |
146 | struct ehci_hcd *ehci; | 156 | struct ehci_hcd *ehci; |
147 | struct clk *clk; | ||
148 | void __iomem *regs; | 157 | void __iomem *regs; |
149 | int irq, err; | 158 | int irq, err; |
150 | enum orion_ehci_phy_ver phy_version; | 159 | enum orion_ehci_phy_ver phy_version; |
160 | struct orion_ehci_hcd *priv; | ||
151 | 161 | ||
152 | if (usb_disabled()) | 162 | if (usb_disabled()) |
153 | return -ENODEV; | 163 | return -ENODEV; |
@@ -187,17 +197,11 @@ static int ehci_orion_drv_probe(struct platform_device *pdev) | |||
187 | goto err; | 197 | goto err; |
188 | } | 198 | } |
189 | 199 | ||
190 | /* Not all platforms can gate the clock, so it is not | ||
191 | an error if the clock does not exists. */ | ||
192 | clk = devm_clk_get(&pdev->dev, NULL); | ||
193 | if (!IS_ERR(clk)) | ||
194 | clk_prepare_enable(clk); | ||
195 | |||
196 | hcd = usb_create_hcd(&ehci_orion_hc_driver, | 200 | hcd = usb_create_hcd(&ehci_orion_hc_driver, |
197 | &pdev->dev, dev_name(&pdev->dev)); | 201 | &pdev->dev, dev_name(&pdev->dev)); |
198 | if (!hcd) { | 202 | if (!hcd) { |
199 | err = -ENOMEM; | 203 | err = -ENOMEM; |
200 | goto err_create_hcd; | 204 | goto err; |
201 | } | 205 | } |
202 | 206 | ||
203 | hcd->rsrc_start = res->start; | 207 | hcd->rsrc_start = res->start; |
@@ -208,6 +212,15 @@ static int ehci_orion_drv_probe(struct platform_device *pdev) | |||
208 | ehci->caps = hcd->regs + 0x100; | 212 | ehci->caps = hcd->regs + 0x100; |
209 | hcd->has_tt = 1; | 213 | hcd->has_tt = 1; |
210 | 214 | ||
215 | priv = hcd_to_orion_priv(hcd); | ||
216 | /* | ||
217 | * Not all platforms can gate the clock, so it is not an error if | ||
218 | * the clock does not exists. | ||
219 | */ | ||
220 | priv->clk = devm_clk_get(&pdev->dev, NULL); | ||
221 | if (!IS_ERR(priv->clk)) | ||
222 | clk_prepare_enable(priv->clk); | ||
223 | |||
211 | /* | 224 | /* |
212 | * (Re-)program MBUS remapping windows if we are asked to. | 225 | * (Re-)program MBUS remapping windows if we are asked to. |
213 | */ | 226 | */ |
@@ -243,10 +256,9 @@ static int ehci_orion_drv_probe(struct platform_device *pdev) | |||
243 | return 0; | 256 | return 0; |
244 | 257 | ||
245 | err_add_hcd: | 258 | err_add_hcd: |
259 | if (!IS_ERR(priv->clk)) | ||
260 | clk_disable_unprepare(priv->clk); | ||
246 | usb_put_hcd(hcd); | 261 | usb_put_hcd(hcd); |
247 | err_create_hcd: | ||
248 | if (!IS_ERR(clk)) | ||
249 | clk_disable_unprepare(clk); | ||
250 | err: | 262 | err: |
251 | dev_err(&pdev->dev, "init %s fail, %d\n", | 263 | dev_err(&pdev->dev, "init %s fail, %d\n", |
252 | dev_name(&pdev->dev), err); | 264 | dev_name(&pdev->dev), err); |
@@ -257,14 +269,15 @@ err: | |||
257 | static int ehci_orion_drv_remove(struct platform_device *pdev) | 269 | static int ehci_orion_drv_remove(struct platform_device *pdev) |
258 | { | 270 | { |
259 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | 271 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
260 | struct clk *clk; | 272 | struct orion_ehci_hcd *priv = hcd_to_orion_priv(hcd); |
261 | 273 | ||
262 | usb_remove_hcd(hcd); | 274 | usb_remove_hcd(hcd); |
275 | |||
276 | if (!IS_ERR(priv->clk)) | ||
277 | clk_disable_unprepare(priv->clk); | ||
278 | |||
263 | usb_put_hcd(hcd); | 279 | usb_put_hcd(hcd); |
264 | 280 | ||
265 | clk = devm_clk_get(&pdev->dev, NULL); | ||
266 | if (!IS_ERR(clk)) | ||
267 | clk_disable_unprepare(clk); | ||
268 | return 0; | 281 | return 0; |
269 | } | 282 | } |
270 | 283 | ||
@@ -292,7 +305,7 @@ static int __init ehci_orion_init(void) | |||
292 | 305 | ||
293 | pr_info("%s: " DRIVER_DESC "\n", hcd_name); | 306 | pr_info("%s: " DRIVER_DESC "\n", hcd_name); |
294 | 307 | ||
295 | ehci_init_driver(&ehci_orion_hc_driver, NULL); | 308 | ehci_init_driver(&ehci_orion_hc_driver, &orion_overrides); |
296 | return platform_driver_register(&ehci_orion_driver); | 309 | return platform_driver_register(&ehci_orion_driver); |
297 | } | 310 | } |
298 | module_init(ehci_orion_init); | 311 | module_init(ehci_orion_init); |