From: Mateusz Korniak Date: Sun, 15 Oct 2006 22:36:49 +0000 (+0000) Subject: - Version 2.6.18.1-3. Added support for PCIe versions of bcm43xx cards. X-Git-Tag: deadbranch-1.2.4~28 X-Git-Url: http://git.pld-linux.org/?a=commitdiff_plain;h=737283c3c0e6634e9a6f82c8ce00b102b2e4e88e;p=packages%2Fkernel.git - Version 2.6.18.1-3. Added support for PCIe versions of bcm43xx cards. Changed files: kernel-bcm43xx-patch_2.6.18.1_for_PCI-E.patch -> 1.1 --- diff --git a/kernel-bcm43xx-patch_2.6.18.1_for_PCI-E.patch b/kernel-bcm43xx-patch_2.6.18.1_for_PCI-E.patch new file mode 100644 index 00000000..04b5ba37 --- /dev/null +++ b/kernel-bcm43xx-patch_2.6.18.1_for_PCI-E.patch @@ -0,0 +1,449 @@ +Index: linux-2.6.18/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +=================================================================== +--- linux-2.6.18.orig/drivers/net/wireless/bcm43xx/bcm43xx_dma.h ++++ linux-2.6.18/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +@@ -314,6 +314,23 @@ int bcm43xx_dma_tx(struct bcm43xx_privat + struct ieee80211_txb *txb); + void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring); + ++/* Helper function that returns the dma mask for this device. */ ++static inline ++u64 bcm43xx_get_supported_dma_mask(struct bcm43xx_private *bcm) ++{ ++ int dma64 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH) & ++ BCM43xx_SBTMSTATEHIGH_DMA64BIT; ++ u16 mmio_base = bcm43xx_dmacontroller_base(dma64, 0); ++ u32 mask = BCM43xx_DMA32_TXADDREXT_MASK; ++ ++ if (dma64) ++ return DMA_64BIT_MASK; ++ bcm43xx_write32(bcm, mmio_base + BCM43xx_DMA32_TXCTL, mask); ++ if (bcm43xx_read32(bcm, mmio_base + BCM43xx_DMA32_TXCTL) & mask) ++ return DMA_32BIT_MASK; ++ return DMA_30BIT_MASK; ++} ++ + #else /* CONFIG_BCM43XX_DMA */ + + +Index: linux-2.6.18/drivers/net/wireless/bcm43xx/bcm43xx_main.c +=================================================================== +--- linux-2.6.18.orig/drivers/net/wireless/bcm43xx/bcm43xx_main.c ++++ linux-2.6.18/drivers/net/wireless/bcm43xx/bcm43xx_main.c +@@ -130,6 +130,10 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for + { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + /* Broadcom 4307 802.11b */ + { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, ++ /* Broadcom 4311 802.11(a)/b/g */ ++ { PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, ++ /* Broadcom 4312 802.11a/b/g */ ++ { PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + /* Broadcom 4318 802.11b/g */ + { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + /* Broadcom 4319 802.11a/b/g */ +@@ -2582,8 +2586,9 @@ static int bcm43xx_probe_cores(struct bc + /* fetch sb_id_hi from core information registers */ + sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI); + +- core_id = (sb_id_hi & 0xFFF0) >> 4; +- core_rev = (sb_id_hi & 0xF); ++ core_id = (sb_id_hi & 0x8FF0) >> 4; ++ core_rev = (sb_id_hi & 0x7000) >> 8; ++ core_rev |= (sb_id_hi & 0xF); + core_vendor = (sb_id_hi & 0xFFFF0000) >> 16; + + /* if present, chipcommon is always core 0; read the chipid from it */ +@@ -2693,6 +2698,7 @@ static int bcm43xx_probe_cores(struct bc + core = NULL; + switch (core_id) { + case BCM43xx_COREID_PCI: ++ case BCM43xx_COREID_PCIE: + core = &bcm->core_pci; + if (core->available) { + printk(KERN_WARNING PFX "Multiple PCI cores found.\n"); +@@ -2731,12 +2737,12 @@ static int bcm43xx_probe_cores(struct bc + case 6: + case 7: + case 9: ++ case 10: + break; + default: +- printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n", ++ printk(KERN_WARNING PFX ++ "Unsupported 80211 core revision %u\n", + core_rev); +- err = -ENODEV; +- goto out; + } + bcm->nr_80211_available++; + core->priv = ext_80211; +@@ -2850,16 +2856,11 @@ static int bcm43xx_wireless_core_init(st + u32 sbimconfiglow; + u8 limit; + +- if (bcm->chip_rev < 5) { ++ if (bcm->core_pci.rev <= 5 && bcm->core_pci.id != BCM43xx_COREID_PCIE) { + sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW); + sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK; + sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK; +- if (bcm->bustype == BCM43xx_BUSTYPE_PCI) +- sbimconfiglow |= 0x32; +- else if (bcm->bustype == BCM43xx_BUSTYPE_SB) +- sbimconfiglow |= 0x53; +- else +- assert(0); ++ sbimconfiglow |= 0x32; + bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow); + } + +@@ -2924,10 +2925,13 @@ static int bcm43xx_wireless_core_init(st + bcm43xx_write16(bcm, 0x043C, 0x000C); + + if (active_wlcore) { +- if (bcm43xx_using_pio(bcm)) ++ if (bcm43xx_using_pio(bcm)) { + err = bcm43xx_pio_init(bcm); +- else ++ } else { + err = bcm43xx_dma_init(bcm); ++ if (err == -ENOSYS) ++ err = bcm43xx_pio_init(bcm); ++ } + if (err) + goto err_chip_cleanup; + } +@@ -2983,22 +2987,64 @@ static void bcm43xx_pcicore_broadcast_va + + static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm) + { +- int err; +- struct bcm43xx_coreinfo *old_core; ++ int err = 0; + +- old_core = bcm->current_core; +- err = bcm43xx_switch_core(bcm, &bcm->core_pci); +- if (err) +- goto out; ++ bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); + +- bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000); ++ if (bcm->core_chipcommon.available) { ++ err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); ++ if (err) ++ goto out; ++ ++ bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000); ++ ++ /* this function is always called when a PCI core is mapped */ ++ err = bcm43xx_switch_core(bcm, &bcm->core_pci); ++ if (err) ++ goto out; ++ } else ++ bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000); ++ ++ bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); + +- bcm43xx_switch_core(bcm, old_core); +- assert(err == 0); + out: + return err; + } + ++static u32 bcm43xx_pcie_reg_read(struct bcm43xx_private *bcm, u32 address) ++{ ++ bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address); ++ return bcm43xx_read32(bcm, BCM43xx_PCIECORE_REG_DATA); ++} ++ ++static void bcm43xx_pcie_reg_write(struct bcm43xx_private *bcm, u32 address, ++ u32 data) ++{ ++ bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address); ++ bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_DATA, data); ++} ++ ++static void bcm43xx_pcie_mdio_write(struct bcm43xx_private *bcm, u8 dev, u8 reg, ++ u16 data) ++{ ++ int i; ++ ++ bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0x0082); ++ bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_DATA, BCM43xx_PCIE_MDIO_ST | ++ BCM43xx_PCIE_MDIO_WT | (dev << BCM43xx_PCIE_MDIO_DEV) | ++ (reg << BCM43xx_PCIE_MDIO_REG) | BCM43xx_PCIE_MDIO_TA | ++ data); ++ udelay(10); ++ ++ for (i = 0; i < 10; i++) { ++ if (bcm43xx_read32(bcm, BCM43xx_PCIECORE_MDIO_CTL) & ++ BCM43xx_PCIE_MDIO_TC) ++ break; ++ msleep(1); ++ } ++ bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0); ++} ++ + /* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable. + * To enable core 0, pass a core_mask of 1<<0 + */ +@@ -3018,7 +3064,8 @@ static int bcm43xx_setup_backplane_pci_c + if (err) + goto out; + +- if (bcm->core_pci.rev < 6) { ++ if (bcm->current_core->rev < 6 || ++ bcm->current_core->id == BCM43xx_COREID_PCI) { + value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC); + value |= (1 << backplane_flag_nr); + bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value); +@@ -3036,21 +3083,46 @@ static int bcm43xx_setup_backplane_pci_c + } + } + +- value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2); +- value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST; +- bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value); +- +- if (bcm->core_pci.rev < 5) { +- value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW); +- value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT) +- & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK; +- value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT) +- & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK; +- bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value); +- err = bcm43xx_pcicore_commit_settings(bcm); +- assert(err == 0); ++ if (bcm->current_core->id == BCM43xx_COREID_PCI) { ++ value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2); ++ value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST; ++ bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value); ++ ++ if (bcm->current_core->rev < 5) { ++ value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW); ++ value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT) ++ & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK; ++ value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT) ++ & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK; ++ bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value); ++ err = bcm43xx_pcicore_commit_settings(bcm); ++ assert(err == 0); ++ } else if (bcm->current_core->rev >= 11) { ++ value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2); ++ value |= BCM43xx_SBTOPCI2_MEMREAD_MULTI; ++ bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value); ++ } ++ } else { ++ if (bcm->current_core->rev == 0 || bcm->current_core->rev == 1) { ++ value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_TLP_WORKAROUND); ++ value |= 0x8; ++ bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_TLP_WORKAROUND, ++ value); ++ } ++ if (bcm->current_core->rev == 0) { ++ bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX, ++ BCM43xx_SERDES_RXTIMER, 0x8128); ++ bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX, ++ BCM43xx_SERDES_CDR, 0x0100); ++ bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX, ++ BCM43xx_SERDES_CDR_BW, 0x1466); ++ } else if (bcm->current_core->rev == 1) { ++ value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_DLLP_LINKCTL); ++ value |= 0x40; ++ bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_DLLP_LINKCTL, ++ value); ++ } + } +- + out_switch_back: + err = bcm43xx_switch_core(bcm, old_core); + out: +@@ -3635,7 +3707,7 @@ static int bcm43xx_read_phyinfo(struct b + bcm->ieee->freq_band = IEEE80211_24GHZ_BAND; + break; + case BCM43xx_PHYTYPE_G: +- if (phy_rev > 7) ++ if (phy_rev > 8) + phy_rev_ok = 0; + bcm->ieee->modulation = IEEE80211_OFDM_MODULATION | + IEEE80211_CCK_MODULATION; +@@ -3986,8 +4058,6 @@ static int bcm43xx_init_private(struct b + struct net_device *net_dev, + struct pci_dev *pci_dev) + { +- int err; +- + bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); + bcm->ieee = netdev_priv(net_dev); + bcm->softmac = ieee80211_priv(net_dev); +@@ -4005,22 +4075,8 @@ static int bcm43xx_init_private(struct b + (void (*)(unsigned long))bcm43xx_interrupt_tasklet, + (unsigned long)bcm); + tasklet_disable_nosync(&bcm->isr_tasklet); +- if (modparam_pio) { ++ if (modparam_pio) + bcm->__using_pio = 1; +- } else { +- err = pci_set_dma_mask(pci_dev, DMA_30BIT_MASK); +- err |= pci_set_consistent_dma_mask(pci_dev, DMA_30BIT_MASK); +- if (err) { +-#ifdef CONFIG_BCM43XX_PIO +- printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n"); +- bcm->__using_pio = 1; +-#else +- printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. " +- "Recompile the driver with PIO support, please.\n"); +- return -ENODEV; +-#endif /* CONFIG_BCM43XX_PIO */ +- } +- } + bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD; + + /* default to sw encryption for now */ +Index: linux-2.6.18/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +=================================================================== +--- linux-2.6.18.orig/drivers/net/wireless/bcm43xx/bcm43xx_dma.c ++++ linux-2.6.18/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +@@ -705,11 +705,30 @@ int bcm43xx_dma_init(struct bcm43xx_priv + struct bcm43xx_dmaring *ring; + int err = -ENOMEM; + int dma64 = 0; +- u32 sbtmstatehi; ++ u64 mask = bcm43xx_get_supported_dma_mask(bcm); ++ int nobits; + +- sbtmstatehi = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); +- if (sbtmstatehi & BCM43xx_SBTMSTATEHIGH_DMA64BIT) ++ if (mask == DMA_64BIT_MASK) { + dma64 = 1; ++ nobits = 64; ++ } else if (mask == DMA_32BIT_MASK) ++ nobits = 32; ++ else ++ nobits = 30; ++ err = pci_set_dma_mask(bcm->pci_dev, mask); ++ err |= pci_set_consistent_dma_mask(bcm->pci_dev, mask); ++ if (err) { ++#ifdef CONFIG_BCM43XX_PIO ++ printk(KERN_WARNING PFX "DMA not supported on this device." ++ " Falling back to PIO.\n"); ++ bcm->__using_pio = 1; ++ return -ENOSYS; ++#else ++ printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. " ++ "Please recompile the driver with PIO support.\n"); ++ return -ENODEV; ++#endif /* CONFIG_BCM43XX_PIO */ ++ } + + /* setup TX DMA channels. */ + ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64); +@@ -755,8 +774,7 @@ int bcm43xx_dma_init(struct bcm43xx_priv + dma->rx_ring3 = ring; + } + +- dprintk(KERN_INFO PFX "%s DMA initialized\n", +- dma64 ? "64-bit" : "32-bit"); ++ dprintk(KERN_INFO PFX "%d-bit DMA initialized\n", nobits); + err = 0; + out: + return err; +Index: linux-2.6.18/drivers/net/wireless/bcm43xx/bcm43xx.h +=================================================================== +--- linux-2.6.18.orig/drivers/net/wireless/bcm43xx/bcm43xx.h ++++ linux-2.6.18/drivers/net/wireless/bcm43xx/bcm43xx.h +@@ -159,6 +159,7 @@ + + /* Chipcommon registers. */ + #define BCM43xx_CHIPCOMMON_CAPABILITIES 0x04 ++#define BCM43xx_CHIPCOMMON_CTL 0x28 + #define BCM43xx_CHIPCOMMON_PLLONDELAY 0xB0 + #define BCM43xx_CHIPCOMMON_FREFSELDELAY 0xB4 + #define BCM43xx_CHIPCOMMON_SLOWCLKCTL 0xB8 +@@ -172,6 +173,33 @@ + /* SBTOPCI2 values. */ + #define BCM43xx_SBTOPCI2_PREFETCH 0x4 + #define BCM43xx_SBTOPCI2_BURST 0x8 ++#define BCM43xx_SBTOPCI2_MEMREAD_MULTI 0x20 ++ ++/* PCI-E core registers. */ ++#define BCM43xx_PCIECORE_REG_ADDR 0x0130 ++#define BCM43xx_PCIECORE_REG_DATA 0x0134 ++#define BCM43xx_PCIECORE_MDIO_CTL 0x0128 ++#define BCM43xx_PCIECORE_MDIO_DATA 0x012C ++ ++/* PCI-E registers. */ ++#define BCM43xx_PCIE_TLP_WORKAROUND 0x0004 ++#define BCM43xx_PCIE_DLLP_LINKCTL 0x0100 ++ ++/* PCI-E MDIO bits. */ ++#define BCM43xx_PCIE_MDIO_ST 0x40000000 ++#define BCM43xx_PCIE_MDIO_WT 0x10000000 ++#define BCM43xx_PCIE_MDIO_DEV 22 ++#define BCM43xx_PCIE_MDIO_REG 18 ++#define BCM43xx_PCIE_MDIO_TA 0x00020000 ++#define BCM43xx_PCIE_MDIO_TC 0x0100 ++ ++/* MDIO devices. */ ++#define BCM43xx_MDIO_SERDES_RX 0x1F ++ ++/* SERDES RX registers. */ ++#define BCM43xx_SERDES_RXTIMER 0x2 ++#define BCM43xx_SERDES_CDR 0x6 ++#define BCM43xx_SERDES_CDR_BW 0x7 + + /* Chipcommon capabilities. */ + #define BCM43xx_CAPABILITIES_PCTL 0x00040000 +@@ -221,6 +249,7 @@ + #define BCM43xx_COREID_USB20_HOST 0x819 + #define BCM43xx_COREID_USB20_DEV 0x81a + #define BCM43xx_COREID_SDIO_HOST 0x81b ++#define BCM43xx_COREID_PCIE 0x820 + + /* Core Information Registers */ + #define BCM43xx_CIR_BASE 0xf00 +Index: linux-2.6.18/drivers/net/wireless/bcm43xx/bcm43xx_power.c +=================================================================== +--- linux-2.6.18.orig/drivers/net/wireless/bcm43xx/bcm43xx_power.c ++++ linux-2.6.18/drivers/net/wireless/bcm43xx/bcm43xx_power.c +@@ -153,8 +153,6 @@ int bcm43xx_pctl_init(struct bcm43xx_pri + int err, maxfreq; + struct bcm43xx_coreinfo *old_core; + +- if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL)) +- return 0; + old_core = bcm->current_core; + err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); + if (err == -ENODEV) +@@ -162,11 +160,27 @@ int bcm43xx_pctl_init(struct bcm43xx_pri + if (err) + goto out; + +- maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1); +- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY, +- (maxfreq * 150 + 999999) / 1000000); +- bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY, +- (maxfreq * 15 + 999999) / 1000000); ++ if (bcm->chip_id == 0x4321) { ++ if (bcm->chip_rev == 0) ++ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x03A4); ++ if (bcm->chip_rev == 1) ++ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x00A4); ++ } ++ ++ if (bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) { ++ if (bcm->current_core->rev >= 10) { ++ /* Set Idle Power clock rate to 1Mhz */ ++ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL, ++ (bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL) ++ & 0x0000FFFF) | 0x40000); ++ } else { ++ maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1); ++ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY, ++ (maxfreq * 150 + 999999) / 1000000); ++ bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY, ++ (maxfreq * 15 + 999999) / 1000000); ++ } ++ } + + err = bcm43xx_switch_core(bcm, old_core); + assert(err == 0);