1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2016  Realtek Corporation.
5  *
6  * Contact Information:
7  * wlanfae <wlanfae@realtek.com>
8  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
9  * Hsinchu 300, Taiwan.
10  *
11  * Larry Finger <Larry.Finger@lwfinger.net>
12  *
13  *****************************************************************************/
14 #include "mp_precomp.h"
15 #include "phydm_precomp.h"
16 #include <linux/module.h>
17 
_rtl_phydm_init_com_info(struct rtl_priv * rtlpriv,enum odm_ic_type ic_type,struct rtl_phydm_params * params)18 static int _rtl_phydm_init_com_info(struct rtl_priv *rtlpriv,
19 				    enum odm_ic_type ic_type,
20 				    struct rtl_phydm_params *params)
21 {
22 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
23 	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
24 	struct rtl_phy *rtlphy = &rtlpriv->phy;
25 	struct rtl_mac *mac = rtl_mac(rtlpriv);
26 	struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
27 	struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
28 	u8 odm_board_type = ODM_BOARD_DEFAULT;
29 	u32 support_ability;
30 	int i;
31 
32 	dm->adapter = (void *)rtlpriv;
33 
34 	odm_cmn_info_init(dm, ODM_CMNINFO_PLATFORM, ODM_CE);
35 
36 	odm_cmn_info_init(dm, ODM_CMNINFO_IC_TYPE, ic_type);
37 
38 	odm_cmn_info_init(dm, ODM_CMNINFO_INTERFACE, ODM_ITRF_PCIE);
39 
40 	odm_cmn_info_init(dm, ODM_CMNINFO_MP_TEST_CHIP, params->mp_chip);
41 
42 	odm_cmn_info_init(dm, ODM_CMNINFO_PATCH_ID, rtlhal->oem_id);
43 
44 	odm_cmn_info_init(dm, ODM_CMNINFO_BWIFI_TEST, 1);
45 
46 	if (rtlphy->rf_type == RF_1T1R)
47 		odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_1T1R);
48 	else if (rtlphy->rf_type == RF_1T2R)
49 		odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_1T2R);
50 	else if (rtlphy->rf_type == RF_2T2R)
51 		odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_2T2R);
52 	else if (rtlphy->rf_type == RF_2T2R_GREEN)
53 		odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_2T2R_GREEN);
54 	else if (rtlphy->rf_type == RF_2T3R)
55 		odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_2T3R);
56 	else if (rtlphy->rf_type == RF_2T4R)
57 		odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_2T4R);
58 	else if (rtlphy->rf_type == RF_3T3R)
59 		odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_3T3R);
60 	else if (rtlphy->rf_type == RF_3T4R)
61 		odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_3T4R);
62 	else if (rtlphy->rf_type == RF_4T4R)
63 		odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_4T4R);
64 	else
65 		odm_cmn_info_init(dm, ODM_CMNINFO_RF_TYPE, ODM_XTXR);
66 
67 	/* 1 ======= BoardType: ODM_CMNINFO_BOARD_TYPE ======= */
68 	if (rtlhal->external_lna_2g != 0) {
69 		odm_board_type |= ODM_BOARD_EXT_LNA;
70 		odm_cmn_info_init(dm, ODM_CMNINFO_EXT_LNA, 1);
71 	}
72 	if (rtlhal->external_lna_5g != 0) {
73 		odm_board_type |= ODM_BOARD_EXT_LNA_5G;
74 		odm_cmn_info_init(dm, ODM_CMNINFO_5G_EXT_LNA, 1);
75 	}
76 	if (rtlhal->external_pa_2g != 0) {
77 		odm_board_type |= ODM_BOARD_EXT_PA;
78 		odm_cmn_info_init(dm, ODM_CMNINFO_EXT_PA, 1);
79 	}
80 	if (rtlhal->external_pa_5g != 0) {
81 		odm_board_type |= ODM_BOARD_EXT_PA_5G;
82 		odm_cmn_info_init(dm, ODM_CMNINFO_5G_EXT_PA, 1);
83 	}
84 	if (rtlpriv->cfg->ops->get_btc_status())
85 		odm_board_type |= ODM_BOARD_BT;
86 
87 	odm_cmn_info_init(dm, ODM_CMNINFO_BOARD_TYPE, odm_board_type);
88 	/* 1 ============== End of BoardType ============== */
89 
90 	odm_cmn_info_init(dm, ODM_CMNINFO_GPA, rtlhal->type_gpa);
91 	odm_cmn_info_init(dm, ODM_CMNINFO_APA, rtlhal->type_apa);
92 	odm_cmn_info_init(dm, ODM_CMNINFO_GLNA, rtlhal->type_glna);
93 	odm_cmn_info_init(dm, ODM_CMNINFO_ALNA, rtlhal->type_alna);
94 
95 	odm_cmn_info_init(dm, ODM_CMNINFO_RFE_TYPE, rtlhal->rfe_type);
96 
97 	odm_cmn_info_init(dm, ODM_CMNINFO_EXT_TRSW, 0);
98 
99 	/*Add by YuChen for kfree init*/
100 	odm_cmn_info_init(dm, ODM_CMNINFO_REGRFKFREEENABLE, 2);
101 	odm_cmn_info_init(dm, ODM_CMNINFO_RFKFREEENABLE, 0);
102 
103 	/*Antenna diversity relative parameters*/
104 	odm_cmn_info_hook(dm, ODM_CMNINFO_ANT_DIV,
105 			  &rtlefuse->antenna_div_cfg);
106 	odm_cmn_info_init(dm, ODM_CMNINFO_RF_ANTENNA_TYPE,
107 			  rtlefuse->antenna_div_type);
108 	odm_cmn_info_init(dm, ODM_CMNINFO_BE_FIX_TX_ANT, 0);
109 	odm_cmn_info_init(dm, ODM_CMNINFO_WITH_EXT_ANTENNA_SWITCH, 0);
110 
111 	/* (8822B) efuse 0x3D7 & 0x3D8 for TX PA bias */
112 	odm_cmn_info_init(dm, ODM_CMNINFO_EFUSE0X3D7, params->efuse0x3d7);
113 	odm_cmn_info_init(dm, ODM_CMNINFO_EFUSE0X3D8, params->efuse0x3d8);
114 
115 	/*Add by YuChen for adaptivity init*/
116 	odm_cmn_info_hook(dm, ODM_CMNINFO_ADAPTIVITY,
117 			  &rtlpriv->phydm.adaptivity_en);
118 	phydm_adaptivity_info_init(dm, PHYDM_ADAPINFO_CARRIER_SENSE_ENABLE,
119 				   false);
120 	phydm_adaptivity_info_init(dm, PHYDM_ADAPINFO_DCBACKOFF, 0);
121 	phydm_adaptivity_info_init(dm, PHYDM_ADAPINFO_DYNAMICLINKADAPTIVITY,
122 				   false);
123 	phydm_adaptivity_info_init(dm, PHYDM_ADAPINFO_TH_L2H_INI, 0);
124 	phydm_adaptivity_info_init(dm, PHYDM_ADAPINFO_TH_EDCCA_HL_DIFF, 0);
125 
126 	odm_cmn_info_init(dm, ODM_CMNINFO_IQKFWOFFLOAD, 0);
127 
128 	/* Pointer reference */
129 	odm_cmn_info_hook(dm, ODM_CMNINFO_TX_UNI,
130 			  &rtlpriv->stats.txbytesunicast);
131 	odm_cmn_info_hook(dm, ODM_CMNINFO_RX_UNI,
132 			  &rtlpriv->stats.rxbytesunicast);
133 	odm_cmn_info_hook(dm, ODM_CMNINFO_BAND, &rtlhal->current_bandtype);
134 	odm_cmn_info_hook(dm, ODM_CMNINFO_FORCED_RATE,
135 			  &rtlpriv->phydm.forced_data_rate);
136 	odm_cmn_info_hook(dm, ODM_CMNINFO_FORCED_IGI_LB,
137 			  &rtlpriv->phydm.forced_igi_lb);
138 
139 	odm_cmn_info_hook(dm, ODM_CMNINFO_SEC_CHNL_OFFSET,
140 			  &mac->cur_40_prime_sc);
141 	odm_cmn_info_hook(dm, ODM_CMNINFO_BW, &rtlphy->current_chan_bw);
142 	odm_cmn_info_hook(dm, ODM_CMNINFO_CHNL, &rtlphy->current_channel);
143 
144 	odm_cmn_info_hook(dm, ODM_CMNINFO_SCAN, &mac->act_scanning);
145 	odm_cmn_info_hook(dm, ODM_CMNINFO_POWER_SAVING,
146 			  &ppsc->dot11_psmode); /* may add new boolean flag */
147 	/*Add by Yuchen for phydm beamforming*/
148 	odm_cmn_info_hook(dm, ODM_CMNINFO_TX_TP,
149 			  &rtlpriv->stats.txbytesunicast_inperiod_tp);
150 	odm_cmn_info_hook(dm, ODM_CMNINFO_RX_TP,
151 			  &rtlpriv->stats.rxbytesunicast_inperiod_tp);
152 	odm_cmn_info_hook(dm, ODM_CMNINFO_ANT_TEST,
153 			  &rtlpriv->phydm.antenna_test);
154 	for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++)
155 		odm_cmn_info_ptr_array_hook(dm, ODM_CMNINFO_STA_STATUS, i,
156 					    NULL);
157 
158 	phydm_init_debug_setting(dm);
159 
160 	odm_cmn_info_init(dm, ODM_CMNINFO_FAB_VER, params->fab_ver);
161 	odm_cmn_info_init(dm, ODM_CMNINFO_CUT_VER, params->cut_ver);
162 
163 	/* after ifup, ability is updated again */
164 	support_ability = ODM_RF_CALIBRATION | ODM_RF_TX_PWR_TRACK;
165 	odm_cmn_info_update(dm, ODM_CMNINFO_ABILITY, support_ability);
166 
167 	return 0;
168 }
169 
rtl_phydm_init_priv(struct rtl_priv * rtlpriv,struct rtl_phydm_params * params)170 static int rtl_phydm_init_priv(struct rtl_priv *rtlpriv,
171 			       struct rtl_phydm_params *params)
172 {
173 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
174 	enum odm_ic_type ic;
175 
176 	if (IS_HARDWARE_TYPE_8822B(rtlpriv))
177 		ic = ODM_RTL8822B;
178 	else
179 		return 0;
180 
181 	rtlpriv->phydm.internal =
182 		kzalloc(sizeof(struct phy_dm_struct), GFP_KERNEL);
183 
184 	_rtl_phydm_init_com_info(rtlpriv, ic, params);
185 
186 	odm_init_all_timers(dm);
187 
188 	return 1;
189 }
190 
rtl_phydm_deinit_priv(struct rtl_priv * rtlpriv)191 static int rtl_phydm_deinit_priv(struct rtl_priv *rtlpriv)
192 {
193 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
194 
195 	odm_cancel_all_timers(dm);
196 
197 	kfree(rtlpriv->phydm.internal);
198 	rtlpriv->phydm.internal = NULL;
199 
200 	return 0;
201 }
202 
rtl_phydm_load_txpower_by_rate(struct rtl_priv * rtlpriv)203 static bool rtl_phydm_load_txpower_by_rate(struct rtl_priv *rtlpriv)
204 {
205 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
206 	enum hal_status status;
207 
208 	status = odm_config_bb_with_header_file(dm, CONFIG_BB_PHY_REG_PG);
209 	if (status != HAL_STATUS_SUCCESS)
210 		return false;
211 
212 	return true;
213 }
214 
rtl_phydm_load_txpower_limit(struct rtl_priv * rtlpriv)215 static bool rtl_phydm_load_txpower_limit(struct rtl_priv *rtlpriv)
216 {
217 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
218 	enum hal_status status;
219 
220 	if (IS_HARDWARE_TYPE_8822B(rtlpriv)) {
221 		odm_read_and_config_mp_8822b_txpwr_lmt(dm);
222 	} else {
223 		status = odm_config_rf_with_header_file(dm, CONFIG_RF_TXPWR_LMT,
224 							0);
225 		if (status != HAL_STATUS_SUCCESS)
226 			return false;
227 	}
228 
229 	return true;
230 }
231 
rtl_phydm_init_dm(struct rtl_priv * rtlpriv)232 static int rtl_phydm_init_dm(struct rtl_priv *rtlpriv)
233 {
234 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
235 	u32 support_ability = 0;
236 
237 	/* clang-format off */
238 	support_ability = 0
239 			| ODM_BB_DIG
240 			| ODM_BB_RA_MASK
241 			| ODM_BB_DYNAMIC_TXPWR
242 			| ODM_BB_FA_CNT
243 			| ODM_BB_RSSI_MONITOR
244 			| ODM_BB_CCK_PD
245 	/*		| ODM_BB_PWR_SAVE*/
246 			| ODM_BB_CFO_TRACKING
247 			| ODM_MAC_EDCA_TURBO
248 			| ODM_RF_TX_PWR_TRACK
249 			| ODM_RF_CALIBRATION
250 			| ODM_BB_NHM_CNT
251 	/*		| ODM_BB_PWR_TRAIN*/
252 			;
253 	/* clang-format on */
254 
255 	odm_cmn_info_update(dm, ODM_CMNINFO_ABILITY, support_ability);
256 
257 	odm_dm_init(dm);
258 
259 	return 0;
260 }
261 
rtl_phydm_deinit_dm(struct rtl_priv * rtlpriv)262 static int rtl_phydm_deinit_dm(struct rtl_priv *rtlpriv)
263 {
264 	return 0;
265 }
266 
rtl_phydm_reset_dm(struct rtl_priv * rtlpriv)267 static int rtl_phydm_reset_dm(struct rtl_priv *rtlpriv)
268 {
269 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
270 
271 	odm_dm_reset(dm);
272 
273 	return 0;
274 }
275 
rtl_phydm_parameter_init(struct rtl_priv * rtlpriv,bool post)276 static bool rtl_phydm_parameter_init(struct rtl_priv *rtlpriv, bool post)
277 {
278 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
279 
280 	if (IS_HARDWARE_TYPE_8822B(rtlpriv))
281 		return config_phydm_parameter_init(dm, post ? ODM_POST_SETTING :
282 							      ODM_PRE_SETTING);
283 
284 	return false;
285 }
286 
rtl_phydm_phy_bb_config(struct rtl_priv * rtlpriv)287 static bool rtl_phydm_phy_bb_config(struct rtl_priv *rtlpriv)
288 {
289 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
290 	enum hal_status status;
291 
292 	status = odm_config_bb_with_header_file(dm, CONFIG_BB_PHY_REG);
293 	if (status != HAL_STATUS_SUCCESS)
294 		return false;
295 
296 	status = odm_config_bb_with_header_file(dm, CONFIG_BB_AGC_TAB);
297 	if (status != HAL_STATUS_SUCCESS)
298 		return false;
299 
300 	return true;
301 }
302 
rtl_phydm_phy_rf_config(struct rtl_priv * rtlpriv)303 static bool rtl_phydm_phy_rf_config(struct rtl_priv *rtlpriv)
304 {
305 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
306 	struct rtl_phy *rtlphy = &rtlpriv->phy;
307 	enum hal_status status;
308 	enum odm_rf_radio_path rfpath;
309 
310 	for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
311 		status = odm_config_rf_with_header_file(dm, CONFIG_RF_RADIO,
312 							rfpath);
313 		if (status != HAL_STATUS_SUCCESS)
314 			return false;
315 	}
316 
317 	status = odm_config_rf_with_tx_pwr_track_header_file(dm);
318 	if (status != HAL_STATUS_SUCCESS)
319 		return false;
320 
321 	return true;
322 }
323 
rtl_phydm_phy_mac_config(struct rtl_priv * rtlpriv)324 static bool rtl_phydm_phy_mac_config(struct rtl_priv *rtlpriv)
325 {
326 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
327 	enum hal_status status;
328 
329 	status = odm_config_mac_with_header_file(dm);
330 	if (status != HAL_STATUS_SUCCESS)
331 		return false;
332 
333 	return true;
334 }
335 
rtl_phydm_trx_mode(struct rtl_priv * rtlpriv,enum radio_mask tx_path,enum radio_mask rx_path,bool is_tx2_path)336 static bool rtl_phydm_trx_mode(struct rtl_priv *rtlpriv,
337 			       enum radio_mask tx_path, enum radio_mask rx_path,
338 			       bool is_tx2_path)
339 {
340 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
341 
342 	if (IS_HARDWARE_TYPE_8822B(rtlpriv))
343 		return config_phydm_trx_mode_8822b(dm,
344 						   (enum odm_rf_path)tx_path,
345 						   (enum odm_rf_path)rx_path,
346 						   is_tx2_path);
347 
348 	return false;
349 }
350 
rtl_phydm_watchdog(struct rtl_priv * rtlpriv)351 static bool rtl_phydm_watchdog(struct rtl_priv *rtlpriv)
352 {
353 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
354 	struct rtl_mac *mac = rtl_mac(rtlpriv);
355 	struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
356 	bool fw_current_inpsmode = false;
357 	bool fw_ps_awake = true;
358 	u8 is_linked = false;
359 	u8 bsta_state = false;
360 	u8 is_bt_enabled = false;
361 
362 	/* check whether do watchdog */
363 	rtlpriv->cfg->ops->get_hw_reg(rtlpriv->hw, HW_VAR_FW_PSMODE_STATUS,
364 				      (u8 *)(&fw_current_inpsmode));
365 	rtlpriv->cfg->ops->get_hw_reg(rtlpriv->hw, HW_VAR_FWLPS_RF_ON,
366 				      (u8 *)(&fw_ps_awake));
367 	if (ppsc->p2p_ps_info.p2p_ps_mode)
368 		fw_ps_awake = false;
369 
370 	if ((ppsc->rfpwr_state == ERFON) &&
371 	    ((!fw_current_inpsmode) && fw_ps_awake) &&
372 	    (!ppsc->rfchange_inprogress))
373 		;
374 	else
375 		return false;
376 
377 	/* update common info before doing watchdog */
378 	if (mac->link_state >= MAC80211_LINKED) {
379 		is_linked = true;
380 		if (mac->vif && mac->vif->type == NL80211_IFTYPE_STATION)
381 			bsta_state = true;
382 	}
383 
384 	if (rtlpriv->cfg->ops->get_btc_status())
385 		is_bt_enabled = !rtlpriv->btcoexist.btc_ops->btc_is_bt_disabled(
386 			rtlpriv);
387 
388 	odm_cmn_info_update(dm, ODM_CMNINFO_LINK, is_linked);
389 	odm_cmn_info_update(dm, ODM_CMNINFO_STATION_STATE, bsta_state);
390 	odm_cmn_info_update(dm, ODM_CMNINFO_BT_ENABLED, is_bt_enabled);
391 
392 	/* do watchdog */
393 	odm_dm_watchdog(dm);
394 
395 	return true;
396 }
397 
rtl_phydm_switch_band(struct rtl_priv * rtlpriv,u8 central_ch)398 static bool rtl_phydm_switch_band(struct rtl_priv *rtlpriv, u8 central_ch)
399 {
400 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
401 
402 	if (IS_HARDWARE_TYPE_8822B(rtlpriv))
403 		return config_phydm_switch_band_8822b(dm, central_ch);
404 
405 	return false;
406 }
407 
rtl_phydm_switch_channel(struct rtl_priv * rtlpriv,u8 central_ch)408 static bool rtl_phydm_switch_channel(struct rtl_priv *rtlpriv, u8 central_ch)
409 {
410 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
411 
412 	if (IS_HARDWARE_TYPE_8822B(rtlpriv))
413 		return config_phydm_switch_channel_8822b(dm, central_ch);
414 
415 	return false;
416 }
417 
rtl_phydm_switch_bandwidth(struct rtl_priv * rtlpriv,u8 primary_ch_idx,enum ht_channel_width bandwidth)418 static bool rtl_phydm_switch_bandwidth(struct rtl_priv *rtlpriv,
419 				       u8 primary_ch_idx,
420 				       enum ht_channel_width bandwidth)
421 {
422 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
423 	enum odm_bw odm_bw = (enum odm_bw)bandwidth;
424 
425 	if (IS_HARDWARE_TYPE_8822B(rtlpriv))
426 		return config_phydm_switch_bandwidth_8822b(dm, primary_ch_idx,
427 							   odm_bw);
428 
429 	return false;
430 }
431 
rtl_phydm_iq_calibrate(struct rtl_priv * rtlpriv)432 static bool rtl_phydm_iq_calibrate(struct rtl_priv *rtlpriv)
433 {
434 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
435 
436 	if (IS_HARDWARE_TYPE_8822B(rtlpriv))
437 		phy_iq_calibrate_8822b(dm, false);
438 	else
439 		return false;
440 
441 	return true;
442 }
443 
rtl_phydm_clear_txpowertracking_state(struct rtl_priv * rtlpriv)444 static bool rtl_phydm_clear_txpowertracking_state(struct rtl_priv *rtlpriv)
445 {
446 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
447 
448 	odm_clear_txpowertracking_state(dm);
449 
450 	return true;
451 }
452 
rtl_phydm_pause_dig(struct rtl_priv * rtlpriv,bool pause)453 static bool rtl_phydm_pause_dig(struct rtl_priv *rtlpriv, bool pause)
454 {
455 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
456 
457 	if (pause)
458 		odm_pause_dig(dm, PHYDM_PAUSE, PHYDM_PAUSE_LEVEL_0, 0x1e);
459 	else /* resume */
460 		odm_pause_dig(dm, PHYDM_RESUME, PHYDM_PAUSE_LEVEL_0, 0xff);
461 
462 	return true;
463 }
464 
rtl_phydm_read_rf_reg(struct rtl_priv * rtlpriv,enum radio_path rfpath,u32 addr,u32 mask)465 static u32 rtl_phydm_read_rf_reg(struct rtl_priv *rtlpriv,
466 				 enum radio_path rfpath, u32 addr, u32 mask)
467 {
468 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
469 	enum odm_rf_radio_path odm_rfpath = (enum odm_rf_radio_path)rfpath;
470 
471 	if (IS_HARDWARE_TYPE_8822B(rtlpriv))
472 		return config_phydm_read_rf_reg_8822b(dm, odm_rfpath, addr,
473 						      mask);
474 
475 	return -1;
476 }
477 
rtl_phydm_write_rf_reg(struct rtl_priv * rtlpriv,enum radio_path rfpath,u32 addr,u32 mask,u32 data)478 static bool rtl_phydm_write_rf_reg(struct rtl_priv *rtlpriv,
479 				   enum radio_path rfpath, u32 addr, u32 mask,
480 				   u32 data)
481 {
482 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
483 	enum odm_rf_radio_path odm_rfpath = (enum odm_rf_radio_path)rfpath;
484 
485 	if (IS_HARDWARE_TYPE_8822B(rtlpriv))
486 		return config_phydm_write_rf_reg_8822b(dm, odm_rfpath, addr,
487 						       mask, data);
488 
489 	return false;
490 }
491 
rtl_phydm_read_txagc(struct rtl_priv * rtlpriv,enum radio_path rfpath,u8 hw_rate)492 static u8 rtl_phydm_read_txagc(struct rtl_priv *rtlpriv, enum radio_path rfpath,
493 			       u8 hw_rate)
494 {
495 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
496 	enum odm_rf_radio_path odm_rfpath = (enum odm_rf_radio_path)rfpath;
497 
498 	if (IS_HARDWARE_TYPE_8822B(rtlpriv))
499 		return config_phydm_read_txagc_8822b(dm, odm_rfpath, hw_rate);
500 
501 	return -1;
502 }
503 
rtl_phydm_write_txagc(struct rtl_priv * rtlpriv,u32 power_index,enum radio_path rfpath,u8 hw_rate)504 static bool rtl_phydm_write_txagc(struct rtl_priv *rtlpriv, u32 power_index,
505 				  enum radio_path rfpath, u8 hw_rate)
506 {
507 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
508 	enum odm_rf_radio_path odm_rfpath = (enum odm_rf_radio_path)rfpath;
509 
510 	if (IS_HARDWARE_TYPE_8822B(rtlpriv))
511 		return config_phydm_write_txagc_8822b(dm, power_index,
512 						      odm_rfpath, hw_rate);
513 
514 	return false;
515 }
516 
rtl_phydm_c2h_content_parsing(struct rtl_priv * rtlpriv,u8 cmd_id,u8 cmd_len,u8 * content)517 static bool rtl_phydm_c2h_content_parsing(struct rtl_priv *rtlpriv, u8 cmd_id,
518 					  u8 cmd_len, u8 *content)
519 {
520 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
521 
522 	if (phydm_c2H_content_parsing(dm, cmd_id, cmd_len, content))
523 		return true;
524 
525 	return false;
526 }
527 
rtl_phydm_query_phy_status(struct rtl_priv * rtlpriv,u8 * phystrpt,struct ieee80211_hdr * hdr,struct rtl_stats * pstatus)528 static bool rtl_phydm_query_phy_status(struct rtl_priv *rtlpriv, u8 *phystrpt,
529 				       struct ieee80211_hdr *hdr,
530 				       struct rtl_stats *pstatus)
531 {
532 	/* NOTE: phystrpt may be NULL, and need to fill default value */
533 
534 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
535 	struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
536 	struct rtl_mac *mac = rtl_mac(rtlpriv);
537 	struct dm_per_pkt_info pktinfo; /* input of pydm */
538 	struct dm_phy_status_info phy_info; /* output of phydm */
539 	__le16 fc = hdr->frame_control;
540 
541 	/* fill driver pstatus */
542 	ether_addr_copy(pstatus->psaddr, ieee80211_get_SA(hdr));
543 
544 	/* fill pktinfo */
545 	memset(&pktinfo, 0, sizeof(pktinfo));
546 
547 	pktinfo.data_rate = pstatus->rate;
548 
549 	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION) {
550 		pktinfo.station_id = 0;
551 	} else {
552 		/* TODO: use rtl_find_sta() to find ID */
553 		pktinfo.station_id = 0xFF;
554 	}
555 
556 	pktinfo.is_packet_match_bssid =
557 		(!ieee80211_is_ctl(fc) &&
558 		 (ether_addr_equal(mac->bssid,
559 				   ieee80211_has_tods(fc) ?
560 					   hdr->addr1 :
561 					   ieee80211_has_fromds(fc) ?
562 					   hdr->addr2 :
563 					   hdr->addr3)) &&
564 		 (!pstatus->hwerror) && (!pstatus->crc) && (!pstatus->icv));
565 	pktinfo.is_packet_to_self =
566 		pktinfo.is_packet_match_bssid &&
567 		(ether_addr_equal(hdr->addr1, rtlefuse->dev_addr));
568 	pktinfo.is_to_self = (!pstatus->icv) && (!pstatus->crc) &&
569 			     (ether_addr_equal(hdr->addr1, rtlefuse->dev_addr));
570 	pktinfo.is_packet_beacon = (ieee80211_is_beacon(fc) ? true : false);
571 
572 	/* query phy status */
573 	if (phystrpt)
574 		odm_phy_status_query(dm, &phy_info, phystrpt, &pktinfo);
575 	else
576 		memset(&phy_info, 0, sizeof(phy_info));
577 
578 	/* copy phy_info from phydm to driver */
579 	pstatus->rx_pwdb_all = phy_info.rx_pwdb_all;
580 	pstatus->bt_rx_rssi_percentage = phy_info.bt_rx_rssi_percentage;
581 	pstatus->recvsignalpower = phy_info.recv_signal_power;
582 	pstatus->signalquality = phy_info.signal_quality;
583 	pstatus->rx_mimo_signalquality[0] = phy_info.rx_mimo_signal_quality[0];
584 	pstatus->rx_mimo_signalquality[1] = phy_info.rx_mimo_signal_quality[1];
585 	pstatus->rx_packet_bw =
586 		phy_info.band_width; /* HT_CHANNEL_WIDTH_20 <- ODM_BW20M */
587 
588 	/* fill driver pstatus */
589 	pstatus->packet_matchbssid = pktinfo.is_packet_match_bssid;
590 	pstatus->packet_toself = pktinfo.is_packet_to_self;
591 	pstatus->packet_beacon = pktinfo.is_packet_beacon;
592 
593 	return true;
594 }
595 
rtl_phydm_rate_id_mapping(struct rtl_priv * rtlpriv,enum wireless_mode wireless_mode,enum rf_type rf_type,enum ht_channel_width bw)596 static u8 rtl_phydm_rate_id_mapping(struct rtl_priv *rtlpriv,
597 				    enum wireless_mode wireless_mode,
598 				    enum rf_type rf_type,
599 				    enum ht_channel_width bw)
600 {
601 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
602 
603 	return phydm_rate_id_mapping(dm, wireless_mode, rf_type, bw);
604 }
605 
rtl_phydm_get_ra_bitmap(struct rtl_priv * rtlpriv,enum wireless_mode wireless_mode,enum rf_type rf_type,enum ht_channel_width bw,u8 tx_rate_level,u32 * tx_bitmap_msb,u32 * tx_bitmap_lsb)606 static bool rtl_phydm_get_ra_bitmap(struct rtl_priv *rtlpriv,
607 				    enum wireless_mode wireless_mode,
608 				    enum rf_type rf_type,
609 				    enum ht_channel_width bw,
610 				    u8 tx_rate_level, /* 0~6 */
611 				    u32 *tx_bitmap_msb,
612 				    u32 *tx_bitmap_lsb)
613 {
614 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
615 	const u8 mimo_ps_enable = 0;
616 	const u8 disable_cck_rate = 0;
617 
618 	phydm_update_hal_ra_mask(dm, wireless_mode, rf_type, bw, mimo_ps_enable,
619 				 disable_cck_rate, tx_bitmap_msb, tx_bitmap_lsb,
620 				 tx_rate_level);
621 
622 	return true;
623 }
624 
_rtl_phydm_get_macid(struct rtl_priv * rtlpriv,struct ieee80211_sta * sta)625 static u8 _rtl_phydm_get_macid(struct rtl_priv *rtlpriv,
626 			       struct ieee80211_sta *sta)
627 {
628 	struct rtl_mac *mac = rtl_mac(rtlpriv);
629 
630 	if (mac->opmode == NL80211_IFTYPE_STATION ||
631 	    mac->opmode == NL80211_IFTYPE_MESH_POINT) {
632 		return 0;
633 	} else if (mac->opmode == NL80211_IFTYPE_AP ||
634 		   mac->opmode == NL80211_IFTYPE_ADHOC)
635 		return sta->aid + 1;
636 
637 	return 0;
638 }
639 
rtl_phydm_add_sta(struct rtl_priv * rtlpriv,struct ieee80211_sta * sta)640 static bool rtl_phydm_add_sta(struct rtl_priv *rtlpriv,
641 			      struct ieee80211_sta *sta)
642 {
643 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
644 	struct rtl_sta_info *sta_entry = (struct rtl_sta_info *)sta->drv_priv;
645 	u8 mac_id = _rtl_phydm_get_macid(rtlpriv, sta);
646 
647 	odm_cmn_info_ptr_array_hook(dm, ODM_CMNINFO_STA_STATUS, mac_id,
648 				    sta_entry);
649 
650 	return true;
651 }
652 
rtl_phydm_del_sta(struct rtl_priv * rtlpriv,struct ieee80211_sta * sta)653 static bool rtl_phydm_del_sta(struct rtl_priv *rtlpriv,
654 			      struct ieee80211_sta *sta)
655 {
656 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
657 	u8 mac_id = _rtl_phydm_get_macid(rtlpriv, sta);
658 
659 	odm_cmn_info_ptr_array_hook(dm, ODM_CMNINFO_STA_STATUS, mac_id, NULL);
660 
661 	return true;
662 }
663 
rtl_phydm_get_version(struct rtl_priv * rtlpriv)664 static u32 rtl_phydm_get_version(struct rtl_priv *rtlpriv)
665 {
666 	u32 ver = 0;
667 
668 	if (IS_HARDWARE_TYPE_8822B(rtlpriv))
669 		ver = RELEASE_VERSION_8822B;
670 
671 	return ver;
672 }
673 
rtl_phydm_modify_ra_pcr_threshold(struct rtl_priv * rtlpriv,u8 ra_offset_direction,u8 ra_threshold_offset)674 static bool rtl_phydm_modify_ra_pcr_threshold(struct rtl_priv *rtlpriv,
675 					      u8 ra_offset_direction,
676 					      u8 ra_threshold_offset)
677 {
678 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
679 
680 	phydm_modify_RA_PCR_threshold(dm, ra_offset_direction,
681 				      ra_threshold_offset);
682 
683 	return true;
684 }
685 
rtl_phydm_query_counter(struct rtl_priv * rtlpriv,const char * info_type)686 static u32 rtl_phydm_query_counter(struct rtl_priv *rtlpriv,
687 				   const char *info_type)
688 {
689 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
690 	static const struct query_entry {
691 		const char *query_name;
692 		enum phydm_info_query query_id;
693 	} query_table[] = {
694 #define QUERY_ENTRY(name)	{#name, name}
695 		QUERY_ENTRY(PHYDM_INFO_FA_OFDM),
696 		QUERY_ENTRY(PHYDM_INFO_FA_CCK),
697 		QUERY_ENTRY(PHYDM_INFO_CCA_OFDM),
698 		QUERY_ENTRY(PHYDM_INFO_CCA_CCK),
699 		QUERY_ENTRY(PHYDM_INFO_CRC32_OK_CCK),
700 		QUERY_ENTRY(PHYDM_INFO_CRC32_OK_LEGACY),
701 		QUERY_ENTRY(PHYDM_INFO_CRC32_OK_HT),
702 		QUERY_ENTRY(PHYDM_INFO_CRC32_OK_VHT),
703 		QUERY_ENTRY(PHYDM_INFO_CRC32_ERROR_CCK),
704 		QUERY_ENTRY(PHYDM_INFO_CRC32_ERROR_LEGACY),
705 		QUERY_ENTRY(PHYDM_INFO_CRC32_ERROR_HT),
706 		QUERY_ENTRY(PHYDM_INFO_CRC32_ERROR_VHT),
707 	};
708 #define QUERY_TABLE_SIZE	ARRAY_SIZE(query_table)
709 
710 	int i;
711 	const struct query_entry *entry;
712 
713 	if (!strcmp(info_type, "IQK_TOTAL"))
714 		return dm->n_iqk_cnt;
715 
716 	if (!strcmp(info_type, "IQK_OK"))
717 		return dm->n_iqk_ok_cnt;
718 
719 	if (!strcmp(info_type, "IQK_FAIL"))
720 		return dm->n_iqk_fail_cnt;
721 
722 	for (i = 0; i < QUERY_TABLE_SIZE; i++) {
723 		entry = &query_table[i];
724 
725 		if (!strcmp(info_type, entry->query_name))
726 			return phydm_cmn_info_query(dm, entry->query_id);
727 	}
728 
729 	pr_err("Unrecognized info_type:%s!!!!:\n", info_type);
730 
731 	return 0xDEADDEAD;
732 }
733 
rtl_phydm_debug_cmd(struct rtl_priv * rtlpriv,char * in,u32 in_len,char * out,u32 out_len)734 static bool rtl_phydm_debug_cmd(struct rtl_priv *rtlpriv, char *in, u32 in_len,
735 				char *out, u32 out_len)
736 {
737 	struct phy_dm_struct *dm = rtlpriv_to_phydm(rtlpriv);
738 
739 	phydm_cmd(dm, in, in_len, 1, out, out_len);
740 
741 	return true;
742 }
743 
744 static struct rtl_phydm_ops rtl_phydm_operation = {
745 	/* init/deinit priv */
746 	.phydm_init_priv = rtl_phydm_init_priv,
747 	.phydm_deinit_priv = rtl_phydm_deinit_priv,
748 	.phydm_load_txpower_by_rate = rtl_phydm_load_txpower_by_rate,
749 	.phydm_load_txpower_limit = rtl_phydm_load_txpower_limit,
750 
751 	/* init hw */
752 	.phydm_init_dm = rtl_phydm_init_dm,
753 	.phydm_deinit_dm = rtl_phydm_deinit_dm,
754 	.phydm_reset_dm = rtl_phydm_reset_dm,
755 	.phydm_parameter_init = rtl_phydm_parameter_init,
756 	.phydm_phy_bb_config = rtl_phydm_phy_bb_config,
757 	.phydm_phy_rf_config = rtl_phydm_phy_rf_config,
758 	.phydm_phy_mac_config = rtl_phydm_phy_mac_config,
759 	.phydm_trx_mode = rtl_phydm_trx_mode,
760 
761 	/* watchdog */
762 	.phydm_watchdog = rtl_phydm_watchdog,
763 
764 	/* channel */
765 	.phydm_switch_band = rtl_phydm_switch_band,
766 	.phydm_switch_channel = rtl_phydm_switch_channel,
767 	.phydm_switch_bandwidth = rtl_phydm_switch_bandwidth,
768 	.phydm_iq_calibrate = rtl_phydm_iq_calibrate,
769 	.phydm_clear_txpowertracking_state =
770 		rtl_phydm_clear_txpowertracking_state,
771 	.phydm_pause_dig = rtl_phydm_pause_dig,
772 
773 	/* read/write reg */
774 	.phydm_read_rf_reg = rtl_phydm_read_rf_reg,
775 	.phydm_write_rf_reg = rtl_phydm_write_rf_reg,
776 	.phydm_read_txagc = rtl_phydm_read_txagc,
777 	.phydm_write_txagc = rtl_phydm_write_txagc,
778 
779 	/* RX */
780 	.phydm_c2h_content_parsing = rtl_phydm_c2h_content_parsing,
781 	.phydm_query_phy_status = rtl_phydm_query_phy_status,
782 
783 	/* TX */
784 	.phydm_rate_id_mapping = rtl_phydm_rate_id_mapping,
785 	.phydm_get_ra_bitmap = rtl_phydm_get_ra_bitmap,
786 
787 	/* STA */
788 	.phydm_add_sta = rtl_phydm_add_sta,
789 	.phydm_del_sta = rtl_phydm_del_sta,
790 
791 	/* BTC */
792 	.phydm_get_version = rtl_phydm_get_version,
793 	.phydm_modify_ra_pcr_threshold = rtl_phydm_modify_ra_pcr_threshold,
794 	.phydm_query_counter = rtl_phydm_query_counter,
795 
796 	/* debug */
797 	.phydm_debug_cmd = rtl_phydm_debug_cmd,
798 };
799 
rtl_phydm_get_ops_pointer(void)800 struct rtl_phydm_ops *rtl_phydm_get_ops_pointer(void)
801 {
802 	return &rtl_phydm_operation;
803 }
804 EXPORT_SYMBOL(rtl_phydm_get_ops_pointer);
805 
806 /* ********************************************************
807  * Define phydm callout function in below
808  * ********************************************************
809  */
810 
phy_get_tx_power_index(void * adapter,u8 rf_path,u8 rate,enum ht_channel_width bandwidth,u8 channel)811 u8 phy_get_tx_power_index(void *adapter, u8 rf_path, u8 rate,
812 			  enum ht_channel_width bandwidth, u8 channel)
813 {
814 	/* rate: DESC_RATE1M */
815 	struct rtl_priv *rtlpriv = (struct rtl_priv *)adapter;
816 
817 	return rtlpriv->cfg->ops->get_txpower_index(rtlpriv->hw, rf_path, rate,
818 						    bandwidth, channel);
819 }
820 
phy_set_tx_power_index_by_rs(void * adapter,u8 ch,u8 path,u8 rs)821 void phy_set_tx_power_index_by_rs(void *adapter, u8 ch, u8 path, u8 rs)
822 {
823 	struct rtl_priv *rtlpriv = (struct rtl_priv *)adapter;
824 
825 	return rtlpriv->cfg->ops->set_tx_power_index_by_rs(rtlpriv->hw, ch,
826 							   path, rs);
827 }
828 
phy_store_tx_power_by_rate(void * adapter,u32 band,u32 rfpath,u32 txnum,u32 regaddr,u32 bitmask,u32 data)829 void phy_store_tx_power_by_rate(void *adapter, u32 band, u32 rfpath, u32 txnum,
830 				u32 regaddr, u32 bitmask, u32 data)
831 {
832 	struct rtl_priv *rtlpriv = (struct rtl_priv *)adapter;
833 
834 	rtlpriv->cfg->ops->store_tx_power_by_rate(
835 		rtlpriv->hw, band, rfpath, txnum, regaddr, bitmask, data);
836 }
837 
phy_set_tx_power_limit(void * dm,u8 * regulation,u8 * band,u8 * bandwidth,u8 * rate_section,u8 * rf_path,u8 * channel,u8 * power_limit)838 void phy_set_tx_power_limit(void *dm, u8 *regulation, u8 *band, u8 *bandwidth,
839 			    u8 *rate_section, u8 *rf_path, u8 *channel,
840 			    u8 *power_limit)
841 {
842 	struct rtl_priv *rtlpriv =
843 		(struct rtl_priv *)((struct phy_dm_struct *)dm)->adapter;
844 
845 	rtlpriv->cfg->ops->phy_set_txpower_limit(rtlpriv->hw, regulation, band,
846 						 bandwidth, rate_section,
847 						 rf_path, channel, power_limit);
848 }
849 
rtl_hal_update_ra_mask(void * adapter,struct rtl_sta_info * psta,u8 rssi_level)850 void rtl_hal_update_ra_mask(void *adapter, struct rtl_sta_info *psta,
851 			    u8 rssi_level)
852 {
853 	struct rtl_priv *rtlpriv = (struct rtl_priv *)adapter;
854 	struct ieee80211_sta *sta =
855 		container_of((void *)psta, struct ieee80211_sta, drv_priv);
856 
857 	rtlpriv->cfg->ops->update_rate_tbl(rtlpriv->hw, sta, rssi_level, false);
858 }
859 
860 MODULE_AUTHOR("Realtek WlanFAE	<wlanfae@realtek.com>");
861 MODULE_AUTHOR("Larry Finger	<Larry.FInger@lwfinger.net>");
862 MODULE_LICENSE("GPL");
863 MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
864