Commit | Line | Data |
---|---|---|
0c817338 LF |
1 | /****************************************************************************** |
2 | * | |
9003a4ab | 3 | * Copyright(c) 2009-2012 Realtek Corporation. |
0c817338 LF |
4 | * |
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. | |
8 | * | |
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 | |
12 | * more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along with | |
15 | * this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | |
17 | * | |
18 | * The full GNU General Public License is included in this distribution in the | |
19 | * file called LICENSE. | |
20 | * | |
21 | * Contact Information: | |
22 | * wlanfae <wlanfae@realtek.com> | |
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | |
24 | * Hsinchu 300, Taiwan. | |
25 | * | |
26 | * Larry Finger <Larry.Finger@lwfinger.net> | |
27 | * | |
28 | *****************************************************************************/ | |
29 | ||
30 | #include "../wifi.h" | |
31 | #include "../pci.h" | |
32 | #include "../ps.h" | |
25b13dbc | 33 | #include "../core.h" |
5c405b5c JL |
34 | #include "reg.h" |
35 | #include "def.h" | |
1472d3a8 | 36 | #include "hw.h" |
5c405b5c | 37 | #include "phy.h" |
9f087a92 | 38 | #include "../rtl8192c/phy_common.h" |
5c405b5c JL |
39 | #include "rf.h" |
40 | #include "dm.h" | |
9f087a92 LF |
41 | #include "../rtl8192c/dm_common.h" |
42 | #include "../rtl8192c/fw_common.h" | |
5c405b5c | 43 | #include "table.h" |
0c817338 | 44 | |
e0b5a507 C |
45 | static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw); |
46 | ||
47 | u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw, | |
0c817338 LF |
48 | enum radio_path rfpath, u32 regaddr, u32 bitmask) |
49 | { | |
50 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
51 | u32 original_value, readback_value, bitshift; | |
52 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | |
0c817338 | 53 | |
f30d7507 JP |
54 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, |
55 | "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n", | |
56 | regaddr, rfpath, bitmask); | |
0c817338 | 57 | |
312d5479 | 58 | spin_lock(&rtlpriv->locks.rf_lock); |
0c817338 LF |
59 | |
60 | if (rtlphy->rf_mode != RF_OP_BY_FW) { | |
61 | original_value = _rtl92c_phy_rf_serial_read(hw, | |
62 | rfpath, regaddr); | |
63 | } else { | |
64 | original_value = _rtl92c_phy_fw_rf_serial_read(hw, | |
65 | rfpath, regaddr); | |
66 | } | |
67 | ||
68 | bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); | |
69 | readback_value = (original_value & bitmask) >> bitshift; | |
70 | ||
312d5479 | 71 | spin_unlock(&rtlpriv->locks.rf_lock); |
0c817338 LF |
72 | |
73 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | |
f30d7507 JP |
74 | "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n", |
75 | regaddr, rfpath, bitmask, original_value); | |
0c817338 LF |
76 | |
77 | return readback_value; | |
78 | } | |
79 | ||
e0b5a507 C |
80 | bool rtl92c_phy_mac_config(struct ieee80211_hw *hw) |
81 | { | |
82 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
83 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | |
84 | bool is92c = IS_92C_SERIAL(rtlhal->version); | |
85 | bool rtstatus = _rtl92c_phy_config_mac_with_headerfile(hw); | |
86 | ||
87 | if (is92c) | |
88 | rtl_write_byte(rtlpriv, 0x14, 0x71); | |
0bd899e7 LF |
89 | else |
90 | rtl_write_byte(rtlpriv, 0x04CA, 0x0A); | |
e0b5a507 C |
91 | return rtstatus; |
92 | } | |
93 | ||
94 | bool rtl92c_phy_bb_config(struct ieee80211_hw *hw) | |
95 | { | |
96 | bool rtstatus = true; | |
97 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
98 | u16 regval; | |
99 | u32 regvaldw; | |
100 | u8 reg_hwparafile = 1; | |
101 | ||
102 | _rtl92c_phy_init_bb_rf_register_definition(hw); | |
103 | regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); | |
104 | rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, | |
105 | regval | BIT(13) | BIT(0) | BIT(1)); | |
106 | rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83); | |
107 | rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb); | |
108 | rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB); | |
109 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, | |
110 | FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE | | |
111 | FEN_BB_GLB_RSTn | FEN_BBRSTB); | |
112 | rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80); | |
113 | regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0); | |
114 | rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23)); | |
115 | if (reg_hwparafile == 1) | |
116 | rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw); | |
117 | return rtstatus; | |
118 | } | |
119 | ||
1472d3a8 | 120 | void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw, |
e0b5a507 C |
121 | enum radio_path rfpath, |
122 | u32 regaddr, u32 bitmask, u32 data) | |
0c817338 LF |
123 | { |
124 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
125 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | |
126 | u32 original_value, bitshift; | |
0c817338 LF |
127 | |
128 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | |
f30d7507 JP |
129 | "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", |
130 | regaddr, bitmask, data, rfpath); | |
0c817338 | 131 | |
312d5479 | 132 | spin_lock(&rtlpriv->locks.rf_lock); |
0c817338 LF |
133 | |
134 | if (rtlphy->rf_mode != RF_OP_BY_FW) { | |
135 | if (bitmask != RFREG_OFFSET_MASK) { | |
136 | original_value = _rtl92c_phy_rf_serial_read(hw, | |
137 | rfpath, | |
138 | regaddr); | |
139 | bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); | |
140 | data = | |
141 | ((original_value & (~bitmask)) | | |
142 | (data << bitshift)); | |
143 | } | |
144 | ||
145 | _rtl92c_phy_rf_serial_write(hw, rfpath, regaddr, data); | |
146 | } else { | |
147 | if (bitmask != RFREG_OFFSET_MASK) { | |
148 | original_value = _rtl92c_phy_fw_rf_serial_read(hw, | |
149 | rfpath, | |
150 | regaddr); | |
151 | bitshift = _rtl92c_phy_calculate_bit_shift(bitmask); | |
152 | data = | |
153 | ((original_value & (~bitmask)) | | |
154 | (data << bitshift)); | |
155 | } | |
156 | _rtl92c_phy_fw_rf_serial_write(hw, rfpath, regaddr, data); | |
157 | } | |
158 | ||
312d5479 | 159 | spin_unlock(&rtlpriv->locks.rf_lock); |
0c817338 | 160 | |
f30d7507 JP |
161 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, |
162 | "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n", | |
163 | regaddr, bitmask, data, rfpath); | |
0c817338 LF |
164 | } |
165 | ||
e0b5a507 | 166 | static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw) |
0c817338 LF |
167 | { |
168 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
169 | u32 i; | |
170 | u32 arraylength; | |
171 | u32 *ptrarray; | |
172 | ||
f30d7507 | 173 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_Array\n"); |
0c817338 LF |
174 | arraylength = MAC_2T_ARRAYLENGTH; |
175 | ptrarray = RTL8192CEMAC_2T_ARRAY; | |
f30d7507 | 176 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:RTL8192CEMAC_2T_ARRAY\n"); |
0c817338 LF |
177 | for (i = 0; i < arraylength; i = i + 2) |
178 | rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]); | |
179 | return true; | |
180 | } | |
181 | ||
1472d3a8 | 182 | bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, |
e0b5a507 | 183 | u8 configtype) |
0c817338 LF |
184 | { |
185 | int i; | |
186 | u32 *phy_regarray_table; | |
187 | u32 *agctab_array_table; | |
188 | u16 phy_reg_arraylen, agctab_arraylen; | |
189 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
190 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | |
191 | ||
192 | if (IS_92C_SERIAL(rtlhal->version)) { | |
193 | agctab_arraylen = AGCTAB_2TARRAYLENGTH; | |
194 | agctab_array_table = RTL8192CEAGCTAB_2TARRAY; | |
195 | phy_reg_arraylen = PHY_REG_2TARRAY_LENGTH; | |
196 | phy_regarray_table = RTL8192CEPHY_REG_2TARRAY; | |
197 | } else { | |
198 | agctab_arraylen = AGCTAB_1TARRAYLENGTH; | |
199 | agctab_array_table = RTL8192CEAGCTAB_1TARRAY; | |
200 | phy_reg_arraylen = PHY_REG_1TARRAY_LENGTH; | |
201 | phy_regarray_table = RTL8192CEPHY_REG_1TARRAY; | |
202 | } | |
203 | if (configtype == BASEBAND_CONFIG_PHY_REG) { | |
204 | for (i = 0; i < phy_reg_arraylen; i = i + 2) { | |
25b13dbc | 205 | rtl_addr_delay(phy_regarray_table[i]); |
0c817338 LF |
206 | rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD, |
207 | phy_regarray_table[i + 1]); | |
208 | udelay(1); | |
209 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | |
f30d7507 JP |
210 | "The phy_regarray_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", |
211 | phy_regarray_table[i], | |
212 | phy_regarray_table[i + 1]); | |
0c817338 | 213 | } |
0c817338 LF |
214 | } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { |
215 | for (i = 0; i < agctab_arraylen; i = i + 2) { | |
216 | rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD, | |
217 | agctab_array_table[i + 1]); | |
218 | udelay(1); | |
219 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | |
f30d7507 JP |
220 | "The agctab_array_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n", |
221 | agctab_array_table[i], | |
222 | agctab_array_table[i + 1]); | |
0c817338 LF |
223 | } |
224 | } | |
225 | return true; | |
226 | } | |
227 | ||
1472d3a8 | 228 | bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, |
e0b5a507 | 229 | u8 configtype) |
0c817338 LF |
230 | { |
231 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
232 | int i; | |
233 | u32 *phy_regarray_table_pg; | |
234 | u16 phy_regarray_pg_len; | |
235 | ||
236 | phy_regarray_pg_len = PHY_REG_ARRAY_PGLENGTH; | |
237 | phy_regarray_table_pg = RTL8192CEPHY_REG_ARRAY_PG; | |
238 | ||
239 | if (configtype == BASEBAND_CONFIG_PHY_REG) { | |
240 | for (i = 0; i < phy_regarray_pg_len; i = i + 3) { | |
25b13dbc | 241 | rtl_addr_delay(phy_regarray_table_pg[i]); |
0c817338 LF |
242 | |
243 | _rtl92c_store_pwrIndex_diffrate_offset(hw, | |
244 | phy_regarray_table_pg[i], | |
245 | phy_regarray_table_pg[i + 1], | |
246 | phy_regarray_table_pg[i + 2]); | |
247 | } | |
248 | } else { | |
249 | ||
250 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, | |
f30d7507 | 251 | "configtype != BaseBand_Config_PHY_REG\n"); |
0c817338 LF |
252 | } |
253 | return true; | |
254 | } | |
255 | ||
e0b5a507 | 256 | bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, |
0c817338 LF |
257 | enum radio_path rfpath) |
258 | { | |
259 | ||
260 | int i; | |
0c817338 LF |
261 | u32 *radioa_array_table; |
262 | u32 *radiob_array_table; | |
263 | u16 radioa_arraylen, radiob_arraylen; | |
264 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
265 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | |
266 | ||
267 | if (IS_92C_SERIAL(rtlhal->version)) { | |
268 | radioa_arraylen = RADIOA_2TARRAYLENGTH; | |
269 | radioa_array_table = RTL8192CERADIOA_2TARRAY; | |
270 | radiob_arraylen = RADIOB_2TARRAYLENGTH; | |
271 | radiob_array_table = RTL8192CE_RADIOB_2TARRAY; | |
272 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | |
f30d7507 | 273 | "Radio_A:RTL8192CERADIOA_2TARRAY\n"); |
0c817338 | 274 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
f30d7507 | 275 | "Radio_B:RTL8192CE_RADIOB_2TARRAY\n"); |
0c817338 LF |
276 | } else { |
277 | radioa_arraylen = RADIOA_1TARRAYLENGTH; | |
278 | radioa_array_table = RTL8192CE_RADIOA_1TARRAY; | |
279 | radiob_arraylen = RADIOB_1TARRAYLENGTH; | |
280 | radiob_array_table = RTL8192CE_RADIOB_1TARRAY; | |
281 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | |
f30d7507 | 282 | "Radio_A:RTL8192CE_RADIOA_1TARRAY\n"); |
0c817338 | 283 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
f30d7507 | 284 | "Radio_B:RTL8192CE_RADIOB_1TARRAY\n"); |
0c817338 | 285 | } |
f30d7507 | 286 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Radio No %x\n", rfpath); |
0c817338 LF |
287 | switch (rfpath) { |
288 | case RF90_PATH_A: | |
289 | for (i = 0; i < radioa_arraylen; i = i + 2) { | |
25b13dbc LF |
290 | rtl_rfreg_delay(hw, rfpath, radioa_array_table[i], |
291 | RFREG_OFFSET_MASK, | |
292 | radioa_array_table[i + 1]); | |
0c817338 | 293 | } |
0c817338 LF |
294 | break; |
295 | case RF90_PATH_B: | |
296 | for (i = 0; i < radiob_arraylen; i = i + 2) { | |
25b13dbc LF |
297 | rtl_rfreg_delay(hw, rfpath, radiob_array_table[i], |
298 | RFREG_OFFSET_MASK, | |
299 | radiob_array_table[i + 1]); | |
0c817338 LF |
300 | } |
301 | break; | |
302 | case RF90_PATH_C: | |
0c817338 LF |
303 | case RF90_PATH_D: |
304 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | |
ad574889 | 305 | "switch case %#x not processed\n", rfpath); |
0c817338 | 306 | break; |
25b13dbc LF |
307 | default: |
308 | break; | |
0c817338 LF |
309 | } |
310 | return true; | |
311 | } | |
312 | ||
099fb8ab LF |
313 | void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw) |
314 | { | |
315 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
316 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | |
317 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | |
318 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | |
319 | u8 reg_bw_opmode; | |
320 | u8 reg_prsr_rsc; | |
321 | ||
f30d7507 JP |
322 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "Switch to %s bandwidth\n", |
323 | rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? | |
324 | "20MHz" : "40MHz"); | |
099fb8ab LF |
325 | |
326 | if (is_hal_stop(rtlhal)) { | |
327 | rtlphy->set_bwmode_inprogress = false; | |
328 | return; | |
329 | } | |
330 | ||
331 | reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE); | |
332 | reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2); | |
333 | ||
334 | switch (rtlphy->current_chan_bw) { | |
335 | case HT_CHANNEL_WIDTH_20: | |
336 | reg_bw_opmode |= BW_OPMODE_20MHZ; | |
337 | rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); | |
338 | break; | |
339 | case HT_CHANNEL_WIDTH_20_40: | |
340 | reg_bw_opmode &= ~BW_OPMODE_20MHZ; | |
341 | rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); | |
342 | reg_prsr_rsc = | |
343 | (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5); | |
344 | rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc); | |
345 | break; | |
346 | default: | |
347 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | |
f30d7507 | 348 | "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); |
099fb8ab LF |
349 | break; |
350 | } | |
351 | ||
352 | switch (rtlphy->current_chan_bw) { | |
353 | case HT_CHANNEL_WIDTH_20: | |
354 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); | |
355 | rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); | |
356 | rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1); | |
357 | break; | |
358 | case HT_CHANNEL_WIDTH_20_40: | |
359 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); | |
360 | rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); | |
361 | ||
362 | rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, | |
363 | (mac->cur_40_prime_sc >> 1)); | |
364 | rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); | |
365 | rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0); | |
366 | ||
367 | rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)), | |
368 | (mac->cur_40_prime_sc == | |
369 | HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1); | |
370 | break; | |
371 | default: | |
372 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | |
f30d7507 | 373 | "unknown bandwidth: %#X\n", rtlphy->current_chan_bw); |
099fb8ab LF |
374 | break; |
375 | } | |
376 | rtl92ce_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); | |
377 | rtlphy->set_bwmode_inprogress = false; | |
f30d7507 | 378 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n"); |
099fb8ab LF |
379 | } |
380 | ||
1472d3a8 | 381 | void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t) |
0c817338 | 382 | { |
4295cd25 LF |
383 | u8 tmpreg; |
384 | u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal; | |
0c817338 | 385 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
0c817338 | 386 | |
4295cd25 | 387 | tmpreg = rtl_read_byte(rtlpriv, 0xd03); |
0c817338 | 388 | |
4295cd25 LF |
389 | if ((tmpreg & 0x70) != 0) |
390 | rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F); | |
391 | else | |
392 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); | |
0c817338 | 393 | |
4295cd25 LF |
394 | if ((tmpreg & 0x70) != 0) { |
395 | rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS); | |
0c817338 LF |
396 | |
397 | if (is2t) | |
398 | rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00, | |
399 | MASK12BITS); | |
400 | ||
401 | rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, | |
402 | (rf_a_mode & 0x8FFFF) | 0x10000); | |
403 | ||
404 | if (is2t) | |
405 | rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, | |
406 | (rf_b_mode & 0x8FFFF) | 0x10000); | |
407 | } | |
408 | lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS); | |
409 | ||
410 | rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000); | |
411 | ||
412 | mdelay(100); | |
413 | ||
414 | if ((tmpreg & 0x70) != 0) { | |
415 | rtl_write_byte(rtlpriv, 0xd03, tmpreg); | |
416 | rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode); | |
417 | ||
418 | if (is2t) | |
419 | rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS, | |
420 | rf_b_mode); | |
421 | } else { | |
422 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); | |
423 | } | |
424 | } | |
425 | ||
e0b5a507 C |
426 | static void _rtl92ce_phy_set_rf_sleep(struct ieee80211_hw *hw) |
427 | { | |
428 | u32 u4b_tmp; | |
429 | u8 delay = 5; | |
430 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
431 | ||
432 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF); | |
433 | rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); | |
434 | rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); | |
435 | u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); | |
436 | while (u4b_tmp != 0 && delay > 0) { | |
437 | rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0); | |
438 | rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); | |
439 | rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); | |
440 | u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK); | |
441 | delay--; | |
442 | } | |
443 | if (delay == 0) { | |
444 | rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00); | |
445 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); | |
446 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); | |
447 | rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00); | |
448 | RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, | |
f30d7507 | 449 | "Switch RF timeout !!!\n"); |
e0b5a507 C |
450 | return; |
451 | } | |
452 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); | |
453 | rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22); | |
454 | } | |
455 | ||
0c817338 LF |
456 | static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw, |
457 | enum rf_pwrstate rfpwr_state) | |
458 | { | |
459 | struct rtl_priv *rtlpriv = rtl_priv(hw); | |
460 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | |
461 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | |
462 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | |
463 | bool bresult = true; | |
464 | u8 i, queue_id; | |
465 | struct rtl8192_tx_ring *ring = NULL; | |
466 | ||
0c817338 LF |
467 | switch (rfpwr_state) { |
468 | case ERFON:{ | |
469 | if ((ppsc->rfpwr_state == ERFOFF) && | |
470 | RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { | |
471 | bool rtstatus; | |
472 | u32 InitializeCount = 0; | |
473 | do { | |
474 | InitializeCount++; | |
475 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | |
f30d7507 | 476 | "IPS Set eRf nic enable\n"); |
0c817338 | 477 | rtstatus = rtl_ps_enable_nic(hw); |
23677ce3 | 478 | } while (!rtstatus && (InitializeCount < 10)); |
0c817338 LF |
479 | RT_CLEAR_PS_LEVEL(ppsc, |
480 | RT_RF_OFF_LEVL_HALT_NIC); | |
481 | } else { | |
482 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | |
f30d7507 JP |
483 | "Set ERFON sleeped:%d ms\n", |
484 | jiffies_to_msecs(jiffies - | |
485 | ppsc-> | |
486 | last_sleep_jiffies)); | |
0c817338 LF |
487 | ppsc->last_awake_jiffies = jiffies; |
488 | rtl92ce_phy_set_rf_on(hw); | |
489 | } | |
490 | if (mac->link_state == MAC80211_LINKED) { | |
491 | rtlpriv->cfg->ops->led_control(hw, | |
492 | LED_CTL_LINK); | |
493 | } else { | |
494 | rtlpriv->cfg->ops->led_control(hw, | |
495 | LED_CTL_NO_LINK); | |
496 | } | |
497 | break; | |
498 | } | |
499 | case ERFOFF:{ | |
0c817338 LF |
500 | if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { |
501 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | |
f30d7507 | 502 | "IPS Set eRf nic disable\n"); |
0c817338 LF |
503 | rtl_ps_disable_nic(hw); |
504 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); | |
505 | } else { | |
506 | if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) { | |
507 | rtlpriv->cfg->ops->led_control(hw, | |
508 | LED_CTL_NO_LINK); | |
509 | } else { | |
510 | rtlpriv->cfg->ops->led_control(hw, | |
511 | LED_CTL_POWER_OFF); | |
512 | } | |
513 | } | |
514 | break; | |
515 | } | |
516 | case ERFSLEEP:{ | |
517 | if (ppsc->rfpwr_state == ERFOFF) | |
99057920 | 518 | break; |
0c817338 LF |
519 | for (queue_id = 0, i = 0; |
520 | queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { | |
521 | ring = &pcipriv->dev.tx_ring[queue_id]; | |
99057920 LF |
522 | if (queue_id == BEACON_QUEUE || |
523 | skb_queue_len(&ring->queue) == 0) { | |
0c817338 LF |
524 | queue_id++; |
525 | continue; | |
526 | } else { | |
527 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | |
f30d7507 JP |
528 | "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n", |
529 | i + 1, queue_id, | |
530 | skb_queue_len(&ring->queue)); | |
e0b5a507 | 531 | |
0c817338 LF |
532 | udelay(10); |
533 | i++; | |
534 | } | |
535 | if (i >= MAX_DOZE_WAITING_TIMES_9x) { | |
536 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | |
f30d7507 JP |
537 | "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n", |
538 | MAX_DOZE_WAITING_TIMES_9x, | |
539 | queue_id, | |
540 | skb_queue_len(&ring->queue)); | |
0c817338 LF |
541 | break; |
542 | } | |
543 | } | |
544 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | |
f30d7507 JP |
545 | "Set ERFSLEEP awaked:%d ms\n", |
546 | jiffies_to_msecs(jiffies - | |
547 | ppsc->last_awake_jiffies)); | |
0c817338 | 548 | ppsc->last_sleep_jiffies = jiffies; |
e0b5a507 | 549 | _rtl92ce_phy_set_rf_sleep(hw); |
0c817338 LF |
550 | break; |
551 | } | |
552 | default: | |
553 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | |
ad574889 | 554 | "switch case %#x not processed\n", rfpwr_state); |
0c817338 LF |
555 | bresult = false; |
556 | break; | |
557 | } | |
558 | if (bresult) | |
559 | ppsc->rfpwr_state = rfpwr_state; | |
0c817338 LF |
560 | return bresult; |
561 | } | |
562 | ||
e0b5a507 | 563 | bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw, |
0c817338 LF |
564 | enum rf_pwrstate rfpwr_state) |
565 | { | |
566 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | |
e0b5a507 | 567 | |
0c817338 LF |
568 | bool bresult = false; |
569 | ||
570 | if (rfpwr_state == ppsc->rfpwr_state) | |
571 | return bresult; | |
572 | bresult = _rtl92ce_phy_set_rf_power_state(hw, rfpwr_state); | |
573 | return bresult; | |
574 | } |