Bitterblue Smith <rtl8821cerfe2@xxxxxxxxx> wrote: > These contain all the logic for the RTL8821AU and RTL8812AU chips. > > Signed-off-by: Bitterblue Smith <rtl8821cerfe2@xxxxxxxxx> > --- > drivers/net/wireless/realtek/rtw88/rtw8821a.c | 4139 +++++++++++++++++ > drivers/net/wireless/realtek/rtw88/rtw8821a.h | 385 ++ > 2 files changed, 4524 insertions(+) > create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821a.c > create mode 100644 drivers/net/wireless/realtek/rtw88/rtw8821a.h > > diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821a.c > b/drivers/net/wireless/realtek/rtw88/rtw8821a.c > new file mode 100644 > index 000000000000..e72599db74ed > --- /dev/null > +++ b/drivers/net/wireless/realtek/rtw88/rtw8821a.c > @@ -0,0 +1,4139 @@ > +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause > +/* Copyright(c) 2018-2019 Realtek Corporation Year 2024 [...] > +static void rtw8812a_config_1t(struct rtw_dev *rtwdev) > +{ > + /* BB OFDM RX Path_A */ > + rtw_write32_mask(rtwdev, REG_RXPSEL, 0xff, 0x11); > + > + /* BB OFDM TX Path_A */ > + rtw_write32_mask(rtwdev, REG_TXPSEL, MASKLWORD, 0x1111); > + > + /* BB CCK R/Rx Path_A */ > + rtw_write32_mask(rtwdev, REG_CCK_RX, 0x0c000000, 0x0); > + > + /* MCS support */ > + rtw_write32_mask(rtwdev, 0x8bc, 0xc0000060, 0x4); #define REG_RX_MCS_LIMIT 0x8bc The setting value is weird to me though. > + > + /* RF Path_B HSSI OFF */ > + rtw_write32_mask(rtwdev, 0xe00, 0xf, 0x4); #define REG_HSSI_WRITE_B 0xe00 > + > + /* RF Path_B Power Down */ > + rtw_write32_mask(rtwdev, REG_LSSI_WRITE_B, MASKDWORD, 0); > + > + /* ADDA Path_B OFF */ > + rtw_write32_mask(rtwdev, REG_AFE_PWR1_B, MASKDWORD, 0); > + rtw_write32_mask(rtwdev, REG_AFE_PWR2_B, MASKDWORD, 0); > +} [...] > + > +static u8 rtw8821a_get_swing_index(struct rtw_dev *rtwdev) > +{ > + u32 swing, table_value; > + u8 i = 0; no need '= 0' > + > + swing = rtw8821a_get_bb_swing(rtwdev, rtwdev->hal.current_band_type, > + RF_PATH_A); > + > + for (i = 0; i < ARRAY_SIZE(rtw8821a_txscale_tbl); i++) { > + table_value = rtw8821a_txscale_tbl[i]; > + if (swing == table_value) > + break; return i; > + } > + > + return i; return ARRAY_SIZE(rtw8821a_txscale_tbl)? (but I don't like it so much) or return 24; Move checking statement from callers to here. > +} > + > +static void rtw8821a_pwrtrack_init(struct rtw_dev *rtwdev) > +{ > + struct rtw_dm_info *dm_info = &rtwdev->dm_info; > + u8 ofdm_swing_idx; > + u8 path; > + > + ofdm_swing_idx = rtw8821a_get_swing_index(rtwdev); > + > + if (ofdm_swing_idx >= ARRAY_SIZE(rtw8821a_txscale_tbl)) > + dm_info->default_ofdm_index = 24; > + else > + dm_info->default_ofdm_index = ofdm_swing_idx; If rtw8821a_get_swing_index(rtwdev) returns 24 for the case we can't find a match from rtw8821a_txscale_tbl[], here can be simply dm_info->default_ofdm_index = rtw8821a_get_swing_index(rtwdev); > + > + if (rtwdev->chip->id == RTW_CHIP_TYPE_8821A) > + dm_info->default_cck_index = 0; > + else > + dm_info->default_cck_index = 24; > + > + for (path = RF_PATH_A; path < rtwdev->hal.rf_path_num; path++) { > + ewma_thermal_init(&dm_info->avg_thermal[path]); > + dm_info->delta_power_index[path] = 0; > + dm_info->delta_power_index_last[path] = 0; > + } > + > + dm_info->pwr_trk_triggered = false; > + dm_info->pwr_trk_init_trigger = true; > + dm_info->thermal_meter_k = rtwdev->efuse.thermal_meter_k; > +} > + [...] > +static int rtw8821a_power_on(struct rtw_dev *rtwdev) > +{ Will the coming RTL8814AU share this flow? If so, we can move this power on to main.c/mac.c as rtw_power_on_v1() or something else. If we decide moving power on flow into chip specific files, the duplicate code will become more and more. Please think about this. > + struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); > + const struct rtw_chip_info *chip = rtwdev->chip; > + struct rtw_efuse *efuse = &rtwdev->efuse; > + struct rtw_hal *hal = &rtwdev->hal; > + int ret; > + > + if (test_bit(RTW_FLAG_POWERON, rtwdev->flags)) > + return 0; > + > + /* Override rtw_chip_efuse_info_setup() */ > + if (chip->id == RTW_CHIP_TYPE_8821A) > + efuse->btcoex = rtw_read32_mask(rtwdev, REG_WL_BT_PWR_CTRL, > + BIT_BT_FUNC_EN); > + > + /* Override rtw_chip_efuse_info_setup() */ > + if (chip->id == RTW_CHIP_TYPE_8812A) > + rtw8812a_read_amplifier_type(rtwdev); > + > + ret = rtw_hci_setup(rtwdev); > + if (ret) { > + rtw_err(rtwdev, "failed to setup hci\n"); > + goto err; > + } > + > + /* Revise for U2/U3 switch we can not update RF-A/B reset. > + * Reset after MAC power on to prevent RF R/W error. > + * Is it a right method? > + */ > + if (chip->id == RTW_CHIP_TYPE_8812A) { > + rtw_write8(rtwdev, REG_RF_CTRL, 5); > + rtw_write8(rtwdev, REG_RF_CTRL, 7); > + rtw_write8(rtwdev, REG_RF_B_CTRL, 5); > + rtw_write8(rtwdev, REG_RF_B_CTRL, 7); > + } > + > + /* If HW didn't go through a complete de-initial procedure, > + * it probably occurs some problem for double initial > + * procedure. > + */ > + rtw8812au_hw_reset(rtwdev); > + > + ret = rtw8812au_init_power_on(rtwdev); > + if (ret) { > + rtw_err(rtwdev, "failed to power on\n"); > + goto err; > + } > + > + ret = rtw_set_trx_fifo_info(rtwdev); > + if (ret) { > + rtw_err(rtwdev, "failed to set trx fifo info\n"); > + goto err; > + } > + > + ret = rtw8821a_llt_init(rtwdev, rtwdev->fifo.rsvd_boundary); > + if (ret) { > + rtw_err(rtwdev, "failed to init llt\n"); > + goto err; > + } > + > + rtw_write32_set(rtwdev, REG_TXDMA_OFFSET_CHK, BIT_DROP_DATA_EN); > + > + ret = rtw_wait_firmware_completion(rtwdev); > + if (ret) { > + rtw_err(rtwdev, "failed to wait firmware completion\n"); > + goto err_off; > + } > + > + ret = rtw_download_firmware(rtwdev, &rtwdev->fw); > + if (ret) { > + rtw_err(rtwdev, "failed to download firmware\n"); > + goto err_off; > + } > + > + rtw_write8(rtwdev, REG_HMETFR, 0xf); > + > + rtw_load_table(rtwdev, chip->mac_tbl); > + > + rtw8821au_init_queue_reserved_page(rtwdev); > + rtw8821au_init_tx_buffer_boundary(rtwdev); > + rtw8821au_init_queue_priority(rtwdev); > + Seemingly above flow looks common. Can it share with other chips? [...] > +} > + > +static u32 rtw8821a_phy_read_rf(struct rtw_dev *rtwdev, > + enum rtw_rf_path rf_path, u32 addr, u32 mask) > +{ read/write RF functions are also common for chips. Can it share with coming RTL8814A? Move this to phy.c as v1? > + static const u32 pi_addr[2] = { 0xc00, 0xe00 }; > + static const u32 read_addr[2][2] = { > + { REG_SI_READ_A, REG_SI_READ_B }, > + { REG_PI_READ_A, REG_PI_READ_B } > + }; [...] > + > +static void rtw8821a_query_phy_status(struct rtw_dev *rtwdev, u8 *phy_status, > + struct rtw_rx_pkt_stat *pkt_stat) > +{ > + struct rtw_dm_info *dm_info = &rtwdev->dm_info; > + struct rtw8821a_phy_status_rpt *phy_sts; > + u8 lna_idx, vga_idx, cck_agc_rpt; > + s8 rx_pwr_db, power_a, power_b; > + const s8 min_rx_power = -120; > + u8 rssi, val, i; > + > + phy_sts = (struct rtw8821a_phy_status_rpt *)phy_status; > + > + if (pkt_stat->rate <= DESC_RATE11M) { > + cck_agc_rpt = phy_sts->cfosho[0]; > + lna_idx = (cck_agc_rpt & 0xE0) >> 5; > + vga_idx = cck_agc_rpt & 0x1F; If we remove "#ifdef __LITTLE_ENDIAN" from rtw8821a_phy_status_rpt and define bit mask there, additionally define these bit masks and then use u8_get_bits(). By the way, shouldn't the field of 'cfosho[2]' be 'u8' instead of 's8'? > + > + if (rtwdev->chip->id == RTW_CHIP_TYPE_8821A) > + rx_pwr_db = rtw8821a_cck_rx_pwr(rtwdev, lna_idx, vga_idx); > + else > + rx_pwr_db = rtw8812a_cck_rx_pwr(rtwdev, lna_idx, vga_idx); > + > + pkt_stat->rx_power[RF_PATH_A] = rx_pwr_db; > + pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, 1); > + dm_info->rssi[RF_PATH_A] = pkt_stat->rssi; > + pkt_stat->bw = RTW_CHANNEL_WIDTH_20; > + pkt_stat->signal_power = rx_pwr_db; > + > + if (rtwdev->chip->id == RTW_CHIP_TYPE_8812A && > + !rtwdev->hal.cck_high_power) { > + if (pkt_stat->rssi >= 80) > + pkt_stat->rssi = ((pkt_stat->rssi - 80) << 1) + > + ((pkt_stat->rssi - 80) >> 1) + 80; > + else if (pkt_stat->rssi <= 78 && pkt_stat->rssi >= 20) > + pkt_stat->rssi += 3; > + } > + } else { /* OFDM rate */ > + for (i = RF_PATH_A; i < rtwdev->hal.rf_path_num; i++) { > + val = phy_sts->gain_trsw[i]; > + pkt_stat->rx_power[i] = (val & 0x7F) - 110; > + rssi = rtw_phy_rf_power_2_rssi(&pkt_stat->rx_power[i], 1); > + dm_info->rssi[i] = rssi; > + } > + > + pkt_stat->rssi = rtw_phy_rf_power_2_rssi(pkt_stat->rx_power, > + rtwdev->hal.rf_path_num); > + > + power_a = pkt_stat->rx_power[RF_PATH_A]; > + power_b = pkt_stat->rx_power[RF_PATH_B]; > + if (rtwdev->hal.rf_path_num == 1) > + power_b = power_a; > + > + pkt_stat->signal_power = max3(power_a, power_b, min_rx_power); > + } > +} > + > +static void rtw8821a_query_rx_desc(struct rtw_dev *rtwdev, u8 *rx_desc, > + struct rtw_rx_pkt_stat *pkt_stat, > + struct ieee80211_rx_status *rx_status) > +{ > + u32 desc_sz = rtwdev->chip->rx_pkt_desc_sz; > + struct ieee80211_hdr *hdr; > + u8 *phy_status = NULL; > + > + memset(pkt_stat, 0, sizeof(*pkt_stat)); > + > + pkt_stat->phy_status = GET_RX_DESC_PHYST(rx_desc); > + pkt_stat->icv_err = GET_RX_DESC_ICV_ERR(rx_desc); > + pkt_stat->crc_err = GET_RX_DESC_CRC32(rx_desc); > + pkt_stat->decrypted = !GET_RX_DESC_SWDEC(rx_desc) && > + GET_RX_DESC_ENC_TYPE(rx_desc) != RX_DESC_ENC_NONE; > + pkt_stat->is_c2h = GET_RX_DESC_C2H(rx_desc); > + pkt_stat->pkt_len = GET_RX_DESC_PKT_LEN(rx_desc); > + pkt_stat->drv_info_sz = GET_RX_DESC_DRV_INFO_SIZE(rx_desc); > + pkt_stat->shift = GET_RX_DESC_SHIFT(rx_desc); > + pkt_stat->rate = GET_RX_DESC_RX_RATE(rx_desc); > + pkt_stat->cam_id = GET_RX_DESC_MACID(rx_desc); > + pkt_stat->ppdu_cnt = 0; > + pkt_stat->tsf_low = GET_RX_DESC_TSFL(rx_desc); > + pkt_stat->bw = GET_RX_DESC_BW(rx_desc); More and more chips use these macros. Please add a patch using struct to access these fields. More, query_rx_desc() are very similar across chips, please move them to mac.c or phy.c as a common function. > + > + /* drv_info_sz is in unit of 8-bytes */ > + pkt_stat->drv_info_sz *= 8; > + > + /* c2h cmd pkt's rx/phy status is not interested */ > + if (pkt_stat->is_c2h) > + return; > + > + hdr = (struct ieee80211_hdr *)(rx_desc + desc_sz + pkt_stat->shift + > + pkt_stat->drv_info_sz); > + if (pkt_stat->phy_status) { > + phy_status = rx_desc + desc_sz + pkt_stat->shift; > + rtw8821a_query_phy_status(rtwdev, phy_status, pkt_stat); > + } > + > + rtw_rx_fill_rx_status(rtwdev, pkt_stat, hdr, rx_status, phy_status); > +} > + [...] > + > +static void rtw8821a_false_alarm_statistics(struct rtw_dev *rtwdev) > +{ > + struct rtw_dm_info *dm_info = &rtwdev->dm_info; > + u32 cck_fa_cnt, ofdm_fa_cnt; > + u32 crc32_cnt, cca32_cnt; > + u32 cck_enable; > + > + cck_enable = rtw_read32(rtwdev, REG_RXPSEL) & BIT(28); > + cck_fa_cnt = rtw_read16(rtwdev, REG_FA_CCK); > + ofdm_fa_cnt = rtw_read16(rtwdev, REG_FA_OFDM); > + > + dm_info->cck_fa_cnt = cck_fa_cnt; > + dm_info->ofdm_fa_cnt = ofdm_fa_cnt; > + dm_info->total_fa_cnt = ofdm_fa_cnt; > + if (cck_enable) > + dm_info->total_fa_cnt += cck_fa_cnt; > + > + crc32_cnt = rtw_read32(rtwdev, REG_CRC_CCK); > + dm_info->cck_ok_cnt = FIELD_GET(GENMASK(15, 0), crc32_cnt); > + dm_info->cck_err_cnt = FIELD_GET(GENMASK(31, 16), crc32_cnt); use u32_get_bits() instead. > + > + crc32_cnt = rtw_read32(rtwdev, REG_CRC_OFDM); > + dm_info->ofdm_ok_cnt = FIELD_GET(GENMASK(15, 0), crc32_cnt); > + dm_info->ofdm_err_cnt = FIELD_GET(GENMASK(31, 16), crc32_cnt); > + > + crc32_cnt = rtw_read32(rtwdev, REG_CRC_HT); > + dm_info->ht_ok_cnt = FIELD_GET(GENMASK(15, 0), crc32_cnt); > + dm_info->ht_err_cnt = FIELD_GET(GENMASK(31, 16), crc32_cnt); > + > + crc32_cnt = rtw_read32(rtwdev, REG_CRC_VHT); > + dm_info->vht_ok_cnt = FIELD_GET(GENMASK(15, 0), crc32_cnt); > + dm_info->vht_err_cnt = FIELD_GET(GENMASK(31, 16), crc32_cnt); > + > + cca32_cnt = rtw_read32(rtwdev, REG_CCA_OFDM); > + dm_info->ofdm_cca_cnt = FIELD_GET(GENMASK(31, 16), cca32_cnt); > + dm_info->total_cca_cnt = dm_info->ofdm_cca_cnt; > + if (cck_enable) { > + cca32_cnt = rtw_read32(rtwdev, REG_CCA_CCK); > + dm_info->cck_cca_cnt = FIELD_GET(GENMASK(15, 0), cca32_cnt); > + dm_info->total_cca_cnt += dm_info->cck_cca_cnt; > + } > + > + rtw_write32_set(rtwdev, REG_FAS, BIT(17)); > + rtw_write32_clr(rtwdev, REG_FAS, BIT(17)); > + rtw_write32_clr(rtwdev, REG_RXDESC, BIT(15)); > + rtw_write32_set(rtwdev, REG_RXDESC, BIT(15)); > + rtw_write32_set(rtwdev, REG_CNTRST, BIT(0)); > + rtw_write32_clr(rtwdev, REG_CNTRST, BIT(0)); > +} > + [...] > + > +static void rtw8821a_iqk_restore_afe(struct rtw_dev *rtwdev, u32 *afe_backup, > + const u32 *backup_afe_reg, u32 afe_num) > +{ > + u32 i; > + > + /* [31] = 0 --> Page C */ > + rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); > + > + /* Reload AFE Parameters */ > + for (i = 0; i < afe_num; i++) > + rtw_write32(rtwdev, backup_afe_reg[i], afe_backup[i]); > + > + /* [31] = 1 --> Page C1 */ > + rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); > + > + rtw_write32(rtwdev, 0xc80, 0x0); > + rtw_write32(rtwdev, 0xc84, 0x0); > + rtw_write32(rtwdev, 0xc88, 0x0); > + rtw_write32(rtwdev, 0xc8c, 0x3c000000); > + rtw_write32(rtwdev, REG_LSSI_WRITE_A, 0x00000080); > + rtw_write32(rtwdev, 0xc94, 0x00000000); > + rtw_write32(rtwdev, 0xcc4, 0x20040000); > + rtw_write32(rtwdev, 0xcc8, 0x20000000); > + rtw_write32(rtwdev, REG_RFECTL_A, 0x0); I think we can reuse existing definitions: rtw8723x.h:#define REG_OFDM_0_XA_TX_IQ_IMBALANCE 0x0c80 rtw8703b.h:#define REG_OFDM0_A_TX_AFE 0x0c84 rtw8723x.h:#define REG_OFDM_0_XB_TX_IQ_IMBALANCE 0x0c88 #define REG_TSSI_TRK_SW 0xc8c rtw8821a.h:#define REG_TXAGCIDX 0xc94 #define REG_IQK_DPD_CFG 0xcc4 #define REG_CFG_PMPD 0xcc8 [...] > + > +static void rtw8821a_iqk_tx_fill(struct rtw_dev *rtwdev, > + unsigned int tx_x, unsigned int tx_y) > +{ > + /* [31] = 1 --> Page C1 */ > + rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); > + > + rtw_write32(rtwdev, REG_LSSI_WRITE_A, 0x00000080); > + rtw_write32(rtwdev, 0xcc4, 0x20040000); > + rtw_write32(rtwdev, 0xcc8, 0x20000000); > + rtw_write32_mask(rtwdev, 0xccc, 0x000007ff, tx_y); > + rtw_write32_mask(rtwdev, 0xcd4, 0x000007ff, tx_x); #define REG_IQC_Y 0xccc #define REG_IQC_X 0xcd4 > +} > + > +static void rtw8821a_iqk_tx_vdf_true(struct rtw_dev *rtwdev, u32 cal, > + bool *tx0iqkok, > + int tx_x0[CAL_NUM_8821A], > + int tx_y0[CAL_NUM_8821A]) > +{ > + u32 cal_retry, delay_count, iqk_ready, tx_fail; > + int tx_dt[3], vdf_y[3], vdf_x[3]; > + int k; > + > + for (k = 0; k <= 2; k++) { '< 3' would be more intuitive, because 'k' is index of array. > + switch (k) { > + case 0: > + /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ > + rtw_write32(rtwdev, 0xc80, 0x18008c38); > + /* RX_Tone_idx[9:0], RxK_Mask[29] */ > + rtw_write32(rtwdev, 0xc84, 0x38008c38); > + rtw_write32_mask(rtwdev, 0xce8, BIT(31), 0x0); > + break; > + case 1: > + rtw_write32_mask(rtwdev, 0xc80, BIT(28), 0x0); > + rtw_write32_mask(rtwdev, 0xc84, BIT(28), 0x0); > + rtw_write32_mask(rtwdev, 0xce8, BIT(31), 0x0); > + break; > + case 2: > + rtw_dbg(rtwdev, RTW_DBG_RFK, > + "vdf_y[1] = %x vdf_y[0] = %x\n", > + vdf_y[1] >> 21 & 0x00007ff, > + vdf_y[0] >> 21 & 0x00007ff); > + > + rtw_dbg(rtwdev, RTW_DBG_RFK, > + "vdf_x[1] = %x vdf_x[0] = %x\n", > + vdf_x[1] >> 21 & 0x00007ff, > + vdf_x[0] >> 21 & 0x00007ff); > + > + tx_dt[cal] = (vdf_y[1] >> 20) - (vdf_y[0] >> 20); > + tx_dt[cal] = (16 * tx_dt[cal]) * 10000 / 15708; > + tx_dt[cal] = (tx_dt[cal] >> 1) + (tx_dt[cal] & BIT(0)); > + > + /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ > + rtw_write32(rtwdev, 0xc80, 0x18008c20); > + /* RX_Tone_idx[9:0], RxK_Mask[29] */ > + rtw_write32(rtwdev, 0xc84, 0x38008c20); > + rtw_write32_mask(rtwdev, 0xce8, BIT(31), 0x1); > + rtw_write32_mask(rtwdev, 0xce8, 0x3fff0000, > + tx_dt[cal] & 0x00003fff); > + break; > + } > + > + rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000); > + cal_retry = 0; > + while (1) { Can we replace 'while()' by 'for (cal_retry = 0; cal_retry < 10; cal_retry++)'? > + /* one shot */ > + rtw_write32(rtwdev, 0x980, 0xfa000000); > + rtw_write32(rtwdev, 0x980, 0xf8000000); > + > + mdelay(10); > + > + rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000); > + > + delay_count = 0; > + while (1) { Similarly. 'for (delay_count = 0; delay_count < 20; delay_count++)'. > + iqk_ready = rtw_read32_mask(rtwdev, 0xd00, BIT(10)); > + > + /* Originally: if (~iqk_ready || delay_count > 20) > + * that looks like a typo so make it more explicit > + */ > + iqk_ready = true; > + > + if (iqk_ready || delay_count > 20) > + break; > + > + mdelay(1); > + delay_count++; > + } > + > + if (delay_count < 20) { > + /* ============TXIQK Check============== */ > + tx_fail = rtw_read32_mask(rtwdev, 0xd00, BIT(12)); > + > + /* Originally: if (~tx_fail) { > + * It looks like a typo, so make it more explicit. > + */ > + tx_fail = false; > + > + if (!tx_fail) { > + rtw_write32(rtwdev, REG_RFECTL_A, > + 0x02000000); > + vdf_x[k] = rtw_read32_mask(rtwdev, 0xd00, > + 0x07ff0000); > + vdf_x[k] <<= 21; > + > + rtw_write32(rtwdev, REG_RFECTL_A, > + 0x04000000); > + vdf_y[k] = rtw_read32_mask(rtwdev, 0xd00, > + 0x07ff0000); > + vdf_y[k] <<= 21; > + > + *tx0iqkok = true; > + break; > + } > + > + rtw_write32_mask(rtwdev, 0xccc, 0x000007ff, 0x0); > + rtw_write32_mask(rtwdev, 0xcd4, 0x000007ff, 0x200); > + > + *tx0iqkok = false; > + cal_retry++; > + if (cal_retry == 10) > + break; > + } else { /* If 20ms No Result, then cal_retry++ */ > + *tx0iqkok = false; > + cal_retry++; > + if (cal_retry == 10) > + break; > + } > + } > + } > + > + if (k == 3) { > + tx_x0[cal] = vdf_x[k - 1]; > + tx_y0[cal] = vdf_y[k - 1]; > + } > +} > + > +static void rtw8821a_iqk_tx_vdf_false(struct rtw_dev *rtwdev, u32 cal, > + bool *tx0iqkok, > + int tx_x0[CAL_NUM_8821A], > + int tx_y0[CAL_NUM_8821A]) > +{ > + u32 cal_retry, delay_count, iqk_ready, tx_fail; > + > + /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ > + rtw_write32(rtwdev, 0xc80, 0x18008c10); > + /* RX_Tone_idx[9:0], RxK_Mask[29] */ > + rtw_write32(rtwdev, 0xc84, 0x38008c10); > + rtw_write32(rtwdev, 0xcb8, 0x00100000); > + > + cal_retry = 0; > + while (1) { Ditto. 'for (cal_retry = 0; cal_retry < 10; cal_retry++)' > + /* one shot */ > + rtw_write32(rtwdev, 0x980, 0xfa000000); > + rtw_write32(rtwdev, 0x980, 0xf8000000); > + > + mdelay(10); > + rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000); > + > + delay_count = 0; > + while (1) { 'for (delay_count = 0; delay_count < 20; delay_count++)'. > + iqk_ready = rtw_read32_mask(rtwdev, 0xd00, BIT(10)); > + > + /* Originally: if (~iqk_ready || delay_count > 20) > + * that looks like a typo so make it more explicit > + */ > + iqk_ready = true; > + > + if (iqk_ready || delay_count > 20) > + break; > + > + mdelay(1); > + delay_count++; > + } > + > + if (delay_count < 20) { > + /* ============TXIQK Check============== */ > + tx_fail = rtw_read32_mask(rtwdev, 0xd00, BIT(12)); > + > + /* Originally: if (~tx_fail) { > + * It looks like a typo, so make it more explicit. > + */ > + tx_fail = false; > + > + if (!tx_fail) { > + rtw_write32(rtwdev, REG_RFECTL_A, 0x02000000); > + tx_x0[cal] = rtw_read32_mask(rtwdev, 0xd00, > + 0x07ff0000); > + tx_x0[cal] <<= 21; > + > + rtw_write32(rtwdev, REG_RFECTL_A, 0x04000000); > + tx_y0[cal] = rtw_read32_mask(rtwdev, 0xd00, > + 0x07ff0000); > + tx_y0[cal] <<= 21; > + > + *tx0iqkok = true; > + break; > + } > + > + rtw_write32_mask(rtwdev, 0xccc, 0x000007ff, 0x0); > + rtw_write32_mask(rtwdev, 0xcd4, 0x000007ff, 0x200); > + > + *tx0iqkok = false; > + cal_retry++; > + if (cal_retry == 10) > + break; > + } else { /* If 20ms No Result, then cal_retry++ */ > + *tx0iqkok = false; > + cal_retry++; > + if (cal_retry == 10) > + break; > + } > + } > +} > + > +static void rtw8821a_iqk_rx(struct rtw_dev *rtwdev, u32 cal, bool *rx0iqkok, > + int rx_x0[CAL_NUM_8821A], > + int rx_y0[CAL_NUM_8821A]) > +{ > + u32 cal_retry, delay_count, iqk_ready, rx_fail; > + > + rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000); > + > + cal_retry = 0; > + while (1) { 'for (cal_retry = 0; cal_retry < 10; cal_retry++)' > + /* one shot */ > + rtw_write32(rtwdev, 0x980, 0xfa000000); > + rtw_write32(rtwdev, 0x980, 0xf8000000); > + > + mdelay(10); > + > + rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000); > + > + delay_count = 0; > + while (1) { 'for (delay_count = 0; delay_count < 20; delay_count++)'. > + iqk_ready = rtw_read32_mask(rtwdev, 0xd00, BIT(10)); > + > + /* Originally: if (~iqk_ready || delay_count > 20) > + * that looks like a typo so make it more explicit > + */ > + iqk_ready = true; > + > + if (iqk_ready || delay_count > 20) > + break; > + > + mdelay(1); > + delay_count++; > + } > + > + if (delay_count < 20) { > + /* ============RXIQK Check============== */ > + rx_fail = rtw_read32_mask(rtwdev, 0xd00, BIT(11)); > + if (!rx_fail) { > + rtw_write32(rtwdev, REG_RFECTL_A, 0x06000000); > + rx_x0[cal] = rtw_read32_mask(rtwdev, 0xd00, > + 0x07ff0000); > + rx_x0[cal] <<= 21; > + > + rtw_write32(rtwdev, REG_RFECTL_A, 0x08000000); > + rx_y0[cal] = rtw_read32_mask(rtwdev, 0xd00, > + 0x07ff0000); > + rx_y0[cal] <<= 21; > + > + *rx0iqkok = true; > + break; > + } > + > + rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A, > + 0x000003ff, 0x200 >> 1); > + rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A, > + 0x03ff0000, 0x0 >> 1); > + > + *rx0iqkok = false; > + cal_retry++; > + if (cal_retry == 10) > + break; > + } else { /* If 20ms No Result, then cal_retry++ */ > + *rx0iqkok = false; > + cal_retry++; > + if (cal_retry == 10) > + break; > + } > + } > +} > + > +static bool rtw8821a_iqk_finish(int average, int threshold, > + int *x_temp, int *y_temp, int *x, int *y, > + bool break_inner, bool break_outer) > +{ > + bool finish = false; > + int i, ii, dx, dy; > + > + for (i = 0; i < average; i++) { > + for (ii = i + 1; ii < average; ii++) { > + dx = abs_diff(x_temp[i] >> 21, x_temp[ii] >> 21); > + dy = abs_diff(y_temp[i] >> 21, y_temp[ii] >> 21); > + > + if (dx < threshold && dy < threshold) { > + *x = ((x_temp[i] >> 21) + (x_temp[ii] >> 21)); > + *y = ((y_temp[i] >> 21) + (y_temp[ii] >> 21)); > + > + *x /= 2; > + *y /= 2; > + > + finish = true; > + > + if (break_inner) > + break; > + } > + } > + > + if (finish && break_outer) > + break; > + } > + > + return finish; > +} > + > +static void rtw8821a_iqk(struct rtw_dev *rtwdev) > +{ > + int tx_average = 0, rx_average = 0, rx_iqk_loop = 0; > + const struct rtw_efuse *efuse = &rtwdev->efuse; > + int tx_x = 0, tx_y = 0, rx_x = 0, rx_y = 0; > + const struct rtw_hal *hal = &rtwdev->hal; > + bool tx0iqkok = false, rx0iqkok = false; > + int rx_x_temp = 0, rx_y_temp = 0; > + int rx_x0[2][CAL_NUM_8821A]; > + int rx_y0[2][CAL_NUM_8821A]; > + int tx_x0[CAL_NUM_8821A]; > + int tx_y0[CAL_NUM_8821A]; > + bool rx_finish1 = false; > + bool rx_finish2 = false; > + bool vdf_enable; > + u32 cal = 0; > + int i; > + > + rtw_dbg(rtwdev, RTW_DBG_RFK, > + "band_width = %d, ext_pa = %d, ext_pa_5g = %d\n", > + hal->current_band_width, efuse->ext_pa_2g, efuse->ext_pa_5g); > + > + vdf_enable = hal->current_band_width == RTW_CHANNEL_WIDTH_80; > + > + while (cal < CAL_NUM_8821A) { for (cal = 0; cal < CAL_NUM_8821A; cal++) [...] > +static void rtw8812a_iqk_rx_fill(struct rtw_dev *rtwdev, enum rtw_rf_path path, > + unsigned int rx_x, unsigned int rx_y) > +{ > + switch (path) { > + case RF_PATH_A: { no need brace for 'case:'. > + /* [31] = 0 --> Page C */ > + rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); > + if (rx_x >> 1 >= 0x112 || (rx_y >> 1 >= 0x12 && rx_y >> 1 <= 0x3ee)) { > + rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A, 0x000003ff, 0x100); > + rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A, 0x03ff0000, 0); > + } else { > + rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A, 0x000003ff, rx_x >> 1); > + rtw_write32_mask(rtwdev, REG_RX_IQC_AB_A, 0x03ff0000, rx_y >> 1); > + } > + rtw_dbg(rtwdev, RTW_DBG_RFK, > + "rx_x = %x;;rx_y = %x ====>fill to IQC\n", > + rx_x >> 1 & 0x000003ff, rx_y >> 1 & 0x000003ff); > + rtw_dbg(rtwdev, RTW_DBG_RFK, "0xc10 = %x ====>fill to IQC\n", > + rtw_read32(rtwdev, REG_RX_IQC_AB_A)); > + } break; > + case RF_PATH_B: { ditto. > + /* [31] = 0 --> Page C */ > + rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); > + if (rx_x >> 1 >= 0x112 || (rx_y >> 1 >= 0x12 && rx_y >> 1 <= 0x3ee)) { > + rtw_write32_mask(rtwdev, REG_RX_IQC_AB_B, 0x000003ff, 0x100); > + rtw_write32_mask(rtwdev, REG_RX_IQC_AB_B, 0x03ff0000, 0); > + } else { > + rtw_write32_mask(rtwdev, REG_RX_IQC_AB_B, 0x000003ff, rx_x >> 1); > + rtw_write32_mask(rtwdev, REG_RX_IQC_AB_B, 0x03ff0000, rx_y >> 1); > + } > + rtw_dbg(rtwdev, RTW_DBG_RFK, > + "rx_x = %x;;rx_y = %x ====>fill to IQC\n", > + rx_x >> 1 & 0x000003ff, rx_y >> 1 & 0x000003ff); > + rtw_dbg(rtwdev, RTW_DBG_RFK, "0xe10 = %x====>fill to IQC\n", > + rtw_read32(rtwdev, REG_RX_IQC_AB_B)); > + } break; > + default: > + break; > + }; no need semicolon > +} > + > +static void rtw8812a_iqk_tx_fill(struct rtw_dev *rtwdev, enum rtw_rf_path path, > + unsigned int tx_x, unsigned int tx_y) > +{ > + switch (path) { > + case RF_PATH_A: { no need brace > + /* [31] = 1 --> Page C1 */ > + rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); > + rtw_write32_mask(rtwdev, 0xc90, BIT(7), 0x1); > + rtw_write32_mask(rtwdev, 0xcc4, BIT(18), 0x1); > + rtw_write32_mask(rtwdev, 0xcc4, BIT(29), 0x1); > + rtw_write32_mask(rtwdev, 0xcc8, BIT(29), 0x1); > + rtw_write32_mask(rtwdev, 0xccc, 0x000007ff, tx_y); > + rtw_write32_mask(rtwdev, 0xcd4, 0x000007ff, tx_x); > + rtw_dbg(rtwdev, RTW_DBG_RFK, > + "tx_x = %x;;tx_y = %x =====> fill to IQC\n", > + tx_x & 0x000007ff, tx_y & 0x000007ff); > + rtw_dbg(rtwdev, RTW_DBG_RFK, > + "0xcd4 = %x;;0xccc = %x ====>fill to IQC\n", > + rtw_read32_mask(rtwdev, 0xcd4, 0x000007ff), > + rtw_read32_mask(rtwdev, 0xccc, 0x000007ff)); > + } break; > + case RF_PATH_B: { ditto. > + /* [31] = 1 --> Page C1 */ > + rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); > + rtw_write32_mask(rtwdev, 0xe90, BIT(7), 0x1); > + rtw_write32_mask(rtwdev, 0xec4, BIT(18), 0x1); > + rtw_write32_mask(rtwdev, 0xec4, BIT(29), 0x1); > + rtw_write32_mask(rtwdev, 0xec8, BIT(29), 0x1); > + rtw_write32_mask(rtwdev, 0xecc, 0x000007ff, tx_y); > + rtw_write32_mask(rtwdev, 0xed4, 0x000007ff, tx_x); > + rtw_dbg(rtwdev, RTW_DBG_RFK, > + "tx_x = %x;;tx_y = %x =====> fill to IQC\n", > + tx_x & 0x000007ff, tx_y & 0x000007ff); > + rtw_dbg(rtwdev, RTW_DBG_RFK, > + "0xed4 = %x;;0xecc = %x ====>fill to IQC\n", > + rtw_read32_mask(rtwdev, 0xed4, 0x000007ff), > + rtw_read32_mask(rtwdev, 0xecc, 0x000007ff)); > + } break; > + default: > + break; > + }; no need semicolon > +} > + > +static void rtw8812a_iqk(struct rtw_dev *rtwdev) > +{ > + int tx_x0_temp[10], tx_y0_temp[10], tx_x1_temp[10], tx_y1_temp[10]; > + int rx_x0_temp[10], rx_y0_temp[10], rx_x1_temp[10], rx_y1_temp[10]; > + bool iqk0_ready = false, tx0_finish = false, rx0_finish = false; > + bool iqk1_ready = false, tx1_finish = false, rx1_finish = false; > + u8 tx0_avg = 0, tx1_avg = 0, rx0_avg = 0, rx1_avg = 0; > + struct rtw_efuse *efuse = &rtwdev->efuse; > + bool tx0_fail = true, rx0_fail = true; > + bool tx1_fail = true, rx1_fail = true; > + int tx_x0, tx_y0, tx_x1, tx_y1; > + int rx_x0, rx_y0, rx_x1, rx_y1; > + u8 cal0_retry, cal1_retry; > + u8 delay_count; > + > + /* [31] = 0 --> Page C */ > + rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); > + > + /* ========path-A AFE all on======== */ > + /* Port 0 DAC/ADC on */ > + rtw_write32(rtwdev, REG_AFE_PWR1_A, 0x77777777); > + rtw_write32(rtwdev, REG_AFE_PWR2_A, 0x77777777); > + > + /* Port 1 DAC/ADC on */ > + rtw_write32(rtwdev, REG_AFE_PWR1_B, 0x77777777); > + rtw_write32(rtwdev, REG_AFE_PWR2_B, 0x77777777); > + > + rtw_write32(rtwdev, REG_RX_WAIT_CCA_TX_CCK_RFON_A, 0x19791979); > + rtw_write32(rtwdev, REG_RX_WAIT_CCA_TX_CCK_RFON_B, 0x19791979); > + > + /* hardware 3-wire off */ > + rtw_write32_mask(rtwdev, 0xc00, 0xf, 0x4); > + rtw_write32_mask(rtwdev, 0xe00, 0xf, 0x4); > + > + /* DAC/ADC sampling rate (160 MHz) */ > + rtw_write32_mask(rtwdev, 0xc5c, BIT(26) | BIT(25) | BIT(24), 0x7); > + rtw_write32_mask(rtwdev, 0xe5c, BIT(26) | BIT(25) | BIT(24), 0x7); > + > + /* [31] = 0 --> Page C */ > + rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x0); > + /* ====== path A TX IQK RF setting ====== */ > + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWE, RFREG_MASK, 0x80002); > + rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_ADDR, RFREG_MASK, 0x20000); > + rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA0, RFREG_MASK, 0x3fffd); > + rtw_write_rf(rtwdev, RF_PATH_A, RF_MODE_TABLE_DATA1, RFREG_MASK, 0xfe83f); > + rtw_write_rf(rtwdev, RF_PATH_A, 0x65, RFREG_MASK, 0x931d5); > + rtw_write_rf(rtwdev, RF_PATH_A, 0x8f, RFREG_MASK, 0x8a001); > + > + /* ====== path B TX IQK RF setting ====== */ > + rtw_write_rf(rtwdev, RF_PATH_B, RF_LUTWE, RFREG_MASK, 0x80002); > + rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_ADDR, RFREG_MASK, 0x20000); > + rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_DATA0, RFREG_MASK, 0x3fffd); > + rtw_write_rf(rtwdev, RF_PATH_B, RF_MODE_TABLE_DATA1, RFREG_MASK, 0xfe83f); > + rtw_write_rf(rtwdev, RF_PATH_B, 0x65, RFREG_MASK, 0x931d5); > + rtw_write_rf(rtwdev, RF_PATH_B, 0x8f, RFREG_MASK, 0x8a001); > + > + rtw_write32(rtwdev, 0x90c, 0x00008000); > + rtw_write32_mask(rtwdev, 0xc94, BIT(0), 0x1); > + rtw_write32_mask(rtwdev, 0xe94, BIT(0), 0x1); > + rtw_write32(rtwdev, 0x978, 0x29002000); /* TX (X,Y) */ > + rtw_write32(rtwdev, 0x97c, 0xa9002000); /* RX (X,Y) */ > + rtw_write32(rtwdev, 0x984, 0x00462910); /* [0]:AGC_en, [15]:idac_K_Mask */ > + /* [31] = 1 --> Page C1 */ > + rtw_write32_mask(rtwdev, REG_CCASEL, BIT(31), 0x1); > + > + if (efuse->ext_pa_5g) { > + if (efuse->rfe_option == 1) { > + rtw_write32(rtwdev, 0xc88, 0x821403e3); > + rtw_write32(rtwdev, 0xe88, 0x821403e3); > + } else { > + rtw_write32(rtwdev, 0xc88, 0x821403f7); > + rtw_write32(rtwdev, 0xe88, 0x821403f7); > + } > + } else { > + rtw_write32(rtwdev, 0xc88, 0x821403f1); > + rtw_write32(rtwdev, 0xe88, 0x821403f1); > + } > + > + if (rtwdev->hal.current_band_type == RTW_BAND_5G) { > + rtw_write32(rtwdev, 0xc8c, 0x68163e96); > + rtw_write32(rtwdev, 0xe8c, 0x68163e96); > + } else { > + rtw_write32(rtwdev, 0xc8c, 0x28163e96); > + rtw_write32(rtwdev, 0xe8c, 0x28163e96); > + > + if (efuse->rfe_option == 3) { > + if (efuse->ext_pa_2g) > + rtw_write32(rtwdev, 0xc88, 0x821403e3); > + else > + rtw_write32(rtwdev, 0xc88, 0x821403f7); > + } > + } > + > + /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ > + rtw_write32(rtwdev, 0xc80, 0x18008c10); > + /* RX_Tone_idx[9:0], RxK_Mask[29] */ > + rtw_write32(rtwdev, 0xc84, 0x38008c10); > + rtw_write32(rtwdev, 0xce8, 0x00000000); > + /* TX_Tone_idx[9:0], TxK_Mask[29] TX_Tone = 16 */ > + rtw_write32(rtwdev, 0xe80, 0x18008c10); > + /* RX_Tone_idx[9:0], RxK_Mask[29] */ > + rtw_write32(rtwdev, 0xe84, 0x38008c10); > + rtw_write32(rtwdev, 0xee8, 0x00000000); > + > + cal0_retry = 0; > + cal1_retry = 0; > + while (1) { > + /* one shot */ > + rtw_write32(rtwdev, REG_RFECTL_A, 0x00100000); > + rtw_write32(rtwdev, REG_RFECTL_B, 0x00100000); > + rtw_write32(rtwdev, 0x980, 0xfa000000); > + rtw_write32(rtwdev, 0x980, 0xf8000000); > + > + mdelay(10); > + > + rtw_write32(rtwdev, REG_RFECTL_A, 0x00000000); > + rtw_write32(rtwdev, REG_RFECTL_B, 0x00000000); > + > + delay_count = 0; > + while (1) { prefer 'for' > + if (!tx0_finish) > + iqk0_ready = rtw_read32_mask(rtwdev, 0xd00, BIT(10)); > + if (!tx1_finish) > + iqk1_ready = rtw_read32_mask(rtwdev, 0xd40, BIT(10)); > + if ((iqk0_ready && iqk1_ready) || delay_count > 20) > + break; > + > + mdelay(1); > + delay_count++; > + } > + > + rtw_dbg(rtwdev, RTW_DBG_RFK, "TX delay_count = %d\n", > + delay_count); > + > + if (delay_count < 20) { /* If 20ms No Result, then cal_retry++ */ > + /* ============TXIQK Check============== */ > + tx0_fail = rtw_read32_mask(rtwdev, 0xd00, BIT(12)); > + tx1_fail = rtw_read32_mask(rtwdev, 0xd40, BIT(12)); Can you collect undefined register addresses? I can try to lookup them in one go. [...] > + > +#define MACBB_REG_NUM_8812A 9 > +#define AFE_REG_NUM_8812A 12 > +#define RF_REG_NUM_8812A 3 > + > +static void rtw8812a_do_iqk(struct rtw_dev *rtwdev) > +{ > + static const u32 backup_macbb_reg[MACBB_REG_NUM_8812A] = { > + 0x520, 0x550, 0x808, 0xa04, 0x90c, 0xc00, 0xe00, 0x838, 0x82c > + }; > + static const u32 backup_afe_reg[AFE_REG_NUM_8812A] = { > + 0xc5c, 0xc60, 0xc64, 0xc68, 0xcb0, 0xcb4, > + 0xe5c, 0xe60, 0xe64, 0xe68, 0xeb0, 0xeb4 > + }; > + static const u32 backup_rf_reg[RF_REG_NUM_8812A] = { > + 0x65, 0x8f, 0x0 > + }; > + u32 macbb_backup[MACBB_REG_NUM_8812A] = {0}; > + u32 afe_backup[AFE_REG_NUM_8812A] = {0}; > + u32 rfa_backup[RF_REG_NUM_8812A] = {0}; > + u32 rfb_backup[RF_REG_NUM_8812A] = {0}; '= {}' [...] > + > +static void rtw8821a_coex_cfg_gnt_fix(struct rtw_dev *rtwdev) > +{} Below looks regular. static void rtw8821a_coex_cfg_gnt_fix(struct rtw_dev *rtwdev) { } As well as rtw8821a_coex_cfg_gnt_debug() and rtw8821a_coex_cfg_wl_rx_gain() [...] > +static struct rtw_hw_reg rtw8821a_dig[] = { const ? > + [0] = { .addr = 0xc50, .mask = 0x7f }, > + [1] = { .addr = 0xe50, .mask = 0x7f }, > +}; > + > +static struct rtw_page_table page_table_8821a[] = { const ? > + /* hq_num, nq_num, lq_num, exq_num, gapq_num */ > + {0, 0, 0, 0, 0}, /* SDIO */ > + {0, 0, 0, 0, 0}, /* PCI */ > + {8, 0, 0, 0, 1}, /* 2 bulk out endpoints */ > + {8, 0, 8, 0, 1}, /* 3 bulk out endpoints */ > + {8, 0, 8, 4, 1}, /* 4 bulk out endpoints */ > +}; > + > +static struct rtw_page_table page_table_8812a[] = { const ? > + /* hq_num, nq_num, lq_num, exq_num, gapq_num */ > + {0, 0, 0, 0, 0}, /* SDIO */ > + {0, 0, 0, 0, 0}, /* PCI */ > + {16, 0, 0, 0, 1}, /* 2 bulk out endpoints */ > + {16, 0, 16, 0, 1}, /* 3 bulk out endpoints */ > + {16, 0, 16, 0, 1}, /* 4 bulk out endpoints */ > +}; > + > +static struct rtw_rqpn rqpn_table_8821a[] = { const ? > + {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, > + RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, > + RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, > + > + {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, > + RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, > + RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, > + > + {RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH, > + RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, > + RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH}, > + > + {RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_NORMAL, > + RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, > + RTW_DMA_MAPPING_HIGH, RTW_DMA_MAPPING_HIGH}, > + > + {RTW_DMA_MAPPING_NORMAL, RTW_DMA_MAPPING_NORMAL, > + RTW_DMA_MAPPING_LOW, RTW_DMA_MAPPING_LOW, > + RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, > +}; > + > +static struct rtw_prioq_addrs prioq_addrs_8821a = { const? > + .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 struct rtw_chip_ops rtw8821a_ops = { > + .power_on = rtw8821a_power_on, > + .power_off = rtw8821a_power_off, > + .phy_set_param = NULL, > + .read_efuse = rtw8821a_read_efuse, > + .query_rx_desc = rtw8821a_query_rx_desc, > + .set_channel = rtw8821a_set_channel, > + .mac_init = NULL, > + .read_rf = rtw8821a_phy_read_rf, > + .write_rf = rtw_phy_write_rf_reg_sipi, > + .set_antenna = NULL, > + .set_tx_power_index = rtw8821a_set_tx_power_index, > + .cfg_ldo25 = rtw8821a_cfg_ldo25, > + .efuse_grant = rtw8821a_efuse_grant, > + .false_alarm_statistics = rtw8821a_false_alarm_statistics, > + .phy_calibration = rtw8821a_phy_calibration, > + .cck_pd_set = rtw8821a_phy_cck_pd_set, > + .pwr_track = rtw8821a_pwr_track, > + .config_bfee = NULL, > + .set_gid_table = NULL, > + .cfg_csi_rate = NULL, > + .fill_txdesc_checksum = rtw8821a_fill_txdesc_checksum, > + .coex_set_init = rtw8821a_coex_cfg_init, > + .coex_set_ant_switch = rtw8821a_coex_cfg_ant_switch, > + .coex_set_gnt_fix = rtw8821a_coex_cfg_gnt_fix, > + .coex_set_gnt_debug = rtw8821a_coex_cfg_gnt_debug, > + .coex_set_rfe_type = rtw8821a_coex_cfg_rfe_type, > + .coex_set_wl_tx_power = rtw8821a_coex_cfg_wl_tx_power, > + .coex_set_wl_rx_gain = rtw8821a_coex_cfg_wl_rx_gain, > +}; > + [...] > + > +const struct rtw_chip_info rtw8812a_hw_spec = { Is it possible moving 8812a to individual file? Since you have rtw8812au.c and rtw8821au.c. > + .ops = &rtw8821a_ops, > + .id = RTW_CHIP_TYPE_8812A, > + .fw_name = "rtw88/rtw8812a_fw.bin", > + .wlan_cpu = RTW_WCPU_11N, > + .tx_pkt_desc_sz = 40, > + .tx_buf_desc_sz = 16, > + .rx_pkt_desc_sz = 24, > + .rx_buf_desc_sz = 8, > + .phy_efuse_size = 512, > + .log_efuse_size = 512, > + .ptct_efuse_size = 96 + 1, /* TODO or just 18? */ > + .txff_size = 131072, > + .rxff_size = 16128, > + .rsvd_drv_pg_num = 9, > + .txgi_factor = 1, > + .is_pwr_by_rate_dec = true, > + .max_power_index = 0x3f, > + .csi_buf_pg_num = 0, > + .band = RTW_BAND_2G | RTW_BAND_5G, > + .page_size = 512, > + .dig_min = 0x20, > + .ht_supported = true, > + .vht_supported = true, > + .lps_deep_mode_supported = 0, > + .sys_func_en = 0xFD, > + .pwr_on_seq = card_enable_flow_8812a, > + .pwr_off_seq = card_disable_flow_8812a, > + .page_table = page_table_8812a, > + .rqpn_table = rqpn_table_8821a, > + .prioq_addrs = &prioq_addrs_8821a, > + .intf_table = &phy_para_table_8821a, > + .dig = rtw8821a_dig, > + .rf_sipi_addr = {REG_LSSI_WRITE_A, REG_LSSI_WRITE_B}, > + .ltecoex_addr = NULL, > + .mac_tbl = &rtw8812a_mac_tbl, > + .agc_tbl = &rtw8812a_agc_tbl, > + .bb_tbl = &rtw8812a_bb_tbl, > + .rf_tbl = {&rtw8812a_rf_a_tbl, &rtw8812a_rf_b_tbl}, > + .rfe_defs = rtw8812a_rfe_defs, > + .rfe_defs_size = ARRAY_SIZE(rtw8812a_rfe_defs), > + .rx_ldpc = false, > + .hw_feature_report = false, > + .c2h_ra_report_size = 4, > + .old_datarate_fb_limit = true, > + .usb_tx_agg_desc_num = 1, > + .iqk_threshold = 8, > + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, > + .max_scan_ie_len = IEEE80211_MAX_DATA_LEN, > + > + .coex_para_ver = 0, /* no coex code in 8812au driver */ > + .bt_desired_ver = 0, > + .scbd_support = false, > + .new_scbd10_def = false, > + .ble_hid_profile_support = false, > + .wl_mimo_ps_support = false, > + .pstdma_type = COEX_PSTDMA_FORCE_LPSOFF, > + .bt_rssi_type = COEX_BTRSSI_RATIO, > + .ant_isolation = 15, > + .rssi_tolerance = 2, > + .wl_rssi_step = wl_rssi_step_8821a, > + .bt_rssi_step = bt_rssi_step_8821a, > + .table_sant_num = 0, > + .table_sant = NULL, > + .table_nsant_num = 0, > + .table_nsant = NULL, > + .tdma_sant_num = 0, > + .tdma_sant = NULL, > + .tdma_nsant_num = 0, > + .tdma_nsant = NULL, > + .wl_rf_para_num = ARRAY_SIZE(rf_para_tx_8821a), > + .wl_rf_para_tx = rf_para_tx_8821a, > + .wl_rf_para_rx = rf_para_rx_8821a, > + .bt_afh_span_bw20 = 0x20, > + .bt_afh_span_bw40 = 0x30, > + .afh_5g_num = 0, > + .afh_5g = NULL, > + > + .coex_info_hw_regs_num = 0, > + .coex_info_hw_regs = NULL, > +}; > +EXPORT_SYMBOL(rtw8812a_hw_spec); > + > +MODULE_FIRMWARE("rtw88/rtw8821a_fw.bin"); > +MODULE_FIRMWARE("rtw88/rtw8812a_fw.bin"); > + > +MODULE_AUTHOR("Realtek Corporation"); > +MODULE_DESCRIPTION("Realtek 802.11ac wireless 8821a/8811a/8812a driver"); > +MODULE_LICENSE("Dual BSD/GPL"); > diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821a.h > b/drivers/net/wireless/realtek/rtw88/rtw8821a.h > new file mode 100644 > index 000000000000..7f1c2d2eb6d2 > --- /dev/null > +++ b/drivers/net/wireless/realtek/rtw88/rtw8821a.h > @@ -0,0 +1,385 @@ > +/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ > +/* Copyright(c) 2018-2019 Realtek Corporation Year 2024 > + */ > + > +#ifndef __RTW8821A_H__ > +#define __RTW8821A_H__ > + > +#include <asm/byteorder.h> > + > +struct rtw8821au_efuse { > + u8 res4[48]; /* 0xd0 */ > + u8 vid[2]; /* 0x100 */ > + u8 pid[2]; > + u8 res8[3]; > + u8 mac_addr[ETH_ALEN]; /* 0x107 */ > + u8 res9[243]; > +}; __packed > + > +struct rtw8812au_efuse { > + u8 vid[2]; /* 0xd0 */ > + u8 pid[2]; /* 0xd2 */ > + u8 res0[3]; > + u8 mac_addr[ETH_ALEN]; /* 0xd7 */ > + u8 res1[291]; > +}; __packed [...] > +#define WLAN_SIFS_CFG (WLAN_SIFS_CCK_CONT_TX | \ > + (WLAN_SIFS_OFDM_CONT_TX << BIT_SHIFT_SIFS_OFDM_CTX) | \ > + (WLAN_SIFS_CCK_TRX << BIT_SHIFT_SIFS_CCK_TRX) | \ > + (WLAN_SIFS_OFDM_TRX << BIT_SHIFT_SIFS_OFDM_TRX)) BIT_SHIFT_SIFS_OFDM_CTX is defined in reg.h, so this header file should include reg.h. Because every header file should be included independently. > + > +#define WLAN_TBTT_TIME (WLAN_TBTT_PROHIBIT |\ > + (WLAN_TBTT_HOLD_TIME << BIT_SHIFT_TBTT_HOLD_TIME_AP)) > + > +#define WLAN_NAV_CFG (WLAN_RDG_NAV | (WLAN_TXOP_NAV << 16)) > +#define WLAN_RX_TSF_CFG (WLAN_CCK_RX_TSF | (WLAN_OFDM_RX_TSF) << 8) > +#define WLAN_PRE_TXCNT_TIME_TH 0x1E4 > + > +struct rtw8821a_phy_status_rpt { > + /* DWORD 0 */ > + u8 gain_trsw[2]; /* path-A and path-B { TRSW, gain[6:0] } */ > + u8 chl_num_lsb; /* channel number[7:0] */ > +#ifdef __LITTLE_ENDIAN > + u8 chl_num_msb:2; /* channel number[9:8] */ > + u8 sub_chnl:4; /* sub-channel location[3:0] */ > + u8 r_rfmod:2; /* RF mode[1:0] */ > +#else > + u8 r_rfmod:2; > + u8 sub_chnl:4; > + u8 chl_num_msb:2; > +#endif Not prefer "#ifdef __LITTLE_ENDIAN" style, because we have never verified big endian part. Prefer to define mask and access them via u8_get_bits() and its friends. > + > + /* DWORD 1 */ > + u8 pwdb_all; /* CCK signal quality / OFDM pwdb all */ > + s8 cfosho[2]; /* CCK AGC report and CCK_BB_Power */ > + /* OFDM path-A and path-B short CFO */ > +#ifdef __LITTLE_ENDIAN > + u8 resvd_0:6; > + u8 bt_rf_ch_msb:2; /* 8812A: 2'b0 8814A: bt rf channel keep[7:6] */ Will you share this struct with 8814A? If not please remove comments related to 8814A. > +#else > + u8 bt_rf_ch_msb:2; > + u8 resvd_0:6; > +#endif [...] > + > +#define REG_SYS_CTRL 0x000 > +#define BIT_FEN_EN BIT(26) > +#define REG_APS_FSMCO 0x04 > +#define APS_FSMCO_MAC_ENABLE BIT(8) > +#define APS_FSMCO_MAC_OFF BIT(9) > +#define APS_FSMCO_HW_POWERDOWN BIT(15) > +#define REG_ACLK_MON 0x3e > +#define REG_RF_B_CTRL 0x76 > +#define REG_HIMR0 0xb0 > +#define REG_HISR0 0xb4 > +#define REG_HIMR1 0xb8 > +#define REG_HISR1 0xbc [...] Can't we move all of these registers (including what I delete) into reg.h?