|
11 | 11 |
|
12 | 12 | #include <linux/pci.h>
|
13 | 13 | #include <linux/acpi.h>
|
| 14 | +#include <linux/delay.h> |
| 15 | +#include <linux/dmi.h> |
14 | 16 | #include <linux/pci_ids.h>
|
| 17 | +#include <linux/bcma/bcma.h> |
| 18 | +#include <linux/bcma/bcma_regs.h> |
15 | 19 | #include <drm/i915_drm.h>
|
16 | 20 | #include <asm/pci-direct.h>
|
17 | 21 | #include <asm/dma.h>
|
|
21 | 25 | #include <asm/iommu.h>
|
22 | 26 | #include <asm/gart.h>
|
23 | 27 | #include <asm/irq_remapping.h>
|
| 28 | +#include <asm/early_ioremap.h> |
| 29 | + |
| 30 | +#define dev_err(msg) pr_err("pci 0000:%02x:%02x.%d: %s", bus, slot, func, msg) |
24 | 31 |
|
25 | 32 | static void __init fix_hypertransport_config(int num, int slot, int func)
|
26 | 33 | {
|
@@ -596,6 +603,61 @@ static void __init force_disable_hpet(int num, int slot, int func)
|
596 | 603 | #endif
|
597 | 604 | }
|
598 | 605 |
|
| 606 | +#define BCM4331_MMIO_SIZE 16384 |
| 607 | +#define BCM4331_PM_CAP 0x40 |
| 608 | +#define bcma_aread32(reg) ioread32(mmio + 1 * BCMA_CORE_SIZE + reg) |
| 609 | +#define bcma_awrite32(reg, val) iowrite32(val, mmio + 1 * BCMA_CORE_SIZE + reg) |
| 610 | + |
| 611 | +static void __init apple_airport_reset(int bus, int slot, int func) |
| 612 | +{ |
| 613 | + void __iomem *mmio; |
| 614 | + u16 pmcsr; |
| 615 | + u64 addr; |
| 616 | + int i; |
| 617 | + |
| 618 | + if (!dmi_match(DMI_SYS_VENDOR, "Apple Inc.")) |
| 619 | + return; |
| 620 | + |
| 621 | + /* Card may have been put into PCI_D3hot by grub quirk */ |
| 622 | + pmcsr = read_pci_config_16(bus, slot, func, BCM4331_PM_CAP + PCI_PM_CTRL); |
| 623 | + |
| 624 | + if ((pmcsr & PCI_PM_CTRL_STATE_MASK) != PCI_D0) { |
| 625 | + pmcsr &= ~PCI_PM_CTRL_STATE_MASK; |
| 626 | + write_pci_config_16(bus, slot, func, BCM4331_PM_CAP + PCI_PM_CTRL, pmcsr); |
| 627 | + mdelay(10); |
| 628 | + |
| 629 | + pmcsr = read_pci_config_16(bus, slot, func, BCM4331_PM_CAP + PCI_PM_CTRL); |
| 630 | + if ((pmcsr & PCI_PM_CTRL_STATE_MASK) != PCI_D0) { |
| 631 | + dev_err("Cannot power up Apple AirPort card\n"); |
| 632 | + return; |
| 633 | + } |
| 634 | + } |
| 635 | + |
| 636 | + addr = read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_0); |
| 637 | + addr |= (u64)read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_1) << 32; |
| 638 | + addr &= PCI_BASE_ADDRESS_MEM_MASK; |
| 639 | + |
| 640 | + mmio = early_ioremap(addr, BCM4331_MMIO_SIZE); |
| 641 | + if (!mmio) { |
| 642 | + dev_err("Cannot iomap Apple AirPort card\n"); |
| 643 | + return; |
| 644 | + } |
| 645 | + |
| 646 | + pr_info("Resetting Apple AirPort card (left enabled by EFI)\n"); |
| 647 | + |
| 648 | + for (i = 0; bcma_aread32(BCMA_RESET_ST) && i < 30; i++) |
| 649 | + udelay(10); |
| 650 | + |
| 651 | + bcma_awrite32(BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); |
| 652 | + bcma_aread32(BCMA_RESET_CTL); |
| 653 | + udelay(1); |
| 654 | + |
| 655 | + bcma_awrite32(BCMA_RESET_CTL, 0); |
| 656 | + bcma_aread32(BCMA_RESET_CTL); |
| 657 | + udelay(10); |
| 658 | + |
| 659 | + early_iounmap(mmio, BCM4331_MMIO_SIZE); |
| 660 | +} |
599 | 661 |
|
600 | 662 | #define QFLAG_APPLY_ONCE 0x1
|
601 | 663 | #define QFLAG_APPLIED 0x2
|
@@ -638,6 +700,8 @@ static struct chipset early_qrk[] __initdata = {
|
638 | 700 | */
|
639 | 701 | { PCI_VENDOR_ID_INTEL, 0x0f00,
|
640 | 702 | PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, force_disable_hpet},
|
| 703 | + { PCI_VENDOR_ID_BROADCOM, 0x4331, |
| 704 | + PCI_CLASS_NETWORK_OTHER, PCI_ANY_ID, 0, apple_airport_reset}, |
641 | 705 | {}
|
642 | 706 | };
|
643 | 707 |
|
|
0 commit comments