Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  rtw8852a_rfk.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2019-2020  Realtek Corporation
 */


#include "coex.h"
#include "debug.h"
#include "mac.h"
#include "phy.h"
#include "reg.h"
#include "rtw8852a.h"
#include "rtw8852a_rfk.h"
#include "rtw8852a_rfk_table.h"
#include "rtw8852a_table.h"

static u8 _kpath(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
{
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RFK]dbcc_en: %x, PHY%d\n",
      rtwdev->dbcc_en, phy_idx);

 if (!rtwdev->dbcc_en)
  return RF_AB;

 if (phy_idx == RTW89_PHY_0)
  return RF_A;
 else
  return RF_B;
}

static const u32 rtw8852a_backup_bb_regs[] = {0x2344, 0x58f0, 0x78f0};
static const u32 rtw8852a_backup_rf_regs[] = {0xef, 0xde, 0x0, 0x1e, 0x2, 0x85, 0x90, 0x5};
#define BACKUP_BB_REGS_NR ARRAY_SIZE(rtw8852a_backup_bb_regs)
#define BACKUP_RF_REGS_NR ARRAY_SIZE(rtw8852a_backup_rf_regs)

static void _rfk_backup_bb_reg(struct rtw89_dev *rtwdev, u32 backup_bb_reg_val[])
{
 u32 i;

 for (i = 0; i < BACKUP_BB_REGS_NR; i++) {
  backup_bb_reg_val[i] =
   rtw89_phy_read32_mask(rtwdev, rtw8852a_backup_bb_regs[i],
           MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK,
       "[IQK]backup bb reg : %x, value =%x\n",
       rtw8852a_backup_bb_regs[i], backup_bb_reg_val[i]);
 }
}

static void _rfk_backup_rf_reg(struct rtw89_dev *rtwdev, u32 backup_rf_reg_val[],
          u8 rf_path)
{
 u32 i;

 for (i = 0; i < BACKUP_RF_REGS_NR; i++) {
  backup_rf_reg_val[i] =
   rtw89_read_rf(rtwdev, rf_path,
          rtw8852a_backup_rf_regs[i], RFREG_MASK);
  rtw89_debug(rtwdev, RTW89_DBG_RFK,
       "[IQK]backup rf S%d reg : %x, value =%x\n", rf_path,
       rtw8852a_backup_rf_regs[i], backup_rf_reg_val[i]);
 }
}

static void _rfk_restore_bb_reg(struct rtw89_dev *rtwdev,
    u32 backup_bb_reg_val[])
{
 u32 i;

 for (i = 0; i < BACKUP_BB_REGS_NR; i++) {
  rtw89_phy_write32_mask(rtwdev, rtw8852a_backup_bb_regs[i],
           MASKDWORD, backup_bb_reg_val[i]);
  rtw89_debug(rtwdev, RTW89_DBG_RFK,
       "[IQK]restore bb reg : %x, value =%x\n",
       rtw8852a_backup_bb_regs[i], backup_bb_reg_val[i]);
 }
}

static void _rfk_restore_rf_reg(struct rtw89_dev *rtwdev,
    u32 backup_rf_reg_val[], u8 rf_path)
{
 u32 i;

 for (i = 0; i < BACKUP_RF_REGS_NR; i++) {
  rtw89_write_rf(rtwdev, rf_path, rtw8852a_backup_rf_regs[i],
          RFREG_MASK, backup_rf_reg_val[i]);

  rtw89_debug(rtwdev, RTW89_DBG_RFK,
       "[IQK]restore rf S%d reg: %x, value =%x\n", rf_path,
       rtw8852a_backup_rf_regs[i], backup_rf_reg_val[i]);
 }
}

static void _wait_rx_mode(struct rtw89_dev *rtwdev, u8 kpath)
{
 u8 path;
 u32 rf_mode;
 int ret;

 for (path = 0; path < RF_PATH_MAX; path++) {
  if (!(kpath & BIT(path)))
   continue;

  ret = read_poll_timeout_atomic(rtw89_read_rf, rf_mode, rf_mode != 2,
            2, 5000, false, rtwdev, path, 0x00,
            RR_MOD_MASK);
  rtw89_debug(rtwdev, RTW89_DBG_RFK,
       "[RFK] Wait S%d to Rx mode!! (ret = %d)\n",
       path, ret);
 }
}

static void _dack_dump(struct rtw89_dev *rtwdev)
{
 struct rtw89_dack_info *dack = &rtwdev->dack;
 u8 i;
 u8 t;

 rtw89_debug(rtwdev, RTW89_DBG_RFK,
      "[DACK]S0 ADC_DCK ic = 0x%x, qc = 0x%x\n",
      dack->addck_d[0][0], dack->addck_d[0][1]);
 rtw89_debug(rtwdev, RTW89_DBG_RFK,
      "[DACK]S1 ADC_DCK ic = 0x%x, qc = 0x%x\n",
      dack->addck_d[1][0], dack->addck_d[1][1]);
 rtw89_debug(rtwdev, RTW89_DBG_RFK,
      "[DACK]S0 DAC_DCK ic = 0x%x, qc = 0x%x\n",
      dack->dadck_d[0][0], dack->dadck_d[0][1]);
 rtw89_debug(rtwdev, RTW89_DBG_RFK,
      "[DACK]S1 DAC_DCK ic = 0x%x, qc = 0x%x\n",
      dack->dadck_d[1][0], dack->dadck_d[1][1]);

 rtw89_debug(rtwdev, RTW89_DBG_RFK,
      "[DACK]S0 biask ic = 0x%x, qc = 0x%x\n",
      dack->biask_d[0][0], dack->biask_d[0][1]);
 rtw89_debug(rtwdev, RTW89_DBG_RFK,
      "[DACK]S1 biask ic = 0x%x, qc = 0x%x\n",
      dack->biask_d[1][0], dack->biask_d[1][1]);

 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK ic:\n");
 for (i = 0; i < RTW89_DACK_MSBK_NR; i++) {
  t = dack->msbk_d[0][0][i];
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n", t);
 }
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK qc:\n");
 for (i = 0; i < RTW89_DACK_MSBK_NR; i++) {
  t = dack->msbk_d[0][1][i];
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n", t);
 }
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK ic:\n");
 for (i = 0; i < RTW89_DACK_MSBK_NR; i++) {
  t = dack->msbk_d[1][0][i];
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n", t);
 }
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK qc:\n");
 for (i = 0; i < RTW89_DACK_MSBK_NR; i++) {
  t = dack->msbk_d[1][1][i];
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x\n", t);
 }
}

static void _afe_init(struct rtw89_dev *rtwdev)
{
 rtw89_rfk_parser(rtwdev, &rtw8852a_rfk_afe_init_defs_tbl);
}

static void _addck_backup(struct rtw89_dev *rtwdev)
{
 struct rtw89_dack_info *dack = &rtwdev->dack;

 rtw89_phy_write32_clr(rtwdev, R_S0_RXDC2, B_S0_RXDC2_SEL);
 dack->addck_d[0][0] = (u16)rtw89_phy_read32_mask(rtwdev, R_S0_ADDCK,
        B_S0_ADDCK_Q);
 dack->addck_d[0][1] = (u16)rtw89_phy_read32_mask(rtwdev, R_S0_ADDCK,
        B_S0_ADDCK_I);

 rtw89_phy_write32_clr(rtwdev, R_S1_RXDC2, B_S1_RXDC2_SEL);
 dack->addck_d[1][0] = (u16)rtw89_phy_read32_mask(rtwdev, R_S1_ADDCK,
        B_S1_ADDCK_Q);
 dack->addck_d[1][1] = (u16)rtw89_phy_read32_mask(rtwdev, R_S1_ADDCK,
        B_S1_ADDCK_I);
}

static void _addck_reload(struct rtw89_dev *rtwdev)
{
 struct rtw89_dack_info *dack = &rtwdev->dack;

 rtw89_phy_write32_mask(rtwdev, R_S0_RXDC, B_S0_RXDC_I, dack->addck_d[0][0]);
 rtw89_phy_write32_mask(rtwdev, R_S0_RXDC2, B_S0_RXDC2_Q2,
          (dack->addck_d[0][1] >> 6));
 rtw89_phy_write32_mask(rtwdev, R_S0_RXDC, B_S0_RXDC_Q,
          (dack->addck_d[0][1] & 0x3f));
 rtw89_phy_write32_set(rtwdev, R_S0_RXDC2, B_S0_RXDC2_MEN);
 rtw89_phy_write32_mask(rtwdev, R_S1_RXDC, B_S1_RXDC_I, dack->addck_d[1][0]);
 rtw89_phy_write32_mask(rtwdev, R_S1_RXDC2, B_S1_RXDC2_Q2,
          (dack->addck_d[1][1] >> 6));
 rtw89_phy_write32_mask(rtwdev, R_S1_RXDC, B_S1_RXDC_Q,
          (dack->addck_d[1][1] & 0x3f));
 rtw89_phy_write32_set(rtwdev, R_S1_RXDC2, B_S1_RXDC2_EN);
}

static void _dack_backup_s0(struct rtw89_dev *rtwdev)
{
 struct rtw89_dack_info *dack = &rtwdev->dack;
 u8 i;

 rtw89_phy_write32_set(rtwdev, R_S0_DACKI, B_S0_DACKI_EN);
 rtw89_phy_write32_set(rtwdev, R_S0_DACKQ, B_S0_DACKQ_EN);
 rtw89_phy_write32_set(rtwdev, R_P0_NRBW, B_P0_NRBW_DBG);

 for (i = 0; i < RTW89_DACK_MSBK_NR; i++) {
  rtw89_phy_write32_mask(rtwdev, R_S0_DACKI, B_S0_DACKI_AR, i);
  dack->msbk_d[0][0][i] =
   (u8)rtw89_phy_read32_mask(rtwdev, R_S0_DACKI7, B_S0_DACKI7_K);
  rtw89_phy_write32_mask(rtwdev, R_S0_DACKQ, B_S0_DACKQ_AR, i);
  dack->msbk_d[0][1][i] =
   (u8)rtw89_phy_read32_mask(rtwdev, R_S0_DACKQ7, B_S0_DACKQ7_K);
 }
 dack->biask_d[0][0] = (u16)rtw89_phy_read32_mask(rtwdev, R_S0_DACKI2,
        B_S0_DACKI2_K);
 dack->biask_d[0][1] = (u16)rtw89_phy_read32_mask(rtwdev, R_S0_DACKQ2,
        B_S0_DACKQ2_K);
 dack->dadck_d[0][0] = (u8)rtw89_phy_read32_mask(rtwdev, R_S0_DACKI8,
       B_S0_DACKI8_K) - 8;
 dack->dadck_d[0][1] = (u8)rtw89_phy_read32_mask(rtwdev, R_S0_DACKQ8,
       B_S0_DACKQ8_K) - 8;
}

