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>
(cherry picked from commit 36f6d6ddcd)
		
	
		
			
				
	
	
		
			2188 lines
		
	
	
		
			63 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			2188 lines
		
	
	
		
			63 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
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
 |