diff options
author | Andy Ross <andy.ross@windriver.com> | 2011-05-11 18:15:51 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-05-12 12:42:00 -0400 |
commit | 5c853013dcdadb60724268bf860d372fba71694c (patch) | |
tree | 052c771044e05670b1cf1d25714ce64ee7e3e8ee /drivers/usb/host/pci-quirks.c | |
parent | af5c5805013d3c97d7f0bc27a56c49baa34b1f8a (diff) |
ehci: pci quirk cleanup
Factor the handoff code out from quirk_usb_disable_ehci
Signed-off-by: Andy Ross <andy.ross@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/pci-quirks.c')
-rw-r--r-- | drivers/usb/host/pci-quirks.c | 136 |
1 files changed, 66 insertions, 70 deletions
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 9b166d70ae91..e300509faa61 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c | |||
@@ -503,14 +503,70 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) | |||
503 | iounmap(base); | 503 | iounmap(base); |
504 | } | 504 | } |
505 | 505 | ||
506 | static void __devinit ehci_bios_handoff(struct pci_dev *pdev, | ||
507 | void __iomem *op_reg_base, | ||
508 | u32 cap, u8 offset) | ||
509 | { | ||
510 | int msec, tried_handoff = 0; | ||
511 | |||
512 | if (cap & EHCI_USBLEGSUP_BIOS) { | ||
513 | dev_dbg(&pdev->dev, "EHCI: BIOS handoff\n"); | ||
514 | |||
515 | #if 0 | ||
516 | /* aleksey_gorelov@phoenix.com reports that some systems need SMI forced on, | ||
517 | * but that seems dubious in general (the BIOS left it off intentionally) | ||
518 | * and is known to prevent some systems from booting. so we won't do this | ||
519 | * unless maybe we can determine when we're on a system that needs SMI forced. | ||
520 | */ | ||
521 | /* BIOS workaround (?): be sure the pre-Linux code | ||
522 | * receives the SMI | ||
523 | */ | ||
524 | pci_read_config_dword(pdev, offset + EHCI_USBLEGCTLSTS, &val); | ||
525 | pci_write_config_dword(pdev, offset + EHCI_USBLEGCTLSTS, | ||
526 | val | EHCI_USBLEGCTLSTS_SOOE); | ||
527 | #endif | ||
528 | |||
529 | /* some systems get upset if this semaphore is | ||
530 | * set for any other reason than forcing a BIOS | ||
531 | * handoff.. | ||
532 | */ | ||
533 | pci_write_config_byte(pdev, offset + 3, 1); | ||
534 | } | ||
535 | |||
536 | /* if boot firmware now owns EHCI, spin till it hands it over. */ | ||
537 | msec = 1000; | ||
538 | while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) { | ||
539 | tried_handoff = 1; | ||
540 | msleep(10); | ||
541 | msec -= 10; | ||
542 | pci_read_config_dword(pdev, offset, &cap); | ||
543 | } | ||
544 | |||
545 | if (cap & EHCI_USBLEGSUP_BIOS) { | ||
546 | /* well, possibly buggy BIOS... try to shut it down, | ||
547 | * and hope nothing goes too wrong | ||
548 | */ | ||
549 | dev_warn(&pdev->dev, "EHCI: BIOS handoff failed" | ||
550 | " (BIOS bug?) %08x\n", cap); | ||
551 | pci_write_config_byte(pdev, offset + 2, 0); | ||
552 | } | ||
553 | |||
554 | /* just in case, always disable EHCI SMIs */ | ||
555 | pci_write_config_dword(pdev, offset + EHCI_USBLEGCTLSTS, 0); | ||
556 | |||
557 | /* If the BIOS ever owned the controller then we can't expect | ||
558 | * any power sessions to remain intact. | ||
559 | */ | ||
560 | if (tried_handoff) | ||
561 | writel(0, op_reg_base + EHCI_CONFIGFLAG); | ||
562 | } | ||
563 | |||
506 | static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) | 564 | static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) |
507 | { | 565 | { |
508 | int wait_time, delta; | ||
509 | void __iomem *base, *op_reg_base; | 566 | void __iomem *base, *op_reg_base; |
510 | u32 hcc_params, val; | 567 | u32 hcc_params, cap, val; |
511 | u8 offset, cap_length; | 568 | u8 offset, cap_length; |
512 | int count = 256/4; | 569 | int wait_time, delta, count = 256/4; |
513 | int tried_handoff = 0; | ||
514 | 570 | ||
515 | if (!mmio_resource_enabled(pdev, 0)) | 571 | if (!mmio_resource_enabled(pdev, 0)) |
516 | return; | 572 | return; |
@@ -529,77 +585,17 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) | |||
529 | hcc_params = readl(base + EHCI_HCC_PARAMS); | 585 | hcc_params = readl(base + EHCI_HCC_PARAMS); |
530 | offset = (hcc_params >> 8) & 0xff; | 586 | offset = (hcc_params >> 8) & 0xff; |
531 | while (offset && --count) { | 587 | while (offset && --count) { |
532 | u32 cap; | ||
533 | int msec; | ||
534 | |||
535 | pci_read_config_dword(pdev, offset, &cap); | 588 | 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 | |||
541 | #if 0 | ||
542 | /* aleksey_gorelov@phoenix.com reports that some systems need SMI forced on, | ||
543 | * but that seems dubious in general (the BIOS left it off intentionally) | ||
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 | 589 | ||
576 | if (cap & EHCI_USBLEGSUP_BIOS) { | 590 | switch (cap & 0xff) { |
577 | /* well, possibly buggy BIOS... try to shut | 591 | case 1: |
578 | * it down, and hope nothing goes too wrong | 592 | ehci_bios_handoff(pdev, op_reg_base, cap, offset); |
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; | 593 | break; |
596 | case 0: /* illegal reserved capability */ | 594 | case 0: /* Illegal reserved cap, set cap=0 so we exit */ |
597 | cap = 0; | 595 | cap = 0; /* then fallthrough... */ |
598 | /* FALLTHROUGH */ | ||
599 | default: | 596 | default: |
600 | dev_warn(&pdev->dev, "EHCI: unrecognized capability " | 597 | dev_warn(&pdev->dev, "EHCI: unrecognized capability " |
601 | "%02x\n", cap & 0xff); | 598 | "%02x\n", cap & 0xff); |
602 | break; | ||
603 | } | 599 | } |
604 | offset = (cap >> 8) & 0xff; | 600 | offset = (cap >> 8) & 0xff; |
605 | } | 601 | } |