static void _dack_backup_s1(struct rtw89_dev *rtwdev)
{
 struct rtw89_dack_info *dack = &rtwdev->dack;
 u8 i;

 rtw89_phy_write32_set(rtwdev, R_S1_DACKI, B_S1_DACKI_EN);
 rtw89_phy_write32_set(rtwdev, R_S1_DACKQ, B_S1_DACKQ_EN);
 rtw89_phy_write32_set(rtwdev, R_P1_DBGMOD, B_P1_DBGMOD_ON);

 for (i = 0; i < RTW89_DACK_MSBK_NR; i++) {
  rtw89_phy_write32_mask(rtwdev, R_S1_DACKI, B_S1_DACKI_AR, i);
  dack->msbk_d[1][0][i] =
   (u8)rtw89_phy_read32_mask(rtwdev, R_S1_DACKI7, B_S1_DACKI_K);
  rtw89_phy_write32_mask(rtwdev, R_S1_DACKQ, B_S1_DACKQ_AR, i);
  dack->msbk_d[1][1][i] =
   (u8)rtw89_phy_read32_mask(rtwdev, R_S1_DACKQ7, B_S1_DACKQ7_K);
 }
 dack->biask_d[1][0] =
  (u16)rtw89_phy_read32_mask(rtwdev, R_S1_DACKI2, B_S1_DACKI2_K);
 dack->biask_d[1][1] =
  (u16)rtw89_phy_read32_mask(rtwdev, R_S1_DACKQ2, B_S1_DACKQ2_K);
 dack->dadck_d[1][0] =
  (u8)rtw89_phy_read32_mask(rtwdev, R_S1_DACKI8, B_S1_DACKI8_K) - 8;
 dack->dadck_d[1][1] =
  (u8)rtw89_phy_read32_mask(rtwdev, R_S1_DACKQ8, B_S1_DACKQ8_K) - 8;
}

static void _dack_reload_by_path(struct rtw89_dev *rtwdev,
     enum rtw89_rf_path path, u8 index)
{
 struct rtw89_dack_info *dack = &rtwdev->dack;
 u32 tmp = 0, tmp_offset, tmp_reg;
 u8 i;
 u32 idx_offset, path_offset;

 if (index == 0)
  idx_offset = 0;
 else
  idx_offset = 0x50;

 if (path == RF_PATH_A)
  path_offset = 0;
 else
  path_offset = 0x2000;

 tmp_offset = idx_offset + path_offset;
 /* msbk_d: 15/14/13/12 */
 tmp = 0x0;
 for (i = 0; i < RTW89_DACK_MSBK_NR / 4; i++)
  tmp |= dack->msbk_d[path][index][i + 12] << (i * 8);
 tmp_reg = 0x5e14 + tmp_offset;
 rtw89_phy_write32(rtwdev, tmp_reg, tmp);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", tmp_reg,
      rtw89_phy_read32_mask(rtwdev, tmp_reg, MASKDWORD));
 /* msbk_d: 11/10/9/8 */
 tmp = 0x0;
 for (i = 0; i < RTW89_DACK_MSBK_NR / 4; i++)
  tmp |= dack->msbk_d[path][index][i + 8] << (i * 8);
 tmp_reg = 0x5e18 + tmp_offset;
 rtw89_phy_write32(rtwdev, tmp_reg, tmp);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", tmp_reg,
      rtw89_phy_read32_mask(rtwdev, tmp_reg, MASKDWORD));
 /* msbk_d: 7/6/5/4 */
 tmp = 0x0;
 for (i = 0; i < RTW89_DACK_MSBK_NR / 4; i++)
  tmp |= dack->msbk_d[path][index][i + 4] << (i * 8);
 tmp_reg = 0x5e1c + tmp_offset;
 rtw89_phy_write32(rtwdev, tmp_reg, tmp);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", tmp_reg,
      rtw89_phy_read32_mask(rtwdev, tmp_reg, MASKDWORD));
 /* msbk_d: 3/2/1/0 */
 tmp = 0x0;
 for (i = 0; i < RTW89_DACK_MSBK_NR / 4; i++)
  tmp |= dack->msbk_d[path][index][i] << (i * 8);
 tmp_reg = 0x5e20 + tmp_offset;
 rtw89_phy_write32(rtwdev, tmp_reg, tmp);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]0x%x=0x%x\n", tmp_reg,
      rtw89_phy_read32_mask(rtwdev, tmp_reg, MASKDWORD));
 /* dadak_d/biask_d */
 tmp = 0x0;
 tmp = (dack->biask_d[path][index] << 22) |
        (dack->dadck_d[path][index] << 14);
 tmp_reg = 0x5e24 + tmp_offset;
 rtw89_phy_write32(rtwdev, tmp_reg, tmp);
}

static void _dack_reload(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
{
 u8 i;

 for (i = 0; i < 2; i++)
  _dack_reload_by_path(rtwdev, path, i);

 rtw89_rfk_parser_by_cond(rtwdev, path == RF_PATH_A,
     &rtw8852a_rfk_dack_reload_defs_a_tbl,
     &rtw8852a_rfk_dack_reload_defs_b_tbl);
}

#define ADDC_T_AVG 100
static void _check_addc(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
{
 s32 dc_re = 0, dc_im = 0;
 u32 tmp;
 u32 i;

 rtw89_rfk_parser_by_cond(rtwdev, path == RF_PATH_A,
     &rtw8852a_rfk_check_addc_defs_a_tbl,
     &rtw8852a_rfk_check_addc_defs_b_tbl);

 for (i = 0; i < ADDC_T_AVG; i++) {
  tmp = rtw89_phy_read32_mask(rtwdev, R_DBG32_D, MASKDWORD);
  dc_re += sign_extend32(FIELD_GET(0xfff000, tmp), 11);
  dc_im += sign_extend32(FIELD_GET(0xfff, tmp), 11);
 }

 dc_re /= ADDC_T_AVG;
 dc_im /= ADDC_T_AVG;

 rtw89_debug(rtwdev, RTW89_DBG_RFK,
      "[DACK]S%d,dc_re = 0x%x,dc_im =0x%x\n", path, dc_re, dc_im);
}

static void _addck(struct rtw89_dev *rtwdev)
{
 struct rtw89_dack_info *dack = &rtwdev->dack;
 u32 val;
 int ret;

 /* S0 */
 rtw89_rfk_parser(rtwdev, &rtw8852a_rfk_addck_reset_defs_a_tbl);

 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]before S0 ADDCK\n");
 _check_addc(rtwdev, RF_PATH_A);

 rtw89_rfk_parser(rtwdev, &rtw8852a_rfk_addck_trigger_defs_a_tbl);

 ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val, 1, 10000,
           false, rtwdev, 0x1e00, BIT(0));
 if (ret) {
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 ADDCK timeout\n");
  dack->addck_timeout[0] = true;
 }
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]ADDCK ret = %d\n", ret);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]after S0 ADDCK\n");
 _check_addc(rtwdev, RF_PATH_A);

 rtw89_rfk_parser(rtwdev, &rtw8852a_rfk_addck_restore_defs_a_tbl);

 /* S1 */
 rtw89_rfk_parser(rtwdev, &rtw8852a_rfk_addck_reset_defs_b_tbl);

 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]before S1 ADDCK\n");
 _check_addc(rtwdev, RF_PATH_B);

 rtw89_rfk_parser(rtwdev, &rtw8852a_rfk_addck_trigger_defs_b_tbl);

 ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val, 1, 10000,
           false, rtwdev, 0x3e00, BIT(0));
 if (ret) {
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 ADDCK timeout\n");
  dack->addck_timeout[1] = true;
 }
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]ADDCK ret = %d\n", ret);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]after S1 ADDCK\n");
 _check_addc(rtwdev, RF_PATH_B);

 rtw89_rfk_parser(rtwdev, &rtw8852a_rfk_addck_restore_defs_b_tbl);
}

static void _check_dadc(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
{
 rtw89_rfk_parser_by_cond(rtwdev, path == RF_PATH_A,
     &rtw8852a_rfk_check_dadc_defs_f_a_tbl,
     &rtw8852a_rfk_check_dadc_defs_f_b_tbl);

 _check_addc(rtwdev, path);

 rtw89_rfk_parser_by_cond(rtwdev, path == RF_PATH_A,
     &rtw8852a_rfk_check_dadc_defs_r_a_tbl,
     &rtw8852a_rfk_check_dadc_defs_r_b_tbl);
}

static void _dack_s0(struct rtw89_dev *rtwdev)
{
 struct rtw89_dack_info *dack = &rtwdev->dack;
 u32 val;
 int ret;

 rtw89_rfk_parser(rtwdev, &rtw8852a_rfk_dack_defs_f_a_tbl);

 ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val, 1, 10000,
           false, rtwdev, 0x5e28, BIT(15));
 ret |= read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val, 1, 10000,
     false, rtwdev, 0x5e78, BIT(15));
 if (ret) {
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 MSBK timeout\n");
  dack->msbk_timeout[0] = true;
 }
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK ret = %d\n", ret);

 rtw89_rfk_parser(rtwdev, &rtw8852a_rfk_dack_defs_m_a_tbl);

 ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val, 1, 10000,
           false, rtwdev, 0x5e48, BIT(17));
 ret |= read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val, 1, 10000,
     false, rtwdev, 0x5e98, BIT(17));
 if (ret) {
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S0 DADACK timeout\n");
  dack->dadck_timeout[0] = true;
 }
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK ret = %d\n", ret);

 rtw89_rfk_parser(rtwdev, &rtw8852a_rfk_dack_defs_r_a_tbl);

 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]after S0 DADCK\n");
 _check_dadc(rtwdev, RF_PATH_A);

 _dack_backup_s0(rtwdev);
 _dack_reload(rtwdev, RF_PATH_A);

 rtw89_phy_write32_clr(rtwdev, R_P0_NRBW, B_P0_NRBW_DBG);
}

static void _dack_s1(struct rtw89_dev *rtwdev)
{
 struct rtw89_dack_info *dack = &rtwdev->dack;
 u32 val;
 int ret;

 rtw89_rfk_parser(rtwdev, &rtw8852a_rfk_dack_defs_f_b_tbl);

 ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val, 1, 10000,
           false, rtwdev, 0x7e28, BIT(15));
 ret |= read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val, 1, 10000,
     false, rtwdev, 0x7e78, BIT(15));
 if (ret) {
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 MSBK timeout\n");
  dack->msbk_timeout[1] = true;
 }
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK ret = %d\n", ret);

 rtw89_rfk_parser(rtwdev, &rtw8852a_rfk_dack_defs_m_b_tbl);

 ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val, 1, 10000,
           false, rtwdev, 0x7e48, BIT(17));
 ret |= read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val, 1, 10000,
     false, rtwdev, 0x7e98, BIT(17));
 if (ret) {
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]S1 DADCK timeout\n");
  dack->dadck_timeout[1] = true;
 }
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK ret = %d\n", ret);

 rtw89_rfk_parser(rtwdev, &rtw8852a_rfk_dack_defs_r_b_tbl);

 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]after S1 DADCK\n");
 _check_dadc(rtwdev, RF_PATH_B);

 _dack_backup_s1(rtwdev);
 _dack_reload(rtwdev, RF_PATH_B);

 rtw89_phy_write32_clr(rtwdev, R_P1_DBGMOD, B_P1_DBGMOD_ON);
}

static void _dack(struct rtw89_dev *rtwdev)
{
 _dack_s0(rtwdev);
 _dack_s1(rtwdev);
}

static void _dac_cal(struct rtw89_dev *rtwdev, bool force,
       enum rtw89_chanctx_idx chanctx_idx)
{
 struct rtw89_dack_info *dack = &rtwdev->dack;
 u32 rf0_0, rf1_0;
 u8 phy_map = rtw89_btc_phymap(rtwdev, RTW89_PHY_0, RF_AB, chanctx_idx);

