Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ehci-vt8500.c
Go to the documentation of this file.
1 /*
2  * drivers/usb/host/ehci-vt8500.c
3  *
4  * Copyright (C) 2010 Alexey Charkov <[email protected]>
5  *
6  * Based on ehci-au1xxx.c
7  *
8  * This software is licensed under the terms of the GNU General Public
9  * License version 2, as published by the Free Software Foundation, and
10  * may be copied, distributed, and modified under those terms.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  */
18 
19 #include <linux/of.h>
20 #include <linux/platform_device.h>
21 
22 static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
23 {
24  struct ehci_hcd *ehci = hcd_to_ehci(hcd);
25  int rc = 0;
26 
27  if (!udev->parent) /* udev is root hub itself, impossible */
28  rc = -1;
29  /* we only support lpm device connected to root hub yet */
30  if (ehci->has_lpm && !udev->parent->parent) {
31  rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
32  if (!rc)
33  rc = ehci_lpm_check(ehci, udev->portnum);
34  }
35  return rc;
36 }
37 
38 static const struct hc_driver vt8500_ehci_hc_driver = {
39  .description = hcd_name,
40  .product_desc = "VT8500 EHCI",
41  .hcd_priv_size = sizeof(struct ehci_hcd),
42 
43  /*
44  * generic hardware linkage
45  */
46  .irq = ehci_irq,
47  .flags = HCD_MEMORY | HCD_USB2,
48 
49  /*
50  * basic lifecycle operations
51  */
52  .reset = ehci_setup,
53  .start = ehci_run,
54  .stop = ehci_stop,
55  .shutdown = ehci_shutdown,
56 
57  /*
58  * managing i/o requests and associated device resources
59  */
60  .urb_enqueue = ehci_urb_enqueue,
61  .urb_dequeue = ehci_urb_dequeue,
62  .endpoint_disable = ehci_endpoint_disable,
63  .endpoint_reset = ehci_endpoint_reset,
64 
65  /*
66  * scheduling support
67  */
68  .get_frame_number = ehci_get_frame,
69 
70  /*
71  * root hub support
72  */
73  .hub_status_data = ehci_hub_status_data,
74  .hub_control = ehci_hub_control,
75  .bus_suspend = ehci_bus_suspend,
76  .bus_resume = ehci_bus_resume,
77  .relinquish_port = ehci_relinquish_port,
78  .port_handed_over = ehci_port_handed_over,
79 
80  /*
81  * call back when device connected and addressed
82  */
83  .update_device = ehci_update_device,
84 
85  .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
86 };
87 
88 static u64 vt8500_ehci_dma_mask = DMA_BIT_MASK(32);
89 
90 static int vt8500_ehci_drv_probe(struct platform_device *pdev)
91 {
92  struct usb_hcd *hcd;
93  struct ehci_hcd *ehci;
94  struct resource *res;
95  int ret;
96 
97  if (usb_disabled())
98  return -ENODEV;
99 
100  /*
101  * Right now device-tree probed devices don't get dma_mask set.
102  * Since shared usb code relies on it, set it here for now.
103  * Once we have dma capability bindings this can go away.
104  */
105  if (!pdev->dev.dma_mask)
106  pdev->dev.dma_mask = &vt8500_ehci_dma_mask;
107 
108  if (pdev->resource[1].flags != IORESOURCE_IRQ) {
109  pr_debug("resource[1] is not IORESOURCE_IRQ");
110  return -ENOMEM;
111  }
112  hcd = usb_create_hcd(&vt8500_ehci_hc_driver, &pdev->dev, "VT8500");
113  if (!hcd)
114  return -ENOMEM;
115 
116  res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
117  hcd->rsrc_start = res->start;
118  hcd->rsrc_len = resource_size(res);
119 
120  hcd->regs = devm_request_and_ioremap(&pdev->dev, res);
121  if (!hcd->regs) {
122  pr_debug("ioremap failed");
123  ret = -ENOMEM;
124  goto err1;
125  }
126 
127  ehci = hcd_to_ehci(hcd);
128  ehci->caps = hcd->regs;
129 
130  ret = usb_add_hcd(hcd, pdev->resource[1].start,
131  IRQF_SHARED);
132  if (ret == 0) {
133  platform_set_drvdata(pdev, hcd);
134  return ret;
135  }
136 
137 err1:
138  usb_put_hcd(hcd);
139  return ret;
140 }
141 
142 static int vt8500_ehci_drv_remove(struct platform_device *pdev)
143 {
144  struct usb_hcd *hcd = platform_get_drvdata(pdev);
145 
146  usb_remove_hcd(hcd);
147  usb_put_hcd(hcd);
148  platform_set_drvdata(pdev, NULL);
149 
150  return 0;
151 }
152 
153 static const struct of_device_id vt8500_ehci_ids[] = {
154  { .compatible = "via,vt8500-ehci", },
155  { .compatible = "wm,prizm-ehci", },
156  {}
157 };
158 
159 static struct platform_driver vt8500_ehci_driver = {
160  .probe = vt8500_ehci_drv_probe,
161  .remove = vt8500_ehci_drv_remove,
162  .shutdown = usb_hcd_platform_shutdown,
163  .driver = {
164  .name = "vt8500-ehci",
165  .owner = THIS_MODULE,
166  .of_match_table = of_match_ptr(vt8500_ehci_ids),
167  }
168 };
169 
170 MODULE_ALIAS("platform:vt8500-ehci");
171 MODULE_DEVICE_TABLE(of, vt8500_ehci_ids);