> -----Original Message----- > From: Bitterblue Smith <rtl8821cerfe2@xxxxxxxxx> > Sent: Wednesday, April 26, 2023 1:28 AM > To: linux-wireless@xxxxxxxxxxxxxxx > Cc: Jes Sorensen <Jes.Sorensen@xxxxxxxxx>; Ping-Ke Shih <pkshih@xxxxxxxxxxx> > Subject: [PATCH] wifi: rtl8xxxu: Support new chip RTL8192FU > > This is a newer chip, similar to the RTL8710BU in that it uses the same > PHY status structs. > > Features: 2.4 GHz, b/g/n mode, 2T2R, 300 Mbps. > > It can allegedly have Bluetooth, but that's not implemented here. > > This chip can have many RFE (RF front end) types, of which type 5 is > the only one tested. Many of the other types need different > initialisation tables. They can be added if someone wants them. > > The vendor driver v5.8.6.2_35538.20191028_COEX20190910-0d02 from > https://github.com/BrightX/rtl8192fu was used as reference. > > Signed-off-by: Bitterblue Smith <rtl8821cerfe2@xxxxxxxxx> > --- > drivers/net/wireless/realtek/rtl8xxxu/Kconfig | 3 +- > .../net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 47 + > .../realtek/rtl8xxxu/rtl8xxxu_8188f.c | 3 +- > .../realtek/rtl8xxxu/rtl8xxxu_8192f.c | 2081 +++++++++++++++++ > .../realtek/rtl8xxxu/rtl8xxxu_8710b.c | 1 + > .../realtek/rtl8xxxu/rtl8xxxu_8723b.c | 1 + > .../wireless/realtek/rtl8xxxu/rtl8xxxu_core.c | 104 +- > .../wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h | 15 + > 8 files changed, 2225 insertions(+), 30 deletions(-) > create mode 100644 drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c > [...] > +static void rtl8192fu_config_kfree(struct rtl8xxxu_priv *priv, u8 channel) > +{ > + u8 bb_gain[3] = { EFUSE_UNDEFINED, EFUSE_UNDEFINED, EFUSE_UNDEFINED }; > + u8 bb_gain_path_mask[2] = { 0x0f, 0xf0 }; > + enum rtl8xxxu_rfpath rfpath; > + u8 bb_gain_for_path; > + u8 channel_idx; > + > + if (channel >= 1 && channel <= 3) > + channel_idx = 0; > + if (channel >= 4 && channel <= 9) > + channel_idx = 1; > + if (channel >= 10 && channel <= 14) > + channel_idx = 2; > + > + rtl8xxxu_read_efuse8(priv, 0x1ee, &bb_gain[1]); > + rtl8xxxu_read_efuse8(priv, 0x1ec, &bb_gain[0]); > + rtl8xxxu_read_efuse8(priv, 0x1ea, &bb_gain[2]); Can you define these fields in struct rtl8192fu_efuse, and access via the struct? > + > + if (bb_gain[1] == EFUSE_UNDEFINED) > + return; > + > + if (bb_gain[0] == EFUSE_UNDEFINED) > + bb_gain[0] = bb_gain[1]; > + > + if (bb_gain[2] == EFUSE_UNDEFINED) > + bb_gain[2] = bb_gain[1]; > + > + for (rfpath = RF_A; rfpath < priv->rf_paths; rfpath++) { > + /* power_trim based on 55[19:14] */ > + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_UNKNOWN_55, > + BIT(5), 1); > + > + /* enable 55[14] for 0.5db step */ > + rtl8xxxu_write_rfreg_mask(priv, rfpath, 0xf5, BIT(18), 1); #define RF6052_REG_GAIN_CTRL 0x55 > + > + /* enter power_trim debug mode */ > + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_UNKNOWN_DF, > + BIT(7), 1); > + > + /* write enable */ > + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_WE_LUT, BIT(7), 1); > + > + bb_gain_for_path = (bb_gain[channel_idx] & bb_gain_path_mask[rfpath]) > + >> __ffs(bb_gain_path_mask[rfpath]); Normally, putting operator >> in tail, but this statement is so long. How about this? bb_gain_for_path = (bb_gain[channel_idx] & bb_gain_path_mask[rfpath]); bb_gain_for_path >>= __ffs(bb_gain_path_mask[rfpath]); > + > + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3, > + 0x70000, channel_idx * 2); > + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3, > + 0x3f, bb_gain_for_path); > + > + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3, > + 0x70000, channel_idx * 2 + 1); > + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3, > + 0x3f, bb_gain_for_path); > + > + /* leave power_trim debug mode */ > + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_UNKNOWN_DF, > + BIT(7), 0); > + > + /* write disable */ > + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_WE_LUT, BIT(7), 0); > + } > +} > + [...] > +static void rtl8192fu_init_phy_bb(struct rtl8xxxu_priv *priv) > +{ > + /* Enable BB and RF */ > + rtl8xxxu_write16_set(priv, REG_SYS_FUNC, > + SYS_FUNC_BBRSTB | SYS_FUNC_BB_GLB_RSTN); > + > + rtl8xxxu_write8(priv, REG_RF_CTRL, RF_ENABLE | RF_RSTB | RF_SDMRSTB); > + > + /* To Fix MAC loopback mode fail. */ > + rtl8xxxu_write8(priv, REG_LDOHCI12_CTRL, 0xf); > + rtl8xxxu_write8(priv, 0x15, 0xe9); #define REG_SYS_SWR_CTRL2 0x14 You can use REG_SYS_SWR_CTRL2 + 1 here. > + > + rtl8xxxu_init_phy_regs(priv, rtl8192fu_phy_init_table); > + > + rtl8xxxu_init_phy_regs(priv, rtl8192f_agc_table); > +} > + [...] > +static int rtl8192fu_iqk_path_a(struct rtl8xxxu_priv *priv) > +{ > + u32 reg_eac, reg_e94, reg_e9c, val32; > + u32 rf_0x58_i, rf_0x58_q; > + u8 rfe = priv->rfe_type; > + int result = 0; > + int ktime, i; > + > + /* Leave IQK mode */ > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); > + > + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0); > + rtl8xxxu_write32(priv, 0xd94, 0x44ffbb44); #define REG_ANAPWR1 0xd94 > + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040); > + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403); > + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4); > + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400); > + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100); > + > + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_UNKNOWN_DF, BIT(4), 1); > + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_UNKNOWN_DF, BIT(11), 1); > + if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12) > + val32 = 0x30; > + else > + val32 = 0xe9; > + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x003ff, val32); > + > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); > + > + /* path-A IQK setting */ > + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x18008c1c); > + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); > + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); > + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); > + > + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x8214000f); > + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28140000); > + > + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); > + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); > + > + /* LO calibration setting */ > + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00e62911); > + > + /* One shot, path A LOK & IQK */ > + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800); > + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800); > + > + mdelay(15); > + > + ktime = 0; > + while (rtl8xxxu_read32(priv, 0xe98) == 0 && ktime < 21) { #define REG_IQK_RTP_TXA 0xe98 > + mdelay(5); > + ktime += 5; > + } > + > + /* Check failed */ > + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); > + reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A); > + reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A); > + > + /* reload 0xdf and CCK_IND off */ > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); > + > + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_WE_LUT, BIT(4), 1); > + > + val32 = rtl8xxxu_read_rfreg(priv, RF_A, 0x58); #define RF6052_REG_TXMOD 0x58 > + rf_0x58_i = u32_get_bits(val32, 0xfc000); > + rf_0x58_q = u32_get_bits(val32, 0x003f0); > + > + for (i = 0; i < 8; i++) { > + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_TXPA_G3, > + 0x1c000, i); > + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_TXPA_G3, > + 0x00fc0, rf_0x58_i); > + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_TXPA_G3, > + 0x0003f, rf_0x58_q); > + } > + > + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_AC, BIT(14), 0); > + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_WE_LUT, BIT(4), 0); > + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00810, 0); > + > + if (!(reg_eac & BIT(28)) && > + ((reg_e94 & 0x03ff0000) != 0x01420000) && > + ((reg_e9c & 0x03ff0000) != 0x00420000)) > + result |= 0x01; > + > + return result; > +} > + > +static int rtl8192fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) > +{ > + u32 reg_ea4, reg_eac, reg_e94, reg_e9c, val32; > + int result = 0; > + int ktime; > + > + /* Leave IQK mode */ > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); > + > + /* PA/PAD control by 0x56, and set = 0x0 */ > + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_UNKNOWN_DF, BIT(1), 1); > + rtl8xxxu_write_rfreg(priv, RF_A, 0x35, 0); #define RF6052_REG_GAIN_P1 0x35 #define RF6052_REG_PAD_TXG 0x56 #define RF6052_REG_GAIN_CCA 0xdf > + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_UNKNOWN_DF, BIT(11), 1); > + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x003ff, 0x27); > + > + /* Enter IQK mode */ > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); > + > + /* path-A IQK setting */ > + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x18008c1c); > + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); > + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); > + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); > + > + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82160027); > + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28160000); > + > + /* Tx IQK setting */ > + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); > + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); > + > + /* LO calibration setting */ > + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0086a911); > + > + /* One shot, path A LOK & IQK */ > + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800); > + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800); > + > + mdelay(15); > + > + ktime = 0; > + while (rtl8xxxu_read32(priv, 0xe98) == 0 && ktime < 21) { #define REG_IQK_RTP_TXA 0xe98 > + mdelay(5); > + ktime += 5; > + } > + > + /* Check failed */ > + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); > + reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A); > + reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A); > + > + if (!(reg_eac & BIT(28)) && > + ((reg_e94 & 0x03ff0000) != 0x01420000) && > + ((reg_e9c & 0x03ff0000) != 0x00420000)) { > + result |= 0x01; > + } else { /* If TX not OK, ignore RX */ > + /* PA/PAD controlled by 0x0 */ > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); > + > + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_UNKNOWN_DF, > + BIT(11), 0); > + > + return result; > + } > + > + val32 = 0x80007c00 | (reg_e94 & 0x3ff0000) | ((reg_e9c & 0x3ff0000) >> 16); > + rtl8xxxu_write32(priv, REG_TX_IQK, val32); > + > + /* Modify RX IQK mode table */ > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); > + > + /* PA/PAD control by 0x56, and set = 0x0 */ > + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_UNKNOWN_DF, BIT(1), 1); > + rtl8xxxu_write_rfreg(priv, RF_A, 0x35, 0); > + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_UNKNOWN_DF, BIT(11), 1); > + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x003ff, 0x1e0); > + > + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0); > + rtl8xxxu_write32(priv, 0xd94, 0x44ffbb44); > + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040); > + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403); > + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4); > + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400); > + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100); > + > + /* Enter IQK mode */ > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); > + > + /* path-A IQK setting */ > + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); > + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x18008c1c); > + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); > + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); > + > + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82170000); > + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28170000); > + > + /* RX IQK setting */ > + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); > + > + /* LO calibration setting */ > + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a8d1); > + > + /* One shot, path A LOK & IQK */ > + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800); > + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800); > + > + mdelay(15); > + > + ktime = 0; > + while (rtl8xxxu_read32(priv, 0xea8) == 0 && ktime < 21) { #define REG_IQK_RTP_RXA 0xea8 > + mdelay(5); > + ktime += 5; > + } > + > + /* Check failed */ > + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); > + reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2); > + > + /* Leave IQK mode */ > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); > + > + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_UNKNOWN_DF, BIT(11), 0); > + rtl8xxxu_write_rfreg(priv, RF_A, 0x35, 0x02000); > + > + if (!(reg_eac & BIT(27)) && > + ((reg_ea4 & 0x03ff0000) != 0x01320000) && > + ((reg_eac & 0x03ff0000) != 0x00360000)) > + result |= 0x02; > + > + return result; > +} > + > +static int rtl8192fu_iqk_path_b(struct rtl8xxxu_priv *priv) > +{ > + u32 reg_eac, reg_eb4, reg_ebc, val32; > + u32 rf_0x58_i, rf_0x58_q; > + u8 rfe = priv->rfe_type; > + int result = 0; > + int ktime, i; > + > + /* PA/PAD controlled by 0x0 */ > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); > + > + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0); > + rtl8xxxu_write32(priv, 0xd94, 0x44ffbb44); > + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040); > + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403); > + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4); > + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400); > + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000000); > + > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_UNKNOWN_DF, BIT(4), 1); > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_UNKNOWN_DF, BIT(11), 1); > + if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12) > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_UNKNOWN_56, > + 0x003ff, 0x30); > + else > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_UNKNOWN_56, > + 0x00fff, 0xe9); > + > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); > + > + /* Path B IQK setting */ > + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); > + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); > + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x18008c1c); > + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); > + > + rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x8214000F); > + rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x28140000); > + > + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); > + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); > + > + /* LO calibration setting */ > + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00e62911); > + > + /* One shot, path B LOK & IQK */ > + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800); > + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800); > + > + mdelay(15); > + > + ktime = 0; > + while (rtl8xxxu_read32(priv, 0xeb8) == 0 && ktime < 21) { #define REG_IQK_RTP_TXB 0xeb8 > + mdelay(5); > + ktime += 5; > + } > + > + /* Check failed */ > + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); > + reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); > + reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); > + > + /* reload 0xdf and CCK_IND off */ > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); > + > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_WE_LUT, BIT(4), 1); > + > + val32 = rtl8xxxu_read_rfreg(priv, RF_B, 0x58); > + rf_0x58_i = u32_get_bits(val32, 0xfc000); > + rf_0x58_q = u32_get_bits(val32, 0x003f0); > + > + for (i = 0; i < 8; i++) { > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_TXPA_G3, > + 0x1c000, i); > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_TXPA_G3, > + 0x00fc0, rf_0x58_i); > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_TXPA_G3, > + 0x0003f, rf_0x58_q); > + } > + > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_AC, BIT(14), 0); > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_WE_LUT, BIT(4), 0); > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00810, 0); > + > + if (!(reg_eac & BIT(31)) && > + ((reg_eb4 & 0x03ff0000) != 0x01420000) && > + ((reg_ebc & 0x03ff0000) != 0x00420000)) > + result |= 0x01; > + else > + dev_warn(&priv->udev->dev, "%s: Path B IQK failed!\n", > + __func__); > + > + return result; > +} > + > +static int rtl8192fu_rx_iqk_path_b(struct rtl8xxxu_priv *priv) > +{ > + u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc, val32; > + int result = 0; > + int ktime; > + > + /* Leave IQK mode */ > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); > + > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_UNKNOWN_DF, BIT(1), 1); > + rtl8xxxu_write_rfreg(priv, RF_B, 0x35, 0); > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_UNKNOWN_DF, BIT(11), 1); > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_UNKNOWN_56, 0x003ff, 0x67); > + > + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0); > + rtl8xxxu_write32(priv, 0xd94, 0x44ffbb44); > + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040); > + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403); > + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4); > + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400); > + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000000); > + > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); > + > + /* path-B IQK setting */ > + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); > + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); > + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x18008c1c); > + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); > + > + rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x82160027); > + rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x28160000); > + > + /* LO calibration setting */ > + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0086a911); > + > + /* One shot, path A LOK & IQK */ > + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800); > + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800); > + > + mdelay(15); > + > + ktime = 0; > + while (rtl8xxxu_read32(priv, 0xeb8) == 0 && ktime < 21) { > + mdelay(5); > + ktime += 5; > + } > + > + /* Check failed */ > + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); > + reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); > + reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); > + > + if (!(reg_eac & BIT(31)) && > + ((reg_eb4 & 0x03ff0000) != 0x01420000) && > + ((reg_ebc & 0x03ff0000) != 0x00420000)) { > + result |= 0x01; > + } else { > + /* PA/PAD controlled by 0x0 */ > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); > + > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_UNKNOWN_DF, > + BIT(11), 0); > + > + return result; > + } > + > + val32 = 0x80007c00 | (reg_eb4 & 0x03ff0000) | ((reg_ebc >> 16) & 0x03ff); > + rtl8xxxu_write32(priv, REG_TX_IQK, val32); > + > + /* Modify RX IQK mode table */ > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); > + > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_UNKNOWN_DF, BIT(1), 1); > + rtl8xxxu_write_rfreg(priv, RF_B, 0x35, 0); > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_UNKNOWN_DF, BIT(11), 1); > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_UNKNOWN_56, 0x003ff, 0x1e0); > + > + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0); > + rtl8xxxu_write32(priv, 0xd94, 0x44ffbb44); > + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040); > + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403); > + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4); > + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400); > + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000000); > + > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); > + > + /* Path B IQK setting */ > + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); > + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); > + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); > + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x18008c1c); > + > + rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x82170000); > + rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x28170000); > + > + /* IQK setting */ > + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); > + > + /* LO calibration setting */ > + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a911); > + > + /* One shot, path A LOK & IQK */ > + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800); > + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800); > + > + mdelay(15); > + > + ktime = 0; > + while (rtl8xxxu_read32(priv, 0xec8) == 0 && ktime < 21) { #define REG_IQK_RTP_RXB 0xec8 > + mdelay(5); > + ktime += 5; > + } > + > + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); > + reg_ec4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2); > + reg_ecc = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2); > + > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); > + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100); > + > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_UNKNOWN_DF, BIT(11), 0); > + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_UNKNOWN_DF, BIT(1), 0); > + rtl8xxxu_write_rfreg(priv, RF_B, 0x35, 0x02000); > + > + if (!(reg_eac & BIT(30)) && > + ((reg_ec4 & 0x03ff0000) != 0x01320000) && > + ((reg_ecc & 0x03ff0000) != 0x00360000)) > + result |= 0x02; > + else > + dev_warn(&priv->udev->dev, "%s: Path B RX IQK failed!\n", > + __func__); > + > + return result; > +} > + > +static void rtl8192fu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, > + int result[][8], int t) > +{ > + static const u32 adda_regs[2] = { > + 0xd94, REG_RX_WAIT_CCA > + }; > + static const u32 iqk_mac_regs[RTL8XXXU_MAC_REGS] = { > + REG_TXPAUSE, REG_BEACON_CTRL, > + REG_BEACON_CTRL_1, REG_GPIO_MUXCFG > + }; > + static const u32 iqk_bb_regs[RTL8XXXU_BB_REGS] = { > + REG_OFDM0_TRX_PATH_ENABLE, REG_OFDM0_TR_MUX_PAR, > + REG_FPGA0_XCD_RF_SW_CTRL, REG_CONFIG_ANT_A, REG_CONFIG_ANT_B, > + REG_DPDT_CTRL, REG_RFE_CTRL_ANTA_SRC, > + 0x938, REG_CCK0_AFE_SETTING > + }; #define REG_RFE_CTRL_ANT_SRC2 0x938 > + u32 rx_initial_gain_a, rx_initial_gain_b; > + struct device *dev = &priv->udev->dev; > + int path_a_ok, path_b_ok; > + u8 rfe = priv->rfe_type; > + int retry = 2; > + u32 i, val32; > + > + /* > + * Note: IQ calibration must be performed after loading > + * PHY_REG.txt , and radio_a, radio_b.txt > + */ > + > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); > + > + rx_initial_gain_a = rtl8xxxu_read32(priv, REG_OFDM0_XA_AGC_CORE1); > + rx_initial_gain_b = rtl8xxxu_read32(priv, REG_OFDM0_XB_AGC_CORE1); > + > + if (t == 0) { > + /* Save ADDA parameters, turn Path A ADDA on */ > + rtl8xxxu_save_regs(priv, adda_regs, priv->adda_backup, > + ARRAY_SIZE(adda_regs)); > + rtl8xxxu_save_mac_regs(priv, iqk_mac_regs, priv->mac_backup); > + rtl8xxxu_save_regs(priv, iqk_bb_regs, > + priv->bb_backup, RTL8XXXU_BB_REGS); > + } > + > + /* Instead of rtl8xxxu_path_adda_on */ > + rtl8xxxu_write32_set(priv, REG_FPGA0_XCD_RF_PARM, BIT(31)); > + > + /* MAC settings */ > + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); > + rtl8xxxu_write8_clear(priv, REG_GPIO_MUXCFG, GPIO_MUXCFG_IO_SEL_ENBT); > + > + if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12) { > + /* in ePA IQK, rfe_func_config & SW both pull down */ > + /* path A */ > + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, 0xF, 0x7); > + rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x1, 0x0); > + > + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, 0xF00, 0x7); > + rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x4, 0x0); > + > + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, 0xF000, 0x7); > + rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x8, 0x0); > + > + /* path B */ > + rtl8xxxu_write32_mask(priv, 0x938, 0xF0, 0x7); > + rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x20000, 0x0); > + > + rtl8xxxu_write32_mask(priv, 0x938, 0xF0000, 0x7); > + rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x100000, 0x0); > + > + rtl8xxxu_write32_mask(priv, 0x93c, 0xF000, 0x7); #define REG_RFE_CTRL_ANT_SRC3 0x93c > + rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x8000000, 0x0); > + } > + > + if (priv->rf_paths > 1) { > + /* path B standby */ > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x000000); > + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC, 0x10000); > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); > + } > + > + for (i = 0; i < retry; i++) { > + path_a_ok = rtl8192fu_iqk_path_a(priv); > + > + if (path_a_ok == 0x01) { > + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A); > + result[t][0] = (val32 >> 16) & 0x3ff; > + > + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A); > + result[t][1] = (val32 >> 16) & 0x3ff; > + break; > + } else { > + result[t][0] = 0x100; > + result[t][1] = 0x0; > + } > + } > + > + for (i = 0; i < retry; i++) { > + path_a_ok = rtl8192fu_rx_iqk_path_a(priv); > + > + if (path_a_ok == 0x03) { > + val32 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2); > + result[t][2] = (val32 >> 16) & 0x3ff; > + > + val32 = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); > + result[t][3] = (val32 >> 16) & 0x3ff; > + break; > + } else { > + result[t][2] = 0x100; > + result[t][3] = 0x0; > + } > + } > + > + if (!path_a_ok) > + dev_warn(dev, "%s: Path A IQK failed!\n", __func__); > + > + if (priv->rf_paths > 1) { > + for (i = 0; i < retry; i++) { > + path_b_ok = rtl8192fu_iqk_path_b(priv); > + > + if (path_b_ok == 0x01) { > + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); > + result[t][4] = (val32 >> 16) & 0x3ff; > + > + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); > + result[t][5] = (val32 >> 16) & 0x3ff; > + break; > + } else { > + result[t][4] = 0x100; > + result[t][5] = 0x0; > + } > + } > + > + for (i = 0; i < retry; i++) { > + path_b_ok = rtl8192fu_rx_iqk_path_b(priv); > + > + if (path_b_ok == 0x03) { > + val32 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2); > + result[t][6] = (val32 >> 16) & 0x3ff; > + > + val32 = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2); > + result[t][7] = (val32 >> 16) & 0x3ff; > + break; > + } else { > + result[t][6] = 0x100; > + result[t][7] = 0x0; > + } > + } > + > + if (!path_b_ok) > + dev_warn(dev, "%s: Path B IQK failed!\n", __func__); > + } > + > + /* Back to BB mode, load original value */ > + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); > + > + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xcc0000c0); > + > + rtl8xxxu_write32(priv, 0xd94, 0x44bbbb44); > + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x80408040); > + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005433); > + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000004e4); > + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04003400); > + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100); > + > + /* Reload ADDA power saving parameters */ > + rtl8xxxu_restore_regs(priv, adda_regs, priv->adda_backup, > + ARRAY_SIZE(adda_regs)); > + > + /* Reload MAC parameters */ > + rtl8xxxu_restore_mac_regs(priv, iqk_mac_regs, priv->mac_backup); > + > + /* Reload BB parameters */ > + rtl8xxxu_restore_regs(priv, iqk_bb_regs, priv->bb_backup, RTL8XXXU_BB_REGS); > + > + rtl8xxxu_write32_clear(priv, REG_FPGA0_XCD_RF_PARM, BIT(31)); > + > + /* Restore RX initial gain */ > + rtl8xxxu_write32_mask(priv, REG_OFDM0_XA_AGC_CORE1, 0xff, 0x50); > + rtl8xxxu_write32_mask(priv, REG_OFDM0_XA_AGC_CORE1, 0xff, > + rx_initial_gain_a & 0xff); > + if (priv->rf_paths > 1) { > + rtl8xxxu_write32_mask(priv, REG_OFDM0_XB_AGC_CORE1, 0xff, 0x50); > + rtl8xxxu_write32_mask(priv, REG_OFDM0_XB_AGC_CORE1, 0xff, > + rx_initial_gain_b & 0xff); > + } > +} > + > +static void rtl8192fu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) > +{ > + s32 reg_e94, reg_e9c, reg_ea4, reg_eac; > + s32 reg_eb4, reg_ebc, reg_ec4, reg_ecc; > + struct device *dev = &priv->udev->dev; > + u32 path_a_0xdf, path_a_0x35; > + u32 path_b_0xdf, path_b_0x35; > + bool path_a_ok, path_b_ok; > + u8 rfe = priv->rfe_type; > + u32 rfe_path_select; > + int result[4][8]; /* last is final result */ > + int i, candidate; > + s32 reg_tmp = 0; > + bool simu; > + u32 val32; > + > + rfe_path_select = rtl8xxxu_read32(priv, REG_RFE_PATH_SELECT); > + > + path_a_0xdf = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF); > + path_a_0x35 = rtl8xxxu_read_rfreg(priv, RF_A, 0x35); > + path_b_0xdf = rtl8xxxu_read_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF); > + path_b_0x35 = rtl8xxxu_read_rfreg(priv, RF_B, 0x35); > + > + memset(result, 0, sizeof(result)); > + candidate = -1; > + > + path_a_ok = false; > + path_b_ok = false; > + > + for (i = 0; i < 3; i++) { > + rtl8192fu_phy_iqcalibrate(priv, result, i); > + > + if (i == 1) { > + simu = rtl8xxxu_gen2_simularity_compare(priv, result, 0, 1); > + if (simu) { > + candidate = 0; > + break; > + } > + } > + > + if (i == 2) { > + simu = rtl8xxxu_gen2_simularity_compare(priv, result, 0, 2); > + if (simu) { > + candidate = 0; > + break; > + } > + > + simu = rtl8xxxu_gen2_simularity_compare(priv, result, 1, 2); > + if (simu) { > + candidate = 1; > + } else { > + for (i = 0; i < 8; i++) > + reg_tmp += result[3][i]; > + > + if (reg_tmp) > + candidate = 3; > + else > + candidate = -1; > + } > + } > + } > + > + if (candidate >= 0) { > + reg_e94 = result[candidate][0]; > + reg_e9c = result[candidate][1]; > + reg_ea4 = result[candidate][2]; > + reg_eac = result[candidate][3]; > + reg_eb4 = result[candidate][4]; > + reg_ebc = result[candidate][5]; > + reg_ec4 = result[candidate][6]; > + reg_ecc = result[candidate][7]; > + > + dev_dbg(dev, "%s: candidate is %x\n", __func__, candidate); > + dev_dbg(dev, "%s: e94=%x e9c=%x ea4=%x eac=%x eb4=%x ebc=%x ec4=%x ecc=%c\n", > + __func__, reg_e94, reg_e9c, reg_ea4, reg_eac, > + reg_eb4, reg_ebc, reg_ec4, reg_ecc); > + > + path_a_ok = true; > + path_b_ok = true; > + } > + > + rtl8xxxu_write32_mask(priv, REG_TX_IQK_TONE_A, 0x3ff00000, 0x100); > + rtl8xxxu_write32_mask(priv, 0xe20, 0x3ff, 0); #define REG_NP_ANTA 0xe20 > + rtl8xxxu_write32_mask(priv, REG_TX_IQK_TONE_B, 0x3ff00000, 0x100); > + rtl8xxxu_write32_mask(priv, REG_TAP_UPD_97F, 0x3ff, 0); > + > + if (candidate >= 0) { > + if (reg_e94) > + rtl8xxxu_fill_iqk_matrix_a(priv, path_a_ok, result, > + candidate, (reg_ea4 == 0)); > + > + if (reg_eb4) > + rtl8xxxu_fill_iqk_matrix_b(priv, path_b_ok, result, > + candidate, (reg_ec4 == 0)); > + } > + > + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, path_a_0xdf); > + rtl8xxxu_write_rfreg(priv, RF_A, 0x35, path_a_0x35); > + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, path_b_0xdf); > + rtl8xxxu_write_rfreg(priv, RF_B, 0x35, path_b_0x35); > + > + if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12) { > + rtl8xxxu_write32_set(priv, REG_SW_GPIO_SHARE_CTRL_1, 0x70000); > + rtl8xxxu_write32_clear(priv, REG_LEDCFG0, 0x6c00000); > + rtl8xxxu_write32_set(priv, REG_PAD_CTRL1, BIT(29) | BIT(28)); > + rtl8xxxu_write32_clear(priv, REG_SW_GPIO_SHARE_CTRL_0, > + 0x600000 | BIT(4)); > + > + /* > + * Originally: > + * odm_set_bb_reg(dm, R_0x944, BIT(11) | 0x1F, 0x3F); > + * > + * It clears bit 11 and sets bits 0..4. The mask doesn't cover > + * bit 5 so it's not modified. Is that what it's supposed to > + * accomplish? > + */ > + val32 = rtl8xxxu_read32(priv, REG_RFE_BUFFER); > + val32 &= ~BIT(11); > + val32 |= 0x1f; > + rtl8xxxu_write32(priv, REG_RFE_BUFFER, val32); > + > + if (rfe == 7) { > + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, > + 0xfffff, 0x23200); > + rtl8xxxu_write32_mask(priv, 0x938, 0xfffff, 0x23200); > + rtl8xxxu_write32_mask(priv, 0x934, 0xf000, 0x3); > + rtl8xxxu_write32_mask(priv, 0x93c, 0xf000, 0x3); > + } else { > + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, > + 0xfffff, 0x22200); > + rtl8xxxu_write32_mask(priv, 0x938, 0xfffff, 0x22200); > + rtl8xxxu_write32_mask(priv, 0x934, 0xf000, 0x2); #define REG_RFE_CTRL_ANT_SRC1 0x934 > + rtl8xxxu_write32_mask(priv, 0x93c, 0xf000, 0x2); > + } > + > + rtl8xxxu_write32_clear(priv, 0x968, BIT(2)); #define REG_REF_OPT62 0x968 > + > + if (rfe == 7) > + rtl8xxxu_write32(priv, 0x920, 0x03000003); #define REG_REF_OPT 0x920 > + > + rtl8xxxu_write32(priv, REG_RFE_PATH_SELECT, rfe_path_select); > + } > +} > + > +static void rtl8192fu_disabled_to_emu(struct rtl8xxxu_priv *priv) > +{ > + rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, > + APS_FSMCO_HW_POWERDOWN | APS_FSMCO_HW_SUSPEND); > + > + rtl8xxxu_write32_clear(priv, REG_GPIO_INTM, BIT(16)); > + > + rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, > + APS_FSMCO_PCIE | APS_FSMCO_HW_SUSPEND); > +} > + > +static int rtl8192fu_emu_to_active(struct rtl8xxxu_priv *priv) > +{ > + u32 val32; > + u16 val16; > + int count; > + > + /* enable LDOA12 MACRO block for all interface */ > + rtl8xxxu_write8_set(priv, REG_LDOA15_CTRL, LDOA15_ENABLE); > + > + /* disable BT_GPS_SEL pins */ > + rtl8xxxu_write32_clear(priv, REG_PAD_CTRL1, BIT(28)); > + > + mdelay(1); > + > + /* release analog Ips to digital */ > + rtl8xxxu_write8_clear(priv, REG_SYS_ISO_CTRL, SYS_ISO_ANALOG_IPS); > + > + val16 = APS_FSMCO_PCIE | APS_FSMCO_HW_SUSPEND | APS_FSMCO_SW_LPS; > + rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, val16); > + > + /* wait till 0x04[17] = 1 power ready */ > + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { > + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); > + if (val32 & BIT(17)) > + break; > + > + udelay(10); > + } > + > + if (!count) > + return -EBUSY; > + > + rtl8xxxu_write32_set(priv, REG_APS_FSMCO, APS_FSMCO_WLON_RESET); > + > + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { > + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); > + if ((val32 & (APS_FSMCO_MAC_ENABLE | APS_FSMCO_MAC_OFF)) == 0) > + break; > + > + udelay(10); > + } > + > + if (!count) > + return -EBUSY; > + > + /* SWR OCP enable */ > + rtl8xxxu_write32_set(priv, REG_AFE_MISC, BIT(18)); > + > + rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, APS_FSMCO_HW_POWERDOWN); > + > + rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, > + APS_FSMCO_PCIE | APS_FSMCO_HW_SUSPEND); > + > + /* 0x7c[31]=1, LDO has max output capability */ > + rtl8xxxu_write32_set(priv, REG_LDO_SW_CTRL, BIT(31)); > + > + rtl8xxxu_write16_set(priv, REG_APS_FSMCO, APS_FSMCO_MAC_ENABLE); > + > + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { > + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); > + if ((val32 & APS_FSMCO_MAC_ENABLE) == 0) > + break; > + > + udelay(10); > + } > + > + if (!count) > + return -EBUSY; > + > + /* Enable WL control XTAL setting */ > + rtl8xxxu_write8_set(priv, REG_AFE_MISC, AFE_MISC_WL_XTAL_CTRL); > + > + /* Enable falling edge triggering interrupt */ > + rtl8xxxu_write16_set(priv, REG_GPIO_INTM, GPIO_INTM_EDGE_TRIG_IRQ); > + > + /* Enable GPIO9 data mode */ > + rtl8xxxu_write16_clear(priv, REG_GPIO_IO_SEL_2, GPIO_IO_SEL_2_GPIO09_IRQ); > + > + /* Enable GPIO9 input mode */ > + rtl8xxxu_write16_clear(priv, REG_GPIO_IO_SEL_2, GPIO_IO_SEL_2_GPIO09_INPUT); > + > + /* Enable HSISR GPIO[C:0] interrupt */ > + rtl8xxxu_write8_set(priv, REG_HSIMR, BIT(0)); > + > + /* RF HW ON/OFF Enable */ > + rtl8xxxu_write8_clear(priv, REG_MULTI_FUNC_CTRL, MULTI_WIFI_HW_ROF_EN); > + > + /* Register Lock Disable */ > + rtl8xxxu_write8_set(priv, REG_RSV_CTRL, BIT(7)); > + > + /* For GPIO9 internal pull high setting */ > + rtl8xxxu_write16_set(priv, REG_MULTI_FUNC_CTRL, BIT(14)); > + > + /* reset RF path S1 */ > + rtl8xxxu_write8(priv, REG_RF_CTRL, 0); > + > + /* reset RF path S0 */ > + rtl8xxxu_write8(priv, 0x7b, 0); #define REG_AFE_CTRL4 0x78 use REG_AFE_CTRL4 + 3 for 0x7b > + > + /* enable RF path S1 */ > + rtl8xxxu_write8(priv, REG_RF_CTRL, RF_SDMRSTB | RF_RSTB | RF_ENABLE); > + > + /* enable RF path S0 */ > + rtl8xxxu_write8(priv, 0x7b, RF_SDMRSTB | RF_RSTB | RF_ENABLE); > + > + /* AFE_Ctrl */ > + rtl8xxxu_write8_set(priv, 0x97, BIT(5)); #define REG_RSVD_1 0x97 > + > + /* AFE_Ctrl */ > + rtl8xxxu_write8(priv, 0xdc, 0xcc); #define REG_RSVD_4 0xdc The name looks not so meaningful, but designers did give it as is. > + > + /* AFE_Ctrl 0x24[4:3]=00 for xtal gmn */ > + rtl8xxxu_write8_clear(priv, REG_AFE_XTAL_CTRL, BIT(4) | BIT(3)); > + > + /* GPIO_A[31:0] Pull down software register */ > + rtl8xxxu_write32(priv, 0x1050, 0xffffffff); #define REG_GPIO_A0 0x1050 > + > + /* GPIO_B[7:0] Pull down software register */ > + rtl8xxxu_write8(priv, 0x105b, 0xff); #define REG_GPIO_B0 0x105b > + > + /* Register Lock Enable */ > + rtl8xxxu_write8_clear(priv, REG_RSV_CTRL, BIT(7)); > + > + return 0; > +} > + [...] > @@ -2842,10 +2864,14 @@ void rtl8xxxu_fill_iqk_matrix_b(struct rtl8xxxu_priv *priv, bool iqk_ok, > > reg = (result[candidate][7] >> 6) & 0xf; > > - val32 = rtl8xxxu_read32(priv, REG_OFDM0_AGCR_SSI_TABLE); > - val32 &= ~0x0000f000; > - val32 |= (reg << 12); > - rtl8xxxu_write32(priv, REG_OFDM0_AGCR_SSI_TABLE, val32); > + if (priv->rtl_chip == RTL8192F) { > + val32 = rtl8xxxu_write32_mask(priv, 0xca8, 0x000000f0, reg); Setting val32 to return value isn't reasonable. #dfine REG_RXIQB_EXT 0xca8 > + } else { > + val32 = rtl8xxxu_read32(priv, REG_OFDM0_AGCR_SSI_TABLE); > + val32 &= ~0x0000f000; > + val32 |= (reg << 12); > + rtl8xxxu_write32(priv, REG_OFDM0_AGCR_SSI_TABLE, val32); > + } > } > [...] I lookup register document for uncertain addresses, but this isn't a simple copy-paste thing, so I may mess something. Please tell me if something look weird. Ping-Ke