 dack->dack_done = false;
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK b\n");
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK start!!!\n");
 rf0_0 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_MOD, RFREG_MASK);
 rf1_0 = rtw89_read_rf(rtwdev, RF_PATH_B, RR_MOD, RFREG_MASK);
 _afe_init(rtwdev);
 rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RR_RSV1_RST, 0x0);
 rtw89_write_rf(rtwdev, RF_PATH_B, RR_RSV1, RR_RSV1_RST, 0x0);
 rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RFREG_MASK, 0x30001);
 rtw89_write_rf(rtwdev, RF_PATH_B, RR_MOD, RFREG_MASK, 0x30001);
 rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_DACK, BTC_WRFK_ONESHOT_START);
 _addck(rtwdev);
 rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_DACK, BTC_WRFK_ONESHOT_STOP);
 _addck_backup(rtwdev);
 _addck_reload(rtwdev);
 rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RFREG_MASK, 0x40001);
 rtw89_write_rf(rtwdev, RF_PATH_B, RR_MOD, RFREG_MASK, 0x40001);
 rtw89_write_rf(rtwdev, RF_PATH_A, RR_MODOPT, RFREG_MASK, 0x0);
 rtw89_write_rf(rtwdev, RF_PATH_B, RR_MODOPT, RFREG_MASK, 0x0);
 rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_DACK, BTC_WRFK_ONESHOT_START);
 _dack(rtwdev);
 rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_DACK, BTC_WRFK_ONESHOT_STOP);
 _dack_dump(rtwdev);
 dack->dack_done = true;
 rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RFREG_MASK, rf0_0);
 rtw89_write_rf(rtwdev, RF_PATH_B, RR_MOD, RFREG_MASK, rf1_0);
 rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RR_RSV1_RST, 0x1);
 rtw89_write_rf(rtwdev, RF_PATH_B, RR_RSV1, RR_RSV1_RST, 0x1);
 dack->dack_cnt++;
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK finish!!!\n");
}

#define RTW8852A_NCTL_VER 0xd
#define RTW8852A_IQK_VER 0x2a
#define RTW8852A_IQK_SS 2
#define RTW8852A_IQK_THR_REK 8
#define RTW8852A_IQK_CFIR_GROUP_NR 4

enum rtw8852a_iqk_type {
 ID_TXAGC,
 ID_FLOK_COARSE,
 ID_FLOK_FINE,
 ID_TXK,
 ID_RXAGC,
 ID_RXK,
 ID_NBTXK,
 ID_NBRXK,
};

static void _iqk_read_fft_dbcc0(struct rtw89_dev *rtwdev, u8 path)
{
 u8 i = 0x0;
 u32 fft[6] = {0x0};

 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
 rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, MASKDWORD, 0x00160000);
 fft[0] = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKDWORD);
 rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, MASKDWORD, 0x00170000);
 fft[1] = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKDWORD);
 rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, MASKDWORD, 0x00180000);
 fft[2] = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKDWORD);
 rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, MASKDWORD, 0x00190000);
 fft[3] = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKDWORD);
 rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, MASKDWORD, 0x001a0000);
 fft[4] = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKDWORD);
 rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, MASKDWORD, 0x001b0000);
 fft[5] = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKDWORD);
 for (i = 0; i < 6; i++)
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x,fft[%x]= %x\n",
       path, i, fft[i]);
}

static void _iqk_read_xym_dbcc0(struct rtw89_dev *rtwdev, u8 path)
{
 u8 i = 0x0;
 u32 tmp = 0x0;

 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
 rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, B_NCTL_CFG_SPAGE, path);
 rtw89_phy_write32_mask(rtwdev, R_IQK_DIF, B_IQK_DIF_TRX, 0x1);

 for (i = 0x0; i < 0x18; i++) {
  rtw89_phy_write32_mask(rtwdev, R_NCTL_N2, MASKDWORD, 0x000000c0 + i);
  rtw89_phy_write32_clr(rtwdev, R_NCTL_N2, MASKDWORD);
  tmp = rtw89_phy_read32_mask(rtwdev, R_TXIQC + (path << 8), MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, 0x8%lx38 = %x\n",
       path, BIT(path), tmp);
  udelay(1);
 }
 rtw89_phy_write32_clr(rtwdev, R_IQK_DIF, B_IQK_DIF_TRX);
 rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8), MASKDWORD, 0x40000000);
 rtw89_phy_write32_mask(rtwdev, R_NCTL_N2, MASKDWORD, 0x80010100);
 udelay(1);
}

static void _iqk_read_txcfir_dbcc0(struct rtw89_dev *rtwdev, u8 path,
       u8 group)
{
 static const u32 base_addrs[RTW8852A_IQK_SS][RTW8852A_IQK_CFIR_GROUP_NR] = {
  {0x8f20, 0x8f54, 0x8f88, 0x8fbc},
  {0x9320, 0x9354, 0x9388, 0x93bc},
 };
 u8 idx = 0x0;
 u32 tmp = 0x0;
 u32 base_addr;

 if (path >= RTW8852A_IQK_SS) {
  rtw89_warn(rtwdev, "cfir path %d out of range\n", path);
  return;
 }
 if (group >= RTW8852A_IQK_CFIR_GROUP_NR) {
  rtw89_warn(rtwdev, "cfir group %d out of range\n", group);
  return;
 }

 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
 rtw89_phy_write32_mask(rtwdev, R_W_COEF + (path << 8), MASKDWORD, 0x00000001);

 base_addr = base_addrs[path][group];

 for (idx = 0; idx < 0x0d; idx++) {
  tmp = rtw89_phy_read32_mask(rtwdev, base_addr + (idx << 2), MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK,
       "[IQK] %x = %x\n",
       base_addr + (idx << 2), tmp);
 }

 if (path == 0x0) {
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]\n");
  tmp = rtw89_phy_read32_mask(rtwdev, R_TXCFIR_P0C0, MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] 0x8f50 = %x\n", tmp);
  tmp = rtw89_phy_read32_mask(rtwdev, R_TXCFIR_P0C1, MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] 0x8f84 = %x\n", tmp);
  tmp = rtw89_phy_read32_mask(rtwdev, R_TXCFIR_P0C2, MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] 0x8fb8 = %x\n", tmp);
  tmp = rtw89_phy_read32_mask(rtwdev, R_TXCFIR_P0C3, MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] 0x8fec = %x\n", tmp);
 } else {
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]\n");
  tmp = rtw89_phy_read32_mask(rtwdev, R_TXCFIR_P1C0, MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] 0x9350 = %x\n", tmp);
  tmp = rtw89_phy_read32_mask(rtwdev, R_TXCFIR_P1C1, MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] 0x9384 = %x\n", tmp);
  tmp = rtw89_phy_read32_mask(rtwdev, R_TXCFIR_P1C2, MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] 0x93b8 = %x\n", tmp);
  tmp = rtw89_phy_read32_mask(rtwdev, R_TXCFIR_P1C3, MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] 0x93ec = %x\n", tmp);
 }
 rtw89_phy_write32_clr(rtwdev, R_W_COEF + (path << 8), MASKDWORD);
 rtw89_phy_write32_mask(rtwdev, R_KIP_RPT + (path << 8), B_KIP_RPT_SEL, 0xc);
 udelay(1);
 tmp = rtw89_phy_read32_mask(rtwdev, R_RPT_PER + (path << 8), MASKDWORD);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, 0x8%lxfc = %x\n", path,
      BIT(path), tmp);
}

static void _iqk_read_rxcfir_dbcc0(struct rtw89_dev *rtwdev, u8 path,
       u8 group)
{
 static const u32 base_addrs[RTW8852A_IQK_SS][RTW8852A_IQK_CFIR_GROUP_NR] = {
  {0x8d00, 0x8d44, 0x8d88, 0x8dcc},
  {0x9100, 0x9144, 0x9188, 0x91cc},
 };
 u8 idx = 0x0;
 u32 tmp = 0x0;
 u32 base_addr;

 if (path >= RTW8852A_IQK_SS) {
  rtw89_warn(rtwdev, "cfir path %d out of range\n", path);
  return;
 }
 if (group >= RTW8852A_IQK_CFIR_GROUP_NR) {
  rtw89_warn(rtwdev, "cfir group %d out of range\n", group);
  return;
 }

 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
 rtw89_phy_write32_mask(rtwdev, R_W_COEF + (path << 8), MASKDWORD, 0x00000001);

 base_addr = base_addrs[path][group];
 for (idx = 0; idx < 0x10; idx++) {
  tmp = rtw89_phy_read32_mask(rtwdev, base_addr + (idx << 2), MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK,
       "[IQK]%x = %x\n",
       base_addr + (idx << 2), tmp);
 }

 if (path == 0x0) {
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]\n");
  tmp = rtw89_phy_read32_mask(rtwdev, R_RXCFIR_P0C0, MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] 0x8d40 = %x\n", tmp);
  tmp = rtw89_phy_read32_mask(rtwdev, R_RXCFIR_P0C1, MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] 0x8d84 = %x\n", tmp);
  tmp = rtw89_phy_read32_mask(rtwdev, R_RXCFIR_P0C2, MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] 0x8dc8 = %x\n", tmp);
  tmp = rtw89_phy_read32_mask(rtwdev, R_RXCFIR_P0C3, MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] 0x8e0c = %x\n", tmp);
 } else {
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]\n");
  tmp = rtw89_phy_read32_mask(rtwdev, R_RXCFIR_P1C0, MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] 0x9140 = %x\n", tmp);
  tmp = rtw89_phy_read32_mask(rtwdev, R_RXCFIR_P1C1, MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] 0x9184 = %x\n", tmp);
  tmp = rtw89_phy_read32_mask(rtwdev, R_RXCFIR_P1C2, MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] 0x91c8 = %x\n", tmp);
  tmp = rtw89_phy_read32_mask(rtwdev, R_RXCFIR_P1C3, MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK] 0x920c = %x\n", tmp);
 }
 rtw89_phy_write32_clr(rtwdev, R_W_COEF + (path << 8), MASKDWORD);
 rtw89_phy_write32_mask(rtwdev, R_KIP_RPT + (path << 8), B_KIP_RPT_SEL, 0xd);
 tmp = rtw89_phy_read32_mask(rtwdev, R_RPT_PER + (path << 8), MASKDWORD);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, 0x8%lxfc = %x\n", path,
      BIT(path), tmp);
}

static void _iqk_sram(struct rtw89_dev *rtwdev, u8 path)
{
 u32 tmp = 0x0;
 u32 i = 0x0;

 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
 rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, MASKDWORD, 0x00020000);
 rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX2, MASKDWORD, 0x00000080);
 rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX, MASKDWORD, 0x00010000);
 rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x009);

 for (i = 0; i <= 0x9f; i++) {
  rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX, MASKDWORD, 0x00010000 + i);
  tmp = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCI);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]0x%x\n", tmp);
 }

 for (i = 0; i <= 0x9f; i++) {
  rtw89_phy_write32_mask(rtwdev, R_SRAM_IQRX, MASKDWORD, 0x00010000 + i);
  tmp = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCQ);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]0x%x\n", tmp);
 }
 rtw89_phy_write32_clr(rtwdev, R_SRAM_IQRX2, MASKDWORD);
 rtw89_phy_write32_clr(rtwdev, R_SRAM_IQRX, MASKDWORD);
}

