aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/core/hcd-pci.c4
-rw-r--r--drivers/usb/host/ohci-hcd.c9
-rw-r--r--drivers/usb/host/ohci-pci.c18
-rw-r--r--drivers/usb/host/ohci.h1
-rw-r--r--drivers/usb/host/pci-quirks.c18
5 files changed, 41 insertions, 9 deletions
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index c3f98543caaf..3799573bd385 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -329,8 +329,10 @@ void usb_hcd_pci_shutdown(struct pci_dev *dev)
329 return; 329 return;
330 330
331 if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && 331 if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) &&
332 hcd->driver->shutdown) 332 hcd->driver->shutdown) {
333 hcd->driver->shutdown(hcd); 333 hcd->driver->shutdown(hcd);
334 pci_disable_device(dev);
335 }
334} 336}
335EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown); 337EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown);
336 338
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index c3b4ccc7337b..8ef3c1944364 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -398,7 +398,14 @@ ohci_shutdown (struct usb_hcd *hcd)
398 398
399 ohci = hcd_to_ohci (hcd); 399 ohci = hcd_to_ohci (hcd);
400 ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); 400 ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
401 ohci_usb_reset (ohci); 401 ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
402
403 /* If the SHUTDOWN quirk is set, don't put the controller in RESET */
404 ohci->hc_control &= (ohci->flags & OHCI_QUIRK_SHUTDOWN ?
405 OHCI_CTRL_RWC | OHCI_CTRL_HCFS :
406 OHCI_CTRL_RWC);
407 ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
408
402 /* flush the writes */ 409 /* flush the writes */
403 (void) ohci_readl (ohci, &ohci->regs->control); 410 (void) ohci_readl (ohci, &ohci->regs->control);
404} 411}
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 6bdc8b25a6a1..36ee9a666e93 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -201,6 +201,20 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
201 return 0; 201 return 0;
202} 202}
203 203
204/* nVidia controllers continue to drive Reset signalling on the bus
205 * even after system shutdown, wasting power. This flag tells the
206 * shutdown routine to leave the controller OPERATIONAL instead of RESET.
207 */
208static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd)
209{
210 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
211
212 ohci->flags |= OHCI_QUIRK_SHUTDOWN;
213 ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
214
215 return 0;
216}
217
204/* 218/*
205 * The hardware normally enables the A-link power management feature, which 219 * The hardware normally enables the A-link power management feature, which
206 * lets the system lower the power consumption in idle states. 220 * lets the system lower the power consumption in idle states.
@@ -332,6 +346,10 @@ static const struct pci_device_id ohci_pci_quirks[] = {
332 PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399), 346 PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399),
333 .driver_data = (unsigned long)ohci_quirk_amd700, 347 .driver_data = (unsigned long)ohci_quirk_amd700,
334 }, 348 },
349 {
350 PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
351 .driver_data = (unsigned long) ohci_quirk_nvidia_shutdown,
352 },
335 353
336 /* FIXME for some of the early AMD 760 southbridges, OHCI 354 /* FIXME for some of the early AMD 760 southbridges, OHCI
337 * won't work at all. blacklist them. 355 * won't work at all. blacklist them.
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 5bf15fed0d9f..51facb985c84 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -403,6 +403,7 @@ struct ohci_hcd {
403#define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */ 403#define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */
404#define OHCI_QUIRK_AMD_ISO 0x200 /* ISO transfers*/ 404#define OHCI_QUIRK_AMD_ISO 0x200 /* ISO transfers*/
405#define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */ 405#define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */
406#define OHCI_QUIRK_SHUTDOWN 0x800 /* nVidia power bug */
406 // there are also chip quirks/bugs in init logic 407 // there are also chip quirks/bugs in init logic
407 408
408 struct work_struct nec_work; /* Worker for NEC quirk */ 409 struct work_struct nec_work; /* Worker for NEC quirk */
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 83b5f9cea85a..464ed977b45d 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -169,6 +169,7 @@ static int __devinit mmio_resource_enabled(struct pci_dev *pdev, int idx)
169static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) 169static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
170{ 170{
171 void __iomem *base; 171 void __iomem *base;
172 u32 control;
172 173
173 if (!mmio_resource_enabled(pdev, 0)) 174 if (!mmio_resource_enabled(pdev, 0))
174 return; 175 return;
@@ -177,10 +178,14 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
177 if (base == NULL) 178 if (base == NULL)
178 return; 179 return;
179 180
181 control = readl(base + OHCI_CONTROL);
182
180/* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ 183/* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
181#ifndef __hppa__ 184#ifdef __hppa__
182{ 185#define OHCI_CTRL_MASK (OHCI_CTRL_RWC | OHCI_CTRL_IR)
183 u32 control = readl(base + OHCI_CONTROL); 186#else
187#define OHCI_CTRL_MASK OHCI_CTRL_RWC
188
184 if (control & OHCI_CTRL_IR) { 189 if (control & OHCI_CTRL_IR) {
185 int wait_time = 500; /* arbitrary; 5 seconds */ 190 int wait_time = 500; /* arbitrary; 5 seconds */
186 writel(OHCI_INTR_OC, base + OHCI_INTRENABLE); 191 writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
@@ -194,13 +199,12 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
194 dev_warn(&pdev->dev, "OHCI: BIOS handoff failed" 199 dev_warn(&pdev->dev, "OHCI: BIOS handoff failed"
195 " (BIOS bug?) %08x\n", 200 " (BIOS bug?) %08x\n",
196 readl(base + OHCI_CONTROL)); 201 readl(base + OHCI_CONTROL));
197
198 /* reset controller, preserving RWC */
199 writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL);
200 } 202 }
201}
202#endif 203#endif
203 204
205 /* reset controller, preserving RWC (and possibly IR) */
206 writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
207
204 /* 208 /*
205 * disable interrupts 209 * disable interrupts
206 */ 210 */