aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2006-12-14 14:53:55 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2007-02-07 18:44:31 -0500
commit4302a595cd9c6363b495460497ecbda49fa16858 (patch)
tree2c348bc94868413cab3dbdc6cdc65777ff1520b9 /drivers/usb/host
parent0873c76485c126a4df70a6961fd354b21b7987f7 (diff)
USB: Rework the OHCI quirk mecanism as suggested by David
This patch applies David Brownell's suggestion for reworking the OHCI quirk mechanism via a table of PCI IDs. It adapts the existing quirks to use that mechanism. This also moves the quirks to reset() as suggested by the comment in there. This is necessary as we need to have the endian properly set before we try to init the controller. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Acked-by: David Brownell <dbrownell@users.sourceforge.net> Acked-by: Geoff Levand <geoffrey.levand@am.sony.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/ohci-pci.c173
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
23static int 23/* AMD 756, for most chips (early revs), corrupts register
24ohci_pci_reset (struct usb_hcd *hcd) 24 * values on read ... so enable the vendor workaround.
25 */
26static 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
32static int __devinit 39/* Apple's OHCI driver has a lot of bizarre workarounds
33ohci_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 */
43static 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 */
56static 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 */
78static 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 */
90static 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
113static 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 137static 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