static void _iqk_rxk_setting(struct rtw89_dev *rtwdev, u8 path)
{
 struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
 u32 tmp = 0x0;

 rtw89_phy_write32_set(rtwdev, R_P0_NRBW + (path << 13), B_P0_NRBW_DBG);
 rtw89_phy_write32_mask(rtwdev, R_ANAPAR_PW15, B_ANAPAR_PW15, 0x3);
 rtw89_phy_write32_mask(rtwdev, R_ANAPAR, B_ANAPAR_15, 0xa041);
 udelay(1);
 rtw89_phy_write32_mask(rtwdev, R_ANAPAR_PW15, B_ANAPAR_PW15_H2, 0x3);
 rtw89_phy_write32_mask(rtwdev, R_ANAPAR, B_ANAPAR_FLTRST, 0x0);
 udelay(1);
 rtw89_phy_write32_mask(rtwdev, R_ANAPAR, B_ANAPAR_FLTRST, 0x1);
 rtw89_phy_write32_mask(rtwdev, R_ANAPAR_PW15, B_ANAPAR_PW15_H2, 0x0);
 udelay(1);
 rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0x0303);
 rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0x0000);

 switch (iqk_info->iqk_band[path]) {
 case RTW89_BAND_2G:
  rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RR_MOD_V_RXK2);
  rtw89_write_rf(rtwdev, path, RR_RXK, RR_RXK_SEL2G, 0x1);
  break;
 case RTW89_BAND_5G:
  rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RR_MOD_V_RXK2);
  rtw89_write_rf(rtwdev, path, RR_WLSEL, RR_WLSEL_AG, 0x5);
  rtw89_write_rf(rtwdev, path, RR_RXK, RR_RXK_SEL5G, 0x1);
  break;
 default:
  break;
 }
 tmp = rtw89_read_rf(rtwdev, path, RR_CFGCH, RFREG_MASK);
 rtw89_write_rf(rtwdev, path, RR_RSV4, RFREG_MASK, tmp);
 rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_OFF, 0x13);
 rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_POW, 0x0);
 rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_POW, 0x1);
 fsleep(128);
}

static bool _iqk_check_cal(struct rtw89_dev *rtwdev, u8 path, u8 ktype)
{
 u32 tmp;
 u32 val;
 int ret;

 ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val == 0x55, 1, 8200,
           false, rtwdev, 0xbff8, MASKBYTE0);
 if (ret)
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]IQK timeout!!!\n");
 rtw89_phy_write32_clr(rtwdev, R_NCTL_N1, MASKBYTE0);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, ret=%d\n", path, ret);
 tmp = rtw89_phy_read32_mask(rtwdev, R_NCTL_RPT, MASKDWORD);
 rtw89_debug(rtwdev, RTW89_DBG_RFK,
      "[IQK]S%x, type= %x, 0x8008 = 0x%x\n", path, ktype, tmp);

 return false;
}

static bool _iqk_one_shot(struct rtw89_dev *rtwdev,
     enum rtw89_phy_idx phy_idx, u8 path, u8 ktype,
     enum rtw89_chanctx_idx chanctx_idx)
{
 struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
 bool fail = false;
 u32 iqk_cmd = 0x0;
 u8 phy_map = rtw89_btc_path_phymap(rtwdev, phy_idx, path, chanctx_idx);
 u32 addr_rfc_ctl = 0x0;

 if (path == RF_PATH_A)
  addr_rfc_ctl = 0x5864;
 else
  addr_rfc_ctl = 0x7864;

 rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_ONESHOT_START);
 switch (ktype) {
 case ID_TXAGC:
  iqk_cmd = 0x008 | (1 << (4 + path)) | (path << 1);
  break;
 case ID_FLOK_COARSE:
  rtw89_phy_write32_set(rtwdev, addr_rfc_ctl, 0x20000000);
  rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x009);
  iqk_cmd = 0x108 | (1 << (4 + path));
  break;
 case ID_FLOK_FINE:
  rtw89_phy_write32_set(rtwdev, addr_rfc_ctl, 0x20000000);
  rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x009);
  iqk_cmd = 0x208 | (1 << (4 + path));
  break;
 case ID_TXK:
  rtw89_phy_write32_clr(rtwdev, addr_rfc_ctl, 0x20000000);
  rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x025);
  iqk_cmd = 0x008 | (1 << (path + 4)) |
     (((0x8 + iqk_info->iqk_bw[path]) & 0xf) << 8);
  break;
 case ID_RXAGC:
  iqk_cmd = 0x508 | (1 << (4 + path)) | (path << 1);
  break;
 case ID_RXK:
  rtw89_phy_write32_set(rtwdev, addr_rfc_ctl, 0x20000000);
  rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x011);
  iqk_cmd = 0x008 | (1 << (path + 4)) |
     (((0xb + iqk_info->iqk_bw[path]) & 0xf) << 8);
  break;
 case ID_NBTXK:
  rtw89_phy_write32_clr(rtwdev, addr_rfc_ctl, 0x20000000);
  rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_TXT, 0x025);
  iqk_cmd = 0x308 | (1 << (4 + path));
  break;
 case ID_NBRXK:
  rtw89_phy_write32_set(rtwdev, addr_rfc_ctl, 0x20000000);
  rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, B_IQK_DIF4_RXT, 0x011);
  iqk_cmd = 0x608 | (1 << (4 + path));
  break;
 default:
  return false;
 }

 rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD, iqk_cmd + 1);
 rtw89_phy_write32_set(rtwdev, R_DPK_CTL, B_DPK_CTL_EN);
 udelay(1);
 fail = _iqk_check_cal(rtwdev, path, ktype);
 if (iqk_info->iqk_xym_en)
  _iqk_read_xym_dbcc0(rtwdev, path);
 if (iqk_info->iqk_fft_en)
  _iqk_read_fft_dbcc0(rtwdev, path);
 if (iqk_info->iqk_sram_en)
  _iqk_sram(rtwdev, path);
 if (iqk_info->iqk_cfir_en) {
  if (ktype == ID_TXK) {
   _iqk_read_txcfir_dbcc0(rtwdev, path, 0x0);
   _iqk_read_txcfir_dbcc0(rtwdev, path, 0x1);
   _iqk_read_txcfir_dbcc0(rtwdev, path, 0x2);
   _iqk_read_txcfir_dbcc0(rtwdev, path, 0x3);
  } else {
   _iqk_read_rxcfir_dbcc0(rtwdev, path, 0x0);
   _iqk_read_rxcfir_dbcc0(rtwdev, path, 0x1);
   _iqk_read_rxcfir_dbcc0(rtwdev, path, 0x2);
   _iqk_read_rxcfir_dbcc0(rtwdev, path, 0x3);
  }
 }

 rtw89_phy_write32_clr(rtwdev, addr_rfc_ctl, 0x20000000);

 rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_ONESHOT_STOP);

 return fail;
}

static bool _rxk_group_sel(struct rtw89_dev *rtwdev,
      enum rtw89_phy_idx phy_idx, u8 path,
      enum rtw89_chanctx_idx chanctx_idx)
{
 struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
 static const u32 rxgn_a[4] = {0x18C, 0x1A0, 0x28C, 0x2A0};
 static const u32 attc2_a[4] = {0x0, 0x0, 0x07, 0x30};
 static const u32 attc1_a[4] = {0x7, 0x5, 0x1, 0x1};
 static const u32 rxgn_g[4] = {0x1CC, 0x1E0, 0x2CC, 0x2E0};
 static const u32 attc2_g[4] = {0x0, 0x15, 0x3, 0x1a};
 static const u32 attc1_g[4] = {0x1, 0x0, 0x1, 0x0};
 u8 gp = 0x0;
 bool fail = false;
 u32 rf0 = 0x0;

 for (gp = 0; gp < 0x4; gp++) {
  switch (iqk_info->iqk_band[path]) {
  case RTW89_BAND_2G:
   rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_M_RXG, rxgn_g[gp]);
   rtw89_write_rf(rtwdev, path, RR_RXBB, RR_RXBB_C2G, attc2_g[gp]);
   rtw89_write_rf(rtwdev, path, RR_RXBB, RR_RXBB_C1G, attc1_g[gp]);
   break;
  case RTW89_BAND_5G:
   rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_M_RXG, rxgn_a[gp]);
   rtw89_write_rf(rtwdev, path, RR_RXA2, RR_RXA2_C2, attc2_a[gp]);
   rtw89_write_rf(rtwdev, path, RR_RXA2, RR_RXA2_C1, attc1_a[gp]);
   break;
  default:
   break;
  }
  rtw89_phy_write32_set(rtwdev, R_IQK_CFG, B_IQK_CFG_SET);
  rf0 = rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK);
  rtw89_phy_write32_mask(rtwdev, R_IQK_DIF2, B_IQK_DIF2_RXPI,
           rf0 | iqk_info->syn1to2);
  rtw89_phy_write32_mask(rtwdev, R_IQK_COM, MASKDWORD, 0x40010100);
  rtw89_phy_write32_clr(rtwdev, R_IQK_RES + (path << 8), B_IQK_RES_RXCFIR);
  rtw89_phy_write32_set(rtwdev, R_CFIR_LUT + (path << 8), B_CFIR_LUT_SEL);
  rtw89_phy_write32_clr(rtwdev, R_CFIR_LUT + (path << 8), B_CFIR_LUT_G3);
  rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT + (path << 8), B_CFIR_LUT_GP, gp);
  rtw89_phy_write32_mask(rtwdev, R_IOQ_IQK_DPK, B_IOQ_IQK_DPK_EN, 0x1);
  rtw89_phy_write32_clr(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP);
  fail = _iqk_one_shot(rtwdev, phy_idx, path, ID_RXK, chanctx_idx);
  rtw89_phy_write32_mask(rtwdev, R_IQKINF, BIT(16 + gp + path * 4), fail);
 }

 switch (iqk_info->iqk_band[path]) {
 case RTW89_BAND_2G:
  rtw89_write_rf(rtwdev, path, RR_RXK, RR_RXK_SEL2G, 0x0);
  rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_POW, 0x0);
  break;
 case RTW89_BAND_5G:
  rtw89_write_rf(rtwdev, path, RR_RXK, RR_RXK_SEL5G, 0x0);
  rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_POW, 0x0);
  rtw89_write_rf(rtwdev, path, RR_WLSEL, RR_WLSEL_AG, 0x0);
  break;
 default:
  break;
 }
 iqk_info->nb_rxcfir[path] = 0x40000000;
 rtw89_phy_write32_mask(rtwdev, R_IQK_RES + (path << 8),
          B_IQK_RES_RXCFIR, 0x5);
 iqk_info->is_wb_rxiqk[path] = true;
 return false;
}

static bool _iqk_nbrxk(struct rtw89_dev *rtwdev,
         enum rtw89_phy_idx phy_idx, u8 path,
         enum rtw89_chanctx_idx chanctx_idx)
{
 struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
 u8 group = 0x0;
 u32 rf0 = 0x0, tmp = 0x0;
 u32 idxrxgain_a = 0x1a0;
 u32 idxattc2_a = 0x00;
 u32 idxattc1_a = 0x5;
 u32 idxrxgain_g = 0x1E0;
 u32 idxattc2_g = 0x15;
 u32 idxattc1_g = 0x0;
 bool fail = false;

