]> Pileus Git - ~andy/linux/blob - drivers/usb/host/ohci-platform.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux...
[~andy/linux] / drivers / usb / host / ohci-platform.c
1 /*
2  * Generic platform ohci driver
3  *
4  * Copyright 2007 Michael Buesch <m@bues.ch>
5  * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de>
6  *
7  * Derived from the OCHI-SSB driver
8  * Derived from the OHCI-PCI driver
9  * Copyright 1999 Roman Weissgaerber
10  * Copyright 2000-2002 David Brownell
11  * Copyright 1999 Linus Torvalds
12  * Copyright 1999 Gregory P. Smith
13  *
14  * Licensed under the GNU/GPL. See COPYING for details.
15  */
16 #include <linux/err.h>
17 #include <linux/platform_device.h>
18 #include <linux/usb/ohci_pdriver.h>
19
20 static int ohci_platform_reset(struct usb_hcd *hcd)
21 {
22         struct platform_device *pdev = to_platform_device(hcd->self.controller);
23         struct usb_ohci_pdata *pdata = pdev->dev.platform_data;
24         struct ohci_hcd *ohci = hcd_to_ohci(hcd);
25         int err;
26
27         if (pdata->big_endian_desc)
28                 ohci->flags |= OHCI_QUIRK_BE_DESC;
29         if (pdata->big_endian_mmio)
30                 ohci->flags |= OHCI_QUIRK_BE_MMIO;
31         if (pdata->no_big_frame_no)
32                 ohci->flags |= OHCI_QUIRK_FRAME_NO;
33
34         ohci_hcd_init(ohci);
35
36         if (pdata->num_ports)
37                 ohci->num_ports = pdata->num_ports;
38
39         err = ohci_init(ohci);
40
41         return err;
42 }
43
44 static int ohci_platform_start(struct usb_hcd *hcd)
45 {
46         struct ohci_hcd *ohci = hcd_to_ohci(hcd);
47         int err;
48
49         err = ohci_run(ohci);
50         if (err < 0) {
51                 ohci_err(ohci, "can't start\n");
52                 ohci_stop(hcd);
53         }
54
55         return err;
56 }
57
58 static const struct hc_driver ohci_platform_hc_driver = {
59         .description            = hcd_name,
60         .product_desc           = "Generic Platform OHCI Controller",
61         .hcd_priv_size          = sizeof(struct ohci_hcd),
62
63         .irq                    = ohci_irq,
64         .flags                  = HCD_MEMORY | HCD_USB11,
65
66         .reset                  = ohci_platform_reset,
67         .start                  = ohci_platform_start,
68         .stop                   = ohci_stop,
69         .shutdown               = ohci_shutdown,
70
71         .urb_enqueue            = ohci_urb_enqueue,
72         .urb_dequeue            = ohci_urb_dequeue,
73         .endpoint_disable       = ohci_endpoint_disable,
74
75         .get_frame_number       = ohci_get_frame,
76
77         .hub_status_data        = ohci_hub_status_data,
78         .hub_control            = ohci_hub_control,
79 #ifdef  CONFIG_PM
80         .bus_suspend            = ohci_bus_suspend,
81         .bus_resume             = ohci_bus_resume,
82 #endif
83
84         .start_port_reset       = ohci_start_port_reset,
85 };
86
87 static int ohci_platform_probe(struct platform_device *dev)
88 {
89         struct usb_hcd *hcd;
90         struct resource *res_mem;
91         struct usb_ohci_pdata *pdata = dev->dev.platform_data;
92         int irq;
93         int err = -ENOMEM;
94
95         if (!pdata) {
96                 WARN_ON(1);
97                 return -ENODEV;
98         }
99
100         if (usb_disabled())
101                 return -ENODEV;
102
103         irq = platform_get_irq(dev, 0);
104         if (irq < 0) {
105                 dev_err(&dev->dev, "no irq provided");
106                 return irq;
107         }
108
109         res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
110         if (!res_mem) {
111                 dev_err(&dev->dev, "no memory resource provided");
112                 return -ENXIO;
113         }
114
115         if (pdata->power_on) {
116                 err = pdata->power_on(dev);
117                 if (err < 0)
118                         return err;
119         }
120
121         hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev,
122                         dev_name(&dev->dev));
123         if (!hcd) {
124                 err = -ENOMEM;
125                 goto err_power;
126         }
127
128         hcd->rsrc_start = res_mem->start;
129         hcd->rsrc_len = resource_size(res_mem);
130
131         hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
132         if (IS_ERR(hcd->regs)) {
133                 err = PTR_ERR(hcd->regs);
134                 goto err_put_hcd;
135         }
136         err = usb_add_hcd(hcd, irq, IRQF_SHARED);
137         if (err)
138                 goto err_put_hcd;
139
140         platform_set_drvdata(dev, hcd);
141
142         return err;
143
144 err_put_hcd:
145         usb_put_hcd(hcd);
146 err_power:
147         if (pdata->power_off)
148                 pdata->power_off(dev);
149
150         return err;
151 }
152
153 static int ohci_platform_remove(struct platform_device *dev)
154 {
155         struct usb_hcd *hcd = platform_get_drvdata(dev);
156         struct usb_ohci_pdata *pdata = dev->dev.platform_data;
157
158         usb_remove_hcd(hcd);
159         usb_put_hcd(hcd);
160         platform_set_drvdata(dev, NULL);
161
162         if (pdata->power_off)
163                 pdata->power_off(dev);
164
165         return 0;
166 }
167
168 #ifdef CONFIG_PM
169
170 static int ohci_platform_suspend(struct device *dev)
171 {
172         struct usb_ohci_pdata *pdata = dev->platform_data;
173         struct platform_device *pdev =
174                 container_of(dev, struct platform_device, dev);
175
176         if (pdata->power_suspend)
177                 pdata->power_suspend(pdev);
178
179         return 0;
180 }
181
182 static int ohci_platform_resume(struct device *dev)
183 {
184         struct usb_hcd *hcd = dev_get_drvdata(dev);
185         struct usb_ohci_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         ohci_resume(hcd, false);
196         return 0;
197 }
198
199 #else /* !CONFIG_PM */
200 #define ohci_platform_suspend   NULL
201 #define ohci_platform_resume    NULL
202 #endif /* CONFIG_PM */
203
204 static const struct platform_device_id ohci_platform_table[] = {
205         { "ohci-platform", 0 },
206         { }
207 };
208 MODULE_DEVICE_TABLE(platform, ohci_platform_table);
209
210 static const struct dev_pm_ops ohci_platform_pm_ops = {
211         .suspend        = ohci_platform_suspend,
212         .resume         = ohci_platform_resume,
213 };
214
215 static struct platform_driver ohci_platform_driver = {
216         .id_table       = ohci_platform_table,
217         .probe          = ohci_platform_probe,
218         .remove         = ohci_platform_remove,
219         .shutdown       = usb_hcd_platform_shutdown,
220         .driver         = {
221                 .owner  = THIS_MODULE,
222                 .name   = "ohci-platform",
223                 .pm     = &ohci_platform_pm_ops,
224         }
225 };