diff options
Diffstat (limited to 'drivers/usb/host/ohci-pci.c')
-rw-r--r-- | drivers/usb/host/ohci-pci.c | 173 |
1 files changed, 110 insertions, 63 deletions
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 596e0b41e606..82fbec305a66 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
@@ -20,79 +20,128 @@ | |||
20 | 20 | ||
21 | /*-------------------------------------------------------------------------*/ | 21 | /*-------------------------------------------------------------------------*/ |
22 | 22 | ||
23 | static int | 23 | /* AMD 756, for most chips (early revs), corrupts register |
24 | ohci_pci_reset (struct usb_hcd *hcd) | 24 | * values on read ... so enable the vendor workaround. |
25 | */ | ||
26 | static int __devinit ohci_quirk_amd756(struct usb_hcd *hcd) | ||
25 | { | 27 | { |
26 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 28 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
27 | 29 | ||
28 | ohci_hcd_init (ohci); | 30 | ohci->flags = OHCI_QUIRK_AMD756; |
29 | return ohci_init (ohci); | 31 | ohci_dbg (ohci, "AMD756 erratum 4 workaround\n"); |
32 | |||
33 | /* also erratum 10 (suspend/resume issues) */ | ||
34 | device_init_wakeup(&hcd->self.root_hub->dev, 0); | ||
35 | |||
36 | return 0; | ||
30 | } | 37 | } |
31 | 38 | ||
32 | static int __devinit | 39 | /* Apple's OHCI driver has a lot of bizarre workarounds |
33 | ohci_pci_start (struct usb_hcd *hcd) | 40 | * for this chip. Evidently control and bulk lists |
41 | * can get confused. (B&W G3 models, and ...) | ||
42 | */ | ||
43 | static int __devinit ohci_quirk_opti(struct usb_hcd *hcd) | ||
34 | { | 44 | { |
35 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 45 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
36 | int ret; | ||
37 | 46 | ||
38 | /* REVISIT this whole block should move to reset(), which handles | 47 | ohci_dbg (ohci, "WARNING: OPTi workarounds unavailable\n"); |
39 | * all the other one-time init. | 48 | |
49 | return 0; | ||
50 | } | ||
51 | |||
52 | /* Check for NSC87560. We have to look at the bridge (fn1) to | ||
53 | * identify the USB (fn2). This quirk might apply to more or | ||
54 | * even all NSC stuff. | ||
55 | */ | ||
56 | static int __devinit ohci_quirk_ns(struct usb_hcd *hcd) | ||
57 | { | ||
58 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | ||
59 | struct pci_dev *b; | ||
60 | |||
61 | b = pci_get_slot (pdev->bus, PCI_DEVFN (PCI_SLOT (pdev->devfn), 1)); | ||
62 | if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO | ||
63 | && b->vendor == PCI_VENDOR_ID_NS) { | ||
64 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
65 | |||
66 | ohci->flags |= OHCI_QUIRK_SUPERIO; | ||
67 | ohci_dbg (ohci, "Using NSC SuperIO setup\n"); | ||
68 | } | ||
69 | pci_dev_put(b); | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | /* Check for Compaq's ZFMicro chipset, which needs short | ||
75 | * delays before control or bulk queues get re-activated | ||
76 | * in finish_unlinks() | ||
77 | */ | ||
78 | static int __devinit ohci_quirk_zfmicro(struct usb_hcd *hcd) | ||
79 | { | ||
80 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
81 | |||
82 | ohci->flags |= OHCI_QUIRK_ZFMICRO; | ||
83 | ohci_dbg (ohci, "enabled Compaq ZFMicro chipset quirk\n"); | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | |||
89 | /* List of quirks for OHCI */ | ||
90 | static const struct pci_device_id ohci_pci_quirks[] = { | ||
91 | { | ||
92 | PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x740c), | ||
93 | .driver_data = (unsigned long)ohci_quirk_amd756, | ||
94 | }, | ||
95 | { | ||
96 | PCI_DEVICE(PCI_VENDOR_ID_OPTI, 0xc861), | ||
97 | .driver_data = (unsigned long)ohci_quirk_opti, | ||
98 | }, | ||
99 | { | ||
100 | PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_ANY_ID), | ||
101 | .driver_data = (unsigned long)ohci_quirk_ns, | ||
102 | }, | ||
103 | { | ||
104 | PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xa0f8), | ||
105 | .driver_data = (unsigned long)ohci_quirk_zfmicro, | ||
106 | }, | ||
107 | /* FIXME for some of the early AMD 760 southbridges, OHCI | ||
108 | * won't work at all. blacklist them. | ||
40 | */ | 109 | */ |
110 | {}, | ||
111 | }; | ||
112 | |||
113 | static int ohci_pci_reset (struct usb_hcd *hcd) | ||
114 | { | ||
115 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
116 | int ret = 0; | ||
117 | |||
41 | if (hcd->self.controller) { | 118 | if (hcd->self.controller) { |
42 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | 119 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); |
120 | const struct pci_device_id *quirk_id; | ||
43 | 121 | ||
44 | /* AMD 756, for most chips (early revs), corrupts register | 122 | quirk_id = pci_match_id(ohci_pci_quirks, pdev); |
45 | * values on read ... so enable the vendor workaround. | 123 | if (quirk_id != NULL) { |
46 | */ | 124 | int (*quirk)(struct usb_hcd *ohci); |
47 | if (pdev->vendor == PCI_VENDOR_ID_AMD | 125 | quirk = (void *)quirk_id->driver_data; |
48 | && pdev->device == 0x740c) { | 126 | ret = quirk(hcd); |
49 | ohci->flags = OHCI_QUIRK_AMD756; | ||
50 | ohci_dbg (ohci, "AMD756 erratum 4 workaround\n"); | ||
51 | /* also erratum 10 (suspend/resume issues) */ | ||
52 | device_init_wakeup(&hcd->self.root_hub->dev, 0); | ||
53 | } | 127 | } |
128 | } | ||
129 | if (ret == 0) { | ||
130 | ohci_hcd_init (ohci); | ||
131 | return ohci_init (ohci); | ||
132 | } | ||
133 | return ret; | ||
134 | } | ||
54 | 135 | ||
55 | /* FIXME for some of the early AMD 760 southbridges, OHCI | ||
56 | * won't work at all. blacklist them. | ||
57 | */ | ||
58 | |||
59 | /* Apple's OHCI driver has a lot of bizarre workarounds | ||
60 | * for this chip. Evidently control and bulk lists | ||
61 | * can get confused. (B&W G3 models, and ...) | ||
62 | */ | ||
63 | else if (pdev->vendor == PCI_VENDOR_ID_OPTI | ||
64 | && pdev->device == 0xc861) { | ||
65 | ohci_dbg (ohci, | ||
66 | "WARNING: OPTi workarounds unavailable\n"); | ||
67 | } | ||
68 | 136 | ||
69 | /* Check for NSC87560. We have to look at the bridge (fn1) to | 137 | static int __devinit ohci_pci_start (struct usb_hcd *hcd) |
70 | * identify the USB (fn2). This quirk might apply to more or | 138 | { |
71 | * even all NSC stuff. | 139 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
72 | */ | 140 | int ret; |
73 | else if (pdev->vendor == PCI_VENDOR_ID_NS) { | ||
74 | struct pci_dev *b; | ||
75 | |||
76 | b = pci_get_slot (pdev->bus, | ||
77 | PCI_DEVFN (PCI_SLOT (pdev->devfn), 1)); | ||
78 | if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO | ||
79 | && b->vendor == PCI_VENDOR_ID_NS) { | ||
80 | ohci->flags |= OHCI_QUIRK_SUPERIO; | ||
81 | ohci_dbg (ohci, "Using NSC SuperIO setup\n"); | ||
82 | } | ||
83 | pci_dev_put(b); | ||
84 | } | ||
85 | 141 | ||
86 | /* Check for Compaq's ZFMicro chipset, which needs short | 142 | #ifdef CONFIG_PM /* avoid warnings about unused pdev */ |
87 | * delays before control or bulk queues get re-activated | 143 | if (hcd->self.controller) { |
88 | * in finish_unlinks() | 144 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); |
89 | */ | ||
90 | else if (pdev->vendor == PCI_VENDOR_ID_COMPAQ | ||
91 | && pdev->device == 0xa0f8) { | ||
92 | ohci->flags |= OHCI_QUIRK_ZFMICRO; | ||
93 | ohci_dbg (ohci, | ||
94 | "enabled Compaq ZFMicro chipset quirk\n"); | ||
95 | } | ||
96 | 145 | ||
97 | /* RWC may not be set for add-in PCI cards, since boot | 146 | /* RWC may not be set for add-in PCI cards, since boot |
98 | * firmware probably ignored them. This transfers PCI | 147 | * firmware probably ignored them. This transfers PCI |
@@ -101,16 +150,14 @@ ohci_pci_start (struct usb_hcd *hcd) | |||
101 | if (device_may_wakeup(&pdev->dev)) | 150 | if (device_may_wakeup(&pdev->dev)) |
102 | ohci->hc_control |= OHCI_CTRL_RWC; | 151 | ohci->hc_control |= OHCI_CTRL_RWC; |
103 | } | 152 | } |
153 | #endif /* CONFIG_PM */ | ||
104 | 154 | ||
105 | /* NOTE: there may have already been a first reset, to | 155 | ret = ohci_run (ohci); |
106 | * keep bios/smm irqs from making trouble | 156 | if (ret < 0) { |
107 | */ | ||
108 | if ((ret = ohci_run (ohci)) < 0) { | ||
109 | ohci_err (ohci, "can't start\n"); | 157 | ohci_err (ohci, "can't start\n"); |
110 | ohci_stop (hcd); | 158 | ohci_stop (hcd); |
111 | return ret; | ||
112 | } | 159 | } |
113 | return 0; | 160 | return ret; |
114 | } | 161 | } |
115 | 162 | ||
116 | #ifdef CONFIG_PM | 163 | #ifdef CONFIG_PM |