 switch (iqk_info->iqk_band[path]) {
 case RTW89_BAND_2G:
  rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_M_RXG, idxrxgain_g);
  rtw89_write_rf(rtwdev, path, RR_RXBB, RR_RXBB_C2G, idxattc2_g);
  rtw89_write_rf(rtwdev, path, RR_RXBB, RR_RXBB_C1G, idxattc1_g);
  break;
 case RTW89_BAND_5G:
  rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_M_RXG, idxrxgain_a);
  rtw89_write_rf(rtwdev, path, RR_RXA2, RR_RXA2_C2, idxattc2_a);
  rtw89_write_rf(rtwdev, path, RR_RXA2, RR_RXA2_C1, idxattc1_a);
  break;
 default:
  break;
 }
 rtw89_phy_write32_set(rtwdev, R_IQK_CFG, B_IQK_CFG_SET);
 rf0 = rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK);
 rtw89_phy_write32_mask(rtwdev, R_IQK_DIF2, B_IQK_DIF2_RXPI,
          rf0 | iqk_info->syn1to2);
 rtw89_phy_write32_mask(rtwdev, R_IQK_COM, MASKDWORD, 0x40010100);
 rtw89_phy_write32_clr(rtwdev, R_IQK_RES + (path << 8), B_IQK_RES_RXCFIR);
 rtw89_phy_write32_set(rtwdev, R_CFIR_LUT + (path << 8), B_CFIR_LUT_SEL);
 rtw89_phy_write32_clr(rtwdev, R_CFIR_LUT + (path << 8), B_CFIR_LUT_G3);
 rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT + (path << 8),
          B_CFIR_LUT_GP, group);
 rtw89_phy_write32_set(rtwdev, R_IOQ_IQK_DPK, B_IOQ_IQK_DPK_EN);
 rtw89_phy_write32_clr(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP);
 fail = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBRXK, chanctx_idx);

 switch (iqk_info->iqk_band[path]) {
 case RTW89_BAND_2G:
  rtw89_write_rf(rtwdev, path, RR_RXK, RR_RXK_SEL2G, 0x0);
  rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_POW, 0x0);
  break;
 case RTW89_BAND_5G:
  rtw89_write_rf(rtwdev, path, RR_RXK, RR_RXK_SEL5G, 0x0);
  rtw89_write_rf(rtwdev, path, RR_RXKPLL, RR_RXKPLL_POW, 0x0);
  rtw89_write_rf(rtwdev, path, RR_WLSEL, RR_WLSEL_AG, 0x0);
  break;
 default:
  break;
 }
 if (!fail) {
  tmp = rtw89_phy_read32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD);
  iqk_info->nb_rxcfir[path] = tmp | 0x2;
 } else {
  iqk_info->nb_rxcfir[path] = 0x40000002;
 }
 return fail;
}

static void _iqk_rxclk_setting(struct rtw89_dev *rtwdev, u8 path)
{
 struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;

 if (iqk_info->iqk_bw[path] == RTW89_CHANNEL_WIDTH_80) {
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
  rtw89_phy_write32_mask(rtwdev, R_CFIR_SYS + (path << 8),
           MASKDWORD, 0x4d000a08);
  rtw89_phy_write32_mask(rtwdev, R_P0_RXCK + (path << 13),
           B_P0_RXCK_VAL, 0x2);
  rtw89_phy_write32_set(rtwdev, R_P0_RXCK + (path << 13), B_P0_RXCK_ON);
  rtw89_phy_write32_set(rtwdev, R_UPD_CLK_ADC, B_UPD_CLK_ADC_ON);
  rtw89_phy_write32_mask(rtwdev, R_UPD_CLK_ADC, B_UPD_CLK_ADC_VAL, 0x1);
 } else {
  rtw89_phy_write32_mask(rtwdev, R_CFIR_SYS + (path << 8),
           MASKDWORD, 0x44000a08);
  rtw89_phy_write32_mask(rtwdev, R_P0_RXCK + (path << 13),
           B_P0_RXCK_VAL, 0x1);
  rtw89_phy_write32_set(rtwdev, R_P0_RXCK + (path << 13), B_P0_RXCK_ON);
  rtw89_phy_write32_set(rtwdev, R_UPD_CLK_ADC, B_UPD_CLK_ADC_ON);
  rtw89_phy_write32_clr(rtwdev, R_UPD_CLK_ADC, B_UPD_CLK_ADC_VAL);
 }
}

static bool _txk_group_sel(struct rtw89_dev *rtwdev,
      enum rtw89_phy_idx phy_idx, u8 path,
      enum rtw89_chanctx_idx chanctx_idx)
{
 static const u32 a_txgain[4] = {0xE466, 0x646D, 0xE4E2, 0x64ED};
 static const u32 g_txgain[4] = {0x60e8, 0x60f0, 0x61e8, 0x61ED};
 static const u32 a_itqt[4] = {0x12, 0x12, 0x12, 0x1b};
 static const u32 g_itqt[4] = {0x09, 0x12, 0x12, 0x12};
 static const u32 g_attsmxr[4] = {0x0, 0x1, 0x1, 0x1};
 struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
 bool fail = false;
 u8 gp = 0x0;
 u32 tmp = 0x0;

 for (gp = 0x0; gp < 0x4; gp++) {
  switch (iqk_info->iqk_band[path]) {
  case RTW89_BAND_2G:
   rtw89_phy_write32_mask(rtwdev, R_RFGAIN_BND + (path << 8),
            B_RFGAIN_BND, 0x08);
   rtw89_write_rf(rtwdev, path, RR_GAINTX, RR_GAINTX_ALL,
           g_txgain[gp]);
   rtw89_write_rf(rtwdev, path, RR_TXG1, RR_TXG1_ATT1,
           g_attsmxr[gp]);
   rtw89_write_rf(rtwdev, path, RR_TXG2, RR_TXG2_ATT0,
           g_attsmxr[gp]);
   rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8),
            MASKDWORD, g_itqt[gp]);
   break;
  case RTW89_BAND_5G:
   rtw89_phy_write32_mask(rtwdev, R_RFGAIN_BND + (path << 8),
            B_RFGAIN_BND, 0x04);
   rtw89_write_rf(rtwdev, path, RR_GAINTX, RR_GAINTX_ALL,
           a_txgain[gp]);
   rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8),
            MASKDWORD, a_itqt[gp]);
   break;
  default:
   break;
  }
  rtw89_phy_write32_clr(rtwdev, R_IQK_RES + (path << 8), B_IQK_RES_TXCFIR);
  rtw89_phy_write32_set(rtwdev, R_CFIR_LUT + (path << 8), B_CFIR_LUT_SEL);
  rtw89_phy_write32_set(rtwdev, R_CFIR_LUT + (path << 8), B_CFIR_LUT_G3);
  rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT + (path << 8),
           B_CFIR_LUT_GP, gp);
  rtw89_phy_write32_clr(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP);
  fail = _iqk_one_shot(rtwdev, phy_idx, path, ID_TXK, chanctx_idx);
  rtw89_phy_write32_mask(rtwdev, R_IQKINF, BIT(8 + gp + path * 4), fail);
 }

 iqk_info->nb_txcfir[path] = 0x40000000;
 rtw89_phy_write32_mask(rtwdev, R_IQK_RES + (path << 8),
          B_IQK_RES_TXCFIR, 0x5);
 iqk_info->is_wb_txiqk[path] = true;
 tmp = rtw89_phy_read32_mask(rtwdev, R_TXIQC + (path << 8), MASKDWORD);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, 0x8%lx38 = 0x%x\n", path,
      BIT(path), tmp);
 return false;
}

static bool _iqk_nbtxk(struct rtw89_dev *rtwdev,
         enum rtw89_phy_idx phy_idx, u8 path,
         enum rtw89_chanctx_idx chanctx_idx)
{
 struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
 u8 group = 0x2;
 u32 a_mode_txgain = 0x64e2;
 u32 g_mode_txgain = 0x61e8;
 u32 attsmxr = 0x1;
 u32 itqt = 0x12;
 u32 tmp = 0x0;
 bool fail = false;

 switch (iqk_info->iqk_band[path]) {
 case RTW89_BAND_2G:
  rtw89_phy_write32_mask(rtwdev, R_RFGAIN_BND + (path << 8),
           B_RFGAIN_BND, 0x08);
  rtw89_write_rf(rtwdev, path, RR_GAINTX, RR_GAINTX_ALL, g_mode_txgain);
  rtw89_write_rf(rtwdev, path, RR_TXG1, RR_TXG1_ATT1, attsmxr);
  rtw89_write_rf(rtwdev, path, RR_TXG2, RR_TXG2_ATT0, attsmxr);
  break;
 case RTW89_BAND_5G:
  rtw89_phy_write32_mask(rtwdev, R_RFGAIN_BND + (path << 8),
           B_RFGAIN_BND, 0x04);
  rtw89_write_rf(rtwdev, path, RR_GAINTX, RR_GAINTX_ALL, a_mode_txgain);
  break;
 default:
  break;
 }
 rtw89_phy_write32_clr(rtwdev, R_IQK_RES + (path << 8), B_IQK_RES_TXCFIR);
 rtw89_phy_write32_set(rtwdev, R_CFIR_LUT + (path << 8), B_CFIR_LUT_SEL);
 rtw89_phy_write32_set(rtwdev, R_CFIR_LUT + (path << 8), B_CFIR_LUT_G3);
 rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT + (path << 8), B_CFIR_LUT_GP, group);
 rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8), MASKDWORD, itqt);
 rtw89_phy_write32_clr(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP);
 fail = _iqk_one_shot(rtwdev, phy_idx, path, ID_NBTXK, chanctx_idx);
 if (!fail) {
  tmp = rtw89_phy_read32_mask(rtwdev, R_TXIQC + (path << 8), MASKDWORD);
  iqk_info->nb_txcfir[path] = tmp | 0x2;
 } else {
  iqk_info->nb_txcfir[path] = 0x40000002;
 }
 tmp = rtw89_phy_read32_mask(rtwdev, R_TXIQC + (path << 8), MASKDWORD);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, 0x8%lx38 = 0x%x\n", path,
      BIT(path), tmp);
 return fail;
}

static void _lok_res_table(struct rtw89_dev *rtwdev, u8 path, u8 ibias)
{
 struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;

 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, ibias = %x\n", path, ibias);
 rtw89_write_rf(rtwdev, path, RR_LUTWE, RFREG_MASK, 0x2);
 if (iqk_info->iqk_band[path] == RTW89_BAND_2G)
  rtw89_write_rf(rtwdev, path, RR_LUTWA, RFREG_MASK, 0x0);
 else
  rtw89_write_rf(rtwdev, path, RR_LUTWA, RFREG_MASK, 0x1);
 rtw89_write_rf(rtwdev, path, RR_LUTWD0, RFREG_MASK, ibias);
 rtw89_write_rf(rtwdev, path, RR_LUTWE, RFREG_MASK, 0x0);
}

static bool _lok_finetune_check(struct rtw89_dev *rtwdev, u8 path)
{
 bool is_fail = false;
 u32 tmp = 0x0;
 u32 core_i = 0x0;
 u32 core_q = 0x0;

 tmp = rtw89_read_rf(rtwdev, path, RR_TXMO, RFREG_MASK);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK][FineLOK] S%x, 0x58 = 0x%x\n",
      path, tmp);
 core_i = FIELD_GET(RR_TXMO_COI, tmp);
 core_q = FIELD_GET(RR_TXMO_COQ, tmp);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, i = 0x%x\n", path, core_i);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%x, q = 0x%x\n", path, core_q);

 if (core_i < 0x2 || core_i > 0x1d || core_q < 0x2 || core_q > 0x1d)
  is_fail = true;
 return is_fail;
}

