Skip to contentSkip to conversation

wifi: b43: AC-PHY support (series 4/4)

RFC PATCH New Andreas Wendleder 1 participant 5 messages Nov 12 B43 wireless driver

lore
Share & tools
lore
#0 lore raw

cover wifi: b43: AC-PHY support (series 4/4)

Radio 2069 and the AC PHY: tables, 2.4 GHz and 5 GHz channel switching (5 GHz in 80 MHz mode), HT and VHT capabilities, and the removal of "depends on BROKEN". Based on series 3/4.

With the four series b43 brings up a BCM4360 on 2.4 GHz and 5 GHz, with HT at 20 MHz on 2.4 GHz and VHT at 80 MHz on 5 GHz (40 MHz is untested), two streams and A-MPDU.

Each patch compiles on its own (kernel 7.2.10 headers). The four series together were run on a MacBookAir6,1 (14e4:43a0, BCM4360, core revision 42, microcode 832.127, 2 of 3 chains wired) on top of v7.3-rc5's b43. The AC PHY only comes with series 4, so the earlier series cannot be exercised on this hardware alone. Association and traffic with WPA2 (software crypto) on 2.4 GHz (HT, about 54-63 Mbit/s) and on 5 GHz (VHT, 80 MHz block, two streams, 40-70 Mbit/s at -78 dBm), no errors in the log. Not tested:
suspend/resume with this exact series, other boards. Not done: TX calibration, hardware crypto, power save.

Known issues, which a review would ask to fix (pointed out by Alessio Ferri): the number of AC cores is forced to 2 on the MacBook boards (0x117, 0x137) and some init loops assume 2 cores, which is wrong for 3-chain boards; and SROM revision 11 values are read at fixed word offsets instead of from parsed SPROM fields (the parsing is in his bcma series, not merged yet).

Where the values come from: the register sequences and table contents were taken from Broadcom's wl driver running on this MacBook, by tracing its register accesses (bpftrace on wl's MMIO accessors), and reduced to what the hardware needs. Parts come from Alessio Ferri's AC-PHY work (the PHY init sequence, the 40 and 80 MHz coefficient tables, a TX gain table, the Farrow resampler formula, the VHT fields of the TX descriptor, register and table names), and some formats follow brcmsmac.
The result was tested on the hardware as described below.

Andreas Wendleder (4):
wifi: b43: radio 2069 and AC-PHY tables
wifi: b43: AC-PHY init and 2.4 GHz channel switching
wifi: b43: 5 GHz, 80 MHz and VHT for the AC PHY
wifi: b43: enable the AC-PHY support

 drivers/net/wireless/broadcom/b43/Kconfig     |    4 +-
 drivers/net/wireless/broadcom/b43/Makefile    |    2 +-
 drivers/net/wireless/broadcom/b43/main.c      |   69 +-
 drivers/net/wireless/broadcom/b43/phy_ac.c    | 1263 +++++++++++++++-
 drivers/net/wireless/broadcom/b43/phy_ac.h    |    4 +
 .../net/wireless/broadcom/b43/phy_ac_farrow.h |  260 ++++
 .../net/wireless/broadcom/b43/phy_common.c    |   25 +-
 .../net/wireless/broadcom/b43/radio_2069.c    |  862 +++++++++++
 .../net/wireless/broadcom/b43/radio_2069.h    |   19 +
 .../net/wireless/broadcom/b43/tables_phy_ac.c | 1273 +++++++++++++++++
 .../net/wireless/broadcom/b43/tables_phy_ac.h |   31 +
 11 files changed, 3801 insertions(+), 11 deletions(-)
 create mode 100644 drivers/net/wireless/broadcom/b43/phy_ac_farrow.h
 create mode 100644 drivers/net/wireless/broadcom/b43/radio_2069.c
 create mode 100644 drivers/net/wireless/broadcom/b43/radio_2069.h
 create mode 100644 drivers/net/wireless/broadcom/b43/tables_phy_ac.c
 create mode 100644 drivers/net/wireless/broadcom/b43/tables_phy_ac.h
#1 lore raw

RFC PATCH 1/4 wifi: b43: radio 2069 and AC-PHY tables

Add the data the AC PHY needs:

- radio_2069.c: the channel tuning table of radio 2069 rev 4 (2.4 GHz and 5 GHz rows) and the register list it programs,
- tables_phy_ac.c: the PHY tables of the PHY init (rev 0 set, RF sequencer, gain limits, gain ladder, the FEM control pattern of femctrl == 2 boards, the 2.4 GHz and 5 GHz TX gain tables), and the values of the remaining table cells this board holds after the vendor driver's init.

