Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH RFC wireless-next 0/4] wifi: b43: AC-PHY support (series 4/4)
@ 2026-11-12 17:56 Andreas Wendleder
  2026-11-12 17:56 ` [PATCH RFC wireless-next 1/4] wifi: b43: radio 2069 and AC-PHY tables Andreas Wendleder
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Andreas Wendleder @ 2026-11-12 17:56 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, b43-dev, Michael Buesch, Alessio Ferri, kvalo,
	julian.calaby, jpeisach, rosenp, linux-kernel

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


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH RFC wireless-next 1/4] wifi: b43: radio 2069 and AC-PHY tables
  2026-11-12 17:56 [PATCH RFC wireless-next 0/4] wifi: b43: AC-PHY support (series 4/4) Andreas Wendleder
@ 2026-11-12 17:56 ` Andreas Wendleder
  2026-11-12 17:56 ` [PATCH RFC wireless-next 2/4] wifi: b43: AC-PHY init and 2.4 GHz channel switching Andreas Wendleder
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Andreas Wendleder @ 2026-11-12 17:56 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, b43-dev, Michael Buesch, Alessio Ferri, kvalo,
	julian.calaby, jpeisach, rosenp, linux-kernel

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.

Co-developed-by: Alessio Ferri <alessio.ferri@mythread.it>
Signed-off-by: Alessio Ferri <alessio.ferri@mythread.it>
Signed-off-by: Andreas Wendleder <gonsolo@gmail.com>
---
 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

diff --git a/drivers/net/wireless/broadcom/b43/Makefile b/drivers/net/wireless/broadcom/b43/Makefile
index 54f92ce..be2c9ca 100644
--- a/drivers/net/wireless/broadcom/b43/Makefile
+++ b/drivers/net/wireless/broadcom/b43/Makefile
@@ -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
diff --git a/drivers/net/wireless/broadcom/b43/radio_2069.c b/drivers/net/wireless/broadcom/b43/radio_2069.c
new file mode 100644
index 0000000..7f0d762
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/radio_2069.c
@@ -0,0 +1,862 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Radio 2069 rev 4 channel tuning table. Generated by tools/gen_radio_2069.py.
+ *
+ * Copyright (c) 2026 Andreas Wendleder <gonsolo@gmail.com>
+ */
+
+#include "b43.h"
+#include "radio_2069.h"
+
+const struct b43_radio_2069_chan b43_radio_2069r4_chans[] = {
+	{ .channel = 184, .freq = 4920,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0ccf, 0x00a4, 0x0000, 0x0290, 0x0000,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3505, 0x0005, 0x0005, 0xff05, 0xffff,
+		0xffff, 0x7068, 0x0000, 0x0000, 0x2000, 0x1000, 0x0000, 0x0000,
+		0x2000, 0x1000, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00ff,
+		0x0fff, 0x00f0, 0x00a9, 0x0fac, 0xc0ff, 0x18c5, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216 } },
+	{ .channel = 185, .freq = 4925,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0cd3, 0x00a4, 0x2aaa, 0x0290, 0xaaaa,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3505, 0x0005, 0x0005, 0xff05, 0xffff,
+		0xffff, 0x7068, 0x3092, 0x0849, 0x162d, 0x0b17, 0x3092, 0x0849,
+		0x162d, 0x0b17, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00ff,
+		0x0fff, 0x00f0, 0x00a9, 0x0fac, 0xc0ff, 0x18c5, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x07b6, 0x07b2, 0x07ae, 0x0213, 0x0214, 0x0215 } },
+	{ .channel = 187, .freq = 4935,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0cd9, 0x00a4, 0x8000, 0x0292, 0x0000,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3505, 0x0005, 0x0005, 0xff05, 0xffff,
+		0xffff, 0x7068, 0x01ee, 0x30f7, 0x1c75, 0x0e3a, 0x01ee, 0x30f7,
+		0x1c75, 0x0e3a, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00ff,
+		0x0fff, 0x00f0, 0x00a9, 0x0fac, 0xc0ff, 0x18c5, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x07ba, 0x07b6, 0x07b2, 0x0212, 0x0213, 0x0214 } },
+	{ .channel = 188, .freq = 4940,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0cdd, 0x00a4, 0xaaaa, 0x0292, 0xaaaa,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3505, 0x0005, 0x0005, 0xff05, 0xffff,
+		0xffff, 0x7068, 0x3d8a, 0x0ec5, 0x1d7b, 0x0ebe, 0x3d8a, 0x0ec5,
+		0x1d7b, 0x0ebe, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00ff,
+		0x0fff, 0x00f0, 0x00a9, 0x0fac, 0xc0ff, 0x18c5, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214 } },
+	{ .channel = 189, .freq = 4945,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0cdf, 0x00a4, 0xd555, 0x0293, 0x5555,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3505, 0x0005, 0x0005, 0xff05, 0xffff,
+		0xffff, 0x7068, 0x05ef, 0x32f7, 0x1e1f, 0x0f0f, 0x05ef, 0x32f7,
+		0x1e1f, 0x0f0f, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00ff,
+		0x0fff, 0x00f0, 0x00a9, 0x0fac, 0xc0ff, 0x18c5, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x07be, 0x07ba, 0x07b6, 0x0211, 0x0212, 0x0213 } },
+	{ .channel = 192, .freq = 4960,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0ce9, 0x00a5, 0x5555, 0x0295, 0x5555,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3505, 0x0005, 0x0005, 0xff05, 0xffff,
+		0xffff, 0x7068, 0x05a6, 0x32d3, 0x1f17, 0x0f8b, 0x05a6, 0x32d3,
+		0x1f17, 0x0f8b, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00ff,
+		0x0fff, 0x00f0, 0x0099, 0x0fac, 0xc0ff, 0x18c5, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212 } },
+	{ .channel = 196, .freq = 4980,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0cf7, 0x00a6, 0x0000, 0x0298, 0x0000,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3505, 0x0005, 0x0005, 0xff05, 0xffff,
+		0xffff, 0x7068, 0x3308, 0x0984, 0x1f95, 0x0fcb, 0x3308, 0x0984,
+		0x1f95, 0x0fcb, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00ff,
+		0x0fff, 0x00f0, 0x0098, 0x0fac, 0xc0ff, 0x18c5, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f } },
+	{ .channel = 207, .freq = 5035,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0d1b, 0x00a7, 0xd555, 0x029f, 0x5555,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3505, 0x0005, 0x0005, 0xff05, 0xfffc,
+		0xfcff, 0x7068, 0x3e4f, 0x0f27, 0x1fd9, 0x0fed, 0x3e4f, 0x0f27,
+		0x1fd9, 0x0fed, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00ee,
+		0x0fef, 0x00f0, 0x0087, 0x0fac, 0xc0ff, 0x18c5, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x07e2, 0x07de, 0x07da, 0x0208, 0x0209, 0x020a } },
+	{ .channel = 208, .freq = 5040,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0d1f, 0x00a8, 0x0000, 0x02a0, 0x0000,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3505, 0x0005, 0x0005, 0xff05, 0xfffc,
+		0xfcff, 0x7068, 0x0000, 0x0000, 0x2000, 0x1000, 0x0000, 0x0000,
+		0x2000, 0x1000, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00ee,
+		0x0fef, 0x00f0, 0x0087, 0x0fac, 0xc0ff, 0x18c5, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209 } },
+	{ .channel = 209, .freq = 5045,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0d23, 0x00a8, 0x2aaa, 0x02a0, 0xaaaa,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3505, 0x0005, 0x0005, 0xff05, 0xfffc,
+		0xfcff, 0x7068, 0x31fb, 0x38fe, 0x15a6, 0x0ad3, 0x31fb, 0x38fe,
+		0x15a6, 0x0ad3, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00ee,
+		0x0fef, 0x00f0, 0x0087, 0x0fac, 0xc0ff, 0x18c5, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x07e6, 0x07e2, 0x07de, 0x0207, 0x0208, 0x0209 } },
+	{ .channel = 210, .freq = 5050,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0d25, 0x00a8, 0x5555, 0x02a1, 0x5555,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3505, 0x0005, 0x0005, 0xff05, 0xfffb,
+		0xfbff, 0x7068, 0x32ab, 0x3955, 0x19f4, 0x0cfa, 0x32ab, 0x3955,
+		0x19f4, 0x0cfa, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00ee,
+		0x0fef, 0x00f0, 0x0087, 0x0fac, 0xc0ff, 0x18c5, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208 } },
+	{ .channel = 212, .freq = 5060,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0d2d, 0x00a8, 0xaaaa, 0x02a2, 0xaaaa,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3505, 0x0005, 0x0005, 0xff05, 0xfffb,
+		0xfbff, 0x7068, 0x3cf7, 0x3e7b, 0x1cc8, 0x0e64, 0x3cf7, 0x3e7b,
+		0x1cc8, 0x0e64, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00ee,
+		0x0fdf, 0x00f0, 0x0087, 0x0fac, 0xc0ff, 0x18c5, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207 } },
+	{ .channel = 216, .freq = 5080,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0d39, 0x00a9, 0x5555, 0x02a5, 0x5555,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3505, 0x0005, 0x0005, 0xff05, 0xfffa,
+		0xfaff, 0x7068, 0x05c4, 0x32e2, 0x1e5b, 0x0f2d, 0x05c4, 0x32e2,
+		0x1e5b, 0x0f2d, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00ee,
+		0x0fde, 0x00f0, 0x0077, 0x0eac, 0xb0ff, 0x18c5, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205 } },
+	{ .channel = 34, .freq = 5170,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0d75, 0x00ac, 0x5555, 0x02b1, 0x5555,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3505, 0x0006, 0x0006, 0xff06, 0xfff5,
+		0xf5fc, 0x7068, 0x083b, 0x341e, 0x1fb1, 0x0fd8, 0x083b, 0x341e,
+		0x1fb1, 0x0fd8, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00cc,
+		0x0ebc, 0x00f0, 0x0079, 0x0bac, 0xa0ff, 0x18c5, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc } },
+	{ .channel = 36, .freq = 5180,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0d7d, 0x00ac, 0xaaaa, 0x02b2, 0xaaaa,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3505, 0x0006, 0x0006, 0xff06, 0xfff5,
+		0xf5fb, 0x7068, 0x3d68, 0x0eb4, 0x1fa1, 0x0fd1, 0x3d68, 0x0eb4,
+		0x1fa1, 0x0fd1, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00c9,
+		0x0b9a, 0x00f0, 0x0079, 0x0cac, 0xa0ff, 0x18c4, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb } },
+	{ .channel = 38, .freq = 5190,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0d83, 0x00ad, 0x0000, 0x02b4, 0x0000,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3505, 0x0006, 0x0006, 0xff06, 0xfff4,
+		0xf4fb, 0x7068, 0x0fa9, 0x07d5, 0x1f92, 0x0fc9, 0x0fa9, 0x07d5,
+		0x1f92, 0x0fc9, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00c9,
+		0x0b9a, 0x00f0, 0x0079, 0x0cac, 0xa0ff, 0x18c4, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa } },
+	{ .channel = 40, .freq = 5200,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0d89, 0x00ad, 0x5555, 0x02b5, 0x5555,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3505, 0x0006, 0x0006, 0xff06, 0xfff4,
+		0xf4fa, 0x7068, 0x013b, 0x009e, 0x1f82, 0x0fc1, 0x013b, 0x009e,
+		0x1f82, 0x0fc1, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00c9,
+		0x0b89, 0x00f0, 0x0079, 0x0bac, 0xa0ff, 0x18c4, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9 } },
+	{ .channel = 42, .freq = 5210,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0d91, 0x00ad, 0xaaaa, 0x02b6, 0xaaaa,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfff4,
+		0xf3fa, 0x7068, 0x30cb, 0x3865, 0x1f72, 0x0fb9, 0x30cb, 0x3865,
+		0x1f72, 0x0fb9, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00c9,
+		0x0b89, 0x00f0, 0x0079, 0x0bac, 0xa0ff, 0x18c4, 0x0001, 0x0188,
+		0x010c, 0x03e0,
+	  },
+	  .bw = { 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8 } },
+	{ .channel = 44, .freq = 5220,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0d97, 0x00ae, 0x0000, 0x02b8, 0x0000,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfff3,
+		0xf3f9, 0x7068, 0x3dea, 0x0ef5, 0x1f63, 0x0fb2, 0x3dea, 0x0ef5,
+		0x1f63, 0x0fb2, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00c9,
+		0x0b89, 0x00f0, 0x0079, 0x0bac, 0xa0ff, 0x18c4, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7 } },
+	{ .channel = 46, .freq = 5230,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0d9d, 0x00ae, 0x5555, 0x02b9, 0x5555,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfff3,
+		0xf3f9, 0x7068, 0x09af, 0x04d8, 0x1f54, 0x0faa, 0x09af, 0x04d8,
+		0x1f54, 0x0faa, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00b8,
+		0x0b89, 0x00f0, 0x0079, 0x0bac, 0xa0ff, 0x18c4, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6 } },
+	{ .channel = 48, .freq = 5240,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0da5, 0x00ae, 0xaaaa, 0x02ba, 0xaaaa,
+		0x0000, 0x0488, 0x0cff, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfff2,
+		0xf2f8, 0x7068, 0x338b, 0x39c5, 0x1f44, 0x0fa2, 0x338b, 0x39c5,
+		0x1f44, 0x0fa2, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00b8,
+		0x0b89, 0x00f0, 0x0069, 0x0aac, 0xa0ff, 0x18c3, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5 } },
+	{ .channel = 52, .freq = 5260,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0db1, 0x00af, 0x5555, 0x02bd, 0x5555,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfff1,
+		0xf1f7, 0x7068, 0x3294, 0x394a, 0x1ff2, 0x0ff9, 0x3294, 0x394a,
+		0x1ff2, 0x0ff9, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00b8,
+		0x0a78, 0x00f0, 0x0068, 0x0aac, 0x90ff, 0x18c3, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3 } },
+	{ .channel = 54, .freq = 5270,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0db9, 0x00af, 0xaaaa, 0x02be, 0xaaaa,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfff1,
+		0xf1f7, 0x7068, 0x02bc, 0x015e, 0x1fd0, 0x0fe8, 0x02bc, 0x015e,
+		0x1fd0, 0x0fe8, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00b8,
+		0x0a78, 0x00f0, 0x0068, 0x0aac, 0x90ff, 0x18c3, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2 } },
+	{ .channel = 56, .freq = 5280,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0dbf, 0x00b0, 0x0000, 0x02c0, 0x0000,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfff0,
+		0xf0f6, 0x7068, 0x0000, 0x0000, 0x2000, 0x1000, 0x0000, 0x0000,
+		0x2000, 0x1000, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00a8,
+		0x0a78, 0x00f0, 0x0068, 0x0aac, 0x80ff, 0x18c3, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1 } },
+	{ .channel = 58, .freq = 5290,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0dc5, 0x00b0, 0x5555, 0x02c1, 0x5555,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfff0,
+		0xf0f6, 0x7068, 0x0941, 0x34a1, 0x1ef9, 0x0f7c, 0x0941, 0x34a1,
+		0x1ef9, 0x0f7c, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00a8,
+		0x0a78, 0x00f0, 0x0068, 0x0aac, 0x80ff, 0x18c3, 0x0001, 0x0188,
+		0x010c, 0x03e0,
+	  },
+	  .bw = { 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0 } },
+	{ .channel = 60, .freq = 5300,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0dcd, 0x00b0, 0xaaaa, 0x02c2, 0xaaaa,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xffef,
+		0xeff5, 0x7068, 0x07f8, 0x03fc, 0x1eea, 0x0f75, 0x07f8, 0x03fc,
+		0x1eea, 0x0f75, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00a8,
+		0x0a78, 0x00f0, 0x0068, 0x09ac, 0x80ff, 0x18c3, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0 } },
+	{ .channel = 62, .freq = 5310,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0dd3, 0x00b1, 0x0000, 0x02c4, 0x0000,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xffef,
+		0xeff5, 0x7068, 0x03eb, 0x31f5, 0x1edb, 0x0f6d, 0x03eb, 0x31f5,
+		0x1edb, 0x0f6d, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00a9,
+		0x0a78, 0x00f0, 0x0068, 0x09ac, 0x80ff, 0x18c3, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef } },
+	{ .channel = 64, .freq = 5320,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0dd9, 0x00b1, 0x5555, 0x02c5, 0x5555,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xffee,
+		0xeef4, 0x7068, 0x3f47, 0x3fa4, 0x1ecc, 0x0f66, 0x3f47, 0x3fa4,
+		0x1ecc, 0x0f66, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x00a7,
+		0x0967, 0x00f0, 0x0068, 0x09ac, 0x80ff, 0x18c3, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee } },
+	{ .channel = 100, .freq = 5500,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e51, 0x00b7, 0x5555, 0x02dd, 0x5555,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfee6,
+		0xe6ec, 0x7068, 0x3410, 0x0a08, 0x1f5b, 0x0fae, 0x3410, 0x0a08,
+		0x1f5b, 0x0fae, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0084,
+		0x0633, 0x00f0, 0x0046, 0x05ac, 0x50ff, 0x18c1, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd } },
+	{ .channel = 102, .freq = 5510,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e59, 0x00b7, 0xaaaa, 0x02de, 0xaaaa,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfee6,
+		0xe6ec, 0x7068, 0x3b3a, 0x0d9d, 0x1fe9, 0x0ff5, 0x3b3a, 0x0d9d,
+		0x1fe9, 0x0ff5, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0084,
+		0x0633, 0x00f0, 0x0046, 0x05ac, 0x50ff, 0x18c1, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd } },
+	{ .channel = 104, .freq = 5520,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e5f, 0x00b8, 0x0000, 0x02e0, 0x0000,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfde6,
+		0xe6eb, 0x7068, 0x0000, 0x0000, 0x2000, 0x1000, 0x0000, 0x0000,
+		0x2000, 0x1000, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0083,
+		0x0623, 0x00f0, 0x0046, 0x05ac, 0x50ff, 0x18c1, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc } },
+	{ .channel = 106, .freq = 5530,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e65, 0x00b8, 0x5555, 0x02e1, 0x5555,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfde5,
+		0xe5eb, 0x7068, 0x0c8f, 0x3647, 0x1da1, 0x0ed0, 0x0c8f, 0x3647,
+		0x1da1, 0x0ed0, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0083,
+		0x0623, 0x00f0, 0x0046, 0x05ac, 0x50ff, 0x18c1, 0x0001, 0x0188,
+		0x010c, 0x03e0,
+	  },
+	  .bw = { 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db } },
+	{ .channel = 108, .freq = 5540,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e6d, 0x00b8, 0xaaaa, 0x02e2, 0xaaaa,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfde5,
+		0xe5eb, 0x7068, 0x02a8, 0x3154, 0x1d93, 0x0ec9, 0x02a8, 0x3154,
+		0x1d93, 0x0ec9, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0073,
+		0x0523, 0x00f0, 0x0045, 0x05ac, 0x50ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da } },
+	{ .channel = 110, .freq = 5550,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e73, 0x00b9, 0x0000, 0x02e4, 0x0000,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfce4,
+		0xe4ea, 0x7068, 0x3641, 0x0b21, 0x1d85, 0x0ec3, 0x3641, 0x0b21,
+		0x1d85, 0x0ec3, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0073,
+		0x0523, 0x00f0, 0x0045, 0x05ac, 0x50ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9 } },
+	{ .channel = 112, .freq = 5560,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e79, 0x00b9, 0x5555, 0x02e5, 0x5555,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfce4,
+		0xe4ea, 0x7068, 0x0c34, 0x361a, 0x1f6f, 0x0fb7, 0x0c34, 0x361a,
+		0x1f6f, 0x0fb7, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0073,
+		0x0523, 0x00f0, 0x0035, 0x05ac, 0x50ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8 } },
+	{ .channel = 114, .freq = 5570,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e81, 0x00b9, 0xaaaa, 0x02e6, 0xaaaa,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfbe3,
+		0xe3e9, 0x7068, 0x3099, 0x384c, 0x1ef6, 0x0f7b, 0x3099, 0x384c,
+		0x1ef6, 0x0f7b, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0073,
+		0x0523, 0x00f0, 0x0035, 0x05ac, 0x50ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7 } },
+	{ .channel = 116, .freq = 5580,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e87, 0x00ba, 0x0000, 0x02e8, 0x0000,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfbe3,
+		0xe3e9, 0x7068, 0x3075, 0x083a, 0x1ea3, 0x0f52, 0x3075, 0x083a,
+		0x1ea3, 0x0f52, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0072,
+		0x0512, 0x00f0, 0x0035, 0x04ac, 0x50ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7 } },
+	{ .channel = 118, .freq = 5590,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e8d, 0x00ba, 0x5555, 0x02e9, 0x5555,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfae3,
+		0xe3e8, 0x7068, 0x3363, 0x39b2, 0x1f90, 0x0fc8, 0x3363, 0x39b2,
+		0x1f90, 0x0fc8, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0072,
+		0x0512, 0x00f0, 0x0035, 0x04ac, 0x50ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6 } },
+	{ .channel = 120, .freq = 5600,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e95, 0x00ba, 0xaaaa, 0x02ea, 0xaaaa,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xfae2,
+		0xe2e8, 0x7068, 0x3b6e, 0x0db7, 0x1f35, 0x0f9b, 0x3b6e, 0x0db7,
+		0x1f35, 0x0f9b, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0072,
+		0x0512, 0x00f0, 0x0035, 0x04ac, 0x40ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5 } },
+	{ .channel = 122, .freq = 5610,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e9b, 0x00bb, 0x0000, 0x02ec, 0x0000,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xf9e2,
+		0xe2e8, 0x7068, 0x3af6, 0x3d7b, 0x1fdc, 0x0fee, 0x3af6, 0x3d7b,
+		0x1fdc, 0x0fee, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0072,
+		0x0512, 0x00f0, 0x0035, 0x04ac, 0x40ff, 0x18c0, 0x0001, 0x0188,
+		0x010c, 0x03e0,
+	  },
+	  .bw = { 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4 } },
+	{ .channel = 124, .freq = 5620,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0ea1, 0x00bb, 0x5555, 0x02ed, 0x5555,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xf9e1,
+		0xe1e7, 0x7068, 0x369b, 0x3b4e, 0x1f84, 0x0fc2, 0x369b, 0x3b4e,
+		0x1f84, 0x0fc2, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0062,
+		0x0402, 0x00f0, 0x0034, 0x04ac, 0x40ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3 } },
+	{ .channel = 126, .freq = 5630,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0ea9, 0x00bb, 0xaaaa, 0x02ee, 0xaaaa,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xf8e1,
+		0xe1e7, 0x7068, 0x3f15, 0x0f8a, 0x1f3b, 0x0f9e, 0x3f15, 0x0f8a,
+		0x1f3b, 0x0f9e, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0062,
+		0x0402, 0x00f0, 0x0034, 0x04ac, 0x40ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2 } },
+	{ .channel = 128, .freq = 5640,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0eaf, 0x00bc, 0x0000, 0x02f0, 0x0000,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xf8e1,
+		0xe1e6, 0x7068, 0x0000, 0x0000, 0x2000, 0x1000, 0x0000, 0x0000,
+		0x2000, 0x1000, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0061,
+		0x0401, 0x00f0, 0x0034, 0x03ac, 0x40ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2 } },
+	{ .channel = 130, .freq = 5650,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0eb5, 0x00bc, 0x5555, 0x02f1, 0x5555,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xf7e0,
+		0xe0e6, 0x7068, 0x0f68, 0x07b4, 0x1d00, 0x0e80, 0x0f68, 0x07b4,
+		0x1d00, 0x0e80, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0061,
+		0x0401, 0x00f0, 0x0034, 0x03ac, 0x40ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1 } },
+	{ .channel = 132, .freq = 5660,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0ebd, 0x00bc, 0xaaaa, 0x02f2, 0xaaaa,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xf7e0,
+		0xe0e5, 0x7068, 0x331c, 0x398e, 0x1cf2, 0x0e79, 0x331c, 0x398e,
+		0x1cf2, 0x0e79, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0061,
+		0x0301, 0x00f0, 0x0034, 0x03ac, 0x30ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0 } },
+	{ .channel = 134, .freq = 5670,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0ec3, 0x00bd, 0x0000, 0x02f4, 0x0000,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xf7df,
+		0xdfe5, 0x7068, 0x04d5, 0x026b, 0x1f86, 0x0fc3, 0x04d5, 0x026b,
+		0x1f86, 0x0fc3, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0061,
+		0x0301, 0x00f0, 0x0034, 0x03ac, 0x30ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf } },
+	{ .channel = 136, .freq = 5680,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0ec9, 0x00bd, 0x5555, 0x02f5, 0x5555,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xf6df,
+		0xdfe5, 0x7068, 0x0c2b, 0x3616, 0x1ec5, 0x0f62, 0x0c2b, 0x3616,
+		0x1ec5, 0x0f62, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0061,
+		0x0301, 0x00f0, 0x0024, 0x03ac, 0x30ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce } },
+	{ .channel = 138, .freq = 5690,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0ed1, 0x00bd, 0xaaaa, 0x02f6, 0xaaaa,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3504, 0x0006, 0x0006, 0xff06, 0xf6df,
+		0xdfe4, 0x7068, 0x3397, 0x39cc, 0x1ffe, 0x0fff, 0x3397, 0x39cc,
+		0x1ffe, 0x0fff, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0061,
+		0x0301, 0x00f0, 0x0024, 0x03ac, 0x30ff, 0x18c0, 0x0001, 0x0188,
+		0x010c, 0x03e0,
+	  },
+	  .bw = { 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce } },
+	{ .channel = 140, .freq = 5700,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0ed7, 0x00be, 0x0000, 0x02f8, 0x0000,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3503, 0x0006, 0x0006, 0xff06, 0xf5de,
+		0xdee4, 0x7068, 0x33f7, 0x09fc, 0x1f5b, 0x0fae, 0x33f7, 0x09fc,
+		0x1f5b, 0x0fae, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0051,
+		0x0300, 0x00f0, 0x0024, 0x03ac, 0x30ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd } },
+	{ .channel = 142, .freq = 5710,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0edd, 0x00be, 0x5555, 0x02f9, 0x5555,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3503, 0x0006, 0x0006, 0xff06, 0xf5de,
+		0xdee3, 0x7068, 0x0d7d, 0x36bf, 0x1ee7, 0x0f73, 0x0d7d, 0x36bf,
+		0x1ee7, 0x0f73, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0051,
+		0x0300, 0x00f0, 0x0024, 0x03ac, 0x30ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc } },
+	{ .channel = 144, .freq = 5720,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0ee5, 0x00be, 0xaaaa, 0x02fa, 0xaaaa,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3503, 0x0006, 0x0006, 0xff06, 0xf4dd,
+		0xdde3, 0x7068, 0x381b, 0x0c0e, 0x1f9b, 0x0fce, 0x381b, 0x0c0e,
+		0x1f9b, 0x0fce, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0051,
+		0x0300, 0x00f0, 0x0024, 0x03ac, 0x30ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb } },
+	{ .channel = 145, .freq = 5725,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0ee7, 0x00be, 0xd555, 0x02fb, 0x5555,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3503, 0x0006, 0x0006, 0xff06, 0xf4dd,
+		0xdde3, 0x7068, 0x36ca, 0x0b65, 0x1f63, 0x0fb2, 0x36ca, 0x0b65,
+		0x1f63, 0x0fb2, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0051,
+		0x0300, 0x00f0, 0x0023, 0x02ac, 0x20ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb } },
+	{ .channel = 146, .freq = 5730,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0eeb, 0x00bf, 0x0000, 0x02fc, 0x0000,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3503, 0x0006, 0x0006, 0xff06, 0xf4dd,
+		0xdde3, 0x7068, 0x34de, 0x0a6f, 0x1f31, 0x0f99, 0x34de, 0x0a6f,
+		0x1f31, 0x0f99, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0051,
+		0x0200, 0x00f0, 0x0023, 0x02ac, 0x20ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca } },
+	{ .channel = 147, .freq = 5735,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0eef, 0x00bf, 0x2aaa, 0x02fc, 0xaaaa,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3503, 0x0006, 0x0006, 0xff06, 0xf4dd,
+		0xdde2, 0x7068, 0x024d, 0x0127, 0x1fee, 0x0ff7, 0x024d, 0x0127,
+		0x1fee, 0x0ff7, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0051,
+		0x0200, 0x00f0, 0x0023, 0x02ac, 0x20ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca } },
+	{ .channel = 148, .freq = 5740,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0ef1, 0x00bf, 0x5555, 0x02fd, 0x5555,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3503, 0x0006, 0x0006, 0xff06, 0xf4dd,
+		0xdde2, 0x7068, 0x3e54, 0x0f2a, 0x1fb7, 0x0fdc, 0x3e54, 0x0f2a,
+		0x1fb7, 0x0fdc, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0051,
+		0x0200, 0x00f0, 0x0023, 0x02ac, 0x20ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9 } },
+	{ .channel = 149, .freq = 5745,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0ef5, 0x00bf, 0x8000, 0x02fe, 0x0000,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3503, 0x0006, 0x0006, 0xff06, 0xf3dc,
+		0xdce2, 0x7068, 0x3694, 0x0b4a, 0x1f85, 0x0fc3, 0x3694, 0x0b4a,
+		0x1f85, 0x0fc3, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0051,
+		0x0200, 0x00f0, 0x0023, 0x02ac, 0x20ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9 } },
+	{ .channel = 151, .freq = 5755,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0efb, 0x00bf, 0xd555, 0x02ff, 0x5555,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3503, 0x0006, 0x0006, 0xff06, 0xf3dc,
+		0xdce2, 0x7068, 0x035e, 0x31af, 0x1ff1, 0x0ff8, 0x035e, 0x31af,
+		0x1ff1, 0x0ff8, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0051,
+		0x0200, 0x00f0, 0x0023, 0x01ac, 0x20ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8 } },
+	{ .channel = 153, .freq = 5765,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0f03, 0x00c0, 0x2aaa, 0x0300, 0xaaaa,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3503, 0x0006, 0x0006, 0xff06, 0xf2dc,
+		0xdce1, 0x7068, 0x34c2, 0x0a61, 0x1c6b, 0x0e36, 0x34c2, 0x0a61,
+		0x1c6b, 0x0e36, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0041,
+		0x0200, 0x00f0, 0x0023, 0x01ac, 0x20ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8 } },
+	{ .channel = 155, .freq = 5775,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0f09, 0x00c0, 0x8000, 0x0302, 0x0000,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3503, 0x0006, 0x0006, 0xff06, 0xf2db,
+		0xdbe1, 0x7068, 0x045a, 0x322d, 0x1c5f, 0x0e2f, 0x045a, 0x322d,
+		0x1c5f, 0x0e2f, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0041,
+		0x0200, 0x00f0, 0x0023, 0x01ac, 0x20ff, 0x18c0, 0x0001, 0x0188,
+		0x010c, 0x03e0,
+	  },
+	  .bw = { 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7 } },
+	{ .channel = 157, .freq = 5785,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0f0f, 0x00c0, 0xd555, 0x0303, 0x5555,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3503, 0x0006, 0x0006, 0xff06, 0xf2db,
+		0xdbe0, 0x7068, 0x039d, 0x01cf, 0x1f78, 0x0fbc, 0x039d, 0x01cf,
+		0x1f78, 0x0fbc, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0040,
+		0x0200, 0x00f0, 0x0023, 0x01ac, 0x20ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6 } },
+	{ .channel = 159, .freq = 5795,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0f17, 0x00c1, 0x2aaa, 0x0304, 0xaaaa,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3503, 0x0006, 0x0006, 0xff06, 0xf1da,
+		0xdae0, 0x7068, 0x0ee3, 0x3771, 0x1e73, 0x0f39, 0x0ee3, 0x3771,
+		0x1e73, 0x0f39, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0040,
+		0x0100, 0x00f0, 0x0023, 0x01ac, 0x20ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5 } },
+	{ .channel = 161, .freq = 5805,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0f1d, 0x00c1, 0x8000, 0x0306, 0x0000,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3503, 0x0006, 0x0006, 0xff06, 0xf1da,
+		0xdae0, 0x7068, 0x3020, 0x3810, 0x1fc0, 0x0fe0, 0x3020, 0x3810,
+		0x1fc0, 0x0fe0, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0040,
+		0x0100, 0x00f0, 0x0023, 0x00ac, 0x10ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4 } },
+	{ .channel = 165, .freq = 5825,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0f2b, 0x00c2, 0x2aaa, 0x0308, 0xaaaa,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0700,
+		0x0000, 0x0000, 0x04a4, 0x3503, 0x0006, 0x0006, 0xff06, 0xf0d9,
+		0xd9df, 0x7068, 0x0941, 0x04a0, 0x1fcc, 0x0fe6, 0x0941, 0x04a0,
+		0x1fcc, 0x0fe6, 0x0000, 0x2000, 0x007f, 0x0000, 0x0070, 0x0030,
+		0x0100, 0x00f0, 0x0023, 0x00ac, 0x10ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3 } },
+	{ .channel = 1, .freq = 2412,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e21, 0x00b4, 0xe666, 0x02d3, 0x9999,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0580,
+		0x0000, 0x0000, 0x048c, 0x3503, 0x0006, 0x0006, 0xff06, 0xffea,
+		0xeaf0, 0xd068, 0x3e7a, 0x3f3d, 0x1da4, 0x0ed2, 0x3e7a, 0x3f3d,
+		0x1da4, 0x0ed2, 0x0790, 0x20e9, 0x037f, 0x0005, 0x0074, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x00ac, 0x00ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443 } },
+	{ .channel = 2, .freq = 2417,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e29, 0x00b5, 0x4666, 0x02d5, 0x1999,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0580,
+		0x0000, 0x0000, 0x048c, 0x3503, 0x0006, 0x0006, 0xff06, 0xffe9,
+		0xe9ef, 0xd068, 0x053b, 0x329d, 0x1ebb, 0x0f5d, 0x053b, 0x329d,
+		0x1ebb, 0x0f5d, 0x0790, 0x20d9, 0x027f, 0x0004, 0x0074, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x00ac, 0x00ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441 } },
+	{ .channel = 3, .freq = 2422,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e31, 0x00b5, 0xa666, 0x02d6, 0x9999,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0580,
+		0x0000, 0x0000, 0x048c, 0x3503, 0x0006, 0x0006, 0xff06, 0xffe9,
+		0xe9ef, 0xd068, 0x0871, 0x3438, 0x1f55, 0x0faa, 0x0871, 0x3438,
+		0x1f55, 0x0faa, 0x0790, 0x20d8, 0x027f, 0x0004, 0x0073, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x00ac, 0x00ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f } },
+	{ .channel = 4, .freq = 2427,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e37, 0x00b6, 0x0666, 0x02d8, 0x1999,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0580,
+		0x0000, 0x0000, 0x048c, 0x3503, 0x0006, 0x0006, 0xff06, 0xffe8,
+		0xe8ee, 0xd068, 0x01c6, 0x30e3, 0x1fb3, 0x0fd9, 0x01c6, 0x30e3,
+		0x1fb3, 0x0fd9, 0x0780, 0x20c8, 0x027f, 0x0003, 0x0073, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x00ac, 0x00ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d } },
+	{ .channel = 5, .freq = 2432,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e3f, 0x00b6, 0x6666, 0x02d9, 0x9999,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0580,
+		0x0000, 0x0000, 0x048c, 0x3503, 0x0006, 0x0006, 0xff06, 0xffe8,
+		0xe8ee, 0xd068, 0x3f40, 0x3fa0, 0x1ff0, 0x0ff8, 0x3f40, 0x3fa0,
+		0x1ff0, 0x0ff8, 0x0780, 0x20c8, 0x027f, 0x0003, 0x0073, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x00ac, 0x00ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a } },
+	{ .channel = 6, .freq = 2437,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e47, 0x00b6, 0xc666, 0x02db, 0x1999,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0580,
+		0x0000, 0x0000, 0x048c, 0x3503, 0x0006, 0x0006, 0xff06, 0xffe7,
+		0xe7ed, 0xd068, 0x3e6d, 0x3f36, 0x1f18, 0x0f8c, 0x3e6d, 0x3f36,
+		0x1f18, 0x0f8c, 0x0780, 0x20b7, 0x027f, 0x0003, 0x0073, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x00ac, 0x00ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438 } },
+	{ .channel = 7, .freq = 2442,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e4f, 0x00b7, 0x2666, 0x02dc, 0x9999,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0580,
+		0x0000, 0x0000, 0x048c, 0x3503, 0x0006, 0x0006, 0xff06, 0xffe7,
+		0xe7ed, 0xd068, 0x35da, 0x0aed, 0x1f4f, 0x0fa8, 0x35da, 0x0aed,
+		0x1f4f, 0x0fa8, 0x0670, 0x20b7, 0x017f, 0x0003, 0x0073, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x00ac, 0x00ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436 } },
+	{ .channel = 8, .freq = 2447,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e55, 0x00b7, 0x8666, 0x02de, 0x1999,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0580,
+		0x0000, 0x0000, 0x048c, 0x3503, 0x0006, 0x0006, 0xff06, 0xfee6,
+		0xe6ec, 0xd068, 0x3d98, 0x3ecc, 0x1f78, 0x0fbc, 0x3d98, 0x3ecc,
+		0x1f78, 0x0fbc, 0x0670, 0x20a7, 0x017f, 0x0003, 0x0073, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x00ac, 0x00ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434 } },
+	{ .channel = 9, .freq = 2452,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e5d, 0x00b7, 0xe666, 0x02df, 0x9999,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0580,
+		0x0000, 0x0000, 0x048c, 0x3503, 0x0006, 0x0006, 0xff06, 0xfee6,
+		0xe6ec, 0xd068, 0x3667, 0x3b34, 0x1f96, 0x0fcb, 0x3667, 0x3b34,
+		0x1f96, 0x0fcb, 0x0670, 0x20a7, 0x017f, 0x0003, 0x0073, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x00ac, 0x00ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431 } },
+	{ .channel = 10, .freq = 2457,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e65, 0x00b8, 0x4666, 0x02e1, 0x1999,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0580,
+		0x0000, 0x0000, 0x048c, 0x3503, 0x0006, 0x0006, 0xff06, 0xfde5,
+		0xe5eb, 0xd068, 0x37e1, 0x0bf0, 0x1873, 0x0c3a, 0x37e1, 0x0bf0,
+		0x1873, 0x0c3a, 0x0670, 0x20a7, 0x017f, 0x0003, 0x0073, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x00ac, 0x00ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f } },
+	{ .channel = 11, .freq = 2462,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e6d, 0x00b8, 0xa666, 0x02e2, 0x9999,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0580,
+		0x0000, 0x0000, 0x048c, 0x3503, 0x0006, 0x0006, 0xff06, 0xfde5,
+		0xe5eb, 0xd068, 0x3600, 0x3b00, 0x1cd6, 0x0e6b, 0x3600, 0x3b00,
+		0x1cd6, 0x0e6b, 0x0670, 0x2097, 0x017f, 0x0003, 0x0073, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x00ac, 0x00ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d } },
+	{ .channel = 12, .freq = 2467,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e73, 0x00b9, 0x0666, 0x02e4, 0x1999,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0580,
+		0x0000, 0x0000, 0x048c, 0x3503, 0x0006, 0x0006, 0xff06, 0xfce4,
+		0xe4ea, 0xd068, 0x3a75, 0x0d3b, 0x1e41, 0x0f21, 0x3a75, 0x0d3b,
+		0x1e41, 0x0f21, 0x0670, 0x2097, 0x017f, 0x0003, 0x0073, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x00ac, 0x00ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b } },
+	{ .channel = 13, .freq = 2472,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e7b, 0x00b9, 0x6666, 0x02e5, 0x9999,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0580,
+		0x0000, 0x0000, 0x048c, 0x3503, 0x0006, 0x0006, 0xff06, 0xfbe4,
+		0xe4ea, 0xd068, 0x3ed4, 0x3f6a, 0x1eee, 0x0f77, 0x3ed4, 0x3f6a,
+		0x1eee, 0x0f77, 0x0570, 0x2087, 0x017f, 0x0003, 0x0073, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x00ac, 0x00ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429 } },
+	{ .channel = 14, .freq = 2484,
+	  .radio = {
+		0x0005, 0x001e, 0x0a09, 0x0e8d, 0x00ba, 0x4ccc, 0x02e9, 0x3333,
+		0x0000, 0x0488, 0x0cef, 0x0000, 0x000b, 0x1d6f, 0x1f00, 0x0580,
+		0x0000, 0x0000, 0x048c, 0x3503, 0x0006, 0x0006, 0xff06, 0xfae3,
+		0xe3e8, 0xd068, 0x33a0, 0x39d0, 0x1f1e, 0x0f8f, 0x33a0, 0x39d0,
+		0x1f1e, 0x0f8f, 0x0570, 0x2076, 0x007f, 0x0003, 0x0073, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x00ac, 0x00ff, 0x18c0, 0x0001, 0x0185,
+		0x00ac, 0x03e0,
+	  },
+	  .bw = { 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424 } },
+};
+
+const unsigned int b43_radio_2069r4_chans_n =
+	ARRAY_SIZE(b43_radio_2069r4_chans);
diff --git a/drivers/net/wireless/broadcom/b43/radio_2069.h b/drivers/net/wireless/broadcom/b43/radio_2069.h
new file mode 100644
index 0000000..097d3cd
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/radio_2069.h
@@ -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_ */
diff --git a/drivers/net/wireless/broadcom/b43/tables_phy_ac.c b/drivers/net/wireless/broadcom/b43/tables_phy_ac.c
new file mode 100644
index 0000000..ba95635
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/tables_phy_ac.c
@@ -0,0 +1,1273 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * AC-PHY rev 0/1 init tables. Generated by tools/gen_tables_phy_ac.py.
+ *
+ * Copyright (c) 2026 Alessio Ferri <alessio.ferri@mythread.it>
+ * Copyright (c) 2026 Andreas Wendleder <gonsolo@gmail.com>
+ */
+
+#include "b43.h"
+#include "tables_phy_ac.h"
+
+/* acphy_mcs_tbl_rev0 */
+static const u16 b43_acphy_tbl_00[] = {
+	0x0000, 0x0008, 0x000a, 0x0010, 0x0012, 0x0019, 0x001a, 0x001c, 0x0080,
+	0x0088, 0x008a, 0x0090,
+	0x0092, 0x0099, 0x009a, 0x009c, 0x0100, 0x0108, 0x010a, 0x0110, 0x0112,
+	0x0119, 0x011a, 0x011c,
+	0x0180, 0x0188, 0x018a, 0x0190, 0x0192, 0x0199, 0x019a, 0x019c, 0x0000,
+	0x0098, 0x00a0, 0x00a8,
+	0x009a, 0x00a2, 0x00aa, 0x0120, 0x0128, 0x0128, 0x0130, 0x0138, 0x0138,
+	0x0140, 0x0122, 0x012a,
+	0x012a, 0x0132, 0x013a, 0x013a, 0x0142, 0x01a8, 0x01b0, 0x01b8, 0x01b0,
+	0x01b8, 0x01c0, 0x01c8,
+	0x01c0, 0x01c8, 0x01d0, 0x01d0, 0x01d8, 0x01aa, 0x01b2, 0x01ba, 0x01b2,
+	0x01ba, 0x01c2, 0x01ca,
+	0x01c2, 0x01ca, 0x01d2, 0x01d2, 0x01da, 0x0001, 0x0002, 0x0004, 0x0009,
+	0x000c, 0x0011, 0x0014,
+	0x0018, 0x0020, 0x0021, 0x0022, 0x0024, 0x0081, 0x0082, 0x0084, 0x0089,
+	0x008c, 0x0091, 0x0094,
+	0x0098, 0x00a0, 0x00a1, 0x00a2, 0x00a4, 0x0007, 0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+};
+
+/* acphy_tx_evm_tbl_rev0 */
+static const u8 b43_acphy_tbl_01[] = {
+	0x09, 0x0e, 0x11, 0x14, 0x17, 0x1a, 0x1d, 0x20, 0x09, 0x0e, 0x11, 0x14,
+	0x17, 0x1a, 0x1d, 0x20, 0x22, 0x24, 0x09, 0x0e, 0x11, 0x14, 0x17, 0x1a,
+	0x1d, 0x20, 0x22, 0x24, 0x09, 0x0e, 0x11, 0x14, 0x17, 0x1a, 0x1d, 0x20,
+	0x22, 0x24,
+};
+
+/* acphy_rx_evm_shaping_tbl_rev0 */
+static const u8 b43_acphy_tbl_02[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+};
+
+/* acphy_noise_shaping_tbl_rev0 */
+static const u32 b43_acphy_tbl_03[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+};
+
+/* acphy_phasetrack_tbl_rev0 */
+static const u32 b43_acphy_tbl_04[] = {
+	0x00035700, 0x0002cc9a, 0x00026666, 0x0001581f, 0x0001581f, 0x0001581f,
+	0x0001581f, 0x0001581f,
+	0x0001581f, 0x0001581f, 0x0001581f, 0x00035700, 0x0002cc9a, 0x00026666,
+	0x0001581f, 0x0001581f,
+	0x0001581f, 0x0001581f, 0x0001581f, 0x0001581f, 0x0001581f, 0x0001581f,
+};
+
+/* acphy_est_pwr_lut_core0_rev0 */
+static const u16 b43_acphy_tbl_05[] = {
+	0x554a, 0x554a, 0x544a, 0x544a, 0x5449, 0x5449, 0x5349, 0x5349, 0x5248,
+	0x5249, 0x5248, 0x5248,
+	0x5147, 0x5147, 0x5147, 0x5147, 0x5046, 0x5046, 0x4f46, 0x4f46, 0x4f45,
+	0x4f45, 0x4e44, 0x4e44,
+	0x4e44, 0x4e44, 0x4d43, 0x4d43, 0x4c43, 0x4c43, 0x4c42, 0x4c42, 0x4b42,
+	0x4b42, 0x4a41, 0x4a41,
+	0x4940, 0x4940, 0x4940, 0x4940, 0x483f, 0x483f, 0x473e, 0x473e, 0x463e,
+	0x463e, 0x463d, 0x463d,
+	0x453c, 0x453c, 0x443b, 0x443b, 0x433b, 0x433b, 0x423a, 0x423a, 0x4139,
+	0x4139, 0x4038, 0x4038,
+	0x4037, 0x4037, 0x3f36, 0x3f36, 0x3e36, 0x3e36, 0x3d35, 0x3d35, 0x3c34,
+	0x3b34, 0x3a33, 0x3a33,
+	0x3932, 0x3932, 0x3831, 0x3830, 0x372f, 0x372f, 0x362e, 0x362e, 0x352d,
+	0x342d, 0x332c, 0x332c,
+	0x322b, 0x322a, 0x3129, 0x3029, 0x2f28, 0x2f27, 0x2e26, 0x2d26, 0x2c25,
+	0x2c24, 0x2b23, 0x2a23,
+	0x2922, 0x2821, 0x2720, 0x261f, 0x251e, 0x241d, 0x231c, 0x221b, 0x211a,
+	0x2019, 0x1f17, 0x1e16,
+	0x1d15, 0x1c14, 0x1a12, 0x1911, 0x180f, 0x170e, 0x150c, 0x140a, 0x1208,
+	0x1006, 0x0e03, 0x0d01,
+	0x0bfe, 0x09fb, 0x07f8, 0x05f5, 0x02f1, 0x00ec, 0xfde7, 0xfde7,
+};
+
+/* acphy_est_pwr_lut_core1_rev0 */
+static const u16 b43_acphy_tbl_06[] = {
+	0x554a, 0x554a, 0x544a, 0x544a, 0x5449, 0x5449, 0x5349, 0x5349, 0x5248,
+	0x5249, 0x5248, 0x5248,
+	0x5147, 0x5147, 0x5147, 0x5147, 0x5046, 0x5046, 0x4f46, 0x4f46, 0x4f45,
+	0x4f45, 0x4e44, 0x4e44,
+	0x4e44, 0x4e44, 0x4d43, 0x4d43, 0x4c43, 0x4c43, 0x4c42, 0x4c42, 0x4b42,
+	0x4b42, 0x4a41, 0x4a41,
+	0x4940, 0x4940, 0x4940, 0x4940, 0x483f, 0x483f, 0x473e, 0x473e, 0x463e,
+	0x463e, 0x463d, 0x463d,
+	0x453c, 0x453c, 0x443b, 0x443b, 0x433b, 0x433b, 0x423a, 0x423a, 0x4139,
+	0x4139, 0x4038, 0x4038,
+	0x4037, 0x4037, 0x3f36, 0x3f36, 0x3e36, 0x3e36, 0x3d35, 0x3d35, 0x3c34,
+	0x3b34, 0x3a33, 0x3a33,
+	0x3932, 0x3932, 0x3831, 0x3830, 0x372f, 0x372f, 0x362e, 0x362e, 0x352d,
+	0x342d, 0x332c, 0x332c,
+	0x322b, 0x322a, 0x3129, 0x3029, 0x2f28, 0x2f27, 0x2e26, 0x2d26, 0x2c25,
+	0x2c24, 0x2b23, 0x2a23,
+	0x2922, 0x2821, 0x2720, 0x261f, 0x251e, 0x241d, 0x231c, 0x221b, 0x211a,
+	0x2019, 0x1f17, 0x1e16,
+	0x1d15, 0x1c14, 0x1a12, 0x1911, 0x180f, 0x170e, 0x150c, 0x140a, 0x1208,
+	0x1006, 0x0e03, 0x0d01,
+	0x0bfe, 0x09fb, 0x07f8, 0x05f5, 0x02f1, 0x00ec, 0xfde7, 0xfde7,
+};
+
+/* acphy_est_pwr_lut_core2_rev0 */
+static const u16 b43_acphy_tbl_07[] = {
+	0x554a, 0x554a, 0x544a, 0x544a, 0x5449, 0x5449, 0x5349, 0x5349, 0x5248,
+	0x5249, 0x5248, 0x5248,
+	0x5147, 0x5147, 0x5147, 0x5147, 0x5046, 0x5046, 0x4f46, 0x4f46, 0x4f45,
+	0x4f45, 0x4e44, 0x4e44,
+	0x4e44, 0x4e44, 0x4d43, 0x4d43, 0x4c43, 0x4c43, 0x4c42, 0x4c42, 0x4b42,
+	0x4b42, 0x4a41, 0x4a41,
+	0x4940, 0x4940, 0x4940, 0x4940, 0x483f, 0x483f, 0x473e, 0x473e, 0x463e,
+	0x463e, 0x463d, 0x463d,
+	0x453c, 0x453c, 0x443b, 0x443b, 0x433b, 0x433b, 0x423a, 0x423a, 0x4139,
+	0x4139, 0x4038, 0x4038,
+	0x4037, 0x4037, 0x3f36, 0x3f36, 0x3e36, 0x3e36, 0x3d35, 0x3d35, 0x3c34,
+	0x3b34, 0x3a33, 0x3a33,
+	0x3932, 0x3932, 0x3831, 0x3830, 0x372f, 0x372f, 0x362e, 0x362e, 0x352d,
+	0x342d, 0x332c, 0x332c,
+	0x322b, 0x322a, 0x3129, 0x3029, 0x2f28, 0x2f27, 0x2e26, 0x2d26, 0x2c25,
+	0x2c24, 0x2b23, 0x2a23,
+	0x2922, 0x2821, 0x2720, 0x261f, 0x251e, 0x241d, 0x231c, 0x221b, 0x211a,
+	0x2019, 0x1f17, 0x1e16,
+	0x1d15, 0x1c14, 0x1a12, 0x1911, 0x180f, 0x170e, 0x150c, 0x140a, 0x1208,
+	0x1006, 0x0e03, 0x0d01,
+	0x0bfe, 0x09fb, 0x07f8, 0x05f5, 0x02f1, 0x00ec, 0xfde7, 0xfde7,
+};
+
+/* acphy_iq_lut_core0_rev0 */
+static const u32 b43_acphy_tbl_08[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+};
+
+/* acphy_iq_lut_core0_rev0 */
+static const u32 b43_acphy_tbl_09[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+};
+
+/* acphy_iq_lut_core2_rev0 */
+static const u32 b43_acphy_tbl_10[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000,
+};
+
+/* acphy_loft_lut_core0_rev0 */
+static const u16 b43_acphy_tbl_11[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+/* acphy_loft_lut_core1_rev0 */
+static const u16 b43_acphy_tbl_12[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+/* acphy_loft_lut_core2_rev0 */
+static const u16 b43_acphy_tbl_13[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+/* acphy_papd_comp_rfpwr_tbl_core0_rev0 */
+static const u16 b43_acphy_tbl_14[] = {
+	0x0048, 0x0047, 0x0046, 0x0044, 0x0043, 0x0042, 0x0040, 0x003f, 0x003e,
+	0x003c, 0x003a, 0x0038,
+	0x0037, 0x0035, 0x0033, 0x0031, 0x002e, 0x002c, 0x002a, 0x0027, 0x0024,
+	0x0020, 0x001d, 0x0019,
+	0x0019, 0x0019, 0x0019, 0x0014, 0x0014, 0x0014, 0x000f, 0x000f, 0x000f,
+	0x0008, 0x0008, 0x0008,
+	0x0008, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0xfff7, 0xfff7, 0xfff7,
+	0xfff7, 0xfff7, 0xfff7,
+	0xfff7, 0xffe8, 0xffe8, 0xffe8, 0xffe8, 0xffe8, 0xffe8, 0xffe8, 0xffe8,
+	0xffe8, 0xffe8, 0xffe8,
+	0xffe8, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
+};
+
+/* acphy_papd_comp_rfpwr_tbl_core1_rev0 */
+static const u16 b43_acphy_tbl_15[] = {
+	0x0048, 0x0047, 0x0046, 0x0044, 0x0043, 0x0042, 0x0040, 0x003f, 0x003e,
+	0x003c, 0x003a, 0x0038,
+	0x0037, 0x0035, 0x0033, 0x0031, 0x002e, 0x002c, 0x002a, 0x0027, 0x0024,
+	0x0020, 0x001d, 0x0019,
+	0x0019, 0x0019, 0x0019, 0x0014, 0x0014, 0x0014, 0x000f, 0x000f, 0x000f,
+	0x0008, 0x0008, 0x0008,
+	0x0008, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0xfff7, 0xfff7, 0xfff7,
+	0xfff7, 0xfff7, 0xfff7,
+	0xfff7, 0xffe8, 0xffe8, 0xffe8, 0xffe8, 0xffe8, 0xffe8, 0xffe8, 0xffe8,
+	0xffe8, 0xffe8, 0xffe8,
+	0xffe8, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
+};
+
+/* acphy_papd_comp_rfpwr_tbl_core2_rev0 */
+static const u16 b43_acphy_tbl_16[] = {
+	0x0048, 0x0047, 0x0046, 0x0044, 0x0043, 0x0042, 0x0040, 0x003f, 0x003e,
+	0x003c, 0x003a, 0x0038,
+	0x0037, 0x0035, 0x0033, 0x0031, 0x002e, 0x002c, 0x002a, 0x0027, 0x0024,
+	0x0020, 0x001d, 0x0019,
+	0x0019, 0x0019, 0x0019, 0x0014, 0x0014, 0x0014, 0x000f, 0x000f, 0x000f,
+	0x0008, 0x0008, 0x0008,
+	0x0008, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0xfff7, 0xfff7, 0xfff7,
+	0xfff7, 0xfff7, 0xfff7,
+	0xfff7, 0xffe8, 0xffe8, 0xffe8, 0xffe8, 0xffe8, 0xffe8, 0xffe8, 0xffe8,
+	0xffe8, 0xffe8, 0xffe8,
+	0xffe8, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0,
+	0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0, 0xffd0,
+};
+
+/* acphy_papd_comp_epsilon_tbl_core0_rev0 */
+static const u32 b43_acphy_tbl_17[] = {
+	0x00000000, 0x03fdfffe, 0x00002003, 0x03fe4001, 0x03ff000a, 0x03fea003,
+	0x03fe7fff, 0x03fe9fff,
+	0x03fee00a, 0x00000029, 0x0001403c, 0x0002004b, 0x0003a04b, 0x0004a04e,
+	0x0005e051, 0x0007004a,
+	0x0008003f, 0x00092034, 0x000aa02f, 0x000ba024, 0x000d2022, 0x000e8021,
+	0x0010001e, 0x0011e01c,
+	0x0013c018, 0x00152014, 0x00172010, 0x0019200a, 0x001a7ff9, 0x001bffe9,
+	0x001d7fd9, 0x001f1fc9,
+	0x0020bfb9, 0x0021ffa7, 0x00233f95, 0x00243f84, 0x00257f73, 0x00269f63,
+	0x00283f57, 0x002a1f53,
+	0x002bff4c, 0x002e3f4a, 0x002fbf3e, 0x0030ff2f, 0x00321f21, 0x00339f12,
+	0x0034df02, 0x00359eee,
+	0x0035ded8, 0x00361ec1, 0x0036beac, 0x00373e96, 0x0037de82, 0x003e5ea3,
+	0x004b5ef3, 0x0056bf29,
+	0x0061bf51, 0x00723fb9, 0x00926203, 0x01308ef5, 0x0152cfff, 0x01516fff,
+	0x014f6fff, 0x014e6fff,
+};
+
+/* acphy_papd_comp_epsilon_tbl_core1_rev0 */
+static const u32 b43_acphy_tbl_18[] = {
+	0x00000000, 0x03fdfffe, 0x00002003, 0x03fe4001, 0x03ff000a, 0x03fea003,
+	0x03fe7fff, 0x03fe9fff,
+	0x03fee00a, 0x00000029, 0x0001403c, 0x0002004b, 0x0003a04b, 0x0004a04e,
+	0x0005e051, 0x0007004a,
+	0x0008003f, 0x00092034, 0x000aa02f, 0x000ba024, 0x000d2022, 0x000e8021,
+	0x0010001e, 0x0011e01c,
+	0x0013c018, 0x00152014, 0x00172010, 0x0019200a, 0x001a7ff9, 0x001bffe9,
+	0x001d7fd9, 0x001f1fc9,
+	0x0020bfb9, 0x0021ffa7, 0x00233f95, 0x00243f84, 0x00257f73, 0x00269f63,
+	0x00283f57, 0x002a1f53,
+	0x002bff4c, 0x002e3f4a, 0x002fbf3e, 0x0030ff2f, 0x00321f21, 0x00339f12,
+	0x0034df02, 0x00359eee,
+	0x0035ded8, 0x00361ec1, 0x0036beac, 0x00373e96, 0x0037de82, 0x003e5ea3,
+	0x004b5ef3, 0x0056bf29,
+	0x0061bf51, 0x00723fb9, 0x00926203, 0x01308ef5, 0x0152cfff, 0x01516fff,
+	0x014f6fff, 0x014e6fff,
+};
+
+/* acphy_papd_comp_epsilon_tbl_core2_rev0 */
+static const u32 b43_acphy_tbl_19[] = {
+	0x00000000, 0x03fdfffe, 0x00002003, 0x03fe4001, 0x03ff000a, 0x03fea003,
+	0x03fe7fff, 0x03fe9fff,
+	0x03fee00a, 0x00000029, 0x0001403c, 0x0002004b, 0x0003a04b, 0x0004a04e,
+	0x0005e051, 0x0007004a,
+	0x0008003f, 0x00092034, 0x000aa02f, 0x000ba024, 0x000d2022, 0x000e8021,
+	0x0010001e, 0x0011e01c,
+	0x0013c018, 0x00152014, 0x00172010, 0x0019200a, 0x001a7ff9, 0x001bffe9,
+	0x001d7fd9, 0x001f1fc9,
+	0x0020bfb9, 0x0021ffa7, 0x00233f95, 0x00243f84, 0x00257f73, 0x00269f63,
+	0x00283f57, 0x002a1f53,
+	0x002bff4c, 0x002e3f4a, 0x002fbf3e, 0x0030ff2f, 0x00321f21, 0x00339f12,
+	0x0034df02, 0x00359eee,
+	0x0035ded8, 0x00361ec1, 0x0036beac, 0x00373e96, 0x0037de82, 0x003e5ea3,
+	0x004b5ef3, 0x0056bf29,
+	0x0061bf51, 0x00723fb9, 0x00926203, 0x01308ef5, 0x0152cfff, 0x01516fff,
+	0x014f6fff, 0x014e6fff,
+};
+
+/* acphy_papd_cal_scalars_tbl_core0_rev0 */
+static const u32 b43_acphy_tbl_20[] = {
+	0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035, 0x09220038, 0x08ab003b,
+	0x081f003f, 0x07a20043,
+	0x07340047, 0x06d2004b, 0x067a004f, 0x06170054, 0x05bf0059, 0x0571005e,
+	0x051e0064, 0x04d3006a,
+	0x04910070, 0x044c0077, 0x040f007e, 0x03d90085, 0x03a1008d, 0x036f0095,
+	0x033d009e, 0x030b00a8,
+	0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3, 0x024900e0, 0x022900ed,
+	0x020a00fb, 0x01ec010a,
+	0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e, 0x01720162, 0x015d0177,
+	0x0149018e, 0x013701a5,
+	0x012601be, 0x011501d8, 0x010601f4, 0x00f70212, 0x00e90231, 0x00dc0253,
+	0x00d00276, 0x00c4029b,
+	0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348, 0x0093037a, 0x008b03af,
+	0x008303e6, 0x007c0422,
+	0x00750460, 0x006e04a3, 0x006804e9, 0x00620533, 0x005d0582, 0x005805d6,
+	0x0053062e, 0x004e068c,
+};
+
+/* acphy_papd_cal_scalars_tbl_core1_rev0 */
+static const u32 b43_acphy_tbl_21[] = {
+	0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035, 0x09220038, 0x08ab003b,
+	0x081f003f, 0x07a20043,
+	0x07340047, 0x06d2004b, 0x067a004f, 0x06170054, 0x05bf0059, 0x0571005e,
+	0x051e0064, 0x04d3006a,
+	0x04910070, 0x044c0077, 0x040f007e, 0x03d90085, 0x03a1008d, 0x036f0095,
+	0x033d009e, 0x030b00a8,
+	0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3, 0x024900e0, 0x022900ed,
+	0x020a00fb, 0x01ec010a,
+	0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e, 0x01720162, 0x015d0177,
+	0x0149018e, 0x013701a5,
+	0x012601be, 0x011501d8, 0x010601f4, 0x00f70212, 0x00e90231, 0x00dc0253,
+	0x00d00276, 0x00c4029b,
+	0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348, 0x0093037a, 0x008b03af,
+	0x008303e6, 0x007c0422,
+	0x00750460, 0x006e04a3, 0x006804e9, 0x00620533, 0x005d0582, 0x005805d6,
+	0x0053062e, 0x004e068c,
+};
+
+/* acphy_papd_cal_scalars_tbl_core2_rev0 */
+static const u32 b43_acphy_tbl_22[] = {
+	0x0b5e002d, 0x0ae2002f, 0x0a3b0032, 0x09a70035, 0x09220038, 0x08ab003b,
+	0x081f003f, 0x07a20043,
+	0x07340047, 0x06d2004b, 0x067a004f, 0x06170054, 0x05bf0059, 0x0571005e,
+	0x051e0064, 0x04d3006a,
+	0x04910070, 0x044c0077, 0x040f007e, 0x03d90085, 0x03a1008d, 0x036f0095,
+	0x033d009e, 0x030b00a8,
+	0x02e000b2, 0x02b900bc, 0x029200c7, 0x026d00d3, 0x024900e0, 0x022900ed,
+	0x020a00fb, 0x01ec010a,
+	0x01d20119, 0x01b7012a, 0x019e013c, 0x0188014e, 0x01720162, 0x015d0177,
+	0x0149018e, 0x013701a5,
+	0x012601be, 0x011501d8, 0x010601f4, 0x00f70212, 0x00e90231, 0x00dc0253,
+	0x00d00276, 0x00c4029b,
+	0x00b902c3, 0x00af02ed, 0x00a50319, 0x009c0348, 0x0093037a, 0x008b03af,
+	0x008303e6, 0x007c0422,
+	0x00750460, 0x006e04a3, 0x006804e9, 0x00620533, 0x005d0582, 0x005805d6,
+	0x0053062e, 0x004e068c,
+};
+
+/* ppr (power per rate) table: all zero until TX power control programs it */
+static const u32 b43_acphy_tbl_ppr[24];
+
+const struct b43_phy_ac_tbl b43_phy_ac_tbls_rev0[] = {
+	{ b43_acphy_tbl_00, 128, 1, 0, 16 },
+	{ b43_acphy_tbl_01, 38, 2, 0, 8 },
+	{ b43_acphy_tbl_02, 256, 4, 0, 8 },
+	{ b43_acphy_tbl_03, 256, 3, 0, 32 },
+	{ b43_acphy_tbl_04, 22, 5, 0, 32 },
+	{ b43_acphy_tbl_05, 128, 64, 0, 16 },
+	{ b43_acphy_tbl_06, 128, 96, 0, 16 },
+	{ b43_acphy_tbl_07, 128, 128, 0, 16 },
+	{ b43_acphy_tbl_08, 128, 65, 0, 32 },
+	{ b43_acphy_tbl_09, 128, 97, 0, 32 },
+	{ b43_acphy_tbl_10, 128, 129, 0, 32 },
+	{ b43_acphy_tbl_11, 128, 66, 0, 16 },
+	{ b43_acphy_tbl_12, 128, 98, 0, 16 },
+	{ b43_acphy_tbl_13, 128, 130, 0, 16 },
+	{ b43_acphy_tbl_14, 128, 64, 0, 16 },
+	{ b43_acphy_tbl_15, 128, 96, 0, 16 },
+	{ b43_acphy_tbl_16, 128, 128, 0, 16 },
+	{ b43_acphy_tbl_17, 64, 71, 0, 32 },
+	{ b43_acphy_tbl_18, 64, 103, 0, 32 },
+	{ b43_acphy_tbl_19, 64, 135, 0, 32 },
+	{ b43_acphy_tbl_20, 64, 72, 0, 32 },
+	{ b43_acphy_tbl_21, 64, 104, 0, 32 },
+	{ b43_acphy_tbl_22, 64, 136, 0, 32 },
+	{ b43_acphy_tbl_ppr, 24, 0x21, 0, 32 },
+};
+
+const unsigned int b43_phy_ac_tbls_rev0_n = ARRAY_SIZE(b43_phy_ac_tbls_rev0);
+/*
+ * RF sequencer tables (table id 7), previously replayed from the vendor
+ * driver's first-load capture. Opcode names after Alessio Ferri's tree; values
+ * are what core revision 42 holds after the vendor driver's init.
+ */
+enum {
+	RFSEQ_NOP = 0x00,
+	RFSEQ_RXG_FBW = 0x01,
+	RFSEQ_TR_SWITCH = 0x02,
+	RFSEQ_INT_PA_PU = 0x03,
+	RFSEQ_EXT_PA = 0x04,
+	RFSEQ_RXPD_TXPD = 0x05,
+	RFSEQ_TX_GAIN = 0x06,
+	RFSEQ_RX_GAIN = 0x07,
+	RFSEQ_CLR_HIQ_DIS = 0x08,
+	RFSEQ_SET_LPF_H_HPC = 0x0a,
+	RFSEQ_SET_LPF_M_HPC = 0x0c,
+	RFSEQ_SET_LPF_L_HPC = 0x0e,
+	RFSEQ_CLR_RXRX_BIAS = 0x0f,
+	RFSEQ_END = 0x1f,
+	RFSEQ_UNK_2A = 0x2a,
+	RFSEQ_UNK_2B = 0x2b,
+	RFSEQ_UNK_35 = 0x35,
+	RFSEQ_UNK_36 = 0x36,
+	RFSEQ_UNK_B3 = 0xb3,
+};
+
+/* receive -> transmit sequencer commands, table 7 @ 0x0 */
+static const u16 b43_rfseq_rx2tx_cmd[] = {
+	RFSEQ_NOP, RFSEQ_RXG_FBW, RFSEQ_TR_SWITCH, RFSEQ_CLR_HIQ_DIS,
+	RFSEQ_RXPD_TXPD, RFSEQ_NOP, RFSEQ_TX_GAIN, RFSEQ_INT_PA_PU,
+	RFSEQ_CLR_RXRX_BIAS, RFSEQ_EXT_PA, RFSEQ_NOP, RFSEQ_UNK_35,
+	RFSEQ_CLR_RXRX_BIAS, RFSEQ_NOP, RFSEQ_UNK_36, RFSEQ_END,
+};
+
+/*
+ * transmit -> receive (starts with an extra 0xb3 opcode on core rev 42), table
+ * 7 @ 0x10
+ */
+static const u16 b43_rfseq_tx2rx_cmd[] = {
+	RFSEQ_UNK_B3, RFSEQ_EXT_PA, RFSEQ_INT_PA_PU, RFSEQ_TX_GAIN,
+	RFSEQ_RXPD_TXPD, RFSEQ_NOP, RFSEQ_TR_SWITCH, RFSEQ_RXG_FBW,
+	RFSEQ_CLR_HIQ_DIS, RFSEQ_UNK_2A, RFSEQ_CLR_RXRX_BIAS, RFSEQ_NOP,
+	RFSEQ_CLR_RXRX_BIAS, RFSEQ_UNK_2B, RFSEQ_END, RFSEQ_END,
+};
+
+/* reset -> receive, table 7 @ 0x20 */
+static const u16 b43_rfseq_reset2rx_cmd[] = {
+	RFSEQ_EXT_PA, RFSEQ_INT_PA_PU, RFSEQ_TX_GAIN, RFSEQ_RXPD_TXPD,
+	RFSEQ_TR_SWITCH, RFSEQ_RXG_FBW, RFSEQ_CLR_HIQ_DIS, RFSEQ_UNK_2A,
+	RFSEQ_UNK_2B, RFSEQ_CLR_RXRX_BIAS, RFSEQ_END, RFSEQ_END,
+	RFSEQ_END, RFSEQ_END, RFSEQ_END, RFSEQ_END,
+};
+
+/* second sequencer, core 0, table 7 @ 0x30 */
+static const u16 b43_rfseq_rfseq2_cmd_c0[] = {
+	RFSEQ_UNK_2A, RFSEQ_RX_GAIN, RFSEQ_SET_LPF_H_HPC, RFSEQ_NOP,
+	RFSEQ_CLR_HIQ_DIS, RFSEQ_UNK_2B, RFSEQ_END, RFSEQ_END,
+};
+
+/* second sequencer, core 1, table 7 @ 0x40 */
+static const u16 b43_rfseq_rfseq2_cmd_c1[] = {
+	RFSEQ_UNK_2A, RFSEQ_RX_GAIN, RFSEQ_CLR_HIQ_DIS, RFSEQ_SET_LPF_M_HPC,
+	RFSEQ_SET_LPF_L_HPC, RFSEQ_UNK_2B, RFSEQ_END, RFSEQ_END,
+};
+
+/* second sequencer, core 2, table 7 @ 0x50 */
+static const u16 b43_rfseq_rfseq2_cmd_c2[] = {
+	RFSEQ_UNK_2A, RFSEQ_RX_GAIN, RFSEQ_CLR_HIQ_DIS, RFSEQ_SET_LPF_L_HPC,
+	RFSEQ_UNK_2B, RFSEQ_END, RFSEQ_END, RFSEQ_END,
+};
+
+/* rx2tx/tx2rx delays, table 7 @ 0x80 */
+static const u16 b43_rfseq_dly_80[] = {
+	0x0001, 0x0008, 0x0004, 0x0002,
+	0x0002, 0x0001, 0x0003, 0x0004,
+	0x0006, 0x0004, 0x000a, 0x0004,
+	0x0002, 0x0001, 0x0001, 0x0001,
+};
+
+/* reset2rx delays, table 7 @ 0x90 */
+static const u16 b43_rfseq_reset2rx_dly[] = {
+	0x000c, 0x0002, 0x0002, 0x0004,
+	0x0004, 0x0006, 0x0001, 0x0004,
+	0x0001, 0x0002, 0x0001, 0x0001,
+	0x0001, 0x0001, 0x0001, 0x0001,
+};
+
+/* rfseq2 delays, core 0, table 7 @ 0xa0 */
+static const u16 b43_rfseq_dly_a[] = {
+	0x0001, 0x0002, 0x0002, 0x0002,
+	0x0010, 0x0001, 0x0001, 0x0001,
+};
+
+/* rfseq2 delays, core 1, table 7 @ 0xb0 */
+static const u16 b43_rfseq_dly_b[] = {
+	0x0001, 0x0006, 0x0012, 0x0008,
+	0x0010, 0x0001, 0x0001, 0x0001,
+};
+
+/* rfseq2 delays, core 2, table 7 @ 0xc0 */
+static const u16 b43_rfseq_dly_c[] = {
+	0x0001, 0x0006, 0x001e, 0x001c,
+	0x0001, 0x0001, 0x0001, 0x0001,
+};
+
+/* rfseq update-delay cells, table 7 @ 0x121 */
+static const u16 b43_rfseq_updl_lpf_hpc0[] = {
+	0x0aaa, 0x0aaa,
+};
+
+/* rfseq update-delay cells, table 7 @ 0x124 */
+static const u16 b43_rfseq_updl_tia_hpc0[] = {
+	0x0222, 0x0222,
+};
+
+/* rfseq update-delay cells, table 7 @ 0x131 */
+static const u16 b43_rfseq_updl_lpf_hpc1[] = {
+	0x0aaa, 0x0aaa,
+};
+
+/* rfseq update-delay cells, table 7 @ 0x137 */
+static const u16 b43_rfseq_updl_tia_hpc1[] = {
+	0x0222, 0x0222,
+};
+
+const struct b43_phy_ac_tbl b43_phy_ac_rfseq_tbls[] = {
+	{ b43_rfseq_rx2tx_cmd, 16, 7, 0x0, 16 },
+	{ b43_rfseq_tx2rx_cmd, 16, 7, 0x10, 16 },
+	{ b43_rfseq_reset2rx_cmd, 16, 7, 0x20, 16 },
+	{ b43_rfseq_rfseq2_cmd_c0, 8, 7, 0x30, 16 },
+	{ b43_rfseq_rfseq2_cmd_c1, 8, 7, 0x40, 16 },
+	{ b43_rfseq_rfseq2_cmd_c2, 8, 7, 0x50, 16 },
+	{ b43_rfseq_dly_80, 16, 7, 0x80, 16 },
+	{ b43_rfseq_reset2rx_dly, 16, 7, 0x90, 16 },
+	{ b43_rfseq_dly_a, 8, 7, 0xa0, 16 },
+	{ b43_rfseq_dly_b, 8, 7, 0xb0, 16 },
+	{ b43_rfseq_dly_c, 8, 7, 0xc0, 16 },
+	{ b43_rfseq_updl_lpf_hpc0, 2, 7, 0x121, 16 },
+	{ b43_rfseq_updl_tia_hpc0, 2, 7, 0x124, 16 },
+	{ b43_rfseq_updl_lpf_hpc1, 2, 7, 0x131, 16 },
+	{ b43_rfseq_updl_tia_hpc1, 2, 7, 0x137, 16 },
+};
+
+const unsigned int b43_phy_ac_rfseq_tbls_n = ARRAY_SIZE(b43_phy_ac_rfseq_tbls);
+
+/*
+ * FEM control pattern (table 0x0a, three 32-byte blocks: A, B, A) for SROM
+ * femctrl == 2, the value the vendor driver holds on this card (Alessio's tree
+ * has the femctrl == 6 variant, 0x06/0x02 where this has 0x04/0x00).
+ */
+static const u8 b43_femctrl2_a[32] = {
+	0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const u8 b43_femctrl2_b[32] = {
+	0x00, 0x00, 0x30, 0x20, 0x00, 0x00, 0x30, 0x20, 0x00,
+	0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40,
+	0x46, 0x42, 0x40, 0x40, 0x46, 0x42, 0x40, 0x41, 0x40,
+	0x40, 0x40, 0x40, 0x40, 0x40,
+};
+
+const struct b43_phy_ac_tbl b43_phy_ac_femctrl2_tbls[] = {
+	{ b43_femctrl2_a, 32, 0x0a, 0x00, 8 },
+	{ b43_femctrl2_b, 32, 0x0a, 0x20, 8 },
+	{ b43_femctrl2_a, 32, 0x0a, 0x40, 8 },
+};
+
+const unsigned int b43_phy_ac_femctrl2_tbls_n =
+	ARRAY_SIZE(b43_phy_ac_femctrl2_tbls);
+
+/* Gain limits (table 0x0b) Names after Alessio's tree. */
+static const u16 b43_glim_a[6] = {
+	0x000b, 0x000c, 0x000e, 0x0020, 0x0024, 0x0028,
+};
+
+static const u16 b43_glim_b[7] = {
+	0x0000, 0x0000, 0x0000, 0x0003, 0x0003, 0x0003, 0x0003,
+};
+
+/*
+ * RX-IQ-cal tone table (table 0x0e): a 20-entry period, two periods at 20 MHz.
+ */
+static const u32 b43_iqcal_tone[20] = {
+	0x0002d400, 0x0002b3c8, 0x00024b96, 0x0001ab6e, 0x0000e354, 0x0000034b,
+	0x000f2354, 0x000e5b6e, 0x000dbb96, 0x000d53c8, 0x000d2c00, 0x000d5038,
+	0x000db86a, 0x000e5892, 0x000f20ac, 0x000000b5, 0x0000e0ac, 0x0001a892,
+	0x0002486a, 0x0002b038,
+};
+
+const struct b43_phy_ac_tbl b43_phy_ac_misc_tbls[] = {
+	{ b43_glim_a, 6, 0x0b, 0x08, 16 },
+	{ b43_glim_b, 7, 0x0b, 0x10, 16 },
+	{ b43_iqcal_tone, 20, 0x0e, 0x00, 32 },
+	{ b43_iqcal_tone, 20, 0x0e, 0x14, 32 },
+};
+
+const unsigned int b43_phy_ac_misc_tbls_n = ARRAY_SIZE(b43_phy_ac_misc_tbls);
+
+/*
+ * Gain ladder "A" (table 0x0c, 18 index/gain pairs per core; name after
+ * Alessio's tree, the variant the vendor driver loads on this card).
+ */
+static const u16 b43_gain_ladder_a_c0[18] = {
+	0x0100, 0x0200, 0x0300, 0x0500, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
+	0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1607, 0x2007, 0x2d07, 0x4007,
+};
+
+static const u16 b43_gain_ladder_a_c1[18] = {
+	0x0100, 0x0200, 0x0300, 0x0500, 0x0800, 0x0b00, 0x1000, 0x1600, 0x2000,
+	0x2d00, 0x4000, 0x4001, 0x4002, 0x4003, 0x4004, 0x4005, 0x4006, 0x4007,
+};
+
+const struct b43_phy_ac_tbl b43_phy_ac_ladder_tbls[] = {
+	{ b43_gain_ladder_a_c0, 18, 0x0c, 0x00, 16 },
+	{ b43_gain_ladder_a_c1, 18, 0x0c, 0x20, 16 },
+};
+
+const unsigned int b43_phy_ac_ladder_tbls_n =
+	ARRAY_SIZE(b43_phy_ac_ladder_tbls);
+
+/*
+ * Remaining 2.4 GHz cells of tables 0x07 (RF sequencer) and 0x0c, values as
+ * the vendor driver programs them on this card. What is known is structure
+ * only, not the meaning of the values:
+ *  - 0x140/0x150 and 0x360/0x370 are identical pairs 0x10 apart, so they
+ *    look like one block per core (two cores).
+ *  - 0x6a/0x6e and 0x3fa/0x3fe repeat the same {0x2f, 0xbef, 0xbef} data.
+ *  - table 0x0c offsets 0x5f and 0x70 end in the same eight words.
+ * Nothing here has been varied independently of the vendor driver, so these
+ * stay literal.
+ */
+static const u16 b43_vendor_7_106[3] = {
+	0x2f, 0xbef, 0xbef,
+};
+
+static const u16 b43_vendor_7_110[2] = {
+	0xbef, 0xbef,
+};
+
+static const u16 b43_vendor_7_249[2] = {
+	0xc8a5, 0xcca5,
+};
+
+static const u16 b43_vendor_7_256[2] = {
+	0xff00, 0xff00,
+};
+
+static const u16 b43_vendor_7_259[2] = {
+	0x7cf, 0x7cf,
+};
+
+static const u16 b43_vendor_7_262[2] = {
+	0xa7, 0xa7,
+};
+
+static const u16 b43_vendor_7_320[11] = {
+	0x2280, 0x2189, 0x40db, 0x40db, 0x40db, 0x4123, 0x4123, 0x4123,
+	0x416b, 0x416b, 0x40db,
+};
+
+static const u16 b43_vendor_7_336[11] = {
+	0x2280, 0x2189, 0x40db, 0x40db, 0x40db, 0x4123, 0x4123, 0x4123,
+	0x416b, 0x416b, 0x40db,
+};
+
+static const u16 b43_vendor_7_398[1] = {
+	0x0,
+};
+
+static const u16 b43_vendor_7_864[11] = {
+	0x140, 0x140, 0x141, 0x141, 0x141, 0x141, 0x141, 0x141,
+	0x141, 0x141, 0x141,
+};
+
+static const u16 b43_vendor_7_880[11] = {
+	0x140, 0x140, 0x141, 0x141, 0x141, 0x141, 0x141, 0x141,
+	0x141, 0x141, 0x141,
+};
+
+static const u16 b43_vendor_7_966[2] = {
+	0x20, 0x20,
+};
+
+static const u16 b43_vendor_7_973[1] = {
+	0x2d3,
+};
+
+static const u16 b43_vendor_7_982[2] = {
+	0x20, 0x20,
+};
+
+static const u16 b43_vendor_7_989[1] = {
+	0x352,
+};
+
+static const u16 b43_vendor_7_998[2] = {
+	0x20, 0x20,
+};
+
+static const u16 b43_vendor_7_1018[3] = {
+	0x2f, 0xbef, 0xbef,
+};
+
+static const u16 b43_vendor_7_1022[2] = {
+	0xbef, 0xbef,
+};
+
+static const u16 b43_vendor_7_1088[4] = {
+	0x140, 0x2192, 0x140, 0x2192,
+};
+
+static const u16 b43_vendor_12_64[2] = {
+	0x40, 0x4,
+};
+
+static const u16 b43_vendor_12_67[3] = {
+	0xff02, 0xff, 0xfe06,
+};
+
+static const u16 b43_vendor_12_72[2] = {
+	0xb, 0x11,
+};
+
+static const u16 b43_vendor_12_75[3] = {
+	0x101, 0xff00, 0x4f3,
+};
+
+static const u16 b43_vendor_12_95[9] = {
+	0xacdc, 0x3f, 0xfff5, 0xff02, 0x3f, 0xa, 0xffff, 0x101,
+	0x3f,
+};
+
+static const u16 b43_vendor_12_112[8] = {
+	0x3f, 0xfff5, 0xff02, 0x3f, 0xa, 0xffff, 0x101, 0x3f,
+};
+
+const struct b43_phy_ac_tbl b43_phy_ac_vendor_tbls[] = {
+	{ b43_vendor_7_106, 3, 0x07, 0x6a, 16 },
+	{ b43_vendor_7_110, 2, 0x07, 0x6e, 16 },
+	{ b43_vendor_7_249, 2, 0x07, 0xf9, 16 },
+	{ b43_vendor_7_256, 2, 0x07, 0x100, 16 },
+	{ b43_vendor_7_259, 2, 0x07, 0x103, 16 },
+	{ b43_vendor_7_262, 2, 0x07, 0x106, 16 },
+	{ b43_vendor_7_320, 11, 0x07, 0x140, 16 },
+	{ b43_vendor_7_336, 11, 0x07, 0x150, 16 },
+	{ b43_vendor_7_398, 1, 0x07, 0x18e, 16 },
+	{ b43_vendor_7_864, 11, 0x07, 0x360, 16 },
+	{ b43_vendor_7_880, 11, 0x07, 0x370, 16 },
+	{ b43_vendor_7_966, 2, 0x07, 0x3c6, 16 },
+	{ b43_vendor_7_973, 1, 0x07, 0x3cd, 16 },
+	{ b43_vendor_7_982, 2, 0x07, 0x3d6, 16 },
+	{ b43_vendor_7_989, 1, 0x07, 0x3dd, 16 },
+	{ b43_vendor_7_998, 2, 0x07, 0x3e6, 16 },
+	{ b43_vendor_7_1018, 3, 0x07, 0x3fa, 16 },
+	{ b43_vendor_7_1022, 2, 0x07, 0x3fe, 16 },
+	{ b43_vendor_7_1088, 4, 0x07, 0x440, 16 },
+	{ b43_vendor_12_64, 2, 0x0c, 0x40, 16 },
+	{ b43_vendor_12_67, 3, 0x0c, 0x43, 16 },
+	{ b43_vendor_12_72, 2, 0x0c, 0x48, 16 },
+	{ b43_vendor_12_75, 3, 0x0c, 0x4b, 16 },
+	{ b43_vendor_12_95, 9, 0x0c, 0x5f, 16 },
+	{ b43_vendor_12_112, 8, 0x0c, 0x70, 16 },
+};
+
+const unsigned int b43_phy_ac_vendor_tbls_n =
+	ARRAY_SIZE(b43_phy_ac_vendor_tbls);
+
+/*
+ * TX gain table for 2.4 GHz with an external PA, acphy_txgain_epa_2g_2069rev4
+ * (from Alessio Ferri's b43 AC-PHY driver; the stock driver loads it whole
+ * into table 0x20). Index 0 is the highest gain. Per entry: bbmult in the
+ * low byte of word 0, then three gain words packed across the rest.
+ */
+const u16 b43_phy_ac_txgain_2g[128][3] = {
+	{ 0x0044, 0xffff, 0xa7ff },
+	{ 0x0040, 0xffff, 0xa7ff },
+	{ 0x003f, 0xffff, 0xa7ef },
+	{ 0x003f, 0xffff, 0xa7df },
+	{ 0x003f, 0xffff, 0xa7cf },
+	{ 0x0040, 0xffff, 0xa7bf },
+	{ 0x0041, 0xffff, 0xa7af },
+	{ 0x0040, 0xffff, 0xa7a7 },
+	{ 0x003f, 0xffff, 0xa79f },
+	{ 0x0041, 0xffff, 0xa78f },
+	{ 0x0041, 0xffff, 0xa787 },
+	{ 0x0040, 0xffff, 0xa77f },
+	{ 0x0040, 0xffff, 0xa777 },
+	{ 0x0040, 0xffff, 0xa76f },
+	{ 0x0041, 0xffff, 0xa767 },
+	{ 0x0042, 0xffff, 0xa75f },
+	{ 0x003e, 0xffff, 0xa75f },
+	{ 0x0040, 0xffff, 0xa757 },
+	{ 0x0042, 0xffff, 0xa74f },
+	{ 0x003e, 0xffff, 0xa74f },
+	{ 0x0041, 0xffff, 0xa747 },
+	{ 0x003d, 0xffff, 0xa747 },
+	{ 0x0040, 0xffff, 0xa73f },
+	{ 0x003d, 0xffff, 0xa73f },
+	{ 0x0041, 0xffff, 0xa737 },
+	{ 0x003d, 0xffff, 0xa737 },
+	{ 0x0043, 0xffff, 0xa72f },
+	{ 0x0040, 0xffff, 0xa72f },
+	{ 0x003c, 0xffff, 0xa72f },
+	{ 0x0043, 0xffff, 0xa727 },
+	{ 0x0040, 0xffff, 0xa727 },
+	{ 0x003c, 0xffff, 0xa727 },
+	{ 0x0046, 0xffff, 0xa71f },
+	{ 0x0042, 0xffff, 0xa71f },
+	{ 0x003e, 0xffff, 0xa71f },
+	{ 0x003b, 0xffff, 0xa71f },
+	{ 0x004a, 0xffff, 0xa717 },
+	{ 0x0046, 0xffff, 0xa717 },
+	{ 0x0042, 0xffff, 0xa717 },
+	{ 0x003e, 0xffff, 0xa717 },
+	{ 0x003b, 0xffff, 0xa717 },
+	{ 0x0037, 0xffff, 0xa717 },
+	{ 0x004c, 0xffff, 0xa70f },
+	{ 0x0048, 0xffff, 0xa70f },
+	{ 0x0044, 0xffff, 0xa70f },
+	{ 0x0040, 0xffff, 0xa70f },
+	{ 0x003c, 0xffff, 0xa70f },
+	{ 0x0039, 0xffff, 0xa70f },
+	{ 0x0036, 0xffff, 0xa70f },
+	{ 0x0033, 0xffff, 0xa70f },
+	{ 0x002f, 0xffff, 0xa70f },
+	{ 0x0055, 0xffff, 0xa707 },
+	{ 0x0050, 0xffff, 0xa707 },
+	{ 0x004b, 0xffff, 0xa707 },
+	{ 0x0047, 0xffff, 0xa707 },
+	{ 0x0043, 0xffff, 0xa707 },
+	{ 0x003f, 0xffff, 0xa707 },
+	{ 0x003c, 0xffff, 0xa707 },
+	{ 0x0038, 0xffff, 0xa707 },
+	{ 0x0035, 0xffff, 0xa707 },
+	{ 0x0032, 0xffff, 0xa707 },
+	{ 0x0030, 0xffff, 0xa707 },
+	{ 0x002d, 0xffff, 0xa707 },
+	{ 0x002a, 0xffff, 0xa707 },
+	{ 0x003f, 0xcfff, 0xa707 },
+	{ 0x0042, 0xc7ff, 0xa707 },
+	{ 0x003f, 0xc7ff, 0xa707 },
+	{ 0x0043, 0xbfff, 0xa707 },
+	{ 0x003f, 0xbfff, 0xa707 },
+	{ 0x0045, 0xb7ff, 0xa707 },
+	{ 0x0041, 0xb7ff, 0xa707 },
+	{ 0x003d, 0xb7ff, 0xa707 },
+	{ 0x0044, 0xafff, 0xa707 },
+	{ 0x0040, 0xafff, 0xa707 },
+	{ 0x003d, 0xafff, 0xa707 },
+	{ 0x0046, 0xa7ff, 0xa707 },
+	{ 0x0041, 0xa7ff, 0xa707 },
+	{ 0x003e, 0xa7ff, 0xa707 },
+	{ 0x003b, 0xa7ff, 0xa707 },
+	{ 0x0046, 0x9fff, 0xa707 },
+	{ 0x0042, 0x9fff, 0xa707 },
+	{ 0x003e, 0x9fff, 0xa707 },
+	{ 0x003b, 0x9fff, 0xa707 },
+	{ 0x0037, 0x9fff, 0xa707 },
+	{ 0x0046, 0x97ff, 0xa707 },
+	{ 0x0042, 0x97ff, 0xa707 },
+	{ 0x003f, 0x97ff, 0xa707 },
+	{ 0x003b, 0x97ff, 0xa707 },
+	{ 0x0038, 0x97ff, 0xa707 },
+	{ 0x0035, 0x97ff, 0xa707 },
+	{ 0x004c, 0x8fff, 0xa707 },
+	{ 0x0048, 0x8fff, 0xa707 },
+	{ 0x0044, 0x8fff, 0xa707 },
+	{ 0x0040, 0x8fff, 0xa707 },
+	{ 0x003c, 0x8fff, 0xa707 },
+	{ 0x0039, 0x8fff, 0xa707 },
+	{ 0x0036, 0x8fff, 0xa707 },
+	{ 0x0033, 0x8fff, 0xa707 },
+	{ 0x0030, 0x8fff, 0xa707 },
+	{ 0x002d, 0x8fff, 0xa707 },
+	{ 0x0058, 0x87ff, 0xa707 },
+	{ 0x0053, 0x87ff, 0xa707 },
+	{ 0x004f, 0x87ff, 0xa707 },
+	{ 0x004a, 0x87ff, 0xa707 },
+	{ 0x0046, 0x87ff, 0xa707 },
+	{ 0x0042, 0x87ff, 0xa707 },
+	{ 0x003e, 0x87ff, 0xa707 },
+	{ 0x003b, 0x87ff, 0xa707 },
+	{ 0x0038, 0x87ff, 0xa707 },
+	{ 0x0035, 0x87ff, 0xa707 },
+	{ 0x0032, 0x87ff, 0xa707 },
+	{ 0x002f, 0x87ff, 0xa707 },
+	{ 0x002c, 0x87ff, 0xa707 },
+	{ 0x002a, 0x87ff, 0xa707 },
+	{ 0x0027, 0x87ff, 0xa707 },
+	{ 0x0025, 0x87ff, 0xa707 },
+	{ 0x0023, 0x87ff, 0xa707 },
+	{ 0x0021, 0x87ff, 0xa707 },
+	{ 0x001f, 0x87ff, 0xa707 },
+	{ 0x001e, 0x87ff, 0xa707 },
+	{ 0x001c, 0x87ff, 0xa707 },
+	{ 0x001a, 0x87ff, 0xa707 },
+	{ 0x0019, 0x87ff, 0xa707 },
+	{ 0x0017, 0x87ff, 0xa707 },
+	{ 0x0016, 0x87ff, 0xa707 },
+	{ 0x0015, 0x87ff, 0xa707 },
+	{ 0x0014, 0x87ff, 0xa707 },
+	{ 0x0013, 0x87ff, 0xa707 },
+};
+
+/*
+ * TX gain table for 5 GHz as the vendor driver loads it into table 0x20 on this
+ * board captured from the vendor driver, same entry format.
+ */
+const u16 b43_phy_ac_txgain_5g[128][3] = {
+	{ 0x0044, 0x7f00, 0xf3ff },
+	{ 0x0040, 0x7f00, 0xf3ff },
+	{ 0x0040, 0x7f00, 0xf3ef },
+	{ 0x0040, 0x7f00, 0xf3df },
+	{ 0x0041, 0x7f00, 0xf3cf },
+	{ 0x003f, 0x7f00, 0xf3c7 },
+	{ 0x0041, 0x7f00, 0xf3b7 },
+	{ 0x0040, 0x7f00, 0xf3af },
+	{ 0x003f, 0x7f00, 0xf3a7 },
+	{ 0x0041, 0x7f00, 0xf397 },
+	{ 0x0041, 0x7f00, 0xf38f },
+	{ 0x0041, 0x7f00, 0xf387 },
+	{ 0x0040, 0x7f00, 0xf37f },
+	{ 0x0040, 0x7f00, 0xf377 },
+	{ 0x0041, 0x7f00, 0xf36f },
+	{ 0x0042, 0x7f00, 0xf367 },
+	{ 0x003e, 0x7f00, 0xf367 },
+	{ 0x003f, 0x7f00, 0xf35f },
+	{ 0x0041, 0x7f00, 0xf357 },
+	{ 0x003d, 0x7f00, 0xf357 },
+	{ 0x0040, 0x7f00, 0xf34f },
+	{ 0x0042, 0x7f00, 0xf347 },
+	{ 0x003f, 0x7f00, 0xf347 },
+	{ 0x0043, 0x7f00, 0xf33f },
+	{ 0x003f, 0x7f00, 0xf33f },
+	{ 0x0044, 0x7f00, 0xf337 },
+	{ 0x0040, 0x7f00, 0xf337 },
+	{ 0x003c, 0x7f00, 0xf337 },
+	{ 0x0043, 0x7f00, 0xf32f },
+	{ 0x003f, 0x7f00, 0xf32f },
+	{ 0x003c, 0x7f00, 0xf32f },
+	{ 0x003f, 0x6f00, 0xf32f },
+	{ 0x003f, 0x6900, 0xf32f },
+	{ 0x003d, 0x6700, 0xf32f },
+	{ 0x003b, 0x6400, 0xf32f },
+	{ 0x003b, 0x5f00, 0xf32f },
+	{ 0x0039, 0x5d00, 0xf32f },
+	{ 0x0037, 0x5900, 0xf32f },
+	{ 0x0037, 0x5700, 0xf32f },
+	{ 0x0035, 0x5300, 0xf32f },
+	{ 0x0034, 0x5000, 0xf32f },
+	{ 0x0034, 0x4b00, 0xf32f },
+	{ 0x0035, 0x4600, 0xf32f },
+	{ 0x0036, 0x4100, 0xf32f },
+	{ 0x0038, 0x3b00, 0xf32f },
+	{ 0x003a, 0x3600, 0xf32f },
+	{ 0x003c, 0x3100, 0xf32f },
+	{ 0x003e, 0x2d00, 0xf32f },
+	{ 0x003e, 0x2b00, 0xf32f },
+	{ 0x003e, 0x2800, 0xf32f },
+	{ 0x0040, 0x2500, 0xf32f },
+	{ 0x0046, 0x1f00, 0xf32f },
+	{ 0x0042, 0x1f00, 0xf32f },
+	{ 0x003e, 0x1f00, 0xf32f },
+	{ 0x003b, 0x1f00, 0xf32f },
+	{ 0x0037, 0x1f00, 0xf32f },
+	{ 0x0047, 0x1700, 0xf32f },
+	{ 0x0043, 0x1700, 0xf32f },
+	{ 0x003f, 0x1700, 0xf32f },
+	{ 0x003c, 0x1700, 0xf32f },
+	{ 0x0039, 0x1700, 0xf32f },
+	{ 0x0037, 0x1600, 0xf32f },
+	{ 0x0037, 0x1500, 0xf32f },
+	{ 0x0035, 0x1400, 0xf32f },
+	{ 0x0035, 0x1300, 0xf32f },
+	{ 0x0034, 0x1200, 0xf32f },
+	{ 0x0034, 0x1100, 0xf32f },
+	{ 0x0034, 0x1000, 0xf32f },
+	{ 0x0036, 0x0f00, 0xf32f },
+	{ 0x0036, 0x0e00, 0xf32f },
+	{ 0x0034, 0x0d00, 0xf32f },
+	{ 0x0035, 0x0c00, 0xf32f },
+	{ 0x0038, 0x0b00, 0xf32f },
+	{ 0x0039, 0x0a00, 0xf32f },
+	{ 0x003d, 0x0900, 0xf32f },
+	{ 0x0040, 0x0800, 0xf32f },
+	{ 0x0044, 0x0700, 0xf32f },
+	{ 0x0040, 0x0700, 0xf32f },
+	{ 0x003c, 0x0700, 0xf32f },
+	{ 0x0038, 0x0700, 0xf32f },
+	{ 0x0034, 0x0700, 0xf32f },
+	{ 0x0030, 0x0700, 0xf32f },
+	{ 0x002c, 0x0700, 0xf32f },
+	{ 0x0028, 0x0700, 0xf32f },
+	{ 0x0024, 0x0700, 0xf32f },
+	{ 0x0020, 0x0700, 0xf32f },
+	{ 0x001c, 0x0700, 0xf32f },
+	{ 0x0018, 0x0700, 0xf32f },
+	{ 0x0014, 0x0700, 0xf32f },
+	{ 0x0012, 0x0700, 0xf32f },
+	{ 0x0011, 0x0700, 0xf32f },
+	{ 0x0010, 0x0700, 0xf32f },
+	{ 0x000f, 0x0700, 0xf32f },
+	{ 0x000e, 0x0700, 0xf32f },
+	{ 0x000d, 0x0700, 0xf32f },
+	{ 0x000c, 0x0700, 0xf32f },
+	{ 0x000c, 0x0700, 0xf32f },
+	{ 0x000b, 0x0700, 0xf32f },
+	{ 0x000a, 0x0700, 0xf32f },
+	{ 0x000a, 0x0700, 0xf32f },
+	{ 0x0009, 0x0700, 0xf32f },
+	{ 0x0009, 0x0700, 0xf32f },
+	{ 0x0008, 0x0700, 0xf32f },
+	{ 0x0008, 0x0700, 0xf32f },
+	{ 0x0007, 0x0700, 0xf32f },
+	{ 0x0007, 0x0700, 0xf32f },
+	{ 0x0007, 0x0700, 0xf32f },
+	{ 0x0006, 0x0700, 0xf32f },
+	{ 0x0006, 0x0700, 0xf32f },
+	{ 0x0006, 0x0700, 0xf32f },
+	{ 0x0005, 0x0700, 0xf32f },
+	{ 0x0005, 0x0700, 0xf32f },
+	{ 0x0005, 0x0700, 0xf32f },
+	{ 0x0004, 0x0700, 0xf32f },
+	{ 0x0004, 0x0700, 0xf32f },
+	{ 0x0004, 0x0700, 0xf32f },
+	{ 0x0004, 0x0700, 0xf32f },
+	{ 0x0003, 0x0700, 0xf32f },
+	{ 0x0003, 0x0700, 0xf32f },
+	{ 0x0003, 0x0700, 0xf32f },
+	{ 0x0003, 0x0700, 0xf32f },
+	{ 0x0003, 0x0700, 0xf32f },
+	{ 0x0003, 0x0700, 0xf32f },
+	{ 0x0002, 0x0700, 0xf32f },
+	{ 0x0002, 0x0700, 0xf32f },
+	{ 0x0002, 0x0700, 0xf32f },
+	{ 0x0002, 0x0700, 0xf32f },
+	{ 0x0002, 0x0700, 0xf32f },
+};
diff --git a/drivers/net/wireless/broadcom/b43/tables_phy_ac.h b/drivers/net/wireless/broadcom/b43/tables_phy_ac.h
new file mode 100644
index 0000000..64a5969
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/tables_phy_ac.h
@@ -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_ */

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH RFC wireless-next 2/4] wifi: b43: AC-PHY init and 2.4 GHz channel switching
  2026-11-12 17:56 [PATCH RFC wireless-next 0/4] wifi: b43: AC-PHY support (series 4/4) Andreas Wendleder
  2026-11-12 17:56 ` [PATCH RFC wireless-next 1/4] wifi: b43: radio 2069 and AC-PHY tables Andreas Wendleder