static bool _iqk_lok(struct rtw89_dev *rtwdev,
       enum rtw89_phy_idx phy_idx, u8 path,
       enum rtw89_chanctx_idx chanctx_idx)
{
 struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
 u32 rf0 = 0x0;
 u8 itqt = 0x12;
 bool fail = false;
 bool tmp = false;

 switch (iqk_info->iqk_band[path]) {
 case RTW89_BAND_2G:
  rtw89_write_rf(rtwdev, path, RR_GAINTX, RR_GAINTX_ALL, 0xe5e0);
  itqt = 0x09;
  break;
 case RTW89_BAND_5G:
  rtw89_write_rf(rtwdev, path, RR_GAINTX, RR_GAINTX_ALL, 0xe4e0);
  itqt = 0x12;
  break;
 default:
  break;
 }
 rtw89_phy_write32_set(rtwdev, R_IQK_CFG, B_IQK_CFG_SET);
 rf0 = rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK);
 rtw89_phy_write32_mask(rtwdev, R_IQK_DIF1, B_IQK_DIF1_TXPI,
          rf0 | iqk_info->syn1to2);
 rtw89_phy_write32_clr(rtwdev, R_IQK_RES + (path << 8), B_IQK_RES_TXCFIR);
 rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT + (path << 8), B_CFIR_LUT_SEL, 0x1);
 rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT + (path << 8), B_CFIR_LUT_G3, 0x1);
 rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT + (path << 8), B_CFIR_LUT_GP, 0x0);
 rtw89_phy_write32_set(rtwdev, R_IOQ_IQK_DPK, B_IOQ_IQK_DPK_EN);
 rtw89_phy_write32_clr(rtwdev, R_NCTL_N1, B_NCTL_N1_CIP);
 rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8), MASKDWORD, itqt);
 tmp = _iqk_one_shot(rtwdev, phy_idx, path, ID_FLOK_COARSE, chanctx_idx);
 iqk_info->lok_cor_fail[0][path] = tmp;
 fsleep(10);
 rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8), MASKDWORD, itqt);
 tmp = _iqk_one_shot(rtwdev, phy_idx, path, ID_FLOK_FINE, chanctx_idx);
 iqk_info->lok_fin_fail[0][path] = tmp;
 fail = _lok_finetune_check(rtwdev, path);
 return fail;
}

static void _iqk_txk_setting(struct rtw89_dev *rtwdev, u8 path)
{
 struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;

 rtw89_phy_write32_set(rtwdev, R_P0_NRBW + (path << 13), B_P0_NRBW_DBG);
 rtw89_phy_write32_mask(rtwdev, R_ANAPAR_PW15, B_ANAPAR_PW15, 0x1f);
 udelay(1);
 rtw89_phy_write32_mask(rtwdev, R_ANAPAR_PW15, B_ANAPAR_PW15, 0x13);
 rtw89_phy_write32_mask(rtwdev, R_ANAPAR, B_ANAPAR_15, 0x0001);
 udelay(1);
 rtw89_phy_write32_mask(rtwdev, R_ANAPAR, B_ANAPAR_15, 0x0041);
 udelay(1);
 rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0x0303);
 rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0x0000);
 switch (iqk_info->iqk_band[path]) {
 case RTW89_BAND_2G:
  rtw89_write_rf(rtwdev, path, RR_XALNA2, RR_XALNA2_SW, 0x00);
  rtw89_write_rf(rtwdev, path, RR_RCKD, RR_RCKD_POW, 0x3f);
  rtw89_write_rf(rtwdev, path, RR_TXG1, RR_TXG1_ATT2, 0x0);
  rtw89_write_rf(rtwdev, path, RR_TXG1, RR_TXG1_ATT1, 0x1);
  rtw89_write_rf(rtwdev, path, RR_TXG2, RR_TXG2_ATT0, 0x1);
  rtw89_write_rf(rtwdev, path, RR_TXGA, RR_TXGA_LOK_EN, 0x0);
  rtw89_write_rf(rtwdev, path, RR_LUTWE, RR_LUTWE_LOK, 0x1);
  rtw89_write_rf(rtwdev, path, RR_LUTDBG, RR_LUTDBG_LOK, 0x0);
  rtw89_write_rf(rtwdev, path, RR_LUTWA, RR_LUTWA_MASK, 0x000);
  rtw89_write_rf(rtwdev, path, RR_RSV2, RFREG_MASK, 0x80200);
  rtw89_write_rf(rtwdev, path, RR_DTXLOK, RFREG_MASK, 0x80200);
  rtw89_write_rf(rtwdev, path, RR_MOD, RFREG_MASK,
          0x403e0 | iqk_info->syn1to2);
  udelay(1);
  break;
 case RTW89_BAND_5G:
  rtw89_write_rf(rtwdev, path, RR_XGLNA2, RR_XGLNA2_SW, 0x00);
  rtw89_write_rf(rtwdev, path, RR_RCKD, RR_RCKD_POW, 0x3f);
  rtw89_write_rf(rtwdev, path, RR_BIASA, RR_BIASA_A, 0x7);
  rtw89_write_rf(rtwdev, path, RR_TXGA, RR_TXGA_LOK_EN, 0x0);
  rtw89_write_rf(rtwdev, path, RR_LUTWE, RR_LUTWE_LOK, 0x1);
  rtw89_write_rf(rtwdev, path, RR_LUTDBG, RR_LUTDBG_LOK, 0x0);
  rtw89_write_rf(rtwdev, path, RR_LUTWA, RR_LUTWA_MASK, 0x100);
  rtw89_write_rf(rtwdev, path, RR_RSV2, RFREG_MASK, 0x80200);
  rtw89_write_rf(rtwdev, path, RR_DTXLOK, RFREG_MASK, 0x80200);
  rtw89_write_rf(rtwdev, path, RR_LUTWD0, RFREG_MASK, 0x1);
  rtw89_write_rf(rtwdev, path, RR_LUTWD0, RFREG_MASK, 0x0);
  rtw89_write_rf(rtwdev, path, RR_MOD, RFREG_MASK,
          0x403e0 | iqk_info->syn1to2);
  udelay(1);
  break;
 default:
  break;
 }
}

static void _iqk_txclk_setting(struct rtw89_dev *rtwdev, u8 path)
{
 rtw89_phy_write32_mask(rtwdev, R_CFIR_SYS + (path << 8), MASKDWORD, 0xce000a08);
}

static void _iqk_info_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
     u8 path)
{
 struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
 u32 tmp = 0x0;
 bool flag = 0x0;

 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_thermal = %lu\n", path,
      ewma_thermal_read(&rtwdev->phystat.avg_thermal[path]));
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_LOK_COR_fail= %d\n", path,
      iqk_info->lok_cor_fail[0][path]);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_LOK_FIN_fail= %d\n", path,
      iqk_info->lok_fin_fail[0][path]);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_TXIQK_fail = %d\n", path,
      iqk_info->iqk_tx_fail[0][path]);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]S%d_RXIQK_fail= %d,\n", path,
      iqk_info->iqk_rx_fail[0][path]);
 flag = iqk_info->lok_cor_fail[0][path];
 rtw89_phy_write32_mask(rtwdev, R_IQKINF, BIT(0) << (path * 4), flag);
 flag = iqk_info->lok_fin_fail[0][path];
 rtw89_phy_write32_mask(rtwdev, R_IQKINF, BIT(1) << (path * 4), flag);
 flag = iqk_info->iqk_tx_fail[0][path];
 rtw89_phy_write32_mask(rtwdev, R_IQKINF, BIT(2) << (path * 4), flag);
 flag = iqk_info->iqk_rx_fail[0][path];
 rtw89_phy_write32_mask(rtwdev, R_IQKINF, BIT(3) << (path * 4), flag);

 tmp = rtw89_phy_read32_mask(rtwdev, R_IQK_RES + (path << 8), MASKDWORD);
 iqk_info->bp_iqkenable[path] = tmp;
 tmp = rtw89_phy_read32_mask(rtwdev, R_TXIQC + (path << 8), MASKDWORD);
 iqk_info->bp_txkresult[path] = tmp;
 tmp = rtw89_phy_read32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD);
 iqk_info->bp_rxkresult[path] = tmp;

 rtw89_phy_write32_mask(rtwdev, R_IQKINF2, B_IQKINF2_KCNT,
          (u8)iqk_info->iqk_times);

 tmp = rtw89_phy_read32_mask(rtwdev, R_IQKINF, 0x0000000f << (path * 4));
 if (tmp != 0x0)
  iqk_info->iqk_fail_cnt++;
 rtw89_phy_write32_mask(rtwdev, R_IQKINF2, 0x00ff0000 << (path * 4),
          iqk_info->iqk_fail_cnt);
}

static
void _iqk_by_path(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, u8 path,
    enum rtw89_chanctx_idx chanctx_idx)
{
 struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
 bool lok_is_fail = false;
 u8 ibias = 0x1;
 u8 i = 0;

 _iqk_txclk_setting(rtwdev, path);

 for (i = 0; i < 3; i++) {
  _lok_res_table(rtwdev, path, ibias++);
  _iqk_txk_setting(rtwdev, path);
  lok_is_fail = _iqk_lok(rtwdev, phy_idx, path, chanctx_idx);
  if (!lok_is_fail)
   break;
 }
 if (iqk_info->is_nbiqk)
  iqk_info->iqk_tx_fail[0][path] = _iqk_nbtxk(rtwdev, phy_idx, path,
           chanctx_idx);
 else
  iqk_info->iqk_tx_fail[0][path] = _txk_group_sel(rtwdev, phy_idx, path,
        chanctx_idx);

 _iqk_rxclk_setting(rtwdev, path);
 _iqk_rxk_setting(rtwdev, path);
 if (iqk_info->is_nbiqk || rtwdev->dbcc_en || iqk_info->iqk_band[path] == RTW89_BAND_2G)
  iqk_info->iqk_rx_fail[0][path] = _iqk_nbrxk(rtwdev, phy_idx, path,
           chanctx_idx);
 else
  iqk_info->iqk_rx_fail[0][path] = _rxk_group_sel(rtwdev, phy_idx, path,
        chanctx_idx);

 _iqk_info_iqk(rtwdev, phy_idx, path);
}