The tables are values as seen in operation on a BCM4360 board (MacBookAir6,1) with the vendor driver; the names of several tables follow Alessio Ferri's b43-ac-wip. They have been checked on this board only. The data is used by the patches that follow.

---
 drivers/net/wireless/broadcom/b43/Makefile    |    2 +-
 .../net/wireless/broadcom/b43/radio_2069.c    |  862 +++++++++++
 .../net/wireless/broadcom/b43/radio_2069.h    |   19 +
 .../net/wireless/broadcom/b43/tables_phy_ac.c | 1273 +++++++++++++++++
 .../net/wireless/broadcom/b43/tables_phy_ac.h |   31 +
 5 files changed, 2186 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/wireless/broadcom/b43/radio_2069.c
 create mode 100644 drivers/net/wireless/broadcom/b43/radio_2069.h
 create mode 100644 drivers/net/wireless/broadcom/b43/tables_phy_ac.c
 create mode 100644 drivers/net/wireless/broadcom/b43/tables_phy_ac.h
drivers/net/wireless/broadcom/b43/Makefile +1 -1
index 54f92ce..be2c9ca 100644
@@ -14,7 +14,7 @@ b43-$(CONFIG_B43_PHY_HT)	+= phy_ht.o
 b43-$(CONFIG_B43_PHY_HT)	+= tables_phy_ht.o
 b43-$(CONFIG_B43_PHY_HT)	+= radio_2059.o
 b43-$(CONFIG_B43_PHY_LCN)	+= phy_lcn.o tables_phy_lcn.o
-b43-$(CONFIG_B43_PHY_AC)	+= phy_ac.o
+b43-$(CONFIG_B43_PHY_AC)	+= phy_ac.o radio_2069.o tables_phy_ac.o
 b43-y				+= sysfs.o
 b43-y				+= xmit.o
 b43-y				+= dma.o
drivers/net/wireless/broadcom/b43/radio_2069.c new file +862 -0

862 lines not on this page · raw message

drivers/net/wireless/broadcom/b43/radio_2069.h new file +19 -0
new file mode 100644
index 0000000..097d3cd
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_RADIO_2069_H_
+#define B43_RADIO_2069_H_
+
+#include <linux/types.h>
+
+#define B43_RADIO_2069_TUNE_REGS	50
+
+struct b43_radio_2069_chan {
+	u16 channel;
+	u16 freq;
+	u16 radio[B43_RADIO_2069_TUNE_REGS];
+	u16 bw[6];
+};
+
+extern const struct b43_radio_2069_chan b43_radio_2069r4_chans[];
+extern const unsigned int b43_radio_2069r4_chans_n;
+
+#endif /* B43_RADIO_2069_H_ */
drivers/net/wireless/broadcom/b43/tables_phy_ac.c new file +1273 -0

1,273 lines not on this page · raw message

drivers/net/wireless/broadcom/b43/tables_phy_ac.h new file +31 -0
new file mode 100644
index 0000000..64a5969
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef B43_TABLES_PHY_AC_H_
+#define B43_TABLES_PHY_AC_H_
+
+#include <linux/types.h>
+
+struct b43_phy_ac_tbl {
+	const void *data;
+	u16 count;
+	u16 id;
+	u16 offset;
+	u8 width;	/* bits per entry: 8, 16 or 32 */
+};
+
+extern const struct b43_phy_ac_tbl b43_phy_ac_tbls_rev0[];
+extern const unsigned int b43_phy_ac_tbls_rev0_n;
+extern const struct b43_phy_ac_tbl b43_phy_ac_rfseq_tbls[];
+extern const unsigned int b43_phy_ac_rfseq_tbls_n;
+extern const struct b43_phy_ac_tbl b43_phy_ac_femctrl2_tbls[];
+extern const unsigned int b43_phy_ac_femctrl2_tbls_n;
+extern const struct b43_phy_ac_tbl b43_phy_ac_misc_tbls[];
+extern const unsigned int b43_phy_ac_misc_tbls_n;
+extern const struct b43_phy_ac_tbl b43_phy_ac_ladder_tbls[];
+extern const unsigned int b43_phy_ac_ladder_tbls_n;
+extern const struct b43_phy_ac_tbl b43_phy_ac_vendor_tbls[];
+extern const unsigned int b43_phy_ac_vendor_tbls_n;
+
+extern const u16 b43_phy_ac_txgain_2g[128][3];
+extern const u16 b43_phy_ac_txgain_5g[128][3];
+
+#endif /* B43_TABLES_PHY_AC_H_ */
#2 lore raw

