diff options
author | Stelios Koroneos <skoroneos@digital-opsis.com> | 2007-02-19 20:18:25 +0000 |
---|---|---|
committer | Stelios Koroneos <skoroneos@digital-opsis.com> | 2007-02-19 20:18:25 +0000 |
commit | 7ed9ddb3fed7b3d38613644df734cedb887502d1 (patch) | |
tree | 27760c6f9b0fe1fa8e426e0e7215640a1babff17 /packages/linux/linux-efika-2.6.20/0006-Rework-the-OHCI-quirk-mecanism-as-suggested-by-David.txt | |
parent | f692fd835e0716ac90c1c2d93fa7d800099715af (diff) |
/packages/linux: Add kernel 2.6.20 for efika
Diffstat (limited to 'packages/linux/linux-efika-2.6.20/0006-Rework-the-OHCI-quirk-mecanism-as-suggested-by-David.txt')
-rw-r--r-- | packages/linux/linux-efika-2.6.20/0006-Rework-the-OHCI-quirk-mecanism-as-suggested-by-David.txt | 236 |
1 files changed, 236 insertions, 0 deletions
diff --git a/packages/linux/linux-efika-2.6.20/0006-Rework-the-OHCI-quirk-mecanism-as-suggested-by-David.txt b/packages/linux/linux-efika-2.6.20/0006-Rework-the-OHCI-quirk-mecanism-as-suggested-by-David.txt new file mode 100644 index 0000000000..39f6fef607 --- /dev/null +++ b/packages/linux/linux-efika-2.6.20/0006-Rework-the-OHCI-quirk-mecanism-as-suggested-by-David.txt @@ -0,0 +1,236 @@ +From 9282a04f14cef512736ac4a895fb48456e6a8989 Mon Sep 17 00:00:00 2001 +From: Benjamin Herrenschmidt <benh@kernel.crashing.org> +Date: Thu, 14 Dec 2006 14:13:26 +1100 +Subject: [PATCH] [PATCH] 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> + + drivers/usb/host/ohci-pci.c | 173 +++++++++++++++++++++++++++----------------- + 1 file changed, 110 insertions(+), 63 deletions(-) +--- + 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 596e0b4..82fbec3 100644 +--- a/drivers/usb/host/ohci-pci.c ++++ b/drivers/usb/host/ohci-pci.c +@@ -20,79 +20,128 @@ + + /*-------------------------------------------------------------------------*/ + +-static int +-ohci_pci_reset (struct usb_hcd *hcd) ++/* AMD 756, for most chips (early revs), corrupts register ++ * values on read ... so enable the vendor workaround. ++ */ ++static int __devinit ohci_quirk_amd756(struct usb_hcd *hcd) + { + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + +- ohci_hcd_init (ohci); +- return ohci_init (ohci); ++ ohci->flags = OHCI_QUIRK_AMD756; ++ ohci_dbg (ohci, "AMD756 erratum 4 workaround\n"); ++ ++ /* also erratum 10 (suspend/resume issues) */ ++ device_init_wakeup(&hcd->self.root_hub->dev, 0); ++ ++ return 0; + } + +-static int __devinit +-ohci_pci_start (struct usb_hcd *hcd) ++/* Apple's OHCI driver has a lot of bizarre workarounds ++ * for this chip. Evidently control and bulk lists ++ * can get confused. (B&W G3 models, and ...) ++ */ ++static int __devinit ohci_quirk_opti(struct usb_hcd *hcd) + { + struct ohci_hcd *ohci = hcd_to_ohci (hcd); +- int ret; + +- /* REVISIT this whole block should move to reset(), which handles +- * all the other one-time init. ++ ohci_dbg (ohci, "WARNING: OPTi workarounds unavailable\n"); ++ ++ return 0; ++} ++ ++/* Check for NSC87560. We have to look at the bridge (fn1) to ++ * identify the USB (fn2). This quirk might apply to more or ++ * even all NSC stuff. ++ */ ++static int __devinit ohci_quirk_ns(struct usb_hcd *hcd) ++{ ++ struct pci_dev *pdev = to_pci_dev(hcd->self.controller); ++ struct pci_dev *b; ++ ++ b = pci_get_slot (pdev->bus, PCI_DEVFN (PCI_SLOT (pdev->devfn), 1)); ++ if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO ++ && b->vendor == PCI_VENDOR_ID_NS) { ++ struct ohci_hcd *ohci = hcd_to_ohci (hcd); ++ ++ ohci->flags |= OHCI_QUIRK_SUPERIO; ++ ohci_dbg (ohci, "Using NSC SuperIO setup\n"); ++ } ++ pci_dev_put(b); ++ ++ return 0; ++} ++ ++/* Check for Compaq's ZFMicro chipset, which needs short ++ * delays before control or bulk queues get re-activated ++ * in finish_unlinks() ++ */ ++static int __devinit ohci_quirk_zfmicro(struct usb_hcd *hcd) ++{ ++ struct ohci_hcd *ohci = hcd_to_ohci (hcd); ++ ++ ohci->flags |= OHCI_QUIRK_ZFMICRO; ++ ohci_dbg (ohci, "enabled Compaq ZFMicro chipset quirk\n"); ++ ++ return 0; ++} ++ ++ ++/* List of quirks for OHCI */ ++static const struct pci_device_id ohci_pci_quirks[] = { ++ { ++ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x740c), ++ .driver_data = (unsigned long)ohci_quirk_amd756, ++ }, ++ { ++ PCI_DEVICE(PCI_VENDOR_ID_OPTI, 0xc861), ++ .driver_data = (unsigned long)ohci_quirk_opti, ++ }, ++ { ++ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_ANY_ID), ++ .driver_data = (unsigned long)ohci_quirk_ns, ++ }, ++ { ++ PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xa0f8), ++ .driver_data = (unsigned long)ohci_quirk_zfmicro, ++ }, ++ /* FIXME for some of the early AMD 760 southbridges, OHCI ++ * won't work at all. blacklist them. + */ ++ {}, ++}; ++ ++static int ohci_pci_reset (struct usb_hcd *hcd) ++{ ++ struct ohci_hcd *ohci = hcd_to_ohci (hcd); ++ int ret = 0; ++ + if (hcd->self.controller) { + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); ++ const struct pci_device_id *quirk_id; + +- /* AMD 756, for most chips (early revs), corrupts register +- * values on read ... so enable the vendor workaround. +- */ +- if (pdev->vendor == PCI_VENDOR_ID_AMD +- && pdev->device == 0x740c) { +- ohci->flags = OHCI_QUIRK_AMD756; +- ohci_dbg (ohci, "AMD756 erratum 4 workaround\n"); +- /* also erratum 10 (suspend/resume issues) */ +- device_init_wakeup(&hcd->self.root_hub->dev, 0); ++ quirk_id = pci_match_id(ohci_pci_quirks, pdev); ++ if (quirk_id != NULL) { ++ int (*quirk)(struct usb_hcd *ohci); ++ quirk = (void *)quirk_id->driver_data; ++ ret = quirk(hcd); + } ++ } ++ if (ret == 0) { ++ ohci_hcd_init (ohci); ++ return ohci_init (ohci); ++ } ++ return ret; ++} + +- /* FIXME for some of the early AMD 760 southbridges, OHCI +- * won't work at all. blacklist them. +- */ +- +- /* Apple's OHCI driver has a lot of bizarre workarounds +- * for this chip. Evidently control and bulk lists +- * can get confused. (B&W G3 models, and ...) +- */ +- else if (pdev->vendor == PCI_VENDOR_ID_OPTI +- && pdev->device == 0xc861) { +- ohci_dbg (ohci, +- "WARNING: OPTi workarounds unavailable\n"); +- } + +- /* Check for NSC87560. We have to look at the bridge (fn1) to +- * identify the USB (fn2). This quirk might apply to more or +- * even all NSC stuff. +- */ +- else if (pdev->vendor == PCI_VENDOR_ID_NS) { +- struct pci_dev *b; +- +- b = pci_get_slot (pdev->bus, +- PCI_DEVFN (PCI_SLOT (pdev->devfn), 1)); +- if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO +- && b->vendor == PCI_VENDOR_ID_NS) { +- ohci->flags |= OHCI_QUIRK_SUPERIO; +- ohci_dbg (ohci, "Using NSC SuperIO setup\n"); +- } +- pci_dev_put(b); +- } ++static int __devinit ohci_pci_start (struct usb_hcd *hcd) ++{ ++ struct ohci_hcd *ohci = hcd_to_ohci (hcd); ++ int ret; + +- /* Check for Compaq's ZFMicro chipset, which needs short +- * delays before control or bulk queues get re-activated +- * in finish_unlinks() +- */ +- else if (pdev->vendor == PCI_VENDOR_ID_COMPAQ +- && pdev->device == 0xa0f8) { +- ohci->flags |= OHCI_QUIRK_ZFMICRO; +- ohci_dbg (ohci, +- "enabled Compaq ZFMicro chipset quirk\n"); +- } ++#ifdef CONFIG_PM /* avoid warnings about unused pdev */ ++ if (hcd->self.controller) { ++ struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + + /* RWC may not be set for add-in PCI cards, since boot + * firmware probably ignored them. This transfers PCI +@@ -101,16 +150,14 @@ ohci_pci_start (struct usb_hcd *hcd) + if (device_may_wakeup(&pdev->dev)) + ohci->hc_control |= OHCI_CTRL_RWC; + } ++#endif /* CONFIG_PM */ + +- /* NOTE: there may have already been a first reset, to +- * keep bios/smm irqs from making trouble +- */ +- if ((ret = ohci_run (ohci)) < 0) { ++ ret = ohci_run (ohci); ++ if (ret < 0) { + ohci_err (ohci, "can't start\n"); + ohci_stop (hcd); +- return ret; + } +- return 0; ++ return ret; + } + + #ifdef CONFIG_PM +-- +1.4.4.2 + |