Path: blob/master/drivers/net/wireless/realtek/rtw88/rtw8723x.c
25924 views
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause1/* Copyright 2024 Fiona Klute2*3* Based on code originally in rtw8723d.[ch],4* Copyright(c) 2018-2019 Realtek Corporation5*/67#include "main.h"8#include "debug.h"9#include "phy.h"10#include "reg.h"11#include "tx.h"12#include "rtw8723x.h"1314static const struct rtw_hw_reg rtw8723x_txagc[] = {15[DESC_RATE1M] = { .addr = 0xe08, .mask = 0x0000ff00 },16[DESC_RATE2M] = { .addr = 0x86c, .mask = 0x0000ff00 },17[DESC_RATE5_5M] = { .addr = 0x86c, .mask = 0x00ff0000 },18[DESC_RATE11M] = { .addr = 0x86c, .mask = 0xff000000 },19[DESC_RATE6M] = { .addr = 0xe00, .mask = 0x000000ff },20[DESC_RATE9M] = { .addr = 0xe00, .mask = 0x0000ff00 },21[DESC_RATE12M] = { .addr = 0xe00, .mask = 0x00ff0000 },22[DESC_RATE18M] = { .addr = 0xe00, .mask = 0xff000000 },23[DESC_RATE24M] = { .addr = 0xe04, .mask = 0x000000ff },24[DESC_RATE36M] = { .addr = 0xe04, .mask = 0x0000ff00 },25[DESC_RATE48M] = { .addr = 0xe04, .mask = 0x00ff0000 },26[DESC_RATE54M] = { .addr = 0xe04, .mask = 0xff000000 },27[DESC_RATEMCS0] = { .addr = 0xe10, .mask = 0x000000ff },28[DESC_RATEMCS1] = { .addr = 0xe10, .mask = 0x0000ff00 },29[DESC_RATEMCS2] = { .addr = 0xe10, .mask = 0x00ff0000 },30[DESC_RATEMCS3] = { .addr = 0xe10, .mask = 0xff000000 },31[DESC_RATEMCS4] = { .addr = 0xe14, .mask = 0x000000ff },32[DESC_RATEMCS5] = { .addr = 0xe14, .mask = 0x0000ff00 },33[DESC_RATEMCS6] = { .addr = 0xe14, .mask = 0x00ff0000 },34[DESC_RATEMCS7] = { .addr = 0xe14, .mask = 0xff000000 },35};3637static void __rtw8723x_lck(struct rtw_dev *rtwdev)38{39u32 lc_cal;40u8 val_ctx, rf_val;41int ret;4243val_ctx = rtw_read8(rtwdev, REG_CTX);44if ((val_ctx & BIT_MASK_CTX_TYPE) != 0)45rtw_write8(rtwdev, REG_CTX, val_ctx & ~BIT_MASK_CTX_TYPE);46else47rtw_write8(rtwdev, REG_TXPAUSE, 0xFF);48lc_cal = rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK);4950rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal | BIT_LCK);5152ret = read_poll_timeout(rtw_read_rf, rf_val, rf_val != 0x1,5310000, 1000000, false,54rtwdev, RF_PATH_A, RF_CFGCH, BIT_LCK);55if (ret)56rtw_warn(rtwdev, "failed to poll LCK status bit\n");5758rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal);59if ((val_ctx & BIT_MASK_CTX_TYPE) != 0)60rtw_write8(rtwdev, REG_CTX, val_ctx);61else62rtw_write8(rtwdev, REG_TXPAUSE, 0x00);63}6465#define DBG_EFUSE_VAL(rtwdev, map, name) \66rtw_dbg(rtwdev, RTW_DBG_EFUSE, # name "=0x%02x\n", \67(map)->name)68#define DBG_EFUSE_2BYTE(rtwdev, map, name) \69rtw_dbg(rtwdev, RTW_DBG_EFUSE, # name "=0x%02x%02x\n", \70(map)->name[0], (map)->name[1])71#define DBG_EFUSE_FIX(rtwdev, name) \72rtw_dbg(rtwdev, RTW_DBG_EFUSE, "Fixed invalid EFUSE value: " \73# name "=0x%x\n", rtwdev->efuse.name)7475static void rtw8723xe_efuse_debug(struct rtw_dev *rtwdev,76struct rtw8723x_efuse *map)77{78rtw_dbg(rtwdev, RTW_DBG_EFUSE, "mac_addr=%pM\n", map->e.mac_addr);79DBG_EFUSE_2BYTE(rtwdev, map, e.vendor_id);80DBG_EFUSE_2BYTE(rtwdev, map, e.device_id);81DBG_EFUSE_2BYTE(rtwdev, map, e.sub_vendor_id);82DBG_EFUSE_2BYTE(rtwdev, map, e.sub_device_id);83}8485static void rtw8723xu_efuse_debug(struct rtw_dev *rtwdev,86struct rtw8723x_efuse *map)87{88DBG_EFUSE_2BYTE(rtwdev, map, u.vendor_id);89DBG_EFUSE_2BYTE(rtwdev, map, u.product_id);90DBG_EFUSE_VAL(rtwdev, map, u.usb_option);91rtw_dbg(rtwdev, RTW_DBG_EFUSE, "mac_addr=%pM\n", map->u.mac_addr);92}9394static void rtw8723xs_efuse_debug(struct rtw_dev *rtwdev,95struct rtw8723x_efuse *map)96{97rtw_dbg(rtwdev, RTW_DBG_EFUSE, "mac_addr=%pM\n", map->s.mac_addr);98}99100static void __rtw8723x_debug_txpwr_limit(struct rtw_dev *rtwdev,101struct rtw_txpwr_idx *table,102int tx_path_count)103{104if (!rtw_dbg_is_enabled(rtwdev, RTW_DBG_EFUSE))105return;106107rtw_dbg(rtwdev, RTW_DBG_EFUSE,108"Power index table (2.4G):\n");109/* CCK base */110rtw_dbg(rtwdev, RTW_DBG_EFUSE, "CCK base\n");111rtw_dbg(rtwdev, RTW_DBG_EFUSE, "RF G0 G1 G2 G3 G4 G5\n");112for (int i = 0; i < tx_path_count; i++)113rtw_dbg(rtwdev, RTW_DBG_EFUSE,114"[%c]: %3u %3u %3u %3u %3u %3u\n",115'A' + i,116table[i].pwr_idx_2g.cck_base[0],117table[i].pwr_idx_2g.cck_base[1],118table[i].pwr_idx_2g.cck_base[2],119table[i].pwr_idx_2g.cck_base[3],120table[i].pwr_idx_2g.cck_base[4],121table[i].pwr_idx_2g.cck_base[5]);122/* CCK diff */123rtw_dbg(rtwdev, RTW_DBG_EFUSE, "CCK diff\n");124rtw_dbg(rtwdev, RTW_DBG_EFUSE, "RF 1S 2S 3S 4S\n");125for (int i = 0; i < tx_path_count; i++)126rtw_dbg(rtwdev, RTW_DBG_EFUSE,127"[%c]: %2d %2d %2d %2d\n",128'A' + i, 0 /* no diff for 1S */,129table[i].pwr_idx_2g.ht_2s_diff.cck,130table[i].pwr_idx_2g.ht_3s_diff.cck,131table[i].pwr_idx_2g.ht_4s_diff.cck);132/* BW40-1S base */133rtw_dbg(rtwdev, RTW_DBG_EFUSE, "BW40-1S base\n");134rtw_dbg(rtwdev, RTW_DBG_EFUSE, "RF G0 G1 G2 G3 G4\n");135for (int i = 0; i < tx_path_count; i++)136rtw_dbg(rtwdev, RTW_DBG_EFUSE,137"[%c]: %3u %3u %3u %3u %3u\n",138'A' + i,139table[i].pwr_idx_2g.bw40_base[0],140table[i].pwr_idx_2g.bw40_base[1],141table[i].pwr_idx_2g.bw40_base[2],142table[i].pwr_idx_2g.bw40_base[3],143table[i].pwr_idx_2g.bw40_base[4]);144/* OFDM diff */145rtw_dbg(rtwdev, RTW_DBG_EFUSE, "OFDM diff\n");146rtw_dbg(rtwdev, RTW_DBG_EFUSE, "RF 1S 2S 3S 4S\n");147for (int i = 0; i < tx_path_count; i++)148rtw_dbg(rtwdev, RTW_DBG_EFUSE,149"[%c]: %2d %2d %2d %2d\n",150'A' + i,151table[i].pwr_idx_2g.ht_1s_diff.ofdm,152table[i].pwr_idx_2g.ht_2s_diff.ofdm,153table[i].pwr_idx_2g.ht_3s_diff.ofdm,154table[i].pwr_idx_2g.ht_4s_diff.ofdm);155/* BW20 diff */156rtw_dbg(rtwdev, RTW_DBG_EFUSE, "BW20 diff\n");157rtw_dbg(rtwdev, RTW_DBG_EFUSE, "RF 1S 2S 3S 4S\n");158for (int i = 0; i < tx_path_count; i++)159rtw_dbg(rtwdev, RTW_DBG_EFUSE,160"[%c]: %2d %2d %2d %2d\n",161'A' + i,162table[i].pwr_idx_2g.ht_1s_diff.bw20,163table[i].pwr_idx_2g.ht_2s_diff.bw20,164table[i].pwr_idx_2g.ht_3s_diff.bw20,165table[i].pwr_idx_2g.ht_4s_diff.bw20);166/* BW40 diff */167rtw_dbg(rtwdev, RTW_DBG_EFUSE, "BW40 diff\n");168rtw_dbg(rtwdev, RTW_DBG_EFUSE, "RF 1S 2S 3S 4S\n");169for (int i = 0; i < tx_path_count; i++)170rtw_dbg(rtwdev, RTW_DBG_EFUSE,171"[%c]: %2d %2d %2d %2d\n",172'A' + i, 0 /* no diff for 1S */,173table[i].pwr_idx_2g.ht_2s_diff.bw40,174table[i].pwr_idx_2g.ht_3s_diff.bw40,175table[i].pwr_idx_2g.ht_4s_diff.bw40);176}177178static void efuse_debug_dump(struct rtw_dev *rtwdev,179struct rtw8723x_efuse *map)180{181if (!rtw_dbg_is_enabled(rtwdev, RTW_DBG_EFUSE))182return;183184rtw_dbg(rtwdev, RTW_DBG_EFUSE, "EFUSE raw logical map:\n");185print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1,186(u8 *)map, sizeof(struct rtw8723x_efuse), false);187rtw_dbg(rtwdev, RTW_DBG_EFUSE, "Parsed rtw8723x EFUSE data:\n");188DBG_EFUSE_VAL(rtwdev, map, rtl_id);189DBG_EFUSE_VAL(rtwdev, map, afe);190rtw8723x_debug_txpwr_limit(rtwdev, map->txpwr_idx_table, 4);191DBG_EFUSE_VAL(rtwdev, map, channel_plan);192DBG_EFUSE_VAL(rtwdev, map, xtal_k);193DBG_EFUSE_VAL(rtwdev, map, thermal_meter);194DBG_EFUSE_VAL(rtwdev, map, iqk_lck);195DBG_EFUSE_VAL(rtwdev, map, pa_type);196DBG_EFUSE_2BYTE(rtwdev, map, lna_type_2g);197DBG_EFUSE_2BYTE(rtwdev, map, lna_type_5g);198DBG_EFUSE_VAL(rtwdev, map, rf_board_option);199DBG_EFUSE_VAL(rtwdev, map, rf_feature_option);200DBG_EFUSE_VAL(rtwdev, map, rf_bt_setting);201DBG_EFUSE_VAL(rtwdev, map, eeprom_version);202DBG_EFUSE_VAL(rtwdev, map, eeprom_customer_id);203DBG_EFUSE_VAL(rtwdev, map, tx_bb_swing_setting_2g);204DBG_EFUSE_VAL(rtwdev, map, tx_pwr_calibrate_rate);205DBG_EFUSE_VAL(rtwdev, map, rf_antenna_option);206DBG_EFUSE_VAL(rtwdev, map, rfe_option);207DBG_EFUSE_2BYTE(rtwdev, map, country_code);208209switch (rtw_hci_type(rtwdev)) {210case RTW_HCI_TYPE_PCIE:211rtw8723xe_efuse_debug(rtwdev, map);212break;213case RTW_HCI_TYPE_USB:214rtw8723xu_efuse_debug(rtwdev, map);215break;216case RTW_HCI_TYPE_SDIO:217rtw8723xs_efuse_debug(rtwdev, map);218break;219default:220/* unsupported now */221break;222}223}224225static void rtw8723xe_efuse_parsing(struct rtw_efuse *efuse,226struct rtw8723x_efuse *map)227{228ether_addr_copy(efuse->addr, map->e.mac_addr);229}230231static void rtw8723xu_efuse_parsing(struct rtw_efuse *efuse,232struct rtw8723x_efuse *map)233{234ether_addr_copy(efuse->addr, map->u.mac_addr);235}236237static void rtw8723xs_efuse_parsing(struct rtw_efuse *efuse,238struct rtw8723x_efuse *map)239{240ether_addr_copy(efuse->addr, map->s.mac_addr);241}242243/* Default power index table for RTL8703B/RTL8723D, used if EFUSE does244* not contain valid data. Replaces EFUSE data from offset 0x10 (start245* of txpwr_idx_table).246*/247static const u8 rtw8723x_txpwr_idx_table[] = {2480x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D,2490x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x02250};251252static int __rtw8723x_read_efuse(struct rtw_dev *rtwdev, u8 *log_map)253{254struct rtw_efuse *efuse = &rtwdev->efuse;255u8 *pwr = (u8 *)efuse->txpwr_idx_table;256struct rtw8723x_efuse *map;257bool valid = false;258int i;259260map = (struct rtw8723x_efuse *)log_map;261efuse_debug_dump(rtwdev, map);262263efuse->rfe_option = 0;264efuse->rf_board_option = map->rf_board_option;265efuse->crystal_cap = map->xtal_k;266efuse->pa_type_2g = map->pa_type;267efuse->lna_type_2g = map->lna_type_2g[0];268efuse->channel_plan = map->channel_plan;269efuse->country_code[0] = map->country_code[0];270efuse->country_code[1] = map->country_code[1];271efuse->bt_setting = map->rf_bt_setting;272efuse->regd = map->rf_board_option & 0x7;273efuse->thermal_meter[0] = map->thermal_meter;274efuse->thermal_meter_k = map->thermal_meter;275efuse->afe = map->afe;276277for (i = 0; i < 4; i++)278efuse->txpwr_idx_table[i] = map->txpwr_idx_table[i];279280switch (rtw_hci_type(rtwdev)) {281case RTW_HCI_TYPE_PCIE:282rtw8723xe_efuse_parsing(efuse, map);283break;284case RTW_HCI_TYPE_USB:285rtw8723xu_efuse_parsing(efuse, map);286break;287case RTW_HCI_TYPE_SDIO:288rtw8723xs_efuse_parsing(efuse, map);289break;290default:291/* unsupported now */292return -EOPNOTSUPP;293}294295/* If TX power index table in EFUSE is invalid, fall back to296* built-in table.297*/298for (i = 0; i < ARRAY_SIZE(rtw8723x_txpwr_idx_table); i++)299if (pwr[i] != 0xff) {300valid = true;301break;302}303if (!valid) {304for (i = 0; i < ARRAY_SIZE(rtw8723x_txpwr_idx_table); i++)305pwr[i] = rtw8723x_txpwr_idx_table[i];306rtw_dbg(rtwdev, RTW_DBG_EFUSE,307"Replaced invalid EFUSE TX power index table.");308rtw8723x_debug_txpwr_limit(rtwdev,309efuse->txpwr_idx_table, 2);310}311312/* Override invalid antenna settings. */313if (efuse->bt_setting == 0xff) {314/* shared antenna */315efuse->bt_setting |= BIT(0);316/* RF path A */317efuse->bt_setting &= ~BIT(6);318DBG_EFUSE_FIX(rtwdev, bt_setting);319}320321/* Override invalid board options: The coex code incorrectly322* assumes that if bits 6 & 7 are set the board doesn't323* support coex. Regd is also derived from rf_board_option and324* should be 0 if there's no valid data.325*/326if (efuse->rf_board_option == 0xff) {327efuse->regd = 0;328efuse->rf_board_option &= GENMASK(5, 0);329DBG_EFUSE_FIX(rtwdev, rf_board_option);330}331332/* Override invalid crystal cap setting, default comes from333* vendor driver. Chip specific.334*/335if (efuse->crystal_cap == 0xff) {336efuse->crystal_cap = 0x20;337DBG_EFUSE_FIX(rtwdev, crystal_cap);338}339340return 0;341}342343#define BIT_CFENDFORM BIT(9)344#define BIT_WMAC_TCR_ERR0 BIT(12)345#define BIT_WMAC_TCR_ERR1 BIT(13)346#define BIT_TCR_CFG (BIT_CFENDFORM | BIT_WMAC_TCR_ERR0 | \347BIT_WMAC_TCR_ERR1)348#define WLAN_RX_FILTER0 0xFFFF349#define WLAN_RX_FILTER1 0x400350#define WLAN_RX_FILTER2 0xFFFF351#define WLAN_RCR_CFG 0x700060CE352353static int __rtw8723x_mac_init(struct rtw_dev *rtwdev)354{355rtw_write32(rtwdev, REG_TCR, BIT_TCR_CFG);356357rtw_write16(rtwdev, REG_RXFLTMAP0, WLAN_RX_FILTER0);358rtw_write16(rtwdev, REG_RXFLTMAP1, WLAN_RX_FILTER1);359rtw_write16(rtwdev, REG_RXFLTMAP2, WLAN_RX_FILTER2);360rtw_write32(rtwdev, REG_RCR, WLAN_RCR_CFG);361362rtw_write32(rtwdev, REG_INT_MIG, 0);363rtw_write32(rtwdev, REG_MCUTST_1, 0x0);364365rtw_write8(rtwdev, REG_MISC_CTRL, BIT_DIS_SECOND_CCA);366rtw_write8(rtwdev, REG_2ND_CCA_CTRL, 0);367368return 0;369}370371static int __rtw8723x_mac_postinit(struct rtw_dev *rtwdev)372{373rtw_write8(rtwdev, REG_FWHW_TXQ_CTRL + 1, WLAN_TXQ_RPT_EN);374375return 0;376}377378static void __rtw8723x_cfg_ldo25(struct rtw_dev *rtwdev, bool enable)379{380u8 ldo_pwr;381382ldo_pwr = rtw_read8(rtwdev, REG_LDO_EFUSE_CTRL + 3);383if (enable) {384ldo_pwr &= ~BIT_MASK_LDO25_VOLTAGE;385ldo_pwr |= (BIT_LDO25_VOLTAGE_V25 << 4) | BIT_LDO25_EN;386} else {387ldo_pwr &= ~BIT_LDO25_EN;388}389rtw_write8(rtwdev, REG_LDO_EFUSE_CTRL + 3, ldo_pwr);390}391392static void393rtw8723x_set_tx_power_index_by_rate(struct rtw_dev *rtwdev, u8 path, u8 rs)394{395struct rtw_hal *hal = &rtwdev->hal;396const struct rtw_hw_reg *txagc;397u8 rate, pwr_index;398int j;399400for (j = 0; j < rtw_rate_size[rs]; j++) {401rate = rtw_rate_section[rs][j];402pwr_index = hal->tx_pwr_tbl[path][rate];403404if (rate >= ARRAY_SIZE(rtw8723x_txagc)) {405rtw_warn(rtwdev, "rate 0x%x isn't supported\n", rate);406continue;407}408txagc = &rtw8723x_txagc[rate];409if (!txagc->addr) {410rtw_warn(rtwdev, "rate 0x%x isn't defined\n", rate);411continue;412}413414rtw_write32_mask(rtwdev, txagc->addr, txagc->mask, pwr_index);415}416}417418static void __rtw8723x_set_tx_power_index(struct rtw_dev *rtwdev)419{420struct rtw_hal *hal = &rtwdev->hal;421int rs, path;422423for (path = 0; path < hal->rf_path_num; path++) {424for (rs = 0; rs <= RTW_RATE_SECTION_HT_1S; rs++)425rtw8723x_set_tx_power_index_by_rate(rtwdev, path, rs);426}427}428429static void __rtw8723x_efuse_grant(struct rtw_dev *rtwdev, bool on)430{431if (on) {432rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON);433434rtw_write16_set(rtwdev, REG_SYS_FUNC_EN, BIT_FEN_ELDR);435rtw_write16_set(rtwdev, REG_SYS_CLKR, BIT_LOADER_CLK_EN | BIT_ANA8M);436} else {437rtw_write8(rtwdev, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);438}439}440441static void __rtw8723x_false_alarm_statistics(struct rtw_dev *rtwdev)442{443struct rtw_dm_info *dm_info = &rtwdev->dm_info;444u32 cck_fa_cnt;445u32 ofdm_fa_cnt;446u32 crc32_cnt;447u32 val32;448449/* hold counter */450rtw_write32_mask(rtwdev, REG_OFDM_FA_HOLDC_11N, BIT_MASK_OFDM_FA_KEEP, 1);451rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_KEEP1, 1);452rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KEEP, 1);453rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KEEP, 1);454455cck_fa_cnt = rtw_read32_mask(rtwdev, REG_CCK_FA_LSB_11N, MASKBYTE0);456cck_fa_cnt += rtw_read32_mask(rtwdev, REG_CCK_FA_MSB_11N, MASKBYTE3) << 8;457458val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE1_11N);459ofdm_fa_cnt = u32_get_bits(val32, BIT_MASK_OFDM_FF_CNT);460ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_SF_CNT);461val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE2_11N);462dm_info->ofdm_cca_cnt = u32_get_bits(val32, BIT_MASK_OFDM_CCA_CNT);463ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_PF_CNT);464val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE3_11N);465ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_RI_CNT);466ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_CRC_CNT);467val32 = rtw_read32(rtwdev, REG_OFDM_FA_TYPE4_11N);468ofdm_fa_cnt += u32_get_bits(val32, BIT_MASK_OFDM_MNS_CNT);469470dm_info->cck_fa_cnt = cck_fa_cnt;471dm_info->ofdm_fa_cnt = ofdm_fa_cnt;472dm_info->total_fa_cnt = cck_fa_cnt + ofdm_fa_cnt;473474dm_info->cck_err_cnt = rtw_read32(rtwdev, REG_IGI_C_11N);475dm_info->cck_ok_cnt = rtw_read32(rtwdev, REG_IGI_D_11N);476crc32_cnt = rtw_read32(rtwdev, REG_OFDM_CRC32_CNT_11N);477dm_info->ofdm_err_cnt = u32_get_bits(crc32_cnt, BIT_MASK_OFDM_LCRC_ERR);478dm_info->ofdm_ok_cnt = u32_get_bits(crc32_cnt, BIT_MASK_OFDM_LCRC_OK);479crc32_cnt = rtw_read32(rtwdev, REG_HT_CRC32_CNT_11N);480dm_info->ht_err_cnt = u32_get_bits(crc32_cnt, BIT_MASK_HT_CRC_ERR);481dm_info->ht_ok_cnt = u32_get_bits(crc32_cnt, BIT_MASK_HT_CRC_OK);482dm_info->vht_err_cnt = 0;483dm_info->vht_ok_cnt = 0;484485val32 = rtw_read32(rtwdev, REG_CCK_CCA_CNT_11N);486dm_info->cck_cca_cnt = (u32_get_bits(val32, BIT_MASK_CCK_FA_MSB) << 8) |487u32_get_bits(val32, BIT_MASK_CCK_FA_LSB);488dm_info->total_cca_cnt = dm_info->cck_cca_cnt + dm_info->ofdm_cca_cnt;489490/* reset counter */491rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTC_11N, BIT_MASK_OFDM_FA_RST, 1);492rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTC_11N, BIT_MASK_OFDM_FA_RST, 0);493rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_RST1, 1);494rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_RST1, 0);495rtw_write32_mask(rtwdev, REG_OFDM_FA_HOLDC_11N, BIT_MASK_OFDM_FA_KEEP, 0);496rtw_write32_mask(rtwdev, REG_OFDM_FA_RSTD_11N, BIT_MASK_OFDM_FA_KEEP1, 0);497rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KPEN, 0);498rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_CNT_KPEN, 2);499rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KPEN, 0);500rtw_write32_mask(rtwdev, REG_CCK_FA_RST_11N, BIT_MASK_CCK_FA_KPEN, 2);501rtw_write32_mask(rtwdev, REG_PAGE_F_RST_11N, BIT_MASK_F_RST_ALL, 1);502rtw_write32_mask(rtwdev, REG_PAGE_F_RST_11N, BIT_MASK_F_RST_ALL, 0);503}504505/* IQK (IQ calibration) */506507static508void __rtw8723x_iqk_backup_regs(struct rtw_dev *rtwdev,509struct rtw8723x_iqk_backup_regs *backup)510{511int i;512513for (i = 0; i < RTW8723X_IQK_ADDA_REG_NUM; i++)514backup->adda[i] = rtw_read32(rtwdev,515rtw8723x_common.iqk_adda_regs[i]);516517for (i = 0; i < RTW8723X_IQK_MAC8_REG_NUM; i++)518backup->mac8[i] = rtw_read8(rtwdev,519rtw8723x_common.iqk_mac8_regs[i]);520for (i = 0; i < RTW8723X_IQK_MAC32_REG_NUM; i++)521backup->mac32[i] = rtw_read32(rtwdev,522rtw8723x_common.iqk_mac32_regs[i]);523524for (i = 0; i < RTW8723X_IQK_BB_REG_NUM; i++)525backup->bb[i] = rtw_read32(rtwdev,526rtw8723x_common.iqk_bb_regs[i]);527528backup->igia = rtw_read32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0);529backup->igib = rtw_read32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0);530531backup->bb_sel_btg = rtw_read32(rtwdev, REG_BB_SEL_BTG);532}533534static535void __rtw8723x_iqk_restore_regs(struct rtw_dev *rtwdev,536const struct rtw8723x_iqk_backup_regs *backup)537{538int i;539540for (i = 0; i < RTW8723X_IQK_ADDA_REG_NUM; i++)541rtw_write32(rtwdev, rtw8723x_common.iqk_adda_regs[i],542backup->adda[i]);543544for (i = 0; i < RTW8723X_IQK_MAC8_REG_NUM; i++)545rtw_write8(rtwdev, rtw8723x_common.iqk_mac8_regs[i],546backup->mac8[i]);547for (i = 0; i < RTW8723X_IQK_MAC32_REG_NUM; i++)548rtw_write32(rtwdev, rtw8723x_common.iqk_mac32_regs[i],549backup->mac32[i]);550551for (i = 0; i < RTW8723X_IQK_BB_REG_NUM; i++)552rtw_write32(rtwdev, rtw8723x_common.iqk_bb_regs[i],553backup->bb[i]);554555rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x50);556rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, backup->igia);557558rtw_write32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0, 0x50);559rtw_write32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0, backup->igib);560561rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x01008c00);562rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x01008c00);563}564565static566bool __rtw8723x_iqk_similarity_cmp(struct rtw_dev *rtwdev,567s32 result[][IQK_NR],568u8 c1, u8 c2)569{570u32 i, j, diff;571u32 bitmap = 0;572u8 candidate[PATH_NR] = {IQK_ROUND_INVALID, IQK_ROUND_INVALID};573bool ret = true;574575s32 tmp1, tmp2;576577for (i = 0; i < IQK_NR; i++) {578tmp1 = iqkxy_to_s32(result[c1][i]);579tmp2 = iqkxy_to_s32(result[c2][i]);580581diff = abs(tmp1 - tmp2);582583if (diff <= MAX_TOLERANCE)584continue;585586if ((i == IQK_S1_RX_X || i == IQK_S0_RX_X) && !bitmap) {587if (result[c1][i] + result[c1][i + 1] == 0)588candidate[i / IQK_SX_NR] = c2;589else if (result[c2][i] + result[c2][i + 1] == 0)590candidate[i / IQK_SX_NR] = c1;591else592bitmap |= BIT(i);593} else {594bitmap |= BIT(i);595}596}597598if (bitmap != 0)599goto check_sim;600601for (i = 0; i < PATH_NR; i++) {602if (candidate[i] == IQK_ROUND_INVALID)603continue;604605for (j = i * IQK_SX_NR; j < i * IQK_SX_NR + 2; j++)606result[IQK_ROUND_HYBRID][j] = result[candidate[i]][j];607ret = false;608}609610return ret;611612check_sim:613for (i = 0; i < IQK_NR; i++) {614j = i & ~1; /* 2 bits are a pair for IQ[X, Y] */615if (bitmap & GENMASK(j + 1, j))616continue;617618result[IQK_ROUND_HYBRID][i] = result[c1][i];619}620621return false;622}623624static u8 __rtw8723x_pwrtrack_get_limit_ofdm(struct rtw_dev *rtwdev)625{626struct rtw_dm_info *dm_info = &rtwdev->dm_info;627u8 tx_rate = dm_info->tx_rate;628u8 limit_ofdm = 30;629630switch (tx_rate) {631case DESC_RATE1M...DESC_RATE5_5M:632case DESC_RATE11M:633break;634case DESC_RATE6M...DESC_RATE48M:635limit_ofdm = 36;636break;637case DESC_RATE54M:638limit_ofdm = 34;639break;640case DESC_RATEMCS0...DESC_RATEMCS2:641limit_ofdm = 38;642break;643case DESC_RATEMCS3...DESC_RATEMCS4:644limit_ofdm = 36;645break;646case DESC_RATEMCS5...DESC_RATEMCS7:647limit_ofdm = 34;648break;649default:650rtw_warn(rtwdev, "pwrtrack unhandled tx_rate 0x%x\n", tx_rate);651break;652}653654return limit_ofdm;655}656657static658void __rtw8723x_pwrtrack_set_xtal(struct rtw_dev *rtwdev, u8 therm_path,659u8 delta)660{661struct rtw_dm_info *dm_info = &rtwdev->dm_info;662const struct rtw_rfe_def *rfe_def = rtw_get_rfe_def(rtwdev);663const struct rtw_pwr_track_tbl *tbl = rfe_def->pwr_track_tbl;664const s8 *pwrtrk_xtal;665s8 xtal_cap;666667if (dm_info->thermal_avg[therm_path] >668rtwdev->efuse.thermal_meter[therm_path])669pwrtrk_xtal = tbl->pwrtrk_xtal_p;670else671pwrtrk_xtal = tbl->pwrtrk_xtal_n;672673xtal_cap = rtwdev->efuse.crystal_cap & 0x3F;674xtal_cap = clamp_t(s8, xtal_cap + pwrtrk_xtal[delta], 0, 0x3F);675rtw_write32_mask(rtwdev, REG_AFE_CTRL3, BIT_MASK_XTAL,676xtal_cap | (xtal_cap << 6));677}678679static680void __rtw8723x_fill_txdesc_checksum(struct rtw_dev *rtwdev,681struct rtw_tx_pkt_info *pkt_info,682u8 *txdesc)683{684size_t words = 32 / 2; /* calculate the first 32 bytes (16 words) */685__le16 chksum = 0;686__le16 *data = (__le16 *)(txdesc);687struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)txdesc;688689le32p_replace_bits(&tx_desc->w7, 0, RTW_TX_DESC_W7_TXDESC_CHECKSUM);690691while (words--)692chksum ^= *data++;693694chksum = ~chksum;695696le32p_replace_bits(&tx_desc->w7, __le16_to_cpu(chksum),697RTW_TX_DESC_W7_TXDESC_CHECKSUM);698}699700static void __rtw8723x_coex_cfg_init(struct rtw_dev *rtwdev)701{702/* enable TBTT nterrupt */703rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION);704705/* BT report packet sample rate */706/* 0x790[5:0]=0x5 */707rtw_write8_mask(rtwdev, REG_BT_TDMA_TIME, BIT_MASK_SAMPLE_RATE, 0x5);708709/* enable BT counter statistics */710rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x1);711712/* enable PTA (3-wire function form BT side) */713rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN);714rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_PO_BT_PTA_PINS);715716/* enable PTA (tx/rx signal form WiFi side) */717rtw_write8_set(rtwdev, REG_QUEUE_CTRL, BIT_PTA_WL_TX_EN);718}719720const struct rtw8723x_common rtw8723x_common = {721.iqk_adda_regs = {7220x85c, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84,7230xe88, 0xe8c, 0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec724},725.iqk_mac8_regs = {0x522, 0x550, 0x551},726.iqk_mac32_regs = {0x40},727.iqk_bb_regs = {7280xc04, 0xc08, 0x874, 0xb68, 0xb6c, 0x870, 0x860, 0x864, 0xa04729},730731.ltecoex_addr = {732.ctrl = REG_LTECOEX_CTRL,733.wdata = REG_LTECOEX_WRITE_DATA,734.rdata = REG_LTECOEX_READ_DATA,735},736.rf_sipi_addr = {737[RF_PATH_A] = { .hssi_1 = 0x820, .lssi_read = 0x8a0,738.hssi_2 = 0x824, .lssi_read_pi = 0x8b8},739[RF_PATH_B] = { .hssi_1 = 0x828, .lssi_read = 0x8a4,740.hssi_2 = 0x82c, .lssi_read_pi = 0x8bc},741},742.dig = {743[0] = { .addr = 0xc50, .mask = 0x7f },744[1] = { .addr = 0xc50, .mask = 0x7f },745},746.dig_cck = {747[0] = { .addr = 0xa0c, .mask = 0x3f00 },748},749.prioq_addrs = {750.prio[RTW_DMA_MAPPING_EXTRA] = {751.rsvd = REG_RQPN_NPQ + 2, .avail = REG_RQPN_NPQ + 3,752},753.prio[RTW_DMA_MAPPING_LOW] = {754.rsvd = REG_RQPN + 1, .avail = REG_FIFOPAGE_CTRL_2 + 1,755},756.prio[RTW_DMA_MAPPING_NORMAL] = {757.rsvd = REG_RQPN_NPQ, .avail = REG_RQPN_NPQ + 1,758},759.prio[RTW_DMA_MAPPING_HIGH] = {760.rsvd = REG_RQPN, .avail = REG_FIFOPAGE_CTRL_2,761},762.wsize = false,763},764765.lck = __rtw8723x_lck,766.read_efuse = __rtw8723x_read_efuse,767.mac_init = __rtw8723x_mac_init,768.mac_postinit = __rtw8723x_mac_postinit,769.cfg_ldo25 = __rtw8723x_cfg_ldo25,770.set_tx_power_index = __rtw8723x_set_tx_power_index,771.efuse_grant = __rtw8723x_efuse_grant,772.false_alarm_statistics = __rtw8723x_false_alarm_statistics,773.iqk_backup_regs = __rtw8723x_iqk_backup_regs,774.iqk_restore_regs = __rtw8723x_iqk_restore_regs,775.iqk_similarity_cmp = __rtw8723x_iqk_similarity_cmp,776.pwrtrack_get_limit_ofdm = __rtw8723x_pwrtrack_get_limit_ofdm,777.pwrtrack_set_xtal = __rtw8723x_pwrtrack_set_xtal,778.coex_cfg_init = __rtw8723x_coex_cfg_init,779.fill_txdesc_checksum = __rtw8723x_fill_txdesc_checksum,780.debug_txpwr_limit = __rtw8723x_debug_txpwr_limit,781};782EXPORT_SYMBOL(rtw8723x_common);783784MODULE_AUTHOR("Realtek Corporation");785MODULE_AUTHOR("Fiona Klute <[email protected]>");786MODULE_DESCRIPTION("Common functions for Realtek 802.11n wireless 8723x drivers");787MODULE_LICENSE("Dual BSD/GPL");788789790