@ 2026-11-12 17:56 ` Andreas Wendleder
  2026-11-12 17:56 ` [PATCH RFC wireless-next 3/4] wifi: b43: 5 GHz, 80 MHz and VHT for the AC PHY Andreas Wendleder
  2026-11-12 17:56 ` [PATCH RFC wireless-next 4/4] wifi: b43: enable the AC-PHY support Andreas Wendleder
  3 siblings, 0 replies; 5+ messages in thread
From: Andreas Wendleder @ 2026-11-12 17:56 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, b43-dev, Michael Buesch, Alessio Ferri, kvalo,
	julian.calaby, jpeisach, rosenp, linux-kernel

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.

Co-developed-by: Alessio Ferri <alessio.ferri@mythread.it>
Signed-off-by: Alessio Ferri <alessio.ferri@mythread.it>
Signed-off-by: Andreas Wendleder <gonsolo@gmail.com>
---
 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

diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c
index 6b80b5e..7d2f9ea 100644
--- a/drivers/net/wireless/broadcom/b43/main.c
+++ b/drivers/net/wireless/broadcom/b43/main.c
@@ -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 ?
diff --git a/drivers/net/wireless/broadcom/b43/phy_ac.c b/drivers/net/wireless/broadcom/b43/phy_ac.c
index fe102ea..4bcf6f8 100644
--- a/drivers/net/wireless/broadcom/b43/phy_ac.c
+++ b/drivers/net/wireless/broadcom/b43/phy_ac.c
@@ -4,10 +4,17 @@
  * IEEE 802.11ac AC-PHY support
  *
  * Copyright (c) 2015 Rafał Miłecki <zajec5@gmail.com>
+ * Copyright (c) 2026 Alessio Ferri <alessio.ferri@mythread.it>
+ * Copyright (c) 2026 Andreas Wendleder <gonsolo@gmail.com>
  */
 
 #include "b43.h"
 #include "phy_ac.h"
+#include "radio_2069.h"
+#include "tables_phy_ac.h"
+#include "dma.h"
+#include "main.h"
+
 
 /**************************************************
  * Basic PHY ops
@@ -42,17 +49,1009 @@ static void b43_phy_ac_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
 		    (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
 }
 
+/*
+ * Unlike the generic b43_phy_write() fallback (two 16-bit writes to CONTROL
+ * and DATA), the vendor driver writes one 32-bit word, (value << 16) | reg,
+ * to the CONTROL address. Do the same.
+ */
+static void b43_phy_ac_op_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+	b43_write32(dev, B43_MMIO_PHY_CONTROL, ((u32)value << 16) | reg);
+}
+
+/*
+ * Which CONTROL/DATA register pair addresses the radio depends on the core
+ * revision: cores 0x1b and below 0x18 use the legacy RADIO_CONTROL and
+ * RADIO_DATA_LOW pair, newer ones (including the BCM4360's) the RADIO24 pair.
+ */
+static bool b43_phy_ac_use_radio24(struct b43_wldev *dev)
+{
+	u8 rev = dev->dev->core_rev;
+
+	return !(rev == 0x1b || rev < 0x18);
+}
+
 static u16 b43_phy_ac_op_radio_read(struct b43_wldev *dev, u16 reg)
 {
-	b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
-	return b43_read16(dev, B43_MMIO_RADIO24_DATA);
+	if (b43_phy_ac_use_radio24(dev)) {
+		b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
+		return b43_read16(dev, B43_MMIO_RADIO24_DATA);
+	}
+
+	b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
+	return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
 }
 
 static void b43_phy_ac_op_radio_write(struct b43_wldev *dev, u16 reg,
 				      u16 value)
 {
-	b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
-	b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
+	if (b43_phy_ac_use_radio24(dev)) {
+		b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
+		b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
+		return;
+	}
+
+	b43_write16f(dev, B43_MMIO_RADIO_CONTROL, reg);
+	b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
+}
+
+static u8 b43_phy_ac_num_cores(struct b43_wldev *dev)
+{
+	u8 cores = b43_phy_read(dev, 0x00b) & 0x7;
+
+	if (dev->dev->chip_id == 0x4360 &&
+	    (dev->dev->board_type == 0x137 || dev->dev->board_type == 0x117))
+		cores = 2;
+	return cores;
+}
+
+/* prefregs_2069_rev4 from the vendor driver. */
+static const u16 b43_radio_2069r4_prefregs[][2] = {
+	{ 0x063a, 0x0000 }, { 0x063d, 0x000f }, { 0x0645, 0x3000 },
+	{ 0x0646, 0x0303 }, { 0x0647, 0x36e2 }, { 0x0649, 0x6000 },
+	{ 0x064a, 0x0003 }, { 0x065e, 0x0ff4 }, { 0x0666, 0x0b2d },
+	{ 0x0667, 0x03ff }, { 0x0115, 0x3337 }, { 0x0117, 0x1337 },
+	{ 0x0718, 0x7777 }, { 0x071c, 0x1000 }, { 0x0726, 0x0100 },
+	{ 0x0727, 0x0002 }, { 0x0761, 0x0100 }, { 0x0407, 0x8382 },
+	{ 0x055e, 0x0020 }, { 0x0885, 0x0700 }, { 0x08e9, 0x01ce },
+	{ 0x08ea, 0x00ff }, { 0x08ec, 0x06ff }, { 0x0972, 0x0600 },
+};
+
+/*
+ * Radio 2069 rev 4 init (as the vendor driver does it). Skipped: a board-flag
+ * dependent "radio 0x8ea |= 0x100" whose flag source we haven't identified.
+ */
+static void b43_radio_2069_init(struct b43_wldev *dev)
+{
+	u16 s728, s408;
+	unsigned int i;
+	u8 core, cores;
+
+	s728 = b43_phy_read(dev, 0x728);
+	s408 = b43_phy_read(dev, B43_PHY_AC_RFCTL_CMD) & 0xfc38;
+	b43_phy_write(dev, 0x415, 0);
+	b43_phy_write(dev, 0x40e, 0);
+	b43_phy_write(dev, 0x40c, 0x2000);
+	b43_phy_write(dev, B43_PHY_AC_RFCTL_CMD, s408);
+	b43_phy_write(dev, 0x417, 0);
+	b43_phy_write(dev, 0x416, 0xd);
+	b43_phy_write(dev, 0x728, s728 & 0x7e7f);
+	b43_phy_set(dev, 0x720, 0x180);
+	b43_phy_write(dev, B43_PHY_AC_RFCTL_CMD, s408);
+	b43_phy_write(dev, B43_PHY_AC_RFCTL_CMD, s408 | 1);
+	udelay(1);
+	b43_phy_write(dev, B43_PHY_AC_RFCTL_CMD, s408);
+
+	for (i = 0; i < ARRAY_SIZE(b43_radio_2069r4_prefregs); i++)
+		b43_radio_write(dev, b43_radio_2069r4_prefregs[i][0],
+				b43_radio_2069r4_prefregs[i][1]);
+
+	b43_radio_set(dev, 0x96b, 0x0800);
+	b43_radio_set(dev, 0x96b, 0x4000);
+	b43_radio_set(dev, 0x96c, 0x0800);
+	b43_radio_set(dev, 0x96b, 0x8000);
+	b43_radio_set(dev, 0x96b, 0x1000);
+	b43_radio_set(dev, 0x96b, 0x0004);
+	b43_radio_set(dev, 0x407, 0x0002);
+	b43_radio_set(dev, 0x55e, 0x0010);
+
+	cores = b43_phy_ac_num_cores(dev);
+	for (core = 0; core < cores; core++) {
+		u16 c = core << 9;
+
+		b43_radio_maskset(dev, 0x126 | c, ~0x300, 0x100);
+		b43_radio_maskset(dev, 0x127 | c, ~0x003, 0x002);
+		b43_radio_mask(dev, 0x06f | c, ~0x004);
+		b43_radio_mask(dev, 0x06f | c, ~0x001);
+		b43_radio_mask(dev, 0x06f | c, ~0x002);
+		b43_radio_mask(dev, 0x065 | c, ~0x001);
+	}
+
+	b43_radio_mask(dev, 0x40c, ~0x10);
+	b43_phy_write(dev, B43_PHY_AC_RFCTL_CMD, s408 | 6);
+	udelay(100);
+	b43_radio_set(dev, 0x40c, 0x10);
+	b43_phy_write(dev, 0x417, 0xd);
+	b43_phy_write(dev, B43_PHY_AC_RFCTL_CMD, s408 | 2);
+	b43_phy_write(dev, 0x728, s728 | 0x180);
+	udelay(100);
+	b43_phy_write(dev, 0x417, 4);
+	b43_phy_write(dev, 0x728, s728 & 0xfeff);
+
+	b43dbg(dev->wl, "phy_ac: radio 2069 init done (%u cores)\n", cores);
+}
+
+/*
+ * Resistor calibration: the vendor's default path when SPROM boardflags3
+ * bits 3 and 13 are clear. bcma does not parse boardflags3, so we assume 0.
+ */
+static bool b43_radio_2069_rcal(struct b43_wldev *dev)
+{
+	u16 v = 0;
+	int i;
+
+	b43_radio_set(dev, 0x8ea, 0x40);
+	b43_radio_set(dev, 0x8ea, 0x80);
+	b43_radio_mask(dev, 0x8ed, ~0x600);
+	b43_radio_mask(dev, 0x8ed, ~0x1800);
+	b43_radio_set(dev, 0x548, 0x1);
+	b43_radio_write(dev, 0x549, 0);
+	b43_radio_write(dev, 0x54a, 0);
+	b43_radio_write(dev, 0x54b, 0);
+	b43_radio_write(dev, 0x54c, 0);
+	b43_radio_mask(dev, 0x40b, ~0x1);
+	udelay(1);
+	b43_radio_set(dev, 0x40b, 0x1);
+	for (i = 0; i < 100; i++) {
+		udelay(10);
+		v = b43_radio_read(dev, 0x40b);
+		if (v & 0x8)
+			break;
+	}
+	b43_radio_read(dev, 0x40b);
+	b43_radio_mask(dev, 0x548, ~0x1);
+	b43_radio_mask(dev, 0x8ea, ~0x40);
+	b43_radio_mask(dev, 0x8ea, ~0x80);
+	b43_radio_mask(dev, 0x40b, ~0x1);
+
+	b43dbg(dev->wl, "phy_ac: RCAL %s after %d polls (0x40b=%04x)\n",
+	       (v & 0x8) ? "done" : "TIMEOUT", i, v);
+	return v & 0x8;
+}
+
+/* RC calibration (as the vendor driver does it), radio type 0 values. */
+static void b43_radio_2069_rccal(struct b43_wldev *dev)
+{
+	static const u8 cal_a[3] = { 1, 0, 0 };
+	static const u8 cal_b[3] = { 0, 2, 1 };
+	static const u8 cal_c[3] = { 0x1c, 0x70, 0x40 };
+	static const u16 cal_d[3] = { 0x14a, 0x101, 0x11a };
+	u8 core, cores = b43_phy_ac_num_cores(dev);
+	u16 v, r1, r2;
+	int step, i;
+	bool done;
+
+	b43_radio_set(dev, 0x8ea, 0x80);
+	b43_radio_maskset(dev, 0x8ed, ~0x600, 0x400);
+
+	for (step = 0; step < 3; step++) {
+		b43_radio_maskset(dev, 0x410, ~0x1000, cal_a[step] << 12);
+		b43_radio_maskset(dev, 0x410, ~0x0018, cal_b[step] << 3);
+		b43_radio_maskset(dev, 0x411, 0x00ff, cal_c[step] << 8);
+		b43_radio_write(dev, 0x412, cal_d[step]);
+		if (step == 2) {
+			for (core = 0; core < cores; core++) {
+				b43_radio_mask(dev, 0x11d | (core << 9), ~0x4);
+				b43_radio_set(dev, 0x171 | (core << 9), 0x2000);
+			}
+		}
+		b43_radio_mask(dev, 0x410, ~0x1);
+		udelay(1);
+		b43_radio_set(dev, 0x410, 0x1);
+		udelay(35);
+		b43_radio_set(dev, 0x411, 0x1);
+
+		done = false;
+		for (i = 0; i < 100; i++) {
+			udelay(100);
+			if (b43_radio_read(dev, 0x413) & 0x10) {
+				done = true;
+				break;
+			}
+		}
+		b43_radio_mask(dev, 0x411, ~0x1);
+
+		if (done) {
+			if (step == 0) {
+				r1 = b43_radio_read(dev, 0x414);
+				r2 = b43_radio_read(dev, 0x415);
+				b43dbg(dev->wl,
+				       "phy_ac: RCCAL step 0: %04x %04x -> %02x\n",
+				       r1, r2,
+				       (((u32)(r2 - r1)) * 0xc1 >> 8) & 0xff);
+			} else if (step == 1) {
+				v = b43_radio_read(dev, 0x416);
+				for (core = 0; core < cores; core++) {
+					b43_radio_maskset(dev,
+							  0x126 | (core << 9),
+							  ~0x1f, v & 0x1f);
+					b43_radio_maskset(dev,
+							  0x043 | (core << 9),
+							  ~0x1f, v & 0x1f);
+				}
+				b43dbg(dev->wl, "phy_ac: RCCAL step 1: %04x\n",
+				       v);
+			} else {
+				v = b43_radio_read(dev, 0x416);
+				for (core = 0; core < cores; core++)
+					b43_radio_mask(dev, 0x171 | (core << 9),
+						       ~0x2000);
+				b43dbg(dev->wl, "phy_ac: RCCAL step 2: %04x\n",
+				       v);
+			}
+		} else {
+			b43dbg(dev->wl, "phy_ac: RCCAL step %d TIMEOUT\n",
+			       step);
+		}
+		b43_radio_mask(dev, 0x410, ~0x1);
+	}
+	b43_radio_mask(dev, 0x8ea, ~0x80);
+}
+
+/* Radio power-up (vendor wlc_phy_switch_radio_acphy, on, radio type 0). */
+static void b43_radio_2069_power_up(struct b43_wldev *dev)
+{
+	b43_radio_2069_init(dev);
+	b43_phy_mask(dev, 0x16b, ~0x400);
+	udelay(3);
+	b43_phy_write(dev, 0x175, 0);
+	udelay(3);
+	b43_radio_2069_rcal(dev);
+	b43_radio_2069_rccal(dev);
+}
+
+/* Radio power-down; the power-up is b43_radio_2069_power_up(). */
+static void b43_radio_2069_power_down(struct b43_wldev *dev)
+{
+	b43_phy_write(dev, 0x173e, 0x1c00);
+	b43_phy_write(dev, 0x1739, 0);
+	b43_phy_write(dev, 0x173a, 0);
+	b43_phy_write(dev, 0x1725, 0x1fff);
+	b43_phy_write(dev, 0x1729, 0);
+	b43_phy_write(dev, 0x1721, 0xffff);
+	b43_phy_write(dev, 0x1728, 0);
+	b43_phy_write(dev, 0x1720, 0x3ff);
+	b43_phy_maskset(dev, B43_PHY_AC_RFCTL_CMD, ~2, 0);
+	b43_phy_write(dev, 0x417, 0);
+	b43_phy_write(dev, 0x416, 1);
+	dev->phy.ac->radio_on = false;
+	b43dbg(dev->wl, "phy_ac: radio powered down\n");
+}
+
+/*
+ * The radio is powered up by software_rfkill(); only switching off is done
+ * here.
+ */
+static void b43_phy_ac_op_switch_analog(struct b43_wldev *dev, bool on)
+{
+	if (!on)
+		b43_radio_2069_power_down(dev);
+}
+
+static void b43_phy_ac_op_software_rfkill(struct b43_wldev *dev, bool blocked)
+{
+	struct b43_phy_ac *phy_ac = dev->phy.ac;
+
+	b43dbg(dev->wl, "phy_ac: software_rfkill(blocked=%d)\n", blocked);
+	if (blocked) {
+		b43_radio_2069_power_down(dev);
+		return;
+	}
+	if (phy_ac->radio_on)
+		return;
+	if (dev->phy.radio_ver != 0x2069 || dev->phy.radio_rev != 4) {
+		b43err(dev->wl,
+		       "phy_ac: no power-up sequence for radio %04x rev %u\n",
+		       dev->phy.radio_ver, dev->phy.radio_rev);
+		return;
+	}
+	b43_radio_2069_power_up(dev);
+	phy_ac->radio_on = true;
+}
+
+static void b43_phy_ac_op_prepare_structs(struct b43_wldev *dev)
+{
+	struct b43_phy *phy = &dev->phy;
+	struct b43_phy_ac *phy_ac = phy->ac;
+
+	b43dbg(dev->wl, "phy_ac: prepare_structs\n");
+	memset(phy_ac, 0, sizeof(*phy_ac));
+}
+
+/*
+ * 2.4 GHz TX gain table index set on a channel switch (0 is the highest gain).
+ * The reset value, 64, is too weak beyond a few metres.
+ */
+#define B43_AC_TXIDX_2G	20
+static void b43_phy_ac_txpwr_by_index(struct b43_wldev *dev, unsigned int idx);
+
+/* One 48-bit PHY table entry: three words through the third data port. */
+static void b43_phy_ac_table_write48(struct b43_wldev *dev, u16 id, u16 offset,
+				     const u16 *w)
+{
+	b43_phy_write(dev, B43_PHY_AC_TABLE_ID, id);
+	b43_phy_write(dev, B43_PHY_AC_TABLE_OFFSET, offset);
+	b43_phy_write(dev, 0x011, w[0]);
+	b43_phy_write(dev, 0x011, w[1]);
+	b43_phy_write(dev, 0x011, w[2]);
+}
+
+/*
+ * The 48-bit wide tables of the 2.4 GHz setup: the TX gain table 0x20, which
+ * hardware TX power control indexes; the RF sequencer extension entry 0x33;
+ * and table 0x11: twelve fixed cells, 448 cells of the SROM's rpcal
+ * coefficient (the value for this board on 2.4 GHz), then four zero cells.
+ */
+static void b43_phy_ac_wide_tables_2g(struct b43_wldev *dev)
+{
+	static const u16 ext33[3] = { 0xe800, 0x0084, 0xd351 };
+	static const u16 head11[12][3] = {
+		{ 0x005b, 0, 0 }, { 0x8250, 0, 0 }, { 0xc338, 0, 0 },
+		{ 0x4527, 1, 0 }, { 0xa6a1, 1, 0 }, { 0x081b, 2, 0 },
+		{ 0x8a18, 2, 0 }, { 0x2c96, 3, 0 }, { 0x8e17, 3, 0 },
+		{ 0x101b, 4, 0 }, { 0x0020, 0, 0 }, { 0x0020, 0, 0 },
+	};
+	static const u16 fill11[3] = { 0xd602, 0x007e, 0x4002 };
+	static const u16 zero[3] = { 0, 0, 0 };
+	unsigned int i;
+
+	for (i = 0; i < 128; i++)
+		b43_phy_ac_table_write48(dev, 0x20, i, b43_phy_ac_txgain_2g[i]);
+	b43_phy_ac_table_write48(dev, 0x14, 0x33, ext33);
+	for (i = 0; i < 12; i++)
+		b43_phy_ac_table_write48(dev, 0x11, i, head11[i]);
+	for (i = 12; i < 460; i++)
+		b43_phy_ac_table_write48(dev, 0x11, i, fill11);
+	for (i = 460; i < 464; i++)
+		b43_phy_ac_table_write48(dev, 0x11, i, zero);
+}
+
+/*
+ * PHY register init for 2.4 GHz and 20 MHz, in the blocks of the reset-time
+ * code of Alessio Ferri's b43-ac-wip (mode_init, set_reg_on_reset,
+ * set_pdet_on_reset, coeff_bank_init), plus the few registers the vendor
+ * driver writes in the same window. Read-modify-write is kept where his
+ * code uses it.
+ */
+#define B43_AC_NCORES	2	/* coremask 0x3 on this chip */
+
+/* 0x17xx analog front end page, AFE on */
+static void b43_phy_ac_mode_init(struct b43_wldev *dev)
+{
+	b43_phy_write(dev, 0x173e, 0x0000);
+	b43_phy_write(dev, 0x1725, 0x0000);
+	b43_phy_write(dev, 0x1722, 0x0000);
+	b43_phy_write(dev, 0x1723, 0x0000);
+	b43_phy_write(dev, 0x1724, 0x0000);
+	b43_phy_write(dev, 0x1727, 0x0000);
+	b43_phy_write(dev, 0x1750, 0x0000);
+	b43_phy_write(dev, 0x1728, 0x0080);
+	b43_phy_write(dev, 0x1720, 0x0180);
+	b43_phy_write(dev, 0x1729, 0x0000);
+	b43_phy_write(dev, 0x1721, 0x5000);
+	b43_phy_write(dev, 0x173a, b43_phy_read(dev, 0x073a) | 0x0100);
+	b43_phy_write(dev, 0x1725, b43_phy_read(dev, 0x1725) | 0x0400);
+}
+
+static void b43_phy_ac_set_reg_on_reset(struct b43_wldev *dev)
+{
+	unsigned int c;
+
+	b43_phy_write(dev, 0x01f2, 0x00c8);
+	b43_phy_write(dev, 0x0026, 0x0092);
+	b43_phy_write(dev, 0x01ed, 0x0050);
+	b43_phy_write(dev, 0x0025, 0x0030);
+
+	/* clip mask: low byte 0x55 */
+	b43_phy_maskset(dev, 0x02ef, (u16)~0x00ff, 0x0055);
+	b43_phy_maskset(dev, 0x02eb, (u16)~0x00ff, 0x0055);
+	b43_phy_maskset(dev, 0x02f7, (u16)~0x00ff, 0x0055);
+	b43_phy_maskset(dev, 0x02f3, (u16)~0x00ff, 0x0055);
+
+	b43_phy_maskset(dev, 0x01ca, (u16)~0x1000, 0);
+	b43_phy_maskset(dev, 0x01b0, (u16)~0x0020, 0);
+	b43_phy_maskset(dev, 0x01b1, (u16)~0x1000, 0x1000);
+	b43_phy_maskset(dev, 0x01b6, (u16)~0x8000, 0);
+	for (c = 0; c < B43_AC_NCORES; c++) {
+		b43_phy_maskset(dev, 0x0690 + c * 0x200, (u16)~0x0200, 0x0200);
+		b43_phy_maskset(dev, 0x0690 + c * 0x200, (u16)~0x0400, 0x0400);
+	}
+	b43_phy_write(dev, 0x01e6, 0x0030);
+}
+
+/* Operating width in MHz; the coefficient bank scales with it. */
+static unsigned int b43_phy_ac_bw_mhz(struct b43_wldev *dev)
+{
+	switch (dev->wl->hw->conf.chandef.width) {
+	case NL80211_CHAN_WIDTH_80:
+		return 80;
+	case NL80211_CHAN_WIDTH_40:
+		return 40;
+	default:
+		return 20;
+	}
+}
+
+/*
+ * RX gain / threshold LUT and per-core words. The 20 MHz values are checked
+ * on 2.4 GHz; the 40 and 80 MHz ones are from Alessio Ferri's tree (5 GHz).
+ */
+static void b43_phy_ac_coeff_bank_init(struct b43_wldev *dev)
+{
+	static const u16 lut[3][21] = {
+		{ 0x0015, 0x0146, 0x0088, 0x0146, 0x076e, 0x01a8, 0x00a3,
+		  0x00f4, 0x00a3, 0x0684, 0x00ad, 0x00e5, 0x0068, 0x00e5,
+		  0x06be, 0x019e, 0x0073, 0x00b2, 0x0073, 0x05fe, 0x00cc },
+		{ 0x000b, 0x0181, 0x005a, 0x0181, 0x0793, 0x01b7, 0x00c1,
+		  0x0102, 0x00c1, 0x06c0, 0x00a9, 0x0162, 0x0042, 0x0162,
+		  0x075c, 0x01b3, 0x00b1, 0x00ed, 0x00b1, 0x0692, 0x00af },
+		{ 0x0005, 0x017a, 0x009e, 0x017a, 0x07ca, 0x01b2, 0x00bd,
+		  0x0114, 0x00bd, 0x06d6, 0x00a2, 0x016c, 0x006f, 0x016c,
+		  0x0793, 0x01b2, 0x00b6, 0x00ff, 0x00b6, 0x06b4, 0x00a8 },
+	};
+	const unsigned int bw = b43_phy_ac_bw_mhz(dev);
+	const unsigned int w = bw / 40;		/* 0, 1, 2 */
+	unsigned int i, c;
+
+	/* width index */
+	b43_phy_maskset(dev, 0x0076, (u16)~0x0007, w + 1);
+	b43_phy_maskset(dev, 0x0180, (u16)~0x001f, lut[w][0]);
+	for (i = 1; i < 21; i++)
+		b43_phy_maskset(dev, 0x0180 + i, (u16)~0x07ff, lut[w][i]);
+	b43_phy_maskset(dev, 0x01b5, (u16)~0x00ff, bw == 40 ? 0x008b : 0x0097);
+	b43_phy_maskset(dev, 0x0312, (u16)~0x00ff, bw == 80 ? 0x0009 : 0x0013);
+	b43_phy_maskset(dev, 0x0313, (u16)~0xff00, bw == 80 ? 0x0900 : 0x1300);
+	for (c = 0; c < B43_AC_NCORES; c++) {
+		u16 st = c * 0x200;
+
+		b43_phy_maskset(dev, 0x06ed + st, (u16)~0x00ff,
+				bw == 20 ? 0x000a : 0x0014);
+		b43_phy_maskset(dev, 0x06ef + st, (u16)~0x00ff,
+				bw == 20 ? 0x0017 :
+					   (bw == 40 ? 0x002a : 0x0054));
+		b43_phy_maskset(dev, 0x06ef + st, (u16)~0xff00,
+				bw == 20 ? 0x0e00 :
+					   (bw == 40 ? 0x1600 : 0x2c00));
+		b43_phy_maskset(dev, 0x06ef + st, (u16)~0x00ff, 15 * (bw / 20));
+	}
+}
+
+static void b43_phy_ac_phyinit(struct b43_wldev *dev)
+{
+	/*
+	 * The prologue of b43_radio_2069_init()
+	 * (0x0415/040e/040c/0408/0417/0416) and the end state of the power-on
+	 * (0x0408 = 0x0c02, 0x0417 = 4)
+	 */
+	b43_phy_write(dev, 0x1739, 0x0000);
+	b43_phy_write(dev, 0x0415, 0x0000);
+	b43_phy_write(dev, 0x040e, 0x0000);
+	b43_phy_write(dev, 0x040c, 0x2000);
+	b43_phy_write(dev, 0x0416, 0x000d);
+	b43_phy_write(dev, 0x0408, 0x0c02);
+	b43_phy_write(dev, 0x0417, 0x0004);
+	b43_phy_write(dev, 0x016b, 0x0000);
+	b43_phy_write(dev, 0x0175, 0x0000);
+
+	b43_phy_ac_mode_init(dev);
+	b43_phy_write(dev, 0x1645, 0x025c);	/* init_regs */
+	b43_phy_write(dev, 0x03c4, 0x0668);
+	b43_phy_ac_set_reg_on_reset(dev);
+	b43_phy_write(dev, 0x0358, 0xc07f);	/* set_pdet_on_reset */
+	/* FEM table 2 / sub 1 setup */
+	b43_phy_set(dev, 0x040a, 0x0100);
+	b43_phy_write(dev, 0x0414, 0x0555);
+	/* Second TX chain: without this bit core 1 does not radiate and
+	 * two-stream rates fail completely.
+	 */
+	if (dev->dev->bus_type == B43_BUS_BCMA)
+		bcma_cc_set32(&dev->dev->bdev->bus->drv_cc, BCMA_CC_CHIPCTL,
+			      0x00000008);
+	b43_phy_ac_coeff_bank_init(dev);
+	/* RX gain control, all cores. Without it the
+	 * receive level is 26 dB down: -66 instead of -40 dBm.
+	 */
+	b43_phy_write(dev, 0x1726, 0x000c);
+	b43_phy_write(dev, 0x0197, 0x0014);	/* channel_setup */
+	b43_phy_write(dev, 0x0198, 0x0010);
+	b43_phy_ac_wide_tables_2g(dev);
+}
+
+static void b43_phy_ac_setup_regs(struct b43_wldev *dev)
+{
+	/*
+	 * Radio state the hardware TX power loop needs (TSSI / power detector
+	 * path, per-core 0x01a-0x01f / 0x21a-0x21f). Without it PHY 0x640/0x840
+	 * freeze at index 0 and the loop never reaches its target.
+	 */
+	b43_radio_write(dev, 0x0548, 0x0001);
+	b43_radio_write(dev, 0x0549, 0x0000);
+	b43_radio_write(dev, 0x054a, 0x0000);
+	b43_radio_write(dev, 0x054c, 0x0000);
+	b43_radio_write(dev, 0x040b, 0x0168);
+	b43_radio_write(dev, 0x054b, 0x0101);
+	b43_radio_write(dev, 0x004e, 0x8400);
+	b43_radio_write(dev, 0x0166, 0x0000);
+	b43_radio_write(dev, 0x024e, 0x8600);
+	b43_radio_write(dev, 0x0366, 0x0000);
+	b43_radio_write(dev, 0x001a, 0x0014);
+	b43_radio_write(dev, 0x001b, 0x0280);
+	b43_radio_write(dev, 0x001c, 0x0044);
+	b43_radio_write(dev, 0x001e, 0x0010);
+	b43_radio_write(dev, 0x001f, 0x0000);
+	b43_radio_write(dev, 0x021a, 0x0014);
+	b43_radio_write(dev, 0x021b, 0x0280);
+	b43_radio_write(dev, 0x021c, 0x0044);
+	b43_radio_write(dev, 0x021e, 0x0010);
+	b43_radio_write(dev, 0x021f, 0x0000);
+	b43_radio_write(dev, 0x0170, 0x0100);
+
+	b43_phy_ac_phyinit(dev);
+	/*
+	 * Hardware TX power control: 0x70 bits 15:13 enable it, 0x71 holds the
+	 * averaging window, 0x72 the rest of its configuration. Enabled: with
+	 * the wide tables it no longer fails frames next to the AP (0x0100
+	 * would switch it off).
+	 */
+	b43_phy_write(dev, 0x0070, 0xe500);
+	b43_phy_write(dev, 0x0071, 0x04c8);
+	b43_phy_write(dev, 0x0072, 0x400d);
+}
+
+/*
+ * Radio registers written from entries [2..51] of the 2069 tuning table, in
+ * table order. Resolved for acphychipid 0x4360 from the vendor driver's
+ * channel-set code.
+ */
+static const u16 b43_radio_2069_tune_regs[B43_RADIO_2069_TUNE_REGS] = {
+	0x8e0, 0x8e1, 0x8dd, 0x8dc, 0x8e6, 0x8e7, 0x8c4, 0x8c5, 0x8e5, 0x8eb,
+	0x8d6, 0x113, 0x8db, 0x8da, 0x8d7, 0x885, 0x886, 0x887, 0x8d9, 0x8d8,
+	0x8c9, 0x8ca, 0x8cc, 0x8c7, 0x8c8, 0x892, 0x894, 0x895, 0x896, 0x897,
+	0x899, 0x89a, 0x89b, 0x89c, 0x112, 0x629, 0x65b, 0x65e, 0x668, 0x11a,
+	0x11b, 0x719, 0x630, 0x65c, 0x662, 0x66d, 0x893, 0x145, 0x146, 0x723,
+};
+
+static const struct b43_radio_2069_chan *
+b43_radio_2069_find_chan(struct b43_wldev *dev, unsigned int channel)
+{
+	unsigned int i;
+
+	if (dev->phy.radio_ver != 0x2069 || dev->phy.radio_rev != 4)
+		return NULL;
+	for (i = 0; i < b43_radio_2069r4_chans_n; i++)
+		if (b43_radio_2069r4_chans[i].channel == channel)
+			return &b43_radio_2069r4_chans[i];
+	return NULL;
+}
+
+/* Synthesizer VCO calibration kick. */
+static void b43_radio_2069_vcocal(struct b43_wldev *dev)
+{
+	b43_radio_mask(dev, 0x8e5, ~0x4000);
+	b43_radio_mask(dev, 0x8d0, ~0x0001);
+	b43_radio_mask(dev, 0x8e8, ~0x0040);
+	b43_radio_mask(dev, 0x8dc, ~0x2000);
+	udelay(11);
+	b43_radio_set(dev, 0x8d0, 0x0001);
+	b43_radio_set(dev, 0x8e8, 0x0040);
+	udelay(1);
+	b43_radio_set(dev, 0x8dc, 0x2000);
+}
+
+/* Reset clear-channel assessment (PHY rev 1 variant). */
+static void b43_phy_ac_resetcca(struct b43_wldev *dev)
+{
+	u16 bbcfg;
+
+	b43_phy_force_clock(dev, true);
+	bbcfg = b43_phy_read(dev, B43_PHY_AC_BBCFG);
+	b43_phy_write(dev, B43_PHY_AC_BBCFG, bbcfg | B43_PHY_AC_BBCFG_RSTCCA);
+	udelay(1);
+	b43_phy_write(dev, B43_PHY_AC_BBCFG, bbcfg & ~B43_PHY_AC_BBCFG_RSTCCA);
+	b43_phy_force_clock(dev, false);
+	udelay(2);
+}
+
+/*
+ * Per-core RF control state of the 2.4 GHz setup that the init does not reach.
+ */
+static void b43_phy_ac_rfctrl_2g(struct b43_wldev *dev)
+{
+	static const u16 regs[][2] = {
+		{ 0x645, 0x024d }, { 0x845, 0x025f },
+		{ 0x725, 0x0600 }, { 0x925, 0x0600 },
+		{ 0x727, 0x0004 }, { 0x927, 0x0004 },
+		{ 0x728, 0x0880 }, { 0x928, 0x0880 },
+		{ 0x729, 0x1000 }, { 0x929, 0x1000 },
+		{ 0x73a, 0x0180 }, { 0x93a, 0x0180 },
+	};
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(regs); i++)
+		b43_phy_write(dev, regs[i][0], regs[i][1]);
+}
+
+#include "phy_ac_farrow.h"
+
+/*
+ * The ADC/DAC run from a clock derived from the synthesizer, so the
+ * fractional resampler to the baseband rate depends on the channel. The vendor
+ * driver writes these on every channel switch; without them every channel
+ * kept channel 6's ratio, 3.5% off on channel 1.
+ */
+static void b43_phy_ac_set_farrow(struct b43_wldev *dev, unsigned int channel)
+{
+	const struct b43_phy_ac_farrow *f = NULL;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(b43_phy_ac_farrow_20); i++)
+		if (b43_phy_ac_farrow_20[i].channel == channel)
+			f = &b43_phy_ac_farrow_20[i];
+	if (!f)
+		return;
+
+	b43_phy_write(dev, 0x19a, f->rx[0]);
+	b43_phy_write(dev, 0x19b, f->rx[1]);
+	b43_phy_write(dev, 0x19c, f->rx[2]);
+	b43_phy_write(dev, 0x199, f->rx[3]);
+	b43_phy_write(dev, 0x1a1, f->rx[0]);
+	b43_phy_write(dev, 0x1a2, f->rx[1]);
+	b43_phy_write(dev, 0x1a3, f->rx[2]);
+	b43_phy_write(dev, 0x1a0, f->rx[3]);
+	b43_phy_write(dev, 0x1603, f->tx[0]);
+	b43_phy_write(dev, 0x1602, f->tx[1]);
+	b43_phy_write(dev, 0x1607, f->tx[2]);
+	b43_phy_write(dev, 0x1606, f->tx[3]);
+	b43_phy_write(dev, 0x1601, b43_phy_read(dev, 0x601));
+}
+
+/* Program the synthesizer and the per-channel radio words of one channel. */
+static void b43_phy_ac_tune(struct b43_wldev *dev,
+			    const struct b43_radio_2069_chan *e,
+			    unsigned int channel)
+{
+	int i;
+
+	for (i = 0; i < B43_RADIO_2069_TUNE_REGS; i++)
+		b43_radio_write(dev, b43_radio_2069_tune_regs[i], e->radio[i]);
+	if (channel == 4) {
+		b43_radio_write(dev, 0x8d6, 0x0ce4);
+		b43_radio_maskset(dev, 0x8ec, ~0x0070, 0x0050);
+	}
+	b43_radio_set(dev, 0x645, 0x7000);
+	b43_radio_write(dev, 0x723, 0x83e0);
+	b43_radio_2069_vcocal(dev);
+}
+
+/*
+ * Channel switch for radio 2069 rev 4, following the vendor driver's
+ * channel-set sequence. Not ported: carrier-search suppression during the
+ * switch, the 5 GHz PLL setup and the per-channel PHY tweaks that follow the BW
+ * registers.
+ */
+static int b43_phy_ac_op_switch_channel(struct b43_wldev *dev,
+					unsigned int new_channel)
+{
+	struct b43_phy_ac *phy_ac = dev->phy.ac;
+	const struct b43_radio_2069_chan *e;
+	u16 save;
+	int i;
+
+	if (b43_current_band(dev->wl) != NL80211_BAND_2GHZ)
+		return -EOPNOTSUPP;
+
+	e = b43_radio_2069_find_chan(dev, new_channel);
+	if (!e) {
+		b43err(dev->wl, "phy_ac: no tuning data for channel %u (radio %04x rev %u)\n",
+		       new_channel, dev->phy.radio_ver, dev->phy.radio_rev);
+		return -ESRCH;
+	}
+	b43dbg(dev->wl, "phy_ac: switch_channel(%u) -> %u MHz\n",
+	       new_channel, e->freq);
+
+	save = b43_phy_read(dev, 0x19e);
+	b43_phy_set(dev, 0x19e, 0x3);
+
+	b43_phy_mask(dev, B43_PHY_AC_BANDCTL, ~0x0100);
+
+	if (!phy_ac->chan_set) {
+		b43_phy_set(dev, 0x728, 0x0100);
+		udelay(1);
+		b43_phy_mask(dev, 0x728, ~0x0100);
+		phy_ac->chan_set = true;
+	}
+
+	b43_phy_ac_tune(dev, e, new_channel);
+	b43_phy_maskset(dev, 0x19e, ~0x3, save & 0x3);
+
+	for (i = 0; i < 6; i++)
+		b43_phy_write(dev, B43_PHY_AC_BW1A + i, e->bw[i]);
+
+	b43_phy_ac_rfctrl_2g(dev);
+	b43_phy_ac_set_farrow(dev, new_channel);
+	b43_phy_ac_resetcca(dev);
+	b43_phy_ac_txpwr_by_index(dev, B43_AC_TXIDX_2G);
+
+	return 0;
+}
+
+/* Write a table of 8, 16 or 32 bit entries through the PHY table ports. */
+static void b43_phy_ac_write_table(struct b43_wldev *dev,
+				   const struct b43_phy_ac_tbl *t)
+{
+	unsigned int i;
+	u32 v;
+
+	b43_phy_write(dev, B43_PHY_AC_TABLE_ID, t->id);
+	b43_phy_write(dev, B43_PHY_AC_TABLE_OFFSET, t->offset);
+	for (i = 0; i < t->count; i++) {
+		switch (t->width) {
+		case 8:
+			b43_phy_write(dev, B43_PHY_AC_TABLE_DATA1,
+				      ((const u8 *)t->data)[i]);
+			break;
+		case 16:
+			b43_phy_write(dev, B43_PHY_AC_TABLE_DATA1,
+				      ((const u16 *)t->data)[i]);
+			break;
+		case 32:
+			v = ((const u32 *)t->data)[i];
+			b43_phy_write(dev, B43_PHY_AC_TABLE_DATA2, v >> 16);
+			b43_phy_write(dev, B43_PHY_AC_TABLE_DATA1, v & 0xffff);
+			break;
+		}
+	}
+}
+
+/*
+ * 2.4 GHz power-estimation LUT of one core (tables 0x40 / 0x60), 128 entries,
+ * from the SROM power-detector triple (a1, b0, b1) = pa2ga words. At step j:
+ * num = 512*b0 + 32*b1*j, den = 0x8000 + a1*j, v = (den/2 + num)/den clamped to
+ * [-8, 0x7f] (the same transfer function as b43_nphy_tx_power_ctl_setup(); it
+ * matches the vendor driver's table entry for entry on this board). SROM word
+ * offsets (rev 11): core 0 pa2ga at 0x6d, core 1 at 0x81.
+ */
+static void b43_phy_ac_write_est_pwr(struct b43_wldev *dev)
+{
+	static const struct {
+		u16 id;
+		u16 word;
+	} core_tbl[] = { { 0x40, 0x6d }, { 0x60, 0x81 } };
+	struct bcma_drv_cc *cc;
+	unsigned int c, j;
+
+	if (dev->dev->bus_type != B43_BUS_BCMA)
+		return;
+	cc = &dev->dev->bdev->bus->drv_cc;
+	for (c = 0; c < ARRAY_SIZE(core_tbl) && c < b43_phy_ac_num_cores(dev);
+	     c++) {
+		u16 base = BCMA_CC_SPROM + 2 * core_tbl[c].word;
+		u16 w0 = bcma_read16(cc->core, base);
+		u16 w1 = bcma_read16(cc->core, base + 2);
+		u16 w2 = bcma_read16(cc->core, base + 4);
+		s32 a1 = (s16)w0, b0 = (s16)w1, b1 = (s16)w2, num, den;
+		u16 lut[128];
+		struct b43_phy_ac_tbl tbl = { lut, 128, core_tbl[c].id, 0, 16 };
+
+		if (w0 == 0xffff && w1 == 0xffff && w2 == 0xffff)
+			/* unprogrammed SROM: keep the default table */
+			continue;
+		num = b0 << 9;
+		den = 0x8000;
+		for (j = 0; j < 128; j++) {
+			s32 d = den ? den : 1;
+			s32 v = (d / 2 + num) / d;
+
+			num += b1 * 0x20;
+			den += a1;
+			lut[j] = (u16)(clamp(v, -8, 0x7f) & 0xff);
+		}
+		b43_phy_ac_write_table(dev, &tbl);
+	}
+}
+
+/*
+ * PHY init for PHY rev 0/1: the AFE page, then the table set of the
+ * acphytbl_info_rev0 plus the FEM tables of this board's control pattern.
+ */
+static void b43_phy_ac_tables_init(struct b43_wldev *dev)
+{
+	static const u16 clear_regs[] = {
+		0x173e, 0x1725, 0x1722, 0x1723, 0x1724, 0x1725, 0x1726, 0x1727,
+		0x1750,
+	};
+	unsigned int i;
+	u16 save;
+
+	b43_phy_write(dev, 0x410, 0x77);
+	for (i = 0; i < ARRAY_SIZE(clear_regs); i++)
+		b43_phy_write(dev, clear_regs[i], 0);
+	b43_phy_write(dev, 0x1728, 0x80);
+	b43_phy_write(dev, 0x1720, 0x180);
+	b43_phy_write(dev, 0x1729, 0);
+	b43_phy_write(dev, 0x1721, 0x5000);
+	b43_phy_write(dev, 0x173a, b43_phy_read(dev, 0x73a) | 0x100);
+	b43_phy_write(dev, 0x1725, b43_phy_read(dev, 0x725) | 0x400);
+
+	save = b43_phy_read(dev, 0x19e);
+	b43_phy_set(dev, 0x19e, 0x2);
+	for (i = 0; i < b43_phy_ac_tbls_rev0_n; i++)
+		b43_phy_ac_write_table(dev, &b43_phy_ac_tbls_rev0[i]);
+	for (i = 0; i < b43_phy_ac_rfseq_tbls_n; i++)
+		b43_phy_ac_write_table(dev, &b43_phy_ac_rfseq_tbls[i]);
+	b43_phy_ac_write_est_pwr(dev);
+	for (i = 0; i < b43_phy_ac_misc_tbls_n; i++)
+		b43_phy_ac_write_table(dev, &b43_phy_ac_misc_tbls[i]);
+	for (i = 0; i < b43_phy_ac_ladder_tbls_n; i++)
+		b43_phy_ac_write_table(dev, &b43_phy_ac_ladder_tbls[i]);
+	for (i = 0; i < b43_phy_ac_vendor_tbls_n; i++)
+		b43_phy_ac_write_table(dev, &b43_phy_ac_vendor_tbls[i]);
+	/*
+	 * FEM control pattern: only the femctrl == 2 variant (this card) is
+	 * known. SROM rev 11 word 0x55 bits 15:11.
+	 */
+	if (dev->dev->bus_type == B43_BUS_BCMA &&
+	    (bcma_read16(dev->dev->bdev->bus->drv_cc.core,
+			 BCMA_CC_SPROM + 0xaa) >>
+	     11) == 2)
+		for (i = 0; i < b43_phy_ac_femctrl2_tbls_n; i++)
+			b43_phy_ac_write_table(dev,
+					       &b43_phy_ac_femctrl2_tbls[i]);
+	b43_phy_maskset(dev, 0x19e, ~0x2, save & 0x2);
+
+	b43_phy_write(dev, 0x1645, 0x25c);
+	b43dbg(dev->wl, "phy_ac: wrote %u PHY tables\n",
+	       b43_phy_ac_tbls_rev0_n);
+}
+
+/*
+ * First-init PHY register setup for PHY rev 0/1. Not ported: the hardware
+ * interference mitigation setup.
+ */
+static void b43_phy_ac_first_init(struct b43_wldev *dev)
+{
+	bool is_2ghz = b43_current_band(dev->wl) == NL80211_BAND_2GHZ;
+	u8 core, cores = b43_phy_ac_num_cores(dev);
+	static const u16 core_reg[3] = { 0x690, 0x890, 0xa90 };
+
+	b43_phy_set(dev, 0x19e, 0x1c0);
+	if (is_2ghz)
+		b43_phy_write(dev, 0x3c4, 0x668);
+	b43_phy_set(dev, 0x19e, 0x200);
+	b43_phy_maskset(dev, 0x19e, ~0x3c, 0x10);
+	b43_phy_write(dev, 0x1f2, 0xc8);
+	b43_phy_write(dev, 0x026, 0x92);
+	b43_phy_write(dev, 0x1ed, 0x50);
+	b43_phy_write(dev, 0x025, 0x30);
+
+	if (dev->dev->bus_type == B43_BUS_BCMA)
+		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL,
+			      bcma_aread32(dev->dev->bdev, BCMA_IOCTL) |
+			      B43_BCMA_IOCTL_MACPHYCLKEN);
+
+	b43_phy_mask(dev, 0x40f, ~0x200);
+	b43_phy_mask(dev, 0x2f1, ~0x20);
+	b43_phy_mask(dev, 0x2ed, ~0x20);
+	b43_phy_mask(dev, 0x2f9, ~0x20);
+	b43_phy_mask(dev, 0x2f5, ~0x20);
+	b43_phy_maskset(dev, 0x2ef, ~0xff, 0x55);
+	b43_phy_maskset(dev, 0x2eb, ~0xff, 0x55);
+	b43_phy_maskset(dev, 0x2f7, ~0xff, 0x55);
+	b43_phy_maskset(dev, 0x2f3, ~0xff, 0x55);
+
+	b43_phy_write(dev, 0x400, 0);
+	b43_phy_mask(dev, 0x1ca, ~0x1000);
+	b43_phy_ac_resetcca(dev);
+	b43_phy_set(dev, 0x072, 0x4);
+	b43_phy_mask(dev, 0x1b0, ~0x20);
+	b43_phy_set(dev, 0x1b1, 0x1000);
+	b43_phy_mask(dev, 0x1b6, 0x7fff);
+	for (core = 0; core < cores && core < 3; core++) {
+		b43_phy_set(dev, core_reg[core], 0x200);
+		b43_phy_set(dev, core_reg[core], 0x400);
+	}
+	b43_phy_write(dev, 0x1e6, 0x30);
+	b43_phy_write(dev, 0x358, 0xc07f);
+
+	b43dbg(dev->wl, "phy_ac: first-init registers done\n");
+}
+
+static void b43_phy_ac_table_write16(struct b43_wldev *dev, u16 id,
+				     u16 offset, u16 value)
+{
+	b43_phy_write(dev, B43_PHY_AC_TABLE_ID, id);
+	b43_phy_write(dev, B43_PHY_AC_TABLE_OFFSET, offset);
+	b43_phy_write(dev, B43_PHY_AC_TABLE_DATA1, value);
+}
+
+/* Set the TX gain of both cores from the 2.4 GHz gain table, as the stock
+ * driver's txpwr_by_index does with hardware power control off.
+ */
+static void b43_phy_ac_txpwr_by_index(struct b43_wldev *dev, unsigned int idx)
+{
+	const u16 *e = b43_phy_ac_txgain_2g[min(idx, 127u)];
+	u16 bbmult = e[0] & 0x00ff;
+	u16 g0 = (e[0] >> 8) | ((e[1] & 0x00ff) << 8);
+	u16 g1 = (e[1] >> 8) | ((e[2] & 0x00ff) << 8);
+	u16 g2 = e[2] >> 8;
+	u8 core, cores = b43_phy_ac_num_cores(dev);
+
+	for (core = 0; core < cores && core < 3; core++) {
+		b43_phy_ac_table_write16(dev, 7, core + 0x100, g0);
+		b43_phy_ac_table_write16(dev, 7, core + 0x103, g1);
+		b43_phy_ac_table_write16(dev, 7, core + 0x106, g2);
+		b43_phy_ac_table_write16(dev, 0xc, 0x63 + 4 * core, bbmult);
+		b43_phy_ac_table_write16(dev, 0xc, 0x73 + 4 * core, bbmult);
+	}
+}
+
+static int b43_phy_ac_op_init(struct b43_wldev *dev)
+{
+	if (dev->phy.rev <= 1) {
+		b43_phy_ac_tables_init(dev);
+		b43_phy_ac_first_init(dev);
+		/* The channel switch that follows init tunes the radio. */
+		b43_phy_ac_setup_regs(dev);
+	} else {
+		b43err(dev->wl, "phy_ac: no table set for PHY rev %u\n",
+		       dev->phy.rev);
+	}
+
+	b43dbg(dev->wl,
+	       "phy_ac: init (core_rev %u, radio24=%d, chip %04x, board %04x, radio_on %d)\n",
+	       dev->dev->core_rev, b43_phy_ac_use_radio24(dev),
+	       dev->dev->chip_id, dev->dev->board_type, dev->phy.ac->radio_on);
+
+	return 0;
+}
+
+/*
+ * Self-healing for a bad init: only about 30 % of fresh inits can transmit; in
+ * the others every TX ends in a PHY TX error. The 15 s work polls the ucode's
+ * txphyerr counter (SHM 0xFE) and restarts the core through mac80211 (fresh
+ * init, fresh coin flip) after >= 3 errors in a window, at most 3 times
+ * (B43_AC_SELFHEAL_MAX); the budget refills after 10 quiet minutes. Polled, not
+ * IRQ-driven: unmasking B43_IRQ_PHY_TXERR hung the machine.
+ */
+#define B43_AC_SELFHEAL_MAX	3
+#define B43_AC_SH_TXPHYERR	0x00FE
+
+static bool b43_phy_ac_check_badinit(struct b43_wldev *dev)
+{
+	static unsigned int restarts;
+	static unsigned long last_restart;
+	static u16 last;
+	u16 now, d;
+
+	if (restarts && time_after(jiffies, last_restart + 600 * HZ))
+		restarts = 0;
+	now = b43_shm_read16(dev, B43_SHM_SHARED, B43_AC_SH_TXPHYERR);
+	d = now - last;
+	last = now;
+	if (d < 3 || restarts >= B43_AC_SELFHEAL_MAX)
+		return false;
+	restarts++;
+	last_restart = jiffies;
+	last = 0;	/* the ucode is reloaded, its counters restart at 0 */
+	b43err(dev->wl, "AC-PHY: bad init (%u PHY TX errors), restart %u/%u\n",
+	       d, restarts, B43_AC_SELFHEAL_MAX);
+	b43_controller_restart(dev, "AC bad init");
+	return true;
+}
+
+static void b43_phy_ac_op_pwork_15sec(struct b43_wldev *dev)
+{
+	b43_phy_ac_check_badinit(dev);
 }
 
 static unsigned int b43_phy_ac_op_get_default_chan(struct b43_wldev *dev)
@@ -79,10 +1078,17 @@ static void b43_phy_ac_op_adjust_txpower(struct b43_wldev *dev)
 const struct b43_phy_operations b43_phyops_ac = {
 	.allocate		= b43_phy_ac_op_allocate,
 	.free			= b43_phy_ac_op_free,
+	.prepare_structs	= b43_phy_ac_op_prepare_structs,
+	.init			= b43_phy_ac_op_init,
+	.phy_write		= b43_phy_ac_op_write,
 	.phy_maskset		= b43_phy_ac_op_maskset,
 	.radio_read		= b43_phy_ac_op_radio_read,
 	.radio_write		= b43_phy_ac_op_radio_write,
+	.software_rfkill	= b43_phy_ac_op_software_rfkill,
+	.switch_analog		= b43_phy_ac_op_switch_analog,
+	.switch_channel		= b43_phy_ac_op_switch_channel,
 	.get_default_chan	= b43_phy_ac_op_get_default_chan,
 	.recalc_txpower		= b43_phy_ac_op_recalc_txpower,
 	.adjust_txpower		= b43_phy_ac_op_adjust_txpower,
+	.pwork_15sec		= b43_phy_ac_op_pwork_15sec,
 };
diff --git a/drivers/net/wireless/broadcom/b43/phy_ac.h b/drivers/net/wireless/broadcom/b43/phy_ac.h
index 02eb6c0..0b6896e 100644
--- a/drivers/net/wireless/broadcom/b43/phy_ac.h
+++ b/drivers/net/wireless/broadcom/b43/phy_ac.h
@@ -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;
diff --git a/drivers/net/wireless/broadcom/b43/phy_ac_farrow.h b/drivers/net/wireless/broadcom/b43/phy_ac_farrow.h
new file mode 100644
index 0000000..c707d4d
--- /dev/null
+++ b/drivers/net/wireless/broadcom/b43/phy_ac_farrow.h
@@ -0,0 +1,260 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * the vendor driver's rx_farrow_tbl / tx_farrow_dac1_tbl, 20 MHz section
+ * (dump_farrow.java).
+ *
+ * Copyright (c) 2026 Andreas Wendleder <gonsolo@gmail.com>
+ */
+static const struct b43_phy_ac_farrow {
+	u8 channel;
+	/* PHY 0x19a/0x19b/0x19c/0x199, core 1 at 0x1a1/0x1a2/0x1a3/0x1a0 */
+	u16 rx[4];
+	u16 tx[4];	/* PHY 0x1603/0x1602/0x1607/0x1606 */
+} b43_phy_ac_farrow_20[] = {
+	{ 184, { 0x0000, 0x0048, 0x0f00, 0x00a7 },
+	       { 0xe706, 0x0063, 0xe706, 0x0063 } },
+	{ 186, { 0xaaab, 0x0048, 0x0f00, 0x00a7 },
+	       { 0xb326, 0x0063, 0xb326, 0x0063 } },
+	{ 188, { 0x5555, 0x0049, 0x0f00, 0x00a7 },
+	       { 0x7f7b, 0x0063, 0x7f7b, 0x0063 } },
+	{ 190, { 0x0000, 0x004a, 0x0f00, 0x00a7 },
+	       { 0x4c06, 0x0063, 0x4c06, 0x0063 } },
+	{ 192, { 0xaaab, 0x004a, 0x0f00, 0x00a7 },
+	       { 0x18c6, 0x0063, 0x18c6, 0x0063 } },
+	{ 194, { 0x5555, 0x004b, 0x0f00, 0x00a7 },
+	       { 0xe5bb, 0x0062, 0xe5bb, 0x0062 } },
+	{ 196, { 0x0000, 0x004c, 0x0f00, 0x00a7 },
+	       { 0xb2e4, 0x0062, 0xb2e4, 0x0062 } },
+	{ 198, { 0xaaab, 0x004c, 0x0f00, 0x00a7 },
+	       { 0x8042, 0x0062, 0x8042, 0x0062 } },
+	{ 200, { 0x5555, 0x004d, 0x0f00, 0x00a7 },
+	       { 0x4dd3, 0x0062, 0x4dd3, 0x0062 } },
+	{ 202, { 0x0000, 0x004e, 0x0f00, 0x00a7 },
+	       { 0x1b98, 0x0062, 0x1b98, 0x0062 } },
+	{ 204, { 0xaaab, 0x004e, 0x0f00, 0x00a7 },
+	       { 0xe990, 0x0061, 0xe990, 0x0061 } },
+	{ 206, { 0x5555, 0x004f, 0x0f00, 0x00a7 },
+	       { 0xb7bb, 0x0061, 0xb7bb, 0x0061 } },
+	{ 208, { 0x0000, 0x0050, 0x0f00, 0x00a7 },
+	       { 0x8618, 0x0061, 0x8618, 0x0061 } },
+	{ 210, { 0xaaab, 0x0050, 0x0f00, 0x00a7 },
+	       { 0x54a8, 0x0061, 0x54a8, 0x0061 } },
+	{ 212, { 0x5555, 0x0051, 0x0f00, 0x00a7 },
+	       { 0x236a, 0x0061, 0x236a, 0x0061 } },
+	{ 214, { 0x0000, 0x0052, 0x0f00, 0x00a7 },
+	       { 0xf25e, 0x0060, 0xf25e, 0x0060 } },
+	{ 216, { 0xaaab, 0x0052, 0x0f00, 0x00a7 },
+	       { 0xc183, 0x0060, 0xc183, 0x0060 } },
+	{ 218, { 0x5555, 0x0053, 0x0f00, 0x00a7 },
+	       { 0x90d9, 0x0060, 0x90d9, 0x0060 } },
+	{ 220, { 0x0000, 0x0054, 0x0f00, 0x00a7 },
+	       { 0x6060, 0x0060, 0x6060, 0x0060 } },
+	{ 222, { 0xaaab, 0x0054, 0x0f00, 0x00a7 },
+	       { 0x3018, 0x0060, 0x3018, 0x0060 } },
+	{ 224, { 0x5555, 0x0055, 0x0f00, 0x00a7 },
+	       { 0x0000, 0x0060, 0x0000, 0x0060 } },
+	{ 226, { 0x0000, 0x0056, 0x0f00, 0x00a7 },
+	       { 0xd018, 0x005f, 0xd018, 0x005f } },
+	{ 228, { 0xaaab, 0x0056, 0x0f00, 0x00a7 },
+	       { 0xa060, 0x005f, 0xa060, 0x005f } },
+	{  32, { 0x0000, 0x0058, 0x0f00, 0x00a7 },
+	       { 0x417d, 0x005f, 0x417d, 0x005f } },
+	{  34, { 0xaaab, 0x0058, 0x0f00, 0x00a7 },
+	       { 0x1252, 0x005f, 0x1252, 0x005f } },
+	{  36, { 0x5555, 0x0059, 0x0f00, 0x00a7 },
+	       { 0xe356, 0x005e, 0xe356, 0x005e } },
+	{  38, { 0x0000, 0x005a, 0x0f00, 0x00a7 },
+	       { 0xb488, 0x005e, 0xb488, 0x005e } },
+	{  40, { 0xaaab, 0x005a, 0x0f00, 0x00a7 },
+	       { 0x85e8, 0x005e, 0x85e8, 0x005e } },
+	{  42, { 0x5555, 0x005b, 0x0f00, 0x00a7 },
+	       { 0x5776, 0x005e, 0x5776, 0x005e } },
+	{  44, { 0x0000, 0x005c, 0x0f00, 0x00a7 },
+	       { 0x2932, 0x005e, 0x2932, 0x005e } },
+	{  46, { 0xaaab, 0x005c, 0x0f00, 0x00a7 },
+	       { 0xfb1b, 0x005d, 0xfb1b, 0x005d } },
+	{  48, { 0x5555, 0x005d, 0x0f00, 0x00a7 },
+	       { 0xcd31, 0x005d, 0xcd31, 0x005d } },
+	{  50, { 0x0000, 0x005e, 0x0f00, 0x00a7 },
+	       { 0x9f74, 0x005d, 0x9f74, 0x005d } },
+	{  52, { 0xaaab, 0x005e, 0x0f00, 0x00a7 },
+	       { 0x71e3, 0x005d, 0x71e3, 0x005d } },
+	{  54, { 0x5555, 0x005f, 0x0f00, 0x00a7 },
+	       { 0x447e, 0x005d, 0x447e, 0x005d } },
+	{  56, { 0x0000, 0x0060, 0x0f00, 0x00a7 },
+	       { 0x1746, 0x005d, 0x1746, 0x005d } },
+	{  58, { 0xaaab, 0x0060, 0x0f00, 0x00a7 },
+	       { 0xea39, 0x005c, 0xea39, 0x005c } },
+	{  60, { 0x5555, 0x0061, 0x0f00, 0x00a7 },
+	       { 0xbd58, 0x005c, 0xbd58, 0x005c } },
+	{  62, { 0x0000, 0x0062, 0x0f00, 0x00a7 },
+	       { 0x90a2, 0x005c, 0x90a2, 0x005c } },
+	{  64, { 0xaaab, 0x0062, 0x0f00, 0x00a7 },
+	       { 0x6417, 0x005c, 0x6417, 0x005c } },
+	{  66, { 0x5555, 0x0063, 0x0f00, 0x00a7 },
+	       { 0x37b7, 0x005c, 0x37b7, 0x005c } },
+	{  68, { 0x0000, 0x0064, 0x0f00, 0x00a7 },
+	       { 0x0b81, 0x005c, 0x0b81, 0x005c } },
+	{  70, { 0xaaab, 0x0064, 0x0f00, 0x00a7 },
+	       { 0xdf76, 0x005b, 0xdf76, 0x005b } },
+	{  72, { 0x5555, 0x0065, 0x0f00, 0x00a7 },
+	       { 0xb395, 0x005b, 0xb395, 0x005b } },
+	{  74, { 0x0000, 0x0066, 0x0f00, 0x00a7 },
+	       { 0x87de, 0x005b, 0x87de, 0x005b } },
+	{  76, { 0xaaab, 0x0066, 0x0f00, 0x00a7 },
+	       { 0x5c50, 0x005b, 0x5c50, 0x005b } },
+	{  78, { 0x5555, 0x0067, 0x0f00, 0x00a7 },
+	       { 0x30ec, 0x005b, 0x30ec, 0x005b } },
+	{  80, { 0x0000, 0x0068, 0x0f00, 0x00a7 },
+	       { 0x05b0, 0x005b, 0x05b0, 0x005b } },
+	{  82, { 0xaaab, 0x0068, 0x0f00, 0x00a7 },
+	       { 0xda9e, 0x005a, 0xda9e, 0x005a } },
+	{  84, { 0x5555, 0x0069, 0x0f00, 0x00a7 },
+	       { 0xafb4, 0x005a, 0xafb4, 0x005a } },
+	{  86, { 0x0000, 0x006a, 0x0f00, 0x00a7 },
+	       { 0x84f3, 0x005a, 0x84f3, 0x005a } },
+	{  88, { 0xaaab, 0x006a, 0x0f00, 0x00a7 },
+	       { 0x5a5a, 0x005a, 0x5a5a, 0x005a } },
+	{  90, { 0x5555, 0x006b, 0x0f00, 0x00a7 },
+	       { 0x2fe9, 0x005a, 0x2fe9, 0x005a } },
+	{  92, { 0x0000, 0x006c, 0x0f00, 0x00a7 },
+	       { 0x05a0, 0x005a, 0x05a0, 0x005a } },
+	{  94, { 0xaaab, 0x006c, 0x0f00, 0x00a7 },
+	       { 0xdb7f, 0x0059, 0xdb7f, 0x0059 } },
+	{  96, { 0x5555, 0x006d, 0x0f00, 0x00a7 },
+	       { 0xb185, 0x0059, 0xb185, 0x0059 } },
+	{  98, { 0x0000, 0x006e, 0x0f00, 0x00a7 },
+	       { 0x87b2, 0x0059, 0x87b2, 0x0059 } },
+	{ 100, { 0xaaab, 0x006e, 0x0f00, 0x00a7 },
+	       { 0x5e06, 0x0059, 0x5e06, 0x0059 } },
+	{ 102, { 0x5555, 0x006f, 0x0f00, 0x00a7 },
+	       { 0x3480, 0x0059, 0x3480, 0x0059 } },
+	{ 104, { 0x0000, 0x0070, 0x0f00, 0x00a7 },
+	       { 0x0b21, 0x0059, 0x0b21, 0x0059 } },
+	{ 106, { 0xaaab, 0x0070, 0x0f00, 0x00a7 },
+	       { 0xe1e9, 0x0058, 0xe1e9, 0x0058 } },
+	{ 108, { 0x5555, 0x0071, 0x0f00, 0x00a7 },
+	       { 0xb8d6, 0x0058, 0xb8d6, 0x0058 } },
+	{ 110, { 0x0000, 0x0072, 0x0f00, 0x00a7 },
+	       { 0x8fea, 0x0058, 0x8fea, 0x0058 } },
+	{ 112, { 0xaaab, 0x0072, 0x0f00, 0x00a7 },
+	       { 0x6723, 0x0058, 0x6723, 0x0058 } },
+	{ 114, { 0x5555, 0x0073, 0x0f00, 0x00a7 },
+	       { 0x3e82, 0x0058, 0x3e82, 0x0058 } },
+	{ 116, { 0x0000, 0x0074, 0x0f00, 0x00a7 },
+	       { 0x1606, 0x0058, 0x1606, 0x0058 } },
+	{ 118, { 0xaaab, 0x0074, 0x0f00, 0x00a7 },
+	       { 0xedae, 0x0057, 0xedae, 0x0057 } },
+	{ 120, { 0x5555, 0x0075, 0x0f00, 0x00a7 },
+	       { 0xc57c, 0x0057, 0xc57c, 0x0057 } },
+	{ 122, { 0x0000, 0x0076, 0x0f00, 0x00a7 },
+	       { 0x9d6f, 0x0057, 0x9d6f, 0x0057 } },
+	{ 124, { 0xaaab, 0x0076, 0x0f00, 0x00a7 },
+	       { 0x7586, 0x0057, 0x7586, 0x0057 } },
+	{ 126, { 0x5555, 0x0077, 0x0f00, 0x00a7 },
+	       { 0x4dc1, 0x0057, 0x4dc1, 0x0057 } },
+	{ 128, { 0x0000, 0x0078, 0x0f00, 0x00a7 },
+	       { 0x2621, 0x0057, 0x2621, 0x0057 } },
+	{ 130, { 0xaaab, 0x0078, 0x0f00, 0x00a7 },
+	       { 0xfea4, 0x0056, 0xfea4, 0x0056 } },
+	{ 132, { 0x5555, 0x0079, 0x0f00, 0x00a7 },
+	       { 0xd74b, 0x0056, 0xd74b, 0x0056 } },
+	{ 134, { 0x0000, 0x007a, 0x0f00, 0x00a7 },
+	       { 0xb016, 0x0056, 0xb016, 0x0056 } },
+	{ 136, { 0xaaab, 0x007a, 0x0f00, 0x00a7 },
+	       { 0x8904, 0x0056, 0x8904, 0x0056 } },
+	{ 138, { 0x5555, 0x007b, 0x0f00, 0x00a7 },
+	       { 0x6215, 0x0056, 0x6215, 0x0056 } },
+	{ 140, { 0x0000, 0x007c, 0x0f00, 0x00a7 },
+	       { 0x3b49, 0x0056, 0x3b49, 0x0056 } },
+	{ 142, { 0xaaab, 0x007c, 0x0f00, 0x00a7 },
+	       { 0x14a0, 0x0056, 0x14a0, 0x0056 } },
+	{ 144, { 0x5555, 0x007d, 0x0f00, 0x00a7 },
+	       { 0xee19, 0x0055, 0xee19, 0x0055 } },
+	{ 145, { 0xaaab, 0x007d, 0x0f00, 0x00a7 },
+	       { 0xdae3, 0x0055, 0xdae3, 0x0055 } },
+	{ 146, { 0x0000, 0x007e, 0x0f00, 0x00a7 },
+	       { 0xc7b5, 0x0055, 0xc7b5, 0x0055 } },
+	{ 147, { 0x5555, 0x007e, 0x0f00, 0x00a7 },
+	       { 0xb490, 0x0055, 0xb490, 0x0055 } },
+	{ 148, { 0xaaab, 0x007e, 0x0f00, 0x00a7 },
+	       { 0xa173, 0x0055, 0xa173, 0x0055 } },
+	{ 149, { 0x0000, 0x007f, 0x0f00, 0x00a7 },
+	       { 0x8e5f, 0x0055, 0x8e5f, 0x0055 } },
+	{ 150, { 0x5555, 0x007f, 0x0f00, 0x00a7 },
+	       { 0x7b53, 0x0055, 0x7b53, 0x0055 } },
+	{ 151, { 0xaaab, 0x007f, 0x0f00, 0x00a7 },
+	       { 0x6850, 0x0055, 0x6850, 0x0055 } },
+	{ 152, { 0x0000, 0x0080, 0x0f00, 0x00a7 },
+	       { 0x5555, 0x0055, 0x5555, 0x0055 } },
+	{ 153, { 0x5555, 0x0080, 0x0f00, 0x00a7 },
+	       { 0x4263, 0x0055, 0x4263, 0x0055 } },
+	{ 154, { 0xaaab, 0x0080, 0x0f00, 0x00a7 },
+	       { 0x2f79, 0x0055, 0x2f79, 0x0055 } },
+	{ 155, { 0x0000, 0x0081, 0x0f00, 0x00a7 },
+	       { 0x1c98, 0x0055, 0x1c98, 0x0055 } },
+	{ 156, { 0x5555, 0x0081, 0x0f00, 0x00a7 },
+	       { 0x09be, 0x0055, 0x09be, 0x0055 } },
+	{ 157, { 0xaaab, 0x0081, 0x0f00, 0x00a7 },
+	       { 0xf6ee, 0x0054, 0xf6ee, 0x0054 } },
+	{ 158, { 0x0000, 0x0082, 0x0f00, 0x00a7 },
+	       { 0xe425, 0x0054, 0xe425, 0x0054 } },
+	{ 159, { 0x5555, 0x0082, 0x0f00, 0x00a7 },
+	       { 0xd165, 0x0054, 0xd165, 0x0054 } },
+	{ 160, { 0xaaab, 0x0082, 0x0f00, 0x00a7 },
+	       { 0xbead, 0x0054, 0xbead, 0x0054 } },
+	{ 161, { 0x0000, 0x0083, 0x0f00, 0x00a7 },
+	       { 0xabfd, 0x0054, 0xabfd, 0x0054 } },
+	{ 162, { 0x5555, 0x0083, 0x0f00, 0x00a7 },
+	       { 0x9956, 0x0054, 0x9956, 0x0054 } },
+	{ 163, { 0xaaab, 0x0083, 0x0f00, 0x00a7 },
+	       { 0x86b7, 0x0054, 0x86b7, 0x0054 } },
+	{ 164, { 0x0000, 0x0084, 0x0f00, 0x00a7 },
+	       { 0x7420, 0x0054, 0x7420, 0x0054 } },
+	{ 165, { 0x5555, 0x0084, 0x0f00, 0x00a7 },
+	       { 0x6191, 0x0054, 0x6191, 0x0054 } },
+	{ 166, { 0xaaab, 0x0084, 0x0f00, 0x00a7 },
+	       { 0x4f0a, 0x0054, 0x4f0a, 0x0054 } },
+	{ 168, { 0x5555, 0x0085, 0x0f00, 0x00a7 },
+	       { 0x2a15, 0x0054, 0x2a15, 0x0054 } },
+	{ 170, { 0x0000, 0x0086, 0x0f00, 0x00a7 },
+	       { 0x0540, 0x0054, 0x0540, 0x0054 } },
+	{ 172, { 0xaaab, 0x0086, 0x0f00, 0x00a7 },
+	       { 0xe08c, 0x0053, 0xe08c, 0x0053 } },
+	{ 174, { 0x5555, 0x0087, 0x0f00, 0x00a7 },
+	       { 0xbbf7, 0x0053, 0xbbf7, 0x0053 } },
+	{ 176, { 0x0000, 0x0088, 0x0f00, 0x00a7 },
+	       { 0x9783, 0x0053, 0x9783, 0x0053 } },
+	{ 178, { 0xaaab, 0x0088, 0x0f00, 0x00a7 },
+	       { 0x732e, 0x0053, 0x732e, 0x0053 } },
+	{ 180, { 0x5555, 0x0089, 0x0f00, 0x00a7 },
+	       { 0x4ef8, 0x0053, 0x4ef8, 0x0053 } },
+	{   1, { 0xcccd, 0x0069, 0x1400, 0x00a7 },
+	       { 0x91c3, 0x005a, 0x91c3, 0x005a } },
+	{   2, { 0x8ccd, 0x006a, 0x1400, 0x00a7 },
+	       { 0x61cc, 0x005a, 0x61cc, 0x005a } },
+	{   3, { 0x4ccd, 0x006b, 0x1400, 0x00a7 },
+	       { 0x3208, 0x005a, 0x3208, 0x005a } },
+	{   4, { 0x0ccd, 0x006c, 0x1400, 0x00a7 },
+	       { 0x0276, 0x005a, 0x0276, 0x005a } },
+	{   5, { 0xcccd, 0x006c, 0x1400, 0x00a7 },
+	       { 0xd316, 0x0059, 0xd316, 0x0059 } },
+	{   6, { 0x8ccd, 0x006d, 0x1400, 0x00a7 },
+	       { 0xa3e9, 0x0059, 0xa3e9, 0x0059 } },
+	{   7, { 0x4ccd, 0x006e, 0x1400, 0x00a7 },
+	       { 0x74ec, 0x0059, 0x74ec, 0x0059 } },
+	{   8, { 0x0ccd, 0x006f, 0x1400, 0x00a7 },
+	       { 0x4621, 0x0059, 0x4621, 0x0059 } },
+	{   9, { 0xcccd, 0x006f, 0x1400, 0x00a7 },
+	       { 0x1787, 0x0059, 0x1787, 0x0059 } },
+	{  10, { 0x8ccd, 0x0070, 0x1400, 0x00a7 },
+	       { 0xe91d, 0x0058, 0xe91d, 0x0058 } },
+	{  11, { 0x4ccd, 0x0071, 0x1400, 0x00a7 },
+	       { 0xbae3, 0x0058, 0xbae3, 0x0058 } },
+	{  12, { 0x0ccd, 0x0072, 0x1400, 0x00a7 },
+	       { 0x8cda, 0x0058, 0x8cda, 0x0058 } },
+	{  13, { 0xcccd, 0x0072, 0x1400, 0x00a7 },
+	       { 0x5f00, 0x0058, 0x5f00, 0x0058 } },
+	{  14, { 0x999a, 0x0074, 0x1400, 0x00a7 },
+	       { 0xf1b6, 0x0057, 0xf1b6, 0x0057 } },
+};

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH RFC wireless-next 3/4] wifi: b43: 5 GHz, 80 MHz and VHT for the AC PHY
  2026-11-12 17:56 [PATCH RFC wireless-next 0/4] wifi: b43: AC-PHY support (series 4/4) Andreas Wendleder
  2026-11-12 17:56 ` [PATCH RFC wireless-next 1/4] wifi: b43: radio 2069 and AC-PHY tables Andreas Wendleder
  2026-11-12 17:56 ` [PATCH RFC wireless-next 2/4] wifi: b43: AC-PHY init and 2.4 GHz channel switching Andreas Wendleder
@ 2026-11-12 17:56 ` Andreas Wendleder
  2026-11-12 17:56 ` [PATCH RFC wireless-next 4/4] wifi: b43: enable the AC-PHY support Andreas Wendleder
  3 siblings, 0 replies; 5+ messages in thread
From: Andreas Wendleder @ 2026-11-12 17:56 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, b43-dev, Michael Buesch, Alessio Ferri, kvalo,
	julian.calaby, jpeisach, rosenp, linux-kernel

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.

Co-developed-by: Alessio Ferri <alessio.ferri@mythread.it>
Signed-off-by: Alessio Ferri <alessio.ferri@mythread.it>
Signed-off-by: Andreas Wendleder <gonsolo@gmail.com>
---
 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(-)

diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c
index 7d2f9ea..eeb70bf 100644
--- a/drivers/net/wireless/broadcom/b43/main.c
+++ b/drivers/net/wireless/broadcom/b43/main.c
@@ -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;
diff --git a/drivers/net/wireless/broadcom/b43/phy_ac.c b/drivers/net/wireless/broadcom/b43/phy_ac.c
index 4bcf6f8..7e041b6 100644
--- a/drivers/net/wireless/broadcom/b43/phy_ac.c
+++ b/drivers/net/wireless/broadcom/b43/phy_ac.c
@@ -368,6 +368,18 @@ static void b43_phy_ac_op_prepare_structs(struct b43_wldev *dev)
 	memset(phy_ac, 0, sizeof(*phy_ac));
 }
 
+/*
+ * 80 MHz mode: on 5 GHz the PHY runs on the 80 MHz block that contains the
+ * primary channel, tuned to the centre of the block.
+ */
+static bool b43_phy_ac_is_80mhz(struct b43_wldev *dev, unsigned int channel)
+{
+	return b43_current_band(dev->wl) == NL80211_BAND_5GHZ &&
+	       b43_ac_80mhz_centre(channel);
+}
+
+static void b43_radio_2069_vcocal(struct b43_wldev *dev);
+
 /*
  * 2.4 GHz TX gain table index set on a channel switch (0 is the highest gain).
  * The reset value, 64, is too weak beyond a few metres.
@@ -416,6 +428,126 @@ static void b43_phy_ac_wide_tables_2g(struct b43_wldev *dev)
 		b43_phy_ac_table_write48(dev, 0x11, i, zero);
 }
 
+/*
+ * The second sequencer's command lists (table 7 at 0x30/0x40/0x50, cores 0-2)
+ * on 5 GHz: no leading 0x2a, and 0xb0/0xb1/0xb2 where 2.4 GHz has 0x2b.
+ */
+static const u16 b43_rfseq2_c0_5g[] = { 0x07, 0x0a, 0x00, 0x08,
+					0xb0, 0xb1, 0x1f, 0x1f };
+static const u16 b43_rfseq2_c1_5g[] = { 0x07, 0x08, 0x0c, 0x0e,
+					0xb0, 0xb2, 0x1f, 0x1f };
+static const u16 b43_rfseq2_c2_5g[] = { 0x07, 0x08, 0x0e, 0xb0,
+					0xb1, 0x1f, 0x1f, 0x1f };
+static const struct b43_phy_ac_tbl b43_rfseq2_5g_tbls[] = {
+	{ b43_rfseq2_c0_5g, 8, 7, 0x30, 16 },
+	{ b43_rfseq2_c1_5g, 8, 7, 0x40, 16 },
+	{ b43_rfseq2_c2_5g, 8, 7, 0x50, 16 },
+};
+
+static void b43_phy_ac_write_table(struct b43_wldev *dev,
+				   const struct b43_phy_ac_tbl *t);
+
+static void b43_phy_ac_table_write16(struct b43_wldev *dev, u16 id, u16 offset,
+				     u16 value);
+
+/*
+ * 5 GHz additions to the sequencer and the wide tables:
+ * - table 0x14 entries 0x30-0x33, the RF sequencer extension (48 bits wide,
+ *   written through the third data port 0x011, low word first). Without
+ *   0x30-0x32 the receiver is deaf on 5 GHz; 2.4 GHz does not need them.
+ *   PHY tables survive a driver reload and a PCI bus reset.
+ * - the command lists above and three table 7 cells, see below,
+ * - the 5 GHz TX gain table and the table 0x11 fill.
+ */
+static void b43_phy_ac_rfseq_ext_5g(struct b43_wldev *dev)
+{
+	static const u16 ext[4][3] = {
+		{ 0x0fd2, 0x0096, 0x0000 },
+		{ 0x0fc2, 0x0086, 0x0000 },
+		{ 0x0fd2, 0x0086, 0x0000 },
+		{ 0x0800, 0x0086, 0x0000 },
+	};
+	unsigned int i;
+
+	static const u16 fill11[3] = { 0xbf25, 0x0071, 0x4002 };
+
+	for (i = 0; i < ARRAY_SIZE(ext); i++)
+		b43_phy_ac_table_write48(dev, 0x14, 0x30 + i, ext[i]);
+	for (i = 0; i < ARRAY_SIZE(b43_rfseq2_5g_tbls); i++)
+		b43_phy_ac_write_table(dev, &b43_rfseq2_5g_tbls[i]);
+	/*
+	 * Table 7 cells of the TX chains (core 0 at 973, core 1 at 989) and the
+	 * cell 398 that differ from the 2.4 GHz defaults: without the core 1
+	 * value no two-stream frame is ever acknowledged, and 398 makes
+	 * two-stream MCS 7 usable.
+	 */
+	b43_phy_ac_table_write16(dev, 7, 973, 0x03a2);
+	b43_phy_ac_table_write16(dev, 7, 989, 0x05d0);
+	b43_phy_ac_table_write16(dev, 7, 398, 0x0049);
+	/*
+	 * The 5 GHz TX gain table and the table 0x11 fill (the twelve head
+	 * cells and the zero tail are band independent).
+	 */
+	for (i = 0; i < 128; i++)
+		b43_phy_ac_table_write48(dev, 0x20, i, b43_phy_ac_txgain_5g[i]);
+	for (i = 12; i < 460; i++)
+		b43_phy_ac_table_write48(dev, 0x11, i, fill11);
+}
+
+static void b43_phy_ac_write_table(struct b43_wldev *dev,
+				   const struct b43_phy_ac_tbl *t);
+
+/* 5 GHz AGC tables as written by the vendor driver on this board:
+ * the same four table ids as 2.4 GHz (0x44/0x45 core 0, 0x64/0x65 core 1) but
+ * with the 5 GHz LNA gains. Offset 0: eLNA, 8: LNA1, 16: LNA2, 32: gain limits.
+ */
+static const u8 b43_ac_agc5_elna[] = { 0x0c, 0x0c };
+static const u8 b43_ac_agc5_lna1_gain[] = {
+	0xfe, 0xfe, 0x04, 0x0a, 0x10, 0x17
+};
+
+static const u8 b43_ac_agc5_lna1_code[] = { 1, 1, 2, 3, 4, 5 };
+static const u8 b43_ac_agc5_lna2_gain[] = { 0xf8, 0xf8, 0xfb, 0xfe,
+					    0x02, 0x05, 0x09 };
+static const u8 b43_ac_agc5_lna2_code[] = { 1, 1, 2, 3, 4, 5, 6 };
+static const u8 b43_ac_agc5_lim7[] = { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 };
+static const u8 b43_ac_agc5_lim2[] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 };
+
+static const struct b43_phy_ac_tbl b43_ac_agc_tbls_5g[] = {
+	{ b43_ac_agc5_elna, 2, 0x44, 0x00, 8 },
+	{ b43_ac_agc5_lna1_gain, 6, 0x44, 0x08, 8 },
+	{ b43_ac_agc5_lna2_gain, 7, 0x44, 0x10, 8 },
+	{ b43_ac_agc5_lim7, 10, 0x44, 0x20, 8 },
+	{ b43_ac_agc5_lna1_code, 6, 0x45, 0x08, 8 },
+	{ b43_ac_agc5_lna2_code, 7, 0x45, 0x10, 8 },
+	{ b43_ac_agc5_lim2, 10, 0x45, 0x20, 8 },
+	{ b43_ac_agc5_elna, 2, 0x64, 0x00, 8 },
+	{ b43_ac_agc5_lna1_gain, 6, 0x64, 0x08, 8 },
+	{ b43_ac_agc5_lna2_gain, 7, 0x64, 0x10, 8 },
+	{ b43_ac_agc5_lim7, 10, 0x64, 0x20, 8 },
+	{ b43_ac_agc5_lna1_code, 6, 0x65, 0x08, 8 },
+	{ b43_ac_agc5_lna2_code, 7, 0x65, 0x10, 8 },
+	{ b43_ac_agc5_lim2, 10, 0x65, 0x20, 8 },
+};
+
+/*
+ * 5 GHz setup, run on every 5 GHz channel switch: the sequencer extension,
+ * VCO calibration, RX gain control and the AGC tables.
+ */
+static void b43_phy_ac_setup_5g(struct b43_wldev *dev)
+{
+	unsigned int i;
+
+	b43_phy_ac_rfseq_ext_5g(dev);
+	b43_radio_2069_vcocal(dev);
+	/* RX gain control, all cores: 0x2c on 5 GHz (the 2.4 GHz setup leaves
+	 * 0x18); about 8 dB more RX level.
+	 */
+	b43_phy_write(dev, 0x173b, 0x002c);
+	for (i = 0; i < ARRAY_SIZE(b43_ac_agc_tbls_5g); i++)
+		b43_phy_ac_write_table(dev, &b43_ac_agc_tbls_5g[i]);
+}
+
 /*
  * PHY register init for 2.4 GHz and 20 MHz, in the blocks of the reset-time
  * code of Alessio Ferri's b43-ac-wip (mode_init, set_reg_on_reset,
@@ -715,6 +847,31 @@ static void b43_phy_ac_set_farrow(struct b43_wldev *dev, unsigned int channel)
 	b43_phy_write(dev, 0x1601, b43_phy_read(dev, 0x601));
 }
 
+/*
+ * Farrow resampler for an 80 MHz channel centred on @freq (MHz). The formula is
+ * from Alessio Ferri's tree: ratio = round(f * 2^18 / 45), deltaphase =
+ * round(0xb40000000 / f); for 5530 MHz it gives the vendor driver's values.
+ */
+static void b43_phy_ac_farrow_80(struct b43_wldev *dev, unsigned int freq)
+{
+	u32 ratio = DIV_ROUND_CLOSEST_ULL((u64)freq << 18, 45);
+	u32 dphase = DIV_ROUND_CLOSEST_ULL(0xb40000000ull, freq);
+	u16 mu = 0x0004 | (((ratio >> 24) & 0x3) << 7);
+
+	b43_phy_write(dev, 0x019a, ratio & 0xffff);
+	b43_phy_write(dev, 0x019b, (ratio >> 16) & 0xff);
+	b43_phy_write(dev, 0x019c, 0x0b40);
+	b43_phy_write(dev, 0x0199, mu);
+	b43_phy_write(dev, 0x01a1, ratio & 0xffff);
+	b43_phy_write(dev, 0x01a2, (ratio >> 16) & 0xff);
+	b43_phy_write(dev, 0x01a3, 0x0b40);
+	b43_phy_write(dev, 0x01a0, mu);
+	b43_phy_write(dev, 0x1603, dphase & 0xffff);
+	b43_phy_write(dev, 0x1602, dphase >> 16);
+	b43_phy_write(dev, 0x1607, dphase & 0xffff);
+	b43_phy_write(dev, 0x1606, dphase >> 16);
+}
+
 /* Program the synthesizer and the per-channel radio words of one channel. */
 static void b43_phy_ac_tune(struct b43_wldev *dev,
 			    const struct b43_radio_2069_chan *e,
@@ -733,6 +890,29 @@ static void b43_phy_ac_tune(struct b43_wldev *dev,
 	b43_radio_2069_vcocal(dev);
 }
 
+static void b43_phy_ac_tables_init(struct b43_wldev *dev);
+
+/* Back on 2.4 GHz after 5 GHz in the same boot: the 5 GHz setup overwrote
+ * the AGC, RF sequencer and TX gain tables and left the core in 80 MHz mode
+ * (without this 2.4 GHz associates and receives, but nothing is sent).
+ */
+static void b43_phy_ac_restore_2g(struct b43_wldev *dev)
+{
+	u32 ioctl;
+
+	b43_phy_ac_tables_init(dev);
+	b43_phy_ac_wide_tables_2g(dev);
+	b43_phy_write(dev, 0x173b, 0x0018);
+	b43_phy_write(dev, 0x18b, 0);
+	ioctl = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+	if ((ioctl & B43_BCMA_IOCTL_PHY_BW) == B43_BCMA_IOCTL_PHY_BW_80MHZ) {
+		ioctl = (ioctl & ~B43_BCMA_IOCTL_PHY_BW) |
+			B43_BCMA_IOCTL_PHY_BW_20MHZ;
+		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, ioctl | 0x2);
+		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, ioctl);
+	}
+}
+
 /*
  * Channel switch for radio 2069 rev 4, following the vendor driver's
  * channel-set sequence. Not ported: carrier-search suppression during the
@@ -744,15 +924,14 @@ static int b43_phy_ac_op_switch_channel(struct b43_wldev *dev,
 {
 	struct b43_phy_ac *phy_ac = dev->phy.ac;
 	const struct b43_radio_2069_chan *e;
+	bool is_5ghz = b43_current_band(dev->wl) == NL80211_BAND_5GHZ;
 	u16 save;
 	int i;
 
-	if (b43_current_band(dev->wl) != NL80211_BAND_2GHZ)
-		return -EOPNOTSUPP;
-
 	e = b43_radio_2069_find_chan(dev, new_channel);
 	if (!e) {
-		b43err(dev->wl, "phy_ac: no tuning data for channel %u (radio %04x rev %u)\n",
+		b43err(dev->wl,
+		       "phy_ac: no tuning data for channel %u (radio %04x rev %u)\n",
 		       new_channel, dev->phy.radio_ver, dev->phy.radio_rev);
 		return -ESRCH;
 	}
@@ -762,14 +941,18 @@ static int b43_phy_ac_op_switch_channel(struct b43_wldev *dev,
 	save = b43_phy_read(dev, 0x19e);
 	b43_phy_set(dev, 0x19e, 0x3);
 
-	b43_phy_mask(dev, B43_PHY_AC_BANDCTL, ~0x0100);
+	b43_phy_maskset(dev, B43_PHY_AC_BANDCTL, ~0x0100, is_5ghz ? 0x0100 : 0);
 
-	if (!phy_ac->chan_set) {
+	if (phy_ac->chan_set && phy_ac->last_5ghz && !is_5ghz)
+		b43_phy_ac_restore_2g(dev);
+
+	if (!phy_ac->chan_set || phy_ac->last_5ghz != is_5ghz) {
 		b43_phy_set(dev, 0x728, 0x0100);
 		udelay(1);
 		b43_phy_mask(dev, 0x728, ~0x0100);
-		phy_ac->chan_set = true;
 	}
+	phy_ac->chan_set = true;
+	phy_ac->last_5ghz = is_5ghz;
 
 	b43_phy_ac_tune(dev, e, new_channel);
 	b43_phy_maskset(dev, 0x19e, ~0x3, save & 0x3);
@@ -777,10 +960,76 @@ static int b43_phy_ac_op_switch_channel(struct b43_wldev *dev,
 	for (i = 0; i < 6; i++)
 		b43_phy_write(dev, B43_PHY_AC_BW1A + i, e->bw[i]);
 
-	b43_phy_ac_rfctrl_2g(dev);
-	b43_phy_ac_set_farrow(dev, new_channel);
+	if (b43_phy_ac_is_80mhz(dev, new_channel)) {
+		u32 ioctl;
+
+		/*
+		 * Tune the synthesizer to the centre of the block, put the
+		 * core's PHY in 80 MHz mode and toggle force-gated-clock around
+		 * the change.
+		 */
+		unsigned int ctr = b43_ac_80mhz_centre(new_channel);
+
+		b43_phy_ac_setup_5g(dev);
+		/*
+		 * PHY word 0x18b is 0 after reset; 80 MHz RX and TX need
+		 * 0x016c.
+		 */
+		b43_phy_write(dev, 0x18b, 0x016c);
+		/*
+		 * The synthesizer, the per-channel PHY words and the resampler
+		 * for the block centre. The calibration results and the rpcal
+		 * fill are those of channel 106; they are not recalibrated per
+		 * block.
+		 */
+		{
+			const struct b43_radio_2069_chan *c =
+				b43_radio_2069_find_chan(dev, ctr);
+
+			if (c) {
+				save = b43_phy_read(dev, 0x19e);
+				b43_phy_set(dev, 0x19e, 0x3);
+				b43_phy_ac_tune(dev, c, ctr);
+				b43_phy_maskset(dev, 0x19e, ~0x3, save & 0x3);
+				for (i = 1; i < 6; i++)
+					b43_phy_write(dev, B43_PHY_AC_BW1A + i,
+						      c->bw[i]);
+				b43_phy_ac_farrow_80(dev, 5000 + 5 * ctr);
+			}
+		}
+		ioctl = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, ioctl | 0x2);
+		ioctl = (ioctl & ~B43_BCMA_IOCTL_PHY_BW) |
+			B43_BCMA_IOCTL_PHY_BW_80MHZ;
+		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, ioctl | 0x2);
+		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, ioctl);
+		b43dbg(dev->wl, "phy_ac: 5 GHz 80 MHz mode, ioctrl %08x\n",
+		       bcma_aread32(dev->dev->bdev, BCMA_IOCTL));
+	} else if (is_5ghz) {
+		b43_phy_ac_setup_5g(dev);
+		/* The filter bank for our width. */
+		b43_phy_ac_coeff_bank_init(dev);
+		save = b43_phy_read(dev, 0x19e);
+		b43_phy_set(dev, 0x19e, 0x3);
+		b43_phy_ac_tune(dev, e, new_channel);
+		b43_phy_maskset(dev, 0x19e, ~0x3, save & 0x3);
+		for (i = 0; i < 6; i++)
+			b43_phy_write(dev, B43_PHY_AC_BW1A + i, e->bw[i]);
+	} else {
+		b43_phy_ac_rfctrl_2g(dev);
+	}
+
+	/*
+	 * The per-channel 20 MHz resampler table; in 80 MHz mode the resampler
+	 * was set for the block centre above.
+	 */
+	if (!b43_phy_ac_is_80mhz(dev, new_channel))
+		b43_phy_ac_set_farrow(dev, new_channel);
+
 	b43_phy_ac_resetcca(dev);
-	b43_phy_ac_txpwr_by_index(dev, B43_AC_TXIDX_2G);
+
+	if (!is_5ghz)
+		b43_phy_ac_txpwr_by_index(dev, B43_AC_TXIDX_2G);
 
 	return 0;
 }
diff --git a/drivers/net/wireless/broadcom/b43/phy_ac.h b/drivers/net/wireless/broadcom/b43/phy_ac.h
index 0b6896e..4a6c1e9 100644
--- a/drivers/net/wireless/broadcom/b43/phy_ac.h
+++ b/drivers/net/wireless/broadcom/b43/phy_ac.h
@@ -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;
 };
 
diff --git a/drivers/net/wireless/broadcom/b43/phy_common.c b/drivers/net/wireless/broadcom/b43/phy_common.c
index cfc14c1..40e99b2 100644
--- a/drivers/net/wireless/broadcom/b43/phy_common.c
+++ b/drivers/net/wireless/broadcom/b43/phy_common.c
@@ -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)

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH RFC wireless-next 4/4] wifi: b43: enable the AC-PHY support
  2026-11-12 17:56 [PATCH RFC wireless-next 0/4] wifi: b43: AC-PHY support (series 4/4) Andreas Wendleder
                   ` (2 preceding siblings ...)
  2026-11-12 17:56 ` [PATCH RFC wireless-next 3/4] wifi: b43: 5 GHz, 80 MHz and VHT for the AC PHY Andreas Wendleder
@ 2026-11-12 17:56 ` Andreas Wendleder
  3 siblings, 0 replies; 5+ messages in thread
