Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ohci-da8xx.c
Go to the documentation of this file.
1 /*
2  * OHCI HCD (Host Controller Driver) for USB.
3  *
4  * TI DA8xx (OMAP-L1x) Bus Glue
5  *
6  * Derived from: ohci-omap.c and ohci-s3c2410.c
7  * Copyright (C) 2008-2009 MontaVista Software, Inc. <[email protected]>
8  *
9  * This file is licensed under the terms of the GNU General Public License
10  * version 2. This program is licensed "as is" without any warranty of any
11  * kind, whether express or implied.
12  */
13 
14 #include <linux/interrupt.h>
15 #include <linux/jiffies.h>
16 #include <linux/platform_device.h>
17 #include <linux/clk.h>
18 
19 #include <mach/da8xx.h>
21 
22 #ifndef CONFIG_ARCH_DAVINCI_DA8XX
23 #error "This file is DA8xx bus glue. Define CONFIG_ARCH_DAVINCI_DA8XX."
24 #endif
25 
26 #define CFGCHIP2 DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG)
27 
28 static struct clk *usb11_clk;
29 static struct clk *usb20_clk;
30 
31 /* Over-current indicator change bitmask */
32 static volatile u16 ocic_mask;
33 
34 static void ohci_da8xx_clock(int on)
35 {
36  u32 cfgchip2;
37 
38  cfgchip2 = __raw_readl(CFGCHIP2);
39  if (on) {
40  clk_enable(usb11_clk);
41 
42  /*
43  * If USB 1.1 reference clock is sourced from USB 2.0 PHY, we
44  * need to enable the USB 2.0 module clocking, start its PHY,
45  * and not allow it to stop the clock during USB 2.0 suspend.
46  */
47  if (!(cfgchip2 & CFGCHIP2_USB1PHYCLKMUX)) {
48  clk_enable(usb20_clk);
49 
50  cfgchip2 &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN);
51  cfgchip2 |= CFGCHIP2_PHY_PLLON;
52  __raw_writel(cfgchip2, CFGCHIP2);
53 
54  pr_info("Waiting for USB PHY clock good...\n");
56  cpu_relax();
57  }
58 
59  /* Enable USB 1.1 PHY */
60  cfgchip2 |= CFGCHIP2_USB1SUSPENDM;
61  } else {
62  clk_disable(usb11_clk);
63  if (!(cfgchip2 & CFGCHIP2_USB1PHYCLKMUX))
64  clk_disable(usb20_clk);
65 
66  /* Disable USB 1.1 PHY */
67  cfgchip2 &= ~CFGCHIP2_USB1SUSPENDM;
68  }
69  __raw_writel(cfgchip2, CFGCHIP2);
70 }
71 
72 /*
73  * Handle the port over-current indicator change.
74  */
75 static void ohci_da8xx_ocic_handler(struct da8xx_ohci_root_hub *hub,
76  unsigned port)
77 {
78  ocic_mask |= 1 << port;
79 
80  /* Once over-current is detected, the port needs to be powered down */
81  if (hub->get_oci(port) > 0)
82  hub->set_power(port, 0);
83 }
84 
85 static int ohci_da8xx_init(struct usb_hcd *hcd)
86 {
87  struct device *dev = hcd->self.controller;
88  struct da8xx_ohci_root_hub *hub = dev->platform_data;
89  struct ohci_hcd *ohci = hcd_to_ohci(hcd);
90  int result;
91  u32 rh_a;
92 
93  dev_dbg(dev, "starting USB controller\n");
94 
95  ohci_da8xx_clock(1);
96 
97  /*
98  * DA8xx only have 1 port connected to the pins but the HC root hub
99  * register A reports 2 ports, thus we'll have to override it...
100  */
101  ohci->num_ports = 1;
102 
103  result = ohci_init(ohci);
104  if (result < 0)
105  return result;
106 
107  /*
108  * Since we're providing a board-specific root hub port power control
109  * and over-current reporting, we have to override the HC root hub A
110  * register's default value, so that ohci_hub_control() could return
111  * the correct hub descriptor...
112  */
113  rh_a = ohci_readl(ohci, &ohci->regs->roothub.a);
114  if (hub->set_power) {
115  rh_a &= ~RH_A_NPS;
116  rh_a |= RH_A_PSM;
117  }
118  if (hub->get_oci) {
119  rh_a &= ~RH_A_NOCP;
120  rh_a |= RH_A_OCPM;
121  }
122  rh_a &= ~RH_A_POTPGT;
123  rh_a |= hub->potpgt << 24;
124  ohci_writel(ohci, rh_a, &ohci->regs->roothub.a);
125 
126  return result;
127 }
128 
129 static void ohci_da8xx_stop(struct usb_hcd *hcd)
130 {
131  ohci_stop(hcd);
132  ohci_da8xx_clock(0);
133 }
134 
135 static int ohci_da8xx_start(struct usb_hcd *hcd)
136 {
137  struct ohci_hcd *ohci = hcd_to_ohci(hcd);
138  int result;
139 
140  result = ohci_run(ohci);
141  if (result < 0)
142  ohci_da8xx_stop(hcd);
143 
144  return result;
145 }
146 
147 /*
148  * Update the status data from the hub with the over-current indicator change.
149  */
150 static int ohci_da8xx_hub_status_data(struct usb_hcd *hcd, char *buf)
151 {
152  int length = ohci_hub_status_data(hcd, buf);
153 
154  /* See if we have OCIC bit set on port 1 */
155  if (ocic_mask & (1 << 1)) {
156  dev_dbg(hcd->self.controller, "over-current indicator change "
157  "on port 1\n");
158 
159  if (!length)
160  length = 1;
161 
162  buf[0] |= 1 << 1;
163  }
164  return length;
165 }
166 
167 /*
168  * Look at the control requests to the root hub and see if we need to override.
169  */
170 static int ohci_da8xx_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
171  u16 wIndex, char *buf, u16 wLength)
172 {
173  struct device *dev = hcd->self.controller;
174  struct da8xx_ohci_root_hub *hub = dev->platform_data;
175  int temp;
176 
177  switch (typeReq) {
178  case GetPortStatus:
179  /* Check the port number */
180  if (wIndex != 1)
181  break;
182 
183  dev_dbg(dev, "GetPortStatus(%u)\n", wIndex);
184 
185  temp = roothub_portstatus(hcd_to_ohci(hcd), wIndex - 1);
186 
187  /* The port power status (PPS) bit defaults to 1 */
188  if (hub->get_power && hub->get_power(wIndex) == 0)
189  temp &= ~RH_PS_PPS;
190 
191  /* The port over-current indicator (POCI) bit is always 0 */
192  if (hub->get_oci && hub->get_oci(wIndex) > 0)
193  temp |= RH_PS_POCI;
194 
195  /* The over-current indicator change (OCIC) bit is 0 too */
196  if (ocic_mask & (1 << wIndex))
197  temp |= RH_PS_OCIC;
198 
199  put_unaligned(cpu_to_le32(temp), (__le32 *)buf);
200  return 0;
201  case SetPortFeature:
202  temp = 1;
203  goto check_port;
204  case ClearPortFeature:
205  temp = 0;
206 
207 check_port:
208  /* Check the port number */
209  if (wIndex != 1)
210  break;
211 
212  switch (wValue) {
213  case USB_PORT_FEAT_POWER:
214  dev_dbg(dev, "%sPortFeature(%u): %s\n",
215  temp ? "Set" : "Clear", wIndex, "POWER");
216 
217  if (!hub->set_power)
218  return -EPIPE;
219 
220  return hub->set_power(wIndex, temp) ? -EPIPE : 0;
222  dev_dbg(dev, "%sPortFeature(%u): %s\n",
223  temp ? "Set" : "Clear", wIndex,
224  "C_OVER_CURRENT");
225 
226  if (temp)
227  ocic_mask |= 1 << wIndex;
228  else
229  ocic_mask &= ~(1 << wIndex);
230  return 0;
231  }
232  }
233 
234  return ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
235 }
236 
237 static const struct hc_driver ohci_da8xx_hc_driver = {
238  .description = hcd_name,
239  .product_desc = "DA8xx OHCI",
240  .hcd_priv_size = sizeof(struct ohci_hcd),
241 
242  /*
243  * generic hardware linkage
244  */
245  .irq = ohci_irq,
246  .flags = HCD_USB11 | HCD_MEMORY,
247 
248  /*
249  * basic lifecycle operations
250  */
251  .reset = ohci_da8xx_init,
252  .start = ohci_da8xx_start,
253  .stop = ohci_da8xx_stop,
254  .shutdown = ohci_shutdown,
255 
256  /*
257  * managing i/o requests and associated device resources
258  */
259  .urb_enqueue = ohci_urb_enqueue,
260  .urb_dequeue = ohci_urb_dequeue,
261  .endpoint_disable = ohci_endpoint_disable,
262 
263  /*
264  * scheduling support
265  */
266  .get_frame_number = ohci_get_frame,
267 
268  /*
269  * root hub support
270  */
271  .hub_status_data = ohci_da8xx_hub_status_data,
272  .hub_control = ohci_da8xx_hub_control,
273 
274 #ifdef CONFIG_PM
275  .bus_suspend = ohci_bus_suspend,
276  .bus_resume = ohci_bus_resume,
277 #endif
278  .start_port_reset = ohci_start_port_reset,
279 };
280 
281 /*-------------------------------------------------------------------------*/
282 
283 
292 static int usb_hcd_da8xx_probe(const struct hc_driver *driver,
293  struct platform_device *pdev)
294 {
295  struct da8xx_ohci_root_hub *hub = pdev->dev.platform_data;
296  struct usb_hcd *hcd;
297  struct resource *mem;
298  int error, irq;
299 
300  if (hub == NULL)
301  return -ENODEV;
302 
303  usb11_clk = clk_get(&pdev->dev, "usb11");
304  if (IS_ERR(usb11_clk))
305  return PTR_ERR(usb11_clk);
306 
307  usb20_clk = clk_get(&pdev->dev, "usb20");
308  if (IS_ERR(usb20_clk)) {
309  error = PTR_ERR(usb20_clk);
310  goto err0;
311  }
312 
313  hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
314  if (!hcd) {
315  error = -ENOMEM;
316  goto err1;
317  }
318 
319  mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
320  if (!mem) {
321  error = -ENODEV;
322  goto err2;
323  }
324  hcd->rsrc_start = mem->start;
325  hcd->rsrc_len = resource_size(mem);
326 
327  if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
328  dev_dbg(&pdev->dev, "request_mem_region failed\n");
329  error = -EBUSY;
330  goto err2;
331  }
332 
333  hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
334  if (!hcd->regs) {
335  dev_err(&pdev->dev, "ioremap failed\n");
336  error = -ENOMEM;
337  goto err3;
338  }
339 
340  ohci_hcd_init(hcd_to_ohci(hcd));
341 
342  irq = platform_get_irq(pdev, 0);
343  if (irq < 0) {
344  error = -ENODEV;
345  goto err4;
346  }
347  error = usb_add_hcd(hcd, irq, 0);
348  if (error)
349  goto err4;
350 
351  if (hub->ocic_notify) {
352  error = hub->ocic_notify(ohci_da8xx_ocic_handler);
353  if (!error)
354  return 0;
355  }
356 
357  usb_remove_hcd(hcd);
358 err4:
359  iounmap(hcd->regs);
360 err3:
361  release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
362 err2:
363  usb_put_hcd(hcd);
364 err1:
365  clk_put(usb20_clk);
366 err0:
367  clk_put(usb11_clk);
368  return error;
369 }
370 
380 static inline void
381 usb_hcd_da8xx_remove(struct usb_hcd *hcd, struct platform_device *pdev)
382 {
383  struct da8xx_ohci_root_hub *hub = pdev->dev.platform_data;
384 
385  hub->ocic_notify(NULL);
386  usb_remove_hcd(hcd);
387  iounmap(hcd->regs);
388  release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
389  usb_put_hcd(hcd);
390  clk_put(usb20_clk);
391  clk_put(usb11_clk);
392 }
393 
394 static int ohci_hcd_da8xx_drv_probe(struct platform_device *dev)
395 {
396  return usb_hcd_da8xx_probe(&ohci_da8xx_hc_driver, dev);
397 }
398 
399 static int ohci_hcd_da8xx_drv_remove(struct platform_device *dev)
400 {
401  struct usb_hcd *hcd = platform_get_drvdata(dev);
402 
403  usb_hcd_da8xx_remove(hcd, dev);
404  platform_set_drvdata(dev, NULL);
405 
406  return 0;
407 }
408 
409 #ifdef CONFIG_PM
410 static int ohci_da8xx_suspend(struct platform_device *dev, pm_message_t message)
411 {
412  struct usb_hcd *hcd = platform_get_drvdata(dev);
413  struct ohci_hcd *ohci = hcd_to_ohci(hcd);
414 
415  if (time_before(jiffies, ohci->next_statechange))
416  msleep(5);
417  ohci->next_statechange = jiffies;
418 
419  ohci_da8xx_clock(0);
420  hcd->state = HC_STATE_SUSPENDED;
421  dev->dev.power.power_state = PMSG_SUSPEND;
422  return 0;
423 }
424 
425 static int ohci_da8xx_resume(struct platform_device *dev)
426 {
427  struct usb_hcd *hcd = platform_get_drvdata(dev);
428  struct ohci_hcd *ohci = hcd_to_ohci(hcd);
429 
430  if (time_before(jiffies, ohci->next_statechange))
431  msleep(5);
432  ohci->next_statechange = jiffies;
433 
434  ohci_da8xx_clock(1);
435  dev->dev.power.power_state = PMSG_ON;
436  usb_hcd_resume_root_hub(hcd);
437  return 0;
438 }
439 #endif
440 
441 /*
442  * Driver definition to register with platform structure.
443  */
444 static struct platform_driver ohci_hcd_da8xx_driver = {
445  .probe = ohci_hcd_da8xx_drv_probe,
446  .remove = ohci_hcd_da8xx_drv_remove,
447  .shutdown = usb_hcd_platform_shutdown,
448 #ifdef CONFIG_PM
449  .suspend = ohci_da8xx_suspend,
450  .resume = ohci_da8xx_resume,
451 #endif
452  .driver = {
453  .owner = THIS_MODULE,
454  .name = "ohci",
455  },
456 };
457 
458 MODULE_ALIAS("platform:ohci");