From patchwork Thu May 7 04:21:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tony Chuang X-Patchwork-Id: 11532385 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 904BC1392 for ; Thu, 7 May 2020 04:22:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 834532082E for ; Thu, 7 May 2020 04:22:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725914AbgEGEWQ (ORCPT ); Thu, 7 May 2020 00:22:16 -0400 Received: from rtits2.realtek.com ([211.75.126.72]:34092 "EHLO rtits2.realtek.com.tw" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725809AbgEGEWQ (ORCPT ); Thu, 7 May 2020 00:22:16 -0400 Authenticated-By: X-SpamFilter-By: ArmorX SpamTrap 5.69 with qID 0474LvomE027273, This message is accepted by code: ctloc85258 Received: from mail.realtek.com (rtexmb06.realtek.com.tw[172.21.6.99]) by rtits2.realtek.com.tw (8.15.2/2.66/5.86) with ESMTPS id 0474LvomE027273 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Thu, 7 May 2020 12:21:57 +0800 Received: from RTEXMB04.realtek.com.tw (172.21.6.97) by RTEXMB06.realtek.com.tw (172.21.6.99) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1779.2; Thu, 7 May 2020 12:21:56 +0800 Received: from localhost.localdomain (172.21.68.128) by RTEXMB04.realtek.com.tw (172.21.6.97) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1779.2; Thu, 7 May 2020 12:21:56 +0800 From: To: CC: , , Subject: [PATCH v2 1/9] rtw88: 8723d: Add LC calibration Date: Thu, 7 May 2020 12:21:43 +0800 Message-ID: <20200507042151.15634-2-yhchuang@realtek.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200507042151.15634-1-yhchuang@realtek.com> References: <20200507042151.15634-1-yhchuang@realtek.com> MIME-Version: 1.0 X-Originating-IP: [172.21.68.128] X-ClientProxiedBy: RTEXMB02.realtek.com.tw (172.21.6.95) To RTEXMB04.realtek.com.tw (172.21.6.97) Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Ping-Ke Shih LC calibration is done by hardware circuit. Driver sets the LCK bit to kick start, and then poll the bit to check if it's done. Signed-off-by: Ping-Ke Shih Signed-off-by: Yan-Hsuan Chuang --- drivers/net/wireless/realtek/rtw88/main.h | 1 + drivers/net/wireless/realtek/rtw88/rtw8723d.c | 31 +++++++++++++++++++ drivers/net/wireless/realtek/rtw88/rtw8723d.h | 3 ++ 3 files changed, 35 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index e0365a70c6f7..c5046986f9af 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "util.h" diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c index 92c742d1ce6d..0f5ddd41b019 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c @@ -64,6 +64,34 @@ static const struct rtw_hw_reg rtw8723d_txagc[] = { #define WLAN_LTR_CTRL1 0xCB004010 #define WLAN_LTR_CTRL2 0x01233425 +static void rtw8723d_lck(struct rtw_dev *rtwdev) +{ + u32 lc_cal; + u8 val_ctx, rf_val; + int ret; + + val_ctx = rtw_read8(rtwdev, REG_CTX); + if ((val_ctx & BIT_MASK_CTX_TYPE) != 0) + rtw_write8(rtwdev, REG_CTX, val_ctx & ~BIT_MASK_CTX_TYPE); + else + rtw_write8(rtwdev, REG_TXPAUSE, 0xFF); + lc_cal = rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK); + + rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal | BIT_LCK); + + ret = read_poll_timeout(rtw_read_rf, rf_val, rf_val != 0x1, + 10000, 1000000, false, + rtwdev, RF_PATH_A, RF_CFGCH, BIT_LCK); + if (ret) + rtw_warn(rtwdev, "failed to poll LCK status bit\n"); + + rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal); + if ((val_ctx & BIT_MASK_CTX_TYPE) != 0) + rtw_write8(rtwdev, REG_CTX, val_ctx); + else + rtw_write8(rtwdev, REG_TXPAUSE, 0x00); +} + static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev) { u8 xtal_cap; @@ -125,6 +153,9 @@ static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev) rtw_phy_init(rtwdev); rtw_write16_set(rtwdev, REG_TXDMA_OFFSET_CHK, BIT_DROP_DATA_EN); + + rtw8723d_lck(rtwdev); + rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x50); rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x20); } diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h index ac66f672bec8..6a7d58992df5 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h @@ -78,6 +78,7 @@ struct rtw8723d_efuse { #define RFCFGCH_BW_20M (BIT(11) | BIT(10)) #define RFCFGCH_BW_40M BIT(10) #define BIT_MASK_RFMOD BIT(0) +#define BIT_LCK BIT(15) #define REG_PSDFN 0x0808 #define REG_ANALOG_P4 0x088c @@ -115,6 +116,8 @@ struct rtw8723d_efuse { #define REG_OFDM_FA_RSTD_11N 0x0d00 #define BIT_MASK_OFDM_FA_RST1 BIT(27) #define BIT_MASK_OFDM_FA_KEEP1 BIT(31) +#define REG_CTX 0x0d03 +#define BIT_MASK_CTX_TYPE GENMASK(6, 4) #define REG_OFDM1_CFOTRK 0x0d2c #define BIT_EN_CFOTRK BIT(28) #define REG_OFDM1_CSI1 0x0d40 From patchwork Thu May 7 04:21:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tony Chuang X-Patchwork-Id: 11532379 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 13ADD18E8 for ; Thu, 7 May 2020 04:22:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E79192082E for ; Thu, 7 May 2020 04:22:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725841AbgEGEWJ (ORCPT ); Thu, 7 May 2020 00:22:09 -0400 Received: from rtits2.realtek.com ([211.75.126.72]:34083 "EHLO rtits2.realtek.com.tw" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725783AbgEGEWI (ORCPT ); Thu, 7 May 2020 00:22:08 -0400 Authenticated-By: X-SpamFilter-By: ArmorX SpamTrap 5.69 with qID 0474Lv4yA027277, This message is accepted by code: ctloc85258 Received: from mail.realtek.com (rtexmb06.realtek.com.tw[172.21.6.99]) by rtits2.realtek.com.tw (8.15.2/2.66/5.86) with ESMTPS id 0474Lv4yA027277 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Thu, 7 May 2020 12:21:57 +0800 Received: from RTEXMB04.realtek.com.tw (172.21.6.97) by RTEXMB06.realtek.com.tw (172.21.6.99) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1779.2; Thu, 7 May 2020 12:21:57 +0800 Received: from localhost.localdomain (172.21.68.128) by RTEXMB04.realtek.com.tw (172.21.6.97) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1779.2; Thu, 7 May 2020 12:21:56 +0800 From: To: CC: , , Subject: [PATCH v2 2/9] rtw88: 8723d: add IQ calibration Date: Thu, 7 May 2020 12:21:44 +0800 Message-ID: <20200507042151.15634-3-yhchuang@realtek.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200507042151.15634-1-yhchuang@realtek.com> References: <20200507042151.15634-1-yhchuang@realtek.com> MIME-Version: 1.0 X-Originating-IP: [172.21.68.128] X-ClientProxiedBy: RTEXMB02.realtek.com.tw (172.21.6.95) To RTEXMB04.realtek.com.tw (172.21.6.97) Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Ping-Ke Shih IQ calibration is used to calibrate RF characteristic to yield expected performance. Basically, we do calibration twice and compare the similarity to determine calibration is good or not, if not we do the third calibration, and then compare with the results of first and second calibration. If it still not similar, IQK is failed. Before doing calibration, we need to backup registers that will be modified in calibration procedure, and restore these registers after calibration is done. A calibration procedure can divided into four sub-procedures that are S1-TX, S1-RX, S0-TX and S0-RX. Where, S1 and S0 represent to path A and B respectively. Each sub-procedure configure proper registers, and then rigger one-shot calibration and poll until completion. For RX calibration, it needs to do twice one-shot calibration, first one is to yield parameter used by second one. The result of TX part is stored for TX power tracking that adjusts TX AGC to output expected power. Signed-off-by: Ping-Ke Shih Signed-off-by: Yan-Hsuan Chuang --- drivers/net/wireless/realtek/rtw88/main.h | 12 + drivers/net/wireless/realtek/rtw88/phy.c | 2 + drivers/net/wireless/realtek/rtw88/reg.h | 10 + drivers/net/wireless/realtek/rtw88/rtw8723d.c | 817 ++++++++++++++++++ drivers/net/wireless/realtek/rtw88/rtw8723d.h | 122 +++ 5 files changed, 963 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index c5046986f9af..af8c50e3687d 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -1400,6 +1400,16 @@ struct rtw_pkt_count { DECLARE_EWMA(evm, 10, 4); DECLARE_EWMA(snr, 10, 4); +struct rtw_iqk_info { + bool done; + struct { + u32 s1_x; + u32 s1_y; + u32 s0_x; + u32 s0_y; + } result; +}; + struct rtw_dm_info { u32 cck_fa_cnt; u32 ofdm_fa_cnt; @@ -1459,6 +1469,8 @@ struct rtw_dm_info { struct rtw_pkt_count last_pkt_count; struct ewma_evm ewma_evm[RTW_EVM_NUM]; struct ewma_snr ewma_snr[RTW_SNR_NUM]; + + struct rtw_iqk_info iqk; }; struct rtw_efuse { diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c index 72a16eff9db3..837b7bd04126 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.c +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -134,6 +134,8 @@ void rtw_phy_init(struct rtw_dev *rtwdev) mask = chip->dig[0].mask; dm_info->igi_history[0] = rtw_read32_mask(rtwdev, addr, mask); rtw_phy_cck_pd_init(rtwdev); + + dm_info->iqk.done = false; } void rtw_phy_dig_write(struct rtw_dev *rtwdev, u8 igi) diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h index 9fdfcdc5c5cf..d57de1a6cdcc 100644 --- a/drivers/net/wireless/realtek/rtw88/reg.h +++ b/drivers/net/wireless/realtek/rtw88/reg.h @@ -69,6 +69,7 @@ #define BIT_DPDT_SEL_EN BIT(23) #define REG_LEDCFG2 0x004E #define REG_PAD_CTRL1 0x0064 +#define BIT_BT_BTG_SEL BIT(31) #define BIT_PAPE_WLBT_SEL BIT(29) #define BIT_LNAON_WLBT_SEL BIT(28) #define BIT_BTGP_JTAG_EN BIT(24) @@ -611,7 +612,10 @@ #define REG_IGN_GNTBT4 0x4160 +#define RF_MODE 0x00 #define RF_MODOPT 0x01 +#define RF_WLINT 0x01 +#define RF_WLSEL 0x02 #define RF_DTXLOK 0x08 #define RF_CFGCH 0x18 #define RF_RCK 0x1d @@ -619,9 +623,15 @@ #define RF_LUTWD1 0x3e #define RF_LUTWD0 0x3f #define RF_T_METER 0x42 +#define RF_BSPAD 0x54 +#define RF_GAINTX 0x56 +#define RF_TXATANK 0x64 +#define RF_TRXIQ 0x66 +#define RF_RXIQGEN 0x8d #define RF_XTALX2 0xb8 #define RF_MALSEL 0xbe #define RF_RCKD 0xde +#define RF_TXADBG 0xde #define RF_LUTDBG 0xdf #define RF_LUTWE2 0xee #define RF_LUTWE 0xef diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c index 0f5ddd41b019..0cfa493e7742 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c @@ -634,6 +634,822 @@ static void rtw8723d_false_alarm_statistics(struct rtw_dev *rtwdev) rtw_write32_mask(rtwdev, REG_PAGE_F_RST_11N, BIT_MASK_F_RST_ALL, 0); } +static const u32 iqk_adda_regs[] = { + 0x85c, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c, + 0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec +}; + +static const u32 iqk_mac8_regs[] = {0x522, 0x550, 0x551}; +static const u32 iqk_mac32_regs[] = {0x40}; + +static const u32 iqk_bb_regs[] = { + 0xc04, 0xc08, 0x874, 0xb68, 0xb6c, 0x870, 0x860, 0x864, 0xa04 +}; + +#define IQK_ADDA_REG_NUM ARRAY_SIZE(iqk_adda_regs) +#define IQK_MAC8_REG_NUM ARRAY_SIZE(iqk_mac8_regs) +#define IQK_MAC32_REG_NUM ARRAY_SIZE(iqk_mac32_regs) +#define IQK_BB_REG_NUM ARRAY_SIZE(iqk_bb_regs) + +struct iqk_backup_regs { + u32 adda[IQK_ADDA_REG_NUM]; + u8 mac8[IQK_MAC8_REG_NUM]; + u32 mac32[IQK_MAC32_REG_NUM]; + u32 bb[IQK_BB_REG_NUM]; + + u32 lte_path; + u32 lte_gnt; + + u32 bb_sel_btg; + u8 btg_sel; + + u8 igia; + u8 igib; +}; + +static void rtw8723d_iqk_backup_regs(struct rtw_dev *rtwdev, + struct iqk_backup_regs *backup) +{ + int i; + + for (i = 0; i < IQK_ADDA_REG_NUM; i++) + backup->adda[i] = rtw_read32(rtwdev, iqk_adda_regs[i]); + + for (i = 0; i < IQK_MAC8_REG_NUM; i++) + backup->mac8[i] = rtw_read8(rtwdev, iqk_mac8_regs[i]); + for (i = 0; i < IQK_MAC32_REG_NUM; i++) + backup->mac32[i] = rtw_read32(rtwdev, iqk_mac32_regs[i]); + + for (i = 0; i < IQK_BB_REG_NUM; i++) + backup->bb[i] = rtw_read32(rtwdev, iqk_bb_regs[i]); + + backup->igia = rtw_read32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0); + backup->igib = rtw_read32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0); + + backup->bb_sel_btg = rtw_read32(rtwdev, REG_BB_SEL_BTG); +} + +static void rtw8723d_iqk_restore_regs(struct rtw_dev *rtwdev, + const struct iqk_backup_regs *backup) +{ + int i; + + for (i = 0; i < IQK_ADDA_REG_NUM; i++) + rtw_write32(rtwdev, iqk_adda_regs[i], backup->adda[i]); + + for (i = 0; i < IQK_MAC8_REG_NUM; i++) + rtw_write8(rtwdev, iqk_mac8_regs[i], backup->mac8[i]); + for (i = 0; i < IQK_MAC32_REG_NUM; i++) + rtw_write32(rtwdev, iqk_mac32_regs[i], backup->mac32[i]); + + for (i = 0; i < IQK_BB_REG_NUM; i++) + rtw_write32(rtwdev, iqk_bb_regs[i], backup->bb[i]); + + rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x50); + rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, backup->igia); + + rtw_write32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0, 0x50); + rtw_write32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0, backup->igib); + + rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x01008c00); + rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x01008c00); +} + +static void rtw8723d_iqk_backup_path_ctrl(struct rtw_dev *rtwdev, + struct iqk_backup_regs *backup) +{ + backup->btg_sel = rtw_read8(rtwdev, REG_BTG_SEL); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] original 0x67 = 0x%x\n", + backup->btg_sel); +} + +static void rtw8723d_iqk_config_path_ctrl(struct rtw_dev *rtwdev) +{ + rtw_write32_mask(rtwdev, REG_PAD_CTRL1, BIT_BT_BTG_SEL, 0x1); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] set 0x67 = 0x%x\n", + rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3)); +} + +static void rtw8723d_iqk_restore_path_ctrl(struct rtw_dev *rtwdev, + const struct iqk_backup_regs *backup) +{ + rtw_write8(rtwdev, REG_BTG_SEL, backup->btg_sel); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] restore 0x67 = 0x%x\n", + rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3)); +} + +static void rtw8723d_iqk_backup_lte_path_gnt(struct rtw_dev *rtwdev, + struct iqk_backup_regs *backup) +{ + backup->lte_path = rtw_read32(rtwdev, REG_LTECOEX_PATH_CONTROL); + rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0x800f0038); + mdelay(1); + backup->lte_gnt = rtw_read32(rtwdev, REG_LTECOEX_READ_DATA); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] OriginalGNT = 0x%x\n", + backup->lte_gnt); +} + +static void rtw8723d_iqk_config_lte_path_gnt(struct rtw_dev *rtwdev) +{ + rtw_write32(rtwdev, REG_LTECOEX_WRITE_DATA, 0x0000ff00); + rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0xc0020038); + rtw_write32_mask(rtwdev, REG_LTECOEX_PATH_CONTROL, BIT_LTE_MUX_CTRL_PATH, 0x1); +} + +static void rtw8723d_iqk_restore_lte_path_gnt(struct rtw_dev *rtwdev, + const struct iqk_backup_regs *bak) +{ + rtw_write32(rtwdev, REG_LTECOEX_WRITE_DATA, bak->lte_gnt); + rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0xc00f0038); + rtw_write32(rtwdev, REG_LTECOEX_PATH_CONTROL, bak->lte_path); +} + +struct rtw_8723d_iqk_cfg { + const char *name; + u32 val_bb_sel_btg; + u32 reg_lutwe; + u32 val_txiqk_pi; + u32 reg_padlut; + u32 reg_gaintx; + u32 reg_bspad; + u32 val_wlint; + u32 val_wlsel; + u32 val_iqkpts; +}; + +static const struct rtw_8723d_iqk_cfg iqk_tx_cfg[PATH_NR] = { + [PATH_S1] = { + .name = "S1", + .val_bb_sel_btg = 0x99000000, + .reg_lutwe = RF_LUTWE, + .val_txiqk_pi = 0x8214019f, + .reg_padlut = RF_LUTDBG, + .reg_gaintx = RF_GAINTX, + .reg_bspad = RF_BSPAD, + .val_wlint = 0xe0d, + .val_wlsel = 0x60d, + .val_iqkpts = 0xfa000000, + }, + [PATH_S0] = { + .name = "S0", + .val_bb_sel_btg = 0x99000280, + .reg_lutwe = RF_LUTWE2, + .val_txiqk_pi = 0x8214018a, + .reg_padlut = RF_TXADBG, + .reg_gaintx = RF_TRXIQ, + .reg_bspad = RF_TXATANK, + .val_wlint = 0xe6d, + .val_wlsel = 0x66d, + .val_iqkpts = 0xf9000000, + }, +}; + +static u8 rtw8723d_iqk_check_tx_failed(struct rtw_dev *rtwdev, + const struct rtw_8723d_iqk_cfg *iqk_cfg) +{ + s32 tx_x, tx_y; + u32 tx_fail; + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0xeac = 0x%x\n", + rtw_read32(rtwdev, REG_IQK_RES_RY)); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0xe94 = 0x%x, 0xe9c = 0x%x\n", + rtw_read32(rtwdev, REG_IQK_RES_TX), + rtw_read32(rtwdev, REG_IQK_RES_TY)); + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] 0xe90(before IQK)= 0x%x, 0xe98(afer IQK) = 0x%x\n", + rtw_read32(rtwdev, 0xe90), + rtw_read32(rtwdev, 0xe98)); + + tx_fail = rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_IQK_TX_FAIL); + tx_x = rtw_read32_mask(rtwdev, REG_IQK_RES_TX, BIT_MASK_RES_TX); + tx_y = rtw_read32_mask(rtwdev, REG_IQK_RES_TY, BIT_MASK_RES_TY); + + if (!tx_fail && tx_x != IQK_TX_X_ERR && tx_y != IQK_TX_Y_ERR) + return IQK_TX_OK; + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] %s TXIQK is failed\n", + iqk_cfg->name); + + return 0; +} + +static u8 rtw8723d_iqk_check_rx_failed(struct rtw_dev *rtwdev, + const struct rtw_8723d_iqk_cfg *iqk_cfg) +{ + s32 rx_x, rx_y; + u32 rx_fail; + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0xea4 = 0x%x, 0xeac = 0x%x\n", + rtw_read32(rtwdev, REG_IQK_RES_RX), + rtw_read32(rtwdev, REG_IQK_RES_RY)); + + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] 0xea0(before IQK)= 0x%x, 0xea8(afer IQK) = 0x%x\n", + rtw_read32(rtwdev, 0xea0), + rtw_read32(rtwdev, 0xea8)); + + rx_fail = rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_IQK_RX_FAIL); + rx_x = rtw_read32_mask(rtwdev, REG_IQK_RES_RX, BIT_MASK_RES_RX); + rx_y = rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_MASK_RES_RY); + rx_y = abs(iqkxy_to_s32(rx_y)); + + if (!rx_fail && rx_x < IQK_RX_X_UPPER && rx_x > IQK_RX_X_LOWER && + rx_y < IQK_RX_Y_LMT) + return IQK_RX_OK; + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] %s RXIQK STEP2 is failed\n", + iqk_cfg->name); + + return 0; +} + +static void rtw8723d_iqk_one_shot(struct rtw_dev *rtwdev, bool tx, + const struct rtw_8723d_iqk_cfg *iqk_cfg) +{ + u32 pts = (tx ? iqk_cfg->val_iqkpts : 0xf9000000); + + /* enter IQK mode */ + rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, EN_IQK); + rtw8723d_iqk_config_lte_path_gnt(rtwdev); + + rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0x800f0054); + mdelay(1); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] GNT_BT @%s %sIQK1 = 0x%x\n", + iqk_cfg->name, tx ? "TX" : "RX", + rtw_read32(rtwdev, REG_LTECOEX_READ_DATA)); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0x948 @%s %sIQK1 = 0x%x\n", + iqk_cfg->name, tx ? "TX" : "RX", + rtw_read32(rtwdev, REG_BB_SEL_BTG)); + + /* One shot, LOK & IQK */ + rtw_write32(rtwdev, REG_IQK_AGC_PTS_11N, pts); + rtw_write32(rtwdev, REG_IQK_AGC_PTS_11N, 0xf8000000); + + if (!check_hw_ready(rtwdev, REG_IQK_RES_RY, BIT_IQK_DONE, 1)) + rtw_warn(rtwdev, "%s %s IQK isn't done\n", iqk_cfg->name, + tx ? "TX" : "RX"); +} + +static void rtw8723d_iqk_txrx_path_post(struct rtw_dev *rtwdev, + const struct rtw_8723d_iqk_cfg *iqk_cfg, + const struct iqk_backup_regs *backup) +{ + rtw8723d_iqk_restore_lte_path_gnt(rtwdev, backup); + rtw_write32(rtwdev, REG_BB_SEL_BTG, backup->bb_sel_btg); + + /* leave IQK mode */ + rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK); + mdelay(1); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_padlut, 0x800, 0x0); + rtw_write_rf(rtwdev, RF_PATH_A, RF_WLINT, BIT(0), 0x0); + rtw_write_rf(rtwdev, RF_PATH_A, RF_WLSEL, BIT(0), 0x0); +} + +static u8 rtw8723d_iqk_tx_path(struct rtw_dev *rtwdev, + const struct rtw_8723d_iqk_cfg *iqk_cfg, + const struct iqk_backup_regs *backup) +{ + u8 status; + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path %s TXIQK!!\n", iqk_cfg->name); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0x67 @%s TXIQK = 0x%x\n", + iqk_cfg->name, + rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3)); + + rtw_write32(rtwdev, REG_BB_SEL_BTG, iqk_cfg->val_bb_sel_btg); + rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK); + mdelay(1); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x80000); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x00004); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD1, RFREG_MASK, 0x0005d); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0xBFFE0); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x00000); + + /* IQK setting */ + rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x08008c0c); + rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x38008c1c); + rtw_write32(rtwdev, REG_TXIQK_PI_A_11N, iqk_cfg->val_txiqk_pi); + rtw_write32(rtwdev, REG_RXIQK_PI_A_11N, 0x28160200); + rtw_write32(rtwdev, REG_TXIQK_11N, 0x01007c00); + rtw_write32(rtwdev, REG_RXIQK_11N, 0x01004800); + + /* LOK setting */ + rtw_write32(rtwdev, REG_IQK_AGC_RSP_11N, 0x00462911); + + /* PA, PAD setting */ + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_padlut, 0x800, 0x1); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_gaintx, 0x600, 0x0); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_gaintx, 0x1E0, 0x3); + rtw_write_rf(rtwdev, RF_PATH_A, RF_RXIQGEN, 0x1F, 0xf); + + /* LOK setting for 8723D */ + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, 0x10, 0x1); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_bspad, 0x1, 0x1); + + rtw_write_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK, iqk_cfg->val_wlint); + rtw_write_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK, iqk_cfg->val_wlsel); + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x1 @%s TXIQK = 0x%x\n", + iqk_cfg->name, + rtw_read_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK)); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x2 @%s TXIQK = 0x%x\n", + iqk_cfg->name, + rtw_read_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK)); + + rtw8723d_iqk_one_shot(rtwdev, true, iqk_cfg); + status = rtw8723d_iqk_check_tx_failed(rtwdev, iqk_cfg); + + rtw8723d_iqk_txrx_path_post(rtwdev, iqk_cfg, backup); + + return status; +} + +static u8 rtw8723d_iqk_rx_path(struct rtw_dev *rtwdev, + const struct rtw_8723d_iqk_cfg *iqk_cfg, + const struct iqk_backup_regs *backup) +{ + u32 tx_x, tx_y; + u8 status; + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path %s RXIQK Step1!!\n", + iqk_cfg->name); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0x67 @%s RXIQK1 = 0x%x\n", + iqk_cfg->name, + rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3)); + rtw_write32(rtwdev, REG_BB_SEL_BTG, iqk_cfg->val_bb_sel_btg); + + rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK); + + /* IQK setting */ + rtw_write32(rtwdev, REG_TXIQK_11N, 0x01007c00); + rtw_write32(rtwdev, REG_RXIQK_11N, 0x01004800); + + /* path IQK setting */ + rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x18008c1c); + rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x38008c1c); + rtw_write32(rtwdev, REG_TX_IQK_TONE_B, 0x38008c1c); + rtw_write32(rtwdev, REG_RX_IQK_TONE_B, 0x38008c1c); + rtw_write32(rtwdev, REG_TXIQK_PI_A_11N, 0x82160000); + rtw_write32(rtwdev, REG_RXIQK_PI_A_11N, 0x28160000); + + /* LOK setting */ + rtw_write32(rtwdev, REG_IQK_AGC_RSP_11N, 0x0046a911); + + /* RXIQK mode */ + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x80000); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x00006); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD1, RFREG_MASK, 0x0005f); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0xa7ffb); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x00000); + + /* PA/PAD=0 */ + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_padlut, 0x800, 0x1); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_gaintx, 0x600, 0x0); + rtw_write_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK, iqk_cfg->val_wlint); + rtw_write_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK, iqk_cfg->val_wlsel); + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x1@ path %s RXIQK1 = 0x%x\n", + iqk_cfg->name, + rtw_read_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK)); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x2@ path %s RXIQK1 = 0x%x\n", + iqk_cfg->name, + rtw_read_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK)); + + rtw8723d_iqk_one_shot(rtwdev, false, iqk_cfg); + status = rtw8723d_iqk_check_tx_failed(rtwdev, iqk_cfg); + + if (!status) + goto restore; + + /* second round */ + tx_x = rtw_read32_mask(rtwdev, REG_IQK_RES_TX, BIT_MASK_RES_TX); + tx_y = rtw_read32_mask(rtwdev, REG_IQK_RES_TY, BIT_MASK_RES_TY); + + rtw_write32(rtwdev, REG_TXIQK_11N, BIT_SET_TXIQK_11N(tx_x, tx_y)); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0xe40 = 0x%x u4tmp = 0x%x\n", + rtw_read32(rtwdev, REG_TXIQK_11N), + BIT_SET_TXIQK_11N(tx_x, tx_y)); + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path %s RXIQK STEP2!!\n", + iqk_cfg->name); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0x67 @%s RXIQK2 = 0x%x\n", + iqk_cfg->name, + rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3)); + + rtw_write32(rtwdev, REG_RXIQK_11N, 0x01004800); + rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x38008c1c); + rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x18008c1c); + rtw_write32(rtwdev, REG_TX_IQK_TONE_B, 0x38008c1c); + rtw_write32(rtwdev, REG_RX_IQK_TONE_B, 0x38008c1c); + rtw_write32(rtwdev, REG_TXIQK_PI_A_11N, 0x82170000); + rtw_write32(rtwdev, REG_RXIQK_PI_A_11N, 0x28171400); + + /* LOK setting */ + rtw_write32(rtwdev, REG_IQK_AGC_RSP_11N, 0x0046a8d1); + + /* RXIQK mode */ + rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK); + mdelay(1); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, 0x80000, 0x1); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x00007); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD1, RFREG_MASK, 0x0005f); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0xb3fdb); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x00000); + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x1 @%s RXIQK2 = 0x%x\n", + iqk_cfg->name, + rtw_read_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK)); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x2 @%s RXIQK2 = 0x%x\n", + iqk_cfg->name, + rtw_read_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK)); + + rtw8723d_iqk_one_shot(rtwdev, false, iqk_cfg); + status |= rtw8723d_iqk_check_rx_failed(rtwdev, iqk_cfg); + +restore: + rtw8723d_iqk_txrx_path_post(rtwdev, iqk_cfg, backup); + + return status; +} + +static +void rtw8723d_iqk_fill_s1_matrix(struct rtw_dev *rtwdev, const s32 result[]) +{ + s32 oldval_1; + s32 x, y; + s32 tx1_a, tx1_a_ext; + s32 tx1_c, tx1_c_ext; + + if (result[IQK_S1_TX_X] == 0) + return; + + oldval_1 = rtw_read32_mask(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE, + BIT_MASK_TXIQ_ELM_D); + + x = iqkxy_to_s32(result[IQK_S1_TX_X]); + tx1_a = iqk_mult(x, oldval_1, &tx1_a_ext); + rtw_write32_mask(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE, + BIT_MASK_TXIQ_ELM_A, tx1_a); + rtw_write32_mask(rtwdev, REG_OFDM_0_ECCA_THRESHOLD, + BIT_MASK_OFDM0_EXT_A, tx1_a_ext); + + y = iqkxy_to_s32(result[IQK_S1_TX_Y]); + tx1_c = iqk_mult(y, oldval_1, &tx1_c_ext); + rtw_write32_mask(rtwdev, REG_TXIQK_MATRIXA_LSB2_11N, MASKH4BITS, + BIT_SET_TXIQ_ELM_C1(tx1_c)); + rtw_write32_mask(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE, + BIT_MASK_TXIQ_ELM_C, BIT_SET_TXIQ_ELM_C2(tx1_c)); + rtw_write32_mask(rtwdev, REG_OFDM_0_ECCA_THRESHOLD, + BIT_MASK_OFDM0_EXT_C, tx1_c_ext); + + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] X = 0x%x, TX1_A = 0x%x, oldval_1 0x%x\n", + x, tx1_a, oldval_1); + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] Y = 0x%x, TX1_C = 0x%x\n", y, tx1_c); + + if (result[IQK_S1_RX_X] == 0) + return; + + rtw_write32_mask(rtwdev, REG_A_RXIQI, BIT_MASK_RXIQ_S1_X, + result[IQK_S1_RX_X]); + rtw_write32_mask(rtwdev, REG_A_RXIQI, BIT_MASK_RXIQ_S1_Y1, + BIT_SET_RXIQ_S1_Y1(result[IQK_S1_RX_Y])); + rtw_write32_mask(rtwdev, REG_RXIQK_MATRIX_LSB_11N, BIT_MASK_RXIQ_S1_Y2, + BIT_SET_RXIQ_S1_Y2(result[IQK_S1_RX_Y])); +} + +static +void rtw8723d_iqk_fill_s0_matrix(struct rtw_dev *rtwdev, const s32 result[]) +{ + s32 oldval_0; + s32 x, y; + s32 tx0_a, tx0_a_ext; + s32 tx0_c, tx0_c_ext; + + if (result[IQK_S0_TX_X] == 0) + return; + + oldval_0 = rtw_read32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_S0); + + x = iqkxy_to_s32(result[IQK_S0_TX_X]); + tx0_a = iqk_mult(x, oldval_0, &tx0_a_ext); + + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_S0, tx0_a); + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_EXT_S0, tx0_a_ext); + + y = iqkxy_to_s32(result[IQK_S0_TX_Y]); + tx0_c = iqk_mult(y, oldval_0, &tx0_c_ext); + + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_S0, tx0_c); + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_EXT_S0, tx0_c_ext); + + if (result[IQK_S0_RX_X] == 0) + return; + + rtw_write32_mask(rtwdev, REG_RXIQ_AB_S0, BIT_MASK_RXIQ_X_S0, + result[IQK_S0_RX_X]); + rtw_write32_mask(rtwdev, REG_RXIQ_AB_S0, BIT_MASK_RXIQ_Y_S0, + result[IQK_S0_RX_Y]); +} + +static void rtw8723d_iqk_path_adda_on(struct rtw_dev *rtwdev) +{ + int i; + + for (i = 0; i < IQK_ADDA_REG_NUM; i++) + rtw_write32(rtwdev, iqk_adda_regs[i], 0x03c00016); +} + +static void rtw8723d_iqk_config_mac(struct rtw_dev *rtwdev) +{ + rtw_write8(rtwdev, REG_TXPAUSE, 0xff); +} + +static +void rtw8723d_iqk_rf_standby(struct rtw_dev *rtwdev, enum rtw_rf_path path) +{ + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path-%s standby mode!\n", + path == RF_PATH_A ? "S1" : "S0"); + + rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK); + mdelay(1); + rtw_write_rf(rtwdev, path, RF_MODE, RFREG_MASK, 0x10000); + rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, EN_IQK); +} + +static +bool rtw8723d_iqk_similarity_cmp(struct rtw_dev *rtwdev, s32 result[][IQK_NR], + u8 c1, u8 c2) +{ + u32 i, j, diff; + u32 bitmap = 0; + u8 candidate[PATH_NR] = {IQK_ROUND_INVALID, IQK_ROUND_INVALID}; + bool ret = true; + + s32 tmp1, tmp2; + + for (i = 0; i < IQK_NR; i++) { + tmp1 = iqkxy_to_s32(result[c1][i]); + tmp2 = iqkxy_to_s32(result[c2][i]); + + diff = abs(tmp1 - tmp2); + + if (diff <= MAX_TOLERANCE) + continue; + + if ((i == IQK_S1_RX_X || i == IQK_S0_RX_X) && !bitmap) { + if (result[c1][i] + result[c1][i + 1] == 0) + candidate[i / IQK_SX_NR] = c2; + else if (result[c2][i] + result[c2][i + 1] == 0) + candidate[i / IQK_SX_NR] = c1; + else + bitmap |= BIT(i); + } else { + bitmap |= BIT(i); + } + } + + if (bitmap != 0) + goto check_sim; + + for (i = 0; i < PATH_NR; i++) { + if (candidate[i] == IQK_ROUND_INVALID) + continue; + + for (j = i * IQK_SX_NR; j < i * IQK_SX_NR + 2; j++) + result[IQK_ROUND_HYBRID][j] = result[candidate[i]][j]; + ret = false; + } + + return ret; + +check_sim: + for (i = 0; i < IQK_NR; i++) { + j = i & ~1; /* 2 bits are a pair for IQ[X, Y] */ + if (bitmap & GENMASK(j + 1, j)) + continue; + + result[IQK_ROUND_HYBRID][i] = result[c1][i]; + } + + return false; +} + +static +void rtw8723d_iqk_precfg_path(struct rtw_dev *rtwdev, enum rtw8723d_path path) +{ + if (path == PATH_S0) { + rtw8723d_iqk_rf_standby(rtwdev, RF_PATH_A); + rtw8723d_iqk_path_adda_on(rtwdev); + } + + rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, EN_IQK); + rtw_write32(rtwdev, REG_TXIQK_11N, 0x01007c00); + rtw_write32(rtwdev, REG_RXIQK_11N, 0x01004800); + + if (path == PATH_S1) { + rtw8723d_iqk_rf_standby(rtwdev, RF_PATH_B); + rtw8723d_iqk_path_adda_on(rtwdev); + } +} + +static +void rtw8723d_iqk_one_round(struct rtw_dev *rtwdev, s32 result[][IQK_NR], u8 t, + const struct iqk_backup_regs *backup) +{ + u32 i; + u8 s1_ok, s0_ok; + + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] IQ Calibration for 1T1R_S0/S1 for %d times\n", t); + + rtw8723d_iqk_path_adda_on(rtwdev); + rtw8723d_iqk_config_mac(rtwdev); + rtw_write32_mask(rtwdev, REG_CCK_ANT_SEL_11N, 0x0f000000, 0xf); + rtw_write32(rtwdev, REG_BB_RX_PATH_11N, 0x03a05611); + rtw_write32(rtwdev, REG_TRMUX_11N, 0x000800e4); + rtw_write32(rtwdev, REG_BB_PWR_SAV1_11N, 0x25204200); + rtw8723d_iqk_precfg_path(rtwdev, PATH_S1); + + for (i = 0; i < PATH_IQK_RETRY; i++) { + s1_ok = rtw8723d_iqk_tx_path(rtwdev, &iqk_tx_cfg[PATH_S1], backup); + if (s1_ok == IQK_TX_OK) { + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] path S1 Tx IQK Success!!\n"); + result[t][IQK_S1_TX_X] = + rtw_read32_mask(rtwdev, REG_IQK_RES_TX, BIT_MASK_RES_TX); + result[t][IQK_S1_TX_Y] = + rtw_read32_mask(rtwdev, REG_IQK_RES_TY, BIT_MASK_RES_TY); + break; + } + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S1 Tx IQK Fail!!\n"); + result[t][IQK_S1_TX_X] = 0x100; + result[t][IQK_S1_TX_Y] = 0x0; + } + + for (i = 0; i < PATH_IQK_RETRY; i++) { + s1_ok = rtw8723d_iqk_rx_path(rtwdev, &iqk_tx_cfg[PATH_S1], backup); + if (s1_ok == (IQK_TX_OK | IQK_RX_OK)) { + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] path S1 Rx IQK Success!!\n"); + result[t][IQK_S1_RX_X] = + rtw_read32_mask(rtwdev, REG_IQK_RES_RX, BIT_MASK_RES_RX); + result[t][IQK_S1_RX_Y] = + rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_MASK_RES_RY); + break; + } + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S1 Rx IQK Fail!!\n"); + result[t][IQK_S1_RX_X] = 0x100; + result[t][IQK_S1_RX_Y] = 0x0; + } + + if (s1_ok == 0x0) + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S1 IQK is failed!!\n"); + + rtw8723d_iqk_precfg_path(rtwdev, PATH_S0); + + for (i = 0; i < PATH_IQK_RETRY; i++) { + s0_ok = rtw8723d_iqk_tx_path(rtwdev, &iqk_tx_cfg[PATH_S0], backup); + if (s0_ok == IQK_TX_OK) { + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] path S0 Tx IQK Success!!\n"); + result[t][IQK_S0_TX_X] = + rtw_read32_mask(rtwdev, REG_IQK_RES_TX, BIT_MASK_RES_TX); + result[t][IQK_S0_TX_Y] = + rtw_read32_mask(rtwdev, REG_IQK_RES_TY, BIT_MASK_RES_TY); + break; + } + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S0 Tx IQK Fail!!\n"); + result[t][IQK_S0_TX_X] = 0x100; + result[t][IQK_S0_TX_Y] = 0x0; + } + + for (i = 0; i < PATH_IQK_RETRY; i++) { + s0_ok = rtw8723d_iqk_rx_path(rtwdev, &iqk_tx_cfg[PATH_S0], backup); + if (s0_ok == (IQK_TX_OK | IQK_RX_OK)) { + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] path S0 Rx IQK Success!!\n"); + + result[t][IQK_S0_RX_X] = + rtw_read32_mask(rtwdev, REG_IQK_RES_RX, BIT_MASK_RES_RX); + result[t][IQK_S0_RX_Y] = + rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_MASK_RES_RY); + break; + } + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S0 Rx IQK Fail!!\n"); + result[t][IQK_S0_RX_X] = 0x100; + result[t][IQK_S0_RX_Y] = 0x0; + } + + if (s0_ok == 0x0) + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S0 IQK is failed!!\n"); + + rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK); + mdelay(1); + + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] back to BB mode, load original value!\n"); +} + +static void rtw8723d_phy_calibration(struct rtw_dev *rtwdev) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + s32 result[IQK_ROUND_SIZE][IQK_NR]; + struct iqk_backup_regs backup; + u8 i, j; + u8 final_candidate = IQK_ROUND_INVALID; + bool good; + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] Start!!!\n"); + + memset(result, 0, sizeof(result)); + + rtw8723d_iqk_backup_path_ctrl(rtwdev, &backup); + rtw8723d_iqk_backup_lte_path_gnt(rtwdev, &backup); + rtw8723d_iqk_backup_regs(rtwdev, &backup); + + for (i = IQK_ROUND_0; i <= IQK_ROUND_2; i++) { + rtw8723d_iqk_config_path_ctrl(rtwdev); + rtw8723d_iqk_config_lte_path_gnt(rtwdev); + + rtw8723d_iqk_one_round(rtwdev, result, i, &backup); + + if (i > IQK_ROUND_0) + rtw8723d_iqk_restore_regs(rtwdev, &backup); + rtw8723d_iqk_restore_lte_path_gnt(rtwdev, &backup); + rtw8723d_iqk_restore_path_ctrl(rtwdev, &backup); + + for (j = IQK_ROUND_0; j < i; j++) { + good = rtw8723d_iqk_similarity_cmp(rtwdev, result, j, i); + + if (good) { + final_candidate = j; + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] cmp %d:%d final_candidate is %x\n", + j, i, final_candidate); + goto iqk_done; + } + } + } + + if (final_candidate == IQK_ROUND_INVALID) { + s32 reg_tmp = 0; + + for (i = 0; i < IQK_NR; i++) + reg_tmp += result[IQK_ROUND_HYBRID][i]; + + if (reg_tmp != 0) { + final_candidate = IQK_ROUND_HYBRID; + } else { + WARN(1, "IQK is failed\n"); + goto out; + } + } + +iqk_done: + rtw8723d_iqk_fill_s1_matrix(rtwdev, result[final_candidate]); + rtw8723d_iqk_fill_s0_matrix(rtwdev, result[final_candidate]); + + dm_info->iqk.result.s1_x = result[final_candidate][IQK_S1_TX_X]; + dm_info->iqk.result.s1_y = result[final_candidate][IQK_S1_TX_Y]; + dm_info->iqk.result.s0_x = result[final_candidate][IQK_S0_TX_X]; + dm_info->iqk.result.s0_y = result[final_candidate][IQK_S0_TX_Y]; + dm_info->iqk.done = true; + +out: + rtw_write32(rtwdev, REG_BB_SEL_BTG, backup.bb_sel_btg); + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] final_candidate is %x\n", + final_candidate); + + for (i = IQK_ROUND_0; i < IQK_ROUND_SIZE; i++) + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] Result %u: rege94_s1=%x rege9c_s1=%x regea4_s1=%x regeac_s1=%x rege94_s0=%x rege9c_s0=%x regea4_s0=%x regeac_s0=%x %s\n", + i, + result[i][0], result[i][1], result[i][2], result[i][3], + result[i][4], result[i][5], result[i][6], result[i][7], + final_candidate == i ? "(final candidate)" : ""); + + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK]0xc80 = 0x%x 0xc94 = 0x%x 0xc14 = 0x%x 0xca0 = 0x%x\n", + rtw_read32(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE), + rtw_read32(rtwdev, REG_TXIQK_MATRIXA_LSB2_11N), + rtw_read32(rtwdev, REG_A_RXIQI), + rtw_read32(rtwdev, REG_RXIQK_MATRIX_LSB_11N)); + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK]0xcd0 = 0x%x 0xcd4 = 0x%x 0xcd8 = 0x%x\n", + rtw_read32(rtwdev, REG_TXIQ_AB_S0), + rtw_read32(rtwdev, REG_TXIQ_CD_S0), + rtw_read32(rtwdev, REG_RXIQ_AB_S0)); + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] finished\n"); +} + static struct rtw_chip_ops rtw8723d_ops = { .phy_set_param = rtw8723d_phy_set_param, .read_efuse = rtw8723d_read_efuse, @@ -647,6 +1463,7 @@ static struct rtw_chip_ops rtw8723d_ops = { .cfg_ldo25 = rtw8723d_cfg_ldo25, .efuse_grant = rtw8723d_efuse_grant, .false_alarm_statistics = rtw8723d_false_alarm_statistics, + .phy_calibration = rtw8723d_phy_calibration, .config_bfee = NULL, .set_gid_table = NULL, .cfg_csi_rate = NULL, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h index 6a7d58992df5..549dfcf7f5da 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h @@ -5,6 +5,34 @@ #ifndef __RTW8723D_H__ #define __RTW8723D_H__ +enum rtw8723d_path { + PATH_S1, + PATH_S0, + PATH_NR, +}; + +enum rtw8723d_iqk_round { + IQK_ROUND_0, + IQK_ROUND_1, + IQK_ROUND_2, + IQK_ROUND_HYBRID, + IQK_ROUND_SIZE, + IQK_ROUND_INVALID = 0xff, +}; + +enum rtw8723d_iqk_result { + IQK_S1_TX_X, + IQK_S1_TX_Y, + IQK_S1_RX_X, + IQK_S1_RX_Y, + IQK_S0_TX_X, + IQK_S0_TX_Y, + IQK_S0_RX_X, + IQK_S0_RX_Y, + IQK_NR, + IQK_SX_NR = IQK_NR / PATH_NR, +}; + struct rtw8723de_efuse { u8 mac_addr[ETH_ALEN]; /* 0xd0 */ u8 vender_id[2]; @@ -66,6 +94,34 @@ struct rtw8723d_efuse { #define GET_PHY_STAT_P1_RXSNR_A(phy_stat) \ le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0)) +static inline s32 iqkxy_to_s32(s32 val) +{ + /* val is Q10.8 */ + return sign_extend32(val, 9); +} + +static inline s32 iqk_mult(s32 x, s32 y, s32 *ext) +{ + /* x, y and return value are Q10.8 */ + s32 t; + + t = x * y; + if (ext) + *ext = (t >> 7) & 0x1; /* Q.16 --> Q.9; get LSB of Q.9 */ + + return (t >> 8); /* Q.16 --> Q.8 */ +} + +#define MAX_TOLERANCE 5 +#define IQK_TX_X_ERR 0x142 +#define IQK_TX_Y_ERR 0x42 +#define IQK_RX_X_UPPER 0x11a +#define IQK_RX_X_LOWER 0xe6 +#define IQK_RX_Y_LMT 0x1a +#define IQK_TX_OK BIT(0) +#define IQK_RX_OK BIT(1) +#define PATH_IQK_RETRY 2 + #define SPUR_THRES 0x16 #define CCK_DFIR_NR 3 #define DIS_3WIRE 0xccf000c0 @@ -80,15 +136,20 @@ struct rtw8723d_efuse { #define BIT_MASK_RFMOD BIT(0) #define BIT_LCK BIT(15) +#define REG_BTG_SEL 0x0067 +#define REG_LTECOEX_PATH_CONTROL 0x0070 #define REG_PSDFN 0x0808 +#define REG_BB_PWR_SAV1_11N 0x0874 #define REG_ANALOG_P4 0x088c #define REG_PSDRPT 0x08b4 #define REG_FPGA1_RFMOD 0x0900 +#define REG_BB_SEL_BTG 0x0948 #define REG_BBRX_DFIR 0x0954 #define BIT_MASK_RXBB_DFIR GENMASK(27, 24) #define BIT_RXBB_DFIR_EN BIT(19) #define REG_CCK0_SYS 0x0a00 #define BIT_CCK_SIDE_BAND BIT(4) +#define REG_CCK_ANT_SEL_11N 0x0a04 #define REG_CCK_FA_RST_11N 0x0a2c #define BIT_MASK_CCK_CNT_KEEP BIT(12) #define BIT_MASK_CCK_CNT_EN BIT(13) @@ -103,13 +164,48 @@ struct rtw8723d_efuse { #define BIT_MASK_CCK_FA_LSB GENMASK(15, 8) #define REG_OFDM_FA_HOLDC_11N 0x0c00 #define BIT_MASK_OFDM_FA_KEEP BIT(31) +#define REG_BB_RX_PATH_11N 0x0c04 +#define REG_TRMUX_11N 0x0c08 #define REG_OFDM_FA_RSTC_11N 0x0c0c #define BIT_MASK_OFDM_FA_RST BIT(31) +#define REG_A_RXIQI 0x0c14 +#define BIT_MASK_RXIQ_S1_X 0x000003FF +#define BIT_MASK_RXIQ_S1_Y1 0x0000FC00 +#define BIT_SET_RXIQ_S1_Y1(y) ((y) & 0x3F) #define REG_OFDM0_RXDSP 0x0c40 #define BIT_MASK_RXDSP GENMASK(28, 24) #define BIT_EN_RXDSP BIT(9) +#define REG_OFDM_0_ECCA_THRESHOLD 0x0c4c +#define BIT_MASK_OFDM0_EXT_A BIT(31) +#define BIT_MASK_OFDM0_EXT_C BIT(29) +#define BIT_MASK_OFDM0_EXTS (BIT(31) | BIT(29) | BIT(28)) +#define BIT_SET_OFDM0_EXTS(a, c, d) (((a) << 31) | ((c) << 29) | ((d) << 28)) #define REG_OFDM0_XAAGC1 0x0c50 #define REG_OFDM0_XBAGC1 0x0c58 +#define REG_OFDM_0_XA_TX_IQ_IMBALANCE 0x0c80 +#define BIT_MASK_TXIQ_ELM_A 0x03ff +#define BIT_SET_TXIQ_ELM_ACD(a, c, d) (((d) << 22) | (((c) & 0x3F) << 16) | \ + ((a) & 0x03ff)) +#define BIT_MASK_TXIQ_ELM_C GENMASK(21, 16) +#define BIT_SET_TXIQ_ELM_C2(c) ((c) & 0x3F) +#define BIT_MASK_TXIQ_ELM_D GENMASK(31, 22) +#define REG_TXIQK_MATRIXA_LSB2_11N 0x0c94 +#define BIT_SET_TXIQ_ELM_C1(c) (((c) & 0x000003C0) >> 6) +#define REG_RXIQK_MATRIX_LSB_11N 0x0ca0 +#define BIT_MASK_RXIQ_S1_Y2 0xF0000000 +#define BIT_SET_RXIQ_S1_Y2(y) (((y) >> 6) & 0xF) +#define REG_TXIQ_AB_S0 0x0cd0 +#define BIT_MASK_TXIQ_A_S0 0x000007FE +#define BIT_MASK_TXIQ_A_EXT_S0 BIT(0) +#define BIT_MASK_TXIQ_B_S0 0x0007E000 +#define REG_TXIQ_CD_S0 0x0cd4 +#define BIT_MASK_TXIQ_C_S0 0x000007FE +#define BIT_MASK_TXIQ_C_EXT_S0 BIT(0) +#define BIT_MASK_TXIQ_D_S0 GENMASK(22, 13) +#define BIT_MASK_TXIQ_D_EXT_S0 BIT(12) +#define REG_RXIQ_AB_S0 0x0cd8 +#define BIT_MASK_RXIQ_X_S0 0x000003FF +#define BIT_MASK_RXIQ_Y_S0 0x003FF000 #define REG_OFDM_FA_TYPE1_11N 0x0cf0 #define BIT_MASK_OFDM_FF_CNT GENMASK(15, 0) #define BIT_MASK_OFDM_SF_CNT GENMASK(31, 16) @@ -132,6 +228,32 @@ struct rtw8723d_efuse { #define BIT_MASK_OFDM_CRC_CNT GENMASK(31, 16) #define REG_OFDM_FA_TYPE4_11N 0x0da8 #define BIT_MASK_OFDM_MNS_CNT GENMASK(15, 0) +#define REG_FPGA0_IQK_11N 0x0e28 +#define BIT_MASK_IQK_MOD 0xffffff00 +#define EN_IQK 0x808000 +#define RST_IQK 0x000000 +#define REG_TXIQK_TONE_A_11N 0x0e30 +#define REG_RXIQK_TONE_A_11N 0x0e34 +#define REG_TXIQK_PI_A_11N 0x0e38 +#define REG_RXIQK_PI_A_11N 0x0e3c +#define REG_TXIQK_11N 0x0e40 +#define BIT_SET_TXIQK_11N(x, y) (0x80007C00 | ((x) << 16) | (y)) +#define REG_RXIQK_11N 0x0e44 +#define REG_IQK_AGC_PTS_11N 0x0e48 +#define REG_IQK_AGC_RSP_11N 0x0e4c +#define REG_TX_IQK_TONE_B 0x0e50 +#define REG_RX_IQK_TONE_B 0x0e54 +#define REG_IQK_RES_TX 0x0e94 +#define BIT_MASK_RES_TX GENMASK(25, 16) +#define REG_IQK_RES_TY 0x0e9c +#define BIT_MASK_RES_TY GENMASK(25, 16) +#define REG_IQK_RES_RX 0x0ea4 +#define BIT_MASK_RES_RX GENMASK(25, 16) +#define REG_IQK_RES_RY 0x0eac +#define BIT_IQK_TX_FAIL BIT(28) +#define BIT_IQK_RX_FAIL BIT(27) +#define BIT_IQK_DONE BIT(26) +#define BIT_MASK_RES_RY GENMASK(25, 16) #define REG_PAGE_F_RST_11N 0x0f14 #define BIT_MASK_F_RST_ALL BIT(16) #define REG_IGI_C_11N 0x0f84 From patchwork Thu May 7 04:21:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tony Chuang X-Patchwork-Id: 11532393 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E52C31392 for ; Thu, 7 May 2020 04:22:21 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CE6772082E for ; Thu, 7 May 2020 04:22:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725964AbgEGEWV (ORCPT ); Thu, 7 May 2020 00:22:21 -0400 Received: from rtits2.realtek.com ([211.75.126.72]:34097 "EHLO rtits2.realtek.com.tw" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725819AbgEGEWU (ORCPT ); Thu, 7 May 2020 00:22:20 -0400 Authenticated-By: X-SpamFilter-By: ArmorX SpamTrap 5.69 with qID 0474Lv502027277, This message is accepted by code: ctloc85258 Received: from mail.realtek.com (rtexmb06.realtek.com.tw[172.21.6.99]) by rtits2.realtek.com.tw (8.15.2/2.66/5.86) with ESMTPS id 0474Lv502027277 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Thu, 7 May 2020 12:21:57 +0800 Received: from RTEXMB04.realtek.com.tw (172.21.6.97) by RTEXMB06.realtek.com.tw (172.21.6.99) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1779.2; Thu, 7 May 2020 12:21:57 +0800 Received: from localhost.localdomain (172.21.68.128) by RTEXMB04.realtek.com.tw (172.21.6.97) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1779.2; Thu, 7 May 2020 12:21:56 +0800 From: To: CC: , , Subject: [PATCH v2 3/9] rtw88: 8723d: Add power tracking Date: Thu, 7 May 2020 12:21:45 +0800 Message-ID: <20200507042151.15634-4-yhchuang@realtek.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200507042151.15634-1-yhchuang@realtek.com> References: <20200507042151.15634-1-yhchuang@realtek.com> MIME-Version: 1.0 X-Originating-IP: [172.21.68.128] X-ClientProxiedBy: RTEXMB02.realtek.com.tw (172.21.6.95) To RTEXMB04.realtek.com.tw (172.21.6.97) Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Ping-Ke Shih When chip's temperature is changed, RF characters are changed. To keep the characters to be consistent, 8723d uses thermal meter to assist in calibrating LCK, IQK, crystal and TX power. A base thermal value is programmed in efuse, all calibration data in MP process is based on this thermal value. So we calucate the delta of thermal value between the base value, and use this delta to reference XTAL and TX power offset tables to know how much we need to adjust. For IQK and LCK, driver checks if delta of thermal value is over 8, then they are triggered. For crystal adjustment, when delta of thermal value is changed, we check XTAL tables to get offset of XTAL value. If thermal value is larger than base value, positive table (_p as suffix) is used. Otherwise, we use negative table (_n as suffix). Then, we add offset to XTAL default value programmed in efuse, and write sum value to register. To compensate TX power, there are two hierarchical tables. First level use delta of thermal value to access eight tables to yield delta of TX power index. Then, plus base TX power index to get index of BB swing table (second level tables) where register value is induced. BB swing table can't deal with all cases, if index of BB swing table is over the size of the table. In this case, TX AGC is used to compensate the remnant part. Assume 'upper' is the upper bound of BB swing table, and 'target' is the desired index. Then, we can illustrate them as compensation method BB swing TX AGC ------------------- -------- -------------- target > upper upper target - upper target < 0 0 target otherwise target 0 For debug purpose, add a column 'rem' to tx_pwr_tbl entry, and it looks like path rate pwr base (byr lmt ) rem A CCK_1M 32(0x20) 34 -2 ( 0 -2) 0 Signed-off-by: Ping-Ke Shih Signed-off-by: Yan-Hsuan Chuang --- drivers/net/wireless/realtek/rtw88/debug.c | 9 +- drivers/net/wireless/realtek/rtw88/main.h | 4 + drivers/net/wireless/realtek/rtw88/phy.c | 6 +- drivers/net/wireless/realtek/rtw88/phy.h | 1 + drivers/net/wireless/realtek/rtw88/rtw8723d.c | 400 ++++++++++++++++++ drivers/net/wireless/realtek/rtw88/rtw8723d.h | 7 + 6 files changed, 422 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c index b4964306de61..09f04feb8fe1 100644 --- a/drivers/net/wireless/realtek/rtw88/debug.c +++ b/drivers/net/wireless/realtek/rtw88/debug.c @@ -531,8 +531,8 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v) u8 ch = hal->current_channel; u8 regd = rtwdev->regd.txpwr_regd; - seq_printf(m, "%-4s %-10s %-3s%6s %-4s %4s (%-4s %-4s)\n", - "path", "rate", "pwr", "", "base", "", "byr", "lmt"); + seq_printf(m, "%-4s %-10s %-3s%6s %-4s %4s (%-4s %-4s) %-4s\n", + "path", "rate", "pwr", "", "base", "", "byr", "lmt", "rem"); mutex_lock(&hal->tx_power_mutex); for (path = RF_PATH_A; path <= RF_PATH_B; path++) { @@ -554,13 +554,14 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v) seq_printf(m, "%4c ", path + 'A'); rtw_print_rate(m, rate); - seq_printf(m, " %3u(0x%02x) %4u %4d (%4d %4d)\n", + seq_printf(m, " %3u(0x%02x) %4u %4d (%4d %4d) %4d\n", hal->tx_pwr_tbl[path][rate], hal->tx_pwr_tbl[path][rate], pwr_param.pwr_base, min_t(s8, pwr_param.pwr_offset, pwr_param.pwr_limit), - pwr_param.pwr_offset, pwr_param.pwr_limit); + pwr_param.pwr_offset, pwr_param.pwr_limit, + pwr_param.pwr_remnant); } } diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index af8c50e3687d..bfdc27c187f6 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -1056,6 +1056,8 @@ struct rtw_pwr_track_tbl { const u8 *pwrtrk_2g_cckb_p; const u8 *pwrtrk_2g_ccka_n; const u8 *pwrtrk_2g_ccka_p; + const s8 *pwrtrk_xtal_n; + const s8 *pwrtrk_xtal_p; }; enum rtw_wlan_cpu { @@ -1447,6 +1449,8 @@ struct rtw_dm_info { bool pwr_trk_triggered; bool pwr_trk_init_trigger; struct ewma_thermal avg_thermal[RTW_RF_PATH_MAX]; + s8 txagc_remnant_cck; + s8 txagc_remnant_ofdm; /* backup dack results for each path and I/Q */ u32 dack_adck[RTW_RF_PATH_MAX]; diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c index 837b7bd04126..45181f602e3f 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.c +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -1785,11 +1785,13 @@ void rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path, u8 rate, u8 bw, u8 ch, u8 regd, struct rtw_power_params *pwr_param) { struct rtw_hal *hal = &rtwdev->hal; + struct rtw_dm_info *dm_info = &rtwdev->dm_info; struct rtw_txpwr_idx *pwr_idx; u8 group, band; u8 *base = &pwr_param->pwr_base; s8 *offset = &pwr_param->pwr_offset; s8 *limit = &pwr_param->pwr_limit; + s8 *remnant = &pwr_param->pwr_remnant; pwr_idx = &rtwdev->efuse.txpwr_idx_table[path]; group = rtw_get_channel_group(ch); @@ -1811,6 +1813,8 @@ void rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path, u8 rate, u8 bw, *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); } u8 @@ -1830,7 +1834,7 @@ rtw_phy_get_tx_power_index(struct rtw_dev *rtwdev, u8 rf_path, u8 rate, if (rtwdev->chip->en_dis_dpd) offset += rtw_phy_get_dis_dpd_by_rate_diff(rtwdev, rate); - tx_power += offset; + tx_power += offset + pwr_param.pwr_remnant; if (tx_power > rtwdev->chip->max_power_index) tx_power = rtwdev->chip->max_power_index; diff --git a/drivers/net/wireless/realtek/rtw88/phy.h b/drivers/net/wireless/realtek/rtw88/phy.h index 413bf7165cc0..b924ed07630a 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.h +++ b/drivers/net/wireless/realtek/rtw88/phy.h @@ -141,6 +141,7 @@ struct rtw_power_params { u8 pwr_base; s8 pwr_offset; s8 pwr_limit; + s8 pwr_remnant; }; void diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c index 0cfa493e7742..4fc2d0bb2704 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c @@ -92,6 +92,46 @@ static void rtw8723d_lck(struct rtw_dev *rtwdev) rtw_write8(rtwdev, REG_TXPAUSE, 0x00); } +static const u32 rtw8723d_ofdm_swing_table[] = { + 0x0b40002d, 0x0c000030, 0x0cc00033, 0x0d800036, 0x0e400039, 0x0f00003c, + 0x10000040, 0x11000044, 0x12000048, 0x1300004c, 0x14400051, 0x15800056, + 0x16c0005b, 0x18000060, 0x19800066, 0x1b00006c, 0x1c800072, 0x1e400079, + 0x20000080, 0x22000088, 0x24000090, 0x26000098, 0x288000a2, 0x2ac000ab, + 0x2d4000b5, 0x300000c0, 0x32c000cb, 0x35c000d7, 0x390000e4, 0x3c8000f2, + 0x40000100, 0x43c0010f, 0x47c0011f, 0x4c000130, 0x50800142, 0x55400155, + 0x5a400169, 0x5fc0017f, 0x65400195, 0x6b8001ae, 0x71c001c7, 0x788001e2, + 0x7f8001fe, +}; + +static const u32 rtw8723d_cck_swing_table[] = { + 0x0CD, 0x0D9, 0x0E6, 0x0F3, 0x102, 0x111, 0x121, 0x132, 0x144, 0x158, + 0x16C, 0x182, 0x198, 0x1B1, 0x1CA, 0x1E5, 0x202, 0x221, 0x241, 0x263, + 0x287, 0x2AE, 0x2D6, 0x301, 0x32F, 0x35F, 0x392, 0x3C9, 0x402, 0x43F, + 0x47F, 0x4C3, 0x50C, 0x558, 0x5A9, 0x5FF, 0x65A, 0x6BA, 0x720, 0x78C, + 0x7FF, +}; + +#define RTW_OFDM_SWING_TABLE_SIZE ARRAY_SIZE(rtw8723d_ofdm_swing_table) +#define RTW_CCK_SWING_TABLE_SIZE ARRAY_SIZE(rtw8723d_cck_swing_table) + +static void rtw8723d_pwrtrack_init(struct rtw_dev *rtwdev) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u8 path; + + dm_info->default_ofdm_index = RTW_DEF_OFDM_SWING_INDEX; + + 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->pwr_trk_triggered = false; + 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; +} + static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev) { u8 xtal_cap; @@ -158,6 +198,8 @@ static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev) rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x50); rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x20); + + rtw8723d_pwrtrack_init(rtwdev); } static void rtw8723de_efuse_parsing(struct rtw_efuse *efuse, @@ -1450,6 +1492,298 @@ static void rtw8723d_phy_calibration(struct rtw_dev *rtwdev) rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] finished\n"); } +static u8 rtw8723d_pwrtrack_get_limit_ofdm(struct rtw_dev *rtwdev) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u8 tx_rate = dm_info->tx_rate; + u8 limit_ofdm = 30; + + switch (tx_rate) { + case DESC_RATE1M...DESC_RATE5_5M: + case DESC_RATE11M: + break; + case DESC_RATE6M...DESC_RATE48M: + limit_ofdm = 36; + break; + case DESC_RATE54M: + limit_ofdm = 34; + break; + case DESC_RATEMCS0...DESC_RATEMCS2: + limit_ofdm = 38; + break; + case DESC_RATEMCS3...DESC_RATEMCS4: + limit_ofdm = 36; + break; + case DESC_RATEMCS5...DESC_RATEMCS7: + limit_ofdm = 34; + break; + default: + rtw_warn(rtwdev, "pwrtrack unhandled tx_rate 0x%x\n", tx_rate); + break; + } + + return limit_ofdm; +} + +static void rtw8723d_set_iqk_matrix_by_result(struct rtw_dev *rtwdev, + u32 ofdm_swing, u8 rf_path) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + s32 ele_A, ele_D, ele_C; + s32 ele_A_ext, ele_C_ext, ele_D_ext; + s32 iqk_result_x; + s32 iqk_result_y; + s32 value32; + + switch (rf_path) { + default: + case RF_PATH_A: + iqk_result_x = dm_info->iqk.result.s1_x; + iqk_result_y = dm_info->iqk.result.s1_y; + break; + case RF_PATH_B: + iqk_result_x = dm_info->iqk.result.s0_x; + iqk_result_y = dm_info->iqk.result.s0_y; + break; + } + + /* new element D */ + ele_D = OFDM_SWING_D(ofdm_swing); + iqk_mult(iqk_result_x, ele_D, &ele_D_ext); + /* new element A */ + iqk_result_x = iqkxy_to_s32(iqk_result_x); + ele_A = iqk_mult(iqk_result_x, ele_D, &ele_A_ext); + /* new element C */ + iqk_result_y = iqkxy_to_s32(iqk_result_y); + ele_C = iqk_mult(iqk_result_y, ele_D, &ele_C_ext); + + switch (rf_path) { + case RF_PATH_A: + default: + /* write new elements A, C, D, and element B is always 0 */ + value32 = BIT_SET_TXIQ_ELM_ACD(ele_A, ele_C, ele_D); + rtw_write32(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE, value32); + value32 = BIT_SET_TXIQ_ELM_C1(ele_C); + rtw_write32_mask(rtwdev, REG_TXIQK_MATRIXA_LSB2_11N, MASKH4BITS, + value32); + value32 = rtw_read32(rtwdev, REG_OFDM_0_ECCA_THRESHOLD); + value32 &= ~BIT_MASK_OFDM0_EXTS; + value32 |= BIT_SET_OFDM0_EXTS(ele_A_ext, ele_C_ext, ele_D_ext); + rtw_write32(rtwdev, REG_OFDM_0_ECCA_THRESHOLD, value32); + break; + + case RF_PATH_B: + /* write new elements A, C, D, and element B is always 0 */ + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_S0, ele_D); + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_S0, ele_C); + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_S0, ele_A); + + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_EXT_S0, + ele_D_ext); + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_EXT_S0, + ele_A_ext); + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_EXT_S0, + ele_C_ext); + break; + } +} + +static void rtw8723d_set_iqk_matrix(struct rtw_dev *rtwdev, s8 ofdm_index, + u8 rf_path) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + s32 value32; + u32 ofdm_swing; + + if (ofdm_index >= RTW_OFDM_SWING_TABLE_SIZE) + ofdm_index = RTW_OFDM_SWING_TABLE_SIZE - 1; + else if (ofdm_index < 0) + ofdm_index = 0; + + ofdm_swing = rtw8723d_ofdm_swing_table[ofdm_index]; + + if (dm_info->iqk.done) { + rtw8723d_set_iqk_matrix_by_result(rtwdev, ofdm_swing, rf_path); + return; + } + + switch (rf_path) { + case RF_PATH_A: + default: + rtw_write32(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE, ofdm_swing); + rtw_write32_mask(rtwdev, REG_TXIQK_MATRIXA_LSB2_11N, MASKH4BITS, + 0x00); + value32 = rtw_read32(rtwdev, REG_OFDM_0_ECCA_THRESHOLD); + value32 &= ~BIT_MASK_OFDM0_EXTS; + rtw_write32(rtwdev, REG_OFDM_0_ECCA_THRESHOLD, value32); + break; + + case RF_PATH_B: + /* image S1:c80 to S0:Cd0 and Cd4 */ + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_S0, + OFDM_SWING_A(ofdm_swing)); + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_B_S0, + OFDM_SWING_B(ofdm_swing)); + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_S0, + OFDM_SWING_C(ofdm_swing)); + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_S0, + OFDM_SWING_D(ofdm_swing)); + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_EXT_S0, 0x0); + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_EXT_S0, 0x0); + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_EXT_S0, 0x0); + break; + } +} + +static void rtw8723d_pwrtrack_set_ofdm_pwr(struct rtw_dev *rtwdev, s8 swing_idx, + s8 txagc_idx) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + + dm_info->txagc_remnant_ofdm = txagc_idx; + + rtw8723d_set_iqk_matrix(rtwdev, swing_idx, RF_PATH_A); + rtw8723d_set_iqk_matrix(rtwdev, swing_idx, RF_PATH_B); +} + +static void rtw8723d_pwrtrack_set_cck_pwr(struct rtw_dev *rtwdev, s8 swing_idx, + s8 txagc_idx) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + + dm_info->txagc_remnant_cck = txagc_idx; + + rtw_write32_mask(rtwdev, 0xab4, 0x000007FF, + rtw8723d_cck_swing_table[swing_idx]); +} + +static void rtw8723d_pwrtrack_set(struct rtw_dev *rtwdev, u8 path) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + struct rtw_hal *hal = &rtwdev->hal; + u8 limit_ofdm; + u8 limit_cck = 40; + s8 final_ofdm_swing_index; + s8 final_cck_swing_index; + + limit_ofdm = rtw8723d_pwrtrack_get_limit_ofdm(rtwdev); + + final_ofdm_swing_index = RTW_DEF_OFDM_SWING_INDEX + + dm_info->delta_power_index[path]; + final_cck_swing_index = RTW_DEF_CCK_SWING_INDEX + + dm_info->delta_power_index[path]; + + if (final_ofdm_swing_index > limit_ofdm) + rtw8723d_pwrtrack_set_ofdm_pwr(rtwdev, limit_ofdm, + final_ofdm_swing_index - limit_ofdm); + else if (final_ofdm_swing_index < 0) + rtw8723d_pwrtrack_set_ofdm_pwr(rtwdev, 0, + final_ofdm_swing_index); + else + rtw8723d_pwrtrack_set_ofdm_pwr(rtwdev, final_ofdm_swing_index, 0); + + if (final_cck_swing_index > limit_cck) + rtw8723d_pwrtrack_set_cck_pwr(rtwdev, limit_cck, + final_cck_swing_index - limit_cck); + else if (final_cck_swing_index < 0) + rtw8723d_pwrtrack_set_cck_pwr(rtwdev, 0, + final_cck_swing_index); + else + rtw8723d_pwrtrack_set_cck_pwr(rtwdev, final_cck_swing_index, 0); + + rtw_phy_set_tx_power_level(rtwdev, hal->current_channel); +} + +static void rtw8723d_pwrtrack_set_xtal(struct rtw_dev *rtwdev, u8 therm_path, + u8 delta) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + const struct rtw_pwr_track_tbl *tbl = rtwdev->chip->pwr_track_tbl; + const s8 *pwrtrk_xtal; + s8 xtal_cap; + + if (dm_info->thermal_avg[therm_path] > + rtwdev->efuse.thermal_meter[therm_path]) + pwrtrk_xtal = tbl->pwrtrk_xtal_p; + else + pwrtrk_xtal = tbl->pwrtrk_xtal_n; + + xtal_cap = rtwdev->efuse.crystal_cap & 0x3F; + xtal_cap = clamp_t(s8, xtal_cap + pwrtrk_xtal[delta], 0, 0x3F); + rtw_write32_mask(rtwdev, REG_AFE_CTRL3, BIT_MASK_XTAL, + xtal_cap | (xtal_cap << 6)); +} + +static void rtw8723d_phy_pwrtrack(struct rtw_dev *rtwdev) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + struct rtw_swing_table swing_table; + u8 thermal_value, delta, path; + bool do_iqk = false; + + rtw_phy_config_swing_table(rtwdev, &swing_table); + + if (rtwdev->efuse.thermal_meter[0] == 0xff) + return; + + thermal_value = rtw_read_rf(rtwdev, RF_PATH_A, RF_T_METER, 0xfc00); + + rtw_phy_pwrtrack_avg(rtwdev, thermal_value, RF_PATH_A); + + do_iqk = rtw_phy_pwrtrack_need_iqk(rtwdev); + + if (do_iqk) + rtw8723d_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); + + delta = min_t(u8, delta, RTW_PWR_TRK_TBL_SZ - 1); + + for (path = 0; path < rtwdev->hal.rf_path_num; path++) { + s8 delta_cur, delta_last; + + delta_last = dm_info->delta_power_index[path]; + delta_cur = rtw_phy_pwrtrack_get_pwridx(rtwdev, &swing_table, + path, RF_PATH_A, delta); + if (delta_last == delta_cur) + continue; + + dm_info->delta_power_index[path] = delta_cur; + rtw8723d_pwrtrack_set(rtwdev, path); + } + + rtw8723d_pwrtrack_set_xtal(rtwdev, RF_PATH_A, delta); + +iqk: + if (do_iqk) + rtw8723d_phy_calibration(rtwdev); +} + +void rtw8723d_pwr_track(struct rtw_dev *rtwdev) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + + if (efuse->power_track_type != 0) + return; + + 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; + } + + rtw8723d_phy_pwrtrack(rtwdev); + dm_info->pwr_trk_triggered = false; +} + static struct rtw_chip_ops rtw8723d_ops = { .phy_set_param = rtw8723d_phy_set_param, .read_efuse = rtw8723d_read_efuse, @@ -1464,6 +1798,7 @@ static struct rtw_chip_ops rtw8723d_ops = { .efuse_grant = rtw8723d_efuse_grant, .false_alarm_statistics = rtw8723d_false_alarm_statistics, .phy_calibration = rtw8723d_phy_calibration, + .pwr_track = rtw8723d_pwr_track, .config_bfee = NULL, .set_gid_table = NULL, .cfg_csi_rate = NULL, @@ -1937,6 +2272,69 @@ static const struct rtw_rfe_def rtw8723d_rfe_defs[] = { .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 +}; + +static const u8 rtw8723d_pwrtrk_2gb_p[] = { + 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, + 7, 8, 8, 8, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10 +}; + +static const u8 rtw8723d_pwrtrk_2ga_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 +}; + +static const u8 rtw8723d_pwrtrk_2ga_p[] = { + 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, + 7, 8, 8, 8, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10 +}; + +static const u8 rtw8723d_pwrtrk_2g_cck_b_n[] = { + 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11 +}; + +static const u8 rtw8723d_pwrtrk_2g_cck_b_p[] = { + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, + 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11 +}; + +static const u8 rtw8723d_pwrtrk_2g_cck_a_n[] = { + 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11 +}; + +static const u8 rtw8723d_pwrtrk_2g_cck_a_p[] = { + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, + 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11 +}; + +static const s8 rtw8723d_pwrtrk_xtal_n[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static const s8 rtw8723d_pwrtrk_xtal_p[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -10, -12, -14, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16 +}; + +static const struct rtw_pwr_track_tbl rtw8723d_rtw_pwr_track_tbl = { + .pwrtrk_2gb_n = rtw8723d_pwrtrk_2gb_n, + .pwrtrk_2gb_p = rtw8723d_pwrtrk_2gb_p, + .pwrtrk_2ga_n = rtw8723d_pwrtrk_2ga_n, + .pwrtrk_2ga_p = rtw8723d_pwrtrk_2ga_p, + .pwrtrk_2g_cckb_n = rtw8723d_pwrtrk_2g_cck_b_n, + .pwrtrk_2g_cckb_p = rtw8723d_pwrtrk_2g_cck_b_p, + .pwrtrk_2g_ccka_n = rtw8723d_pwrtrk_2g_cck_a_n, + .pwrtrk_2g_ccka_p = rtw8723d_pwrtrk_2g_cck_a_p, + .pwrtrk_xtal_p = rtw8723d_pwrtrk_xtal_p, + .pwrtrk_xtal_n = rtw8723d_pwrtrk_xtal_n, +}; + struct rtw_chip_info rtw8723d_hw_spec = { .ops = &rtw8723d_ops, .id = RTW_CHIP_TYPE_8723D, @@ -1979,6 +2377,8 @@ struct rtw_chip_info rtw8723d_hw_spec = { .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, }; EXPORT_SYMBOL(rtw8723d_hw_spec); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h index 549dfcf7f5da..843472a1cd54 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h @@ -112,6 +112,13 @@ static inline s32 iqk_mult(s32 x, s32 y, s32 *ext) return (t >> 8); /* Q.16 --> Q.8 */ } +#define OFDM_SWING_A(swing) FIELD_GET(GENMASK(9, 0), swing) +#define OFDM_SWING_B(swing) FIELD_GET(GENMASK(15, 10), swing) +#define OFDM_SWING_C(swing) FIELD_GET(GENMASK(21, 16), swing) +#define OFDM_SWING_D(swing) FIELD_GET(GENMASK(31, 22), swing) +#define RTW_DEF_OFDM_SWING_INDEX 28 +#define RTW_DEF_CCK_SWING_INDEX 28 + #define MAX_TOLERANCE 5 #define IQK_TX_X_ERR 0x142 #define IQK_TX_Y_ERR 0x42 From patchwork Thu May 7 04:21:46 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tony Chuang X-Patchwork-Id: 11532389 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4E70217EF for ; Thu, 7 May 2020 04:22:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 402A72082E for ; Thu, 7 May 2020 04:22:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725947AbgEGEWR (ORCPT ); Thu, 7 May 2020 00:22:17 -0400 Received: from rtits2.realtek.com ([211.75.126.72]:34096 "EHLO rtits2.realtek.com.tw" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725862AbgEGEWR (ORCPT ); Thu, 7 May 2020 00:22:17 -0400 Authenticated-By: X-SpamFilter-By: ArmorX SpamTrap 5.69 with qID 0474Lv512027277, This message is accepted by code: ctloc85258 Received: from mail.realtek.com (rtexmb06.realtek.com.tw[172.21.6.99]) by rtits2.realtek.com.tw (8.15.2/2.66/5.86) with ESMTPS id 0474Lv512027277 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Thu, 7 May 2020 12:21:57 +0800 Received: from RTEXMB04.realtek.com.tw (172.21.6.97) by RTEXMB06.realtek.com.tw (172.21.6.99) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1779.2; Thu, 7 May 2020 12:21:57 +0800 Received: from localhost.localdomain (172.21.68.128) by RTEXMB04.realtek.com.tw (172.21.6.97) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1779.2; Thu, 7 May 2020 12:21:56 +0800 From: To: CC: , , Subject: [PATCH v2 4/9] rtw88: 8723d: Add shutdown callback to disable BT USB suspend Date: Thu, 7 May 2020 12:21:46 +0800 Message-ID: <20200507042151.15634-5-yhchuang@realtek.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200507042151.15634-1-yhchuang@realtek.com> References: <20200507042151.15634-1-yhchuang@realtek.com> MIME-Version: 1.0 X-Originating-IP: [172.21.68.128] X-ClientProxiedBy: RTEXMB02.realtek.com.tw (172.21.6.95) To RTEXMB04.realtek.com.tw (172.21.6.97) Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Ping-Ke Shih Without this patch, wifi card can't initialize properly due to BT in USB suspend state. So, we disable BT USB suspend (wakeup) in shutdown callback that is the moment before rebooting. To save BT USB power, we can't do this in 'remove' callback. Signed-off-by: Ping-Ke Shih Signed-off-by: Yan-Hsuan Chuang --- drivers/net/wireless/realtek/rtw88/main.h | 1 + drivers/net/wireless/realtek/rtw88/pci.c | 17 +++++++++++++++++ drivers/net/wireless/realtek/rtw88/reg.h | 1 + drivers/net/wireless/realtek/rtw88/rtw8723d.c | 6 ++++++ 4 files changed, 25 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index bfdc27c187f6..592b28ed9376 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -795,6 +795,7 @@ struct rtw_regulatory { struct rtw_chip_ops { int (*mac_init)(struct rtw_dev *rtwdev); + void (*shutdown)(struct rtw_dev *rtwdev); int (*read_efuse)(struct rtw_dev *rtwdev, u8 *map); void (*phy_set_param)(struct rtw_dev *rtwdev); void (*set_channel)(struct rtw_dev *rtwdev, u8 channel, diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index b9a5868a5da0..493903e0562e 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -1578,6 +1578,22 @@ static void rtw_pci_remove(struct pci_dev *pdev) ieee80211_free_hw(hw); } +static void rtw_pci_shutdown(struct pci_dev *pdev) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct rtw_dev *rtwdev; + struct rtw_chip_info *chip; + + if (!hw) + return; + + rtwdev = hw->priv; + chip = rtwdev->chip; + + if (chip->ops->shutdown) + chip->ops->shutdown(rtwdev); +} + static const struct pci_device_id rtw_pci_id_table[] = { #ifdef CONFIG_RTW88_8822BE { RTK_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xB822, rtw8822b_hw_spec) }, @@ -1598,6 +1614,7 @@ static struct pci_driver rtw_pci_driver = { .probe = rtw_pci_probe, .remove = rtw_pci_remove, .driver.pm = RTW_PM_OPS, + .shutdown = rtw_pci_shutdown, }; module_pci_driver(rtw_pci_driver); diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h index d57de1a6cdcc..5a3e9cc7c400 100644 --- a/drivers/net/wireless/realtek/rtw88/reg.h +++ b/drivers/net/wireless/realtek/rtw88/reg.h @@ -83,6 +83,7 @@ #define BIT_DBG_GNT_WL_BT BIT(27) #define BIT_LTE_MUX_CTRL_PATH BIT(26) #define REG_HCI_OPT_CTRL 0x0074 +#define BIT_USB_SUS_DIS BIT(8) #define REG_AFE_CTRL_4 0x0078 #define BIT_CK320M_AFE_EN BIT(4) diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c index 4fc2d0bb2704..bfad27d10c40 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c @@ -549,6 +549,11 @@ static int rtw8723d_mac_init(struct rtw_dev *rtwdev) return 0; } +static void rtw8723d_shutdown(struct rtw_dev *rtwdev) +{ + rtw_write16_set(rtwdev, REG_HCI_OPT_CTRL, BIT_USB_SUS_DIS); +} + static void rtw8723d_cfg_ldo25(struct rtw_dev *rtwdev, bool enable) { u8 ldo_pwr; @@ -1790,6 +1795,7 @@ static struct rtw_chip_ops rtw8723d_ops = { .query_rx_desc = rtw8723d_query_rx_desc, .set_channel = rtw8723d_set_channel, .mac_init = rtw8723d_mac_init, + .shutdown = rtw8723d_shutdown, .read_rf = rtw_phy_read_rf_sipi, .write_rf = rtw_phy_write_rf_reg_sipi, .set_tx_power_index = rtw8723d_set_tx_power_index, From patchwork Thu May 7 04:21:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tony Chuang X-Patchwork-Id: 11532387 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4773217EF for ; Thu, 7 May 2020 04:22:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 35CA92082E for ; Thu, 7 May 2020 04:22:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725927AbgEGEWR (ORCPT ); Thu, 7 May 2020 00:22:17 -0400 Received: from rtits2.realtek.com ([211.75.126.72]:34094 "EHLO rtits2.realtek.com.tw" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725848AbgEGEWQ (ORCPT ); Thu, 7 May 2020 00:22:16 -0400 Authenticated-By: X-SpamFilter-By: ArmorX SpamTrap 5.69 with qID 0474Lv522027277, This message is accepted by code: ctloc85258 Received: from mail.realtek.com (rtexmb06.realtek.com.tw[172.21.6.99]) by rtits2.realtek.com.tw (8.15.2/2.66/5.86) with ESMTPS id 0474Lv522027277 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Thu, 7 May 2020 12:21:57 +0800 Received: from RTEXMB04.realtek.com.tw (172.21.6.97) by RTEXMB06.realtek.com.tw (172.21.6.99) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1779.2; Thu, 7 May 2020 12:21:57 +0800 Received: from localhost.localdomain (172.21.68.128) by RTEXMB04.realtek.com.tw (172.21.6.97) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1779.2; Thu, 7 May 2020 12:21:57 +0800 From: To: CC: , , Subject: [PATCH v2 5/9] rtw88: 8723d: implement flush queue Date: Thu, 7 May 2020 12:21:47 +0800 Message-ID: <20200507042151.15634-6-yhchuang@realtek.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200507042151.15634-1-yhchuang@realtek.com> References: <20200507042151.15634-1-yhchuang@realtek.com> MIME-Version: 1.0 X-Originating-IP: [172.21.68.128] X-ClientProxiedBy: RTEXMB02.realtek.com.tw (172.21.6.95) To RTEXMB04.realtek.com.tw (172.21.6.97) Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Ping-Ke Shih Flush queue is used to check if queue is empty, before doing something else. Since 8723D uses different registers and page number of availabl/reserved occupy 8 bits instead of 16 bits, so use a 'wsize' field to discriminate which rtw_read{8,16} is adopted. Signed-off-by: Ping-Ke Shih Signed-off-by: Yan-Hsuan Chuang --- drivers/net/wireless/realtek/rtw88/mac.c | 29 +++++++------------ drivers/net/wireless/realtek/rtw88/main.h | 11 +++++++ drivers/net/wireless/realtek/rtw88/rtw8723d.c | 17 +++++++++++ drivers/net/wireless/realtek/rtw88/rtw8822b.c | 17 +++++++++++ drivers/net/wireless/realtek/rtw88/rtw8822c.c | 17 +++++++++++ 5 files changed, 73 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c index e8ffeb338584..3a5cfebe5a62 100644 --- a/drivers/net/wireless/realtek/rtw88/mac.c +++ b/drivers/net/wireless/realtek/rtw88/mac.c @@ -919,31 +919,24 @@ static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues) static void __rtw_mac_flush_prio_queue(struct rtw_dev *rtwdev, u32 prio_queue, bool drop) { - u32 addr; + struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_prioq_addr *addr; + bool wsize; u16 avail_page, rsvd_page; int i; - switch (prio_queue) { - case RTW_DMA_MAPPING_EXTRA: - addr = REG_FIFOPAGE_INFO_4; - break; - case RTW_DMA_MAPPING_LOW: - addr = REG_FIFOPAGE_INFO_2; - break; - case RTW_DMA_MAPPING_NORMAL: - addr = REG_FIFOPAGE_INFO_3; - break; - case RTW_DMA_MAPPING_HIGH: - addr = REG_FIFOPAGE_INFO_1; - break; - default: + if (prio_queue >= RTW_DMA_MAPPING_MAX) return; - } + + addr = &chip->prioq_addrs->prio[prio_queue]; + wsize = chip->prioq_addrs->wsize; /* check if all of the reserved pages are available for 100 msecs */ for (i = 0; i < 5; i++) { - rsvd_page = rtw_read16(rtwdev, addr); - avail_page = rtw_read16(rtwdev, addr + 2); + rsvd_page = wsize ? rtw_read16(rtwdev, addr->rsvd) : + rtw_read8(rtwdev, addr->rsvd); + avail_page = wsize ? rtw_read16(rtwdev, addr->avail) : + rtw_read8(rtwdev, addr->avail); if (rsvd_page == avail_page) return; diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 592b28ed9376..28f88c44cb84 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -945,6 +945,16 @@ struct rtw_rqpn { enum rtw_dma_mapping dma_map_hi; }; +struct rtw_prioq_addr { + u32 rsvd; + u32 avail; +}; + +struct rtw_prioq_addrs { + struct rtw_prioq_addr prio[RTW_DMA_MAPPING_MAX]; + bool wsize; +}; + struct rtw_page_table { u16 hq_num; u16 nq_num; @@ -1101,6 +1111,7 @@ struct rtw_chip_info { const struct rtw_pwr_seq_cmd **pwr_on_seq; const struct rtw_pwr_seq_cmd **pwr_off_seq; const struct rtw_rqpn *rqpn_table; + const struct rtw_prioq_addrs *prioq_addrs; const struct rtw_page_table *page_table; const struct rtw_intf_phy_para_table *intf_table; diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c index bfad27d10c40..66bf907131d7 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c @@ -2237,6 +2237,22 @@ static const struct rtw_rqpn rqpn_table_8723d[] = { RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, }; +static const struct rtw_prioq_addrs prioq_addrs_8723d = { + .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_intf_phy_para pcie_gen1_param_8723d[] = { {0x0008, 0x4a22, RTW_IP_SEL_PHY, @@ -2370,6 +2386,7 @@ struct rtw_chip_info rtw8723d_hw_spec = { .pwr_off_seq = card_disable_flow_8723d, .page_table = page_table_8723d, .rqpn_table = rqpn_table_8723d, + .prioq_addrs = &prioq_addrs_8723d, .intf_table = &phy_para_table_8723d, .dig = rtw8723d_dig, .dig_cck = rtw8723d_dig_cck, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c index 45636382dafd..22a7baeb87f6 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -2083,6 +2083,22 @@ static const struct rtw_rqpn rqpn_table_8822b[] = { RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, }; +static struct rtw_prioq_addrs prioq_addrs_8822b = { + .prio[RTW_DMA_MAPPING_EXTRA] = { + .rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2, + }, + .prio[RTW_DMA_MAPPING_LOW] = { + .rsvd = REG_FIFOPAGE_INFO_2, .avail = REG_FIFOPAGE_INFO_2 + 2, + }, + .prio[RTW_DMA_MAPPING_NORMAL] = { + .rsvd = REG_FIFOPAGE_INFO_3, .avail = REG_FIFOPAGE_INFO_3 + 2, + }, + .prio[RTW_DMA_MAPPING_HIGH] = { + .rsvd = REG_FIFOPAGE_INFO_1, .avail = REG_FIFOPAGE_INFO_1 + 2, + }, + .wsize = true, +}; + static struct rtw_chip_ops rtw8822b_ops = { .phy_set_param = rtw8822b_phy_set_param, .read_efuse = rtw8822b_read_efuse, @@ -2433,6 +2449,7 @@ struct rtw_chip_info rtw8822b_hw_spec = { .pwr_off_seq = card_disable_flow_8822b, .page_table = page_table_8822b, .rqpn_table = rqpn_table_8822b, + .prioq_addrs = &prioq_addrs_8822b, .intf_table = &phy_para_table_8822b, .dig = rtw8822b_dig, .dig_cck = NULL, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index 64b77a7cbffd..e4b184485cad 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -3933,6 +3933,22 @@ static const struct rtw_rqpn rqpn_table_8822c[] = { RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, }; +static struct rtw_prioq_addrs prioq_addrs_8822c = { + .prio[RTW_DMA_MAPPING_EXTRA] = { + .rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2, + }, + .prio[RTW_DMA_MAPPING_LOW] = { + .rsvd = REG_FIFOPAGE_INFO_2, .avail = REG_FIFOPAGE_INFO_2 + 2, + }, + .prio[RTW_DMA_MAPPING_NORMAL] = { + .rsvd = REG_FIFOPAGE_INFO_3, .avail = REG_FIFOPAGE_INFO_3 + 2, + }, + .prio[RTW_DMA_MAPPING_HIGH] = { + .rsvd = REG_FIFOPAGE_INFO_1, .avail = REG_FIFOPAGE_INFO_1 + 2, + }, + .wsize = true, +}; + static struct rtw_chip_ops rtw8822c_ops = { .phy_set_param = rtw8822c_phy_set_param, .read_efuse = rtw8822c_read_efuse, @@ -4295,6 +4311,7 @@ struct rtw_chip_info rtw8822c_hw_spec = { .pwr_off_seq = card_disable_flow_8822c, .page_table = page_table_8822c, .rqpn_table = rqpn_table_8822c, + .prioq_addrs = &prioq_addrs_8822c, .intf_table = &phy_para_table_8822c, .dig = rtw8822c_dig, .dig_cck = NULL, From patchwork Thu May 7 04:21:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tony Chuang X-Patchwork-Id: 11532375 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 65C1D14B4 for ; Thu, 7 May 2020 04:22:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 46FEF2082E for ; Thu, 7 May 2020 04:22:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725802AbgEGEWH (ORCPT ); Thu, 7 May 2020 00:22:07 -0400 Received: from rtits2.realtek.com ([211.75.126.72]:34082 "EHLO rtits2.realtek.com.tw" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725763AbgEGEWH (ORCPT ); Thu, 7 May 2020 00:22:07 -0400 Authenticated-By: X-SpamFilter-By: ArmorX SpamTrap 5.69 with qID 0474Lw4yA027277, This message is accepted by code: ctloc85258 Received: from mail.realtek.com (rtexmb06.realtek.com.tw[172.21.6.99]) by rtits2.realtek.com.tw (8.15.2/2.66/5.86) with ESMTPS id 0474Lw4yA027277 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Thu, 7 May 2020 12:21:58 +0800 Received: from RTEXMB04.realtek.com.tw (172.21.6.97) by RTEXMB06.realtek.com.tw (172.21.6.99) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1779.2; Thu, 7 May 2020 12:21:57 +0800 Received: from localhost.localdomain (172.21.68.128) by RTEXMB04.realtek.com.tw (172.21.6.97) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1779.2; Thu, 7 May 2020 12:21:57 +0800 From: To: CC: , , Subject: [PATCH v2 6/9] rtw88: 8723d: set ltecoex register address in chip_info Date: Thu, 7 May 2020 12:21:48 +0800 Message-ID: <20200507042151.15634-7-yhchuang@realtek.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200507042151.15634-1-yhchuang@realtek.com> References: <20200507042151.15634-1-yhchuang@realtek.com> MIME-Version: 1.0 X-Originating-IP: [172.21.68.128] X-ClientProxiedBy: RTEXMB02.realtek.com.tw (172.21.6.95) To RTEXMB04.realtek.com.tw (172.21.6.97) Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Ping-Ke Shih Since 8723D use different address of ltecoex register, this commit add a new field in chip_info and fill proper address. Then, ltecoex_read_reg() and ltecoex_reg_write() can use them to access ltecoex according to chip. Signed-off-by: Ping-Ke Shih Signed-off-by: Yan-Hsuan Chuang --- drivers/net/wireless/realtek/rtw88/main.h | 7 +++++++ drivers/net/wireless/realtek/rtw88/rtw8723d.c | 7 +++++++ drivers/net/wireless/realtek/rtw88/rtw8723d.h | 3 +++ drivers/net/wireless/realtek/rtw88/rtw8822b.c | 7 +++++++ drivers/net/wireless/realtek/rtw88/rtw8822c.c | 7 +++++++ drivers/net/wireless/realtek/rtw88/util.c | 18 ++++++++++++------ 6 files changed, 43 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index 28f88c44cb84..c9156b9b532c 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -519,6 +519,12 @@ struct rtw_hw_reg { u32 mask; }; +struct rtw_ltecoex_addr { + u32 ctrl; + u32 wdata; + u32 rdata; +}; + struct rtw_reg_domain { u32 addr; u32 mask; @@ -1121,6 +1127,7 @@ struct rtw_chip_info { u32 rf_sipi_addr[2]; const struct rtw_rf_sipi_addr *rf_sipi_read_addr; u8 fix_rf_phy_num; + const struct rtw_ltecoex_addr *ltecoex_addr; const struct rtw_table *mac_tbl; const struct rtw_table *agc_tbl; diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c index 66bf907131d7..e3dc27d6a6ad 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c @@ -2289,6 +2289,12 @@ static const struct rtw_rf_sipi_addr rtw8723d_rf_sipi_addr[] = { .hssi_2 = 0x82c, .lssi_read_pi = 0x8bc}, }; +static const struct rtw_ltecoex_addr rtw8723d_ltecoex_addr = { + .ctrl = REG_LTECOEX_CTRL, + .wdata = REG_LTECOEX_WRITE_DATA, + .rdata = REG_LTECOEX_READ_DATA, +}; + static const struct rtw_rfe_def rtw8723d_rfe_defs[] = { [0] = { .phy_pg_tbl = &rtw8723d_bb_pg_tbl, .txpwr_lmt_tbl = &rtw8723d_txpwr_lmt_tbl,}, @@ -2393,6 +2399,7 @@ struct rtw_chip_info rtw8723d_hw_spec = { .rf_sipi_addr = {0x840, 0x844}, .rf_sipi_read_addr = rtw8723d_rf_sipi_addr, .fix_rf_phy_num = 2, + .ltecoex_addr = &rtw8723d_ltecoex_addr, .mac_tbl = &rtw8723d_mac_tbl, .agc_tbl = &rtw8723d_agc_tbl, .bb_tbl = &rtw8723d_bb_tbl, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h index 843472a1cd54..d1f1c1a594ad 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h @@ -145,6 +145,9 @@ static inline s32 iqk_mult(s32 x, s32 y, s32 *ext) #define REG_BTG_SEL 0x0067 #define REG_LTECOEX_PATH_CONTROL 0x0070 +#define REG_LTECOEX_CTRL 0x07c0 +#define REG_LTECOEX_WRITE_DATA 0x07c4 +#define REG_LTECOEX_READ_DATA 0x07c8 #define REG_PSDFN 0x0808 #define REG_BB_PWR_SAV1_11N 0x0874 #define REG_ANALOG_P4 0x088c diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c index 22a7baeb87f6..18c5a5a96d90 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -2057,6 +2057,12 @@ static const struct rtw_hw_reg rtw8822b_dig[] = { [1] = { .addr = 0xe50, .mask = 0x7f }, }; +static const struct rtw_ltecoex_addr rtw8822b_ltecoex_addr = { + .ctrl = LTECOEX_ACCESS_CTRL, + .wdata = LTECOEX_WRITE_DATA, + .rdata = LTECOEX_READ_DATA, +}; + static const struct rtw_page_table page_table_8822b[] = { {64, 64, 64, 64, 1}, {64, 64, 64, 64, 1}, @@ -2455,6 +2461,7 @@ struct rtw_chip_info rtw8822b_hw_spec = { .dig_cck = NULL, .rf_base_addr = {0x2800, 0x2c00}, .rf_sipi_addr = {0xc90, 0xe90}, + .ltecoex_addr = &rtw8822b_ltecoex_addr, .mac_tbl = &rtw8822b_mac_tbl, .agc_tbl = &rtw8822b_agc_tbl, .bb_tbl = &rtw8822b_bb_tbl, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index e4b184485cad..d697d70170af 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -3907,6 +3907,12 @@ static const struct rtw_hw_reg rtw8822c_dig[] = { [1] = { .addr = 0x1d70, .mask = 0x7f00 }, }; +static const struct rtw_ltecoex_addr rtw8822c_ltecoex_addr = { + .ctrl = LTECOEX_ACCESS_CTRL, + .wdata = LTECOEX_WRITE_DATA, + .rdata = LTECOEX_READ_DATA, +}; + static const struct rtw_page_table page_table_8822c[] = { {64, 64, 64, 64, 1}, {64, 64, 64, 64, 1}, @@ -4317,6 +4323,7 @@ struct rtw_chip_info rtw8822c_hw_spec = { .dig_cck = NULL, .rf_base_addr = {0x3c00, 0x4c00}, .rf_sipi_addr = {0x1808, 0x4108}, + .ltecoex_addr = &rtw8822c_ltecoex_addr, .mac_tbl = &rtw8822c_mac_tbl, .agc_tbl = &rtw8822c_agc_tbl, .bb_tbl = &rtw8822c_bb_tbl, diff --git a/drivers/net/wireless/realtek/rtw88/util.c b/drivers/net/wireless/realtek/rtw88/util.c index 10f1117c0cfb..42cf177cd445 100644 --- a/drivers/net/wireless/realtek/rtw88/util.c +++ b/drivers/net/wireless/realtek/rtw88/util.c @@ -22,22 +22,28 @@ bool check_hw_ready(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 target) bool ltecoex_read_reg(struct rtw_dev *rtwdev, u16 offset, u32 *val) { - if (!check_hw_ready(rtwdev, LTECOEX_ACCESS_CTRL, LTECOEX_READY, 1)) + struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_ltecoex_addr *ltecoex = chip->ltecoex_addr; + + if (!check_hw_ready(rtwdev, ltecoex->ctrl, LTECOEX_READY, 1)) return false; - rtw_write32(rtwdev, LTECOEX_ACCESS_CTRL, 0x800F0000 | offset); - *val = rtw_read32(rtwdev, LTECOEX_READ_DATA); + rtw_write32(rtwdev, ltecoex->ctrl, 0x800F0000 | offset); + *val = rtw_read32(rtwdev, ltecoex->rdata); return true; } bool ltecoex_reg_write(struct rtw_dev *rtwdev, u16 offset, u32 value) { - if (!check_hw_ready(rtwdev, LTECOEX_ACCESS_CTRL, LTECOEX_READY, 1)) + struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_ltecoex_addr *ltecoex = chip->ltecoex_addr; + + if (!check_hw_ready(rtwdev, ltecoex->ctrl, LTECOEX_READY, 1)) return false; - rtw_write32(rtwdev, LTECOEX_WRITE_DATA, value); - rtw_write32(rtwdev, LTECOEX_ACCESS_CTRL, 0xC00F0000 | offset); + rtw_write32(rtwdev, ltecoex->wdata, value); + rtw_write32(rtwdev, ltecoex->ctrl, 0xC00F0000 | offset); return true; } From patchwork Thu May 7 04:21:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tony Chuang X-Patchwork-Id: 11532383 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0C03517EF for ; Thu, 7 May 2020 04:22:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E55A9206DB for ; Thu, 7 May 2020 04:22:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725905AbgEGEWP (ORCPT ); Thu, 7 May 2020 00:22:15 -0400 Received: from rtits2.realtek.com ([211.75.126.72]:34095 "EHLO rtits2.realtek.com.tw" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725857AbgEGEWP (ORCPT ); Thu, 7 May 2020 00:22:15 -0400 Authenticated-By: X-SpamFilter-By: ArmorX SpamTrap 5.69 with qID 0474LwVT2027294, This message is accepted by code: ctloc85258 Received: from mail.realtek.com (rtexmb06.realtek.com.tw[172.21.6.99]) by rtits2.realtek.com.tw (8.15.2/2.66/5.86) with ESMTPS id 0474LwVT2027294 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Thu, 7 May 2020 12:21:58 +0800 Received: from RTEXMB04.realtek.com.tw (172.21.6.97) by RTEXMB06.realtek.com.tw (172.21.6.99) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1779.2; Thu, 7 May 2020 12:21:58 +0800 Received: from localhost.localdomain (172.21.68.128) by RTEXMB04.realtek.com.tw (172.21.6.97) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1779.2; Thu, 7 May 2020 12:21:57 +0800 From: To: CC: , , Subject: [PATCH v2 8/9] rtw88: fill zeros to words 0x06 and 0x07 of security cam entry Date: Thu, 7 May 2020 12:21:50 +0800 Message-ID: <20200507042151.15634-9-yhchuang@realtek.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200507042151.15634-1-yhchuang@realtek.com> References: <20200507042151.15634-1-yhchuang@realtek.com> MIME-Version: 1.0 X-Originating-IP: [172.21.68.128] X-ClientProxiedBy: RTEXMB02.realtek.com.tw (172.21.6.95) To RTEXMB04.realtek.com.tw (172.21.6.97) Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Ping-Ke Shih 8723D adds some experimental features to word 0x06 of cam entry, so fill zeros to initialize them to off state. For existing chips, these two words are reserved and always zeros, so this change is harmless for them. Signed-off-by: Ping-Ke Shih Signed-off-by: Yan-Hsuan Chuang --- drivers/net/wireless/realtek/rtw88/sec.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/realtek/rtw88/sec.c b/drivers/net/wireless/realtek/rtw88/sec.c index d0d7fbb10d58..ce46e5b4a60a 100644 --- a/drivers/net/wireless/realtek/rtw88/sec.c +++ b/drivers/net/wireless/realtek/rtw88/sec.c @@ -44,7 +44,7 @@ void rtw_sec_write_cam(struct rtw_dev *rtwdev, write_cmd = RTW_SEC_CMD_WRITE_ENABLE | RTW_SEC_CMD_POLLING; addr = hw_key_idx << RTW_SEC_CAM_ENTRY_SHIFT; - for (i = 5; i >= 0; i--) { + for (i = 7; i >= 0; i--) { switch (i) { case 0: content = ((key->keyidx & 0x3)) | @@ -60,6 +60,10 @@ void rtw_sec_write_cam(struct rtw_dev *rtwdev, (cam->addr[4] << 16) | (cam->addr[5] << 24); break; + case 6: + case 7: + content = 0; + break; default: j = (i - 2) << 2; content = (key->key[j]) | From patchwork Thu May 7 04:21:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tony Chuang X-Patchwork-Id: 11532381 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6A1BC14B4 for ; Thu, 7 May 2020 04:22:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4AA30206DB for ; Thu, 7 May 2020 04:22:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725900AbgEGEWP (ORCPT ); Thu, 7 May 2020 00:22:15 -0400 Received: from rtits2.realtek.com ([211.75.126.72]:34090 "EHLO rtits2.realtek.com.tw" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725783AbgEGEWP (ORCPT ); Thu, 7 May 2020 00:22:15 -0400 Authenticated-By: X-SpamFilter-By: ArmorX SpamTrap 5.69 with qID 0474LwJ72027301, This message is accepted by code: ctloc85258 Received: from mail.realtek.com (rtexmb06.realtek.com.tw[172.21.6.99]) by rtits2.realtek.com.tw (8.15.2/2.66/5.86) with ESMTPS id 0474LwJ72027301 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT); Thu, 7 May 2020 12:21:58 +0800 Received: from RTEXMB04.realtek.com.tw (172.21.6.97) by RTEXMB06.realtek.com.tw (172.21.6.99) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1779.2; Thu, 7 May 2020 12:21:58 +0800 Received: from localhost.localdomain (172.21.68.128) by RTEXMB04.realtek.com.tw (172.21.6.97) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1779.2; Thu, 7 May 2020 12:21:57 +0800 From: To: CC: , , Subject: [PATCH v2 9/9] rtw88: 8723d: Add 8723DE to Kconfig and Makefile Date: Thu, 7 May 2020 12:21:51 +0800 Message-ID: <20200507042151.15634-10-yhchuang@realtek.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200507042151.15634-1-yhchuang@realtek.com> References: <20200507042151.15634-1-yhchuang@realtek.com> MIME-Version: 1.0 X-Originating-IP: [172.21.68.128] X-ClientProxiedBy: RTEXMB02.realtek.com.tw (172.21.6.95) To RTEXMB04.realtek.com.tw (172.21.6.97) Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org From: Ping-Ke Shih Since 8723D code is ready, we can build it. Signed-off-by: Ping-Ke Shih Signed-off-by: Yan-Hsuan Chuang Reported-by: kbuild test robot --- drivers/net/wireless/realtek/rtw88/Kconfig | 10 ++++++++++ drivers/net/wireless/realtek/rtw88/Makefile | 1 + 2 files changed, 11 insertions(+) diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig index 33bd7ed797ff..7a5fa68945c4 100644 --- a/drivers/net/wireless/realtek/rtw88/Kconfig +++ b/drivers/net/wireless/realtek/rtw88/Kconfig @@ -36,6 +36,16 @@ config RTW88_8822CE 802.11ac PCIe wireless network adapter +config RTW88_8723DE + bool "Realtek 8723DE PCI wireless network adapter" + depends on PCI + select RTW88_CORE + select RTW88_PCI + help + Select this option will enable support for 8723DE chipset + + 802.11n PCIe wireless network adapter + config RTW88_DEBUG bool "Realtek rtw88 debug support" depends on RTW88_CORE diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile index cac148d13cf1..385facc0dd20 100644 --- a/drivers/net/wireless/realtek/rtw88/Makefile +++ b/drivers/net/wireless/realtek/rtw88/Makefile @@ -20,6 +20,7 @@ rtw88-y += main.o \ rtw88-$(CONFIG_RTW88_8822BE) += rtw8822b.o rtw8822b_table.o rtw88-$(CONFIG_RTW88_8822CE) += rtw8822c.o rtw8822c_table.o +rtw88-$(CONFIG_RTW88_8723DE) += rtw8723d.o rtw8723d_table.o obj-$(CONFIG_RTW88_PCI) += rtwpci.o rtwpci-objs := pci.o