cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rf.c (13642B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright(c) 2009-2012  Realtek Corporation.*/
      3
      4#include "../wifi.h"
      5#include "reg.h"
      6#include "def.h"
      7#include "phy.h"
      8#include "rf.h"
      9#include "dm.h"
     10
     11
     12static void _rtl92s_get_powerbase(struct ieee80211_hw *hw, u8 *p_pwrlevel,
     13				  u8 chnl, u32 *ofdmbase, u32 *mcsbase,
     14				  u8 *p_final_pwridx)
     15{
     16	struct rtl_priv *rtlpriv = rtl_priv(hw);
     17	struct rtl_phy *rtlphy = &(rtlpriv->phy);
     18	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
     19	u32 pwrbase0, pwrbase1;
     20	u8 legacy_pwrdiff = 0, ht20_pwrdiff = 0;
     21	u8 i, pwrlevel[4];
     22
     23	for (i = 0; i < 2; i++)
     24		pwrlevel[i] = p_pwrlevel[i];
     25
     26	/* We only care about the path A for legacy. */
     27	if (rtlefuse->eeprom_version < 2) {
     28		pwrbase0 = pwrlevel[0] + (rtlefuse->legacy_ht_txpowerdiff & 0xf);
     29	} else {
     30		legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff
     31						[RF90_PATH_A][chnl - 1];
     32
     33		/* For legacy OFDM, tx pwr always > HT OFDM pwr.
     34		 * We do not care Path B
     35		 * legacy OFDM pwr diff. NO BB register
     36		 * to notify HW. */
     37		pwrbase0 = pwrlevel[0] + legacy_pwrdiff;
     38	}
     39
     40	pwrbase0 = (pwrbase0 << 24) | (pwrbase0 << 16) | (pwrbase0 << 8) |
     41		    pwrbase0;
     42	*ofdmbase = pwrbase0;
     43
     44	/* MCS rates */
     45	if (rtlefuse->eeprom_version >= 2) {
     46		/* Check HT20 to HT40 diff	*/
     47		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {
     48			for (i = 0; i < 2; i++) {
     49				/* rf-A, rf-B */
     50				/* HT 20<->40 pwr diff */
     51				ht20_pwrdiff = rtlefuse->txpwr_ht20diff
     52							[i][chnl - 1];
     53
     54				if (ht20_pwrdiff < 8) /* 0~+7 */
     55					pwrlevel[i] += ht20_pwrdiff;
     56				else /* index8-15=-8~-1 */
     57					pwrlevel[i] -= (16 - ht20_pwrdiff);
     58			}
     59		}
     60	}
     61
     62	/* use index of rf-A */
     63	pwrbase1 = pwrlevel[0];
     64	pwrbase1 = (pwrbase1 << 24) | (pwrbase1 << 16) | (pwrbase1 << 8) |
     65				pwrbase1;
     66	*mcsbase = pwrbase1;
     67
     68	/* The following is for Antenna
     69	 * diff from Ant-B to Ant-A */
     70	p_final_pwridx[0] = pwrlevel[0];
     71	p_final_pwridx[1] = pwrlevel[1];
     72
     73	switch (rtlefuse->eeprom_regulatory) {
     74	case 3:
     75		/* The following is for calculation
     76		 * of the power diff for Ant-B to Ant-A. */
     77		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
     78			p_final_pwridx[0] += rtlefuse->pwrgroup_ht40
     79						[RF90_PATH_A][
     80						chnl - 1];
     81			p_final_pwridx[1] += rtlefuse->pwrgroup_ht40
     82						[RF90_PATH_B][
     83						chnl - 1];
     84		} else {
     85			p_final_pwridx[0] += rtlefuse->pwrgroup_ht20
     86						[RF90_PATH_A][
     87						chnl - 1];
     88			p_final_pwridx[1] += rtlefuse->pwrgroup_ht20
     89						[RF90_PATH_B][
     90						chnl - 1];
     91		}
     92		break;
     93	default:
     94		break;
     95	}
     96
     97	if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
     98		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
     99			"40MHz finalpwr_idx (A / B) = 0x%x / 0x%x\n",
    100			p_final_pwridx[0], p_final_pwridx[1]);
    101	} else {
    102		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
    103			"20MHz finalpwr_idx (A / B) = 0x%x / 0x%x\n",
    104			p_final_pwridx[0], p_final_pwridx[1]);
    105	}
    106}
    107
    108static void _rtl92s_set_antennadiff(struct ieee80211_hw *hw,
    109				    u8 *p_final_pwridx)
    110{
    111	struct rtl_priv *rtlpriv = rtl_priv(hw);
    112	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
    113	struct rtl_phy *rtlphy = &(rtlpriv->phy);
    114	s8 ant_pwr_diff = 0;
    115	u32	u4reg_val = 0;
    116
    117	if (rtlphy->rf_type == RF_2T2R) {
    118		ant_pwr_diff = p_final_pwridx[1] - p_final_pwridx[0];
    119
    120		/* range is from 7~-8,
    121		 * index = 0x0~0xf */
    122		if (ant_pwr_diff > 7)
    123			ant_pwr_diff = 7;
    124		if (ant_pwr_diff < -8)
    125			ant_pwr_diff = -8;
    126
    127		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
    128			"Antenna Diff from RF-B to RF-A = %d (0x%x)\n",
    129			ant_pwr_diff, ant_pwr_diff & 0xf);
    130
    131		ant_pwr_diff &= 0xf;
    132	}
    133
    134	/* Antenna TX power difference */
    135	rtlefuse->antenna_txpwdiff[2] = 0;/* RF-D, don't care */
    136	rtlefuse->antenna_txpwdiff[1] = 0;/* RF-C, don't care */
    137	rtlefuse->antenna_txpwdiff[0] = (u8)(ant_pwr_diff);	/* RF-B */
    138
    139	u4reg_val = rtlefuse->antenna_txpwdiff[2] << 8 |
    140				rtlefuse->antenna_txpwdiff[1] << 4 |
    141				rtlefuse->antenna_txpwdiff[0];
    142
    143	rtl_set_bbreg(hw, RFPGA0_TXGAINSTAGE, (BXBTXAGC | BXCTXAGC | BXDTXAGC),
    144		      u4reg_val);
    145
    146	rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, "Write BCD-Diff(0x%x) = 0x%x\n",
    147		RFPGA0_TXGAINSTAGE, u4reg_val);
    148}
    149
    150static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw,
    151						      u8 chnl, u8 index,
    152						      u32 pwrbase0,
    153						      u32 pwrbase1,
    154						      u32 *p_outwrite_val)
    155{
    156	struct rtl_priv *rtlpriv = rtl_priv(hw);
    157	struct rtl_phy *rtlphy = &(rtlpriv->phy);
    158	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
    159	u8 i, chnlgroup, pwrdiff_limit[4];
    160	u32 writeval, customer_limit;
    161
    162	/* Index 0 & 1= legacy OFDM, 2-5=HT_MCS rate */
    163	switch (rtlefuse->eeprom_regulatory) {
    164	case 0:
    165		/* Realtek better performance increase power diff
    166		 * defined by Realtek for large power */
    167		chnlgroup = 0;
    168
    169		writeval = rtlphy->mcs_offset[chnlgroup][index] +
    170				((index < 2) ? pwrbase0 : pwrbase1);
    171
    172		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
    173			"RTK better performance, writeval = 0x%x\n", writeval);
    174		break;
    175	case 1:
    176		/* Realtek regulatory increase power diff defined
    177		 * by Realtek for regulatory */
    178		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
    179			writeval = ((index < 2) ? pwrbase0 : pwrbase1);
    180
    181			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
    182				"Realtek regulatory, 40MHz, writeval = 0x%x\n",
    183				writeval);
    184		} else {
    185			chnlgroup = 0;
    186
    187			if (rtlphy->pwrgroup_cnt >= 3) {
    188				if (chnl <= 3)
    189					chnlgroup = 0;
    190				else if (chnl >= 4 && chnl <= 8)
    191					chnlgroup = 1;
    192				else if (chnl > 8)
    193					chnlgroup = 2;
    194				if (rtlphy->pwrgroup_cnt == 4)
    195					chnlgroup++;
    196			}
    197
    198			writeval = rtlphy->mcs_offset[chnlgroup][index]
    199					+ ((index < 2) ?
    200					pwrbase0 : pwrbase1);
    201
    202			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
    203				"Realtek regulatory, 20MHz, writeval = 0x%x\n",
    204				writeval);
    205		}
    206		break;
    207	case 2:
    208		/* Better regulatory don't increase any power diff */
    209		writeval = ((index < 2) ? pwrbase0 : pwrbase1);
    210		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
    211			"Better regulatory, writeval = 0x%x\n", writeval);
    212		break;
    213	case 3:
    214		/* Customer defined power diff. increase power diff
    215		  defined by customer. */
    216		chnlgroup = 0;
    217
    218		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
    219			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
    220				"customer's limit, 40MHz = 0x%x\n",
    221				rtlefuse->pwrgroup_ht40
    222				[RF90_PATH_A][chnl - 1]);
    223		} else {
    224			rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
    225				"customer's limit, 20MHz = 0x%x\n",
    226				rtlefuse->pwrgroup_ht20
    227				[RF90_PATH_A][chnl - 1]);
    228		}
    229
    230		for (i = 0; i < 4; i++) {
    231			pwrdiff_limit[i] = (u8)((rtlphy->mcs_offset
    232				[chnlgroup][index] & (0x7f << (i * 8)))
    233				>> (i * 8));
    234
    235			if (rtlphy->current_chan_bw ==
    236			    HT_CHANNEL_WIDTH_20_40) {
    237				if (pwrdiff_limit[i] >
    238				    rtlefuse->pwrgroup_ht40
    239				    [RF90_PATH_A][chnl - 1]) {
    240					pwrdiff_limit[i] =
    241					  rtlefuse->pwrgroup_ht40
    242					  [RF90_PATH_A][chnl - 1];
    243				}
    244			} else {
    245				if (pwrdiff_limit[i] >
    246				    rtlefuse->pwrgroup_ht20
    247				    [RF90_PATH_A][chnl - 1]) {
    248					pwrdiff_limit[i] =
    249					    rtlefuse->pwrgroup_ht20
    250					    [RF90_PATH_A][chnl - 1];
    251				}
    252			}
    253		}
    254
    255		customer_limit = (pwrdiff_limit[3] << 24) |
    256				(pwrdiff_limit[2] << 16) |
    257				(pwrdiff_limit[1] << 8) |
    258				(pwrdiff_limit[0]);
    259		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
    260			"Customer's limit = 0x%x\n", customer_limit);
    261
    262		writeval = customer_limit + ((index < 2) ?
    263					     pwrbase0 : pwrbase1);
    264		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
    265			"Customer, writeval = 0x%x\n", writeval);
    266		break;
    267	default:
    268		chnlgroup = 0;
    269		writeval = rtlphy->mcs_offset[chnlgroup][index] +
    270				((index < 2) ? pwrbase0 : pwrbase1);
    271		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
    272			"RTK better performance, writeval = 0x%x\n", writeval);
    273		break;
    274	}
    275
    276	if (rtlpriv->dm.dynamic_txhighpower_lvl == TX_HIGH_PWR_LEVEL_LEVEL1)
    277		writeval = 0x10101010;
    278	else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
    279		 TX_HIGH_PWR_LEVEL_LEVEL2)
    280		writeval = 0x0;
    281
    282	*p_outwrite_val = writeval;
    283
    284}
    285
    286static void _rtl92s_write_ofdm_powerreg(struct ieee80211_hw *hw,
    287					u8 index, u32 val)
    288{
    289	struct rtl_priv *rtlpriv = rtl_priv(hw);
    290	struct rtl_phy *rtlphy = &(rtlpriv->phy);
    291	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
    292	u16 regoffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c};
    293	u8 i, rfa_pwr[4];
    294	u8 rfa_lower_bound = 0, rfa_upper_bound = 0, rf_pwr_diff = 0;
    295	u32 writeval = val;
    296
    297	/* If path A and Path B coexist, we must limit Path A tx power.
    298	 * Protect Path B pwr over or under flow. We need to calculate
    299	 * upper and lower bound of path A tx power. */
    300	if (rtlphy->rf_type == RF_2T2R) {
    301		rf_pwr_diff = rtlefuse->antenna_txpwdiff[0];
    302
    303		/* Diff=-8~-1 */
    304		if (rf_pwr_diff >= 8) {
    305			/* Prevent underflow!! */
    306			rfa_lower_bound = 0x10 - rf_pwr_diff;
    307		/* if (rf_pwr_diff >= 0) Diff = 0-7 */
    308		} else {
    309			rfa_upper_bound = RF6052_MAX_TX_PWR - rf_pwr_diff;
    310		}
    311	}
    312
    313	for (i = 0; i < 4; i++) {
    314		rfa_pwr[i] = (u8)((writeval & (0x7f << (i * 8))) >> (i * 8));
    315		if (rfa_pwr[i]  > RF6052_MAX_TX_PWR)
    316			rfa_pwr[i]  = RF6052_MAX_TX_PWR;
    317
    318		/* If path A and Path B coexist, we must limit Path A tx power.
    319		 * Protect Path B pwr over or under flow. We need to calculate
    320		 * upper and lower bound of path A tx power. */
    321		if (rtlphy->rf_type == RF_2T2R) {
    322			/* Diff=-8~-1 */
    323			if (rf_pwr_diff >= 8) {
    324				/* Prevent underflow!! */
    325				if (rfa_pwr[i] < rfa_lower_bound)
    326					rfa_pwr[i] = rfa_lower_bound;
    327			/* Diff = 0-7 */
    328			} else if (rf_pwr_diff >= 1) {
    329				/* Prevent overflow */
    330				if (rfa_pwr[i] > rfa_upper_bound)
    331					rfa_pwr[i] = rfa_upper_bound;
    332			}
    333		}
    334
    335	}
    336
    337	writeval = (rfa_pwr[3] << 24) | (rfa_pwr[2] << 16) | (rfa_pwr[1] << 8) |
    338				rfa_pwr[0];
    339
    340	rtl_set_bbreg(hw, regoffset[index], 0x7f7f7f7f, writeval);
    341}
    342
    343void rtl92s_phy_rf6052_set_ofdmtxpower(struct ieee80211_hw *hw,
    344				       u8 *p_pwrlevel, u8 chnl)
    345{
    346	u32 writeval, pwrbase0, pwrbase1;
    347	u8 index = 0;
    348	u8 finalpwr_idx[4];
    349
    350	_rtl92s_get_powerbase(hw, p_pwrlevel, chnl, &pwrbase0, &pwrbase1,
    351			&finalpwr_idx[0]);
    352	_rtl92s_set_antennadiff(hw, &finalpwr_idx[0]);
    353
    354	for (index = 0; index < 6; index++) {
    355		_rtl92s_get_txpower_writeval_byregulatory(hw, chnl, index,
    356				pwrbase0, pwrbase1, &writeval);
    357
    358		_rtl92s_write_ofdm_powerreg(hw, index, writeval);
    359	}
    360}
    361
    362void rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw, u8 pwrlevel)
    363{
    364	struct rtl_priv *rtlpriv = rtl_priv(hw);
    365	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
    366	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
    367	u32 txagc = 0;
    368	bool dont_inc_cck_or_turboscanoff = false;
    369
    370	if (((rtlefuse->eeprom_version >= 2) &&
    371	      (rtlefuse->txpwr_safetyflag == 1)) ||
    372	      ((rtlefuse->eeprom_version >= 2) &&
    373	      (rtlefuse->eeprom_regulatory != 0)))
    374		dont_inc_cck_or_turboscanoff = true;
    375
    376	if (mac->act_scanning) {
    377		txagc = 0x3f;
    378		if (dont_inc_cck_or_turboscanoff)
    379			txagc = pwrlevel;
    380	} else {
    381		txagc = pwrlevel;
    382
    383		if (rtlpriv->dm.dynamic_txhighpower_lvl ==
    384		    TX_HIGH_PWR_LEVEL_LEVEL1)
    385			txagc = 0x10;
    386		else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
    387			TX_HIGH_PWR_LEVEL_LEVEL2)
    388			txagc = 0x0;
    389	}
    390
    391	if (txagc > RF6052_MAX_TX_PWR)
    392		txagc = RF6052_MAX_TX_PWR;
    393
    394	rtl_set_bbreg(hw, RTXAGC_CCK_MCS32, BTX_AGCRATECCK, txagc);
    395
    396}
    397
    398bool rtl92s_phy_rf6052_config(struct ieee80211_hw *hw)
    399{
    400	struct rtl_priv *rtlpriv = rtl_priv(hw);
    401	struct rtl_phy *rtlphy = &(rtlpriv->phy);
    402	u32 u4reg_val = 0;
    403	u8 rfpath;
    404	bool rtstatus = true;
    405	struct bb_reg_def *pphyreg;
    406
    407	/* Initialize RF */
    408	for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
    409
    410		pphyreg = &rtlphy->phyreg_def[rfpath];
    411
    412		/* Store original RFENV control type */
    413		switch (rfpath) {
    414		case RF90_PATH_A:
    415		case RF90_PATH_C:
    416			u4reg_val = rtl92s_phy_query_bb_reg(hw,
    417							    pphyreg->rfintfs,
    418							    BRFSI_RFENV);
    419			break;
    420		case RF90_PATH_B:
    421		case RF90_PATH_D:
    422			u4reg_val = rtl92s_phy_query_bb_reg(hw,
    423							    pphyreg->rfintfs,
    424							    BRFSI_RFENV << 16);
    425			break;
    426		}
    427
    428		/* Set RF_ENV enable */
    429		rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfe,
    430				      BRFSI_RFENV << 16, 0x1);
    431
    432		/* Set RF_ENV output high */
    433		rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
    434
    435		/* Set bit number of Address and Data for RF register */
    436		rtl92s_phy_set_bb_reg(hw, pphyreg->rfhssi_para2,
    437				B3WIRE_ADDRESSLENGTH, 0x0);
    438		rtl92s_phy_set_bb_reg(hw, pphyreg->rfhssi_para2,
    439				B3WIRE_DATALENGTH, 0x0);
    440
    441		/* Initialize RF fom connfiguration file */
    442		switch (rfpath) {
    443		case RF90_PATH_A:
    444			rtstatus = rtl92s_phy_config_rf(hw,
    445						(enum radio_path)rfpath);
    446			break;
    447		case RF90_PATH_B:
    448			rtstatus = rtl92s_phy_config_rf(hw,
    449						(enum radio_path)rfpath);
    450			break;
    451		case RF90_PATH_C:
    452			break;
    453		case RF90_PATH_D:
    454			break;
    455		}
    456
    457		/* Restore RFENV control type */
    458		switch (rfpath) {
    459		case RF90_PATH_A:
    460		case RF90_PATH_C:
    461			rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfs, BRFSI_RFENV,
    462					      u4reg_val);
    463			break;
    464		case RF90_PATH_B:
    465		case RF90_PATH_D:
    466			rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfs,
    467					      BRFSI_RFENV << 16,
    468					      u4reg_val);
    469			break;
    470		}
    471
    472		if (!rtstatus) {
    473			pr_err("Radio[%d] Fail!!\n", rfpath);
    474			goto fail;
    475		}
    476
    477	}
    478
    479	return rtstatus;
    480
    481fail:
    482	return rtstatus;
    483}
    484
    485void rtl92s_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
    486{
    487	struct rtl_priv *rtlpriv = rtl_priv(hw);
    488	struct rtl_phy *rtlphy = &(rtlpriv->phy);
    489
    490	switch (bandwidth) {
    491	case HT_CHANNEL_WIDTH_20:
    492		rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
    493					   0xfffff3ff) | 0x0400);
    494		rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
    495					rtlphy->rfreg_chnlval[0]);
    496		break;
    497	case HT_CHANNEL_WIDTH_20_40:
    498		rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
    499					    0xfffff3ff));
    500		rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
    501					rtlphy->rfreg_chnlval[0]);
    502		break;
    503	default:
    504		pr_err("unknown bandwidth: %#X\n", bandwidth);
    505		break;
    506	}
    507}