1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2009-2014 Realtek Corporation.*/
5 #include "phy_common.h"
6 #include "../rtl8723ae/reg.h"
7 #include <linux/module.h>
9 /* These routines are common to RTL8723AE and RTL8723bE */
11 u32
rtl8723_phy_query_bb_reg(struct ieee80211_hw
*hw
,
12 u32 regaddr
, u32 bitmask
)
14 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
15 u32 returnvalue
, originalvalue
, bitshift
;
17 RT_TRACE(rtlpriv
, COMP_RF
, DBG_TRACE
,
18 "regaddr(%#x), bitmask(%#x)\n", regaddr
, bitmask
);
19 originalvalue
= rtl_read_dword(rtlpriv
, regaddr
);
20 bitshift
= rtl8723_phy_calculate_bit_shift(bitmask
);
21 returnvalue
= (originalvalue
& bitmask
) >> bitshift
;
23 RT_TRACE(rtlpriv
, COMP_RF
, DBG_TRACE
,
24 "BBR MASK=0x%x Addr[0x%x]=0x%x\n", bitmask
,
25 regaddr
, originalvalue
);
28 EXPORT_SYMBOL_GPL(rtl8723_phy_query_bb_reg
);
30 void rtl8723_phy_set_bb_reg(struct ieee80211_hw
*hw
, u32 regaddr
,
31 u32 bitmask
, u32 data
)
33 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
34 u32 originalvalue
, bitshift
;
36 RT_TRACE(rtlpriv
, COMP_RF
, DBG_TRACE
,
37 "regaddr(%#x), bitmask(%#x), data(%#x)\n", regaddr
, bitmask
,
40 if (bitmask
!= MASKDWORD
) {
41 originalvalue
= rtl_read_dword(rtlpriv
, regaddr
);
42 bitshift
= rtl8723_phy_calculate_bit_shift(bitmask
);
43 data
= ((originalvalue
& (~bitmask
)) | (data
<< bitshift
));
46 rtl_write_dword(rtlpriv
, regaddr
, data
);
48 RT_TRACE(rtlpriv
, COMP_RF
, DBG_TRACE
,
49 "regaddr(%#x), bitmask(%#x), data(%#x)\n",
50 regaddr
, bitmask
, data
);
52 EXPORT_SYMBOL_GPL(rtl8723_phy_set_bb_reg
);
54 u32
rtl8723_phy_calculate_bit_shift(u32 bitmask
)
58 for (i
= 0; i
<= 31; i
++) {
59 if (((bitmask
>> i
) & 0x1) == 1)
64 EXPORT_SYMBOL_GPL(rtl8723_phy_calculate_bit_shift
);
66 u32
rtl8723_phy_rf_serial_read(struct ieee80211_hw
*hw
,
67 enum radio_path rfpath
, u32 offset
)
69 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
70 struct rtl_phy
*rtlphy
= &(rtlpriv
->phy
);
71 struct bb_reg_def
*pphyreg
= &rtlphy
->phyreg_def
[rfpath
];
73 u32 tmplong
, tmplong2
;
79 if (RT_CANNOT_IO(hw
)) {
80 pr_err("return all one\n");
83 tmplong
= rtl_get_bbreg(hw
, RFPGA0_XA_HSSIPARAMETER2
, MASKDWORD
);
84 if (rfpath
== RF90_PATH_A
)
87 tmplong2
= rtl_get_bbreg(hw
, pphyreg
->rfhssi_para2
, MASKDWORD
);
88 tmplong2
= (tmplong2
& (~BLSSIREADADDRESS
)) |
89 (newoffset
<< 23) | BLSSIREADEDGE
;
90 rtl_set_bbreg(hw
, RFPGA0_XA_HSSIPARAMETER2
, MASKDWORD
,
91 tmplong
& (~BLSSIREADEDGE
));
92 rtl_set_bbreg(hw
, pphyreg
->rfhssi_para2
, MASKDWORD
, tmplong2
);
93 rtl_set_bbreg(hw
, RFPGA0_XA_HSSIPARAMETER2
, MASKDWORD
,
94 tmplong
| BLSSIREADEDGE
);
96 if (rfpath
== RF90_PATH_A
)
97 rfpi_enable
= (u8
) rtl_get_bbreg(hw
, RFPGA0_XA_HSSIPARAMETER1
,
99 else if (rfpath
== RF90_PATH_B
)
100 rfpi_enable
= (u8
) rtl_get_bbreg(hw
, RFPGA0_XB_HSSIPARAMETER1
,
103 retvalue
= rtl_get_bbreg(hw
, pphyreg
->rf_rbpi
,
106 retvalue
= rtl_get_bbreg(hw
, pphyreg
->rf_rb
,
108 RT_TRACE(rtlpriv
, COMP_RF
, DBG_TRACE
,
109 "RFR-%d Addr[0x%x]=0x%x\n",
110 rfpath
, pphyreg
->rf_rb
, retvalue
);
113 EXPORT_SYMBOL_GPL(rtl8723_phy_rf_serial_read
);
115 void rtl8723_phy_rf_serial_write(struct ieee80211_hw
*hw
,
116 enum radio_path rfpath
,
117 u32 offset
, u32 data
)
121 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
122 struct rtl_phy
*rtlphy
= &(rtlpriv
->phy
);
123 struct bb_reg_def
*pphyreg
= &rtlphy
->phyreg_def
[rfpath
];
125 if (RT_CANNOT_IO(hw
)) {
131 data_and_addr
= ((newoffset
<< 20) | (data
& 0x000fffff)) & 0x0fffffff;
132 rtl_set_bbreg(hw
, pphyreg
->rf3wire_offset
, MASKDWORD
, data_and_addr
);
133 RT_TRACE(rtlpriv
, COMP_RF
, DBG_TRACE
,
134 "RFW-%d Addr[0x%x]=0x%x\n",
135 rfpath
, pphyreg
->rf3wire_offset
,
138 EXPORT_SYMBOL_GPL(rtl8723_phy_rf_serial_write
);
140 long rtl8723_phy_txpwr_idx_to_dbm(struct ieee80211_hw
*hw
,
141 enum wireless_mode wirelessmode
,
147 switch (wirelessmode
) {
148 case WIRELESS_MODE_B
:
151 case WIRELESS_MODE_G
:
152 case WIRELESS_MODE_N_24G
:
159 pwrout_dbm
= txpwridx
/ 2 + offset
;
162 EXPORT_SYMBOL_GPL(rtl8723_phy_txpwr_idx_to_dbm
);
164 void rtl8723_phy_init_bb_rf_reg_def(struct ieee80211_hw
*hw
)
166 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
167 struct rtl_phy
*rtlphy
= &(rtlpriv
->phy
);
169 rtlphy
->phyreg_def
[RF90_PATH_A
].rfintfs
= RFPGA0_XAB_RFINTERFACESW
;
170 rtlphy
->phyreg_def
[RF90_PATH_B
].rfintfs
= RFPGA0_XAB_RFINTERFACESW
;
171 rtlphy
->phyreg_def
[RF90_PATH_C
].rfintfs
= RFPGA0_XCD_RFINTERFACESW
;
172 rtlphy
->phyreg_def
[RF90_PATH_D
].rfintfs
= RFPGA0_XCD_RFINTERFACESW
;
174 rtlphy
->phyreg_def
[RF90_PATH_A
].rfintfi
= RFPGA0_XAB_RFINTERFACERB
;
175 rtlphy
->phyreg_def
[RF90_PATH_B
].rfintfi
= RFPGA0_XAB_RFINTERFACERB
;
176 rtlphy
->phyreg_def
[RF90_PATH_C
].rfintfi
= RFPGA0_XCD_RFINTERFACERB
;
177 rtlphy
->phyreg_def
[RF90_PATH_D
].rfintfi
= RFPGA0_XCD_RFINTERFACERB
;
179 rtlphy
->phyreg_def
[RF90_PATH_A
].rfintfo
= RFPGA0_XA_RFINTERFACEOE
;
180 rtlphy
->phyreg_def
[RF90_PATH_B
].rfintfo
= RFPGA0_XB_RFINTERFACEOE
;
182 rtlphy
->phyreg_def
[RF90_PATH_A
].rfintfe
= RFPGA0_XA_RFINTERFACEOE
;
183 rtlphy
->phyreg_def
[RF90_PATH_B
].rfintfe
= RFPGA0_XB_RFINTERFACEOE
;
185 rtlphy
->phyreg_def
[RF90_PATH_A
].rf3wire_offset
=
186 RFPGA0_XA_LSSIPARAMETER
;
187 rtlphy
->phyreg_def
[RF90_PATH_B
].rf3wire_offset
=
188 RFPGA0_XB_LSSIPARAMETER
;
190 rtlphy
->phyreg_def
[RF90_PATH_A
].rflssi_select
= RFPGA0_XAB_RFPARAMETER
;
191 rtlphy
->phyreg_def
[RF90_PATH_B
].rflssi_select
= RFPGA0_XAB_RFPARAMETER
;
192 rtlphy
->phyreg_def
[RF90_PATH_C
].rflssi_select
= RFPGA0_XCD_RFPARAMETER
;
193 rtlphy
->phyreg_def
[RF90_PATH_D
].rflssi_select
= RFPGA0_XCD_RFPARAMETER
;
195 rtlphy
->phyreg_def
[RF90_PATH_A
].rftxgain_stage
= RFPGA0_TXGAINSTAGE
;
196 rtlphy
->phyreg_def
[RF90_PATH_B
].rftxgain_stage
= RFPGA0_TXGAINSTAGE
;
197 rtlphy
->phyreg_def
[RF90_PATH_C
].rftxgain_stage
= RFPGA0_TXGAINSTAGE
;
198 rtlphy
->phyreg_def
[RF90_PATH_D
].rftxgain_stage
= RFPGA0_TXGAINSTAGE
;
200 rtlphy
->phyreg_def
[RF90_PATH_A
].rfhssi_para1
= RFPGA0_XA_HSSIPARAMETER1
;
201 rtlphy
->phyreg_def
[RF90_PATH_B
].rfhssi_para1
= RFPGA0_XB_HSSIPARAMETER1
;
203 rtlphy
->phyreg_def
[RF90_PATH_A
].rfhssi_para2
= RFPGA0_XA_HSSIPARAMETER2
;
204 rtlphy
->phyreg_def
[RF90_PATH_B
].rfhssi_para2
= RFPGA0_XB_HSSIPARAMETER2
;
206 rtlphy
->phyreg_def
[RF90_PATH_A
].rfsw_ctrl
= RFPGA0_XAB_SWITCHCONTROL
;
207 rtlphy
->phyreg_def
[RF90_PATH_B
].rfsw_ctrl
= RFPGA0_XAB_SWITCHCONTROL
;
208 rtlphy
->phyreg_def
[RF90_PATH_C
].rfsw_ctrl
= RFPGA0_XCD_SWITCHCONTROL
;
209 rtlphy
->phyreg_def
[RF90_PATH_D
].rfsw_ctrl
= RFPGA0_XCD_SWITCHCONTROL
;
211 rtlphy
->phyreg_def
[RF90_PATH_A
].rfagc_control1
= ROFDM0_XAAGCCORE1
;
212 rtlphy
->phyreg_def
[RF90_PATH_B
].rfagc_control1
= ROFDM0_XBAGCCORE1
;
213 rtlphy
->phyreg_def
[RF90_PATH_C
].rfagc_control1
= ROFDM0_XCAGCCORE1
;
214 rtlphy
->phyreg_def
[RF90_PATH_D
].rfagc_control1
= ROFDM0_XDAGCCORE1
;
216 rtlphy
->phyreg_def
[RF90_PATH_A
].rfagc_control2
= ROFDM0_XAAGCCORE2
;
217 rtlphy
->phyreg_def
[RF90_PATH_B
].rfagc_control2
= ROFDM0_XBAGCCORE2
;
218 rtlphy
->phyreg_def
[RF90_PATH_C
].rfagc_control2
= ROFDM0_XCAGCCORE2
;
219 rtlphy
->phyreg_def
[RF90_PATH_D
].rfagc_control2
= ROFDM0_XDAGCCORE2
;
221 rtlphy
->phyreg_def
[RF90_PATH_A
].rfrxiq_imbal
= ROFDM0_XARXIQIMBALANCE
;
222 rtlphy
->phyreg_def
[RF90_PATH_B
].rfrxiq_imbal
= ROFDM0_XBRXIQIMBALANCE
;
223 rtlphy
->phyreg_def
[RF90_PATH_C
].rfrxiq_imbal
= ROFDM0_XCRXIQIMBANLANCE
;
224 rtlphy
->phyreg_def
[RF90_PATH_D
].rfrxiq_imbal
= ROFDM0_XDRXIQIMBALANCE
;
226 rtlphy
->phyreg_def
[RF90_PATH_A
].rfrx_afe
= ROFDM0_XARXAFE
;
227 rtlphy
->phyreg_def
[RF90_PATH_B
].rfrx_afe
= ROFDM0_XBRXAFE
;
228 rtlphy
->phyreg_def
[RF90_PATH_C
].rfrx_afe
= ROFDM0_XCRXAFE
;
229 rtlphy
->phyreg_def
[RF90_PATH_D
].rfrx_afe
= ROFDM0_XDRXAFE
;
231 rtlphy
->phyreg_def
[RF90_PATH_A
].rftxiq_imbal
= ROFDM0_XATXIQIMBALANCE
;
232 rtlphy
->phyreg_def
[RF90_PATH_B
].rftxiq_imbal
= ROFDM0_XBTXIQIMBALANCE
;
233 rtlphy
->phyreg_def
[RF90_PATH_C
].rftxiq_imbal
= ROFDM0_XCTXIQIMBALANCE
;
234 rtlphy
->phyreg_def
[RF90_PATH_D
].rftxiq_imbal
= ROFDM0_XDTXIQIMBALANCE
;
236 rtlphy
->phyreg_def
[RF90_PATH_A
].rftx_afe
= ROFDM0_XATXAFE
;
237 rtlphy
->phyreg_def
[RF90_PATH_B
].rftx_afe
= ROFDM0_XBTXAFE
;
238 rtlphy
->phyreg_def
[RF90_PATH_C
].rftx_afe
= ROFDM0_XCTXAFE
;
239 rtlphy
->phyreg_def
[RF90_PATH_D
].rftx_afe
= ROFDM0_XDTXAFE
;
241 rtlphy
->phyreg_def
[RF90_PATH_A
].rf_rb
= RFPGA0_XA_LSSIREADBACK
;
242 rtlphy
->phyreg_def
[RF90_PATH_B
].rf_rb
= RFPGA0_XB_LSSIREADBACK
;
243 rtlphy
->phyreg_def
[RF90_PATH_C
].rf_rb
= RFPGA0_XC_LSSIREADBACK
;
244 rtlphy
->phyreg_def
[RF90_PATH_D
].rf_rb
= RFPGA0_XD_LSSIREADBACK
;
246 rtlphy
->phyreg_def
[RF90_PATH_A
].rf_rbpi
= TRANSCEIVEA_HSPI_READBACK
;
247 rtlphy
->phyreg_def
[RF90_PATH_B
].rf_rbpi
= TRANSCEIVEB_HSPI_READBACK
;
250 EXPORT_SYMBOL_GPL(rtl8723_phy_init_bb_rf_reg_def
);
252 bool rtl8723_phy_set_sw_chnl_cmdarray(struct swchnlcmd
*cmdtable
,
255 enum swchnlcmd_id cmdid
,
256 u32 para1
, u32 para2
,
259 struct swchnlcmd
*pcmd
;
261 if (cmdtable
== NULL
) {
262 WARN_ONCE(true, "rtl8723-common: cmdtable cannot be NULL.\n");
266 if (cmdtableidx
>= cmdtablesz
)
269 pcmd
= cmdtable
+ cmdtableidx
;
273 pcmd
->msdelay
= msdelay
;
276 EXPORT_SYMBOL_GPL(rtl8723_phy_set_sw_chnl_cmdarray
);
278 void rtl8723_phy_path_a_fill_iqk_matrix(struct ieee80211_hw
*hw
,
284 u32 oldval_0
, x
, tx0_a
, reg
;
287 if (final_candidate
== 0xFF) {
290 oldval_0
= (rtl_get_bbreg(hw
, ROFDM0_XATXIQIMBALANCE
,
291 MASKDWORD
) >> 22) & 0x3FF;
292 x
= result
[final_candidate
][0];
293 if ((x
& 0x00000200) != 0)
295 tx0_a
= (x
* oldval_0
) >> 8;
296 rtl_set_bbreg(hw
, ROFDM0_XATXIQIMBALANCE
, 0x3FF, tx0_a
);
297 rtl_set_bbreg(hw
, ROFDM0_ECCATHRESHOLD
, BIT(31),
298 ((x
* oldval_0
>> 7) & 0x1));
299 y
= result
[final_candidate
][1];
300 if ((y
& 0x00000200) != 0)
302 tx0_c
= (y
* oldval_0
) >> 8;
303 rtl_set_bbreg(hw
, ROFDM0_XCTXAFE
, 0xF0000000,
304 ((tx0_c
& 0x3C0) >> 6));
305 rtl_set_bbreg(hw
, ROFDM0_XATXIQIMBALANCE
, 0x003F0000,
307 rtl_set_bbreg(hw
, ROFDM0_ECCATHRESHOLD
, BIT(29),
308 ((y
* oldval_0
>> 7) & 0x1));
311 reg
= result
[final_candidate
][2];
312 rtl_set_bbreg(hw
, ROFDM0_XARXIQIMBALANCE
, 0x3FF, reg
);
313 reg
= result
[final_candidate
][3] & 0x3F;
314 rtl_set_bbreg(hw
, ROFDM0_XARXIQIMBALANCE
, 0xFC00, reg
);
315 reg
= (result
[final_candidate
][3] >> 6) & 0xF;
316 rtl_set_bbreg(hw
, 0xca0, 0xF0000000, reg
);
319 EXPORT_SYMBOL_GPL(rtl8723_phy_path_a_fill_iqk_matrix
);
321 void rtl8723_save_adda_registers(struct ieee80211_hw
*hw
, u32
*addareg
,
322 u32
*addabackup
, u32 registernum
)
326 for (i
= 0; i
< registernum
; i
++)
327 addabackup
[i
] = rtl_get_bbreg(hw
, addareg
[i
], MASKDWORD
);
329 EXPORT_SYMBOL_GPL(rtl8723_save_adda_registers
);
331 void rtl8723_phy_save_mac_registers(struct ieee80211_hw
*hw
,
332 u32
*macreg
, u32
*macbackup
)
334 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
337 for (i
= 0; i
< (IQK_MAC_REG_NUM
- 1); i
++)
338 macbackup
[i
] = rtl_read_byte(rtlpriv
, macreg
[i
]);
339 macbackup
[i
] = rtl_read_dword(rtlpriv
, macreg
[i
]);
341 EXPORT_SYMBOL_GPL(rtl8723_phy_save_mac_registers
);
343 void rtl8723_phy_reload_adda_registers(struct ieee80211_hw
*hw
,
344 u32
*addareg
, u32
*addabackup
,
349 for (i
= 0; i
< regiesternum
; i
++)
350 rtl_set_bbreg(hw
, addareg
[i
], MASKDWORD
, addabackup
[i
]);
352 EXPORT_SYMBOL_GPL(rtl8723_phy_reload_adda_registers
);
354 void rtl8723_phy_reload_mac_registers(struct ieee80211_hw
*hw
,
355 u32
*macreg
, u32
*macbackup
)
357 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
360 for (i
= 0; i
< (IQK_MAC_REG_NUM
- 1); i
++)
361 rtl_write_byte(rtlpriv
, macreg
[i
], (u8
) macbackup
[i
]);
362 rtl_write_dword(rtlpriv
, macreg
[i
], macbackup
[i
]);
364 EXPORT_SYMBOL_GPL(rtl8723_phy_reload_mac_registers
);
366 void rtl8723_phy_path_adda_on(struct ieee80211_hw
*hw
, u32
*addareg
,
367 bool is_patha_on
, bool is2t
)
369 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
373 if (rtlhal
->hw_type
== HARDWARE_TYPE_RTL8723AE
) {
374 pathon
= is_patha_on
? 0x04db25a4 : 0x0b1b25a4;
377 rtl_set_bbreg(hw
, addareg
[0], MASKDWORD
, 0x0b1b25a0);
379 rtl_set_bbreg(hw
, addareg
[0], MASKDWORD
, pathon
);
384 rtl_set_bbreg(hw
, addareg
[0], MASKDWORD
, pathon
);
387 for (i
= 1; i
< IQK_ADDA_REG_NUM
; i
++)
388 rtl_set_bbreg(hw
, addareg
[i
], MASKDWORD
, pathon
);
390 EXPORT_SYMBOL_GPL(rtl8723_phy_path_adda_on
);
392 void rtl8723_phy_mac_setting_calibration(struct ieee80211_hw
*hw
,
393 u32
*macreg
, u32
*macbackup
)
395 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
398 rtl_write_byte(rtlpriv
, macreg
[i
], 0x3F);
400 for (i
= 1; i
< (IQK_MAC_REG_NUM
- 1); i
++)
401 rtl_write_byte(rtlpriv
, macreg
[i
],
402 (u8
) (macbackup
[i
] & (~BIT(3))));
403 rtl_write_byte(rtlpriv
, macreg
[i
], (u8
) (macbackup
[i
] & (~BIT(5))));
405 EXPORT_SYMBOL_GPL(rtl8723_phy_mac_setting_calibration
);
407 void rtl8723_phy_path_a_standby(struct ieee80211_hw
*hw
)
409 rtl_set_bbreg(hw
, 0xe28, MASKDWORD
, 0x0);
410 rtl_set_bbreg(hw
, 0x840, MASKDWORD
, 0x00010000);
411 rtl_set_bbreg(hw
, 0xe28, MASKDWORD
, 0x80800000);
413 EXPORT_SYMBOL_GPL(rtl8723_phy_path_a_standby
);
415 void rtl8723_phy_pi_mode_switch(struct ieee80211_hw
*hw
, bool pi_mode
)
419 mode
= pi_mode
? 0x01000100 : 0x01000000;
420 rtl_set_bbreg(hw
, 0x820, MASKDWORD
, mode
);
421 rtl_set_bbreg(hw
, 0x828, MASKDWORD
, mode
);
423 EXPORT_SYMBOL_GPL(rtl8723_phy_pi_mode_switch
);