1 /******************************************************************************
3 * Copyright(c) 2009-2014 Realtek Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * The full GNU General Public License is included in this distribution in the
15 * file called LICENSE.
17 * Contact Information:
18 * wlanfae <wlanfae@realtek.com>
19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20 * Hsinchu 300, Taiwan.
22 * Larry Finger <Larry.Finger@lwfinger.net>
24 *****************************************************************************/
27 #include "phy_common.h"
28 #include "../rtl8723ae/reg.h"
29 #include <linux/module.h>
31 /* These routines are common to RTL8723AE and RTL8723bE */
33 u32
rtl8723_phy_query_bb_reg(struct ieee80211_hw
*hw
,
34 u32 regaddr
, u32 bitmask
)
36 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
37 u32 returnvalue
, originalvalue
, bitshift
;
39 RT_TRACE(rtlpriv
, COMP_RF
, DBG_TRACE
,
40 "regaddr(%#x), bitmask(%#x)\n", regaddr
, bitmask
);
41 originalvalue
= rtl_read_dword(rtlpriv
, regaddr
);
42 bitshift
= rtl8723_phy_calculate_bit_shift(bitmask
);
43 returnvalue
= (originalvalue
& bitmask
) >> bitshift
;
45 RT_TRACE(rtlpriv
, COMP_RF
, DBG_TRACE
,
46 "BBR MASK=0x%x Addr[0x%x]=0x%x\n", bitmask
,
47 regaddr
, originalvalue
);
50 EXPORT_SYMBOL_GPL(rtl8723_phy_query_bb_reg
);
52 void rtl8723_phy_set_bb_reg(struct ieee80211_hw
*hw
, u32 regaddr
,
53 u32 bitmask
, u32 data
)
55 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
56 u32 originalvalue
, bitshift
;
58 RT_TRACE(rtlpriv
, COMP_RF
, DBG_TRACE
,
59 "regaddr(%#x), bitmask(%#x), data(%#x)\n", regaddr
, bitmask
,
62 if (bitmask
!= MASKDWORD
) {
63 originalvalue
= rtl_read_dword(rtlpriv
, regaddr
);
64 bitshift
= rtl8723_phy_calculate_bit_shift(bitmask
);
65 data
= ((originalvalue
& (~bitmask
)) | (data
<< bitshift
));
68 rtl_write_dword(rtlpriv
, regaddr
, data
);
70 RT_TRACE(rtlpriv
, COMP_RF
, DBG_TRACE
,
71 "regaddr(%#x), bitmask(%#x), data(%#x)\n",
72 regaddr
, bitmask
, data
);
74 EXPORT_SYMBOL_GPL(rtl8723_phy_set_bb_reg
);
76 u32
rtl8723_phy_calculate_bit_shift(u32 bitmask
)
80 for (i
= 0; i
<= 31; i
++) {
81 if (((bitmask
>> i
) & 0x1) == 1)
86 EXPORT_SYMBOL_GPL(rtl8723_phy_calculate_bit_shift
);
88 u32
rtl8723_phy_rf_serial_read(struct ieee80211_hw
*hw
,
89 enum radio_path rfpath
, u32 offset
)
91 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
92 struct rtl_phy
*rtlphy
= &(rtlpriv
->phy
);
93 struct bb_reg_def
*pphyreg
= &rtlphy
->phyreg_def
[rfpath
];
95 u32 tmplong
, tmplong2
;
101 if (RT_CANNOT_IO(hw
)) {
102 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_EMERG
, "return all one\n");
105 tmplong
= rtl_get_bbreg(hw
, RFPGA0_XA_HSSIPARAMETER2
, MASKDWORD
);
106 if (rfpath
== RF90_PATH_A
)
109 tmplong2
= rtl_get_bbreg(hw
, pphyreg
->rfhssi_para2
, MASKDWORD
);
110 tmplong2
= (tmplong2
& (~BLSSIREADADDRESS
)) |
111 (newoffset
<< 23) | BLSSIREADEDGE
;
112 rtl_set_bbreg(hw
, RFPGA0_XA_HSSIPARAMETER2
, MASKDWORD
,
113 tmplong
& (~BLSSIREADEDGE
));
115 rtl_set_bbreg(hw
, pphyreg
->rfhssi_para2
, MASKDWORD
, tmplong2
);
117 rtl_set_bbreg(hw
, RFPGA0_XA_HSSIPARAMETER2
, MASKDWORD
,
118 tmplong
| BLSSIREADEDGE
);
120 if (rfpath
== RF90_PATH_A
)
121 rfpi_enable
= (u8
) rtl_get_bbreg(hw
, RFPGA0_XA_HSSIPARAMETER1
,
123 else if (rfpath
== RF90_PATH_B
)
124 rfpi_enable
= (u8
) rtl_get_bbreg(hw
, RFPGA0_XB_HSSIPARAMETER1
,
127 retvalue
= rtl_get_bbreg(hw
, pphyreg
->rf_rbpi
,
130 retvalue
= rtl_get_bbreg(hw
, pphyreg
->rf_rb
,
132 RT_TRACE(rtlpriv
, COMP_RF
, DBG_TRACE
,
133 "RFR-%d Addr[0x%x]=0x%x\n",
134 rfpath
, pphyreg
->rf_rb
, retvalue
);
137 EXPORT_SYMBOL_GPL(rtl8723_phy_rf_serial_read
);
139 void rtl8723_phy_rf_serial_write(struct ieee80211_hw
*hw
,
140 enum radio_path rfpath
,
141 u32 offset
, u32 data
)
145 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
146 struct rtl_phy
*rtlphy
= &(rtlpriv
->phy
);
147 struct bb_reg_def
*pphyreg
= &rtlphy
->phyreg_def
[rfpath
];
149 if (RT_CANNOT_IO(hw
)) {
150 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_EMERG
, "stop\n");
155 data_and_addr
= ((newoffset
<< 20) | (data
& 0x000fffff)) & 0x0fffffff;
156 rtl_set_bbreg(hw
, pphyreg
->rf3wire_offset
, MASKDWORD
, data_and_addr
);
157 RT_TRACE(rtlpriv
, COMP_RF
, DBG_TRACE
,
158 "RFW-%d Addr[0x%x]=0x%x\n",
159 rfpath
, pphyreg
->rf3wire_offset
,
162 EXPORT_SYMBOL_GPL(rtl8723_phy_rf_serial_write
);
164 long rtl8723_phy_txpwr_idx_to_dbm(struct ieee80211_hw
*hw
,
165 enum wireless_mode wirelessmode
,
171 switch (wirelessmode
) {
172 case WIRELESS_MODE_B
:
175 case WIRELESS_MODE_G
:
176 case WIRELESS_MODE_N_24G
:
183 pwrout_dbm
= txpwridx
/ 2 + offset
;
186 EXPORT_SYMBOL_GPL(rtl8723_phy_txpwr_idx_to_dbm
);
188 void rtl8723_phy_init_bb_rf_reg_def(struct ieee80211_hw
*hw
)
190 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
191 struct rtl_phy
*rtlphy
= &(rtlpriv
->phy
);
193 rtlphy
->phyreg_def
[RF90_PATH_A
].rfintfs
= RFPGA0_XAB_RFINTERFACESW
;
194 rtlphy
->phyreg_def
[RF90_PATH_B
].rfintfs
= RFPGA0_XAB_RFINTERFACESW
;
195 rtlphy
->phyreg_def
[RF90_PATH_C
].rfintfs
= RFPGA0_XCD_RFINTERFACESW
;
196 rtlphy
->phyreg_def
[RF90_PATH_D
].rfintfs
= RFPGA0_XCD_RFINTERFACESW
;
198 rtlphy
->phyreg_def
[RF90_PATH_A
].rfintfi
= RFPGA0_XAB_RFINTERFACERB
;
199 rtlphy
->phyreg_def
[RF90_PATH_B
].rfintfi
= RFPGA0_XAB_RFINTERFACERB
;
200 rtlphy
->phyreg_def
[RF90_PATH_C
].rfintfi
= RFPGA0_XCD_RFINTERFACERB
;
201 rtlphy
->phyreg_def
[RF90_PATH_D
].rfintfi
= RFPGA0_XCD_RFINTERFACERB
;
203 rtlphy
->phyreg_def
[RF90_PATH_A
].rfintfo
= RFPGA0_XA_RFINTERFACEOE
;
204 rtlphy
->phyreg_def
[RF90_PATH_B
].rfintfo
= RFPGA0_XB_RFINTERFACEOE
;
206 rtlphy
->phyreg_def
[RF90_PATH_A
].rfintfe
= RFPGA0_XA_RFINTERFACEOE
;
207 rtlphy
->phyreg_def
[RF90_PATH_B
].rfintfe
= RFPGA0_XB_RFINTERFACEOE
;
209 rtlphy
->phyreg_def
[RF90_PATH_A
].rf3wire_offset
=
210 RFPGA0_XA_LSSIPARAMETER
;
211 rtlphy
->phyreg_def
[RF90_PATH_B
].rf3wire_offset
=
212 RFPGA0_XB_LSSIPARAMETER
;
214 rtlphy
->phyreg_def
[RF90_PATH_A
].rflssi_select
= RFPGA0_XAB_RFPARAMETER
;
215 rtlphy
->phyreg_def
[RF90_PATH_B
].rflssi_select
= RFPGA0_XAB_RFPARAMETER
;
216 rtlphy
->phyreg_def
[RF90_PATH_C
].rflssi_select
= RFPGA0_XCD_RFPARAMETER
;
217 rtlphy
->phyreg_def
[RF90_PATH_D
].rflssi_select
= RFPGA0_XCD_RFPARAMETER
;
219 rtlphy
->phyreg_def
[RF90_PATH_A
].rftxgain_stage
= RFPGA0_TXGAINSTAGE
;
220 rtlphy
->phyreg_def
[RF90_PATH_B
].rftxgain_stage
= RFPGA0_TXGAINSTAGE
;
221 rtlphy
->phyreg_def
[RF90_PATH_C
].rftxgain_stage
= RFPGA0_TXGAINSTAGE
;
222 rtlphy
->phyreg_def
[RF90_PATH_D
].rftxgain_stage
= RFPGA0_TXGAINSTAGE
;
224 rtlphy
->phyreg_def
[RF90_PATH_A
].rfhssi_para1
= RFPGA0_XA_HSSIPARAMETER1
;
225 rtlphy
->phyreg_def
[RF90_PATH_B
].rfhssi_para1
= RFPGA0_XB_HSSIPARAMETER1
;
227 rtlphy
->phyreg_def
[RF90_PATH_A
].rfhssi_para2
= RFPGA0_XA_HSSIPARAMETER2
;
228 rtlphy
->phyreg_def
[RF90_PATH_B
].rfhssi_para2
= RFPGA0_XB_HSSIPARAMETER2
;
230 rtlphy
->phyreg_def
[RF90_PATH_A
].rfsw_ctrl
= RFPGA0_XAB_SWITCHCONTROL
;
231 rtlphy
->phyreg_def
[RF90_PATH_B
].rfsw_ctrl
= RFPGA0_XAB_SWITCHCONTROL
;
232 rtlphy
->phyreg_def
[RF90_PATH_C
].rfsw_ctrl
= RFPGA0_XCD_SWITCHCONTROL
;
233 rtlphy
->phyreg_def
[RF90_PATH_D
].rfsw_ctrl
= RFPGA0_XCD_SWITCHCONTROL
;
235 rtlphy
->phyreg_def
[RF90_PATH_A
].rfagc_control1
= ROFDM0_XAAGCCORE1
;
236 rtlphy
->phyreg_def
[RF90_PATH_B
].rfagc_control1
= ROFDM0_XBAGCCORE1
;
237 rtlphy
->phyreg_def
[RF90_PATH_C
].rfagc_control1
= ROFDM0_XCAGCCORE1
;
238 rtlphy
->phyreg_def
[RF90_PATH_D
].rfagc_control1
= ROFDM0_XDAGCCORE1
;
240 rtlphy
->phyreg_def
[RF90_PATH_A
].rfagc_control2
= ROFDM0_XAAGCCORE2
;
241 rtlphy
->phyreg_def
[RF90_PATH_B
].rfagc_control2
= ROFDM0_XBAGCCORE2
;
242 rtlphy
->phyreg_def
[RF90_PATH_C
].rfagc_control2
= ROFDM0_XCAGCCORE2
;
243 rtlphy
->phyreg_def
[RF90_PATH_D
].rfagc_control2
= ROFDM0_XDAGCCORE2
;
245 rtlphy
->phyreg_def
[RF90_PATH_A
].rfrxiq_imbal
= ROFDM0_XARXIQIMBALANCE
;
246 rtlphy
->phyreg_def
[RF90_PATH_B
].rfrxiq_imbal
= ROFDM0_XBRXIQIMBALANCE
;
247 rtlphy
->phyreg_def
[RF90_PATH_C
].rfrxiq_imbal
= ROFDM0_XCRXIQIMBANLANCE
;
248 rtlphy
->phyreg_def
[RF90_PATH_D
].rfrxiq_imbal
= ROFDM0_XDRXIQIMBALANCE
;
250 rtlphy
->phyreg_def
[RF90_PATH_A
].rfrx_afe
= ROFDM0_XARXAFE
;
251 rtlphy
->phyreg_def
[RF90_PATH_B
].rfrx_afe
= ROFDM0_XBRXAFE
;
252 rtlphy
->phyreg_def
[RF90_PATH_C
].rfrx_afe
= ROFDM0_XCRXAFE
;
253 rtlphy
->phyreg_def
[RF90_PATH_D
].rfrx_afe
= ROFDM0_XDRXAFE
;
255 rtlphy
->phyreg_def
[RF90_PATH_A
].rftxiq_imbal
= ROFDM0_XATXIQIMBALANCE
;
256 rtlphy
->phyreg_def
[RF90_PATH_B
].rftxiq_imbal
= ROFDM0_XBTXIQIMBALANCE
;
257 rtlphy
->phyreg_def
[RF90_PATH_C
].rftxiq_imbal
= ROFDM0_XCTXIQIMBALANCE
;
258 rtlphy
->phyreg_def
[RF90_PATH_D
].rftxiq_imbal
= ROFDM0_XDTXIQIMBALANCE
;
260 rtlphy
->phyreg_def
[RF90_PATH_A
].rftx_afe
= ROFDM0_XATXAFE
;
261 rtlphy
->phyreg_def
[RF90_PATH_B
].rftx_afe
= ROFDM0_XBTXAFE
;
262 rtlphy
->phyreg_def
[RF90_PATH_C
].rftx_afe
= ROFDM0_XCTXAFE
;
263 rtlphy
->phyreg_def
[RF90_PATH_D
].rftx_afe
= ROFDM0_XDTXAFE
;
265 rtlphy
->phyreg_def
[RF90_PATH_A
].rf_rb
= RFPGA0_XA_LSSIREADBACK
;
266 rtlphy
->phyreg_def
[RF90_PATH_B
].rf_rb
= RFPGA0_XB_LSSIREADBACK
;
267 rtlphy
->phyreg_def
[RF90_PATH_C
].rf_rb
= RFPGA0_XC_LSSIREADBACK
;
268 rtlphy
->phyreg_def
[RF90_PATH_D
].rf_rb
= RFPGA0_XD_LSSIREADBACK
;
270 rtlphy
->phyreg_def
[RF90_PATH_A
].rf_rbpi
= TRANSCEIVEA_HSPI_READBACK
;
271 rtlphy
->phyreg_def
[RF90_PATH_B
].rf_rbpi
= TRANSCEIVEB_HSPI_READBACK
;
274 EXPORT_SYMBOL_GPL(rtl8723_phy_init_bb_rf_reg_def
);
276 bool rtl8723_phy_set_sw_chnl_cmdarray(struct swchnlcmd
*cmdtable
,
279 enum swchnlcmd_id cmdid
,
280 u32 para1
, u32 para2
,
283 struct swchnlcmd
*pcmd
;
285 if (cmdtable
== NULL
) {
286 RT_ASSERT(false, "cmdtable cannot be NULL.\n");
290 if (cmdtableidx
>= cmdtablesz
)
293 pcmd
= cmdtable
+ cmdtableidx
;
297 pcmd
->msdelay
= msdelay
;
300 EXPORT_SYMBOL_GPL(rtl8723_phy_set_sw_chnl_cmdarray
);
302 void rtl8723_phy_path_a_fill_iqk_matrix(struct ieee80211_hw
*hw
,
308 u32 oldval_0
, x
, tx0_a
, reg
;
311 if (final_candidate
== 0xFF) {
314 oldval_0
= (rtl_get_bbreg(hw
, ROFDM0_XATXIQIMBALANCE
,
315 MASKDWORD
) >> 22) & 0x3FF;
316 x
= result
[final_candidate
][0];
317 if ((x
& 0x00000200) != 0)
319 tx0_a
= (x
* oldval_0
) >> 8;
320 rtl_set_bbreg(hw
, ROFDM0_XATXIQIMBALANCE
, 0x3FF, tx0_a
);
321 rtl_set_bbreg(hw
, ROFDM0_ECCATHRESHOLD
, BIT(31),
322 ((x
* oldval_0
>> 7) & 0x1));
323 y
= result
[final_candidate
][1];
324 if ((y
& 0x00000200) != 0)
326 tx0_c
= (y
* oldval_0
) >> 8;
327 rtl_set_bbreg(hw
, ROFDM0_XCTXAFE
, 0xF0000000,
328 ((tx0_c
& 0x3C0) >> 6));
329 rtl_set_bbreg(hw
, ROFDM0_XATXIQIMBALANCE
, 0x003F0000,
331 rtl_set_bbreg(hw
, ROFDM0_ECCATHRESHOLD
, BIT(29),
332 ((y
* oldval_0
>> 7) & 0x1));
335 reg
= result
[final_candidate
][2];
336 rtl_set_bbreg(hw
, ROFDM0_XARXIQIMBALANCE
, 0x3FF, reg
);
337 reg
= result
[final_candidate
][3] & 0x3F;
338 rtl_set_bbreg(hw
, ROFDM0_XARXIQIMBALANCE
, 0xFC00, reg
);
339 reg
= (result
[final_candidate
][3] >> 6) & 0xF;
340 rtl_set_bbreg(hw
, 0xca0, 0xF0000000, reg
);
343 EXPORT_SYMBOL_GPL(rtl8723_phy_path_a_fill_iqk_matrix
);
345 void rtl8723_save_adda_registers(struct ieee80211_hw
*hw
, u32
*addareg
,
346 u32
*addabackup
, u32 registernum
)
350 for (i
= 0; i
< registernum
; i
++)
351 addabackup
[i
] = rtl_get_bbreg(hw
, addareg
[i
], MASKDWORD
);
353 EXPORT_SYMBOL_GPL(rtl8723_save_adda_registers
);
355 void rtl8723_phy_save_mac_registers(struct ieee80211_hw
*hw
,
356 u32
*macreg
, u32
*macbackup
)
358 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
361 for (i
= 0; i
< (IQK_MAC_REG_NUM
- 1); i
++)
362 macbackup
[i
] = rtl_read_byte(rtlpriv
, macreg
[i
]);
363 macbackup
[i
] = rtl_read_dword(rtlpriv
, macreg
[i
]);
365 EXPORT_SYMBOL_GPL(rtl8723_phy_save_mac_registers
);
367 void rtl8723_phy_reload_adda_registers(struct ieee80211_hw
*hw
,
368 u32
*addareg
, u32
*addabackup
,
373 for (i
= 0; i
< regiesternum
; i
++)
374 rtl_set_bbreg(hw
, addareg
[i
], MASKDWORD
, addabackup
[i
]);
376 EXPORT_SYMBOL_GPL(rtl8723_phy_reload_adda_registers
);
378 void rtl8723_phy_reload_mac_registers(struct ieee80211_hw
*hw
,
379 u32
*macreg
, u32
*macbackup
)
381 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
384 for (i
= 0; i
< (IQK_MAC_REG_NUM
- 1); i
++)
385 rtl_write_byte(rtlpriv
, macreg
[i
], (u8
) macbackup
[i
]);
386 rtl_write_dword(rtlpriv
, macreg
[i
], macbackup
[i
]);
388 EXPORT_SYMBOL_GPL(rtl8723_phy_reload_mac_registers
);
390 void rtl8723_phy_path_adda_on(struct ieee80211_hw
*hw
, u32
*addareg
,
391 bool is_patha_on
, bool is2t
)
393 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
397 if (rtlhal
->hw_type
== HARDWARE_TYPE_RTL8723AE
) {
398 pathon
= is_patha_on
? 0x04db25a4 : 0x0b1b25a4;
401 rtl_set_bbreg(hw
, addareg
[0], MASKDWORD
, 0x0b1b25a0);
403 rtl_set_bbreg(hw
, addareg
[0], MASKDWORD
, pathon
);
408 rtl_set_bbreg(hw
, addareg
[0], MASKDWORD
, pathon
);
411 for (i
= 1; i
< IQK_ADDA_REG_NUM
; i
++)
412 rtl_set_bbreg(hw
, addareg
[i
], MASKDWORD
, pathon
);
414 EXPORT_SYMBOL_GPL(rtl8723_phy_path_adda_on
);
416 void rtl8723_phy_mac_setting_calibration(struct ieee80211_hw
*hw
,
417 u32
*macreg
, u32
*macbackup
)
419 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
422 rtl_write_byte(rtlpriv
, macreg
[i
], 0x3F);
424 for (i
= 1; i
< (IQK_MAC_REG_NUM
- 1); i
++)
425 rtl_write_byte(rtlpriv
, macreg
[i
],
426 (u8
) (macbackup
[i
] & (~BIT(3))));
427 rtl_write_byte(rtlpriv
, macreg
[i
], (u8
) (macbackup
[i
] & (~BIT(5))));
429 EXPORT_SYMBOL_GPL(rtl8723_phy_mac_setting_calibration
);
431 void rtl8723_phy_path_a_standby(struct ieee80211_hw
*hw
)
433 rtl_set_bbreg(hw
, 0xe28, MASKDWORD
, 0x0);
434 rtl_set_bbreg(hw
, 0x840, MASKDWORD
, 0x00010000);
435 rtl_set_bbreg(hw
, 0xe28, MASKDWORD
, 0x80800000);
437 EXPORT_SYMBOL_GPL(rtl8723_phy_path_a_standby
);
439 void rtl8723_phy_pi_mode_switch(struct ieee80211_hw
*hw
, bool pi_mode
)
443 mode
= pi_mode
? 0x01000100 : 0x01000000;
444 rtl_set_bbreg(hw
, 0x820, MASKDWORD
, mode
);
445 rtl_set_bbreg(hw
, 0x828, MASKDWORD
, mode
);
447 EXPORT_SYMBOL_GPL(rtl8723_phy_pi_mode_switch
);