Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ehci-cns3xxx.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Cavium Networks
3  *
4  * This file is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License, Version 2, as
6  * published by the Free Software Foundation.
7  */
8 
10 #include <linux/atomic.h>
11 #include <mach/cns3xxx.h>
12 #include <mach/pm.h>
13 
14 static int cns3xxx_ehci_init(struct usb_hcd *hcd)
15 {
16  struct ehci_hcd *ehci = hcd_to_ehci(hcd);
17  int retval;
18 
19  /*
20  * EHCI and OHCI share the same clock and power,
21  * resetting twice would cause the 1st controller been reset.
22  * Therefore only do power up at the first up device, and
23  * power down at the last down device.
24  *
25  * Set USB AHB INCR length to 16
26  */
27  if (atomic_inc_return(&usb_pwr_ref) == 1) {
33  }
34 
35  ehci->caps = hcd->regs;
36 
37  hcd->has_tt = 0;
38 
39  retval = ehci_setup(hcd);
40  if (retval)
41  return retval;
42 
43  ehci_port_power(ehci, 0);
44 
45  return retval;
46 }
47 
48 static const struct hc_driver cns3xxx_ehci_hc_driver = {
49  .description = hcd_name,
50  .product_desc = "CNS3XXX EHCI Host Controller",
51  .hcd_priv_size = sizeof(struct ehci_hcd),
52  .irq = ehci_irq,
53  .flags = HCD_MEMORY | HCD_USB2,
54  .reset = cns3xxx_ehci_init,
55  .start = ehci_run,
56  .stop = ehci_stop,
57  .shutdown = ehci_shutdown,
58  .urb_enqueue = ehci_urb_enqueue,
59  .urb_dequeue = ehci_urb_dequeue,
60  .endpoint_disable = ehci_endpoint_disable,
61  .endpoint_reset = ehci_endpoint_reset,
62  .get_frame_number = ehci_get_frame,
63  .hub_status_data = ehci_hub_status_data,
64  .hub_control = ehci_hub_control,
65 #ifdef CONFIG_PM
66  .bus_suspend = ehci_bus_suspend,
67  .bus_resume = ehci_bus_resume,
68 #endif
69  .relinquish_port = ehci_relinquish_port,
70  .port_handed_over = ehci_port_handed_over,
71 
72  .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
73 };
74 
75 static int cns3xxx_ehci_probe(struct platform_device *pdev)
76 {
77  struct device *dev = &pdev->dev;
78  struct usb_hcd *hcd;
79  const struct hc_driver *driver = &cns3xxx_ehci_hc_driver;
80  struct resource *res;
81  int irq;
82  int retval;
83 
84  if (usb_disabled())
85  return -ENODEV;
86 
87  res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
88  if (!res) {
89  dev_err(dev, "Found HC with no IRQ.\n");
90  return -ENODEV;
91  }
92  irq = res->start;
93 
94  hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
95  if (!hcd)
96  return -ENOMEM;
97 
98  res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
99  if (!res) {
100  dev_err(dev, "Found HC with no register addr.\n");
101  retval = -ENODEV;
102  goto err1;
103  }
104 
105  hcd->rsrc_start = res->start;
106  hcd->rsrc_len = resource_size(res);
107 
108  hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
109  if (hcd->regs == NULL) {
110  dev_dbg(dev, "error mapping memory\n");
111  retval = -EFAULT;
112  goto err1;
113  }
114 
115  retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
116  if (retval == 0)
117  return retval;
118 
119 err1:
120  usb_put_hcd(hcd);
121 
122  return retval;
123 }
124 
125 static int cns3xxx_ehci_remove(struct platform_device *pdev)
126 {
127  struct usb_hcd *hcd = platform_get_drvdata(pdev);
128 
129  usb_remove_hcd(hcd);
130 
131  /*
132  * EHCI and OHCI share the same clock and power,
133  * resetting twice would cause the 1st controller been reset.
134  * Therefore only do power up at the first up device, and
135  * power down at the last down device.
136  */
137  if (atomic_dec_return(&usb_pwr_ref) == 0)
139 
140  usb_put_hcd(hcd);
141 
142  platform_set_drvdata(pdev, NULL);
143 
144  return 0;
145 }
146 
147 MODULE_ALIAS("platform:cns3xxx-ehci");
148 
149 static struct platform_driver cns3xxx_ehci_driver = {
150  .probe = cns3xxx_ehci_probe,
151  .remove = cns3xxx_ehci_remove,
152  .driver = {
153  .name = "cns3xxx-ehci",
154  },
155 };