Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ohci-xls.c
Go to the documentation of this file.
1 /*
2  * OHCI HCD for Netlogic XLS processors.
3  *
4  * (C) Copyright 2011 Netlogic Microsystems Inc.
5  *
6  * Based on ohci-au1xxx.c, and other Linux OHCI drivers.
7  *
8  * This file is subject to the terms and conditions of the GNU General Public
9  * License. See the file COPYING in the main directory of this archive for
10  * more details.
11  */
12 
13 #include <linux/platform_device.h>
14 #include <linux/signal.h>
15 
16 static int ohci_xls_probe_internal(const struct hc_driver *driver,
17  struct platform_device *dev)
18 {
19  struct resource *res;
20  struct usb_hcd *hcd;
21  int retval, irq;
22 
23  /* Get our IRQ from an earlier registered Platform Resource */
24  irq = platform_get_irq(dev, 0);
25  if (irq < 0) {
26  dev_err(&dev->dev, "Found HC with no IRQ\n");
27  return -ENODEV;
28  }
29 
30  /* Get our Memory Handle */
32  if (!res) {
33  dev_err(&dev->dev, "MMIO Handle incorrect!\n");
34  return -ENODEV;
35  }
36 
37  hcd = usb_create_hcd(driver, &dev->dev, "XLS");
38  if (!hcd) {
39  retval = -ENOMEM;
40  goto err1;
41  }
42  hcd->rsrc_start = res->start;
43  hcd->rsrc_len = resource_size(res);
44 
45  if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
46  driver->description)) {
47  dev_dbg(&dev->dev, "Controller already in use\n");
48  retval = -EBUSY;
49  goto err2;
50  }
51 
52  hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
53  if (hcd->regs == NULL) {
54  dev_dbg(&dev->dev, "error mapping memory\n");
55  retval = -EFAULT;
56  goto err3;
57  }
58 
59  retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
60  if (retval != 0)
61  goto err4;
62  return retval;
63 
64 err4:
65  iounmap(hcd->regs);
66 err3:
67  release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
68 err2:
69  usb_put_hcd(hcd);
70 err1:
71  dev_err(&dev->dev, "init fail, %d\n", retval);
72  return retval;
73 }
74 
75 static int ohci_xls_reset(struct usb_hcd *hcd)
76 {
77  struct ohci_hcd *ohci = hcd_to_ohci(hcd);
78 
79  ohci_hcd_init(ohci);
80  return ohci_init(ohci);
81 }
82 
83 static int __devinit ohci_xls_start(struct usb_hcd *hcd)
84 {
85  struct ohci_hcd *ohci;
86  int ret;
87 
88  ohci = hcd_to_ohci(hcd);
89  ret = ohci_run(ohci);
90  if (ret < 0) {
91  dev_err(hcd->self.controller, "can't start %s\n",
92  hcd->self.bus_name);
93  ohci_stop(hcd);
94  return ret;
95  }
96  return 0;
97 }
98 
99 static struct hc_driver ohci_xls_hc_driver = {
100  .description = hcd_name,
101  .product_desc = "XLS OHCI Host Controller",
102  .hcd_priv_size = sizeof(struct ohci_hcd),
103  .irq = ohci_irq,
104  .flags = HCD_MEMORY | HCD_USB11,
105  .reset = ohci_xls_reset,
106  .start = ohci_xls_start,
107  .stop = ohci_stop,
108  .shutdown = ohci_shutdown,
109  .urb_enqueue = ohci_urb_enqueue,
110  .urb_dequeue = ohci_urb_dequeue,
111  .endpoint_disable = ohci_endpoint_disable,
112  .get_frame_number = ohci_get_frame,
113  .hub_status_data = ohci_hub_status_data,
114  .hub_control = ohci_hub_control,
115 #ifdef CONFIG_PM
116  .bus_suspend = ohci_bus_suspend,
117  .bus_resume = ohci_bus_resume,
118 #endif
119  .start_port_reset = ohci_start_port_reset,
120 };
121 
122 static int ohci_xls_probe(struct platform_device *dev)
123 {
124  int ret;
125 
126  pr_debug("In ohci_xls_probe");
127  if (usb_disabled())
128  return -ENODEV;
129  ret = ohci_xls_probe_internal(&ohci_xls_hc_driver, dev);
130  return ret;
131 }
132 
133 static int ohci_xls_remove(struct platform_device *dev)
134 {
135  struct usb_hcd *hcd = platform_get_drvdata(dev);
136 
137  usb_remove_hcd(hcd);
138  iounmap(hcd->regs);
139  release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
140  usb_put_hcd(hcd);
141  return 0;
142 }
143 
144 static struct platform_driver ohci_xls_driver = {
145  .probe = ohci_xls_probe,
146  .remove = ohci_xls_remove,
147  .shutdown = usb_hcd_platform_shutdown,
148  .driver = {
149  .name = "ohci-xls-0",
150  .owner = THIS_MODULE,
151  },
152 };