RFC PATCH 2/4 wifi: b43: AC-PHY init and 2.4 GHz channel switching

In reply to Andreas Wendleder

Replace the placeholder AC-PHY code with an initialization that brings the BCM4360 (PHY AC rev 1, radio 2069 rev 4) up on 2.4 GHz at 20 MHz:

- radio 2069 power-up (init, resistor and RC calibration) and power-down from software_rfkill,
- PHY init: the table set, the first-init registers, the reset-time register blocks, hardware TX power control with the wide tables, and the second TX chain, which stays dark unless chipcontrol bit 3 is set,
- channel switching: tune the synthesizer from the radio table, the per-channel Farrow resampler words and BW registers, reset CCA, with PHY 0x0003 bit 8 (the band) cleared on 2.4 GHz,
- a fixed 2.4 GHz TX gain table index as the starting point of the power loop,
- the 15 second work restarts the core when the microcode counts PHY TX errors in several fresh inits (only about a third of fresh inits can transmit, the rest fail every frame), at most three times,
- HT capabilities for the 2.4 GHz band.

5 GHz channels are refused for now.

---
 drivers/net/wireless/broadcom/b43/main.c      |   23 +-
 drivers/net/wireless/broadcom/b43/phy_ac.c    | 1014 ++++++++++++++++-
 drivers/net/wireless/broadcom/b43/phy_ac.h    |    3 +
 .../net/wireless/broadcom/b43/phy_ac_farrow.h |  260 +++++
 4 files changed, 1295 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/wireless/broadcom/b43/phy_ac_farrow.h
drivers/net/wireless/broadcom/b43/main.c +22 -1
index 6b80b5e..7d2f9ea 100644
@@ -352,6 +352,25 @@ static struct ieee80211_supported_band b43_band_2GHz = {
 	.n_bitrates	= b43_g_ratetable_size,
 };
 
