Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ehci-grlib.c
Go to the documentation of this file.
1 /*
2  * Driver for Aeroflex Gaisler GRLIB GRUSBHC EHCI host controller
3  *
4  * GRUSBHC is typically found on LEON/GRLIB SoCs
5  *
6  * (c) Jan Andersson <[email protected]>
7  *
8  * Based on ehci-ppc-of.c which is:
9  * (c) Valentine Barshak <[email protected]>
10  * and in turn based on "ehci-ppc-soc.c" by Stefan Roese <[email protected]>
11  * and "ohci-ppc-of.c" by Sylvain Munaut <[email protected]>
12  *
13  * This program is free software; you can redistribute it and/or modify it
14  * under the terms of the GNU General Public License as published by the
15  * Free Software Foundation; either version 2 of the License, or (at your
16  * option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful, but
19  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  * for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26  */
27 
28 
29 #include <linux/signal.h>
30 
31 #include <linux/of_irq.h>
32 #include <linux/of_address.h>
33 #include <linux/of_platform.h>
34 
35 #define GRUSBHC_HCIVERSION 0x0100 /* Known value of cap. reg. HCIVERSION */
36 
37 /* called during probe() after chip reset completes */
38 static int ehci_grlib_setup(struct usb_hcd *hcd)
39 {
40  struct ehci_hcd *ehci = hcd_to_ehci(hcd);
41  int retval;
42 
43  retval = ehci_setup(hcd);
44  if (retval)
45  return retval;
46 
47  ehci_port_power(ehci, 1);
48 
49  return retval;
50 }
51 
52 
53 static const struct hc_driver ehci_grlib_hc_driver = {
54  .description = hcd_name,
55  .product_desc = "GRLIB GRUSBHC EHCI",
56  .hcd_priv_size = sizeof(struct ehci_hcd),
57 
58  /*
59  * generic hardware linkage
60  */
61  .irq = ehci_irq,
62  .flags = HCD_MEMORY | HCD_USB2,
63 
64  /*
65  * basic lifecycle operations
66  */
67  .reset = ehci_grlib_setup,
68  .start = ehci_run,
69  .stop = ehci_stop,
70  .shutdown = ehci_shutdown,
71 
72  /*
73  * managing i/o requests and associated device resources
74  */
75  .urb_enqueue = ehci_urb_enqueue,
76  .urb_dequeue = ehci_urb_dequeue,
77  .endpoint_disable = ehci_endpoint_disable,
78  .endpoint_reset = ehci_endpoint_reset,
79 
80  /*
81  * scheduling support
82  */
83  .get_frame_number = ehci_get_frame,
84 
85  /*
86  * root hub support
87  */
88  .hub_status_data = ehci_hub_status_data,
89  .hub_control = ehci_hub_control,
90 #ifdef CONFIG_PM
91  .bus_suspend = ehci_bus_suspend,
92  .bus_resume = ehci_bus_resume,
93 #endif
94  .relinquish_port = ehci_relinquish_port,
95  .port_handed_over = ehci_port_handed_over,
96 
97  .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
98 };
99 
100 
101 static int __devinit ehci_hcd_grlib_probe(struct platform_device *op)
102 {
103  struct device_node *dn = op->dev.of_node;
104  struct usb_hcd *hcd;
105  struct ehci_hcd *ehci = NULL;
106  struct resource res;
107  u32 hc_capbase;
108  int irq;
109  int rv;
110 
111  if (usb_disabled())
112  return -ENODEV;
113 
114  dev_dbg(&op->dev, "initializing GRUSBHC EHCI USB Controller\n");
115 
116  rv = of_address_to_resource(dn, 0, &res);
117  if (rv)
118  return rv;
119 
120  /* usb_create_hcd requires dma_mask != NULL */
121  op->dev.dma_mask = &op->dev.coherent_dma_mask;
122  hcd = usb_create_hcd(&ehci_grlib_hc_driver, &op->dev,
123  "GRUSBHC EHCI USB");
124  if (!hcd)
125  return -ENOMEM;
126 
127  hcd->rsrc_start = res.start;
128  hcd->rsrc_len = resource_size(&res);
129 
130  irq = irq_of_parse_and_map(dn, 0);
131  if (irq == NO_IRQ) {
132  printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__);
133  rv = -EBUSY;
134  goto err_irq;
135  }
136 
137  hcd->regs = devm_request_and_ioremap(&op->dev, &res);
138  if (!hcd->regs) {
139  pr_err("%s: devm_request_and_ioremap failed\n", __FILE__);
140  rv = -ENOMEM;
141  goto err_ioremap;
142  }
143 
144  ehci = hcd_to_ehci(hcd);
145 
146  ehci->caps = hcd->regs;
147 
148  /* determine endianness of this implementation */
149  hc_capbase = ehci_readl(ehci, &ehci->caps->hc_capbase);
150  if (HC_VERSION(ehci, hc_capbase) != GRUSBHC_HCIVERSION) {
151  ehci->big_endian_mmio = 1;
152  ehci->big_endian_desc = 1;
153  ehci->big_endian_capbase = 1;
154  }
155 
156  rv = usb_add_hcd(hcd, irq, 0);
157  if (rv)
158  goto err_ioremap;
159 
160  return 0;
161 
162 err_ioremap:
163  irq_dispose_mapping(irq);
164 err_irq:
165  usb_put_hcd(hcd);
166 
167  return rv;
168 }
169 
170 
171 static int ehci_hcd_grlib_remove(struct platform_device *op)
172 {
173  struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
174 
175  dev_set_drvdata(&op->dev, NULL);
176 
177  dev_dbg(&op->dev, "stopping GRLIB GRUSBHC EHCI USB Controller\n");
178 
179  usb_remove_hcd(hcd);
180 
181  irq_dispose_mapping(hcd->irq);
182 
183  usb_put_hcd(hcd);
184 
185  return 0;
186 }
187 
188 
189 static void ehci_hcd_grlib_shutdown(struct platform_device *op)
190 {
191  struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
192 
193  if (hcd->driver->shutdown)
194  hcd->driver->shutdown(hcd);
195 }
196 
197 
198 static const struct of_device_id ehci_hcd_grlib_of_match[] = {
199  {
200  .name = "GAISLER_EHCI",
201  },
202  {
203  .name = "01_026",
204  },
205  {},
206 };
207 MODULE_DEVICE_TABLE(of, ehci_hcd_grlib_of_match);
208 
209 
210 static struct platform_driver ehci_grlib_driver = {
211  .probe = ehci_hcd_grlib_probe,
212  .remove = ehci_hcd_grlib_remove,
213  .shutdown = ehci_hcd_grlib_shutdown,
214  .driver = {
215  .name = "grlib-ehci",
216  .owner = THIS_MODULE,
217  .of_match_table = ehci_hcd_grlib_of_match,
218  },
219 };