[PATCH 2/2] b43: N-PHY: add sub calls of band width setting

Rafał Miłecki zajec5 at gmail.com
Sun Aug 22 15:49:49 EDT 2010


Signed-off-by: Rafał Miłecki <zajec5 at gmail.com>
---
 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); */
+		}
+
+		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




More information about the b43-dev mailing list