1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/pci.h>
22#include <linux/usb.h>
23
24#include <asm/io.h>
25#include <asm/irq.h>
26
27#ifdef CONFIG_PPC_PMAC
28#include <asm/machdep.h>
29#include <asm/pmac_feature.h>
30#include <asm/pci-bridge.h>
31#include <asm/prom.h>
32#endif
33
34#include "usb.h"
35#include "hcd.h"
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
59{
60 struct hc_driver *driver;
61 struct usb_hcd *hcd;
62 int retval;
63
64 if (usb_disabled())
65 return -ENODEV;
66
67 if (!id)
68 return -EINVAL;
69 driver = (struct hc_driver *)id->driver_data;
70 if (!driver)
71 return -EINVAL;
72
73 if (pci_enable_device(dev) < 0)
74 return -ENODEV;
75 dev->current_state = PCI_D0;
76
77 if (!dev->irq) {
78 dev_err(&dev->dev,
79 "Found HC with no IRQ. Check BIOS/PCI %s setup!\n",
80 pci_name(dev));
81 retval = -ENODEV;
82 goto err1;
83 }
84
85 hcd = usb_create_hcd(driver, &dev->dev, pci_name(dev));
86 if (!hcd) {
87 retval = -ENOMEM;
88 goto err1;
89 }
90
91 if (driver->flags & HCD_MEMORY) {
92
93 hcd->rsrc_start = pci_resource_start(dev, 0);
94 hcd->rsrc_len = pci_resource_len(dev, 0);
95 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
96 driver->description)) {
97 dev_dbg(&dev->dev, "controller already in use\n");
98 retval = -EBUSY;
99 goto err2;
100 }
101 hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
102 if (hcd->regs == NULL) {
103 dev_dbg(&dev->dev, "error mapping memory\n");
104 retval = -EFAULT;
105 goto err3;
106 }
107
108 } else {
109
110 int region;
111
112 for (region = 0; region < PCI_ROM_RESOURCE; region++) {
113 if (!(pci_resource_flags(dev, region) &
114 IORESOURCE_IO))
115 continue;
116
117 hcd->rsrc_start = pci_resource_start(dev, region);
118 hcd->rsrc_len = pci_resource_len(dev, region);
119 if (request_region(hcd->rsrc_start, hcd->rsrc_len,
120 driver->description))
121 break;
122 }
123 if (region == PCI_ROM_RESOURCE) {
124 dev_dbg(&dev->dev, "no i/o regions available\n");
125 retval = -EBUSY;
126 goto err1;
127 }
128 }
129
130 pci_set_master(dev);
131
132 retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED);
133 if (retval != 0)
134 goto err4;
135 return retval;
136
137 err4:
138 if (driver->flags & HCD_MEMORY) {
139 iounmap(hcd->regs);
140 err3:
141 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
142 } else
143 release_region(hcd->rsrc_start, hcd->rsrc_len);
144 err2:
145 usb_put_hcd(hcd);
146 err1:
147 pci_disable_device(dev);
148 dev_err(&dev->dev, "init %s fail, %d\n", pci_name(dev), retval);
149 return retval;
150}
151EXPORT_SYMBOL_GPL(usb_hcd_pci_probe);
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168void usb_hcd_pci_remove(struct pci_dev *dev)
169{
170 struct usb_hcd *hcd;
171
172 hcd = pci_get_drvdata(dev);
173 if (!hcd)
174 return;
175
176 usb_remove_hcd(hcd);
177 if (hcd->driver->flags & HCD_MEMORY) {
178 iounmap(hcd->regs);
179 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
180 } else {
181 release_region(hcd->rsrc_start, hcd->rsrc_len);
182 }
183 usb_put_hcd(hcd);
184 pci_disable_device(dev);
185}
186EXPORT_SYMBOL_GPL(usb_hcd_pci_remove);
187
188
189#ifdef CONFIG_PM
190
191
192
193
194
195
196
197
198int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
199{
200 struct usb_hcd *hcd;
201 int retval = 0;
202 int has_pci_pm;
203
204 hcd = pci_get_drvdata(dev);
205
206
207
208
209
210
211
212
213
214 if (!(hcd->state == HC_STATE_SUSPENDED ||
215 hcd->state == HC_STATE_HALT))
216 return -EBUSY;
217
218 if (hcd->driver->pci_suspend) {
219 retval = hcd->driver->pci_suspend(hcd, message);
220 suspend_report_result(hcd->driver->pci_suspend, retval);
221 if (retval)
222 goto done;
223 }
224 synchronize_irq(dev->irq);
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242 has_pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM);
243
244
245
246
247
248
249 if (hcd->state == HC_STATE_SUSPENDED) {
250
251
252 if (dev->current_state == PCI_D0) {
253 pci_save_state(dev);
254 pci_disable_device(dev);
255 }
256
257 if (message.event == PM_EVENT_FREEZE ||
258 message.event == PM_EVENT_PRETHAW) {
259 dev_dbg(hcd->self.controller, "--> no state change\n");
260 goto done;
261 }
262
263 if (!has_pci_pm) {
264 dev_dbg(hcd->self.controller, "--> PCI D0/legacy\n");
265 goto done;
266 }
267
268
269
270
271
272
273 retval = pci_set_power_state(dev, PCI_D3hot);
274 suspend_report_result(pci_set_power_state, retval);
275 if (retval == 0) {
276 int wake = device_can_wakeup(&hcd->self.root_hub->dev);
277
278 wake = wake && device_may_wakeup(hcd->self.controller);
279
280 dev_dbg(hcd->self.controller, "--> PCI D3%s\n",
281 wake ? "/wakeup" : "");
282
283
284
285
286
287 (void) pci_enable_wake(dev, PCI_D3hot, wake);
288 (void) pci_enable_wake(dev, PCI_D3cold, wake);
289 } else {
290 dev_dbg(&dev->dev, "PCI D3 suspend fail, %d\n",
291 retval);
292 (void) usb_hcd_pci_resume(dev);
293 }
294
295 } else if (hcd->state != HC_STATE_HALT) {
296 dev_dbg(hcd->self.controller, "hcd state %d; not suspended\n",
297 hcd->state);
298 WARN_ON(1);
299 retval = -EINVAL;
300 }
301
302done:
303 if (retval == 0) {
304#ifdef CONFIG_PPC_PMAC
305
306 if (machine_is(powermac)) {
307 struct device_node *of_node;
308
309 of_node = pci_device_to_OF_node(dev);
310 if (of_node)
311 pmac_call_feature(PMAC_FTR_USB_ENABLE,
312 of_node, 0, 0);
313 }
314#endif
315 }
316
317 return retval;
318}
319EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend);
320
321
322
323
324
325
326
327int usb_hcd_pci_resume(struct pci_dev *dev)
328{
329 struct usb_hcd *hcd;
330 int retval;
331
332 hcd = pci_get_drvdata(dev);
333 if (hcd->state != HC_STATE_SUSPENDED) {
334 dev_dbg(hcd->self.controller,
335 "can't resume, not suspended!\n");
336 return 0;
337 }
338
339#ifdef CONFIG_PPC_PMAC
340
341 if (machine_is(powermac)) {
342 struct device_node *of_node;
343
344 of_node = pci_device_to_OF_node(dev);
345 if (of_node)
346 pmac_call_feature(PMAC_FTR_USB_ENABLE,
347 of_node, 0, 1);
348 }
349#endif
350
351
352
353
354
355 if (dev->current_state != PCI_D0) {
356#ifdef DEBUG
357 int pci_pm;
358 u16 pmcr;
359
360 pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM);
361 pci_read_config_word(dev, pci_pm + PCI_PM_CTRL, &pmcr);
362 pmcr &= PCI_PM_CTRL_STATE_MASK;
363 if (pmcr) {
364
365
366
367 dev_dbg(hcd->self.controller, "resume from PCI D%d\n",
368 pmcr);
369 } else {
370
371
372
373
374
375
376
377
378
379 dev_dbg(hcd->self.controller,
380 "PCI D0, from previous PCI D%d\n",
381 dev->current_state);
382 }
383#endif
384
385 (void) pci_enable_wake(dev, dev->current_state, 0);
386 (void) pci_enable_wake(dev, PCI_D3cold, 0);
387 } else {
388
389 dev_dbg(hcd->self.controller, "PCI legacy resume\n");
390 }
391
392
393
394
395
396
397 retval = pci_enable_device(dev);
398 if (retval < 0) {
399 dev_err(hcd->self.controller,
400 "can't re-enable after resume, %d!\n", retval);
401 return retval;
402 }
403 pci_set_master(dev);
404 pci_restore_state(dev);
405
406 clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
407
408 if (hcd->driver->pci_resume) {
409 retval = hcd->driver->pci_resume(hcd);
410 if (retval) {
411 dev_err(hcd->self.controller,
412 "PCI post-resume error %d!\n", retval);
413 usb_hc_died(hcd);
414 }
415 }
416
417 return retval;
418}
419EXPORT_SYMBOL_GPL(usb_hcd_pci_resume);
420
421#endif
422
423
424
425
426
427void usb_hcd_pci_shutdown(struct pci_dev *dev)
428{
429 struct usb_hcd *hcd;
430
431 hcd = pci_get_drvdata(dev);
432 if (!hcd)
433 return;
434
435 if (hcd->driver->shutdown)
436 hcd->driver->shutdown(hcd);
437}
438EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown);
439
440