static void _iqk_get_ch_info(struct rtw89_dev *rtwdev,
        enum rtw89_phy_idx phy, u8 path,
        enum rtw89_chanctx_idx chanctx_idx)
{
 struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, chanctx_idx);
 u32 reg_rf18 = 0x0, reg_35c = 0x0;
 u8 idx = 0;
 u8 get_empty_table = false;

 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
 for  (idx = 0; idx < RTW89_IQK_CHS_NR; idx++) {
  if (iqk_info->iqk_mcc_ch[idx][path] == 0) {
   get_empty_table = true;
   break;
  }
 }
 if (!get_empty_table) {
  idx = iqk_info->iqk_table_idx[path] + 1;
  if (idx > RTW89_IQK_CHS_NR - 1)
   idx = 0;
 }
 reg_rf18 = rtw89_read_rf(rtwdev, path, RR_CFGCH, RFREG_MASK);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]cfg ch = %d\n", reg_rf18);
 reg_35c = rtw89_phy_read32_mask(rtwdev, 0x35c, 0x00000c00);

 iqk_info->iqk_band[path] = chan->band_type;
 iqk_info->iqk_bw[path] = chan->band_width;
 iqk_info->iqk_ch[path] = chan->channel;

 rtw89_debug(rtwdev, RTW89_DBG_RFK,
      "[IQK]iqk_info->iqk_band[%x] = 0x%x\n", path,
      iqk_info->iqk_band[path]);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]iqk_info->iqk_bw[%x] = 0x%x\n",
      path, iqk_info->iqk_bw[path]);
 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]iqk_info->iqk_ch[%x] = 0x%x\n",
      path, iqk_info->iqk_ch[path]);
 rtw89_debug(rtwdev, RTW89_DBG_RFK,
      "[IQK]S%d (PHY%d): / DBCC %s/ %s/ CH%d/ %s\n", path, phy,
      rtwdev->dbcc_en ? "on" : "off",
      iqk_info->iqk_band[path] == 0 ? "2G" :
      iqk_info->iqk_band[path] == 1 ? "5G" : "6G",
      iqk_info->iqk_ch[path],
      iqk_info->iqk_bw[path] == 0 ? "20M" :
      iqk_info->iqk_bw[path] == 1 ? "40M" : "80M");
 if (reg_35c == 0x01)
  iqk_info->syn1to2 = 0x1;
 else
  iqk_info->syn1to2 = 0x0;

 rtw89_phy_write32_mask(rtwdev, R_IQKINF, B_IQKINF_VER, RTW8852A_IQK_VER);
 rtw89_phy_write32_mask(rtwdev, R_IQKCH, 0x000f << (path * 16),
          (u8)iqk_info->iqk_band[path]);
 rtw89_phy_write32_mask(rtwdev, R_IQKCH, 0x00f0 << (path * 16),
          (u8)iqk_info->iqk_bw[path]);
 rtw89_phy_write32_mask(rtwdev, R_IQKCH, 0xff00 << (path * 16),
          (u8)iqk_info->iqk_ch[path]);

 rtw89_phy_write32_mask(rtwdev, R_IQKINF2, 0x000000ff, RTW8852A_NCTL_VER);
}

static void _iqk_start_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
      u8 path, enum rtw89_chanctx_idx chanctx_idx)
{
 _iqk_by_path(rtwdev, phy_idx, path, chanctx_idx);
}

static void _iqk_restore(struct rtw89_dev *rtwdev, u8 path)
{
 struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;

 rtw89_phy_write32_mask(rtwdev, R_TXIQC + (path << 8), MASKDWORD,
          iqk_info->nb_txcfir[path]);
 rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD,
          iqk_info->nb_rxcfir[path]);
 rtw89_phy_write32_clr(rtwdev, R_NCTL_RPT, MASKDWORD);
 rtw89_phy_write32_clr(rtwdev, R_MDPK_RX_DCK, MASKDWORD);
 rtw89_phy_write32_mask(rtwdev, R_KIP_SYSCFG, MASKDWORD, 0x80000000);
 rtw89_phy_write32_clr(rtwdev, R_KPATH_CFG, MASKDWORD);
 rtw89_phy_write32_clr(rtwdev, R_GAPK, B_GAPK_ADR);
 rtw89_phy_write32_mask(rtwdev, R_CFIR_SYS + (path << 8), MASKDWORD, 0x10010000);
 rtw89_phy_write32_clr(rtwdev, R_KIP + (path << 8), B_KIP_RFGAIN);
 rtw89_phy_write32_mask(rtwdev, R_CFIR_MAP + (path << 8), MASKDWORD, 0xe4e4e4e4);
 rtw89_phy_write32_clr(rtwdev, R_CFIR_LUT + (path << 8), B_CFIR_LUT_SEL);
 rtw89_phy_write32_clr(rtwdev, R_KIP_IQP + (path << 8), B_KIP_IQP_IQSW);
 rtw89_phy_write32_mask(rtwdev, R_LOAD_COEF + (path << 8), MASKDWORD, 0x00000002);
 rtw89_write_rf(rtwdev, path, RR_LUTWE, RR_LUTWE_LOK, 0x0);
 rtw89_write_rf(rtwdev, path, RR_RCKD, RR_RCKD_POW, 0x0);
 rtw89_write_rf(rtwdev, path, RR_LUTWE, RR_LUTWE_LOK, 0x0);
 rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RR_MOD_V_RX);
 rtw89_write_rf(rtwdev, path, RR_TXRSV, RR_TXRSV_GAPK, 0x0);
 rtw89_write_rf(rtwdev, path, RR_BIAS, RR_BIAS_GAPK, 0x0);
 rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x1);
}

static void _iqk_afebb_restore(struct rtw89_dev *rtwdev,
          enum rtw89_phy_idx phy_idx, u8 path)
{
 const struct rtw89_rfk_tbl *tbl;

 switch (_kpath(rtwdev, phy_idx)) {
 case RF_A:
  tbl = &rtw8852a_rfk_iqk_restore_defs_dbcc_path0_tbl;
  break;
 case RF_B:
  tbl = &rtw8852a_rfk_iqk_restore_defs_dbcc_path1_tbl;
  break;
 default:
  tbl = &rtw8852a_rfk_iqk_restore_defs_nondbcc_path01_tbl;
  break;
 }

 rtw89_rfk_parser(rtwdev, tbl);
}

static void _iqk_preset(struct rtw89_dev *rtwdev, u8 path)
{
 struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
 u8 idx = iqk_info->iqk_table_idx[path];

 if (rtwdev->dbcc_en) {
  rtw89_phy_write32_mask(rtwdev, R_COEF_SEL + (path << 8),
           B_COEF_SEL_IQC, path & 0x1);
  rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT + (path << 8),
           B_CFIR_LUT_G2, path & 0x1);
 } else {
  rtw89_phy_write32_mask(rtwdev, R_COEF_SEL + (path << 8),
           B_COEF_SEL_IQC, idx);
  rtw89_phy_write32_mask(rtwdev, R_CFIR_LUT + (path << 8),
           B_CFIR_LUT_G2, idx);
 }
 rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0);
 rtw89_phy_write32_mask(rtwdev, R_NCTL_RPT, MASKDWORD, 0x00000080);
 rtw89_phy_write32_clr(rtwdev, R_NCTL_RW, MASKDWORD);
 rtw89_phy_write32_mask(rtwdev, R_KIP_SYSCFG, MASKDWORD, 0x81ff010a);
 rtw89_phy_write32_mask(rtwdev, R_KPATH_CFG, MASKDWORD, 0x00200000);
 rtw89_phy_write32_mask(rtwdev, R_MDPK_RX_DCK, MASKDWORD, 0x80000000);
 rtw89_phy_write32_clr(rtwdev, R_LOAD_COEF + (path << 8), MASKDWORD);
}

static void _iqk_macbb_setting(struct rtw89_dev *rtwdev,
          enum rtw89_phy_idx phy_idx, u8 path)
{
 const struct rtw89_rfk_tbl *tbl;

 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===> %s\n", __func__);

 switch (_kpath(rtwdev, phy_idx)) {
 case RF_A:
  tbl = &rtw8852a_rfk_iqk_set_defs_dbcc_path0_tbl;
  break;
 case RF_B:
  tbl = &rtw8852a_rfk_iqk_set_defs_dbcc_path1_tbl;
  break;
 default:
  tbl = &rtw8852a_rfk_iqk_set_defs_nondbcc_path01_tbl;
  break;
 }

 rtw89_rfk_parser(rtwdev, tbl);
}

static void _iqk_dbcc(struct rtw89_dev *rtwdev, u8 path,
        enum rtw89_chanctx_idx chanctx_idx)
{
 struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
 u8 phy_idx = 0x0;

 iqk_info->iqk_times++;

 if (path == 0x0)
  phy_idx = RTW89_PHY_0;
 else
  phy_idx = RTW89_PHY_1;

 _iqk_get_ch_info(rtwdev, phy_idx, path, chanctx_idx);
 _iqk_macbb_setting(rtwdev, phy_idx, path);
 _iqk_preset(rtwdev, path);
 _iqk_start_iqk(rtwdev, phy_idx, path, chanctx_idx);
 _iqk_restore(rtwdev, path);
 _iqk_afebb_restore(rtwdev, phy_idx, path);
}

static void _rck(struct rtw89_dev *rtwdev, enum rtw89_rf_path path)
{
 u32 rf_reg5, rck_val = 0;
 u32 val;
 int ret;

 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] ====== S%d RCK ======\n", path);

 rf_reg5 = rtw89_read_rf(rtwdev, path, RR_RSV1, RFREG_MASK);

 rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0);
 rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RR_MOD_V_RX);

 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] RF0x00 = 0x%x\n",
      rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK));

 /* RCK trigger */
 rtw89_write_rf(rtwdev, path, RR_RCKC, RFREG_MASK, 0x00240);

 ret = read_poll_timeout_atomic(rtw89_read_rf, val, val, 2, 20,
           false, rtwdev, path, 0x1c, BIT(3));
 if (ret)
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] RCK timeout\n");

 rck_val = rtw89_read_rf(rtwdev, path, RR_RCKC, RR_RCKC_CA);
 rtw89_write_rf(rtwdev, path, RR_RCKC, RFREG_MASK, rck_val);

 /* RCK_ADC_OFFSET */
 rtw89_write_rf(rtwdev, path, RR_RCKO, RR_RCKO_OFF, 0x4);

 rtw89_write_rf(rtwdev, path, RR_RFC, RR_RFC_CKEN, 0x1);
 rtw89_write_rf(rtwdev, path, RR_RFC, RR_RFC_CKEN, 0x0);

 rtw89_write_rf(rtwdev, path, RR_RSV1, RFREG_MASK, rf_reg5);

 rtw89_debug(rtwdev, RTW89_DBG_RFK,
      "[RCK] RF 0x1b / 0x1c / 0x1d = 0x%x / 0x%x / 0x%x\n",
      rtw89_read_rf(rtwdev, path, RR_RCKC, RFREG_MASK),
      rtw89_read_rf(rtwdev, path, RR_RCKS, RFREG_MASK),
      rtw89_read_rf(rtwdev, path, RR_RCKO, RFREG_MASK));
}

static void _iqk_init(struct rtw89_dev *rtwdev)
{
 struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
 u8 ch, path;

 rtw89_phy_write32_clr(rtwdev, R_IQKINF, MASKDWORD);
 if (iqk_info->is_iqk_init)
  return;

 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
 iqk_info->is_iqk_init = true;
 iqk_info->is_nbiqk = false;
 iqk_info->iqk_fft_en = false;
 iqk_info->iqk_sram_en = false;
 iqk_info->iqk_cfir_en = false;
 iqk_info->iqk_xym_en = false;
 iqk_info->iqk_times = 0x0;

 for (ch = 0; ch < RTW89_IQK_CHS_NR; ch++) {
  iqk_info->iqk_channel[ch] = 0x0;
  for (path = 0; path < RTW8852A_IQK_SS; path++) {
   iqk_info->lok_cor_fail[ch][path] = false;
   iqk_info->lok_fin_fail[ch][path] = false;
   iqk_info->iqk_tx_fail[ch][path] = false;
   iqk_info->iqk_rx_fail[ch][path] = false;
   iqk_info->iqk_mcc_ch[ch][path] = 0x0;
   iqk_info->iqk_table_idx[path] = 0x0;
  }
 }
}

