rtw88: 8723d: Add set_channel
authorPing-Ke Shih <pkshih@realtek.com>
Mon, 4 May 2020 10:50:05 +0000 (18:50 +0800)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 6 May 2020 08:34:17 +0000 (11:34 +0300)
Set MAC/BB/RF register according to specified channel. The function
rtw_set_channel_mac() is used to set MAC registers, but 8723D only need
some of them.

For channel 14, we need to set different CCK DFIR values, so restore the
values when channel 1 to 13 is selected.

Spur calibration is needed in channel 13 and 14, and we do notch if spur
is over threshold.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20200504105010.10780-4-yhchuang@realtek.com
drivers/net/wireless/realtek/rtw88/mac.c
drivers/net/wireless/realtek/rtw88/rtw8723d.c
drivers/net/wireless/realtek/rtw88/rtw8723d.h

index bd82b48..e8ffeb3 100644 (file)
@@ -40,6 +40,9 @@ void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw,
        }
        rtw_write32(rtwdev, REG_WMAC_TRXPTCL_CTL, value32);
 
+       if (rtw_chip_wcpu_11n(rtwdev))
+               return;
+
        value32 = rtw_read32(rtwdev, REG_AFE_CTRL1) & ~(BIT_MAC_CLK_SEL);
        value32 |= (MAC_CLK_HW_DEF_80M << BIT_SHIFT_MAC_CLK_SEL);
        rtw_write32(rtwdev, REG_AFE_CTRL1, value32);
index 653cfa9..6011ca8 100644 (file)
@@ -287,6 +287,166 @@ static void rtw8723d_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc,
        rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status);
 }
 
+static bool rtw8723d_check_spur_ov_thres(struct rtw_dev *rtwdev,
+                                        u8 channel, u32 thres)
+{
+       u32 freq;
+       bool ret = false;
+
+       if (channel == 13)
+               freq = FREQ_CH13;
+       else if (channel == 14)
+               freq = FREQ_CH14;
+       else
+               return false;
+
+       rtw_write32(rtwdev, REG_ANALOG_P4, DIS_3WIRE);
+       rtw_write32(rtwdev, REG_PSDFN, freq);
+       rtw_write32(rtwdev, REG_PSDFN, START_PSD | freq);
+
+       msleep(30);
+       if (rtw_read32(rtwdev, REG_PSDRPT) >= thres)
+               ret = true;
+
+       rtw_write32(rtwdev, REG_PSDFN, freq);
+       rtw_write32(rtwdev, REG_ANALOG_P4, EN_3WIRE);
+
+       return ret;
+}
+
+static void rtw8723d_cfg_notch(struct rtw_dev *rtwdev, u8 channel, bool notch)
+{
+       if (!notch) {
+               rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_MASK_RXDSP, 0x1f);
+               rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_EN_RXDSP, 0x0);
+               rtw_write32(rtwdev, REG_OFDM1_CSI1, 0x00000000);
+               rtw_write32(rtwdev, REG_OFDM1_CSI2, 0x00000000);
+               rtw_write32(rtwdev, REG_OFDM1_CSI3, 0x00000000);
+               rtw_write32(rtwdev, REG_OFDM1_CSI4, 0x00000000);
+               rtw_write32_mask(rtwdev, REG_OFDM1_CFOTRK, BIT_EN_CFOTRK, 0x0);
+               return;
+       }
+
+       switch (channel) {
+       case 13:
+               rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_MASK_RXDSP, 0xb);
+               rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_EN_RXDSP, 0x1);
+               rtw_write32(rtwdev, REG_OFDM1_CSI1, 0x04000000);
+               rtw_write32(rtwdev, REG_OFDM1_CSI2, 0x00000000);
+               rtw_write32(rtwdev, REG_OFDM1_CSI3, 0x00000000);
+               rtw_write32(rtwdev, REG_OFDM1_CSI4, 0x00000000);
+               rtw_write32_mask(rtwdev, REG_OFDM1_CFOTRK, BIT_EN_CFOTRK, 0x1);
+               break;
+       case 14:
+               rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_MASK_RXDSP, 0x5);
+               rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_EN_RXDSP, 0x1);
+               rtw_write32(rtwdev, REG_OFDM1_CSI1, 0x00000000);
+               rtw_write32(rtwdev, REG_OFDM1_CSI2, 0x00000000);
+               rtw_write32(rtwdev, REG_OFDM1_CSI3, 0x00000000);
+               rtw_write32(rtwdev, REG_OFDM1_CSI4, 0x00080000);
+               rtw_write32_mask(rtwdev, REG_OFDM1_CFOTRK, BIT_EN_CFOTRK, 0x1);
+               break;
+       default:
+               rtw_write32_mask(rtwdev, REG_OFDM0_RXDSP, BIT_EN_RXDSP, 0x0);
+               rtw_write32_mask(rtwdev, REG_OFDM1_CFOTRK, BIT_EN_CFOTRK, 0x0);
+               break;
+       }
+}
+
+static void rtw8723d_spur_cal(struct rtw_dev *rtwdev, u8 channel)
+{
+       bool notch;
+
+       if (channel < 13) {
+               rtw8723d_cfg_notch(rtwdev, channel, false);
+               return;
+       }
+
+       notch = rtw8723d_check_spur_ov_thres(rtwdev, channel, SPUR_THRES);
+       rtw8723d_cfg_notch(rtwdev, channel, notch);
+}
+
+static void rtw8723d_set_channel_rf(struct rtw_dev *rtwdev, u8 channel, u8 bw)
+{
+       u32 rf_cfgch_a, rf_cfgch_b;
+
+       rf_cfgch_a = rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK);
+       rf_cfgch_b = rtw_read_rf(rtwdev, RF_PATH_B, RF_CFGCH, RFREG_MASK);
+
+       rf_cfgch_a &= ~RFCFGCH_CHANNEL_MASK;
+       rf_cfgch_b &= ~RFCFGCH_CHANNEL_MASK;
+       rf_cfgch_a |= (channel & RFCFGCH_CHANNEL_MASK);
+       rf_cfgch_b |= (channel & RFCFGCH_CHANNEL_MASK);
+
+       rf_cfgch_a &= ~RFCFGCH_BW_MASK;
+       switch (bw) {
+       case RTW_CHANNEL_WIDTH_20:
+               rf_cfgch_a |= RFCFGCH_BW_20M;
+               break;
+       case RTW_CHANNEL_WIDTH_40:
+               rf_cfgch_a |= RFCFGCH_BW_40M;
+               break;
+       default:
+               break;
+       }
+
+       rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, rf_cfgch_a);
+       rtw_write_rf(rtwdev, RF_PATH_B, RF_CFGCH, RFREG_MASK, rf_cfgch_b);
+
+       rtw8723d_spur_cal(rtwdev, channel);
+}
+
+static const struct rtw_backup_info cck_dfir_cfg[][CCK_DFIR_NR] = {
+       [0] = {
+               { .len = 4, .reg = 0xA24, .val = 0x64B80C1C },
+               { .len = 4, .reg = 0xA28, .val = 0x00008810 },
+               { .len = 4, .reg = 0xAAC, .val = 0x01235667 },
+       },
+       [1] = {
+               { .len = 4, .reg = 0xA24, .val = 0x0000B81C },
+               { .len = 4, .reg = 0xA28, .val = 0x00000000 },
+               { .len = 4, .reg = 0xAAC, .val = 0x00003667 },
+       },
+};
+
+static void rtw8723d_set_channel_bb(struct rtw_dev *rtwdev, u8 channel, u8 bw,
+                                   u8 primary_ch_idx)
+{
+       const struct rtw_backup_info *cck_dfir;
+       int i;
+
+       cck_dfir = channel <= 13 ? cck_dfir_cfg[0] : cck_dfir_cfg[1];
+
+       for (i = 0; i < CCK_DFIR_NR; i++, cck_dfir++)
+               rtw_write32(rtwdev, cck_dfir->reg, cck_dfir->val);
+
+       switch (bw) {
+       case RTW_CHANNEL_WIDTH_20:
+               rtw_write32_mask(rtwdev, REG_FPGA0_RFMOD, BIT_MASK_RFMOD, 0x0);
+               rtw_write32_mask(rtwdev, REG_FPGA1_RFMOD, BIT_MASK_RFMOD, 0x0);
+               rtw_write32_mask(rtwdev, REG_BBRX_DFIR, BIT_RXBB_DFIR_EN, 1);
+               rtw_write32_mask(rtwdev, REG_BBRX_DFIR, BIT_MASK_RXBB_DFIR, 0xa);
+               break;
+       case RTW_CHANNEL_WIDTH_40:
+               rtw_write32_mask(rtwdev, REG_FPGA0_RFMOD, BIT_MASK_RFMOD, 0x1);
+               rtw_write32_mask(rtwdev, REG_FPGA1_RFMOD, BIT_MASK_RFMOD, 0x1);
+               rtw_write32_mask(rtwdev, REG_BBRX_DFIR, BIT_RXBB_DFIR_EN, 0);
+               rtw_write32_mask(rtwdev, REG_CCK0_SYS, BIT_CCK_SIDE_BAND,
+                                (primary_ch_idx == RTW_SC_20_UPPER ? 1 : 0));
+               break;
+       default:
+               break;
+       }
+}
+
+static void rtw8723d_set_channel(struct rtw_dev *rtwdev, u8 channel, u8 bw,
+                                u8 primary_chan_idx)
+{
+       rtw8723d_set_channel_rf(rtwdev, channel, bw);
+       rtw_set_channel_mac(rtwdev, channel, bw, primary_chan_idx);
+       rtw8723d_set_channel_bb(rtwdev, channel, bw, primary_chan_idx);
+}
+
 #define BIT_CFENDFORM          BIT(9)
 #define BIT_WMAC_TCR_ERR0      BIT(12)
 #define BIT_WMAC_TCR_ERR1      BIT(13)
