]> Pileus Git - ~andy/linux/blob - drivers/usb/host/ehci-platform.c
Merge branch 'for-linus' of git://git.linaro.org/people/rmk/linux-arm
[~andy/linux] / drivers / usb / host / ehci-platform.c
1 /*
2  * Generic platform ehci driver
3  *
4  * Copyright 2007 Steven Brown <sbrown@cortland.com>
5  * Copyright 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
6  *
7  * Derived from the ohci-ssb driver
8  * Copyright 2007 Michael Buesch <m@bues.ch>
9  *
10  * Derived from the EHCI-PCI driver
11  * Copyright (c) 2000-2004 by David Brownell
12  *
13  * Derived from the ohci-pci driver
14  * Copyright 1999 Roman Weissgaerber
15  * Copyright 2000-2002 David Brownell
16  * Copyright 1999 Linus Torvalds
17  * Copyright 1999 Gregory P. Smith
18  *
19  * Licensed under the GNU/GPL. See COPYING for details.
20  */
21 #include <linux/platform_device.h>
22 #include <linux/usb/ehci_pdriver.h>
23
24 static int ehci_platform_reset(struct usb_hcd *hcd)
25 {
26         struct platform_device *pdev = to_platform_device(hcd->self.controller);
27         struct usb_ehci_pdata *pdata = pdev->dev.platform_data;
28         struct ehci_hcd *ehci = hcd_to_ehci(hcd);
29         int retval;
30
31         hcd->has_tt = pdata->has_tt;
32         ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
33         ehci->big_endian_desc = pdata->big_endian_desc;
34         ehci->big_endian_mmio = pdata->big_endian_mmio;
35
36         ehci->caps = hcd->regs + pdata->caps_offset;
37         retval = ehci_setup(hcd);
38         if (retval)
39                 return retval;
40
41         if (pdata->port_power_on)
42                 ehci_port_power(ehci, 1);
43         if (pdata->port_power_off)
44                 ehci_port_power(ehci, 0);
45
46         return 0;
47 }
48
49 static const struct hc_driver ehci_platform_hc_driver = {
50         .description            = hcd_name,
51         .product_desc           = "Generic Platform EHCI Controller",
52         .hcd_priv_size          = sizeof(struct ehci_hcd),
53
54         .irq                    = ehci_irq,
55         .flags                  = HCD_MEMORY | HCD_USB2,
56
57         .reset                  = ehci_platform_reset,
58         .start                  = ehci_run,
59         .stop                   = ehci_stop,
60         .shutdown               = ehci_shutdown,
61
62         .urb_enqueue            = ehci_urb_enqueue,
63         .urb_dequeue            = ehci_urb_dequeue,
64         .endpoint_disable       = ehci_endpoint_disable,
65         .endpoint_reset         = ehci_endpoint_reset,
66
67         .get_frame_number       = ehci_get_frame,
68
69         .hub_status_data        = ehci_hub_status_data,
70         .hub_control            = ehci_hub_control,
71 #if defined(CONFIG_PM)
72         .bus_suspend            = ehci_bus_suspend,
73         .bus_resume             = ehci_bus_resume,
74 #endif
75         .relinquish_port        = ehci_relinquish_port,
76         .port_handed_over       = ehci_port_handed_over,
77
78         .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
79 };
80
81 static int __devinit ehci_platform_probe(struct platform_device *dev)
82 {
83         struct usb_hcd *hcd;
84         struct resource *res_mem;
85         struct usb_ehci_pdata *pdata = dev->dev.platform_data;
86         int irq;
87         int err = -ENOMEM;
88
89         if (!pdata) {
90                 WARN_ON(1);
91                 return -ENODEV;
92         }
93
94         if (usb_disabled())
95                 return -ENODEV;
96
97         irq = platform_get_irq(dev, 0);
98         if (irq < 0) {
99                 pr_err("no irq provided");
100                 return irq;
101         }
102         res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
103         if (!res_mem) {
104                 pr_err("no memory recourse provided");
105                 return -ENXIO;
106         }
107
108         if (pdata->power_on) {
109                 err = pdata->power_on(dev);
110                 if (err < 0)
111                         return err;
112         }
113
114         hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
115                              dev_name(&dev->dev));
116         if (!hcd) {
117                 err = -ENOMEM;
118                 goto err_power;
119         }
120
121         hcd->rsrc_start = res_mem->start;
122         hcd->rsrc_len = resource_size(res_mem);
123
124         if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
125                 pr_err("controller already in use");
126                 err = -EBUSY;
127                 goto err_put_hcd;
128         }
129
130         hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
131         if (!hcd->regs) {
132                 err = -ENOMEM;
133                 goto err_release_region;
134         }
135         err = usb_add_hcd(hcd, irq, IRQF_SHARED);
136         if (err)
137                 goto err_iounmap;
138
139         platform_set_drvdata(dev, hcd);
140
141         return err;
142
143 err_iounmap:
144         iounmap(hcd->regs);
145 err_release_region:
146         release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
147 err_put_hcd:
148         usb_put_hcd(hcd);
149 err_power:
150         if (pdata->power_off)
151                 pdata->power_off(dev);
152
153         return err;
154 }
155
156 static int __devexit ehci_platform_remove(struct platform_device *dev)
157 {
158         struct usb_hcd *hcd = platform_get_drvdata(dev);
159         struct usb_ehci_pdata *pdata = dev->dev.platform_data;
160
161         usb_remove_hcd(hcd);
162         iounmap(hcd->regs);
163         release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
164         usb_put_hcd(hcd);
165         platform_set_drvdata(dev, NULL);
166
167         if (pdata->power_off)
168                 pdata->power_off(dev);
169
170         return 0;
171 }
172
173 #ifdef CONFIG_PM
174
175 static int ehci_platform_suspend(struct device *dev)
176 {
177         struct usb_hcd *hcd = dev_get_drvdata(dev);
178         struct usb_ehci_pdata *pdata = dev->platform_data;
179         struct platform_device *pdev =
180                 container_of(dev, struct platform_device, dev);
181         bool do_wakeup = device_may_wakeup(dev);
182         int ret;
183
184         ret = ehci_suspend(hcd, do_wakeup);
185
186         if (pdata->power_suspend)
187                 pdata->power_suspend(pdev);
188
189         return ret;
190 }
191
192 static int ehci_platform_resume(struct device *dev)
193 {
194         struct usb_hcd *hcd = dev_get_drvdata(dev);
195         struct usb_ehci_pdata *pdata = dev->platform_data;
196         struct platform_device *pdev =
197                 container_of(dev, struct platform_device, dev);
198
199         if (pdata->power_on) {
200                 int err = pdata->power_on(pdev);
201                 if (err < 0)
202                         return err;
203         }
204
205         ehci_resume(hcd, false);
206         return 0;
207 }
208
209 #else /* !CONFIG_PM */
210 #define ehci_platform_suspend   NULL
211 #define ehci_platform_resume    NULL
212 #endif /* CONFIG_PM */
213
214 static const struct platform_device_id ehci_platform_table[] = {
215         { "ehci-platform", 0 },
216         { }
217 };
218 MODULE_DEVICE_TABLE(platform, ehci_platform_table);
219
220 static const struct dev_pm_ops ehci_platform_pm_ops = {
221         .suspend        = ehci_platform_suspend,
222         .resume         = ehci_platform_resume,
223 };
224
225 static struct platform_driver ehci_platform_driver = {
226         .id_table       = ehci_platform_table,
227         .probe          = ehci_platform_probe,
228         .remove         = __devexit_p(ehci_platform_remove),
229         .shutdown       = usb_hcd_platform_shutdown,
230         .driver         = {
231                 .owner  = THIS_MODULE,
232                 .name   = "ehci-platform",
233                 .pm     = &ehci_platform_pm_ops,
234         }
235 };