+static struct ieee80211_supported_band b43_band_2GHz_ac = {
+	.band		= NL80211_BAND_2GHZ,
+	.channels	= b43_2ghz_chantable,
+	.n_channels	= ARRAY_SIZE(b43_2ghz_chantable),
+	.bitrates	= b43_g_ratetable,
+	.n_bitrates	= b43_g_ratetable_size,
+	.ht_cap		= {
+		.ht_supported	= true,
+		/* static SM power save disabled */
+		.cap		= IEEE80211_HT_CAP_SM_PS,
+		.ampdu_factor	= IEEE80211_HT_MAX_AMPDU_8K,
+		.ampdu_density	= IEEE80211_HT_MPDU_DENSITY_NONE,
+		.mcs		= {
+			.rx_mask	= { 0xff, 0xff },
+			.tx_params	= IEEE80211_HT_MCS_TX_DEFINED,
+		},
+	},
+};
+
 static struct ieee80211_supported_band b43_band_2ghz_limited = {
 	.band		= NL80211_BAND_2GHZ,
 	.channels	= b43_2ghz_chantable,
@@ -5613,7 +5632,9 @@ static int b43_setup_bands(struct b43_wldev *dev,
 
 	if (have_2ghz_phy)
 		hw->wiphy->bands[NL80211_BAND_2GHZ] = limited_2g ?
-			&b43_band_2ghz_limited : &b43_band_2GHz;
+			&b43_band_2ghz_limited :
+			(dev->phy.type == B43_PHYTYPE_AC ?
+			 &b43_band_2GHz_ac : &b43_band_2GHz);
 	if (dev->phy.type == B43_PHYTYPE_N) {
 		if (have_5ghz_phy)
 			hw->wiphy->bands[NL80211_BAND_5GHZ] = limited_5g ?
drivers/net/wireless/broadcom/b43/phy_ac.c +1010 -4

1,047 lines not on this page · raw message

drivers/net/wireless/broadcom/b43/phy_ac.h +3 -0
index 02eb6c0..0b6896e 100644
@@ -32,6 +32,9 @@
 #define  B43_PHY_AC_C3_CLIP_DIS			0x4000
 
 struct b43_phy_ac {
+	/* Band of the last channel switch; valid once chan_set is true. */
+	bool chan_set;
+	bool radio_on;
 };
 
 extern const struct b43_phy_operations b43_phyops_ac;
drivers/net/wireless/broadcom/b43/phy_ac_farrow.h new file +260 -0

260 lines not on this page · raw message

#3 lore raw

RFC PATCH 3/4 wifi: b43: 5 GHz, 80 MHz and VHT for the AC PHY

In reply to Andreas Wendleder

Add 5 GHz channel switching: the RF sequencer extension, the second sequencer's command lists and three table 7 cells (which keep the second TX chain working), the 5 GHz TX gain table and AGC tables, VCO calibration and the RX gain control word. Switching back to 2.4 GHz rewrites the 2.4 GHz tables and the 20 MHz PHY bandwidth.

On 5 GHz the PHY runs in its 80 MHz mode on the 80 MHz block that contains the primary channel, tuned to the centre of the block, with the Farrow resampler words computed for it. The chanspec of such a channel names the centre channel, the width and the position of the primary. Only an AP with an 80 MHz channel was tested; with a 20 or 40 MHz AP the primary channel's frames should still be received in the block.

Register the 5 GHz band with HT and VHT capabilities (two streams, MCS 0-9, 80 MHz); mac80211 wants 40 MHz capability before it uses 80 MHz.

---
 drivers/net/wireless/broadcom/b43/main.c      |  46 +++
 drivers/net/wireless/broadcom/b43/phy_ac.c    | 269 +++++++++++++++++-
 drivers/net/wireless/broadcom/b43/phy_ac.h    |   1 +
 .../net/wireless/broadcom/b43/phy_common.c    |  25 +-
 4 files changed, 328 insertions(+), 13 deletions(-)
drivers/net/wireless/broadcom/b43/main.c +46 -0
index 7d2f9ea..eeb70bf 100644
@@ -317,6 +317,21 @@ static struct ieee80211_channel b43_5ghz_aphy_chantable[] = {
 	CHAN5G(208, 0),		CHAN5G(212, 0),
 	CHAN5G(216, 0),
 };
+
+static struct ieee80211_channel b43_5ghz_acphy_chantable[] = {
+	CHAN5G(36, 0),		CHAN5G(40, 0),
+	CHAN5G(44, 0),		CHAN5G(48, 0),
+	CHAN5G(52, 0),		CHAN5G(56, 0),
+	CHAN5G(60, 0),		CHAN5G(64, 0),
+	CHAN5G(100, 0),		CHAN5G(104, 0),
+	CHAN5G(108, 0),		CHAN5G(112, 0),
+	CHAN5G(116, 0),		CHAN5G(120, 0),
+	CHAN5G(124, 0),		CHAN5G(128, 0),
+	CHAN5G(132, 0),		CHAN5G(136, 0),
+	CHAN5G(140, 0),		CHAN5G(149, 0),
+	CHAN5G(153, 0),		CHAN5G(157, 0),
+	CHAN5G(161, 0),		CHAN5G(165, 0),
+};
 #undef CHAN4G
 #undef CHAN5G
 
@@ -336,6 +351,14 @@ static struct ieee80211_supported_band b43_band_5GHz_nphy_limited = {
 	.n_bitrates	= b43_a_ratetable_size,
 };
 
+static struct ieee80211_supported_band b43_band_5GHz_acphy = {
+	.band		= NL80211_BAND_5GHZ,
+	.channels	= b43_5ghz_acphy_chantable,
+	.n_channels	= ARRAY_SIZE(b43_5ghz_acphy_chantable),
+	.bitrates	= b43_a_ratetable,
+	.n_bitrates	= b43_a_ratetable_size,
+};
+
 static struct ieee80211_supported_band b43_band_5GHz_aphy = {
 	.band		= NL80211_BAND_5GHZ,
 	.channels	= b43_5ghz_aphy_chantable,
@@ -5640,6 +5663,29 @@ static int b43_setup_bands(struct b43_wldev *dev,
 			hw->wiphy->bands[NL80211_BAND_5GHZ] = limited_5g ?
 				&b43_band_5GHz_nphy_limited :
 				&b43_band_5GHz_nphy;
+	} else if (dev->phy.type == B43_PHYTYPE_AC) {
+		if (have_5ghz_phy) {
+			struct ieee80211_sta_vht_cap *vht =
+				&b43_band_5GHz_acphy.vht_cap;
+
+			/*
+			 * The AP refuses a station without HT here (status 18)
+			 */
+			b43_band_5GHz_acphy.ht_cap = b43_band_2GHz_ac.ht_cap;
+			/*
+			 * mac80211 wants 40 MHz capability before it uses 80
+			 * MHz
+			 */
+			b43_band_5GHz_acphy.ht_cap.cap |=
+				IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+			vht->vht_supported = true;
+			vht->cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
+			/* MCS 0-9 on one and two streams */
+			vht->vht_mcs.rx_mcs_map = cpu_to_le16(0xfffa);
+			vht->vht_mcs.tx_mcs_map = cpu_to_le16(0xfffa);
+			hw->wiphy->bands[NL80211_BAND_5GHZ] =
+				&b43_band_5GHz_acphy;
+		}
 	} else {
 		if (have_5ghz_phy)
 			hw->wiphy->bands[NL80211_BAND_5GHZ] = &b43_band_5GHz_aphy;
drivers/net/wireless/broadcom/b43/phy_ac.c +259 -10

322 lines not on this page · raw message

drivers/net/wireless/broadcom/b43/phy_ac.h +1 -0
index 0b6896e..4a6c1e9 100644
@@ -34,6 +34,7 @@
 struct b43_phy_ac {
 	/* Band of the last channel switch; valid once chan_set is true. */
 	bool chan_set;
+	bool last_5ghz;
 	bool radio_on;
 };
 
drivers/net/wireless/broadcom/b43/phy_common.c +22 -3
index cfc14c1..40e99b2 100644
@@ -413,15 +413,34 @@ void b43_phy_take_out_of_reset(struct b43_wldev *dev)
 	}
 }
 
+/* Centre channel of the 80 MHz block a 5 GHz primary belongs to, 0 if none */
+unsigned int b43_ac_80mhz_centre(unsigned int channel)
+{
+	static const u8 centre[] = { 42, 58, 106, 122, 138, 155 };
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(centre); i++)
+		if (channel >= centre[i] - 6u && channel <= centre[i] + 6u &&
+		    (channel - (centre[i] - 6u)) % 4 == 0)
+			return centre[i];
+	return 0;
+}
+
 /*
  * The 11ac chanspec of a primary channel as the AC microcode takes it in
  * SHM and in the TX and RX headers: channel, 0x1000 for 20 MHz, 0xc000 on
- * 5 GHz.
+ * 5 GHz. In 80 MHz mode (every 5 GHz channel inside an 80 MHz block) the
+ * centre channel, 0x2000 for the width and the primary's position in the
+ * block in bits 10:8 (primary channel 112: 0xe36a).
  */
 u16 b43_ac_chanspec(struct b43_wldev *dev, unsigned int channel)
 {
-	return channel | 0x1000 |
-	       (b43_current_band(dev->wl) == NL80211_BAND_5GHZ ? 0xc000 : 0);
+	bool is_5ghz = b43_current_band(dev->wl) == NL80211_BAND_5GHZ;
+	unsigned int centre = is_5ghz ? b43_ac_80mhz_centre(channel) : 0;
+
+	if (centre)
+		return 0xe000 | (((channel - (centre - 6)) / 4) << 8) | centre;
+	return channel | 0x1000 | (is_5ghz ? 0xc000 : 0);
 }
 
 int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel)
#4 lore raw

RFC PATCH 4/4 wifi: b43: enable the AC-PHY support

In reply to Andreas Wendleder

The AC-PHY now brings up a BCM4352/BCM4360 on 2.4 GHz and 5 GHz and transmits and receives with HT (20 MHz, 2.4 GHz) and VHT (80 MHz, 5 GHz), the two that were tested. Remove the
dependency on BROKEN and say what is missing: no TX calibration, no TX power control beyond the hardware loop, no hardware crypto and no power save.

---
 drivers/net/wireless/broadcom/b43/Kconfig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/broadcom/b43/Kconfig +2 -2
index 4559549..a8321ca 100644
@@ -149,8 +149,8 @@ config B43_PHY_LCN
 	  Say N, this is BROKEN and crashes driver.
 
 config B43_PHY_AC
-	bool "Support for AC-PHY (802.11ac) devices (BROKEN)"
-	depends on B43 && B43_BCMA && BROKEN
+	bool "Support for AC-PHY (802.11ac) devices (EXPERIMENTAL)"
+	depends on B43 && B43_BCMA
 	help
 	  This PHY type can be found in the following chipsets:
 	  PCI: BCM4352, BCM4360