Rev 846 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1049 | mauro | 1 | /* |
2 | * OHCI HCD (Host Controller Driver) for USB. |
||
3 | * |
||
4 | * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> |
||
5 | * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> |
||
6 | * |
||
7 | * [ Initialisation is based on Linus' ] |
||
8 | * [ uhci code and gregs ohci fragments ] |
||
9 | * [ (C) Copyright 1999 Linus Torvalds ] |
||
10 | * [ (C) Copyright 1999 Gregory P. Smith] |
||
11 | * |
||
12 | * PCI Bus Glue |
||
13 | * |
||
14 | * This file is licenced under the GPL. |
||
15 | */ |
||
16 | |||
17 | #ifdef CONFIG_PMAC_PBOOK |
||
18 | #include <asm/machdep.h> |
||
19 | #include <asm/pmac_feature.h> |
||
20 | #include <asm/pci-bridge.h> |
||
21 | #include <asm/prom.h> |
||
22 | #ifndef CONFIG_PM |
||
23 | # define CONFIG_PM |
||
24 | #endif |
||
25 | #endif |
||
26 | |||
27 | #ifndef CONFIG_PCI |
||
28 | #error "This file is PCI bus glue. CONFIG_PCI must be defined." |
||
29 | #endif |
||
30 | |||
31 | /*-------------------------------------------------------------------------*/ |
||
32 | |||
33 | static int |
||
34 | ohci_pci_reset (struct usb_hcd *hcd) |
||
35 | { |
||
36 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
||
37 | |||
38 | ohci->regs = hcd->regs; |
||
39 | return hc_reset (ohci); |
||
40 | } |
||
41 | |||
42 | static int __devinit |
||
43 | ohci_pci_start (struct usb_hcd *hcd) |
||
44 | { |
||
45 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
||
46 | int ret; |
||
47 | |||
48 | if (hcd->pdev) { |
||
49 | ohci->hcca = pci_alloc_consistent_usb (hcd->pdev, |
||
50 | sizeof *ohci->hcca, &ohci->hcca_dma); |
||
51 | |||
52 | if (!ohci->hcca) |
||
53 | return -ENOMEM; |
||
54 | |||
55 | /* AMD 756, for most chips (early revs), corrupts register |
||
56 | * values on read ... so enable the vendor workaround. |
||
57 | */ |
||
58 | if (hcd->pdev->vendor == PCI_VENDOR_ID_AMD |
||
59 | && hcd->pdev->device == 0x740c) { |
||
60 | ohci->flags = OHCI_QUIRK_AMD756; |
||
61 | ohci_info (ohci, "AMD756 erratum 4 workaround\n"); |
||
62 | } |
||
63 | |||
64 | /* FIXME for some of the early AMD 760 southbridges, OHCI |
||
65 | * won't work at all. blacklist them. |
||
66 | */ |
||
67 | |||
68 | /* Apple's OHCI driver has a lot of bizarre workarounds |
||
69 | * for this chip. Evidently control and bulk lists |
||
70 | * can get confused. (B&W G3 models, and ...) |
||
71 | */ |
||
72 | else if (hcd->pdev->vendor == PCI_VENDOR_ID_OPTI |
||
73 | && hcd->pdev->device == 0xc861) { |
||
74 | ohci_info (ohci, |
||
75 | "WARNING: OPTi workarounds unavailable\n"); |
||
76 | } |
||
77 | |||
78 | /* Check for NSC87560. We have to look at the bridge (fn1) to |
||
79 | * identify the USB (fn2). This quirk might apply to more or |
||
80 | * even all NSC stuff. |
||
81 | */ |
||
82 | else if (hcd->pdev->vendor == PCI_VENDOR_ID_NS) { |
||
83 | struct pci_dev *b, *hc; |
||
84 | |||
85 | hc = hcd->pdev; |
||
86 | b = pci_find_slot (hc->bus->number, |
||
87 | PCI_DEVFN (PCI_SLOT (hc->devfn), 1)); |
||
88 | if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO |
||
89 | && b->vendor == PCI_VENDOR_ID_NS) { |
||
90 | ohci->flags |= OHCI_QUIRK_SUPERIO; |
||
91 | ohci_info (ohci, "Using NSC SuperIO setup\n"); |
||
92 | } |
||
93 | } |
||
94 | |||
95 | } |
||
96 | |||
97 | memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); |
||
98 | if ((ret = ohci_mem_init (ohci)) < 0) { |
||
99 | ohci_stop (hcd); |
||
100 | return ret; |
||
101 | } |
||
102 | |||
103 | if (hc_start (ohci) < 0) { |
||
104 | ohci_err (ohci, "can't start\n"); |
||
105 | ohci_stop (hcd); |
||
106 | return -EBUSY; |
||
107 | } |
||
108 | create_debug_files (ohci); |
||
109 | |||
110 | #ifdef DEBUG |
||
111 | ohci_dump (ohci, 1); |
||
112 | #endif |
||
113 | return 0; |
||
114 | } |
||
115 | |||
116 | #ifdef CONFIG_PM |
||
117 | |||
118 | static int ohci_pci_suspend (struct usb_hcd *hcd, u32 state) |
||
119 | { |
||
120 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
||
121 | u16 cmd; |
||
122 | u32 tmp; |
||
123 | |||
124 | if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER) { |
||
125 | ohci_dbg (ohci, "can't suspend (state is %s)\n", |
||
126 | hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS)); |
||
127 | return -EIO; |
||
128 | } |
||
129 | |||
130 | /* act as if usb suspend can always be used */ |
||
131 | ohci_dbg (ohci, "suspend to %d\n", state); |
||
132 | |||
133 | /* First stop processing */ |
||
134 | spin_lock_irq (&ohci->lock); |
||
135 | ohci->hc_control &= |
||
136 | ~(OHCI_CTRL_PLE|OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_IE); |
||
137 | writel (ohci->hc_control, &ohci->regs->control); |
||
138 | writel (OHCI_INTR_SF, &ohci->regs->intrstatus); |
||
139 | (void) readl (&ohci->regs->intrstatus); |
||
140 | spin_unlock_irq (&ohci->lock); |
||
141 | |||
142 | /* Wait a frame or two */ |
||
143 | mdelay (1); |
||
144 | if (!readl (&ohci->regs->intrstatus) & OHCI_INTR_SF) |
||
145 | mdelay (1); |
||
146 | |||
147 | #ifdef CONFIG_PMAC_PBOOK |
||
148 | if (_machine == _MACH_Pmac) |
||
149 | disable_irq (hcd->pdev->irq); |
||
150 | /* else, 2.4 assumes shared irqs -- don't disable */ |
||
151 | #endif |
||
152 | |||
153 | /* Enable remote wakeup */ |
||
154 | writel (readl (&ohci->regs->intrenable) | OHCI_INTR_RD, |
||
155 | &ohci->regs->intrenable); |
||
156 | |||
157 | /* Suspend chip and let things settle down a bit */ |
||
158 | spin_lock_irq (&ohci->lock); |
||
159 | ohci->hc_control = OHCI_USB_SUSPEND; |
||
160 | writel (ohci->hc_control, &ohci->regs->control); |
||
161 | (void) readl (&ohci->regs->control); |
||
162 | spin_unlock_irq (&ohci->lock); |
||
163 | |||
164 | set_current_state (TASK_UNINTERRUPTIBLE); |
||
165 | schedule_timeout (HZ/2); |
||
166 | |||
167 | tmp = readl (&ohci->regs->control) | OHCI_CTRL_HCFS; |
||
168 | switch (tmp) { |
||
169 | case OHCI_USB_RESET: |
||
170 | case OHCI_USB_RESUME: |
||
171 | case OHCI_USB_OPER: |
||
172 | ohci_err (ohci, "can't suspend; hcfs %d\n", tmp); |
||
173 | break; |
||
174 | case OHCI_USB_SUSPEND: |
||
175 | ohci_dbg (ohci, "suspended\n"); |
||
176 | break; |
||
177 | } |
||
178 | |||
179 | /* In some rare situations, Apple's OHCI have happily trashed |
||
180 | * memory during sleep. We disable its bus master bit during |
||
181 | * suspend |
||
182 | */ |
||
183 | pci_read_config_word (hcd->pdev, PCI_COMMAND, &cmd); |
||
184 | cmd &= ~PCI_COMMAND_MASTER; |
||
185 | pci_write_config_word (hcd->pdev, PCI_COMMAND, cmd); |
||
186 | #ifdef CONFIG_PMAC_PBOOK |
||
187 | { |
||
188 | struct device_node *of_node; |
||
189 | |||
190 | /* Disable USB PAD & cell clock */ |
||
191 | of_node = pci_device_to_OF_node (hcd->pdev); |
||
192 | if (of_node) |
||
193 | pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); |
||
194 | } |
||
195 | #endif |
||
196 | return 0; |
||
197 | } |
||
198 | |||
199 | |||
200 | static int ohci_pci_resume (struct usb_hcd *hcd) |
||
201 | { |
||
202 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
||
203 | int temp; |
||
204 | int retval = 0; |
||
205 | |||
206 | #ifdef CONFIG_PMAC_PBOOK |
||
207 | { |
||
208 | struct device_node *of_node; |
||
209 | |||
210 | /* Re-enable USB PAD & cell clock */ |
||
211 | of_node = pci_device_to_OF_node (hcd->pdev); |
||
212 | if (of_node) |
||
213 | pmac_call_feature (PMAC_FTR_USB_ENABLE, of_node, 0, 1); |
||
214 | } |
||
215 | #endif |
||
216 | /* did we suspend, or were we powered off? */ |
||
217 | ohci->hc_control = readl (&ohci->regs->control); |
||
218 | temp = ohci->hc_control & OHCI_CTRL_HCFS; |
||
219 | |||
220 | #ifdef DEBUG |
||
221 | /* the registers may look crazy here */ |
||
222 | ohci_dump_status (ohci, 0, 0); |
||
223 | #endif |
||
224 | |||
225 | /* Re-enable bus mastering */ |
||
226 | pci_set_master (ohci->hcd.pdev); |
||
227 | |||
228 | switch (temp) { |
||
229 | |||
230 | case OHCI_USB_RESET: // lost power |
||
231 | restart: |
||
232 | ohci_info (ohci, "USB restart\n"); |
||
233 | retval = hc_restart (ohci); |
||
234 | break; |
||
235 | |||
236 | case OHCI_USB_SUSPEND: // host wakeup |
||
237 | case OHCI_USB_RESUME: // remote wakeup |
||
238 | ohci_info (ohci, "USB continue from %s wakeup\n", |
||
239 | (temp == OHCI_USB_SUSPEND) |
||
240 | ? "host" : "remote"); |
||
241 | |||
242 | /* we "should" only need RESUME if we're SUSPENDed ... */ |
||
243 | ohci->hc_control = OHCI_USB_RESUME; |
||
244 | writel (ohci->hc_control, &ohci->regs->control); |
||
245 | (void) readl (&ohci->regs->control); |
||
246 | /* Some controllers (lucent) need extra-long delays */ |
||
247 | mdelay (35); /* no schedule here ! */ |
||
248 | |||
249 | temp = readl (&ohci->regs->control); |
||
250 | temp = ohci->hc_control & OHCI_CTRL_HCFS; |
||
251 | if (temp != OHCI_USB_RESUME) { |
||
252 | ohci_err (ohci, "controller won't resume\n"); |
||
253 | /* maybe we can reset */ |
||
254 | goto restart; |
||
255 | } |
||
256 | |||
257 | /* Then re-enable operations */ |
||
258 | writel (OHCI_USB_OPER, &ohci->regs->control); |
||
259 | (void) readl (&ohci->regs->control); |
||
260 | mdelay (3); |
||
261 | |||
262 | spin_lock_irq (&ohci->lock); |
||
263 | ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; |
||
264 | if (!ohci->ed_rm_list) { |
||
265 | if (ohci->ed_controltail) |
||
266 | ohci->hc_control |= OHCI_CTRL_CLE; |
||
267 | if (ohci->ed_bulktail) |
||
268 | ohci->hc_control |= OHCI_CTRL_BLE; |
||
269 | } |
||
270 | hcd->state = USB_STATE_RUNNING; |
||
271 | writel (ohci->hc_control, &ohci->regs->control); |
||
272 | |||
273 | /* trigger a start-frame interrupt (why?) */ |
||
274 | writel (OHCI_INTR_SF, &ohci->regs->intrstatus); |
||
275 | writel (OHCI_INTR_SF, &ohci->regs->intrenable); |
||
276 | |||
277 | writel (OHCI_INTR_WDH, &ohci->regs->intrdisable); |
||
278 | (void) readl (&ohci->regs->intrdisable); |
||
279 | spin_unlock_irq (&ohci->lock); |
||
280 | |||
281 | #ifdef CONFIG_PMAC_PBOOK |
||
282 | if (_machine == _MACH_Pmac) |
||
283 | enable_irq (hcd->pdev->irq); |
||
284 | #endif |
||
285 | |||
286 | /* Check for a pending done list */ |
||
287 | if (ohci->hcca->done_head) |
||
288 | dl_done_list (ohci, dl_reverse_done_list (ohci), NULL); |
||
289 | writel (OHCI_INTR_WDH, &ohci->regs->intrenable); |
||
290 | |||
291 | /* assume there are TDs on the bulk and control lists */ |
||
292 | writel (OHCI_BLF | OHCI_CLF, &ohci->regs->cmdstatus); |
||
293 | break; |
||
294 | |||
295 | default: |
||
296 | ohci_warn (ohci, "odd PCI resume\n"); |
||
297 | } |
||
298 | return retval; |
||
299 | } |
||
300 | |||
301 | #endif /* CONFIG_PM */ |
||
302 | |||
303 | |||
304 | /*-------------------------------------------------------------------------*/ |
||
305 | |||
306 | static const struct hc_driver ohci_pci_hc_driver = { |
||
307 | .description = hcd_name, |
||
308 | |||
309 | /* |
||
310 | * generic hardware linkage |
||
311 | */ |
||
312 | .irq = ohci_irq, |
||
313 | .flags = HCD_MEMORY | HCD_USB11, |
||
314 | |||
315 | /* |
||
316 | * basic lifecycle operations |
||
317 | */ |
||
318 | .reset = ohci_pci_reset, |
||
319 | .start = ohci_pci_start, |
||
320 | #ifdef CONFIG_PM |
||
321 | .suspend = ohci_pci_suspend, |
||
322 | .resume = ohci_pci_resume, |
||
323 | #endif |
||
324 | .stop = ohci_stop, |
||
325 | |||
326 | /* |
||
327 | * memory lifecycle (except per-request) |
||
328 | */ |
||
329 | .hcd_alloc = ohci_hcd_alloc, |
||
330 | .hcd_free = ohci_hcd_free, |
||
331 | |||
332 | /* |
||
333 | * managing i/o requests and associated device resources |
||
334 | */ |
||
335 | .urb_enqueue = ohci_urb_enqueue, |
||
336 | .urb_dequeue = ohci_urb_dequeue, |
||
337 | .endpoint_disable = ohci_endpoint_disable, |
||
338 | |||
339 | /* |
||
340 | * scheduling support |
||
341 | */ |
||
342 | .get_frame_number = ohci_get_frame, |
||
343 | |||
344 | /* |
||
345 | * root hub support |
||
346 | */ |
||
347 | .hub_status_data = ohci_hub_status_data, |
||
348 | .hub_control = ohci_hub_control, |
||
349 | }; |
||
350 | |||
351 | /*-------------------------------------------------------------------------*/ |
||
352 | |||
353 | |||
354 | static const struct pci_device_id pci_ids [] = { { |
||
355 | /* handle any USB OHCI controller */ |
||
356 | PCI_DEVICE_CLASS((PCI_CLASS_SERIAL_USB << 8) | 0x10, ~0), |
||
357 | .driver_data = (unsigned long) &ohci_pci_hc_driver, |
||
358 | }, { /* end: all zeroes */ } |
||
359 | }; |
||
360 | MODULE_DEVICE_TABLE (pci, pci_ids); |
||
361 | |||
362 | /* pci driver glue; this is a "new style" PCI driver module */ |
||
363 | static struct pci_driver ohci_pci_driver = { |
||
364 | .name = (char *) hcd_name, |
||
365 | .id_table = pci_ids, |
||
366 | |||
367 | .probe = usb_hcd_pci_probe, |
||
368 | .remove = usb_hcd_pci_remove, |
||
369 | |||
370 | #ifdef CONFIG_PM |
||
371 | .suspend = usb_hcd_pci_suspend, |
||
372 | .resume = usb_hcd_pci_resume, |
||
373 | #endif |
||
374 | }; |
||
375 | |||
376 | |||
377 | /*static*/ int __init ohci_hcd_pci_init (void) |
||
378 | { |
||
379 | printk (KERN_DEBUG "%s: " DRIVER_INFO " (PCI)\n", hcd_name); |
||
380 | if (usb_disabled()) |
||
381 | return -ENODEV; |
||
382 | |||
383 | printk (KERN_DEBUG "%s: block sizes: ed %Zd td %Zd\n", hcd_name, |
||
384 | sizeof (struct ed), sizeof (struct td)); |
||
385 | //*** printk (KERN_DEBUG "File: %s @Line:%d\n", __FILE__, __LINE__); |
||
386 | return pci_module_init (&ohci_pci_driver); |
||
387 | } |
||
388 | module_init (ohci_hcd_pci_init); |
||
389 | |||
390 | /*-------------------------------------------------------------------------*/ |
||
391 | |||
392 | /*static*/ void /*__exit*/ ohci_hcd_pci_cleanup (void) |
||
393 | { |
||
394 | pci_unregister_driver (&ohci_pci_driver); |
||
395 | } |
||
396 | module_exit (ohci_hcd_pci_cleanup); |