static void _doiqk(struct rtw89_dev *rtwdev, bool force,
     enum rtw89_phy_idx phy_idx, u8 path,
     enum rtw89_chanctx_idx chanctx_idx)
{
 struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
 u32 backup_bb_val[BACKUP_BB_REGS_NR];
 u32 backup_rf_val[RTW8852A_IQK_SS][BACKUP_RF_REGS_NR];
 u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, RF_AB, chanctx_idx);

 rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_ONESHOT_START);

 rtw89_debug(rtwdev, RTW89_DBG_RFK,
      "[IQK]==========IQK start!!!!!==========\n");
 iqk_info->iqk_times++;
 iqk_info->version = RTW8852A_IQK_VER;

 rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]Test Ver 0x%x\n", iqk_info->version);
 _iqk_get_ch_info(rtwdev, phy_idx, path, chanctx_idx);
 _rfk_backup_bb_reg(rtwdev, &backup_bb_val[0]);
 _rfk_backup_rf_reg(rtwdev, &backup_rf_val[path][0], path);
 _iqk_macbb_setting(rtwdev, phy_idx, path);
 _iqk_preset(rtwdev, path);
 _iqk_start_iqk(rtwdev, phy_idx, path, chanctx_idx);
 _iqk_restore(rtwdev, path);
 _iqk_afebb_restore(rtwdev, phy_idx, path);
 _rfk_restore_bb_reg(rtwdev, &backup_bb_val[0]);
 _rfk_restore_rf_reg(rtwdev, &backup_rf_val[path][0], path);
 rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_ONESHOT_STOP);
}

static void _iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, bool force,
   enum rtw89_chanctx_idx chanctx_idx)
{
 switch (_kpath(rtwdev, phy_idx)) {
 case RF_A:
  _doiqk(rtwdev, force, phy_idx, RF_PATH_A, chanctx_idx);
  break;
 case RF_B:
  _doiqk(rtwdev, force, phy_idx, RF_PATH_B, chanctx_idx);
  break;
 case RF_AB:
  _doiqk(rtwdev, force, phy_idx, RF_PATH_A, chanctx_idx);
  _doiqk(rtwdev, force, phy_idx, RF_PATH_B, chanctx_idx);
  break;
 default:
  break;
 }
}

#define RXDCK_VER_8852A 0xe

static void _set_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
   enum rtw89_rf_path path, bool is_afe,
   enum rtw89_chanctx_idx chanctx_idx)
{
 u8 phy_map = rtw89_btc_path_phymap(rtwdev, phy, path, chanctx_idx);
 u32 ori_val;

 rtw89_debug(rtwdev, RTW89_DBG_RFK,
      "[RX_DCK] ==== S%d RX DCK (by %s)====\n",
      path, is_afe ? "AFE" : "RFC");

 ori_val = rtw89_phy_read32_mask(rtwdev, R_P0_RXCK + (path << 13), MASKDWORD);

 if (is_afe) {
  rtw89_phy_write32_set(rtwdev, R_P0_NRBW + (path << 13), B_P0_NRBW_DBG);
  rtw89_phy_write32_set(rtwdev, R_P0_RXCK + (path << 13), B_P0_RXCK_ON);
  rtw89_phy_write32_mask(rtwdev, R_P0_RXCK + (path << 13),
           B_P0_RXCK_VAL, 0x3);
  rtw89_phy_write32_set(rtwdev, R_S0_RXDC2 + (path << 13), B_S0_RXDC2_MEN);
  rtw89_phy_write32_mask(rtwdev, R_S0_RXDC2 + (path << 13),
           B_S0_RXDC2_AVG, 0x3);
  rtw89_phy_write32_mask(rtwdev, R_ANAPAR_PW15, B_ANAPAR_PW15_H, 0x3);
  rtw89_phy_write32_clr(rtwdev, R_ANAPAR, B_ANAPAR_ADCCLK);
  rtw89_phy_write32_clr(rtwdev, R_ANAPAR, B_ANAPAR_FLTRST);
  rtw89_phy_write32_set(rtwdev, R_ANAPAR, B_ANAPAR_FLTRST);
  rtw89_phy_write32_mask(rtwdev, R_ANAPAR, B_ANAPAR_CRXBB, 0x1);
 }

 rtw89_write_rf(rtwdev, path, RR_DCK2, RR_DCK2_CYCLE, 0x3f);
 rtw89_write_rf(rtwdev, path, RR_DCK1, RR_DCK1_SEL, is_afe);

 rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_RXDCK, BTC_WRFK_ONESHOT_START);

 rtw89_write_rf(rtwdev, path, RR_DCK, RR_DCK_LV, 0x0);
 rtw89_write_rf(rtwdev, path, RR_DCK, RR_DCK_LV, 0x1);

 fsleep(600);

 rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_RXDCK, BTC_WRFK_ONESHOT_STOP);

 rtw89_write_rf(rtwdev, path, RR_DCK, RR_DCK_LV, 0x0);

 if (is_afe) {
  rtw89_phy_write32_clr(rtwdev, R_P0_NRBW + (path << 13), B_P0_NRBW_DBG);
  rtw89_phy_write32_mask(rtwdev, R_P0_RXCK + (path << 13),
           MASKDWORD, ori_val);
 }
}

static void _rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
      bool is_afe, enum rtw89_chanctx_idx chanctx_idx)
{
 u8 path, kpath, dck_tune;
 u32 rf_reg5;
 u32 addr;

 rtw89_debug(rtwdev, RTW89_DBG_RFK,
      "[RX_DCK] ****** RXDCK Start (Ver: 0x%x, Cv: %d) ******\n",
      RXDCK_VER_8852A, rtwdev->hal.cv);

 kpath = _kpath(rtwdev, phy);

 for (path = 0; path < 2; path++) {
  if (!(kpath & BIT(path)))
   continue;

  rf_reg5 = rtw89_read_rf(rtwdev, path, RR_RSV1, RFREG_MASK);
  dck_tune = (u8)rtw89_read_rf(rtwdev, path, RR_DCK, RR_DCK_FINE);

  if (rtwdev->is_tssi_mode[path]) {
   addr = 0x5818 + (path << 13);
   /* TSSI pause */
   rtw89_phy_write32_set(rtwdev, addr, BIT(30));
  }

  rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0);
  rtw89_write_rf(rtwdev, path, RR_DCK, RR_DCK_FINE, 0x0);
  rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RR_MOD_V_RX);
  _set_rx_dck(rtwdev, phy, path, is_afe, chanctx_idx);
  rtw89_write_rf(rtwdev, path, RR_DCK, RR_DCK_FINE, dck_tune);
  rtw89_write_rf(rtwdev, path, RR_RSV1, RFREG_MASK, rf_reg5);

  if (rtwdev->is_tssi_mode[path]) {
   addr = 0x5818 + (path << 13);
   /* TSSI resume */
   rtw89_phy_write32_clr(rtwdev, addr, BIT(30));
  }
 }
}

#define RTW8852A_RF_REL_VERSION 34
#define RTW8852A_DPK_VER 0x10
#define RTW8852A_DPK_TH_AVG_NUM 4
#define RTW8852A_DPK_RF_PATH 2
#define RTW8852A_DPK_KIP_REG_NUM 2

enum rtw8852a_dpk_id {
 LBK_RXIQK = 0x06,
 SYNC  = 0x10,
 MDPK_IDL = 0x11,
 MDPK_MPA = 0x12,
 GAIN_LOSS = 0x13,
 GAIN_CAL = 0x14,
};

static void _rf_direct_cntrl(struct rtw89_dev *rtwdev,
        enum rtw89_rf_path path, bool is_bybb)
{
 if (is_bybb)
  rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x1);
 else
  rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0);
}

static void _dpk_onoff(struct rtw89_dev *rtwdev,
         enum rtw89_rf_path path, bool off);

static void _dpk_bkup_kip(struct rtw89_dev *rtwdev, u32 *reg,
     u32 reg_bkup[][RTW8852A_DPK_KIP_REG_NUM],
     u8 path)
{
 u8 i;

 for (i = 0; i < RTW8852A_DPK_KIP_REG_NUM; i++) {
  reg_bkup[path][i] = rtw89_phy_read32_mask(rtwdev,
         reg[i] + (path << 8),
         MASKDWORD);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Backup 0x%x = %x\n",
       reg[i] + (path << 8), reg_bkup[path][i]);
 }
}

static void _dpk_reload_kip(struct rtw89_dev *rtwdev, u32 *reg,
       u32 reg_bkup[][RTW8852A_DPK_KIP_REG_NUM], u8 path)
{
 u8 i;

 for (i = 0; i < RTW8852A_DPK_KIP_REG_NUM; i++) {
  rtw89_phy_write32_mask(rtwdev, reg[i] + (path << 8),
           MASKDWORD, reg_bkup[path][i]);
  rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Reload 0x%x = %x\n",
       reg[i] + (path << 8), reg_bkup[path][i]);
 }
}

static u8 _dpk_one_shot(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
   enum rtw89_rf_path path, enum rtw8852a_dpk_id id,
   enum rtw89_chanctx_idx chanctx_idx)
{
 u8 phy_map  = rtw89_btc_path_phymap(rtwdev, phy, path, chanctx_idx);
 u16 dpk_cmd = 0x0;
 u32 val;
 int ret;

 dpk_cmd = (u16)((id << 8) | (0x19 + (path << 4)));

 rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_DPK, BTC_WRFK_ONESHOT_START);

 rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD, dpk_cmd);
 rtw89_phy_write32_set(rtwdev, R_DPK_CTL, B_DPK_CTL_EN);

 ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val == 0x55,
           10, 20000, false, rtwdev, 0xbff8, MASKBYTE0);

 rtw89_phy_write32_clr(rtwdev, R_NCTL_N1, MASKBYTE0);

 rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_DPK, BTC_WRFK_ONESHOT_STOP);

 rtw89_debug(rtwdev, RTW89_DBG_RFK,
      "[DPK] one-shot for %s = 0x%x (ret=%d)\n",
      id == 0x06 ? "LBK_RXIQK" :
      id == 0x10 ? "SYNC" :
      id == 0x11 ? "MDPK_IDL" :
      id == 0x12 ? "MDPK_MPA" :
      id == 0x13 ? "GAIN_LOSS" : "PWR_CAL",
      dpk_cmd, ret);

 if (ret) {
  rtw89_debug(rtwdev, RTW89_DBG_RFK,
       "[DPK] one-shot over 20ms!!!!\n");
  return 1;
 }

 return 0;
}

static void _dpk_rx_dck(struct rtw89_dev *rtwdev,
   enum rtw89_phy_idx phy,
   enum rtw89_rf_path path,
   enum rtw89_chanctx_idx chanctx_idx)
{
 rtw89_write_rf(rtwdev, path, RR_RXBB2, RR_EN_TIA_IDA, 0x3);
 _set_rx_dck(rtwdev, phy, path, false, chanctx_idx);
}

static void _dpk_information(struct rtw89_dev *rtwdev,
        enum rtw89_phy_idx phy,
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=97 H=94 G=95

¤ Dauer der Verarbeitung: 0.19 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge