mac80211: realtek: backport support for RTL8812AU/RTL8821AU
authorMarty Jones <mj8263788@gmail.com>
Mon, 25 Nov 2024 17:58:57 +0000 (12:58 -0500)
committerHauke Mehrtens <hauke@hauke-m.de>
Sat, 30 Nov 2024 16:38:19 +0000 (17:38 +0100)
Backport support for RTL8812AU/RTL8821AU USB adapters
Manually backported patch:
045-v6.13-wifi-rtw88-Enable-the-new-RTL8821AU-RTL8812AU-driver
Patches from 046 to 051 are pending.

Signed-off-by: Marty Jones <mj8263788@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/17079
[Move BPAUTO_WANT_DEV_COREDUMP to original patch]
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
43 files changed:
package/kernel/mac80211/patches/rtl/001-v6.12-wifi-rtw88-Set-efuse-ext_lna_5g-fix-typo.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/002-v6.12-wifi-rtw88-usb-Support-USB-3-with-RTL8822CU-RTL8822B.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/004-v6.12-wifi-rtw88-debugfs-support-multiple-adapters-debuggi.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/005-v6.12-wifi-rtw88-select-WANT_DEV_COREDUMP.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/008-v6.12-wifi-rtw88-8822c-Parse-channel-from-IE-to-correct-in.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/010-v6.12-wifi-rtw88-usb-Init-RX-burst-length-according-to-USB.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/011-v6.12-wifi-rtw88-usb-Update-the-RX-stats-after-every-frame.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/012-v6.12-wifi-rtw88-usb-Support-RX-aggregation.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/013-v6.12-wifi-rtw88-Enable-USB-RX-aggregation-for-8822c-8822b.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/016-v6.12-wifi-rtw88-assign-mac_id-for-vif-sta-and-update-to-T.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/017-v6.13-wifi-rtw88-Constify-some-arrays-and-structs.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/019-v6.13-wifi-rtw88-Parse-the-RX-descriptor-with-a-single-fun.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/020-v6.12-wifi-rtw88-Fix-the-RX-aggregation-in-USB-3-mode.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/022-v6.13-wifi-rtw88-Refactor-looping-in-rtw_phy_store_tx_powe.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/023-v6.13-wifi-rtw88-Report-the-signal-strength-only-if-it-s-k.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/024-v6.13-wifi-rtw88-Add-some-definitions-for-RTL8821AU-RTL881.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/025-v6.13-wifi-rtw88-Dump-the-HW-features-only-for-some-chips.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/026-v6.13-wifi-rtw88-Allow-different-C2H-RA-report-sizes.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/027-v6.13-wifi-rtw88-Extend-the-init-table-parsing-for-RTL8812.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/028-v6.13-wifi-rtw88-Allow-rtw_chip_info.ltecoex_addr-to-be-NU.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/029-v6.13-wifi-rtw88-Let-each-driver-control-the-power-on-off-.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/030-v6.13-wifi-rtw88-Enable-data-rate-fallback-for-older-chips.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/031-v6.13-wifi-rtw88-Make-txagc_remnant_ofdm-an-array.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/032-v6.13-wifi-rtw88-Support-TX-page-sizes-bigger-than-128.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/033-v6.13-wifi-rtw88-Move-pwr_track_tbl-to-struct-rtw_rfe_def.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/034-v6.13-wifi-rtw88-usb-Set-pkt_info.ls-for-the-reserved-page.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/035-v6.13-wifi-rtw88-Detect-beacon-loss-with-chips-other-than-.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/036-v6.13-wifi-rtw88-coex-Support-chips-without-a-scoreboard.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/037-v6.13-wifi-rtw88-8821a-Regularly-ask-for-BT-info-updates.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/038-v6.13-wifi-rtw88-8812a-Mitigate-beacon-loss.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/039-v6.13-wifi-rtw88-Add-rtw8812a_table.-c-h.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/040-v6.13-wifi-rtw88-Add-rtw8821a_table.-c-h.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/041-v6.13-wifi-rtw88-Add-rtw88xxa.-c-h.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/042-v6.13-wifi-rtw88-Add-rtw8821a.-c-h.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/043-v6.13-wifi-rtw88-Add-rtw8812a.-c-h.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/044-v6.13-wifi-rtw88-Add-rtw8821au.c-and-rtw8812au.c.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/045-v6.13-wifi-rtw88-Enable-the-new-RTL8821AU-RTL8812AU-driver.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/046-wifi-rtw88-8821au-Add-additional-devices-to-the-USB_.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/047-wifi-rtw88-8812au-Add-more-device-IDs.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/048-wifi-rtw88-usb-Support-USB-3-with-RTL8812AU.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/049-wifi-rtw88-usb-Enable-RX-aggregation-for-8821au-8812.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/050-wifi-rtlwifi-rtl8821ae-phy-restore-removed-code-to-f.patch [new file with mode: 0644]
package/kernel/mac80211/patches/rtl/051-wifi-rtw88-Add-additional-USB-IDs-for-RTL8812BU.patch [new file with mode: 0644]

diff --git a/package/kernel/mac80211/patches/rtl/001-v6.12-wifi-rtw88-Set-efuse-ext_lna_5g-fix-typo.patch b/package/kernel/mac80211/patches/rtl/001-v6.12-wifi-rtw88-Set-efuse-ext_lna_5g-fix-typo.patch
new file mode 100644 (file)
index 0000000..96a6743
--- /dev/null
@@ -0,0 +1,30 @@
+From 8fbcaa308591b91e9037ab6a8d733873b749a70d Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Sat, 6 Jul 2024 01:40:58 +0300
+Subject: [PATCH] wifi: rtw88: Set efuse->ext_lna_5g - fix typo
+
+efuse->ext_lna_2g is set twice and efuse->ext_lna_5g is not set at all.
+Set each one once.
+
+Nothing uses these members right now. They will be used by the RTL8821AU
+and RTL8812AU drivers.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Acked-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/8ccc9e13-0d45-417d-8f88-93a0ad294f77@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/main.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/main.c
++++ b/drivers/net/wireless/realtek/rtw88/main.c
+@@ -2006,7 +2006,7 @@ static int rtw_chip_efuse_info_setup(str
+       efuse->ext_pa_2g = efuse->pa_type_2g & BIT(4) ? 1 : 0;
+       efuse->ext_lna_2g = efuse->lna_type_2g & BIT(3) ? 1 : 0;
+       efuse->ext_pa_5g = efuse->pa_type_5g & BIT(0) ? 1 : 0;
+-      efuse->ext_lna_2g = efuse->lna_type_5g & BIT(3) ? 1 : 0;
++      efuse->ext_lna_5g = efuse->lna_type_5g & BIT(3) ? 1 : 0;
+       if (!is_valid_ether_addr(efuse->addr)) {
+               eth_random_addr(efuse->addr);
diff --git a/package/kernel/mac80211/patches/rtl/002-v6.12-wifi-rtw88-usb-Support-USB-3-with-RTL8822CU-RTL8822B.patch b/package/kernel/mac80211/patches/rtl/002-v6.12-wifi-rtw88-usb-Support-USB-3-with-RTL8822CU-RTL8822B.patch
new file mode 100644 (file)
index 0000000..2faa59d
--- /dev/null
@@ -0,0 +1,284 @@
+From 315c23a64e99552502dd4d18d6ddc073fad9a7c3 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Thu, 11 Jul 2024 01:11:33 +0300
+Subject: [PATCH] wifi: rtw88: usb: Support USB 3 with RTL8822CU/RTL8822BU
+
+The Realtek wifi 5 devices which support USB 3 are weird: when first
+plugged in, they pretend to be USB 2. The driver needs to send some
+commands to the device, which make it disappear and come back as a
+USB 3 device.
+
+Implement the required commands in rtw88.
+
+When a USB 3 device is plugged into a USB 2 port, rtw88 will try to
+switch it to USB 3 mode only once. The device will disappear and come
+back still in USB 2 mode, of course.
+
+Some people experience heavy interference in the 2.4 GHz band in
+USB 3 mode, so add a module parameter switch_usb_mode with the
+default value 1 to let people disable the switching.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Acked-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/77906c62-5674-426f-bde1-1b2a12a0339d@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/debug.h    |  1 +
+ drivers/net/wireless/realtek/rtw88/main.h     |  2 +
+ drivers/net/wireless/realtek/rtw88/reg.h      | 11 +++
+ drivers/net/wireless/realtek/rtw88/rtw8822b.c |  1 +
+ drivers/net/wireless/realtek/rtw88/rtw8822b.h |  4 +-
+ drivers/net/wireless/realtek/rtw88/rtw8822c.c |  1 +
+ drivers/net/wireless/realtek/rtw88/rtw8822c.h | 24 +++---
+ drivers/net/wireless/realtek/rtw88/usb.c      | 84 +++++++++++++++++++
+ 8 files changed, 116 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/debug.h
++++ b/drivers/net/wireless/realtek/rtw88/debug.h
+@@ -25,6 +25,7 @@ enum rtw_debug_mask {
+       RTW_DBG_HW_SCAN         = 0x00010000,
+       RTW_DBG_STATE           = 0x00020000,
+       RTW_DBG_SDIO            = 0x00040000,
++      RTW_DBG_USB             = 0x00080000,
+       RTW_DBG_UNEXP           = 0x80000000,
+       RTW_DBG_ALL             = 0xffffffff
+--- a/drivers/net/wireless/realtek/rtw88/main.h
++++ b/drivers/net/wireless/realtek/rtw88/main.h
+@@ -1785,6 +1785,8 @@ struct rtw_efuse {
+       bool share_ant;
+       u8 bt_setting;
++      u8 usb_mode_switch;
++
+       struct {
+               u8 hci;
+               u8 bw;
+--- a/drivers/net/wireless/realtek/rtw88/reg.h
++++ b/drivers/net/wireless/realtek/rtw88/reg.h
+@@ -15,6 +15,7 @@
+ #define BIT_WLOCK_1C_B6               BIT(5)
+ #define REG_SYS_PW_CTRL               0x0004
+ #define BIT_PFM_WOWL          BIT(3)
++#define BIT_APFM_OFFMAC               BIT(9)
+ #define REG_SYS_CLK_CTRL      0x0008
+ #define BIT_CPU_CLK_EN                BIT(14)
+@@ -133,6 +134,14 @@
+ #define REG_PMC_DBG_CTRL1     0xa8
+ #define BITS_PMC_BT_IQK_STS   GENMASK(22, 21)
++#define REG_PAD_CTRL2         0x00C4
++#define BIT_RSM_EN_V1         BIT(16)
++#define BIT_NO_PDN_CHIPOFF_V1 BIT(17)
++#define BIT_MASK_USB23_SW_MODE_V1     GENMASK(19, 18)
++#define BIT_USB3_USB2_TRANSITION      BIT(20)
++#define BIT_USB_MODE_U2               1
++#define BIT_USB_MODE_U3               2
++
+ #define REG_EFUSE_ACCESS      0x00CF
+ #define EFUSE_ACCESS_ON               0x69
+ #define EFUSE_ACCESS_OFF      0x00
+@@ -568,6 +577,8 @@
+ #define BIT_WL_SECURITY_CLK   BIT(15)
+ #define BIT_DDMA_EN           BIT(8)
++#define REG_SW_MDIO           0x10C0
++
+ #define REG_H2C_PKT_READADDR  0x10D0
+ #define REG_H2C_PKT_WRITEADDR 0x10D4
+ #define REG_FW_DBG6           0x10F8
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+@@ -46,6 +46,7 @@ static int rtw8822b_read_efuse(struct rt
+       map = (struct rtw8822b_efuse *)log_map;
++      efuse->usb_mode_switch = u8_get_bits(map->usb_mode, BIT(7));
+       efuse->rfe_option = map->rfe_option;
+       efuse->rf_board_option = map->rf_board_option;
+       efuse->crystal_cap = map->xtal_k;
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.h
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.h
+@@ -72,7 +72,9 @@ struct rtw8822bs_efuse {
+ struct rtw8822b_efuse {
+       __le16 rtl_id;
+-      u8 res0[0x0e];
++      u8 res0[4];
++      u8 usb_mode;
++      u8 res1[0x09];
+       /* power index for four RF paths */
+       struct rtw_txpwr_idx txpwr_idx_table[4];
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+@@ -49,6 +49,7 @@ static int rtw8822c_read_efuse(struct rt
+       map = (struct rtw8822c_efuse *)log_map;
++      efuse->usb_mode_switch = u8_get_bits(map->usb_mode, BIT(7));
+       efuse->rfe_option = map->rfe_option;
+       efuse->rf_board_option = map->rf_board_option;
+       efuse->crystal_cap = map->xtal_k & XCAP_MASK;
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.h
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.h
+@@ -59,16 +59,18 @@ struct rtw8822ce_efuse {
+ struct rtw8822c_efuse {
+       __le16 rtl_id;
+-      u8 res0[0x0e];
++      u8 res0[4];
++      u8 usb_mode;
++      u8 res1[0x09];
+       /* power index for four RF paths */
+       struct rtw_txpwr_idx txpwr_idx_table[4];
+       u8 channel_plan;                /* 0xb8 */
+       u8 xtal_k;
+-      u8 res1;
++      u8 res2;
+       u8 iqk_lck;
+-      u8 res2[5];                     /* 0xbc */
++      u8 res3[5];                     /* 0xbc */
+       u8 rf_board_option;
+       u8 rf_feature_option;
+       u8 rf_bt_setting;
+@@ -80,21 +82,21 @@ struct rtw8822c_efuse {
+       u8 rf_antenna_option;           /* 0xc9 */
+       u8 rfe_option;
+       u8 country_code[2];
+-      u8 res3[3];
++      u8 res4[3];
+       u8 path_a_thermal;              /* 0xd0 */
+       u8 path_b_thermal;
+-      u8 res4[2];
++      u8 res5[2];
+       u8 rx_gain_gap_2g_ofdm;
+-      u8 res5;
+-      u8 rx_gain_gap_2g_cck;
+       u8 res6;
+-      u8 rx_gain_gap_5gl;
++      u8 rx_gain_gap_2g_cck;
+       u8 res7;
+-      u8 rx_gain_gap_5gm;
++      u8 rx_gain_gap_5gl;
+       u8 res8;
+-      u8 rx_gain_gap_5gh;
++      u8 rx_gain_gap_5gm;
+       u8 res9;
+-      u8 res10[0x42];
++      u8 rx_gain_gap_5gh;
++      u8 res10;
++      u8 res11[0x42];
+       union {
+               struct rtw8822ce_efuse e;
+               struct rtw8822cu_efuse u;
+--- a/drivers/net/wireless/realtek/rtw88/usb.c
++++ b/drivers/net/wireless/realtek/rtw88/usb.c
+@@ -14,6 +14,11 @@
+ #include "ps.h"
+ #include "usb.h"
++static bool rtw_switch_usb_mode = true;
++module_param_named(switch_usb_mode, rtw_switch_usb_mode, bool, 0644);
++MODULE_PARM_DESC(switch_usb_mode,
++               "Set to N to disable switching to USB 3 mode to avoid potential interference in the 2.4 GHz band (default: Y)");
++
+ #define RTW_USB_MAX_RXQ_LEN   512
+ struct rtw_usb_txcb {
+@@ -841,6 +846,77 @@ static void rtw_usb_intf_deinit(struct r
+       usb_set_intfdata(intf, NULL);
+ }
++static int rtw_usb_switch_mode_new(struct rtw_dev *rtwdev)
++{
++      enum usb_device_speed cur_speed;
++      u8 id = rtwdev->chip->id;
++      bool can_switch;
++      u32 pad_ctrl2;
++
++      if (rtw_read8(rtwdev, REG_SYS_CFG2 + 3) == 0x20)
++              cur_speed = USB_SPEED_SUPER;
++      else
++              cur_speed = USB_SPEED_HIGH;
++
++      if (cur_speed == USB_SPEED_SUPER)
++              return 0;
++
++      pad_ctrl2 = rtw_read32(rtwdev, REG_PAD_CTRL2);
++
++      can_switch = !!(pad_ctrl2 & (BIT_MASK_USB23_SW_MODE_V1 |
++                                   BIT_USB3_USB2_TRANSITION));
++
++      if (!can_switch) {
++              rtw_dbg(rtwdev, RTW_DBG_USB,
++                      "Switching to USB 3 mode unsupported by the chip\n");
++              return 0;
++      }
++
++      /* At this point cur_speed is USB_SPEED_HIGH. If we already tried
++       * to switch don't try again - it's a USB 2 port.
++       */
++      if (u32_get_bits(pad_ctrl2, BIT_MASK_USB23_SW_MODE_V1) == BIT_USB_MODE_U3)
++              return 0;
++
++      /* Enable IO wrapper timeout */
++      if (id == RTW_CHIP_TYPE_8822B || id == RTW_CHIP_TYPE_8821C)
++              rtw_write8_clr(rtwdev, REG_SW_MDIO + 3, BIT(0));
++
++      u32p_replace_bits(&pad_ctrl2, BIT_USB_MODE_U3, BIT_MASK_USB23_SW_MODE_V1);
++      pad_ctrl2 |= BIT_RSM_EN_V1;
++
++      rtw_write32(rtwdev, REG_PAD_CTRL2, pad_ctrl2);
++      rtw_write8(rtwdev, REG_PAD_CTRL2 + 1, 4);
++
++      rtw_write16_set(rtwdev, REG_SYS_PW_CTRL, BIT_APFM_OFFMAC);
++      usleep_range(1000, 1001);
++      rtw_write32_set(rtwdev, REG_PAD_CTRL2, BIT_NO_PDN_CHIPOFF_V1);
++
++      return 1;
++}
++
++static int rtw_usb_switch_mode(struct rtw_dev *rtwdev)
++{
++      u8 id = rtwdev->chip->id;
++
++      if (id != RTW_CHIP_TYPE_8822C && id != RTW_CHIP_TYPE_8822B)
++              return 0;
++
++      if (!rtwdev->efuse.usb_mode_switch) {
++              rtw_dbg(rtwdev, RTW_DBG_USB,
++                      "Switching to USB 3 mode disabled by chip's efuse\n");
++              return 0;
++      }
++
++      if (!rtw_switch_usb_mode) {
++              rtw_dbg(rtwdev, RTW_DBG_USB,
++                      "Switching to USB 3 mode disabled by module parameter\n");
++              return 0;
++      }
++
++      return rtw_usb_switch_mode_new(rtwdev);
++}
++
+ int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+ {
+       struct rtw_dev *rtwdev;
+@@ -896,6 +972,14 @@ int rtw_usb_probe(struct usb_interface *
+               goto err_destroy_rxwq;
+       }
++      ret = rtw_usb_switch_mode(rtwdev);
++      if (ret) {
++              /* Not a fail, but we do need to skip rtw_register_hw. */
++              rtw_dbg(rtwdev, RTW_DBG_USB, "switching to USB 3 mode\n");
++              ret = 0;
++              goto err_destroy_rxwq;
++      }
++
+       ret = rtw_register_hw(rtwdev, rtwdev->hw);
+       if (ret) {
+               rtw_err(rtwdev, "failed to register hw\n");
diff --git a/package/kernel/mac80211/patches/rtl/004-v6.12-wifi-rtw88-debugfs-support-multiple-adapters-debuggi.patch b/package/kernel/mac80211/patches/rtl/004-v6.12-wifi-rtw88-debugfs-support-multiple-adapters-debuggi.patch
new file mode 100644 (file)
index 0000000..d965fbc
--- /dev/null
@@ -0,0 +1,454 @@
+From 8db6c1ca64664ef9b071e6eeb646023ac5b240a8 Mon Sep 17 00:00:00 2001
+From: Ping-Ke Shih <pkshih@realtek.com>
+Date: Thu, 18 Jul 2024 14:41:55 +0800
+Subject: [PATCH] wifi: rtw88: debugfs: support multiple adapters debugging
+
+Originally in order to read partial registers from large area, we write
+a range value stored into a static variable and read registers according
+to the static variable.
+
+However, if we install more than one adapters supported by this driver,
+the static variables will be overwritten by latter adapters. To resolve
+the problem, move the static variables to struct rtw_dev for each adapter.
+
+With changes, smatch spends too much time to parse rtw_debugfs_init():
+    debug.c:1289 rtw_debugfs_init() parse error: turning off implications
+    after 60 seconds
+Move stuffs of adding debugfs entries to three rtw_debugfs_add_xxx()
+functions.
+
+Reported-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Closes: https://lore.kernel.org/linux-wireless/cd6a2acf3c2c36d938b40140b52a779516f446a9.camel@realtek.com/T/#m27662022c70d9f893ba96f6c6a8dd8fce2434dfe
+Tested-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20240718064155.38955-1-pkshih@realtek.com
+---
+ drivers/net/wireless/realtek/rtw88/debug.c | 303 ++++++++++++---------
+ drivers/net/wireless/realtek/rtw88/debug.h |   2 +
+ drivers/net/wireless/realtek/rtw88/main.c  |   1 +
+ drivers/net/wireless/realtek/rtw88/main.h  |   3 +-
+ 4 files changed, 180 insertions(+), 129 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/debug.c
++++ b/drivers/net/wireless/realtek/rtw88/debug.c
+@@ -43,6 +43,62 @@ struct rtw_debugfs_priv {
+       };
+ };
++struct rtw_debugfs {
++      struct rtw_debugfs_priv mac_0;
++      struct rtw_debugfs_priv mac_1;
++      struct rtw_debugfs_priv mac_2;
++      struct rtw_debugfs_priv mac_3;
++      struct rtw_debugfs_priv mac_4;
++      struct rtw_debugfs_priv mac_5;
++      struct rtw_debugfs_priv mac_6;
++      struct rtw_debugfs_priv mac_7;
++      struct rtw_debugfs_priv mac_10;
++      struct rtw_debugfs_priv mac_11;
++      struct rtw_debugfs_priv mac_12;
++      struct rtw_debugfs_priv mac_13;
++      struct rtw_debugfs_priv mac_14;
++      struct rtw_debugfs_priv mac_15;
++      struct rtw_debugfs_priv mac_16;
++      struct rtw_debugfs_priv mac_17;
++      struct rtw_debugfs_priv bb_8;
++      struct rtw_debugfs_priv bb_9;
++      struct rtw_debugfs_priv bb_a;
++      struct rtw_debugfs_priv bb_b;
++      struct rtw_debugfs_priv bb_c;
++      struct rtw_debugfs_priv bb_d;
++      struct rtw_debugfs_priv bb_e;
++      struct rtw_debugfs_priv bb_f;
++      struct rtw_debugfs_priv bb_18;
++      struct rtw_debugfs_priv bb_19;
++      struct rtw_debugfs_priv bb_1a;
++      struct rtw_debugfs_priv bb_1b;
++      struct rtw_debugfs_priv bb_1c;
++      struct rtw_debugfs_priv bb_1d;
++      struct rtw_debugfs_priv bb_1e;
++      struct rtw_debugfs_priv bb_1f;
++      struct rtw_debugfs_priv bb_2c;
++      struct rtw_debugfs_priv bb_2d;
++      struct rtw_debugfs_priv bb_40;
++      struct rtw_debugfs_priv bb_41;
++      struct rtw_debugfs_priv rf_dump;
++      struct rtw_debugfs_priv tx_pwr_tbl;
++      struct rtw_debugfs_priv write_reg;
++      struct rtw_debugfs_priv h2c;
++      struct rtw_debugfs_priv rf_write;
++      struct rtw_debugfs_priv rf_read;
++      struct rtw_debugfs_priv read_reg;
++      struct rtw_debugfs_priv fix_rate;
++      struct rtw_debugfs_priv dump_cam;
++      struct rtw_debugfs_priv rsvd_page;
++      struct rtw_debugfs_priv phy_info;
++      struct rtw_debugfs_priv coex_enable;
++      struct rtw_debugfs_priv coex_info;
++      struct rtw_debugfs_priv edcca_enable;
++      struct rtw_debugfs_priv fw_crash;
++      struct rtw_debugfs_priv force_lowest_basic_rate;
++      struct rtw_debugfs_priv dm_cap;
++};
++
+ static const char * const rtw_dm_cap_strs[] = {
+       [RTW_DM_CAP_NA] = "NA",
+       [RTW_DM_CAP_TXGAPK] = "TXGAPK",
+@@ -524,7 +580,7 @@ static int rtw_debug_get_bb_page(struct
+       return 0;
+ }
+-static int rtw_debug_get_rf_dump(struct seq_file *m, void *v)
++static int rtw_debugfs_get_rf_dump(struct seq_file *m, void *v)
+ {
+       struct rtw_debugfs_priv *debugfs_priv = m->private;
+       struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
+@@ -1074,139 +1130,102 @@ static int rtw_debugfs_get_dm_cap(struct
+       return 0;
+ }
+-#define rtw_debug_impl_mac(page, addr)                                \
+-static struct rtw_debugfs_priv rtw_debug_priv_mac_ ##page = { \
++#define rtw_debug_priv_mac(addr)                              \
++{                                                             \
+       .cb_read = rtw_debug_get_mac_page,                      \
+       .cb_data = addr,                                        \
+ }
+-rtw_debug_impl_mac(0, 0x0000);
+-rtw_debug_impl_mac(1, 0x0100);
+-rtw_debug_impl_mac(2, 0x0200);
+-rtw_debug_impl_mac(3, 0x0300);
+-rtw_debug_impl_mac(4, 0x0400);
+-rtw_debug_impl_mac(5, 0x0500);
+-rtw_debug_impl_mac(6, 0x0600);
+-rtw_debug_impl_mac(7, 0x0700);
+-rtw_debug_impl_mac(10, 0x1000);
+-rtw_debug_impl_mac(11, 0x1100);
+-rtw_debug_impl_mac(12, 0x1200);
+-rtw_debug_impl_mac(13, 0x1300);
+-rtw_debug_impl_mac(14, 0x1400);
+-rtw_debug_impl_mac(15, 0x1500);
+-rtw_debug_impl_mac(16, 0x1600);
+-rtw_debug_impl_mac(17, 0x1700);
+-
+-#define rtw_debug_impl_bb(page, addr)                 \
+-static struct rtw_debugfs_priv rtw_debug_priv_bb_ ##page = {  \
++#define rtw_debug_priv_bb(addr)                                       \
++{                                                             \
+       .cb_read = rtw_debug_get_bb_page,                       \
+       .cb_data = addr,                                        \
+ }
+-rtw_debug_impl_bb(8, 0x0800);
+-rtw_debug_impl_bb(9, 0x0900);
+-rtw_debug_impl_bb(a, 0x0a00);
+-rtw_debug_impl_bb(b, 0x0b00);
+-rtw_debug_impl_bb(c, 0x0c00);
+-rtw_debug_impl_bb(d, 0x0d00);
+-rtw_debug_impl_bb(e, 0x0e00);
+-rtw_debug_impl_bb(f, 0x0f00);
+-rtw_debug_impl_bb(18, 0x1800);
+-rtw_debug_impl_bb(19, 0x1900);
+-rtw_debug_impl_bb(1a, 0x1a00);
+-rtw_debug_impl_bb(1b, 0x1b00);
+-rtw_debug_impl_bb(1c, 0x1c00);
+-rtw_debug_impl_bb(1d, 0x1d00);
+-rtw_debug_impl_bb(1e, 0x1e00);
+-rtw_debug_impl_bb(1f, 0x1f00);
+-rtw_debug_impl_bb(2c, 0x2c00);
+-rtw_debug_impl_bb(2d, 0x2d00);
+-rtw_debug_impl_bb(40, 0x4000);
+-rtw_debug_impl_bb(41, 0x4100);
+-
+-static struct rtw_debugfs_priv rtw_debug_priv_rf_dump = {
+-      .cb_read = rtw_debug_get_rf_dump,
+-};
+-
+-static struct rtw_debugfs_priv rtw_debug_priv_tx_pwr_tbl = {
+-      .cb_read = rtw_debugfs_get_tx_pwr_tbl,
+-};
+-
+-static struct rtw_debugfs_priv rtw_debug_priv_write_reg = {
+-      .cb_write = rtw_debugfs_set_write_reg,
+-};
+-
+-static struct rtw_debugfs_priv rtw_debug_priv_h2c = {
+-      .cb_write = rtw_debugfs_set_h2c,
+-};
+-
+-static struct rtw_debugfs_priv rtw_debug_priv_rf_write = {
+-      .cb_write = rtw_debugfs_set_rf_write,
+-};
+-
+-static struct rtw_debugfs_priv rtw_debug_priv_rf_read = {
+-      .cb_write = rtw_debugfs_set_rf_read,
+-      .cb_read = rtw_debugfs_get_rf_read,
+-};
+-
+-static struct rtw_debugfs_priv rtw_debug_priv_read_reg = {
+-      .cb_write = rtw_debugfs_set_read_reg,
+-      .cb_read = rtw_debugfs_get_read_reg,
+-};
+-
+-static struct rtw_debugfs_priv rtw_debug_priv_fix_rate = {
+-      .cb_write = rtw_debugfs_set_fix_rate,
+-      .cb_read = rtw_debugfs_get_fix_rate,
+-};
+-
+-static struct rtw_debugfs_priv rtw_debug_priv_dump_cam = {
+-      .cb_write = rtw_debugfs_set_single_input,
+-      .cb_read = rtw_debugfs_get_dump_cam,
+-};
+-
+-static struct rtw_debugfs_priv rtw_debug_priv_rsvd_page = {
+-      .cb_write = rtw_debugfs_set_rsvd_page,
+-      .cb_read = rtw_debugfs_get_rsvd_page,
+-};
+-
+-static struct rtw_debugfs_priv rtw_debug_priv_phy_info = {
+-      .cb_read = rtw_debugfs_get_phy_info,
+-};
+-
+-static struct rtw_debugfs_priv rtw_debug_priv_coex_enable = {
+-      .cb_write = rtw_debugfs_set_coex_enable,
+-      .cb_read = rtw_debugfs_get_coex_enable,
+-};
+-
+-static struct rtw_debugfs_priv rtw_debug_priv_coex_info = {
+-      .cb_read = rtw_debugfs_get_coex_info,
+-};
+-
+-static struct rtw_debugfs_priv rtw_debug_priv_edcca_enable = {
+-      .cb_write = rtw_debugfs_set_edcca_enable,
+-      .cb_read = rtw_debugfs_get_edcca_enable,
+-};
+-
+-static struct rtw_debugfs_priv rtw_debug_priv_fw_crash = {
+-      .cb_write = rtw_debugfs_set_fw_crash,
+-      .cb_read = rtw_debugfs_get_fw_crash,
+-};
+-
+-static struct rtw_debugfs_priv rtw_debug_priv_force_lowest_basic_rate = {
+-      .cb_write = rtw_debugfs_set_force_lowest_basic_rate,
+-      .cb_read = rtw_debugfs_get_force_lowest_basic_rate,
+-};
+-
+-static struct rtw_debugfs_priv rtw_debug_priv_dm_cap = {
+-      .cb_write = rtw_debugfs_set_dm_cap,
+-      .cb_read = rtw_debugfs_get_dm_cap,
++#define rtw_debug_priv_get(name)                              \
++{                                                             \
++      .cb_read = rtw_debugfs_get_ ##name,                     \
++}
++
++#define rtw_debug_priv_set(name)                              \
++{                                                             \
++      .cb_write = rtw_debugfs_set_ ##name,                    \
++}
++
++#define rtw_debug_priv_set_and_get(name)                      \
++{                                                             \
++      .cb_write = rtw_debugfs_set_ ##name,                    \
++      .cb_read = rtw_debugfs_get_ ##name,                     \
++}
++
++#define rtw_debug_priv_set_single_and_get(name)                       \
++{                                                             \
++      .cb_write = rtw_debugfs_set_single_input,               \
++      .cb_read = rtw_debugfs_get_ ##name,                     \
++}
++
++static const struct rtw_debugfs rtw_debugfs_templ = {
++      .mac_0 = rtw_debug_priv_mac(0x0000),
++      .mac_1 = rtw_debug_priv_mac(0x0100),
++      .mac_2 = rtw_debug_priv_mac(0x0200),
++      .mac_3 = rtw_debug_priv_mac(0x0300),
++      .mac_4 = rtw_debug_priv_mac(0x0400),
++      .mac_5 = rtw_debug_priv_mac(0x0500),
++      .mac_6 = rtw_debug_priv_mac(0x0600),
++      .mac_7 = rtw_debug_priv_mac(0x0700),
++      .mac_10 = rtw_debug_priv_mac(0x1000),
++      .mac_11 = rtw_debug_priv_mac(0x1100),
++      .mac_12 = rtw_debug_priv_mac(0x1200),
++      .mac_13 = rtw_debug_priv_mac(0x1300),
++      .mac_14 = rtw_debug_priv_mac(0x1400),
++      .mac_15 = rtw_debug_priv_mac(0x1500),
++      .mac_16 = rtw_debug_priv_mac(0x1600),
++      .mac_17 = rtw_debug_priv_mac(0x1700),
++      .bb_8 = rtw_debug_priv_bb(0x0800),
++      .bb_9 = rtw_debug_priv_bb(0x0900),
++      .bb_a = rtw_debug_priv_bb(0x0a00),
++      .bb_b = rtw_debug_priv_bb(0x0b00),
++      .bb_c = rtw_debug_priv_bb(0x0c00),
++      .bb_d = rtw_debug_priv_bb(0x0d00),
++      .bb_e = rtw_debug_priv_bb(0x0e00),
++      .bb_f = rtw_debug_priv_bb(0x0f00),
++      .bb_18 = rtw_debug_priv_bb(0x1800),
++      .bb_19 = rtw_debug_priv_bb(0x1900),
++      .bb_1a = rtw_debug_priv_bb(0x1a00),
++      .bb_1b = rtw_debug_priv_bb(0x1b00),
++      .bb_1c = rtw_debug_priv_bb(0x1c00),
++      .bb_1d = rtw_debug_priv_bb(0x1d00),
++      .bb_1e = rtw_debug_priv_bb(0x1e00),
++      .bb_1f = rtw_debug_priv_bb(0x1f00),
++      .bb_2c = rtw_debug_priv_bb(0x2c00),
++      .bb_2d = rtw_debug_priv_bb(0x2d00),
++      .bb_40 = rtw_debug_priv_bb(0x4000),
++      .bb_41 = rtw_debug_priv_bb(0x4100),
++      .rf_dump = rtw_debug_priv_get(rf_dump),
++      .tx_pwr_tbl = rtw_debug_priv_get(tx_pwr_tbl),
++      .write_reg = rtw_debug_priv_set(write_reg),
++      .h2c = rtw_debug_priv_set(h2c),
++      .rf_write = rtw_debug_priv_set(rf_write),
++      .rf_read = rtw_debug_priv_set_and_get(rf_read),
++      .read_reg = rtw_debug_priv_set_and_get(read_reg),
++      .fix_rate = rtw_debug_priv_set_and_get(fix_rate),
++      .dump_cam = rtw_debug_priv_set_single_and_get(dump_cam),
++      .rsvd_page = rtw_debug_priv_set_and_get(rsvd_page),
++      .phy_info = rtw_debug_priv_get(phy_info),
++      .coex_enable = rtw_debug_priv_set_and_get(coex_enable),
++      .coex_info = rtw_debug_priv_get(coex_info),
++      .edcca_enable = rtw_debug_priv_set_and_get(edcca_enable),
++      .fw_crash = rtw_debug_priv_set_and_get(fw_crash),
++      .force_lowest_basic_rate = rtw_debug_priv_set_and_get(force_lowest_basic_rate),
++      .dm_cap = rtw_debug_priv_set_and_get(dm_cap),
+ };
+ #define rtw_debugfs_add_core(name, mode, fopname, parent)             \
+       do {                                                            \
+-              rtw_debug_priv_ ##name.rtwdev = rtwdev;                 \
++              struct rtw_debugfs_priv *priv = &rtwdev->debugfs->name; \
++              priv->rtwdev = rtwdev;                                  \
+               if (IS_ERR(debugfs_create_file(#name, mode,             \
+-                                       parent, &rtw_debug_priv_ ##name,\
++                                       parent, priv,                  \
+                                        &file_ops_ ##fopname)))        \
+                       pr_debug("Unable to initialize debugfs:%s\n",   \
+                              #name);                                  \
+@@ -1219,12 +1238,9 @@ static struct rtw_debugfs_priv rtw_debug
+ #define rtw_debugfs_add_r(name)                                               \
+       rtw_debugfs_add_core(name, S_IFREG | 0444, single_r, debugfs_topdir)
+-void rtw_debugfs_init(struct rtw_dev *rtwdev)
++static
++void rtw_debugfs_add_basic(struct rtw_dev *rtwdev, struct dentry *debugfs_topdir)
+ {
+-      struct dentry *debugfs_topdir;
+-
+-      debugfs_topdir = debugfs_create_dir("rtw88",
+-                                          rtwdev->hw->wiphy->debugfsdir);
+       rtw_debugfs_add_w(write_reg);
+       rtw_debugfs_add_rw(read_reg);
+       rtw_debugfs_add_w(rf_write);
+@@ -1236,6 +1252,17 @@ void rtw_debugfs_init(struct rtw_dev *rt
+       rtw_debugfs_add_r(coex_info);
+       rtw_debugfs_add_rw(coex_enable);
+       rtw_debugfs_add_w(h2c);
++      rtw_debugfs_add_r(rf_dump);
++      rtw_debugfs_add_r(tx_pwr_tbl);
++      rtw_debugfs_add_rw(edcca_enable);
++      rtw_debugfs_add_rw(fw_crash);
++      rtw_debugfs_add_rw(force_lowest_basic_rate);
++      rtw_debugfs_add_rw(dm_cap);
++}
++
++static
++void rtw_debugfs_add_sec0(struct rtw_dev *rtwdev, struct dentry *debugfs_topdir)
++{
+       rtw_debugfs_add_r(mac_0);
+       rtw_debugfs_add_r(mac_1);
+       rtw_debugfs_add_r(mac_2);
+@@ -1252,6 +1279,11 @@ void rtw_debugfs_init(struct rtw_dev *rt
+       rtw_debugfs_add_r(bb_d);
+       rtw_debugfs_add_r(bb_e);
+       rtw_debugfs_add_r(bb_f);
++}
++
++static
++void rtw_debugfs_add_sec1(struct rtw_dev *rtwdev, struct dentry *debugfs_topdir)
++{
+       rtw_debugfs_add_r(mac_10);
+       rtw_debugfs_add_r(mac_11);
+       rtw_debugfs_add_r(mac_12);
+@@ -1274,14 +1306,29 @@ void rtw_debugfs_init(struct rtw_dev *rt
+               rtw_debugfs_add_r(bb_40);
+               rtw_debugfs_add_r(bb_41);
+       }
+-      rtw_debugfs_add_r(rf_dump);
+-      rtw_debugfs_add_r(tx_pwr_tbl);
+-      rtw_debugfs_add_rw(edcca_enable);
+-      rtw_debugfs_add_rw(fw_crash);
+-      rtw_debugfs_add_rw(force_lowest_basic_rate);
+-      rtw_debugfs_add_rw(dm_cap);
+ }
++void rtw_debugfs_init(struct rtw_dev *rtwdev)
++{
++      struct dentry *debugfs_topdir;
++
++      rtwdev->debugfs = kmemdup(&rtw_debugfs_templ, sizeof(rtw_debugfs_templ),
++                                GFP_KERNEL);
++      if (!rtwdev->debugfs)
++              return;
++
++      debugfs_topdir = debugfs_create_dir("rtw88",
++                                          rtwdev->hw->wiphy->debugfsdir);
++
++      rtw_debugfs_add_basic(rtwdev, debugfs_topdir);
++      rtw_debugfs_add_sec0(rtwdev, debugfs_topdir);
++      rtw_debugfs_add_sec1(rtwdev, debugfs_topdir);
++}
++
++void rtw_debugfs_deinit(struct rtw_dev *rtwdev)
++{
++      kfree(rtwdev->debugfs);
++}
+ #endif /* CPTCFG_RTW88_DEBUGFS */
+ #ifdef CPTCFG_RTW88_DEBUG
+--- a/drivers/net/wireless/realtek/rtw88/debug.h
++++ b/drivers/net/wireless/realtek/rtw88/debug.h
+@@ -34,11 +34,13 @@ enum rtw_debug_mask {
+ #ifdef CPTCFG_RTW88_DEBUGFS
+ void rtw_debugfs_init(struct rtw_dev *rtwdev);
++void rtw_debugfs_deinit(struct rtw_dev *rtwdev);
+ void rtw_debugfs_get_simple_phy_info(struct seq_file *m);
+ #else
+ static inline void rtw_debugfs_init(struct rtw_dev *rtwdev) {}
++static inline void rtw_debugfs_deinit(struct rtw_dev *rtwdev) {}
+ #endif /* CPTCFG_RTW88_DEBUGFS */
+--- a/drivers/net/wireless/realtek/rtw88/main.c
++++ b/drivers/net/wireless/realtek/rtw88/main.c
+@@ -2300,6 +2300,7 @@ void rtw_unregister_hw(struct rtw_dev *r
+       ieee80211_unregister_hw(hw);
+       rtw_unset_supported_band(hw, chip);
++      rtw_debugfs_deinit(rtwdev);
+ }
+ EXPORT_SYMBOL(rtw_unregister_hw);
+--- a/drivers/net/wireless/realtek/rtw88/main.h
++++ b/drivers/net/wireless/realtek/rtw88/main.h
+@@ -50,6 +50,7 @@ extern const struct ieee80211_ops rtw_op
+ #define RTW_MAX_CHANNEL_NUM_5G 49
+ struct rtw_dev;
++struct rtw_debugfs;
+ enum rtw_hci_type {
+       RTW_HCI_TYPE_PCIE,
+@@ -2053,7 +2054,7 @@ struct rtw_dev {
+       bool beacon_loss;
+       struct completion lps_leave_check;
+-      struct dentry *debugfs;
++      struct rtw_debugfs *debugfs;
+       u8 sta_cnt;
+       u32 rts_threshold;
diff --git a/package/kernel/mac80211/patches/rtl/005-v6.12-wifi-rtw88-select-WANT_DEV_COREDUMP.patch b/package/kernel/mac80211/patches/rtl/005-v6.12-wifi-rtw88-select-WANT_DEV_COREDUMP.patch
new file mode 100644 (file)
index 0000000..6c31b5e
--- /dev/null
@@ -0,0 +1,25 @@
+From 7e989b0c1e33210c07340bf5228aa83ea52515b5 Mon Sep 17 00:00:00 2001
+From: Zong-Zhe Yang <kevin_yang@realtek.com>
+Date: Thu, 18 Jul 2024 15:06:15 +0800
+Subject: [PATCH] wifi: rtw88: select WANT_DEV_COREDUMP
+
+We have invoked device coredump when fw crash.
+Should select WANT_DEV_COREDUMP by ourselves.
+
+Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20240718070616.42217-1-pkshih@realtek.com
+---
+ drivers/net/wireless/realtek/rtw88/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/realtek/rtw88/Kconfig
++++ b/drivers/net/wireless/realtek/rtw88/Kconfig
+@@ -14,6 +14,7 @@ if RTW88
+ config RTW88_CORE
+       tristate
+       depends on m
++      select BPAUTO_WANT_DEV_COREDUMP
+ config RTW88_PCI
+       tristate
diff --git a/package/kernel/mac80211/patches/rtl/008-v6.12-wifi-rtw88-8822c-Parse-channel-from-IE-to-correct-in.patch b/package/kernel/mac80211/patches/rtl/008-v6.12-wifi-rtw88-8822c-Parse-channel-from-IE-to-correct-in.patch
new file mode 100644 (file)
index 0000000..a304cd7
--- /dev/null
@@ -0,0 +1,151 @@
+From 53ed4b25a79aeec5991c2dc579e635b136ef7676 Mon Sep 17 00:00:00 2001
+From: Po-Hao Huang <phhuang@realtek.com>
+Date: Wed, 24 Jul 2024 13:05:01 +0800
+Subject: [PATCH] wifi: rtw88: 8822c: Parse channel from IE to correct invalid
+ hardware reports
+
+For CCK packets we could get incorrect reports from hardware.
+And this causes wrong frequencies being reported. Parse the channel
+information from IE if provided by AP to fix this.
+
+Signed-off-by: Po-Hao Huang <phhuang@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20240724050501.7550-1-pkshih@realtek.com
+---
+ drivers/net/wireless/realtek/rtw88/main.h     |  1 +
+ drivers/net/wireless/realtek/rtw88/pci.c      |  1 +
+ drivers/net/wireless/realtek/rtw88/rtw8822c.c |  7 ++--
+ drivers/net/wireless/realtek/rtw88/rx.c       | 41 +++++++++++++++++++
+ drivers/net/wireless/realtek/rtw88/rx.h       | 13 ++++++
+ drivers/net/wireless/realtek/rtw88/sdio.c     |  1 +
+ drivers/net/wireless/realtek/rtw88/usb.c      |  2 +
+ 7 files changed, 63 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/main.h
++++ b/drivers/net/wireless/realtek/rtw88/main.h
+@@ -623,6 +623,7 @@ struct rtw_rx_pkt_stat {
+       bool crc_err;
+       bool decrypted;
+       bool is_c2h;
++      bool channel_invalid;
+       s32 signal_power;
+       u16 pkt_len;
+--- a/drivers/net/wireless/realtek/rtw88/pci.c
++++ b/drivers/net/wireless/realtek/rtw88/pci.c
+@@ -1088,6 +1088,7 @@ static u32 rtw_pci_rx_napi(struct rtw_de
+                       /* remove rx_desc */
+                       skb_pull(new, pkt_offset);
++                      rtw_update_rx_freq_for_invalid(rtwdev, new, &rx_status, &pkt_stat);
+                       rtw_rx_stats(rtwdev, pkt_stat.vif, new);
+                       memcpy(new->cb, &rx_status, sizeof(rx_status));
+                       ieee80211_rx_napi(rtwdev->hw, NULL, new, napi);
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+@@ -2576,9 +2576,10 @@ static void query_phy_status_page0(struc
+       rx_power[RF_PATH_B] -= 110;
+       channel = GET_PHY_STAT_P0_CHANNEL(phy_status);
+-      if (channel == 0)
+-              channel = rtwdev->hal.current_channel;
+-      rtw_set_rx_freq_band(pkt_stat, channel);
++      if (channel != 0)
++              rtw_set_rx_freq_band(pkt_stat, channel);
++      else
++              pkt_stat->channel_invalid = true;
+       pkt_stat->rx_power[RF_PATH_A] = rx_power[RF_PATH_A];
+       pkt_stat->rx_power[RF_PATH_B] = rx_power[RF_PATH_B];
+--- a/drivers/net/wireless/realtek/rtw88/rx.c
++++ b/drivers/net/wireless/realtek/rtw88/rx.c
+@@ -146,6 +146,47 @@ static void rtw_set_rx_freq_by_pktstat(s
+       rx_status->band = pkt_stat->band;
+ }
++void rtw_update_rx_freq_from_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
++                              struct ieee80211_rx_status *rx_status,
++                              struct rtw_rx_pkt_stat *pkt_stat)
++{
++      struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
++      int channel = rtwdev->hal.current_channel;
++      size_t hdr_len, ielen;
++      int channel_number;
++      u8 *variable;
++
++      if (!test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
++              goto fill_rx_status;
++
++      if (ieee80211_is_beacon(mgmt->frame_control)) {
++              variable = mgmt->u.beacon.variable;
++              hdr_len = offsetof(struct ieee80211_mgmt,
++                                 u.beacon.variable);
++      } else if (ieee80211_is_probe_resp(mgmt->frame_control)) {
++              variable = mgmt->u.probe_resp.variable;
++              hdr_len = offsetof(struct ieee80211_mgmt,
++                                 u.probe_resp.variable);
++      } else {
++              goto fill_rx_status;
++      }
++
++      if (skb->len > hdr_len)
++              ielen = skb->len - hdr_len;
++      else
++              goto fill_rx_status;
++
++      channel_number = cfg80211_get_ies_channel_number(variable, ielen,
++                                                       NL80211_BAND_2GHZ);
++      if (channel_number != -1)
++              channel = channel_number;
++
++fill_rx_status:
++      rtw_set_rx_freq_band(pkt_stat, channel);
++      rtw_set_rx_freq_by_pktstat(pkt_stat, rx_status);
++}
++EXPORT_SYMBOL(rtw_update_rx_freq_from_ie);
++
+ void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
+                          struct rtw_rx_pkt_stat *pkt_stat,
+                          struct ieee80211_hdr *hdr,
+--- a/drivers/net/wireless/realtek/rtw88/rx.h
++++ b/drivers/net/wireless/realtek/rtw88/rx.h
+@@ -50,5 +50,18 @@ void rtw_rx_fill_rx_status(struct rtw_de
+                          struct ieee80211_hdr *hdr,
+                          struct ieee80211_rx_status *rx_status,
+                          u8 *phy_status);
++void rtw_update_rx_freq_from_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
++                              struct ieee80211_rx_status *rx_status,
++                              struct rtw_rx_pkt_stat *pkt_stat);
++
++static inline
++void rtw_update_rx_freq_for_invalid(struct rtw_dev *rtwdev, struct sk_buff *skb,
++                                  struct ieee80211_rx_status *rx_status,
++                                  struct rtw_rx_pkt_stat *pkt_stat)
++{
++      if (pkt_stat->channel_invalid)
++              rtw_update_rx_freq_from_ie(rtwdev, skb, rx_status, pkt_stat);
++}
++
+ #endif
+--- a/drivers/net/wireless/realtek/rtw88/sdio.c
++++ b/drivers/net/wireless/realtek/rtw88/sdio.c
+@@ -948,6 +948,7 @@ static void rtw_sdio_rx_skb(struct rtw_d
+       skb_put(skb, pkt_stat->pkt_len);
+       skb_reserve(skb, pkt_offset);
++      rtw_update_rx_freq_for_invalid(rtwdev, skb, rx_status, pkt_stat);
+       rtw_rx_stats(rtwdev, pkt_stat->vif, skb);
+       ieee80211_rx_irqsafe(rtwdev->hw, skb);
+--- a/drivers/net/wireless/realtek/rtw88/usb.c
++++ b/drivers/net/wireless/realtek/rtw88/usb.c
+@@ -579,6 +579,8 @@ static void rtw_usb_rx_handler(struct wo
+               skb_put(skb, pkt_stat.pkt_len);
+               skb_reserve(skb, pkt_offset);
++
++              rtw_update_rx_freq_for_invalid(rtwdev, skb, &rx_status, &pkt_stat);
+               memcpy(skb->cb, &rx_status, sizeof(rx_status));
+               ieee80211_rx_irqsafe(rtwdev->hw, skb);
+       }
diff --git a/package/kernel/mac80211/patches/rtl/010-v6.12-wifi-rtw88-usb-Init-RX-burst-length-according-to-USB.patch b/package/kernel/mac80211/patches/rtl/010-v6.12-wifi-rtw88-usb-Init-RX-burst-length-according-to-USB.patch
new file mode 100644 (file)
index 0000000..191c87f
--- /dev/null
@@ -0,0 +1,73 @@
+From fbbd8cb347e25b68d25c4f3871821afc495ee7a9 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Thu, 8 Aug 2024 01:19:36 +0300
+Subject: [PATCH] wifi: rtw88: usb: Init RX burst length according to USB speed
+
+This is needed in order to make USB RX aggregation work with RTL8811CU
+(and presumably RTL8822BU and RTL8822CU also).
+
+I don't know what BIT_DMA_BURST_CNT, BIT_DMA_MODE, and BIT_DROP_DATA_EN
+are doing.
+
+Tested with RTL8822CU, RTL8811CU, and RTL8723DU.
+
+The RX speed is unchanged in my tests.
+
+Tested-by: Sascha Hauer <s.hauer@pengutronix.de>
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/ac569c6f-7129-4341-b523-901fe10cabff@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/reg.h |  6 ++++++
+ drivers/net/wireless/realtek/rtw88/usb.c | 23 ++++++++++++++++++++++-
+ 2 files changed, 28 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/reg.h
++++ b/drivers/net/wireless/realtek/rtw88/reg.h
+@@ -322,6 +322,12 @@
+ #define REG_RXDMA_DPR         0x028C
+ #define REG_RXDMA_MODE                0x0290
+ #define BIT_DMA_MODE          BIT(1)
++#define BIT_DMA_BURST_CNT     GENMASK(3, 2)
++#define BIT_DMA_BURST_SIZE    GENMASK(5, 4)
++#define BIT_DMA_BURST_SIZE_64 2
++#define BIT_DMA_BURST_SIZE_512        1
++#define BIT_DMA_BURST_SIZE_1024       0
++
+ #define REG_RXPKTNUM          0x02B0
+ #define REG_INT_MIG           0x0304
+--- a/drivers/net/wireless/realtek/rtw88/usb.c
++++ b/drivers/net/wireless/realtek/rtw88/usb.c
+@@ -720,9 +720,30 @@ static void rtw_usb_link_ps(struct rtw_d
+       /* empty function for rtw_hci_ops */
+ }
++static void rtw_usb_init_burst_pkt_len(struct rtw_dev *rtwdev)
++{
++      struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
++      enum usb_device_speed speed = rtwusb->udev->speed;
++      u8 rxdma, burst_size;
++
++      rxdma = BIT_DMA_BURST_CNT | BIT_DMA_MODE;
++
++      if (speed == USB_SPEED_SUPER)
++              burst_size = BIT_DMA_BURST_SIZE_1024;
++      else if (speed == USB_SPEED_HIGH)
++              burst_size = BIT_DMA_BURST_SIZE_512;
++      else
++              burst_size = BIT_DMA_BURST_SIZE_64;
++
++      u8p_replace_bits(&rxdma, burst_size, BIT_DMA_BURST_SIZE);
++
++      rtw_write8(rtwdev, REG_RXDMA_MODE, rxdma);
++      rtw_write16_set(rtwdev, REG_TXDMA_OFFSET_CHK, BIT_DROP_DATA_EN);
++}
++
+ static void rtw_usb_interface_cfg(struct rtw_dev *rtwdev)
+ {
+-      /* empty function for rtw_hci_ops */
++      rtw_usb_init_burst_pkt_len(rtwdev);
+ }
+ static struct rtw_hci_ops rtw_usb_ops = {
diff --git a/package/kernel/mac80211/patches/rtl/011-v6.12-wifi-rtw88-usb-Update-the-RX-stats-after-every-frame.patch b/package/kernel/mac80211/patches/rtl/011-v6.12-wifi-rtw88-usb-Update-the-RX-stats-after-every-frame.patch
new file mode 100644 (file)
index 0000000..f78f43b
--- /dev/null
@@ -0,0 +1,31 @@
+From 38ea04a79ad0f8cc30bb5e9ad98d665e4ae5060c Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Thu, 8 Aug 2024 01:20:36 +0300
+Subject: [PATCH] wifi: rtw88: usb: Update the RX stats after every frame
+
+Update the number of received unicast data frames and bytes every time
+a frame is received. This is what the PCI and SDIO drivers do.
+
+This has an influence on the power saving, bluetooth coexistence, and
+(in a future patch) the use of RX aggregation.
+
+Tested with RTL8822CU, RTL8811CU, and RTL8723DU.
+
+Tested-by: Sascha Hauer <s.hauer@pengutronix.de>
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/75a2ca52-8f01-45c5-926f-d3a68ae3b284@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/usb.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/realtek/rtw88/usb.c
++++ b/drivers/net/wireless/realtek/rtw88/usb.c
+@@ -581,6 +581,7 @@ static void rtw_usb_rx_handler(struct wo
+               skb_reserve(skb, pkt_offset);
+               rtw_update_rx_freq_for_invalid(rtwdev, skb, &rx_status, &pkt_stat);
++              rtw_rx_stats(rtwdev, pkt_stat.vif, skb);
+               memcpy(skb->cb, &rx_status, sizeof(rx_status));
+               ieee80211_rx_irqsafe(rtwdev->hw, skb);
+       }
diff --git a/package/kernel/mac80211/patches/rtl/012-v6.12-wifi-rtw88-usb-Support-RX-aggregation.patch b/package/kernel/mac80211/patches/rtl/012-v6.12-wifi-rtw88-usb-Support-RX-aggregation.patch
new file mode 100644 (file)
index 0000000..bc8eac8
--- /dev/null
@@ -0,0 +1,118 @@
+From df3d8f463b1dfc7cb8f4fb52b1b81d290b850d03 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Thu, 8 Aug 2024 01:21:36 +0300
+Subject: [PATCH] wifi: rtw88: usb: Support RX aggregation
+
+The chips can be configured to aggregate several frames into a single
+USB transfer. Modify rtw_usb_rx_handler() to support this case.
+
+RX aggregation improves the RX speed of RTL8811CU on certain ARM
+systems, like the NanoPi NEO Core2. It also improves the RX speed of
+RTL8822CU on some x86_64 systems.
+
+Currently none of the chips are configured to aggregate frames.
+
+Tested with RTL8822CU, RTL8811CU, and RTL8723DU.
+
+Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
+Tested-by: Sascha Hauer <s.hauer@pengutronix.de>
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/f845826d-de71-492d-9a22-e48c07989a1f@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/usb.c | 61 ++++++++++++++++--------
+ 1 file changed, 40 insertions(+), 21 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/usb.c
++++ b/drivers/net/wireless/realtek/rtw88/usb.c
+@@ -546,11 +546,12 @@ static void rtw_usb_rx_handler(struct wo
+       struct rtw_usb *rtwusb = container_of(work, struct rtw_usb, rx_work);
+       struct rtw_dev *rtwdev = rtwusb->rtwdev;
+       const struct rtw_chip_info *chip = rtwdev->chip;
+-      struct rtw_rx_pkt_stat pkt_stat;
++      u32 pkt_desc_sz = chip->rx_pkt_desc_sz;
+       struct ieee80211_rx_status rx_status;
++      u32 pkt_offset, next_pkt, urb_len;
++      struct rtw_rx_pkt_stat pkt_stat;
++      struct sk_buff *next_skb;
+       struct sk_buff *skb;
+-      u32 pkt_desc_sz = chip->rx_pkt_desc_sz;
+-      u32 pkt_offset;
+       u8 *rx_desc;
+       int limit;
+@@ -559,31 +560,48 @@ static void rtw_usb_rx_handler(struct wo
+               if (!skb)
+                       break;
+-              rx_desc = skb->data;
+-              chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat,
+-                                       &rx_status);
+-              pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
+-                           pkt_stat.shift;
+-
+-              if (pkt_stat.is_c2h) {
+-                      skb_put(skb, pkt_stat.pkt_len + pkt_offset);
+-                      rtw_fw_c2h_cmd_rx_irqsafe(rtwdev, pkt_offset, skb);
+-                      continue;
+-              }
+-
+               if (skb_queue_len(&rtwusb->rx_queue) >= RTW_USB_MAX_RXQ_LEN) {
+                       dev_dbg_ratelimited(rtwdev->dev, "failed to get rx_queue, overflow\n");
+                       dev_kfree_skb_any(skb);
+                       continue;
+               }
+-              skb_put(skb, pkt_stat.pkt_len);
+-              skb_reserve(skb, pkt_offset);
++              urb_len = skb->len;
++
++              do {
++                      rx_desc = skb->data;
++                      chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat,
++                                               &rx_status);
++                      pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
++                                   pkt_stat.shift;
++
++                      next_pkt = round_up(pkt_stat.pkt_len + pkt_offset, 8);
++
++                      if (urb_len >= next_pkt + pkt_desc_sz)
++                              next_skb = skb_clone(skb, GFP_KERNEL);
++                      else
++                              next_skb = NULL;
++
++                      if (pkt_stat.is_c2h) {
++                              skb_trim(skb, pkt_stat.pkt_len + pkt_offset);
++                              rtw_fw_c2h_cmd_rx_irqsafe(rtwdev, pkt_offset, skb);
++                      } else {
++                              skb_pull(skb, pkt_offset);
++                              skb_trim(skb, pkt_stat.pkt_len);
++                              rtw_update_rx_freq_for_invalid(rtwdev, skb,
++                                                             &rx_status,
++                                                             &pkt_stat);
++                              rtw_rx_stats(rtwdev, pkt_stat.vif, skb);
++                              memcpy(skb->cb, &rx_status, sizeof(rx_status));
++                              ieee80211_rx_irqsafe(rtwdev->hw, skb);
++                      }
++
++                      skb = next_skb;
++                      if (skb)
++                              skb_pull(skb, next_pkt);
+-              rtw_update_rx_freq_for_invalid(rtwdev, skb, &rx_status, &pkt_stat);
+-              rtw_rx_stats(rtwdev, pkt_stat.vif, skb);
+-              memcpy(skb->cb, &rx_status, sizeof(rx_status));
+-              ieee80211_rx_irqsafe(rtwdev->hw, skb);
++                      urb_len -= next_pkt;
++              } while (skb);
+       }
+ }
+@@ -627,6 +645,7 @@ static void rtw_usb_read_port_complete(s
+                       if (skb)
+                               dev_kfree_skb_any(skb);
+               } else {
++                      skb_put(skb, urb->actual_length);
+                       skb_queue_tail(&rtwusb->rx_queue, skb);
+                       queue_work(rtwusb->rxwq, &rtwusb->rx_work);
+               }
diff --git a/package/kernel/mac80211/patches/rtl/013-v6.12-wifi-rtw88-Enable-USB-RX-aggregation-for-8822c-8822b.patch b/package/kernel/mac80211/patches/rtl/013-v6.12-wifi-rtw88-Enable-USB-RX-aggregation-for-8822c-8822b.patch
new file mode 100644 (file)
index 0000000..7117532
--- /dev/null
@@ -0,0 +1,168 @@
+From 002a5db9a52a0e7af0fa9a450d31049748435748 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Thu, 8 Aug 2024 01:23:06 +0300
+Subject: [PATCH] wifi: rtw88: Enable USB RX aggregation for 8822c/8822b/8821c
+
+Enable USB RX aggregation when there is at least 1 Mbps RX or TX
+traffic, otherwise disable it.
+
+USB RX aggregation improves the RX speed of RTL8811CU on certain ARM
+systems, like the NanoPi NEO Core2. Before: 28 Mbps, after: 231 Mbps.
+
+It also improves the RX speed of RTL8822CU on some x86_64 systems.
+Before: ~200 Mbps, after: ~300 Mbps.
+
+The official drivers for these chips use the same logic for SDIO, but
+for some reason the SDIO driver in rtw88 always enables RX aggregation,
+so this patch only toggles aggregation for USB devices.
+
+RTL8703B is likely not found in USB devices, and RTL8723DU doesn't like
+aggregation.
+
+Tested-by: Sascha Hauer <s.hauer@pengutronix.de>
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/b4c0d54c-6755-4b0f-9dd7-f9196fd74b68@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/hci.h  |  7 ++++
+ drivers/net/wireless/realtek/rtw88/main.c | 13 +++++---
+ drivers/net/wireless/realtek/rtw88/pci.c  |  1 +
+ drivers/net/wireless/realtek/rtw88/sdio.c |  1 +
+ drivers/net/wireless/realtek/rtw88/usb.c  | 40 +++++++++++++++++++++++
+ 5 files changed, 58 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/hci.h
++++ b/drivers/net/wireless/realtek/rtw88/hci.h
+@@ -18,6 +18,7 @@ struct rtw_hci_ops {
+       void (*deep_ps)(struct rtw_dev *rtwdev, bool enter);
+       void (*link_ps)(struct rtw_dev *rtwdev, bool enter);
+       void (*interface_cfg)(struct rtw_dev *rtwdev);
++      void (*dynamic_rx_agg)(struct rtw_dev *rtwdev, bool enable);
+       int (*write_data_rsvd_page)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
+       int (*write_data_h2c)(struct rtw_dev *rtwdev, u8 *buf, u32 size);
+@@ -72,6 +73,12 @@ static inline void rtw_hci_interface_cfg
+       rtwdev->hci.ops->interface_cfg(rtwdev);
+ }
++static inline void rtw_hci_dynamic_rx_agg(struct rtw_dev *rtwdev, bool enable)
++{
++      if (rtwdev->hci.ops->dynamic_rx_agg)
++              rtwdev->hci.ops->dynamic_rx_agg(rtwdev, enable);
++}
++
+ static inline int
+ rtw_hci_write_data_rsvd_page(struct rtw_dev *rtwdev, u8 *buf, u32 size)
+ {
+--- a/drivers/net/wireless/realtek/rtw88/main.c
++++ b/drivers/net/wireless/realtek/rtw88/main.c
+@@ -212,6 +212,7 @@ static void rtw_watch_dog_work(struct wo
+       struct rtw_traffic_stats *stats = &rtwdev->stats;
+       struct rtw_watch_dog_iter_data data = {};
+       bool busy_traffic = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
++      u32 tx_unicast_mbps, rx_unicast_mbps;
+       bool ps_active;
+       mutex_lock(&rtwdev->mutex);
+@@ -236,10 +237,11 @@ static void rtw_watch_dog_work(struct wo
+       else
+               ps_active = false;
+-      ewma_tp_add(&stats->tx_ewma_tp,
+-                  (u32)(stats->tx_unicast >> RTW_TP_SHIFT));
+-      ewma_tp_add(&stats->rx_ewma_tp,
+-                  (u32)(stats->rx_unicast >> RTW_TP_SHIFT));
++      tx_unicast_mbps = stats->tx_unicast >> RTW_TP_SHIFT;
++      rx_unicast_mbps = stats->rx_unicast >> RTW_TP_SHIFT;
++
++      ewma_tp_add(&stats->tx_ewma_tp, tx_unicast_mbps);
++      ewma_tp_add(&stats->rx_ewma_tp, rx_unicast_mbps);
+       stats->tx_throughput = ewma_tp_read(&stats->tx_ewma_tp);
+       stats->rx_throughput = ewma_tp_read(&stats->rx_ewma_tp);
+@@ -259,6 +261,9 @@ static void rtw_watch_dog_work(struct wo
+       rtw_phy_dynamic_mechanism(rtwdev);
++      rtw_hci_dynamic_rx_agg(rtwdev,
++                             tx_unicast_mbps >= 1 || rx_unicast_mbps >= 1);
++
+       data.rtwdev = rtwdev;
+       /* rtw_iterate_vifs internally uses an atomic iterator which is needed
+        * to avoid taking local->iflist_mtx mutex
+--- a/drivers/net/wireless/realtek/rtw88/pci.c
++++ b/drivers/net/wireless/realtek/rtw88/pci.c
+@@ -1601,6 +1601,7 @@ static struct rtw_hci_ops rtw_pci_ops =
+       .deep_ps = rtw_pci_deep_ps,
+       .link_ps = rtw_pci_link_ps,
+       .interface_cfg = rtw_pci_interface_cfg,
++      .dynamic_rx_agg = NULL,
+       .read8 = rtw_pci_read8,
+       .read16 = rtw_pci_read16,
+--- a/drivers/net/wireless/realtek/rtw88/sdio.c
++++ b/drivers/net/wireless/realtek/rtw88/sdio.c
+@@ -1157,6 +1157,7 @@ static struct rtw_hci_ops rtw_sdio_ops =
+       .deep_ps = rtw_sdio_deep_ps,
+       .link_ps = rtw_sdio_link_ps,
+       .interface_cfg = rtw_sdio_interface_cfg,
++      .dynamic_rx_agg = NULL,
+       .read8 = rtw_sdio_read8,
+       .read16 = rtw_sdio_read16,
+--- a/drivers/net/wireless/realtek/rtw88/usb.c
++++ b/drivers/net/wireless/realtek/rtw88/usb.c
+@@ -766,6 +766,45 @@ static void rtw_usb_interface_cfg(struct
+       rtw_usb_init_burst_pkt_len(rtwdev);
+ }
++static void rtw_usb_dynamic_rx_agg_v1(struct rtw_dev *rtwdev, bool enable)
++{
++      u8 size, timeout;
++      u16 val16;
++
++      rtw_write32_set(rtwdev, REG_RXDMA_AGG_PG_TH, BIT_EN_PRE_CALC);
++      rtw_write8_set(rtwdev, REG_TXDMA_PQ_MAP, BIT_RXDMA_AGG_EN);
++      rtw_write8_clr(rtwdev, REG_RXDMA_AGG_PG_TH + 3, BIT(7));
++
++      if (enable) {
++              size = 0x5;
++              timeout = 0x20;
++      } else {
++              size = 0x0;
++              timeout = 0x1;
++      }
++      val16 = u16_encode_bits(size, BIT_RXDMA_AGG_PG_TH) |
++              u16_encode_bits(timeout, BIT_DMA_AGG_TO_V1);
++
++      rtw_write16(rtwdev, REG_RXDMA_AGG_PG_TH, val16);
++}
++
++static void rtw_usb_dynamic_rx_agg(struct rtw_dev *rtwdev, bool enable)
++{
++      switch (rtwdev->chip->id) {
++      case RTW_CHIP_TYPE_8822C:
++      case RTW_CHIP_TYPE_8822B:
++      case RTW_CHIP_TYPE_8821C:
++              rtw_usb_dynamic_rx_agg_v1(rtwdev, enable);
++              break;
++      case RTW_CHIP_TYPE_8723D:
++              /* Doesn't like aggregation. */
++              break;
++      case RTW_CHIP_TYPE_8703B:
++              /* Likely not found in USB devices. */
++              break;
++      }
++}
++
+ static struct rtw_hci_ops rtw_usb_ops = {
+       .tx_write = rtw_usb_tx_write,
+       .tx_kick_off = rtw_usb_tx_kick_off,
+@@ -775,6 +814,7 @@ static struct rtw_hci_ops rtw_usb_ops =
+       .deep_ps = rtw_usb_deep_ps,
+       .link_ps = rtw_usb_link_ps,
+       .interface_cfg = rtw_usb_interface_cfg,
++      .dynamic_rx_agg = rtw_usb_dynamic_rx_agg,
+       .write8  = rtw_usb_write8,
+       .write16 = rtw_usb_write16,
diff --git a/package/kernel/mac80211/patches/rtl/016-v6.12-wifi-rtw88-assign-mac_id-for-vif-sta-and-update-to-T.patch b/package/kernel/mac80211/patches/rtl/016-v6.12-wifi-rtw88-assign-mac_id-for-vif-sta-and-update-to-T.patch
new file mode 100644 (file)
index 0000000..ce110c5
--- /dev/null
@@ -0,0 +1,231 @@
+From 902cb7b11f9a7ff07233cc4c626b54c3e4703149 Mon Sep 17 00:00:00 2001
+From: Ping-Ke Shih <pkshih@realtek.com>
+Date: Mon, 19 Aug 2024 10:52:48 +0800
+Subject: [PATCH] wifi: rtw88: assign mac_id for vif/sta and update to TX desc
+
+A mac_id as an instance in firmware has to be assigned for each station
+including AP and connected stations. Firmware will use the mac_id to
+control TX rate and do statistics.
+
+Assignment rule is to assign mac_id to each vif when adding vif.
+For station mode, sta->mac_id will reuse vif->mac_id. For AP mode,
+dynamically allocate an sta->mac_id to a station, and vif->mac_id is
+used to send broadcast/multicast packets which are not belong to
+a station. For example,
+
+                  vif->mac_id      sta->mac_id
+vif0 (STA mode)        0               0
+vif1 (AP mode)         1               2...
+
+By the way, remove unused RTW_BC_MC_MACID, which was planed to send
+broadcast/multicast packets on fixed mac_id.
+
+Tested-on RTL8822CE with STA + AP SCC mode.
+
+Link: https://lore.kernel.org/linux-wireless/e4be0a75-43b2-4ae5-9aab-5c4a88e78097@gmail.com/
+Cc: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20240819025248.17939-1-pkshih@realtek.com
+---
+ drivers/net/wireless/realtek/rtw88/mac80211.c | 13 ++++++--
+ drivers/net/wireless/realtek/rtw88/main.c     | 30 ++++++++-----------
+ drivers/net/wireless/realtek/rtw88/main.h     | 14 +++++++--
+ drivers/net/wireless/realtek/rtw88/tx.c       | 11 +++++--
+ drivers/net/wireless/realtek/rtw88/tx.h       |  1 +
+ 5 files changed, 44 insertions(+), 25 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/mac80211.c
++++ b/drivers/net/wireless/realtek/rtw88/mac80211.c
+@@ -167,6 +167,12 @@ static int rtw_ops_add_interface(struct
+       mutex_lock(&rtwdev->mutex);
++      rtwvif->mac_id = rtw_acquire_macid(rtwdev);
++      if (rtwvif->mac_id >= RTW_MAX_MAC_ID_NUM) {
++              mutex_unlock(&rtwdev->mutex);
++              return -ENOSPC;
++      }
++
+       port = find_first_zero_bit(rtwdev->hw_port, RTW_PORT_NUM);
+       if (port >= RTW_PORT_NUM) {
+               mutex_unlock(&rtwdev->mutex);
+@@ -214,7 +220,8 @@ static int rtw_ops_add_interface(struct
+       mutex_unlock(&rtwdev->mutex);
+-      rtw_dbg(rtwdev, RTW_DBG_STATE, "start vif %pM on port %d\n", vif->addr, rtwvif->port);
++      rtw_dbg(rtwdev, RTW_DBG_STATE, "start vif %pM mac_id %d on port %d\n",
++              vif->addr, rtwvif->mac_id, rtwvif->port);
+       return 0;
+ }
+@@ -225,7 +232,8 @@ static void rtw_ops_remove_interface(str
+       struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
+       u32 config = 0;
+-      rtw_dbg(rtwdev, RTW_DBG_STATE, "stop vif %pM on port %d\n", vif->addr, rtwvif->port);
++      rtw_dbg(rtwdev, RTW_DBG_STATE, "stop vif %pM mac_id %d on port %d\n",
++              vif->addr, rtwvif->mac_id, rtwvif->port);
+       mutex_lock(&rtwdev->mutex);
+@@ -242,6 +250,7 @@ static void rtw_ops_remove_interface(str
+       config |= PORT_SET_BCN_CTRL;
+       rtw_vif_port_config(rtwdev, rtwvif, config);
+       clear_bit(rtwvif->port, rtwdev->hw_port);
++      rtw_release_macid(rtwdev, rtwvif->mac_id);
+       rtw_recalc_lps(rtwdev, NULL);
+       mutex_unlock(&rtwdev->mutex);
+--- a/drivers/net/wireless/realtek/rtw88/main.c
++++ b/drivers/net/wireless/realtek/rtw88/main.c
+@@ -311,17 +311,6 @@ static void rtw_ips_work(struct work_str
+       mutex_unlock(&rtwdev->mutex);
+ }
+-static u8 rtw_acquire_macid(struct rtw_dev *rtwdev)
+-{
+-      unsigned long mac_id;
+-
+-      mac_id = find_first_zero_bit(rtwdev->mac_id_map, RTW_MAX_MAC_ID_NUM);
+-      if (mac_id < RTW_MAX_MAC_ID_NUM)
+-              set_bit(mac_id, rtwdev->mac_id_map);
+-
+-      return mac_id;
+-}
+-
+ static void rtw_sta_rc_work(struct work_struct *work)
+ {
+       struct rtw_sta_info *si = container_of(work, struct rtw_sta_info,
+@@ -340,12 +329,14 @@ int rtw_sta_add(struct rtw_dev *rtwdev,
+       struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
+       int i;
+-      si->mac_id = rtw_acquire_macid(rtwdev);
+-      if (si->mac_id >= RTW_MAX_MAC_ID_NUM)
+-              return -ENOSPC;
++      if (vif->type == NL80211_IFTYPE_STATION) {
++              si->mac_id = rtwvif->mac_id;
++      } else {
++              si->mac_id = rtw_acquire_macid(rtwdev);
++              if (si->mac_id >= RTW_MAX_MAC_ID_NUM)
++                      return -ENOSPC;
++      }
+-      if (vif->type == NL80211_IFTYPE_STATION && vif->cfg.assoc == 0)
+-              rtwvif->mac_id = si->mac_id;
+       si->rtwdev = rtwdev;
+       si->sta = sta;
+       si->vif = vif;
+@@ -370,11 +361,13 @@ void rtw_sta_remove(struct rtw_dev *rtwd
+                   bool fw_exist)
+ {
+       struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
++      struct ieee80211_vif *vif = si->vif;
+       int i;
+       cancel_work_sync(&si->rc_work);
+-      rtw_release_macid(rtwdev, si->mac_id);
++      if (vif->type != NL80211_IFTYPE_STATION)
++              rtw_release_macid(rtwdev, si->mac_id);
+       if (fw_exist)
+               rtw_fw_media_status_report(rtwdev, si->mac_id, false);
+@@ -614,6 +607,8 @@ static void rtw_reset_vif_iter(void *dat
+       rtw_bf_disassoc(rtwdev, vif, NULL);
+       rtw_vif_assoc_changed(rtwvif, NULL);
+       rtw_txq_cleanup(rtwdev, vif->txq);
++
++      rtw_release_macid(rtwdev, rtwvif->mac_id);
+ }
+ void rtw_fw_recovery(struct rtw_dev *rtwdev)
+@@ -2139,7 +2134,6 @@ int rtw_core_init(struct rtw_dev *rtwdev
+       rtwdev->sec.total_cam_num = 32;
+       rtwdev->hal.current_channel = 1;
+       rtwdev->dm_info.fix_rate = U8_MAX;
+-      set_bit(RTW_BC_MC_MACID, rtwdev->mac_id_map);
+       rtw_stats_init(rtwdev);
+--- a/drivers/net/wireless/realtek/rtw88/main.h
++++ b/drivers/net/wireless/realtek/rtw88/main.h
+@@ -742,7 +742,6 @@ struct rtw_txq {
+       unsigned long flags;
+ };
+-#define RTW_BC_MC_MACID 1
+ DECLARE_EWMA(rssi, 10, 16);
+ struct rtw_sta_info {
+@@ -805,7 +804,7 @@ struct rtw_bf_info {
+ struct rtw_vif {
+       enum rtw_net_type net_type;
+       u16 aid;
+-      u8 mac_id; /* for STA mode only */
++      u8 mac_id;
+       u8 mac_addr[ETH_ALEN];
+       u8 bssid[ETH_ALEN];
+       u8 port;
+@@ -2131,6 +2130,17 @@ static inline bool rtw_chip_has_tx_stbc(
+       return rtwdev->chip->tx_stbc;
+ }
++static inline u8 rtw_acquire_macid(struct rtw_dev *rtwdev)
++{
++      unsigned long mac_id;
++
++      mac_id = find_first_zero_bit(rtwdev->mac_id_map, RTW_MAX_MAC_ID_NUM);
++      if (mac_id < RTW_MAX_MAC_ID_NUM)
++              set_bit(mac_id, rtwdev->mac_id_map);
++
++      return mac_id;
++}
++
+ static inline void rtw_release_macid(struct rtw_dev *rtwdev, u8 mac_id)
+ {
+       clear_bit(mac_id, rtwdev->mac_id_map);
+--- a/drivers/net/wireless/realtek/rtw88/tx.c
++++ b/drivers/net/wireless/realtek/rtw88/tx.c
+@@ -46,7 +46,8 @@ void rtw_tx_fill_tx_desc(struct rtw_tx_p
+                     le32_encode_bits(pkt_info->ls, RTW_TX_DESC_W0_LS) |
+                     le32_encode_bits(pkt_info->dis_qselseq, RTW_TX_DESC_W0_DISQSELSEQ);
+-      tx_desc->w1 = le32_encode_bits(pkt_info->qsel, RTW_TX_DESC_W1_QSEL) |
++      tx_desc->w1 = le32_encode_bits(pkt_info->mac_id, RTW_TX_DESC_W1_MACID) |
++                    le32_encode_bits(pkt_info->qsel, RTW_TX_DESC_W1_QSEL) |
+                     le32_encode_bits(pkt_info->rate_id, RTW_TX_DESC_W1_RATE_ID) |
+                     le32_encode_bits(pkt_info->sec_type, RTW_TX_DESC_W1_SEC_TYPE) |
+                     le32_encode_bits(pkt_info->pkt_offset, RTW_TX_DESC_W1_PKT_OFFSET) |
+@@ -401,14 +402,18 @@ void rtw_tx_pkt_info_update(struct rtw_d
+       const struct rtw_chip_info *chip = rtwdev->chip;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
++      struct ieee80211_vif *vif = info->control.vif;
+       struct rtw_sta_info *si;
+-      struct ieee80211_vif *vif = NULL;
++      struct rtw_vif *rtwvif;
+       __le16 fc = hdr->frame_control;
+       bool bmc;
+       if (sta) {
+               si = (struct rtw_sta_info *)sta->drv_priv;
+-              vif = si->vif;
++              pkt_info->mac_id = si->mac_id;
++      } else if (vif) {
++              rtwvif = (struct rtw_vif *)vif->drv_priv;
++              pkt_info->mac_id = rtwvif->mac_id;
+       }
+       if (ieee80211_is_mgmt(fc) || ieee80211_is_nullfunc(fc))
+--- a/drivers/net/wireless/realtek/rtw88/tx.h
++++ b/drivers/net/wireless/realtek/rtw88/tx.h
+@@ -27,6 +27,7 @@ struct rtw_tx_desc {
+ #define RTW_TX_DESC_W0_BMC BIT(24)
+ #define RTW_TX_DESC_W0_LS BIT(26)
+ #define RTW_TX_DESC_W0_DISQSELSEQ BIT(31)
++#define RTW_TX_DESC_W1_MACID GENMASK(7, 0)
+ #define RTW_TX_DESC_W1_QSEL GENMASK(12, 8)
+ #define RTW_TX_DESC_W1_RATE_ID GENMASK(20, 16)
+ #define RTW_TX_DESC_W1_SEC_TYPE GENMASK(23, 22)
diff --git a/package/kernel/mac80211/patches/rtl/017-v6.13-wifi-rtw88-Constify-some-arrays-and-structs.patch b/package/kernel/mac80211/patches/rtl/017-v6.13-wifi-rtw88-Constify-some-arrays-and-structs.patch
new file mode 100644 (file)
index 0000000..8d2bb9a
--- /dev/null
@@ -0,0 +1,374 @@
+From 140403599b74839b0a57c5397b7e8579e5332364 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 18 Sep 2024 01:53:55 +0300
+Subject: [PATCH] wifi: rtw88: Constify some arrays and structs
+
+These are never modified, so make them const:
+
+card_enable_flow_8703b
+card_disable_flow_8703b
+rtw8703b_ops
+
+rtw8723d_ops
+card_enable_flow_8723d
+card_disable_flow_8723d
+
+trans_carddis_to_cardemu_8821c
+trans_cardemu_to_act_8821c
+trans_act_to_cardemu_8821c
+trans_cardemu_to_carddis_8821c
+card_enable_flow_8821c
+card_disable_flow_8821c
+rtw8821c_dig
+page_table_8821c
+rqpn_table_8821c
+prioq_addrs_8821c
+rtw8821c_ops
+
+card_enable_flow_8822b
+card_disable_flow_8822b
+prioq_addrs_8822b
+rtw8822b_ops
+rtw8822b_edcca_th
+
+card_enable_flow_8822c
+card_disable_flow_8822c
+prioq_addrs_8822c
+rtw8822c_ops
+rtw8822c_edcca_th
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Acked-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/dae7994f-3491-40de-b537-ebf68df084bb@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/fw.c       |  2 +-
+ drivers/net/wireless/realtek/rtw88/mac.c      |  4 ++--
+ drivers/net/wireless/realtek/rtw88/main.h     |  8 +++----
+ drivers/net/wireless/realtek/rtw88/phy.c      |  2 +-
+ drivers/net/wireless/realtek/rtw88/rtw8703b.c |  6 ++---
+ drivers/net/wireless/realtek/rtw88/rtw8723d.c |  6 ++---
+ drivers/net/wireless/realtek/rtw88/rtw8821c.c | 22 +++++++++----------
+ drivers/net/wireless/realtek/rtw88/rtw8822b.c | 10 ++++-----
+ drivers/net/wireless/realtek/rtw88/rtw8822c.c | 10 ++++-----
+ 9 files changed, 35 insertions(+), 35 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/fw.c
++++ b/drivers/net/wireless/realtek/rtw88/fw.c
+@@ -267,7 +267,7 @@ static void rtw_fw_scan_result(struct rt
+ static void rtw_fw_adaptivity_result(struct rtw_dev *rtwdev, u8 *payload,
+                                    u8 length)
+ {
+-      struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th;
++      const struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th;
+       struct rtw_c2h_adaptivity *result = (struct rtw_c2h_adaptivity *)payload;
+       rtw_dbg(rtwdev, RTW_DBG_ADAPTIVITY,
+--- a/drivers/net/wireless/realtek/rtw88/mac.c
++++ b/drivers/net/wireless/realtek/rtw88/mac.c
+@@ -228,7 +228,7 @@ static int rtw_sub_pwr_seq_parser(struct
+ }
+ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev,
+-                            const struct rtw_pwr_seq_cmd **cmd_seq)
++                            const struct rtw_pwr_seq_cmd * const *cmd_seq)
+ {
+       u8 cut_mask;
+       u8 intf_mask;
+@@ -271,7 +271,7 @@ static int rtw_pwr_seq_parser(struct rtw
+ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on)
+ {
+       const struct rtw_chip_info *chip = rtwdev->chip;
+-      const struct rtw_pwr_seq_cmd **pwr_seq;
++      const struct rtw_pwr_seq_cmd * const *pwr_seq;
+       u32 imr = 0;
+       u8 rpwm;
+       bool cur_pwr;
+--- a/drivers/net/wireless/realtek/rtw88/main.h
++++ b/drivers/net/wireless/realtek/rtw88/main.h
+@@ -1167,7 +1167,7 @@ enum rtw_fwcd_item {
+ /* hardware configuration for each IC */
+ struct rtw_chip_info {
+-      struct rtw_chip_ops *ops;
++      const struct rtw_chip_ops *ops;
+       u8 id;
+       const char *fw_name;
+@@ -1209,8 +1209,8 @@ struct rtw_chip_info {
+       /* init values */
+       u8 sys_func_en;
+-      const struct rtw_pwr_seq_cmd **pwr_on_seq;
+-      const struct rtw_pwr_seq_cmd **pwr_off_seq;
++      const struct rtw_pwr_seq_cmd * const *pwr_on_seq;
++      const struct rtw_pwr_seq_cmd * const *pwr_off_seq;
+       const struct rtw_rqpn *rqpn_table;
+       const struct rtw_prioq_addrs *prioq_addrs;
+       const struct rtw_page_table *page_table;
+@@ -1242,7 +1242,7 @@ struct rtw_chip_info {
+       u8 bfer_su_max_num;
+       u8 bfer_mu_max_num;
+-      struct rtw_hw_reg_offset *edcca_th;
++      const struct rtw_hw_reg_offset *edcca_th;
+       s8 l2h_th_ini_cs;
+       s8 l2h_th_ini_ad;
+--- a/drivers/net/wireless/realtek/rtw88/phy.c
++++ b/drivers/net/wireless/realtek/rtw88/phy.c
+@@ -123,7 +123,7 @@ static void rtw_phy_cck_pd_init(struct r
+ void rtw_phy_set_edcca_th(struct rtw_dev *rtwdev, u8 l2h, u8 h2l)
+ {
+-      struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th;
++      const struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th;
+       rtw_write32_mask(rtwdev,
+                        edcca_th[EDCCA_TH_L2H_IDX].hw_reg.addr,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c
+@@ -481,14 +481,14 @@ static const struct rtw_pwr_seq_cmd tran
+       {TRANS_SEQ_END},
+ };
+-static const struct rtw_pwr_seq_cmd *card_enable_flow_8703b[] = {
++static const struct rtw_pwr_seq_cmd * const card_enable_flow_8703b[] = {
+       trans_pre_enable_8703b,
+       trans_carddis_to_cardemu_8703b,
+       trans_cardemu_to_act_8703b,
+       NULL
+ };
+-static const struct rtw_pwr_seq_cmd *card_disable_flow_8703b[] = {
++static const struct rtw_pwr_seq_cmd * const card_disable_flow_8703b[] = {
+       trans_act_to_lps_8703b,
+       trans_act_to_reset_mcu_8703b,
+       trans_act_to_cardemu_8703b,
+@@ -1941,7 +1941,7 @@ static const struct coex_tdma_para tdma_
+       { {0x61, 0x08, 0x03, 0x11, 0x11} },
+ };
+-static struct rtw_chip_ops rtw8703b_ops = {
++static const struct rtw_chip_ops rtw8703b_ops = {
+       .mac_init               = rtw8723x_mac_init,
+       .dump_fw_crash          = NULL,
+       .shutdown               = NULL,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+@@ -1430,7 +1430,7 @@ static void rtw8723d_pwr_track(struct rt
+       dm_info->pwr_trk_triggered = false;
+ }
+-static struct rtw_chip_ops rtw8723d_ops = {
++static const struct rtw_chip_ops rtw8723d_ops = {
+       .phy_set_param          = rtw8723d_phy_set_param,
+       .read_efuse             = rtw8723x_read_efuse,
+       .query_rx_desc          = rtw8723d_query_rx_desc,
+@@ -1788,7 +1788,7 @@ static const struct rtw_pwr_seq_cmd tran
+        RTW_PWR_CMD_END, 0, 0},
+ };
+-static const struct rtw_pwr_seq_cmd *card_enable_flow_8723d[] = {
++static const struct rtw_pwr_seq_cmd * const card_enable_flow_8723d[] = {
+       trans_carddis_to_cardemu_8723d,
+       trans_cardemu_to_act_8723d,
+       NULL
+@@ -2004,7 +2004,7 @@ static const struct rtw_pwr_seq_cmd tran
+        RTW_PWR_CMD_END, 0, 0},
+ };
+-static const struct rtw_pwr_seq_cmd *card_disable_flow_8723d[] = {
++static const struct rtw_pwr_seq_cmd * const card_disable_flow_8723d[] = {
+       trans_act_to_lps_8723d,
+       trans_act_to_pre_carddis_8723d,
+       trans_act_to_cardemu_8723d,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
+@@ -1254,7 +1254,7 @@ static void rtw8821c_fill_txdesc_checksu
+       fill_txdesc_checksum_common(txdesc, 16);
+ }
+-static struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = {
++static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821c[] = {
+       {0x0086,
+        RTW_PWR_CUT_ALL_MSK,
+        RTW_PWR_INTF_SDIO_MSK,
+@@ -1292,7 +1292,7 @@ static struct rtw_pwr_seq_cmd trans_card
+        RTW_PWR_CMD_END, 0, 0},
+ };
+-static struct rtw_pwr_seq_cmd trans_cardemu_to_act_8821c[] = {
++static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8821c[] = {
+       {0x0020,
+        RTW_PWR_CUT_ALL_MSK,
+        RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
+@@ -1396,7 +1396,7 @@ static struct rtw_pwr_seq_cmd trans_card
+        RTW_PWR_CMD_END, 0, 0},
+ };
+-static struct rtw_pwr_seq_cmd trans_act_to_cardemu_8821c[] = {
++static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8821c[] = {
+       {0x0093,
+        RTW_PWR_CUT_ALL_MSK,
+        RTW_PWR_INTF_ALL_MSK,
+@@ -1454,7 +1454,7 @@ static struct rtw_pwr_seq_cmd trans_act_
+        RTW_PWR_CMD_END, 0, 0},
+ };
+-static struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8821c[] = {
++static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8821c[] = {
+       {0x0007,
+        RTW_PWR_CUT_ALL_MSK,
+        RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
+@@ -1567,13 +1567,13 @@ static struct rtw_pwr_seq_cmd trans_card
+        RTW_PWR_CMD_END, 0, 0},
+ };
+-static const struct rtw_pwr_seq_cmd *card_enable_flow_8821c[] = {
++static const struct rtw_pwr_seq_cmd * const card_enable_flow_8821c[] = {
+       trans_carddis_to_cardemu_8821c,
+       trans_cardemu_to_act_8821c,
+       NULL
+ };
+-static const struct rtw_pwr_seq_cmd *card_disable_flow_8821c[] = {
++static const struct rtw_pwr_seq_cmd * const card_disable_flow_8821c[] = {
+       trans_act_to_cardemu_8821c,
+       trans_cardemu_to_carddis_8821c,
+       NULL
+@@ -1629,7 +1629,7 @@ static const struct rtw_rfe_def rtw8821c
+       [6] = RTW_DEF_RFE(8821c, 0, 0),
+ };
+-static struct rtw_hw_reg rtw8821c_dig[] = {
++static const struct rtw_hw_reg rtw8821c_dig[] = {
+       [0] = { .addr = 0xc50, .mask = 0x7f },
+ };
+@@ -1639,7 +1639,7 @@ static const struct rtw_ltecoex_addr rtw
+       .rdata = LTECOEX_READ_DATA,
+ };
+-static struct rtw_page_table page_table_8821c[] = {
++static const struct rtw_page_table page_table_8821c[] = {
+       /* not sure what [0] stands for */
+       {16, 16, 16, 14, 1},
+       {16, 16, 16, 14, 1},
+@@ -1648,7 +1648,7 @@ static struct rtw_page_table page_table_
+       {16, 16, 16, 14, 1},
+ };
+-static struct rtw_rqpn rqpn_table_8821c[] = {
++static const struct rtw_rqpn rqpn_table_8821c[] = {
+       /* not sure what [0] stands for */
+       {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
+        RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
+@@ -1667,7 +1667,7 @@ static struct rtw_rqpn rqpn_table_8821c[
+        RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
+ };
+-static struct rtw_prioq_addrs prioq_addrs_8821c = {
++static const struct rtw_prioq_addrs prioq_addrs_8821c = {
+       .prio[RTW_DMA_MAPPING_EXTRA] = {
+               .rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2,
+       },
+@@ -1683,7 +1683,7 @@ static struct rtw_prioq_addrs prioq_addr
+       .wsize = true,
+ };
+-static struct rtw_chip_ops rtw8821c_ops = {
++static const struct rtw_chip_ops rtw8821c_ops = {
+       .phy_set_param          = rtw8821c_phy_set_param,
+       .read_efuse             = rtw8821c_read_efuse,
+       .query_rx_desc          = rtw8821c_query_rx_desc,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+@@ -1978,13 +1978,13 @@ static const struct rtw_pwr_seq_cmd tran
+        RTW_PWR_CMD_END, 0, 0},
+ };
+-static const struct rtw_pwr_seq_cmd *card_enable_flow_8822b[] = {
++static const struct rtw_pwr_seq_cmd * const card_enable_flow_8822b[] = {
+       trans_carddis_to_cardemu_8822b,
+       trans_cardemu_to_act_8822b,
+       NULL
+ };
+-static const struct rtw_pwr_seq_cmd *card_disable_flow_8822b[] = {
++static const struct rtw_pwr_seq_cmd * const card_disable_flow_8822b[] = {
+       trans_act_to_cardemu_8822b,
+       trans_cardemu_to_carddis_8822b,
+       NULL
+@@ -2156,7 +2156,7 @@ static const struct rtw_rqpn rqpn_table_
+        RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
+ };
+-static struct rtw_prioq_addrs prioq_addrs_8822b = {
++static const struct rtw_prioq_addrs prioq_addrs_8822b = {
+       .prio[RTW_DMA_MAPPING_EXTRA] = {
+               .rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2,
+       },
+@@ -2172,7 +2172,7 @@ static struct rtw_prioq_addrs prioq_addr
+       .wsize = true,
+ };
+-static struct rtw_chip_ops rtw8822b_ops = {
++static const struct rtw_chip_ops rtw8822b_ops = {
+       .phy_set_param          = rtw8822b_phy_set_param,
+       .read_efuse             = rtw8822b_read_efuse,
+       .query_rx_desc          = rtw8822b_query_rx_desc,
+@@ -2521,7 +2521,7 @@ static const struct rtw_reg_domain coex_
+       {0xc50,  MASKBYTE0, RTW_REG_DOMAIN_MAC8},
+ };
+-static struct rtw_hw_reg_offset rtw8822b_edcca_th[] = {
++static const struct rtw_hw_reg_offset rtw8822b_edcca_th[] = {
+       [EDCCA_TH_L2H_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE0}, .offset = 0},
+       [EDCCA_TH_H2L_IDX] = {{.addr = 0x8a4, .mask = MASKBYTE1}, .offset = 0},
+ };
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+@@ -4874,13 +4874,13 @@ static const struct rtw_pwr_seq_cmd tran
+        RTW_PWR_CMD_END, 0, 0},
+ };
+-static const struct rtw_pwr_seq_cmd *card_enable_flow_8822c[] = {
++static const struct rtw_pwr_seq_cmd * const card_enable_flow_8822c[] = {
+       trans_carddis_to_cardemu_8822c,
+       trans_cardemu_to_act_8822c,
+       NULL
+ };
+-static const struct rtw_pwr_seq_cmd *card_disable_flow_8822c[] = {
++static const struct rtw_pwr_seq_cmd * const card_disable_flow_8822c[] = {
+       trans_act_to_cardemu_8822c,
+       trans_cardemu_to_carddis_8822c,
+       NULL
+@@ -4972,7 +4972,7 @@ static const struct rtw_rqpn rqpn_table_
+        RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
+ };
+-static struct rtw_prioq_addrs prioq_addrs_8822c = {
++static const struct rtw_prioq_addrs prioq_addrs_8822c = {
+       .prio[RTW_DMA_MAPPING_EXTRA] = {
+               .rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2,
+       },
+@@ -4988,7 +4988,7 @@ static struct rtw_prioq_addrs prioq_addr
+       .wsize = true,
+ };
+-static struct rtw_chip_ops rtw8822c_ops = {
++static const struct rtw_chip_ops rtw8822c_ops = {
+       .phy_set_param          = rtw8822c_phy_set_param,
+       .read_efuse             = rtw8822c_read_efuse,
+       .query_rx_desc          = rtw8822c_query_rx_desc,
+@@ -5301,7 +5301,7 @@ static const struct rtw_pwr_track_tbl rt
+       .pwrtrk_2g_ccka_p = rtw8822c_pwrtrk_2g_cck_a_p,
+ };
+-static struct rtw_hw_reg_offset rtw8822c_edcca_th[] = {
++static const struct rtw_hw_reg_offset rtw8822c_edcca_th[] = {
+       [EDCCA_TH_L2H_IDX] = {
+               {.addr = 0x84c, .mask = MASKBYTE2}, .offset = 0x80
+       },
diff --git a/package/kernel/mac80211/patches/rtl/019-v6.13-wifi-rtw88-Parse-the-RX-descriptor-with-a-single-fun.patch b/package/kernel/mac80211/patches/rtl/019-v6.13-wifi-rtw88-Parse-the-RX-descriptor-with-a-single-fun.patch
new file mode 100644 (file)
index 0000000..9828f50
--- /dev/null
@@ -0,0 +1,560 @@
+From bbb6f9be7f99464d5ab7e2f321fa728d33eeec9a Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Fri, 20 Sep 2024 22:27:30 +0300
+Subject: [PATCH] wifi: rtw88: Parse the RX descriptor with a single function
+
+rtw8703b_query_rx_desc(), rtw8723d_query_rx_desc(),
+rtw8821c_query_rx_desc(), rtw8822b_query_rx_desc(), and
+rtw8822c_query_rx_desc() are almost identical, so replace them all with
+a single function, rtw_rx_query_rx_desc().
+
+Also, access the RX descriptor using a struct with __le32 members and
+le32_get_bits().
+
+Tested with RTL8811CU, RTL8811AU, and RTL8812AU.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Tested-by: Ping-Ke Shih <pkshih@realtek.com> # RTL8723DE and RTL8822CE
+Acked-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/913f1747-38fc-4409-85a4-57bb9cee506b@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/main.h     |  5 +-
+ drivers/net/wireless/realtek/rtw88/pci.c      |  2 +-
+ drivers/net/wireless/realtek/rtw88/rtw8703b.c | 56 +--------------
+ drivers/net/wireless/realtek/rtw88/rtw8723d.c | 43 +-----------
+ drivers/net/wireless/realtek/rtw88/rtw8821c.c | 43 +-----------
+ drivers/net/wireless/realtek/rtw88/rtw8822b.c | 43 +-----------
+ drivers/net/wireless/realtek/rtw88/rtw8822c.c | 44 +-----------
+ drivers/net/wireless/realtek/rtw88/rx.c       | 70 +++++++++++++++++--
+ drivers/net/wireless/realtek/rtw88/rx.h       | 64 ++++++++---------
+ drivers/net/wireless/realtek/rtw88/sdio.c     |  3 +-
+ drivers/net/wireless/realtek/rtw88/usb.c      |  4 +-
+ 11 files changed, 106 insertions(+), 271 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/main.h
++++ b/drivers/net/wireless/realtek/rtw88/main.h
+@@ -848,9 +848,8 @@ struct rtw_chip_ops {
+       void (*phy_set_param)(struct rtw_dev *rtwdev);
+       void (*set_channel)(struct rtw_dev *rtwdev, u8 channel,
+                           u8 bandwidth, u8 primary_chan_idx);
+-      void (*query_rx_desc)(struct rtw_dev *rtwdev, u8 *rx_desc,
+-                            struct rtw_rx_pkt_stat *pkt_stat,
+-                            struct ieee80211_rx_status *rx_status);
++      void (*query_phy_status)(struct rtw_dev *rtwdev, u8 *phy_status,
++                               struct rtw_rx_pkt_stat *pkt_stat);
+       u32 (*read_rf)(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
+                      u32 addr, u32 mask);
+       bool (*write_rf)(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
+--- a/drivers/net/wireless/realtek/rtw88/pci.c
++++ b/drivers/net/wireless/realtek/rtw88/pci.c
+@@ -1065,7 +1065,7 @@ static u32 rtw_pci_rx_napi(struct rtw_de
+               dma_sync_single_for_cpu(rtwdev->dev, dma, RTK_PCI_RX_BUF_SIZE,
+                                       DMA_FROM_DEVICE);
+               rx_desc = skb->data;
+-              chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status);
++              rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status);
+               /* offset from rx_desc to payload */
+               pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
+--- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c
+@@ -29,9 +29,6 @@
+ #define TBTT_PROHIBIT_HOLD_TIME 0x80
+ #define TBTT_PROHIBIT_HOLD_TIME_STOP_BCN 0x64
+-/* raw pkt_stat->drv_info_sz is in unit of 8-bytes */
+-#define RX_DRV_INFO_SZ_UNIT_8703B 8
+-
+ #define TRANS_SEQ_END                 \
+       0xFFFF,                         \
+       RTW_PWR_CUT_ALL_MSK,            \
+@@ -1032,57 +1029,6 @@ static void query_phy_status(struct rtw_
+               query_phy_status_ofdm(rtwdev, phy_status, pkt_stat);
+ }
+-static void rtw8703b_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc,
+-                                 struct rtw_rx_pkt_stat *pkt_stat,
+-                                 struct ieee80211_rx_status *rx_status)
+-{
+-      struct ieee80211_hdr *hdr;
+-      u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz;
+-      u8 *phy_status = NULL;
+-
+-      memset(pkt_stat, 0, sizeof(*pkt_stat));
+-
+-      pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc);
+-      pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc);
+-      pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc);
+-      pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) &&
+-                            GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE;
+-      pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc);
+-      pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc);
+-      pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc);
+-      pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc);
+-      pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc);
+-      pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc);
+-      pkt_stat->ppdu_cnt = 0;
+-      pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc);
+-
+-      pkt_stat->drv_info_sz *= RX_DRV_INFO_SZ_UNIT_8703B;
+-
+-      if (pkt_stat->is_c2h)
+-              return;
+-
+-      hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift +
+-                                     pkt_stat->drv_info_sz);
+-
+-      pkt_stat->bw = GET_RX_DESC_BW(rx_desc);
+-
+-      if (pkt_stat->phy_status) {
+-              phy_status = rx_desc + desc_sz + pkt_stat->shift;
+-              query_phy_status(rtwdev, phy_status, pkt_stat);
+-      }
+-
+-      rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status);
+-
+-      /* Rtl8723cs driver checks for size < 14 or size > 8192 and
+-       * simply drops the packet. Maybe this should go into
+-       * rtw_rx_fill_rx_status()?
+-       */
+-      if (pkt_stat->pkt_len == 0) {
+-              rx_status->flag |= RX_FLAG_NO_PSDU;
+-              rtw_dbg(rtwdev, RTW_DBG_RX, "zero length packet");
+-      }
+-}
+-
+ #define ADDA_ON_VAL_8703B 0x03c00014
+ static
+@@ -1948,7 +1894,7 @@ static const struct rtw_chip_ops rtw8703
+       .read_efuse             = rtw8703b_read_efuse,
+       .phy_set_param          = rtw8703b_phy_set_param,
+       .set_channel            = rtw8703b_set_channel,
+-      .query_rx_desc          = rtw8703b_query_rx_desc,
++      .query_phy_status       = query_phy_status,
+       .read_rf                = rtw_phy_read_rf_sipi,
+       .write_rf               = rtw_phy_write_rf_reg_sipi,
+       .set_tx_power_index     = rtw8723x_set_tx_power_index,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+@@ -227,47 +227,6 @@ static void query_phy_status(struct rtw_
+       }
+ }
+-static void rtw8723d_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc,
+-                                 struct rtw_rx_pkt_stat *pkt_stat,
+-                                 struct ieee80211_rx_status *rx_status)
+-{
+-      struct ieee80211_hdr *hdr;
+-      u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz;
+-      u8 *phy_status = NULL;
+-
+-      memset(pkt_stat, 0, sizeof(*pkt_stat));
+-
+-      pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc);
+-      pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc);
+-      pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc);
+-      pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) &&
+-                            GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE;
+-      pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc);
+-      pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc);
+-      pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc);
+-      pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc);
+-      pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc);
+-      pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc);
+-      pkt_stat->ppdu_cnt = 0;
+-      pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc);
+-
+-      /* drv_info_sz is in unit of 8-bytes */
+-      pkt_stat->drv_info_sz *= 8;
+-
+-      /* c2h cmd pkt's rx/phy status is not interested */
+-      if (pkt_stat->is_c2h)
+-              return;
+-
+-      hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift +
+-                                     pkt_stat->drv_info_sz);
+-      if (pkt_stat->phy_status) {
+-              phy_status = rx_desc + desc_sz + pkt_stat->shift;
+-              query_phy_status(rtwdev, phy_status, pkt_stat);
+-      }
+-
+-      rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status);
+-}
+-
+ static bool rtw8723d_check_spur_ov_thres(struct rtw_dev *rtwdev,
+                                        u8 channel, u32 thres)
+ {
+@@ -1433,7 +1392,7 @@ static void rtw8723d_pwr_track(struct rt
+ static const struct rtw_chip_ops rtw8723d_ops = {
+       .phy_set_param          = rtw8723d_phy_set_param,
+       .read_efuse             = rtw8723x_read_efuse,
+-      .query_rx_desc          = rtw8723d_query_rx_desc,
++      .query_phy_status       = query_phy_status,
+       .set_channel            = rtw8723d_set_channel,
+       .mac_init               = rtw8723x_mac_init,
+       .shutdown               = rtw8723d_shutdown,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
+@@ -679,47 +679,6 @@ static void query_phy_status(struct rtw_
+       }
+ }
+-static void rtw8821c_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc,
+-                                 struct rtw_rx_pkt_stat *pkt_stat,
+-                                 struct ieee80211_rx_status *rx_status)
+-{
+-      struct ieee80211_hdr *hdr;
+-      u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz;
+-      u8 *phy_status = NULL;
+-
+-      memset(pkt_stat, 0, sizeof(*pkt_stat));
+-
+-      pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc);
+-      pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc);
+-      pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc);
+-      pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) &&
+-                            GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE;
+-      pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc);
+-      pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc);
+-      pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc);
+-      pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc);
+-      pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc);
+-      pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc);
+-      pkt_stat->ppdu_cnt = GET_RX_DESC_PPDU_CNT(rx_desc);
+-      pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc);
+-
+-      /* drv_info_sz is in unit of 8-bytes */
+-      pkt_stat->drv_info_sz *= 8;
+-
+-      /* c2h cmd pkt's rx/phy status is not interested */
+-      if (pkt_stat->is_c2h)
+-              return;
+-
+-      hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift +
+-                                     pkt_stat->drv_info_sz);
+-      if (pkt_stat->phy_status) {
+-              phy_status = rx_desc + desc_sz + pkt_stat->shift;
+-              query_phy_status(rtwdev, phy_status, pkt_stat);
+-      }
+-
+-      rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status);
+-}
+-
+ static void
+ rtw8821c_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs)
+ {
+@@ -1686,7 +1645,7 @@ static const struct rtw_prioq_addrs prio
+ static const struct rtw_chip_ops rtw8821c_ops = {
+       .phy_set_param          = rtw8821c_phy_set_param,
+       .read_efuse             = rtw8821c_read_efuse,
+-      .query_rx_desc          = rtw8821c_query_rx_desc,
++      .query_phy_status       = query_phy_status,
+       .set_channel            = rtw8821c_set_channel,
+       .mac_init               = rtw8821c_mac_init,
+       .read_rf                = rtw_phy_read_rf,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+@@ -934,47 +934,6 @@ static void query_phy_status(struct rtw_
+       }
+ }
+-static void rtw8822b_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc,
+-                                 struct rtw_rx_pkt_stat *pkt_stat,
+-                                 struct ieee80211_rx_status *rx_status)
+-{
+-      struct ieee80211_hdr *hdr;
+-      u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz;
+-      u8 *phy_status = NULL;
+-
+-      memset(pkt_stat, 0, sizeof(*pkt_stat));
+-
+-      pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc);
+-      pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc);
+-      pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc);
+-      pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) &&
+-                            GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE;
+-      pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc);
+-      pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc);
+-      pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc);
+-      pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc);
+-      pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc);
+-      pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc);
+-      pkt_stat->ppdu_cnt = GET_RX_DESC_PPDU_CNT(rx_desc);
+-      pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc);
+-
+-      /* drv_info_sz is in unit of 8-bytes */
+-      pkt_stat->drv_info_sz *= 8;
+-
+-      /* c2h cmd pkt's rx/phy status is not interested */
+-      if (pkt_stat->is_c2h)
+-              return;
+-
+-      hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift +
+-                                     pkt_stat->drv_info_sz);
+-      if (pkt_stat->phy_status) {
+-              phy_status = rx_desc + desc_sz + pkt_stat->shift;
+-              query_phy_status(rtwdev, phy_status, pkt_stat);
+-      }
+-
+-      rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status);
+-}
+-
+ static void
+ rtw8822b_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs)
+ {
+@@ -2175,7 +2134,7 @@ static const struct rtw_prioq_addrs prio
+ static const struct rtw_chip_ops rtw8822b_ops = {
+       .phy_set_param          = rtw8822b_phy_set_param,
+       .read_efuse             = rtw8822b_read_efuse,
+-      .query_rx_desc          = rtw8822b_query_rx_desc,
++      .query_phy_status       = query_phy_status,
+       .set_channel            = rtw8822b_set_channel,
+       .mac_init               = rtw8822b_mac_init,
+       .read_rf                = rtw_phy_read_rf,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+@@ -2690,48 +2690,6 @@ static void query_phy_status(struct rtw_
+       }
+ }
+-static void rtw8822c_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc,
+-                                 struct rtw_rx_pkt_stat *pkt_stat,
+-                                 struct ieee80211_rx_status *rx_status)
+-{
+-      struct ieee80211_hdr *hdr;
+-      u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz;
+-      u8 *phy_status = NULL;
+-
+-      memset(pkt_stat, 0, sizeof(*pkt_stat));
+-
+-      pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc);
+-      pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc);
+-      pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc);
+-      pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) &&
+-                            GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE;
+-      pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc);
+-      pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc);
+-      pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc);
+-      pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc);
+-      pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc);
+-      pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc);
+-      pkt_stat->ppdu_cnt = GET_RX_DESC_PPDU_CNT(rx_desc);
+-      pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc);
+-
+-      /* drv_info_sz is in unit of 8-bytes */
+-      pkt_stat->drv_info_sz *= 8;
+-
+-      /* c2h cmd pkt's rx/phy status is not interested */
+-      if (pkt_stat->is_c2h)
+-              return;
+-
+-      hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift +
+-                                     pkt_stat->drv_info_sz);
+-      pkt_stat->hdr = hdr;
+-      if (pkt_stat->phy_status) {
+-              phy_status = rx_desc + desc_sz + pkt_stat->shift;
+-              query_phy_status(rtwdev, phy_status, pkt_stat);
+-      }
+-
+-      rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status);
+-}
+-
+ static void
+ rtw8822c_set_write_tx_power_ref(struct rtw_dev *rtwdev, u8 *tx_pwr_ref_cck,
+                               u8 *tx_pwr_ref_ofdm)
+@@ -4991,7 +4949,7 @@ static const struct rtw_prioq_addrs prio
+ static const struct rtw_chip_ops rtw8822c_ops = {
+       .phy_set_param          = rtw8822c_phy_set_param,
+       .read_efuse             = rtw8822c_read_efuse,
+-      .query_rx_desc          = rtw8822c_query_rx_desc,
++      .query_phy_status       = query_phy_status,
+       .set_channel            = rtw8822c_set_channel,
+       .mac_init               = rtw8822c_mac_init,
+       .dump_fw_crash          = rtw8822c_dump_fw_crash,
+--- a/drivers/net/wireless/realtek/rtw88/rx.c
++++ b/drivers/net/wireless/realtek/rtw88/rx.c
+@@ -187,11 +187,10 @@ fill_rx_status:
+ }
+ EXPORT_SYMBOL(rtw_update_rx_freq_from_ie);
+-void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
+-                         struct rtw_rx_pkt_stat *pkt_stat,
+-                         struct ieee80211_hdr *hdr,
+-                         struct ieee80211_rx_status *rx_status,
+-                         u8 *phy_status)
++static void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
++                                struct rtw_rx_pkt_stat *pkt_stat,
++                                struct ieee80211_hdr *hdr,
++                                struct ieee80211_rx_status *rx_status)
+ {
+       struct ieee80211_hw *hw = rtwdev->hw;
+       u8 path;
+@@ -242,5 +241,64 @@ void rtw_rx_fill_rx_status(struct rtw_de
+       }
+       rtw_rx_addr_match(rtwdev, pkt_stat, hdr);
++
++      /* Rtl8723cs driver checks for size < 14 or size > 8192 and
++       * simply drops the packet.
++       */
++      if (rtwdev->chip->id == RTW_CHIP_TYPE_8703B && pkt_stat->pkt_len == 0) {
++              rx_status->flag |= RX_FLAG_NO_PSDU;
++              rtw_dbg(rtwdev, RTW_DBG_RX, "zero length packet");
++      }
++}
++
++void rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8,
++                        struct rtw_rx_pkt_stat *pkt_stat,
++                        struct ieee80211_rx_status *rx_status)
++{
++      u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz;
++      struct rtw_rx_desc *rx_desc = rx_desc8;
++      struct ieee80211_hdr *hdr;
++      u32 enc_type, swdec;
++      void *phy_status;
++
++      memset(pkt_stat, 0, sizeof(*pkt_stat));
++
++      pkt_stat->pkt_len = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_PKT_LEN);
++      pkt_stat->crc_err = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_CRC32);
++      pkt_stat->icv_err = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_ICV_ERR);
++      pkt_stat->drv_info_sz = le32_get_bits(rx_desc->w0,
++                                            RTW_RX_DESC_W0_DRV_INFO_SIZE);
++      enc_type = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_ENC_TYPE);
++      pkt_stat->shift = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_SHIFT);
++      pkt_stat->phy_status = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_PHYST);
++      swdec = le32_get_bits(rx_desc->w0, RTW_RX_DESC_W0_SWDEC);
++      pkt_stat->decrypted = !swdec && enc_type != RX_DESC_ENC_NONE;
++
++      pkt_stat->cam_id = le32_get_bits(rx_desc->w1, RTW_RX_DESC_W1_MACID);
++
++      pkt_stat->is_c2h = le32_get_bits(rx_desc->w2, RTW_RX_DESC_W2_C2H);
++      pkt_stat->ppdu_cnt = le32_get_bits(rx_desc->w2, RTW_RX_DESC_W2_PPDU_CNT);
++
++      pkt_stat->rate = le32_get_bits(rx_desc->w3, RTW_RX_DESC_W3_RX_RATE);
++
++      pkt_stat->bw = le32_get_bits(rx_desc->w4, RTW_RX_DESC_W4_BW);
++
++      pkt_stat->tsf_low = le32_get_bits(rx_desc->w5, RTW_RX_DESC_W5_TSFL);
++
++      /* drv_info_sz is in unit of 8-bytes */
++      pkt_stat->drv_info_sz *= 8;
++
++      /* c2h cmd pkt's rx/phy status is not interested */
++      if (pkt_stat->is_c2h)
++              return;
++
++      phy_status = rx_desc8 + desc_sz + pkt_stat->shift;
++      hdr = phy_status + pkt_stat->drv_info_sz;
++      pkt_stat->hdr = hdr;
++
++      if (pkt_stat->phy_status)
++              rtwdev->chip->ops->query_phy_status(rtwdev, phy_status, pkt_stat);
++
++      rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status);
+ }
+-EXPORT_SYMBOL(rtw_rx_fill_rx_status);
++EXPORT_SYMBOL(rtw_rx_query_rx_desc);
+--- a/drivers/net/wireless/realtek/rtw88/rx.h
++++ b/drivers/net/wireless/realtek/rtw88/rx.h
+@@ -14,42 +14,40 @@ enum rtw_rx_desc_enc {
+       RX_DESC_ENC_WEP104      = 5,
+ };
+-#define GET_RX_DESC_PHYST(rxdesc)                                              \
+-      le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(26))
+-#define GET_RX_DESC_ICV_ERR(rxdesc)                                            \
+-      le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(15))
+-#define GET_RX_DESC_CRC32(rxdesc)                                              \
+-      le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(14))
+-#define GET_RX_DESC_SWDEC(rxdesc)                                              \
+-      le32_get_bits(*((__le32 *)(rxdesc) + 0x00), BIT(27))
+-#define GET_RX_DESC_C2H(rxdesc)                                                \
+-      le32_get_bits(*((__le32 *)(rxdesc) + 0x02), BIT(28))
+-#define GET_RX_DESC_PKT_LEN(rxdesc)                                            \
+-      le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(13, 0))
+-#define GET_RX_DESC_DRV_INFO_SIZE(rxdesc)                                      \
+-      le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(19, 16))
+-#define GET_RX_DESC_SHIFT(rxdesc)                                              \
+-      le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(25, 24))
+-#define GET_RX_DESC_ENC_TYPE(rxdesc)                                           \
+-      le32_get_bits(*((__le32 *)(rxdesc) + 0x00), GENMASK(22, 20))
+-#define GET_RX_DESC_RX_RATE(rxdesc)                                            \
+-      le32_get_bits(*((__le32 *)(rxdesc) + 0x03), GENMASK(6, 0))
+-#define GET_RX_DESC_MACID(rxdesc)                                              \
+-      le32_get_bits(*((__le32 *)(rxdesc) + 0x01), GENMASK(6, 0))
+-#define GET_RX_DESC_PPDU_CNT(rxdesc)                                           \
+-      le32_get_bits(*((__le32 *)(rxdesc) + 0x02), GENMASK(30, 29))
+-#define GET_RX_DESC_TSFL(rxdesc)                                               \
+-      le32_get_bits(*((__le32 *)(rxdesc) + 0x05), GENMASK(31, 0))
+-#define GET_RX_DESC_BW(rxdesc)                                                 \
+-      (le32_get_bits(*((__le32 *)(rxdesc) + 0x04), GENMASK(5, 4)))
++struct rtw_rx_desc {
++      __le32 w0;
++      __le32 w1;
++      __le32 w2;
++      __le32 w3;
++      __le32 w4;
++      __le32 w5;
++} __packed;
++
++#define RTW_RX_DESC_W0_PKT_LEN                GENMASK(13, 0)
++#define RTW_RX_DESC_W0_CRC32          BIT(14)
++#define RTW_RX_DESC_W0_ICV_ERR                BIT(15)
++#define RTW_RX_DESC_W0_DRV_INFO_SIZE  GENMASK(19, 16)
++#define RTW_RX_DESC_W0_ENC_TYPE               GENMASK(22, 20)
++#define RTW_RX_DESC_W0_SHIFT          GENMASK(25, 24)
++#define RTW_RX_DESC_W0_PHYST          BIT(26)
++#define RTW_RX_DESC_W0_SWDEC          BIT(27)
++
++#define RTW_RX_DESC_W1_MACID          GENMASK(6, 0)
++
++#define RTW_RX_DESC_W2_C2H            BIT(28)
++#define RTW_RX_DESC_W2_PPDU_CNT               GENMASK(30, 29)
++
++#define RTW_RX_DESC_W3_RX_RATE                GENMASK(6, 0)
++
++#define RTW_RX_DESC_W4_BW             GENMASK(5, 4)
++
++#define RTW_RX_DESC_W5_TSFL           GENMASK(31, 0)
+ void rtw_rx_stats(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
+                 struct sk_buff *skb);
+-void rtw_rx_fill_rx_status(struct rtw_dev *rtwdev,
+-                         struct rtw_rx_pkt_stat *pkt_stat,
+-                         struct ieee80211_hdr *hdr,
+-                         struct ieee80211_rx_status *rx_status,
+-                         u8 *phy_status);
++void rtw_rx_query_rx_desc(struct rtw_dev *rtwdev, void *rx_desc8,
++                        struct rtw_rx_pkt_stat *pkt_stat,
++                        struct ieee80211_rx_status *rx_status);
+ void rtw_update_rx_freq_from_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
+                               struct ieee80211_rx_status *rx_status,
+                               struct rtw_rx_pkt_stat *pkt_stat);
+--- a/drivers/net/wireless/realtek/rtw88/sdio.c
++++ b/drivers/net/wireless/realtek/rtw88/sdio.c
+@@ -981,8 +981,7 @@ static void rtw_sdio_rxfifo_recv(struct
+       while (true) {
+               rx_desc = skb->data;
+-              chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat,
+-                                       &rx_status);
++              rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat, &rx_status);
+               pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
+                            pkt_stat.shift;
+--- a/drivers/net/wireless/realtek/rtw88/usb.c
++++ b/drivers/net/wireless/realtek/rtw88/usb.c
+@@ -570,8 +570,8 @@ static void rtw_usb_rx_handler(struct wo
+               do {
+                       rx_desc = skb->data;
+-                      chip->ops->query_rx_desc(rtwdev, rx_desc, &pkt_stat,
+-                                               &rx_status);
++                      rtw_rx_query_rx_desc(rtwdev, rx_desc, &pkt_stat,
++                                           &rx_status);
+                       pkt_offset = pkt_desc_sz + pkt_stat.drv_info_sz +
+                                    pkt_stat.shift;
diff --git a/package/kernel/mac80211/patches/rtl/020-v6.12-wifi-rtw88-Fix-the-RX-aggregation-in-USB-3-mode.patch b/package/kernel/mac80211/patches/rtl/020-v6.12-wifi-rtw88-Fix-the-RX-aggregation-in-USB-3-mode.patch
new file mode 100644 (file)
index 0000000..174ee10
--- /dev/null
@@ -0,0 +1,70 @@
+From 4aefde403da7af30757915e0462d88398c9388c5 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Tue, 8 Oct 2024 21:44:02 +0300
+Subject: [PATCH] wifi: rtw88: Fix the RX aggregation in USB 3 mode
+
+RTL8822CU, RTL8822BU, and RTL8821CU don't need BIT_EN_PRE_CALC.
+In fact, RTL8822BU in USB 3 mode doesn't pass all the frames to the
+driver, resulting in much lower download speed than normal:
+
+$ iperf3 -c 192.168.0.1 -R
+Connecting to host 192.168.0.1, port 5201
+Reverse mode, remote host 192.168.0.1 is sending
+[  5] local 192.168.0.50 port 43062 connected to 192.168.0.1 port 5201
+[ ID] Interval           Transfer     Bitrate
+[  5]   0.00-1.00   sec  26.9 MBytes   225 Mbits/sec
+[  5]   1.00-2.00   sec  7.50 MBytes  62.9 Mbits/sec
+[  5]   2.00-3.00   sec  8.50 MBytes  71.3 Mbits/sec
+[  5]   3.00-4.00   sec  8.38 MBytes  70.3 Mbits/sec
+[  5]   4.00-5.00   sec  7.75 MBytes  65.0 Mbits/sec
+[  5]   5.00-6.00   sec  8.00 MBytes  67.1 Mbits/sec
+[  5]   6.00-7.00   sec  8.00 MBytes  67.1 Mbits/sec
+[  5]   7.00-8.00   sec  7.75 MBytes  65.0 Mbits/sec
+[  5]   8.00-9.00   sec  7.88 MBytes  66.1 Mbits/sec
+[  5]   9.00-10.00  sec  7.88 MBytes  66.1 Mbits/sec
+- - - - - - - - - - - - - - - - - - - - - - - - -
+[ ID] Interval           Transfer     Bitrate         Retr
+[  5]   0.00-10.02  sec   102 MBytes  85.1 Mbits/sec  224             sender
+[  5]   0.00-10.00  sec  98.6 MBytes  82.7 Mbits/sec                  receiver
+
+Don't set BIT_EN_PRE_CALC. Then the speed is much better:
+
+% iperf3 -c 192.168.0.1 -R
+Connecting to host 192.168.0.1, port 5201
+Reverse mode, remote host 192.168.0.1 is sending
+[  5] local 192.168.0.50 port 39000 connected to 192.168.0.1 port 5201
+[ ID] Interval           Transfer     Bitrate
+[  5]   0.00-1.00   sec  52.8 MBytes   442 Mbits/sec
+[  5]   1.00-2.00   sec  71.9 MBytes   603 Mbits/sec
+[  5]   2.00-3.00   sec  74.8 MBytes   627 Mbits/sec
+[  5]   3.00-4.00   sec  75.9 MBytes   636 Mbits/sec
+[  5]   4.00-5.00   sec  76.0 MBytes   638 Mbits/sec
+[  5]   5.00-6.00   sec  74.1 MBytes   622 Mbits/sec
+[  5]   6.00-7.00   sec  74.0 MBytes   621 Mbits/sec
+[  5]   7.00-8.00   sec  76.0 MBytes   638 Mbits/sec
+[  5]   8.00-9.00   sec  74.4 MBytes   624 Mbits/sec
+[  5]   9.00-10.00  sec  63.9 MBytes   536 Mbits/sec
+- - - - - - - - - - - - - - - - - - - - - - - - -
+[ ID] Interval           Transfer     Bitrate         Retr
+[  5]   0.00-10.00  sec   717 MBytes   601 Mbits/sec   24             sender
+[  5]   0.00-10.00  sec   714 MBytes   599 Mbits/sec                  receiver
+
+Fixes: 002a5db9a52a ("wifi: rtw88: Enable USB RX aggregation for 8822c/8822b/8821c")
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Acked-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://patch.msgid.link/afb94a82-3d18-459e-97fc-1a217608cdf0@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/usb.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/usb.c
++++ b/drivers/net/wireless/realtek/rtw88/usb.c
+@@ -771,7 +771,6 @@ static void rtw_usb_dynamic_rx_agg_v1(st
+       u8 size, timeout;
+       u16 val16;
+-      rtw_write32_set(rtwdev, REG_RXDMA_AGG_PG_TH, BIT_EN_PRE_CALC);
+       rtw_write8_set(rtwdev, REG_TXDMA_PQ_MAP, BIT_RXDMA_AGG_EN);
+       rtw_write8_clr(rtwdev, REG_RXDMA_AGG_PG_TH + 3, BIT(7));
diff --git a/package/kernel/mac80211/patches/rtl/022-v6.13-wifi-rtw88-Refactor-looping-in-rtw_phy_store_tx_powe.patch b/package/kernel/mac80211/patches/rtl/022-v6.13-wifi-rtw88-Refactor-looping-in-rtw_phy_store_tx_powe.patch
new file mode 100644 (file)
index 0000000..4f01961
--- /dev/null
@@ -0,0 +1,34 @@
+From 7846f0b63562f4db45f712cc7dab091985baf07b Mon Sep 17 00:00:00 2001
+From: Mohammed Anees <pvmohammedanees2003@gmail.com>
+Date: Thu, 17 Oct 2024 13:36:38 +0530
+Subject: [PATCH] wifi: rtw88: Refactor looping in
+ rtw_phy_store_tx_power_by_rate
+
+The previous implementation included an unnecessary else
+condition paired with a continue statement. Since a check
+is already performed to determine if the band is either
+2G or 5G, the else condition will never be triggered.
+We can remove this check.
+
+Signed-off-by: Mohammed Anees <pvmohammedanees2003@gmail.com>
+Acked-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/20241017080638.13074-1-pvmohammedanees2003@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/phy.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/phy.c
++++ b/drivers/net/wireless/realtek/rtw88/phy.c
+@@ -1470,10 +1470,8 @@ static void rtw_phy_store_tx_power_by_ra
+               rate = rates[i];
+               if (band == PHY_BAND_2G)
+                       hal->tx_pwr_by_rate_offset_2g[rfpath][rate] = offset;
+-              else if (band == PHY_BAND_5G)
+-                      hal->tx_pwr_by_rate_offset_5g[rfpath][rate] = offset;
+               else
+-                      continue;
++                      hal->tx_pwr_by_rate_offset_5g[rfpath][rate] = offset;
+       }
+ }
diff --git a/package/kernel/mac80211/patches/rtl/023-v6.13-wifi-rtw88-Report-the-signal-strength-only-if-it-s-k.patch b/package/kernel/mac80211/patches/rtl/023-v6.13-wifi-rtw88-Report-the-signal-strength-only-if-it-s-k.patch
new file mode 100644 (file)
index 0000000..accbf2b
--- /dev/null
@@ -0,0 +1,39 @@
+From 47f754b3f838205f3b25c4839f74801d180995bf Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Tue, 22 Oct 2024 20:20:26 +0300
+Subject: [PATCH] wifi: rtw88: Report the signal strength only if it's known
+
+RTL8811CU doesn't report the signal strength for many (any?) data
+frames. When the signal strength is not known, set
+RX_FLAG_NO_SIGNAL_VAL in order to avoid reporting a signal
+strength of 0.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Acked-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/f7e1e448-2c9b-498f-b8b1-a14dd967d7d3@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/rx.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/rx.c
++++ b/drivers/net/wireless/realtek/rtw88/rx.c
+@@ -234,10 +234,14 @@ static void rtw_rx_fill_rx_status(struct
+       else
+               rx_status->bw = RATE_INFO_BW_20;
+-      rx_status->signal = pkt_stat->signal_power;
+-      for (path = 0; path < rtwdev->hal.rf_path_num; path++) {
+-              rx_status->chains |= BIT(path);
+-              rx_status->chain_signal[path] = pkt_stat->rx_power[path];
++      if (pkt_stat->phy_status) {
++              rx_status->signal = pkt_stat->signal_power;
++              for (path = 0; path < rtwdev->hal.rf_path_num; path++) {
++                      rx_status->chains |= BIT(path);
++                      rx_status->chain_signal[path] = pkt_stat->rx_power[path];
++              }
++      } else {
++              rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
+       }
+       rtw_rx_addr_match(rtwdev, pkt_stat, hdr);
diff --git a/package/kernel/mac80211/patches/rtl/024-v6.13-wifi-rtw88-Add-some-definitions-for-RTL8821AU-RTL881.patch b/package/kernel/mac80211/patches/rtl/024-v6.13-wifi-rtw88-Add-some-definitions-for-RTL8821AU-RTL881.patch
new file mode 100644 (file)
index 0000000..bf3d2fe
--- /dev/null
@@ -0,0 +1,490 @@
+From d12722830ea4f562e91586927ec21b64d0369544 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 23 Oct 2024 17:00:59 +0300
+Subject: [PATCH] wifi: rtw88: Add some definitions for RTL8821AU/RTL8812AU
+
+Add 8821A and 8812A chip type enums.
+
+Add cck_high_power member to struct rtw_hal. This will be used to
+calculate the RX signal strength of RTL8812AU.
+
+Add various register definitions which will be used by the new drivers.
+
+Move some existing register definitions from rtw8821c.h and rtw8822b.h.
+They were duplicated in those headers and will also be used by the new
+drivers.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/9279a9cd-6f86-4dc3-a095-7c36cb9b9d06@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/main.h     |   3 +
+ drivers/net/wireless/realtek/rtw88/reg.h      | 174 ++++++++++++++++++
+ drivers/net/wireless/realtek/rtw88/rtw8821c.h |  24 ---
+ drivers/net/wireless/realtek/rtw88/rtw8822b.h |  12 --
+ 4 files changed, 177 insertions(+), 36 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/main.h
++++ b/drivers/net/wireless/realtek/rtw88/main.h
+@@ -189,6 +189,8 @@ enum rtw_chip_type {
+       RTW_CHIP_TYPE_8723D,
+       RTW_CHIP_TYPE_8821C,
+       RTW_CHIP_TYPE_8703B,
++      RTW_CHIP_TYPE_8821A,
++      RTW_CHIP_TYPE_8812A,
+ };
+ enum rtw_tx_queue_type {
+@@ -1934,6 +1936,7 @@ struct rtw_hal {
+       u32 antenna_rx;
+       u8 bfee_sts_cap;
+       bool txrx_1ss;
++      bool cck_high_power;
+       /* protect tx power section */
+       struct mutex tx_power_mutex;
+--- a/drivers/net/wireless/realtek/rtw88/reg.h
++++ b/drivers/net/wireless/realtek/rtw88/reg.h
+@@ -9,6 +9,7 @@
+ #define BIT_FEN_EN_25_1               BIT(13)
+ #define BIT_FEN_ELDR          BIT(12)
+ #define BIT_FEN_CPUEN         BIT(2)
++#define BIT_FEN_USBA          BIT(2)
+ #define BIT_FEN_BB_GLB_RST    BIT(1)
+ #define BIT_FEN_BB_RSTB               BIT(0)
+ #define BIT_R_DIS_PRST                BIT(6)
+@@ -16,6 +17,10 @@
+ #define REG_SYS_PW_CTRL               0x0004
+ #define BIT_PFM_WOWL          BIT(3)
+ #define BIT_APFM_OFFMAC               BIT(9)
++#define REG_APS_FSMCO         0x0004
++#define APS_FSMCO_MAC_ENABLE  BIT(8)
++#define APS_FSMCO_MAC_OFF     BIT(9)
++#define APS_FSMCO_HW_POWERDOWN        BIT(15)
+ #define REG_SYS_CLK_CTRL      0x0008
+ #define BIT_CPU_CLK_EN                BIT(14)
+@@ -58,6 +63,8 @@
+ #define BIT_SHIFT_LDO25_VOLTAGE       4
+ #define BIT_LDO25_EN          BIT(7)
++#define REG_ACLK_MON          0x3e
++
+ #define REG_GPIO_MUXCFG               0x0040
+ #define BIT_FSPI_EN           BIT(19)
+ #define BIT_EN_SIC            BIT(12)
+@@ -90,6 +97,8 @@
+ #define BIT_USB_SUS_DIS               BIT(8)
+ #define BIT_SDIO_PAD_E5               BIT(18)
++#define REG_RF_B_CTRL         0x76
++
+ #define REG_AFE_CTRL_4                0x0078
+ #define BIT_CK320M_AFE_EN     BIT(4)
+ #define BIT_EN_SYN            BIT(15)
+@@ -134,6 +143,11 @@
+ #define REG_PMC_DBG_CTRL1     0xa8
+ #define BITS_PMC_BT_IQK_STS   GENMASK(22, 21)
++#define REG_HIMR0             0xb0
++#define REG_HISR0             0xb4
++#define REG_HIMR1             0xb8
++#define REG_HISR1             0xbc
++
+ #define REG_PAD_CTRL2         0x00C4
+ #define BIT_RSM_EN_V1         BIT(16)
+ #define BIT_NO_PDN_CHIPOFF_V1 BIT(17)
+@@ -185,6 +199,15 @@
+ #define MAC_TRX_ENABLE        (BIT_HCI_TXDMA_EN | BIT_HCI_RXDMA_EN | BIT_TXDMA_EN | \
+                       BIT_RXDMA_EN | BIT_PROTOCOL_EN | BIT_SCHEDULE_EN | \
+                       BIT_MACTXEN | BIT_MACRXEN)
++#define REG_PBP                       0x104
++#define PBP_RX_MASK           0x0f
++#define PBP_TX_MASK           0xf0
++#define PBP_64                        0x0
++#define PBP_128                       0x1
++#define PBP_256                       0x2
++#define PBP_512                       0x3
++#define PBP_1024              0x4
++
+ #define BIT_SHIFT_TXDMA_VOQ_MAP       4
+ #define BIT_MASK_TXDMA_VOQ_MAP        0x3
+ #define BIT_TXDMA_VOQ_MAP(x)                                                   \
+@@ -256,6 +279,8 @@
+ #define REG_HMEBOX1           0x01D4
+ #define REG_HMEBOX2           0x01D8
+ #define REG_HMEBOX3           0x01DC
++#define REG_LLT_INIT          0x01E0
++#define BIT_LLT_WRITE_ACCESS  BIT(30)
+ #define REG_HMEBOX0_EX                0x01F0
+ #define REG_HMEBOX1_EX                0x01F4
+ #define REG_HMEBOX2_EX                0x01F8
+@@ -298,6 +323,7 @@
+ #define REG_AUTO_LLT          0x0224
+ #define BIT_AUTO_INIT_LLT     BIT(16)
++#define REG_DWBCN1_CTRL               0x0228
+ #define REG_RQPN_CTRL_1               0x0228
+ #define REG_RQPN_CTRL_2               0x022C
+ #define BIT_LD_RQPN           BIT(31)
+@@ -329,6 +355,7 @@
+ #define BIT_DMA_BURST_SIZE_1024       0
+ #define REG_RXPKTNUM          0x02B0
++#define REG_EARLY_MODE_CONTROL        0x02BC
+ #define REG_INT_MIG           0x0304
+ #define REG_HCI_MIX_CFG               0x03FC
+@@ -336,6 +363,7 @@
+ #define REG_BCNQ_INFO         0x0418
+ #define BIT_MGQ_CPU_EMPTY     BIT(24)
++#define REG_TXPKT_EMPTY               0x041A
+ #define REG_FWHW_TXQ_CTRL     0x0420
+ #define BIT_EN_BCNQ_DL                BIT(22)
+ #define BIT_EN_WR_FREE_TAIL   BIT(20)
+@@ -362,10 +390,12 @@
+ #define REG_AMPDU_MAX_TIME_V1 0x0455
+ #define REG_BCNQ1_BDNY_V1     0x0456
+ #define REG_AMPDU_MAX_TIME    0x0456
++#define REG_AMPDU_MAX_LENGTH  0x0458
+ #define REG_WMAC_LBK_BF_HD    0x045D
+ #define REG_TX_HANG_CTRL      0x045E
+ #define BIT_EN_GNT_BT_AWAKE   BIT(3)
+ #define BIT_EN_EOF_V1         BIT(2)
++#define REG_FAST_EDCA_CTRL    0x0460
+ #define REG_DATA_SC           0x0483
+ #define REG_ARFR2_V1          0x048C
+ #define REG_ARFRH2_V1         0x0490
+@@ -390,6 +420,8 @@
+ #define REG_PRECNT_CTRL               0x04E5
+ #define BIT_BTCCA_CTRL                (BIT(0) | BIT(1))
+ #define BIT_EN_PRECNT         BIT(11)
++#define REG_TX_RPT_CTRL               0x04EC
++#define REG_TX_RPT_TIME               0x04F0
+ #define REG_DUMMY_PAGE4_V1    0x04FC
+ #define REG_EDCA_VO_PARAM     0x0500
+@@ -400,6 +432,7 @@
+ #define BIT_MASK_CWMAX                GENMASK(15, 12)
+ #define BIT_MASK_CWMIN                GENMASK(11, 8)
+ #define BIT_MASK_AIFS         GENMASK(7, 0)
++#define REG_BCNTCFG           0x0510
+ #define REG_PIFS              0x0512
+ #define REG_SIFS              0x0514
+ #define BIT_SHIFT_SIFS_OFDM_CTX       8
+@@ -526,6 +559,8 @@
+ #define REG_BT_COEX_V2                0x0762
+ #define BIT_GNT_BT_POLARITY   BIT(12)
+ #define BIT_LTE_COEX_EN               BIT(7)
++#define REG_GNT_BT            0x0765
++#define BIT_PTA_SW_CTL                GENMASK(4, 3)
+ #define REG_BT_COEX_ENH_INTR_CTRL     0x76E
+ #define BIT_R_GRANTALL_WLMASK BIT(3)
+ #define BIT_STATIS_BT_EN      BIT(2)
+@@ -543,14 +578,43 @@
+ #define REG_FPGA0_RFMOD               0x0800
+ #define BIT_CCKEN             BIT(24)
+ #define BIT_OFDMEN            BIT(25)
++#define REG_CCK_RPT_FORMAT    0x0804
++#define BIT_CCK_RPT_FORMAT    BIT(16)
++#define REG_RXPSEL            0x0808
++#define BIT_RX_PSEL_RST               (BIT(28) | BIT(29))
++#define REG_TXPSEL            0x080C
+ #define REG_RX_GAIN_EN                0x081c
++#define REG_CCASEL            0x082C
++#define REG_PDMFTH            0x0830
++#define REG_BWINDICATION      0x0834
++#define REG_CCA2ND            0x0838
++#define REG_L1PKTH            0x0848
++#define REG_CLKTRK            0x0860
++#define REG_ADCCLK            0x08AC
++#define REG_HSSI_READ         0x08B0
++#define REG_FPGA0_XCD_RF_PARA 0x08B4
++#define REG_RX_MCS_LIMIT      0x08BC
++#define REG_ADC160            0x08C4
++#define REG_ANTSEL_SW         0x0900
++#define REG_DAC_RSTB          0x090c
++#define REG_SINGLE_TONE_CONT_TX       0x0914
+ #define REG_RFE_CTRL_E                0x0974
+ #define REG_2ND_CCA_CTRL      0x0976
++#define REG_IQK_COM00         0x0978
++#define REG_IQK_COM32         0x097c
++#define REG_IQK_COM64         0x0980
++#define REG_IQK_COM96         0x0984
++
++#define REG_FAS                       0x09a4
++#define REG_RXSB              0x0a00
++#define REG_CCK_RX            0x0a04
++#define REG_CCK_PD_TH         0x0a0a
+ #define REG_CCK0_FAREPORT     0xa2c
+ #define BIT_CCK0_2RX          BIT(18)
+ #define BIT_CCK0_MRC          BIT(22)
++#define REG_FA_CCK            0x0a5c
+ #define REG_DIS_DPD           0x0a70
+ #define DIS_DPD_MASK          GENMASK(9, 0)
+@@ -566,13 +630,109 @@
+ #define DIS_DPD_RATEVHT2SS_MCS1       BIT(9)
+ #define DIS_DPD_RATEALL               GENMASK(9, 0)
++#define REG_CNTRST            0x0b58
++
++#define REG_3WIRE_SWA         0x0c00
++#define REG_RX_IQC_AB_A               0x0c10
++#define REG_TXSCALE_A         0x0c1c
++#define BB_SWING_MASK         GENMASK(31, 21)
++#define REG_TX_AGC_A_CCK_11_CCK_1             0xc20
++#define REG_TX_AGC_A_OFDM18_OFDM6             0xc24
++#define REG_TX_AGC_A_OFDM54_OFDM24            0xc28
++#define REG_TX_AGC_A_MCS3_MCS0                        0xc2c
++#define REG_TX_AGC_A_MCS7_MCS4                        0xc30
++#define REG_TX_AGC_A_MCS11_MCS8                       0xc34
++#define REG_TX_AGC_A_MCS15_MCS12              0xc38
++#define REG_TX_AGC_A_NSS1_INDEX3_NSS1_INDEX0  0xc3c
++#define REG_TX_AGC_A_NSS1_INDEX7_NSS1_INDEX4  0xc40
++#define REG_TX_AGC_A_NSS2_INDEX1_NSS1_INDEX8  0xc44
++#define REG_TX_AGC_A_NSS2_INDEX5_NSS2_INDEX2  0xc48
++#define REG_TX_AGC_A_NSS2_INDEX9_NSS2_INDEX6  0xc4c
++#define REG_RXIGI_A           0x0c50
++#define REG_TX_PWR_TRAINING_A 0x0c54
++#define REG_CK_MONHA          0x0c5c
++#define REG_AFE_PWR1_A                0x0c60
++#define REG_AFE_PWR2_A                0x0c64
++#define REG_RX_WAIT_CCA_TX_CCK_RFON_A 0x0c68
++#define REG_OFDM0_XA_TX_IQ_IMBALANCE  0x0c80
++#define REG_OFDM0_A_TX_AFE    0x0c84
++#define REG_OFDM0_XB_TX_IQ_IMBALANCE  0x0c88
++#define REG_TSSI_TRK_SW               0x0c8c
++#define REG_LSSI_WRITE_A      0x0c90
++#define REG_PREDISTA          0x0c90
++#define REG_TXAGCIDX          0x0c94
++
++#define REG_RFE_PINMUX_A      0x0cb0
++#define REG_RFE_INV_A         0x0cb4
+ #define REG_RFE_CTRL8         0x0cb4
+ #define BIT_MASK_RFE_SEL89    GENMASK(7, 0)
++#define PTA_CTRL_PIN          0x66
++#define DPDT_CTRL_PIN         0x77
++#define RFE_INV_MASK          0x3ff00000
++#define REG_RFECTL_A          0x0cb8
+ #define REG_RFE_INV8          0x0cbd
+ #define BIT_MASK_RFE_INV89    GENMASK(1, 0)
+ #define REG_RFE_INV16         0x0cbe
+ #define BIT_RFE_BUF_EN                BIT(3)
++#define REG_IQK_DPD_CFG               0x0cc4
++#define REG_CFG_PMPD          0x0cc8
++#define REG_IQC_Y             0x0ccc
++#define REG_IQC_X             0x0cd4
++#define REG_INTPO_SETA                0x0ce8
++
++#define REG_IQKA_END          0x0d00
++#define REG_PI_READ_A         0x0d04
++#define REG_SI_READ_A         0x0d08
++#define REG_IQKB_END          0x0d40
++#define REG_PI_READ_B         0x0d44
++#define REG_SI_READ_B         0x0d48
++
++#define REG_3WIRE_SWB         0x0e00
++#define REG_RX_IQC_AB_B               0x0e10
++#define REG_TXSCALE_B         0x0e1c
++#define REG_TX_AGC_B_CCK_11_CCK_1             0xe20
++#define REG_TX_AGC_B_OFDM18_OFDM6             0xe24
++#define REG_TX_AGC_B_OFDM54_OFDM24            0xe28
++#define REG_TX_AGC_B_MCS3_MCS0                        0xe2c
++#define REG_TX_AGC_B_MCS7_MCS4                        0xe30
++#define REG_TX_AGC_B_MCS11_MCS8                       0xe34
++#define REG_TX_AGC_B_MCS15_MCS12              0xe38
++#define REG_TX_AGC_B_NSS1_INDEX3_NSS1_INDEX0  0xe3c
++#define REG_TX_AGC_B_NSS1_INDEX7_NSS1_INDEX4  0xe40
++#define REG_TX_AGC_B_NSS2_INDEX1_NSS1_INDEX8  0xe44
++#define REG_TX_AGC_B_NSS2_INDEX5_NSS2_INDEX2  0xe48
++#define REG_TX_AGC_B_NSS2_INDEX9_NSS2_INDEX6  0xe4c
++#define REG_RXIGI_B           0x0e50
++#define REG_TX_PWR_TRAINING_B 0x0e54
++#define REG_CK_MONHB          0x0e5c
++#define REG_AFE_PWR1_B                0x0e60
++#define REG_AFE_PWR2_B                0x0e64
++#define REG_RX_WAIT_CCA_TX_CCK_RFON_B 0x0e68
++#define REG_TXTONEB           0x0e80
++#define REG_RXTONEB           0x0e84
++#define REG_TXPITMB           0x0e88
++#define REG_RXPITMB           0x0e8c
++#define REG_LSSI_WRITE_B      0x0e90
++#define REG_PREDISTB          0x0e90
++#define REG_INIDLYB           0x0e94
++#define REG_RFE_PINMUX_B      0x0eb0
++#define REG_RFE_INV_B         0x0eb4
++#define REG_RFECTL_B          0x0eb8
++#define REG_BPBDB             0x0ec4
++#define REG_PHYTXONB          0x0ec8
++#define REG_IQKYB             0x0ecc
++#define REG_IQKXB             0x0ed4
++#define REG_INTPO_SETB                0x0ee8
++
++#define REG_CRC_CCK           0x0f04
++#define REG_CCA_OFDM          0x0f08
++#define REG_CRC_VHT           0x0f0c
++#define REG_CRC_HT            0x0f10
++#define REG_CRC_OFDM          0x0f14
++#define REG_FA_OFDM           0x0f48
++#define REG_CCA_CCK           0x0fcc
++
+ #define REG_ANAPARSW_MAC_0    0x1010
+ #define BIT_CF_L_V2           GENMASK(29, 28)
+@@ -709,6 +869,10 @@
+ #define REG_IGN_GNTBT4        0x4160
++#define REG_USB_MOD   0xf008
++#define REG_USB3_RXITV        0xf050
++#define REG_USB_HRPWM 0xfe58
++
+ #define RF_MODE               0x00
+ #define RF_MODOPT     0x01
+ #define RF_WLINT      0x01
+@@ -716,7 +880,13 @@
+ #define RF_DTXLOK     0x08
+ #define RF_CFGCH      0x18
+ #define BIT_BAND      GENMASK(18, 16)
++#define RF18_BAND_MASK        (BIT(16) | BIT(9) | BIT(8))
++#define RF18_CHANNEL_MASK     (MASKBYTE0)
++#define RF18_RFSI_MASK        (BIT(18) | BIT(17))
+ #define RF_RCK                0x1d
++#define RF_MODE_TABLE_ADDR    0x30
++#define RF_MODE_TABLE_DATA0   0x31
++#define RF_MODE_TABLE_DATA1   0x32
+ #define RF_LUTWA      0x33
+ #define RF_LUTWD1     0x3e
+ #define RF_LUTWD0     0x3f
+@@ -725,10 +895,14 @@
+ #define RF_T_METER    0x42
+ #define RF_BSPAD      0x54
+ #define RF_GAINTX     0x56
++#define RF_TXMOD      0x58
+ #define RF_TXATANK    0x64
++#define RF_TXA_PREPAD 0x65
+ #define RF_TRXIQ      0x66
+ #define RF_RXIQGEN    0x8d
++#define RF_RXBB2      0x8f
+ #define RF_SYN_PFD    0xb0
++#define RF_LCK                0xb4
+ #define RF_XTALX2     0xb8
+ #define RF_SYN_CTRL   0xbb
+ #define RF_MALSEL     0xbe
+--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.h
++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.h
+@@ -214,19 +214,10 @@ extern const struct rtw_chip_info rtw882
+ #define BIT_FEN_EN    BIT(26)
+ #define REG_INIRTS_RATE_SEL 0x0480
+ #define REG_HTSTFWT   0x800
+-#define REG_RXPSEL    0x808
+-#define BIT_RX_PSEL_RST               (BIT(28) | BIT(29))
+-#define REG_TXPSEL    0x80c
+ #define REG_RXCCAMSK  0x814
+-#define REG_CCASEL    0x82c
+-#define REG_PDMFTH    0x830
+-#define REG_CCA2ND    0x838
+ #define REG_L1WT      0x83c
+ #define REG_L1PKWT    0x840
+ #define REG_MRC               0x850
+-#define REG_CLKTRK    0x860
+-#define REG_ADCCLK    0x8ac
+-#define REG_ADC160    0x8c4
+ #define REG_ADC40     0x8c8
+ #define REG_CHFIR     0x8f0
+ #define REG_CDDTXP    0x93c
+@@ -234,14 +225,11 @@ extern const struct rtw_chip_info rtw882
+ #define REG_ACBB0     0x948
+ #define REG_ACBBRXFIR 0x94c
+ #define REG_ACGG2TBL  0x958
+-#define REG_FAS               0x9a4
+-#define REG_RXSB      0xa00
+ #define REG_ADCINI    0xa04
+ #define REG_PWRTH     0xa08
+ #define REG_CCA_FLTR  0xa20
+ #define REG_TXSF2     0xa24
+ #define REG_TXSF6     0xa28
+-#define REG_FA_CCK    0xa5c
+ #define REG_RXDESC    0xa2c
+ #define REG_ENTXCCK   0xa80
+ #define BTG_LNA               0xfc84
+@@ -252,12 +240,8 @@ extern const struct rtw_chip_info rtw882
+ #define REG_PWRTH2    0xaa8
+ #define REG_CSRATIO   0xaaa
+ #define REG_TXFILTER  0xaac
+-#define REG_CNTRST    0xb58
+ #define REG_AGCTR_A   0xc08
+-#define REG_TXSCALE_A 0xc1c
+ #define REG_TXDFIR    0xc20
+-#define REG_RXIGI_A   0xc50
+-#define REG_TXAGCIDX  0xc94
+ #define REG_TRSW      0xca0
+ #define REG_RFESEL0   0xcb0
+ #define REG_RFESEL8   0xcb4
+@@ -269,14 +253,6 @@ extern const struct rtw_chip_info rtw882
+ #define B_WLA_SWITCH  BIT(23)
+ #define REG_RFEINV    0xcbc
+ #define REG_AGCTR_B   0xe08
+-#define REG_RXIGI_B   0xe50
+-#define REG_CRC_CCK   0xf04
+-#define REG_CRC_OFDM  0xf14
+-#define REG_CRC_HT    0xf10
+-#define REG_CRC_VHT   0xf0c
+-#define REG_CCA_OFDM  0xf08
+-#define REG_FA_OFDM   0xf48
+-#define REG_CCA_CCK   0xfcc
+ #define REG_DMEM_CTRL 0x1080
+ #define BIT_WL_RST    BIT(16)
+ #define REG_ANTWT     0x1904
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.h
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.h
+@@ -151,21 +151,12 @@ _rtw_write32s_mask(struct rtw_dev *rtwde
+ #define RTW8822B_EDCCA_MAX    0x7f
+ #define RTW8822B_EDCCA_SRC_DEF        1
+ #define REG_HTSTFWT   0x800
+-#define REG_RXPSEL    0x808
+-#define BIT_RX_PSEL_RST               (BIT(28) | BIT(29))
+-#define REG_TXPSEL    0x80c
+ #define REG_RXCCAMSK  0x814
+-#define REG_CCASEL    0x82c
+-#define REG_PDMFTH    0x830
+-#define REG_CCA2ND    0x838
+ #define REG_L1WT      0x83c
+ #define REG_L1PKWT    0x840
+ #define REG_MRC               0x850
+-#define REG_CLKTRK    0x860
+ #define REG_EDCCA_POW_MA      0x8a0
+ #define BIT_MA_LEVEL  GENMASK(1, 0)
+-#define REG_ADCCLK    0x8ac
+-#define REG_ADC160    0x8c4
+ #define REG_ADC40     0x8c8
+ #define REG_EDCCA_DECISION    0x8dc
+ #define BIT_EDCCA_OPTION      BIT(5)
+@@ -176,7 +167,6 @@ _rtw_write32s_mask(struct rtw_dev *rtwde
+ #define REG_ACBB0     0x948
+ #define REG_ACBBRXFIR 0x94c
+ #define REG_ACGG2TBL  0x958
+-#define REG_RXSB      0xa00
+ #define REG_ADCINI    0xa04
+ #define REG_TXSF2     0xa24
+ #define REG_TXSF6     0xa28
+@@ -184,14 +174,12 @@ _rtw_write32s_mask(struct rtw_dev *rtwde
+ #define REG_ENTXCCK   0xa80
+ #define REG_AGCTR_A   0xc08
+ #define REG_TXDFIR    0xc20
+-#define REG_RXIGI_A   0xc50
+ #define REG_TRSW      0xca0
+ #define REG_RFESEL0   0xcb0
+ #define REG_RFESEL8   0xcb4
+ #define REG_RFECTL    0xcb8
+ #define REG_RFEINV    0xcbc
+ #define REG_AGCTR_B   0xe08
+-#define REG_RXIGI_B   0xe50
+ #define REG_ANTWT     0x1904
+ #define REG_IQKFAILMSK        0x1bf0
diff --git a/package/kernel/mac80211/patches/rtl/025-v6.13-wifi-rtw88-Dump-the-HW-features-only-for-some-chips.patch b/package/kernel/mac80211/patches/rtl/025-v6.13-wifi-rtw88-Dump-the-HW-features-only-for-some-chips.patch
new file mode 100644 (file)
index 0000000..279e8ba
--- /dev/null
@@ -0,0 +1,93 @@
+From 87341ca1eac9a3bac23bd41f6e24f3c93b77452f Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 23 Oct 2024 17:02:05 +0300
+Subject: [PATCH] wifi: rtw88: Dump the HW features only for some chips
+
+RTL8821AU and RTL8812AU don't support this. They hit the "failed to read
+hw feature report" error.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/8becd851-8760-4480-8e8c-c4869ce72507@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/main.c     | 3 +++
+ drivers/net/wireless/realtek/rtw88/main.h     | 1 +
+ drivers/net/wireless/realtek/rtw88/rtw8703b.c | 1 +
+ drivers/net/wireless/realtek/rtw88/rtw8723d.c | 1 +
+ drivers/net/wireless/realtek/rtw88/rtw8821c.c | 1 +
+ drivers/net/wireless/realtek/rtw88/rtw8822b.c | 1 +
+ drivers/net/wireless/realtek/rtw88/rtw8822c.c | 1 +
+ 7 files changed, 9 insertions(+)
+
+--- a/drivers/net/wireless/realtek/rtw88/main.c
++++ b/drivers/net/wireless/realtek/rtw88/main.c
+@@ -1917,6 +1917,9 @@ static int rtw_dump_hw_feature(struct rt
+       u8 bw;
+       int i;
++      if (!rtwdev->chip->hw_feature_report)
++              return 0;
++
+       id = rtw_read8(rtwdev, REG_C2HEVT);
+       if (id != C2H_HW_FEATURE_REPORT) {
+               rtw_err(rtwdev, "failed to read hw feature report\n");
+--- a/drivers/net/wireless/realtek/rtw88/main.h
++++ b/drivers/net/wireless/realtek/rtw88/main.h
+@@ -1200,6 +1200,7 @@ struct rtw_chip_info {
+       const struct rtw_fwcd_segs *fwcd_segs;
+       u8 usb_tx_agg_desc_num;
++      bool hw_feature_report;
+       u8 default_1ss_tx_path;
+--- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c
+@@ -1960,6 +1960,7 @@ const struct rtw_chip_info rtw8703b_hw_s
+       .max_power_index = 0x3f,
+       .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
+       .usb_tx_agg_desc_num = 1, /* Not sure if this chip has USB interface */
++      .hw_feature_report = true,
+       .path_div_supported = false,
+       .ht_supported = true,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+@@ -2131,6 +2131,7 @@ const struct rtw_chip_info rtw8723d_hw_s
+       .page_size = TX_PAGE_SIZE,
+       .dig_min = 0x20,
+       .usb_tx_agg_desc_num = 1,
++      .hw_feature_report = true,
+       .ht_supported = true,
+       .vht_supported = false,
+       .lps_deep_mode_supported = 0,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
+@@ -1968,6 +1968,7 @@ const struct rtw_chip_info rtw8821c_hw_s
+       .page_size = TX_PAGE_SIZE,
+       .dig_min = 0x1c,
+       .usb_tx_agg_desc_num = 3,
++      .hw_feature_report = true,
+       .ht_supported = true,
+       .vht_supported = true,
+       .lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK),
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+@@ -2509,6 +2509,7 @@ const struct rtw_chip_info rtw8822b_hw_s
+       .page_size = TX_PAGE_SIZE,
+       .dig_min = 0x1c,
+       .usb_tx_agg_desc_num = 3,
++      .hw_feature_report = true,
+       .ht_supported = true,
+       .vht_supported = true,
+       .lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK),
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+@@ -5329,6 +5329,7 @@ const struct rtw_chip_info rtw8822c_hw_s
+       .page_size = TX_PAGE_SIZE,
+       .dig_min = 0x20,
+       .usb_tx_agg_desc_num = 3,
++      .hw_feature_report = true,
+       .default_1ss_tx_path = BB_PATH_A,
+       .path_div_supported = true,
+       .ht_supported = true,
diff --git a/package/kernel/mac80211/patches/rtl/026-v6.13-wifi-rtw88-Allow-different-C2H-RA-report-sizes.patch b/package/kernel/mac80211/patches/rtl/026-v6.13-wifi-rtw88-Allow-different-C2H-RA-report-sizes.patch
new file mode 100644 (file)
index 0000000..0e97feb
--- /dev/null
@@ -0,0 +1,175 @@
+From d9018f4373517d4560ce2ebf12684f77f5fbdad6 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 23 Oct 2024 17:06:14 +0300
+Subject: [PATCH] wifi: rtw88: Allow different C2H RA report sizes
+
+The RTL8821AU and RTL8812AU have smaller RA report size, only 4 bytes.
+Avoid the "invalid ra report c2h length" error.
+
+Also, use a struct and u8_get_bits() to access the RA report C2H.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/c3e73c3a-fb2f-4013-9f06-d5274211e282@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/fw.c       | 21 +++++++++++++------
+ drivers/net/wireless/realtek/rtw88/fw.h       | 17 +++++++++++----
+ drivers/net/wireless/realtek/rtw88/main.h     |  1 +
+ drivers/net/wireless/realtek/rtw88/rtw8703b.c |  1 +
+ drivers/net/wireless/realtek/rtw88/rtw8723d.c |  1 +
+ drivers/net/wireless/realtek/rtw88/rtw8821c.c |  1 +
+ drivers/net/wireless/realtek/rtw88/rtw8822b.c |  1 +
+ drivers/net/wireless/realtek/rtw88/rtw8822c.c |  1 +
+ 8 files changed, 34 insertions(+), 10 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/fw.c
++++ b/drivers/net/wireless/realtek/rtw88/fw.c
+@@ -139,25 +139,30 @@ static u16 get_max_amsdu_len(u32 bit_rat
+ struct rtw_fw_iter_ra_data {
+       struct rtw_dev *rtwdev;
+       u8 *payload;
++      u8 length;
+ };
+ static void rtw_fw_ra_report_iter(void *data, struct ieee80211_sta *sta)
+ {
+       struct rtw_fw_iter_ra_data *ra_data = data;
++      struct rtw_c2h_ra_rpt *ra_rpt = (struct rtw_c2h_ra_rpt *)ra_data->payload;
+       struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
+       u8 mac_id, rate, sgi, bw;
+       u8 mcs, nss;
+       u32 bit_rate;
+-      mac_id = GET_RA_REPORT_MACID(ra_data->payload);
++      mac_id = ra_rpt->mac_id;
+       if (si->mac_id != mac_id)
+               return;
+       si->ra_report.txrate.flags = 0;
+-      rate = GET_RA_REPORT_RATE(ra_data->payload);
+-      sgi = GET_RA_REPORT_SGI(ra_data->payload);
+-      bw = GET_RA_REPORT_BW(ra_data->payload);
++      rate = u8_get_bits(ra_rpt->rate_sgi, RTW_C2H_RA_RPT_RATE);
++      sgi = u8_get_bits(ra_rpt->rate_sgi, RTW_C2H_RA_RPT_SGI);
++      if (ra_data->length >= offsetofend(typeof(*ra_rpt), bw))
++              bw = ra_rpt->bw;
++      else
++              bw = si->bw_mode;
+       if (rate < DESC_RATEMCS0) {
+               si->ra_report.txrate.legacy = rtw_desc_to_bitrate(rate);
+@@ -197,14 +202,18 @@ legacy:
+ static void rtw_fw_ra_report_handle(struct rtw_dev *rtwdev, u8 *payload,
+                                   u8 length)
+ {
++      struct rtw_c2h_ra_rpt *ra_rpt = (struct rtw_c2h_ra_rpt *)payload;
+       struct rtw_fw_iter_ra_data ra_data;
+-      if (WARN(length < 7, "invalid ra report c2h length\n"))
++      if (WARN(length < rtwdev->chip->c2h_ra_report_size,
++               "invalid ra report c2h length %d\n", length))
+               return;
+-      rtwdev->dm_info.tx_rate = GET_RA_REPORT_RATE(payload);
++      rtwdev->dm_info.tx_rate = u8_get_bits(ra_rpt->rate_sgi,
++                                            RTW_C2H_RA_RPT_RATE);
+       ra_data.rtwdev = rtwdev;
+       ra_data.payload = payload;
++      ra_data.length = length;
+       rtw_iterate_stas_atomic(rtwdev, rtw_fw_ra_report_iter, &ra_data);
+ }
+--- a/drivers/net/wireless/realtek/rtw88/fw.h
++++ b/drivers/net/wireless/realtek/rtw88/fw.h
+@@ -85,6 +85,19 @@ struct rtw_c2h_adaptivity {
+       u8 option;
+ } __packed;
++struct rtw_c2h_ra_rpt {
++      u8 rate_sgi;
++      u8 mac_id;
++      u8 byte2;
++      u8 status;
++      u8 byte4;
++      u8 ra_ratio;
++      u8 bw;
++} __packed;
++
++#define RTW_C2H_RA_RPT_RATE   GENMASK(6, 0)
++#define RTW_C2H_RA_RPT_SGI    BIT(7)
++
+ struct rtw_h2c_register {
+       u32 w0;
+       u32 w1;
+@@ -364,10 +377,6 @@ struct rtw_fw_hdr_legacy {
+ #define GET_CHAN_SWITCH_CENTRAL_CH(c2h_payload)       (c2h_payload[2])
+ #define GET_CHAN_SWITCH_ID(c2h_payload)               (c2h_payload[3])
+ #define GET_CHAN_SWITCH_STATUS(c2h_payload)   (c2h_payload[4])
+-#define GET_RA_REPORT_RATE(c2h_payload)               (c2h_payload[0] & 0x7f)
+-#define GET_RA_REPORT_SGI(c2h_payload)                ((c2h_payload[0] & 0x80) >> 7)
+-#define GET_RA_REPORT_BW(c2h_payload)         (c2h_payload[6])
+-#define GET_RA_REPORT_MACID(c2h_payload)      (c2h_payload[1])
+ #define GET_BCN_FILTER_NOTIFY_TYPE(c2h_payload)       (c2h_payload[1] & 0xf)
+ #define GET_BCN_FILTER_NOTIFY_EVENT(c2h_payload)      (c2h_payload[1] & 0x10)
+--- a/drivers/net/wireless/realtek/rtw88/main.h
++++ b/drivers/net/wireless/realtek/rtw88/main.h
+@@ -1201,6 +1201,7 @@ struct rtw_chip_info {
+       u8 usb_tx_agg_desc_num;
+       bool hw_feature_report;
++      u8 c2h_ra_report_size;
+       u8 default_1ss_tx_path;
+--- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c
+@@ -1961,6 +1961,7 @@ const struct rtw_chip_info rtw8703b_hw_s
+       .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
+       .usb_tx_agg_desc_num = 1, /* Not sure if this chip has USB interface */
+       .hw_feature_report = true,
++      .c2h_ra_report_size = 7,
+       .path_div_supported = false,
+       .ht_supported = true,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+@@ -2132,6 +2132,7 @@ const struct rtw_chip_info rtw8723d_hw_s
+       .dig_min = 0x20,
+       .usb_tx_agg_desc_num = 1,
+       .hw_feature_report = true,
++      .c2h_ra_report_size = 7,
+       .ht_supported = true,
+       .vht_supported = false,
+       .lps_deep_mode_supported = 0,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
+@@ -1969,6 +1969,7 @@ const struct rtw_chip_info rtw8821c_hw_s
+       .dig_min = 0x1c,
+       .usb_tx_agg_desc_num = 3,
+       .hw_feature_report = true,
++      .c2h_ra_report_size = 7,
+       .ht_supported = true,
+       .vht_supported = true,
+       .lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK),
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+@@ -2510,6 +2510,7 @@ const struct rtw_chip_info rtw8822b_hw_s
+       .dig_min = 0x1c,
+       .usb_tx_agg_desc_num = 3,
+       .hw_feature_report = true,
++      .c2h_ra_report_size = 7,
+       .ht_supported = true,
+       .vht_supported = true,
+       .lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK),
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+@@ -5330,6 +5330,7 @@ const struct rtw_chip_info rtw8822c_hw_s
+       .dig_min = 0x20,
+       .usb_tx_agg_desc_num = 3,
+       .hw_feature_report = true,
++      .c2h_ra_report_size = 7,
+       .default_1ss_tx_path = BB_PATH_A,
+       .path_div_supported = true,
+       .ht_supported = true,
diff --git a/package/kernel/mac80211/patches/rtl/027-v6.13-wifi-rtw88-Extend-the-init-table-parsing-for-RTL8812.patch b/package/kernel/mac80211/patches/rtl/027-v6.13-wifi-rtw88-Extend-the-init-table-parsing-for-RTL8812.patch
new file mode 100644 (file)
index 0000000..aec2e6a
--- /dev/null
@@ -0,0 +1,165 @@
+From 95a772e30b60e7954d03f3372268722475aa303f Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 23 Oct 2024 17:08:24 +0300
+Subject: [PATCH] wifi: rtw88: Extend the init table parsing for RTL8812AU
+
+The chips supported so far only use the first condition, and so the
+parsing code ignores the second condition. RTL8812AU's init tables use
+the second condition also. Make the parsing code check it.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/1bee6b74-6eab-44a3-9f40-794ca006c72d@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/main.h | 15 ++++++
+ drivers/net/wireless/realtek/rtw88/phy.c  | 62 ++++++++++++++++++++---
+ 2 files changed, 69 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/main.h
++++ b/drivers/net/wireless/realtek/rtw88/main.h
+@@ -1835,6 +1835,20 @@ struct rtw_phy_cond {
+       #define BRANCH_ENDIF    3
+ };
++struct rtw_phy_cond2 {
++#ifdef __LITTLE_ENDIAN
++      u8 type_glna;
++      u8 type_gpa;
++      u8 type_alna;
++      u8 type_apa;
++#else
++      u8 type_apa;
++      u8 type_alna;
++      u8 type_gpa;
++      u8 type_glna;
++#endif
++};
++
+ struct rtw_fifo_conf {
+       /* tx fifo information */
+       u16 rsvd_boundary;
+@@ -1916,6 +1930,7 @@ struct rtw_hal {
+       u8 oem_id;
+       u8 pkg_type;
+       struct rtw_phy_cond phy_cond;
++      struct rtw_phy_cond2 phy_cond2;
+       bool rfe_btg;
+       u8 ps_mode;
+--- a/drivers/net/wireless/realtek/rtw88/phy.c
++++ b/drivers/net/wireless/realtek/rtw88/phy.c
+@@ -18,7 +18,10 @@ struct phy_cfg_pair {
+ };
+ union phy_table_tile {
+-      struct rtw_phy_cond cond;
++      struct {
++              struct rtw_phy_cond cond;
++              struct rtw_phy_cond2 cond2;
++      } __packed;
+       struct phy_cfg_pair cfg;
+ };
+@@ -1041,7 +1044,8 @@ void rtw_phy_setup_phy_cond(struct rtw_d
+ {
+       struct rtw_hal *hal = &rtwdev->hal;
+       struct rtw_efuse *efuse = &rtwdev->efuse;
+-      struct rtw_phy_cond cond = {0};
++      struct rtw_phy_cond cond = {};
++      struct rtw_phy_cond2 cond2 = {};
+       cond.cut = hal->cut_version ? hal->cut_version : 15;
+       cond.pkg = pkg ? pkg : 15;
+@@ -1061,15 +1065,34 @@ void rtw_phy_setup_phy_cond(struct rtw_d
+               break;
+       }
++      if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A ||
++          rtwdev->chip->id == RTW_CHIP_TYPE_8821A) {
++              cond.rfe = 0;
++              cond.rfe |= efuse->ext_lna_2g;
++              cond.rfe |= efuse->ext_pa_2g  << 1;
++              cond.rfe |= efuse->ext_lna_5g << 2;
++              cond.rfe |= efuse->ext_pa_5g  << 3;
++              cond.rfe |= efuse->btcoex     << 4;
++
++              cond2.type_alna = efuse->alna_type;
++              cond2.type_glna = efuse->glna_type;
++              cond2.type_apa = efuse->apa_type;
++              cond2.type_gpa = efuse->gpa_type;
++      }
++
+       hal->phy_cond = cond;
++      hal->phy_cond2 = cond2;
+-      rtw_dbg(rtwdev, RTW_DBG_PHY, "phy cond=0x%08x\n", *((u32 *)&hal->phy_cond));
++      rtw_dbg(rtwdev, RTW_DBG_PHY, "phy cond=0x%08x cond2=0x%08x\n",
++              *((u32 *)&hal->phy_cond), *((u32 *)&hal->phy_cond2));
+ }
+-static bool check_positive(struct rtw_dev *rtwdev, struct rtw_phy_cond cond)
++static bool check_positive(struct rtw_dev *rtwdev, struct rtw_phy_cond cond,
++                         struct rtw_phy_cond2 cond2)
+ {
+       struct rtw_hal *hal = &rtwdev->hal;
+       struct rtw_phy_cond drv_cond = hal->phy_cond;
++      struct rtw_phy_cond2 drv_cond2 = hal->phy_cond2;
+       if (cond.cut && cond.cut != drv_cond.cut)
+               return false;
+@@ -1080,8 +1103,29 @@ static bool check_positive(struct rtw_de
+       if (cond.intf && cond.intf != drv_cond.intf)
+               return false;
+-      if (cond.rfe != drv_cond.rfe)
+-              return false;
++      if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A ||
++          rtwdev->chip->id == RTW_CHIP_TYPE_8821A) {
++              if (!(cond.rfe & 0x0f))
++                      return true;
++
++              if ((cond.rfe & drv_cond.rfe) != cond.rfe)
++                      return false;
++
++              if ((cond.rfe & BIT(0)) && cond2.type_glna != drv_cond2.type_glna)
++                      return false;
++
++              if ((cond.rfe & BIT(1)) && cond2.type_gpa != drv_cond2.type_gpa)
++                      return false;
++
++              if ((cond.rfe & BIT(2)) && cond2.type_alna != drv_cond2.type_alna)
++                      return false;
++
++              if ((cond.rfe & BIT(3)) && cond2.type_apa != drv_cond2.type_apa)
++                      return false;
++      } else {
++              if (cond.rfe != drv_cond.rfe)
++                      return false;
++      }
+       return true;
+ }
+@@ -1090,7 +1134,8 @@ void rtw_parse_tbl_phy_cond(struct rtw_d
+ {
+       const union phy_table_tile *p = tbl->data;
+       const union phy_table_tile *end = p + tbl->size / 2;
+-      struct rtw_phy_cond pos_cond = {0};
++      struct rtw_phy_cond pos_cond = {};
++      struct rtw_phy_cond2 pos_cond2 = {};
+       bool is_matched = true, is_skipped = false;
+       BUILD_BUG_ON(sizeof(union phy_table_tile) != sizeof(struct phy_cfg_pair));
+@@ -1109,11 +1154,12 @@ void rtw_parse_tbl_phy_cond(struct rtw_d
+                       case BRANCH_ELIF:
+                       default:
+                               pos_cond = p->cond;
++                              pos_cond2 = p->cond2;
+                               break;
+                       }
+               } else if (p->cond.neg) {
+                       if (!is_skipped) {
+-                              if (check_positive(rtwdev, pos_cond)) {
++                              if (check_positive(rtwdev, pos_cond, pos_cond2)) {
+                                       is_matched = true;
+                                       is_skipped = true;
+                               } else {
diff --git a/package/kernel/mac80211/patches/rtl/028-v6.13-wifi-rtw88-Allow-rtw_chip_info.ltecoex_addr-to-be-NU.patch b/package/kernel/mac80211/patches/rtl/028-v6.13-wifi-rtw88-Allow-rtw_chip_info.ltecoex_addr-to-be-NU.patch
new file mode 100644 (file)
index 0000000..5486fb2
--- /dev/null
@@ -0,0 +1,58 @@
+From 7c5bbeba7c36575a3a57ef4be775b2f3fb68c3f9 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 23 Oct 2024 17:09:04 +0300
+Subject: [PATCH] wifi: rtw88: Allow rtw_chip_info.ltecoex_addr to be NULL
+
+RTL8821A doesn't have this. Trying to use it results in error messages,
+so don't try if ltecoex_addr is NULL.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/d1004817-1760-41d1-9136-3d799757c444@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/coex.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/coex.c
++++ b/drivers/net/wireless/realtek/rtw88/coex.c
+@@ -950,12 +950,18 @@ static void rtw_coex_coex_ctrl_owner(str
+ static void rtw_coex_set_gnt_bt(struct rtw_dev *rtwdev, u8 state)
+ {
++      if (!rtwdev->chip->ltecoex_addr)
++              return;
++
+       rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0xc000, state);
+       rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0c00, state);
+ }
+ static void rtw_coex_set_gnt_wl(struct rtw_dev *rtwdev, u8 state)
+ {
++      if (!rtwdev->chip->ltecoex_addr)
++              return;
++
+       rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x3000, state);
+       rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, 0x0300, state);
+ }
+@@ -3904,7 +3910,7 @@ void rtw_coex_display_coex_info(struct r
+       u8 sys_lte;
+       u16 score_board_WB, score_board_BW;
+       u32 wl_reg_6c0, wl_reg_6c4, wl_reg_6c8, wl_reg_778, wl_reg_6cc;
+-      u32 lte_coex, bt_coex;
++      u32 lte_coex = 0, bt_coex = 0;
+       int i;
+       score_board_BW = rtw_coex_read_scbd(rtwdev);
+@@ -3916,8 +3922,10 @@ void rtw_coex_display_coex_info(struct r
+       wl_reg_778 = rtw_read8(rtwdev, REG_BT_STAT_CTRL);
+       sys_lte = rtw_read8(rtwdev, 0x73);
+-      lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38);
+-      bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54);
++      if (rtwdev->chip->ltecoex_addr) {
++              lte_coex = rtw_coex_read_indirect_reg(rtwdev, 0x38);
++              bt_coex = rtw_coex_read_indirect_reg(rtwdev, 0x54);
++      }
+       if (!coex_stat->wl_under_ips &&
+           (!coex_stat->wl_under_lps || coex_stat->wl_force_lps_ctrl) &&
diff --git a/package/kernel/mac80211/patches/rtl/029-v6.13-wifi-rtw88-Let-each-driver-control-the-power-on-off-.patch b/package/kernel/mac80211/patches/rtl/029-v6.13-wifi-rtw88-Let-each-driver-control-the-power-on-off-.patch
new file mode 100644 (file)
index 0000000..10464b8
--- /dev/null
@@ -0,0 +1,272 @@
+From fbb5e1b3637a720c83c91a7b1476ab0429bfc747 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 23 Oct 2024 17:09:47 +0300
+Subject: [PATCH] wifi: rtw88: Let each driver control the power on/off process
+
+RTL8821AU and RTL8812AU have to do some things differently, so let
+them have full control.
+
+The other chips use the same functions as before.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/98ab839f-9100-44ae-9551-9af743a4aa3a@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/coex.c     |  3 +++
+ drivers/net/wireless/realtek/rtw88/mac.c      | 11 +++++++----
+ drivers/net/wireless/realtek/rtw88/mac.h      |  3 +++
+ drivers/net/wireless/realtek/rtw88/main.c     | 13 ++++++++-----
+ drivers/net/wireless/realtek/rtw88/main.h     |  5 +++++
+ drivers/net/wireless/realtek/rtw88/rtw8703b.c |  2 ++
+ drivers/net/wireless/realtek/rtw88/rtw8723d.c |  2 ++
+ drivers/net/wireless/realtek/rtw88/rtw8821c.c |  2 ++
+ drivers/net/wireless/realtek/rtw88/rtw8822b.c |  2 ++
+ drivers/net/wireless/realtek/rtw88/rtw8822c.c |  2 ++
+ 10 files changed, 36 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/coex.c
++++ b/drivers/net/wireless/realtek/rtw88/coex.c
+@@ -2753,16 +2753,19 @@ void rtw_coex_power_on_setting(struct rt
+       rtw_write8(rtwdev, 0xff1a, 0x0);
+       rtw_coex_set_gnt_debug(rtwdev);
+ }
++EXPORT_SYMBOL(rtw_coex_power_on_setting);
+ void rtw_coex_power_off_setting(struct rtw_dev *rtwdev)
+ {
+       rtw_write16(rtwdev, REG_WIFI_BT_INFO, BIT_BT_INT_EN);
+ }
++EXPORT_SYMBOL(rtw_coex_power_off_setting);
+ void rtw_coex_init_hw_config(struct rtw_dev *rtwdev, bool wifi_only)
+ {
+       __rtw_coex_init_hw_config(rtwdev, wifi_only);
+ }
++EXPORT_SYMBOL(rtw_coex_init_hw_config);
+ void rtw_coex_ips_notify(struct rtw_dev *rtwdev, u8 type)
+ {
+--- a/drivers/net/wireless/realtek/rtw88/mac.c
++++ b/drivers/net/wireless/realtek/rtw88/mac.c
+@@ -227,8 +227,8 @@ static int rtw_sub_pwr_seq_parser(struct
+       return 0;
+ }
+-static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev,
+-                            const struct rtw_pwr_seq_cmd * const *cmd_seq)
++int rtw_pwr_seq_parser(struct rtw_dev *rtwdev,
++                     const struct rtw_pwr_seq_cmd * const *cmd_seq)
+ {
+       u8 cut_mask;
+       u8 intf_mask;
+@@ -267,6 +267,7 @@ static int rtw_pwr_seq_parser(struct rtw
+       return 0;
+ }
++EXPORT_SYMBOL(rtw_pwr_seq_parser);
+ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on)
+ {
+@@ -994,6 +995,7 @@ int rtw_download_firmware(struct rtw_dev
+       return 0;
+ }
++EXPORT_SYMBOL(rtw_download_firmware);
+ static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues)
+ {
+@@ -1127,7 +1129,7 @@ static int txdma_queue_mapping(struct rt
+       return 0;
+ }
+-static int set_trx_fifo_info(struct rtw_dev *rtwdev)
++int rtw_set_trx_fifo_info(struct rtw_dev *rtwdev)
+ {
+       const struct rtw_chip_info *chip = rtwdev->chip;
+       struct rtw_fifo_conf *fifo = &rtwdev->fifo;
+@@ -1179,6 +1181,7 @@ static int set_trx_fifo_info(struct rtw_
+       return 0;
+ }
++EXPORT_SYMBOL(rtw_set_trx_fifo_info);
+ static int __priority_queue_cfg(struct rtw_dev *rtwdev,
+                               const struct rtw_page_table *pg_tbl,
+@@ -1256,7 +1259,7 @@ static int priority_queue_cfg(struct rtw
+       u16 pubq_num;
+       int ret;
+-      ret = set_trx_fifo_info(rtwdev);
++      ret = rtw_set_trx_fifo_info(rtwdev);
+       if (ret)
+               return ret;
+--- a/drivers/net/wireless/realtek/rtw88/mac.h
++++ b/drivers/net/wireless/realtek/rtw88/mac.h
+@@ -30,11 +30,14 @@
+ void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw,
+                        u8 primary_ch_idx);
++int rtw_pwr_seq_parser(struct rtw_dev *rtwdev,
++                     const struct rtw_pwr_seq_cmd * const *cmd_seq);
+ int rtw_mac_power_on(struct rtw_dev *rtwdev);
+ void rtw_mac_power_off(struct rtw_dev *rtwdev);
+ int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw);
+ int rtw_mac_init(struct rtw_dev *rtwdev);
+ void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop);
++int rtw_set_trx_fifo_info(struct rtw_dev *rtwdev);
+ int rtw_ddma_to_fw_fifo(struct rtw_dev *rtwdev, u32 ocp_src, u32 size);
+ static inline void rtw_mac_flush_all_queues(struct rtw_dev *rtwdev, bool drop)
+--- a/drivers/net/wireless/realtek/rtw88/main.c
++++ b/drivers/net/wireless/realtek/rtw88/main.c
+@@ -1309,7 +1309,7 @@ void rtw_update_sta_info(struct rtw_dev
+       rtw_fw_send_ra_info(rtwdev, si, reset_ra_mask);
+ }
+-static int rtw_wait_firmware_completion(struct rtw_dev *rtwdev)
++int rtw_wait_firmware_completion(struct rtw_dev *rtwdev)
+ {
+       const struct rtw_chip_info *chip = rtwdev->chip;
+       struct rtw_fw_state *fw;
+@@ -1329,6 +1329,7 @@ static int rtw_wait_firmware_completion(
+       return ret;
+ }
++EXPORT_SYMBOL(rtw_wait_firmware_completion);
+ static enum rtw_lps_deep_mode rtw_update_lps_deep_mode(struct rtw_dev *rtwdev,
+                                                      struct rtw_fw_state *fw)
+@@ -1350,7 +1351,7 @@ static enum rtw_lps_deep_mode rtw_update
+       return LPS_DEEP_MODE_NONE;
+ }
+-static int rtw_power_on(struct rtw_dev *rtwdev)
++int rtw_power_on(struct rtw_dev *rtwdev)
+ {
+       const struct rtw_chip_info *chip = rtwdev->chip;
+       struct rtw_fw_state *fw = &rtwdev->fw;
+@@ -1413,6 +1414,7 @@ err_off:
+ err:
+       return ret;
+ }
++EXPORT_SYMBOL(rtw_power_on);
+ void rtw_core_fw_scan_notify(struct rtw_dev *rtwdev, bool start)
+ {
+@@ -1485,7 +1487,7 @@ int rtw_core_start(struct rtw_dev *rtwde
+ {
+       int ret;
+-      ret = rtw_power_on(rtwdev);
++      ret = rtwdev->chip->ops->power_on(rtwdev);
+       if (ret)
+               return ret;
+@@ -1505,12 +1507,13 @@ int rtw_core_start(struct rtw_dev *rtwde
+       return 0;
+ }
+-static void rtw_power_off(struct rtw_dev *rtwdev)
++void rtw_power_off(struct rtw_dev *rtwdev)
+ {
+       rtw_hci_stop(rtwdev);
+       rtw_coex_power_off_setting(rtwdev);
+       rtw_mac_power_off(rtwdev);
+ }
++EXPORT_SYMBOL(rtw_power_off);
+ void rtw_core_stop(struct rtw_dev *rtwdev)
+ {
+@@ -1535,7 +1538,7 @@ void rtw_core_stop(struct rtw_dev *rtwde
+       mutex_lock(&rtwdev->mutex);
+-      rtw_power_off(rtwdev);
++      rtwdev->chip->ops->power_off(rtwdev);
+ }
+ static void rtw_init_ht_cap(struct rtw_dev *rtwdev,
+--- a/drivers/net/wireless/realtek/rtw88/main.h
++++ b/drivers/net/wireless/realtek/rtw88/main.h
+@@ -843,6 +843,8 @@ struct rtw_regd {
+ };
+ struct rtw_chip_ops {
++      int (*power_on)(struct rtw_dev *rtwdev);
++      void (*power_off)(struct rtw_dev *rtwdev);
+       int (*mac_init)(struct rtw_dev *rtwdev);
+       int (*dump_fw_crash)(struct rtw_dev *rtwdev);
+       void (*shutdown)(struct rtw_dev *rtwdev);
+@@ -2209,6 +2211,7 @@ void rtw_core_scan_start(struct rtw_dev
+ void rtw_core_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
+                           bool hw_scan);
+ int rtw_core_start(struct rtw_dev *rtwdev);
++void rtw_power_off(struct rtw_dev *rtwdev);
+ void rtw_core_stop(struct rtw_dev *rtwdev);
+ int rtw_chip_info_setup(struct rtw_dev *rtwdev);
+ int rtw_core_init(struct rtw_dev *rtwdev);
+@@ -2223,6 +2226,8 @@ int rtw_sta_add(struct rtw_dev *rtwdev,
+ void rtw_sta_remove(struct rtw_dev *rtwdev, struct ieee80211_sta *sta,
+                   bool fw_exist);
+ void rtw_fw_recovery(struct rtw_dev *rtwdev);
++int rtw_wait_firmware_completion(struct rtw_dev *rtwdev);
++int rtw_power_on(struct rtw_dev *rtwdev);
+ void rtw_core_fw_scan_notify(struct rtw_dev *rtwdev, bool start);
+ int rtw_dump_fw(struct rtw_dev *rtwdev, const u32 ocp_src, u32 size,
+               u32 fwcd_item);
+--- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c
+@@ -1888,6 +1888,8 @@ static const struct coex_tdma_para tdma_
+ };
+ static const struct rtw_chip_ops rtw8703b_ops = {
++      .power_on               = rtw_power_on,
++      .power_off              = rtw_power_off,
+       .mac_init               = rtw8723x_mac_init,
+       .dump_fw_crash          = NULL,
+       .shutdown               = NULL,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+@@ -1390,6 +1390,8 @@ static void rtw8723d_pwr_track(struct rt
+ }
+ static const struct rtw_chip_ops rtw8723d_ops = {
++      .power_on               = rtw_power_on,
++      .power_off              = rtw_power_off,
+       .phy_set_param          = rtw8723d_phy_set_param,
+       .read_efuse             = rtw8723x_read_efuse,
+       .query_phy_status       = query_phy_status,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
+@@ -1643,6 +1643,8 @@ static const struct rtw_prioq_addrs prio
+ };
+ static const struct rtw_chip_ops rtw8821c_ops = {
++      .power_on               = rtw_power_on,
++      .power_off              = rtw_power_off,
+       .phy_set_param          = rtw8821c_phy_set_param,
+       .read_efuse             = rtw8821c_read_efuse,
+       .query_phy_status       = query_phy_status,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+@@ -2132,6 +2132,8 @@ static const struct rtw_prioq_addrs prio
+ };
+ static const struct rtw_chip_ops rtw8822b_ops = {
++      .power_on               = rtw_power_on,
++      .power_off              = rtw_power_off,
+       .phy_set_param          = rtw8822b_phy_set_param,
+       .read_efuse             = rtw8822b_read_efuse,
+       .query_phy_status       = query_phy_status,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+@@ -4947,6 +4947,8 @@ static const struct rtw_prioq_addrs prio
+ };
+ static const struct rtw_chip_ops rtw8822c_ops = {
++      .power_on               = rtw_power_on,
++      .power_off              = rtw_power_off,
+       .phy_set_param          = rtw8822c_phy_set_param,
+       .read_efuse             = rtw8822c_read_efuse,
+       .query_phy_status       = query_phy_status,
diff --git a/package/kernel/mac80211/patches/rtl/030-v6.13-wifi-rtw88-Enable-data-rate-fallback-for-older-chips.patch b/package/kernel/mac80211/patches/rtl/030-v6.13-wifi-rtw88-Enable-data-rate-fallback-for-older-chips.patch
new file mode 100644 (file)
index 0000000..153c04e
--- /dev/null
@@ -0,0 +1,194 @@
+From c7706b1173c77185a2ef40c7d1811021566563f3 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 23 Oct 2024 17:10:32 +0300
+Subject: [PATCH] wifi: rtw88: Enable data rate fallback for older chips
+
+RTL8811AU fails to perform the 4-way handshake when the AP is too far
+because it transmits the EAPOL frames at MCS9 and when that doesn't
+work it retries 48 times with the same rate, to no avail.
+
+Retrying 48 times with the same rate seems pointless. Set the
+appropriate field in the TX descriptor to allow it to use lower rates
+when retrying.
+
+Set it for RTL8723D and RTL8703B because they interpret this field the
+same way as RTL8811A.
+
+The newer RTL8822C, RTL8822B, RTL8821C seem to interpret this field in
+the TX descriptor differently, so leave it alone for those chips.
+
+Tested with RTL8811AU and RTL8723DU.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/2b3e3e6f-541b-4a3b-8ca3-65b267e6a95a@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/fw.c       | 2 +-
+ drivers/net/wireless/realtek/rtw88/main.h     | 1 +
+ drivers/net/wireless/realtek/rtw88/pci.c      | 2 +-
+ drivers/net/wireless/realtek/rtw88/rtw8703b.c | 1 +
+ drivers/net/wireless/realtek/rtw88/rtw8723d.c | 1 +
+ drivers/net/wireless/realtek/rtw88/rtw8821c.c | 1 +
+ drivers/net/wireless/realtek/rtw88/rtw8822b.c | 1 +
+ drivers/net/wireless/realtek/rtw88/rtw8822c.c | 1 +
+ drivers/net/wireless/realtek/rtw88/sdio.c     | 2 +-
+ drivers/net/wireless/realtek/rtw88/tx.c       | 6 +++++-
+ drivers/net/wireless/realtek/rtw88/tx.h       | 4 +++-
+ drivers/net/wireless/realtek/rtw88/usb.c      | 4 ++--
+ 12 files changed, 19 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/fw.c
++++ b/drivers/net/wireless/realtek/rtw88/fw.c
+@@ -1290,7 +1290,7 @@ static void rtw_fill_rsvd_page_desc(stru
+       rtw_tx_rsvd_page_pkt_info_update(rtwdev, &pkt_info, skb, type);
+       pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz);
+       memset(pkt_desc, 0, chip->tx_pkt_desc_sz);
+-      rtw_tx_fill_tx_desc(&pkt_info, skb);
++      rtw_tx_fill_tx_desc(rtwdev, &pkt_info, skb);
+ }
+ static inline u8 rtw_len_to_page(unsigned int len, u8 page_size)
+--- a/drivers/net/wireless/realtek/rtw88/main.h
++++ b/drivers/net/wireless/realtek/rtw88/main.h
+@@ -1204,6 +1204,7 @@ struct rtw_chip_info {
+       u8 usb_tx_agg_desc_num;
+       bool hw_feature_report;
+       u8 c2h_ra_report_size;
++      bool old_datarate_fb_limit;
+       u8 default_1ss_tx_path;
+--- a/drivers/net/wireless/realtek/rtw88/pci.c
++++ b/drivers/net/wireless/realtek/rtw88/pci.c
+@@ -824,7 +824,7 @@ static int rtw_pci_tx_write_data(struct
+       pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz);
+       memset(pkt_desc, 0, tx_pkt_desc_sz);
+       pkt_info->qsel = rtw_pci_get_tx_qsel(skb, queue);
+-      rtw_tx_fill_tx_desc(pkt_info, skb);
++      rtw_tx_fill_tx_desc(rtwdev, pkt_info, skb);
+       dma = dma_map_single(&rtwpci->pdev->dev, skb->data, skb->len,
+                            DMA_TO_DEVICE);
+       if (dma_mapping_error(&rtwpci->pdev->dev, dma))
+--- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c
+@@ -1964,6 +1964,7 @@ const struct rtw_chip_info rtw8703b_hw_s
+       .usb_tx_agg_desc_num = 1, /* Not sure if this chip has USB interface */
+       .hw_feature_report = true,
+       .c2h_ra_report_size = 7,
++      .old_datarate_fb_limit = true,
+       .path_div_supported = false,
+       .ht_supported = true,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+@@ -2135,6 +2135,7 @@ const struct rtw_chip_info rtw8723d_hw_s
+       .usb_tx_agg_desc_num = 1,
+       .hw_feature_report = true,
+       .c2h_ra_report_size = 7,
++      .old_datarate_fb_limit = true,
+       .ht_supported = true,
+       .vht_supported = false,
+       .lps_deep_mode_supported = 0,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
+@@ -1972,6 +1972,7 @@ const struct rtw_chip_info rtw8821c_hw_s
+       .usb_tx_agg_desc_num = 3,
+       .hw_feature_report = true,
+       .c2h_ra_report_size = 7,
++      .old_datarate_fb_limit = false,
+       .ht_supported = true,
+       .vht_supported = true,
+       .lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK),
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+@@ -2513,6 +2513,7 @@ const struct rtw_chip_info rtw8822b_hw_s
+       .usb_tx_agg_desc_num = 3,
+       .hw_feature_report = true,
+       .c2h_ra_report_size = 7,
++      .old_datarate_fb_limit = false,
+       .ht_supported = true,
+       .vht_supported = true,
+       .lps_deep_mode_supported = BIT(LPS_DEEP_MODE_LCLK),
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+@@ -5333,6 +5333,7 @@ const struct rtw_chip_info rtw8822c_hw_s
+       .usb_tx_agg_desc_num = 3,
+       .hw_feature_report = true,
+       .c2h_ra_report_size = 7,
++      .old_datarate_fb_limit = false,
+       .default_1ss_tx_path = BB_PATH_A,
+       .path_div_supported = true,
+       .ht_supported = true,
+--- a/drivers/net/wireless/realtek/rtw88/sdio.c
++++ b/drivers/net/wireless/realtek/rtw88/sdio.c
+@@ -864,7 +864,7 @@ static void rtw_sdio_tx_skb_prepare(stru
+       pkt_info->qsel = rtw_sdio_get_tx_qsel(rtwdev, skb, queue);
+-      rtw_tx_fill_tx_desc(pkt_info, skb);
++      rtw_tx_fill_tx_desc(rtwdev, pkt_info, skb);
+       rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, pkt_desc);
+ }
+--- a/drivers/net/wireless/realtek/rtw88/tx.c
++++ b/drivers/net/wireless/realtek/rtw88/tx.c
+@@ -32,7 +32,8 @@ void rtw_tx_stats(struct rtw_dev *rtwdev
+       }
+ }
+-void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb)
++void rtw_tx_fill_tx_desc(struct rtw_dev *rtwdev,
++                       struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb)
+ {
+       struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)skb->data;
+       bool more_data = false;
+@@ -67,6 +68,9 @@ void rtw_tx_fill_tx_desc(struct rtw_tx_p
+       tx_desc->w4 = le32_encode_bits(pkt_info->rate, RTW_TX_DESC_W4_DATARATE);
++      if (rtwdev->chip->old_datarate_fb_limit)
++              tx_desc->w4 |= le32_encode_bits(0x1f, RTW_TX_DESC_W4_DATARATE_FB_LIMIT);
++
+       tx_desc->w5 = le32_encode_bits(pkt_info->short_gi, RTW_TX_DESC_W5_DATA_SHORT) |
+                     le32_encode_bits(pkt_info->bw, RTW_TX_DESC_W5_DATA_BW) |
+                     le32_encode_bits(pkt_info->ldpc, RTW_TX_DESC_W5_DATA_LDPC) |
+--- a/drivers/net/wireless/realtek/rtw88/tx.h
++++ b/drivers/net/wireless/realtek/rtw88/tx.h
+@@ -44,6 +44,7 @@ struct rtw_tx_desc {
+ #define RTW_TX_DESC_W3_NAVUSEHDR BIT(15)
+ #define RTW_TX_DESC_W3_MAX_AGG_NUM GENMASK(21, 17)
+ #define RTW_TX_DESC_W4_DATARATE GENMASK(6, 0)
++#define RTW_TX_DESC_W4_DATARATE_FB_LIMIT GENMASK(12, 8)
+ #define RTW_TX_DESC_W4_RTSRATE GENMASK(28, 24)
+ #define RTW_TX_DESC_W5_DATA_SHORT BIT(4)
+ #define RTW_TX_DESC_W5_DATA_BW GENMASK(6, 5)
+@@ -94,7 +95,8 @@ void rtw_tx_pkt_info_update(struct rtw_d
+                           struct rtw_tx_pkt_info *pkt_info,
+                           struct ieee80211_sta *sta,
+                           struct sk_buff *skb);
+-void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb);
++void rtw_tx_fill_tx_desc(struct rtw_dev *rtwdev,
++                       struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb);
+ void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn);
+ void rtw_tx_report_handle(struct rtw_dev *rtwdev, struct sk_buff *skb, int src);
+ void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
+--- a/drivers/net/wireless/realtek/rtw88/usb.c
++++ b/drivers/net/wireless/realtek/rtw88/usb.c
+@@ -457,7 +457,7 @@ static int rtw_usb_write_data(struct rtw
+       skb_put_data(skb, buf, size);
+       skb_push(skb, chip->tx_pkt_desc_sz);
+       memset(skb->data, 0, chip->tx_pkt_desc_sz);
+-      rtw_tx_fill_tx_desc(pkt_info, skb);
++      rtw_tx_fill_tx_desc(rtwdev, pkt_info, skb);
+       rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, skb->data);
+       ret = rtw_usb_write_port(rtwdev, qsel, skb,
+@@ -524,7 +524,7 @@ static int rtw_usb_tx_write(struct rtw_d
+       pkt_desc = skb_push(skb, chip->tx_pkt_desc_sz);
+       memset(pkt_desc, 0, chip->tx_pkt_desc_sz);
+       ep = qsel_to_ep(rtwusb, pkt_info->qsel);
+-      rtw_tx_fill_tx_desc(pkt_info, skb);
++      rtw_tx_fill_tx_desc(rtwdev, pkt_info, skb);
+       rtw_tx_fill_txdesc_checksum(rtwdev, pkt_info, skb->data);
+       tx_data = rtw_usb_get_tx_data(skb);
+       tx_data->sn = pkt_info->sn;
diff --git a/package/kernel/mac80211/patches/rtl/031-v6.13-wifi-rtw88-Make-txagc_remnant_ofdm-an-array.patch b/package/kernel/mac80211/patches/rtl/031-v6.13-wifi-rtw88-Make-txagc_remnant_ofdm-an-array.patch
new file mode 100644 (file)
index 0000000..10fc773
--- /dev/null
@@ -0,0 +1,85 @@
+From abb0f19492ba6289ffba6ec1057c0426240958af Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 23 Oct 2024 17:10:54 +0300
+Subject: [PATCH] wifi: rtw88: Make txagc_remnant_ofdm an array
+
+txagc_remnant_ofdm member of struct rtw_dm_info should be different for
+each RF path, so make it an array of size RTW_RF_PATH_MAX (4).
+
+Until now all the chips using this had only one RF path, but RTL8812AU
+has two, and RTL8814AU has four.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/68571ba9-e504-4b2d-bfa1-62f468753649@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/main.h     | 2 +-
+ drivers/net/wireless/realtek/rtw88/phy.c      | 4 ++--
+ drivers/net/wireless/realtek/rtw88/rtw8703b.c | 4 ++--
+ drivers/net/wireless/realtek/rtw88/rtw8723d.c | 4 ++--
+ 4 files changed, 7 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/main.h
++++ b/drivers/net/wireless/realtek/rtw88/main.h
+@@ -1715,7 +1715,7 @@ struct rtw_dm_info {
+       bool pwr_trk_init_trigger;
+       struct ewma_thermal avg_thermal[RTW_RF_PATH_MAX];
+       s8 txagc_remnant_cck;
+-      s8 txagc_remnant_ofdm;
++      s8 txagc_remnant_ofdm[RTW_RF_PATH_MAX];
+       u8 rx_cck_agc_report_type;
+       /* backup dack results for each path and I/Q */
+--- a/drivers/net/wireless/realtek/rtw88/phy.c
++++ b/drivers/net/wireless/realtek/rtw88/phy.c
+@@ -2169,8 +2169,8 @@ void rtw_get_tx_power_params(struct rtw_
+       *limit = rtw_phy_get_tx_power_limit(rtwdev, band, bw, path,
+                                           rate, ch, regd);
+-      *remnant = (rate <= DESC_RATE11M ? dm_info->txagc_remnant_cck :
+-                  dm_info->txagc_remnant_ofdm);
++      *remnant = rate <= DESC_RATE11M ? dm_info->txagc_remnant_cck :
++                                        dm_info->txagc_remnant_ofdm[path];
+       *sar = rtw_phy_get_tx_power_sar(rtwdev, hal->sar_band, path, rate);
+ }
+--- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c
+@@ -637,7 +637,7 @@ static void rtw8703b_pwrtrack_init(struc
+       dm_info->pwr_trk_init_trigger = true;
+       dm_info->thermal_meter_k = rtwdev->efuse.thermal_meter_k;
+       dm_info->txagc_remnant_cck = 0;
+-      dm_info->txagc_remnant_ofdm = 0;
++      dm_info->txagc_remnant_ofdm[RF_PATH_A] = 0;
+ }
+ static void rtw8703b_phy_set_param(struct rtw_dev *rtwdev)
+@@ -1589,7 +1589,7 @@ static void rtw8703b_pwrtrack_set_ofdm_p
+ {
+       struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+-      dm_info->txagc_remnant_ofdm = txagc_idx;
++      dm_info->txagc_remnant_ofdm[RF_PATH_A] = txagc_idx;
+       /* Only path A is calibrated for rtl8703b */
+       rtw8703b_set_iqk_matrix(rtwdev, swing_idx, RF_PATH_A);
+--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+@@ -79,7 +79,7 @@ static void rtw8723d_pwrtrack_init(struc
+       dm_info->pwr_trk_init_trigger = true;
+       dm_info->thermal_meter_k = rtwdev->efuse.thermal_meter_k;
+       dm_info->txagc_remnant_cck = 0;
+-      dm_info->txagc_remnant_ofdm = 0;
++      dm_info->txagc_remnant_ofdm[RF_PATH_A] = 0;
+ }
+ static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev)
+@@ -1265,7 +1265,7 @@ static void rtw8723d_pwrtrack_set_ofdm_p
+ {
+       struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+-      dm_info->txagc_remnant_ofdm = txagc_idx;
++      dm_info->txagc_remnant_ofdm[RF_PATH_A] = txagc_idx;
+       rtw8723d_set_iqk_matrix(rtwdev, swing_idx, RF_PATH_A);
+       rtw8723d_set_iqk_matrix(rtwdev, swing_idx, RF_PATH_B);
diff --git a/package/kernel/mac80211/patches/rtl/032-v6.13-wifi-rtw88-Support-TX-page-sizes-bigger-than-128.patch b/package/kernel/mac80211/patches/rtl/032-v6.13-wifi-rtw88-Support-TX-page-sizes-bigger-than-128.patch
new file mode 100644 (file)
index 0000000..7d77e0e
--- /dev/null
@@ -0,0 +1,115 @@
+From 82a617413e8545775ec03a1970809ac5f549ef32 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 23 Oct 2024 17:12:06 +0300
+Subject: [PATCH] wifi: rtw88: Support TX page sizes bigger than 128
+
+All the chips supported so far have a TX page size of 128 bytes.
+
+Change the type of the page_size member of struct rtw_chip_info from u8
+to u16 in order to support RTL8821AU (page size of 256 bytes) and
+RTL8812AU (page size of 512 bytes). Also change the types of several
+related variables and function parameters from u8 to u16.
+
+The TX page size is used, among other things, to construct the beacon,
+null data, QOS null data, and PS poll templates which are uploaded to
+the chip's reserved page. Each template needs to be aligned on a
+multiple of the TX page size. Power saving can't work if the TX page
+size is wrong.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/acdefbb1-3daf-4349-9e03-9472754d5f1e@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/debug.c |  2 +-
+ drivers/net/wireless/realtek/rtw88/fw.c    | 21 +++++++++++----------
+ drivers/net/wireless/realtek/rtw88/mac.c   |  2 +-
+ drivers/net/wireless/realtek/rtw88/main.h  |  2 +-
+ 4 files changed, 14 insertions(+), 13 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/debug.c
++++ b/drivers/net/wireless/realtek/rtw88/debug.c
+@@ -308,7 +308,7 @@ static int rtw_debugfs_get_rsvd_page(str
+ {
+       struct rtw_debugfs_priv *debugfs_priv = m->private;
+       struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
+-      u8 page_size = rtwdev->chip->page_size;
++      u16 page_size = rtwdev->chip->page_size;
+       u32 buf_size = debugfs_priv->rsvd_page.page_num * page_size;
+       u32 offset = debugfs_priv->rsvd_page.page_offset * page_size;
+       u8 *buf;
+--- a/drivers/net/wireless/realtek/rtw88/fw.c
++++ b/drivers/net/wireless/realtek/rtw88/fw.c
+@@ -1293,13 +1293,13 @@ static void rtw_fill_rsvd_page_desc(stru
+       rtw_tx_fill_tx_desc(rtwdev, &pkt_info, skb);
+ }
+-static inline u8 rtw_len_to_page(unsigned int len, u8 page_size)
++static inline u8 rtw_len_to_page(unsigned int len, u16 page_size)
+ {
+       return DIV_ROUND_UP(len, page_size);
+ }
+-static void rtw_rsvd_page_list_to_buf(struct rtw_dev *rtwdev, u8 page_size,
+-                                    u8 page_margin, u32 page, u8 *buf,
++static void rtw_rsvd_page_list_to_buf(struct rtw_dev *rtwdev, u16 page_size,
++                                    u16 page_margin, u32 page, u8 *buf,
+                                     struct rtw_rsvd_page *rsvd_pkt)
+ {
+       struct sk_buff *skb = rsvd_pkt->skb;
+@@ -1601,13 +1601,13 @@ static int  __rtw_build_rsvd_page_from_v
+ static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev, u32 *size)
+ {
+-      struct ieee80211_hw *hw = rtwdev->hw;
+       const struct rtw_chip_info *chip = rtwdev->chip;
+-      struct sk_buff *iter;
++      struct ieee80211_hw *hw = rtwdev->hw;
+       struct rtw_rsvd_page *rsvd_pkt;
+-      u32 page = 0;
++      struct sk_buff *iter;
++      u16 page_size, page_margin, tx_desc_sz;
+       u8 total_page = 0;
+-      u8 page_size, page_margin, tx_desc_sz;
++      u32 page = 0;
+       u8 *buf;
+       int ret;
+@@ -2013,12 +2013,13 @@ static int _rtw_hw_scan_update_probe_req
+ {
+       const struct rtw_chip_info *chip = rtwdev->chip;
+       struct sk_buff *skb, *tmp;
+-      u8 page_offset = 1, *buf, page_size = chip->page_size;
+       u16 pg_addr = rtwdev->fifo.rsvd_h2c_info_addr, loc;
+-      u16 buf_offset = page_size * page_offset;
+       u8 tx_desc_sz = chip->tx_pkt_desc_sz;
+-      u8 page_cnt, pages;
++      u16 page_size = chip->page_size;
++      u8 page_offset = 1, *buf;
++      u16 buf_offset = page_size * page_offset;
+       unsigned int pkt_len;
++      u8 page_cnt, pages;
+       int ret;
+       if (rtw_fw_feature_ext_check(&rtwdev->fw, FW_FEATURE_EXT_OLD_PAGE_NUM))
+--- a/drivers/net/wireless/realtek/rtw88/mac.c
++++ b/drivers/net/wireless/realtek/rtw88/mac.c
+@@ -1138,7 +1138,7 @@ int rtw_set_trx_fifo_info(struct rtw_dev
+       /* config rsvd page num */
+       fifo->rsvd_drv_pg_num = chip->rsvd_drv_pg_num;
+-      fifo->txff_pg_num = chip->txff_size >> 7;
++      fifo->txff_pg_num = chip->txff_size / chip->page_size;
+       if (rtw_chip_wcpu_11n(rtwdev))
+               fifo->rsvd_pg_num = fifo->rsvd_drv_pg_num;
+       else
+--- a/drivers/net/wireless/realtek/rtw88/main.h
++++ b/drivers/net/wireless/realtek/rtw88/main.h
+@@ -1187,7 +1187,7 @@ struct rtw_chip_info {
+       u32 fw_rxff_size;
+       u16 rsvd_drv_pg_num;
+       u8 band;
+-      u8 page_size;
++      u16 page_size;
+       u8 csi_buf_pg_num;
+       u8 dig_max;
+       u8 dig_min;
diff --git a/package/kernel/mac80211/patches/rtl/033-v6.13-wifi-rtw88-Move-pwr_track_tbl-to-struct-rtw_rfe_def.patch b/package/kernel/mac80211/patches/rtl/033-v6.13-wifi-rtw88-Move-pwr_track_tbl-to-struct-rtw_rfe_def.patch
new file mode 100644 (file)
index 0000000..cda3e7a
--- /dev/null
@@ -0,0 +1,297 @@
+From 67d915604e6993ff627ac001983a2de63ff71b13 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 23 Oct 2024 17:12:39 +0300
+Subject: [PATCH] wifi: rtw88: Move pwr_track_tbl to struct rtw_rfe_def
+
+RTL8812AU uses one set of TX power tracking tables for RFE 3, and
+another set for everything else.
+
+Move pwr_track_tbl from struct rtw_chip_info to struct rtw_rfe_def in
+order to load the right set of tables for each RFE (RF front end) type.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/904d0ab1-c046-40cd-a3a3-d4fdcf663c9d@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/main.h     |  8 ++++---
+ drivers/net/wireless/realtek/rtw88/phy.c      |  3 ++-
+ drivers/net/wireless/realtek/rtw88/rtw8703b.c | 12 +++++-----
+ drivers/net/wireless/realtek/rtw88/rtw8723d.c | 12 +++++-----
+ drivers/net/wireless/realtek/rtw88/rtw8723x.c |  3 ++-
+ drivers/net/wireless/realtek/rtw88/rtw8821c.c | 17 +++++++-------
+ drivers/net/wireless/realtek/rtw88/rtw8822b.c | 15 ++++++------
+ drivers/net/wireless/realtek/rtw88/rtw8822c.c | 23 +++++++++----------
+ 8 files changed, 47 insertions(+), 46 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/main.h
++++ b/drivers/net/wireless/realtek/rtw88/main.h
+@@ -1099,17 +1099,20 @@ enum rtw_rfe_fem {
+ struct rtw_rfe_def {
+       const struct rtw_table *phy_pg_tbl;
+       const struct rtw_table *txpwr_lmt_tbl;
++      const struct rtw_pwr_track_tbl *pwr_track_tbl;
+       const struct rtw_table *agc_btg_tbl;
+ };
+-#define RTW_DEF_RFE(chip, bb_pg, pwrlmt) {                              \
++#define RTW_DEF_RFE(chip, bb_pg, pwrlmt, track) {                               \
+       .phy_pg_tbl = &rtw ## chip ## _bb_pg_type ## bb_pg ## _tbl,       \
+       .txpwr_lmt_tbl = &rtw ## chip ## _txpwr_lmt_type ## pwrlmt ## _tbl, \
++      .pwr_track_tbl = &rtw ## chip ## _pwr_track_type ## track ## _tbl, \
+       }
+-#define RTW_DEF_RFE_EXT(chip, bb_pg, pwrlmt, btg) {                     \
++#define RTW_DEF_RFE_EXT(chip, bb_pg, pwrlmt, track, btg) {                      \
+       .phy_pg_tbl = &rtw ## chip ## _bb_pg_type ## bb_pg ## _tbl,       \
+       .txpwr_lmt_tbl = &rtw ## chip ## _txpwr_lmt_type ## pwrlmt ## _tbl, \
++      .pwr_track_tbl = &rtw ## chip ## _pwr_track_type ## track ## _tbl, \
+       .agc_btg_tbl = &rtw ## chip ## _agc_btg_type ## btg ## _tbl, \
+       }
+@@ -1243,7 +1246,6 @@ struct rtw_chip_info {
+       u16 dpd_ratemask;
+       u8 iqk_threshold;
+       u8 lck_threshold;
+-      const struct rtw_pwr_track_tbl *pwr_track_tbl;
+       u8 bfer_su_max_num;
+       u8 bfer_mu_max_num;
+--- a/drivers/net/wireless/realtek/rtw88/phy.c
++++ b/drivers/net/wireless/realtek/rtw88/phy.c
+@@ -2384,7 +2384,8 @@ void rtw_phy_init_tx_power(struct rtw_de
+ void rtw_phy_config_swing_table(struct rtw_dev *rtwdev,
+                               struct rtw_swing_table *swing_table)
+ {
+-      const struct rtw_pwr_track_tbl *tbl = rtwdev->chip->pwr_track_tbl;
++      const struct rtw_rfe_def *rfe_def = rtw_get_rfe_def(rtwdev);
++      const struct rtw_pwr_track_tbl *tbl = rfe_def->pwr_track_tbl;
+       u8 channel = rtwdev->hal.current_channel;
+       if (IS_CH_2G_BAND(channel)) {
+--- a/drivers/net/wireless/realtek/rtw88/rtw8703b.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8703b.c
+@@ -493,11 +493,6 @@ static const struct rtw_pwr_seq_cmd * co
+       NULL
+ };
+-static const struct rtw_rfe_def rtw8703b_rfe_defs[] = {
+-      [0] = { .phy_pg_tbl     = &rtw8703b_bb_pg_tbl,
+-              .txpwr_lmt_tbl  = &rtw8703b_txpwr_lmt_tbl,},
+-};
+-
+ static const struct rtw_page_table page_table_8703b[] = {
+       {12, 2, 2, 0, 1},
+       {12, 2, 2, 0, 1},
+@@ -1818,6 +1813,12 @@ static const struct rtw_pwr_track_tbl rt
+       .pwrtrk_xtal_p = rtw8703b_pwrtrk_xtal_p,
+ };
++static const struct rtw_rfe_def rtw8703b_rfe_defs[] = {
++      [0] = { .phy_pg_tbl     = &rtw8703b_bb_pg_tbl,
++              .txpwr_lmt_tbl  = &rtw8703b_txpwr_lmt_tbl,
++              .pwr_track_tbl  = &rtw8703b_rtw_pwr_track_tbl, },
++};
++
+ /* Shared-Antenna Coex Table */
+ static const struct coex_table_para table_sant_8703b[] = {
+       {0xffffffff, 0xffffffff}, /* case-0 */
+@@ -1997,7 +1998,6 @@ const struct rtw_chip_info rtw8703b_hw_s
+       .rfe_defs_size = ARRAY_SIZE(rtw8703b_rfe_defs),
+       .iqk_threshold = 8,
+-      .pwr_track_tbl = &rtw8703b_rtw_pwr_track_tbl,
+       /* WOWLAN firmware exists, but not implemented yet */
+       .wow_fw_name = "rtw88/rtw8703b_wow_fw.bin",
+--- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c
+@@ -2020,11 +2020,6 @@ static const struct rtw_intf_phy_para_ta
+       .n_gen1_para    = ARRAY_SIZE(pcie_gen1_param_8723d),
+ };
+-static const struct rtw_rfe_def rtw8723d_rfe_defs[] = {
+-      [0] = { .phy_pg_tbl     = &rtw8723d_bb_pg_tbl,
+-              .txpwr_lmt_tbl  = &rtw8723d_txpwr_lmt_tbl,},
+-};
+-
+ static const u8 rtw8723d_pwrtrk_2gb_n[] = {
+       0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5,
+       6, 6, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 10
+@@ -2088,6 +2083,12 @@ static const struct rtw_pwr_track_tbl rt
+       .pwrtrk_xtal_n = rtw8723d_pwrtrk_xtal_n,
+ };
++static const struct rtw_rfe_def rtw8723d_rfe_defs[] = {
++      [0] = { .phy_pg_tbl     = &rtw8723d_bb_pg_tbl,
++              .txpwr_lmt_tbl  = &rtw8723d_txpwr_lmt_tbl,
++              .pwr_track_tbl  = &rtw8723d_rtw_pwr_track_tbl, },
++};
++
+ static const struct rtw_reg_domain coex_info_hw_regs_8723d[] = {
+       {0x948, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+       {0x67, BIT(7), RTW_REG_DOMAIN_MAC8},
+@@ -2159,7 +2160,6 @@ const struct rtw_chip_info rtw8723d_hw_s
+       .rfe_defs = rtw8723d_rfe_defs,
+       .rfe_defs_size = ARRAY_SIZE(rtw8723d_rfe_defs),
+       .rx_ldpc = false,
+-      .pwr_track_tbl = &rtw8723d_rtw_pwr_track_tbl,
+       .iqk_threshold = 8,
+       .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
+       .max_scan_ie_len = IEEE80211_MAX_DATA_LEN,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8723x.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8723x.c
+@@ -595,7 +595,8 @@ void __rtw8723x_pwrtrack_set_xtal(struct
+                                 u8 delta)
+ {
+       struct rtw_dm_info *dm_info = &rtwdev->dm_info;
+-      const struct rtw_pwr_track_tbl *tbl = rtwdev->chip->pwr_track_tbl;
++      const struct rtw_rfe_def *rfe_def = rtw_get_rfe_def(rtwdev);
++      const struct rtw_pwr_track_tbl *tbl = rfe_def->pwr_track_tbl;
+       const s8 *pwrtrk_xtal;
+       s8 xtal_cap;
+--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
+@@ -1581,13 +1581,6 @@ static const struct rtw_intf_phy_para_ta
+       .n_gen2_para    = ARRAY_SIZE(pcie_gen2_param_8821c),
+ };
+-static const struct rtw_rfe_def rtw8821c_rfe_defs[] = {
+-      [0] = RTW_DEF_RFE(8821c, 0, 0),
+-      [2] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2),
+-      [4] = RTW_DEF_RFE_EXT(8821c, 0, 0, 2),
+-      [6] = RTW_DEF_RFE(8821c, 0, 0),
+-};
+-
+ static const struct rtw_hw_reg rtw8821c_dig[] = {
+       [0] = { .addr = 0xc50, .mask = 0x7f },
+ };
+@@ -1899,7 +1892,7 @@ static const u8 rtw8821c_pwrtrk_2g_cck_a
+       5, 6, 6, 7, 7, 7, 8, 8, 9, 9, 9, 9, 9, 9
+ };
+-static const struct rtw_pwr_track_tbl rtw8821c_rtw_pwr_track_tbl = {
++static const struct rtw_pwr_track_tbl rtw8821c_pwr_track_type0_tbl = {
+       .pwrtrk_5gb_n[0] = rtw8821c_pwrtrk_5gb_n[0],
+       .pwrtrk_5gb_n[1] = rtw8821c_pwrtrk_5gb_n[1],
+       .pwrtrk_5gb_n[2] = rtw8821c_pwrtrk_5gb_n[2],
+@@ -1922,6 +1915,13 @@ static const struct rtw_pwr_track_tbl rt
+       .pwrtrk_2g_ccka_p = rtw8821c_pwrtrk_2g_cck_a_p,
+ };
++static const struct rtw_rfe_def rtw8821c_rfe_defs[] = {
++      [0] = RTW_DEF_RFE(8821c, 0, 0, 0),
++      [2] = RTW_DEF_RFE_EXT(8821c, 0, 0, 0, 2),
++      [4] = RTW_DEF_RFE_EXT(8821c, 0, 0, 0, 2),
++      [6] = RTW_DEF_RFE(8821c, 0, 0, 0),
++};
++
+ static const struct rtw_reg_domain coex_info_hw_regs_8821c[] = {
+       {0xCB0, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+       {0xCB4, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+@@ -1994,7 +1994,6 @@ const struct rtw_chip_info rtw8821c_hw_s
+       .rfe_defs = rtw8821c_rfe_defs,
+       .rfe_defs_size = ARRAY_SIZE(rtw8821c_rfe_defs),
+       .rx_ldpc = false,
+-      .pwr_track_tbl = &rtw8821c_rtw_pwr_track_tbl,
+       .iqk_threshold = 8,
+       .bfer_su_max_num = 2,
+       .bfer_mu_max_num = 1,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c
+@@ -2072,12 +2072,6 @@ static const struct rtw_intf_phy_para_ta
+       .n_gen2_para    = ARRAY_SIZE(pcie_gen2_param_8822b),
+ };
+-static const struct rtw_rfe_def rtw8822b_rfe_defs[] = {
+-      [2] = RTW_DEF_RFE(8822b, 2, 2),
+-      [3] = RTW_DEF_RFE(8822b, 3, 0),
+-      [5] = RTW_DEF_RFE(8822b, 5, 5),
+-};
+-
+ static const struct rtw_hw_reg rtw8822b_dig[] = {
+       [0] = { .addr = 0xc50, .mask = 0x7f },
+       [1] = { .addr = 0xe50, .mask = 0x7f },
+@@ -2432,7 +2426,7 @@ static const u8 rtw8822b_pwrtrk_2g_cck_a
+       10, 11, 11, 12, 12, 13, 13, 14, 14, 15
+ };
+-static const struct rtw_pwr_track_tbl rtw8822b_rtw_pwr_track_tbl = {
++static const struct rtw_pwr_track_tbl rtw8822b_pwr_track_type0_tbl = {
+       .pwrtrk_5gb_n[RTW_PWR_TRK_5G_1] = rtw8822b_pwrtrk_5gb_n[RTW_PWR_TRK_5G_1],
+       .pwrtrk_5gb_n[RTW_PWR_TRK_5G_2] = rtw8822b_pwrtrk_5gb_n[RTW_PWR_TRK_5G_2],
+       .pwrtrk_5gb_n[RTW_PWR_TRK_5G_3] = rtw8822b_pwrtrk_5gb_n[RTW_PWR_TRK_5G_3],
+@@ -2455,6 +2449,12 @@ static const struct rtw_pwr_track_tbl rt
+       .pwrtrk_2g_ccka_p = rtw8822b_pwrtrk_2g_cck_a_p,
+ };
++static const struct rtw_rfe_def rtw8822b_rfe_defs[] = {
++      [2] = RTW_DEF_RFE(8822b, 2, 2, 0),
++      [3] = RTW_DEF_RFE(8822b, 3, 0, 0),
++      [5] = RTW_DEF_RFE(8822b, 5, 5, 0),
++};
++
+ static const struct rtw_reg_domain coex_info_hw_regs_8822b[] = {
+       {0xcb0, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+       {0xcb4, MASKDWORD, RTW_REG_DOMAIN_MAC32},
+@@ -2535,7 +2535,6 @@ const struct rtw_chip_info rtw8822b_hw_s
+       .rf_tbl = {&rtw8822b_rf_a_tbl, &rtw8822b_rf_b_tbl},
+       .rfe_defs = rtw8822b_rfe_defs,
+       .rfe_defs_size = ARRAY_SIZE(rtw8822b_rfe_defs),
+-      .pwr_track_tbl = &rtw8822b_rtw_pwr_track_tbl,
+       .iqk_threshold = 8,
+       .bfer_su_max_num = 2,
+       .bfer_mu_max_num = 1,
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c
+@@ -4883,16 +4883,6 @@ static const struct rtw_intf_phy_para_ta
+       .n_gen2_para    = ARRAY_SIZE(pcie_gen2_param_8822c),
+ };
+-static const struct rtw_rfe_def rtw8822c_rfe_defs[] = {
+-      [0] = RTW_DEF_RFE(8822c, 0, 0),
+-      [1] = RTW_DEF_RFE(8822c, 0, 0),
+-      [2] = RTW_DEF_RFE(8822c, 0, 0),
+-      [3] = RTW_DEF_RFE(8822c, 0, 0),
+-      [4] = RTW_DEF_RFE(8822c, 0, 0),
+-      [5] = RTW_DEF_RFE(8822c, 0, 5),
+-      [6] = RTW_DEF_RFE(8822c, 0, 0),
+-};
+-
+ static const struct rtw_hw_reg rtw8822c_dig[] = {
+       [0] = { .addr = 0x1d70, .mask = 0x7f },
+       [1] = { .addr = 0x1d70, .mask = 0x7f00 },
+@@ -5238,7 +5228,7 @@ static const u8 rtw8822c_pwrtrk_2g_cck_a
+       18, 18, 19, 20, 21, 22, 23, 24, 24, 25
+ };
+-static const struct rtw_pwr_track_tbl rtw8822c_rtw_pwr_track_tbl = {
++static const struct rtw_pwr_track_tbl rtw8822c_pwr_track_type0_tbl = {
+       .pwrtrk_5gb_n[RTW_PWR_TRK_5G_1] = rtw8822c_pwrtrk_5gb_n[RTW_PWR_TRK_5G_1],
+       .pwrtrk_5gb_n[RTW_PWR_TRK_5G_2] = rtw8822c_pwrtrk_5gb_n[RTW_PWR_TRK_5G_2],
+       .pwrtrk_5gb_n[RTW_PWR_TRK_5G_3] = rtw8822c_pwrtrk_5gb_n[RTW_PWR_TRK_5G_3],
+@@ -5261,6 +5251,16 @@ static const struct rtw_pwr_track_tbl rt
+       .pwrtrk_2g_ccka_p = rtw8822c_pwrtrk_2g_cck_a_p,
+ };
++static const struct rtw_rfe_def rtw8822c_rfe_defs[] = {
++      [0] = RTW_DEF_RFE(8822c, 0, 0, 0),
++      [1] = RTW_DEF_RFE(8822c, 0, 0, 0),
++      [2] = RTW_DEF_RFE(8822c, 0, 0, 0),
++      [3] = RTW_DEF_RFE(8822c, 0, 0, 0),
++      [4] = RTW_DEF_RFE(8822c, 0, 0, 0),
++      [5] = RTW_DEF_RFE(8822c, 0, 5, 0),
++      [6] = RTW_DEF_RFE(8822c, 0, 0, 0),
++};
++
+ static const struct rtw_hw_reg_offset rtw8822c_edcca_th[] = {
+       [EDCCA_TH_L2H_IDX] = {
+               {.addr = 0x84c, .mask = MASKBYTE2}, .offset = 0x80
+@@ -5360,7 +5360,6 @@ const struct rtw_chip_info rtw8822c_hw_s
+       .rfe_defs_size = ARRAY_SIZE(rtw8822c_rfe_defs),
+       .en_dis_dpd = true,
+       .dpd_ratemask = DIS_DPD_RATEALL,
+-      .pwr_track_tbl = &rtw8822c_rtw_pwr_track_tbl,
+       .iqk_threshold = 8,
+       .lck_threshold = 8,
+       .bfer_su_max_num = 2,
diff --git a/package/kernel/mac80211/patches/rtl/034-v6.13-wifi-rtw88-usb-Set-pkt_info.ls-for-the-reserved-page.patch b/package/kernel/mac80211/patches/rtl/034-v6.13-wifi-rtw88-usb-Set-pkt_info.ls-for-the-reserved-page.patch
new file mode 100644 (file)
index 0000000..7c6e135
--- /dev/null
@@ -0,0 +1,27 @@
+From 85bf3041a0ea40a60b5295749268e179f056546a Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 23 Oct 2024 17:13:10 +0300
+Subject: [PATCH] wifi: rtw88: usb: Set pkt_info.ls for the reserved page
+
+"ls" meaning "last segment". Without this RTL8812AU can't upload the
+reserved page in USB 2 mode. (Somehow it's fine in USB 3 mode.)
+
+Also tested with RTL8822CU, RTL8812BU, RTL8811CU, RTL8723DU, RTL8811AU.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/e443f5d9-4b53-4f64-985c-64313ec80bef@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/usb.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/realtek/rtw88/usb.c
++++ b/drivers/net/wireless/realtek/rtw88/usb.c
+@@ -477,6 +477,7 @@ static int rtw_usb_write_data_rsvd_page(
+       pkt_info.tx_pkt_size = size;
+       pkt_info.qsel = TX_DESC_QSEL_BEACON;
+       pkt_info.offset = chip->tx_pkt_desc_sz;
++      pkt_info.ls = true;
+       return rtw_usb_write_data(rtwdev, &pkt_info, buf);
+ }
diff --git a/package/kernel/mac80211/patches/rtl/035-v6.13-wifi-rtw88-Detect-beacon-loss-with-chips-other-than-.patch b/package/kernel/mac80211/patches/rtl/035-v6.13-wifi-rtw88-Detect-beacon-loss-with-chips-other-than-.patch
new file mode 100644 (file)
index 0000000..de64f33
--- /dev/null
@@ -0,0 +1,63 @@
+From 57289d30cd2ae315ab9b28213d63d1dbf8570cf3 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 23 Oct 2024 17:13:45 +0300
+Subject: [PATCH] wifi: rtw88: Detect beacon loss with chips other than 8822c
+
+The driver is supposed to avoid entering LPS (power saving) when there
+is beacon loss, but only RTL8822C detects the beacon loss (because it
+has beacon filtering in the firmware).
+
+Detect beacon loss with the other chips by checking if we received less
+than half the expected number of beacons in the last 2-second interval.
+
+This gets rid of the occasional "failed to get tx report from firmware"
+warnings with RTL8821AU. It may also avoid some disconnections.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/f52b2fcf-bf94-48bc-89bd-e55ebc3a2f2d@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/main.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+--- a/drivers/net/wireless/realtek/rtw88/main.c
++++ b/drivers/net/wireless/realtek/rtw88/main.c
+@@ -202,6 +202,21 @@ static void rtw_vif_watch_dog_iter(void
+       rtwvif->stats.rx_cnt = 0;
+ }
++static void rtw_sw_beacon_loss_check(struct rtw_dev *rtwdev,
++                                   struct rtw_vif *rtwvif, int received_beacons)
++{
++      int watchdog_delay = 2000000 / 1024; /* TU */
++      int beacon_int, expected_beacons;
++
++      if (rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_BCN_FILTER) || !rtwvif)
++              return;
++
++      beacon_int = rtwvif_to_vif(rtwvif)->bss_conf.beacon_int;
++      expected_beacons = DIV_ROUND_UP(watchdog_delay, beacon_int);
++
++      rtwdev->beacon_loss = received_beacons < expected_beacons / 2;
++}
++
+ /* process TX/RX statistics periodically for hardware,
+  * the information helps hardware to enhance performance
+  */
+@@ -212,6 +227,7 @@ static void rtw_watch_dog_work(struct wo
+       struct rtw_traffic_stats *stats = &rtwdev->stats;
+       struct rtw_watch_dog_iter_data data = {};
+       bool busy_traffic = test_bit(RTW_FLAG_BUSY_TRAFFIC, rtwdev->flags);
++      int received_beacons = rtwdev->dm_info.cur_pkt_count.num_bcn_pkt;
+       u32 tx_unicast_mbps, rx_unicast_mbps;
+       bool ps_active;
+@@ -270,6 +286,8 @@ static void rtw_watch_dog_work(struct wo
+        */
+       rtw_iterate_vifs(rtwdev, rtw_vif_watch_dog_iter, &data);
++      rtw_sw_beacon_loss_check(rtwdev, data.rtwvif, received_beacons);
++
+       /* fw supports only one station associated to enter lps, if there are
+        * more than two stations associated to the AP, then we can not enter
+        * lps, because fw does not handle the overlapped beacon interval
diff --git a/package/kernel/mac80211/patches/rtl/036-v6.13-wifi-rtw88-coex-Support-chips-without-a-scoreboard.patch b/package/kernel/mac80211/patches/rtl/036-v6.13-wifi-rtw88-coex-Support-chips-without-a-scoreboard.patch
new file mode 100644 (file)
index 0000000..b2fb04f
--- /dev/null
@@ -0,0 +1,66 @@
+From b19840afc05121293ae59f017cb9924814eb5d77 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 23 Oct 2024 17:14:12 +0300
+Subject: [PATCH] wifi: rtw88: coex: Support chips without a scoreboard
+
+All the chips currently supported have a "scoreboard": the chip keeps
+track of certain things related to bluetooth, for example, whether
+bluetooth is active. The information can be read from register 0xaa.
+
+RTL8821AU doesn't have this. Implement bluetooth activity detection in
+rtw_coex_monitor_bt_enable() based on the bluetooth TX/RX counters.
+
+This is mostly important for RTL8811AU, the version of RTL8821AU without
+bluetooth. Without this change, the driver thinks bluetooth is active
+and the wifi speeds are low.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/5058f23d-2086-42cd-82ad-eef31a348467@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/coex.c | 18 ++++++++++++++++++
+ drivers/net/wireless/realtek/rtw88/main.h |  1 +
+ 2 files changed, 19 insertions(+)
+
+--- a/drivers/net/wireless/realtek/rtw88/coex.c
++++ b/drivers/net/wireless/realtek/rtw88/coex.c
+@@ -494,11 +494,29 @@ static void rtw_coex_monitor_bt_enable(s
+       struct rtw_coex_stat *coex_stat = &coex->stat;
+       struct rtw_coex_dm *coex_dm = &coex->dm;
+       bool bt_disabled = false;
++      bool bt_active = true;
+       u16 score_board;
+       if (chip->scbd_support) {
+               score_board = rtw_coex_read_scbd(rtwdev);
+               bt_disabled = !(score_board & COEX_SCBD_ONOFF);
++      } else {
++              if (coex_stat->hi_pri_tx == 0 && coex_stat->hi_pri_rx == 0 &&
++                  coex_stat->lo_pri_tx == 0 && coex_stat->lo_pri_rx == 0)
++                      bt_active = false;
++
++              if (coex_stat->hi_pri_tx == 0xffff && coex_stat->hi_pri_rx == 0xffff &&
++                  coex_stat->lo_pri_tx == 0xffff && coex_stat->lo_pri_rx == 0xffff)
++                      bt_active = false;
++
++              if (bt_active) {
++                      coex_stat->bt_disable_cnt = 0;
++                      bt_disabled = false;
++              } else {
++                      coex_stat->bt_disable_cnt++;
++                      if (coex_stat->bt_disable_cnt >= 10)
++                              bt_disabled = true;
++              }
+       }
+       if (coex_stat->bt_disabled != bt_disabled) {
+--- a/drivers/net/wireless/realtek/rtw88/main.h
++++ b/drivers/net/wireless/realtek/rtw88/main.h
+@@ -1494,6 +1494,7 @@ struct rtw_coex_stat {
+       u8 bt_hid_slot;
+       u8 bt_a2dp_bitpool;
+       u8 bt_iqk_state;
++      u8 bt_disable_cnt;
+       u16 wl_beacon_interval;
+       u8 wl_noisy_level;
diff --git a/package/kernel/mac80211/patches/rtl/037-v6.13-wifi-rtw88-8821a-Regularly-ask-for-BT-info-updates.patch b/package/kernel/mac80211/patches/rtl/037-v6.13-wifi-rtw88-8821a-Regularly-ask-for-BT-info-updates.patch
new file mode 100644 (file)
index 0000000..e0e840f
--- /dev/null
@@ -0,0 +1,67 @@
+From bfcee5ee924fc5f706d20f5dc31586ca47912304 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 23 Oct 2024 17:14:45 +0300
+Subject: [PATCH] wifi: rtw88: 8821a: Regularly ask for BT info updates
+
+The RTL8821AU firmware sends C2H_BT_INFO by itself when bluetooth
+headphones are connected, but not when they are disconnected. This leads
+to the coexistence code still using the A2DP algorithm long after the
+headphones are disconnected, which means the wifi speeds are much lower
+than they should be. Work around this by asking for updates every two
+seconds if the chip is RTL8821AU.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/358acdd2-6aae-46c1-9c66-fcce4e700b96@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/coex.c |  2 +-
+ drivers/net/wireless/realtek/rtw88/coex.h | 11 +++++++++++
+ drivers/net/wireless/realtek/rtw88/main.c |  1 +
+ 3 files changed, 13 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/coex.c
++++ b/drivers/net/wireless/realtek/rtw88/coex.c
+@@ -446,7 +446,7 @@ static void rtw_coex_check_rfk(struct rt
+       }
+ }
+-static void rtw_coex_query_bt_info(struct rtw_dev *rtwdev)
++void rtw_coex_query_bt_info(struct rtw_dev *rtwdev)
+ {
+       struct rtw_coex *coex = &rtwdev->coex;
+       struct rtw_coex_stat *coex_stat = &coex->stat;
+--- a/drivers/net/wireless/realtek/rtw88/coex.h
++++ b/drivers/net/wireless/realtek/rtw88/coex.h
+@@ -384,6 +384,7 @@ u32 rtw_coex_read_indirect_reg(struct rt
+ void rtw_coex_write_indirect_reg(struct rtw_dev *rtwdev, u16 addr,
+                                u32 mask, u32 val);
+ void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set);
++void rtw_coex_query_bt_info(struct rtw_dev *rtwdev);
+ void rtw_coex_bt_relink_work(struct work_struct *work);
+ void rtw_coex_bt_reenable_work(struct work_struct *work);
+@@ -419,4 +420,14 @@ static inline bool rtw_coex_disabled(str
+       return coex_stat->bt_disabled;
+ }
++static inline void rtw_coex_active_query_bt_info(struct rtw_dev *rtwdev)
++{
++      /* The RTL8821AU firmware doesn't send C2H_BT_INFO by itself
++       * when bluetooth headphones are disconnected, so we have to
++       * ask for it regularly.
++       */
++      if (rtwdev->chip->id == RTW_CHIP_TYPE_8821A && rtwdev->efuse.btcoex)
++              rtw_coex_query_bt_info(rtwdev);
++}
++
+ #endif
+--- a/drivers/net/wireless/realtek/rtw88/main.c
++++ b/drivers/net/wireless/realtek/rtw88/main.c
+@@ -274,6 +274,7 @@ static void rtw_watch_dog_work(struct wo
+       rtw_leave_lps(rtwdev);
+       rtw_coex_wl_status_check(rtwdev);
+       rtw_coex_query_bt_hid_list(rtwdev);
++      rtw_coex_active_query_bt_info(rtwdev);
+       rtw_phy_dynamic_mechanism(rtwdev);
diff --git a/package/kernel/mac80211/patches/rtl/038-v6.13-wifi-rtw88-8812a-Mitigate-beacon-loss.patch b/package/kernel/mac80211/patches/rtl/038-v6.13-wifi-rtw88-8812a-Mitigate-beacon-loss.patch
new file mode 100644 (file)
index 0000000..f862f80
--- /dev/null
@@ -0,0 +1,37 @@
+From f9e0189cbc2d6447dde392944c769546cdf48140 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 23 Oct 2024 17:15:13 +0300
+Subject: [PATCH] wifi: rtw88: 8812a: Mitigate beacon loss
+
+The RTL8812AU has a reception problem, maybe only in the 5 GHz band.
+Sometimes, in some positions, it stops receiving anything even though
+the distance to the AP is only ~3 meters and there are no obstacles.
+Moving it a few centimeters fixes it.
+
+Switch the initial gain to maximum coverage when there is beacon loss.
+This only helps sometimes. This is similar to what the official driver
+does.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/203f5043-4fe1-4f35-8b8f-d3b6f44e1fd9@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/phy.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/net/wireless/realtek/rtw88/phy.c
++++ b/drivers/net/wireless/realtek/rtw88/phy.c
+@@ -530,6 +530,13 @@ static void rtw_phy_dig(struct rtw_dev *
+        */
+       rtw_phy_dig_recorder(dm_info, cur_igi, fa_cnt);
++      /* Mitigate beacon loss and connectivity issues, mainly (only?)
++       * in the 5 GHz band
++       */
++      if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A && rtwdev->beacon_loss &&
++          linked && dm_info->total_fa_cnt < DIG_PERF_FA_TH_EXTRA_HIGH)
++              cur_igi = DIG_CVRG_MIN;
++
+       if (cur_igi != pre_igi)
+               rtw_phy_dig_write(rtwdev, cur_igi);
+ }
diff --git a/package/kernel/mac80211/patches/rtl/039-v6.13-wifi-rtw88-Add-rtw8812a_table.-c-h.patch b/package/kernel/mac80211/patches/rtl/039-v6.13-wifi-rtw88-Add-rtw8812a_table.-c-h.patch
new file mode 100644 (file)
index 0000000..59a04b4
--- /dev/null
@@ -0,0 +1,2862 @@
+From 528f902ecc0eb8fb766bde519421255729623dd8 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 30 Oct 2024 20:24:33 +0200
+Subject: [PATCH] wifi: rtw88: Add rtw8812a_table.{c,h}
+
+These contain various arrays for initialising RTL8812AU. Also TX power
+limits.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/086f476c-e832-4867-963c-a64a63252fd6@gmail.com
+---
+ .../wireless/realtek/rtw88/rtw8812a_table.c   | 2812 +++++++++++++++++
+ .../wireless/realtek/rtw88/rtw8812a_table.h   |   26 +
+ 2 files changed, 2838 insertions(+)
+ create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8812a_table.c
+ create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8812a_table.h
+
+--- /dev/null
++++ b/drivers/net/wireless/realtek/rtw88/rtw8812a_table.c
+@@ -0,0 +1,2812 @@
++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
++/* Copyright(c) 2024  Realtek Corporation
++ */
++
++#include "main.h"
++#include "phy.h"
++#include "rtw8812a_table.h"
++
++static const u32 rtw8812a_mac[] = {
++      0x010, 0x0000000C,
++      0x80000200,     0x00000000,     0x40000000,     0x00000000,
++      0x011, 0x00000066,
++      0xA0000000,     0x00000000,
++      0x011, 0x0000005A,
++      0xB0000000,     0x00000000,
++      0x025, 0x0000000F,
++      0x072, 0x00000000,
++      0x420, 0x00000080,
++      0x428, 0x0000000A,
++      0x429, 0x00000010,
++      0x430, 0x00000000,
++      0x431, 0x00000000,
++      0x432, 0x00000000,
++      0x433, 0x00000001,
++      0x434, 0x00000002,
++      0x435, 0x00000003,
++      0x436, 0x00000005,
++      0x437, 0x00000007,
++      0x438, 0x00000000,
++      0x439, 0x00000000,
++      0x43A, 0x00000000,
++      0x43B, 0x00000001,
++      0x43C, 0x00000002,
++      0x43D, 0x00000003,
++      0x43E, 0x00000005,
++      0x43F, 0x00000007,
++      0x440, 0x0000005D,
++      0x441, 0x00000001,
++      0x442, 0x00000000,
++      0x444, 0x00000010,
++      0x445, 0x00000000,
++      0x446, 0x00000000,
++      0x447, 0x00000000,
++      0x448, 0x00000000,
++      0x449, 0x000000F0,
++      0x44A, 0x0000000F,
++      0x44B, 0x0000003E,
++      0x44C, 0x00000010,
++      0x44D, 0x00000000,
++      0x44E, 0x00000000,
++      0x44F, 0x00000000,
++      0x450, 0x00000000,
++      0x451, 0x000000F0,
++      0x452, 0x0000000F,
++      0x453, 0x00000000,
++      0x45B, 0x00000080,
++      0x460, 0x00000066,
++      0x461, 0x00000066,
++      0x4C8, 0x000000FF,
++      0x4C9, 0x00000008,
++      0x4CC, 0x000000FF,
++      0x4CD, 0x000000FF,
++      0x4CE, 0x00000001,
++      0x500, 0x00000026,
++      0x501, 0x000000A2,
++      0x502, 0x0000002F,
++      0x503, 0x00000000,
++      0x504, 0x00000028,
++      0x505, 0x000000A3,
++      0x506, 0x0000005E,
++      0x507, 0x00000000,
++      0x508, 0x0000002B,
++      0x509, 0x000000A4,
++      0x50A, 0x0000005E,
++      0x50B, 0x00000000,
++      0x50C, 0x0000004F,
++      0x50D, 0x000000A4,
++      0x50E, 0x00000000,
++      0x50F, 0x00000000,
++      0x512, 0x0000001C,
++      0x514, 0x0000000A,
++      0x516, 0x0000000A,
++      0x525, 0x0000004F,
++      0x550, 0x00000010,
++      0x551, 0x00000010,
++      0x559, 0x00000002,
++      0x55C, 0x00000050,
++      0x55D, 0x000000FF,
++      0x604, 0x00000009,
++      0x605, 0x00000030,
++      0x607, 0x00000003,
++      0x608, 0x0000000E,
++      0x609, 0x0000002A,
++      0x620, 0x000000FF,
++      0x621, 0x000000FF,
++      0x622, 0x000000FF,
++      0x623, 0x000000FF,
++      0x624, 0x000000FF,
++      0x625, 0x000000FF,
++      0x626, 0x000000FF,
++      0x627, 0x000000FF,
++      0x638, 0x00000050,
++      0x63C, 0x0000000A,
++      0x63D, 0x0000000A,
++      0x63E, 0x0000000E,
++      0x63F, 0x0000000E,
++      0x640, 0x00000080,
++      0x642, 0x00000040,
++      0x643, 0x00000000,
++      0x652, 0x000000C8,
++      0x66E, 0x00000005,
++      0x700, 0x00000021,
++      0x701, 0x00000043,
++      0x702, 0x00000065,
++      0x703, 0x00000087,
++      0x708, 0x00000021,
++      0x709, 0x00000043,
++      0x70A, 0x00000065,
++      0x70B, 0x00000087,
++      0x718, 0x00000040,
++};
++
++RTW_DECL_TABLE_PHY_COND(rtw8812a_mac, rtw_phy_cfg_mac);
++
++static const u32 rtw8812a_agc[] = {
++      0x80000001,     0x00000000,     0x40000000,     0x00000000,
++      0x81C, 0xFC000001,
++      0x81C, 0xFB020001,
++      0x81C, 0xFA040001,
++      0x81C, 0xF9060001,
++      0x81C, 0xF8080001,
++      0x81C, 0xF70A0001,
++      0x81C, 0xF60C0001,
++      0x81C, 0xF50E0001,
++      0x81C, 0xF4100001,
++      0x81C, 0xF3120001,
++      0x81C, 0xF2140001,
++      0x81C, 0xF1160001,
++      0x81C, 0xF0180001,
++      0x81C, 0xEF1A0001,
++      0x81C, 0xEE1C0001,
++      0x81C, 0xED1E0001,
++      0x81C, 0xEC200001,
++      0x81C, 0xEB220001,
++      0x81C, 0xEA240001,
++      0x81C, 0xCD260001,
++      0x81C, 0xCC280001,
++      0x81C, 0xCB2A0001,
++      0x81C, 0xCA2C0001,
++      0x81C, 0xC92E0001,
++      0x81C, 0xC8300001,
++      0x81C, 0xA6320001,
++      0x81C, 0xA5340001,
++      0x81C, 0xA4360001,
++      0x81C, 0xA3380001,
++      0x81C, 0xA23A0001,
++      0x81C, 0x883C0001,
++      0x81C, 0x873E0001,
++      0x81C, 0x86400001,
++      0x81C, 0x85420001,
++      0x81C, 0x84440001,
++      0x81C, 0x83460001,
++      0x81C, 0x82480001,
++      0x81C, 0x814A0001,
++      0x81C, 0x484C0001,
++      0x81C, 0x474E0001,
++      0x81C, 0x46500001,
++      0x81C, 0x45520001,
++      0x81C, 0x44540001,
++      0x81C, 0x43560001,
++      0x81C, 0x42580001,
++      0x81C, 0x415A0001,
++      0x81C, 0x255C0001,
++      0x81C, 0x245E0001,
++      0x81C, 0x23600001,
++      0x81C, 0x22620001,
++      0x81C, 0x21640001,
++      0x81C, 0x21660001,
++      0x81C, 0x21680001,
++      0x81C, 0x216A0001,
++      0x81C, 0x216C0001,
++      0x81C, 0x216E0001,
++      0x81C, 0x21700001,
++      0x81C, 0x21720001,
++      0x81C, 0x21740001,
++      0x81C, 0x21760001,
++      0x81C, 0x21780001,
++      0x81C, 0x217A0001,
++      0x81C, 0x217C0001,
++      0x81C, 0x217E0001,
++      0x90000001,     0x00000005,     0x40000000,     0x00000000,
++      0x81C, 0xF9000001,
++      0x81C, 0xF8020001,
++      0x81C, 0xF7040001,
++      0x81C, 0xF6060001,
++      0x81C, 0xF5080001,
++      0x81C, 0xF40A0001,
++      0x81C, 0xF30C0001,
++      0x81C, 0xF20E0001,
++      0x81C, 0xF1100001,
++      0x81C, 0xF0120001,
++      0x81C, 0xEF140001,
++      0x81C, 0xEE160001,
++      0x81C, 0xED180001,
++      0x81C, 0xEC1A0001,
++      0x81C, 0xEB1C0001,
++      0x81C, 0xEA1E0001,
++      0x81C, 0xCD200001,
++      0x81C, 0xCC220001,
++      0x81C, 0xCB240001,
++      0x81C, 0xCA260001,
++      0x81C, 0xC9280001,
++      0x81C, 0xC82A0001,
++      0x81C, 0xC72C0001,
++      0x81C, 0xC62E0001,
++      0x81C, 0xA5300001,
++      0x81C, 0xA4320001,
++      0x81C, 0xA3340001,
++      0x81C, 0xA2360001,
++      0x81C, 0x88380001,
++      0x81C, 0x873A0001,
++      0x81C, 0x863C0001,
++      0x81C, 0x853E0001,
++      0x81C, 0x84400001,
++      0x81C, 0x83420001,
++      0x81C, 0x82440001,
++      0x81C, 0x81460001,
++      0x81C, 0x48480001,
++      0x81C, 0x474A0001,
++      0x81C, 0x464C0001,
++      0x81C, 0x454E0001,
++      0x81C, 0x44500001,
++      0x81C, 0x43520001,
++      0x81C, 0x42540001,
++      0x81C, 0x41560001,
++      0x81C, 0x25580001,
++      0x81C, 0x245A0001,
++      0x81C, 0x235C0001,
++      0x81C, 0x225E0001,
++      0x81C, 0x21600001,
++      0x81C, 0x21620001,
++      0x81C, 0x21640001,
++      0x81C, 0x21660001,
++      0x81C, 0x21680001,
++      0x81C, 0x216A0001,
++      0x81C, 0x236C0001,
++      0x81C, 0x226E0001,
++      0x81C, 0x21700001,
++      0x81C, 0x21720001,
++      0x81C, 0x21740001,
++      0x81C, 0x21760001,
++      0x81C, 0x21780001,
++      0x81C, 0x217A0001,
++      0x81C, 0x217C0001,
++      0x81C, 0x217E0001,
++      0xA0000000,     0x00000000,
++      0x81C, 0xFF000001,
++      0x81C, 0xFF020001,
++      0x81C, 0xFF040001,
++      0x81C, 0xFF060001,
++      0x81C, 0xFF080001,
++      0x81C, 0xFE0A0001,
++      0x81C, 0xFD0C0001,
++      0x81C, 0xFC0E0001,
++      0x81C, 0xFB100001,
++      0x81C, 0xFA120001,
++      0x81C, 0xF9140001,
++      0x81C, 0xF8160001,
++      0x81C, 0xF7180001,
++      0x81C, 0xF61A0001,
++      0x81C, 0xF51C0001,
++      0x81C, 0xF41E0001,
++      0x81C, 0xF3200001,
++      0x81C, 0xF2220001,
++      0x81C, 0xF1240001,
++      0x81C, 0xF0260001,
++      0x81C, 0xEF280001,
++      0x81C, 0xEE2A0001,
++      0x81C, 0xED2C0001,
++      0x81C, 0xEC2E0001,
++      0x81C, 0xEB300001,
++      0x81C, 0xEA320001,
++      0x81C, 0xE9340001,
++      0x81C, 0xE8360001,
++      0x81C, 0xE7380001,
++      0x81C, 0xE63A0001,
++      0x81C, 0xE53C0001,
++      0x81C, 0xC73E0001,
++      0x81C, 0xC6400001,
++      0x81C, 0xC5420001,
++      0x81C, 0xC4440001,
++      0x81C, 0xC3460001,
++      0x81C, 0xC2480001,
++      0x81C, 0xC14A0001,
++      0x81C, 0xA74C0001,
++      0x81C, 0xA64E0001,
++      0x81C, 0xA5500001,
++      0x81C, 0xA4520001,
++      0x81C, 0xA3540001,
++      0x81C, 0xA2560001,
++      0x81C, 0xA1580001,
++      0x81C, 0x675A0001,
++      0x81C, 0x665C0001,
++      0x81C, 0x655E0001,
++      0x81C, 0x64600001,
++      0x81C, 0x63620001,
++      0x81C, 0x48640001,
++      0x81C, 0x47660001,
++      0x81C, 0x46680001,
++      0x81C, 0x456A0001,
++      0x81C, 0x446C0001,
++      0x81C, 0x436E0001,
++      0x81C, 0x42700001,
++      0x81C, 0x41720001,
++      0x81C, 0x41740001,
++      0x81C, 0x41760001,
++      0x81C, 0x41780001,
++      0x81C, 0x417A0001,
++      0x81C, 0x417C0001,
++      0x81C, 0x417E0001,
++      0xB0000000,     0x00000000,
++      0x80000004,     0x00000000,     0x40000000,     0x00000000,
++      0x81C, 0xFC800001,
++      0x81C, 0xFB820001,
++      0x81C, 0xFA840001,
++      0x81C, 0xF9860001,
++      0x81C, 0xF8880001,
++      0x81C, 0xF78A0001,
++      0x81C, 0xF68C0001,
++      0x81C, 0xF58E0001,
++      0x81C, 0xF4900001,
++      0x81C, 0xF3920001,
++      0x81C, 0xF2940001,
++      0x81C, 0xF1960001,
++      0x81C, 0xF0980001,
++      0x81C, 0xEF9A0001,
++      0x81C, 0xEE9C0001,
++      0x81C, 0xED9E0001,
++      0x81C, 0xECA00001,
++      0x81C, 0xEBA20001,
++      0x81C, 0xEAA40001,
++      0x81C, 0xE9A60001,
++      0x81C, 0xE8A80001,
++      0x81C, 0xE7AA0001,
++      0x81C, 0xE6AC0001,
++      0x81C, 0xE5AE0001,
++      0x81C, 0xE4B00001,
++      0x81C, 0xE3B20001,
++      0x81C, 0xA8B40001,
++      0x81C, 0xA7B60001,
++      0x81C, 0xA6B80001,
++      0x81C, 0xA5BA0001,
++      0x81C, 0xA4BC0001,
++      0x81C, 0xA3BE0001,
++      0x81C, 0xA2C00001,
++      0x81C, 0xA1C20001,
++      0x81C, 0x68C40001,
++      0x81C, 0x67C60001,
++      0x81C, 0x66C80001,
++      0x81C, 0x65CA0001,
++      0x81C, 0x64CC0001,
++      0x81C, 0x47CE0001,
++      0x81C, 0x46D00001,
++      0x81C, 0x45D20001,
++      0x81C, 0x44D40001,
++      0x81C, 0x43D60001,
++      0x81C, 0x42D80001,
++      0x81C, 0x08DA0001,
++      0x81C, 0x07DC0001,
++      0x81C, 0x06DE0001,
++      0x81C, 0x05E00001,
++      0x81C, 0x04E20001,
++      0x81C, 0x03E40001,
++      0x81C, 0x02E60001,
++      0x81C, 0x01E80001,
++      0x81C, 0x01EA0001,
++      0x81C, 0x01EC0001,
++      0x81C, 0x01EE0001,
++      0x81C, 0x01F00001,
++      0x81C, 0x01F20001,
++      0x81C, 0x01F40001,
++      0x81C, 0x01F60001,
++      0x81C, 0x01F80001,
++      0x81C, 0x01FA0001,
++      0x81C, 0x01FC0001,
++      0x81C, 0x01FE0001,
++      0xA0000000,     0x00000000,
++      0x81C, 0xFF800001,
++      0x81C, 0xFF820001,
++      0x81C, 0xFF840001,
++      0x81C, 0xFE860001,
++      0x81C, 0xFD880001,
++      0x81C, 0xFC8A0001,
++      0x81C, 0xFB8C0001,
++      0x81C, 0xFA8E0001,
++      0x81C, 0xF9900001,
++      0x81C, 0xF8920001,
++      0x81C, 0xF7940001,
++      0x81C, 0xF6960001,
++      0x81C, 0xF5980001,
++      0x81C, 0xF49A0001,
++      0x81C, 0xF39C0001,
++      0x81C, 0xF29E0001,
++      0x81C, 0xF1A00001,
++      0x81C, 0xF0A20001,
++      0x81C, 0xEFA40001,
++      0x81C, 0xEEA60001,
++      0x81C, 0xEDA80001,
++      0x81C, 0xECAA0001,
++      0x81C, 0xEBAC0001,
++      0x81C, 0xEAAE0001,
++      0x81C, 0xE9B00001,
++      0x81C, 0xE8B20001,
++      0x81C, 0xE7B40001,
++      0x81C, 0xE6B60001,
++      0x81C, 0xE5B80001,
++      0x81C, 0xE4BA0001,
++      0x81C, 0xE3BC0001,
++      0x81C, 0xA8BE0001,
++      0x81C, 0xA7C00001,
++      0x81C, 0xA6C20001,
++      0x81C, 0xA5C40001,
++      0x81C, 0xA4C60001,
++      0x81C, 0xA3C80001,
++      0x81C, 0xA2CA0001,
++      0x81C, 0xA1CC0001,
++      0x81C, 0x68CE0001,
++      0x81C, 0x67D00001,
++      0x81C, 0x66D20001,
++      0x81C, 0x65D40001,
++      0x81C, 0x64D60001,
++      0x81C, 0x47D80001,
++      0x81C, 0x46DA0001,
++      0x81C, 0x45DC0001,
++      0x81C, 0x44DE0001,
++      0x81C, 0x43E00001,
++      0x81C, 0x42E20001,
++      0x81C, 0x08E40001,
++      0x81C, 0x07E60001,
++      0x81C, 0x06E80001,
++      0x81C, 0x05EA0001,
++      0x81C, 0x04EC0001,
++      0x81C, 0x03EE0001,
++      0x81C, 0x02F00001,
++      0x81C, 0x01F20001,
++      0x81C, 0x01F40001,
++      0x81C, 0x01F60001,
++      0x81C, 0x01F80001,
++      0x81C, 0x01FA0001,
++      0x81C, 0x01FC0001,
++      0x81C, 0x01FE0001,
++      0xB0000000,     0x00000000,
++      0xC50, 0x00000022,
++      0xC50, 0x00000020,
++      0xE50, 0x00000022,
++      0xE50, 0x00000020,
++};
++
++RTW_DECL_TABLE_PHY_COND(rtw8812a_agc, rtw_phy_cfg_agc);
++
++static const u32 rtw8812a_agc_diff_lb[] = {
++      0x80000004,     0x00000000,     0x40000000,     0x00000000,
++      0x81C, 0x47CE0001,
++      0x81C, 0x46D00001,
++      0x81C, 0x45D20001,
++      0x81C, 0x44D40001,
++      0x81C, 0x43D60001,
++      0x81C, 0x42D80001,
++      0x81C, 0x08DA0001,
++      0x81C, 0x07DC0001,
++      0x81C, 0x06DE0001,
++      0x81C, 0x05E00001,
++      0x81C, 0x04E20001,
++      0x81C, 0x03E40001,
++      0x81C, 0x02E60001,
++      0xA0000000,     0x00000000,
++      0x81C, 0x47D80001,
++      0x81C, 0x46DA0001,
++      0x81C, 0x45DC0001,
++      0x81C, 0x44DE0001,
++      0x81C, 0x43E00001,
++      0x81C, 0x42E20001,
++      0x81C, 0x08E40001,
++      0x81C, 0x07E60001,
++      0x81C, 0x06E80001,
++      0x81C, 0x05EA0001,
++      0x81C, 0x04EC0001,
++      0x81C, 0x03EE0001,
++      0x81C, 0x02F00001,
++      0xB0000000,     0x00000000,
++};
++
++RTW_DECL_TABLE_PHY_COND(rtw8812a_agc_diff_lb, rtw_phy_cfg_agc);
++
++static const u32 rtw8812a_agc_diff_hb[] = {
++      0x80000004,     0x00000000,     0x40000000,     0x00000000,
++      0x81C, 0x45CE0001,
++      0x81C, 0x44D00001,
++      0x81C, 0x43D20001,
++      0x81C, 0x42D40001,
++      0x81C, 0x08D60001,
++      0x81C, 0x07D80001,
++      0x81C, 0x06DA0001,
++      0x81C, 0x05DC0001,
++      0x81C, 0x04DE0001,
++      0x81C, 0x03E00001,
++      0x81C, 0x02E20001,
++      0x81C, 0x01E40001,
++      0x81C, 0x01E60001,
++      0xA0000000,     0x00000000,
++      0x81C, 0x45D80001,
++      0x81C, 0x44DA0001,
++      0x81C, 0x43DC0001,
++      0x81C, 0x42DE0001,
++      0x81C, 0x08E00001,
++      0x81C, 0x07E20001,
++      0x81C, 0x06E40001,
++      0x81C, 0x05E60001,
++      0x81C, 0x04E80001,
++      0x81C, 0x03EA0001,
++      0x81C, 0x02EC0001,
++      0x81C, 0x01EE0001,
++      0x81C, 0x01F00001,
++      0xB0000000,     0x00000000,
++};
++
++RTW_DECL_TABLE_PHY_COND(rtw8812a_agc_diff_hb, rtw_phy_cfg_agc);
++
++static const u32 rtw8812a_bb[] = {
++      0x800, 0x8020D010,
++      0x804, 0x080112E0,
++      0x808, 0x0E028233,
++      0x80C, 0x12131113,
++      0x810, 0x20101263,
++      0x814, 0x020C3D10,
++      0x818, 0x03A00385,
++      0x820, 0x00000000,
++      0x824, 0x00030FE0,
++      0x828, 0x00000000,
++      0x82C, 0x002083DD,
++      0x830, 0x2EAAEEB8,
++      0x834, 0x0037A706,
++      0x838, 0x06C89B44,
++      0x83C, 0x0000095B,
++      0x840, 0xC0000001,
++      0x844, 0x40003CDE,
++      0x848, 0x6210FF8B,
++      0x84C, 0x6CFDFFB8,
++      0x850, 0x28874706,
++      0x854, 0x0001520C,
++      0x858, 0x8060E000,
++      0x85C, 0x74210168,
++      0x860, 0x6929C321,
++      0x864, 0x79727432,
++      0x868, 0x8CA7A314,
++      0x86C, 0x338C2878,
++      0x870, 0x03333333,
++      0x874, 0x31602C2E,
++      0x878, 0x00003152,
++      0x87C, 0x000FC000,
++      0x8A0, 0x00000013,
++      0x8A4, 0x7F7F7F7F,
++      0x8A8, 0xA202033E,
++      0x8AC, 0x0FF0FA0A,
++      0x8B0, 0x00000600,
++      0x8B4, 0x000FC080,
++      0x8B8, 0x6C10D7FF,
++      0x8BC, 0x4CA520A3,
++      0x8C0, 0x27F00020,
++      0x8C4, 0x00000000,
++      0x8C8, 0x00012D69,
++      0x8CC, 0x08248492,
++      0x8D0, 0x0000B800,
++      0x8DC, 0x00000000,
++      0x8D4, 0x940008A0,
++      0x8D8, 0x290B5612,
++      0x8F8, 0x400002C0,
++      0x8FC, 0x00000000,
++      0x900, 0x00000701,
++      0x90C, 0x00000000,
++      0x910, 0x0000FC00,
++      0x914, 0x00000404,
++      0x918, 0x1C1028C0,
++      0x91C, 0x64B11A1C,
++      0x920, 0xE0767233,
++      0x924, 0x055AA500,
++      0x928, 0x00000004,
++      0x92C, 0xFFFE0000,
++      0x930, 0xFFFFFFFE,
++      0x934, 0x001FFFFF,
++      0x960, 0x00000000,
++      0x964, 0x00000000,
++      0x968, 0x00000000,
++      0x96C, 0x00000000,
++      0x970, 0x801FFFFF,
++      0x978, 0x00000000,
++      0x97C, 0x00000000,
++      0x980, 0x00000000,
++      0x984, 0x00000000,
++      0x988, 0x00000000,
++      0x990, 0x27100000,
++      0x994, 0xFFFF0100,
++      0x998, 0xFFFFFF5C,
++      0x99C, 0xFFFFFFFF,
++      0x9A0, 0x000000FF,
++      0x9A4, 0x00080080,
++      0x9A8, 0x00000000,
++      0x9AC, 0x00000000,
++      0x9B0, 0x81081008,
++      0x9B4, 0x00000000,
++      0x9B8, 0x01081008,
++      0x9BC, 0x01081008,
++      0x9D0, 0x00000000,
++      0x9D4, 0x00000000,
++      0x9D8, 0x00000000,
++      0x9DC, 0x00000000,
++      0x9E4, 0x00000003,
++      0x9E8, 0x000002D5,
++      0xA00, 0x00D047C8,
++      0xA04, 0x01FF000C,
++      0xA08, 0x8C838300,
++      0xA0C, 0x2E7F000F,
++      0xA10, 0x9500BB78,
++      0xA14, 0x11144028,
++      0xA18, 0x00881117,
++      0xA1C, 0x89140F00,
++      0xA20, 0x1A1B0000,
++      0xA24, 0x090E1217,
++      0xA28, 0x00000305,
++      0xA2C, 0x00900000,
++      0xA70, 0x101FFF00,
++      0xA74, 0x00000008,
++      0xA78, 0x00000900,
++      0xA7C, 0x225B0606,
++      0xA80, 0x218075B2,
++      0xA84, 0x001F8C80,
++      0xB00, 0x03100000,
++      0xB04, 0x0000B000,
++      0xB08, 0xAE0201EB,
++      0xB0C, 0x01003207,
++      0xB10, 0x00009807,
++      0xB14, 0x01000000,
++      0xB18, 0x00000002,
++      0xB1C, 0x00000002,
++      0xB20, 0x0000001F,
++      0xB24, 0x03020100,
++      0xB28, 0x07060504,
++      0xB2C, 0x0B0A0908,
++      0xB30, 0x0F0E0D0C,
++      0xB34, 0x13121110,
++      0xB38, 0x17161514,
++      0xB3C, 0x0000003A,
++      0xB40, 0x00000000,
++      0xB44, 0x00000000,
++      0xB48, 0x13000032,
++      0xB4C, 0x48080000,
++      0xB50, 0x00000000,
++      0xB54, 0x00000000,
++      0xB58, 0x00000000,
++      0xB5C, 0x00000000,
++      0xC00, 0x00000007,
++      0xC04, 0x00042020,
++      0xC08, 0x80410231,
++      0xC0C, 0x00000000,
++      0xC10, 0x00000100,
++      0xC14, 0x01000000,
++      0xC1C, 0x40000003,
++      0xC20, 0x12121212,
++      0xC24, 0x12121212,
++      0xC28, 0x12121212,
++      0xC2C, 0x12121212,
++      0xC30, 0x12121212,
++      0xC34, 0x12121212,
++      0xC38, 0x12121212,
++      0xC3C, 0x12121212,
++      0xC40, 0x12121212,
++      0xC44, 0x12121212,
++      0xC48, 0x12121212,
++      0xC4C, 0x12121212,
++      0xC50, 0x00000020,
++      0xC54, 0x0008121C,
++      0xC58, 0x30000C1C,
++      0xC5C, 0x00000058,
++      0xC60, 0x34344443,
++      0xC64, 0x07003333,
++      0x80000008,     0x00000000,     0x40000000,     0x00000000,
++      0xC68, 0x59791979,
++      0x90000008,     0x05000000,     0x40000000,     0x00000000,
++      0xC68, 0x59791979,
++      0x90000002,     0x00000000,     0x40000000,     0x00000000,
++      0xC68, 0x59791979,
++      0x90000004,     0x00000000,     0x40000000,     0x00000000,
++      0xC68, 0x59791979,
++      0x90000001,     0x00000000,     0x40000000,     0x00000000,
++      0xC68, 0x59791979,
++      0x90000001,     0x00000005,     0x40000000,     0x00000000,
++      0xC68, 0x59791979,
++      0xA0000000,     0x00000000,
++      0xC68, 0x59799979,
++      0xB0000000,     0x00000000,
++      0xC6C, 0x59795979,
++      0xC70, 0x19795979,
++      0xC74, 0x19795979,
++      0xC78, 0x19791979,
++      0xC7C, 0x19791979,
++      0xC80, 0x19791979,
++      0xC84, 0x19791979,
++      0xC94, 0x0100005C,
++      0xC98, 0x00000000,
++      0xC9C, 0x00000000,
++      0xCA0, 0x00000029,
++      0xCA4, 0x08040201,
++      0xCA8, 0x80402010,
++      0xCB0, 0x77547777,
++      0xCB4, 0x00000077,
++      0xCB8, 0x00508242,
++      0xE00, 0x00000007,
++      0xE04, 0x00042020,
++      0xE08, 0x80410231,
++      0xE0C, 0x00000000,
++      0xE10, 0x00000100,
++      0xE14, 0x01000000,
++      0xE1C, 0x40000003,
++      0xE20, 0x12121212,
++      0xE24, 0x12121212,
++      0xE28, 0x12121212,
++      0xE2C, 0x12121212,
++      0xE30, 0x12121212,
++      0xE34, 0x12121212,
++      0xE38, 0x12121212,
++      0xE3C, 0x12121212,
++      0xE40, 0x12121212,
++      0xE44, 0x12121212,
++      0xE48, 0x12121212,
++      0xE4C, 0x12121212,
++      0xE50, 0x00000020,
++      0xE54, 0x0008121C,
++      0xE58, 0x30000C1C,
++      0xE5C, 0x00000058,
++      0xE60, 0x34344443,
++      0xE64, 0x07003333,
++      0xE68, 0x59791979,
++      0xE6C, 0x59795979,
++      0xE70, 0x19795979,
++      0xE74, 0x19795979,
++      0xE78, 0x19791979,
++      0xE7C, 0x19791979,
++      0xE80, 0x19791979,
++      0xE84, 0x19791979,
++      0xE94, 0x0100005C,
++      0xE98, 0x00000000,
++      0xE9C, 0x00000000,
++      0xEA0, 0x00000029,
++      0xEA4, 0x08040201,
++      0xEA8, 0x80402010,
++      0xEB0, 0x77547777,
++      0xEB4, 0x00000077,
++      0xEB8, 0x00508242,
++};
++
++RTW_DECL_TABLE_PHY_COND(rtw8812a_bb, rtw_phy_cfg_bb);
++
++static const struct rtw_phy_pg_cfg_pair rtw8812a_bb_pg[] = {
++      { 0, 0, 0, 0x00000c20, 0xffffffff, 0x34363840, },
++      { 0, 0, 0, 0x00000c24, 0xffffffff, 0x42424444, },
++      { 0, 0, 0, 0x00000c28, 0xffffffff, 0x30323638, },
++      { 0, 0, 0, 0x00000c2c, 0xffffffff, 0x40424444, },
++      { 0, 0, 0, 0x00000c30, 0xffffffff, 0x28303236, },
++      { 0, 0, 1, 0x00000c34, 0xffffffff, 0x38404242, },
++      { 0, 0, 1, 0x00000c38, 0xffffffff, 0x26283034, },
++      { 0, 0, 0, 0x00000c3c, 0xffffffff, 0x40424444, },
++      { 0, 0, 0, 0x00000c40, 0xffffffff, 0x28303236, },
++      { 0, 0, 0, 0x00000c44, 0xffffffff, 0x42422426, },
++      { 0, 0, 1, 0x00000c48, 0xffffffff, 0x30343840, },
++      { 0, 0, 1, 0x00000c4c, 0xffffffff, 0x22242628, },
++      { 0, 1, 0, 0x00000e20, 0xffffffff, 0x34363840, },
++      { 0, 1, 0, 0x00000e24, 0xffffffff, 0x42424444, },
++      { 0, 1, 0, 0x00000e28, 0xffffffff, 0x30323638, },
++      { 0, 1, 0, 0x00000e2c, 0xffffffff, 0x40424444, },
++      { 0, 1, 0, 0x00000e30, 0xffffffff, 0x28303236, },
++      { 0, 1, 1, 0x00000e34, 0xffffffff, 0x38404242, },
++      { 0, 1, 1, 0x00000e38, 0xffffffff, 0x26283034, },
++      { 0, 1, 0, 0x00000e3c, 0xffffffff, 0x40424444, },
++      { 0, 1, 0, 0x00000e40, 0xffffffff, 0x28303236, },
++      { 0, 1, 0, 0x00000e44, 0xffffffff, 0x42422426, },
++      { 0, 1, 1, 0x00000e48, 0xffffffff, 0x30343840, },
++      { 0, 1, 1, 0x00000e4c, 0xffffffff, 0x22242628, },
++      { 1, 0, 0, 0x00000c24, 0xffffffff, 0x42424444, },
++      { 1, 0, 0, 0x00000c28, 0xffffffff, 0x30323640, },
++      { 1, 0, 0, 0x00000c2c, 0xffffffff, 0x40424444, },
++      { 1, 0, 0, 0x00000c30, 0xffffffff, 0x28303236, },
++      { 1, 0, 1, 0x00000c34, 0xffffffff, 0x38404242, },
++      { 1, 0, 1, 0x00000c38, 0xffffffff, 0x26283034, },
++      { 1, 0, 0, 0x00000c3c, 0xffffffff, 0x40424444, },
++      { 1, 0, 0, 0x00000c40, 0xffffffff, 0x28303236, },
++      { 1, 0, 0, 0x00000c44, 0xffffffff, 0x42422426, },
++      { 1, 0, 1, 0x00000c48, 0xffffffff, 0x30343840, },
++      { 1, 0, 1, 0x00000c4c, 0xffffffff, 0x22242628, },
++      { 1, 1, 0, 0x00000e24, 0xffffffff, 0x42424444, },
++      { 1, 1, 0, 0x00000e28, 0xffffffff, 0x30323640, },
++      { 1, 1, 0, 0x00000e2c, 0xffffffff, 0x40424444, },
++      { 1, 1, 0, 0x00000e30, 0xffffffff, 0x28303236, },
++      { 1, 1, 1, 0x00000e34, 0xffffffff, 0x38404242, },
++      { 1, 1, 1, 0x00000e38, 0xffffffff, 0x26283034, },
++      { 1, 1, 0, 0x00000e3c, 0xffffffff, 0x40424444, },
++      { 1, 1, 0, 0x00000e40, 0xffffffff, 0x28303236, },
++      { 1, 1, 0, 0x00000e44, 0xffffffff, 0x42422426, },
++      { 1, 1, 1, 0x00000e48, 0xffffffff, 0x30343840, },
++      { 1, 1, 1, 0x00000e4c, 0xffffffff, 0x22242628, },
++};
++
++RTW_DECL_TABLE_BB_PG(rtw8812a_bb_pg);
++
++static const struct rtw_phy_pg_cfg_pair rtw8812a_bb_pg_rfe3[] = {
++      { 0, 0, 0, 0x00000c20, 0xffffffff, 0x34343434, },
++      { 0, 0, 0, 0x00000c24, 0xffffffff, 0x32323232, },
++      { 0, 0, 0, 0x00000c28, 0xffffffff, 0x28303232, },
++      { 0, 0, 0, 0x00000c2c, 0xffffffff, 0x32323232, },
++      { 0, 0, 0, 0x00000c30, 0xffffffff, 0x28303232, },
++      { 0, 0, 1, 0x00000c34, 0xffffffff, 0x32323232, },
++      { 0, 0, 1, 0x00000c38, 0xffffffff, 0x26283032, },
++      { 0, 0, 0, 0x00000c3c, 0xffffffff, 0x32323232, },
++      { 0, 0, 0, 0x00000c40, 0xffffffff, 0x28303232, },
++      { 0, 0, 0, 0x00000c44, 0xffffffff, 0x32322426, },
++      { 0, 0, 1, 0x00000c48, 0xffffffff, 0x32323232, },
++      { 0, 0, 1, 0x00000c4c, 0xffffffff, 0x24262830, },
++      { 0, 1, 0, 0x00000e20, 0xffffffff, 0x34343434, },
++      { 0, 1, 0, 0x00000e24, 0xffffffff, 0x32323232, },
++      { 0, 1, 0, 0x00000e28, 0xffffffff, 0x28303232, },
++      { 0, 1, 0, 0x00000e2c, 0xffffffff, 0x32323232, },
++      { 0, 1, 0, 0x00000e30, 0xffffffff, 0x28303232, },
++      { 0, 1, 1, 0x00000e34, 0xffffffff, 0x32323232, },
++      { 0, 1, 1, 0x00000e38, 0xffffffff, 0x26283032, },
++      { 0, 1, 0, 0x00000e3c, 0xffffffff, 0x32323232, },
++      { 0, 1, 0, 0x00000e40, 0xffffffff, 0x28303232, },
++      { 0, 1, 0, 0x00000e44, 0xffffffff, 0x32322426, },
++      { 0, 1, 1, 0x00000e48, 0xffffffff, 0x32323232, },
++      { 0, 1, 1, 0x00000e4c, 0xffffffff, 0x24262830, },
++      { 1, 0, 0, 0x00000c24, 0xffffffff, 0x32323232, },
++      { 1, 0, 0, 0x00000c28, 0xffffffff, 0x28303232, },
++      { 1, 0, 0, 0x00000c2c, 0xffffffff, 0x32323232, },
++      { 1, 0, 0, 0x00000c30, 0xffffffff, 0x24262830, },
++      { 1, 0, 1, 0x00000c34, 0xffffffff, 0x32323232, },
++      { 1, 0, 1, 0x00000c38, 0xffffffff, 0x24262830, },
++      { 1, 0, 0, 0x00000c3c, 0xffffffff, 0x32323232, },
++      { 1, 0, 0, 0x00000c40, 0xffffffff, 0x24262830, },
++      { 1, 0, 0, 0x00000c44, 0xffffffff, 0x32322222, },
++      { 1, 0, 1, 0x00000c48, 0xffffffff, 0x28303232, },
++      { 1, 0, 1, 0x00000c4c, 0xffffffff, 0x22222426, },
++      { 1, 1, 0, 0x00000e24, 0xffffffff, 0x32323232, },
++      { 1, 1, 0, 0x00000e28, 0xffffffff, 0x28303232, },
++      { 1, 1, 0, 0x00000e2c, 0xffffffff, 0x32323232, },
++      { 1, 1, 0, 0x00000e30, 0xffffffff, 0x24262830, },
++      { 1, 1, 1, 0x00000e34, 0xffffffff, 0x32323232, },
++      { 1, 1, 1, 0x00000e38, 0xffffffff, 0x24262830, },
++      { 1, 1, 0, 0x00000e3c, 0xffffffff, 0x32323232, },
++      { 1, 1, 0, 0x00000e40, 0xffffffff, 0x24262830, },
++      { 1, 1, 0, 0x00000e44, 0xffffffff, 0x32322222, },
++      { 1, 1, 1, 0x00000e48, 0xffffffff, 0x28303232, },
++      { 1, 1, 1, 0x00000e4c, 0xffffffff, 0x22222426, },
++};
++
++RTW_DECL_TABLE_BB_PG(rtw8812a_bb_pg_rfe3);
++
++static const u32 rtw8812a_rf_a[] = {
++      0x000, 0x00010000,
++      0x018, 0x0001712A,
++      0x056, 0x00051CF2,
++      0x066, 0x00040000,
++      0x01E, 0x00080000,
++      0x089, 0x00000080,
++      0x80000001,     0x00000000,     0x40000000,     0x00000000,
++      0x086, 0x00014B3A,
++      0x90000001,     0x00000005,     0x40000000,     0x00000000,
++      0x086, 0x00014B3A,
++      0xA0000000,     0x00000000,
++      0x086, 0x00014B38,
++      0xB0000000,     0x00000000,
++      0x80000004,     0x00000000,     0x40000000,     0x00000000,
++      0x08B, 0x00080180,
++      0xA0000000,     0x00000000,
++      0x08B, 0x00087180,
++      0xB0000000,     0x00000000,
++      0x0B1, 0x0001FC1A,
++      0x0B3, 0x000F0810,
++      0x0B4, 0x0001A78D,
++      0x0BA, 0x00086180,
++      0x018, 0x00000006,
++      0x0EF, 0x00002000,
++      0x80000001,     0x00000000,     0x40000000,     0x00000000,
++      0x03B, 0x0003F218,
++      0x03B, 0x00030A58,
++      0x03B, 0x0002FA58,
++      0x03B, 0x00022590,
++      0x03B, 0x0001FA50,
++      0x03B, 0x00010248,
++      0x03B, 0x00008240,
++      0x90000001,     0x00000005,     0x40000000,     0x00000000,
++      0x03B, 0x0003F218,
++      0x03B, 0x00030A58,
++      0x03B, 0x0002FA58,
++      0x03B, 0x00022590,
++      0x03B, 0x0001FA50,
++      0x03B, 0x00010248,
++      0x03B, 0x00008240,
++      0xA0000000,     0x00000000,
++      0x03B, 0x00038A58,
++      0x03B, 0x00037A58,
++      0x03B, 0x0002A590,
++      0x03B, 0x00027A50,
++      0x03B, 0x00018248,
++      0x03B, 0x00010240,
++      0x03B, 0x00008240,
++      0xB0000000,     0x00000000,
++      0x0EF, 0x00000100,
++      0x80000002,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0000A4EE,
++      0x034, 0x00009076,
++      0x034, 0x00008073,
++      0x034, 0x00007070,
++      0x034, 0x0000606D,
++      0x034, 0x0000506A,
++      0x034, 0x00004049,
++      0x034, 0x00003046,
++      0x034, 0x00002028,
++      0x034, 0x00001025,
++      0x034, 0x00000022,
++      0xA0000000,     0x00000000,
++      0x034, 0x0000ADF4,
++      0x034, 0x00009DF1,
++      0x034, 0x00008DEE,
++      0x034, 0x00007DEB,
++      0x034, 0x00006DE8,
++      0x034, 0x00005DE5,
++      0x034, 0x00004DE2,
++      0x034, 0x00003CE6,
++      0x034, 0x000024E7,
++      0x034, 0x000014E4,
++      0x034, 0x000004E1,
++      0xB0000000,     0x00000000,
++      0x0EF, 0x00000000,
++      0x0EF, 0x000020A2,
++      0x0DF, 0x00000080,
++      0x035, 0x00000192,
++      0x035, 0x00008192,
++      0x035, 0x00010192,
++      0x036, 0x00000024,
++      0x036, 0x00008024,
++      0x036, 0x00010024,
++      0x036, 0x00018024,
++      0x0EF, 0x00000000,
++      0x051, 0x00000C21,
++      0x052, 0x000006D9,
++      0x053, 0x000FC649,
++      0x054, 0x0000017E,
++      0x0EF, 0x00000002,
++      0x008, 0x00008400,
++      0x018, 0x0001712A,
++      0x0EF, 0x00001000,
++      0x03A, 0x00000080,
++      0x03B, 0x0003A02C,
++      0x03C, 0x00004000,
++      0x03A, 0x00000400,
++      0x03B, 0x0003202C,
++      0x03C, 0x00010000,
++      0x03A, 0x000000A0,
++      0x03B, 0x0002B064,
++      0x03C, 0x00004000,
++      0x03A, 0x000000D8,
++      0x03B, 0x00023070,
++      0x03C, 0x00004000,
++      0x03A, 0x00000468,
++      0x03B, 0x0001B870,
++      0x03C, 0x00010000,
++      0x03A, 0x00000098,
++      0x03B, 0x00012085,
++      0x03C, 0x000E4000,
++      0x03A, 0x00000418,
++      0x03B, 0x0000A080,
++      0x03C, 0x000F0000,
++      0x03A, 0x00000418,
++      0x03B, 0x00002080,
++      0x03C, 0x00010000,
++      0x03A, 0x00000080,
++      0x03B, 0x0007A02C,
++      0x03C, 0x00004000,
++      0x03A, 0x00000400,
++      0x03B, 0x0007202C,
++      0x03C, 0x00010000,
++      0x03A, 0x000000A0,
++      0x03B, 0x0006B064,
++      0x03C, 0x00004000,
++      0x03A, 0x000000D8,
++      0x03B, 0x00063070,
++      0x03C, 0x00004000,
++      0x03A, 0x00000468,
++      0x03B, 0x0005B870,
++      0x03C, 0x00010000,
++      0x03A, 0x00000098,
++      0x03B, 0x00052085,
++      0x03C, 0x000E4000,
++      0x03A, 0x00000418,
++      0x03B, 0x0004A080,
++      0x03C, 0x000F0000,
++      0x03A, 0x00000418,
++      0x03B, 0x00042080,
++      0x03C, 0x00010000,
++      0x03A, 0x00000080,
++      0x03B, 0x000BA02C,
++      0x03C, 0x00004000,
++      0x03A, 0x00000400,
++      0x03B, 0x000B202C,
++      0x03C, 0x00010000,
++      0x03A, 0x000000A0,
++      0x03B, 0x000AB064,
++      0x03C, 0x00004000,
++      0x03A, 0x000000D8,
++      0x03B, 0x000A3070,
++      0x03C, 0x00004000,
++      0x03A, 0x00000468,
++      0x03B, 0x0009B870,
++      0x03C, 0x00010000,
++      0x03A, 0x00000098,
++      0x03B, 0x00092085,
++      0x03C, 0x000E4000,
++      0x03A, 0x00000418,
++      0x03B, 0x0008A080,
++      0x03C, 0x000F0000,
++      0x03A, 0x00000418,
++      0x03B, 0x00082080,
++      0x03C, 0x00010000,
++      0x0EF, 0x00001100,
++      0x80000008,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0004A0B2,
++      0x034, 0x000490AF,
++      0x034, 0x00048070,
++      0x034, 0x0004706D,
++      0x034, 0x00046050,
++      0x034, 0x0004504D,
++      0x034, 0x0004404A,
++      0x034, 0x00043047,
++      0x034, 0x0004200A,
++      0x034, 0x00041007,
++      0x034, 0x00040004,
++      0x90000008,     0x05000000,     0x40000000,     0x00000000,
++      0x034, 0x0004A0B2,
++      0x034, 0x000490AF,
++      0x034, 0x00048070,
++      0x034, 0x0004706D,
++      0x034, 0x0004604D,
++      0x034, 0x0004504A,
++      0x034, 0x00044047,
++      0x034, 0x00043044,
++      0x034, 0x00042007,
++      0x034, 0x00041004,
++      0x034, 0x00040001,
++      0xA0000000,     0x00000000,
++      0x034, 0x0004ADF5,
++      0x034, 0x00049DF2,
++      0x034, 0x00048DEF,
++      0x034, 0x00047DEC,
++      0x034, 0x00046DE9,
++      0x034, 0x00045DE6,
++      0x034, 0x00044DE3,
++      0x034, 0x000438C8,
++      0x034, 0x000428C5,
++      0x034, 0x000418C2,
++      0x034, 0x000408C0,
++      0xB0000000,     0x00000000,
++      0x80000008,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0002A0B2,
++      0x034, 0x000290AF,
++      0x034, 0x00028070,
++      0x034, 0x0002706D,
++      0x034, 0x00026050,
++      0x034, 0x0002504D,
++      0x034, 0x0002404A,
++      0x034, 0x00023047,
++      0x034, 0x0002200A,
++      0x034, 0x00021007,
++      0x034, 0x00020004,
++      0x90000008,     0x05000000,     0x40000000,     0x00000000,
++      0x034, 0x0002A0B4,
++      0x034, 0x000290B1,
++      0x034, 0x00028072,
++      0x034, 0x0002706F,
++      0x034, 0x0002604F,
++      0x034, 0x0002504C,
++      0x034, 0x00024049,
++      0x034, 0x00023046,
++      0x034, 0x00022009,
++      0x034, 0x00021006,
++      0x034, 0x00020003,
++      0xA0000000,     0x00000000,
++      0x034, 0x0002ADF5,
++      0x034, 0x00029DF2,
++      0x034, 0x00028DEF,
++      0x034, 0x00027DEC,
++      0x034, 0x00026DE9,
++      0x034, 0x00025DE6,
++      0x034, 0x00024DE3,
++      0x034, 0x000238C8,
++      0x034, 0x000228C5,
++      0x034, 0x000218C2,
++      0x034, 0x000208C0,
++      0xB0000000,     0x00000000,
++      0x80000008,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0000A0B2,
++      0x034, 0x000090AF,
++      0x034, 0x00008070,
++      0x034, 0x0000706D,
++      0x034, 0x00006050,
++      0x034, 0x0000504D,
++      0x034, 0x0000404A,
++      0x034, 0x00003047,
++      0x034, 0x0000200A,
++      0x034, 0x00001007,
++      0x034, 0x00000004,
++      0x90000008,     0x05000000,     0x40000000,     0x00000000,
++      0x034, 0x0000A0B2,
++      0x034, 0x000090AF,
++      0x034, 0x00008070,
++      0x034, 0x0000706D,
++      0x034, 0x0000604D,
++      0x034, 0x0000504A,
++      0x034, 0x00004047,
++      0x034, 0x00003044,
++      0x034, 0x00002007,
++      0x034, 0x00001004,
++      0x034, 0x00000001,
++      0xA0000000,     0x00000000,
++      0x034, 0x0000AFF7,
++      0x034, 0x00009DF7,
++      0x034, 0x00008DF4,
++      0x034, 0x00007DF1,
++      0x034, 0x00006DEE,
++      0x034, 0x00005DEB,
++      0x034, 0x00004DE8,
++      0x034, 0x000038CC,
++      0x034, 0x000028C9,
++      0x034, 0x000018C6,
++      0x034, 0x000008C3,
++      0xB0000000,     0x00000000,
++      0x0EF, 0x00000000,
++      0x80000008,     0x00000000,     0x40000000,     0x00000000,
++      0x018, 0x0001712A,
++      0x0EF, 0x00000040,
++      0x035, 0x000001D4,
++      0x035, 0x000081D4,
++      0x035, 0x000101D4,
++      0x035, 0x000201B4,
++      0x035, 0x000281B4,
++      0x035, 0x000301B4,
++      0x035, 0x000401B4,
++      0x035, 0x000481B4,
++      0x035, 0x000501B4,
++      0x90000008,     0x05000000,     0x40000000,     0x00000000,
++      0x018, 0x0001712A,
++      0x0EF, 0x00000040,
++      0x035, 0x000001D4,
++      0x035, 0x000081D4,
++      0x035, 0x000101D4,
++      0x035, 0x000201B4,
++      0x035, 0x000281B4,
++      0x035, 0x000301B4,
++      0x035, 0x000401B4,
++      0x035, 0x000481B4,
++      0x035, 0x000501B4,
++      0xA0000000,     0x00000000,
++      0x018, 0x0001712A,
++      0x0EF, 0x00000040,
++      0x035, 0x00000188,
++      0x035, 0x00008147,
++      0x035, 0x00010147,
++      0x035, 0x000201D7,
++      0x035, 0x000281D7,
++      0x035, 0x000301D7,
++      0x035, 0x000401D8,
++      0x035, 0x000481D8,
++      0x035, 0x000501D8,
++      0xB0000000,     0x00000000,
++      0x0EF, 0x00000000,
++      0x80000008,     0x00000000,     0x40000000,     0x00000000,
++      0x018, 0x0001712A,
++      0x0EF, 0x00000010,
++      0x036, 0x00004BFB,
++      0x036, 0x0000CBFB,
++      0x036, 0x00014BFB,
++      0x036, 0x0001CBFB,
++      0x036, 0x00024F4B,
++      0x036, 0x0002CF4B,
++      0x036, 0x00034F4B,
++      0x036, 0x0003CF4B,
++      0x036, 0x00044F4B,
++      0x036, 0x0004CF4B,
++      0x036, 0x00054F4B,
++      0x036, 0x0005CF4B,
++      0x90000008,     0x05000000,     0x40000000,     0x00000000,
++      0x018, 0x0001712A,
++      0x0EF, 0x00000010,
++      0x036, 0x00004BFB,
++      0x036, 0x0000CBFB,
++      0x036, 0x00014BFB,
++      0x036, 0x0001CBFB,
++      0x036, 0x00024F4B,
++      0x036, 0x0002CF4B,
++      0x036, 0x00034F4B,
++      0x036, 0x0003CF4B,
++      0x036, 0x00044F4B,
++      0x036, 0x0004CF4B,
++      0x036, 0x00054F4B,
++      0x036, 0x0005CF4B,
++      0xA0000000,     0x00000000,
++      0x018, 0x0001712A,
++      0x0EF, 0x00000010,
++      0x036, 0x00084EB4,
++      0x036, 0x0008CC35,
++      0x036, 0x00094C35,
++      0x036, 0x0009CC35,
++      0x036, 0x000A4C35,
++      0x036, 0x000ACC35,
++      0x036, 0x000B4C35,
++      0x036, 0x000BCC35,
++      0x036, 0x000C4C34,
++      0x036, 0x000CCC35,
++      0x036, 0x000D4C35,
++      0x036, 0x000DCC35,
++      0xB0000000,     0x00000000,
++      0x0EF, 0x00000000,
++      0x0EF, 0x00000008,
++      0x80000008,     0x00000000,     0x40000000,     0x00000000,
++      0x03C, 0x000002CC,
++      0x03C, 0x00000522,
++      0x03C, 0x00000902,
++      0x90000008,     0x05000000,     0x40000000,     0x00000000,
++      0x03C, 0x000002CC,
++      0x03C, 0x00000522,
++      0x03C, 0x00000902,
++      0xA0000000,     0x00000000,
++      0x03C, 0x000002A8,
++      0x03C, 0x000005A2,
++      0x03C, 0x00000880,
++      0xB0000000,     0x00000000,
++      0x0EF, 0x00000000,
++      0x018, 0x0001712A,
++      0x0EF, 0x00000002,
++      0x0DF, 0x00000080,
++      0x01F, 0x00000064,
++      0x80000008,     0x00000000,     0x40000000,     0x00000000,
++      0x061, 0x000FDD43,
++      0x062, 0x00038F4B,
++      0x063, 0x00032117,
++      0x064, 0x000194AC,
++      0x065, 0x000931D1,
++      0x90000008,     0x05000000,     0x40000000,     0x00000000,
++      0x061, 0x000FDD43,
++      0x062, 0x00038F4B,
++      0x063, 0x00032117,
++      0x064, 0x000194AC,
++      0x065, 0x000931D2,
++      0xA0000000,     0x00000000,
++      0x061, 0x000E5D53,
++      0x062, 0x00038FCD,
++      0x063, 0x000114EB,
++      0x064, 0x000196AC,
++      0x065, 0x000911D7,
++      0xB0000000,     0x00000000,
++      0x008, 0x00008400,
++      0x01C, 0x000739D2,
++      0x0B4, 0x0001E78D,
++      0x018, 0x0001F12A,
++      0xFFE, 0x00000000,
++      0xFFE, 0x00000000,
++      0xFFE, 0x00000000,
++      0xFFE, 0x00000000,
++      0x0B4, 0x0001A78D,
++      0x018, 0x0001712A,
++};
++
++RTW_DECL_TABLE_RF_RADIO(rtw8812a_rf_a, A);
++
++static const u32 rtw8812a_rf_b[] = {
++      0x056, 0x00051CF2,
++      0x066, 0x00040000,
++      0x089, 0x00000080,
++      0x80000001,     0x00000000,     0x40000000,     0x00000000,
++      0x086, 0x00014B3A,
++      0x90000001,     0x00000005,     0x40000000,     0x00000000,
++      0x086, 0x00014B3A,
++      0xA0000000,     0x00000000,
++      0x086, 0x00014B38,
++      0xB0000000,     0x00000000,
++      0x80000004,     0x00000000,     0x40000000,     0x00000000,
++      0x08B, 0x00080180,
++      0xA0000000,     0x00000000,
++      0x08B, 0x00087180,
++      0xB0000000,     0x00000000,
++      0x018, 0x00000006,
++      0x0EF, 0x00002000,
++      0x80000001,     0x00000000,     0x40000000,     0x00000000,
++      0x03B, 0x0003F218,
++      0x03B, 0x00030A58,
++      0x03B, 0x0002FA58,
++      0x03B, 0x00022590,
++      0x03B, 0x0001FA50,
++      0x03B, 0x00010248,
++      0x03B, 0x00008240,
++      0x90000001,     0x00000005,     0x40000000,     0x00000000,
++      0x03B, 0x0003F218,
++      0x03B, 0x00030A58,
++      0x03B, 0x0002FA58,
++      0x03B, 0x00022590,
++      0x03B, 0x0001FA50,
++      0x03B, 0x00010248,
++      0x03B, 0x00008240,
++      0xA0000000,     0x00000000,
++      0x03B, 0x00038A58,
++      0x03B, 0x00037A58,
++      0x03B, 0x0002A590,
++      0x03B, 0x00027A50,
++      0x03B, 0x00018248,
++      0x03B, 0x00010240,
++      0x03B, 0x00008240,
++      0xB0000000,     0x00000000,
++      0x0EF, 0x00000100,
++      0x80000002,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0000A4EE,
++      0x034, 0x00009076,
++      0x034, 0x00008073,
++      0x034, 0x00007070,
++      0x034, 0x0000606D,
++      0x034, 0x0000506A,
++      0x034, 0x00004049,
++      0x034, 0x00003046,
++      0x034, 0x00002028,
++      0x034, 0x00001025,
++      0x034, 0x00000022,
++      0xA0000000,     0x00000000,
++      0x034, 0x0000ADF4,
++      0x034, 0x00009DF1,
++      0x034, 0x00008DEE,
++      0x034, 0x00007DEB,
++      0x034, 0x00006DE8,
++      0x034, 0x00005DE5,
++      0x034, 0x00004DE2,
++      0x034, 0x00003CE6,
++      0x034, 0x000024E7,
++      0x034, 0x000014E4,
++      0x034, 0x000004E1,
++      0xB0000000,     0x00000000,
++      0x0EF, 0x00000000,
++      0x0EF, 0x000020A2,
++      0x0DF, 0x00000080,
++      0x035, 0x00000192,
++      0x035, 0x00008192,
++      0x035, 0x00010192,
++      0x036, 0x00000024,
++      0x036, 0x00008024,
++      0x036, 0x00010024,
++      0x036, 0x00018024,
++      0x0EF, 0x00000000,
++      0x051, 0x00000C21,
++      0x052, 0x000006D9,
++      0x053, 0x000FC649,
++      0x054, 0x0000017E,
++      0x0EF, 0x00000002,
++      0x008, 0x00008400,
++      0x018, 0x0001712A,
++      0x0EF, 0x00001000,
++      0x03A, 0x00000080,
++      0x03B, 0x0003A02C,
++      0x03C, 0x00004000,
++      0x03A, 0x00000400,
++      0x03B, 0x0003202C,
++      0x03C, 0x00010000,
++      0x03A, 0x000000A0,
++      0x03B, 0x0002B064,
++      0x03C, 0x00004000,
++      0x03A, 0x000000D8,
++      0x03B, 0x00023070,
++      0x03C, 0x00004000,
++      0x03A, 0x00000468,
++      0x03B, 0x0001B870,
++      0x03C, 0x00010000,
++      0x03A, 0x00000098,
++      0x03B, 0x00012085,
++      0x03C, 0x000E4000,
++      0x03A, 0x00000418,
++      0x03B, 0x0000A080,
++      0x03C, 0x000F0000,
++      0x03A, 0x00000418,
++      0x03B, 0x00002080,
++      0x03C, 0x00010000,
++      0x03A, 0x00000080,
++      0x03B, 0x0007A02C,
++      0x03C, 0x00004000,
++      0x03A, 0x00000400,
++      0x03B, 0x0007202C,
++      0x03C, 0x00010000,
++      0x03A, 0x000000A0,
++      0x03B, 0x0006B064,
++      0x03C, 0x00004000,
++      0x03A, 0x000000D8,
++      0x03B, 0x00063070,
++      0x03C, 0x00004000,
++      0x03A, 0x00000468,
++      0x03B, 0x0005B870,
++      0x03C, 0x00010000,
++      0x03A, 0x00000098,
++      0x03B, 0x00052085,
++      0x03C, 0x000E4000,
++      0x03A, 0x00000418,
++      0x03B, 0x0004A080,
++      0x03C, 0x000F0000,
++      0x03A, 0x00000418,
++      0x03B, 0x00042080,
++      0x03C, 0x00010000,
++      0x03A, 0x00000080,
++      0x03B, 0x000BA02C,
++      0x03C, 0x00004000,
++      0x03A, 0x00000400,
++      0x03B, 0x000B202C,
++      0x03C, 0x00010000,
++      0x03A, 0x000000A0,
++      0x03B, 0x000AB064,
++      0x03C, 0x00004000,
++      0x03A, 0x000000D8,
++      0x03B, 0x000A3070,
++      0x03C, 0x00004000,
++      0x03A, 0x00000468,
++      0x03B, 0x0009B870,
++      0x03C, 0x00010000,
++      0x03A, 0x00000098,
++      0x03B, 0x00092085,
++      0x03C, 0x000E4000,
++      0x03A, 0x00000418,
++      0x03B, 0x0008A080,
++      0x03C, 0x000F0000,
++      0x03A, 0x00000418,
++      0x03B, 0x00082080,
++      0x03C, 0x00010000,
++      0x0EF, 0x00001100,
++      0x80000008,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0004A0B2,
++      0x034, 0x000490AF,
++      0x034, 0x00048070,
++      0x034, 0x0004706D,
++      0x034, 0x00046050,
++      0x034, 0x0004504D,
++      0x034, 0x0004404A,
++      0x034, 0x00043047,
++      0x034, 0x0004200A,
++      0x034, 0x00041007,
++      0x034, 0x00040004,
++      0x90000008,     0x05000000,     0x40000000,     0x00000000,
++      0x034, 0x0004A0B1,
++      0x034, 0x000490AE,
++      0x034, 0x0004806F,
++      0x034, 0x0004706C,
++      0x034, 0x0004604C,
++      0x034, 0x00045049,
++      0x034, 0x00044046,
++      0x034, 0x00043043,
++      0x034, 0x00042006,
++      0x034, 0x00041003,
++      0x034, 0x00040000,
++      0xA0000000,     0x00000000,
++      0x034, 0x0004ADF5,
++      0x034, 0x00049DF2,
++      0x034, 0x00048DEF,
++      0x034, 0x00047DEC,
++      0x034, 0x00046DE9,
++      0x034, 0x00045DE6,
++      0x034, 0x00044DE3,
++      0x034, 0x000438C8,
++      0x034, 0x000428C5,
++      0x034, 0x000418C2,
++      0x034, 0x000408C0,
++      0xB0000000,     0x00000000,
++      0x80000008,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0002A0B2,
++      0x034, 0x000290AF,
++      0x034, 0x00028070,
++      0x034, 0x0002706D,
++      0x034, 0x00026050,
++      0x034, 0x0002504D,
++      0x034, 0x0002404A,
++      0x034, 0x00023047,
++      0x034, 0x0002200A,
++      0x034, 0x00021007,
++      0x034, 0x00020004,
++      0x90000008,     0x05000000,     0x40000000,     0x00000000,
++      0x034, 0x0002A0B3,
++      0x034, 0x000290B0,
++      0x034, 0x00028071,
++      0x034, 0x0002706E,
++      0x034, 0x0002604E,
++      0x034, 0x0002504B,
++      0x034, 0x00024048,
++      0x034, 0x00023045,
++      0x034, 0x00022008,
++      0x034, 0x00021005,
++      0x034, 0x00020002,
++      0xA0000000,     0x00000000,
++      0x034, 0x0002ADF5,
++      0x034, 0x00029DF2,
++      0x034, 0x00028DEF,
++      0x034, 0x00027DEC,
++      0x034, 0x00026DE9,
++      0x034, 0x00025DE6,
++      0x034, 0x00024DE3,
++      0x034, 0x000238C8,
++      0x034, 0x000228C5,
++      0x034, 0x000218C2,
++      0x034, 0x000208C0,
++      0xB0000000,     0x00000000,
++      0x80000008,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0000A0B2,
++      0x034, 0x000090AF,
++      0x034, 0x00008070,
++      0x034, 0x0000706D,
++      0x034, 0x00006050,
++      0x034, 0x0000504D,
++      0x034, 0x0000404A,
++      0x034, 0x00003047,
++      0x034, 0x0000200A,
++      0x034, 0x00001007,
++      0x034, 0x00000004,
++      0x90000008,     0x05000000,     0x40000000,     0x00000000,
++      0x034, 0x0000A0B3,
++      0x034, 0x000090B0,
++      0x034, 0x00008070,
++      0x034, 0x0000706D,
++      0x034, 0x0000604D,
++      0x034, 0x0000504A,
++      0x034, 0x00004047,
++      0x034, 0x00003044,
++      0x034, 0x00002007,
++      0x034, 0x00001004,
++      0x034, 0x00000001,
++      0xA0000000,     0x00000000,
++      0x034, 0x0000AFF7,
++      0x034, 0x00009DF7,
++      0x034, 0x00008DF4,
++      0x034, 0x00007DF1,
++      0x034, 0x00006DEE,
++      0x034, 0x00005DEB,
++      0x034, 0x00004DE8,
++      0x034, 0x000038CC,
++      0x034, 0x000028C9,
++      0x034, 0x000018C6,
++      0x034, 0x000008C3,
++      0xB0000000,     0x00000000,
++      0x0EF, 0x00000000,
++      0x80000008,     0x00000000,     0x40000000,     0x00000000,
++      0x018, 0x0001712A,
++      0x0EF, 0x00000040,
++      0x035, 0x000001C5,
++      0x035, 0x000081C5,
++      0x035, 0x000101C5,
++      0x035, 0x00020174,
++      0x035, 0x00028174,
++      0x035, 0x00030174,
++      0x035, 0x00040185,
++      0x035, 0x00048185,
++      0x035, 0x00050185,
++      0x0EF, 0x00000000,
++      0x90000008,     0x05000000,     0x40000000,     0x00000000,
++      0x018, 0x0001712A,
++      0x0EF, 0x00000040,
++      0x035, 0x000001C5,
++      0x035, 0x000081C5,
++      0x035, 0x000101C5,
++      0x035, 0x00020174,
++      0x035, 0x00028174,
++      0x035, 0x00030174,
++      0x035, 0x00040185,
++      0x035, 0x00048185,
++      0x035, 0x00050185,
++      0x0EF, 0x00000000,
++      0xA0000000,     0x00000000,
++      0x018, 0x0001712A,
++      0x0EF, 0x00000040,
++      0x035, 0x00000188,
++      0x035, 0x00008147,
++      0x035, 0x00010147,
++      0x035, 0x000201D7,
++      0x035, 0x000281D7,
++      0x035, 0x000301D7,
++      0x035, 0x000401D8,
++      0x035, 0x000481D8,
++      0x035, 0x000501D8,
++      0x0EF, 0x00000000,
++      0xB0000000,     0x00000000,
++      0x80000008,     0x00000000,     0x40000000,     0x00000000,
++      0x018, 0x0001712A,
++      0x0EF, 0x00000010,
++      0x036, 0x00005B8B,
++      0x036, 0x0000DB8B,
++      0x036, 0x00015B8B,
++      0x036, 0x0001DB8B,
++      0x036, 0x000262DB,
++      0x036, 0x0002E2DB,
++      0x036, 0x000362DB,
++      0x036, 0x0003E2DB,
++      0x036, 0x0004553B,
++      0x036, 0x0004D53B,
++      0x036, 0x0005553B,
++      0x036, 0x0005D53B,
++      0x90000008,     0x05000000,     0x40000000,     0x00000000,
++      0x018, 0x0001712A,
++      0x0EF, 0x00000010,
++      0x036, 0x00005B8B,
++      0x036, 0x0000DB8B,
++      0x036, 0x00015B8B,
++      0x036, 0x0001DB8B,
++      0x036, 0x000262DB,
++      0x036, 0x0002E2DB,
++      0x036, 0x000362DB,
++      0x036, 0x0003E2DB,
++      0x036, 0x0004553B,
++      0x036, 0x0004D53B,
++      0x036, 0x0005553B,
++      0x036, 0x0005D53B,
++      0xA0000000,     0x00000000,
++      0x018, 0x0001712A,
++      0x0EF, 0x00000010,
++      0x036, 0x00084EB4,
++      0x036, 0x0008CC35,
++      0x036, 0x00094C35,
++      0x036, 0x0009CC35,
++      0x036, 0x000A4C35,
++      0x036, 0x000ACC35,
++      0x036, 0x000B4C35,
++      0x036, 0x000BCC35,
++      0x036, 0x000C4C34,
++      0x036, 0x000CCC35,
++      0x036, 0x000D4C35,
++      0x036, 0x000DCC35,
++      0xB0000000,     0x00000000,
++      0x0EF, 0x00000000,
++      0x0EF, 0x00000008,
++      0x80000008,     0x00000000,     0x40000000,     0x00000000,
++      0x03C, 0x000002DC,
++      0x03C, 0x00000524,
++      0x03C, 0x00000902,
++      0x90000008,     0x05000000,     0x40000000,     0x00000000,
++      0x03C, 0x000002DC,
++      0x03C, 0x00000524,
++      0x03C, 0x00000902,
++      0xA0000000,     0x00000000,
++      0x03C, 0x000002A8,
++      0x03C, 0x000005A2,
++      0x03C, 0x00000880,
++      0xB0000000,     0x00000000,
++      0x0EF, 0x00000000,
++      0x018, 0x0001712A,
++      0x0EF, 0x00000002,
++      0x0DF, 0x00000080,
++      0x80000008,     0x00000000,     0x40000000,     0x00000000,
++      0x061, 0x000EAC43,
++      0x062, 0x00038F47,
++      0x063, 0x00031157,
++      0x064, 0x0001C4AC,
++      0x065, 0x000931D1,
++      0x90000008,     0x05000000,     0x40000000,     0x00000000,
++      0x061, 0x000EAC43,
++      0x062, 0x00038F47,
++      0x063, 0x00031157,
++      0x064, 0x0001C4AC,
++      0x065, 0x000931D2,
++      0x90000002,     0x00000000,     0x40000000,     0x00000000,
++      0x061, 0x000EAC43,
++      0x062, 0x00038F47,
++      0x063, 0x00031157,
++      0x064, 0x0001C4AC,
++      0x065, 0x000931D1,
++      0xA0000000,     0x00000000,
++      0x061, 0x000E5D53,
++      0x062, 0x00038FCD,
++      0x063, 0x000114EB,
++      0x064, 0x000196AC,
++      0x065, 0x000911D7,
++      0xB0000000,     0x00000000,
++      0x008, 0x00008400,
++};
++
++RTW_DECL_TABLE_RF_RADIO(rtw8812a_rf_b, B);
++
++static const struct rtw_txpwr_lmt_cfg_pair rtw8812a_txpwr_lmt[] = {
++      { 0, 0, 0, 0, 1, 36, },
++      { 2, 0, 0, 0, 1, 32, },
++      { 1, 0, 0, 0, 1, 32, },
++      { 0, 0, 0, 0, 2, 36, },
++      { 2, 0, 0, 0, 2, 32, },
++      { 1, 0, 0, 0, 2, 32, },
++      { 0, 0, 0, 0, 3, 36, },
++      { 2, 0, 0, 0, 3, 32, },
++      { 1, 0, 0, 0, 3, 32, },
++      { 0, 0, 0, 0, 4, 36, },
++      { 2, 0, 0, 0, 4, 32, },
++      { 1, 0, 0, 0, 4, 32, },
++      { 0, 0, 0, 0, 5, 36, },
++      { 2, 0, 0, 0, 5, 32, },
++      { 1, 0, 0, 0, 5, 32, },
++      { 0, 0, 0, 0, 6, 36, },
++      { 2, 0, 0, 0, 6, 32, },
++      { 1, 0, 0, 0, 6, 32, },
++      { 0, 0, 0, 0, 7, 36, },
++      { 2, 0, 0, 0, 7, 32, },
++      { 1, 0, 0, 0, 7, 32, },
++      { 0, 0, 0, 0, 8, 36, },
++      { 2, 0, 0, 0, 8, 32, },
++      { 1, 0, 0, 0, 8, 32, },
++      { 0, 0, 0, 0, 9, 36, },
++      { 2, 0, 0, 0, 9, 32, },
++      { 1, 0, 0, 0, 9, 32, },
++      { 0, 0, 0, 0, 10, 36, },
++      { 2, 0, 0, 0, 10, 32, },
++      { 1, 0, 0, 0, 10, 32, },
++      { 0, 0, 0, 0, 11, 36, },
++      { 2, 0, 0, 0, 11, 32, },
++      { 1, 0, 0, 0, 11, 32, },
++      { 0, 0, 0, 0, 12, 63, },
++      { 2, 0, 0, 0, 12, 32, },
++      { 1, 0, 0, 0, 12, 32, },
++      { 0, 0, 0, 0, 13, 63, },
++      { 2, 0, 0, 0, 13, 32, },
++      { 1, 0, 0, 0, 13, 32, },
++      { 0, 0, 0, 0, 14, 63, },
++      { 2, 0, 0, 0, 14, 63, },
++      { 1, 0, 0, 0, 14, 32, },
++      { 0, 0, 0, 1, 1, 34, },
++      { 2, 0, 0, 1, 1, 32, },
++      { 1, 0, 0, 1, 1, 32, },
++      { 0, 0, 0, 1, 2, 36, },
++      { 2, 0, 0, 1, 2, 32, },
++      { 1, 0, 0, 1, 2, 32, },
++      { 0, 0, 0, 1, 3, 36, },
++      { 2, 0, 0, 1, 3, 32, },
++      { 1, 0, 0, 1, 3, 32, },
++      { 0, 0, 0, 1, 4, 36, },
++      { 2, 0, 0, 1, 4, 32, },
++      { 1, 0, 0, 1, 4, 32, },
++      { 0, 0, 0, 1, 5, 36, },
++      { 2, 0, 0, 1, 5, 32, },
++      { 1, 0, 0, 1, 5, 32, },
++      { 0, 0, 0, 1, 6, 36, },
++      { 2, 0, 0, 1, 6, 32, },
++      { 1, 0, 0, 1, 6, 32, },
++      { 0, 0, 0, 1, 7, 36, },
++      { 2, 0, 0, 1, 7, 32, },
++      { 1, 0, 0, 1, 7, 32, },
++      { 0, 0, 0, 1, 8, 36, },
++      { 2, 0, 0, 1, 8, 32, },
++      { 1, 0, 0, 1, 8, 32, },
++      { 0, 0, 0, 1, 9, 36, },
++      { 2, 0, 0, 1, 9, 32, },
++      { 1, 0, 0, 1, 9, 32, },
++      { 0, 0, 0, 1, 10, 36, },
++      { 2, 0, 0, 1, 10, 32, },
++      { 1, 0, 0, 1, 10, 32, },
++      { 0, 0, 0, 1, 11, 32, },
++      { 2, 0, 0, 1, 11, 32, },
++      { 1, 0, 0, 1, 11, 32, },
++      { 0, 0, 0, 1, 12, 63, },
++      { 2, 0, 0, 1, 12, 32, },
++      { 1, 0, 0, 1, 12, 32, },
++      { 0, 0, 0, 1, 13, 63, },
++      { 2, 0, 0, 1, 13, 32, },
++      { 1, 0, 0, 1, 13, 32, },
++      { 0, 0, 0, 1, 14, 63, },
++      { 2, 0, 0, 1, 14, 63, },
++      { 1, 0, 0, 1, 14, 63, },
++      { 0, 0, 0, 2, 1, 34, },
++      { 2, 0, 0, 2, 1, 32, },
++      { 1, 0, 0, 2, 1, 32, },
++      { 0, 0, 0, 2, 2, 36, },
++      { 2, 0, 0, 2, 2, 32, },
++      { 1, 0, 0, 2, 2, 32, },
++      { 0, 0, 0, 2, 3, 36, },
++      { 2, 0, 0, 2, 3, 32, },
++      { 1, 0, 0, 2, 3, 32, },
++      { 0, 0, 0, 2, 4, 36, },
++      { 2, 0, 0, 2, 4, 32, },
++      { 1, 0, 0, 2, 4, 32, },
++      { 0, 0, 0, 2, 5, 36, },
++      { 2, 0, 0, 2, 5, 32, },
++      { 1, 0, 0, 2, 5, 32, },
++      { 0, 0, 0, 2, 6, 36, },
++      { 2, 0, 0, 2, 6, 32, },
++      { 1, 0, 0, 2, 6, 32, },
++      { 0, 0, 0, 2, 7, 36, },
++      { 2, 0, 0, 2, 7, 32, },
++      { 1, 0, 0, 2, 7, 32, },
++      { 0, 0, 0, 2, 8, 36, },
++      { 2, 0, 0, 2, 8, 32, },
++      { 1, 0, 0, 2, 8, 32, },
++      { 0, 0, 0, 2, 9, 36, },
++      { 2, 0, 0, 2, 9, 32, },
++      { 1, 0, 0, 2, 9, 32, },
++      { 0, 0, 0, 2, 10, 36, },
++      { 2, 0, 0, 2, 10, 32, },
++      { 1, 0, 0, 2, 10, 32, },
++      { 0, 0, 0, 2, 11, 32, },
++      { 2, 0, 0, 2, 11, 32, },
++      { 1, 0, 0, 2, 11, 32, },
++      { 0, 0, 0, 2, 12, 63, },
++      { 2, 0, 0, 2, 12, 32, },
++      { 1, 0, 0, 2, 12, 32, },
++      { 0, 0, 0, 2, 13, 63, },
++      { 2, 0, 0, 2, 13, 32, },
++      { 1, 0, 0, 2, 13, 32, },
++      { 0, 0, 0, 2, 14, 63, },
++      { 2, 0, 0, 2, 14, 63, },
++      { 1, 0, 0, 2, 14, 63, },
++      { 0, 0, 0, 3, 1, 32, },
++      { 2, 0, 0, 3, 1, 32, },
++      { 1, 0, 0, 3, 1, 32, },
++      { 0, 0, 0, 3, 2, 34, },
++      { 2, 0, 0, 3, 2, 32, },
++      { 1, 0, 0, 3, 2, 32, },
++      { 0, 0, 0, 3, 3, 34, },
++      { 2, 0, 0, 3, 3, 32, },
++      { 1, 0, 0, 3, 3, 32, },
++      { 0, 0, 0, 3, 4, 34, },
++      { 2, 0, 0, 3, 4, 32, },
++      { 1, 0, 0, 3, 4, 32, },
++      { 0, 0, 0, 3, 5, 34, },
++      { 2, 0, 0, 3, 5, 32, },
++      { 1, 0, 0, 3, 5, 32, },
++      { 0, 0, 0, 3, 6, 34, },
++      { 2, 0, 0, 3, 6, 32, },
++      { 1, 0, 0, 3, 6, 32, },
++      { 0, 0, 0, 3, 7, 34, },
++      { 2, 0, 0, 3, 7, 32, },
++      { 1, 0, 0, 3, 7, 32, },
++      { 0, 0, 0, 3, 8, 34, },
++      { 2, 0, 0, 3, 8, 32, },
++      { 1, 0, 0, 3, 8, 32, },
++      { 0, 0, 0, 3, 9, 34, },
++      { 2, 0, 0, 3, 9, 32, },
++      { 1, 0, 0, 3, 9, 32, },
++      { 0, 0, 0, 3, 10, 34, },
++      { 2, 0, 0, 3, 10, 32, },
++      { 1, 0, 0, 3, 10, 32, },
++      { 0, 0, 0, 3, 11, 30, },
++      { 2, 0, 0, 3, 11, 32, },
++      { 1, 0, 0, 3, 11, 32, },
++      { 0, 0, 0, 3, 12, 63, },
++      { 2, 0, 0, 3, 12, 32, },
++      { 1, 0, 0, 3, 12, 32, },
++      { 0, 0, 0, 3, 13, 63, },
++      { 2, 0, 0, 3, 13, 32, },
++      { 1, 0, 0, 3, 13, 32, },
++      { 0, 0, 0, 3, 14, 63, },
++      { 2, 0, 0, 3, 14, 63, },
++      { 1, 0, 0, 3, 14, 63, },
++      { 0, 0, 1, 2, 1, 63, },
++      { 2, 0, 1, 2, 1, 63, },
++      { 1, 0, 1, 2, 1, 63, },
++      { 0, 0, 1, 2, 2, 63, },
++      { 2, 0, 1, 2, 2, 63, },
++      { 1, 0, 1, 2, 2, 63, },
++      { 0, 0, 1, 2, 3, 32, },
++      { 2, 0, 1, 2, 3, 32, },
++      { 1, 0, 1, 2, 3, 32, },
++      { 0, 0, 1, 2, 4, 36, },
++      { 2, 0, 1, 2, 4, 32, },
++      { 1, 0, 1, 2, 4, 32, },
++      { 0, 0, 1, 2, 5, 36, },
++      { 2, 0, 1, 2, 5, 32, },
++      { 1, 0, 1, 2, 5, 32, },
++      { 0, 0, 1, 2, 6, 36, },
++      { 2, 0, 1, 2, 6, 32, },
++      { 1, 0, 1, 2, 6, 32, },
++      { 0, 0, 1, 2, 7, 36, },
++      { 2, 0, 1, 2, 7, 32, },
++      { 1, 0, 1, 2, 7, 32, },
++      { 0, 0, 1, 2, 8, 36, },
++      { 2, 0, 1, 2, 8, 32, },
++      { 1, 0, 1, 2, 8, 32, },
++      { 0, 0, 1, 2, 9, 36, },
++      { 2, 0, 1, 2, 9, 32, },
++      { 1, 0, 1, 2, 9, 32, },
++      { 0, 0, 1, 2, 10, 36, },
++      { 2, 0, 1, 2, 10, 32, },
++      { 1, 0, 1, 2, 10, 32, },
++      { 0, 0, 1, 2, 11, 32, },
++      { 2, 0, 1, 2, 11, 32, },
++      { 1, 0, 1, 2, 11, 32, },
++      { 0, 0, 1, 2, 12, 63, },
++      { 2, 0, 1, 2, 12, 32, },
++      { 1, 0, 1, 2, 12, 32, },
++      { 0, 0, 1, 2, 13, 63, },
++      { 2, 0, 1, 2, 13, 32, },
++      { 1, 0, 1, 2, 13, 32, },
++      { 0, 0, 1, 2, 14, 63, },
++      { 2, 0, 1, 2, 14, 63, },
++      { 1, 0, 1, 2, 14, 63, },
++      { 0, 0, 1, 3, 1, 63, },
++      { 2, 0, 1, 3, 1, 63, },
++      { 1, 0, 1, 3, 1, 63, },
++      { 0, 0, 1, 3, 2, 63, },
++      { 2, 0, 1, 3, 2, 63, },
++      { 1, 0, 1, 3, 2, 63, },
++      { 0, 0, 1, 3, 3, 30, },
++      { 2, 0, 1, 3, 3, 30, },
++      { 1, 0, 1, 3, 3, 30, },
++      { 0, 0, 1, 3, 4, 34, },
++      { 2, 0, 1, 3, 4, 30, },
++      { 1, 0, 1, 3, 4, 30, },
++      { 0, 0, 1, 3, 5, 34, },
++      { 2, 0, 1, 3, 5, 30, },
++      { 1, 0, 1, 3, 5, 30, },
++      { 0, 0, 1, 3, 6, 34, },
++      { 2, 0, 1, 3, 6, 30, },
++      { 1, 0, 1, 3, 6, 30, },
++      { 0, 0, 1, 3, 7, 34, },
++      { 2, 0, 1, 3, 7, 30, },
++      { 1, 0, 1, 3, 7, 30, },
++      { 0, 0, 1, 3, 8, 34, },
++      { 2, 0, 1, 3, 8, 30, },
++      { 1, 0, 1, 3, 8, 30, },
++      { 0, 0, 1, 3, 9, 34, },
++      { 2, 0, 1, 3, 9, 30, },
++      { 1, 0, 1, 3, 9, 30, },
++      { 0, 0, 1, 3, 10, 34, },
++      { 2, 0, 1, 3, 10, 30, },
++      { 1, 0, 1, 3, 10, 30, },
++      { 0, 0, 1, 3, 11, 30, },
++      { 2, 0, 1, 3, 11, 30, },
++      { 1, 0, 1, 3, 11, 30, },
++      { 0, 0, 1, 3, 12, 63, },
++      { 2, 0, 1, 3, 12, 32, },
++      { 1, 0, 1, 3, 12, 32, },
++      { 0, 0, 1, 3, 13, 63, },
++      { 2, 0, 1, 3, 13, 32, },
++      { 1, 0, 1, 3, 13, 32, },
++      { 0, 0, 1, 3, 14, 63, },
++      { 2, 0, 1, 3, 14, 63, },
++      { 1, 0, 1, 3, 14, 63, },
++      { 0, 1, 0, 1, 36, 30, },
++      { 2, 1, 0, 1, 36, 32, },
++      { 1, 1, 0, 1, 36, 32, },
++      { 0, 1, 0, 1, 40, 30, },
++      { 2, 1, 0, 1, 40, 32, },
++      { 1, 1, 0, 1, 40, 32, },
++      { 0, 1, 0, 1, 44, 30, },
++      { 2, 1, 0, 1, 44, 32, },
++      { 1, 1, 0, 1, 44, 32, },
++      { 0, 1, 0, 1, 48, 30, },
++      { 2, 1, 0, 1, 48, 32, },
++      { 1, 1, 0, 1, 48, 32, },
++      { 0, 1, 0, 1, 52, 36, },
++      { 2, 1, 0, 1, 52, 32, },
++      { 1, 1, 0, 1, 52, 32, },
++      { 0, 1, 0, 1, 56, 34, },
++      { 2, 1, 0, 1, 56, 32, },
++      { 1, 1, 0, 1, 56, 32, },
++      { 0, 1, 0, 1, 60, 32, },
++      { 2, 1, 0, 1, 60, 32, },
++      { 1, 1, 0, 1, 60, 32, },
++      { 0, 1, 0, 1, 64, 28, },
++      { 2, 1, 0, 1, 64, 32, },
++      { 1, 1, 0, 1, 64, 32, },
++      { 0, 1, 0, 1, 100, 30, },
++      { 2, 1, 0, 1, 100, 32, },
++      { 1, 1, 0, 1, 100, 32, },
++      { 0, 1, 0, 1, 104, 30, },
++      { 2, 1, 0, 1, 104, 32, },
++      { 1, 1, 0, 1, 104, 32, },
++      { 0, 1, 0, 1, 108, 32, },
++      { 2, 1, 0, 1, 108, 32, },
++      { 1, 1, 0, 1, 108, 32, },
++      { 0, 1, 0, 1, 112, 34, },
++      { 2, 1, 0, 1, 112, 32, },
++      { 1, 1, 0, 1, 112, 32, },
++      { 0, 1, 0, 1, 116, 34, },
++      { 2, 1, 0, 1, 116, 32, },
++      { 1, 1, 0, 1, 116, 32, },
++      { 0, 1, 0, 1, 120, 36, },
++      { 2, 1, 0, 1, 120, 32, },
++      { 1, 1, 0, 1, 120, 32, },
++      { 0, 1, 0, 1, 124, 34, },
++      { 2, 1, 0, 1, 124, 32, },
++      { 1, 1, 0, 1, 124, 32, },
++      { 0, 1, 0, 1, 128, 32, },
++      { 2, 1, 0, 1, 128, 32, },
++      { 1, 1, 0, 1, 128, 32, },
++      { 0, 1, 0, 1, 132, 30, },
++      { 2, 1, 0, 1, 132, 32, },
++      { 1, 1, 0, 1, 132, 32, },
++      { 0, 1, 0, 1, 136, 30, },
++      { 2, 1, 0, 1, 136, 32, },
++      { 1, 1, 0, 1, 136, 32, },
++      { 0, 1, 0, 1, 140, 28, },
++      { 2, 1, 0, 1, 140, 32, },
++      { 1, 1, 0, 1, 140, 32, },
++      { 0, 1, 0, 1, 149, 36, },
++      { 2, 1, 0, 1, 149, 32, },
++      { 1, 1, 0, 1, 149, 63, },
++      { 0, 1, 0, 1, 153, 36, },
++      { 2, 1, 0, 1, 153, 32, },
++      { 1, 1, 0, 1, 153, 63, },
++      { 0, 1, 0, 1, 157, 36, },
++      { 2, 1, 0, 1, 157, 32, },
++      { 1, 1, 0, 1, 157, 63, },
++      { 0, 1, 0, 1, 161, 36, },
++      { 2, 1, 0, 1, 161, 32, },
++      { 1, 1, 0, 1, 161, 63, },
++      { 0, 1, 0, 1, 165, 36, },
++      { 2, 1, 0, 1, 165, 32, },
++      { 1, 1, 0, 1, 165, 63, },
++      { 0, 1, 0, 2, 36, 30, },
++      { 2, 1, 0, 2, 36, 32, },
++      { 1, 1, 0, 2, 36, 32, },
++      { 0, 1, 0, 2, 40, 30, },
++      { 2, 1, 0, 2, 40, 32, },
++      { 1, 1, 0, 2, 40, 32, },
++      { 0, 1, 0, 2, 44, 30, },
++      { 2, 1, 0, 2, 44, 32, },
++      { 1, 1, 0, 2, 44, 32, },
++      { 0, 1, 0, 2, 48, 30, },
++      { 2, 1, 0, 2, 48, 32, },
++      { 1, 1, 0, 2, 48, 32, },
++      { 0, 1, 0, 2, 52, 36, },
++      { 2, 1, 0, 2, 52, 32, },
++      { 1, 1, 0, 2, 52, 32, },
++      { 0, 1, 0, 2, 56, 34, },
++      { 2, 1, 0, 2, 56, 32, },
++      { 1, 1, 0, 2, 56, 32, },
++      { 0, 1, 0, 2, 60, 32, },
++      { 2, 1, 0, 2, 60, 32, },
++      { 1, 1, 0, 2, 60, 32, },
++      { 0, 1, 0, 2, 64, 28, },
++      { 2, 1, 0, 2, 64, 32, },
++      { 1, 1, 0, 2, 64, 32, },
++      { 0, 1, 0, 2, 100, 30, },
++      { 2, 1, 0, 2, 100, 32, },
++      { 1, 1, 0, 2, 100, 32, },
++      { 0, 1, 0, 2, 104, 30, },
++      { 2, 1, 0, 2, 104, 32, },
++      { 1, 1, 0, 2, 104, 32, },
++      { 0, 1, 0, 2, 108, 32, },
++      { 2, 1, 0, 2, 108, 32, },
++      { 1, 1, 0, 2, 108, 32, },
++      { 0, 1, 0, 2, 112, 34, },
++      { 2, 1, 0, 2, 112, 32, },
++      { 1, 1, 0, 2, 112, 32, },
++      { 0, 1, 0, 2, 116, 34, },
++      { 2, 1, 0, 2, 116, 32, },
++      { 1, 1, 0, 2, 116, 32, },
++      { 0, 1, 0, 2, 120, 36, },
++      { 2, 1, 0, 2, 120, 32, },
++      { 1, 1, 0, 2, 120, 32, },
++      { 0, 1, 0, 2, 124, 34, },
++      { 2, 1, 0, 2, 124, 32, },
++      { 1, 1, 0, 2, 124, 32, },
++      { 0, 1, 0, 2, 128, 32, },
++      { 2, 1, 0, 2, 128, 32, },
++      { 1, 1, 0, 2, 128, 32, },
++      { 0, 1, 0, 2, 132, 30, },
++      { 2, 1, 0, 2, 132, 32, },
++      { 1, 1, 0, 2, 132, 32, },
++      { 0, 1, 0, 2, 136, 30, },
++      { 2, 1, 0, 2, 136, 32, },
++      { 1, 1, 0, 2, 136, 32, },
++      { 0, 1, 0, 2, 140, 28, },
++      { 2, 1, 0, 2, 140, 32, },
++      { 1, 1, 0, 2, 140, 32, },
++      { 0, 1, 0, 2, 149, 36, },
++      { 2, 1, 0, 2, 149, 32, },
++      { 1, 1, 0, 2, 149, 63, },
++      { 0, 1, 0, 2, 153, 36, },
++      { 2, 1, 0, 2, 153, 32, },
++      { 1, 1, 0, 2, 153, 63, },
++      { 0, 1, 0, 2, 157, 36, },
++      { 2, 1, 0, 2, 157, 32, },
++      { 1, 1, 0, 2, 157, 63, },
++      { 0, 1, 0, 2, 161, 36, },
++      { 2, 1, 0, 2, 161, 32, },
++      { 1, 1, 0, 2, 161, 63, },
++      { 0, 1, 0, 2, 165, 36, },
++      { 2, 1, 0, 2, 165, 32, },
++      { 1, 1, 0, 2, 165, 63, },
++      { 0, 1, 0, 3, 36, 28, },
++      { 2, 1, 0, 3, 36, 30, },
++      { 1, 1, 0, 3, 36, 30, },
++      { 0, 1, 0, 3, 40, 28, },
++      { 2, 1, 0, 3, 40, 30, },
++      { 1, 1, 0, 3, 40, 30, },
++      { 0, 1, 0, 3, 44, 28, },
++      { 2, 1, 0, 3, 44, 30, },
++      { 1, 1, 0, 3, 44, 30, },
++      { 0, 1, 0, 3, 48, 28, },
++      { 2, 1, 0, 3, 48, 30, },
++      { 1, 1, 0, 3, 48, 30, },
++      { 0, 1, 0, 3, 52, 34, },
++      { 2, 1, 0, 3, 52, 30, },
++      { 1, 1, 0, 3, 52, 30, },
++      { 0, 1, 0, 3, 56, 32, },
++      { 2, 1, 0, 3, 56, 30, },
++      { 1, 1, 0, 3, 56, 30, },
++      { 0, 1, 0, 3, 60, 30, },
++      { 2, 1, 0, 3, 60, 30, },
++      { 1, 1, 0, 3, 60, 30, },
++      { 0, 1, 0, 3, 64, 26, },
++      { 2, 1, 0, 3, 64, 30, },
++      { 1, 1, 0, 3, 64, 30, },
++      { 0, 1, 0, 3, 100, 28, },
++      { 2, 1, 0, 3, 100, 30, },
++      { 1, 1, 0, 3, 100, 30, },
++      { 0, 1, 0, 3, 104, 28, },
++      { 2, 1, 0, 3, 104, 30, },
++      { 1, 1, 0, 3, 104, 30, },
++      { 0, 1, 0, 3, 108, 30, },
++      { 2, 1, 0, 3, 108, 30, },
++      { 1, 1, 0, 3, 108, 30, },
++      { 0, 1, 0, 3, 112, 32, },
++      { 2, 1, 0, 3, 112, 30, },
++      { 1, 1, 0, 3, 112, 30, },
++      { 0, 1, 0, 3, 116, 32, },
++      { 2, 1, 0, 3, 116, 30, },
++      { 1, 1, 0, 3, 116, 30, },
++      { 0, 1, 0, 3, 120, 34, },
++      { 2, 1, 0, 3, 120, 30, },
++      { 1, 1, 0, 3, 120, 30, },
++      { 0, 1, 0, 3, 124, 32, },
++      { 2, 1, 0, 3, 124, 30, },
++      { 1, 1, 0, 3, 124, 30, },
++      { 0, 1, 0, 3, 128, 30, },
++      { 2, 1, 0, 3, 128, 30, },
++      { 1, 1, 0, 3, 128, 30, },
++      { 0, 1, 0, 3, 132, 28, },
++      { 2, 1, 0, 3, 132, 30, },
++      { 1, 1, 0, 3, 132, 30, },
++      { 0, 1, 0, 3, 136, 28, },
++      { 2, 1, 0, 3, 136, 30, },
++      { 1, 1, 0, 3, 136, 30, },
++      { 0, 1, 0, 3, 140, 26, },
++      { 2, 1, 0, 3, 140, 30, },
++      { 1, 1, 0, 3, 140, 30, },
++      { 0, 1, 0, 3, 149, 34, },
++      { 2, 1, 0, 3, 149, 30, },
++      { 1, 1, 0, 3, 149, 63, },
++      { 0, 1, 0, 3, 153, 34, },
++      { 2, 1, 0, 3, 153, 30, },
++      { 1, 1, 0, 3, 153, 63, },
++      { 0, 1, 0, 3, 157, 34, },
++      { 2, 1, 0, 3, 157, 30, },
++      { 1, 1, 0, 3, 157, 63, },
++      { 0, 1, 0, 3, 161, 34, },
++      { 2, 1, 0, 3, 161, 30, },
++      { 1, 1, 0, 3, 161, 63, },
++      { 0, 1, 0, 3, 165, 34, },
++      { 2, 1, 0, 3, 165, 30, },
++      { 1, 1, 0, 3, 165, 63, },
++      { 0, 1, 1, 2, 38, 30, },
++      { 2, 1, 1, 2, 38, 32, },
++      { 1, 1, 1, 2, 38, 32, },
++      { 0, 1, 1, 2, 46, 30, },
++      { 2, 1, 1, 2, 46, 32, },
++      { 1, 1, 1, 2, 46, 32, },
++      { 0, 1, 1, 2, 54, 32, },
++      { 2, 1, 1, 2, 54, 32, },
++      { 1, 1, 1, 2, 54, 32, },
++      { 0, 1, 1, 2, 62, 32, },
++      { 2, 1, 1, 2, 62, 32, },
++      { 1, 1, 1, 2, 62, 32, },
++      { 0, 1, 1, 2, 102, 28, },
++      { 2, 1, 1, 2, 102, 32, },
++      { 1, 1, 1, 2, 102, 32, },
++      { 0, 1, 1, 2, 110, 32, },
++      { 2, 1, 1, 2, 110, 32, },
++      { 1, 1, 1, 2, 110, 32, },
++      { 0, 1, 1, 2, 118, 36, },
++      { 2, 1, 1, 2, 118, 32, },
++      { 1, 1, 1, 2, 118, 32, },
++      { 0, 1, 1, 2, 126, 34, },
++      { 2, 1, 1, 2, 126, 32, },
++      { 1, 1, 1, 2, 126, 32, },
++      { 0, 1, 1, 2, 134, 32, },
++      { 2, 1, 1, 2, 134, 32, },
++      { 1, 1, 1, 2, 134, 32, },
++      { 0, 1, 1, 2, 151, 36, },
++      { 2, 1, 1, 2, 151, 32, },
++      { 1, 1, 1, 2, 151, 63, },
++      { 0, 1, 1, 2, 159, 36, },
++      { 2, 1, 1, 2, 159, 32, },
++      { 1, 1, 1, 2, 159, 63, },
++      { 0, 1, 1, 3, 38, 28, },
++      { 2, 1, 1, 3, 38, 30, },
++      { 1, 1, 1, 3, 38, 30, },
++      { 0, 1, 1, 3, 46, 28, },
++      { 2, 1, 1, 3, 46, 30, },
++      { 1, 1, 1, 3, 46, 30, },
++      { 0, 1, 1, 3, 54, 30, },
++      { 2, 1, 1, 3, 54, 30, },
++      { 1, 1, 1, 3, 54, 30, },
++      { 0, 1, 1, 3, 62, 30, },
++      { 2, 1, 1, 3, 62, 30, },
++      { 1, 1, 1, 3, 62, 30, },
++      { 0, 1, 1, 3, 102, 26, },
++      { 2, 1, 1, 3, 102, 30, },
++      { 1, 1, 1, 3, 102, 30, },
++      { 0, 1, 1, 3, 110, 30, },
++      { 2, 1, 1, 3, 110, 30, },
++      { 1, 1, 1, 3, 110, 30, },
++      { 0, 1, 1, 3, 118, 34, },
++      { 2, 1, 1, 3, 118, 30, },
++      { 1, 1, 1, 3, 118, 30, },
++      { 0, 1, 1, 3, 126, 32, },
++      { 2, 1, 1, 3, 126, 30, },
++      { 1, 1, 1, 3, 126, 30, },
++      { 0, 1, 1, 3, 134, 30, },
++      { 2, 1, 1, 3, 134, 30, },
++      { 1, 1, 1, 3, 134, 30, },
++      { 0, 1, 1, 3, 151, 34, },
++      { 2, 1, 1, 3, 151, 30, },
++      { 1, 1, 1, 3, 151, 63, },
++      { 0, 1, 1, 3, 159, 34, },
++      { 2, 1, 1, 3, 159, 30, },
++      { 1, 1, 1, 3, 159, 63, },
++      { 0, 1, 2, 4, 42, 30, },
++      { 2, 1, 2, 4, 42, 32, },
++      { 1, 1, 2, 4, 42, 32, },
++      { 0, 1, 2, 4, 58, 28, },
++      { 2, 1, 2, 4, 58, 32, },
++      { 1, 1, 2, 4, 58, 32, },
++      { 0, 1, 2, 4, 106, 30, },
++      { 2, 1, 2, 4, 106, 32, },
++      { 1, 1, 2, 4, 106, 32, },
++      { 0, 1, 2, 4, 122, 34, },
++      { 2, 1, 2, 4, 122, 32, },
++      { 1, 1, 2, 4, 122, 32, },
++      { 0, 1, 2, 4, 155, 36, },
++      { 2, 1, 2, 4, 155, 32, },
++      { 1, 1, 2, 4, 155, 63, },
++      { 0, 1, 2, 5, 42, 28, },
++      { 2, 1, 2, 5, 42, 30, },
++      { 1, 1, 2, 5, 42, 30, },
++      { 0, 1, 2, 5, 58, 26, },
++      { 2, 1, 2, 5, 58, 30, },
++      { 1, 1, 2, 5, 58, 30, },
++      { 0, 1, 2, 5, 106, 28, },
++      { 2, 1, 2, 5, 106, 30, },
++      { 1, 1, 2, 5, 106, 30, },
++      { 0, 1, 2, 5, 122, 32, },
++      { 2, 1, 2, 5, 122, 30, },
++      { 1, 1, 2, 5, 122, 30, },
++      { 0, 1, 2, 5, 155, 34, },
++      { 2, 1, 2, 5, 155, 30, },
++      { 1, 1, 2, 5, 155, 63, },
++};
++
++RTW_DECL_TABLE_TXPWR_LMT(rtw8812a_txpwr_lmt);
++
++static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8812a[] = {
++      {0x0012,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
++      {0x0014,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0x80, 0},
++      {0x0015,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0x01, 0},
++      {0x0023,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0x10, 0},
++      {0x0046,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0x00},
++      {0x0043,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0x00},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_PCI_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(2), 0},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(3), 0},
++      {0x0003,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(2), BIT(2)},
++      {0x0301,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_PCI_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0},
++      {0x0024,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(1), BIT(1)},
++      {0x0028,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(3), BIT(3)},
++      {0xFFFF,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       0,
++       RTW_PWR_CMD_END, 0, 0},
++};
++
++static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8812a[] = {
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(2), 0},
++      {0x0006,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_POLLING, BIT(1), BIT(1)},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_PCI_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(7), 0},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(3), 0},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_POLLING, BIT(0), 0},
++      {0x0024,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(1), 0},
++      {0x0028,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(3), 0},
++      {0xFFFF,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       0,
++       RTW_PWR_CMD_END, 0, 0},
++};
++
++static const struct rtw_pwr_seq_cmd trans_act_to_lps_8812a[] = {
++      {0x0301,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_PCI_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0xFF},
++      {0x0522,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0x7F},
++      {0x05F8,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_POLLING, 0xFF, 0},
++      {0x05F9,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_POLLING, 0xFF, 0},
++      {0x05FA,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_POLLING, 0xFF, 0},
++      {0x05FB,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_POLLING, 0xFF, 0},
++      {0x0c00,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0x04},
++      {0x0e00,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0x04},
++      {0x0002,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(0), 0},
++      {0x0002,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_DELAY, 0, RTW_PWR_DELAY_US},
++      {0x0002,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(1), 0},
++      {0x0100,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0x03},
++      {0x0101,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(1), 0},
++      {0x0553,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(5), BIT(5)},
++      {0xFFFF,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       0,
++       RTW_PWR_CMD_END, 0, 0},
++};
++
++static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8812a[] = {
++      {0x0c00,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0x04},
++      {0x0e00,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0x04},
++      {0x0002,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(0), 0},
++      {0x0002,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_DELAY, 0, RTW_PWR_DELAY_US},
++      {0x0002,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_PCI_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(1), 0},
++      {0x0007,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0x2A},
++      {0x0008,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0x02, 0},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(1), BIT(1)},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_POLLING, BIT(1), 0},
++      {0xFFFF,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       0,
++       RTW_PWR_CMD_END, 0, 0},
++};
++
++static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8812a[] = {
++      {0x0003,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(2), 0},
++      {0x0080,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0x05},
++      {0x0042,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xF0, 0xcc},
++      {0x0042,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_PCI_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xF0, 0xEC},
++      {0x0043,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0x07},
++      {0x0045,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0x00},
++      {0x0046,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0xff},
++      {0x0047,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0},
++      {0x0014,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0x80, BIT(7)},
++      {0x0015,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0x01, BIT(0)},
++      {0x0012,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0x01, 0},
++      {0x0023,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0x10, BIT(4)},
++      {0x0008,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0x02, 0},
++      {0x0007,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0x20},
++      {0x001f,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(1), 0},
++      {0x0076,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(1), 0},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(3), BIT(3)},
++      {0xFFFF,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       0,
++       RTW_PWR_CMD_END, 0, 0},
++};
++
++const struct rtw_pwr_seq_cmd * const card_enable_flow_8812a[] = {
++      trans_carddis_to_cardemu_8812a,
++      trans_cardemu_to_act_8812a,
++      NULL
++};
++
++const struct rtw_pwr_seq_cmd * const enter_lps_flow_8812a[] = {
++      trans_act_to_lps_8812a,
++      NULL
++};
++
++const struct rtw_pwr_seq_cmd * const card_disable_flow_8812a[] = {
++      trans_act_to_cardemu_8812a,
++      trans_cardemu_to_carddis_8812a,
++      NULL
++};
++
++static const u8 rtw8812a_pwrtrk_5gb_n[][RTW_PWR_TRK_TBL_SZ] = {
++      {0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12,
++       12, 13, 13, 14, 14, 14, 14, 14, 14},
++      {0, 1, 1, 2, 2, 3, 4, 4, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12,
++       12, 13, 13, 14, 14, 14, 14, 14, 14},
++      {0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 11, 11, 12, 12, 13,
++       13, 14, 14, 15, 16, 16, 16, 16, 16},
++};
++
++static const u8 rtw8812a_pwrtrk_5gb_p[][RTW_PWR_TRK_TBL_SZ] = {
++      {0, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11,
++       11, 11, 11, 11, 11, 11, 11, 11, 11},
++      {0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11,
++       11, 11, 11, 11, 11, 11, 11, 11, 11},
++      {0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 8, 9, 9, 10, 11, 11, 11, 11, 11,
++       11, 11, 11, 11, 11, 11, 11, 11, 11},
++};
++
++static const u8 rtw8812a_pwrtrk_5ga_n[][RTW_PWR_TRK_TBL_SZ] = {
++      {0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12,
++       12, 13, 13, 14, 15, 15, 15, 15, 15},
++      {0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12,
++       12, 13, 13, 14, 15, 15, 15, 15, 15},
++      {0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12,
++       12, 13, 13, 14, 15, 15, 15, 15, 15},
++};
++
++static const u8 rtw8812a_pwrtrk_5ga_p[][RTW_PWR_TRK_TBL_SZ] = {
++      {0, 1, 1, 2, 2, 3, 4, 5, 6, 7, 7, 8, 8, 9, 10, 11, 11, 11, 11, 11, 11,
++       11, 11, 11, 11, 11, 11, 11, 11, 11},
++      {0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 8, 9, 10, 11, 11, 11, 11, 11, 11,
++       11, 11, 11, 11, 11, 11, 11, 11, 11},
++      {0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 8, 9, 10, 11, 11, 12, 12, 11, 11,
++       11, 11, 11, 11, 11, 11, 11, 11, 11},
++};
++
++static const u8 rtw8812a_pwrtrk_2gb_n[] = {
++      0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6,
++      7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11
++};
++
++static const u8 rtw8812a_pwrtrk_2gb_p[] = {
++      0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
++      6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
++};
++
++static const u8 rtw8812a_pwrtrk_2ga_n[] = {
++      0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
++      6, 6, 7, 7, 7, 8, 8, 9, 10, 10, 10, 10, 10, 10
++};
++
++static const u8 rtw8812a_pwrtrk_2ga_p[] = {
++      0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
++      6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
++};
++
++static const u8 rtw8812a_pwrtrk_2g_cck_b_n[] = {
++      0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6,
++      7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11
++};
++
++static const u8 rtw8812a_pwrtrk_2g_cck_b_p[] = {
++      0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
++      6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
++};
++
++static const u8 rtw8812a_pwrtrk_2g_cck_a_n[] = {
++      0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
++      6, 6, 7, 7, 7, 8, 8, 9, 10, 10, 10, 10, 10, 10
++};
++
++static const u8 rtw8812a_pwrtrk_2g_cck_a_p[] = {
++      0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
++      6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
++};
++
++const struct rtw_pwr_track_tbl rtw8812a_rtw_pwr_track_tbl = {
++      .pwrtrk_5gb_n[0] = rtw8812a_pwrtrk_5gb_n[0],
++      .pwrtrk_5gb_n[1] = rtw8812a_pwrtrk_5gb_n[1],
++      .pwrtrk_5gb_n[2] = rtw8812a_pwrtrk_5gb_n[2],
++      .pwrtrk_5gb_p[0] = rtw8812a_pwrtrk_5gb_p[0],
++      .pwrtrk_5gb_p[1] = rtw8812a_pwrtrk_5gb_p[1],
++      .pwrtrk_5gb_p[2] = rtw8812a_pwrtrk_5gb_p[2],
++      .pwrtrk_5ga_n[0] = rtw8812a_pwrtrk_5ga_n[0],
++      .pwrtrk_5ga_n[1] = rtw8812a_pwrtrk_5ga_n[1],
++      .pwrtrk_5ga_n[2] = rtw8812a_pwrtrk_5ga_n[2],
++      .pwrtrk_5ga_p[0] = rtw8812a_pwrtrk_5ga_p[0],
++      .pwrtrk_5ga_p[1] = rtw8812a_pwrtrk_5ga_p[1],
++      .pwrtrk_5ga_p[2] = rtw8812a_pwrtrk_5ga_p[2],
++      .pwrtrk_2gb_n = rtw8812a_pwrtrk_2gb_n,
++      .pwrtrk_2gb_p = rtw8812a_pwrtrk_2gb_p,
++      .pwrtrk_2ga_n = rtw8812a_pwrtrk_2ga_n,
++      .pwrtrk_2ga_p = rtw8812a_pwrtrk_2ga_p,
++      .pwrtrk_2g_cckb_n = rtw8812a_pwrtrk_2g_cck_b_n,
++      .pwrtrk_2g_cckb_p = rtw8812a_pwrtrk_2g_cck_b_p,
++      .pwrtrk_2g_ccka_n = rtw8812a_pwrtrk_2g_cck_a_n,
++      .pwrtrk_2g_ccka_p = rtw8812a_pwrtrk_2g_cck_a_p,
++};
++
++static const u8 rtw8812a_pwrtrk_rfe3_5gb_n[][RTW_PWR_TRK_TBL_SZ] = {
++      {0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 13,
++       13, 14, 15, 16, 16, 17, 17, 18, 18},
++      {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11,
++       12, 14, 13, 13, 14, 14, 14, 15, 15},
++      {0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12,
++       12, 13, 13, 14, 14, 15, 15, 16, 16},
++};
++
++static const u8 rtw8812a_pwrtrk_rfe3_5gb_p[][RTW_PWR_TRK_TBL_SZ] = {
++      {0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11,
++       11, 11, 11, 11, 11, 11, 11, 11, 11},
++      {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11,
++       11, 11, 11, 11, 11, 11, 11, 11, 11},
++      {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 9, 10, 10, 11, 11, 11,
++       11, 11, 11, 11, 11, 11, 11, 11, 11},
++};
++
++static const u8 rtw8812a_pwrtrk_rfe3_5ga_n[][RTW_PWR_TRK_TBL_SZ] = {
++      {0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12,
++       13, 14, 15, 16, 16, 17, 17, 18, 18},
++      {0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 9, 9, 10, 10, 11, 11, 12,
++       12, 13, 13, 14, 15, 16, 16, 17, 17},
++      {0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 12, 13,
++       13, 14, 14, 15, 15, 16, 17, 18, 18},
++};
++
++static const u8 rtw8812a_pwrtrk_rfe3_5ga_p[][RTW_PWR_TRK_TBL_SZ] = {
++      {0, 1, 1, 2, 2, 3, 4, 5, 6, 7, 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11,
++       11, 11, 11, 11, 11, 11, 11, 11, 11},
++      {0, 1, 2, 3, 4, 4, 5, 5, 6, 7, 7, 8, 9, 9, 10, 11, 11, 11, 11, 11, 11,
++       11, 11, 11, 11, 11, 11, 11, 11, 11},
++      {0, 1, 2, 3, 4, 4, 5, 5, 6, 7, 7, 8, 9, 9, 10, 11, 11, 11, 11, 11, 11,
++       11, 11, 11, 11, 11, 11, 11, 11, 11},
++};
++
++static const u8 rtw8812a_pwrtrk_rfe3_2gb_n[] = {
++      0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7,
++      7, 7, 8, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, 15
++};
++
++static const u8 rtw8812a_pwrtrk_rfe3_2gb_p[] = {
++      0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
++      6, 7, 7, 8, 9, 10, 10, 10, 10, 11, 11, 11, 11, 11
++};
++
++static const u8 rtw8812a_pwrtrk_rfe3_2ga_n[] = {
++      0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 6, 7, 7, 8, 8, 9,
++      10, 10, 11, 11, 12, 12, 13, 13, 13, 13, 14, 14, 15, 15
++};
++
++static const u8 rtw8812a_pwrtrk_rfe3_2ga_p[] = {
++      0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6,
++      6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11
++};
++
++static const u8 rtw8812a_pwrtrk_rfe3_2g_cck_b_n[] = {
++      0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 6, 7,
++      7, 7, 8, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15, 15
++};
++
++static const u8 rtw8812a_pwrtrk_rfe3_2g_cck_b_p[] = {
++      0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
++      6, 7, 7, 8, 9, 10, 10, 10, 10, 11, 11, 11, 11, 11
++};
++
++static const u8 rtw8812a_pwrtrk_rfe3_2g_cck_a_n[] = {
++      0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 6, 7, 7, 8, 8, 9,
++      10, 10, 11, 11, 12, 12, 13, 13, 13, 13, 14, 14, 15, 15
++};
++
++static const u8 rtw8812a_pwrtrk_rfe3_2g_cck_a_p[] = {
++      0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6,
++      6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11
++};
++
++const struct rtw_pwr_track_tbl rtw8812a_rtw_pwr_track_rfe3_tbl = {
++      .pwrtrk_5gb_n[0] = rtw8812a_pwrtrk_rfe3_5gb_n[0],
++      .pwrtrk_5gb_n[1] = rtw8812a_pwrtrk_rfe3_5gb_n[1],
++      .pwrtrk_5gb_n[2] = rtw8812a_pwrtrk_rfe3_5gb_n[2],
++      .pwrtrk_5gb_p[0] = rtw8812a_pwrtrk_rfe3_5gb_p[0],
++      .pwrtrk_5gb_p[1] = rtw8812a_pwrtrk_rfe3_5gb_p[1],
++      .pwrtrk_5gb_p[2] = rtw8812a_pwrtrk_rfe3_5gb_p[2],
++      .pwrtrk_5ga_n[0] = rtw8812a_pwrtrk_rfe3_5ga_n[0],
++      .pwrtrk_5ga_n[1] = rtw8812a_pwrtrk_rfe3_5ga_n[1],
++      .pwrtrk_5ga_n[2] = rtw8812a_pwrtrk_rfe3_5ga_n[2],
++      .pwrtrk_5ga_p[0] = rtw8812a_pwrtrk_rfe3_5ga_p[0],
++      .pwrtrk_5ga_p[1] = rtw8812a_pwrtrk_rfe3_5ga_p[1],
++      .pwrtrk_5ga_p[2] = rtw8812a_pwrtrk_rfe3_5ga_p[2],
++      .pwrtrk_2gb_n = rtw8812a_pwrtrk_rfe3_2gb_n,
++      .pwrtrk_2gb_p = rtw8812a_pwrtrk_rfe3_2gb_p,
++      .pwrtrk_2ga_n = rtw8812a_pwrtrk_rfe3_2ga_n,
++      .pwrtrk_2ga_p = rtw8812a_pwrtrk_rfe3_2ga_p,
++      .pwrtrk_2g_cckb_n = rtw8812a_pwrtrk_rfe3_2g_cck_b_n,
++      .pwrtrk_2g_cckb_p = rtw8812a_pwrtrk_rfe3_2g_cck_b_p,
++      .pwrtrk_2g_ccka_n = rtw8812a_pwrtrk_rfe3_2g_cck_a_n,
++      .pwrtrk_2g_ccka_p = rtw8812a_pwrtrk_rfe3_2g_cck_a_p,
++};
+--- /dev/null
++++ b/drivers/net/wireless/realtek/rtw88/rtw8812a_table.h
+@@ -0,0 +1,26 @@
++/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
++/* Copyright(c) 2024  Realtek Corporation
++ */
++
++#ifndef __RTW8812A_TABLE_H__
++#define __RTW8812A_TABLE_H__
++
++extern const struct rtw_table rtw8812a_mac_tbl;
++extern const struct rtw_table rtw8812a_agc_tbl;
++extern const struct rtw_table rtw8812a_agc_diff_lb_tbl;
++extern const struct rtw_table rtw8812a_agc_diff_hb_tbl;
++extern const struct rtw_table rtw8812a_bb_tbl;
++extern const struct rtw_table rtw8812a_bb_pg_tbl;
++extern const struct rtw_table rtw8812a_bb_pg_rfe3_tbl;
++extern const struct rtw_table rtw8812a_rf_a_tbl;
++extern const struct rtw_table rtw8812a_rf_b_tbl;
++extern const struct rtw_table rtw8812a_txpwr_lmt_tbl;
++
++extern const struct rtw_pwr_seq_cmd * const card_enable_flow_8812a[];
++extern const struct rtw_pwr_seq_cmd * const enter_lps_flow_8812a[];
++extern const struct rtw_pwr_seq_cmd * const card_disable_flow_8812a[];
++
++extern const struct rtw_pwr_track_tbl rtw8812a_rtw_pwr_track_tbl;
++extern const struct rtw_pwr_track_tbl rtw8812a_rtw_pwr_track_rfe3_tbl;
++
++#endif
diff --git a/package/kernel/mac80211/patches/rtl/040-v6.13-wifi-rtw88-Add-rtw8821a_table.-c-h.patch b/package/kernel/mac80211/patches/rtl/040-v6.13-wifi-rtw88-Add-rtw8821a_table.-c-h.patch
new file mode 100644 (file)
index 0000000..e8ceaba
--- /dev/null
@@ -0,0 +1,2395 @@
+From 4b81da5cd2b4c7231272216639bacecc818d8b51 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 30 Oct 2024 20:25:16 +0200
+Subject: [PATCH] wifi: rtw88: Add rtw8821a_table.{c,h}
+
+These contain various arrays for initialising RTL8821AU. Also TX power
+limits.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/087c7260-fcc3-4e22-886b-ac477cad9198@gmail.com
+---
+ .../wireless/realtek/rtw88/rtw8821a_table.c   | 2350 +++++++++++++++++
+ .../wireless/realtek/rtw88/rtw8821a_table.h   |   21 +
+ 2 files changed, 2371 insertions(+)
+ create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821a_table.c
+ create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821a_table.h
+
+--- /dev/null
++++ b/drivers/net/wireless/realtek/rtw88/rtw8821a_table.c
+@@ -0,0 +1,2350 @@
++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
++/* Copyright(c) 2024  Realtek Corporation
++ */
++
++#include "main.h"
++#include "phy.h"
++#include "rtw8821a_table.h"
++
++static const u32 rtw8821a_mac[] = {
++      0x421, 0x0000000F,
++      0x428, 0x0000000A,
++      0x429, 0x00000010,
++      0x430, 0x00000000,
++      0x431, 0x00000000,
++      0x432, 0x00000000,
++      0x433, 0x00000001,
++      0x434, 0x00000004,
++      0x435, 0x00000005,
++      0x436, 0x00000007,
++      0x437, 0x00000008,
++      0x43C, 0x00000004,
++      0x43D, 0x00000005,
++      0x43E, 0x00000007,
++      0x43F, 0x00000008,
++      0x440, 0x0000005D,
++      0x441, 0x00000001,
++      0x442, 0x00000000,
++      0x444, 0x00000010,
++      0x445, 0x00000000,
++      0x446, 0x00000000,
++      0x447, 0x00000000,
++      0x448, 0x00000000,
++      0x449, 0x000000F0,
++      0x44A, 0x0000000F,
++      0x44B, 0x0000003E,
++      0x44C, 0x00000010,
++      0x44D, 0x00000000,
++      0x44E, 0x00000000,
++      0x44F, 0x00000000,
++      0x450, 0x00000000,
++      0x451, 0x000000F0,
++      0x452, 0x0000000F,
++      0x453, 0x00000000,
++      0x456, 0x0000005E,
++      0x460, 0x00000066,
++      0x461, 0x00000066,
++      0x4C8, 0x0000003F,
++      0x4C9, 0x000000FF,
++      0x4CC, 0x000000FF,
++      0x4CD, 0x000000FF,
++      0x4CE, 0x00000001,
++      0x500, 0x00000026,
++      0x501, 0x000000A2,
++      0x502, 0x0000002F,
++      0x503, 0x00000000,
++      0x504, 0x00000028,
++      0x505, 0x000000A3,
++      0x506, 0x0000005E,
++      0x507, 0x00000000,
++      0x508, 0x0000002B,
++      0x509, 0x000000A4,
++      0x50A, 0x0000005E,
++      0x50B, 0x00000000,
++      0x50C, 0x0000004F,
++      0x50D, 0x000000A4,
++      0x50E, 0x00000000,
++      0x50F, 0x00000000,
++      0x512, 0x0000001C,
++      0x514, 0x0000000A,
++      0x516, 0x0000000A,
++      0x525, 0x0000004F,
++      0x550, 0x00000010,
++      0x551, 0x00000010,
++      0x559, 0x00000002,
++      0x55C, 0x00000050,
++      0x55D, 0x000000FF,
++      0x605, 0x00000030,
++      0x607, 0x00000007,
++      0x608, 0x0000000E,
++      0x609, 0x0000002A,
++      0x620, 0x000000FF,
++      0x621, 0x000000FF,
++      0x622, 0x000000FF,
++      0x623, 0x000000FF,
++      0x624, 0x000000FF,
++      0x625, 0x000000FF,
++      0x626, 0x000000FF,
++      0x627, 0x000000FF,
++      0x638, 0x00000050,
++      0x63C, 0x0000000A,
++      0x63D, 0x0000000A,
++      0x63E, 0x0000000E,
++      0x63F, 0x0000000E,
++      0x640, 0x00000040,
++      0x642, 0x00000040,
++      0x643, 0x00000000,
++      0x652, 0x000000C8,
++      0x66E, 0x00000005,
++      0x700, 0x00000021,
++      0x701, 0x00000043,
++      0x702, 0x00000065,
++      0x703, 0x00000087,
++      0x708, 0x00000021,
++      0x709, 0x00000043,
++      0x70A, 0x00000065,
++      0x70B, 0x00000087,
++      0x718, 0x00000040,
++};
++
++RTW_DECL_TABLE_PHY_COND(rtw8821a_mac, rtw_phy_cfg_mac);
++
++static const u32 rtw8821a_agc[] = {
++      0x81C, 0xBF000001,
++      0x81C, 0xBF020001,
++      0x81C, 0xBF040001,
++      0x81C, 0xBF060001,
++      0x81C, 0xBE080001,
++      0x81C, 0xBD0A0001,
++      0x81C, 0xBC0C0001,
++      0x81C, 0xBA0E0001,
++      0x81C, 0xB9100001,
++      0x81C, 0xB8120001,
++      0x81C, 0xB7140001,
++      0x81C, 0xB6160001,
++      0x81C, 0xB5180001,
++      0x81C, 0xB41A0001,
++      0x81C, 0xB31C0001,
++      0x81C, 0xB21E0001,
++      0x81C, 0xB1200001,
++      0x81C, 0xB0220001,
++      0x81C, 0xAF240001,
++      0x81C, 0xAE260001,
++      0x81C, 0xAD280001,
++      0x81C, 0xAC2A0001,
++      0x81C, 0xAB2C0001,
++      0x81C, 0xAA2E0001,
++      0x81C, 0xA9300001,
++      0x81C, 0xA8320001,
++      0x81C, 0xA7340001,
++      0x81C, 0xA6360001,
++      0x81C, 0xA5380001,
++      0x81C, 0xA43A0001,
++      0x81C, 0x683C0001,
++      0x81C, 0x673E0001,
++      0x81C, 0x66400001,
++      0x81C, 0x65420001,
++      0x81C, 0x64440001,
++      0x81C, 0x63460001,
++      0x81C, 0x62480001,
++      0x81C, 0x614A0001,
++      0x81C, 0x474C0001,
++      0x81C, 0x464E0001,
++      0x81C, 0x45500001,
++      0x81C, 0x44520001,
++      0x81C, 0x43540001,
++      0x81C, 0x42560001,
++      0x81C, 0x41580001,
++      0x81C, 0x285A0001,
++      0x81C, 0x275C0001,
++      0x81C, 0x265E0001,
++      0x81C, 0x25600001,
++      0x81C, 0x24620001,
++      0x81C, 0x0A640001,
++      0x81C, 0x09660001,
++      0x81C, 0x08680001,
++      0x81C, 0x076A0001,
++      0x81C, 0x066C0001,
++      0x81C, 0x056E0001,
++      0x81C, 0x04700001,
++      0x81C, 0x03720001,
++      0x81C, 0x02740001,
++      0x81C, 0x01760001,
++      0x81C, 0x01780001,
++      0x81C, 0x017A0001,
++      0x81C, 0x017C0001,
++      0x81C, 0x017E0001,
++      0x8000020c,     0x00000000,     0x40000000,     0x00000000,
++      0x81C, 0xFB000101,
++      0x81C, 0xFA020101,
++      0x81C, 0xF9040101,
++      0x81C, 0xF8060101,
++      0x81C, 0xF7080101,
++      0x81C, 0xF60A0101,
++      0x81C, 0xF50C0101,
++      0x81C, 0xF40E0101,
++      0x81C, 0xF3100101,
++      0x81C, 0xF2120101,
++      0x81C, 0xF1140101,
++      0x81C, 0xF0160101,
++      0x81C, 0xEF180101,
++      0x81C, 0xEE1A0101,
++      0x81C, 0xED1C0101,
++      0x81C, 0xEC1E0101,
++      0x81C, 0xEB200101,
++      0x81C, 0xEA220101,
++      0x81C, 0xE9240101,
++      0x81C, 0xE8260101,
++      0x81C, 0xE7280101,
++      0x81C, 0xE62A0101,
++      0x81C, 0xE52C0101,
++      0x81C, 0xE42E0101,
++      0x81C, 0xE3300101,
++      0x81C, 0xA5320101,
++      0x81C, 0xA4340101,
++      0x81C, 0xA3360101,
++      0x81C, 0x87380101,
++      0x81C, 0x863A0101,
++      0x81C, 0x853C0101,
++      0x81C, 0x843E0101,
++      0x81C, 0x69400101,
++      0x81C, 0x68420101,
++      0x81C, 0x67440101,
++      0x81C, 0x66460101,
++      0x81C, 0x49480101,
++      0x81C, 0x484A0101,
++      0x81C, 0x474C0101,
++      0x81C, 0x2A4E0101,
++      0x81C, 0x29500101,
++      0x81C, 0x28520101,
++      0x81C, 0x27540101,
++      0x81C, 0x26560101,
++      0x81C, 0x25580101,
++      0x81C, 0x245A0101,
++      0x81C, 0x235C0101,
++      0x81C, 0x055E0101,
++      0x81C, 0x04600101,
++      0x81C, 0x03620101,
++      0x81C, 0x02640101,
++      0x81C, 0x01660101,
++      0x81C, 0x01680101,
++      0x81C, 0x016A0101,
++      0x81C, 0x016C0101,
++      0x81C, 0x016E0101,
++      0x81C, 0x01700101,
++      0x81C, 0x01720101,
++      0x9000040c,     0x00000000,     0x40000000,     0x00000000,
++      0x81C, 0xFB000101,
++      0x81C, 0xFA020101,
++      0x81C, 0xF9040101,
++      0x81C, 0xF8060101,
++      0x81C, 0xF7080101,
++      0x81C, 0xF60A0101,
++      0x81C, 0xF50C0101,
++      0x81C, 0xF40E0101,
++      0x81C, 0xF3100101,
++      0x81C, 0xF2120101,
++      0x81C, 0xF1140101,
++      0x81C, 0xF0160101,
++      0x81C, 0xEF180101,
++      0x81C, 0xEE1A0101,
++      0x81C, 0xED1C0101,
++      0x81C, 0xEC1E0101,
++      0x81C, 0xEB200101,
++      0x81C, 0xEA220101,
++      0x81C, 0xE9240101,
++      0x81C, 0xE8260101,
++      0x81C, 0xE7280101,
++      0x81C, 0xE62A0101,
++      0x81C, 0xE52C0101,
++      0x81C, 0xE42E0101,
++      0x81C, 0xE3300101,
++      0x81C, 0xA5320101,
++      0x81C, 0xA4340101,
++      0x81C, 0xA3360101,
++      0x81C, 0x87380101,
++      0x81C, 0x863A0101,
++      0x81C, 0x853C0101,
++      0x81C, 0x843E0101,
++      0x81C, 0x69400101,
++      0x81C, 0x68420101,
++      0x81C, 0x67440101,
++      0x81C, 0x66460101,
++      0x81C, 0x49480101,
++      0x81C, 0x484A0101,
++      0x81C, 0x474C0101,
++      0x81C, 0x2A4E0101,
++      0x81C, 0x29500101,
++      0x81C, 0x28520101,
++      0x81C, 0x27540101,
++      0x81C, 0x26560101,
++      0x81C, 0x25580101,
++      0x81C, 0x245A0101,
++      0x81C, 0x235C0101,
++      0x81C, 0x055E0101,
++      0x81C, 0x04600101,
++      0x81C, 0x03620101,
++      0x81C, 0x02640101,
++      0x81C, 0x01660101,
++      0x81C, 0x01680101,
++      0x81C, 0x016A0101,
++      0x81C, 0x016C0101,
++      0x81C, 0x016E0101,
++      0x81C, 0x01700101,
++      0x81C, 0x01720101,
++      0xA0000000,     0x00000000,
++      0x81C, 0xFF000101,
++      0x81C, 0xFF020101,
++      0x81C, 0xFE040101,
++      0x81C, 0xFD060101,
++      0x81C, 0xFC080101,
++      0x81C, 0xFD0A0101,
++      0x81C, 0xFC0C0101,
++      0x81C, 0xFB0E0101,
++      0x81C, 0xFA100101,
++      0x81C, 0xF9120101,
++      0x81C, 0xF8140101,
++      0x81C, 0xF7160101,
++      0x81C, 0xF6180101,
++      0x81C, 0xF51A0101,
++      0x81C, 0xF41C0101,
++      0x81C, 0xF31E0101,
++      0x81C, 0xF2200101,
++      0x81C, 0xF1220101,
++      0x81C, 0xF0240101,
++      0x81C, 0xEF260101,
++      0x81C, 0xEE280101,
++      0x81C, 0xED2A0101,
++      0x81C, 0xEC2C0101,
++      0x81C, 0xEB2E0101,
++      0x81C, 0xEA300101,
++      0x81C, 0xE9320101,
++      0x81C, 0xE8340101,
++      0x81C, 0xE7360101,
++      0x81C, 0xE6380101,
++      0x81C, 0xE53A0101,
++      0x81C, 0xE43C0101,
++      0x81C, 0xE33E0101,
++      0x81C, 0xA5400101,
++      0x81C, 0xA4420101,
++      0x81C, 0xA3440101,
++      0x81C, 0x87460101,
++      0x81C, 0x86480101,
++      0x81C, 0x854A0101,
++      0x81C, 0x844C0101,
++      0x81C, 0x694E0101,
++      0x81C, 0x68500101,
++      0x81C, 0x67520101,
++      0x81C, 0x66540101,
++      0x81C, 0x49560101,
++      0x81C, 0x48580101,
++      0x81C, 0x475A0101,
++      0x81C, 0x2A5C0101,
++      0x81C, 0x295E0101,
++      0x81C, 0x28600101,
++      0x81C, 0x27620101,
++      0x81C, 0x26640101,
++      0x81C, 0x25660101,
++      0x81C, 0x24680101,
++      0x81C, 0x236A0101,
++      0x81C, 0x056C0101,
++      0x81C, 0x046E0101,
++      0x81C, 0x03700101,
++      0x81C, 0x02720101,
++      0xB0000000,     0x00000000,
++      0x81C, 0x01740101,
++      0x81C, 0x01760101,
++      0x81C, 0x01780101,
++      0x81C, 0x017A0101,
++      0x81C, 0x017C0101,
++      0x81C, 0x017E0101,
++      0xC50, 0x00000022,
++      0xC50, 0x00000020,
++};
++
++RTW_DECL_TABLE_PHY_COND(rtw8821a_agc, rtw_phy_cfg_agc);
++
++static const u32 rtw8821a_bb[] = {
++      0x800, 0x0020D090,
++      0x804, 0x080112E0,
++      0x808, 0x0E028211,
++      0x80C, 0x92131111,
++      0x810, 0x20101261,
++      0x814, 0x020C3D10,
++      0x818, 0x03A00385,
++      0x820, 0x00000000,
++      0x824, 0x00030FE0,
++      0x828, 0x00000000,
++      0x82C, 0x002081DD,
++      0x830, 0x2AAAEEC8,
++      0x834, 0x0037A706,
++      0x838, 0x06489B44,
++      0x83C, 0x0000095B,
++      0x840, 0xC0000001,
++      0x844, 0x40003CDE,
++      0x848, 0x62103F8B,
++      0x84C, 0x6CFDFFB8,
++      0x850, 0x28874706,
++      0x854, 0x0001520C,
++      0x858, 0x8060E000,
++      0x85C, 0x74210168,
++      0x860, 0x6929C321,
++      0x864, 0x79727432,
++      0x868, 0x8CA7A314,
++      0x86C, 0x888C2878,
++      0x870, 0x08888888,
++      0x874, 0x31612C2E,
++      0x878, 0x00000152,
++      0x87C, 0x000FD000,
++      0x8A0, 0x00000013,
++      0x8A4, 0x7F7F7F7F,
++      0x8A8, 0xA2000338,
++      0x8AC, 0x0FF0FA0A,
++      0x8B4, 0x000FC080,
++      0x8B8, 0x6C10D7FF,
++      0x8BC, 0x0CA52090,
++      0x8C0, 0x1BF00020,
++      0x8C4, 0x00000000,
++      0x8C8, 0x00013169,
++      0x8CC, 0x08248492,
++      0x8D4, 0x940008A0,
++      0x8D8, 0x290B5612,
++      0x8F8, 0x400002C0,
++      0x8FC, 0x00000000,
++      0x900, 0x00000700,
++      0x90C, 0x00000000,
++      0x910, 0x0000FC00,
++      0x914, 0x00000404,
++      0x918, 0x1C1028C0,
++      0x91C, 0x64B11A1C,
++      0x920, 0xE0767233,
++      0x924, 0x055AA500,
++      0x928, 0x00000004,
++      0x92C, 0xFFFE0000,
++      0x930, 0xFFFFFFFE,
++      0x934, 0x001FFFFF,
++      0x960, 0x00000000,
++      0x964, 0x00000000,
++      0x968, 0x00000000,
++      0x96C, 0x00000000,
++      0x970, 0x801FFFFF,
++      0x974, 0x000003FF,
++      0x978, 0x00000000,
++      0x97C, 0x00000000,
++      0x980, 0x00000000,
++      0x984, 0x00000000,
++      0x988, 0x00000000,
++      0x990, 0x27100000,
++      0x994, 0xFFFF0100,
++      0x998, 0xFFFFFF5C,
++      0x99C, 0xFFFFFFFF,
++      0x9A0, 0x000000FF,
++      0x9A4, 0x00480080,
++      0x9A8, 0x00000000,
++      0x9AC, 0x00000000,
++      0x9B0, 0x81081008,
++      0x9B4, 0x01081008,
++      0x9B8, 0x01081008,
++      0x9BC, 0x01081008,
++      0x9D0, 0x00000000,
++      0x9D4, 0x00000000,
++      0x9D8, 0x00000000,
++      0x9DC, 0x00000000,
++      0x9E0, 0x00005D00,
++      0x9E4, 0x00000003,
++      0x9E8, 0x00000001,
++      0xA00, 0x00D047C8,
++      0xA04, 0x01FF800C,
++      0xA08, 0x8C8A8300,
++      0xA0C, 0x2E68000F,
++      0xA10, 0x9500BB78,
++      0xA14, 0x11144028,
++      0xA18, 0x00881117,
++      0xA1C, 0x89140F00,
++      0xA20, 0x1A1B0000,
++      0xA24, 0x090E1317,
++      0xA28, 0x00000204,
++      0xA2C, 0x00900000,
++      0xA70, 0x101FFF00,
++      0xA74, 0x00000008,
++      0xA78, 0x00000900,
++      0xA7C, 0x225B0606,
++      0xA80, 0x21805490,
++      0xA84, 0x001F0000,
++      0XB00, 0x03100040,
++      0XB04, 0x0000B000,
++      0XB08, 0xAE0201EB,
++      0XB0C, 0x01003207,
++      0XB10, 0x00009807,
++      0XB14, 0x01000000,
++      0XB18, 0x00000002,
++      0XB1C, 0x00000002,
++      0XB20, 0x0000001F,
++      0XB24, 0x03020100,
++      0XB28, 0x07060504,
++      0XB2C, 0x0B0A0908,
++      0XB30, 0x0F0E0D0C,
++      0XB34, 0x13121110,
++      0XB38, 0x17161514,
++      0XB3C, 0x0000003A,
++      0XB40, 0x00000000,
++      0XB44, 0x00000000,
++      0XB48, 0x13000032,
++      0XB4C, 0x48080000,
++      0XB50, 0x00000000,
++      0XB54, 0x00000000,
++      0XB58, 0x00000000,
++      0XB5C, 0x00000000,
++      0xC00, 0x00000007,
++      0xC04, 0x00042020,
++      0xC08, 0x80410231,
++      0xC0C, 0x00000000,
++      0xC10, 0x00000100,
++      0xC14, 0x01000000,
++      0xC1C, 0x40000003,
++      0xC20, 0x2C2C2C2C,
++      0xC24, 0x30303030,
++      0xC28, 0x30303030,
++      0xC2C, 0x2C2C2C2C,
++      0xC30, 0x2C2C2C2C,
++      0xC34, 0x2C2C2C2C,
++      0xC38, 0x2C2C2C2C,
++      0xC3C, 0x2A2A2A2A,
++      0xC40, 0x2A2A2A2A,
++      0xC44, 0x2A2A2A2A,
++      0xC48, 0x2A2A2A2A,
++      0xC4C, 0x2A2A2A2A,
++      0xC50, 0x00000020,
++      0xC54, 0x001C1208,
++      0xC58, 0x30000C1C,
++      0xC5C, 0x00000058,
++      0xC60, 0x34344443,
++      0xC64, 0x07003333,
++      0xC68, 0x19791979,
++      0xC6C, 0x19791979,
++      0xC70, 0x19791979,
++      0xC74, 0x19791979,
++      0xC78, 0x19791979,
++      0xC7C, 0x19791979,
++      0xC80, 0x19791979,
++      0xC84, 0x19791979,
++      0xC94, 0x0100005C,
++      0xC98, 0x00000000,
++      0xC9C, 0x00000000,
++      0xCA0, 0x00000029,
++      0xCA4, 0x08040201,
++      0xCA8, 0x80402010,
++      0xCB0, 0x77775747,
++      0xCB4, 0x10000077,
++      0xCB8, 0x00508240,
++};
++
++RTW_DECL_TABLE_PHY_COND(rtw8821a_bb, rtw_phy_cfg_bb);
++
++static const struct rtw_phy_pg_cfg_pair rtw8821a_bb_pg[] = {
++      { 0, 0, 0, 0x00000c20, 0xffffffff, 0x32343638, },
++      { 0, 0, 0, 0x00000c24, 0xffffffff, 0x36363838, },
++      { 0, 0, 0, 0x00000c28, 0xffffffff, 0x28303234, },
++      { 0, 0, 0, 0x00000c2c, 0xffffffff, 0x34363838, },
++      { 0, 0, 0, 0x00000c30, 0xffffffff, 0x26283032, },
++      { 0, 0, 0, 0x00000c3c, 0xffffffff, 0x32343636, },
++      { 0, 0, 0, 0x00000c40, 0xffffffff, 0x24262830, },
++      { 0, 0, 0, 0x00000c44, 0x0000ffff, 0x00002022, },
++      { 1, 0, 0, 0x00000c24, 0xffffffff, 0x34343636, },
++      { 1, 0, 0, 0x00000c28, 0xffffffff, 0x26283032, },
++      { 1, 0, 0, 0x00000c2c, 0xffffffff, 0x32343636, },
++      { 1, 0, 0, 0x00000c30, 0xffffffff, 0x24262830, },
++      { 1, 0, 0, 0x00000c3c, 0xffffffff, 0x32343636, },
++      { 1, 0, 0, 0x00000c40, 0xffffffff, 0x24262830, },
++      { 1, 0, 0, 0x00000c44, 0x0000ffff, 0x00002022, },
++};
++
++RTW_DECL_TABLE_BB_PG(rtw8821a_bb_pg);
++
++static const u32 rtw8821a_rf_a[] = {
++      0x018, 0x0001712A,
++      0x056, 0x00051CF2,
++      0x066, 0x00040000,
++      0x000, 0x00010000,
++      0x01E, 0x00080000,
++      0x082, 0x00000830,
++      0x083, 0x00021800,
++      0x084, 0x00028000,
++      0x085, 0x00048000,
++      0x80000111,     0x00000000,     0x40000000,     0x00000000,
++      0x086, 0x0009483A,
++      0xA0000000,     0x00000000,
++      0x086, 0x00094838,
++      0xB0000000,     0x00000000,
++      0x087, 0x00044980,
++      0x088, 0x00048000,
++      0x089, 0x0000D480,
++      0x08A, 0x00042240,
++      0x08B, 0x000F0380,
++      0x08C, 0x00090000,
++      0x08D, 0x00022852,
++      0x08E, 0x00065540,
++      0x08F, 0x00088001,
++      0x0EF, 0x00020000,
++      0x03E, 0x00000380,
++      0x03F, 0x00090018,
++      0x03E, 0x00020380,
++      0x03F, 0x000A0018,
++      0x03E, 0x00040308,
++      0x03F, 0x000A0018,
++      0x03E, 0x00060018,
++      0x03F, 0x000A0018,
++      0x0EF, 0x00000000,
++      0x018, 0x0001712A,
++      0x089, 0x00000080,
++      0x08B, 0x00080180,
++      0x0EF, 0x00001000,
++      0x03A, 0x00000244,
++      0x03B, 0x00038027,
++      0x03C, 0x00082000,
++      0x03A, 0x00000244,
++      0x03B, 0x00030113,
++      0x03C, 0x00082000,
++      0x03A, 0x0000014C,
++      0x03B, 0x00028027,
++      0x03C, 0x00082000,
++      0x03A, 0x000000CC,
++      0x03B, 0x00027027,
++      0x03C, 0x00042000,
++      0x03A, 0x0000014C,
++      0x03B, 0x0001F913,
++      0x03C, 0x00042000,
++      0x03A, 0x0000010C,
++      0x03B, 0x00017F10,
++      0x03C, 0x00012000,
++      0x03A, 0x000000D0,
++      0x03B, 0x00008027,
++      0x03C, 0x000CA000,
++      0x03A, 0x00000244,
++      0x03B, 0x00078027,
++      0x03C, 0x00082000,
++      0x03A, 0x00000244,
++      0x03B, 0x00070113,
++      0x03C, 0x00082000,
++      0x03A, 0x0000014C,
++      0x03B, 0x00068027,
++      0x03C, 0x00082000,
++      0x03A, 0x000000CC,
++      0x03B, 0x00067027,
++      0x03C, 0x00042000,
++      0x03A, 0x0000014C,
++      0x03B, 0x0005F913,
++      0x03C, 0x00042000,
++      0x03A, 0x0000010C,
++      0x03B, 0x00057F10,
++      0x03C, 0x00012000,
++      0x03A, 0x000000D0,
++      0x03B, 0x00048027,
++      0x03C, 0x000CA000,
++      0x03A, 0x00000244,
++      0x03B, 0x000B8027,
++      0x03C, 0x00082000,
++      0x03A, 0x00000244,
++      0x03B, 0x000B0113,
++      0x03C, 0x00082000,
++      0x03A, 0x0000014C,
++      0x03B, 0x000A8027,
++      0x03C, 0x00082000,
++      0x03A, 0x000000CC,
++      0x03B, 0x000A7027,
++      0x03C, 0x00042000,
++      0x03A, 0x0000014C,
++      0x03B, 0x0009F913,
++      0x03C, 0x00042000,
++      0x03A, 0x0000010C,
++      0x03B, 0x00097F10,
++      0x03C, 0x00012000,
++      0x03A, 0x000000D0,
++      0x03B, 0x00088027,
++      0x03C, 0x000CA000,
++      0x0EF, 0x00000000,
++      0x0EF, 0x00001100,
++      0x80000111,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0004ADF3,
++      0x034, 0x00049DF0,
++      0x90000110,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0004ADF3,
++      0x034, 0x00049DF0,
++      0x90000210,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0004ADF5,
++      0x034, 0x00049DF2,
++      0x9000020c,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0004A0F3,
++      0x034, 0x000490B1,
++      0x9000040c,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0004A0F3,
++      0x034, 0x000490B1,
++      0x90000200,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0004ADF5,
++      0x034, 0x00049DF2,
++      0x90000410,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0004ADF3,
++      0x034, 0x00049DF0,
++      0xA0000000,     0x00000000,
++      0x034, 0x0004ADF7,
++      0x034, 0x00049DF3,
++      0xB0000000,     0x00000000,
++      0x80000111,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x00048DED,
++      0x034, 0x00047DEA,
++      0x034, 0x00046DE7,
++      0x034, 0x00045CE9,
++      0x034, 0x00044CE6,
++      0x034, 0x000438C6,
++      0x034, 0x00042886,
++      0x034, 0x00041486,
++      0x034, 0x00040447,
++      0x90000110,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x00048DED,
++      0x034, 0x00047DEA,
++      0x034, 0x00046DE7,
++      0x034, 0x00045CE9,
++      0x034, 0x00044CE6,
++      0x034, 0x000438C6,
++      0x034, 0x00042886,
++      0x034, 0x00041486,
++      0x034, 0x00040447,
++      0x9000020c,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x000480AE,
++      0x034, 0x000470AB,
++      0x034, 0x0004608B,
++      0x034, 0x00045069,
++      0x034, 0x00044048,
++      0x034, 0x00043045,
++      0x034, 0x00042026,
++      0x034, 0x00041023,
++      0x034, 0x00040002,
++      0x9000040c,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x000480AE,
++      0x034, 0x000470AB,
++      0x034, 0x0004608B,
++      0x034, 0x00045069,
++      0x034, 0x00044048,
++      0x034, 0x00043045,
++      0x034, 0x00042026,
++      0x034, 0x00041023,
++      0x034, 0x00040002,
++      0x90000410,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x00048DED,
++      0x034, 0x00047DEA,
++      0x034, 0x00046DE7,
++      0x034, 0x00045CE9,
++      0x034, 0x00044CE6,
++      0x034, 0x000438C6,
++      0x034, 0x00042886,
++      0x034, 0x00041486,
++      0x034, 0x00040447,
++      0xA0000000,     0x00000000,
++      0x034, 0x00048DEF,
++      0x034, 0x00047DEC,
++      0x034, 0x00046DE9,
++      0x034, 0x00045CCB,
++      0x034, 0x0004488D,
++      0x034, 0x0004348D,
++      0x034, 0x0004248A,
++      0x034, 0x0004108D,
++      0x034, 0x0004008A,
++      0xB0000000,     0x00000000,
++      0x80000210,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0002ADF4,
++      0x9000020c,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0002A0F3,
++      0x9000040c,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0002A0F3,
++      0x90000200,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0002ADF4,
++      0xA0000000,     0x00000000,
++      0x034, 0x0002ADF7,
++      0xB0000000,     0x00000000,
++      0x80000111,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x00029DF4,
++      0x90000110,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x00029DF4,
++      0x90000210,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x00029DF1,
++      0x9000020c,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x000290F0,
++      0x9000040c,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x000290F0,
++      0x90000200,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x00029DF1,
++      0x90000410,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x00029DF4,
++      0xA0000000,     0x00000000,
++      0x034, 0x00029DF2,
++      0xB0000000,     0x00000000,
++      0x80000111,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x00028DF1,
++      0x034, 0x00027DEE,
++      0x034, 0x00026DEB,
++      0x034, 0x00025CEC,
++      0x034, 0x00024CE9,
++      0x034, 0x000238CA,
++      0x034, 0x00022889,
++      0x034, 0x00021489,
++      0x034, 0x0002044A,
++      0x90000110,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x00028DF1,
++      0x034, 0x00027DEE,
++      0x034, 0x00026DEB,
++      0x034, 0x00025CEC,
++      0x034, 0x00024CE9,
++      0x034, 0x000238CA,
++      0x034, 0x00022889,
++      0x034, 0x00021489,
++      0x034, 0x0002044A,
++      0x9000020c,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x000280AF,
++      0x034, 0x000270AC,
++      0x034, 0x0002608B,
++      0x034, 0x00025069,
++      0x034, 0x00024048,
++      0x034, 0x00023045,
++      0x034, 0x00022026,
++      0x034, 0x00021023,
++      0x034, 0x00020002,
++      0x9000040c,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x000280AF,
++      0x034, 0x000270AC,
++      0x034, 0x0002608B,
++      0x034, 0x00025069,
++      0x034, 0x00024048,
++      0x034, 0x00023045,
++      0x034, 0x00022026,
++      0x034, 0x00021023,
++      0x034, 0x00020002,
++      0x90000410,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x00028DF1,
++      0x034, 0x00027DEE,
++      0x034, 0x00026DEB,
++      0x034, 0x00025CEC,
++      0x034, 0x00024CE9,
++      0x034, 0x000238CA,
++      0x034, 0x00022889,
++      0x034, 0x00021489,
++      0x034, 0x0002044A,
++      0xA0000000,     0x00000000,
++      0x034, 0x00028DEE,
++      0x034, 0x00027DEB,
++      0x034, 0x00026CCD,
++      0x034, 0x00025CCA,
++      0x034, 0x0002488C,
++      0x034, 0x0002384C,
++      0x034, 0x00022849,
++      0x034, 0x00021449,
++      0x034, 0x0002004D,
++      0xB0000000,     0x00000000,
++      0x8000020c,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0000A0D7,
++      0x034, 0x000090D3,
++      0x034, 0x000080B1,
++      0x034, 0x000070AE,
++      0x9000040c,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0000A0D7,
++      0x034, 0x000090D3,
++      0x034, 0x000080B1,
++      0x034, 0x000070AE,
++      0xA0000000,     0x00000000,
++      0x034, 0x0000ADF7,
++      0x034, 0x00009DF4,
++      0x034, 0x00008DF1,
++      0x034, 0x00007DEE,
++      0xB0000000,     0x00000000,
++      0x80000111,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x00006DEB,
++      0x034, 0x00005CEC,
++      0x034, 0x00004CE9,
++      0x034, 0x000038CA,
++      0x034, 0x00002889,
++      0x034, 0x00001489,
++      0x034, 0x0000044A,
++      0x90000110,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x00006DEB,
++      0x034, 0x00005CEC,
++      0x034, 0x00004CE9,
++      0x034, 0x000038CA,
++      0x034, 0x00002889,
++      0x034, 0x00001489,
++      0x034, 0x0000044A,
++      0x9000020c,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0000608D,
++      0x034, 0x0000506B,
++      0x034, 0x0000404A,
++      0x034, 0x00003047,
++      0x034, 0x00002044,
++      0x034, 0x00001025,
++      0x034, 0x00000004,
++      0x9000040c,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x0000608D,
++      0x034, 0x0000506B,
++      0x034, 0x0000404A,
++      0x034, 0x00003047,
++      0x034, 0x00002044,
++      0x034, 0x00001025,
++      0x034, 0x00000004,
++      0x90000410,     0x00000000,     0x40000000,     0x00000000,
++      0x034, 0x00006DEB,
++      0x034, 0x00005CEC,
++      0x034, 0x00004CE9,
++      0x034, 0x000038CA,
++      0x034, 0x00002889,
++      0x034, 0x00001489,
++      0x034, 0x0000044A,
++      0xA0000000,     0x00000000,
++      0x034, 0x00006DCD,
++      0x034, 0x00005CCD,
++      0x034, 0x00004CCA,
++      0x034, 0x0000388C,
++      0x034, 0x00002888,
++      0x034, 0x00001488,
++      0x034, 0x00000486,
++      0xB0000000,     0x00000000,
++      0x0EF, 0x00000000,
++      0x018, 0x0001712A,
++      0x0EF, 0x00000040,
++      0x80000111,     0x00000000,     0x40000000,     0x00000000,
++      0x035, 0x00000187,
++      0x035, 0x00008187,
++      0x035, 0x00010187,
++      0x035, 0x00020188,
++      0x035, 0x00028188,
++      0x035, 0x00030188,
++      0x035, 0x00040188,
++      0x035, 0x00048188,
++      0x035, 0x00050188,
++      0x90000110,     0x00000000,     0x40000000,     0x00000000,
++      0x035, 0x00000187,
++      0x035, 0x00008187,
++      0x035, 0x00010187,
++      0x035, 0x00020188,
++      0x035, 0x00028188,
++      0x035, 0x00030188,
++      0x035, 0x00040188,
++      0x035, 0x00048188,
++      0x035, 0x00050188,
++      0x90000210,     0x00000000,     0x40000000,     0x00000000,
++      0x035, 0x00000128,
++      0x035, 0x00008128,
++      0x035, 0x00010128,
++      0x035, 0x000201C8,
++      0x035, 0x000281C8,
++      0x035, 0x000301C8,
++      0x035, 0x000401C8,
++      0x035, 0x000481C8,
++      0x035, 0x000501C8,
++      0x9000040c,     0x00000000,     0x40000000,     0x00000000,
++      0x035, 0x00000145,
++      0x035, 0x00008145,
++      0x035, 0x00010145,
++      0x035, 0x00020196,
++      0x035, 0x00028196,
++      0x035, 0x00030196,
++      0x035, 0x000401C7,
++      0x035, 0x000481C7,
++      0x035, 0x000501C7,
++      0x90000200,     0x00000000,     0x40000000,     0x00000000,
++      0x035, 0x00000128,
++      0x035, 0x00008128,
++      0x035, 0x00010128,
++      0x035, 0x000201C8,
++      0x035, 0x000281C8,
++      0x035, 0x000301C8,
++      0x035, 0x000401C8,
++      0x035, 0x000481C8,
++      0x035, 0x000501C8,
++      0x90000410,     0x00000000,     0x40000000,     0x00000000,
++      0x035, 0x00000187,
++      0x035, 0x00008187,
++      0x035, 0x00010187,
++      0x035, 0x00020188,
++      0x035, 0x00028188,
++      0x035, 0x00030188,
++      0x035, 0x00040188,
++      0x035, 0x00048188,
++      0x035, 0x00050188,
++      0xA0000000,     0x00000000,
++      0x035, 0x00000145,
++      0x035, 0x00008145,
++      0x035, 0x00010145,
++      0x035, 0x00020196,
++      0x035, 0x00028196,
++      0x035, 0x00030196,
++      0x035, 0x000401C7,
++      0x035, 0x000481C7,
++      0x035, 0x000501C7,
++      0xB0000000,     0x00000000,
++      0x0EF, 0x00000000,
++      0x018, 0x0001712A,
++      0x0EF, 0x00000010,
++      0x80000111,     0x00000000,     0x40000000,     0x00000000,
++      0x036, 0x00085733,
++      0x036, 0x0008D733,
++      0x036, 0x00095733,
++      0x036, 0x0009D733,
++      0x036, 0x000A64B4,
++      0x036, 0x000AE4B4,
++      0x036, 0x000B64B4,
++      0x036, 0x000BE4B4,
++      0x036, 0x000C64B4,
++      0x036, 0x000CE4B4,
++      0x036, 0x000D64B4,
++      0x036, 0x000DE4B4,
++      0x90000110,     0x00000000,     0x40000000,     0x00000000,
++      0x036, 0x00085733,
++      0x036, 0x0008D733,
++      0x036, 0x00095733,
++      0x036, 0x0009D733,
++      0x036, 0x000A64B4,
++      0x036, 0x000AE4B4,
++      0x036, 0x000B64B4,
++      0x036, 0x000BE4B4,
++      0x036, 0x000C64B4,
++      0x036, 0x000CE4B4,
++      0x036, 0x000D64B4,
++      0x036, 0x000DE4B4,
++      0x90000210,     0x00000000,     0x40000000,     0x00000000,
++      0x036, 0x000063B5,
++      0x036, 0x0000E3B5,
++      0x036, 0x000163B5,
++      0x036, 0x0001E3B5,
++      0x036, 0x000263B5,
++      0x036, 0x0002E3B5,
++      0x036, 0x000363B5,
++      0x036, 0x0003E3B5,
++      0x036, 0x000463B5,
++      0x036, 0x0004E3B5,
++      0x036, 0x000563B5,
++      0x036, 0x0005E3B5,
++      0x9000040c,     0x00000000,     0x40000000,     0x00000000,
++      0x036, 0x000056B3,
++      0x036, 0x0000D6B3,
++      0x036, 0x000156B3,
++      0x036, 0x0001D6B3,
++      0x036, 0x00026634,
++      0x036, 0x0002E634,
++      0x036, 0x00036634,
++      0x036, 0x0003E634,
++      0x036, 0x000467B4,
++      0x036, 0x0004E7B4,
++      0x036, 0x000567B4,
++      0x036, 0x0005E7B4,
++      0x90000200,     0x00000000,     0x40000000,     0x00000000,
++      0x036, 0x000063B5,
++      0x036, 0x0000E3B5,
++      0x036, 0x000163B5,
++      0x036, 0x0001E3B5,
++      0x036, 0x000263B5,
++      0x036, 0x0002E3B5,
++      0x036, 0x000363B5,
++      0x036, 0x0003E3B5,
++      0x036, 0x000463B5,
++      0x036, 0x0004E3B5,
++      0x036, 0x000563B5,
++      0x036, 0x0005E3B5,
++      0x90000410,     0x00000000,     0x40000000,     0x00000000,
++      0x036, 0x00085733,
++      0x036, 0x0008D733,
++      0x036, 0x00095733,
++      0x036, 0x0009D733,
++      0x036, 0x000A64B4,
++      0x036, 0x000AE4B4,
++      0x036, 0x000B64B4,
++      0x036, 0x000BE4B4,
++      0x036, 0x000C64B4,
++      0x036, 0x000CE4B4,
++      0x036, 0x000D64B4,
++      0x036, 0x000DE4B4,
++      0xA0000000,     0x00000000,
++      0x036, 0x000056B3,
++      0x036, 0x0000D6B3,
++      0x036, 0x000156B3,
++      0x036, 0x0001D6B3,
++      0x036, 0x00026634,
++      0x036, 0x0002E634,
++      0x036, 0x00036634,
++      0x036, 0x0003E634,
++      0x036, 0x000467B4,
++      0x036, 0x0004E7B4,
++      0x036, 0x000567B4,
++      0x036, 0x0005E7B4,
++      0xB0000000,     0x00000000,
++      0x0EF, 0x00000000,
++      0x0EF, 0x00000008,
++      0x80000111,     0x00000000,     0x40000000,     0x00000000,
++      0x03C, 0x000001C8,
++      0x03C, 0x00000492,
++      0x90000110,     0x00000000,     0x40000000,     0x00000000,
++      0x03C, 0x000001C8,
++      0x03C, 0x00000492,
++      0x90000210,     0x00000000,     0x40000000,     0x00000000,
++      0x03C, 0x000001B6,
++      0x03C, 0x00000492,
++      0x9000040c,     0x00000000,     0x40000000,     0x00000000,
++      0x03C, 0x0000022A,
++      0x03C, 0x00000594,
++      0x90000200,     0x00000000,     0x40000000,     0x00000000,
++      0x03C, 0x000001B6,
++      0x03C, 0x00000492,
++      0x90000410,     0x00000000,     0x40000000,     0x00000000,
++      0x03C, 0x000001C8,
++      0x03C, 0x00000492,
++      0xA0000000,     0x00000000,
++      0x03C, 0x0000022A,
++      0x03C, 0x00000594,
++      0xB0000000,     0x00000000,
++      0x80000111,     0x00000000,     0x40000000,     0x00000000,
++      0x03C, 0x00000800,
++      0x90000110,     0x00000000,     0x40000000,     0x00000000,
++      0x03C, 0x00000800,
++      0x90000210,     0x00000000,     0x40000000,     0x00000000,
++      0x03C, 0x00000800,
++      0x9000020c,     0x00000000,     0x40000000,     0x00000000,
++      0x03C, 0x00000820,
++      0x9000040c,     0x00000000,     0x40000000,     0x00000000,
++      0x03C, 0x00000820,
++      0x90000200,     0x00000000,     0x40000000,     0x00000000,
++      0x03C, 0x00000800,
++      0x90000410,     0x00000000,     0x40000000,     0x00000000,
++      0x03C, 0x00000800,
++      0xA0000000,     0x00000000,
++      0x03C, 0x00000900,
++      0xB0000000,     0x00000000,
++      0x0EF, 0x00000000,
++      0x018, 0x0001712A,
++      0x0EF, 0x00000002,
++      0x80000111,     0x00000000,     0x40000000,     0x00000000,
++      0x008, 0x0004E400,
++      0x90000110,     0x00000000,     0x40000000,     0x00000000,
++      0x008, 0x0004E400,
++      0x90000210,     0x00000000,     0x40000000,     0x00000000,
++      0x008, 0x00002000,
++      0x9000020c,     0x00000000,     0x40000000,     0x00000000,
++      0x008, 0x00002000,
++      0x9000040c,     0x00000000,     0x40000000,     0x00000000,
++      0x008, 0x00002000,
++      0x90000200,     0x00000000,     0x40000000,     0x00000000,
++      0x008, 0x00002000,
++      0x90000410,     0x00000000,     0x40000000,     0x00000000,
++      0x008, 0x0004E400,
++      0xA0000000,     0x00000000,
++      0x008, 0x00002000,
++      0xB0000000,     0x00000000,
++      0x0EF, 0x00000000,
++      0x0DF, 0x000000C0,
++      0x01F, 0x00000064,
++      0x80000111,     0x00000000,     0x40000000,     0x00000000,
++      0x058, 0x000A7284,
++      0x059, 0x000600EC,
++      0x90000110,     0x00000000,     0x40000000,     0x00000000,
++      0x058, 0x000A7284,
++      0x059, 0x000600EC,
++      0x9000020c,     0x00000000,     0x40000000,     0x00000000,
++      0x058, 0x00081184,
++      0x059, 0x0006016C,
++      0x9000040c,     0x00000000,     0x40000000,     0x00000000,
++      0x058, 0x00081184,
++      0x059, 0x0006016C,
++      0x90000200,     0x00000000,     0x40000000,     0x00000000,
++      0x058, 0x00081184,
++      0x059, 0x0006016C,
++      0x90000410,     0x00000000,     0x40000000,     0x00000000,
++      0x058, 0x000A7284,
++      0x059, 0x000600EC,
++      0xA0000000,     0x00000000,
++      0x058, 0x00081184,
++      0x059, 0x0006016C,
++      0xB0000000,     0x00000000,
++      0x80000111,     0x00000000,     0x40000000,     0x00000000,
++      0x061, 0x000E8D73,
++      0x062, 0x00093FC5,
++      0x90000110,     0x00000000,     0x40000000,     0x00000000,
++      0x061, 0x000E8D73,
++      0x062, 0x00093FC5,
++      0x90000210,     0x00000000,     0x40000000,     0x00000000,
++      0x061, 0x000EFD83,
++      0x062, 0x00093FCC,
++      0x9000040c,     0x00000000,     0x40000000,     0x00000000,
++      0x061, 0x000EAD53,
++      0x062, 0x00093BC4,
++      0x90000200,     0x00000000,     0x40000000,     0x00000000,
++      0x061, 0x000EFD83,
++      0x062, 0x00093FCC,
++      0x90000410,     0x00000000,     0x40000000,     0x00000000,
++      0x061, 0x000E8D73,
++      0x062, 0x00093FC5,
++      0xA0000000,     0x00000000,
++      0x061, 0x000EAD53,
++      0x062, 0x00093BC4,
++      0xB0000000,     0x00000000,
++      0x80000111,     0x00000000,     0x40000000,     0x00000000,
++      0x063, 0x000110E9,
++      0x90000110,     0x00000000,     0x40000000,     0x00000000,
++      0x063, 0x000110E9,
++      0x90000210,     0x00000000,     0x40000000,     0x00000000,
++      0x063, 0x000110EB,
++      0x9000020c,     0x00000000,     0x40000000,     0x00000000,
++      0x063, 0x000110E9,
++      0x9000040c,     0x00000000,     0x40000000,     0x00000000,
++      0x063, 0x000110E9,
++      0x90000200,     0x00000000,     0x40000000,     0x00000000,
++      0x063, 0x000110EB,
++      0x90000410,     0x00000000,     0x40000000,     0x00000000,
++      0x063, 0x000110E9,
++      0xA0000000,     0x00000000,
++      0x063, 0x000714E9,
++      0xB0000000,     0x00000000,
++      0x80000111,     0x00000000,     0x40000000,     0x00000000,
++      0x064, 0x0001C27C,
++      0x90000110,     0x00000000,     0x40000000,     0x00000000,
++      0x064, 0x0001C27C,
++      0x90000210,     0x00000000,     0x40000000,     0x00000000,
++      0x064, 0x0001C27C,
++      0x9000040c,     0x00000000,     0x40000000,     0x00000000,
++      0x064, 0x0001C67C,
++      0x90000200,     0x00000000,     0x40000000,     0x00000000,
++      0x064, 0x0001C27C,
++      0x90000410,     0x00000000,     0x40000000,     0x00000000,
++      0x064, 0x0001C27C,
++      0xA0000000,     0x00000000,
++      0x064, 0x0001C67C,
++      0xB0000000,     0x00000000,
++      0x80000111,     0x00000000,     0x40000000,     0x00000000,
++      0x065, 0x00091016,
++      0x90000110,     0x00000000,     0x40000000,     0x00000000,
++      0x065, 0x00091016,
++      0x90000210,     0x00000000,     0x40000000,     0x00000000,
++      0x065, 0x00093016,
++      0x9000020c,     0x00000000,     0x40000000,     0x00000000,
++      0x065, 0x00093015,
++      0x9000040c,     0x00000000,     0x40000000,     0x00000000,
++      0x065, 0x00093015,
++      0x90000200,     0x00000000,     0x40000000,     0x00000000,
++      0x065, 0x00093016,
++      0xA0000000,     0x00000000,
++      0x065, 0x00091016,
++      0xB0000000,     0x00000000,
++      0x018, 0x00000006,
++      0x0EF, 0x00002000,
++      0x03B, 0x0003824B,
++      0x03B, 0x0003024B,
++      0x03B, 0x0002844B,
++      0x03B, 0x00020F4B,
++      0x03B, 0x00018F4B,
++      0x03B, 0x000104B2,
++      0x03B, 0x00008049,
++      0x03B, 0x00000148,
++      0x03B, 0x0007824B,
++      0x03B, 0x0007024B,
++      0x03B, 0x0006824B,
++      0x03B, 0x00060F4B,
++      0x03B, 0x00058F4B,
++      0x03B, 0x000504B2,
++      0x03B, 0x00048049,
++      0x03B, 0x00040148,
++      0x0EF, 0x00000000,
++      0x0EF, 0x00000100,
++      0x034, 0x0000ADF3,
++      0x034, 0x00009DF0,
++      0x034, 0x00008D70,
++      0x034, 0x00007D6D,
++      0x034, 0x00006CEE,
++      0x034, 0x00005CCC,
++      0x034, 0x000044EC,
++      0x034, 0x000034AC,
++      0x034, 0x0000246D,
++      0x034, 0x0000106F,
++      0x034, 0x0000006C,
++      0x0EF, 0x00000000,
++      0x0ED, 0x00000010,
++      0x044, 0x0000ADF2,
++      0x044, 0x00009DEF,
++      0x044, 0x00008DEC,
++      0x044, 0x00007DE9,
++      0x044, 0x00006CEC,
++      0x044, 0x00005CE9,
++      0x044, 0x000044EC,
++      0x044, 0x000034E9,
++      0x044, 0x0000246C,
++      0x044, 0x00001469,
++      0x044, 0x0000006C,
++      0x0ED, 0x00000000,
++      0x0ED, 0x00000001,
++      0x040, 0x00038DA7,
++      0x040, 0x000300C2,
++      0x040, 0x000288E2,
++      0x040, 0x000200B8,
++      0x040, 0x000188A5,
++      0x040, 0x00010FBC,
++      0x040, 0x00008F71,
++      0x040, 0x00000240,
++      0x0ED, 0x00000000,
++      0x0EF, 0x000020A2,
++      0x0DF, 0x00000080,
++      0x035, 0x00000120,
++      0x035, 0x00008120,
++      0x035, 0x00010120,
++      0x036, 0x00000085,
++      0x036, 0x00008085,
++      0x036, 0x00010085,
++      0x036, 0x00018085,
++      0x0EF, 0x00000000,
++      0x051, 0x00000C31,
++      0x052, 0x00000622,
++      0x053, 0x000FC70B,
++      0x054, 0x0000017E,
++      0x056, 0x00051DF3,
++      0x051, 0x00000C01,
++      0x052, 0x000006D6,
++      0x053, 0x000FC649,
++      0x070, 0x00049661,
++      0x071, 0x0007843E,
++      0x072, 0x00000382,
++      0x074, 0x00051400,
++      0x035, 0x00000160,
++      0x035, 0x00008160,
++      0x035, 0x00010160,
++      0x036, 0x00000124,
++      0x036, 0x00008124,
++      0x036, 0x00010124,
++      0x036, 0x00018124,
++      0x0ED, 0x0000000C,
++      0x045, 0x00000140,
++      0x045, 0x00008140,
++      0x045, 0x00010140,
++      0x046, 0x00000124,
++      0x046, 0x00008124,
++      0x046, 0x00010124,
++      0x046, 0x00018124,
++      0x0DF, 0x00000088,
++      0x0B3, 0x000F0E18,
++      0x0B4, 0x0001214C,
++      0x0B7, 0x0003000C,
++      0x01C, 0x000539D2,
++      0x0C4, 0x000AFE00,
++      0x018, 0x0001F12A,
++      0xFFE, 0x00000000,
++      0xFFE, 0x00000000,
++      0x018, 0x0001712A,
++};
++
++RTW_DECL_TABLE_RF_RADIO(rtw8821a_rf_a, A);
++
++static const struct rtw_txpwr_lmt_cfg_pair rtw8821a_txpwr_lmt[] = {
++      { 0, 0, 0, 0, 1, 32, },
++      { 2, 0, 0, 0, 1, 28, },
++      { 1, 0, 0, 0, 1, 32, },
++      { 0, 0, 0, 0, 2, 32, },
++      { 2, 0, 0, 0, 2, 28, },
++      { 1, 0, 0, 0, 2, 32, },
++      { 0, 0, 0, 0, 3, 36, },
++      { 2, 0, 0, 0, 3, 28, },
++      { 1, 0, 0, 0, 3, 32, },
++      { 0, 0, 0, 0, 4, 36, },
++      { 2, 0, 0, 0, 4, 28, },
++      { 1, 0, 0, 0, 4, 32, },
++      { 0, 0, 0, 0, 5, 36, },
++      { 2, 0, 0, 0, 5, 28, },
++      { 1, 0, 0, 0, 5, 32, },
++      { 0, 0, 0, 0, 6, 36, },
++      { 2, 0, 0, 0, 6, 28, },
++      { 1, 0, 0, 0, 6, 32, },
++      { 0, 0, 0, 0, 7, 36, },
++      { 2, 0, 0, 0, 7, 28, },
++      { 1, 0, 0, 0, 7, 32, },
++      { 0, 0, 0, 0, 8, 36, },
++      { 2, 0, 0, 0, 8, 28, },
++      { 1, 0, 0, 0, 8, 32, },
++      { 0, 0, 0, 0, 9, 32, },
++      { 2, 0, 0, 0, 9, 28, },
++      { 1, 0, 0, 0, 9, 32, },
++      { 0, 0, 0, 0, 10, 32, },
++      { 2, 0, 0, 0, 10, 28, },
++      { 1, 0, 0, 0, 10, 32, },
++      { 0, 0, 0, 0, 11, 32, },
++      { 2, 0, 0, 0, 11, 28, },
++      { 1, 0, 0, 0, 11, 32, },
++      { 0, 0, 0, 0, 12, 28, },
++      { 2, 0, 0, 0, 12, 28, },
++      { 1, 0, 0, 0, 12, 32, },
++      { 0, 0, 0, 0, 13, 26, },
++      { 2, 0, 0, 0, 13, 28, },
++      { 1, 0, 0, 0, 13, 32, },
++      { 0, 0, 0, 0, 14, 63, },
++      { 2, 0, 0, 0, 14, 63, },
++      { 1, 0, 0, 0, 14, 32, },
++      { 0, 0, 0, 1, 1, 30, },
++      { 2, 0, 0, 1, 1, 30, },
++      { 1, 0, 0, 1, 1, 32, },
++      { 0, 0, 0, 1, 2, 30, },
++      { 2, 0, 0, 1, 2, 32, },
++      { 1, 0, 0, 1, 2, 32, },
++      { 0, 0, 0, 1, 3, 32, },
++      { 2, 0, 0, 1, 3, 32, },
++      { 1, 0, 0, 1, 3, 32, },
++      { 0, 0, 0, 1, 4, 32, },
++      { 2, 0, 0, 1, 4, 32, },
++      { 1, 0, 0, 1, 4, 32, },
++      { 0, 0, 0, 1, 5, 32, },
++      { 2, 0, 0, 1, 5, 32, },
++      { 1, 0, 0, 1, 5, 32, },
++      { 0, 0, 0, 1, 6, 32, },
++      { 2, 0, 0, 1, 6, 32, },
++      { 1, 0, 0, 1, 6, 32, },
++      { 0, 0, 0, 1, 7, 32, },
++      { 2, 0, 0, 1, 7, 32, },
++      { 1, 0, 0, 1, 7, 32, },
++      { 0, 0, 0, 1, 8, 32, },
++      { 2, 0, 0, 1, 8, 32, },
++      { 1, 0, 0, 1, 8, 32, },
++      { 0, 0, 0, 1, 9, 30, },
++      { 2, 0, 0, 1, 9, 32, },
++      { 1, 0, 0, 1, 9, 32, },
++      { 0, 0, 0, 1, 10, 30, },
++      { 2, 0, 0, 1, 10, 32, },
++      { 1, 0, 0, 1, 10, 32, },
++      { 0, 0, 0, 1, 11, 30, },
++      { 2, 0, 0, 1, 11, 32, },
++      { 1, 0, 0, 1, 11, 32, },
++      { 0, 0, 0, 1, 12, 26, },
++      { 2, 0, 0, 1, 12, 32, },
++      { 1, 0, 0, 1, 12, 32, },
++      { 0, 0, 0, 1, 13, 24, },
++      { 2, 0, 0, 1, 13, 30, },
++      { 1, 0, 0, 1, 13, 32, },
++      { 0, 0, 0, 1, 14, 63, },
++      { 2, 0, 0, 1, 14, 63, },
++      { 1, 0, 0, 1, 14, 63, },
++      { 0, 0, 0, 2, 1, 26, },
++      { 2, 0, 0, 2, 1, 26, },
++      { 1, 0, 0, 2, 1, 32, },
++      { 0, 0, 0, 2, 2, 26, },
++      { 2, 0, 0, 2, 2, 32, },
++      { 1, 0, 0, 2, 2, 32, },
++      { 0, 0, 0, 2, 3, 32, },
++      { 2, 0, 0, 2, 3, 32, },
++      { 1, 0, 0, 2, 3, 32, },
++      { 0, 0, 0, 2, 4, 32, },
++      { 2, 0, 0, 2, 4, 32, },
++      { 1, 0, 0, 2, 4, 32, },
++      { 0, 0, 0, 2, 5, 32, },
++      { 2, 0, 0, 2, 5, 32, },
++      { 1, 0, 0, 2, 5, 32, },
++      { 0, 0, 0, 2, 6, 32, },
++      { 2, 0, 0, 2, 6, 32, },
++      { 1, 0, 0, 2, 6, 32, },
++      { 0, 0, 0, 2, 7, 32, },
++      { 2, 0, 0, 2, 7, 32, },
++      { 1, 0, 0, 2, 7, 32, },
++      { 0, 0, 0, 2, 8, 32, },
++      { 2, 0, 0, 2, 8, 32, },
++      { 1, 0, 0, 2, 8, 32, },
++      { 0, 0, 0, 2, 9, 26, },
++      { 2, 0, 0, 2, 9, 32, },
++      { 1, 0, 0, 2, 9, 32, },
++      { 0, 0, 0, 2, 10, 26, },
++      { 2, 0, 0, 2, 10, 32, },
++      { 1, 0, 0, 2, 10, 32, },
++      { 0, 0, 0, 2, 11, 26, },
++      { 2, 0, 0, 2, 11, 32, },
++      { 1, 0, 0, 2, 11, 32, },
++      { 0, 0, 0, 2, 12, 26, },
++      { 2, 0, 0, 2, 12, 32, },
++      { 1, 0, 0, 2, 12, 32, },
++      { 0, 0, 0, 2, 13, 24, },
++      { 2, 0, 0, 2, 13, 26, },
++      { 1, 0, 0, 2, 13, 32, },
++      { 0, 0, 0, 2, 14, 63, },
++      { 2, 0, 0, 2, 14, 63, },
++      { 1, 0, 0, 2, 14, 63, },
++      { 0, 0, 0, 3, 1, 30, },
++      { 2, 0, 0, 3, 1, 32, },
++      { 1, 0, 0, 3, 1, 32, },
++      { 0, 0, 0, 3, 2, 32, },
++      { 2, 0, 0, 3, 2, 32, },
++      { 1, 0, 0, 3, 2, 32, },
++      { 0, 0, 0, 3, 3, 32, },
++      { 2, 0, 0, 3, 3, 32, },
++      { 1, 0, 0, 3, 3, 32, },
++      { 0, 0, 0, 3, 4, 32, },
++      { 2, 0, 0, 3, 4, 32, },
++      { 1, 0, 0, 3, 4, 32, },
++      { 0, 0, 0, 3, 5, 32, },
++      { 2, 0, 0, 3, 5, 32, },
++      { 1, 0, 0, 3, 5, 32, },
++      { 0, 0, 0, 3, 6, 32, },
++      { 2, 0, 0, 3, 6, 32, },
++      { 1, 0, 0, 3, 6, 32, },
++      { 0, 0, 0, 3, 7, 32, },
++      { 2, 0, 0, 3, 7, 32, },
++      { 1, 0, 0, 3, 7, 32, },
++      { 0, 0, 0, 3, 8, 32, },
++      { 2, 0, 0, 3, 8, 32, },
++      { 1, 0, 0, 3, 8, 32, },
++      { 0, 0, 0, 3, 9, 32, },
++      { 2, 0, 0, 3, 9, 32, },
++      { 1, 0, 0, 3, 9, 32, },
++      { 0, 0, 0, 3, 10, 32, },
++      { 2, 0, 0, 3, 10, 32, },
++      { 1, 0, 0, 3, 10, 32, },
++      { 0, 0, 0, 3, 11, 30, },
++      { 2, 0, 0, 3, 11, 32, },
++      { 1, 0, 0, 3, 11, 32, },
++      { 0, 0, 0, 3, 12, 63, },
++      { 2, 0, 0, 3, 12, 32, },
++      { 1, 0, 0, 3, 12, 32, },
++      { 0, 0, 0, 3, 13, 63, },
++      { 2, 0, 0, 3, 13, 32, },
++      { 1, 0, 0, 3, 13, 32, },
++      { 0, 0, 0, 3, 14, 63, },
++      { 2, 0, 0, 3, 14, 63, },
++      { 1, 0, 0, 3, 14, 63, },
++      { 0, 0, 1, 2, 1, 63, },
++      { 2, 0, 1, 2, 1, 63, },
++      { 1, 0, 1, 2, 1, 63, },
++      { 0, 0, 1, 2, 2, 63, },
++      { 2, 0, 1, 2, 2, 63, },
++      { 1, 0, 1, 2, 2, 63, },
++      { 0, 0, 1, 2, 3, 26, },
++      { 2, 0, 1, 2, 3, 26, },
++      { 1, 0, 1, 2, 3, 32, },
++      { 0, 0, 1, 2, 4, 26, },
++      { 2, 0, 1, 2, 4, 32, },
++      { 1, 0, 1, 2, 4, 32, },
++      { 0, 0, 1, 2, 5, 26, },
++      { 2, 0, 1, 2, 5, 32, },
++      { 1, 0, 1, 2, 5, 32, },
++      { 0, 0, 1, 2, 6, 32, },
++      { 2, 0, 1, 2, 6, 32, },
++      { 1, 0, 1, 2, 6, 32, },
++      { 0, 0, 1, 2, 7, 32, },
++      { 2, 0, 1, 2, 7, 32, },
++      { 1, 0, 1, 2, 7, 32, },
++      { 0, 0, 1, 2, 8, 32, },
++      { 2, 0, 1, 2, 8, 32, },
++      { 1, 0, 1, 2, 8, 32, },
++      { 0, 0, 1, 2, 9, 26, },
++      { 2, 0, 1, 2, 9, 32, },
++      { 1, 0, 1, 2, 9, 32, },
++      { 0, 0, 1, 2, 10, 24, },
++      { 2, 0, 1, 2, 10, 32, },
++      { 1, 0, 1, 2, 10, 32, },
++      { 0, 0, 1, 2, 11, 22, },
++      { 2, 0, 1, 2, 11, 26, },
++      { 1, 0, 1, 2, 11, 32, },
++      { 0, 0, 1, 2, 12, 63, },
++      { 2, 0, 1, 2, 12, 63, },
++      { 1, 0, 1, 2, 12, 63, },
++      { 0, 0, 1, 2, 13, 63, },
++      { 2, 0, 1, 2, 13, 63, },
++      { 1, 0, 1, 2, 13, 63, },
++      { 0, 0, 1, 2, 14, 63, },
++      { 2, 0, 1, 2, 14, 63, },
++      { 1, 0, 1, 2, 14, 63, },
++      { 0, 0, 1, 3, 1, 63, },
++      { 2, 0, 1, 3, 1, 63, },
++      { 1, 0, 1, 3, 1, 63, },
++      { 0, 0, 1, 3, 2, 63, },
++      { 2, 0, 1, 3, 2, 63, },
++      { 1, 0, 1, 3, 2, 63, },
++      { 0, 0, 1, 3, 3, 30, },
++      { 2, 0, 1, 3, 3, 30, },
++      { 1, 0, 1, 3, 3, 30, },
++      { 0, 0, 1, 3, 4, 32, },
++      { 2, 0, 1, 3, 4, 30, },
++      { 1, 0, 1, 3, 4, 30, },
++      { 0, 0, 1, 3, 5, 32, },
++      { 2, 0, 1, 3, 5, 30, },
++      { 1, 0, 1, 3, 5, 30, },
++      { 0, 0, 1, 3, 6, 32, },
++      { 2, 0, 1, 3, 6, 30, },
++      { 1, 0, 1, 3, 6, 30, },
++      { 0, 0, 1, 3, 7, 32, },
++      { 2, 0, 1, 3, 7, 30, },
++      { 1, 0, 1, 3, 7, 30, },
++      { 0, 0, 1, 3, 8, 32, },
++      { 2, 0, 1, 3, 8, 30, },
++      { 1, 0, 1, 3, 8, 30, },
++      { 0, 0, 1, 3, 9, 32, },
++      { 2, 0, 1, 3, 9, 30, },
++      { 1, 0, 1, 3, 9, 30, },
++      { 0, 0, 1, 3, 10, 32, },
++      { 2, 0, 1, 3, 10, 30, },
++      { 1, 0, 1, 3, 10, 30, },
++      { 0, 0, 1, 3, 11, 30, },
++      { 2, 0, 1, 3, 11, 30, },
++      { 1, 0, 1, 3, 11, 30, },
++      { 0, 0, 1, 3, 12, 63, },
++      { 2, 0, 1, 3, 12, 32, },
++      { 1, 0, 1, 3, 12, 32, },
++      { 0, 0, 1, 3, 13, 63, },
++      { 2, 0, 1, 3, 13, 32, },
++      { 1, 0, 1, 3, 13, 32, },
++      { 0, 0, 1, 3, 14, 63, },
++      { 2, 0, 1, 3, 14, 63, },
++      { 1, 0, 1, 3, 14, 63, },
++      { 0, 1, 0, 1, 36, 32, },
++      { 2, 1, 0, 1, 36, 30, },
++      { 1, 1, 0, 1, 36, 30, },
++      { 0, 1, 0, 1, 40, 32, },
++      { 2, 1, 0, 1, 40, 30, },
++      { 1, 1, 0, 1, 40, 30, },
++      { 0, 1, 0, 1, 44, 32, },
++      { 2, 1, 0, 1, 44, 30, },
++      { 1, 1, 0, 1, 44, 30, },
++      { 0, 1, 0, 1, 48, 32, },
++      { 2, 1, 0, 1, 48, 30, },
++      { 1, 1, 0, 1, 48, 30, },
++      { 0, 1, 0, 1, 52, 32, },
++      { 2, 1, 0, 1, 52, 30, },
++      { 1, 1, 0, 1, 52, 30, },
++      { 0, 1, 0, 1, 56, 32, },
++      { 2, 1, 0, 1, 56, 30, },
++      { 1, 1, 0, 1, 56, 30, },
++      { 0, 1, 0, 1, 60, 32, },
++      { 2, 1, 0, 1, 60, 30, },
++      { 1, 1, 0, 1, 60, 30, },
++      { 0, 1, 0, 1, 64, 32, },
++      { 2, 1, 0, 1, 64, 30, },
++      { 1, 1, 0, 1, 64, 30, },
++      { 0, 1, 0, 1, 100, 32, },
++      { 2, 1, 0, 1, 100, 30, },
++      { 1, 1, 0, 1, 100, 30, },
++      { 0, 1, 0, 1, 104, 32, },
++      { 2, 1, 0, 1, 104, 30, },
++      { 1, 1, 0, 1, 104, 30, },
++      { 0, 1, 0, 1, 108, 32, },
++      { 2, 1, 0, 1, 108, 30, },
++      { 1, 1, 0, 1, 108, 30, },
++      { 0, 1, 0, 1, 112, 32, },
++      { 2, 1, 0, 1, 112, 30, },
++      { 1, 1, 0, 1, 112, 30, },
++      { 0, 1, 0, 1, 116, 32, },
++      { 2, 1, 0, 1, 116, 30, },
++      { 1, 1, 0, 1, 116, 30, },
++      { 0, 1, 0, 1, 120, 32, },
++      { 2, 1, 0, 1, 120, 30, },
++      { 1, 1, 0, 1, 120, 30, },
++      { 0, 1, 0, 1, 124, 32, },
++      { 2, 1, 0, 1, 124, 30, },
++      { 1, 1, 0, 1, 124, 30, },
++      { 0, 1, 0, 1, 128, 32, },
++      { 2, 1, 0, 1, 128, 30, },
++      { 1, 1, 0, 1, 128, 30, },
++      { 0, 1, 0, 1, 132, 32, },
++      { 2, 1, 0, 1, 132, 30, },
++      { 1, 1, 0, 1, 132, 30, },
++      { 0, 1, 0, 1, 136, 32, },
++      { 2, 1, 0, 1, 136, 30, },
++      { 1, 1, 0, 1, 136, 30, },
++      { 0, 1, 0, 1, 140, 32, },
++      { 2, 1, 0, 1, 140, 30, },
++      { 1, 1, 0, 1, 140, 30, },
++      { 0, 1, 0, 1, 149, 32, },
++      { 2, 1, 0, 1, 149, 30, },
++      { 1, 1, 0, 1, 149, 63, },
++      { 0, 1, 0, 1, 153, 32, },
++      { 2, 1, 0, 1, 153, 30, },
++      { 1, 1, 0, 1, 153, 63, },
++      { 0, 1, 0, 1, 157, 32, },
++      { 2, 1, 0, 1, 157, 30, },
++      { 1, 1, 0, 1, 157, 63, },
++      { 0, 1, 0, 1, 161, 32, },
++      { 2, 1, 0, 1, 161, 30, },
++      { 1, 1, 0, 1, 161, 63, },
++      { 0, 1, 0, 1, 165, 32, },
++      { 2, 1, 0, 1, 165, 30, },
++      { 1, 1, 0, 1, 165, 63, },
++      { 0, 1, 0, 2, 36, 32, },
++      { 2, 1, 0, 2, 36, 30, },
++      { 1, 1, 0, 2, 36, 30, },
++      { 0, 1, 0, 2, 40, 32, },
++      { 2, 1, 0, 2, 40, 30, },
++      { 1, 1, 0, 2, 40, 30, },
++      { 0, 1, 0, 2, 44, 32, },
++      { 2, 1, 0, 2, 44, 30, },
++      { 1, 1, 0, 2, 44, 30, },
++      { 0, 1, 0, 2, 48, 32, },
++      { 2, 1, 0, 2, 48, 30, },
++      { 1, 1, 0, 2, 48, 30, },
++      { 0, 1, 0, 2, 52, 32, },
++      { 2, 1, 0, 2, 52, 30, },
++      { 1, 1, 0, 2, 52, 30, },
++      { 0, 1, 0, 2, 56, 32, },
++      { 2, 1, 0, 2, 56, 30, },
++      { 1, 1, 0, 2, 56, 30, },
++      { 0, 1, 0, 2, 60, 32, },
++      { 2, 1, 0, 2, 60, 30, },
++      { 1, 1, 0, 2, 60, 30, },
++      { 0, 1, 0, 2, 64, 32, },
++      { 2, 1, 0, 2, 64, 30, },
++      { 1, 1, 0, 2, 64, 30, },
++      { 0, 1, 0, 2, 100, 32, },
++      { 2, 1, 0, 2, 100, 30, },
++      { 1, 1, 0, 2, 100, 30, },
++      { 0, 1, 0, 2, 104, 32, },
++      { 2, 1, 0, 2, 104, 30, },
++      { 1, 1, 0, 2, 104, 30, },
++      { 0, 1, 0, 2, 108, 32, },
++      { 2, 1, 0, 2, 108, 30, },
++      { 1, 1, 0, 2, 108, 30, },
++      { 0, 1, 0, 2, 112, 32, },
++      { 2, 1, 0, 2, 112, 30, },
++      { 1, 1, 0, 2, 112, 30, },
++      { 0, 1, 0, 2, 116, 32, },
++      { 2, 1, 0, 2, 116, 30, },
++      { 1, 1, 0, 2, 116, 30, },
++      { 0, 1, 0, 2, 120, 32, },
++      { 2, 1, 0, 2, 120, 30, },
++      { 1, 1, 0, 2, 120, 30, },
++      { 0, 1, 0, 2, 124, 32, },
++      { 2, 1, 0, 2, 124, 30, },
++      { 1, 1, 0, 2, 124, 30, },
++      { 0, 1, 0, 2, 128, 32, },
++      { 2, 1, 0, 2, 128, 30, },
++      { 1, 1, 0, 2, 128, 30, },
++      { 0, 1, 0, 2, 132, 32, },
++      { 2, 1, 0, 2, 132, 30, },
++      { 1, 1, 0, 2, 132, 30, },
++      { 0, 1, 0, 2, 136, 32, },
++      { 2, 1, 0, 2, 136, 30, },
++      { 1, 1, 0, 2, 136, 30, },
++      { 0, 1, 0, 2, 140, 32, },
++      { 2, 1, 0, 2, 140, 30, },
++      { 1, 1, 0, 2, 140, 30, },
++      { 0, 1, 0, 2, 149, 32, },
++      { 2, 1, 0, 2, 149, 30, },
++      { 1, 1, 0, 2, 149, 63, },
++      { 0, 1, 0, 2, 153, 32, },
++      { 2, 1, 0, 2, 153, 30, },
++      { 1, 1, 0, 2, 153, 63, },
++      { 0, 1, 0, 2, 157, 32, },
++      { 2, 1, 0, 2, 157, 30, },
++      { 1, 1, 0, 2, 157, 63, },
++      { 0, 1, 0, 2, 161, 32, },
++      { 2, 1, 0, 2, 161, 30, },
++      { 1, 1, 0, 2, 161, 63, },
++      { 0, 1, 0, 2, 165, 32, },
++      { 2, 1, 0, 2, 165, 30, },
++      { 1, 1, 0, 2, 165, 63, },
++      { 0, 1, 0, 3, 36, 28, },
++      { 2, 1, 0, 3, 36, 30, },
++      { 1, 1, 0, 3, 36, 30, },
++      { 0, 1, 0, 3, 40, 28, },
++      { 2, 1, 0, 3, 40, 30, },
++      { 1, 1, 0, 3, 40, 30, },
++      { 0, 1, 0, 3, 44, 28, },
++      { 2, 1, 0, 3, 44, 30, },
++      { 1, 1, 0, 3, 44, 30, },
++      { 0, 1, 0, 3, 48, 28, },
++      { 2, 1, 0, 3, 48, 30, },
++      { 1, 1, 0, 3, 48, 30, },
++      { 0, 1, 0, 3, 52, 34, },
++      { 2, 1, 0, 3, 52, 30, },
++      { 1, 1, 0, 3, 52, 30, },
++      { 0, 1, 0, 3, 56, 32, },
++      { 2, 1, 0, 3, 56, 30, },
++      { 1, 1, 0, 3, 56, 30, },
++      { 0, 1, 0, 3, 60, 30, },
++      { 2, 1, 0, 3, 60, 30, },
++      { 1, 1, 0, 3, 60, 30, },
++      { 0, 1, 0, 3, 64, 26, },
++      { 2, 1, 0, 3, 64, 30, },
++      { 1, 1, 0, 3, 64, 30, },
++      { 0, 1, 0, 3, 100, 28, },
++      { 2, 1, 0, 3, 100, 30, },
++      { 1, 1, 0, 3, 100, 30, },
++      { 0, 1, 0, 3, 104, 28, },
++      { 2, 1, 0, 3, 104, 30, },
++      { 1, 1, 0, 3, 104, 30, },
++      { 0, 1, 0, 3, 108, 30, },
++      { 2, 1, 0, 3, 108, 30, },
++      { 1, 1, 0, 3, 108, 30, },
++      { 0, 1, 0, 3, 112, 32, },
++      { 2, 1, 0, 3, 112, 30, },
++      { 1, 1, 0, 3, 112, 30, },
++      { 0, 1, 0, 3, 116, 32, },
++      { 2, 1, 0, 3, 116, 30, },
++      { 1, 1, 0, 3, 116, 30, },
++      { 0, 1, 0, 3, 120, 34, },
++      { 2, 1, 0, 3, 120, 30, },
++      { 1, 1, 0, 3, 120, 30, },
++      { 0, 1, 0, 3, 124, 32, },
++      { 2, 1, 0, 3, 124, 30, },
++      { 1, 1, 0, 3, 124, 30, },
++      { 0, 1, 0, 3, 128, 30, },
++      { 2, 1, 0, 3, 128, 30, },
++      { 1, 1, 0, 3, 128, 30, },
++      { 0, 1, 0, 3, 132, 28, },
++      { 2, 1, 0, 3, 132, 30, },
++      { 1, 1, 0, 3, 132, 30, },
++      { 0, 1, 0, 3, 136, 28, },
++      { 2, 1, 0, 3, 136, 30, },
++      { 1, 1, 0, 3, 136, 30, },
++      { 0, 1, 0, 3, 140, 26, },
++      { 2, 1, 0, 3, 140, 30, },
++      { 1, 1, 0, 3, 140, 30, },
++      { 0, 1, 0, 3, 149, 34, },
++      { 2, 1, 0, 3, 149, 30, },
++      { 1, 1, 0, 3, 149, 63, },
++      { 0, 1, 0, 3, 153, 34, },
++      { 2, 1, 0, 3, 153, 30, },
++      { 1, 1, 0, 3, 153, 63, },
++      { 0, 1, 0, 3, 157, 34, },
++      { 2, 1, 0, 3, 157, 30, },
++      { 1, 1, 0, 3, 157, 63, },
++      { 0, 1, 0, 3, 161, 34, },
++      { 2, 1, 0, 3, 161, 30, },
++      { 1, 1, 0, 3, 161, 63, },
++      { 0, 1, 0, 3, 165, 34, },
++      { 2, 1, 0, 3, 165, 30, },
++      { 1, 1, 0, 3, 165, 63, },
++      { 0, 1, 1, 2, 38, 26, },
++      { 2, 1, 1, 2, 38, 30, },
++      { 1, 1, 1, 2, 38, 30, },
++      { 0, 1, 1, 2, 46, 32, },
++      { 2, 1, 1, 2, 46, 30, },
++      { 1, 1, 1, 2, 46, 30, },
++      { 0, 1, 1, 2, 54, 32, },
++      { 2, 1, 1, 2, 54, 30, },
++      { 1, 1, 1, 2, 54, 30, },
++      { 0, 1, 1, 2, 62, 24, },
++      { 2, 1, 1, 2, 62, 30, },
++      { 1, 1, 1, 2, 62, 30, },
++      { 0, 1, 1, 2, 102, 24, },
++      { 2, 1, 1, 2, 102, 30, },
++      { 1, 1, 1, 2, 102, 30, },
++      { 0, 1, 1, 2, 110, 32, },
++      { 2, 1, 1, 2, 110, 30, },
++      { 1, 1, 1, 2, 110, 30, },
++      { 0, 1, 1, 2, 118, 32, },
++      { 2, 1, 1, 2, 118, 30, },
++      { 1, 1, 1, 2, 118, 30, },
++      { 0, 1, 1, 2, 126, 32, },
++      { 2, 1, 1, 2, 126, 30, },
++      { 1, 1, 1, 2, 126, 30, },
++      { 0, 1, 1, 2, 134, 32, },
++      { 2, 1, 1, 2, 134, 30, },
++      { 1, 1, 1, 2, 134, 30, },
++      { 0, 1, 1, 2, 151, 30, },
++      { 2, 1, 1, 2, 151, 30, },
++      { 1, 1, 1, 2, 151, 63, },
++      { 0, 1, 1, 2, 159, 32, },
++      { 2, 1, 1, 2, 159, 30, },
++      { 1, 1, 1, 2, 159, 63, },
++      { 0, 1, 1, 3, 38, 28, },
++      { 2, 1, 1, 3, 38, 30, },
++      { 1, 1, 1, 3, 38, 30, },
++      { 0, 1, 1, 3, 46, 28, },
++      { 2, 1, 1, 3, 46, 30, },
++      { 1, 1, 1, 3, 46, 30, },
++      { 0, 1, 1, 3, 54, 30, },
++      { 2, 1, 1, 3, 54, 30, },
++      { 1, 1, 1, 3, 54, 30, },
++      { 0, 1, 1, 3, 62, 30, },
++      { 2, 1, 1, 3, 62, 30, },
++      { 1, 1, 1, 3, 62, 30, },
++      { 0, 1, 1, 3, 102, 26, },
++      { 2, 1, 1, 3, 102, 30, },
++      { 1, 1, 1, 3, 102, 30, },
++      { 0, 1, 1, 3, 110, 30, },
++      { 2, 1, 1, 3, 110, 30, },
++      { 1, 1, 1, 3, 110, 30, },
++      { 0, 1, 1, 3, 118, 34, },
++      { 2, 1, 1, 3, 118, 30, },
++      { 1, 1, 1, 3, 118, 30, },
++      { 0, 1, 1, 3, 126, 32, },
++      { 2, 1, 1, 3, 126, 30, },
++      { 1, 1, 1, 3, 126, 30, },
++      { 0, 1, 1, 3, 134, 30, },
++      { 2, 1, 1, 3, 134, 30, },
++      { 1, 1, 1, 3, 134, 30, },
++      { 0, 1, 1, 3, 151, 34, },
++      { 2, 1, 1, 3, 151, 30, },
++      { 1, 1, 1, 3, 151, 63, },
++      { 0, 1, 1, 3, 159, 34, },
++      { 2, 1, 1, 3, 159, 30, },
++      { 1, 1, 1, 3, 159, 63, },
++      { 0, 1, 2, 4, 42, 22, },
++      { 2, 1, 2, 4, 42, 30, },
++      { 1, 1, 2, 4, 42, 30, },
++      { 0, 1, 2, 4, 58, 20, },
++      { 2, 1, 2, 4, 58, 30, },
++      { 1, 1, 2, 4, 58, 30, },
++      { 0, 1, 2, 4, 106, 20, },
++      { 2, 1, 2, 4, 106, 30, },
++      { 1, 1, 2, 4, 106, 30, },
++      { 0, 1, 2, 4, 122, 20, },
++      { 2, 1, 2, 4, 122, 30, },
++      { 1, 1, 2, 4, 122, 30, },
++      { 0, 1, 2, 4, 155, 28, },
++      { 2, 1, 2, 4, 155, 30, },
++      { 1, 1, 2, 4, 155, 63, },
++      { 0, 1, 2, 5, 42, 28, },
++      { 2, 1, 2, 5, 42, 30, },
++      { 1, 1, 2, 5, 42, 30, },
++      { 0, 1, 2, 5, 58, 26, },
++      { 2, 1, 2, 5, 58, 30, },
++      { 1, 1, 2, 5, 58, 30, },
++      { 0, 1, 2, 5, 106, 28, },
++      { 2, 1, 2, 5, 106, 30, },
++      { 1, 1, 2, 5, 106, 30, },
++      { 0, 1, 2, 5, 122, 32, },
++      { 2, 1, 2, 5, 122, 30, },
++      { 1, 1, 2, 5, 122, 30, },
++      { 0, 1, 2, 5, 155, 34, },
++      { 2, 1, 2, 5, 155, 30, },
++      { 1, 1, 2, 5, 155, 63, },
++};
++
++RTW_DECL_TABLE_TXPWR_LMT(rtw8821a_txpwr_lmt);
++
++static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8821a[] = {
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(3) | BIT(7), 0},
++      {0x0086,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_SDIO_MSK,
++       RTW_PWR_ADDR_SDIO,
++       RTW_PWR_CMD_WRITE, BIT(0), 0},
++      {0x0086,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_SDIO_MSK,
++       RTW_PWR_ADDR_SDIO,
++       RTW_PWR_CMD_POLLING, BIT(1), BIT(1)},
++      {0x004A,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(0), 0},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(3) | BIT(4), 0},
++      {0x0023,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_SDIO_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(4), 0},
++      {0x0301,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_PCI_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0},
++      {0xFFFF,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       0,
++       RTW_PWR_CMD_END, 0, 0},
++};
++
++static const struct rtw_pwr_seq_cmd trans_cardemu_to_act_8821a[] = {
++      {0x0020,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
++      {0x0067,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(4), 0},
++      {0x0001,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_DELAY, 1, RTW_PWR_DELAY_MS},
++      {0x0000,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(5), 0},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(4) | BIT(3) | BIT(2), 0},
++      {0x0075,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_PCI_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
++      {0x0006,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_POLLING, BIT(1), BIT(1)},
++      {0x0075,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_PCI_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(0), 0},
++      {0x0006,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(7), 0},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(4) | BIT(3), 0},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_POLLING, BIT(0), 0},
++      {0x004F,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
++      {0x0067,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(5) | BIT(4), BIT(5) | BIT(4)},
++      {0x0025,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(6), 0},
++      {0x0049,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(1), BIT(1)},
++      {0x0063,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(1), BIT(1)},
++      {0x0062,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(1), 0},
++      {0x0058,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
++      {0x005A,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(1), BIT(1)},
++      {0x002E,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0x82},
++      {0x0010,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(6), BIT(6)},
++      {0xFFFF,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       0,
++       RTW_PWR_CMD_END, 0, 0},
++};
++
++static const struct rtw_pwr_seq_cmd trans_act_to_lps_8821a[] = {
++      {0x0301,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_PCI_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0xFF},
++      {0x0522,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0xFF},
++      {0x05F8,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_POLLING, 0xFF, 0},
++      {0x05F9,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_POLLING, 0xFF, 0},
++      {0x05FA,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_POLLING, 0xFF, 0},
++      {0x05FB,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_POLLING, 0xFF, 0},
++      {0x0002,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(0), 0},
++      {0x0002,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_DELAY, 0, RTW_PWR_DELAY_US},
++      {0x0002,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(1), 0},
++      {0x0100,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0x03},
++      {0x0101,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(1), 0},
++      {0x0093,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_SDIO_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0x00},
++      {0x0553,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(5), BIT(5)},
++      {0xFFFF,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       0,
++       RTW_PWR_CMD_END, 0, 0},
++};
++
++static const struct rtw_pwr_seq_cmd trans_act_to_cardemu_8821a[] = {
++      {0x001F,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0},
++      {0x004F,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(0), 0},
++      {0x0049,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(1), 0},
++      {0x0006,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(1), BIT(1)},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_POLLING, BIT(1), 0},
++      {0x0000,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(5), BIT(5)},
++      {0x0020,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(0), 0},
++      {0xFFFF,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       0,
++       RTW_PWR_CMD_END, 0, 0},
++};
++
++static const struct rtw_pwr_seq_cmd trans_cardemu_to_carddis_8821a[] = {
++      {0x0007,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_SDIO_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, 0xFF, 0x20},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK | RTW_PWR_INTF_SDIO_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3)},
++      {0x0005,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_PCI_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(2), BIT(2)},
++      {0x004A,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_USB_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(0), 1},
++      {0x0023,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_SDIO_MSK,
++       RTW_PWR_ADDR_MAC,
++       RTW_PWR_CMD_WRITE, BIT(4), BIT(4)},
++      {0x0086,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_SDIO_MSK,
++       RTW_PWR_ADDR_SDIO,
++       RTW_PWR_CMD_WRITE, BIT(0), BIT(0)},
++      {0x0086,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_SDIO_MSK,
++       RTW_PWR_ADDR_SDIO,
++       RTW_PWR_CMD_POLLING, BIT(1), 0},
++      {0xFFFF,
++       RTW_PWR_CUT_ALL_MSK,
++       RTW_PWR_INTF_ALL_MSK,
++       0,
++       RTW_PWR_CMD_END, 0, 0},
++};
++
++const struct rtw_pwr_seq_cmd * const card_enable_flow_8821a[] = {
++      trans_carddis_to_cardemu_8821a,
++      trans_cardemu_to_act_8821a,
++      NULL
++};
++
++const struct rtw_pwr_seq_cmd * const enter_lps_flow_8821a[] = {
++      trans_act_to_lps_8821a,
++      NULL
++};
++
++const struct rtw_pwr_seq_cmd * const card_disable_flow_8821a[] = {
++      trans_act_to_cardemu_8821a,
++      trans_cardemu_to_carddis_8821a,
++      NULL
++};
++
++static const u8 rtw8821a_pwrtrk_5gb_n[][RTW_PWR_TRK_TBL_SZ] = {
++      {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
++       15, 16, 16, 16, 16, 16, 16, 16, 16},
++      {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
++       15, 16, 16, 16, 16, 16, 16, 16, 16},
++      {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
++       15, 16, 16, 16, 16, 16, 16, 16, 16},
++};
++
++static const u8 rtw8821a_pwrtrk_5gb_p[][RTW_PWR_TRK_TBL_SZ] = {
++      {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
++       15, 16, 16, 16, 16, 16, 16, 16, 16},
++      {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
++       15, 16, 16, 16, 16, 16, 16, 16, 16},
++      {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
++       15, 16, 16, 16, 16, 16, 16, 16, 16},
++};
++
++static const u8 rtw8821a_pwrtrk_5ga_n[][RTW_PWR_TRK_TBL_SZ] = {
++      {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
++       15, 16, 16, 16, 16, 16, 16, 16, 16},
++      {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
++       15, 16, 16, 16, 16, 16, 16, 16, 16},
++      {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
++       15, 16, 16, 16, 16, 16, 16, 16, 16},
++};
++
++static const u8 rtw8821a_pwrtrk_5ga_p[][RTW_PWR_TRK_TBL_SZ] = {
++      {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
++       15, 16, 16, 16, 16, 16, 16, 16, 16},
++      {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
++       15, 16, 16, 16, 16, 16, 16, 16, 16},
++      {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11, 12, 12, 13, 14, 15,
++       15, 16, 16, 16, 16, 16, 16, 16, 16},
++};
++
++static const u8 rtw8821a_pwrtrk_2gb_n[] = {
++      0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
++      6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10
++};
++
++static const u8 rtw8821a_pwrtrk_2gb_p[] = {
++      0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
++      8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12
++};
++
++static const u8 rtw8821a_pwrtrk_2ga_n[] = {
++      0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
++      6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10
++};
++
++static const u8 rtw8821a_pwrtrk_2ga_p[] = {
++      0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
++      8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12
++};
++
++static const u8 rtw8821a_pwrtrk_2g_cck_b_n[] = {
++      0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
++      6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10
++};
++
++static const u8 rtw8821a_pwrtrk_2g_cck_b_p[] = {
++      0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
++      8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12
++};
++
++static const u8 rtw8821a_pwrtrk_2g_cck_a_n[] = {
++      0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6,
++      6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10
++};
++
++static const u8 rtw8821a_pwrtrk_2g_cck_a_p[] = {
++      0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7,
++      8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12
++};
++
++const struct rtw_pwr_track_tbl rtw8821a_rtw_pwr_track_tbl = {
++      .pwrtrk_5gb_n[0] = rtw8821a_pwrtrk_5gb_n[0],
++      .pwrtrk_5gb_n[1] = rtw8821a_pwrtrk_5gb_n[1],
++      .pwrtrk_5gb_n[2] = rtw8821a_pwrtrk_5gb_n[2],
++      .pwrtrk_5gb_p[0] = rtw8821a_pwrtrk_5gb_p[0],
++      .pwrtrk_5gb_p[1] = rtw8821a_pwrtrk_5gb_p[1],
++      .pwrtrk_5gb_p[2] = rtw8821a_pwrtrk_5gb_p[2],
++      .pwrtrk_5ga_n[0] = rtw8821a_pwrtrk_5ga_n[0],
++      .pwrtrk_5ga_n[1] = rtw8821a_pwrtrk_5ga_n[1],
++      .pwrtrk_5ga_n[2] = rtw8821a_pwrtrk_5ga_n[2],
++      .pwrtrk_5ga_p[0] = rtw8821a_pwrtrk_5ga_p[0],
++      .pwrtrk_5ga_p[1] = rtw8821a_pwrtrk_5ga_p[1],
++      .pwrtrk_5ga_p[2] = rtw8821a_pwrtrk_5ga_p[2],
++      .pwrtrk_2gb_n = rtw8821a_pwrtrk_2gb_n,
++      .pwrtrk_2gb_p = rtw8821a_pwrtrk_2gb_p,
++      .pwrtrk_2ga_n = rtw8821a_pwrtrk_2ga_n,
++      .pwrtrk_2ga_p = rtw8821a_pwrtrk_2ga_p,
++      .pwrtrk_2g_cckb_n = rtw8821a_pwrtrk_2g_cck_b_n,
++      .pwrtrk_2g_cckb_p = rtw8821a_pwrtrk_2g_cck_b_p,
++      .pwrtrk_2g_ccka_n = rtw8821a_pwrtrk_2g_cck_a_n,
++      .pwrtrk_2g_ccka_p = rtw8821a_pwrtrk_2g_cck_a_p,
++};
+--- /dev/null
++++ b/drivers/net/wireless/realtek/rtw88/rtw8821a_table.h
+@@ -0,0 +1,21 @@
++/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
++/* Copyright(c) 2024  Realtek Corporation
++ */
++
++#ifndef __RTW8821A_TABLE_H__
++#define __RTW8821A_TABLE_H__
++
++extern const struct rtw_table rtw8821a_mac_tbl;
++extern const struct rtw_table rtw8821a_agc_tbl;
++extern const struct rtw_table rtw8821a_bb_tbl;
++extern const struct rtw_table rtw8821a_bb_pg_tbl;
++extern const struct rtw_table rtw8821a_rf_a_tbl;
++extern const struct rtw_table rtw8821a_txpwr_lmt_tbl;
++
++extern const struct rtw_pwr_seq_cmd * const card_enable_flow_8821a[];
++extern const struct rtw_pwr_seq_cmd * const enter_lps_flow_8821a[];
++extern const struct rtw_pwr_seq_cmd * const card_disable_flow_8821a[];
++
++extern const struct rtw_pwr_track_tbl rtw8821a_rtw_pwr_track_tbl;
++
++#endif
diff --git a/package/kernel/mac80211/patches/rtl/041-v6.13-wifi-rtw88-Add-rtw88xxa.-c-h.patch b/package/kernel/mac80211/patches/rtl/041-v6.13-wifi-rtw88-Add-rtw88xxa.-c-h.patch
new file mode 100644 (file)
index 0000000..79e1dee
--- /dev/null
@@ -0,0 +1,2187 @@
+From b870b9d31c9e4e6b20c410e1e017f8c87d4c2ae0 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 30 Oct 2024 20:27:39 +0200
+Subject: [PATCH] wifi: rtw88: Add rtw88xxa.{c,h}
+
+These contain code shared by both RTL8821AU and RTL8812AU chips.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/b8590382-a954-412d-a96b-63e360b97acc@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/rtw88xxa.c | 1989 +++++++++++++++++
+ drivers/net/wireless/realtek/rtw88/rtw88xxa.h |  175 ++
+ 2 files changed, 2164 insertions(+)
+ create mode 100644 drivers/net/wireless/realtek/rtw88/rtw88xxa.c
+ create mode 100644 drivers/net/wireless/realtek/rtw88/rtw88xxa.h
+
+--- /dev/null
++++ b/drivers/net/wireless/realtek/rtw88/rtw88xxa.c
+@@ -0,0 +1,1989 @@
++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
++/* Copyright(c) 2024  Realtek Corporation
++ */
++
++#include <linux/usb.h>
++#include "main.h"
++#include "coex.h"
++#include "phy.h"
++#include "rtw88xxa.h"
++#include "mac.h"
++#include "reg.h"
++#include "sec.h"
++#include "debug.h"
++#include "bf.h"
++#include "efuse.h"
++#include "usb.h"
++
++void rtw88xxa_efuse_grant(struct rtw_dev *rtwdev, bool on)
++{
++      if (on) {
++              rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);
++
++              rtw_write16_set(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_ELDR);
++              rtw_write16_set(rtwdev, REG_SYS_CLKR,
++                              BIT_LOADER_CLK_EN | BIT_ANA8M);
++      } else {
++              rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
++      }
++}
++EXPORT_SYMBOL(rtw88xxa_efuse_grant);
++
++static void rtw8812a_read_amplifier_type(struct rtw_dev *rtwdev)
++{
++      struct rtw_efuse *efuse = &rtwdev->efuse;
++
++      efuse->ext_pa_2g = (efuse->pa_type_2g & BIT(5)) &&
++                         (efuse->pa_type_2g & BIT(4));
++      efuse->ext_lna_2g = (efuse->lna_type_2g & BIT(7)) &&
++                          (efuse->lna_type_2g & BIT(3));
++
++      efuse->ext_pa_5g = (efuse->pa_type_5g & BIT(1)) &&
++                         (efuse->pa_type_5g & BIT(0));
++      efuse->ext_lna_5g = (efuse->lna_type_5g & BIT(7)) &&
++                          (efuse->lna_type_5g & BIT(3));
++
++      /* For rtw_phy_cond2: */
++      if (efuse->ext_pa_2g) {
++              u8 ext_type_pa_2g_a = u8_get_bits(efuse->lna_type_2g, BIT(2));
++              u8 ext_type_pa_2g_b = u8_get_bits(efuse->lna_type_2g, BIT(6));
++
++              efuse->gpa_type = (ext_type_pa_2g_b << 2) | ext_type_pa_2g_a;
++      }
++
++      if (efuse->ext_pa_5g) {
++              u8 ext_type_pa_5g_a = u8_get_bits(efuse->lna_type_5g, BIT(2));
++              u8 ext_type_pa_5g_b = u8_get_bits(efuse->lna_type_5g, BIT(6));
++
++              efuse->apa_type = (ext_type_pa_5g_b << 2) | ext_type_pa_5g_a;
++      }
++
++      if (efuse->ext_lna_2g) {
++              u8 ext_type_lna_2g_a = u8_get_bits(efuse->lna_type_2g,
++                                                 BIT(1) | BIT(0));
++              u8 ext_type_lna_2g_b = u8_get_bits(efuse->lna_type_2g,
++                                                 BIT(5) | BIT(4));
++
++              efuse->glna_type = (ext_type_lna_2g_b << 2) | ext_type_lna_2g_a;
++      }
++
++      if (efuse->ext_lna_5g) {
++              u8 ext_type_lna_5g_a = u8_get_bits(efuse->lna_type_5g,
++                                                 BIT(1) | BIT(0));
++              u8 ext_type_lna_5g_b = u8_get_bits(efuse->lna_type_5g,
++                                                 BIT(5) | BIT(4));
++
++              efuse->alna_type = (ext_type_lna_5g_b << 2) | ext_type_lna_5g_a;
++      }
++}
++
++static void rtw8812a_read_rfe_type(struct rtw_dev *rtwdev,
++                                 struct rtw88xxa_efuse *map)
++{
++      struct rtw_efuse *efuse = &rtwdev->efuse;
++
++      if (map->rfe_option == 0xff) {
++              if (rtwdev->hci.type == RTW_HCI_TYPE_USB)
++                      efuse->rfe_option = 0;
++              else if (rtwdev->hci.type == RTW_HCI_TYPE_PCIE)
++                      efuse->rfe_option = 2;
++              else
++                      efuse->rfe_option = 4;
++      } else if (map->rfe_option & BIT(7)) {
++              if (efuse->ext_lna_5g) {
++                      if (efuse->ext_pa_5g) {
++                              if (efuse->ext_lna_2g && efuse->ext_pa_2g)
++                                      efuse->rfe_option = 3;
++                              else
++                                      efuse->rfe_option = 0;
++                      } else {
++                              efuse->rfe_option = 2;
++                      }
++              } else {
++                      efuse->rfe_option = 4;
++              }
++      } else {
++              efuse->rfe_option = map->rfe_option & 0x3f;
++
++              /* Due to other customer already use incorrect EFUSE map for
++               * their product. We need to add workaround to prevent to
++               * modify spec and notify all customer to revise the IC 0xca
++               * content.
++               */
++              if (efuse->rfe_option == 4 &&
++                  (efuse->ext_pa_5g || efuse->ext_pa_2g ||
++                   efuse->ext_lna_5g || efuse->ext_lna_2g)) {
++                      if (rtwdev->hci.type == RTW_HCI_TYPE_USB)
++                              efuse->rfe_option = 0;
++                      else if (rtwdev->hci.type == RTW_HCI_TYPE_PCIE)
++                              efuse->rfe_option = 2;
++              }
++      }
++}
++
++static void rtw88xxa_read_usb_type(struct rtw_dev *rtwdev)
++{
++      struct rtw_efuse *efuse = &rtwdev->efuse;
++      struct rtw_hal *hal = &rtwdev->hal;
++      u8 antenna = 0;
++      u8 wmode = 0;
++      u8 val8, i;
++
++      efuse->hw_cap.bw = BIT(RTW_CHANNEL_WIDTH_20) |
++                         BIT(RTW_CHANNEL_WIDTH_40) |
++                         BIT(RTW_CHANNEL_WIDTH_80);
++      efuse->hw_cap.ptcl = EFUSE_HW_CAP_PTCL_VHT;
++
++      if (rtwdev->chip->id == RTW_CHIP_TYPE_8821A)
++              efuse->hw_cap.nss = 1;
++      else
++              efuse->hw_cap.nss = 2;
++
++      if (rtwdev->chip->id == RTW_CHIP_TYPE_8821A)
++              goto print_hw_cap;
++
++      for (i = 0; i < 2; i++) {
++              rtw_read8_physical_efuse(rtwdev, 1019 - i, &val8);
++
++              antenna = u8_get_bits(val8, GENMASK(7, 5));
++              if (antenna)
++                      break;
++              antenna = u8_get_bits(val8, GENMASK(3, 1));
++              if (antenna)
++                      break;
++      }
++
++      for (i = 0; i < 2; i++) {
++              rtw_read8_physical_efuse(rtwdev, 1021 - i, &val8);
++
++              wmode = u8_get_bits(val8, GENMASK(3, 2));
++              if (wmode)
++                      break;
++      }
++
++      if (antenna == 1) {
++              rtw_info(rtwdev, "This RTL8812AU says it is 1T1R.\n");
++
++              efuse->hw_cap.nss = 1;
++              hal->rf_type = RF_1T1R;
++              hal->rf_path_num = 1;
++              hal->rf_phy_num = 1;
++              hal->antenna_tx = BB_PATH_A;
++              hal->antenna_rx = BB_PATH_A;
++      } else {
++              /* Override rtw_chip_parameter_setup(). It detects 8812au as 1T1R. */
++              efuse->hw_cap.nss = 2;
++              hal->rf_type = RF_2T2R;
++              hal->rf_path_num = 2;
++              hal->rf_phy_num = 2;
++              hal->antenna_tx = BB_PATH_AB;
++              hal->antenna_rx = BB_PATH_AB;
++
++              if (antenna == 2 && wmode == 2) {
++                      rtw_info(rtwdev, "This RTL8812AU says it can't do VHT.\n");
++
++                      /* Can't be EFUSE_HW_CAP_IGNORE and can't be
++                       * EFUSE_HW_CAP_PTCL_VHT, so make it 1.
++                       */
++                      efuse->hw_cap.ptcl = 1;
++                      efuse->hw_cap.bw &= ~BIT(RTW_CHANNEL_WIDTH_80);
++              }
++      }
++
++print_hw_cap:
++      rtw_dbg(rtwdev, RTW_DBG_EFUSE,
++              "hw cap: hci=0x%02x, bw=0x%02x, ptcl=0x%02x, ant_num=%d, nss=%d\n",
++              efuse->hw_cap.hci, efuse->hw_cap.bw, efuse->hw_cap.ptcl,
++              efuse->hw_cap.ant_num, efuse->hw_cap.nss);
++}
++
++int rtw88xxa_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)
++{
++      const struct rtw_chip_info *chip = rtwdev->chip;
++      struct rtw_efuse *efuse = &rtwdev->efuse;
++      struct rtw88xxa_efuse *map;
++      int i;
++
++      if (chip->id == RTW_CHIP_TYPE_8812A)
++              rtwdev->hal.cut_version += 1;
++
++      if (rtw_dbg_is_enabled(rtwdev, RTW_DBG_EFUSE))
++              print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,
++                             log_map, chip->log_efuse_size, true);
++
++      map = (struct rtw88xxa_efuse *)log_map;
++
++      efuse->rf_board_option = map->rf_board_option;
++      efuse->crystal_cap = map->xtal_k;
++      if (efuse->crystal_cap == 0xff)
++              efuse->crystal_cap = 0x20;
++      efuse->pa_type_2g = map->pa_type;
++      efuse->pa_type_5g = map->pa_type;
++      efuse->lna_type_2g = map->lna_type_2g;
++      efuse->lna_type_5g = map->lna_type_5g;
++      if (chip->id == RTW_CHIP_TYPE_8812A) {
++              rtw8812a_read_amplifier_type(rtwdev);
++              rtw8812a_read_rfe_type(rtwdev, map);
++
++              efuse->usb_mode_switch = u8_get_bits(map->usb_mode, BIT(1));
++      }
++      efuse->channel_plan = map->channel_plan;
++      efuse->country_code[0] = map->country_code[0];
++      efuse->country_code[1] = map->country_code[1];
++      efuse->bt_setting = map->rf_bt_setting;
++      efuse->regd = map->rf_board_option & 0x7;
++      efuse->thermal_meter[0] = map->thermal_meter;
++      efuse->thermal_meter[1] = map->thermal_meter;
++      efuse->thermal_meter_k = map->thermal_meter;
++      efuse->tx_bb_swing_setting_2g = map->tx_bb_swing_setting_2g;
++      efuse->tx_bb_swing_setting_5g = map->tx_bb_swing_setting_5g;
++
++      rtw88xxa_read_usb_type(rtwdev);
++
++      if (chip->id == RTW_CHIP_TYPE_8821A)
++              efuse->btcoex = rtw_read32_mask(rtwdev, REG_WL_BT_PWR_CTRL,
++                                              BIT_BT_FUNC_EN);
++      else
++              efuse->btcoex = (map->rf_board_option & 0xe0) == 0x20;
++      efuse->share_ant = !!(efuse->bt_setting & BIT(0));
++
++      /* No antenna diversity because it's disabled in the vendor driver */
++      efuse->ant_div_cfg = 0;
++
++      efuse->ant_div_type = map->rf_antenna_option;
++      if (efuse->ant_div_type == 0xff)
++              efuse->ant_div_type = 0x3;
++
++      for (i = 0; i < 4; i++)
++              efuse->txpwr_idx_table[i] = map->txpwr_idx_table[i];
++
++      switch (rtw_hci_type(rtwdev)) {
++      case RTW_HCI_TYPE_USB:
++              if (chip->id == RTW_CHIP_TYPE_8821A)
++                      ether_addr_copy(efuse->addr, map->rtw8821au.mac_addr);
++              else
++                      ether_addr_copy(efuse->addr, map->rtw8812au.mac_addr);
++              break;
++      case RTW_HCI_TYPE_PCIE:
++      case RTW_HCI_TYPE_SDIO:
++      default:
++              /* unsupported now */
++              return -EOPNOTSUPP;
++      }
++
++      return 0;
++}
++EXPORT_SYMBOL(rtw88xxa_read_efuse);
++
++static void rtw88xxa_reset_8051(struct rtw_dev *rtwdev)
++{
++      const struct rtw_chip_info *chip = rtwdev->chip;
++      u8 val8;
++
++      /* Reset MCU IO Wrapper */
++      rtw_write8_clr(rtwdev, REG_RSV_CTRL, BIT(1));
++      if (chip->id == RTW_CHIP_TYPE_8812A)
++              rtw_write8_clr(rtwdev, REG_RSV_CTRL + 1, BIT(3));
++      else
++              rtw_write8_clr(rtwdev, REG_RSV_CTRL + 1, BIT(0));
++
++      val8 = rtw_read8(rtwdev, REG_SYS_FUNC_EN + 1);
++      rtw_write8(rtwdev, REG_SYS_FUNC_EN + 1, val8 & ~BIT(2));
++
++      /* Enable MCU IO Wrapper */
++      rtw_write8_clr(rtwdev, REG_RSV_CTRL, BIT(1));
++      if (chip->id == RTW_CHIP_TYPE_8812A)
++              rtw_write8_set(rtwdev, REG_RSV_CTRL + 1, BIT(3));
++      else
++              rtw_write8_set(rtwdev, REG_RSV_CTRL + 1, BIT(0));
++
++      rtw_write8(rtwdev, REG_SYS_FUNC_EN + 1, val8 | BIT(2));
++}
++
++/* A lightweight deinit function */
++static void rtw88xxau_hw_reset(struct rtw_dev *rtwdev)
++{
++      u8 val8;
++
++      if (!(rtw_read8(rtwdev, REG_MCUFW_CTRL) & BIT_RAM_DL_SEL))
++              return;
++
++      rtw88xxa_reset_8051(rtwdev);
++      rtw_write8(rtwdev, REG_MCUFW_CTRL, 0x00);
++
++      /* before BB reset should do clock gated */
++      rtw_write32_set(rtwdev, REG_FPGA0_XCD_RF_PARA, BIT(6));
++
++      /* reset BB */
++      rtw_write8_clr(rtwdev, REG_SYS_FUNC_EN, BIT(0) | BIT(1));
++
++      /* reset RF */
++      rtw_write8(rtwdev, REG_RF_CTRL, 0);
++
++      /* reset TRX path */
++      rtw_write16(rtwdev, REG_CR, 0);
++
++      /* reset MAC, reg0x5[1], auto FSM off */
++      rtw_write8_set(rtwdev, REG_APS_FSMCO + 1, APS_FSMCO_MAC_OFF >> 8);
++
++      /* check if reg0x5[1] auto cleared */
++      if (read_poll_timeout_atomic(rtw_read8, val8,
++                                   !(val8 & (APS_FSMCO_MAC_OFF >> 8)),
++                                   1, 5000, false,
++                                   rtwdev, REG_APS_FSMCO + 1))
++              rtw_err(rtwdev, "%s: timed out waiting for 0x5[1]\n", __func__);
++
++      /* reg0x5[0], auto FSM on */
++      val8 |= APS_FSMCO_MAC_ENABLE >> 8;
++      rtw_write8(rtwdev, REG_APS_FSMCO + 1, val8);
++
++      rtw_write8_clr(rtwdev, REG_SYS_FUNC_EN + 1, BIT(4) | BIT(7));
++      rtw_write8_set(rtwdev, REG_SYS_FUNC_EN + 1, BIT(4) | BIT(7));
++}
++
++static int rtw88xxau_init_power_on(struct rtw_dev *rtwdev)
++{
++      const struct rtw_chip_info *chip = rtwdev->chip;
++      u16 val16;
++      int ret;
++
++      ret = rtw_pwr_seq_parser(rtwdev, chip->pwr_on_seq);
++      if (ret) {
++              rtw_err(rtwdev, "power on flow failed\n");
++              return ret;
++      }
++
++      rtw_write16(rtwdev, REG_CR, 0);
++      val16 = BIT_HCI_TXDMA_EN | BIT_HCI_RXDMA_EN | BIT_TXDMA_EN |
++              BIT_RXDMA_EN | BIT_PROTOCOL_EN | BIT_SCHEDULE_EN |
++              BIT_MAC_SEC_EN | BIT_32K_CAL_TMR_EN;
++      rtw_write16_set(rtwdev, REG_CR, val16);
++
++      if (chip->id == RTW_CHIP_TYPE_8821A) {
++              if (rtw_read8(rtwdev, REG_SYS_CFG1 + 3) & BIT(0))
++                      rtw_write8_set(rtwdev, REG_LDO_SWR_CTRL, BIT(6));
++      }
++
++      return ret;
++}
++
++static int rtw88xxa_llt_write(struct rtw_dev *rtwdev, u32 address, u32 data)
++{
++      u32 value = BIT_LLT_WRITE_ACCESS | (address << 8) | data;
++      int count = 0;
++
++      rtw_write32(rtwdev, REG_LLT_INIT, value);
++
++      do {
++              if (!rtw_read32_mask(rtwdev, REG_LLT_INIT, BIT(31) | BIT(30)))
++                      break;
++
++              if (count > 20) {
++                      rtw_err(rtwdev, "Failed to poll write LLT done at %d!\n",
++                              address);
++                      return -EBUSY;
++              }
++      } while (++count);
++
++      return 0;
++}
++
++static int rtw88xxa_llt_init(struct rtw_dev *rtwdev, u32 boundary)
++{
++      u32 last_entry = 255;
++      int status = 0;
++      u32 i;
++
++      for (i = 0; i < boundary - 1; i++) {
++              status = rtw88xxa_llt_write(rtwdev, i, i + 1);
++              if (status)
++                      return status;
++      }
++
++      status = rtw88xxa_llt_write(rtwdev, boundary - 1, 0xFF);
++      if (status)
++              return status;
++
++      for (i = boundary; i < last_entry; i++) {
++              status = rtw88xxa_llt_write(rtwdev, i, i + 1);
++              if (status)
++                      return status;
++      }
++
++      status = rtw88xxa_llt_write(rtwdev, last_entry, boundary);
++
++      return status;
++}
++
++static void rtw88xxau_init_queue_reserved_page(struct rtw_dev *rtwdev)
++{
++      const struct rtw_chip_info *chip = rtwdev->chip;
++      struct rtw_fifo_conf *fifo = &rtwdev->fifo;
++      const struct rtw_page_table *pg_tbl = NULL;
++      u16 pubq_num;
++      u32 val32;
++
++      switch (rtw_hci_type(rtwdev)) {
++      case RTW_HCI_TYPE_PCIE:
++              pg_tbl = &chip->page_table[1];
++              break;
++      case RTW_HCI_TYPE_USB:
++              if (rtwdev->hci.bulkout_num == 2)
++                      pg_tbl = &chip->page_table[2];
++              else if (rtwdev->hci.bulkout_num == 3)
++                      pg_tbl = &chip->page_table[3];
++              else if (rtwdev->hci.bulkout_num == 4)
++                      pg_tbl = &chip->page_table[4];
++              break;
++      case RTW_HCI_TYPE_SDIO:
++              pg_tbl = &chip->page_table[0];
++              break;
++      default:
++              break;
++      }
++
++      pubq_num = fifo->acq_pg_num - pg_tbl->hq_num - pg_tbl->lq_num -
++                 pg_tbl->nq_num - pg_tbl->exq_num - pg_tbl->gapq_num;
++
++      val32 = BIT_RQPN_NE(pg_tbl->nq_num, pg_tbl->exq_num);
++      rtw_write32(rtwdev, REG_RQPN_NPQ, val32);
++
++      val32 = BIT_RQPN_HLP(pg_tbl->hq_num, pg_tbl->lq_num, pubq_num);
++      rtw_write32(rtwdev, REG_RQPN, val32);
++}
++
++static void rtw88xxau_init_tx_buffer_boundary(struct rtw_dev *rtwdev)
++{
++      struct rtw_fifo_conf *fifo = &rtwdev->fifo;
++
++      rtw_write8(rtwdev, REG_BCNQ_BDNY, fifo->rsvd_boundary);
++      rtw_write8(rtwdev, REG_MGQ_BDNY, fifo->rsvd_boundary);
++      rtw_write8(rtwdev, REG_WMAC_LBK_BF_HD, fifo->rsvd_boundary);
++      rtw_write8(rtwdev, REG_TRXFF_BNDY, fifo->rsvd_boundary);
++      rtw_write8(rtwdev, REG_DWBCN0_CTRL + 1, fifo->rsvd_boundary);
++}
++
++static int rtw88xxau_init_queue_priority(struct rtw_dev *rtwdev)
++{
++      const struct rtw_chip_info *chip = rtwdev->chip;
++      u8 bulkout_num = rtwdev->hci.bulkout_num;
++      const struct rtw_rqpn *rqpn = NULL;
++      u16 txdma_pq_map;
++
++      switch (rtw_hci_type(rtwdev)) {
++      case RTW_HCI_TYPE_PCIE:
++              rqpn = &chip->rqpn_table[1];
++              break;
++      case RTW_HCI_TYPE_USB:
++              if (bulkout_num == 2)
++                      rqpn = &chip->rqpn_table[2];
++              else if (bulkout_num == 3)
++                      rqpn = &chip->rqpn_table[3];
++              else if (bulkout_num == 4)
++                      rqpn = &chip->rqpn_table[4];
++              else
++                      return -EINVAL;
++              break;
++      case RTW_HCI_TYPE_SDIO:
++              rqpn = &chip->rqpn_table[0];
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      rtwdev->fifo.rqpn = rqpn;
++
++      txdma_pq_map = rtw_read16(rtwdev, REG_TXDMA_PQ_MAP) & 0x7;
++      txdma_pq_map |= BIT_TXDMA_HIQ_MAP(rqpn->dma_map_hi);
++      txdma_pq_map |= BIT_TXDMA_MGQ_MAP(rqpn->dma_map_mg);
++      txdma_pq_map |= BIT_TXDMA_BKQ_MAP(rqpn->dma_map_bk);
++      txdma_pq_map |= BIT_TXDMA_BEQ_MAP(rqpn->dma_map_be);
++      txdma_pq_map |= BIT_TXDMA_VIQ_MAP(rqpn->dma_map_vi);
++      txdma_pq_map |= BIT_TXDMA_VOQ_MAP(rqpn->dma_map_vo);
++      rtw_write16(rtwdev, REG_TXDMA_PQ_MAP, txdma_pq_map);
++
++      /* Packet in Hi Queue Tx immediately (No constraint for ATIM Period). */
++      if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB && bulkout_num == 4)
++              rtw_write8(rtwdev, REG_HIQ_NO_LMT_EN, 0xff);
++
++      return 0;
++}
++
++static void rtw88xxa_init_wmac_setting(struct rtw_dev *rtwdev)
++{
++      rtw_write16(rtwdev, REG_RXFLTMAP0, 0xffff);
++      rtw_write16(rtwdev, REG_RXFLTMAP1, 0x0400);
++      rtw_write16(rtwdev, REG_RXFLTMAP2, 0xffff);
++
++      rtw_write32(rtwdev, REG_MAR, 0xffffffff);
++      rtw_write32(rtwdev, REG_MAR + 4, 0xffffffff);
++}
++
++static void rtw88xxa_init_adaptive_ctrl(struct rtw_dev *rtwdev)
++{
++      rtw_write32_mask(rtwdev, REG_RRSR, 0xfffff, 0xffff1);
++      rtw_write16(rtwdev, REG_RETRY_LIMIT, 0x3030);
++}
++
++static void rtw88xxa_init_edca(struct rtw_dev *rtwdev)
++{
++      rtw_write16(rtwdev, REG_SPEC_SIFS, 0x100a);
++      rtw_write16(rtwdev, REG_MAC_SPEC_SIFS, 0x100a);
++
++      rtw_write16(rtwdev, REG_SIFS, 0x100a);
++      rtw_write16(rtwdev, REG_SIFS + 2, 0x100a);
++
++      rtw_write32(rtwdev, REG_EDCA_BE_PARAM, 0x005EA42B);
++      rtw_write32(rtwdev, REG_EDCA_BK_PARAM, 0x0000A44F);
++      rtw_write32(rtwdev, REG_EDCA_VI_PARAM, 0x005EA324);
++      rtw_write32(rtwdev, REG_EDCA_VO_PARAM, 0x002FA226);
++
++      rtw_write8(rtwdev, REG_USTIME_TSF, 0x50);
++      rtw_write8(rtwdev, REG_USTIME_EDCA, 0x50);
++}
++
++static void rtw88xxau_tx_aggregation(struct rtw_dev *rtwdev)
++{
++      const struct rtw_chip_info *chip = rtwdev->chip;
++
++      rtw_write32_mask(rtwdev, REG_DWBCN0_CTRL, 0xf0,
++                       chip->usb_tx_agg_desc_num);
++
++      if (chip->id == RTW_CHIP_TYPE_8821A)
++              rtw_write8(rtwdev, REG_DWBCN1_CTRL,
++                         chip->usb_tx_agg_desc_num << 1);
++}
++
++static void rtw88xxa_init_beacon_parameters(struct rtw_dev *rtwdev)
++{
++      u16 val16;
++
++      val16 = (BIT_DIS_TSF_UDT << 8) | BIT_DIS_TSF_UDT;
++      if (rtwdev->efuse.btcoex)
++              val16 |= BIT_EN_BCN_FUNCTION;
++      rtw_write16(rtwdev, REG_BCN_CTRL, val16);
++
++      rtw_write32_mask(rtwdev, REG_TBTT_PROHIBIT, 0xfffff, WLAN_TBTT_TIME);
++      rtw_write8(rtwdev, REG_DRVERLYINT, 0x05);
++      rtw_write8(rtwdev, REG_BCNDMATIM, WLAN_BCN_DMA_TIME);
++      rtw_write16(rtwdev, REG_BCNTCFG, 0x4413);
++}
++
++static void rtw88xxa_phy_bb_config(struct rtw_dev *rtwdev)
++{
++      u8 val8, crystal_cap;
++
++      /* power on BB/RF domain */
++      val8 = rtw_read8(rtwdev, REG_SYS_FUNC_EN);
++      val8 |= BIT_FEN_USBA;
++      rtw_write8(rtwdev, REG_SYS_FUNC_EN, val8);
++
++      /* toggle BB reset */
++      val8 |= BIT_FEN_BB_RSTB | BIT_FEN_BB_GLB_RST;
++      rtw_write8(rtwdev, REG_SYS_FUNC_EN, val8);
++
++      rtw_write8(rtwdev, REG_RF_CTRL,
++                 BIT_RF_EN | BIT_RF_RSTB | BIT_RF_SDM_RSTB);
++      rtw_write8(rtwdev, REG_RF_B_CTRL,
++                 BIT_RF_EN | BIT_RF_RSTB | BIT_RF_SDM_RSTB);
++
++      rtw_load_table(rtwdev, rtwdev->chip->bb_tbl);
++      rtw_load_table(rtwdev, rtwdev->chip->agc_tbl);
++
++      crystal_cap = rtwdev->efuse.crystal_cap & 0x3F;
++      if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A)
++              rtw_write32_mask(rtwdev, REG_AFE_CTRL3, 0x7FF80000,
++                               crystal_cap | (crystal_cap << 6));
++      else
++              rtw_write32_mask(rtwdev, REG_AFE_CTRL3, 0x00FFF000,
++                               crystal_cap | (crystal_cap << 6));
++}
++
++static void rtw88xxa_phy_rf_config(struct rtw_dev *rtwdev)
++{
++      u8 rf_path;
++
++      for (rf_path = 0; rf_path < rtwdev->hal.rf_path_num; rf_path++)
++              rtw_load_table(rtwdev, rtwdev->chip->rf_tbl[rf_path]);
++}
++
++static void rtw8812a_config_1t(struct rtw_dev *rtwdev)
++{
++      /* BB OFDM RX Path_A */
++      rtw_write32_mask(rtwdev, REG_RXPSEL, 0xff, 0x11);
++
++      /* BB OFDM TX Path_A */
++      rtw_write32_mask(rtwdev, REG_TXPSEL, MASKLWORD, 0x1111);
++
++      /* BB CCK R/Rx Path_A */
++      rtw_write32_mask(rtwdev, REG_CCK_RX, 0x0c000000, 0x0);
++
++      /* MCS support */
++      rtw_write32_mask(rtwdev, REG_RX_MCS_LIMIT, 0xc0000060, 0x4);
++
++      /* RF Path_B HSSI OFF */
++      rtw_write32_mask(rtwdev, REG_3WIRE_SWB, 0xf, 0x4);
++
++      /* RF Path_B Power Down */
++      rtw_write32_mask(rtwdev, REG_LSSI_WRITE_B, MASKDWORD, 0);
++
++      /* ADDA Path_B OFF */
++      rtw_write32_mask(rtwdev, REG_AFE_PWR1_B, MASKDWORD, 0);
++      rtw_write32_mask(rtwdev, REG_AFE_PWR2_B, MASKDWORD, 0);
++}
++
++static const u32 rtw88xxa_txscale_tbl[] = {
++      0x081, 0x088, 0x090, 0x099, 0x0a2, 0x0ac, 0x0b6, 0x0c0, 0x0cc, 0x0d8,
++      0x0e5, 0x0f2, 0x101, 0x110, 0x120, 0x131, 0x143, 0x156, 0x16a, 0x180,
++      0x197, 0x1af, 0x1c8, 0x1e3, 0x200, 0x21e, 0x23e, 0x261, 0x285, 0x2ab,
++      0x2d3, 0x2fe, 0x32b, 0x35c, 0x38e, 0x3c4, 0x3fe
++};
++
++static u32 rtw88xxa_get_bb_swing(struct rtw_dev *rtwdev, u8 band, u8 path)
++{
++      static const u32 swing2setting[4] = {0x200, 0x16a, 0x101, 0x0b6};
++      struct rtw_efuse *efuse = &rtwdev->efuse;
++      u8 tx_bb_swing;
++
++      if (band == RTW_BAND_2G)
++              tx_bb_swing = efuse->tx_bb_swing_setting_2g;
++      else
++              tx_bb_swing = efuse->tx_bb_swing_setting_5g;
++
++      if (path == RF_PATH_B)
++              tx_bb_swing >>= 2;
++      tx_bb_swing &= 0x3;
++
++      return swing2setting[tx_bb_swing];
++}
++
++static u8 rtw88xxa_get_swing_index(struct rtw_dev *rtwdev)
++{
++      u32 swing, table_value;
++      u8 i;
++
++      swing = rtw88xxa_get_bb_swing(rtwdev, rtwdev->hal.current_band_type,
++                                    RF_PATH_A);
++
++      for (i = 0; i < ARRAY_SIZE(rtw88xxa_txscale_tbl); i++) {
++              table_value = rtw88xxa_txscale_tbl[i];
++              if (swing == table_value)
++                      return i;
++      }
++
++      return 24;
++}
++
++static void rtw88xxa_pwrtrack_init(struct rtw_dev *rtwdev)
++{
++      struct rtw_dm_info *dm_info = &rtwdev->dm_info;
++      u8 path;
++
++      dm_info->default_ofdm_index = rtw88xxa_get_swing_index(rtwdev);
++
++      if (rtwdev->chip->id == RTW_CHIP_TYPE_8821A)
++              dm_info->default_cck_index = 0;
++      else
++              dm_info->default_cck_index = 24;
++
++      for (path = RF_PATH_A; path < rtwdev->hal.rf_path_num; path++) {
++              ewma_thermal_init(&dm_info->avg_thermal[path]);
++              dm_info->delta_power_index[path] = 0;
++              dm_info->delta_power_index_last[path] = 0;
++      }
++
++      dm_info->pwr_trk_triggered = false;
++      dm_info->pwr_trk_init_trigger = true;
++      dm_info->thermal_meter_k = rtwdev->efuse.thermal_meter_k;
++}
++
++void rtw88xxa_power_off(struct rtw_dev *rtwdev,
++                      const struct rtw_pwr_seq_cmd *const *enter_lps_flow)
++{
++      struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
++      enum usb_device_speed speed = rtwusb->udev->speed;
++      u16 ori_fsmc0;
++      u8 reg_cr;
++
++      reg_cr = rtw_read8(rtwdev, REG_CR);
++
++      /* Already powered off */
++      if (reg_cr == 0 || reg_cr == 0xEA)
++              return;
++
++      rtw_hci_stop(rtwdev);
++
++      if (!rtwdev->efuse.btcoex)
++              rtw_write16_clr(rtwdev, REG_GPIO_MUXCFG, BIT_EN_SIC);
++
++      /* set Reg 0xf008[3:4] to 2'11 to enable U1/U2 Mode in USB3.0. */
++      if (speed == USB_SPEED_SUPER)
++              rtw_write8_set(rtwdev, REG_USB_MOD, 0x18);
++
++      rtw_write32(rtwdev, REG_HISR0, 0xffffffff);
++      rtw_write32(rtwdev, REG_HISR1, 0xffffffff);
++      rtw_write32(rtwdev, REG_HIMR0, 0);
++      rtw_write32(rtwdev, REG_HIMR1, 0);
++
++      if (rtwdev->efuse.btcoex)
++              rtw_coex_power_off_setting(rtwdev);
++
++      ori_fsmc0 = rtw_read16(rtwdev, REG_APS_FSMCO);
++      rtw_write16(rtwdev, REG_APS_FSMCO, ori_fsmc0 & ~APS_FSMCO_HW_POWERDOWN);
++
++      /* Stop Tx Report Timer. */
++      rtw_write8_clr(rtwdev, REG_TX_RPT_CTRL, BIT(1));
++
++      /* Stop Rx */
++      rtw_write8(rtwdev, REG_CR, 0);
++
++      rtw_pwr_seq_parser(rtwdev, enter_lps_flow);
++
++      if (rtw_read8(rtwdev, REG_MCUFW_CTRL) & BIT_RAM_DL_SEL)
++              rtw88xxa_reset_8051(rtwdev);
++
++      rtw_write8_clr(rtwdev, REG_SYS_FUNC_EN + 1, BIT(2));
++      rtw_write8(rtwdev, REG_MCUFW_CTRL, 0);
++
++      rtw_pwr_seq_parser(rtwdev, rtwdev->chip->pwr_off_seq);
++
++      if (ori_fsmc0 & APS_FSMCO_HW_POWERDOWN)
++              rtw_write16_set(rtwdev, REG_APS_FSMCO, APS_FSMCO_HW_POWERDOWN);
++
++      clear_bit(RTW_FLAG_POWERON, rtwdev->flags);
++}
++EXPORT_SYMBOL(rtw88xxa_power_off);
++
++static void rtw88xxa_set_channel_bb_swing(struct rtw_dev *rtwdev, u8 band)
++{
++      rtw_write32_mask(rtwdev, REG_TXSCALE_A, BB_SWING_MASK,
++                       rtw88xxa_get_bb_swing(rtwdev, band, RF_PATH_A));
++      rtw_write32_mask(rtwdev, REG_TXSCALE_B, BB_SWING_MASK,
++                       rtw88xxa_get_bb_swing(rtwdev, band, RF_PATH_B));
++      rtw88xxa_pwrtrack_init(rtwdev);
++}
++
++static void rtw8821a_set_ext_band_switch(struct rtw_dev *rtwdev, u8 band)
++{
++      rtw_write32_mask(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN, 0);
++      rtw_write32_mask(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL, 1);
++      rtw_write32_mask(rtwdev, REG_RFE_INV_A, 0xf, 7);
++      rtw_write32_mask(rtwdev, REG_RFE_INV_A, 0xf0, 7);
++
++      if (band == RTW_BAND_2G)
++              rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(29) | BIT(28), 1);
++      else
++              rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(29) | BIT(28), 2);
++}
++
++static void rtw8821a_phy_set_rfe_reg_24g(struct rtw_dev *rtwdev)
++{
++      struct rtw_efuse *efuse = &rtwdev->efuse;
++
++      /* Turn off RF PA and LNA */
++
++      /* 0xCB0[15:12] = 0x7 (LNA_On)*/
++      rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, 0xF000, 0x7);
++      /* 0xCB0[7:4] = 0x7 (PAPE_A)*/
++      rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, 0xF0, 0x7);
++
++      if (efuse->ext_lna_2g) {
++              /* Turn on 2.4G External LNA */
++              rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(20), 1);
++              rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(22), 0);
++              rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, GENMASK(2, 0), 0x2);
++              rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, GENMASK(10, 8), 0x2);
++      } else {
++              /* Bypass 2.4G External LNA */
++              rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(20), 0);
++              rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(22), 0);
++              rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, GENMASK(2, 0), 0x7);
++              rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, GENMASK(10, 8), 0x7);
++      }
++}
++
++static void rtw8821a_phy_set_rfe_reg_5g(struct rtw_dev *rtwdev)
++{
++      /* Turn ON RF PA and LNA */
++
++      /* 0xCB0[15:12] = 0x7 (LNA_On)*/
++      rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, 0xF000, 0x5);
++      /* 0xCB0[7:4] = 0x7 (PAPE_A)*/
++      rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, 0xF0, 0x4);
++
++      /* Bypass 2.4G External LNA */
++      rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(20), 0);
++      rtw_write32_mask(rtwdev, REG_RFE_INV_A, BIT(22), 0);
++      rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, GENMASK(2, 0), 0x7);
++      rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, GENMASK(10, 8), 0x7);
++}
++
++static void rtw8812a_phy_set_rfe_reg_24g(struct rtw_dev *rtwdev)
++{
++      switch (rtwdev->efuse.rfe_option) {
++      case 0:
++      case 2:
++              rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77777777);
++              rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777777);
++              rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x000);
++              rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x000);
++              break;
++      case 1:
++              if (rtwdev->efuse.btcoex) {
++                      rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, 0xffffff, 0x777777);
++                      rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777777);
++                      rtw_write32_mask(rtwdev, REG_RFE_INV_A, 0x33f00000, 0x000);
++                      rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x000);
++              } else {
++                      rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77777777);
++                      rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777777);
++                      rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x000);
++                      rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x000);
++              }
++              break;
++      case 3:
++              rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x54337770);
++              rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x54337770);
++              rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x010);
++              rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x010);
++              rtw_write32_mask(rtwdev, REG_ANTSEL_SW, 0x00000303, 0x1);
++              break;
++      case 4:
++              rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77777777);
++              rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777777);
++              rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x001);
++              rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x001);
++              break;
++      case 5:
++              rtw_write8(rtwdev, REG_RFE_PINMUX_A + 2, 0x77);
++              rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777777);
++              rtw_write8_clr(rtwdev, REG_RFE_INV_A + 3, BIT(0));
++              rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x000);
++              break;
++      case 6:
++              rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x07772770);
++              rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x07772770);
++              rtw_write32(rtwdev, REG_RFE_INV_A, 0x00000077);
++              rtw_write32(rtwdev, REG_RFE_INV_B, 0x00000077);
++              break;
++      default:
++              break;
++      }
++}
++
++static void rtw8812a_phy_set_rfe_reg_5g(struct rtw_dev *rtwdev)
++{
++      switch (rtwdev->efuse.rfe_option) {
++      case 0:
++              rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77337717);
++              rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77337717);
++              rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x010);
++              rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x010);
++              break;
++      case 1:
++              if (rtwdev->efuse.btcoex) {
++                      rtw_write32_mask(rtwdev, REG_RFE_PINMUX_A, 0xffffff, 0x337717);
++                      rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77337717);
++                      rtw_write32_mask(rtwdev, REG_RFE_INV_A, 0x33f00000, 0x000);
++                      rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x000);
++              } else {
++                      rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77337717);
++                      rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77337717);
++                      rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x000);
++                      rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x000);
++              }
++              break;
++      case 2:
++      case 4:
++              rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77337777);
++              rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77337777);
++              rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x010);
++              rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x010);
++              break;
++      case 3:
++              rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x54337717);
++              rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x54337717);
++              rtw_write32_mask(rtwdev, REG_RFE_INV_A, RFE_INV_MASK, 0x010);
++              rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x010);
++              rtw_write32_mask(rtwdev, REG_ANTSEL_SW, 0x00000303, 0x1);
++              break;
++      case 5:
++              rtw_write8(rtwdev, REG_RFE_PINMUX_A + 2, 0x33);
++              rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77337777);
++              rtw_write8_set(rtwdev, REG_RFE_INV_A + 3, BIT(0));
++              rtw_write32_mask(rtwdev, REG_RFE_INV_B, RFE_INV_MASK, 0x010);
++              break;
++      case 6:
++              rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x07737717);
++              rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x07737717);
++              rtw_write32(rtwdev, REG_RFE_INV_A, 0x00000077);
++              rtw_write32(rtwdev, REG_RFE_INV_B, 0x00000077);
++              break;
++      default:
++              break;
++      }
++}
++
++static void rtw88xxa_switch_band(struct rtw_dev *rtwdev, u8 new_band, u8 bw)
++{
++      const struct rtw_chip_info *chip = rtwdev->chip;
++      u16 basic_rates, reg_41a;
++
++      /* 8811au one antenna module doesn't support antenna div, so driver must
++       * control antenna band, otherwise one of the band will have issue
++       */
++      if (chip->id == RTW_CHIP_TYPE_8821A && !rtwdev->efuse.btcoex &&
++          rtwdev->efuse.ant_div_cfg == 0)
++              rtw8821a_set_ext_band_switch(rtwdev, new_band);
++
++      if (new_band == RTW_BAND_2G) {
++              rtw_write32_set(rtwdev, REG_RXPSEL, BIT_RX_PSEL_RST);
++
++              if (chip->id == RTW_CHIP_TYPE_8821A) {
++                      rtw8821a_phy_set_rfe_reg_24g(rtwdev);
++
++                      rtw_write32_mask(rtwdev, REG_TXSCALE_A, 0xf00, 0);
++              } else {
++                      rtw_write32_mask(rtwdev, REG_BWINDICATION, 0x3, 0x1);
++                      rtw_write32_mask(rtwdev, REG_PDMFTH, GENMASK(17, 13), 0x17);
++
++                      if (bw == RTW_CHANNEL_WIDTH_20 &&
++                          rtwdev->hal.rf_type == RF_1T1R &&
++                          !rtwdev->efuse.ext_lna_2g)
++                              rtw_write32_mask(rtwdev, REG_PDMFTH, GENMASK(3, 1), 0x02);
++                      else
++                              rtw_write32_mask(rtwdev, REG_PDMFTH, GENMASK(3, 1), 0x04);
++
++                      rtw_write32_mask(rtwdev, REG_CCASEL, 0x3, 0);
++
++                      rtw8812a_phy_set_rfe_reg_24g(rtwdev);
++              }
++
++              rtw_write32_mask(rtwdev, REG_TXPSEL, 0xf0, 0x1);
++              rtw_write32_mask(rtwdev, REG_CCK_RX, 0x0f000000, 0x1);
++
++              basic_rates = BIT(DESC_RATE1M) | BIT(DESC_RATE2M) |
++                            BIT(DESC_RATE5_5M) | BIT(DESC_RATE11M) |
++                            BIT(DESC_RATE6M) | BIT(DESC_RATE12M) |
++                            BIT(DESC_RATE24M);
++              rtw_write32_mask(rtwdev, REG_RRSR, 0xfffff, basic_rates);
++
++              rtw_write8_clr(rtwdev, REG_CCK_CHECK, BIT_CHECK_CCK_EN);
++      } else { /* RTW_BAND_5G */
++              if (chip->id == RTW_CHIP_TYPE_8821A)
++                      rtw8821a_phy_set_rfe_reg_5g(rtwdev);
++
++              rtw_write8_set(rtwdev, REG_CCK_CHECK, BIT_CHECK_CCK_EN);
++
++              read_poll_timeout_atomic(rtw_read16, reg_41a, (reg_41a & 0x30) == 0x30,
++                                       50, 2500, false, rtwdev, REG_TXPKT_EMPTY);
++
++              rtw_write32_set(rtwdev, REG_RXPSEL, BIT_RX_PSEL_RST);
++
++              if (chip->id == RTW_CHIP_TYPE_8821A) {
++                      rtw_write32_mask(rtwdev, REG_TXSCALE_A, 0xf00, 1);
++              } else {
++                      rtw_write32_mask(rtwdev, REG_BWINDICATION, 0x3, 0x2);
++                      rtw_write32_mask(rtwdev, REG_PDMFTH, GENMASK(17, 13), 0x15);
++                      rtw_write32_mask(rtwdev, REG_PDMFTH, GENMASK(3, 1), 0x04);
++
++                      rtw_write32_mask(rtwdev, REG_CCASEL, 0x3, 1);
++
++                      rtw8812a_phy_set_rfe_reg_5g(rtwdev);
++              }
++
++              rtw_write32_mask(rtwdev, REG_TXPSEL, 0xf0, 0);
++              rtw_write32_mask(rtwdev, REG_CCK_RX, 0x0f000000, 0xf);
++
++              basic_rates = BIT(DESC_RATE6M) | BIT(DESC_RATE12M) |
++                            BIT(DESC_RATE24M);
++              rtw_write32_mask(rtwdev, REG_RRSR, 0xfffff, basic_rates);
++      }
++
++      rtw88xxa_set_channel_bb_swing(rtwdev, new_band);
++}
++
++int rtw88xxa_power_on(struct rtw_dev *rtwdev)
++{
++      struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
++      const struct rtw_chip_info *chip = rtwdev->chip;
++      struct rtw_efuse *efuse = &rtwdev->efuse;
++      struct rtw_hal *hal = &rtwdev->hal;
++      int ret;
++
++      if (test_bit(RTW_FLAG_POWERON, rtwdev->flags))
++              return 0;
++
++      /* Override rtw_chip_efuse_info_setup() */
++      if (chip->id == RTW_CHIP_TYPE_8821A)
++              efuse->btcoex = rtw_read32_mask(rtwdev, REG_WL_BT_PWR_CTRL,
++                                              BIT_BT_FUNC_EN);
++
++      /* Override rtw_chip_efuse_info_setup() */
++      if (chip->id == RTW_CHIP_TYPE_8812A)
++              rtw8812a_read_amplifier_type(rtwdev);
++
++      ret = rtw_hci_setup(rtwdev);
++      if (ret) {
++              rtw_err(rtwdev, "failed to setup hci\n");
++              goto err;
++      }
++
++      /* Revise for U2/U3 switch we can not update RF-A/B reset.
++       * Reset after MAC power on to prevent RF R/W error.
++       * Is it a right method?
++       */
++      if (chip->id == RTW_CHIP_TYPE_8812A) {
++              rtw_write8(rtwdev, REG_RF_CTRL, 5);
++              rtw_write8(rtwdev, REG_RF_CTRL, 7);
++              rtw_write8(rtwdev, REG_RF_B_CTRL, 5);
++              rtw_write8(rtwdev, REG_RF_B_CTRL, 7);
++      }
++
++      /* If HW didn't go through a complete de-initial procedure,
++       * it probably occurs some problem for double initial
++       * procedure.
++       */
++      rtw88xxau_hw_reset(rtwdev);
++
++      ret = rtw88xxau_init_power_on(rtwdev);
++      if (ret) {
++              rtw_err(rtwdev, "failed to power on\n");
++              goto err;
++      }
++
++      ret = rtw_set_trx_fifo_info(rtwdev);
++      if (ret) {
++              rtw_err(rtwdev, "failed to set trx fifo info\n");
++              goto err;
++      }
++
++      ret = rtw88xxa_llt_init(rtwdev, rtwdev->fifo.rsvd_boundary);
++      if (ret) {
++              rtw_err(rtwdev, "failed to init llt\n");
++              goto err;
++      }
++
++      rtw_write32_set(rtwdev, REG_TXDMA_OFFSET_CHK, BIT_DROP_DATA_EN);
++
++      ret = rtw_wait_firmware_completion(rtwdev);
++      if (ret) {
++              rtw_err(rtwdev, "failed to wait firmware completion\n");
++              goto err_off;
++      }
++
++      ret = rtw_download_firmware(rtwdev, &rtwdev->fw);
++      if (ret) {
++              rtw_err(rtwdev, "failed to download firmware\n");
++              goto err_off;
++      }
++
++      rtw_write8(rtwdev, REG_HMETFR, 0xf);
++
++      rtw_load_table(rtwdev, chip->mac_tbl);
++
++      rtw88xxau_init_queue_reserved_page(rtwdev);
++      rtw88xxau_init_tx_buffer_boundary(rtwdev);
++      rtw88xxau_init_queue_priority(rtwdev);
++
++      rtw_write16(rtwdev, REG_TRXFF_BNDY + 2,
++                  chip->rxff_size - REPORT_BUF - 1);
++
++      if (chip->id == RTW_CHIP_TYPE_8812A)
++              rtw_write8(rtwdev, REG_PBP,
++                         u8_encode_bits(PBP_512, PBP_TX_MASK) |
++                         u8_encode_bits(PBP_64, PBP_RX_MASK));
++
++      rtw_write8(rtwdev, REG_RX_DRVINFO_SZ, PHY_STATUS_SIZE);
++
++      rtw_write32(rtwdev, REG_HIMR0, 0);
++      rtw_write32(rtwdev, REG_HIMR1, 0);
++
++      rtw_write32_mask(rtwdev, REG_CR, 0x30000, 0x2);
++
++      rtw88xxa_init_wmac_setting(rtwdev);
++      rtw88xxa_init_adaptive_ctrl(rtwdev);
++      rtw88xxa_init_edca(rtwdev);
++
++      rtw_write8_set(rtwdev, REG_FWHW_TXQ_CTRL, BIT(7));
++      rtw_write8(rtwdev, REG_ACKTO, 0x80);
++
++      rtw88xxau_tx_aggregation(rtwdev);
++
++      rtw88xxa_init_beacon_parameters(rtwdev);
++      rtw_write8(rtwdev, REG_BCN_MAX_ERR, 0xff);
++
++      rtw_hci_interface_cfg(rtwdev);
++
++      /* usb3 rx interval */
++      rtw_write8(rtwdev, REG_USB3_RXITV, 0x01);
++
++      /* burst length=4, set 0x3400 for burst length=2 */
++      rtw_write16(rtwdev, REG_RXDMA_STATUS, 0x7400);
++      rtw_write8(rtwdev, REG_RXDMA_STATUS + 1, 0xf5);
++
++      /* 0x456 = 0x70, sugguested by Zhilin */
++      if (chip->id == RTW_CHIP_TYPE_8821A)
++              rtw_write8(rtwdev, REG_AMPDU_MAX_TIME, 0x5e);
++      else
++              rtw_write8(rtwdev, REG_AMPDU_MAX_TIME, 0x70);
++
++      rtw_write32(rtwdev, REG_AMPDU_MAX_LENGTH, 0xffffffff);
++      rtw_write8(rtwdev, REG_USTIME_TSF, 0x50);
++      rtw_write8(rtwdev, REG_USTIME_EDCA, 0x50);
++
++      if (rtwusb->udev->speed == USB_SPEED_SUPER)
++              /* Disable U1/U2 Mode to avoid 2.5G spur in USB3.0. */
++              rtw_write8_clr(rtwdev, REG_USB_MOD, BIT(4) | BIT(3));
++
++      rtw_write8_set(rtwdev, REG_SINGLE_AMPDU_CTRL, BIT_EN_SINGLE_APMDU);
++
++      /* for VHT packet length 11K */
++      rtw_write8(rtwdev, REG_RX_PKT_LIMIT, 0x18);
++
++      rtw_write8(rtwdev, REG_PIFS, 0x00);
++
++      if (chip->id == RTW_CHIP_TYPE_8821A) {
++              /* 0x0a0a too small, it can't pass AC logo. change to 0x1f1f */
++              rtw_write16(rtwdev, REG_MAX_AGGR_NUM, 0x1f1f);
++              rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL, 0x80);
++              rtw_write32(rtwdev, REG_FAST_EDCA_CTRL, 0x03087777);
++      } else {
++              rtw_write16(rtwdev, REG_MAX_AGGR_NUM, 0x1f1f);
++              rtw_write8_clr(rtwdev, REG_FWHW_TXQ_CTRL, BIT(7));
++      }
++
++       /* to prevent mac is reseted by bus. */
++      rtw_write8_set(rtwdev, REG_RSV_CTRL, BIT(5) | BIT(6));
++
++      /* ARFB table 9 for 11ac 5G 2SS */
++      rtw_write32(rtwdev, REG_ARFR0, 0x00000010);
++      rtw_write32(rtwdev, REG_ARFRH0, 0xfffff000);
++
++      /* ARFB table 10 for 11ac 5G 1SS */
++      rtw_write32(rtwdev, REG_ARFR1_V1, 0x00000010);
++      rtw_write32(rtwdev, REG_ARFRH1_V1, 0x003ff000);
++
++      /* ARFB table 11 for 11ac 24G 1SS */
++      rtw_write32(rtwdev, REG_ARFR2_V1, 0x00000015);
++      rtw_write32(rtwdev, REG_ARFRH2_V1, 0x003ff000);
++
++      /* ARFB table 12 for 11ac 24G 2SS */
++      rtw_write32(rtwdev, REG_ARFR3_V1, 0x00000015);
++      rtw_write32(rtwdev, REG_ARFRH3_V1, 0xffcff000);
++
++      rtw_write8_set(rtwdev, REG_CR, BIT_MACTXEN | BIT_MACRXEN);
++
++      rtw88xxa_phy_bb_config(rtwdev);
++      rtw88xxa_phy_rf_config(rtwdev);
++
++      if (chip->id == RTW_CHIP_TYPE_8812A && hal->rf_path_num == 1)
++              rtw8812a_config_1t(rtwdev);
++
++      rtw88xxa_switch_band(rtwdev, RTW_BAND_2G, RTW_CHANNEL_WIDTH_20);
++
++      rtw_write32(rtwdev, RTW_SEC_CMD_REG, BIT(31) | BIT(30));
++
++      rtw_write8(rtwdev, REG_HWSEQ_CTRL, 0xff);
++      rtw_write32(rtwdev, REG_BAR_MODE_CTRL, 0x0201ffff);
++      rtw_write8(rtwdev, REG_NAV_CTRL + 2, 0);
++
++      rtw_write8_clr(rtwdev, REG_GPIO_MUXCFG, BIT(5));
++
++      rtw_phy_init(rtwdev);
++
++      rtw88xxa_pwrtrack_init(rtwdev);
++
++      /* 0x4c6[3] 1: RTS BW = Data BW
++       * 0: RTS BW depends on CCA / secondary CCA result.
++       */
++      rtw_write8_clr(rtwdev, REG_QUEUE_CTRL, BIT(3));
++
++      /* enable Tx report. */
++      rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 1, 0x0f);
++
++      /* Pretx_en, for WEP/TKIP SEC */
++      rtw_write8(rtwdev, REG_EARLY_MODE_CONTROL + 3, 0x01);
++
++      rtw_write16(rtwdev, REG_TX_RPT_TIME, 0x3df0);
++
++      /* Reset USB mode switch setting */
++      rtw_write8(rtwdev, REG_SYS_SDIO_CTRL, 0x0);
++      rtw_write8(rtwdev, REG_ACLK_MON, 0x0);
++
++      rtw_write8(rtwdev, REG_USB_HRPWM, 0);
++
++      /* ack for xmit mgmt frames. */
++      rtw_write32_set(rtwdev, REG_FWHW_TXQ_CTRL, BIT(12));
++
++      hal->cck_high_power = rtw_read32_mask(rtwdev, REG_CCK_RPT_FORMAT,
++                                            BIT_CCK_RPT_FORMAT);
++
++      ret = rtw_hci_start(rtwdev);
++      if (ret) {
++              rtw_err(rtwdev, "failed to start hci\n");
++              goto err_off;
++      }
++
++      if (efuse->btcoex) {
++              rtw_coex_power_on_setting(rtwdev);
++              rtw_coex_init_hw_config(rtwdev, false);
++      }
++
++      set_bit(RTW_FLAG_POWERON, rtwdev->flags);
++
++      return 0;
++
++err_off:
++      chip->ops->power_off(rtwdev);
++
++err:
++      return ret;
++}
++EXPORT_SYMBOL(rtw88xxa_power_on);
++
++u32 rtw88xxa_phy_read_rf(struct rtw_dev *rtwdev,
++                       enum rtw_rf_path rf_path, u32 addr, u32 mask)
++{
++      static const u32 pi_addr[2] = { REG_3WIRE_SWA, REG_3WIRE_SWB };
++      static const u32 read_addr[2][2] = {
++              { REG_SI_READ_A, REG_SI_READ_B },
++              { REG_PI_READ_A, REG_PI_READ_B }
++      };
++      const struct rtw_chip_info *chip = rtwdev->chip;
++      const struct rtw_hal *hal = &rtwdev->hal;
++      bool set_cca, pi_mode;
++      u32 val;
++
++      if (rf_path >= hal->rf_phy_num) {
++              rtw_err(rtwdev, "unsupported rf path (%d)\n", rf_path);
++              return INV_RF_DATA;
++      }
++
++      /* CCA off to avoid reading the wrong value.
++       * Toggling CCA would affect RF 0x0, skip it.
++       */
++      set_cca = addr != 0x0 && chip->id == RTW_CHIP_TYPE_8812A &&
++                hal->cut_version != RTW_CHIP_VER_CUT_C;
++
++      if (set_cca)
++              rtw_write32_set(rtwdev, REG_CCA2ND, BIT(3));
++
++      addr &= 0xff;
++
++      pi_mode = rtw_read32_mask(rtwdev, pi_addr[rf_path], 0x4);
++
++      rtw_write32_mask(rtwdev, REG_HSSI_READ, MASKBYTE0, addr);
++
++      if (chip->id == RTW_CHIP_TYPE_8821A ||
++          hal->cut_version == RTW_CHIP_VER_CUT_C)
++              udelay(20);
++
++      val = rtw_read32_mask(rtwdev, read_addr[pi_mode][rf_path], mask);
++
++      /* CCA on */
++      if (set_cca)
++              rtw_write32_clr(rtwdev, REG_CCA2ND, BIT(3));
++
++      return val;
++}
++EXPORT_SYMBOL(rtw88xxa_phy_read_rf);
++
++static void rtw8812a_phy_fix_spur(struct rtw_dev *rtwdev, u8 channel, u8 bw)
++{
++      /* C cut Item12 ADC FIFO CLOCK */
++      if (rtwdev->hal.cut_version == RTW_CHIP_VER_CUT_C) {
++              if (bw == RTW_CHANNEL_WIDTH_40 && channel == 11)
++                      rtw_write32_mask(rtwdev, REG_ADCCLK, 0xC00, 0x3);
++              else
++                      rtw_write32_mask(rtwdev, REG_ADCCLK, 0xC00, 0x2);
++
++              /* A workaround to resolve 2480Mhz spur by setting ADC clock
++               * as 160M.
++               */
++              if (bw == RTW_CHANNEL_WIDTH_20 && (channel == 13 || channel == 14)) {
++                      rtw_write32_mask(rtwdev, REG_ADCCLK, 0x300, 0x3);
++                      rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 1);
++              } else if (bw == RTW_CHANNEL_WIDTH_40 && channel == 11) {
++                      rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 1);
++              } else if (bw != RTW_CHANNEL_WIDTH_80) {
++                      rtw_write32_mask(rtwdev, REG_ADCCLK, 0x300, 0x2);
++                      rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 0);
++              }
++      } else {
++              /* A workaround to resolve 2480Mhz spur by setting ADC clock
++               * as 160M.
++               */
++              if (bw == RTW_CHANNEL_WIDTH_20 && (channel == 13 || channel == 14))
++                      rtw_write32_mask(rtwdev, REG_ADCCLK, 0x300, 0x3);
++              else if (channel <= 14) /* 2.4G only */
++                      rtw_write32_mask(rtwdev, REG_ADCCLK, 0x300, 0x2);
++      }
++}
++
++static void rtw88xxa_switch_channel(struct rtw_dev *rtwdev, u8 channel, u8 bw)
++{
++      struct rtw_hal *hal = &rtwdev->hal;
++      u32 fc_area, rf_mod_ag;
++      u8 path;
++
++      switch (channel) {
++      case 36 ... 48:
++              fc_area = 0x494;
++              break;
++      case 50 ... 64:
++              fc_area = 0x453;
++              break;
++      case 100 ... 116:
++              fc_area = 0x452;
++              break;
++      default:
++              if (channel >= 118)
++                      fc_area = 0x412;
++              else
++                      fc_area = 0x96a;
++              break;
++      }
++
++      rtw_write32_mask(rtwdev, REG_CLKTRK, 0x1ffe0000, fc_area);
++
++      for (path = 0; path < hal->rf_path_num; path++) {
++              switch (channel) {
++              case 36 ... 64:
++                      rf_mod_ag = 0x101;
++                      break;
++              case 100 ... 140:
++                      rf_mod_ag = 0x301;
++                      break;
++              default:
++                      if (channel > 140)
++                              rf_mod_ag = 0x501;
++                      else
++                              rf_mod_ag = 0x000;
++                      break;
++              }
++
++              rtw_write_rf(rtwdev, path, RF_CFGCH,
++                           RF18_RFSI_MASK | RF18_BAND_MASK, rf_mod_ag);
++
++              if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A)
++                      rtw8812a_phy_fix_spur(rtwdev, channel, bw);
++
++              rtw_write_rf(rtwdev, path, RF_CFGCH, RF18_CHANNEL_MASK, channel);
++      }
++}
++
++static void rtw88xxa_set_reg_bw(struct rtw_dev *rtwdev, u8 bw)
++{
++      u16 val16 = rtw_read16(rtwdev, REG_WMAC_TRXPTCL_CTL);
++
++      val16 &= ~BIT_RFMOD;
++      if (bw == RTW_CHANNEL_WIDTH_80)
++              val16 |= BIT_RFMOD_80M;
++      else if (bw == RTW_CHANNEL_WIDTH_40)
++              val16 |= BIT_RFMOD_40M;
++
++      rtw_write16(rtwdev, REG_WMAC_TRXPTCL_CTL, val16);
++}
++
++static void rtw88xxa_post_set_bw_mode(struct rtw_dev *rtwdev, u8 channel,
++                                    u8 bw, u8 primary_chan_idx)
++{
++      struct rtw_hal *hal = &rtwdev->hal;
++      u8 txsc40 = 0, txsc20, txsc;
++      u8 reg_837, l1pkval;
++
++      rtw88xxa_set_reg_bw(rtwdev, bw);
++
++      txsc20 = primary_chan_idx;
++      if (bw == RTW_CHANNEL_WIDTH_80) {
++              if (txsc20 == RTW_SC_20_UPPER || txsc20 == RTW_SC_20_UPMOST)
++                      txsc40 = RTW_SC_40_UPPER;
++              else
++                      txsc40 = RTW_SC_40_LOWER;
++      }
++
++      txsc = BIT_TXSC_20M(txsc20) | BIT_TXSC_40M(txsc40);
++      rtw_write8(rtwdev, REG_DATA_SC, txsc);
++
++      reg_837 = rtw_read8(rtwdev, REG_BWINDICATION + 3);
++
++      switch (bw) {
++      default:
++      case RTW_CHANNEL_WIDTH_20:
++              rtw_write32_mask(rtwdev, REG_ADCCLK, 0x003003C3, 0x00300200);
++              rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 0);
++
++              if (hal->rf_type == RF_2T2R)
++                      rtw_write32_mask(rtwdev, REG_L1PKTH, 0x03C00000, 7);
++              else
++                      rtw_write32_mask(rtwdev, REG_L1PKTH, 0x03C00000, 8);
++
++              break;
++      case RTW_CHANNEL_WIDTH_40:
++              rtw_write32_mask(rtwdev, REG_ADCCLK, 0x003003C3, 0x00300201);
++              rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 0);
++              rtw_write32_mask(rtwdev, REG_ADCCLK, 0x3C, txsc);
++              rtw_write32_mask(rtwdev, REG_CCA2ND, 0xf0000000, txsc);
++
++              if (reg_837 & BIT(2)) {
++                      l1pkval = 6;
++              } else {
++                      if (hal->rf_type == RF_2T2R)
++                              l1pkval = 7;
++                      else
++                              l1pkval = 8;
++              }
++
++              rtw_write32_mask(rtwdev, REG_L1PKTH, 0x03C00000, l1pkval);
++
++              if (txsc == RTW_SC_20_UPPER)
++                      rtw_write32_set(rtwdev, REG_RXSB, BIT(4));
++              else
++                      rtw_write32_clr(rtwdev, REG_RXSB, BIT(4));
++
++              break;
++      case RTW_CHANNEL_WIDTH_80:
++              rtw_write32_mask(rtwdev, REG_ADCCLK, 0x003003C3, 0x00300202);
++              rtw_write32_mask(rtwdev, REG_ADC160, BIT(30), 1);
++              rtw_write32_mask(rtwdev, REG_ADCCLK, 0x3C, txsc);
++              rtw_write32_mask(rtwdev, REG_CCA2ND, 0xf0000000, txsc);
++
++              if (reg_837 & BIT(2)) {
++                      l1pkval = 5;
++              } else {
++                      if (hal->rf_type == RF_2T2R)
++                              l1pkval = 6;
++                      else
++                              l1pkval = 7;
++              }
++
++              rtw_write32_mask(rtwdev, REG_L1PKTH, 0x03C00000, l1pkval);
++
++              break;
++      }
++}
++
++static void rtw88xxa_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw)
++{
++      u8 path;
++
++      for (path = RF_PATH_A; path < rtwdev->hal.rf_path_num; path++) {
++              switch (bw) {
++              case RTW_CHANNEL_WIDTH_5:
++              case RTW_CHANNEL_WIDTH_10:
++              case RTW_CHANNEL_WIDTH_20:
++              default:
++                      rtw_write_rf(rtwdev, path, RF_CFGCH, RF18_BW_MASK, 3);
++                      break;
++              case RTW_CHANNEL_WIDTH_40:
++                      rtw_write_rf(rtwdev, path, RF_CFGCH, RF18_BW_MASK, 1);
++                      break;
++              case RTW_CHANNEL_WIDTH_80:
++                      rtw_write_rf(rtwdev, path, RF_CFGCH, RF18_BW_MASK, 0);
++                      break;
++              }
++      }
++}
++
++void rtw88xxa_set_channel(struct rtw_dev *rtwdev, u8 channel, u8 bw,
++                        u8 primary_chan_idx)
++{
++      u8 old_band, new_band;
++
++      if (rtw_read8(rtwdev, REG_CCK_CHECK) & BIT_CHECK_CCK_EN)
++              old_band = RTW_BAND_5G;
++      else
++              old_band = RTW_BAND_2G;
++
++      if (channel > 14)
++              new_band = RTW_BAND_5G;
++      else
++              new_band = RTW_BAND_2G;
++
++      if (new_band != old_band)
++              rtw88xxa_switch_band(rtwdev, new_band, bw);
++
++      rtw88xxa_switch_channel(rtwdev, channel, bw);
++
++      rtw88xxa_post_set_bw_mode(rtwdev, channel, bw, primary_chan_idx);
++
++      if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A)
++              rtw8812a_phy_fix_spur(rtwdev, channel, bw);
++
++      rtw88xxa_set_channel_rf(rtwdev, channel, bw);
++}
++EXPORT_SYMBOL(rtw88xxa_set_channel);
++
++void rtw88xxa_query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
++                             struct rtw_rx_pkt_stat *pkt_stat,
++                             s8 (*cck_rx_pwr)(u8 lna_idx, u8 vga_idx))
++{
++      struct rtw_dm_info *dm_info = &rtwdev->dm_info;
++      struct rtw_jaguar_phy_status_rpt *rpt;
++      u8 gain[RTW_RF_PATH_MAX], rssi, i;
++      s8 rx_pwr_db, power_a, power_b;
++      const s8 min_rx_power = -120;
++      u8 lna_idx, vga_idx;
++
++      rpt = (struct rtw_jaguar_phy_status_rpt *)phy_status;
++
++      if (pkt_stat->rate <= DESC_RATE11M) {
++              lna_idx = le32_get_bits(rpt->w1, RTW_JGRPHY_W1_AGC_RPT_LNA_IDX);
++              vga_idx = le32_get_bits(rpt->w1, RTW_JGRPHY_W1_AGC_RPT_VGA_IDX);
++
++              rx_pwr_db = cck_rx_pwr(lna_idx, vga_idx);
++
++              pkt_stat->rx_power[RF_PATH_A] = rx_pwr_db;
++              pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 1);
++              dm_info->rssi[RF_PATH_A] = pkt_stat->rssi;
++              pkt_stat->bw = RTW_CHANNEL_WIDTH_20;
++              pkt_stat->signal_power = rx_pwr_db;
++      } else { /* OFDM rate */
++              gain[RF_PATH_A] = le32_get_bits(rpt->w0, RTW_JGRPHY_W0_GAIN_A);
++              gain[RF_PATH_B] = le32_get_bits(rpt->w0, RTW_JGRPHY_W0_GAIN_B);
++
++              for (i = RF_PATH_A; i < rtwdev->hal.rf_path_num; i++) {
++                      pkt_stat->rx_power[i] = gain[i] - 110;
++                      rssi = rtw_phy_rf_power_2_rssi(&pkt_stat->rx_power[i], 1);
++                      dm_info->rssi[i] = rssi;
++              }
++
++              pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power,
++                                                       rtwdev->hal.rf_path_num);
++
++              power_a = pkt_stat->rx_power[RF_PATH_A];
++              power_b = pkt_stat->rx_power[RF_PATH_B];
++              if (rtwdev->hal.rf_path_num == 1)
++                      power_b = power_a;
++
++              pkt_stat->signal_power = max3(power_a, power_b, min_rx_power);
++      }
++}
++EXPORT_SYMBOL(rtw88xxa_query_phy_status);
++
++static void
++rtw88xxa_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path,
++                                  u8 rs, u32 *phy_pwr_idx)
++{
++      static const u32 offset_txagc[2] = {
++              REG_TX_AGC_A_CCK_11_CCK_1, REG_TX_AGC_B_CCK_11_CCK_1
++      };
++      u8 rate, rate_idx, pwr_index, shift;
++      struct rtw_hal *hal = &rtwdev->hal;
++      bool write_1ss_mcs9;
++      u32 mask;
++      int j;
++
++      for (j = 0; j < rtw_rate_size[rs]; j++) {
++              rate = rtw_rate_section[rs][j];
++
++              pwr_index = hal->tx_pwr_tbl[path][rate];
++
++              shift = rate & 0x3;
++              *phy_pwr_idx |= ((u32)pwr_index << (shift * 8));
++
++              write_1ss_mcs9 = rate == DESC_RATEVHT1SS_MCS9 &&
++                               hal->rf_path_num == 1;
++
++              if (write_1ss_mcs9)
++                      mask = MASKLWORD;
++              else
++                      mask = MASKDWORD;
++
++              if (shift == 0x3 || write_1ss_mcs9) {
++                      rate_idx = rate & 0xfc;
++                      if (rate >= DESC_RATEVHT1SS_MCS0)
++                              rate_idx -= 0x10;
++
++                      rtw_write32_mask(rtwdev, offset_txagc[path] + rate_idx,
++                                       mask, *phy_pwr_idx);
++
++                      *phy_pwr_idx = 0;
++              }
++      }
++}
++
++static void rtw88xxa_tx_power_training(struct rtw_dev *rtwdev, u8 bw,
++                                     u8 channel, u8 path)
++{
++      static const u32 write_offset[] = {
++              REG_TX_PWR_TRAINING_A, REG_TX_PWR_TRAINING_B,
++      };
++      u32 power_level, write_data;
++      u8 i;
++
++      power_level = rtwdev->hal.tx_pwr_tbl[path][DESC_RATEMCS7];
++      write_data = 0;
++
++      for (i = 0; i < 3; i++) {
++              if (i == 0)
++                      power_level -= 10;
++              else if (i == 1)
++                      power_level -= 8;
++              else
++                      power_level -= 6;
++
++              write_data |= max_t(u32, power_level, 2) << (i * 8);
++      }
++
++      rtw_write32_mask(rtwdev, write_offset[path], 0xffffff, write_data);
++}
++
++void rtw88xxa_set_tx_power_index(struct rtw_dev *rtwdev)
++{
++      struct rtw_hal *hal = &rtwdev->hal;
++      u32 phy_pwr_idx = 0;
++      int rs, path;
++
++      for (path = 0; path < hal->rf_path_num; path++) {
++              for (rs = 0; rs < RTW_RATE_SECTION_MAX; rs++) {
++                      if (hal->rf_path_num == 1 &&
++                          (rs == RTW_RATE_SECTION_HT_2S ||
++                           rs == RTW_RATE_SECTION_VHT_2S))
++                              continue;
++
++                      if (test_bit(RTW_FLAG_SCANNING, rtwdev->flags) &&
++                          rs > RTW_RATE_SECTION_OFDM)
++                              continue;
++
++                      if (hal->current_band_type == RTW_BAND_5G &&
++                          rs == RTW_RATE_SECTION_CCK)
++                              continue;
++
++                      rtw88xxa_set_tx_power_index_by_rate(rtwdev, path, rs,
++                                                          &phy_pwr_idx);
++              }
++
++              rtw88xxa_tx_power_training(rtwdev, hal->current_band_width,
++                                         hal->current_channel, path);
++      }
++}
++EXPORT_SYMBOL(rtw88xxa_set_tx_power_index);
++
++void rtw88xxa_false_alarm_statistics(struct rtw_dev *rtwdev)
++{
++      struct rtw_dm_info *dm_info = &rtwdev->dm_info;
++      u32 cck_fa_cnt, ofdm_fa_cnt;
++      u32 crc32_cnt, cca32_cnt;
++      u32 cck_enable;
++
++      cck_enable = rtw_read32(rtwdev, REG_RXPSEL) & BIT(28);
++      cck_fa_cnt = rtw_read16(rtwdev, REG_FA_CCK);
++      ofdm_fa_cnt = rtw_read16(rtwdev, REG_FA_OFDM);
++
++      dm_info->cck_fa_cnt = cck_fa_cnt;
++      dm_info->ofdm_fa_cnt = ofdm_fa_cnt;
++      dm_info->total_fa_cnt = ofdm_fa_cnt;
++      if (cck_enable)
++              dm_info->total_fa_cnt += cck_fa_cnt;
++
++      crc32_cnt = rtw_read32(rtwdev, REG_CRC_CCK);
++      dm_info->cck_ok_cnt = u32_get_bits(crc32_cnt, MASKLWORD);
++      dm_info->cck_err_cnt = u32_get_bits(crc32_cnt, MASKHWORD);
++
++      crc32_cnt = rtw_read32(rtwdev, REG_CRC_OFDM);
++      dm_info->ofdm_ok_cnt = u32_get_bits(crc32_cnt, MASKLWORD);
++      dm_info->ofdm_err_cnt = u32_get_bits(crc32_cnt, MASKHWORD);
++
++      crc32_cnt = rtw_read32(rtwdev, REG_CRC_HT);
++      dm_info->ht_ok_cnt = u32_get_bits(crc32_cnt, MASKLWORD);
++      dm_info->ht_err_cnt = u32_get_bits(crc32_cnt, MASKHWORD);
++
++      crc32_cnt = rtw_read32(rtwdev, REG_CRC_VHT);
++      dm_info->vht_ok_cnt = u32_get_bits(crc32_cnt, MASKLWORD);
++      dm_info->vht_err_cnt = u32_get_bits(crc32_cnt, MASKHWORD);
++
++      cca32_cnt = rtw_read32(rtwdev, REG_CCA_OFDM);
++      dm_info->ofdm_cca_cnt = u32_get_bits(cca32_cnt, MASKHWORD);
++      dm_info->total_cca_cnt = dm_info->ofdm_cca_cnt;
++      if (cck_enable) {
++              cca32_cnt = rtw_read32(rtwdev, REG_CCA_CCK);
++              dm_info->cck_cca_cnt = u32_get_bits(cca32_cnt, MASKLWORD);
++              dm_info->total_cca_cnt += dm_info->cck_cca_cnt;
++      }
++
++      rtw_write32_set(rtwdev, REG_FAS, BIT(17));
++      rtw_write32_clr(rtwdev, REG_FAS, BIT(17));
++      rtw_write32_clr(rtwdev, REG_CCK0_FAREPORT, BIT(15));
++      rtw_write32_set(rtwdev, REG_CCK0_FAREPORT, BIT(15));
++      rtw_write32_set(rtwdev, REG_CNTRST, BIT(0));
++      rtw_write32_clr(rtwdev, REG_CNTRST, BIT(0));
++}
++EXPORT_SYMBOL(rtw88xxa_false_alarm_statistics);
++
++void rtw88xxa_iqk_backup_mac_bb(struct rtw_dev *rtwdev,
++                              u32 *macbb_backup,
++                              const u32 *backup_macbb_reg,
++                              u32 macbb_num)
++{
++      u32 i;
++
++      /* [31] = 0 --> Page C */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++
++      /* save MACBB default value */
++      for (i = 0; i < macbb_num; i++)
++              macbb_backup[i] = rtw_read32(rtwdev, backup_macbb_reg[i]);
++}
++EXPORT_SYMBOL(rtw88xxa_iqk_backup_mac_bb);
++
++void rtw88xxa_iqk_backup_afe(struct rtw_dev *rtwdev, u32 *afe_backup,
++                           const u32 *backup_afe_reg, u32 afe_num)
++{
++      u32 i;
++
++      /* [31] = 0 --> Page C */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++
++      /* Save AFE Parameters */
++      for (i = 0; i < afe_num; i++)
++              afe_backup[i] = rtw_read32(rtwdev, backup_afe_reg[i]);
++}
++EXPORT_SYMBOL(rtw88xxa_iqk_backup_afe);
++
++void rtw88xxa_iqk_restore_mac_bb(struct rtw_dev *rtwdev,
++                               u32 *macbb_backup,
++                               const u32 *backup_macbb_reg,
++                               u32 macbb_num)
++{
++      u32 i;
++
++      /* [31] = 0 --> Page C */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++
++      /* Reload MacBB Parameters */
++      for (i = 0; i < macbb_num; i++)
++              rtw_write32(rtwdev, backup_macbb_reg[i], macbb_backup[i]);
++}
++EXPORT_SYMBOL(rtw88xxa_iqk_restore_mac_bb);
++
++void rtw88xxa_iqk_configure_mac(struct rtw_dev *rtwdev)
++{
++      /* [31] = 0 --> Page C */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++
++      rtw_write8(rtwdev, REG_TXPAUSE, 0x3f);
++      rtw_write32_mask(rtwdev, REG_BCN_CTRL,
++                       (BIT_EN_BCN_FUNCTION << 8) | BIT_EN_BCN_FUNCTION, 0x0);
++
++      /* RX ante off */
++      rtw_write8(rtwdev, REG_RXPSEL, 0x00);
++
++      /* CCA off */
++      rtw_write32_mask(rtwdev, REG_CCA2ND, 0xf, 0xc);
++
++      /* CCK RX path off */
++      rtw_write8(rtwdev, REG_CCK_RX + 3, 0xf);
++}
++EXPORT_SYMBOL(rtw88xxa_iqk_configure_mac);
++
++bool rtw88xxa_iqk_finish(int average, int threshold,
++                       int *x_temp, int *y_temp, int *x, int *y,
++                       bool break_inner, bool break_outer)
++{
++      bool finish = false;
++      int i, ii, dx, dy;
++
++      for (i = 0; i < average; i++) {
++              for (ii = i + 1; ii < average; ii++) {
++                      dx = abs_diff(x_temp[i] >> 21, x_temp[ii] >> 21);
++                      dy = abs_diff(y_temp[i] >> 21, y_temp[ii] >> 21);
++
++                      if (dx < threshold && dy < threshold) {
++                              *x = ((x_temp[i] >> 21) + (x_temp[ii] >> 21));
++                              *y = ((y_temp[i] >> 21) + (y_temp[ii] >> 21));
++
++                              *x /= 2;
++                              *y /= 2;
++
++                              finish = true;
++
++                              if (break_inner)
++                                      break;
++                      }
++              }
++
++              if (finish && break_outer)
++                      break;
++      }
++
++      return finish;
++}
++EXPORT_SYMBOL(rtw88xxa_iqk_finish);
++
++static void rtw88xxa_pwrtrack_set(struct rtw_dev *rtwdev, u8 tx_rate, u8 path)
++{
++      static const u32 reg_txscale[2] = { REG_TXSCALE_A, REG_TXSCALE_B };
++      struct rtw_dm_info *dm_info = &rtwdev->dm_info;
++      u8 cck_swing_idx, ofdm_swing_idx;
++      u8 pwr_tracking_limit;
++
++      switch (tx_rate) {
++      case DESC_RATE1M ... DESC_RATE11M:
++              pwr_tracking_limit = 32;
++              break;
++      case DESC_RATE6M ... DESC_RATE48M:
++      case DESC_RATEMCS3 ... DESC_RATEMCS4:
++      case DESC_RATEMCS11 ... DESC_RATEMCS12:
++      case DESC_RATEVHT1SS_MCS3 ... DESC_RATEVHT1SS_MCS4:
++      case DESC_RATEVHT2SS_MCS3 ... DESC_RATEVHT2SS_MCS4:
++              pwr_tracking_limit = 30;
++              break;
++      case DESC_RATE54M:
++      case DESC_RATEMCS5 ... DESC_RATEMCS7:
++      case DESC_RATEMCS13 ... DESC_RATEMCS15:
++      case DESC_RATEVHT1SS_MCS5 ... DESC_RATEVHT1SS_MCS6:
++      case DESC_RATEVHT2SS_MCS5 ... DESC_RATEVHT2SS_MCS6:
++              pwr_tracking_limit = 28;
++              break;
++      case DESC_RATEMCS0 ... DESC_RATEMCS2:
++      case DESC_RATEMCS8 ... DESC_RATEMCS10:
++      case DESC_RATEVHT1SS_MCS0 ... DESC_RATEVHT1SS_MCS2:
++      case DESC_RATEVHT2SS_MCS0 ... DESC_RATEVHT2SS_MCS2:
++              pwr_tracking_limit = 34;
++              break;
++      case DESC_RATEVHT1SS_MCS7:
++      case DESC_RATEVHT2SS_MCS7:
++              pwr_tracking_limit = 26;
++              break;
++      default:
++      case DESC_RATEVHT1SS_MCS8:
++      case DESC_RATEVHT2SS_MCS8:
++              pwr_tracking_limit = 24;
++              break;
++      case DESC_RATEVHT1SS_MCS9:
++      case DESC_RATEVHT2SS_MCS9:
++              pwr_tracking_limit = 22;
++              break;
++      }
++
++      cck_swing_idx = dm_info->delta_power_index[path] + dm_info->default_cck_index;
++      ofdm_swing_idx = dm_info->delta_power_index[path] + dm_info->default_ofdm_index;
++
++      if (ofdm_swing_idx > pwr_tracking_limit) {
++              if (path == RF_PATH_A)
++                      dm_info->txagc_remnant_cck = cck_swing_idx - pwr_tracking_limit;
++              dm_info->txagc_remnant_ofdm[path] = ofdm_swing_idx - pwr_tracking_limit;
++
++              ofdm_swing_idx = pwr_tracking_limit;
++      } else if (ofdm_swing_idx == 0) {
++              if (path == RF_PATH_A)
++                      dm_info->txagc_remnant_cck = cck_swing_idx;
++              dm_info->txagc_remnant_ofdm[path] = ofdm_swing_idx;
++      } else {
++              if (path == RF_PATH_A)
++                      dm_info->txagc_remnant_cck = 0;
++              dm_info->txagc_remnant_ofdm[path] = 0;
++      }
++
++      rtw_write32_mask(rtwdev, reg_txscale[path], GENMASK(31, 21),
++                       rtw88xxa_txscale_tbl[ofdm_swing_idx]);
++}
++
++void rtw88xxa_phy_pwrtrack(struct rtw_dev *rtwdev,
++                         void (*do_lck)(struct rtw_dev *rtwdev),
++                         void (*do_iqk)(struct rtw_dev *rtwdev))
++{
++      struct rtw_dm_info *dm_info = &rtwdev->dm_info;
++      struct rtw_hal *hal = &rtwdev->hal;
++      struct rtw_swing_table swing_table;
++      s8 remnant_pre[RTW_RF_PATH_MAX];
++      u8 thermal_value, delta, path;
++      bool need_iqk;
++
++      rtw_phy_config_swing_table(rtwdev, &swing_table);
++
++      if (rtwdev->efuse.thermal_meter[0] == 0xff) {
++              pr_err_once("efuse thermal meter is 0xff\n");
++              return;
++      }
++
++      thermal_value = rtw_read_rf(rtwdev, RF_PATH_A, RF_T_METER, 0xfc00);
++
++      rtw_phy_pwrtrack_avg(rtwdev, thermal_value, RF_PATH_A);
++
++      need_iqk = rtw_phy_pwrtrack_need_iqk(rtwdev);
++
++      if (need_iqk && do_lck)
++              do_lck(rtwdev);
++
++      if (dm_info->pwr_trk_init_trigger)
++              dm_info->pwr_trk_init_trigger = false;
++      else if (!rtw_phy_pwrtrack_thermal_changed(rtwdev, thermal_value,
++                                                 RF_PATH_A))
++              goto iqk;
++
++      delta = rtw_phy_pwrtrack_get_delta(rtwdev, RF_PATH_A);
++
++      for (path = RF_PATH_A; path < hal->rf_path_num; path++) {
++              remnant_pre[path] = dm_info->txagc_remnant_ofdm[path];
++
++              dm_info->delta_power_index[path] =
++                      rtw_phy_pwrtrack_get_pwridx(rtwdev, &swing_table, path,
++                                                  RF_PATH_A, delta);
++
++              if (dm_info->delta_power_index[path] !=
++                  dm_info->delta_power_index_last[path]) {
++                      dm_info->delta_power_index_last[path] =
++                              dm_info->delta_power_index[path];
++
++                      rtw88xxa_pwrtrack_set(rtwdev, dm_info->tx_rate, path);
++              }
++      }
++
++      for (path = RF_PATH_A; path < hal->rf_path_num; path++) {
++              if (remnant_pre[path] != dm_info->txagc_remnant_ofdm[path]) {
++                      rtw_phy_set_tx_power_level(rtwdev,
++                                                 hal->current_channel);
++                      break;
++              }
++      }
++
++iqk:
++      if (need_iqk)
++              do_iqk(rtwdev);
++}
++EXPORT_SYMBOL(rtw88xxa_phy_pwrtrack);
++
++void rtw88xxa_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl)
++{
++      static const u8 pd[CCK_PD_LV_MAX] = {0x40, 0x83, 0xcd, 0xdd, 0xed};
++      struct rtw_dm_info *dm_info = &rtwdev->dm_info;
++
++      /* Override rtw_phy_cck_pd_lv_link(). It implements something
++       * like type 2/3/4. We need type 1 here.
++       */
++      if (rtw_is_assoc(rtwdev)) {
++              if (dm_info->min_rssi > 60) {
++                      new_lvl = CCK_PD_LV3;
++              } else if (dm_info->min_rssi > 35) {
++                      new_lvl = CCK_PD_LV2;
++              } else if (dm_info->min_rssi > 20) {
++                      if (dm_info->cck_fa_avg > 500)
++                              new_lvl = CCK_PD_LV2;
++                      else if (dm_info->cck_fa_avg < 250)
++                              new_lvl = CCK_PD_LV1;
++                      else
++                              return;
++              } else {
++                      new_lvl = CCK_PD_LV1;
++              }
++      }
++
++      rtw_dbg(rtwdev, RTW_DBG_PHY, "lv: (%d) -> (%d)\n",
++              dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A], new_lvl);
++
++      if (dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A] == new_lvl)
++              return;
++
++      dm_info->cck_fa_avg = CCK_FA_AVG_RESET;
++      dm_info->cck_pd_lv[RTW_CHANNEL_WIDTH_20][RF_PATH_A] = new_lvl;
++
++      rtw_write8(rtwdev, REG_CCK_PD_TH, pd[new_lvl]);
++}
++EXPORT_SYMBOL(rtw88xxa_phy_cck_pd_set);
++
++MODULE_AUTHOR("Realtek Corporation");
++MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821a/8811a/8812a common code");
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null
++++ b/drivers/net/wireless/realtek/rtw88/rtw88xxa.h
+@@ -0,0 +1,175 @@
++/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
++/* Copyright(c) 2024  Realtek Corporation
++ */
++
++#ifndef __RTW88XXA_H__
++#define __RTW88XXA_H__
++
++#include <asm/byteorder.h>
++#include "reg.h"
++
++struct rtw8821au_efuse {
++      u8 res4[48];                    /* 0xd0 */
++      u8 vid[2];                      /* 0x100 */
++      u8 pid[2];
++      u8 res8[3];
++      u8 mac_addr[ETH_ALEN];          /* 0x107 */
++      u8 res9[243];
++} __packed;
++
++struct rtw8812au_efuse {
++      u8 vid[2];                      /* 0xd0 */
++      u8 pid[2];                      /* 0xd2 */
++      u8 res0[3];
++      u8 mac_addr[ETH_ALEN];          /* 0xd7 */
++      u8 res1[291];
++} __packed;
++
++struct rtw88xxa_efuse {
++      __le16 rtl_id;
++      u8 res0[6];                     /* 0x02 */
++      u8 usb_mode;                    /* 0x08 */
++      u8 res1[7];                     /* 0x09 */
++
++      /* power index for four RF paths */
++      struct rtw_txpwr_idx txpwr_idx_table[4];
++
++      u8 channel_plan;                /* 0xb8 */
++      u8 xtal_k;
++      u8 thermal_meter;
++      u8 iqk_lck;
++      u8 pa_type;                     /* 0xbc */
++      u8 lna_type_2g;                 /* 0xbd */
++      u8 res2;
++      u8 lna_type_5g;                 /* 0xbf */
++      u8 res3;
++      u8 rf_board_option;             /* 0xc1 */
++      u8 rf_feature_option;
++      u8 rf_bt_setting;
++      u8 eeprom_version;
++      u8 eeprom_customer_id;          /* 0xc5 */
++      u8 tx_bb_swing_setting_2g;
++      u8 tx_bb_swing_setting_5g;
++      u8 tx_pwr_calibrate_rate;
++      u8 rf_antenna_option;           /* 0xc9 */
++      u8 rfe_option;
++      u8 country_code[2];
++      u8 res4[3];
++      union {
++              struct rtw8821au_efuse rtw8821au;
++              struct rtw8812au_efuse rtw8812au;
++      };
++} __packed;
++
++static_assert(sizeof(struct rtw88xxa_efuse) == 512);
++
++#define WLAN_BCN_DMA_TIME                     0x02
++#define WLAN_TBTT_PROHIBIT                    0x04
++#define WLAN_TBTT_HOLD_TIME                   0x064
++#define WLAN_TBTT_TIME        (WLAN_TBTT_PROHIBIT |\
++                      (WLAN_TBTT_HOLD_TIME << BIT_SHIFT_TBTT_HOLD_TIME_AP))
++
++struct rtw_jaguar_phy_status_rpt {
++      __le32 w0;
++      __le32 w1;
++      __le32 w2;
++      __le32 w3;
++      __le32 w4;
++      __le32 w5;
++      __le32 w6;
++} __packed;
++
++#define RTW_JGRPHY_W0_GAIN_A          GENMASK(6, 0)
++#define RTW_JGRPHY_W0_TRSW_A          BIT(7)
++#define RTW_JGRPHY_W0_GAIN_B          GENMASK(14, 8)
++#define RTW_JGRPHY_W0_TRSW_B          BIT(15)
++#define RTW_JGRPHY_W0_CHL_NUM         GENMASK(25, 16)
++#define RTW_JGRPHY_W0_SUB_CHNL                GENMASK(29, 26)
++#define RTW_JGRPHY_W0_R_RFMOD         GENMASK(31, 30)
++
++/* CCK: */
++#define RTW_JGRPHY_W1_SIG_QUAL                GENMASK(7, 0)
++#define RTW_JGRPHY_W1_AGC_RPT_VGA_IDX GENMASK(12, 8)
++#define RTW_JGRPHY_W1_AGC_RPT_LNA_IDX GENMASK(15, 13)
++#define RTW_JGRPHY_W1_BB_POWER                GENMASK(23, 16)
++/* OFDM: */
++#define RTW_JGRPHY_W1_PWDB_ALL                GENMASK(7, 0)
++#define RTW_JGRPHY_W1_CFO_SHORT_A     GENMASK(15, 8)  /* s8 */
++#define RTW_JGRPHY_W1_CFO_SHORT_B     GENMASK(23, 16) /* s8 */
++#define RTW_JGRPHY_W1_BT_RF_CH_MSB    GENMASK(31, 30)
++
++#define RTW_JGRPHY_W2_ANT_DIV_SW_A    BIT(0)
++#define RTW_JGRPHY_W2_ANT_DIV_SW_B    BIT(1)
++#define RTW_JGRPHY_W2_BT_RF_CH_LSB    GENMASK(7, 2)
++#define RTW_JGRPHY_W2_CFO_TAIL_A      GENMASK(15, 8)  /* s8 */
++#define RTW_JGRPHY_W2_CFO_TAIL_B      GENMASK(23, 16) /* s8 */
++#define RTW_JGRPHY_W2_PCTS_MSK_RPT_0  GENMASK(31, 24)
++
++#define RTW_JGRPHY_W3_PCTS_MSK_RPT_1  GENMASK(7, 0)
++/* Stream 1 and 2 RX EVM: */
++#define RTW_JGRPHY_W3_RXEVM_1         GENMASK(15, 8)  /* s8 */
++#define RTW_JGRPHY_W3_RXEVM_2         GENMASK(23, 16) /* s8 */
++#define RTW_JGRPHY_W3_RXSNR_A         GENMASK(31, 24) /* s8 */
++
++#define RTW_JGRPHY_W4_RXSNR_B         GENMASK(7, 0)   /* s8 */
++#define RTW_JGRPHY_W4_PCTS_MSK_RPT_2  GENMASK(21, 8)
++#define RTW_JGRPHY_W4_PCTS_RPT_VALID  BIT(22)
++#define RTW_JGRPHY_W4_RXEVM_3         GENMASK(31, 24) /* s8 */
++
++#define RTW_JGRPHY_W5_RXEVM_4         GENMASK(7, 0)   /* s8 */
++/* 8812a, stream 1 and 2 CSI: */
++#define RTW_JGRPHY_W5_CSI_CURRENT_1   GENMASK(15, 8)
++#define RTW_JGRPHY_W5_CSI_CURRENT_2   GENMASK(23, 16)
++/* 8814a: */
++#define RTW_JGRPHY_W5_RXSNR_C         GENMASK(15, 8)  /* s8 */
++#define RTW_JGRPHY_W5_RXSNR_D         GENMASK(23, 16) /* s8 */
++#define RTW_JGRPHY_W5_GAIN_C          GENMASK(30, 24)
++#define RTW_JGRPHY_W5_TRSW_C          BIT(31)
++
++#define RTW_JGRPHY_W6_GAIN_D          GENMASK(6, 0)
++#define RTW_JGRPHY_W6_TRSW_D          BIT(7)
++#define RTW_JGRPHY_W6_SIGEVM          GENMASK(15, 8)  /* s8 */
++#define RTW_JGRPHY_W6_ANTIDX_ANTC     GENMASK(18, 16)
++#define RTW_JGRPHY_W6_ANTIDX_ANTD     GENMASK(21, 19)
++#define RTW_JGRPHY_W6_DPDT_CTRL_KEEP  BIT(22)
++#define RTW_JGRPHY_W6_GNT_BT_KEEP     BIT(23)
++#define RTW_JGRPHY_W6_ANTIDX_ANTA     GENMASK(26, 24)
++#define RTW_JGRPHY_W6_ANTIDX_ANTB     GENMASK(29, 27)
++#define RTW_JGRPHY_W6_HW_ANTSW_OCCUR  GENMASK(31, 30)
++
++#define RF18_BW_MASK          (BIT(11) | BIT(10))
++
++void rtw88xxa_efuse_grant(struct rtw_dev *rtwdev, bool on);
++int rtw88xxa_read_efuse(struct rtw_dev *rtwdev, u8 *log_map);
++void rtw88xxa_power_off(struct rtw_dev *rtwdev,
++                      const struct rtw_pwr_seq_cmd *const *enter_lps_flow);
++int rtw88xxa_power_on(struct rtw_dev *rtwdev);
++u32 rtw88xxa_phy_read_rf(struct rtw_dev *rtwdev,
++                       enum rtw_rf_path rf_path, u32 addr, u32 mask);
++void rtw88xxa_set_channel(struct rtw_dev *rtwdev, u8 channel, u8 bw,
++                        u8 primary_chan_idx);
++void rtw88xxa_query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
++                             struct rtw_rx_pkt_stat *pkt_stat,
++                             s8 (*cck_rx_pwr)(u8 lna_idx, u8 vga_idx));
++void rtw88xxa_set_tx_power_index(struct rtw_dev *rtwdev);
++void rtw88xxa_false_alarm_statistics(struct rtw_dev *rtwdev);
++void rtw88xxa_iqk_backup_mac_bb(struct rtw_dev *rtwdev,
++                              u32 *macbb_backup,
++                              const u32 *backup_macbb_reg,
++                              u32 macbb_num);
++void rtw88xxa_iqk_backup_afe(struct rtw_dev *rtwdev, u32 *afe_backup,
++                           const u32 *backup_afe_reg, u32 afe_num);
++void rtw88xxa_iqk_restore_mac_bb(struct rtw_dev *rtwdev,
++                               u32 *macbb_backup,
++                               const u32 *backup_macbb_reg,
++                               u32 macbb_num);
++void rtw88xxa_iqk_configure_mac(struct rtw_dev *rtwdev);
++bool rtw88xxa_iqk_finish(int average, int threshold,
++                       int *x_temp, int *y_temp, int *x, int *y,
++                       bool break_inner, bool break_outer);
++void rtw88xxa_phy_pwrtrack(struct rtw_dev *rtwdev,
++                         void (*do_lck)(struct rtw_dev *rtwdev),
++                         void (*do_iqk)(struct rtw_dev *rtwdev));
++void rtw88xxa_phy_cck_pd_set(struct rtw_dev *rtwdev, u8 new_lvl);
++
++#endif
diff --git a/package/kernel/mac80211/patches/rtl/042-v6.13-wifi-rtw88-Add-rtw8821a.-c-h.patch b/package/kernel/mac80211/patches/rtl/042-v6.13-wifi-rtw88-Add-rtw8821a.-c-h.patch
new file mode 100644 (file)
index 0000000..dca3f7b
--- /dev/null
@@ -0,0 +1,1230 @@
+From 32e284a238806d1984ea68cda25f6b09a4053b94 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 30 Oct 2024 20:28:15 +0200
+Subject: [PATCH] wifi: rtw88: Add rtw8821a.{c,h}
+
+These contain code specific to RTL8821AU.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/37218648-ada7-4fad-b7bd-d2aee28cefb9@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/rtw8821a.c | 1197 +++++++++++++++++
+ drivers/net/wireless/realtek/rtw88/rtw8821a.h |   10 +
+ 2 files changed, 1207 insertions(+)
+ create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821a.c
+ create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821a.h
+
+--- /dev/null
++++ b/drivers/net/wireless/realtek/rtw88/rtw8821a.c
+@@ -0,0 +1,1197 @@
++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
++/* Copyright(c) 2024  Realtek Corporation
++ */
++
++#include "main.h"
++#include "coex.h"
++#include "phy.h"
++#include "reg.h"
++#include "rtw88xxa.h"
++#include "rtw8821a.h"
++#include "rtw8821a_table.h"
++#include "tx.h"
++
++static void rtw8821a_power_off(struct rtw_dev *rtwdev)
++{
++      rtw88xxa_power_off(rtwdev, enter_lps_flow_8821a);
++}
++
++static s8 rtw8821a_cck_rx_pwr(u8 lna_idx, u8 vga_idx)
++{
++      static const s8 lna_gain_table[] = {15, -1, -17, 0, -30, -38};
++      s8 rx_pwr_all = 0;
++      s8 lna_gain;
++
++      switch (lna_idx) {
++      case 5:
++      case 4:
++      case 2:
++      case 1:
++      case 0:
++              lna_gain = lna_gain_table[lna_idx];
++              rx_pwr_all = lna_gain - 2 * vga_idx;
++              break;
++      default:
++              break;
++      }
++
++      return rx_pwr_all;
++}
++
++static void rtw8821a_query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
++                                    struct rtw_rx_pkt_stat *pkt_stat)
++{
++      rtw88xxa_query_phy_status(rtwdev, phy_status, pkt_stat,
++                                rtw8821a_cck_rx_pwr);
++}
++
++static void rtw8821a_cfg_ldo25(struct rtw_dev *rtwdev, bool enable)
++{
++}
++
++#define CAL_NUM_8821A 3
++#define MACBB_REG_NUM_8821A 8
++#define AFE_REG_NUM_8821A 4
++#define RF_REG_NUM_8821A 3
++
++static void rtw8821a_iqk_backup_rf(struct rtw_dev *rtwdev, u32 *rfa_backup,
++                                 const u32 *backup_rf_reg, u32 rf_num)
++{
++      u32 i;
++
++      /* [31] = 0 --> Page C */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++
++      /* Save RF Parameters */
++      for (i = 0; i < rf_num; i++)
++              rfa_backup[i] = rtw_read_rf(rtwdev, RF_PATH_A,
++                                          backup_rf_reg[i], MASKDWORD);
++}
++
++static void rtw8821a_iqk_restore_rf(struct rtw_dev *rtwdev,
++                                  const u32 *backup_rf_reg,
++                                  u32 *RF_backup, u32 rf_reg_num)
++{
++      u32 i;
++
++      /* [31] = 0 --> Page C */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++
++      for (i = 0; i < rf_reg_num; i++)
++              rtw_write_rf(rtwdev, RF_PATH_A, backup_rf_reg[i],
++                           RFREG_MASK, RF_backup[i]);
++}
++
++static void rtw8821a_iqk_restore_afe(struct rtw_dev *rtwdev, u32 *afe_backup,
++                                   const u32 *backup_afe_reg, u32 afe_num)
++{
++      u32 i;
++
++      /* [31] = 0 --> Page C */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++
++      /* Reload AFE Parameters */
++      for (i = 0; i < afe_num; i++)
++              rtw_write32(rtwdev, backup_afe_reg[i], afe_backup[i]);
++
++      /* [31] = 1 --> Page C1 */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
++
++      rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x0);
++      rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x0);
++      rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x0);
++      rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x3c000000);
++      rtw_write32(rtwdev, REG_LSSI_WRITE_A, 0x00000080);
++      rtw_write32(rtwdev, REG_TXAGCIDX, 0x00000000);
++      rtw_write32(rtwdev, REG_IQK_DPD_CFG, 0x20040000);
++      rtw_write32(rtwdev, REG_CFG_PMPD, 0x20000000);
++      rtw_write32(rtwdev, REG_RFECTL_A, 0x0);
++}
++
++static void rtw8821a_iqk_rx_fill(struct rtw_dev *rtwdev,
++                               unsigned int rx_x, unsigned int rx_y)
++{
++      /* [31] = 0 --> Page C */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++
++      rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A,
++                       0x000003ff, rx_x >> 1);
++      rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A,
++                       0x03ff0000, (rx_y >> 1) & 0x3ff);
++}
++
++static void rtw8821a_iqk_tx_fill(struct rtw_dev *rtwdev,
++                               unsigned int tx_x, unsigned int tx_y)
++{
++      /* [31] = 1 --> Page C1 */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
++
++      rtw_write32(rtwdev, REG_LSSI_WRITE_A, 0x00000080);
++      rtw_write32(rtwdev, REG_IQK_DPD_CFG, 0x20040000);
++      rtw_write32(rtwdev, REG_CFG_PMPD, 0x20000000);
++      rtw_write32_mask(rtwdev, REG_IQC_Y, 0x000007ff, tx_y);
++      rtw_write32_mask(rtwdev, REG_IQC_X, 0x000007ff, tx_x);
++}
++
++static void rtw8821a_iqk_tx_vdf_true(struct rtw_dev *rtwdev, u32 cal,
++                                   bool *tx0iqkok,
++                                   int tx_x0[CAL_NUM_8821A],
++                                   int tx_y0[CAL_NUM_8821A])
++{
++      u32 cal_retry, delay_count, iqk_ready, tx_fail;
++      int tx_dt[3], vdf_y[3], vdf_x[3];
++      int k;
++
++      for (k = 0; k < 3; k++) {
++              switch (k) {
++              case 0:
++                      /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */
++                      rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE,
++                                  0x18008c38);
++                      /* RX_Tone_idx[9:0], RxK_Mask[29] */
++                      rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x38008c38);
++                      rtw_write32_mask(rtwdev, REG_INTPO_SETA, BIT(31), 0x0);
++                      break;
++              case 1:
++                      rtw_write32_mask(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE,
++                                       BIT(28), 0x0);
++                      rtw_write32_mask(rtwdev, REG_OFDM0_A_TX_AFE,
++                                       BIT(28), 0x0);
++                      rtw_write32_mask(rtwdev, REG_INTPO_SETA, BIT(31), 0x0);
++                      break;
++              case 2:
++                      rtw_dbg(rtwdev, RTW_DBG_RFK,
++                              "vdf_y[1] = %x vdf_y[0] = %x\n",
++                              vdf_y[1] >> 21 & 0x00007ff,
++                              vdf_y[0] >> 21 & 0x00007ff);
++
++                      rtw_dbg(rtwdev, RTW_DBG_RFK,
++                              "vdf_x[1] = %x vdf_x[0] = %x\n",
++                              vdf_x[1] >> 21 & 0x00007ff,
++                              vdf_x[0] >> 21 & 0x00007ff);
++
++                      tx_dt[cal] = (vdf_y[1] >> 20) - (vdf_y[0] >> 20);
++                      tx_dt[cal] = (16 * tx_dt[cal]) * 10000 / 15708;
++                      tx_dt[cal] = (tx_dt[cal] >> 1) + (tx_dt[cal] & BIT(0));
++
++                      /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */
++                      rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE,
++                                  0x18008c20);
++                      /* RX_Tone_idx[9:0], RxK_Mask[29] */
++                      rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x38008c20);
++                      rtw_write32_mask(rtwdev, REG_INTPO_SETA, BIT(31), 0x1);
++                      rtw_write32_mask(rtwdev, REG_INTPO_SETA, 0x3fff0000,
++                                       tx_dt[cal] & 0x00003fff);
++                      break;
++              }
++
++              rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000);
++
++              for (cal_retry = 0; cal_retry < 10; cal_retry++) {
++                      /* one shot */
++                      rtw_write32(rtwdev, REG_IQK_COM64, 0xfa000000);
++                      rtw_write32(rtwdev, REG_IQK_COM64, 0xf8000000);
++
++                      mdelay(10);
++
++                      rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000);
++
++                      for (delay_count = 0; delay_count < 20; delay_count++) {
++                              iqk_ready = rtw_read32_mask(rtwdev,
++                                                          REG_IQKA_END,
++                                                          BIT(10));
++
++                              /* Originally: if (~iqk_ready || delay_count > 20)
++                               * that looks like a typo so make it more explicit
++                               */
++                              iqk_ready = true;
++
++                              if (iqk_ready)
++                                      break;
++
++                              mdelay(1);
++                      }
++
++                      if (delay_count < 20) {
++                              /* ============TXIQK Check============== */
++                              tx_fail = rtw_read32_mask(rtwdev,
++                                                        REG_IQKA_END,
++                                                        BIT(12));
++
++                              /* Originally: if (~tx_fail) {
++                               * It looks like a typo, so make it more explicit.
++                               */
++                              tx_fail = false;
++
++                              if (!tx_fail) {
++                                      rtw_write32(rtwdev, REG_RFECTL_A,
++                                                  0x02000000);
++                                      vdf_x[k] = rtw_read32_mask(rtwdev,
++                                                                 REG_IQKA_END,
++                                                                 0x07ff0000);
++                                      vdf_x[k] <<= 21;
++
++                                      rtw_write32(rtwdev, REG_RFECTL_A,
++                                                  0x04000000);
++                                      vdf_y[k] = rtw_read32_mask(rtwdev,
++                                                                 REG_IQKA_END,
++                                                                 0x07ff0000);
++                                      vdf_y[k] <<= 21;
++
++                                      *tx0iqkok = true;
++                                      break;
++                              }
++
++                              rtw_write32_mask(rtwdev, REG_IQC_Y,
++                                               0x000007ff, 0x0);
++                              rtw_write32_mask(rtwdev, REG_IQC_X,
++                                               0x000007ff, 0x200);
++                      }
++
++                      *tx0iqkok = false;
++              }
++      }
++
++      if (k == 3) {
++              tx_x0[cal] = vdf_x[k - 1];
++              tx_y0[cal] = vdf_y[k - 1];
++      }
++}
++
++static void rtw8821a_iqk_tx_vdf_false(struct rtw_dev *rtwdev, u32 cal,
++                                    bool *tx0iqkok,
++                                    int tx_x0[CAL_NUM_8821A],
++                                    int tx_y0[CAL_NUM_8821A])
++{
++      u32 cal_retry, delay_count, iqk_ready, tx_fail;
++
++      /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */
++      rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x18008c10);
++      /* RX_Tone_idx[9:0], RxK_Mask[29] */
++      rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x38008c10);
++      rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000);
++
++      for (cal_retry = 0; cal_retry < 10; cal_retry++) {
++              /* one shot */
++              rtw_write32(rtwdev, REG_IQK_COM64, 0xfa000000);
++              rtw_write32(rtwdev, REG_IQK_COM64, 0xf8000000);
++
++              mdelay(10);
++              rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000);
++
++              for (delay_count = 0; delay_count < 20; delay_count++) {
++                      iqk_ready = rtw_read32_mask(rtwdev, REG_IQKA_END, BIT(10));
++
++                      /* Originally: if (~iqk_ready || delay_count > 20)
++                       * that looks like a typo so make it more explicit
++                       */
++                      iqk_ready = true;
++
++                      if (iqk_ready)
++                              break;
++
++                      mdelay(1);
++              }
++
++              if (delay_count < 20) {
++                      /* ============TXIQK Check============== */
++                      tx_fail = rtw_read32_mask(rtwdev, REG_IQKA_END, BIT(12));
++
++                      /* Originally: if (~tx_fail) {
++                       * It looks like a typo, so make it more explicit.
++                       */
++                      tx_fail = false;
++
++                      if (!tx_fail) {
++                              rtw_write32(rtwdev, REG_RFECTL_A, 0x02000000);
++                              tx_x0[cal] = rtw_read32_mask(rtwdev, REG_IQKA_END,
++                                                           0x07ff0000);
++                              tx_x0[cal] <<= 21;
++
++                              rtw_write32(rtwdev, REG_RFECTL_A, 0x04000000);
++                              tx_y0[cal] = rtw_read32_mask(rtwdev, REG_IQKA_END,
++                                                           0x07ff0000);
++                              tx_y0[cal] <<= 21;
++
++                              *tx0iqkok = true;
++                              break;
++                      }
++
++                      rtw_write32_mask(rtwdev, REG_IQC_Y, 0x000007ff, 0x0);
++                      rtw_write32_mask(rtwdev, REG_IQC_X, 0x000007ff, 0x200);
++              }
++
++              *tx0iqkok = false;
++      }
++}
++
++static void rtw8821a_iqk_rx(struct rtw_dev *rtwdev, u32 cal, bool *rx0iqkok,
++                          int rx_x0[CAL_NUM_8821A],
++                          int rx_y0[CAL_NUM_8821A])
++{
++      u32 cal_retry, delay_count, iqk_ready, rx_fail;
++
++      rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000);
++
++      for (cal_retry = 0; cal_retry < 10; cal_retry++) {
++              /* one shot */
++              rtw_write32(rtwdev, REG_IQK_COM64, 0xfa000000);
++              rtw_write32(rtwdev, REG_IQK_COM64, 0xf8000000);
++
++              mdelay(10);
++
++              rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000);
++
++              for (delay_count = 0; delay_count < 20; delay_count++) {
++                      iqk_ready = rtw_read32_mask(rtwdev, REG_IQKA_END, BIT(10));
++
++                      /* Originally: if (~iqk_ready || delay_count > 20)
++                       * that looks like a typo so make it more explicit
++                       */
++                      iqk_ready = true;
++
++                      if (iqk_ready)
++                              break;
++
++                      mdelay(1);
++              }
++
++              if (delay_count < 20) {
++                      /* ============RXIQK Check============== */
++                      rx_fail = rtw_read32_mask(rtwdev, REG_IQKA_END, BIT(11));
++                      if (!rx_fail) {
++                              rtw_write32(rtwdev, REG_RFECTL_A, 0x06000000);
++                              rx_x0[cal] = rtw_read32_mask(rtwdev, REG_IQKA_END,
++                                                           0x07ff0000);
++                              rx_x0[cal] <<= 21;
++
++                              rtw_write32(rtwdev, REG_RFECTL_A, 0x08000000);
++                              rx_y0[cal] = rtw_read32_mask(rtwdev, REG_IQKA_END,
++                                                           0x07ff0000);
++                              rx_y0[cal] <<= 21;
++
++                              *rx0iqkok = true;
++                              break;
++                      }
++
++                      rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A,
++                                       0x000003ff, 0x200 >> 1);
++                      rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A,
++                                       0x03ff0000, 0x0 >> 1);
++              }
++
++              *rx0iqkok = false;
++      }
++}
++
++static void rtw8821a_iqk(struct rtw_dev *rtwdev)
++{
++      int tx_average = 0, rx_average = 0, rx_iqk_loop = 0;
++      const struct rtw_efuse *efuse = &rtwdev->efuse;
++      int tx_x = 0, tx_y = 0, rx_x = 0, rx_y = 0;
++      const struct rtw_hal *hal = &rtwdev->hal;
++      bool tx0iqkok = false, rx0iqkok = false;
++      int rx_x_temp = 0, rx_y_temp = 0;
++      int rx_x0[2][CAL_NUM_8821A];
++      int rx_y0[2][CAL_NUM_8821A];
++      int tx_x0[CAL_NUM_8821A];
++      int tx_y0[CAL_NUM_8821A];
++      bool rx_finish1 = false;
++      bool rx_finish2 = false;
++      bool vdf_enable;
++      u32 cal;
++      int i;
++
++      rtw_dbg(rtwdev, RTW_DBG_RFK,
++              "band_width = %d, ext_pa = %d, ext_pa_5g = %d\n",
++              hal->current_band_width, efuse->ext_pa_2g, efuse->ext_pa_5g);
++
++      vdf_enable = hal->current_band_width == RTW_CHANNEL_WIDTH_80;
++
++      for (cal = 0; cal < CAL_NUM_8821A; cal++) {
++              /* path-A LOK */
++
++              /* [31] = 0 --> Page C */
++              rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++
++              /* ========path-A AFE all on======== */
++              /* Port 0 DAC/ADC on */
++              rtw_write32(rtwdev, REG_AFE_PWR1_A, 0x77777777);
++              rtw_write32(rtwdev, REG_AFE_PWR2_A, 0x77777777);
++
++              rtw_write32(rtwdev, REG_RX_WAIT_CCA_TX_CCK_RFON_A, 0x19791979);
++
++              /* hardware 3-wire off */
++              rtw_write32_mask(rtwdev, REG_3WIRE_SWA, 0xf, 0x4);
++
++              /* LOK setting */
++
++              /* 1. DAC/ADC sampling rate (160 MHz) */
++              rtw_write32_mask(rtwdev, REG_CK_MONHA, GENMASK(26, 24), 0x7);
++
++              /* 2. LoK RF setting (at BW = 20M) */
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x80002);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, 0x00c00, 0x3);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_ADDR, RFREG_MASK,
++                           0x20000);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA0, RFREG_MASK,
++                           0x0003f);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA1, RFREG_MASK,
++                           0xf3fc3);
++
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_TXA_PREPAD, RFREG_MASK,
++                           0x931d5);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_RXBB2, RFREG_MASK, 0x8a001);
++              rtw_write32(rtwdev, REG_DAC_RSTB, 0x00008000);
++              rtw_write32_mask(rtwdev, REG_TXAGCIDX, BIT(0), 0x1);
++              /* TX (X,Y) */
++              rtw_write32(rtwdev, REG_IQK_COM00, 0x29002000);
++              /* RX (X,Y) */
++              rtw_write32(rtwdev, REG_IQK_COM32, 0xa9002000);
++              /* [0]:AGC_en, [15]:idac_K_Mask */
++              rtw_write32(rtwdev, REG_IQK_COM96, 0x00462910);
++
++              /* [31] = 1 --> Page C1 */
++              rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
++
++              if (efuse->ext_pa_5g)
++                      rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE,
++                                  0x821403f7);
++              else
++                      rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE,
++                                  0x821403f4);
++
++              if (hal->current_band_type == RTW_BAND_5G)
++                      rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x68163e96);
++              else
++                      rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x28163e96);
++
++              /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */
++              rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x18008c10);
++              /* RX_Tone_idx[9:0], RxK_Mask[29] */
++              rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x38008c10);
++              rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000);
++              rtw_write32(rtwdev, REG_IQK_COM64, 0xfa000000);
++              rtw_write32(rtwdev, REG_IQK_COM64, 0xf8000000);
++
++              mdelay(10);
++              rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000);
++
++              /* [31] = 0 --> Page C */
++              rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_TXMOD, 0x7fe00,
++                           rtw_read_rf(rtwdev, RF_PATH_A, RF_DTXLOK, 0xffc00));
++
++              if (hal->current_band_width == RTW_CHANNEL_WIDTH_40)
++                      rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH,
++                                   RF18_BW_MASK, 0x1);
++              else if (hal->current_band_width == RTW_CHANNEL_WIDTH_80)
++                      rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH,
++                                   RF18_BW_MASK, 0x0);
++
++              /* [31] = 1 --> Page C1 */
++              rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
++
++              /* 3. TX RF setting */
++              /* [31] = 0 --> Page C */
++              rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x80000);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_ADDR, RFREG_MASK,
++                           0x20000);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA0, RFREG_MASK,
++                           0x0003f);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA1, RFREG_MASK,
++                           0xf3fc3);
++
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_TXA_PREPAD, RFREG_MASK, 0x931d5);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_RXBB2, RFREG_MASK, 0x8a001);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x00000);
++              rtw_write32(rtwdev, REG_DAC_RSTB, 0x00008000);
++              rtw_write32_mask(rtwdev, REG_TXAGCIDX, BIT(0), 0x1);
++              /* TX (X,Y) */
++              rtw_write32(rtwdev, REG_IQK_COM00, 0x29002000);
++              /* RX (X,Y) */
++              rtw_write32(rtwdev, REG_IQK_COM32, 0xa9002000);
++              /* [0]:AGC_en, [15]:idac_K_Mask */
++              rtw_write32(rtwdev, REG_IQK_COM96, 0x0046a910);
++
++              /* [31] = 1 --> Page C1 */
++              rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
++
++              if (efuse->ext_pa_5g)
++                      rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE,
++                                  0x821403f7);
++              else
++                      rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE,
++                                  0x821403e3);
++
++              if (hal->current_band_type == RTW_BAND_5G)
++                      rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x40163e96);
++              else
++                      rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x00163e96);
++
++              if (vdf_enable)
++                      rtw8821a_iqk_tx_vdf_true(rtwdev, cal, &tx0iqkok,
++                                               tx_x0, tx_y0);
++              else
++                      rtw8821a_iqk_tx_vdf_false(rtwdev, cal, &tx0iqkok,
++                                                tx_x0, tx_y0);
++
++              if (!tx0iqkok)
++                      break; /* TXK fail, Don't do RXK */
++
++              /* ====== RX IQK ====== */
++              /* [31] = 0 --> Page C */
++              rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++              /* 1. RX RF setting */
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x80000);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_ADDR, RFREG_MASK,
++                           0x30000);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA0, RFREG_MASK,
++                           0x0002f);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA1, RFREG_MASK,
++                           0xfffbb);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_RXBB2, RFREG_MASK, 0x88001);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_TXA_PREPAD, RFREG_MASK, 0x931d8);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x00000);
++
++              rtw_write32_mask(rtwdev, REG_IQK_COM00, 0x03FF8000,
++                               (tx_x0[cal] >> 21) & 0x000007ff);
++              rtw_write32_mask(rtwdev, REG_IQK_COM00, 0x000007FF,
++                               (tx_y0[cal] >> 21) & 0x000007ff);
++              rtw_write32_mask(rtwdev, REG_IQK_COM00, BIT(31), 0x1);
++              rtw_write32_mask(rtwdev, REG_IQK_COM00, BIT(31), 0x0);
++              rtw_write32(rtwdev, REG_DAC_RSTB, 0x00008000);
++              rtw_write32(rtwdev, REG_IQK_COM96, 0x0046a911);
++
++              /* [31] = 1 --> Page C1 */
++              rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
++
++              /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */
++              rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x38008c10);
++              /* RX_Tone_idx[9:0], RxK_Mask[29] */
++              rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x18008c10);
++              rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x02140119);
++
++              if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE)
++                      rx_iqk_loop = 2; /* for 2% fail; */
++              else
++                      rx_iqk_loop = 1;
++
++              for (i = 0; i < rx_iqk_loop; i++) {
++                      if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE && i == 0)
++                              rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x28161100); /* Good */
++                      else
++                              rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x28160d00);
++
++                      rtw8821a_iqk_rx(rtwdev, cal, &rx0iqkok,
++                                      rx_x0[i], rx_y0[i]);
++              }
++
++              if (tx0iqkok)
++                      tx_average++;
++              if (rx0iqkok)
++                      rx_average++;
++      }
++
++      /* FillIQK Result */
++
++      if (tx_average == 0)
++              return;
++
++      for (i = 0; i < tx_average; i++)
++              rtw_dbg(rtwdev, RTW_DBG_RFK,
++                      "tx_x0[%d] = %x ;; tx_y0[%d] = %x\n",
++                      i, (tx_x0[i] >> 21) & 0x000007ff,
++                      i, (tx_y0[i] >> 21) & 0x000007ff);
++
++      if (rtw88xxa_iqk_finish(tx_average, 3, tx_x0, tx_y0,
++                              &tx_x, &tx_y, true, true))
++              rtw8821a_iqk_tx_fill(rtwdev, tx_x, tx_y);
++      else
++              rtw8821a_iqk_tx_fill(rtwdev, 0x200, 0x0);
++
++      if (rx_average == 0)
++              return;
++
++      for (i = 0; i < rx_average; i++) {
++              rtw_dbg(rtwdev, RTW_DBG_RFK,
++                      "rx_x0[0][%d] = %x ;; rx_y0[0][%d] = %x\n",
++                      i, (rx_x0[0][i] >> 21) & 0x000007ff,
++                      i, (rx_y0[0][i] >> 21) & 0x000007ff);
++
++              if (rx_iqk_loop == 2)
++                      rtw_dbg(rtwdev, RTW_DBG_RFK,
++                              "rx_x0[1][%d] = %x ;; rx_y0[1][%d] = %x\n",
++                              i, (rx_x0[1][i] >> 21) & 0x000007ff,
++                              i, (rx_y0[1][i] >> 21) & 0x000007ff);
++      }
++
++      rx_finish1 = rtw88xxa_iqk_finish(rx_average, 4, rx_x0[0], rx_y0[0],
++                                       &rx_x_temp, &rx_y_temp, true, true);
++
++      if (rx_finish1) {
++              rx_x = rx_x_temp;
++              rx_y = rx_y_temp;
++      }
++
++      if (rx_iqk_loop == 2) {
++              rx_finish2 = rtw88xxa_iqk_finish(rx_average, 4,
++                                               rx_x0[1], rx_y0[1],
++                                               &rx_x, &rx_y, true, true);
++
++              if (rx_finish1 && rx_finish2) {
++                      rx_x = (rx_x + rx_x_temp) / 2;
++                      rx_y = (rx_y + rx_y_temp) / 2;
++              }
++      }
++
++      if (rx_finish1 || rx_finish2)
++              rtw8821a_iqk_rx_fill(rtwdev, rx_x, rx_y);
++      else
++              rtw8821a_iqk_rx_fill(rtwdev, 0x200, 0x0);
++}
++
++static void rtw8821a_do_iqk(struct rtw_dev *rtwdev)
++{
++      static const u32 backup_macbb_reg[MACBB_REG_NUM_8821A] = {
++              0x520, 0x550, 0x808, 0xa04, 0x90c, 0xc00, 0x838, 0x82c
++      };
++      static const u32 backup_afe_reg[AFE_REG_NUM_8821A] = {
++              0xc5c, 0xc60, 0xc64, 0xc68
++      };
++      static const u32 backup_rf_reg[RF_REG_NUM_8821A] = {
++              0x65, 0x8f, 0x0
++      };
++      u32 macbb_backup[MACBB_REG_NUM_8821A];
++      u32 afe_backup[AFE_REG_NUM_8821A];
++      u32 rfa_backup[RF_REG_NUM_8821A];
++
++      rtw88xxa_iqk_backup_mac_bb(rtwdev, macbb_backup,
++                                 backup_macbb_reg, MACBB_REG_NUM_8821A);
++      rtw88xxa_iqk_backup_afe(rtwdev, afe_backup,
++                              backup_afe_reg, AFE_REG_NUM_8821A);
++      rtw8821a_iqk_backup_rf(rtwdev, rfa_backup,
++                             backup_rf_reg, RF_REG_NUM_8821A);
++
++      rtw88xxa_iqk_configure_mac(rtwdev);
++
++      rtw8821a_iqk(rtwdev);
++
++      rtw8821a_iqk_restore_rf(rtwdev, backup_rf_reg,
++                              rfa_backup, RF_REG_NUM_8821A);
++      rtw8821a_iqk_restore_afe(rtwdev, afe_backup,
++                               backup_afe_reg, AFE_REG_NUM_8821A);
++      rtw88xxa_iqk_restore_mac_bb(rtwdev, macbb_backup,
++                                  backup_macbb_reg, MACBB_REG_NUM_8821A);
++}
++
++static void rtw8821a_phy_calibration(struct rtw_dev *rtwdev)
++{
++      rtw8821a_do_iqk(rtwdev);
++}
++
++static void rtw8821a_pwr_track(struct rtw_dev *rtwdev)
++{
++      struct rtw_dm_info *dm_info = &rtwdev->dm_info;
++
++      if (!dm_info->pwr_trk_triggered) {
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_T_METER,
++                           GENMASK(17, 16), 0x03);
++              dm_info->pwr_trk_triggered = true;
++              return;
++      }
++
++      rtw88xxa_phy_pwrtrack(rtwdev, NULL, rtw8821a_do_iqk);
++      dm_info->pwr_trk_triggered = false;
++}
++
++static void rtw8821a_fill_txdesc_checksum(struct rtw_dev *rtwdev,
++                                        struct rtw_tx_pkt_info *pkt_info,
++                                        u8 *txdesc)
++{
++      fill_txdesc_checksum_common(txdesc, 16);
++}
++
++static void rtw8821a_coex_cfg_init(struct rtw_dev *rtwdev)
++{
++      u8 val8;
++
++      /* BT report packet sample rate */
++      rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, BIT_MASK_SAMPLE_RATE, 0x5);
++
++      val8 = BIT_STATIS_BT_EN;
++      if (rtwdev->efuse.share_ant)
++              val8 |= BIT_R_GRANTALL_WLMASK;
++      rtw_write8(rtwdev, REG_BT_COEX_ENH_INTR_CTRL, val8);
++
++      /* enable BT counter statistics */
++      rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x3);
++
++      /* enable PTA */
++      rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN);
++}
++
++static void rtw8821a_coex_cfg_ant_switch(struct rtw_dev *rtwdev, u8 ctrl_type,
++                                       u8 pos_type)
++{
++      bool share_ant = rtwdev->efuse.share_ant;
++      struct rtw_coex *coex = &rtwdev->coex;
++      struct rtw_coex_dm *coex_dm = &coex->dm;
++      u32 phase = coex_dm->cur_ant_pos_type;
++
++      if (!rtwdev->efuse.btcoex)
++              return;
++
++      switch (phase) {
++      case COEX_SET_ANT_POWERON:
++      case COEX_SET_ANT_INIT:
++              rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN);
++              rtw_write32_set(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL);
++              rtw_write8_set(rtwdev, REG_GNT_BT, BIT_PTA_SW_CTL);
++
++              rtw_write8(rtwdev, REG_RFE_CTRL8,
++                         share_ant ? PTA_CTRL_PIN : DPDT_CTRL_PIN);
++              rtw_write32_mask(rtwdev, REG_RFE_CTRL8, 0x30000000, 0x1);
++              break;
++      case COEX_SET_ANT_WONLY:
++              rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN);
++              rtw_write32_set(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL);
++              rtw_write8_clr(rtwdev, REG_GNT_BT, BIT_PTA_SW_CTL);
++
++              rtw_write8(rtwdev, REG_RFE_CTRL8, DPDT_CTRL_PIN);
++              rtw_write32_mask(rtwdev, REG_RFE_CTRL8, 0x30000000, 0x1);
++              break;
++      case COEX_SET_ANT_2G:
++              rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN);
++              rtw_write32_set(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL);
++              rtw_write8_clr(rtwdev, REG_GNT_BT, BIT_PTA_SW_CTL);
++
++              rtw_write8(rtwdev, REG_RFE_CTRL8,
++                         share_ant ? PTA_CTRL_PIN : DPDT_CTRL_PIN);
++              rtw_write32_mask(rtwdev, REG_RFE_CTRL8, 0x30000000, 0x1);
++              break;
++      case COEX_SET_ANT_5G:
++              rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN);
++              rtw_write32_set(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL);
++              rtw_write8_set(rtwdev, REG_GNT_BT, BIT_PTA_SW_CTL);
++
++              rtw_write8(rtwdev, REG_RFE_CTRL8, DPDT_CTRL_PIN);
++              rtw_write32_mask(rtwdev, REG_RFE_CTRL8, 0x30000000,
++                               share_ant ? 0x2 : 0x1);
++              break;
++      case COEX_SET_ANT_WOFF:
++              rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_SEL_EN);
++              rtw_write32_clr(rtwdev, REG_LED_CFG, BIT_DPDT_WL_SEL);
++              rtw_write8_set(rtwdev, REG_GNT_BT, BIT_PTA_SW_CTL);
++
++              rtw_write8(rtwdev, REG_RFE_CTRL8, DPDT_CTRL_PIN);
++              rtw_write32_mask(rtwdev, REG_RFE_CTRL8, 0x30000000,
++                               share_ant ? 0x2 : 0x1);
++              break;
++      default:
++              rtw_warn(rtwdev, "%s: not handling phase %d\n",
++                       __func__, phase);
++              break;
++      }
++}
++
++static void rtw8821a_coex_cfg_gnt_fix(struct rtw_dev *rtwdev)
++{
++}
++
++static void rtw8821a_coex_cfg_gnt_debug(struct rtw_dev *rtwdev)
++{
++}
++
++static void rtw8821a_coex_cfg_rfe_type(struct rtw_dev *rtwdev)
++{
++      struct rtw_coex *coex = &rtwdev->coex;
++      struct rtw_coex_rfe *coex_rfe = &coex->rfe;
++
++      coex_rfe->ant_switch_exist = true;
++}
++
++static void rtw8821a_coex_cfg_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr)
++{
++      struct rtw_coex *coex = &rtwdev->coex;
++      struct rtw_coex_dm *coex_dm = &coex->dm;
++      struct rtw_efuse *efuse = &rtwdev->efuse;
++      bool share_ant = efuse->share_ant;
++
++      if (share_ant)
++              return;
++
++      if (wl_pwr == coex_dm->cur_wl_pwr_lvl)
++              return;
++
++      coex_dm->cur_wl_pwr_lvl = wl_pwr;
++}
++
++static void rtw8821a_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)
++{
++}
++
++static const struct rtw_chip_ops rtw8821a_ops = {
++      .power_on               = rtw88xxa_power_on,
++      .power_off              = rtw8821a_power_off,
++      .phy_set_param          = NULL,
++      .read_efuse             = rtw88xxa_read_efuse,
++      .query_phy_status       = rtw8821a_query_phy_status,
++      .set_channel            = rtw88xxa_set_channel,
++      .mac_init               = NULL,
++      .read_rf                = rtw88xxa_phy_read_rf,
++      .write_rf               = rtw_phy_write_rf_reg_sipi,
++      .set_antenna            = NULL,
++      .set_tx_power_index     = rtw88xxa_set_tx_power_index,
++      .cfg_ldo25              = rtw8821a_cfg_ldo25,
++      .efuse_grant            = rtw88xxa_efuse_grant,
++      .false_alarm_statistics = rtw88xxa_false_alarm_statistics,
++      .phy_calibration        = rtw8821a_phy_calibration,
++      .cck_pd_set             = rtw88xxa_phy_cck_pd_set,
++      .pwr_track              = rtw8821a_pwr_track,
++      .config_bfee            = NULL,
++      .set_gid_table          = NULL,
++      .cfg_csi_rate           = NULL,
++      .fill_txdesc_checksum   = rtw8821a_fill_txdesc_checksum,
++      .coex_set_init          = rtw8821a_coex_cfg_init,
++      .coex_set_ant_switch    = rtw8821a_coex_cfg_ant_switch,
++      .coex_set_gnt_fix       = rtw8821a_coex_cfg_gnt_fix,
++      .coex_set_gnt_debug     = rtw8821a_coex_cfg_gnt_debug,
++      .coex_set_rfe_type      = rtw8821a_coex_cfg_rfe_type,
++      .coex_set_wl_tx_power   = rtw8821a_coex_cfg_wl_tx_power,
++      .coex_set_wl_rx_gain    = rtw8821a_coex_cfg_wl_rx_gain,
++};
++
++static const struct rtw_page_table page_table_8821a[] = {
++      /* hq_num, nq_num, lq_num, exq_num, gapq_num */
++      {0, 0, 0, 0, 0},        /* SDIO */
++      {0, 0, 0, 0, 0},        /* PCI */
++      {8, 0, 0, 0, 1},        /* 2 bulk out endpoints */
++      {8, 0, 8, 0, 1},        /* 3 bulk out endpoints */
++      {8, 0, 8, 4, 1},        /* 4 bulk out endpoints */
++};
++
++static const struct rtw_rqpn rqpn_table_8821a[] = {
++      {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
++       RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
++       RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
++
++      {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
++       RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
++       RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
++
++      {RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH,
++       RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
++       RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH},
++
++      {RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_NORMAL,
++       RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
++       RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH},
++
++      {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
++       RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
++       RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
++};
++
++static const struct rtw_prioq_addrs prioq_addrs_8821a = {
++      .prio[RTW_DMA_MAPPING_EXTRA] = {
++              .rsvd = REG_RQPN_NPQ + 2, .avail = REG_RQPN_NPQ + 3,
++      },
++      .prio[RTW_DMA_MAPPING_LOW] = {
++              .rsvd = REG_RQPN + 1, .avail = REG_FIFOPAGE_CTRL_2 + 1,
++      },
++      .prio[RTW_DMA_MAPPING_NORMAL] = {
++              .rsvd = REG_RQPN_NPQ, .avail = REG_RQPN_NPQ + 1,
++      },
++      .prio[RTW_DMA_MAPPING_HIGH] = {
++              .rsvd = REG_RQPN, .avail = REG_FIFOPAGE_CTRL_2,
++      },
++      .wsize = false,
++};
++
++static const struct rtw_hw_reg rtw8821a_dig[] = {
++      [0] = { .addr = REG_RXIGI_A, .mask = 0x7f },
++};
++
++static const struct rtw_rfe_def rtw8821a_rfe_defs[] = {
++      [0] = { .phy_pg_tbl     = &rtw8821a_bb_pg_tbl,
++              .txpwr_lmt_tbl  = &rtw8821a_txpwr_lmt_tbl,
++              .pwr_track_tbl  = &rtw8821a_rtw_pwr_track_tbl, },
++};
++
++/* TODO */
++/* rssi in percentage % (dbm = % - 100) */
++static const u8 wl_rssi_step_8821a[] = {101, 45, 101, 40};
++static const u8 bt_rssi_step_8821a[] = {101, 101, 101, 101};
++
++/* table_sant_8821a, table_nsant_8821a, tdma_sant_8821a, and tdma_nsant_8821a
++ * are copied from rtw8821c.c because the 8821au driver's tables are not
++ * compatible with the coex code in rtw88.
++ *
++ * tdma case 112 (A2DP) byte 0 had to be modified from 0x61 to 0x51,
++ * otherwise the firmware gets confused after pausing the music:
++ * rtw_8821au 1-2:1.2: [BTCoex], Bt_info[1], len=7, data=[81 00 0a 01 00 00]
++ * - 81 means PAN (personal area network) when it should be 4x (A2DP)
++ * The music is not smooth with the PAN algorithm.
++ */
++
++/* Shared-Antenna Coex Table */
++static const struct coex_table_para table_sant_8821a[] = {
++      {0x55555555, 0x55555555}, /* case-0 */
++      {0x55555555, 0x55555555},
++      {0x66555555, 0x66555555},
++      {0xaaaaaaaa, 0xaaaaaaaa},
++      {0x5a5a5a5a, 0x5a5a5a5a},
++      {0xfafafafa, 0xfafafafa}, /* case-5 */
++      {0x6a5a5555, 0xaaaaaaaa},
++      {0x6a5a56aa, 0x6a5a56aa},
++      {0x6a5a5a5a, 0x6a5a5a5a},
++      {0x66555555, 0x5a5a5a5a},
++      {0x66555555, 0x6a5a5a5a}, /* case-10 */
++      {0x66555555, 0xaaaaaaaa},
++      {0x66555555, 0x6a5a5aaa},
++      {0x66555555, 0x6aaa6aaa},
++      {0x66555555, 0x6a5a5aaa},
++      {0x66555555, 0xaaaaaaaa}, /* case-15 */
++      {0xffff55ff, 0xfafafafa},
++      {0xffff55ff, 0x6afa5afa},
++      {0xaaffffaa, 0xfafafafa},
++      {0xaa5555aa, 0x5a5a5a5a},
++      {0xaa5555aa, 0x6a5a5a5a}, /* case-20 */
++      {0xaa5555aa, 0xaaaaaaaa},
++      {0xffffffff, 0x55555555},
++      {0xffffffff, 0x5a5a5a5a},
++      {0xffffffff, 0x5a5a5a5a},
++      {0xffffffff, 0x5a5a5aaa}, /* case-25 */
++      {0x55555555, 0x5a5a5a5a},
++      {0x55555555, 0xaaaaaaaa},
++      {0x66555555, 0x6a5a6a5a},
++      {0x66556655, 0x66556655},
++      {0x66556aaa, 0x6a5a6aaa}, /* case-30 */
++      {0xffffffff, 0x5aaa5aaa},
++      {0x56555555, 0x5a5a5aaa}
++};
++
++/* Non-Shared-Antenna Coex Table */
++static const struct coex_table_para table_nsant_8821a[] = {
++      {0xffffffff, 0xffffffff}, /* case-100 */
++      {0xffff55ff, 0xfafafafa},
++      {0x66555555, 0x66555555},
++      {0xaaaaaaaa, 0xaaaaaaaa},
++      {0x5a5a5a5a, 0x5a5a5a5a},
++      {0xffffffff, 0xffffffff}, /* case-105 */
++      {0x5afa5afa, 0x5afa5afa},
++      {0x55555555, 0xfafafafa},
++      {0x66555555, 0xfafafafa},
++      {0x66555555, 0x5a5a5a5a},
++      {0x66555555, 0x6a5a5a5a}, /* case-110 */
++      {0x66555555, 0xaaaaaaaa},
++      {0xffff55ff, 0xfafafafa},
++      {0xffff55ff, 0x5afa5afa},
++      {0xffff55ff, 0xaaaaaaaa},
++      {0xffff55ff, 0xffff55ff}, /* case-115 */
++      {0xaaffffaa, 0x5afa5afa},
++      {0xaaffffaa, 0xaaaaaaaa},
++      {0xffffffff, 0xfafafafa},
++      {0xffff55ff, 0xfafafafa},
++      {0xffffffff, 0xaaaaaaaa}, /* case-120 */
++      {0xffff55ff, 0x5afa5afa},
++      {0xffff55ff, 0x5afa5afa},
++      {0x55ff55ff, 0x55ff55ff}
++};
++
++/* Shared-Antenna TDMA */
++static const struct coex_tdma_para tdma_sant_8821a[] = {
++      { {0x00, 0x00, 0x00, 0x00, 0x00} }, /* case-0 */
++      { {0x61, 0x45, 0x03, 0x11, 0x11} }, /* case-1 */
++      { {0x61, 0x3a, 0x03, 0x11, 0x11} },
++      { {0x61, 0x35, 0x03, 0x11, 0x11} },
++      { {0x61, 0x20, 0x03, 0x11, 0x11} },
++      { {0x61, 0x3a, 0x03, 0x11, 0x11} }, /* case-5 */
++      { {0x61, 0x45, 0x03, 0x11, 0x10} },
++      { {0x61, 0x35, 0x03, 0x11, 0x10} },
++      { {0x61, 0x30, 0x03, 0x11, 0x10} },
++      { {0x61, 0x20, 0x03, 0x11, 0x10} },
++      { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-10 */
++      { {0x61, 0x08, 0x03, 0x11, 0x15} },
++      { {0x61, 0x08, 0x03, 0x10, 0x14} },
++      { {0x51, 0x08, 0x03, 0x10, 0x54} },
++      { {0x51, 0x08, 0x03, 0x10, 0x55} },
++      { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-15 */
++      { {0x51, 0x45, 0x03, 0x10, 0x50} },
++      { {0x51, 0x3a, 0x03, 0x11, 0x50} },
++      { {0x51, 0x30, 0x03, 0x10, 0x50} },
++      { {0x51, 0x21, 0x03, 0x10, 0x50} },
++      { {0x51, 0x10, 0x03, 0x10, 0x50} }, /* case-20 */
++      { {0x51, 0x4a, 0x03, 0x10, 0x50} },
++      { {0x51, 0x08, 0x03, 0x30, 0x54} },
++      { {0x55, 0x08, 0x03, 0x10, 0x54} },
++      { {0x65, 0x10, 0x03, 0x11, 0x10} },
++      { {0x51, 0x10, 0x03, 0x10, 0x51} }, /* case-25 */
++      { {0x51, 0x21, 0x03, 0x10, 0x50} },
++      { {0x61, 0x08, 0x03, 0x11, 0x11} }
++};
++
++/* Non-Shared-Antenna TDMA */
++static const struct coex_tdma_para tdma_nsant_8821a[] = {
++      { {0x00, 0x00, 0x00, 0x40, 0x00} }, /* case-100 */
++      { {0x61, 0x45, 0x03, 0x11, 0x11} },
++      { {0x61, 0x25, 0x03, 0x11, 0x11} },
++      { {0x61, 0x35, 0x03, 0x11, 0x11} },
++      { {0x61, 0x20, 0x03, 0x11, 0x11} },
++      { {0x61, 0x10, 0x03, 0x11, 0x11} }, /* case-105 */
++      { {0x61, 0x45, 0x03, 0x11, 0x10} },
++      { {0x61, 0x30, 0x03, 0x11, 0x10} },
++      { {0x61, 0x30, 0x03, 0x11, 0x10} },
++      { {0x61, 0x20, 0x03, 0x11, 0x10} },
++      { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-110 */
++      { {0x61, 0x10, 0x03, 0x11, 0x11} },
++      { {0x51, 0x08, 0x03, 0x10, 0x14} }, /* a2dp high rssi */
++      { {0x51, 0x08, 0x03, 0x10, 0x54} }, /* a2dp not high rssi */
++      { {0x51, 0x08, 0x03, 0x10, 0x55} },
++      { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-115 */
++      { {0x51, 0x45, 0x03, 0x10, 0x50} },
++      { {0x51, 0x3a, 0x03, 0x10, 0x50} },
++      { {0x51, 0x30, 0x03, 0x10, 0x50} },
++      { {0x51, 0x21, 0x03, 0x10, 0x50} },
++      { {0x51, 0x21, 0x03, 0x10, 0x50} }, /* case-120 */
++      { {0x51, 0x10, 0x03, 0x10, 0x50} }
++};
++
++/* TODO */
++static const struct coex_rf_para rf_para_tx_8821a[] = {
++      {0, 0, false, 7},  /* for normal */
++      {0, 20, false, 7}, /* for WL-CPT */
++      {8, 17, true, 4},
++      {7, 18, true, 4},
++      {6, 19, true, 4},
++      {5, 20, true, 4}
++};
++
++static const struct coex_rf_para rf_para_rx_8821a[] = {
++      {0, 0, false, 7},  /* for normal */
++      {0, 20, false, 7}, /* for WL-CPT */
++      {3, 24, true, 5},
++      {2, 26, true, 5},
++      {1, 27, true, 5},
++      {0, 28, true, 5}
++};
++
++static_assert(ARRAY_SIZE(rf_para_tx_8821a) == ARRAY_SIZE(rf_para_rx_8821a));
++
++static const struct coex_5g_afh_map afh_5g_8821a[] = { {0, 0, 0} };
++
++static const struct rtw_reg_domain coex_info_hw_regs_8821a[] = {
++      {0xCB0, MASKDWORD, RTW_REG_DOMAIN_MAC32},
++      {0xCB4, MASKDWORD, RTW_REG_DOMAIN_MAC32},
++      {0xCBA, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
++      {0, 0, RTW_REG_DOMAIN_NL},
++      {0x430, MASKDWORD, RTW_REG_DOMAIN_MAC32},
++      {0x434, MASKDWORD, RTW_REG_DOMAIN_MAC32},
++      {0x42a, MASKLWORD, RTW_REG_DOMAIN_MAC16},
++      {0x426, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
++      {0x45e, BIT(3), RTW_REG_DOMAIN_MAC8},
++      {0x454, MASKLWORD, RTW_REG_DOMAIN_MAC16},
++      {0, 0, RTW_REG_DOMAIN_NL},
++      {0x4c, BIT(24) | BIT(23), RTW_REG_DOMAIN_MAC32},
++      {0x64, BIT(0), RTW_REG_DOMAIN_MAC8},
++      {0x4c6, BIT(4), RTW_REG_DOMAIN_MAC8},
++      {0x40, BIT(5), RTW_REG_DOMAIN_MAC8},
++      {0x1, RFREG_MASK, RTW_REG_DOMAIN_RF_A},
++      {0, 0, RTW_REG_DOMAIN_NL},
++      {0x550, MASKDWORD, RTW_REG_DOMAIN_MAC32},
++      {0x522, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
++      {0x953, BIT(1), RTW_REG_DOMAIN_MAC8},
++      {0xc50,  MASKBYTE0, RTW_REG_DOMAIN_MAC8},
++      {0x60A, MASKBYTE0, RTW_REG_DOMAIN_MAC8},
++};
++
++const struct rtw_chip_info rtw8821a_hw_spec = {
++      .ops = &rtw8821a_ops,
++      .id = RTW_CHIP_TYPE_8821A,
++      .fw_name = "rtw88/rtw8821a_fw.bin",
++      .wlan_cpu = RTW_WCPU_11N,
++      .tx_pkt_desc_sz = 40,
++      .tx_buf_desc_sz = 16,
++      .rx_pkt_desc_sz = 24,
++      .rx_buf_desc_sz = 8,
++      .phy_efuse_size = 512,
++      .log_efuse_size = 512,
++      .ptct_efuse_size = 96 + 1, /* TODO or just 18? */
++      .txff_size = 65536,
++      .rxff_size = 16128,
++      .rsvd_drv_pg_num = 8,
++      .txgi_factor = 1,
++      .is_pwr_by_rate_dec = true,
++      .max_power_index = 0x3f,
++      .csi_buf_pg_num = 0,
++      .band = RTW_BAND_2G | RTW_BAND_5G,
++      .page_size = 256,
++      .dig_min = 0x20,
++      .ht_supported = true,
++      .vht_supported = true,
++      .lps_deep_mode_supported = 0,
++      .sys_func_en = 0xFD,
++      .pwr_on_seq = card_enable_flow_8821a,
++      .pwr_off_seq = card_disable_flow_8821a,
++      .page_table = page_table_8821a,
++      .rqpn_table = rqpn_table_8821a,
++      .prioq_addrs = &prioq_addrs_8821a,
++      .intf_table = NULL,
++      .dig = rtw8821a_dig,
++      .rf_sipi_addr = {REG_LSSI_WRITE_A, REG_LSSI_WRITE_B},
++      .ltecoex_addr = NULL,
++      .mac_tbl = &rtw8821a_mac_tbl,
++      .agc_tbl = &rtw8821a_agc_tbl,
++      .bb_tbl = &rtw8821a_bb_tbl,
++      .rf_tbl = {&rtw8821a_rf_a_tbl},
++      .rfe_defs = rtw8821a_rfe_defs,
++      .rfe_defs_size = ARRAY_SIZE(rtw8821a_rfe_defs),
++      .rx_ldpc = false,
++      .hw_feature_report = false,
++      .c2h_ra_report_size = 4,
++      .old_datarate_fb_limit = true,
++      .usb_tx_agg_desc_num = 6,
++      .iqk_threshold = 8,
++      .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
++      .max_scan_ie_len = IEEE80211_MAX_DATA_LEN,
++
++      .coex_para_ver = 20190509, /* glcoex_ver_date_8821a_1ant */
++      .bt_desired_ver = 0x62, /* But for 2 ant it's 0x5c */
++      .scbd_support = false,
++      .new_scbd10_def = false,
++      .ble_hid_profile_support = false,
++      .wl_mimo_ps_support = false,
++      .pstdma_type = COEX_PSTDMA_FORCE_LPSOFF,
++      .bt_rssi_type = COEX_BTRSSI_RATIO,
++      .ant_isolation = 10,
++      .rssi_tolerance = 2,
++      .wl_rssi_step = wl_rssi_step_8821a,
++      .bt_rssi_step = bt_rssi_step_8821a,
++      .table_sant_num = ARRAY_SIZE(table_sant_8821a),
++      .table_sant = table_sant_8821a,
++      .table_nsant_num = ARRAY_SIZE(table_nsant_8821a),
++      .table_nsant = table_nsant_8821a,
++      .tdma_sant_num = ARRAY_SIZE(tdma_sant_8821a),
++      .tdma_sant = tdma_sant_8821a,
++      .tdma_nsant_num = ARRAY_SIZE(tdma_nsant_8821a),
++      .tdma_nsant = tdma_nsant_8821a,
++      .wl_rf_para_num = ARRAY_SIZE(rf_para_tx_8821a),
++      .wl_rf_para_tx = rf_para_tx_8821a,
++      .wl_rf_para_rx = rf_para_rx_8821a,
++      .bt_afh_span_bw20 = 0x20,
++      .bt_afh_span_bw40 = 0x30,
++      .afh_5g_num = ARRAY_SIZE(afh_5g_8821a),
++      .afh_5g = afh_5g_8821a,
++
++      .coex_info_hw_regs_num = ARRAY_SIZE(coex_info_hw_regs_8821a),
++      .coex_info_hw_regs = coex_info_hw_regs_8821a,
++};
++EXPORT_SYMBOL(rtw8821a_hw_spec);
++
++MODULE_FIRMWARE("rtw88/rtw8821a_fw.bin");
++
++MODULE_AUTHOR("Realtek Corporation");
++MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821a/8811a driver");
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null
++++ b/drivers/net/wireless/realtek/rtw88/rtw8821a.h
+@@ -0,0 +1,10 @@
++/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
++/* Copyright(c) 2024  Realtek Corporation
++ */
++
++#ifndef __RTW8821A_H__
++#define __RTW8821A_H__
++
++extern const struct rtw_chip_info rtw8821a_hw_spec;
++
++#endif
diff --git a/package/kernel/mac80211/patches/rtl/043-v6.13-wifi-rtw88-Add-rtw8812a.-c-h.patch b/package/kernel/mac80211/patches/rtl/043-v6.13-wifi-rtw88-Add-rtw8812a.-c-h.patch
new file mode 100644 (file)
index 0000000..610dca0
--- /dev/null
@@ -0,0 +1,1135 @@
+From 4f8ec8927bc292b2a71cd5a253c96ce3c6b2927f Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 30 Oct 2024 20:28:49 +0200
+Subject: [PATCH] wifi: rtw88: Add rtw8812a.{c,h}
+
+These contain code specific to RTL8812AU.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/a0057683-79eb-4ab2-8f74-11a3bc58adfb@gmail.com
+---
+ drivers/net/wireless/realtek/rtw88/rtw8812a.c | 1102 +++++++++++++++++
+ drivers/net/wireless/realtek/rtw88/rtw8812a.h |   10 +
+ 2 files changed, 1112 insertions(+)
+ create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8812a.c
+ create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8812a.h
+
+--- /dev/null
++++ b/drivers/net/wireless/realtek/rtw88/rtw8812a.c
+@@ -0,0 +1,1102 @@
++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
++/* Copyright(c) 2024  Realtek Corporation
++ */
++
++#include "main.h"
++#include "coex.h"
++#include "phy.h"
++#include "reg.h"
++#include "rtw88xxa.h"
++#include "rtw8812a.h"
++#include "rtw8812a_table.h"
++#include "tx.h"
++
++static void rtw8812a_power_off(struct rtw_dev *rtwdev)
++{
++      rtw88xxa_power_off(rtwdev, enter_lps_flow_8812a);
++}
++
++static s8 rtw8812a_cck_rx_pwr(u8 lna_idx, u8 vga_idx)
++{
++      s8 rx_pwr_all = 0;
++
++      switch (lna_idx) {
++      case 7:
++              if (vga_idx <= 27)
++                      rx_pwr_all = -94 + 2 * (27 - vga_idx);
++              else
++                      rx_pwr_all = -94;
++              break;
++      case 6:
++              rx_pwr_all = -42 + 2 * (2 - vga_idx);
++              break;
++      case 5:
++              rx_pwr_all = -36 + 2 * (7 - vga_idx);
++              break;
++      case 4:
++              rx_pwr_all = -30 + 2 * (7 - vga_idx);
++              break;
++      case 3:
++              rx_pwr_all = -18 + 2 * (7 - vga_idx);
++              break;
++      case 2:
++              rx_pwr_all = 2 * (5 - vga_idx);
++              break;
++      case 1:
++              rx_pwr_all = 14 - 2 * vga_idx;
++              break;
++      case 0:
++              rx_pwr_all = 20 - 2 * vga_idx;
++              break;
++      default:
++              break;
++      }
++
++      return rx_pwr_all;
++}
++
++static void rtw8812a_query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status,
++                                    struct rtw_rx_pkt_stat *pkt_stat)
++{
++      rtw88xxa_query_phy_status(rtwdev, phy_status, pkt_stat,
++                                rtw8812a_cck_rx_pwr);
++
++      if (pkt_stat->rate >= DESC_RATE6M)
++              return;
++
++      if (rtwdev->hal.cck_high_power)
++              return;
++
++      if (pkt_stat->rssi >= 80)
++              pkt_stat->rssi = ((pkt_stat->rssi - 80) << 1) +
++                               ((pkt_stat->rssi - 80) >> 1) + 80;
++      else if (pkt_stat->rssi <= 78 && pkt_stat->rssi >= 20)
++              pkt_stat->rssi += 3;
++}
++
++static void rtw8812a_cfg_ldo25(struct rtw_dev *rtwdev, bool enable)
++{
++}
++
++static void rtw8812a_do_lck(struct rtw_dev *rtwdev)
++{
++      u32 cont_tx, lc_cal, i;
++
++      cont_tx = rtw_read32_mask(rtwdev, REG_SINGLE_TONE_CONT_TX, 0x70000);
++
++      lc_cal = rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK);
++
++      if (!cont_tx)
++              rtw_write8(rtwdev, REG_TXPAUSE, 0xff);
++
++      rtw_write_rf(rtwdev, RF_PATH_A, RF_LCK, BIT(14), 1);
++
++      rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, 0x08000, 1);
++
++      mdelay(150);
++
++      for (i = 0; i < 5; i++) {
++              if (rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, 0x08000) != 1)
++                      break;
++
++              mdelay(10);
++      }
++
++      if (i == 5)
++              rtw_dbg(rtwdev, RTW_DBG_RFK, "LCK timed out\n");
++
++      rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal);
++
++      rtw_write_rf(rtwdev, RF_PATH_A, RF_LCK, BIT(14), 0);
++
++      if (!cont_tx)
++              rtw_write8(rtwdev, REG_TXPAUSE, 0);
++
++      rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal);
++}
++
++static void rtw8812a_iqk_backup_rf(struct rtw_dev *rtwdev, u32 *rfa_backup,
++                                 u32 *rfb_backup, const u32 *backup_rf_reg,
++                                 u32 rf_num)
++{
++      u32 i;
++
++      /* [31] = 0 --> Page C */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++
++      /* Save RF Parameters */
++      for (i = 0; i < rf_num; i++) {
++              rfa_backup[i] = rtw_read_rf(rtwdev, RF_PATH_A,
++                                          backup_rf_reg[i], MASKDWORD);
++              rfb_backup[i] = rtw_read_rf(rtwdev, RF_PATH_B,
++                                          backup_rf_reg[i], MASKDWORD);
++      }
++}
++
++static void rtw8812a_iqk_restore_rf(struct rtw_dev *rtwdev,
++                                  enum rtw_rf_path path,
++                                  const u32 *backup_rf_reg,
++                                  u32 *RF_backup, u32 rf_reg_num)
++{
++      u32 i;
++
++      /* [31] = 0 --> Page C */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++
++      for (i = 0; i < rf_reg_num; i++)
++              rtw_write_rf(rtwdev, path, backup_rf_reg[i],
++                           RFREG_MASK, RF_backup[i]);
++
++      rtw_write_rf(rtwdev, path, RF_LUTWE, RFREG_MASK, 0);
++}
++
++static void rtw8812a_iqk_restore_afe(struct rtw_dev *rtwdev, u32 *afe_backup,
++                                   const u32 *backup_afe_reg, u32 afe_num)
++{
++      u32 i;
++
++      /* [31] = 0 --> Page C */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++
++      /* Reload AFE Parameters */
++      for (i = 0; i < afe_num; i++)
++              rtw_write32(rtwdev, backup_afe_reg[i], afe_backup[i]);
++
++      /* [31] = 1 --> Page C1 */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
++
++      rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x0);
++      rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x0);
++      rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x0);
++      rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x3c000000);
++      rtw_write32_mask(rtwdev, REG_LSSI_WRITE_A, BIT(7), 1);
++      rtw_write32_mask(rtwdev, REG_IQK_DPD_CFG, BIT(18), 1);
++      rtw_write32_mask(rtwdev, REG_IQK_DPD_CFG, BIT(29), 1);
++      rtw_write32_mask(rtwdev, REG_CFG_PMPD, BIT(29), 1);
++
++      rtw_write32(rtwdev, REG_TXTONEB, 0x0);
++      rtw_write32(rtwdev, REG_RXTONEB, 0x0);
++      rtw_write32(rtwdev, REG_TXPITMB, 0x0);
++      rtw_write32(rtwdev, REG_RXPITMB, 0x3c000000);
++      rtw_write32_mask(rtwdev, REG_LSSI_WRITE_B, BIT(7), 1);
++      rtw_write32_mask(rtwdev, REG_BPBDB, BIT(18), 1);
++      rtw_write32_mask(rtwdev, REG_BPBDB, BIT(29), 1);
++      rtw_write32_mask(rtwdev, REG_PHYTXONB, BIT(29), 1);
++}
++
++static void rtw8812a_iqk_rx_fill(struct rtw_dev *rtwdev, enum rtw_rf_path path,
++                               unsigned int rx_x, unsigned int rx_y)
++{
++      switch (path) {
++      case RF_PATH_A:
++              /* [31] = 0 --> Page C */
++              rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++              if (rx_x >> 1 >= 0x112 ||
++                  (rx_y >> 1 >= 0x12 && rx_y >> 1 <= 0x3ee)) {
++                      rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A,
++                                       0x000003ff, 0x100);
++                      rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A,
++                                       0x03ff0000, 0);
++              } else {
++                      rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A,
++                                       0x000003ff, rx_x >> 1);
++                      rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A,
++                                       0x03ff0000, rx_y >> 1);
++              }
++              rtw_dbg(rtwdev, RTW_DBG_RFK,
++                      "rx_x = %x;;rx_y = %x ====>fill to IQC\n",
++                      rx_x >> 1 & 0x000003ff, rx_y >> 1 & 0x000003ff);
++              rtw_dbg(rtwdev, RTW_DBG_RFK, "0xc10 = %x ====>fill to IQC\n",
++                      rtw_read32(rtwdev, REG_RX_IQC_AB_A));
++              break;
++      case RF_PATH_B:
++              /* [31] = 0 --> Page C */
++              rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++              if (rx_x >> 1 >= 0x112 ||
++                  (rx_y >> 1 >= 0x12 && rx_y >> 1 <= 0x3ee)) {
++                      rtw_write32_mask(rtwdev, REG_RX_IQC_AB_B,
++                                       0x000003ff, 0x100);
++                      rtw_write32_mask(rtwdev, REG_RX_IQC_AB_B,
++                                       0x03ff0000, 0);
++              } else {
++                      rtw_write32_mask(rtwdev, REG_RX_IQC_AB_B,
++                                       0x000003ff, rx_x >> 1);
++                      rtw_write32_mask(rtwdev, REG_RX_IQC_AB_B,
++                                       0x03ff0000, rx_y >> 1);
++              }
++              rtw_dbg(rtwdev, RTW_DBG_RFK,
++                      "rx_x = %x;;rx_y = %x ====>fill to IQC\n",
++                      rx_x >> 1 & 0x000003ff, rx_y >> 1 & 0x000003ff);
++              rtw_dbg(rtwdev, RTW_DBG_RFK, "0xe10 = %x====>fill to IQC\n",
++                      rtw_read32(rtwdev, REG_RX_IQC_AB_B));
++              break;
++      default:
++              break;
++      }
++}
++
++static void rtw8812a_iqk_tx_fill(struct rtw_dev *rtwdev, enum rtw_rf_path path,
++                               unsigned int tx_x, unsigned int tx_y)
++{
++      switch (path) {
++      case RF_PATH_A:
++              /* [31] = 1 --> Page C1 */
++              rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
++              rtw_write32_mask(rtwdev, REG_PREDISTA, BIT(7), 0x1);
++              rtw_write32_mask(rtwdev, REG_IQK_DPD_CFG, BIT(18), 0x1);
++              rtw_write32_mask(rtwdev, REG_IQK_DPD_CFG, BIT(29), 0x1);
++              rtw_write32_mask(rtwdev, REG_CFG_PMPD, BIT(29), 0x1);
++              rtw_write32_mask(rtwdev, REG_IQC_Y, 0x000007ff, tx_y);
++              rtw_write32_mask(rtwdev, REG_IQC_X, 0x000007ff, tx_x);
++              rtw_dbg(rtwdev, RTW_DBG_RFK,
++                      "tx_x = %x;;tx_y = %x =====> fill to IQC\n",
++                      tx_x & 0x000007ff, tx_y & 0x000007ff);
++              rtw_dbg(rtwdev, RTW_DBG_RFK,
++                      "0xcd4 = %x;;0xccc = %x ====>fill to IQC\n",
++                      rtw_read32_mask(rtwdev, REG_IQC_X, 0x000007ff),
++                      rtw_read32_mask(rtwdev, REG_IQC_Y, 0x000007ff));
++              break;
++      case RF_PATH_B:
++              /* [31] = 1 --> Page C1 */
++              rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
++              rtw_write32_mask(rtwdev, REG_PREDISTB, BIT(7), 0x1);
++              rtw_write32_mask(rtwdev, REG_BPBDB, BIT(18), 0x1);
++              rtw_write32_mask(rtwdev, REG_BPBDB, BIT(29), 0x1);
++              rtw_write32_mask(rtwdev, REG_PHYTXONB, BIT(29), 0x1);
++              rtw_write32_mask(rtwdev, REG_IQKYB, 0x000007ff, tx_y);
++              rtw_write32_mask(rtwdev, REG_IQKXB, 0x000007ff, tx_x);
++              rtw_dbg(rtwdev, RTW_DBG_RFK,
++                      "tx_x = %x;;tx_y = %x =====> fill to IQC\n",
++                      tx_x & 0x000007ff, tx_y & 0x000007ff);
++              rtw_dbg(rtwdev, RTW_DBG_RFK,
++                      "0xed4 = %x;;0xecc = %x ====>fill to IQC\n",
++                      rtw_read32_mask(rtwdev, REG_IQKXB, 0x000007ff),
++                      rtw_read32_mask(rtwdev, REG_IQKYB, 0x000007ff));
++              break;
++      default:
++              break;
++      }
++}
++
++static void rtw8812a_iqk(struct rtw_dev *rtwdev)
++{
++      int tx_x0_temp[10], tx_y0_temp[10], tx_x1_temp[10], tx_y1_temp[10];
++      int rx_x0_temp[10], rx_y0_temp[10], rx_x1_temp[10], rx_y1_temp[10];
++      bool iqk0_ready = false, tx0_finish = false, rx0_finish = false;
++      bool iqk1_ready = false, tx1_finish = false, rx1_finish = false;
++      u8 tx0_avg = 0, tx1_avg = 0, rx0_avg = 0, rx1_avg = 0;
++      int tx_x0 = 0, tx_y0 = 0, tx_x1 = 0, tx_y1 = 0;
++      int rx_x0 = 0, rx_y0 = 0, rx_x1 = 0, rx_y1 = 0;
++      struct rtw_efuse *efuse = &rtwdev->efuse;
++      bool tx0_fail = true, rx0_fail = true;
++      bool tx1_fail = true, rx1_fail = true;
++      u8 cal0_retry, cal1_retry;
++      u8 delay_count;
++
++      /* [31] = 0 --> Page C */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++
++      /* ========path-A AFE all on======== */
++      /* Port 0 DAC/ADC on */
++      rtw_write32(rtwdev, REG_AFE_PWR1_A, 0x77777777);
++      rtw_write32(rtwdev, REG_AFE_PWR2_A, 0x77777777);
++
++      /* Port 1 DAC/ADC on */
++      rtw_write32(rtwdev, REG_AFE_PWR1_B, 0x77777777);
++      rtw_write32(rtwdev, REG_AFE_PWR2_B, 0x77777777);
++
++      rtw_write32(rtwdev, REG_RX_WAIT_CCA_TX_CCK_RFON_A, 0x19791979);
++      rtw_write32(rtwdev, REG_RX_WAIT_CCA_TX_CCK_RFON_B, 0x19791979);
++
++      /* hardware 3-wire off */
++      rtw_write32_mask(rtwdev, REG_3WIRE_SWA, 0xf, 0x4);
++      rtw_write32_mask(rtwdev, REG_3WIRE_SWB, 0xf, 0x4);
++
++      /* DAC/ADC sampling rate (160 MHz) */
++      rtw_write32_mask(rtwdev, REG_CK_MONHA, GENMASK(26, 24), 0x7);
++      rtw_write32_mask(rtwdev, REG_CK_MONHB, GENMASK(26, 24), 0x7);
++
++      /* [31] = 0 --> Page C */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++      /* ====== path A TX IQK RF setting ====== */
++      rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x80002);
++      rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_ADDR, RFREG_MASK, 0x20000);
++      rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA0, RFREG_MASK, 0x3fffd);
++      rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA1, RFREG_MASK, 0xfe83f);
++      rtw_write_rf(rtwdev, RF_PATH_A, RF_TXA_PREPAD, RFREG_MASK, 0x931d5);
++      rtw_write_rf(rtwdev, RF_PATH_A, RF_RXBB2, RFREG_MASK, 0x8a001);
++
++      /* ====== path B TX IQK RF setting ====== */
++      rtw_write_rf(rtwdev, RF_PATH_B, RF_LUTWE, RFREG_MASK, 0x80002);
++      rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_ADDR, RFREG_MASK, 0x20000);
++      rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_DATA0, RFREG_MASK, 0x3fffd);
++      rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_DATA1, RFREG_MASK, 0xfe83f);
++      rtw_write_rf(rtwdev, RF_PATH_B, RF_TXA_PREPAD, RFREG_MASK, 0x931d5);
++      rtw_write_rf(rtwdev, RF_PATH_B, RF_RXBB2, RFREG_MASK, 0x8a001);
++
++      rtw_write32(rtwdev, REG_DAC_RSTB, 0x00008000);
++      rtw_write32_mask(rtwdev, REG_TXAGCIDX, BIT(0), 0x1);
++      rtw_write32_mask(rtwdev, REG_INIDLYB, BIT(0), 0x1);
++      rtw_write32(rtwdev, REG_IQK_COM00, 0x29002000); /* TX (X,Y) */
++      rtw_write32(rtwdev, REG_IQK_COM32, 0xa9002000); /* RX (X,Y) */
++      rtw_write32(rtwdev, REG_IQK_COM96, 0x00462910); /* [0]:AGC_en, [15]:idac_K_Mask */
++      /* [31] = 1 --> Page C1 */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
++
++      if (efuse->ext_pa_5g) {
++              if (efuse->rfe_option == 1) {
++                      rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x821403e3);
++                      rtw_write32(rtwdev, REG_TXPITMB, 0x821403e3);
++              } else {
++                      rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x821403f7);
++                      rtw_write32(rtwdev, REG_TXPITMB, 0x821403f7);
++              }
++      } else {
++              rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x821403f1);
++              rtw_write32(rtwdev, REG_TXPITMB, 0x821403f1);
++      }
++
++      if (rtwdev->hal.current_band_type == RTW_BAND_5G) {
++              rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x68163e96);
++              rtw_write32(rtwdev, REG_RXPITMB, 0x68163e96);
++      } else {
++              rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x28163e96);
++              rtw_write32(rtwdev, REG_RXPITMB, 0x28163e96);
++
++              if (efuse->rfe_option == 3) {
++                      if (efuse->ext_pa_2g)
++                              rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE,
++                                          0x821403e3);
++                      else
++                              rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE,
++                                          0x821403f7);
++              }
++      }
++
++      /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */
++      rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x18008c10);
++      /* RX_Tone_idx[9:0], RxK_Mask[29] */
++      rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x38008c10);
++      rtw_write32(rtwdev, REG_INTPO_SETA, 0x00000000);
++      /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */
++      rtw_write32(rtwdev, REG_TXTONEB, 0x18008c10);
++      /* RX_Tone_idx[9:0], RxK_Mask[29] */
++      rtw_write32(rtwdev, REG_RXTONEB, 0x38008c10);
++      rtw_write32(rtwdev, REG_INTPO_SETB, 0x00000000);
++
++      cal0_retry = 0;
++      cal1_retry = 0;
++      while (1) {
++              /* one shot */
++              rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000);
++              rtw_write32(rtwdev, REG_RFECTL_B, 0x00100000);
++              rtw_write32(rtwdev, REG_IQK_COM64, 0xfa000000);
++              rtw_write32(rtwdev, REG_IQK_COM64, 0xf8000000);
++
++              mdelay(10);
++
++              rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000);
++              rtw_write32(rtwdev, REG_RFECTL_B, 0x00000000);
++
++              for (delay_count = 0; delay_count < 20; delay_count++) {
++                      if (!tx0_finish)
++                              iqk0_ready = rtw_read32_mask(rtwdev,
++                                                           REG_IQKA_END,
++                                                           BIT(10));
++                      if (!tx1_finish)
++                              iqk1_ready = rtw_read32_mask(rtwdev,
++                                                           REG_IQKB_END,
++                                                           BIT(10));
++                      if (iqk0_ready && iqk1_ready)
++                              break;
++
++                      mdelay(1);
++              }
++
++              rtw_dbg(rtwdev, RTW_DBG_RFK, "TX delay_count = %d\n",
++                      delay_count);
++
++              if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */
++                      /* ============TXIQK Check============== */
++                      tx0_fail = rtw_read32_mask(rtwdev, REG_IQKA_END, BIT(12));
++                      tx1_fail = rtw_read32_mask(rtwdev, REG_IQKB_END, BIT(12));
++
++                      if (!(tx0_fail || tx0_finish)) {
++                              rtw_write32(rtwdev, REG_RFECTL_A, 0x02000000);
++                              tx_x0_temp[tx0_avg] = rtw_read32_mask(rtwdev,
++                                                                    REG_IQKA_END,
++                                                                    0x07ff0000);
++                              rtw_write32(rtwdev, REG_RFECTL_A, 0x04000000);
++                              tx_y0_temp[tx0_avg] = rtw_read32_mask(rtwdev,
++                                                                    REG_IQKA_END,
++                                                                    0x07ff0000);
++
++                              rtw_dbg(rtwdev, RTW_DBG_RFK,
++                                      "tx_x0[%d] = %x ;; tx_y0[%d] = %x\n",
++                                      tx0_avg, tx_x0_temp[tx0_avg],
++                                      tx0_avg, tx_y0_temp[tx0_avg]);
++
++                              tx_x0_temp[tx0_avg] <<= 21;
++                              tx_y0_temp[tx0_avg] <<= 21;
++
++                              tx0_avg++;
++                      } else {
++                              cal0_retry++;
++                              if (cal0_retry == 10)
++                                      break;
++                      }
++
++                      if (!(tx1_fail || tx1_finish)) {
++                              rtw_write32(rtwdev, REG_RFECTL_B, 0x02000000);
++                              tx_x1_temp[tx1_avg] = rtw_read32_mask(rtwdev,
++                                                                    REG_IQKB_END,
++                                                                    0x07ff0000);
++                              rtw_write32(rtwdev, REG_RFECTL_B, 0x04000000);
++                              tx_y1_temp[tx1_avg] = rtw_read32_mask(rtwdev,
++                                                                    REG_IQKB_END,
++                                                                    0x07ff0000);
++
++                              rtw_dbg(rtwdev, RTW_DBG_RFK,
++                                      "tx_x1[%d] = %x ;; tx_y1[%d] = %x\n",
++                                      tx1_avg, tx_x1_temp[tx1_avg],
++                                      tx1_avg, tx_y1_temp[tx1_avg]);
++
++                              tx_x1_temp[tx1_avg] <<= 21;
++                              tx_y1_temp[tx1_avg] <<= 21;
++
++                              tx1_avg++;
++                      } else {
++                              cal1_retry++;
++                              if (cal1_retry == 10)
++                                      break;
++                      }
++              } else {
++                      cal0_retry++;
++                      cal1_retry++;
++
++                      rtw_dbg(rtwdev, RTW_DBG_RFK,
++                              "delay 20ms TX IQK Not Ready!!!!!\n");
++
++                      if (cal0_retry == 10)
++                              break;
++              }
++
++              if (tx0_avg >= 2)
++                      tx0_finish = rtw88xxa_iqk_finish(tx0_avg, 4,
++                                                       tx_x0_temp, tx_y0_temp, &tx_x0, &tx_y0,
++                                                       false, false);
++
++              if (tx1_avg >= 2)
++                      tx1_finish = rtw88xxa_iqk_finish(tx1_avg, 4,
++                                                       tx_x1_temp, tx_y1_temp, &tx_x1, &tx_y1,
++                                                       false, false);
++
++              rtw_dbg(rtwdev, RTW_DBG_RFK,
++                      "tx0_average = %d, tx1_average = %d\n",
++                      tx0_avg, tx1_avg);
++              rtw_dbg(rtwdev, RTW_DBG_RFK,
++                      "tx0_finish = %d, tx1_finish = %d\n",
++                      tx0_finish, tx1_finish);
++
++              if (tx0_finish && tx1_finish)
++                      break;
++
++              if ((cal0_retry + tx0_avg) >= 10 ||
++                  (cal1_retry + tx1_avg) >= 10)
++                      break;
++      }
++
++      rtw_dbg(rtwdev, RTW_DBG_RFK, "TXA_cal_retry = %d\n", cal0_retry);
++      rtw_dbg(rtwdev, RTW_DBG_RFK, "TXB_cal_retry = %d\n", cal1_retry);
++
++      /* [31] = 0 --> Page C */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++      /* Load LOK */
++      rtw_write_rf(rtwdev, RF_PATH_A, RF_TXMOD, 0x7fe00,
++                   rtw_read_rf(rtwdev, RF_PATH_A, RF_DTXLOK, 0xffc00));
++      rtw_write_rf(rtwdev, RF_PATH_B, RF_TXMOD, 0x7fe00,
++                   rtw_read_rf(rtwdev, RF_PATH_B, RF_DTXLOK, 0xffc00));
++      /* [31] = 1 --> Page C1 */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
++
++      /* [31] = 0 --> Page C */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++      if (tx0_finish) {
++              /* ====== path A RX IQK RF setting====== */
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x80000);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_ADDR, RFREG_MASK,
++                           0x30000);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA0, RFREG_MASK,
++                           0x3f7ff);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA1, RFREG_MASK,
++                           0xfe7bf);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_RXBB2, RFREG_MASK, 0x88001);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_TXA_PREPAD, RFREG_MASK, 0x931d1);
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x00000);
++      }
++      if (tx1_finish) {
++              /* ====== path B RX IQK RF setting====== */
++              rtw_write_rf(rtwdev, RF_PATH_B, RF_LUTWE, RFREG_MASK, 0x80000);
++              rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_ADDR, RFREG_MASK,
++                           0x30000);
++              rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_DATA0, RFREG_MASK,
++                           0x3f7ff);
++              rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_DATA1, RFREG_MASK,
++                           0xfe7bf);
++              rtw_write_rf(rtwdev, RF_PATH_B, RF_RXBB2, RFREG_MASK, 0x88001);
++              rtw_write_rf(rtwdev, RF_PATH_B, RF_TXA_PREPAD, RFREG_MASK, 0x931d1);
++              rtw_write_rf(rtwdev, RF_PATH_B, RF_LUTWE, RFREG_MASK, 0x00000);
++      }
++
++      rtw_write32_mask(rtwdev, REG_IQK_COM00, BIT(31), 0x1);
++      rtw_write32_mask(rtwdev, REG_IQK_COM00, BIT(31), 0x0);
++      rtw_write32(rtwdev, REG_DAC_RSTB, 0x00008000);
++
++      if (rtwdev->hci.type == RTW_HCI_TYPE_PCIE)
++              rtw_write32(rtwdev, REG_IQK_COM96, 0x0046a911);
++      else
++              rtw_write32(rtwdev, REG_IQK_COM96, 0x0046a890);
++
++      if (efuse->rfe_option == 1) {
++              rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77777717);
++              rtw_write32(rtwdev, REG_RFE_INV_A, 0x00000077);
++              rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777717);
++              rtw_write32(rtwdev, REG_RFE_INV_B, 0x00000077);
++      } else {
++              rtw_write32(rtwdev, REG_RFE_PINMUX_A, 0x77777717);
++              rtw_write32(rtwdev, REG_RFE_INV_A, 0x02000077);
++              rtw_write32(rtwdev, REG_RFE_PINMUX_B, 0x77777717);
++              rtw_write32(rtwdev, REG_RFE_INV_B, 0x02000077);
++      }
++
++      /* [31] = 1 --> Page C1 */
++      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
++
++      if (tx0_finish) {
++              /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */
++              rtw_write32(rtwdev, REG_OFDM0_XA_TX_IQ_IMBALANCE, 0x38008c10);
++              /* RX_Tone_idx[9:0], RxK_Mask[29] */
++              rtw_write32(rtwdev, REG_OFDM0_A_TX_AFE, 0x18008c10);
++              rtw_write32(rtwdev, REG_OFDM0_XB_TX_IQ_IMBALANCE, 0x82140119);
++      }
++      if (tx1_finish) {
++              /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */
++              rtw_write32(rtwdev, REG_TXTONEB, 0x38008c10);
++              /* RX_Tone_idx[9:0], RxK_Mask[29] */
++              rtw_write32(rtwdev, REG_RXTONEB, 0x18008c10);
++              rtw_write32(rtwdev, REG_TXPITMB, 0x82140119);
++      }
++
++      cal0_retry = 0;
++      cal1_retry = 0;
++      while (1) {
++              /* one shot */
++              /* [31] = 0 --> Page C */
++              rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++
++              if (tx0_finish) {
++                      rtw_write32_mask(rtwdev, REG_IQK_COM00, 0x03FF8000,
++                                       tx_x0 & 0x000007ff);
++                      rtw_write32_mask(rtwdev, REG_IQK_COM00, 0x000007FF,
++                                       tx_y0 & 0x000007ff);
++                      /* [31] = 1 --> Page C1 */
++                      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
++                      if (efuse->rfe_option == 1)
++                              rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x28161500);
++                      else
++                              rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x28160cc0);
++                      rtw_write32(rtwdev, REG_RFECTL_A, 0x00300000);
++                      rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000);
++                      mdelay(5);
++                      rtw_write32(rtwdev, REG_TSSI_TRK_SW, 0x3c000000);
++                      rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000);
++              }
++
++              if (tx1_finish) {
++                      /* [31] = 0 --> Page C */
++                      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0);
++                      rtw_write32_mask(rtwdev, REG_IQK_COM00, 0x03FF8000,
++                                       tx_x1 & 0x000007ff);
++                      rtw_write32_mask(rtwdev, REG_IQK_COM00, 0x000007FF,
++                                       tx_y1 & 0x000007ff);
++                      /* [31] = 1 --> Page C1 */
++                      rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1);
++                      if (efuse->rfe_option == 1)
++                              rtw_write32(rtwdev, REG_RXPITMB, 0x28161500);
++                      else
++                              rtw_write32(rtwdev, REG_RXPITMB, 0x28160ca0);
++                      rtw_write32(rtwdev, REG_RFECTL_B, 0x00300000);
++                      rtw_write32(rtwdev, REG_RFECTL_B, 0x00100000);
++                      mdelay(5);
++                      rtw_write32(rtwdev, REG_RXPITMB, 0x3c000000);
++                      rtw_write32(rtwdev, REG_RFECTL_B, 0x00000000);
++              }
++
++              for (delay_count = 0; delay_count < 20; delay_count++) {
++                      if (!rx0_finish && tx0_finish)
++                              iqk0_ready = rtw_read32_mask(rtwdev,
++                                                           REG_IQKA_END,
++                                                           BIT(10));
++                      if (!rx1_finish && tx1_finish)
++                              iqk1_ready = rtw_read32_mask(rtwdev,
++                                                           REG_IQKB_END,
++                                                           BIT(10));
++                      if (iqk0_ready && iqk1_ready)
++                              break;
++
++                      mdelay(1);
++              }
++
++              rtw_dbg(rtwdev, RTW_DBG_RFK, "RX delay_count = %d\n",
++                      delay_count);
++
++              if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */
++                      /* ============RXIQK Check============== */
++                      rx0_fail = rtw_read32_mask(rtwdev, REG_IQKA_END, BIT(11));
++                      rx1_fail = rtw_read32_mask(rtwdev, REG_IQKB_END, BIT(11));
++
++                      if (!(rx0_fail || rx0_finish) && tx0_finish) {
++                              rtw_write32(rtwdev, REG_RFECTL_A, 0x06000000);
++                              rx_x0_temp[rx0_avg] = rtw_read32_mask(rtwdev,
++                                                                    REG_IQKA_END,
++                                                                    0x07ff0000);
++                              rtw_write32(rtwdev, REG_RFECTL_A, 0x08000000);
++                              rx_y0_temp[rx0_avg] = rtw_read32_mask(rtwdev,
++                                                                    REG_IQKA_END,
++                                                                    0x07ff0000);
++
++                              rtw_dbg(rtwdev, RTW_DBG_RFK,
++                                      "rx_x0[%d] = %x ;; rx_y0[%d] = %x\n",
++                                      rx0_avg, rx_x0_temp[rx0_avg],
++                                      rx0_avg, rx_y0_temp[rx0_avg]);
++
++                              rx_x0_temp[rx0_avg] <<= 21;
++                              rx_y0_temp[rx0_avg] <<= 21;
++
++                              rx0_avg++;
++                      } else {
++                              rtw_dbg(rtwdev, RTW_DBG_RFK,
++                                      "1. RXA_cal_retry = %d\n", cal0_retry);
++
++                              cal0_retry++;
++                              if (cal0_retry == 10)
++                                      break;
++                      }
++
++                      if (!(rx1_fail || rx1_finish) && tx1_finish) {
++                              rtw_write32(rtwdev, REG_RFECTL_B, 0x06000000);
++                              rx_x1_temp[rx1_avg] = rtw_read32_mask(rtwdev,
++                                                                    REG_IQKB_END,
++                                                                    0x07ff0000);
++                              rtw_write32(rtwdev, REG_RFECTL_B, 0x08000000);
++                              rx_y1_temp[rx1_avg] = rtw_read32_mask(rtwdev,
++                                                                    REG_IQKB_END,
++                                                                    0x07ff0000);
++
++                              rtw_dbg(rtwdev, RTW_DBG_RFK,
++                                      "rx_x1[%d] = %x ;; rx_y1[%d] = %x\n",
++                                      rx1_avg, rx_x1_temp[rx1_avg],
++                                      rx1_avg, rx_y1_temp[rx1_avg]);
++
++                              rx_x1_temp[rx1_avg] <<= 21;
++                              rx_y1_temp[rx1_avg] <<= 21;
++
++                              rx1_avg++;
++                      } else {
++                              cal1_retry++;
++                              if (cal1_retry == 10)
++                                      break;
++                      }
++              } else {
++                      rtw_dbg(rtwdev, RTW_DBG_RFK,
++                              "2. RXA_cal_retry = %d\n", cal0_retry);
++
++                      cal0_retry++;
++                      cal1_retry++;
++
++                      rtw_dbg(rtwdev, RTW_DBG_RFK,
++                              "delay 20ms RX IQK Not Ready!!!!!\n");
++
++                      if (cal0_retry == 10)
++                              break;
++              }
++
++              rtw_dbg(rtwdev, RTW_DBG_RFK, "3. RXA_cal_retry = %d\n",
++                      cal0_retry);
++
++              if (rx0_avg >= 2)
++                      rx0_finish = rtw88xxa_iqk_finish(rx0_avg, 4,
++                                                       rx_x0_temp, rx_y0_temp,
++                                                       &rx_x0, &rx_y0,
++                                                       true, false);
++
++              if (rx1_avg >= 2)
++                      rx1_finish = rtw88xxa_iqk_finish(rx1_avg, 4,
++                                                       rx_x1_temp, rx_y1_temp,
++                                                       &rx_x1, &rx_y1,
++                                                       true, false);
++
++              rtw_dbg(rtwdev, RTW_DBG_RFK,
++                      "rx0_average = %d, rx1_average = %d\n",
++                      rx0_avg, rx1_avg);
++              rtw_dbg(rtwdev, RTW_DBG_RFK,
++                      "rx0_finish = %d, rx1_finish = %d\n",
++                      rx0_finish, rx1_finish);
++
++              if ((rx0_finish || !tx0_finish) && (rx1_finish || !tx1_finish))
++                      break;
++
++              if ((cal0_retry + rx0_avg) >= 10 ||
++                  (cal1_retry + rx1_avg) >= 10 ||
++                  rx0_avg == 3 || rx1_avg == 3)
++                      break;
++      }
++
++      rtw_dbg(rtwdev, RTW_DBG_RFK, "RXA_cal_retry = %d\n", cal0_retry);
++      rtw_dbg(rtwdev, RTW_DBG_RFK, "RXB_cal_retry = %d\n", cal1_retry);
++
++      /* FillIQK Result */
++      rtw_dbg(rtwdev, RTW_DBG_RFK, "========Path_A =======\n");
++
++      if (tx0_finish)
++              rtw8812a_iqk_tx_fill(rtwdev, RF_PATH_A, tx_x0, tx_y0);
++      else
++              rtw8812a_iqk_tx_fill(rtwdev, RF_PATH_A, 0x200, 0x0);
++
++      if (rx0_finish)
++              rtw8812a_iqk_rx_fill(rtwdev, RF_PATH_A, rx_x0, rx_y0);
++      else
++              rtw8812a_iqk_rx_fill(rtwdev, RF_PATH_A, 0x200, 0x0);
++
++      rtw_dbg(rtwdev, RTW_DBG_RFK, "========Path_B =======\n");
++
++      if (tx1_finish)
++              rtw8812a_iqk_tx_fill(rtwdev, RF_PATH_B, tx_x1, tx_y1);
++      else
++              rtw8812a_iqk_tx_fill(rtwdev, RF_PATH_B, 0x200, 0x0);
++
++      if (rx1_finish)
++              rtw8812a_iqk_rx_fill(rtwdev, RF_PATH_B, rx_x1, rx_y1);
++      else
++              rtw8812a_iqk_rx_fill(rtwdev, RF_PATH_B, 0x200, 0x0);
++}
++
++#define MACBB_REG_NUM_8812A 9
++#define AFE_REG_NUM_8812A 12
++#define RF_REG_NUM_8812A 3
++
++static void rtw8812a_do_iqk(struct rtw_dev *rtwdev)
++{
++      static const u32 backup_macbb_reg[MACBB_REG_NUM_8812A] = {
++              0x520, 0x550, 0x808, 0xa04, 0x90c, 0xc00, 0xe00, 0x838, 0x82c
++      };
++      static const u32 backup_afe_reg[AFE_REG_NUM_8812A] = {
++              0xc5c, 0xc60, 0xc64, 0xc68, 0xcb0, 0xcb4,
++              0xe5c, 0xe60, 0xe64, 0xe68, 0xeb0, 0xeb4
++      };
++      static const u32 backup_rf_reg[RF_REG_NUM_8812A] = {
++              0x65, 0x8f, 0x0
++      };
++      u32 macbb_backup[MACBB_REG_NUM_8812A] = {};
++      u32 afe_backup[AFE_REG_NUM_8812A] = {};
++      u32 rfa_backup[RF_REG_NUM_8812A] = {};
++      u32 rfb_backup[RF_REG_NUM_8812A] = {};
++      u32 reg_cb8, reg_eb8;
++
++      rtw88xxa_iqk_backup_mac_bb(rtwdev, macbb_backup,
++                                 backup_macbb_reg, MACBB_REG_NUM_8812A);
++
++      rtw_write32_set(rtwdev, REG_CCASEL, BIT(31));
++      reg_cb8 = rtw_read32(rtwdev, REG_RFECTL_A);
++      reg_eb8 = rtw_read32(rtwdev, REG_RFECTL_B);
++      rtw_write32_clr(rtwdev, REG_CCASEL, BIT(31));
++
++      rtw88xxa_iqk_backup_afe(rtwdev, afe_backup,
++                              backup_afe_reg, AFE_REG_NUM_8812A);
++      rtw8812a_iqk_backup_rf(rtwdev, rfa_backup, rfb_backup,
++                             backup_rf_reg, RF_REG_NUM_8812A);
++
++      rtw88xxa_iqk_configure_mac(rtwdev);
++
++      rtw8812a_iqk(rtwdev);
++
++      rtw8812a_iqk_restore_rf(rtwdev, RF_PATH_A, backup_rf_reg,
++                              rfa_backup, RF_REG_NUM_8812A);
++      rtw8812a_iqk_restore_rf(rtwdev, RF_PATH_B, backup_rf_reg,
++                              rfb_backup, RF_REG_NUM_8812A);
++
++      rtw8812a_iqk_restore_afe(rtwdev, afe_backup,
++                               backup_afe_reg, AFE_REG_NUM_8812A);
++
++      rtw_write32_set(rtwdev, REG_CCASEL, BIT(31));
++      rtw_write32(rtwdev, REG_RFECTL_A, reg_cb8);
++      rtw_write32(rtwdev, REG_RFECTL_B, reg_eb8);
++      rtw_write32_clr(rtwdev, REG_CCASEL, BIT(31));
++
++      rtw88xxa_iqk_restore_mac_bb(rtwdev, macbb_backup,
++                                  backup_macbb_reg, MACBB_REG_NUM_8812A);
++}
++
++static void rtw8812a_phy_calibration(struct rtw_dev *rtwdev)
++{
++      u8 channel = rtwdev->hal.current_channel;
++
++      rtw8812a_do_iqk(rtwdev);
++
++      /* The official driver wants to do this after connecting
++       * but before first writing a new igi (phydm_get_new_igi).
++       * Here seems close enough.
++       */
++      if (channel >= 36 && channel <= 64)
++              rtw_load_table(rtwdev, &rtw8812a_agc_diff_lb_tbl);
++      else if (channel >= 100)
++              rtw_load_table(rtwdev, &rtw8812a_agc_diff_hb_tbl);
++}
++
++static void rtw8812a_pwr_track(struct rtw_dev *rtwdev)
++{
++      struct rtw_dm_info *dm_info = &rtwdev->dm_info;
++
++      if (!dm_info->pwr_trk_triggered) {
++              rtw_write_rf(rtwdev, RF_PATH_A, RF_T_METER,
++                           GENMASK(17, 16), 0x03);
++              dm_info->pwr_trk_triggered = true;
++              return;
++      }
++
++      rtw88xxa_phy_pwrtrack(rtwdev, rtw8812a_do_lck, rtw8812a_do_iqk);
++      dm_info->pwr_trk_triggered = false;
++}
++
++static void rtw8812a_fill_txdesc_checksum(struct rtw_dev *rtwdev,
++                                        struct rtw_tx_pkt_info *pkt_info,
++                                        u8 *txdesc)
++{
++      fill_txdesc_checksum_common(txdesc, 16);
++}
++
++static void rtw8812a_coex_cfg_init(struct rtw_dev *rtwdev)
++{
++}
++
++static void rtw8812a_coex_cfg_gnt_fix(struct rtw_dev *rtwdev)
++{
++}
++
++static void rtw8821a_coex_cfg_rfe_type(struct rtw_dev *rtwdev)
++{
++}
++
++static void rtw8821a_coex_cfg_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr)
++{
++}
++
++static void rtw8821a_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)
++{
++}
++
++static const struct rtw_chip_ops rtw8812a_ops = {
++      .power_on               = rtw88xxa_power_on,
++      .power_off              = rtw8812a_power_off,
++      .phy_set_param          = NULL,
++      .read_efuse             = rtw88xxa_read_efuse,
++      .query_phy_status       = rtw8812a_query_phy_status,
++      .set_channel            = rtw88xxa_set_channel,
++      .mac_init               = NULL,
++      .read_rf                = rtw88xxa_phy_read_rf,
++      .write_rf               = rtw_phy_write_rf_reg_sipi,
++      .set_antenna            = NULL,
++      .set_tx_power_index     = rtw88xxa_set_tx_power_index,
++      .cfg_ldo25              = rtw8812a_cfg_ldo25,
++      .efuse_grant            = rtw88xxa_efuse_grant,
++      .false_alarm_statistics = rtw88xxa_false_alarm_statistics,
++      .phy_calibration        = rtw8812a_phy_calibration,
++      .cck_pd_set             = rtw88xxa_phy_cck_pd_set,
++      .pwr_track              = rtw8812a_pwr_track,
++      .config_bfee            = NULL,
++      .set_gid_table          = NULL,
++      .cfg_csi_rate           = NULL,
++      .fill_txdesc_checksum   = rtw8812a_fill_txdesc_checksum,
++      .coex_set_init          = rtw8812a_coex_cfg_init,
++      .coex_set_ant_switch    = NULL,
++      .coex_set_gnt_fix       = rtw8812a_coex_cfg_gnt_fix,
++      .coex_set_gnt_debug     = NULL,
++      .coex_set_rfe_type      = rtw8821a_coex_cfg_rfe_type,
++      .coex_set_wl_tx_power   = rtw8821a_coex_cfg_wl_tx_power,
++      .coex_set_wl_rx_gain    = rtw8821a_coex_cfg_wl_rx_gain,
++};
++
++static const struct rtw_page_table page_table_8812a[] = {
++      /* hq_num, nq_num, lq_num, exq_num, gapq_num */
++      {0, 0, 0, 0, 0},        /* SDIO */
++      {0, 0, 0, 0, 0},        /* PCI */
++      {16, 0, 0, 0, 1},       /* 2 bulk out endpoints */
++      {16, 0, 16, 0, 1},      /* 3 bulk out endpoints */
++      {16, 0, 16, 0, 1},      /* 4 bulk out endpoints */
++};
++
++static const struct rtw_rqpn rqpn_table_8812a[] = {
++      {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
++       RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
++       RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
++
++      {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
++       RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
++       RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
++
++      {RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH,
++       RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
++       RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH},
++
++      {RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_NORMAL,
++       RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
++       RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH},
++
++      {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL,
++       RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW,
++       RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH},
++};
++
++static const struct rtw_prioq_addrs prioq_addrs_8812a = {
++      .prio[RTW_DMA_MAPPING_EXTRA] = {
++              .rsvd = REG_RQPN_NPQ + 2, .avail = REG_RQPN_NPQ + 3,
++      },
++      .prio[RTW_DMA_MAPPING_LOW] = {
++              .rsvd = REG_RQPN + 1, .avail = REG_FIFOPAGE_CTRL_2 + 1,
++      },
++      .prio[RTW_DMA_MAPPING_NORMAL] = {
++              .rsvd = REG_RQPN_NPQ, .avail = REG_RQPN_NPQ + 1,
++      },
++      .prio[RTW_DMA_MAPPING_HIGH] = {
++              .rsvd = REG_RQPN, .avail = REG_FIFOPAGE_CTRL_2,
++      },
++      .wsize = false,
++};
++
++static const struct rtw_hw_reg rtw8812a_dig[] = {
++      [0] = { .addr = REG_RXIGI_A, .mask = 0x7f },
++      [1] = { .addr = REG_RXIGI_B, .mask = 0x7f },
++};
++
++static const struct rtw_rfe_def rtw8812a_rfe_defs[] = {
++      [0] = { .phy_pg_tbl     = &rtw8812a_bb_pg_tbl,
++              .txpwr_lmt_tbl  = &rtw8812a_txpwr_lmt_tbl,
++              .pwr_track_tbl  = &rtw8812a_rtw_pwr_track_tbl, },
++      [1] = { .phy_pg_tbl     = &rtw8812a_bb_pg_tbl,
++              .txpwr_lmt_tbl  = &rtw8812a_txpwr_lmt_tbl,
++              .pwr_track_tbl  = &rtw8812a_rtw_pwr_track_tbl, },
++      [3] = { .phy_pg_tbl     = &rtw8812a_bb_pg_rfe3_tbl,
++              .txpwr_lmt_tbl  = &rtw8812a_txpwr_lmt_tbl,
++              .pwr_track_tbl  = &rtw8812a_rtw_pwr_track_rfe3_tbl, },
++};
++
++static const u8 wl_rssi_step_8812a[] = {101, 45, 101, 40};
++static const u8 bt_rssi_step_8812a[] = {101, 101, 101, 101};
++
++static const struct coex_rf_para rf_para_tx_8812a[] = {
++      {0, 0, false, 7},  /* for normal */
++      {0, 20, false, 7}, /* for WL-CPT */
++      {8, 17, true, 4},
++      {7, 18, true, 4},
++      {6, 19, true, 4},
++      {5, 20, true, 4}
++};
++
++static const struct coex_rf_para rf_para_rx_8812a[] = {
++      {0, 0, false, 7},  /* for normal */
++      {0, 20, false, 7}, /* for WL-CPT */
++      {3, 24, true, 5},
++      {2, 26, true, 5},
++      {1, 27, true, 5},
++      {0, 28, true, 5}
++};
++
++static_assert(ARRAY_SIZE(rf_para_tx_8812a) == ARRAY_SIZE(rf_para_rx_8812a));
++
++const struct rtw_chip_info rtw8812a_hw_spec = {
++      .ops = &rtw8812a_ops,
++      .id = RTW_CHIP_TYPE_8812A,
++      .fw_name = "rtw88/rtw8812a_fw.bin",
++      .wlan_cpu = RTW_WCPU_11N,
++      .tx_pkt_desc_sz = 40,
++      .tx_buf_desc_sz = 16,
++      .rx_pkt_desc_sz = 24,
++      .rx_buf_desc_sz = 8,
++      .phy_efuse_size = 512,
++      .log_efuse_size = 512,
++      .ptct_efuse_size = 96 + 1, /* TODO or just 18? */
++      .txff_size = 131072,
++      .rxff_size = 16128,
++      .rsvd_drv_pg_num = 9,
++      .txgi_factor = 1,
++      .is_pwr_by_rate_dec = true,
++      .max_power_index = 0x3f,
++      .csi_buf_pg_num = 0,
++      .band = RTW_BAND_2G | RTW_BAND_5G,
++      .page_size = 512,
++      .dig_min = 0x20,
++      .ht_supported = true,
++      .vht_supported = true,
++      .lps_deep_mode_supported = 0,
++      .sys_func_en = 0xFD,
++      .pwr_on_seq = card_enable_flow_8812a,
++      .pwr_off_seq = card_disable_flow_8812a,
++      .page_table = page_table_8812a,
++      .rqpn_table = rqpn_table_8812a,
++      .prioq_addrs = &prioq_addrs_8812a,
++      .intf_table = NULL,
++      .dig = rtw8812a_dig,
++      .rf_sipi_addr = {REG_LSSI_WRITE_A, REG_LSSI_WRITE_B},
++      .ltecoex_addr = NULL,
++      .mac_tbl = &rtw8812a_mac_tbl,
++      .agc_tbl = &rtw8812a_agc_tbl,
++      .bb_tbl = &rtw8812a_bb_tbl,
++      .rf_tbl = {&rtw8812a_rf_a_tbl, &rtw8812a_rf_b_tbl},
++      .rfe_defs = rtw8812a_rfe_defs,
++      .rfe_defs_size = ARRAY_SIZE(rtw8812a_rfe_defs),
++      .rx_ldpc = false,
++      .hw_feature_report = false,
++      .c2h_ra_report_size = 4,
++      .old_datarate_fb_limit = true,
++      .usb_tx_agg_desc_num = 1,
++      .iqk_threshold = 8,
++      .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
++      .max_scan_ie_len = IEEE80211_MAX_DATA_LEN,
++
++      .coex_para_ver = 0, /* no coex code in 8812au driver */
++      .bt_desired_ver = 0,
++      .scbd_support = false,
++      .new_scbd10_def = false,
++      .ble_hid_profile_support = false,
++      .wl_mimo_ps_support = false,
++      .pstdma_type = COEX_PSTDMA_FORCE_LPSOFF,
++      .bt_rssi_type = COEX_BTRSSI_RATIO,
++      .ant_isolation = 15,
++      .rssi_tolerance = 2,
++      .wl_rssi_step = wl_rssi_step_8812a,
++      .bt_rssi_step = bt_rssi_step_8812a,
++      .table_sant_num = 0,
++      .table_sant = NULL,
++      .table_nsant_num = 0,
++      .table_nsant = NULL,
++      .tdma_sant_num = 0,
++      .tdma_sant = NULL,
++      .tdma_nsant_num = 0,
++      .tdma_nsant = NULL,
++      .wl_rf_para_num = ARRAY_SIZE(rf_para_tx_8812a),
++      .wl_rf_para_tx = rf_para_tx_8812a,
++      .wl_rf_para_rx = rf_para_rx_8812a,
++      .bt_afh_span_bw20 = 0x20,
++      .bt_afh_span_bw40 = 0x30,
++      .afh_5g_num = 0,
++      .afh_5g = NULL,
++      .coex_info_hw_regs_num = 0,
++      .coex_info_hw_regs = NULL,
++};
++EXPORT_SYMBOL(rtw8812a_hw_spec);
++
++MODULE_FIRMWARE("rtw88/rtw8812a_fw.bin");
++
++MODULE_AUTHOR("Realtek Corporation");
++MODULE_DESCRIPTION("Realtek 802.11ac wireless 8812a driver");
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null
++++ b/drivers/net/wireless/realtek/rtw88/rtw8812a.h
+@@ -0,0 +1,10 @@
++/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
++/* Copyright(c) 2024  Realtek Corporation
++ */
++
++#ifndef __RTW8812A_H__
++#define __RTW8812A_H__
++
++extern const struct rtw_chip_info rtw8812a_hw_spec;
++
++#endif
diff --git a/package/kernel/mac80211/patches/rtl/044-v6.13-wifi-rtw88-Add-rtw8821au.c-and-rtw8812au.c.patch b/package/kernel/mac80211/patches/rtl/044-v6.13-wifi-rtw88-Add-rtw8821au.c-and-rtw8812au.c.patch
new file mode 100644 (file)
index 0000000..a37f131
--- /dev/null
@@ -0,0 +1,80 @@
+From 8f82bb2cfaf7b8992e0e8493cb765138254f87c9 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 30 Oct 2024 20:29:28 +0200
+Subject: [PATCH] wifi: rtw88: Add rtw8821au.c and rtw8812au.c
+
+These are the entry points for the new modules rtw88_8821au
+(RTL8821AU/RTL8811AU) and rtw88_8812au (RTL8812AU).
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/91c495f8-a607-429b-8bc0-5a45d3c1393e@gmail.com
+---
+ .../net/wireless/realtek/rtw88/rtw8812au.c    | 28 +++++++++++++++++++
+ .../net/wireless/realtek/rtw88/rtw8821au.c    | 28 +++++++++++++++++++
+ 2 files changed, 56 insertions(+)
+ create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8812au.c
+ create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821au.c
+
+--- /dev/null
++++ b/drivers/net/wireless/realtek/rtw88/rtw8812au.c
+@@ -0,0 +1,28 @@
++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
++/* Copyright(c) 2024  Realtek Corporation
++ */
++
++#include <linux/module.h>
++#include <linux/usb.h>
++#include "main.h"
++#include "rtw8812a.h"
++#include "usb.h"
++
++static const struct usb_device_id rtw_8812au_id_table[] = {
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2604, 0x0012, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) },
++      {},
++};
++MODULE_DEVICE_TABLE(usb, rtw_8812au_id_table);
++
++static struct usb_driver rtw_8812au_driver = {
++      .name = "rtw_8812au",
++      .id_table = rtw_8812au_id_table,
++      .probe = rtw_usb_probe,
++      .disconnect = rtw_usb_disconnect,
++};
++module_usb_driver(rtw_8812au_driver);
++
++MODULE_AUTHOR("Bitterblue Smith <rtl8821cerfe2@gmail.com>");
++MODULE_DESCRIPTION("Realtek 802.11ac wireless 8812au driver");
++MODULE_LICENSE("Dual BSD/GPL");
+--- /dev/null
++++ b/drivers/net/wireless/realtek/rtw88/rtw8821au.c
+@@ -0,0 +1,28 @@
++// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
++/* Copyright(c) 2024  Realtek Corporation
++ */
++
++#include <linux/module.h>
++#include <linux/usb.h>
++#include "main.h"
++#include "rtw8821a.h"
++#include "usb.h"
++
++static const struct usb_device_id rtw_8821au_id_table[] = {
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x011e, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) },
++      {},
++};
++MODULE_DEVICE_TABLE(usb, rtw_8821au_id_table);
++
++static struct usb_driver rtw_8821au_driver = {
++      .name = "rtw_8821au",
++      .id_table = rtw_8821au_id_table,
++      .probe = rtw_usb_probe,
++      .disconnect = rtw_usb_disconnect,
++};
++module_usb_driver(rtw_8821au_driver);
++
++MODULE_AUTHOR("Bitterblue Smith <rtl8821cerfe2@gmail.com>");
++MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821au/8811au driver");
++MODULE_LICENSE("Dual BSD/GPL");
diff --git a/package/kernel/mac80211/patches/rtl/045-v6.13-wifi-rtw88-Enable-the-new-RTL8821AU-RTL8812AU-driver.patch b/package/kernel/mac80211/patches/rtl/045-v6.13-wifi-rtw88-Enable-the-new-RTL8821AU-RTL8812AU-driver.patch
new file mode 100644 (file)
index 0000000..6a4a2af
--- /dev/null
@@ -0,0 +1,153 @@
+From 0e3e8284f8e1bf2fc0f7bf247194efe5cfc568c1 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Wed, 30 Oct 2024 20:31:28 +0200
+Subject: [PATCH] wifi: rtw88: Enable the new RTL8821AU/RTL8812AU drivers
+
+These are older Wifi 5 chips. RTL8821AU is 1x1, with or without
+Bluetooth. RTL8812AU is 2x2, without Bluetooth.
+
+Beamforming is not implemented. It looks like these chips need a
+different implementation than what is in bf.c.
+
+Speed tests with RTL8821AU: 137 Mbps download, 144 Mbps upload.
+Speed tests with RTL8812AU: 344 Mbps download, 387 Mbps upload.
+
+Station mode and AP mode were tested.
+
+Bluetooth coexistence works. I used my Bluetooth headphones for
+several days, listening to music and watching videos. There is only
+a problem with the wifi speeds with one router:
+
+With ISP's HG6544C router:
+Official driver: 3/5 Mbps.
+rtw88: a bit more, but not steady at all. Not enough to watch a 1080p
+Youtube video.
+
+With my D-Link Eagle R32 router running Openwrt, on the same channel:
+Official driver: 6/10 Mbps.
+rtw88: download starts around 30, climbs to 50 / upload is 10 Mbps.
+I can watch a 1080p Youtube video.
+
+The music doesn't cut out during any speed tests.
+
+I also tested transferring files to and from my phone. I don't have
+other types of Bluetooth devices to test.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Link: https://patch.msgid.link/0b8e8093-8103-4999-86bf-0055ec52ea64@gmail.com
+---
+Kconfig.local                               | 15 ++++++++
+ drivers/net/wireless/realtek/rtw88/Kconfig  | 40 ++++++++++++++++++++-
+ drivers/net/wireless/realtek/rtw88/Makefile | 15 ++++++++
+ 3 files changed, 69 insertions(+), 1 deletion(-)
+
+--- a/Kconfig.local
++++ b/Kconfig.local
+@@ -1144,6 +1144,15 @@ config BACKPORTED_RTW88_8723D
+ config BACKPORTED_RTW88_8821C
+       tristate
+       default RTW88_8821C
++config BACKPORTED_RTW88_88XXA
++      tristate
++      default RTW88_88XXA
++config BACKPORTED_RTW88_8821A
++      tristate
++      default RTW88_8821A
++config BACKPORTED_RTW88_8812A
++      tristate
++      default RTW88_8812A
+ config BACKPORTED_RTW88_8822BE
+       tristate
+       default RTW88_8822BE
+@@ -1183,6 +1192,12 @@ config BACKPORTED_RTW88_8821CS
+ config BACKPORTED_RTW88_8821CU
+       tristate
+       default RTW88_8821CU
++config BACKPORTED_RTW88_8821AU
++      tristate
++      default RTW88_8821AU
++config BACKPORTED_RTW88_8812AU
++      tristate
++      default RTW88_8812AU
+ config BACKPORTED_RTW88_DEBUG
+       tristate
+       default RTW88_DEBUG
+--- a/drivers/net/wireless/realtek/rtw88/Kconfig
++++ b/drivers/net/wireless/realtek/rtw88/Kconfig
+@@ -54,6 +54,20 @@ config RTW88_8821C
+       tristate
+       depends on m
++config RTW88_88XXA
++      tristate
++      depends on m
++
++config RTW88_8821A
++      tristate
++      depends on m
++      select RTW88_88XXA
++
++config RTW88_8812A
++      tristate
++      depends on m
++      select RTW88_88XXA
++
+ config RTW88_8822BE
+       tristate "Realtek 8822BE PCI wireless network adapter"
+       depends on m
+@@ -213,6 +227,30 @@ config RTW88_8821CU
+         802.11ac USB wireless network adapter
++config RTW88_8821AU
++      tristate "Realtek 8821AU/8811AU USB wireless network adapter"
++      depends on m
++      depends on USB
++      select RTW88_CORE
++      select RTW88_USB
++      select RTW88_8821A
++      help
++        Select this option will enable support for 8821AU and 8811AU chipset
++
++        802.11ac USB wireless network adapter
++
++config RTW88_8812AU
++      tristate "Realtek 8812AU USB wireless network adapter"
++      depends on m
++      depends on USB
++      select RTW88_CORE
++      select RTW88_USB
++      select RTW88_8812A
++      help
++        Select this option will enable support for 8812AU chipset
++
++        802.11ac USB wireless network adapter
++
+ config RTW88_DEBUG
+       bool "Realtek rtw88 debug support"
+       depends on RTW88_CORE
+--- a/drivers/net/wireless/realtek/rtw88/Makefile
++++ b/drivers/net/wireless/realtek/rtw88/Makefile
+@@ -77,6 +77,21 @@ rtw88_8821cs-objs           := rtw8821cs.o
+ obj-$(CPTCFG_RTW88_8821CU)    += rtw88_8821cu.o
+ rtw88_8821cu-objs             := rtw8821cu.o
++obj-$(CPTCFG_RTW88_88XXA)     += rtw88_88xxa.o
++rtw88_88xxa-objs              := rtw88xxa.o
++
++obj-$(CPTCFG_RTW88_8821A)     += rtw88_8821a.o
++rtw88_8821a-objs              := rtw8821a.o rtw8821a_table.o
++
++obj-$(CPTCFG_RTW88_8812A)     += rtw88_8812a.o
++rtw88_8812a-objs              := rtw8812a.o rtw8812a_table.o
++
++obj-$(CPTCFG_RTW88_8821AU)    += rtw88_8821au.o
++rtw88_8821au-objs             := rtw8821au.o
++
++obj-$(CPTCFG_RTW88_8812AU)    += rtw88_8812au.o
++rtw88_8812au-objs             := rtw8812au.o
++
+ obj-$(CPTCFG_RTW88_PCI)               += rtw88_pci.o
+ rtw88_pci-objs                        := pci.o
diff --git a/package/kernel/mac80211/patches/rtl/046-wifi-rtw88-8821au-Add-additional-devices-to-the-USB_.patch b/package/kernel/mac80211/patches/rtl/046-wifi-rtw88-8821au-Add-additional-devices-to-the-USB_.patch
new file mode 100644 (file)
index 0000000..a83094b
--- /dev/null
@@ -0,0 +1,77 @@
+From ff5a1c94e53c0d24f610c2c30add82f75b728737 Mon Sep 17 00:00:00 2001
+From: Larry Finger <Larry.Finger@gmail.com>
+Date: Wed, 6 Nov 2024 15:55:31 +0200
+Subject: [PATCH 1/6] wifi: rtw88: 8821au: Add additional devices to the
+ USB_DEVICE list
+
+These are the entries that Nick Morrow provided. From
+https://github.com/morrownr/8821au-20210708
+
+Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+---
+ .../net/wireless/realtek/rtw88/rtw8821au.c    | 52 ++++++++++++++++++-
+ 1 file changed, 51 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/rtw8821au.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8821au.c
+@@ -9,8 +9,58 @@
+ #include "usb.h"
+ static const struct usb_device_id rtw_8821au_id_table[] = {
+-      { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x011e, 0xff, 0xff, 0xff),
++      { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x0811, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) },
++      { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x0820, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) },
++      { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x0821, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) },
++      { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8822, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) },
++      { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x0823, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) },
++      { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xa811, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) },
++      { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x0242, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Buffalo */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x029b, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Buffalo */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x0953, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* I-O DATA */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x4007, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* ELECOM */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x400e, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* ELECOM */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x400f, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* ELECOM */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9052, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Netgear */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0023, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* HAWKING */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3314, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* D-Link */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3318, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* D-Link */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab32, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Planex */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x804b, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* TRENDnet */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x011e, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* TP Link */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x011f, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* TP Link */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0120, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* TP Link */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x3823, 0x6249, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Obihai */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa811, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Edimax */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa812, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Edimax */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa813, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Edimax */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xb611, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Edimax */
+       {},
+ };
+ MODULE_DEVICE_TABLE(usb, rtw_8821au_id_table);
diff --git a/package/kernel/mac80211/patches/rtl/047-wifi-rtw88-8812au-Add-more-device-IDs.patch b/package/kernel/mac80211/patches/rtl/047-wifi-rtw88-8812au-Add-more-device-IDs.patch
new file mode 100644 (file)
index 0000000..a93f921
--- /dev/null
@@ -0,0 +1,91 @@
+From d21ad2e4edfb64d3f32685607a457576eea3c5cd Mon Sep 17 00:00:00 2001
+From: Nick Morrow <usbwifi2024@gmail.com>
+Date: Wed, 6 Nov 2024 15:57:10 +0200
+Subject: [PATCH 2/6] wifi: rtw88: 8812au: Add more device IDs
+
+From https://github.com/morrownr/8812au-20210820.
+
+Signed-off-by: Nick Morrow <usbwifi2024@gmail.com>
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+---
+ .../net/wireless/realtek/rtw88/rtw8812au.c    | 68 ++++++++++++++++++-
+ 1 file changed, 67 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/rtw8812au.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8812au.c
+@@ -9,8 +9,74 @@
+ #include "usb.h"
+ static const struct usb_device_id rtw_8812au_id_table[] = {
+-      { USB_DEVICE_AND_INTERFACE_INFO(0x2604, 0x0012, 0xff, 0xff, 0xff),
++      { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8812, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) },
++      { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x881a, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) },
++      { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x881b, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) },
++      { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x881c, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) },
++      { USB_DEVICE_AND_INTERFACE_INFO(0x0409, 0x0408, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* NEC */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x025d, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Buffalo */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x0952, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* I-O DATA */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1106, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Belkin */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1109, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Belkin */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x0586, 0x3426, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* ZyXEL */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x0789, 0x016e, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Logitec */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8812, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Abocom */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9051, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Netgear */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x17d2, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* ASUS */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0074, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Sitecom */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0022, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Hawking */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x1058, 0x0632, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* WD */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x003f, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Linksys */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x148f, 0x9097, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Amped Wireless */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x1740, 0x0100, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* EnGenius */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330e, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* D-Link */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3313, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* D-Link */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3315, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* D-Link */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3316, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* D-Link */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab30, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Planex */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x805b, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TRENDnet */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0101, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0103, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x010d, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x010e, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x010f, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0122, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2604, 0x0012, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Tenda */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa822, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Edimax */
+       {},
+ };
+ MODULE_DEVICE_TABLE(usb, rtw_8812au_id_table);
diff --git a/package/kernel/mac80211/patches/rtl/048-wifi-rtw88-usb-Support-USB-3-with-RTL8812AU.patch b/package/kernel/mac80211/patches/rtl/048-wifi-rtw88-usb-Support-USB-3-with-RTL8812AU.patch
new file mode 100644 (file)
index 0000000..2ccefb9
--- /dev/null
@@ -0,0 +1,69 @@
+From 213dfa630285bb0241f3eaeb778db8ff128f10ba Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Fri, 8 Nov 2024 01:41:08 +0200
+Subject: [PATCH 3/6] wifi: rtw88: usb: Support USB 3 with RTL8812AU
+
+Add the function to automatically switch the RTL8812AU into USB 3 mode.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+---
+ drivers/net/wireless/realtek/rtw88/usb.c | 34 ++++++++++++++++++++++--
+ 1 file changed, 32 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/realtek/rtw88/usb.c
++++ b/drivers/net/wireless/realtek/rtw88/usb.c
+@@ -929,6 +929,32 @@ static void rtw_usb_intf_deinit(struct r
+       usb_set_intfdata(intf, NULL);
+ }
++static int rtw_usb_switch_mode_old(struct rtw_dev *rtwdev)
++{
++      struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
++      enum usb_device_speed cur_speed = rtwusb->udev->speed;
++      u8 hci_opt;
++
++      if (cur_speed == USB_SPEED_HIGH) {
++              hci_opt = rtw_read8(rtwdev, REG_HCI_OPT_CTRL);
++
++              if ((hci_opt & (BIT(2) | BIT(3))) != BIT(3)) {
++                      rtw_write8(rtwdev, REG_HCI_OPT_CTRL, 0x8);
++                      rtw_write8(rtwdev, REG_SYS_SDIO_CTRL, 0x2);
++                      rtw_write8(rtwdev, REG_ACLK_MON, 0x1);
++                      rtw_write8(rtwdev, 0x3d, 0x3);
++                      /* usb disconnect */
++                      rtw_write8(rtwdev, REG_SYS_PW_CTRL + 1, 0x80);
++                      return 1;
++              }
++      } else if (cur_speed == USB_SPEED_SUPER) {
++              rtw_write8_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT(1));
++              rtw_write8_clr(rtwdev, REG_ACLK_MON, BIT(0));
++      }
++
++      return 0;
++}
++
+ static int rtw_usb_switch_mode_new(struct rtw_dev *rtwdev)
+ {
+       enum usb_device_speed cur_speed;
+@@ -982,7 +1008,8 @@ static int rtw_usb_switch_mode(struct rt
+ {
+       u8 id = rtwdev->chip->id;
+-      if (id != RTW_CHIP_TYPE_8822C && id != RTW_CHIP_TYPE_8822B)
++      if (id != RTW_CHIP_TYPE_8822C && id != RTW_CHIP_TYPE_8822B &&
++          id != RTW_CHIP_TYPE_8812A)
+               return 0;
+       if (!rtwdev->efuse.usb_mode_switch) {
+@@ -997,7 +1024,10 @@ static int rtw_usb_switch_mode(struct rt
+               return 0;
+       }
+-      return rtw_usb_switch_mode_new(rtwdev);
++      if (id == RTW_CHIP_TYPE_8812A)
++              return rtw_usb_switch_mode_old(rtwdev);
++      else /* RTL8822CU, RTL8822BU */
++              return rtw_usb_switch_mode_new(rtwdev);
+ }
+ int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
diff --git a/package/kernel/mac80211/patches/rtl/049-wifi-rtw88-usb-Enable-RX-aggregation-for-8821au-8812.patch b/package/kernel/mac80211/patches/rtl/049-wifi-rtw88-usb-Enable-RX-aggregation-for-8821au-8812.patch
new file mode 100644 (file)
index 0000000..00775c0
--- /dev/null
@@ -0,0 +1,65 @@
+From 2b38362bd3b8e0a3691f0a8e82444a54f702e384 Mon Sep 17 00:00:00 2001
+From: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+Date: Fri, 8 Nov 2024 01:43:50 +0200
+Subject: [PATCH 4/6] wifi: rtw88: usb: Enable RX aggregation for 8821au/8812au
+
+USB RX aggregation improves the RX speed on certain ARM systems, like
+the NanoPi NEO Core2. With RTL8811AU, before: 30 Mbps, after: 224 Mbps.
+
+The out-of-tree driver uses aggregation size of 7 in USB 3 mode, but
+that doesn't work here. rtw88 advertises support for receiving AMSDU
+in AMPDU, so the AP sends larger frames, up to ~5100 bytes. With a size
+of 7 RTL8812AU frequently tries to aggregate more frames than will fit
+in 32768 bytes. Use a size of 6 instead.
+
+Signed-off-by: Bitterblue Smith <rtl8821cerfe2@gmail.com>
+---
+ drivers/net/wireless/realtek/rtw88/usb.c | 30 ++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+--- a/drivers/net/wireless/realtek/rtw88/usb.c
++++ b/drivers/net/wireless/realtek/rtw88/usb.c
+@@ -788,6 +788,32 @@ static void rtw_usb_dynamic_rx_agg_v1(st
+       rtw_write16(rtwdev, REG_RXDMA_AGG_PG_TH, val16);
+ }
++static void rtw_usb_dynamic_rx_agg_v2(struct rtw_dev *rtwdev, bool enable)
++{
++      struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
++      u8 size, timeout;
++      u16 val16;
++
++      if (rtwusb->udev->speed == USB_SPEED_SUPER) {
++              size = 0x6;
++              timeout = 0x1a;
++      } else {
++              size = 0x5;
++              timeout = 0x20;
++      }
++
++      if (!enable) {
++              size = 0x0;
++              timeout = 0x1;
++      }
++
++      val16 = u16_encode_bits(size, BIT_RXDMA_AGG_PG_TH) |
++              u16_encode_bits(timeout, BIT_DMA_AGG_TO_V1);
++
++      rtw_write16(rtwdev, REG_RXDMA_AGG_PG_TH, val16);
++      rtw_write8_set(rtwdev, REG_TXDMA_PQ_MAP, BIT_RXDMA_AGG_EN);
++}
++
+ static void rtw_usb_dynamic_rx_agg(struct rtw_dev *rtwdev, bool enable)
+ {
+       switch (rtwdev->chip->id) {
+@@ -796,6 +822,10 @@ static void rtw_usb_dynamic_rx_agg(struc
+       case RTW_CHIP_TYPE_8821C:
+               rtw_usb_dynamic_rx_agg_v1(rtwdev, enable);
+               break;
++      case RTW_CHIP_TYPE_8821A:
++      case RTW_CHIP_TYPE_8812A:
++              rtw_usb_dynamic_rx_agg_v2(rtwdev, enable);
++              break;
+       case RTW_CHIP_TYPE_8723D:
+               /* Doesn't like aggregation. */
+               break;
diff --git a/package/kernel/mac80211/patches/rtl/050-wifi-rtlwifi-rtl8821ae-phy-restore-removed-code-to-f.patch b/package/kernel/mac80211/patches/rtl/050-wifi-rtlwifi-rtl8821ae-phy-restore-removed-code-to-f.patch
new file mode 100644 (file)
index 0000000..798a593
--- /dev/null
@@ -0,0 +1,32 @@
+From 927dcd0ab53f39ee00a2d1f204b5aac77e28fcf9 Mon Sep 17 00:00:00 2001
+From: Colin Ian King <colin.i.king@gmail.com>
+Date: Wed, 6 Nov 2024 15:46:42 +0000
+Subject: [PATCH 5/6] wifi: rtlwifi: rtl8821ae: phy: restore removed code to
+ fix infinite loop
+
+A previous clean-up fix removed the assignment of v2 inside a while loop
+that turned it into an infinite loop. Fix this by restoring the assignment
+of v2 from array[] so that v2 is updated inside the loop.
+
+Fixes: cda37445718d ("wifi: rtlwifi: rtl8821ae: phy: remove some useless code")
+Signed-off-by: Colin Ian King <colin.i.king@gmail.com>
+Tested-by: Ping-Ke Shih <pkshih@realtek.com>
+Reviewed-by: Su Hui <suhui@nfschina.com>
+---
+ drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
++++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
+@@ -2033,8 +2033,10 @@ static bool _rtl8821ae_phy_config_bb_wit
+                       if (!_rtl8821ae_check_condition(hw, v1)) {
+                               i += 2; /* skip the pair of expression*/
+                               v2 = array[i+1];
+-                              while (v2 != 0xDEAD)
++                              while (v2 != 0xDEAD) {
+                                       i += 3;
++                                      v2 = array[i + 1];
++                              }
+                       }
+               }
+       }
diff --git a/package/kernel/mac80211/patches/rtl/051-wifi-rtw88-Add-additional-USB-IDs-for-RTL8812BU.patch b/package/kernel/mac80211/patches/rtl/051-wifi-rtw88-Add-additional-USB-IDs-for-RTL8812BU.patch
new file mode 100644 (file)
index 0000000..e4e26c7
--- /dev/null
@@ -0,0 +1,31 @@
+From acadf3a63b39ad03167a633fa3cea8c0fc2ab87f Mon Sep 17 00:00:00 2001
+From: Nick Morrow <usbwifi2024@gmail.com>
+Date: Thu, 7 Nov 2024 08:28:46 +0800
+Subject: [PATCH 6/6] wifi: rtw88: Add additional USB IDs for RTL8812BU
+
+Add three additional USB IDs found in
+https://github.com/morrownr/88x2bu-20210702
+to support more RTL8812BU devices.
+
+Signed-off-by: Nick Morrow <usbwifi2024@gmail.com>
+Signed-off-by: Zenm Chen <zenmchen@gmail.com>
+Signed-off-by: Mikhail Novosyolov <m.novosyolov@rosalinux.ru>
+---
+ drivers/net/wireless/realtek/rtw88/rtw8822bu.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/net/wireless/realtek/rtw88/rtw8822bu.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8822bu.c
+@@ -67,6 +67,12 @@ static const struct usb_device_id rtw_88
+         .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* LiteOn */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x808a, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TRENDnet TEW-808UBM */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x805a, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TRENDnet TEW-805UBH */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x4011, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ELECOM WDB-867DU3S */
++      { USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x0107, 0xff, 0xff, 0xff),
++        .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Mercusys MA30H */
+       {},
+ };
+ MODULE_DEVICE_TABLE(usb, rtw_8822bu_id_table);