diff options
Diffstat (limited to 'drivers/usb/host/pci-quirks.c')
-rw-r--r-- | drivers/usb/host/pci-quirks.c | 151 |
1 files changed, 81 insertions, 70 deletions
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 9b166d70ae91..f16c59d5f487 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
16 | #include <linux/acpi.h> | 16 | #include <linux/acpi.h> |
17 | #include <linux/dmi.h> | ||
17 | #include "pci-quirks.h" | 18 | #include "pci-quirks.h" |
18 | #include "xhci-ext-caps.h" | 19 | #include "xhci-ext-caps.h" |
19 | 20 | ||
@@ -503,14 +504,84 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) | |||
503 | iounmap(base); | 504 | iounmap(base); |
504 | } | 505 | } |
505 | 506 | ||
507 | static void __devinit ehci_bios_handoff(struct pci_dev *pdev, | ||
508 | void __iomem *op_reg_base, | ||
509 | u32 cap, u8 offset) | ||
510 | { | ||
511 | int try_handoff = 1, tried_handoff = 0; | ||
512 | |||
513 | /* The Pegatron Lucid (ExoPC) tablet sporadically waits for 90 | ||
514 | * seconds trying the handoff on its unused controller. Skip | ||
515 | * it. */ | ||
516 | if (pdev->vendor == 0x8086 && pdev->device == 0x283a) { | ||
517 | const char *dmi_bn = dmi_get_system_info(DMI_BOARD_NAME); | ||
518 | const char *dmi_bv = dmi_get_system_info(DMI_BIOS_VERSION); | ||
519 | if (dmi_bn && !strcmp(dmi_bn, "EXOPG06411") && | ||
520 | dmi_bv && !strcmp(dmi_bv, "Lucid-CE-133")) | ||
521 | try_handoff = 0; | ||
522 | } | ||
523 | |||
524 | if (try_handoff && (cap & EHCI_USBLEGSUP_BIOS)) { | ||
525 | dev_dbg(&pdev->dev, "EHCI: BIOS handoff\n"); | ||
526 | |||
527 | #if 0 | ||
528 | /* aleksey_gorelov@phoenix.com reports that some systems need SMI forced on, | ||
529 | * but that seems dubious in general (the BIOS left it off intentionally) | ||
530 | * and is known to prevent some systems from booting. so we won't do this | ||
531 | * unless maybe we can determine when we're on a system that needs SMI forced. | ||
532 | */ | ||
533 | /* BIOS workaround (?): be sure the pre-Linux code | ||
534 | * receives the SMI | ||
535 | */ | ||
536 | pci_read_config_dword(pdev, offset + EHCI_USBLEGCTLSTS, &val); | ||
537 | pci_write_config_dword(pdev, offset + EHCI_USBLEGCTLSTS, | ||
538 | val | EHCI_USBLEGCTLSTS_SOOE); | ||
539 | #endif | ||
540 | |||
541 | /* some systems get upset if this semaphore is | ||
542 | * set for any other reason than forcing a BIOS | ||
543 | * handoff.. | ||
544 | */ | ||
545 | pci_write_config_byte(pdev, offset + 3, 1); | ||
546 | } | ||
547 | |||
548 | /* if boot firmware now owns EHCI, spin till it hands it over. */ | ||
549 | if (try_handoff) { | ||
550 | int msec = 1000; | ||
551 | while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) { | ||
552 | tried_handoff = 1; | ||
553 | msleep(10); | ||
554 | msec -= 10; | ||
555 | pci_read_config_dword(pdev, offset, &cap); | ||
556 | } | ||
557 | } | ||
558 | |||
559 | if (cap & EHCI_USBLEGSUP_BIOS) { | ||
560 | /* well, possibly buggy BIOS... try to shut it down, | ||
561 | * and hope nothing goes too wrong | ||
562 | */ | ||
563 | if (try_handoff) | ||
564 | dev_warn(&pdev->dev, "EHCI: BIOS handoff failed" | ||
565 | " (BIOS bug?) %08x\n", cap); | ||
566 | pci_write_config_byte(pdev, offset + 2, 0); | ||
567 | } | ||
568 | |||
569 | /* just in case, always disable EHCI SMIs */ | ||
570 | pci_write_config_dword(pdev, offset + EHCI_USBLEGCTLSTS, 0); | ||
571 | |||
572 | /* If the BIOS ever owned the controller then we can't expect | ||
573 | * any power sessions to remain intact. | ||
574 | */ | ||
575 | if (tried_handoff) | ||
576 | writel(0, op_reg_base + EHCI_CONFIGFLAG); | ||
577 | } | ||
578 | |||
506 | static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) | 579 | static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) |
507 | { | 580 | { |
508 | int wait_time, delta; | ||
509 | void __iomem *base, *op_reg_base; | 581 | void __iomem *base, *op_reg_base; |
510 | u32 hcc_params, val; | 582 | u32 hcc_params, cap, val; |
511 | u8 offset, cap_length; | 583 | u8 offset, cap_length; |
512 | int count = 256/4; | 584 | int wait_time, delta, count = 256/4; |
513 | int tried_handoff = 0; | ||
514 | 585 | ||
515 | if (!mmio_resource_enabled(pdev, 0)) | 586 | if (!mmio_resource_enabled(pdev, 0)) |
516 | return; | 587 | return; |
@@ -529,77 +600,17 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) | |||
529 | hcc_params = readl(base + EHCI_HCC_PARAMS); | 600 | hcc_params = readl(base + EHCI_HCC_PARAMS); |
530 | offset = (hcc_params >> 8) & 0xff; | 601 | offset = (hcc_params >> 8) & 0xff; |
531 | while (offset && --count) { | 602 | while (offset && --count) { |
532 | u32 cap; | ||
533 | int msec; | ||
534 | |||
535 | pci_read_config_dword(pdev, offset, &cap); | 603 | pci_read_config_dword(pdev, offset, &cap); |
536 | switch (cap & 0xff) { | ||
537 | case 1: /* BIOS/SMM/... handoff support */ | ||
538 | if ((cap & EHCI_USBLEGSUP_BIOS)) { | ||
539 | dev_dbg(&pdev->dev, "EHCI: BIOS handoff\n"); | ||
540 | 604 | ||
541 | #if 0 | 605 | switch (cap & 0xff) { |
542 | /* aleksey_gorelov@phoenix.com reports that some systems need SMI forced on, | 606 | case 1: |
543 | * but that seems dubious in general (the BIOS left it off intentionally) | 607 | ehci_bios_handoff(pdev, op_reg_base, cap, offset); |
544 | * and is known to prevent some systems from booting. so we won't do this | ||
545 | * unless maybe we can determine when we're on a system that needs SMI forced. | ||
546 | */ | ||
547 | /* BIOS workaround (?): be sure the | ||
548 | * pre-Linux code receives the SMI | ||
549 | */ | ||
550 | pci_read_config_dword(pdev, | ||
551 | offset + EHCI_USBLEGCTLSTS, | ||
552 | &val); | ||
553 | pci_write_config_dword(pdev, | ||
554 | offset + EHCI_USBLEGCTLSTS, | ||
555 | val | EHCI_USBLEGCTLSTS_SOOE); | ||
556 | #endif | ||
557 | |||
558 | /* some systems get upset if this semaphore is | ||
559 | * set for any other reason than forcing a BIOS | ||
560 | * handoff.. | ||
561 | */ | ||
562 | pci_write_config_byte(pdev, offset + 3, 1); | ||
563 | } | ||
564 | |||
565 | /* if boot firmware now owns EHCI, spin till | ||
566 | * it hands it over. | ||
567 | */ | ||
568 | msec = 1000; | ||
569 | while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) { | ||
570 | tried_handoff = 1; | ||
571 | msleep(10); | ||
572 | msec -= 10; | ||
573 | pci_read_config_dword(pdev, offset, &cap); | ||
574 | } | ||
575 | |||
576 | if (cap & EHCI_USBLEGSUP_BIOS) { | ||
577 | /* well, possibly buggy BIOS... try to shut | ||
578 | * it down, and hope nothing goes too wrong | ||
579 | */ | ||
580 | dev_warn(&pdev->dev, "EHCI: BIOS handoff failed" | ||
581 | " (BIOS bug?) %08x\n", cap); | ||
582 | pci_write_config_byte(pdev, offset + 2, 0); | ||
583 | } | ||
584 | |||
585 | /* just in case, always disable EHCI SMIs */ | ||
586 | pci_write_config_dword(pdev, | ||
587 | offset + EHCI_USBLEGCTLSTS, | ||
588 | 0); | ||
589 | |||
590 | /* If the BIOS ever owned the controller then we | ||
591 | * can't expect any power sessions to remain intact. | ||
592 | */ | ||
593 | if (tried_handoff) | ||
594 | writel(0, op_reg_base + EHCI_CONFIGFLAG); | ||
595 | break; | 608 | break; |
596 | case 0: /* illegal reserved capability */ | 609 | case 0: /* Illegal reserved cap, set cap=0 so we exit */ |
597 | cap = 0; | 610 | cap = 0; /* then fallthrough... */ |
598 | /* FALLTHROUGH */ | ||
599 | default: | 611 | default: |
600 | dev_warn(&pdev->dev, "EHCI: unrecognized capability " | 612 | dev_warn(&pdev->dev, "EHCI: unrecognized capability " |
601 | "%02x\n", cap & 0xff); | 613 | "%02x\n", cap & 0xff); |
602 | break; | ||
603 | } | 614 | } |
604 | offset = (cap >> 8) & 0xff; | 615 | offset = (cap >> 8) & 0xff; |
605 | } | 616 | } |