2010/8/22 Rafał Miłecki <zajec5@xxxxxxxxx>: > Signed-off-by: Rafał Miłecki <zajec5@xxxxxxxxx> > --- > drivers/net/wireless/b43/b43.h | 1 + > drivers/net/wireless/b43/phy_common.c | 150 ++++++++++++++++++++++++++++++++- > drivers/net/wireless/b43/phy_common.h | 7 ++ > 3 files changed, 157 insertions(+), 1 deletions(-) > > diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h > index 8674a99..73376ff 100644 > --- a/drivers/net/wireless/b43/b43.h > +++ b/drivers/net/wireless/b43/b43.h > @@ -57,6 +57,7 @@ > #define B43_MMIO_TSF_CFP_REP 0x188 > #define B43_MMIO_TSF_CFP_START 0x18C > #define B43_MMIO_TSF_CFP_MAXDUR 0x190 > +#define B43_MMIO_CLKCTL 0x1E0 /* clock control status */ > > /* 32-bit DMA */ > #define B43_MMIO_DMA32_BASE0 0x200 > diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c > index b06e3f0..10b9e6f 100644 > --- a/drivers/net/wireless/b43/phy_common.c > +++ b/drivers/net/wireless/b43/phy_common.c > @@ -467,10 +467,158 @@ struct b43_c32 b43_cordic(int theta) > return ret; > } > > +/* http://bcm-v4.sipsolutions.net/802.11/NcClkCtlCc */ > +static bool b43_no_check_clock_control_chip_common(struct b43_wldev *dev, > + u32 mode) > +{ > + /* TODO: this is temporary hack */ > + return (mode == 0); > +} > + > +/* http://bcm-v4.sipsolutions.net/802.11/ClkCtlCc */ > +static bool b43_clock_control_chip_common(struct b43_wldev *dev, u32 mode) > +{ > + struct ssb_bus *bus = dev->dev->bus; > + u16 chip_id = bus->chip_id; > + u16 chip_rev = bus->chip_rev; > + /* TODO: specs distinguish PCI and PCIe */ > + bool pci = (bus->bustype == SSB_BUSTYPE_PCI); > + > + if (dev->dev->id.revision < 6) > + return false; > + if (pci && ((chip_id == 0x4311 && chip_rev < 2) || > + (pci && chip_id == 0x4321) || > + (pci && chip_id == 0x4716))) > + return (mode == 0); > + return b43_no_check_clock_control_chip_common(dev, mode); > +} > + > +/* http://bcm-v4.sipsolutions.net/802.11/PHY/BmacWaitForWake */ > +static void b43_phy_bmac_wait_for_wake(struct b43_wldev *dev) > +{ > + u8 core_rev = dev->dev->bus->pcicore.dev->id.revision; > + u16 tmp, i; > + > + if (core_rev == 4) { > + udelay(5); > + return; > + } > + > + if (dev->phy.type == B43_PHYTYPE_G && core_rev == 5) > + udelay(2000); > + else > + udelay(40); > + > + for (i = 0; i < 1500; i++) { > + tmp = b43_shm_read16(dev, B43_SHM_SHARED, > + B43_SHM_SH_UCODESTAT); > + if (tmp == B43_SHM_SH_UCODESTAT_SLEEP) { > + i = 0; > + break; > + } > + udelay(10); > + } > + if (i) > + b43err(dev->wl, "ucode wake up timeout\n"); > +} > + > +/* http://bcm-v4.sipsolutions.net/802.11/PHY/MctrlWrite */ > +static void b43_phy_mac_control_write(struct b43_wldev *dev) > +{ > + u32 tmp = dev->phy.maccontrol; > + if (dev->phy.wake_override) > + tmp |= B43_MACCTL_AWAKE; > + if (dev->phy.mute_override) > + tmp &= ~B43_MACCTL_AP; > + tmp |= B43_MACCTL_INFRA; > + b43_write32(dev, B43_MMIO_MACCTL, tmp); > +} > + > +/* http://bcm-v4.sipsolutions.net/802.11/PHY/UcodeWakeOverrideSet */ > +static void b43_ucode_wake_override_set(struct b43_wldev *dev, u32 override) > +{ > + dev->phy.wake_override |= override; > + if (dev->phy.wake_override || dev->phy.maccontrol & B43_MACCTL_AWAKE) > + return; > + b43_phy_mac_control_write(dev); > + b43_phy_bmac_wait_for_wake(dev); > +} > + > +/* http://bcm-v4.sipsolutions.net/802.11/PHY/UcodeWakeOverrideClear */ > +static void b43_ucode_wake_override_clear(struct b43_wldev *dev, u32 override) > +{ > + dev->phy.wake_override &= ~override; > + if (dev->phy.wake_override != (dev->phy.maccontrol & B43_MACCTL_AWAKE)) > + return; > + b43_phy_mac_control_write(dev); > +} > + > /* http://bcm-v4.sipsolutions.net/802.11/PHY/ClkCtlClk */ > static void b43_clock_control(struct b43_wldev *dev, u32 mode) > { > - ; /* TODO */ > + struct b43_phy *phy = &dev->phy; > + struct ssb_bus *bus = dev->dev->bus; > + u8 core_rev = bus->pcicore.dev->id.revision; > + u16 i; > + u32 clkctl; > + bool wakeup; > + > + if (bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU) { /* PMU Present */ > + B43_WARN_ON(core_rev < 20); > + if (phy->clk) { > + bool tmp = (bus->chipco.pmu.rev == 0 && > + (b43_read32(dev, B43_MMIO_CLKCTL) & 0x12)); > + > + if (mode == 0) { > + clkctl = b43_read32(dev, B43_MMIO_CLKCTL); > + clkctl |= 0x2; > + b43_write32(dev, B43_MMIO_CLKCTL, clkctl); > + udelay(33); > + } > + > + if (mode == 0 || tmp) { > + for (i = 0; i < 1500; i++) { > + clkctl = b43_read32(dev, B43_MMIO_CLKCTL); > + if ((clkctl & 0x20000) == 0) { > + i = 0; > + break; > + } > + udelay(10); > + } > + if (i) > + b43err(dev->wl, "clock timeout\n"); > + } > + > + if (mode != 0 && tmp) { > + clkctl = b43_read32(dev, B43_MMIO_CLKCTL); > + clkctl &= ~0x2; > + b43_write32(dev, B43_MMIO_CLKCTL, clkctl); > + } > + } > + phy->forcefastclk = (mode == 0); > + } else { > + B43_WARN_ON(core_rev >= 20); > + > + wakeup = (core_rev < 9); > + if (phy->up && wakeup) > + b43_ucode_wake_override_set(dev, 1); > + > + phy->forcefastclk = b43_clock_control_chip_common(dev, mode); > + if (core_rev < 11) { > + if (phy->forcefastclk) > + ; /* TODO: b43_mhf(dev, 0, 0x400, 0x400, 3); */ > + else > + ; /* TODO: b43_mhf(dev, 0, 0x400, 0, 3); */ We do implement mhf already, though it is done differently than in wl. See my earlier "Add missing HF write" patch. > + } > + > + if (phy->forcefastclk) > + phy->wake_override |= 0x10; > + else > + phy->wake_override &= ~0x10; > + > + if (phy->up && wakeup) > + b43_ucode_wake_override_clear(dev, 1); > + } > } > > /* http://bcm-v4.sipsolutions.net/802.11/PHY/BmacBwSet */ > diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h > index 9886db0..fa20548 100644 > --- a/drivers/net/wireless/b43/phy_common.h > +++ b/drivers/net/wireless/b43/phy_common.h > @@ -260,8 +260,15 @@ struct b43_phy { > atomic_t txerr_cnt; > > /* Clock */ > + u32 clk; > bool forcefastclk; > > + bool up; > + u32 maccontrol; > + > + u32 wake_override; > + u32 mute_override; > + > #ifdef CONFIG_B43_DEBUG > /* PHY registers locked (w.r.t. firmware) */ > bool phy_locked; > -- > 1.7.1 > > -- Vista: [V]iruses, [I]ntruders, [S]pyware, [T]rojans and [A]dware. :-) ��.n��������+%������w��{.n�����{���zW����ܨ}���Ơz�j:+v�����w����ޙ��&�)ߡ�a����z�ޗ���ݢj��w�f