Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ehci-mv.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2011 Marvell International Ltd. All rights reserved.
3  * Author: Chao Xie <[email protected]>
4  * Neil Zhang <[email protected]>
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation; either version 2 of the License, or (at your
9  * option) any later version.
10  */
11 
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 #include <linux/clk.h>
16 #include <linux/err.h>
17 #include <linux/usb/otg.h>
19 
20 #define CAPLENGTH_MASK (0xff)
21 
22 struct ehci_hcd_mv {
23  struct usb_hcd *hcd;
24 
25  /* Which mode does this ehci running OTG/Host ? */
26  int mode;
27 
31 
32  struct usb_phy *otg;
33 
35 
36  /* clock source and total clock number */
37  unsigned int clknum;
38  struct clk *clk[0];
39 };
40 
41 static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv)
42 {
43  unsigned int i;
44 
45  for (i = 0; i < ehci_mv->clknum; i++)
46  clk_enable(ehci_mv->clk[i]);
47 }
48 
49 static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv)
50 {
51  unsigned int i;
52 
53  for (i = 0; i < ehci_mv->clknum; i++)
54  clk_disable(ehci_mv->clk[i]);
55 }
56 
57 static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv)
58 {
59  int retval;
60 
61  ehci_clock_enable(ehci_mv);
62  if (ehci_mv->pdata->phy_init) {
63  retval = ehci_mv->pdata->phy_init(ehci_mv->phy_regs);
64  if (retval)
65  return retval;
66  }
67 
68  return 0;
69 }
70 
71 static void mv_ehci_disable(struct ehci_hcd_mv *ehci_mv)
72 {
73  if (ehci_mv->pdata->phy_deinit)
74  ehci_mv->pdata->phy_deinit(ehci_mv->phy_regs);
75  ehci_clock_disable(ehci_mv);
76 }
77 
78 static int mv_ehci_reset(struct usb_hcd *hcd)
79 {
80  struct device *dev = hcd->self.controller;
81  struct ehci_hcd_mv *ehci_mv = dev_get_drvdata(dev);
82  int retval;
83 
84  if (ehci_mv == NULL) {
85  dev_err(dev, "Can not find private ehci data\n");
86  return -ENODEV;
87  }
88 
89  hcd->has_tt = 1;
90 
91  retval = ehci_setup(hcd);
92  if (retval)
93  dev_err(dev, "ehci_setup failed %d\n", retval);
94 
95  return retval;
96 }
97 
98 static const struct hc_driver mv_ehci_hc_driver = {
99  .description = hcd_name,
100  .product_desc = "Marvell EHCI",
101  .hcd_priv_size = sizeof(struct ehci_hcd),
102 
103  /*
104  * generic hardware linkage
105  */
106  .irq = ehci_irq,
107  .flags = HCD_MEMORY | HCD_USB2,
108 
109  /*
110  * basic lifecycle operations
111  */
112  .reset = mv_ehci_reset,
113  .start = ehci_run,
114  .stop = ehci_stop,
115  .shutdown = ehci_shutdown,
116 
117  /*
118  * managing i/o requests and associated device resources
119  */
120  .urb_enqueue = ehci_urb_enqueue,
121  .urb_dequeue = ehci_urb_dequeue,
122  .endpoint_disable = ehci_endpoint_disable,
123  .endpoint_reset = ehci_endpoint_reset,
124  .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
125 
126  /*
127  * scheduling support
128  */
129  .get_frame_number = ehci_get_frame,
130 
131  /*
132  * root hub support
133  */
134  .hub_status_data = ehci_hub_status_data,
135  .hub_control = ehci_hub_control,
136  .bus_suspend = ehci_bus_suspend,
137  .bus_resume = ehci_bus_resume,
138 };
139 
140 static int mv_ehci_probe(struct platform_device *pdev)
141 {
142  struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
143  struct usb_hcd *hcd;
144  struct ehci_hcd *ehci;
145  struct ehci_hcd_mv *ehci_mv;
146  struct resource *r;
147  int clk_i, retval = -ENODEV;
148  u32 offset;
149  size_t size;
150 
151  if (!pdata) {
152  dev_err(&pdev->dev, "missing platform_data\n");
153  return -ENODEV;
154  }
155 
156  if (usb_disabled())
157  return -ENODEV;
158 
159  hcd = usb_create_hcd(&mv_ehci_hc_driver, &pdev->dev, "mv ehci");
160  if (!hcd)
161  return -ENOMEM;
162 
163  size = sizeof(*ehci_mv) + sizeof(struct clk *) * pdata->clknum;
164  ehci_mv = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
165  if (ehci_mv == NULL) {
166  dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n");
167  retval = -ENOMEM;
168  goto err_put_hcd;
169  }
170 
171  platform_set_drvdata(pdev, ehci_mv);
172  ehci_mv->pdata = pdata;
173  ehci_mv->hcd = hcd;
174 
175  ehci_mv->clknum = pdata->clknum;
176  for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) {
177  ehci_mv->clk[clk_i] =
178  devm_clk_get(&pdev->dev, pdata->clkname[clk_i]);
179  if (IS_ERR(ehci_mv->clk[clk_i])) {
180  dev_err(&pdev->dev, "error get clck \"%s\"\n",
181  pdata->clkname[clk_i]);
182  retval = PTR_ERR(ehci_mv->clk[clk_i]);
183  goto err_clear_drvdata;
184  }
185  }
186 
187  r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phyregs");
188  if (r == NULL) {
189  dev_err(&pdev->dev, "no phy I/O memory resource defined\n");
190  retval = -ENODEV;
191  goto err_clear_drvdata;
192  }
193 
194  ehci_mv->phy_regs = devm_ioremap(&pdev->dev, r->start,
195  resource_size(r));
196  if (ehci_mv->phy_regs == 0) {
197  dev_err(&pdev->dev, "failed to map phy I/O memory\n");
198  retval = -EFAULT;
199  goto err_clear_drvdata;
200  }
201 
202  r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "capregs");
203  if (!r) {
204  dev_err(&pdev->dev, "no I/O memory resource defined\n");
205  retval = -ENODEV;
206  goto err_clear_drvdata;
207  }
208 
209  ehci_mv->cap_regs = devm_ioremap(&pdev->dev, r->start,
210  resource_size(r));
211  if (ehci_mv->cap_regs == NULL) {
212  dev_err(&pdev->dev, "failed to map I/O memory\n");
213  retval = -EFAULT;
214  goto err_clear_drvdata;
215  }
216 
217  retval = mv_ehci_enable(ehci_mv);
218  if (retval) {
219  dev_err(&pdev->dev, "init phy error %d\n", retval);
220  goto err_clear_drvdata;
221  }
222 
223  offset = readl(ehci_mv->cap_regs) & CAPLENGTH_MASK;
224  ehci_mv->op_regs =
225  (void __iomem *) ((unsigned long) ehci_mv->cap_regs + offset);
226 
227  hcd->rsrc_start = r->start;
228  hcd->rsrc_len = r->end - r->start + 1;
229  hcd->regs = ehci_mv->op_regs;
230 
231  hcd->irq = platform_get_irq(pdev, 0);
232  if (!hcd->irq) {
233  dev_err(&pdev->dev, "Cannot get irq.");
234  retval = -ENODEV;
235  goto err_disable_clk;
236  }
237 
238  ehci = hcd_to_ehci(hcd);
239  ehci->caps = (struct ehci_caps *) ehci_mv->cap_regs;
240 
241  ehci_mv->mode = pdata->mode;
242  if (ehci_mv->mode == MV_USB_MODE_OTG) {
243 #ifdef CONFIG_USB_OTG_UTILS
244  ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
245  if (IS_ERR_OR_NULL(ehci_mv->otg)) {
246  dev_err(&pdev->dev,
247  "unable to find transceiver\n");
248  retval = -ENODEV;
249  goto err_disable_clk;
250  }
251 
252  retval = otg_set_host(ehci_mv->otg->otg, &hcd->self);
253  if (retval < 0) {
254  dev_err(&pdev->dev,
255  "unable to register with transceiver\n");
256  retval = -ENODEV;
257  goto err_disable_clk;
258  }
259  /* otg will enable clock before use as host */
260  mv_ehci_disable(ehci_mv);
261 #else
262  dev_info(&pdev->dev, "MV_USB_MODE_OTG "
263  "must have CONFIG_USB_OTG_UTILS enabled\n");
264  goto err_disable_clk;
265 #endif
266  } else {
267  if (pdata->set_vbus)
268  pdata->set_vbus(1);
269 
270  retval = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
271  if (retval) {
272  dev_err(&pdev->dev,
273  "failed to add hcd with err %d\n", retval);
274  goto err_set_vbus;
275  }
276  }
277 
278  if (pdata->private_init)
279  pdata->private_init(ehci_mv->op_regs, ehci_mv->phy_regs);
280 
281  dev_info(&pdev->dev,
282  "successful find EHCI device with regs 0x%p irq %d"
283  " working in %s mode\n", hcd->regs, hcd->irq,
284  ehci_mv->mode == MV_USB_MODE_OTG ? "OTG" : "Host");
285 
286  return 0;
287 
288 err_set_vbus:
289  if (pdata->set_vbus)
290  pdata->set_vbus(0);
291 err_disable_clk:
292  mv_ehci_disable(ehci_mv);
293 err_clear_drvdata:
294  platform_set_drvdata(pdev, NULL);
295 err_put_hcd:
296  usb_put_hcd(hcd);
297 
298  return retval;
299 }
300 
301 static int mv_ehci_remove(struct platform_device *pdev)
302 {
303  struct ehci_hcd_mv *ehci_mv = platform_get_drvdata(pdev);
304  struct usb_hcd *hcd = ehci_mv->hcd;
305  int clk_i;
306 
307  if (hcd->rh_registered)
308  usb_remove_hcd(hcd);
309 
310  if (!IS_ERR_OR_NULL(ehci_mv->otg))
311  otg_set_host(ehci_mv->otg->otg, NULL);
312 
313  if (ehci_mv->mode == MV_USB_MODE_HOST) {
314  if (ehci_mv->pdata->set_vbus)
315  ehci_mv->pdata->set_vbus(0);
316 
317  mv_ehci_disable(ehci_mv);
318  }
319 
320  platform_set_drvdata(pdev, NULL);
321 
322  usb_put_hcd(hcd);
323 
324  return 0;
325 }
326 
327 MODULE_ALIAS("mv-ehci");
328 
329 static const struct platform_device_id ehci_id_table[] = {
330  {"pxa-u2oehci", PXA_U2OEHCI},
331  {"pxa-sph", PXA_SPH},
332  {"mmp3-hsic", MMP3_HSIC},
333  {"mmp3-fsic", MMP3_FSIC},
334  {},
335 };
336 
337 static void mv_ehci_shutdown(struct platform_device *pdev)
338 {
339  struct ehci_hcd_mv *ehci_mv = platform_get_drvdata(pdev);
340  struct usb_hcd *hcd = ehci_mv->hcd;
341 
342  if (!hcd->rh_registered)
343  return;
344 
345  if (hcd->driver->shutdown)
346  hcd->driver->shutdown(hcd);
347 }
348 
349 static struct platform_driver ehci_mv_driver = {
350  .probe = mv_ehci_probe,
351  .remove = mv_ehci_remove,
352  .shutdown = mv_ehci_shutdown,
353  .driver = {
354  .name = "mv-ehci",
355  .bus = &platform_bus_type,
356  },
357  .id_table = ehci_id_table,
358 };