]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/usb/host/ehci-platform.c
Merge remote-tracking branch 'signal/for-next'
[karo-tx-linux.git] / 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->no_io_watchdog)
42                 ehci->need_io_watchdog = 0;
43         if (pdata->port_power_on)
44                 ehci_port_power(ehci, 1);
45         if (pdata->port_power_off)
46                 ehci_port_power(ehci, 0);
47
48         return 0;
49 }
50
51 static const struct hc_driver ehci_platform_hc_driver = {
52         .description            = hcd_name,
53         .product_desc           = "Generic Platform EHCI Controller",
54         .hcd_priv_size          = sizeof(struct ehci_hcd),
55
56         .irq                    = ehci_irq,
57         .flags                  = HCD_MEMORY | HCD_USB2,
58
59         .reset                  = ehci_platform_reset,
60         .start                  = ehci_run,
61         .stop                   = ehci_stop,
62         .shutdown               = ehci_shutdown,
63
64         .urb_enqueue            = ehci_urb_enqueue,
65         .urb_dequeue            = ehci_urb_dequeue,
66         .endpoint_disable       = ehci_endpoint_disable,
67         .endpoint_reset         = ehci_endpoint_reset,
68
69         .get_frame_number       = ehci_get_frame,
70
71         .hub_status_data        = ehci_hub_status_data,
72         .hub_control            = ehci_hub_control,
73 #if defined(CONFIG_PM)
74         .bus_suspend            = ehci_bus_suspend,
75         .bus_resume             = ehci_bus_resume,
76 #endif
77         .relinquish_port        = ehci_relinquish_port,
78         .port_handed_over       = ehci_port_handed_over,
79
80         .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
81 };
82
83 static int __devinit ehci_platform_probe(struct platform_device *dev)
84 {
85         struct usb_hcd *hcd;
86         struct resource *res_mem;
87         struct usb_ehci_pdata *pdata = dev->dev.platform_data;
88         int irq;
89         int err = -ENOMEM;
90
91         if (!pdata) {
92                 WARN_ON(1);
93                 return -ENODEV;
94         }
95
96         if (usb_disabled())
97                 return -ENODEV;
98
99         irq = platform_get_irq(dev, 0);
100         if (irq < 0) {
101                 dev_err(&dev->dev, "no irq provided");
102                 return irq;
103         }
104         res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
105         if (!res_mem) {
106                 dev_err(&dev->dev, "no memory resource provided");
107                 return -ENXIO;
108         }
109
110         if (pdata->power_on) {
111                 err = pdata->power_on(dev);
112                 if (err < 0)
113                         return err;
114         }
115
116         hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev,
117                              dev_name(&dev->dev));
118         if (!hcd) {
119                 err = -ENOMEM;
120                 goto err_power;
121         }
122
123         hcd->rsrc_start = res_mem->start;
124         hcd->rsrc_len = resource_size(res_mem);
125
126         hcd->regs = devm_request_and_ioremap(&dev->dev, res_mem);
127         if (!hcd->regs) {
128                 err = -ENOMEM;
129                 goto err_put_hcd;
130         }
131         err = usb_add_hcd(hcd, irq, IRQF_SHARED);
132         if (err)
133                 goto err_put_hcd;
134
135         platform_set_drvdata(dev, hcd);
136
137         return err;
138
139 err_put_hcd:
140         usb_put_hcd(hcd);
141 err_power:
142         if (pdata->power_off)
143                 pdata->power_off(dev);
144
145         return err;
146 }
147
148 static int __devexit ehci_platform_remove(struct platform_device *dev)
149 {
150         struct usb_hcd *hcd = platform_get_drvdata(dev);
151         struct usb_ehci_pdata *pdata = dev->dev.platform_data;
152
153         usb_remove_hcd(hcd);
154         usb_put_hcd(hcd);
155         platform_set_drvdata(dev, NULL);
156
157         if (pdata->power_off)
158                 pdata->power_off(dev);
159
160         return 0;
161 }
162
163 #ifdef CONFIG_PM
164
165 static int ehci_platform_suspend(struct device *dev)
166 {
167         struct usb_hcd *hcd = dev_get_drvdata(dev);
168         struct usb_ehci_pdata *pdata = dev->platform_data;
169         struct platform_device *pdev =
170                 container_of(dev, struct platform_device, dev);
171         bool do_wakeup = device_may_wakeup(dev);
172         int ret;
173
174         ret = ehci_suspend(hcd, do_wakeup);
175
176         if (pdata->power_suspend)
177                 pdata->power_suspend(pdev);
178
179         return ret;
180 }
181
182 static int ehci_platform_resume(struct device *dev)
183 {
184         struct usb_hcd *hcd = dev_get_drvdata(dev);
185         struct usb_ehci_pdata *pdata = dev->platform_data;
186         struct platform_device *pdev =
187                 container_of(dev, struct platform_device, dev);
188
189         if (pdata->power_on) {
190                 int err = pdata->power_on(pdev);
191                 if (err < 0)
192                         return err;
193         }
194
195         ehci_resume(hcd, false);
196         return 0;
197 }
198
199 #else /* !CONFIG_PM */
200 #define ehci_platform_suspend   NULL
201 #define ehci_platform_resume    NULL
202 #endif /* CONFIG_PM */
203
204 static const struct platform_device_id ehci_platform_table[] = {
205         { "ehci-platform", 0 },
206         { }
207 };
208 MODULE_DEVICE_TABLE(platform, ehci_platform_table);
209
210 static const struct dev_pm_ops ehci_platform_pm_ops = {
211         .suspend        = ehci_platform_suspend,
212         .resume         = ehci_platform_resume,
213 };
214
215 static struct platform_driver ehci_platform_driver = {
216         .id_table       = ehci_platform_table,
217         .probe          = ehci_platform_probe,
218         .remove         = __devexit_p(ehci_platform_remove),
219         .shutdown       = usb_hcd_platform_shutdown,
220         .driver         = {
221                 .owner  = THIS_MODULE,
222                 .name   = "ehci-platform",
223                 .pm     = &ehci_platform_pm_ops,
224         }
225 };