From: Andreas Wendleder @ 2026-11-12 17:56 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, b43-dev, Michael Buesch, Alessio Ferri, kvalo,
	julian.calaby, jpeisach, rosenp, linux-kernel

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.
Signed-off-by: Andreas Wendleder <gonsolo@gmail.com>
---
 drivers/net/wireless/broadcom/b43/Kconfig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/broadcom/b43/Kconfig b/drivers/net/wireless/broadcom/b43/Kconfig
index 4559549..a8321ca 100644
--- a/drivers/net/wireless/broadcom/b43/Kconfig
+++ b/drivers/net/wireless/broadcom/b43/Kconfig
@@ -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

^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-11-12 17:57 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-12 17:56 [PATCH RFC wireless-next 0/4] wifi: b43: AC-PHY support (series 4/4) Andreas Wendleder
2026-11-12 17:56 ` [PATCH RFC wireless-next 1/4] wifi: b43: radio 2069 and AC-PHY tables Andreas Wendleder
2026-11-12 17:56 ` [PATCH RFC wireless-next 2/4] wifi: b43: AC-PHY init and 2.4 GHz channel switching Andreas Wendleder
2026-11-12 17:56 ` [PATCH RFC wireless-next 3/4] wifi: b43: 5 GHz, 80 MHz and VHT for the AC PHY Andreas Wendleder
2026-11-12 17:56 ` [PATCH RFC wireless-next 4/4] wifi: b43: enable the AC-PHY support Andreas Wendleder

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox