Hi Rafal, hi list, had a look at it myself, the culprit is the missing setting operations in case CONFIG_B43_SSB is used. The attached patch fixes the problem in my case, chip_id 0x4322, bus=SSB, channel=6/13. Regards, Stefan
--- phy_n.c_orig 2012-12-17 03:38:22.338451489 +0100 +++ phy_n.c 2012-12-17 04:28:02.308743464 +0100 @@ -4518,10 +4518,20 @@ b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6); } +/* copied verbatim from ssb/driver_chipcommon_pmu.c */ +static void ssb_chipco_pll_write(struct ssb_chipcommon *cc, + u32 offset, u32 value) +{ + chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, offset); + chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, value); +} + + /* http://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */ static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid) { struct bcma_drv_cc __maybe_unused *cc; + struct ssb_chipcommon __maybe_unused *ssb_cc; u32 __maybe_unused pmu_ctl; switch (dev->dev->bus_type) { @@ -4583,6 +4593,28 @@ #ifdef CONFIG_B43_SSB case B43_BUS_SSB: /* FIXME */ + b43info(dev->wl, "Spur avoid: bus type=%i (SSB, experimental)" + "chip_id=%i/0x%x avoid=%i\n", dev->dev->bus_type, + dev->dev->chip_id, dev->dev->chip_id, avoid); + ssb_cc = &dev->dev->sdev->bus->chipco; + if (dev->dev->chip_id == 0x4322 || + dev->dev->chip_id == 0x4340 || + dev->dev->chip_id == 0x4341) { + ssb_chipco_pll_write(ssb_cc, 0x0, 0x11100070); + ssb_chipco_pll_write(ssb_cc, 0x1, 0x1014140a); + ssb_chipco_pll_write(ssb_cc, 0x5, 0x88888854); + if (avoid) + ssb_chipco_pll_write(ssb_cc, 0x2, 0x05201828); + else + ssb_chipco_pll_write(ssb_cc, 0x2, 0x05001828); + /* guessed by comparing {bcma,ssb}_driver_chipcommon.h */ + #define SSB_CHIPCO_PMU_CTL_PLL_UPD 0x400; + pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD; + } else { + b43err(dev->wl, "unsupported!\n"); + return; + } + chipco_set32(ssb_cc, SSB_CHIPCO_PMU_CTL, pmu_ctl); break; #endif } @@ -4635,6 +4667,11 @@ b43_nphy_tx_lp_fbw(dev); + b43info(dev->wl, "phy.rev=%i phy.n->spavoid=%i(%s) ch=%i\n", + dev->phy.rev, dev->phy.n->spur_avoid, + (dev->phy.n->spur_avoid == B43_SPUR_AVOID_AUTO)?"auto":"?", + ch); + if (dev->phy.rev >= 3 && dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) { bool avoid = false;