@@ -383,6 +543,7 @@ static struct rtw_chip_ops rtw8723d_ops = {
        .phy_set_param          = rtw8723d_phy_set_param,
        .read_efuse             = rtw8723d_read_efuse,
        .query_rx_desc          = rtw8723d_query_rx_desc,
+       .set_channel            = rtw8723d_set_channel,
        .mac_init               = rtw8723d_mac_init,
        .read_rf                = rtw_phy_read_rf_sipi,
        .write_rf               = rtw_phy_write_rf_reg_sipi,
index 035049a..0661460 100644 (file)
@@ -66,7 +66,38 @@ struct rtw8723d_efuse {
 #define GET_PHY_STAT_P1_RXSNR_A(phy_stat)                                      \
        le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0))
 
+#define SPUR_THRES             0x16
+#define CCK_DFIR_NR            3
+#define DIS_3WIRE              0xccf000c0
+#define EN_3WIRE               0xccc000c0
+#define START_PSD              0x400000
+#define FREQ_CH13              0xfccd
+#define FREQ_CH14              0xff9a
+#define RFCFGCH_CHANNEL_MASK   GENMASK(7, 0)
+#define RFCFGCH_BW_MASK                (BIT(11) | BIT(10))
+#define RFCFGCH_BW_20M         (BIT(11) | BIT(10))
+#define RFCFGCH_BW_40M         BIT(10)
+#define BIT_MASK_RFMOD         BIT(0)
+
+#define REG_PSDFN              0x0808
+#define REG_ANALOG_P4          0x088c
+#define REG_PSDRPT             0x08b4
+#define REG_FPGA1_RFMOD                0x0900
+#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_OFDM0_RXDSP                0x0c40
+#define BIT_MASK_RXDSP         GENMASK(28, 24)
+#define BIT_EN_RXDSP           BIT(9)
 #define REG_OFDM0_XAAGC1       0x0c50
 #define REG_OFDM0_XBAGC1       0x0c58
+#define REG_OFDM1_CFOTRK       0x0d2c
+#define BIT_EN_CFOTRK          BIT(28)
+#define REG_OFDM1_CSI1         0x0d40
+#define REG_OFDM1_CSI2         0x0d44
+#define REG_OFDM1_CSI3         0x0d48
+#define REG_OFDM1_CSI4         0x0d4c
 
 #endif