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