Hello, Thank you for implementing BCM4331 support!
I am not interested in running the wireless-testing kernel, so I hacked together a patch to enable BCM4331 support on linux-3.1-rc5. Since others may be interested in this as well, I am posting it to this list. The patch consists of the following patches posted to this list: [PATCH 1/3] b43: rename TX header formats [PATCH 2/3] b43: use enum for firmware header format [PATCH 3/3] b43: support new TX header, noticed to be used by 598.314+ fw [PATCH 4/3 V2] b43: support new RX header, noticed to be used in 598.314+ fw [PATCH V2] bcma: implement BCM4331 workaround for external PA lines [PATCH 1/2] b43: include HT-PHY in some common code [PATCH 2/2] b43: make forcing clock common (HT-PHY also uses that) [RFC][PATCH] b43: HT-PHY: allow writing longer tables with a single call [PATCH 1/4] b43: HT-PHY: init: zero EXTG registers [PATCH 2/4] b43: HT-PHY: init: implement few simple PHY writes [PATCH 3/4] b43: HT-PHY: init: copy tables and reset CCA [PATCH V2 4/4] b43: HT-PHY: init: init BPHY and upload 0x1a table [PATCH 1/2] b43: HT-PHY: init: add missing PHY mask/set ops [PATCH 2/2] b43: HT-PHY: init: add some AFE (Analog Frontend) operation [PATCH] b43: HT-PHY: init: add missing small-tables writes [PATCH 1/2] b43: HT-PHY: use separated function for forcing RF sequence [PATCH 2/2] b43: HT-PHY: read clip state [wireless-next][PATCH 1/3] b43: Relax requirement for descriptors to be in the DMA zone [wireless-next][PATCH 2/3] b43: use 8K buffers for 64-bit DMA to workaround hardware bug [wireless-next][PATCH 3/3] b43: make HT-PHY support experimental The combined patch is attached. I can confirm that wireless now works on my MacBookPro8,2. Please let me know if I missed anything important. Also, I would be interested in testing any patches that make the driver work with BCM4331 after being suspended to RAM. Regards, -- Benjamin Lee http://www.b1c1l1.com/
diff -ruN linux-3.1-rc5.orig/drivers/bcma/driver_chipcommon_pmu.c linux-3.1-rc5/drivers/bcma/driver_chipcommon_pmu.c --- linux-3.1-rc5.orig/drivers/bcma/driver_chipcommon_pmu.c 2011-09-04 15:45:10.000000000 -0700 +++ linux-3.1-rc5/drivers/bcma/driver_chipcommon_pmu.c 2011-09-11 16:44:25.595409713 -0700 @@ -83,6 +83,24 @@ } } +/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */ +void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable) +{ + struct bcma_bus *bus = cc->core->bus; + u32 val; + + val = bcma_cc_read32(cc, BCMA_CC_CHIPCTL); + if (enable) { + val |= BCMA_CHIPCTL_4331_EXTPA_EN; + if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11) + val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; + } else { + val &= ~BCMA_CHIPCTL_4331_EXTPA_EN; + val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; + } + bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val); +} + void bcma_pmu_workarounds(struct bcma_drv_cc *cc) { struct bcma_bus *bus = cc->core->bus; @@ -92,7 +110,7 @@ bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7); break; case 0x4331: - pr_err("Enabling Ext PA lines not implemented\n"); + /* BCM4331 workaround is SPROM-related, we put it in sprom.c */ break; case 43224: if (bus->chipinfo.rev == 0) { diff -ruN linux-3.1-rc5.orig/drivers/bcma/sprom.c linux-3.1-rc5/drivers/bcma/sprom.c --- linux-3.1-rc5.orig/drivers/bcma/sprom.c 2011-09-04 15:45:10.000000000 -0700 +++ linux-3.1-rc5/drivers/bcma/sprom.c 2011-09-11 16:44:25.595409713 -0700 @@ -152,6 +152,9 @@ if (!sprom) return -ENOMEM; + if (bus->chipinfo.id == 0x4331) + bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); + /* Most cards have SPROM moved by additional offset 0x30 (48 dwords). * According to brcm80211 this applies to cards with PCIe rev >= 6 * TODO: understand this condition and use it */ @@ -159,6 +162,9 @@ BCMA_CC_SPROM_PCIE6; bcma_sprom_read(bus, offset, sprom); + if (bus->chipinfo.id == 0x4331) + bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); + err = bcma_sprom_valid(sprom); if (err) goto out; diff -ruN linux-3.1-rc5.orig/drivers/net/wireless/b43/Kconfig linux-3.1-rc5/drivers/net/wireless/b43/Kconfig --- linux-3.1-rc5.orig/drivers/net/wireless/b43/Kconfig 2011-09-04 15:45:10.000000000 -0700 +++ linux-3.1-rc5/drivers/net/wireless/b43/Kconfig 2011-09-11 16:45:07.004360152 -0700 @@ -124,12 +124,12 @@ (802.11a support is optional, and currently disabled). config B43_PHY_HT - bool "Support for HT-PHY devices (BROKEN)" - depends on B43 && BROKEN + bool "Support for HT-PHY (high throughput) devices (EXPERIMENTAL)" + depends on B43 && EXPERIMENTAL ---help--- Support for the HT-PHY. - Say N, this is BROKEN and crashes driver. + Enables support for BCM4331 and possibly other chipsets with that PHY. config B43_PHY_LCN bool "Support for LCN-PHY devices (BROKEN)" diff -ruN linux-3.1-rc5.orig/drivers/net/wireless/b43/b43.h linux-3.1-rc5/drivers/net/wireless/b43/b43.h --- linux-3.1-rc5.orig/drivers/net/wireless/b43/b43.h 2011-09-04 15:45:10.000000000 -0700 +++ linux-3.1-rc5/drivers/net/wireless/b43/b43.h 2011-09-11 16:44:18.745583091 -0700 @@ -694,6 +694,12 @@ enum b43_firmware_file_type type; }; +enum b43_firmware_hdr_format { + B43_FW_HDR_598, + B43_FW_HDR_410, + B43_FW_HDR_351, +}; + /* Pointers to the firmware data and meta information about it. */ struct b43_firmware { /* Microcode */ @@ -710,6 +716,9 @@ /* Firmware patchlevel */ u16 patch; + /* Format of header used by firmware */ + enum b43_firmware_hdr_format hdr_format; + /* Set to true, if we are using an opensource firmware. * Use this to check for proprietary vs opensource. */ bool opensource; @@ -875,7 +884,7 @@ struct b43_leds leds; /* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */ - u8 pio_scratchspace[110] __attribute__((__aligned__(8))); + u8 pio_scratchspace[118] __attribute__((__aligned__(8))); u8 pio_tailspace[4] __attribute__((__aligned__(8))); }; diff -ruN linux-3.1-rc5.orig/drivers/net/wireless/b43/dma.c linux-3.1-rc5/drivers/net/wireless/b43/dma.c --- linux-3.1-rc5.orig/drivers/net/wireless/b43/dma.c 2011-09-04 15:45:10.000000000 -0700 +++ linux-3.1-rc5/drivers/net/wireless/b43/dma.c 2011-09-11 16:45:02.524473816 -0700 @@ -389,33 +389,34 @@ gfp_t flags = GFP_KERNEL; /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K - * alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing - * has shown that 4K is sufficient for the latter as long as the buffer - * does not cross an 8K boundary. - * - * For unknown reasons - possibly a hardware error - the BCM4311 rev - * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, - * which accounts for the GFP_DMA flag below. - * - * The flags here must match the flags in free_ringmemory below! + * alignment and 8K buffers for 64-bit DMA with 8K alignment. + * In practice we could use smaller buffers for the latter, but the + * alignment is really important because of the hardware bug. If bit + * 0x00001000 is used in DMA address, some hardware (like BCM4331) + * copies that bit into B43_DMA64_RXSTATUS and we get false values from + * B43_DMA64_RXSTATDPTR. Let's just use 8K buffers even if we don't use + * more than 256 slots for ring. */ - if (ring->type == B43_DMA_64BIT) - flags |= GFP_DMA; + u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ? + B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE; + ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev, - B43_DMA_RINGMEMSIZE, - &(ring->dmabase), flags); + ring_mem_size, &(ring->dmabase), + flags); if (!ring->descbase) { b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); return -ENOMEM; } - memset(ring->descbase, 0, B43_DMA_RINGMEMSIZE); + memset(ring->descbase, 0, ring_mem_size); return 0; } static void free_ringmemory(struct b43_dmaring *ring) { - dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE, + u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ? + B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE; + dma_free_coherent(ring->dev->dev->dma_dev, ring_mem_size, ring->descbase, ring->dmabase); } @@ -872,8 +873,17 @@ ring->current_slot = -1; } else { if (ring->index == 0) { - ring->rx_buffersize = B43_DMA0_RX_BUFFERSIZE; - ring->frameoffset = B43_DMA0_RX_FRAMEOFFSET; + switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: + ring->rx_buffersize = B43_DMA0_RX_FW598_BUFSIZE; + ring->frameoffset = B43_DMA0_RX_FW598_FO; + break; + case B43_FW_HDR_410: + case B43_FW_HDR_351: + ring->rx_buffersize = B43_DMA0_RX_FW351_BUFSIZE; + ring->frameoffset = B43_DMA0_RX_FW351_FO; + break; + } } else B43_WARN_ON(1); } diff -ruN linux-3.1-rc5.orig/drivers/net/wireless/b43/dma.h linux-3.1-rc5/drivers/net/wireless/b43/dma.h --- linux-3.1-rc5.orig/drivers/net/wireless/b43/dma.h 2011-09-04 15:45:10.000000000 -0700 +++ linux-3.1-rc5/drivers/net/wireless/b43/dma.h 2011-09-11 16:45:02.524473816 -0700 @@ -161,13 +161,17 @@ } __packed; /* Misc DMA constants */ -#define B43_DMA_RINGMEMSIZE PAGE_SIZE -#define B43_DMA0_RX_FRAMEOFFSET 30 +#define B43_DMA32_RINGMEMSIZE 4096 +#define B43_DMA64_RINGMEMSIZE 8192 +/* Offset of frame with actual data */ +#define B43_DMA0_RX_FW598_FO 38 +#define B43_DMA0_RX_FW351_FO 30 /* DMA engine tuning knobs */ #define B43_TXRING_SLOTS 256 #define B43_RXRING_SLOTS 64 -#define B43_DMA0_RX_BUFFERSIZE (B43_DMA0_RX_FRAMEOFFSET + IEEE80211_MAX_FRAME_LEN) +#define B43_DMA0_RX_FW598_BUFSIZE (B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN) +#define B43_DMA0_RX_FW351_BUFSIZE (B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN) /* Pointer poison */ #define B43_DMA_PTR_POISON ((void *)ERR_PTR(-ENOMEM)) diff -ruN linux-3.1-rc5.orig/drivers/net/wireless/b43/main.c linux-3.1-rc5/drivers/net/wireless/b43/main.c --- linux-3.1-rc5.orig/drivers/net/wireless/b43/main.c 2011-09-04 15:45:10.000000000 -0700 +++ linux-3.1-rc5/drivers/net/wireless/b43/main.c 2011-09-11 16:44:35.375162052 -0700 @@ -2510,6 +2510,12 @@ } dev->fw.rev = fwrev; dev->fw.patch = fwpatch; + if (dev->fw.rev >= 598) + dev->fw.hdr_format = B43_FW_HDR_598; + else if (dev->fw.rev >= 410) + dev->fw.hdr_format = B43_FW_HDR_410; + else + dev->fw.hdr_format = B43_FW_HDR_351; dev->fw.opensource = (fwdate == 0xFFFF); /* Default to use-all-queues. */ @@ -2557,7 +2563,7 @@ dev->fw.rev, dev->fw.patch); wiphy->hw_version = dev->dev->core_id; - if (b43_is_old_txhdr_format(dev)) { + if (dev->fw.hdr_format == B43_FW_HDR_351) { /* We're over the deadline, but we keep support for old fw * until it turns out to be in major conflict with something new. */ b43warn(dev->wl, "You are using an old firmware image. " @@ -2943,6 +2949,7 @@ case B43_PHYTYPE_G: case B43_PHYTYPE_N: case B43_PHYTYPE_LP: + case B43_PHYTYPE_HT: b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1); b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1); b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1); diff -ruN linux-3.1-rc5.orig/drivers/net/wireless/b43/phy_common.c linux-3.1-rc5/drivers/net/wireless/b43/phy_common.c --- linux-3.1-rc5.orig/drivers/net/wireless/b43/phy_common.c 2011-09-04 15:45:10.000000000 -0700 +++ linux-3.1-rc5/drivers/net/wireless/b43/phy_common.c 2011-09-11 16:44:37.435109868 -0700 @@ -448,6 +448,38 @@ channel_type == NL80211_CHAN_HT40PLUS); } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */ +void b43_phy_force_clock(struct b43_wldev *dev, bool force) +{ + u32 tmp; + + WARN_ON(dev->phy.type != B43_PHYTYPE_N && + dev->phy.type != B43_PHYTYPE_HT); + + switch (dev->dev->bus_type) { +#ifdef CONFIG_B43_BCMA + case B43_BUS_BCMA: + tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); + if (force) + tmp |= BCMA_IOCTL_FGC; + else + tmp &= ~BCMA_IOCTL_FGC; + bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); + break; +#endif +#ifdef CONFIG_B43_SSB + case B43_BUS_SSB: + tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); + if (force) + tmp |= SSB_TMSLOW_FGC; + else + tmp &= ~SSB_TMSLOW_FGC; + ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); + break; +#endif + } +} + /* http://bcm-v4.sipsolutions.net/802.11/PHY/Cordic */ struct b43_c32 b43_cordic(int theta) { diff -ruN linux-3.1-rc5.orig/drivers/net/wireless/b43/phy_common.h linux-3.1-rc5/drivers/net/wireless/b43/phy_common.h --- linux-3.1-rc5.orig/drivers/net/wireless/b43/phy_common.h 2011-09-04 15:45:10.000000000 -0700 +++ linux-3.1-rc5/drivers/net/wireless/b43/phy_common.h 2011-09-11 16:44:37.435109868 -0700 @@ -444,6 +444,8 @@ bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type); +void b43_phy_force_clock(struct b43_wldev *dev, bool force); + struct b43_c32 b43_cordic(int theta); #endif /* LINUX_B43_PHY_COMMON_H_ */ diff -ruN linux-3.1-rc5.orig/drivers/net/wireless/b43/phy_ht.c linux-3.1-rc5/drivers/net/wireless/b43/phy_ht.c --- linux-3.1-rc5.orig/drivers/net/wireless/b43/phy_ht.c 2011-09-04 15:45:10.000000000 -0700 +++ linux-3.1-rc5/drivers/net/wireless/b43/phy_ht.c 2011-09-11 16:59:36.266832596 -0700 @@ -152,6 +152,92 @@ } /************************************************** + * Various PHY ops + **************************************************/ + +static void b43_phy_ht_zero_extg(struct b43_wldev *dev) +{ + u8 i, j; + u16 base[] = { 0x40, 0x60, 0x80 }; + + for (i = 0; i < ARRAY_SIZE(base); i++) { + for (j = 0; j < 4; j++) + b43_phy_write(dev, B43_PHY_EXTG(base[i] + j), 0); + } + + for (i = 0; i < ARRAY_SIZE(base); i++) + b43_phy_write(dev, B43_PHY_EXTG(base[i] + 0xc), 0); +} + +/* Some unknown AFE (Analog Frondned) op */ +static void b43_phy_ht_afe_unk1(struct b43_wldev *dev) +{ + u8 i; + + const u16 ctl_regs[3][2] = { + { B43_PHY_HT_AFE_CTL1, B43_PHY_HT_AFE_CTL2 }, + { B43_PHY_HT_AFE_CTL3, B43_PHY_HT_AFE_CTL4 }, + { B43_PHY_HT_AFE_CTL5, B43_PHY_HT_AFE_CTL6}, + }; + + for (i = 0; i < 3; i++) { + /* TODO: verify masks&sets */ + b43_phy_set(dev, ctl_regs[i][1], 0x4); + b43_phy_set(dev, ctl_regs[i][0], 0x4); + b43_phy_mask(dev, ctl_regs[i][1], ~0x1); + b43_phy_set(dev, ctl_regs[i][0], 0x1); + b43_httab_write(dev, B43_HTTAB16(8, 5 + (i * 0x10)), 0); + b43_phy_mask(dev, ctl_regs[i][0], ~0x4); + } +} + +static void b43_phy_ht_force_rf_sequence(struct b43_wldev *dev, u16 rf_seq) +{ + u8 i; + + u16 save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE); + b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, 0x3); + + b43_phy_set(dev, B43_PHY_HT_RF_SEQ_TRIG, rf_seq); + for (i = 0; i < 200; i++) { + if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & rf_seq)) { + i = 0; + break; + } + msleep(1); + } + if (i) + b43err(dev->wl, "Forcing RF sequence timeout\n"); + + b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode); +} + +static void b43_phy_ht_read_clip_detection(struct b43_wldev *dev, u16 *clip_st) +{ + clip_st[0] = b43_phy_read(dev, B43_PHY_HT_C1_CLIP1THRES); + clip_st[1] = b43_phy_read(dev, B43_PHY_HT_C2_CLIP1THRES); + clip_st[2] = b43_phy_read(dev, B43_PHY_HT_C3_CLIP1THRES); +} + +static void b43_phy_ht_bphy_init(struct b43_wldev *dev) +{ + unsigned int i; + u16 val; + + val = 0x1E1F; + for (i = 0; i < 16; i++) { + b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val); + val -= 0x202; + } + val = 0x3E3F; + for (i = 0; i < 16; i++) { + b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val); + val -= 0x202; + } + b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); +} + +/************************************************** * Channel switching ops. **************************************************/ @@ -255,8 +341,125 @@ static int b43_phy_ht_op_init(struct b43_wldev *dev) { + u16 tmp; + u16 clip_state[3]; + b43_phy_ht_tables_init(dev); + b43_phy_mask(dev, 0x0be, ~0x2); + b43_phy_set(dev, 0x23f, 0x7ff); + b43_phy_set(dev, 0x240, 0x7ff); + b43_phy_set(dev, 0x241, 0x7ff); + + b43_phy_ht_zero_extg(dev); + + b43_phy_mask(dev, B43_PHY_EXTG(0), ~0x3); + + b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0); + b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0); + b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0); + + b43_phy_write(dev, B43_PHY_EXTG(0x103), 0x20); + b43_phy_write(dev, B43_PHY_EXTG(0x101), 0x20); + b43_phy_write(dev, 0x20d, 0xb8); + b43_phy_write(dev, B43_PHY_EXTG(0x14f), 0xc8); + b43_phy_write(dev, 0x70, 0x50); + b43_phy_write(dev, 0x1ff, 0x30); + + if (0) /* TODO: condition */ + ; /* TODO: PHY op on reg 0x217 */ + + b43_phy_read(dev, 0xb0); /* TODO: what for? */ + b43_phy_set(dev, 0xb0, 0x1); + + b43_phy_set(dev, 0xb1, 0x91); + b43_phy_write(dev, 0x32f, 0x0003); + b43_phy_write(dev, 0x077, 0x0010); + b43_phy_write(dev, 0x0b4, 0x0258); + b43_phy_mask(dev, 0x17e, ~0x4000); + + b43_phy_write(dev, 0x0b9, 0x0072); + + b43_httab_write_few(dev, B43_HTTAB16(7, 0x14e), 2, 0x010f, 0x010f); + b43_httab_write_few(dev, B43_HTTAB16(7, 0x15e), 2, 0x010f, 0x010f); + b43_httab_write_few(dev, B43_HTTAB16(7, 0x16e), 2, 0x010f, 0x010f); + + b43_phy_ht_afe_unk1(dev); + + b43_httab_write_few(dev, B43_HTTAB16(7, 0x130), 9, 0x777, 0x111, 0x111, + 0x777, 0x111, 0x111, 0x777, 0x111, 0x111); + + b43_httab_write(dev, B43_HTTAB16(7, 0x120), 0x0777); + b43_httab_write(dev, B43_HTTAB16(7, 0x124), 0x0777); + + b43_httab_write(dev, B43_HTTAB16(8, 0x00), 0x02); + b43_httab_write(dev, B43_HTTAB16(8, 0x10), 0x02); + b43_httab_write(dev, B43_HTTAB16(8, 0x20), 0x02); + + b43_httab_write_few(dev, B43_HTTAB16(8, 0x08), 4, + 0x8e, 0x96, 0x96, 0x96); + b43_httab_write_few(dev, B43_HTTAB16(8, 0x18), 4, + 0x8f, 0x9f, 0x9f, 0x9f); + b43_httab_write_few(dev, B43_HTTAB16(8, 0x28), 4, + 0x8f, 0x9f, 0x9f, 0x9f); + + b43_httab_write_few(dev, B43_HTTAB16(8, 0x0c), 4, 0x2, 0x2, 0x2, 0x2); + b43_httab_write_few(dev, B43_HTTAB16(8, 0x1c), 4, 0x2, 0x2, 0x2, 0x2); + b43_httab_write_few(dev, B43_HTTAB16(8, 0x2c), 4, 0x2, 0x2, 0x2, 0x2); + + b43_phy_maskset(dev, 0x0280, 0xff00, 0x3e); + b43_phy_maskset(dev, 0x0283, 0xff00, 0x3e); + b43_phy_maskset(dev, B43_PHY_OFDM(0x0141), 0xff00, 0x46); + b43_phy_maskset(dev, 0x0283, 0xff00, 0x40); + + b43_httab_write_few(dev, B43_HTTAB16(00, 0x8), 4, + 0x09, 0x0e, 0x13, 0x18); + b43_httab_write_few(dev, B43_HTTAB16(01, 0x8), 4, + 0x09, 0x0e, 0x13, 0x18); + /* TODO: Did wl mean 2 instead of 40? */ + b43_httab_write_few(dev, B43_HTTAB16(40, 0x8), 4, + 0x09, 0x0e, 0x13, 0x18); + + b43_phy_maskset(dev, B43_PHY_OFDM(0x24), 0x3f, 0xd); + b43_phy_maskset(dev, B43_PHY_OFDM(0x64), 0x3f, 0xd); + b43_phy_maskset(dev, B43_PHY_OFDM(0xa4), 0x3f, 0xd); + + b43_phy_set(dev, B43_PHY_EXTG(0x060), 0x1); + b43_phy_set(dev, B43_PHY_EXTG(0x064), 0x1); + b43_phy_set(dev, B43_PHY_EXTG(0x080), 0x1); + b43_phy_set(dev, B43_PHY_EXTG(0x084), 0x1); + + /* Copy some tables entries */ + tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x144)); + b43_httab_write(dev, B43_HTTAB16(7, 0x14a), tmp); + tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x154)); + b43_httab_write(dev, B43_HTTAB16(7, 0x15a), tmp); + tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x164)); + b43_httab_write(dev, B43_HTTAB16(7, 0x16a), tmp); + + /* Reset CCA */ + b43_phy_force_clock(dev, true); + tmp = b43_phy_read(dev, B43_PHY_HT_BBCFG); + b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp | B43_PHY_HT_BBCFG_RSTCCA); + b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp & ~B43_PHY_HT_BBCFG_RSTCCA); + b43_phy_force_clock(dev, false); + + b43_mac_phy_clock_set(dev, true); + + b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RX2TX); + b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX); + + /* TODO: PHY op on reg 0xb0 */ + + /* TODO: Should we restore it? Or store it in global PHY info? */ + b43_phy_ht_read_clip_detection(dev, clip_state); + + if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) + b43_phy_ht_bphy_init(dev); + + b43_httab_write_bulk(dev, B43_HTTAB32(0x1a, 0xc0), + B43_HTTAB_1A_C0_LATE_SIZE, b43_httab_0x1a_0xc0_late); + return 0; } diff -ruN linux-3.1-rc5.orig/drivers/net/wireless/b43/phy_ht.h linux-3.1-rc5/drivers/net/wireless/b43/phy_ht.h --- linux-3.1-rc5.orig/drivers/net/wireless/b43/phy_ht.h 2011-09-04 15:45:10.000000000 -0700 +++ linux-3.1-rc5/drivers/net/wireless/b43/phy_ht.h 2011-09-11 16:59:36.266832596 -0700 @@ -4,7 +4,11 @@ #include "phy_common.h" +#define B43_PHY_HT_BBCFG 0x001 /* BB config */ +#define B43_PHY_HT_BBCFG_RSTCCA 0x4000 /* Reset CCA */ +#define B43_PHY_HT_BBCFG_RSTRX 0x8000 /* Reset RX */ #define B43_PHY_HT_BANDCTL 0x009 /* Band control */ +#define B43_PHY_HT_BANDCTL_5GHZ 0x0001 /* Use the 5GHz band */ #define B43_PHY_HT_TABLE_ADDR 0x072 /* Table address */ #define B43_PHY_HT_TABLE_DATALO 0x073 /* Table data low */ #define B43_PHY_HT_TABLE_DATAHI 0x074 /* Table data high */ @@ -15,6 +19,21 @@ #define B43_PHY_HT_BW5 0x1D2 #define B43_PHY_HT_BW6 0x1D3 +#define B43_PHY_HT_C1_CLIP1THRES B43_PHY_OFDM(0x00E) +#define B43_PHY_HT_C2_CLIP1THRES B43_PHY_OFDM(0x04E) +#define B43_PHY_HT_C3_CLIP1THRES B43_PHY_OFDM(0x08E) + +#define B43_PHY_HT_RF_SEQ_MODE B43_PHY_EXTG(0x000) +#define B43_PHY_HT_RF_SEQ_TRIG B43_PHY_EXTG(0x003) +#define B43_PHY_HT_RF_SEQ_TRIG_RX2TX 0x0001 /* RX2TX */ +#define B43_PHY_HT_RF_SEQ_TRIG_TX2RX 0x0002 /* TX2RX */ +#define B43_PHY_HT_RF_SEQ_TRIG_UPGH 0x0004 /* Update gain H */ +#define B43_PHY_HT_RF_SEQ_TRIG_UPGL 0x0008 /* Update gain L */ +#define B43_PHY_HT_RF_SEQ_TRIG_UPGU 0x0010 /* Update gain U */ +#define B43_PHY_HT_RF_SEQ_TRIG_RST2RX 0x0020 /* Reset to RX */ +#define B43_PHY_HT_RF_SEQ_STATUS B43_PHY_EXTG(0x004) +/* Values for the status are the same as for the trigger */ + #define B43_PHY_HT_RF_CTL1 B43_PHY_EXTG(0x010) #define B43_PHY_HT_AFE_CTL1 B43_PHY_EXTG(0x110) diff -ruN linux-3.1-rc5.orig/drivers/net/wireless/b43/phy_n.c linux-3.1-rc5/drivers/net/wireless/b43/phy_n.c --- linux-3.1-rc5.orig/drivers/net/wireless/b43/phy_n.c 2011-09-04 15:45:10.000000000 -0700 +++ linux-3.1-rc5/drivers/net/wireless/b43/phy_n.c 2011-09-11 16:44:37.435109868 -0700 @@ -600,49 +600,17 @@ } } -/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */ -static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force) -{ - u32 tmp; - - if (dev->phy.type != B43_PHYTYPE_N) - return; - - switch (dev->dev->bus_type) { -#ifdef CONFIG_B43_BCMA - case B43_BUS_BCMA: - tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); - if (force) - tmp |= BCMA_IOCTL_FGC; - else - tmp &= ~BCMA_IOCTL_FGC; - bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); - break; -#endif -#ifdef CONFIG_B43_SSB - case B43_BUS_SSB: - tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); - if (force) - tmp |= SSB_TMSLOW_FGC; - else - tmp &= ~SSB_TMSLOW_FGC; - ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); - break; -#endif - } -} - /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */ static void b43_nphy_reset_cca(struct b43_wldev *dev) { u16 bbcfg; - b43_nphy_bmac_clock_fgc(dev, 1); + b43_phy_force_clock(dev, 1); bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG); b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA); udelay(1); b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA); - b43_nphy_bmac_clock_fgc(dev, 0); + b43_phy_force_clock(dev, 0); b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); } @@ -3715,11 +3683,11 @@ b43_nphy_workarounds(dev); /* Reset CCA, in init code it differs a little from standard way */ - b43_nphy_bmac_clock_fgc(dev, 1); + b43_phy_force_clock(dev, 1); tmp = b43_phy_read(dev, B43_NPHY_BBCFG); b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA); b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA); - b43_nphy_bmac_clock_fgc(dev, 0); + b43_phy_force_clock(dev, 0); b43_mac_phy_clock_set(dev, true); diff -ruN linux-3.1-rc5.orig/drivers/net/wireless/b43/pio.c linux-3.1-rc5/drivers/net/wireless/b43/pio.c --- linux-3.1-rc5.orig/drivers/net/wireless/b43/pio.c 2011-09-04 15:45:10.000000000 -0700 +++ linux-3.1-rc5/drivers/net/wireless/b43/pio.c 2011-09-11 16:44:23.725457051 -0700 @@ -676,7 +676,15 @@ goto rx_error; } - macstat = le32_to_cpu(rxhdr->mac_status); + switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: + macstat = le32_to_cpu(rxhdr->format_598.mac_status); + break; + case B43_FW_HDR_410: + case B43_FW_HDR_351: + macstat = le32_to_cpu(rxhdr->format_351.mac_status); + break; + } if (macstat & B43_RX_MAC_FCSERR) { if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) { /* Drop frames with failed FCS. */ diff -ruN linux-3.1-rc5.orig/drivers/net/wireless/b43/tables_phy_ht.c linux-3.1-rc5/drivers/net/wireless/b43/tables_phy_ht.c --- linux-3.1-rc5.orig/drivers/net/wireless/b43/tables_phy_ht.c 2011-09-04 15:45:10.000000000 -0700 +++ linux-3.1-rc5/drivers/net/wireless/b43/tables_phy_ht.c 2011-09-11 16:44:48.854820469 -0700 @@ -574,6 +574,42 @@ 0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c, }; +/* Some late-init table */ +const u32 b43_httab_0x1a_0xc0_late[] = { + 0x10f90040, 0x10e10040, 0x10e1003c, 0x10c9003d, + 0x10b9003c, 0x10a9003d, 0x10a1003c, 0x1099003b, + 0x1091003b, 0x1089003a, 0x1081003a, 0x10790039, + 0x10710039, 0x1069003a, 0x1061003b, 0x1059003d, + 0x1051003f, 0x10490042, 0x1049003e, 0x1049003b, + 0x1041003e, 0x1041003b, 0x1039003e, 0x1039003b, + 0x10390038, 0x10390035, 0x1031003a, 0x10310036, + 0x10310033, 0x1029003a, 0x10290037, 0x10290034, + 0x10290031, 0x10210039, 0x10210036, 0x10210033, + 0x10210030, 0x1019003c, 0x10190039, 0x10190036, + 0x10190033, 0x10190030, 0x1019002d, 0x1019002b, + 0x10190028, 0x1011003a, 0x10110036, 0x10110033, + 0x10110030, 0x1011002e, 0x1011002b, 0x10110029, + 0x10110027, 0x10110024, 0x10110022, 0x10110020, + 0x1011001f, 0x1011001d, 0x1009003a, 0x10090037, + 0x10090034, 0x10090031, 0x1009002e, 0x1009002c, + 0x10090029, 0x10090027, 0x10090025, 0x10090023, + 0x10090021, 0x1009001f, 0x1009001d, 0x1009001b, + 0x1009001a, 0x10090018, 0x10090017, 0x10090016, + 0x10090015, 0x10090013, 0x10090012, 0x10090011, + 0x10090010, 0x1009000f, 0x1009000f, 0x1009000e, + 0x1009000d, 0x1009000c, 0x1009000c, 0x1009000b, + 0x1009000a, 0x1009000a, 0x10090009, 0x10090009, + 0x10090008, 0x10090008, 0x10090007, 0x10090007, + 0x10090007, 0x10090006, 0x10090006, 0x10090005, + 0x10090005, 0x10090005, 0x10090005, 0x10090004, + 0x10090004, 0x10090004, 0x10090004, 0x10090003, + 0x10090003, 0x10090003, 0x10090003, 0x10090003, + 0x10090003, 0x10090002, 0x10090002, 0x10090002, + 0x10090002, 0x10090002, 0x10090002, 0x10090002, + 0x10090002, 0x10090002, 0x10090001, 0x10090001, + 0x10090001, 0x10090001, 0x10090001, 0x10090001, +}; + /************************************************** * R/W ops. **************************************************/ @@ -674,6 +710,51 @@ return; } +void b43_httab_write_few(struct b43_wldev *dev, u32 offset, size_t num, ...) +{ + va_list args; + u32 type, value; + unsigned int i; + + type = offset & B43_HTTAB_TYPEMASK; + offset &= 0xFFFF; + + va_start(args, num); + switch (type) { + case B43_HTTAB_8BIT: + b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); + for (i = 0; i < num; i++) { + value = va_arg(args, int); + B43_WARN_ON(value & ~0xFF); + b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value); + } + break; + case B43_HTTAB_16BIT: + b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); + for (i = 0; i < num; i++) { + value = va_arg(args, int); + B43_WARN_ON(value & ~0xFFFF); + b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value); + } + break; + case B43_HTTAB_32BIT: + b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); + for (i = 0; i < num; i++) { + value = va_arg(args, int); + b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, + value >> 16); + b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, + value & 0xFFFF); + } + break; + default: + B43_WARN_ON(1); + } + va_end(args); + + return; +} + void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset, unsigned int nr_elements, const void *_data) { @@ -723,6 +804,9 @@ } while (0) void b43_phy_ht_tables_init(struct b43_wldev *dev) { + BUILD_BUG_ON(ARRAY_SIZE(b43_httab_0x1a_0xc0_late) != + B43_HTTAB_1A_C0_LATE_SIZE); + httab_upload(dev, B43_HTTAB16(0x12, 0), b43_httab_0x12); httab_upload(dev, B43_HTTAB16(0x27, 0), b43_httab_0x27); httab_upload(dev, B43_HTTAB16(0x26, 0), b43_httab_0x26); diff -ruN linux-3.1-rc5.orig/drivers/net/wireless/b43/tables_phy_ht.h linux-3.1-rc5/drivers/net/wireless/b43/tables_phy_ht.h --- linux-3.1-rc5.orig/drivers/net/wireless/b43/tables_phy_ht.h 2011-09-04 15:45:10.000000000 -0700 +++ linux-3.1-rc5/drivers/net/wireless/b43/tables_phy_ht.h 2011-09-11 16:44:48.854820469 -0700 @@ -14,9 +14,13 @@ void b43_httab_read_bulk(struct b43_wldev *dev, u32 offset, unsigned int nr_elements, void *_data); void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value); +void b43_httab_write_few(struct b43_wldev *dev, u32 offset, size_t num, ...); void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset, unsigned int nr_elements, const void *_data); void b43_phy_ht_tables_init(struct b43_wldev *dev); +#define B43_HTTAB_1A_C0_LATE_SIZE 128 +extern const u32 b43_httab_0x1a_0xc0_late[]; + #endif /* B43_TABLES_PHY_HT_H_ */ diff -ruN linux-3.1-rc5.orig/drivers/net/wireless/b43/xmit.c linux-3.1-rc5/drivers/net/wireless/b43/xmit.c --- linux-3.1-rc5.orig/drivers/net/wireless/b43/xmit.c 2011-09-04 15:45:10.000000000 -0700 +++ linux-3.1-rc5/drivers/net/wireless/b43/xmit.c 2011-09-11 16:44:35.375162052 -0700 @@ -337,12 +337,19 @@ memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); } } - if (b43_is_old_txhdr_format(dev)) { - b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp), + switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: + b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_598.plcp), plcp_fragment_len, rate); - } else { - b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->new_format.plcp), + break; + case B43_FW_HDR_351: + b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_351.plcp), + plcp_fragment_len, rate); + break; + case B43_FW_HDR_410: + b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_410.plcp), plcp_fragment_len, rate); + break; } b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb), plcp_fragment_len, rate_fb); @@ -415,10 +422,10 @@ if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) { unsigned int len; - struct ieee80211_hdr *hdr; + struct ieee80211_hdr *uninitialized_var(hdr); int rts_rate, rts_rate_fb; int rts_rate_ofdm, rts_rate_fb_ofdm; - struct b43_plcp_hdr6 *plcp; + struct b43_plcp_hdr6 *uninitialized_var(plcp); struct ieee80211_rate *rts_cts_rate; rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info); @@ -429,14 +436,21 @@ rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - struct ieee80211_cts *cts; + struct ieee80211_cts *uninitialized_var(cts); - if (b43_is_old_txhdr_format(dev)) { + switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: cts = (struct ieee80211_cts *) - (txhdr->old_format.rts_frame); - } else { + (txhdr->format_598.rts_frame); + break; + case B43_FW_HDR_351: cts = (struct ieee80211_cts *) - (txhdr->new_format.rts_frame); + (txhdr->format_351.rts_frame); + break; + case B43_FW_HDR_410: + cts = (struct ieee80211_cts *) + (txhdr->format_410.rts_frame); + break; } ieee80211_ctstoself_get(dev->wl->hw, info->control.vif, fragment_data, fragment_len, @@ -444,14 +458,21 @@ mac_ctl |= B43_TXH_MAC_SENDCTS; len = sizeof(struct ieee80211_cts); } else { - struct ieee80211_rts *rts; + struct ieee80211_rts *uninitialized_var(rts); - if (b43_is_old_txhdr_format(dev)) { + switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: rts = (struct ieee80211_rts *) - (txhdr->old_format.rts_frame); - } else { + (txhdr->format_598.rts_frame); + break; + case B43_FW_HDR_351: + rts = (struct ieee80211_rts *) + (txhdr->format_351.rts_frame); + break; + case B43_FW_HDR_410: rts = (struct ieee80211_rts *) - (txhdr->new_format.rts_frame); + (txhdr->format_410.rts_frame); + break; } ieee80211_rts_get(dev->wl->hw, info->control.vif, fragment_data, fragment_len, @@ -462,22 +483,36 @@ len += FCS_LEN; /* Generate the PLCP headers for the RTS/CTS frame */ - if (b43_is_old_txhdr_format(dev)) - plcp = &txhdr->old_format.rts_plcp; - else - plcp = &txhdr->new_format.rts_plcp; + switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: + plcp = &txhdr->format_598.rts_plcp; + break; + case B43_FW_HDR_351: + plcp = &txhdr->format_351.rts_plcp; + break; + case B43_FW_HDR_410: + plcp = &txhdr->format_410.rts_plcp; + break; + } b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp, len, rts_rate); plcp = &txhdr->rts_plcp_fb; b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp, len, rts_rate_fb); - if (b43_is_old_txhdr_format(dev)) { + switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: hdr = (struct ieee80211_hdr *) - (&txhdr->old_format.rts_frame); - } else { + (&txhdr->format_598.rts_frame); + break; + case B43_FW_HDR_351: + hdr = (struct ieee80211_hdr *) + (&txhdr->format_351.rts_frame); + break; + case B43_FW_HDR_410: hdr = (struct ieee80211_hdr *) - (&txhdr->new_format.rts_frame); + (&txhdr->format_410.rts_frame); + break; } txhdr->rts_dur_fb = hdr->duration_id; @@ -505,10 +540,17 @@ } /* Magic cookie */ - if (b43_is_old_txhdr_format(dev)) - txhdr->old_format.cookie = cpu_to_le16(cookie); - else - txhdr->new_format.cookie = cpu_to_le16(cookie); + switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: + txhdr->format_598.cookie = cpu_to_le16(cookie); + break; + case B43_FW_HDR_351: + txhdr->format_351.cookie = cpu_to_le16(cookie); + break; + case B43_FW_HDR_410: + txhdr->format_410.cookie = cpu_to_le16(cookie); + break; + } if (phy->type == B43_PHYTYPE_N) { txhdr->phy_ctl1 = @@ -611,8 +653,9 @@ struct ieee80211_hdr *wlhdr; const struct b43_rxhdr_fw4 *rxhdr = _rxhdr; __le16 fctl; - u16 phystat0, phystat3, chanstat, mactime; - u32 macstat; + u16 phystat0, phystat3; + u16 uninitialized_var(chanstat), uninitialized_var(mactime); + u32 uninitialized_var(macstat); u16 chanid; u16 phytype; int padding; @@ -622,9 +665,19 @@ /* Get metadata about the frame from the header. */ phystat0 = le16_to_cpu(rxhdr->phy_status0); phystat3 = le16_to_cpu(rxhdr->phy_status3); - macstat = le32_to_cpu(rxhdr->mac_status); - mactime = le16_to_cpu(rxhdr->mac_time); - chanstat = le16_to_cpu(rxhdr->channel); + switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: + macstat = le32_to_cpu(rxhdr->format_598.mac_status); + mactime = le16_to_cpu(rxhdr->format_598.mac_time); + chanstat = le16_to_cpu(rxhdr->format_598.channel); + break; + case B43_FW_HDR_410: + case B43_FW_HDR_351: + macstat = le32_to_cpu(rxhdr->format_351.mac_status); + mactime = le16_to_cpu(rxhdr->format_351.mac_time); + chanstat = le16_to_cpu(rxhdr->format_351.channel); + break; + } phytype = chanstat & B43_RX_CHAN_PHYTYPE; if (unlikely(macstat & B43_RX_MAC_FCSERR)) { @@ -744,6 +797,7 @@ break; case B43_PHYTYPE_N: case B43_PHYTYPE_LP: + case B43_PHYTYPE_HT: /* chanid is the SHM channel cookie. Which is the plain * channel number in b43. */ if (chanstat & B43_RX_CHAN_5GHZ) { diff -ruN linux-3.1-rc5.orig/drivers/net/wireless/b43/xmit.h linux-3.1-rc5/drivers/net/wireless/b43/xmit.h --- linux-3.1-rc5.orig/drivers/net/wireless/b43/xmit.h 2011-09-04 15:45:10.000000000 -0700 +++ linux-3.1-rc5/drivers/net/wireless/b43/xmit.h 2011-09-11 16:44:23.725457051 -0700 @@ -46,7 +46,24 @@ __le32 timeout; /* Timeout */ union { - /* The new r410 format. */ + /* Tested with 598.314, 644.1001 and 666.2 */ + struct { + __le16 mimo_antenna; /* MIMO antenna select */ + __le16 preload_size; /* Preload size */ + PAD_BYTES(2); + __le16 cookie; /* TX frame cookie */ + __le16 tx_status; /* TX status */ + __le16 max_n_mpdus; + __le16 max_a_bytes_mrt; + __le16 max_a_bytes_fbr; + __le16 min_m_bytes; + struct b43_plcp_hdr6 rts_plcp; /* RTS PLCP header */ + __u8 rts_frame[16]; /* The RTS frame (if used) */ + PAD_BYTES(2); + struct b43_plcp_hdr6 plcp; /* Main PLCP header */ + } format_598 __packed; + + /* Tested with 410.2160, 478.104 and 508.* */ struct { __le16 mimo_antenna; /* MIMO antenna select */ __le16 preload_size; /* Preload size */ @@ -57,9 +74,9 @@ __u8 rts_frame[16]; /* The RTS frame (if used) */ PAD_BYTES(2); struct b43_plcp_hdr6 plcp; /* Main PLCP header */ - } new_format __packed; + } format_410 __packed; - /* The old r351 format. */ + /* Tested with 351.126 */ struct { PAD_BYTES(2); __le16 cookie; /* TX frame cookie */ @@ -68,7 +85,7 @@ __u8 rts_frame[16]; /* The RTS frame (if used) */ PAD_BYTES(2); struct b43_plcp_hdr6 plcp; /* Main PLCP header */ - } old_format __packed; + } format_351 __packed; } __packed; } __packed; @@ -166,19 +183,18 @@ #define B43_TXH_PHY1_MODUL_QAM256 0x2000 /* QAM256 */ -/* r351 firmware compatibility stuff. */ -static inline -bool b43_is_old_txhdr_format(struct b43_wldev *dev) -{ - return (dev->fw.rev <= 351); -} - static inline size_t b43_txhdr_size(struct b43_wldev *dev) { - if (b43_is_old_txhdr_format(dev)) + switch (dev->fw.hdr_format) { + case B43_FW_HDR_598: + return 112 + sizeof(struct b43_plcp_hdr6); + case B43_FW_HDR_410: + return 104 + sizeof(struct b43_plcp_hdr6); + case B43_FW_HDR_351: return 100 + sizeof(struct b43_plcp_hdr6); - return 104 + sizeof(struct b43_plcp_hdr6); + } + return 0; } @@ -234,9 +250,23 @@ } __packed; __le16 phy_status2; /* PHY RX Status 2 */ __le16 phy_status3; /* PHY RX Status 3 */ - __le32 mac_status; /* MAC RX status */ - __le16 mac_time; - __le16 channel; + union { + /* Tested with 598.314, 644.1001 and 666.2 */ + struct { + __le16 phy_status4; /* PHY RX Status 4 */ + __le16 phy_status5; /* PHY RX Status 5 */ + __le32 mac_status; /* MAC RX status */ + __le16 mac_time; + __le16 channel; + } format_598 __packed; + + /* Tested with 351.126, 410.2160, 478.104 and 508.* */ + struct { + __le32 mac_status; /* MAC RX status */ + __le16 mac_time; + __le16 channel; + } format_351 __packed; + } __packed; } __packed; /* PHY RX Status 0 */ diff -ruN linux-3.1-rc5.orig/include/linux/bcma/bcma_driver_chipcommon.h linux-3.1-rc5/include/linux/bcma/bcma_driver_chipcommon.h --- linux-3.1-rc5.orig/include/linux/bcma/bcma_driver_chipcommon.h 2011-09-04 15:45:10.000000000 -0700 +++ linux-3.1-rc5/include/linux/bcma/bcma_driver_chipcommon.h 2011-09-11 16:44:25.595409713 -0700 @@ -239,6 +239,22 @@ #define BCMA_CC_SPROM 0x0800 /* SPROM beginning */ #define BCMA_CC_SPROM_PCIE6 0x0830 /* SPROM beginning on PCIe rev >= 6 */ +/* BCM4331 ChipControl numbers. */ +#define BCMA_CHIPCTL_4331_BT_COEXIST BIT(0) /* 0 disable */ +#define BCMA_CHIPCTL_4331_SECI BIT(1) /* 0 SECI is disabled (JATG functional) */ +#define BCMA_CHIPCTL_4331_EXT_LNA BIT(2) /* 0 disable */ +#define BCMA_CHIPCTL_4331_SPROM_GPIO13_15 BIT(3) /* sprom/gpio13-15 mux */ +#define BCMA_CHIPCTL_4331_EXTPA_EN BIT(4) /* 0 ext pa disable, 1 ext pa enabled */ +#define BCMA_CHIPCTL_4331_GPIOCLK_ON_SPROMCS BIT(5) /* set drive out GPIO_CLK on sprom_cs pin */ +#define BCMA_CHIPCTL_4331_PCIE_MDIO_ON_SPROMCS BIT(6) /* use sprom_cs pin as PCIE mdio interface */ +#define BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5 BIT(7) /* aband extpa will be at gpio2/5 and sprom_dout */ +#define BCMA_CHIPCTL_4331_OVR_PIPEAUXCLKEN BIT(8) /* override core control on pipe_AuxClkEnable */ +#define BCMA_CHIPCTL_4331_OVR_PIPEAUXPWRDOWN BIT(9) /* override core control on pipe_AuxPowerDown */ +#define BCMA_CHIPCTL_4331_PCIE_AUXCLKEN BIT(10) /* pcie_auxclkenable */ +#define BCMA_CHIPCTL_4331_PCIE_PIPE_PLLDOWN BIT(11) /* pcie_pipe_pllpowerdown */ +#define BCMA_CHIPCTL_4331_BT_SHD0_ON_GPIO4 BIT(16) /* enable bt_shd0 at gpio4 */ +#define BCMA_CHIPCTL_4331_BT_SHD1_ON_GPIO5 BIT(17) /* enable bt_shd1 at gpio5 */ + /* Data for the PMU, if available. * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) */ @@ -275,6 +291,8 @@ extern void bcma_chipco_suspend(struct bcma_drv_cc *cc); extern void bcma_chipco_resume(struct bcma_drv_cc *cc); +void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable); + extern void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks);
signature.asc
Description: OpenPGP digital signature
_______________________________________________ b43-dev mailing list b43-dev@lists.infradead.org http://lists.infradead.org/mailman/listinfo/b43-dev