1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright(c) 2009-2012 Realtek Corporation.*/ |
3 | |
4 | #include "../wifi.h" |
5 | #include "../efuse.h" |
6 | #include "../base.h" |
7 | #include "../cam.h" |
8 | #include "../ps.h" |
9 | #include "../usb.h" |
10 | #include "reg.h" |
11 | #include "def.h" |
12 | #include "phy.h" |
13 | #include "../rtl8192c/phy_common.h" |
14 | #include "mac.h" |
15 | #include "dm.h" |
16 | #include "../rtl8192c/dm_common.h" |
17 | #include "../rtl8192c/fw_common.h" |
18 | #include "hw.h" |
19 | #include "../rtl8192ce/hw.h" |
20 | #include "trx.h" |
21 | #include "led.h" |
22 | #include "table.h" |
23 | |
24 | static void _rtl92cu_phy_param_tab_init(struct ieee80211_hw *hw) |
25 | { |
26 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
27 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
28 | struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv); |
29 | |
30 | rtlphy->hwparam_tables[MAC_REG].length = RTL8192CUMAC_2T_ARRAYLENGTH; |
31 | rtlphy->hwparam_tables[MAC_REG].pdata = RTL8192CUMAC_2T_ARRAY; |
32 | if (IS_HIGHT_PA(rtlefuse->board_type)) { |
33 | rtlphy->hwparam_tables[PHY_REG_PG].length = |
34 | RTL8192CUPHY_REG_ARRAY_PG_HPLENGTH; |
35 | rtlphy->hwparam_tables[PHY_REG_PG].pdata = |
36 | RTL8192CUPHY_REG_ARRAY_PG_HP; |
37 | } else { |
38 | rtlphy->hwparam_tables[PHY_REG_PG].length = |
39 | RTL8192CUPHY_REG_ARRAY_PGLENGTH; |
40 | rtlphy->hwparam_tables[PHY_REG_PG].pdata = |
41 | RTL8192CUPHY_REG_ARRAY_PG; |
42 | } |
43 | /* 2T */ |
44 | rtlphy->hwparam_tables[PHY_REG_2T].length = |
45 | RTL8192CUPHY_REG_2TARRAY_LENGTH; |
46 | rtlphy->hwparam_tables[PHY_REG_2T].pdata = |
47 | RTL8192CUPHY_REG_2TARRAY; |
48 | rtlphy->hwparam_tables[RADIOA_2T].length = |
49 | RTL8192CURADIOA_2TARRAYLENGTH; |
50 | rtlphy->hwparam_tables[RADIOA_2T].pdata = |
51 | RTL8192CURADIOA_2TARRAY; |
52 | rtlphy->hwparam_tables[RADIOB_2T].length = |
53 | RTL8192CURADIOB_2TARRAYLENGTH; |
54 | rtlphy->hwparam_tables[RADIOB_2T].pdata = |
55 | RTL8192CU_RADIOB_2TARRAY; |
56 | rtlphy->hwparam_tables[AGCTAB_2T].length = |
57 | RTL8192CUAGCTAB_2TARRAYLENGTH; |
58 | rtlphy->hwparam_tables[AGCTAB_2T].pdata = |
59 | RTL8192CUAGCTAB_2TARRAY; |
60 | /* 1T */ |
61 | if (IS_HIGHT_PA(rtlefuse->board_type)) { |
62 | rtlphy->hwparam_tables[PHY_REG_1T].length = |
63 | RTL8192CUPHY_REG_1T_HPARRAYLENGTH; |
64 | rtlphy->hwparam_tables[PHY_REG_1T].pdata = |
65 | RTL8192CUPHY_REG_1T_HPARRAY; |
66 | rtlphy->hwparam_tables[RADIOA_1T].length = |
67 | RTL8192CURADIOA_1T_HPARRAYLENGTH; |
68 | rtlphy->hwparam_tables[RADIOA_1T].pdata = |
69 | RTL8192CURADIOA_1T_HPARRAY; |
70 | rtlphy->hwparam_tables[RADIOB_1T].length = |
71 | RTL8192CURADIOB_1TARRAYLENGTH; |
72 | rtlphy->hwparam_tables[RADIOB_1T].pdata = |
73 | RTL8192CU_RADIOB_1TARRAY; |
74 | rtlphy->hwparam_tables[AGCTAB_1T].length = |
75 | RTL8192CUAGCTAB_1T_HPARRAYLENGTH; |
76 | rtlphy->hwparam_tables[AGCTAB_1T].pdata = |
77 | RTL8192CUAGCTAB_1T_HPARRAY; |
78 | } else { |
79 | rtlphy->hwparam_tables[PHY_REG_1T].length = |
80 | RTL8192CUPHY_REG_1TARRAY_LENGTH; |
81 | rtlphy->hwparam_tables[PHY_REG_1T].pdata = |
82 | RTL8192CUPHY_REG_1TARRAY; |
83 | rtlphy->hwparam_tables[RADIOA_1T].length = |
84 | RTL8192CURADIOA_1TARRAYLENGTH; |
85 | rtlphy->hwparam_tables[RADIOA_1T].pdata = |
86 | RTL8192CU_RADIOA_1TARRAY; |
87 | rtlphy->hwparam_tables[RADIOB_1T].length = |
88 | RTL8192CURADIOB_1TARRAYLENGTH; |
89 | rtlphy->hwparam_tables[RADIOB_1T].pdata = |
90 | RTL8192CU_RADIOB_1TARRAY; |
91 | rtlphy->hwparam_tables[AGCTAB_1T].length = |
92 | RTL8192CUAGCTAB_1TARRAYLENGTH; |
93 | rtlphy->hwparam_tables[AGCTAB_1T].pdata = |
94 | RTL8192CUAGCTAB_1TARRAY; |
95 | } |
96 | } |
97 | |
98 | static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, |
99 | bool autoload_fail, |
100 | u8 *hwinfo) |
101 | { |
102 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
103 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
104 | u8 rf_path, index, tempval; |
105 | u16 i; |
106 | |
107 | for (rf_path = 0; rf_path < 2; rf_path++) { |
108 | for (i = 0; i < 3; i++) { |
109 | if (!autoload_fail) { |
110 | rtlefuse-> |
111 | eeprom_chnlarea_txpwr_cck[rf_path][i] = |
112 | hwinfo[EEPROM_TXPOWERCCK + rf_path * 3 + i]; |
113 | rtlefuse-> |
114 | eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = |
115 | hwinfo[EEPROM_TXPOWERHT40_1S + rf_path * 3 + |
116 | i]; |
117 | } else { |
118 | rtlefuse-> |
119 | eeprom_chnlarea_txpwr_cck[rf_path][i] = |
120 | EEPROM_DEFAULT_TXPOWERLEVEL; |
121 | rtlefuse-> |
122 | eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = |
123 | EEPROM_DEFAULT_TXPOWERLEVEL; |
124 | } |
125 | } |
126 | } |
127 | for (i = 0; i < 3; i++) { |
128 | if (!autoload_fail) |
129 | tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i]; |
130 | else |
131 | tempval = EEPROM_DEFAULT_HT40_2SDIFF; |
132 | rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_A][i] = |
133 | (tempval & 0xf); |
134 | rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_B][i] = |
135 | ((tempval & 0xf0) >> 4); |
136 | } |
137 | for (rf_path = 0; rf_path < 2; rf_path++) |
138 | for (i = 0; i < 3; i++) |
139 | RTPRINT(rtlpriv, FINIT, INIT_EEPROM, |
140 | "RF(%d) EEPROM CCK Area(%d) = 0x%x\n" , |
141 | rf_path, i, |
142 | rtlefuse-> |
143 | eeprom_chnlarea_txpwr_cck[rf_path][i]); |
144 | for (rf_path = 0; rf_path < 2; rf_path++) |
145 | for (i = 0; i < 3; i++) |
146 | RTPRINT(rtlpriv, FINIT, INIT_EEPROM, |
147 | "RF(%d) EEPROM HT40 1S Area(%d) = 0x%x\n" , |
148 | rf_path, i, |
149 | rtlefuse-> |
150 | eeprom_chnlarea_txpwr_ht40_1s[rf_path][i]); |
151 | for (rf_path = 0; rf_path < 2; rf_path++) |
152 | for (i = 0; i < 3; i++) |
153 | RTPRINT(rtlpriv, FINIT, INIT_EEPROM, |
154 | "RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n" , |
155 | rf_path, i, |
156 | rtlefuse-> |
157 | eprom_chnl_txpwr_ht40_2sdf[rf_path][i]); |
158 | for (rf_path = 0; rf_path < 2; rf_path++) { |
159 | for (i = 0; i < 14; i++) { |
160 | index = rtl92c_get_chnl_group(chnl: (u8)i); |
161 | rtlefuse->txpwrlevel_cck[rf_path][i] = |
162 | rtlefuse->eeprom_chnlarea_txpwr_cck[rf_path][index]; |
163 | rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = |
164 | rtlefuse-> |
165 | eeprom_chnlarea_txpwr_ht40_1s[rf_path][index]; |
166 | if ((rtlefuse-> |
167 | eeprom_chnlarea_txpwr_ht40_1s[rf_path][index] - |
168 | rtlefuse-> |
169 | eprom_chnl_txpwr_ht40_2sdf[rf_path][index]) |
170 | > 0) { |
171 | rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = |
172 | rtlefuse-> |
173 | eeprom_chnlarea_txpwr_ht40_1s[rf_path] |
174 | [index] - rtlefuse-> |
175 | eprom_chnl_txpwr_ht40_2sdf[rf_path] |
176 | [index]; |
177 | } else { |
178 | rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = 0; |
179 | } |
180 | } |
181 | for (i = 0; i < 14; i++) { |
182 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
183 | "RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = [0x%x / 0x%x / 0x%x]\n" , rf_path, i, |
184 | rtlefuse->txpwrlevel_cck[rf_path][i], |
185 | rtlefuse->txpwrlevel_ht40_1s[rf_path][i], |
186 | rtlefuse->txpwrlevel_ht40_2s[rf_path][i]); |
187 | } |
188 | } |
189 | for (i = 0; i < 3; i++) { |
190 | if (!autoload_fail) { |
191 | rtlefuse->eeprom_pwrlimit_ht40[i] = |
192 | hwinfo[EEPROM_TXPWR_GROUP + i]; |
193 | rtlefuse->eeprom_pwrlimit_ht20[i] = |
194 | hwinfo[EEPROM_TXPWR_GROUP + 3 + i]; |
195 | } else { |
196 | rtlefuse->eeprom_pwrlimit_ht40[i] = 0; |
197 | rtlefuse->eeprom_pwrlimit_ht20[i] = 0; |
198 | } |
199 | } |
200 | for (rf_path = 0; rf_path < 2; rf_path++) { |
201 | for (i = 0; i < 14; i++) { |
202 | index = rtl92c_get_chnl_group(chnl: (u8)i); |
203 | if (rf_path == RF90_PATH_A) { |
204 | rtlefuse->pwrgroup_ht20[rf_path][i] = |
205 | (rtlefuse->eeprom_pwrlimit_ht20[index] |
206 | & 0xf); |
207 | rtlefuse->pwrgroup_ht40[rf_path][i] = |
208 | (rtlefuse->eeprom_pwrlimit_ht40[index] |
209 | & 0xf); |
210 | } else if (rf_path == RF90_PATH_B) { |
211 | rtlefuse->pwrgroup_ht20[rf_path][i] = |
212 | ((rtlefuse->eeprom_pwrlimit_ht20[index] |
213 | & 0xf0) >> 4); |
214 | rtlefuse->pwrgroup_ht40[rf_path][i] = |
215 | ((rtlefuse->eeprom_pwrlimit_ht40[index] |
216 | & 0xf0) >> 4); |
217 | } |
218 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
219 | "RF-%d pwrgroup_ht20[%d] = 0x%x\n" , |
220 | rf_path, i, |
221 | rtlefuse->pwrgroup_ht20[rf_path][i]); |
222 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
223 | "RF-%d pwrgroup_ht40[%d] = 0x%x\n" , |
224 | rf_path, i, |
225 | rtlefuse->pwrgroup_ht40[rf_path][i]); |
226 | } |
227 | } |
228 | for (i = 0; i < 14; i++) { |
229 | index = rtl92c_get_chnl_group(chnl: (u8)i); |
230 | if (!autoload_fail) |
231 | tempval = hwinfo[EEPROM_TXPOWERHT20DIFF + index]; |
232 | else |
233 | tempval = EEPROM_DEFAULT_HT20_DIFF; |
234 | rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] = (tempval & 0xF); |
235 | rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] = |
236 | ((tempval >> 4) & 0xF); |
237 | if (rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] & BIT(3)) |
238 | rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] |= 0xF0; |
239 | if (rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] & BIT(3)) |
240 | rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] |= 0xF0; |
241 | index = rtl92c_get_chnl_group(chnl: (u8)i); |
242 | if (!autoload_fail) |
243 | tempval = hwinfo[EEPROM_TXPOWER_OFDMDIFF + index]; |
244 | else |
245 | tempval = EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF; |
246 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i] = (tempval & 0xF); |
247 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i] = |
248 | ((tempval >> 4) & 0xF); |
249 | } |
250 | rtlefuse->legacy_ht_txpowerdiff = |
251 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7]; |
252 | for (i = 0; i < 14; i++) |
253 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
254 | "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n" , |
255 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]); |
256 | for (i = 0; i < 14; i++) |
257 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
258 | "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n" , |
259 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]); |
260 | for (i = 0; i < 14; i++) |
261 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
262 | "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n" , |
263 | i, rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]); |
264 | for (i = 0; i < 14; i++) |
265 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
266 | "RF-B Legacy to HT40 Diff[%d] = 0x%x\n" , |
267 | i, rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]); |
268 | if (!autoload_fail) |
269 | rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7); |
270 | else |
271 | rtlefuse->eeprom_regulatory = 0; |
272 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
273 | "eeprom_regulatory = 0x%x\n" , rtlefuse->eeprom_regulatory); |
274 | if (!autoload_fail) { |
275 | rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A]; |
276 | rtlefuse->eeprom_tssi[RF90_PATH_B] = hwinfo[EEPROM_TSSI_B]; |
277 | } else { |
278 | rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI; |
279 | rtlefuse->eeprom_tssi[RF90_PATH_B] = EEPROM_DEFAULT_TSSI; |
280 | } |
281 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
282 | "TSSI_A = 0x%x, TSSI_B = 0x%x\n" , |
283 | rtlefuse->eeprom_tssi[RF90_PATH_A], |
284 | rtlefuse->eeprom_tssi[RF90_PATH_B]); |
285 | if (!autoload_fail) |
286 | tempval = hwinfo[EEPROM_THERMAL_METER]; |
287 | else |
288 | tempval = EEPROM_DEFAULT_THERMALMETER; |
289 | rtlefuse->eeprom_thermalmeter = (tempval & 0x1f); |
290 | if (rtlefuse->eeprom_thermalmeter < 0x06 || |
291 | rtlefuse->eeprom_thermalmeter > 0x1c) |
292 | rtlefuse->eeprom_thermalmeter = 0x12; |
293 | if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail) |
294 | rtlefuse->apk_thermalmeterignore = true; |
295 | rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter; |
296 | RTPRINT(rtlpriv, FINIT, INIT_TXPOWER, |
297 | "thermalmeter = 0x%x\n" , rtlefuse->eeprom_thermalmeter); |
298 | } |
299 | |
300 | static void _rtl92cu_read_board_type(struct ieee80211_hw *hw, u8 *contents) |
301 | { |
302 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
303 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
304 | u8 boardtype; |
305 | |
306 | if (IS_NORMAL_CHIP(rtlhal->version)) { |
307 | boardtype = ((contents[EEPROM_RF_OPT1]) & |
308 | BOARD_TYPE_NORMAL_MASK) >> 5; /*bit[7:5]*/ |
309 | } else { |
310 | boardtype = contents[EEPROM_RF_OPT4]; |
311 | boardtype &= BOARD_TYPE_TEST_MASK; |
312 | } |
313 | rtlefuse->board_type = boardtype; |
314 | if (IS_HIGHT_PA(rtlefuse->board_type)) |
315 | rtlefuse->external_pa = 1; |
316 | pr_info("Board Type %x\n" , rtlefuse->board_type); |
317 | } |
318 | |
319 | static void _rtl92cu_read_adapter_info(struct ieee80211_hw *hw) |
320 | { |
321 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
322 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
323 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
324 | int params[] = {RTL8190_EEPROM_ID, EEPROM_VID, EEPROM_DID, |
325 | EEPROM_SVID, EEPROM_SMID, EEPROM_MAC_ADDR, |
326 | EEPROM_CHANNELPLAN, EEPROM_VERSION, EEPROM_CUSTOMER_ID, |
327 | 0}; |
328 | u8 *hwinfo; |
329 | |
330 | hwinfo = kzalloc(HWSET_MAX_SIZE, GFP_KERNEL); |
331 | if (!hwinfo) |
332 | return; |
333 | |
334 | if (rtl_get_hwinfo(hw, rtlpriv, HWSET_MAX_SIZE, hwinfo, params)) |
335 | goto exit; |
336 | |
337 | _rtl92cu_read_txpower_info_from_hwpg(hw, |
338 | autoload_fail: rtlefuse->autoload_failflag, hwinfo); |
339 | _rtl92cu_read_board_type(hw, contents: hwinfo); |
340 | |
341 | rtlefuse->txpwr_fromeprom = true; |
342 | if (rtlhal->oem_id == RT_CID_DEFAULT) { |
343 | switch (rtlefuse->eeprom_oemid) { |
344 | case EEPROM_CID_DEFAULT: |
345 | if (rtlefuse->eeprom_did == 0x8176) { |
346 | if ((rtlefuse->eeprom_svid == 0x103C && |
347 | rtlefuse->eeprom_smid == 0x1629)) |
348 | rtlhal->oem_id = RT_CID_819X_HP; |
349 | else |
350 | rtlhal->oem_id = RT_CID_DEFAULT; |
351 | } else { |
352 | rtlhal->oem_id = RT_CID_DEFAULT; |
353 | } |
354 | break; |
355 | case EEPROM_CID_TOSHIBA: |
356 | rtlhal->oem_id = RT_CID_TOSHIBA; |
357 | break; |
358 | case EEPROM_CID_QMI: |
359 | rtlhal->oem_id = RT_CID_819X_QMI; |
360 | break; |
361 | case EEPROM_CID_WHQL: |
362 | default: |
363 | rtlhal->oem_id = RT_CID_DEFAULT; |
364 | break; |
365 | } |
366 | } |
367 | exit: |
368 | kfree(objp: hwinfo); |
369 | } |
370 | |
371 | static void _rtl92cu_hal_customized_behavior(struct ieee80211_hw *hw) |
372 | { |
373 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
374 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
375 | |
376 | switch (rtlhal->oem_id) { |
377 | case RT_CID_819X_HP: |
378 | rtlpriv->ledctl.led_opendrain = true; |
379 | break; |
380 | case RT_CID_819X_LENOVO: |
381 | case RT_CID_DEFAULT: |
382 | case RT_CID_TOSHIBA: |
383 | case RT_CID_CCX: |
384 | case RT_CID_819X_ACER: |
385 | case RT_CID_WHQL: |
386 | default: |
387 | break; |
388 | } |
389 | rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "RT Customized ID: 0x%02X\n" , |
390 | rtlhal->oem_id); |
391 | } |
392 | |
393 | void rtl92cu_read_eeprom_info(struct ieee80211_hw *hw) |
394 | { |
395 | |
396 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
397 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
398 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
399 | u8 tmp_u1b; |
400 | |
401 | if (!IS_NORMAL_CHIP(rtlhal->version)) |
402 | return; |
403 | tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR); |
404 | rtlefuse->epromtype = (tmp_u1b & BOOT_FROM_EEPROM) ? |
405 | EEPROM_93C46 : EEPROM_BOOT_EFUSE; |
406 | rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, "Boot from %s\n" , |
407 | tmp_u1b & BOOT_FROM_EEPROM ? "EERROM" : "EFUSE" ); |
408 | rtlefuse->autoload_failflag = (tmp_u1b & EEPROM_EN) ? false : true; |
409 | rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "Autoload %s\n" , |
410 | tmp_u1b & EEPROM_EN ? "OK!!" : "ERR!!" ); |
411 | _rtl92cu_read_adapter_info(hw); |
412 | _rtl92cu_hal_customized_behavior(hw); |
413 | return; |
414 | } |
415 | |
416 | static int _rtl92cu_init_power_on(struct ieee80211_hw *hw) |
417 | { |
418 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
419 | int status = 0; |
420 | u16 value16; |
421 | u8 value8; |
422 | /* polling autoload done. */ |
423 | u32 pollingcount = 0; |
424 | |
425 | do { |
426 | if (rtl_read_byte(rtlpriv, REG_APS_FSMCO) & PFM_ALDN) { |
427 | rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, |
428 | "Autoload Done!\n" ); |
429 | break; |
430 | } |
431 | if (pollingcount++ > 100) { |
432 | pr_err("Failed to polling REG_APS_FSMCO[PFM_ALDN] done!\n" ); |
433 | return -ENODEV; |
434 | } |
435 | } while (true); |
436 | /* 0. RSV_CTRL 0x1C[7:0] = 0 unlock ISO/CLK/Power control register */ |
437 | rtl_write_byte(rtlpriv, REG_RSV_CTRL, val8: 0x0); |
438 | /* Power on when re-enter from IPS/Radio off/card disable */ |
439 | /* enable SPS into PWM mode */ |
440 | rtl_write_byte(rtlpriv, REG_SPS0_CTRL, val8: 0x2b); |
441 | udelay(100); |
442 | value8 = rtl_read_byte(rtlpriv, REG_LDOV12D_CTRL); |
443 | if (0 == (value8 & LDV12_EN)) { |
444 | value8 |= LDV12_EN; |
445 | rtl_write_byte(rtlpriv, REG_LDOV12D_CTRL, val8: value8); |
446 | rtl_dbg(rtlpriv, COMP_INIT, DBG_DMESG, |
447 | " power-on :REG_LDOV12D_CTRL Reg0x21:0x%02x\n" , |
448 | value8); |
449 | udelay(100); |
450 | value8 = rtl_read_byte(rtlpriv, REG_SYS_ISO_CTRL); |
451 | value8 &= ~ISO_MD2PP; |
452 | rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, val8: value8); |
453 | } |
454 | /* auto enable WLAN */ |
455 | pollingcount = 0; |
456 | value16 = rtl_read_word(rtlpriv, REG_APS_FSMCO); |
457 | value16 |= APFM_ONMAC; |
458 | rtl_write_word(rtlpriv, REG_APS_FSMCO, val16: value16); |
459 | do { |
460 | if (!(rtl_read_word(rtlpriv, REG_APS_FSMCO) & APFM_ONMAC)) { |
461 | pr_info("MAC auto ON okay!\n" ); |
462 | break; |
463 | } |
464 | if (pollingcount++ > 1000) { |
465 | pr_err("Failed to polling REG_APS_FSMCO[APFM_ONMAC] done!\n" ); |
466 | return -ENODEV; |
467 | } |
468 | } while (true); |
469 | /* Enable Radio ,GPIO ,and LED function */ |
470 | rtl_write_word(rtlpriv, REG_APS_FSMCO, val16: 0x0812); |
471 | /* release RF digital isolation */ |
472 | value16 = rtl_read_word(rtlpriv, REG_SYS_ISO_CTRL); |
473 | value16 &= ~ISO_DIOR; |
474 | rtl_write_word(rtlpriv, REG_SYS_ISO_CTRL, val16: value16); |
475 | /* Reconsider when to do this operation after asking HWSD. */ |
476 | pollingcount = 0; |
477 | rtl_write_byte(rtlpriv, REG_APSD_CTRL, val8: (rtl_read_byte(rtlpriv, |
478 | REG_APSD_CTRL) & ~BIT(6))); |
479 | do { |
480 | pollingcount++; |
481 | } while ((pollingcount < 200) && |
482 | (rtl_read_byte(rtlpriv, REG_APSD_CTRL) & BIT(7))); |
483 | /* Enable MAC DMA/WMAC/SCHEDULE/SEC block */ |
484 | value16 = rtl_read_word(rtlpriv, REG_CR); |
485 | value16 |= (HCI_TXDMA_EN | HCI_RXDMA_EN | TXDMA_EN | RXDMA_EN | |
486 | PROTOCOL_EN | SCHEDULE_EN | MACTXEN | MACRXEN | ENSEC); |
487 | rtl_write_word(rtlpriv, REG_CR, val16: value16); |
488 | return status; |
489 | } |
490 | |
491 | static void _rtl92cu_init_queue_reserved_page(struct ieee80211_hw *hw, |
492 | bool wmm_enable, |
493 | u8 out_ep_num, |
494 | u8 queue_sel) |
495 | { |
496 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
497 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
498 | bool ischipn = IS_NORMAL_CHIP(rtlhal->version); |
499 | u32 outepnum = (u32)out_ep_num; |
500 | u32 numhq = 0; |
501 | u32 numlq = 0; |
502 | u32 numnq = 0; |
503 | u32 numpubq; |
504 | u32 value32; |
505 | u8 value8; |
506 | u32 txqpagenum, txqpageunit, txqremaininpage; |
507 | |
508 | if (!wmm_enable) { |
509 | numpubq = (ischipn) ? CHIP_B_PAGE_NUM_PUBQ : |
510 | CHIP_A_PAGE_NUM_PUBQ; |
511 | txqpagenum = TX_TOTAL_PAGE_NUMBER - numpubq; |
512 | |
513 | txqpageunit = txqpagenum / outepnum; |
514 | txqremaininpage = txqpagenum % outepnum; |
515 | if (queue_sel & TX_SELE_HQ) |
516 | numhq = txqpageunit; |
517 | if (queue_sel & TX_SELE_LQ) |
518 | numlq = txqpageunit; |
519 | /* HIGH priority queue always present in the configuration of |
520 | * 2 out-ep. Remainder pages have assigned to High queue */ |
521 | if (outepnum > 1 && txqremaininpage) |
522 | numhq += txqremaininpage; |
523 | /* NOTE: This step done before writing REG_RQPN. */ |
524 | if (ischipn) { |
525 | if (queue_sel & TX_SELE_NQ) |
526 | numnq = txqpageunit; |
527 | value8 = (u8)_NPQ(numnq); |
528 | rtl_write_byte(rtlpriv, REG_RQPN_NPQ, val8: value8); |
529 | } |
530 | } else { |
531 | /* for WMM ,number of out-ep must more than or equal to 2! */ |
532 | numpubq = ischipn ? WMM_CHIP_B_PAGE_NUM_PUBQ : |
533 | WMM_CHIP_A_PAGE_NUM_PUBQ; |
534 | if (queue_sel & TX_SELE_HQ) { |
535 | numhq = ischipn ? WMM_CHIP_B_PAGE_NUM_HPQ : |
536 | WMM_CHIP_A_PAGE_NUM_HPQ; |
537 | } |
538 | if (queue_sel & TX_SELE_LQ) { |
539 | numlq = ischipn ? WMM_CHIP_B_PAGE_NUM_LPQ : |
540 | WMM_CHIP_A_PAGE_NUM_LPQ; |
541 | } |
542 | /* NOTE: This step done before writing REG_RQPN. */ |
543 | if (ischipn) { |
544 | if (queue_sel & TX_SELE_NQ) |
545 | numnq = WMM_CHIP_B_PAGE_NUM_NPQ; |
546 | value8 = (u8)_NPQ(numnq); |
547 | rtl_write_byte(rtlpriv, REG_RQPN_NPQ, val8: value8); |
548 | } |
549 | } |
550 | /* TX DMA */ |
551 | value32 = _HPQ(numhq) | _LPQ(numlq) | _PUBQ(numpubq) | LD_RQPN; |
552 | rtl_write_dword(rtlpriv, REG_RQPN, val32: value32); |
553 | } |
554 | |
555 | static void _rtl92c_init_trx_buffer(struct ieee80211_hw *hw, bool wmm_enable) |
556 | { |
557 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
558 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
559 | u8 txpktbuf_bndy; |
560 | u8 value8; |
561 | |
562 | if (!wmm_enable) |
563 | txpktbuf_bndy = TX_PAGE_BOUNDARY; |
564 | else /* for WMM */ |
565 | txpktbuf_bndy = (IS_NORMAL_CHIP(rtlhal->version)) |
566 | ? WMM_CHIP_B_TX_PAGE_BOUNDARY |
567 | : WMM_CHIP_A_TX_PAGE_BOUNDARY; |
568 | rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, val8: txpktbuf_bndy); |
569 | rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, val8: txpktbuf_bndy); |
570 | rtl_write_byte(rtlpriv, REG_TXPKTBUF_WMAC_LBK_BF_HD, val8: txpktbuf_bndy); |
571 | rtl_write_byte(rtlpriv, REG_TRXFF_BNDY, val8: txpktbuf_bndy); |
572 | rtl_write_byte(rtlpriv, REG_TDECTRL+1, val8: txpktbuf_bndy); |
573 | rtl_write_word(rtlpriv, addr: (REG_TRXFF_BNDY + 2), val16: 0x27FF); |
574 | value8 = _PSRX(RX_PAGE_SIZE_REG_VALUE) | _PSTX(PBP_128); |
575 | rtl_write_byte(rtlpriv, REG_PBP, val8: value8); |
576 | } |
577 | |
578 | static void _rtl92c_init_chipn_reg_priority(struct ieee80211_hw *hw, u16 beq, |
579 | u16 bkq, u16 viq, u16 voq, |
580 | u16 mgtq, u16 hiq) |
581 | { |
582 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
583 | u16 value16 = (rtl_read_word(rtlpriv, REG_TRXDMA_CTRL) & 0x7); |
584 | |
585 | value16 |= _TXDMA_BEQ_MAP(beq) | _TXDMA_BKQ_MAP(bkq) | |
586 | _TXDMA_VIQ_MAP(viq) | _TXDMA_VOQ_MAP(voq) | |
587 | _TXDMA_MGQ_MAP(mgtq) | _TXDMA_HIQ_MAP(hiq); |
588 | rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, val16: value16); |
589 | } |
590 | |
591 | static void _rtl92cu_init_chipn_one_out_ep_priority(struct ieee80211_hw *hw, |
592 | bool wmm_enable, |
593 | u8 queue_sel) |
594 | { |
595 | u16 value; |
596 | |
597 | switch (queue_sel) { |
598 | case TX_SELE_HQ: |
599 | value = QUEUE_HIGH; |
600 | break; |
601 | case TX_SELE_LQ: |
602 | value = QUEUE_LOW; |
603 | break; |
604 | case TX_SELE_NQ: |
605 | value = QUEUE_NORMAL; |
606 | break; |
607 | default: |
608 | WARN_ON(1); /* Shall not reach here! */ |
609 | return; |
610 | } |
611 | _rtl92c_init_chipn_reg_priority(hw, beq: value, bkq: value, viq: value, voq: value, |
612 | mgtq: value, hiq: value); |
613 | pr_info("Tx queue select: 0x%02x\n" , queue_sel); |
614 | } |
615 | |
616 | static void _rtl92cu_init_chipn_two_out_ep_priority(struct ieee80211_hw *hw, |
617 | bool wmm_enable, |
618 | u8 queue_sel) |
619 | { |
620 | u16 beq, bkq, viq, voq, mgtq, hiq; |
621 | u16 valuehi; |
622 | u16 valuelow; |
623 | |
624 | switch (queue_sel) { |
625 | default: |
626 | WARN_ON(1); |
627 | fallthrough; |
628 | case (TX_SELE_HQ | TX_SELE_LQ): |
629 | valuehi = QUEUE_HIGH; |
630 | valuelow = QUEUE_LOW; |
631 | break; |
632 | case (TX_SELE_NQ | TX_SELE_LQ): |
633 | valuehi = QUEUE_NORMAL; |
634 | valuelow = QUEUE_LOW; |
635 | break; |
636 | case (TX_SELE_HQ | TX_SELE_NQ): |
637 | valuehi = QUEUE_HIGH; |
638 | valuelow = QUEUE_NORMAL; |
639 | break; |
640 | } |
641 | if (!wmm_enable) { |
642 | beq = valuelow; |
643 | bkq = valuelow; |
644 | viq = valuehi; |
645 | voq = valuehi; |
646 | mgtq = valuehi; |
647 | hiq = valuehi; |
648 | } else {/* for WMM ,CONFIG_OUT_EP_WIFI_MODE */ |
649 | beq = valuehi; |
650 | bkq = valuelow; |
651 | viq = valuelow; |
652 | voq = valuehi; |
653 | mgtq = valuehi; |
654 | hiq = valuehi; |
655 | } |
656 | _rtl92c_init_chipn_reg_priority(hw, beq, bkq, viq, voq, mgtq, hiq); |
657 | pr_info("Tx queue select: 0x%02x\n" , queue_sel); |
658 | } |
659 | |
660 | static void _rtl92cu_init_chipn_three_out_ep_priority(struct ieee80211_hw *hw, |
661 | bool wmm_enable, |
662 | u8 queue_sel) |
663 | { |
664 | u16 beq, bkq, viq, voq, mgtq, hiq; |
665 | |
666 | if (!wmm_enable) { /* typical setting */ |
667 | beq = QUEUE_LOW; |
668 | bkq = QUEUE_LOW; |
669 | viq = QUEUE_NORMAL; |
670 | voq = QUEUE_HIGH; |
671 | mgtq = QUEUE_HIGH; |
672 | hiq = QUEUE_HIGH; |
673 | } else { /* for WMM */ |
674 | beq = QUEUE_LOW; |
675 | bkq = QUEUE_NORMAL; |
676 | viq = QUEUE_NORMAL; |
677 | voq = QUEUE_HIGH; |
678 | mgtq = QUEUE_HIGH; |
679 | hiq = QUEUE_HIGH; |
680 | } |
681 | _rtl92c_init_chipn_reg_priority(hw, beq, bkq, viq, voq, mgtq, hiq); |
682 | pr_info("Tx queue select :0x%02x..\n" , queue_sel); |
683 | } |
684 | |
685 | static void _rtl92cu_init_chipn_queue_priority(struct ieee80211_hw *hw, |
686 | bool wmm_enable, |
687 | u8 out_ep_num, |
688 | u8 queue_sel) |
689 | { |
690 | switch (out_ep_num) { |
691 | case 1: |
692 | _rtl92cu_init_chipn_one_out_ep_priority(hw, wmm_enable, |
693 | queue_sel); |
694 | break; |
695 | case 2: |
696 | _rtl92cu_init_chipn_two_out_ep_priority(hw, wmm_enable, |
697 | queue_sel); |
698 | break; |
699 | case 3: |
700 | _rtl92cu_init_chipn_three_out_ep_priority(hw, wmm_enable, |
701 | queue_sel); |
702 | break; |
703 | default: |
704 | WARN_ON(1); /* Shall not reach here! */ |
705 | break; |
706 | } |
707 | } |
708 | |
709 | static void _rtl92cu_init_chipt_queue_priority(struct ieee80211_hw *hw, |
710 | bool wmm_enable, |
711 | u8 out_ep_num, |
712 | u8 queue_sel) |
713 | { |
714 | u8 hq_sele = 0; |
715 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
716 | |
717 | switch (out_ep_num) { |
718 | case 2: /* (TX_SELE_HQ|TX_SELE_LQ) */ |
719 | if (!wmm_enable) /* typical setting */ |
720 | hq_sele = HQSEL_VOQ | HQSEL_VIQ | HQSEL_MGTQ | |
721 | HQSEL_HIQ; |
722 | else /* for WMM */ |
723 | hq_sele = HQSEL_VOQ | HQSEL_BEQ | HQSEL_MGTQ | |
724 | HQSEL_HIQ; |
725 | break; |
726 | case 1: |
727 | if (TX_SELE_LQ == queue_sel) { |
728 | /* map all endpoint to Low queue */ |
729 | hq_sele = 0; |
730 | } else if (TX_SELE_HQ == queue_sel) { |
731 | /* map all endpoint to High queue */ |
732 | hq_sele = HQSEL_VOQ | HQSEL_VIQ | HQSEL_BEQ | |
733 | HQSEL_BKQ | HQSEL_MGTQ | HQSEL_HIQ; |
734 | } |
735 | break; |
736 | default: |
737 | WARN_ON(1); /* Shall not reach here! */ |
738 | break; |
739 | } |
740 | rtl_write_byte(rtlpriv, addr: (REG_TRXDMA_CTRL+1), val8: hq_sele); |
741 | pr_info("Tx queue select :0x%02x..\n" , hq_sele); |
742 | } |
743 | |
744 | static void _rtl92cu_init_queue_priority(struct ieee80211_hw *hw, |
745 | bool wmm_enable, |
746 | u8 out_ep_num, |
747 | u8 queue_sel) |
748 | { |
749 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
750 | |
751 | if (IS_NORMAL_CHIP(rtlhal->version)) |
752 | _rtl92cu_init_chipn_queue_priority(hw, wmm_enable, out_ep_num, |
753 | queue_sel); |
754 | else |
755 | _rtl92cu_init_chipt_queue_priority(hw, wmm_enable, out_ep_num, |
756 | queue_sel); |
757 | } |
758 | |
759 | static void _rtl92cu_init_wmac_setting(struct ieee80211_hw *hw) |
760 | { |
761 | u16 value16; |
762 | u32 value32; |
763 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
764 | |
765 | value32 = (RCR_APM | RCR_AM | RCR_ADF | RCR_AB | RCR_APPFCS | |
766 | RCR_APP_ICV | RCR_AMF | RCR_HTC_LOC_CTRL | |
767 | RCR_APP_MIC | RCR_APP_PHYSTS | RCR_ACRC32); |
768 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(&value32)); |
769 | /* Accept all multicast address */ |
770 | rtl_write_dword(rtlpriv, REG_MAR, val32: 0xFFFFFFFF); |
771 | rtl_write_dword(rtlpriv, REG_MAR + 4, val32: 0xFFFFFFFF); |
772 | /* Accept all management frames */ |
773 | value16 = 0xFFFF; |
774 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MGT_FILTER, |
775 | (u8 *)(&value16)); |
776 | /* Reject all control frame - default value is 0 */ |
777 | value16 = 0x0; |
778 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CTRL_FILTER, |
779 | (u8 *)(&value16)); |
780 | /* Accept all data frames */ |
781 | value16 = 0xFFFF; |
782 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_DATA_FILTER, |
783 | (u8 *)(&value16)); |
784 | } |
785 | |
786 | static void _rtl92cu_init_beacon_parameters(struct ieee80211_hw *hw) |
787 | { |
788 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
789 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); |
790 | |
791 | rtl_write_word(rtlpriv, REG_BCN_CTRL, val16: 0x1010); |
792 | |
793 | /* TODO: Remove these magic number */ |
794 | rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, val16: 0x6404); |
795 | rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME); |
796 | rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME); |
797 | /* Change beacon AIFS to the largest number |
798 | * beacause test chip does not contension before sending beacon. |
799 | */ |
800 | if (IS_NORMAL_CHIP(rtlhal->version)) |
801 | rtl_write_word(rtlpriv, REG_BCNTCFG, val16: 0x660F); |
802 | else |
803 | rtl_write_word(rtlpriv, REG_BCNTCFG, val16: 0x66FF); |
804 | } |
805 | |
806 | static int _rtl92cu_init_mac(struct ieee80211_hw *hw) |
807 | { |
808 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
809 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
810 | struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw); |
811 | struct rtl_usb *rtlusb = rtl_usbdev(usb_priv); |
812 | int err = 0; |
813 | u32 boundary = 0; |
814 | u8 wmm_enable = false; /* TODO */ |
815 | u8 out_ep_nums = rtlusb->out_ep_nums; |
816 | u8 queue_sel = rtlusb->out_queue_sel; |
817 | |
818 | err = _rtl92cu_init_power_on(hw); |
819 | |
820 | if (err) { |
821 | pr_err("Failed to init power on!\n" ); |
822 | return err; |
823 | } |
824 | if (!wmm_enable) { |
825 | boundary = TX_PAGE_BOUNDARY; |
826 | } else { /* for WMM */ |
827 | boundary = (IS_NORMAL_CHIP(rtlhal->version)) |
828 | ? WMM_CHIP_B_TX_PAGE_BOUNDARY |
829 | : WMM_CHIP_A_TX_PAGE_BOUNDARY; |
830 | } |
831 | if (!rtl92c_init_llt_table(hw, boundary)) { |
832 | pr_err("Failed to init LLT Table!\n" ); |
833 | return -EINVAL; |
834 | } |
835 | _rtl92cu_init_queue_reserved_page(hw, wmm_enable, out_ep_num: out_ep_nums, |
836 | queue_sel); |
837 | _rtl92c_init_trx_buffer(hw, wmm_enable); |
838 | _rtl92cu_init_queue_priority(hw, wmm_enable, out_ep_num: out_ep_nums, |
839 | queue_sel); |
840 | /* Get Rx PHY status in order to report RSSI and others. */ |
841 | rtl92c_init_driver_info_size(hw, RTL92C_DRIVER_INFO_SIZE); |
842 | rtl92c_init_interrupt(hw); |
843 | rtl92c_init_network_type(hw); |
844 | _rtl92cu_init_wmac_setting(hw); |
845 | rtl92c_init_adaptive_ctrl(hw); |
846 | rtl92c_init_edca(hw); |
847 | rtl92c_init_rate_fallback(hw); |
848 | rtl92c_init_retry_function(hw); |
849 | rtlpriv->cfg->ops->set_bw_mode(hw, NL80211_CHAN_HT20); |
850 | rtl92c_set_min_space(hw, IS_92C_SERIAL(rtlhal->version)); |
851 | _rtl92cu_init_beacon_parameters(hw); |
852 | rtl92c_init_ampdu_aggregation(hw); |
853 | rtl92c_init_beacon_max_error(hw); |
854 | return err; |
855 | } |
856 | |
857 | void rtl92cu_enable_hw_security_config(struct ieee80211_hw *hw) |
858 | { |
859 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
860 | u8 sec_reg_value = 0x0; |
861 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); |
862 | |
863 | rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, |
864 | "PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n" , |
865 | rtlpriv->sec.pairwise_enc_algorithm, |
866 | rtlpriv->sec.group_enc_algorithm); |
867 | if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { |
868 | rtl_dbg(rtlpriv, COMP_SEC, DBG_DMESG, |
869 | "not open sw encryption\n" ); |
870 | return; |
871 | } |
872 | sec_reg_value = SCR_TXENCENABLE | SCR_RXDECENABLE; |
873 | if (rtlpriv->sec.use_defaultkey) { |
874 | sec_reg_value |= SCR_TXUSEDK; |
875 | sec_reg_value |= SCR_RXUSEDK; |
876 | } |
877 | if (IS_NORMAL_CHIP(rtlhal->version)) |
878 | sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); |
879 | rtl_write_byte(rtlpriv, REG_CR + 1, val8: 0x02); |
880 | rtl_dbg(rtlpriv, COMP_SEC, DBG_LOUD, "The SECR-value %x\n" , |
881 | sec_reg_value); |
882 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); |
883 | } |
884 | |
885 | static void _rtl92cu_hw_configure(struct ieee80211_hw *hw) |
886 | { |
887 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
888 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
889 | |
890 | /* To Fix MAC loopback mode fail. */ |
891 | rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, val8: 0x0f); |
892 | rtl_write_byte(rtlpriv, addr: 0x15, val8: 0xe9); |
893 | /* HW SEQ CTRL */ |
894 | /* set 0x0 to 0xFF by tynli. Default enable HW SEQ NUM. */ |
895 | rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, val8: 0xFF); |
896 | /* fixed USB interface interference issue */ |
897 | rtl_write_byte(rtlpriv, addr: 0xfe40, val8: 0xe0); |
898 | rtl_write_byte(rtlpriv, addr: 0xfe41, val8: 0x8d); |
899 | rtl_write_byte(rtlpriv, addr: 0xfe42, val8: 0x80); |
900 | rtlusb->reg_bcn_ctrl_val = 0x18; |
901 | rtl_write_byte(rtlpriv, REG_BCN_CTRL, val8: (u8)rtlusb->reg_bcn_ctrl_val); |
902 | } |
903 | |
904 | static void _initpabias(struct ieee80211_hw *hw) |
905 | { |
906 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
907 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
908 | u8 pa_setting; |
909 | |
910 | /* FIXED PA current issue */ |
911 | pa_setting = efuse_read_1byte(hw, address: 0x1FA); |
912 | if (!(pa_setting & BIT(0))) { |
913 | rtl_set_rfreg(hw, rfpath: RF90_PATH_A, regaddr: 0x15, bitmask: 0x0FFFFF, data: 0x0F406); |
914 | rtl_set_rfreg(hw, rfpath: RF90_PATH_A, regaddr: 0x15, bitmask: 0x0FFFFF, data: 0x4F406); |
915 | rtl_set_rfreg(hw, rfpath: RF90_PATH_A, regaddr: 0x15, bitmask: 0x0FFFFF, data: 0x8F406); |
916 | rtl_set_rfreg(hw, rfpath: RF90_PATH_A, regaddr: 0x15, bitmask: 0x0FFFFF, data: 0xCF406); |
917 | } |
918 | if (!(pa_setting & BIT(1)) && IS_NORMAL_CHIP(rtlhal->version) && |
919 | IS_92C_SERIAL(rtlhal->version)) { |
920 | rtl_set_rfreg(hw, rfpath: RF90_PATH_B, regaddr: 0x15, bitmask: 0x0FFFFF, data: 0x0F406); |
921 | rtl_set_rfreg(hw, rfpath: RF90_PATH_B, regaddr: 0x15, bitmask: 0x0FFFFF, data: 0x4F406); |
922 | rtl_set_rfreg(hw, rfpath: RF90_PATH_B, regaddr: 0x15, bitmask: 0x0FFFFF, data: 0x8F406); |
923 | rtl_set_rfreg(hw, rfpath: RF90_PATH_B, regaddr: 0x15, bitmask: 0x0FFFFF, data: 0xCF406); |
924 | } |
925 | if (!(pa_setting & BIT(4))) { |
926 | pa_setting = rtl_read_byte(rtlpriv, addr: 0x16); |
927 | pa_setting &= 0x0F; |
928 | rtl_write_byte(rtlpriv, addr: 0x16, val8: pa_setting | 0x90); |
929 | } |
930 | } |
931 | |
932 | int rtl92cu_hw_init(struct ieee80211_hw *hw) |
933 | { |
934 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
935 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
936 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
937 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
938 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
939 | int err = 0; |
940 | unsigned long flags; |
941 | |
942 | /* As this function can take a very long time (up to 350 ms) |
943 | * and can be called with irqs disabled, reenable the irqs |
944 | * to let the other devices continue being serviced. |
945 | * |
946 | * It is safe doing so since our own interrupts will only be enabled |
947 | * in a subsequent step. |
948 | */ |
949 | local_save_flags(flags); |
950 | local_irq_enable(); |
951 | |
952 | rtlhal->fw_ready = false; |
953 | rtlhal->hw_type = HARDWARE_TYPE_RTL8192CU; |
954 | err = _rtl92cu_init_mac(hw); |
955 | if (err) { |
956 | pr_err("init mac failed!\n" ); |
957 | goto exit; |
958 | } |
959 | err = rtl92c_download_fw(hw); |
960 | if (err) { |
961 | rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING, |
962 | "Failed to download FW. Init HW without FW now..\n" ); |
963 | err = 1; |
964 | goto exit; |
965 | } |
966 | |
967 | rtlhal->fw_ready = true; |
968 | rtlhal->last_hmeboxnum = 0; /* h2c */ |
969 | _rtl92cu_phy_param_tab_init(hw); |
970 | rtl92cu_phy_mac_config(hw); |
971 | rtl92cu_phy_bb_config(hw); |
972 | rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; |
973 | rtl92c_phy_rf_config(hw); |
974 | if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && |
975 | !IS_92C_SERIAL(rtlhal->version)) { |
976 | rtl_set_rfreg(hw, rfpath: RF90_PATH_A, RF_RX_G1, MASKDWORD, data: 0x30255); |
977 | rtl_set_rfreg(hw, rfpath: RF90_PATH_A, RF_RX_G2, MASKDWORD, data: 0x50a00); |
978 | } |
979 | rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, rfpath: (enum radio_path)0, |
980 | RF_CHNLBW, RFREG_OFFSET_MASK); |
981 | rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, rfpath: (enum radio_path)1, |
982 | RF_CHNLBW, RFREG_OFFSET_MASK); |
983 | rtl92cu_bb_block_on(hw); |
984 | rtl_cam_reset_all_entry(hw); |
985 | rtl92cu_enable_hw_security_config(hw); |
986 | ppsc->rfpwr_state = ERFON; |
987 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); |
988 | if (ppsc->rfpwr_state == ERFON) { |
989 | rtl92c_phy_set_rfpath_switch(hw, bmain: 1); |
990 | if (rtlphy->iqk_initialized) { |
991 | rtl92c_phy_iq_calibrate(hw, recovery: true); |
992 | } else { |
993 | rtl92c_phy_iq_calibrate(hw, recovery: false); |
994 | rtlphy->iqk_initialized = true; |
995 | } |
996 | rtl92c_dm_check_txpower_tracking(hw); |
997 | rtl92c_phy_lc_calibrate(hw); |
998 | } |
999 | _rtl92cu_hw_configure(hw); |
1000 | _initpabias(hw); |
1001 | rtl92c_dm_init(hw); |
1002 | exit: |
1003 | local_irq_disable(); |
1004 | local_irq_restore(flags); |
1005 | return err; |
1006 | } |
1007 | |
1008 | static void disable_rfafeandresetbb(struct ieee80211_hw *hw) |
1009 | { |
1010 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1011 | /************************************** |
1012 | a. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue |
1013 | b. RF path 0 offset 0x00 = 0x00 disable RF |
1014 | c. APSD_CTRL 0x600[7:0] = 0x40 |
1015 | d. SYS_FUNC_EN 0x02[7:0] = 0x16 reset BB state machine |
1016 | e. SYS_FUNC_EN 0x02[7:0] = 0x14 reset BB state machine |
1017 | ***************************************/ |
1018 | u8 erfpath = 0, value8 = 0; |
1019 | |
1020 | rtl_write_byte(rtlpriv, REG_TXPAUSE, val8: 0xFF); |
1021 | rtl_set_rfreg(hw, rfpath: (enum radio_path)erfpath, regaddr: 0x0, MASKBYTE0, data: 0x0); |
1022 | |
1023 | value8 |= APSDOFF; |
1024 | rtl_write_byte(rtlpriv, REG_APSD_CTRL, val8: value8); /*0x40*/ |
1025 | value8 = 0; |
1026 | value8 |= (FEN_USBD | FEN_USBA | FEN_BB_GLB_RSTN); |
1027 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, val8: value8);/*0x16*/ |
1028 | value8 &= (~FEN_BB_GLB_RSTN); |
1029 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, val8: value8); /*0x14*/ |
1030 | } |
1031 | |
1032 | static void _resetdigitalprocedure1(struct ieee80211_hw *hw, bool withouthwsm) |
1033 | { |
1034 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1035 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
1036 | |
1037 | if (rtlhal->fw_version <= 0x20) { |
1038 | /***************************** |
1039 | f. MCUFWDL 0x80[7:0]=0 reset MCU ready status |
1040 | g. SYS_FUNC_EN 0x02[10]= 0 reset MCU reg, (8051 reset) |
1041 | h. SYS_FUNC_EN 0x02[15-12]= 5 reset MAC reg, DCORE |
1042 | i. SYS_FUNC_EN 0x02[10]= 1 enable MCU reg, (8051 enable) |
1043 | ******************************/ |
1044 | u16 valu16 = 0; |
1045 | |
1046 | rtl_write_byte(rtlpriv, REG_MCUFWDL, val8: 0); |
1047 | valu16 = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); |
1048 | rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, val16: (valu16 & |
1049 | (~FEN_CPUEN))); /* reset MCU ,8051 */ |
1050 | valu16 = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN)&0x0FFF; |
1051 | rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, val16: (valu16 | |
1052 | (FEN_HWPDN|FEN_ELDR))); /* reset MAC */ |
1053 | valu16 = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); |
1054 | rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, val16: (valu16 | |
1055 | FEN_CPUEN)); /* enable MCU ,8051 */ |
1056 | } else { |
1057 | u8 retry_cnts = 0; |
1058 | |
1059 | /* IF fw in RAM code, do reset */ |
1060 | if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(1)) { |
1061 | /* reset MCU ready status */ |
1062 | rtl_write_byte(rtlpriv, REG_MCUFWDL, val8: 0); |
1063 | /* 8051 reset by self */ |
1064 | rtl_write_byte(rtlpriv, REG_HMETFR+3, val8: 0x20); |
1065 | while ((retry_cnts++ < 100) && |
1066 | (FEN_CPUEN & rtl_read_word(rtlpriv, |
1067 | REG_SYS_FUNC_EN))) { |
1068 | udelay(50); |
1069 | } |
1070 | if (retry_cnts >= 100) { |
1071 | pr_err("8051 reset failed!.........................\n" ); |
1072 | /* if 8051 reset fail, reset MAC. */ |
1073 | rtl_write_byte(rtlpriv, |
1074 | REG_SYS_FUNC_EN + 1, |
1075 | val8: 0x50); |
1076 | udelay(100); |
1077 | } |
1078 | } |
1079 | /* Reset MAC and Enable 8051 */ |
1080 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, val8: 0x54); |
1081 | rtl_write_byte(rtlpriv, REG_MCUFWDL, val8: 0); |
1082 | } |
1083 | if (withouthwsm) { |
1084 | /***************************** |
1085 | Without HW auto state machine |
1086 | g.SYS_CLKR 0x08[15:0] = 0x30A3 disable MAC clock |
1087 | h.AFE_PLL_CTRL 0x28[7:0] = 0x80 disable AFE PLL |
1088 | i.AFE_XTAL_CTRL 0x24[15:0] = 0x880F gated AFE DIG_CLOCK |
1089 | j.SYS_ISu_CTRL 0x00[7:0] = 0xF9 isolated digital to PON |
1090 | ******************************/ |
1091 | rtl_write_word(rtlpriv, REG_SYS_CLKR, val16: 0x70A3); |
1092 | rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, val8: 0x80); |
1093 | rtl_write_word(rtlpriv, REG_AFE_XTAL_CTRL, val16: 0x880F); |
1094 | rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, val8: 0xF9); |
1095 | } |
1096 | } |
1097 | |
1098 | static void _resetdigitalprocedure2(struct ieee80211_hw *hw) |
1099 | { |
1100 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1101 | /***************************** |
1102 | k. SYS_FUNC_EN 0x03[7:0] = 0x44 disable ELDR runction |
1103 | l. SYS_CLKR 0x08[15:0] = 0x3083 disable ELDR clock |
1104 | m. SYS_ISO_CTRL 0x01[7:0] = 0x83 isolated ELDR to PON |
1105 | ******************************/ |
1106 | rtl_write_word(rtlpriv, REG_SYS_CLKR, val16: 0x70A3); |
1107 | rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL+1, val8: 0x82); |
1108 | } |
1109 | |
1110 | static void _disablegpio(struct ieee80211_hw *hw) |
1111 | { |
1112 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1113 | /*************************************** |
1114 | j. GPIO_PIN_CTRL 0x44[31:0]=0x000 |
1115 | k. Value = GPIO_PIN_CTRL[7:0] |
1116 | l. GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); write ext PIN level |
1117 | m. GPIO_MUXCFG 0x42 [15:0] = 0x0780 |
1118 | n. LEDCFG 0x4C[15:0] = 0x8080 |
1119 | ***************************************/ |
1120 | u8 value8; |
1121 | u16 value16; |
1122 | u32 value32; |
1123 | |
1124 | /* 1. Disable GPIO[7:0] */ |
1125 | rtl_write_word(rtlpriv, REG_GPIO_PIN_CTRL+2, val16: 0x0000); |
1126 | value32 = rtl_read_dword(rtlpriv, REG_GPIO_PIN_CTRL) & 0xFFFF00FF; |
1127 | value8 = (u8)(value32&0x000000FF); |
1128 | value32 |= ((value8<<8) | 0x00FF0000); |
1129 | rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, val32: value32); |
1130 | /* 2. Disable GPIO[10:8] */ |
1131 | rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG+3, val8: 0x00); |
1132 | value16 = rtl_read_word(rtlpriv, REG_GPIO_MUXCFG+2) & 0xFF0F; |
1133 | value8 = (u8)(value16&0x000F); |
1134 | value16 |= ((value8<<4) | 0x0780); |
1135 | rtl_write_word(rtlpriv, REG_GPIO_PIN_CTRL+2, val16: value16); |
1136 | /* 3. Disable LED0 & 1 */ |
1137 | rtl_write_word(rtlpriv, REG_LEDCFG0, val16: 0x8080); |
1138 | } |
1139 | |
1140 | static void disable_analog(struct ieee80211_hw *hw, bool withouthwsm) |
1141 | { |
1142 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1143 | u16 value16 = 0; |
1144 | u8 value8 = 0; |
1145 | |
1146 | if (withouthwsm) { |
1147 | /***************************** |
1148 | n. LDOA15_CTRL 0x20[7:0] = 0x04 disable A15 power |
1149 | o. LDOV12D_CTRL 0x21[7:0] = 0x54 disable digital core power |
1150 | r. When driver call disable, the ASIC will turn off remaining |
1151 | clock automatically |
1152 | ******************************/ |
1153 | rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, val8: 0x04); |
1154 | value8 = rtl_read_byte(rtlpriv, REG_LDOV12D_CTRL); |
1155 | value8 &= (~LDV12_EN); |
1156 | rtl_write_byte(rtlpriv, REG_LDOV12D_CTRL, val8: value8); |
1157 | } |
1158 | |
1159 | /***************************** |
1160 | h. SPS0_CTRL 0x11[7:0] = 0x23 enter PFM mode |
1161 | i. APS_FSMCO 0x04[15:0] = 0x4802 set USB suspend |
1162 | ******************************/ |
1163 | rtl_write_byte(rtlpriv, REG_SPS0_CTRL, val8: 0x23); |
1164 | value16 |= (APDM_HOST | AFSM_HSUS | PFM_ALDN); |
1165 | rtl_write_word(rtlpriv, REG_APS_FSMCO, val16: (u16)value16); |
1166 | rtl_write_byte(rtlpriv, REG_RSV_CTRL, val8: 0x0E); |
1167 | } |
1168 | |
1169 | static void carddisable_hwsm(struct ieee80211_hw *hw) |
1170 | { |
1171 | /* ==== RF Off Sequence ==== */ |
1172 | disable_rfafeandresetbb(hw); |
1173 | /* ==== Reset digital sequence ====== */ |
1174 | _resetdigitalprocedure1(hw, withouthwsm: false); |
1175 | /* ==== Pull GPIO PIN to balance level and LED control ====== */ |
1176 | _disablegpio(hw); |
1177 | /* ==== Disable analog sequence === */ |
1178 | disable_analog(hw, withouthwsm: false); |
1179 | } |
1180 | |
1181 | static void carddisablewithout_hwsm(struct ieee80211_hw *hw) |
1182 | { |
1183 | /*==== RF Off Sequence ==== */ |
1184 | disable_rfafeandresetbb(hw); |
1185 | /* ==== Reset digital sequence ====== */ |
1186 | _resetdigitalprocedure1(hw, withouthwsm: true); |
1187 | /* ==== Pull GPIO PIN to balance level and LED control ====== */ |
1188 | _disablegpio(hw); |
1189 | /* ==== Reset digital sequence ====== */ |
1190 | _resetdigitalprocedure2(hw); |
1191 | /* ==== Disable analog sequence === */ |
1192 | disable_analog(hw, withouthwsm: true); |
1193 | } |
1194 | |
1195 | static void _rtl92cu_set_bcn_ctrl_reg(struct ieee80211_hw *hw, |
1196 | u8 set_bits, u8 clear_bits) |
1197 | { |
1198 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1199 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
1200 | |
1201 | rtlusb->reg_bcn_ctrl_val |= set_bits; |
1202 | rtlusb->reg_bcn_ctrl_val &= ~clear_bits; |
1203 | rtl_write_byte(rtlpriv, REG_BCN_CTRL, val8: (u8)rtlusb->reg_bcn_ctrl_val); |
1204 | } |
1205 | |
1206 | static void _rtl92cu_stop_tx_beacon(struct ieee80211_hw *hw) |
1207 | { |
1208 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1209 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); |
1210 | u8 tmp1byte = 0; |
1211 | |
1212 | if (IS_NORMAL_CHIP(rtlhal->version)) { |
1213 | tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); |
1214 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, |
1215 | val8: tmp1byte & (~BIT(6))); |
1216 | rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, val8: 0x64); |
1217 | tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); |
1218 | tmp1byte &= ~(BIT(0)); |
1219 | rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, val8: tmp1byte); |
1220 | } else { |
1221 | rtl_write_byte(rtlpriv, REG_TXPAUSE, |
1222 | val8: rtl_read_byte(rtlpriv, REG_TXPAUSE) | BIT(6)); |
1223 | } |
1224 | } |
1225 | |
1226 | static void _rtl92cu_resume_tx_beacon(struct ieee80211_hw *hw) |
1227 | { |
1228 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1229 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); |
1230 | u8 tmp1byte = 0; |
1231 | |
1232 | if (IS_NORMAL_CHIP(rtlhal->version)) { |
1233 | tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); |
1234 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, |
1235 | val8: tmp1byte | BIT(6)); |
1236 | rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, val8: 0xff); |
1237 | tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2); |
1238 | tmp1byte |= BIT(0); |
1239 | rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, val8: tmp1byte); |
1240 | } else { |
1241 | rtl_write_byte(rtlpriv, REG_TXPAUSE, |
1242 | val8: rtl_read_byte(rtlpriv, REG_TXPAUSE) & (~BIT(6))); |
1243 | } |
1244 | } |
1245 | |
1246 | static void _rtl92cu_enable_bcn_sub_func(struct ieee80211_hw *hw) |
1247 | { |
1248 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1249 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); |
1250 | |
1251 | if (IS_NORMAL_CHIP(rtlhal->version)) |
1252 | _rtl92cu_set_bcn_ctrl_reg(hw, set_bits: 0, BIT(1)); |
1253 | else |
1254 | _rtl92cu_set_bcn_ctrl_reg(hw, set_bits: 0, BIT(4)); |
1255 | } |
1256 | |
1257 | static void _rtl92cu_disable_bcn_sub_func(struct ieee80211_hw *hw) |
1258 | { |
1259 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1260 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); |
1261 | |
1262 | if (IS_NORMAL_CHIP(rtlhal->version)) |
1263 | _rtl92cu_set_bcn_ctrl_reg(hw, BIT(1), clear_bits: 0); |
1264 | else |
1265 | _rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), clear_bits: 0); |
1266 | } |
1267 | |
1268 | static int _rtl92cu_set_media_status(struct ieee80211_hw *hw, |
1269 | enum nl80211_iftype type) |
1270 | { |
1271 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1272 | u8 bt_msr = rtl_read_byte(rtlpriv, MSR); |
1273 | enum led_ctl_mode ledaction = LED_CTL_NO_LINK; |
1274 | |
1275 | bt_msr &= 0xfc; |
1276 | if (type == NL80211_IFTYPE_UNSPECIFIED || type == |
1277 | NL80211_IFTYPE_STATION) { |
1278 | _rtl92cu_stop_tx_beacon(hw); |
1279 | _rtl92cu_enable_bcn_sub_func(hw); |
1280 | } else if (type == NL80211_IFTYPE_ADHOC || type == NL80211_IFTYPE_AP) { |
1281 | _rtl92cu_resume_tx_beacon(hw); |
1282 | _rtl92cu_disable_bcn_sub_func(hw); |
1283 | } else { |
1284 | rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING, |
1285 | "Set HW_VAR_MEDIA_STATUS:No such media status(%x)\n" , |
1286 | type); |
1287 | } |
1288 | switch (type) { |
1289 | case NL80211_IFTYPE_UNSPECIFIED: |
1290 | bt_msr |= MSR_NOLINK; |
1291 | ledaction = LED_CTL_LINK; |
1292 | rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, |
1293 | "Set Network type to NO LINK!\n" ); |
1294 | break; |
1295 | case NL80211_IFTYPE_ADHOC: |
1296 | bt_msr |= MSR_ADHOC; |
1297 | rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, |
1298 | "Set Network type to Ad Hoc!\n" ); |
1299 | break; |
1300 | case NL80211_IFTYPE_STATION: |
1301 | bt_msr |= MSR_INFRA; |
1302 | ledaction = LED_CTL_LINK; |
1303 | rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, |
1304 | "Set Network type to STA!\n" ); |
1305 | break; |
1306 | case NL80211_IFTYPE_AP: |
1307 | bt_msr |= MSR_AP; |
1308 | rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, |
1309 | "Set Network type to AP!\n" ); |
1310 | break; |
1311 | default: |
1312 | pr_err("Network type %d not supported!\n" , type); |
1313 | goto error_out; |
1314 | } |
1315 | rtl_write_byte(rtlpriv, MSR, val8: bt_msr); |
1316 | rtlpriv->cfg->ops->led_control(hw, ledaction); |
1317 | if ((bt_msr & MSR_MASK) == MSR_AP) |
1318 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, val8: 0x00); |
1319 | else |
1320 | rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, val8: 0x66); |
1321 | return 0; |
1322 | error_out: |
1323 | return 1; |
1324 | } |
1325 | |
1326 | void rtl92cu_card_disable(struct ieee80211_hw *hw) |
1327 | { |
1328 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1329 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
1330 | struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); |
1331 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
1332 | enum nl80211_iftype opmode; |
1333 | |
1334 | mac->link_state = MAC80211_NOLINK; |
1335 | opmode = NL80211_IFTYPE_UNSPECIFIED; |
1336 | _rtl92cu_set_media_status(hw, type: opmode); |
1337 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); |
1338 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); |
1339 | if (rtlusb->disablehwsm) |
1340 | carddisable_hwsm(hw); |
1341 | else |
1342 | carddisablewithout_hwsm(hw); |
1343 | |
1344 | /* after power off we should do iqk again */ |
1345 | rtlpriv->phy.iqk_initialized = false; |
1346 | } |
1347 | |
1348 | void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) |
1349 | { |
1350 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1351 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); |
1352 | u32 reg_rcr; |
1353 | |
1354 | if (rtlpriv->psc.rfpwr_state != ERFON) |
1355 | return; |
1356 | |
1357 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); |
1358 | |
1359 | if (check_bssid) { |
1360 | u8 tmp; |
1361 | |
1362 | if (IS_NORMAL_CHIP(rtlhal->version)) { |
1363 | reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); |
1364 | tmp = BIT(4); |
1365 | } else { |
1366 | reg_rcr |= RCR_CBSSID; |
1367 | tmp = BIT(4) | BIT(5); |
1368 | } |
1369 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, |
1370 | (u8 *) (®_rcr)); |
1371 | _rtl92cu_set_bcn_ctrl_reg(hw, set_bits: 0, clear_bits: tmp); |
1372 | } else { |
1373 | u8 tmp; |
1374 | |
1375 | if (IS_NORMAL_CHIP(rtlhal->version)) { |
1376 | reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); |
1377 | tmp = BIT(4); |
1378 | } else { |
1379 | reg_rcr &= ~RCR_CBSSID; |
1380 | tmp = BIT(4) | BIT(5); |
1381 | } |
1382 | reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); |
1383 | rtlpriv->cfg->ops->set_hw_reg(hw, |
1384 | HW_VAR_RCR, (u8 *) (®_rcr)); |
1385 | _rtl92cu_set_bcn_ctrl_reg(hw, set_bits: tmp, clear_bits: 0); |
1386 | } |
1387 | } |
1388 | |
1389 | /*========================================================================== */ |
1390 | |
1391 | int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) |
1392 | { |
1393 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1394 | |
1395 | if (_rtl92cu_set_media_status(hw, type)) |
1396 | return -EOPNOTSUPP; |
1397 | |
1398 | if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { |
1399 | if (type != NL80211_IFTYPE_AP) |
1400 | rtl92cu_set_check_bssid(hw, check_bssid: true); |
1401 | } else { |
1402 | rtl92cu_set_check_bssid(hw, check_bssid: false); |
1403 | } |
1404 | |
1405 | return 0; |
1406 | } |
1407 | |
1408 | static void _beacon_function_enable(struct ieee80211_hw *hw) |
1409 | { |
1410 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1411 | |
1412 | _rtl92cu_set_bcn_ctrl_reg(hw, set_bits: (BIT(4) | BIT(3) | BIT(1)), clear_bits: 0x00); |
1413 | rtl_write_byte(rtlpriv, REG_RD_CTRL+1, val8: 0x6F); |
1414 | } |
1415 | |
1416 | void rtl92cu_set_beacon_related_registers(struct ieee80211_hw *hw) |
1417 | { |
1418 | |
1419 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1420 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
1421 | u16 bcn_interval, atim_window; |
1422 | u32 value32; |
1423 | |
1424 | bcn_interval = mac->beacon_interval; |
1425 | atim_window = 2; /*FIX MERGE */ |
1426 | rtl_write_word(rtlpriv, REG_ATIMWND, val16: atim_window); |
1427 | rtl_write_word(rtlpriv, REG_BCN_INTERVAL, val16: bcn_interval); |
1428 | _rtl92cu_init_beacon_parameters(hw); |
1429 | rtl_write_byte(rtlpriv, REG_SLOT, val8: 0x09); |
1430 | /* |
1431 | * Force beacon frame transmission even after receiving beacon frame |
1432 | * from other ad hoc STA |
1433 | * |
1434 | * |
1435 | * Reset TSF Timer to zero, added by Roger. 2008.06.24 |
1436 | */ |
1437 | value32 = rtl_read_dword(rtlpriv, REG_TCR); |
1438 | value32 &= ~TSFRST; |
1439 | rtl_write_dword(rtlpriv, REG_TCR, val32: value32); |
1440 | value32 |= TSFRST; |
1441 | rtl_write_dword(rtlpriv, REG_TCR, val32: value32); |
1442 | rtl_dbg(rtlpriv, COMP_INIT | COMP_BEACON, DBG_LOUD, |
1443 | "SetBeaconRelatedRegisters8192CUsb(): Set TCR(%x)\n" , |
1444 | value32); |
1445 | /* TODO: Modify later (Find the right parameters) |
1446 | * NOTE: Fix test chip's bug (about contention windows's randomness) */ |
1447 | if ((mac->opmode == NL80211_IFTYPE_ADHOC) || |
1448 | (mac->opmode == NL80211_IFTYPE_MESH_POINT) || |
1449 | (mac->opmode == NL80211_IFTYPE_AP)) { |
1450 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, val8: 0x50); |
1451 | rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, val8: 0x50); |
1452 | } |
1453 | _beacon_function_enable(hw); |
1454 | } |
1455 | |
1456 | void rtl92cu_set_beacon_interval(struct ieee80211_hw *hw) |
1457 | { |
1458 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1459 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
1460 | u16 bcn_interval = mac->beacon_interval; |
1461 | |
1462 | rtl_dbg(rtlpriv, COMP_BEACON, DBG_DMESG, "beacon_interval:%d\n" , |
1463 | bcn_interval); |
1464 | rtl_write_word(rtlpriv, REG_BCN_INTERVAL, val16: bcn_interval); |
1465 | } |
1466 | |
1467 | void rtl92cu_update_interrupt_mask(struct ieee80211_hw *hw, |
1468 | u32 add_msr, u32 rm_msr) |
1469 | { |
1470 | } |
1471 | |
1472 | void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) |
1473 | { |
1474 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1475 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
1476 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
1477 | |
1478 | switch (variable) { |
1479 | case HW_VAR_RCR: |
1480 | *((u32 *)(val)) = mac->rx_conf; |
1481 | break; |
1482 | case HW_VAR_RF_STATE: |
1483 | *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; |
1484 | break; |
1485 | case HW_VAR_FWLPS_RF_ON:{ |
1486 | enum rf_pwrstate rfstate; |
1487 | u32 val_rcr; |
1488 | |
1489 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE, |
1490 | (u8 *)(&rfstate)); |
1491 | if (rfstate == ERFOFF) { |
1492 | *((bool *) (val)) = true; |
1493 | } else { |
1494 | val_rcr = rtl_read_dword(rtlpriv, REG_RCR); |
1495 | val_rcr &= 0x00070000; |
1496 | if (val_rcr) |
1497 | *((bool *) (val)) = false; |
1498 | else |
1499 | *((bool *) (val)) = true; |
1500 | } |
1501 | break; |
1502 | } |
1503 | case HW_VAR_FW_PSMODE_STATUS: |
1504 | *((bool *) (val)) = ppsc->fw_current_inpsmode; |
1505 | break; |
1506 | case HW_VAR_CORRECT_TSF:{ |
1507 | u64 tsf; |
1508 | u32 *ptsf_low = (u32 *)&tsf; |
1509 | u32 *ptsf_high = ((u32 *)&tsf) + 1; |
1510 | |
1511 | *ptsf_high = rtl_read_dword(rtlpriv, addr: (REG_TSFTR + 4)); |
1512 | *ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR); |
1513 | *((u64 *)(val)) = tsf; |
1514 | break; |
1515 | } |
1516 | case HW_VAR_MGT_FILTER: |
1517 | *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP0); |
1518 | break; |
1519 | case HW_VAR_CTRL_FILTER: |
1520 | *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP1); |
1521 | break; |
1522 | case HW_VAR_DATA_FILTER: |
1523 | *((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP2); |
1524 | break; |
1525 | case HAL_DEF_WOWLAN: |
1526 | break; |
1527 | default: |
1528 | pr_err("switch case %#x not processed\n" , variable); |
1529 | break; |
1530 | } |
1531 | } |
1532 | |
1533 | static bool usb_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb) |
1534 | { |
1535 | /* Currently nothing happens here. |
1536 | * Traffic stops after some seconds in WPA2 802.11n mode. |
1537 | * Maybe because rtl8192cu chip should be set from here? |
1538 | * If I understand correctly, the realtek vendor driver sends some urbs |
1539 | * if its "here". |
1540 | * |
1541 | * This is maybe necessary: |
1542 | * rtlpriv->cfg->ops->fill_tx_cmddesc(hw, buffer, skb); |
1543 | */ |
1544 | dev_kfree_skb(skb); |
1545 | |
1546 | return true; |
1547 | } |
1548 | |
1549 | void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) |
1550 | { |
1551 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1552 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
1553 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
1554 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
1555 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
1556 | enum wireless_mode wirelessmode = mac->mode; |
1557 | u8 idx = 0; |
1558 | |
1559 | switch (variable) { |
1560 | case HW_VAR_ETHER_ADDR:{ |
1561 | for (idx = 0; idx < ETH_ALEN; idx++) { |
1562 | rtl_write_byte(rtlpriv, addr: (REG_MACID + idx), |
1563 | val8: val[idx]); |
1564 | } |
1565 | break; |
1566 | } |
1567 | case HW_VAR_BASIC_RATE:{ |
1568 | u16 rate_cfg = ((u16 *) val)[0]; |
1569 | u8 rate_index = 0; |
1570 | |
1571 | rate_cfg &= 0x15f; |
1572 | /* TODO */ |
1573 | /* if (mac->current_network.vender == HT_IOT_PEER_CISCO |
1574 | * && ((rate_cfg & 0x150) == 0)) { |
1575 | * rate_cfg |= 0x010; |
1576 | * } */ |
1577 | rate_cfg |= 0x01; |
1578 | rtl_write_byte(rtlpriv, REG_RRSR, val8: rate_cfg & 0xff); |
1579 | rtl_write_byte(rtlpriv, REG_RRSR + 1, |
1580 | val8: (rate_cfg >> 8) & 0xff); |
1581 | while (rate_cfg > 0x1) { |
1582 | rate_cfg >>= 1; |
1583 | rate_index++; |
1584 | } |
1585 | rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, |
1586 | val8: rate_index); |
1587 | break; |
1588 | } |
1589 | case HW_VAR_BSSID:{ |
1590 | for (idx = 0; idx < ETH_ALEN; idx++) { |
1591 | rtl_write_byte(rtlpriv, addr: (REG_BSSID + idx), |
1592 | val8: val[idx]); |
1593 | } |
1594 | break; |
1595 | } |
1596 | case HW_VAR_SIFS:{ |
1597 | rtl_write_byte(rtlpriv, REG_SIFS_CCK + 1, val8: val[0]); |
1598 | rtl_write_byte(rtlpriv, REG_SIFS_OFDM + 1, val8: val[1]); |
1599 | rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val8: val[0]); |
1600 | rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val8: val[0]); |
1601 | rtl_write_byte(rtlpriv, REG_R2T_SIFS+1, val8: val[0]); |
1602 | rtl_write_byte(rtlpriv, REG_T2T_SIFS+1, val8: val[0]); |
1603 | rtl_dbg(rtlpriv, COMP_MLME, DBG_LOUD, "HW_VAR_SIFS\n" ); |
1604 | break; |
1605 | } |
1606 | case HW_VAR_SLOT_TIME:{ |
1607 | u8 e_aci; |
1608 | u8 QOS_MODE = 1; |
1609 | |
1610 | rtl_write_byte(rtlpriv, REG_SLOT, val8: val[0]); |
1611 | rtl_dbg(rtlpriv, COMP_MLME, DBG_LOUD, |
1612 | "HW_VAR_SLOT_TIME %x\n" , val[0]); |
1613 | if (QOS_MODE) { |
1614 | for (e_aci = 0; e_aci < AC_MAX; e_aci++) |
1615 | rtlpriv->cfg->ops->set_hw_reg(hw, |
1616 | HW_VAR_AC_PARAM, |
1617 | &e_aci); |
1618 | } else { |
1619 | u8 sifstime = 0; |
1620 | u8 u1baifs; |
1621 | |
1622 | if (IS_WIRELESS_MODE_A(wirelessmode) || |
1623 | IS_WIRELESS_MODE_N_24G(wirelessmode) || |
1624 | IS_WIRELESS_MODE_N_5G(wirelessmode)) |
1625 | sifstime = 16; |
1626 | else |
1627 | sifstime = 10; |
1628 | u1baifs = sifstime + (2 * val[0]); |
1629 | rtl_write_byte(rtlpriv, REG_EDCA_VO_PARAM, |
1630 | val8: u1baifs); |
1631 | rtl_write_byte(rtlpriv, REG_EDCA_VI_PARAM, |
1632 | val8: u1baifs); |
1633 | rtl_write_byte(rtlpriv, REG_EDCA_BE_PARAM, |
1634 | val8: u1baifs); |
1635 | rtl_write_byte(rtlpriv, REG_EDCA_BK_PARAM, |
1636 | val8: u1baifs); |
1637 | } |
1638 | break; |
1639 | } |
1640 | case HW_VAR_ACK_PREAMBLE:{ |
1641 | u8 reg_tmp; |
1642 | u8 short_preamble = (bool)*val; |
1643 | |
1644 | reg_tmp = 0; |
1645 | if (short_preamble) |
1646 | reg_tmp |= 0x80; |
1647 | rtl_write_byte(rtlpriv, REG_RRSR + 2, val8: reg_tmp); |
1648 | break; |
1649 | } |
1650 | case HW_VAR_AMPDU_MIN_SPACE:{ |
1651 | u8 min_spacing_to_set; |
1652 | u8 sec_min_space; |
1653 | |
1654 | min_spacing_to_set = *val; |
1655 | if (min_spacing_to_set <= 7) { |
1656 | switch (rtlpriv->sec.pairwise_enc_algorithm) { |
1657 | case NO_ENCRYPTION: |
1658 | case AESCCMP_ENCRYPTION: |
1659 | sec_min_space = 0; |
1660 | break; |
1661 | case WEP40_ENCRYPTION: |
1662 | case WEP104_ENCRYPTION: |
1663 | case TKIP_ENCRYPTION: |
1664 | sec_min_space = 6; |
1665 | break; |
1666 | default: |
1667 | sec_min_space = 7; |
1668 | break; |
1669 | } |
1670 | if (min_spacing_to_set < sec_min_space) |
1671 | min_spacing_to_set = sec_min_space; |
1672 | mac->min_space_cfg = ((mac->min_space_cfg & |
1673 | 0xf8) | |
1674 | min_spacing_to_set); |
1675 | *val = min_spacing_to_set; |
1676 | rtl_dbg(rtlpriv, COMP_MLME, DBG_LOUD, |
1677 | "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n" , |
1678 | mac->min_space_cfg); |
1679 | rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, |
1680 | val8: mac->min_space_cfg); |
1681 | } |
1682 | break; |
1683 | } |
1684 | case HW_VAR_SHORTGI_DENSITY:{ |
1685 | u8 density_to_set; |
1686 | |
1687 | density_to_set = *val; |
1688 | density_to_set &= 0x1f; |
1689 | mac->min_space_cfg &= 0x07; |
1690 | mac->min_space_cfg |= (density_to_set << 3); |
1691 | rtl_dbg(rtlpriv, COMP_MLME, DBG_LOUD, |
1692 | "Set HW_VAR_SHORTGI_DENSITY: %#x\n" , |
1693 | mac->min_space_cfg); |
1694 | rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, |
1695 | val8: mac->min_space_cfg); |
1696 | break; |
1697 | } |
1698 | case HW_VAR_AMPDU_FACTOR:{ |
1699 | u8 regtoset_normal[4] = {0x41, 0xa8, 0x72, 0xb9}; |
1700 | u8 factor_toset; |
1701 | u8 *p_regtoset = NULL; |
1702 | u8 index = 0; |
1703 | |
1704 | p_regtoset = regtoset_normal; |
1705 | factor_toset = *val; |
1706 | if (factor_toset <= 3) { |
1707 | factor_toset = (1 << (factor_toset + 2)); |
1708 | if (factor_toset > 0xf) |
1709 | factor_toset = 0xf; |
1710 | for (index = 0; index < 4; index++) { |
1711 | if ((p_regtoset[index] & 0xf0) > |
1712 | (factor_toset << 4)) |
1713 | p_regtoset[index] = |
1714 | (p_regtoset[index] & 0x0f) |
1715 | | (factor_toset << 4); |
1716 | if ((p_regtoset[index] & 0x0f) > |
1717 | factor_toset) |
1718 | p_regtoset[index] = |
1719 | (p_regtoset[index] & 0xf0) |
1720 | | (factor_toset); |
1721 | rtl_write_byte(rtlpriv, |
1722 | addr: (REG_AGGLEN_LMT + index), |
1723 | val8: p_regtoset[index]); |
1724 | } |
1725 | rtl_dbg(rtlpriv, COMP_MLME, DBG_LOUD, |
1726 | "Set HW_VAR_AMPDU_FACTOR: %#x\n" , |
1727 | factor_toset); |
1728 | } |
1729 | break; |
1730 | } |
1731 | case HW_VAR_AC_PARAM:{ |
1732 | u8 e_aci = *val; |
1733 | u32 u4b_ac_param; |
1734 | u16 cw_min = le16_to_cpu(mac->ac[e_aci].cw_min); |
1735 | u16 cw_max = le16_to_cpu(mac->ac[e_aci].cw_max); |
1736 | u16 tx_op = le16_to_cpu(mac->ac[e_aci].tx_op); |
1737 | |
1738 | u4b_ac_param = (u32) mac->ac[e_aci].aifs; |
1739 | u4b_ac_param |= (u32) ((cw_min & 0xF) << |
1740 | AC_PARAM_ECW_MIN_OFFSET); |
1741 | u4b_ac_param |= (u32) ((cw_max & 0xF) << |
1742 | AC_PARAM_ECW_MAX_OFFSET); |
1743 | u4b_ac_param |= (u32) tx_op << AC_PARAM_TXOP_OFFSET; |
1744 | rtl_dbg(rtlpriv, COMP_MLME, DBG_LOUD, |
1745 | "queue:%x, ac_param:%x\n" , |
1746 | e_aci, u4b_ac_param); |
1747 | switch (e_aci) { |
1748 | case AC1_BK: |
1749 | rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, |
1750 | val32: u4b_ac_param); |
1751 | break; |
1752 | case AC0_BE: |
1753 | rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, |
1754 | val32: u4b_ac_param); |
1755 | break; |
1756 | case AC2_VI: |
1757 | rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, |
1758 | val32: u4b_ac_param); |
1759 | break; |
1760 | case AC3_VO: |
1761 | rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, |
1762 | val32: u4b_ac_param); |
1763 | break; |
1764 | default: |
1765 | WARN_ONCE(true, "rtl8192cu: invalid aci: %d !\n" , |
1766 | e_aci); |
1767 | break; |
1768 | } |
1769 | break; |
1770 | } |
1771 | case HW_VAR_RCR:{ |
1772 | rtl_write_dword(rtlpriv, REG_RCR, val32: ((u32 *) (val))[0]); |
1773 | mac->rx_conf = ((u32 *) (val))[0]; |
1774 | rtl_dbg(rtlpriv, COMP_RECV, DBG_DMESG, |
1775 | "### Set RCR(0x%08x) ###\n" , mac->rx_conf); |
1776 | break; |
1777 | } |
1778 | case HW_VAR_RETRY_LIMIT:{ |
1779 | u8 retry_limit = val[0]; |
1780 | |
1781 | rtl_write_word(rtlpriv, REG_RL, |
1782 | val16: retry_limit << RETRY_LIMIT_SHORT_SHIFT | |
1783 | retry_limit << RETRY_LIMIT_LONG_SHIFT); |
1784 | rtl_dbg(rtlpriv, COMP_MLME, DBG_DMESG, |
1785 | "Set HW_VAR_RETRY_LIMIT(0x%08x)\n" , |
1786 | retry_limit); |
1787 | break; |
1788 | } |
1789 | case HW_VAR_DUAL_TSF_RST: |
1790 | rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, val8: (BIT(0) | BIT(1))); |
1791 | break; |
1792 | case HW_VAR_EFUSE_BYTES: |
1793 | rtlefuse->efuse_usedbytes = *((u16 *) val); |
1794 | break; |
1795 | case HW_VAR_EFUSE_USAGE: |
1796 | rtlefuse->efuse_usedpercentage = *val; |
1797 | break; |
1798 | case HW_VAR_IO_CMD: |
1799 | rtl92c_phy_set_io_cmd(hw, iotype: (*(enum io_type *)val)); |
1800 | break; |
1801 | case HW_VAR_WPA_CONFIG: |
1802 | rtl_write_byte(rtlpriv, REG_SECCFG, val8: *val); |
1803 | break; |
1804 | case HW_VAR_SET_RPWM:{ |
1805 | u8 rpwm_val = rtl_read_byte(rtlpriv, REG_USB_HRPWM); |
1806 | |
1807 | if (rpwm_val & BIT(7)) |
1808 | rtl_write_byte(rtlpriv, REG_USB_HRPWM, val8: *val); |
1809 | else |
1810 | rtl_write_byte(rtlpriv, REG_USB_HRPWM, |
1811 | val8: *val | BIT(7)); |
1812 | break; |
1813 | } |
1814 | case HW_VAR_H2C_FW_PWRMODE:{ |
1815 | u8 psmode = *val; |
1816 | |
1817 | if ((psmode != FW_PS_ACTIVE_MODE) && |
1818 | (!IS_92C_SERIAL(rtlhal->version))) |
1819 | rtl92c_dm_rf_saving(hw, bforce_in_normal: true); |
1820 | rtl92c_set_fw_pwrmode_cmd(hw, mode: (*val)); |
1821 | break; |
1822 | } |
1823 | case HW_VAR_FW_PSMODE_STATUS: |
1824 | ppsc->fw_current_inpsmode = *((bool *) val); |
1825 | break; |
1826 | case HW_VAR_H2C_FW_JOINBSSRPT:{ |
1827 | u8 mstatus = *val; |
1828 | u8 tmp_reg422; |
1829 | bool recover = false; |
1830 | |
1831 | if (mstatus == RT_MEDIA_CONNECT) { |
1832 | rtlpriv->cfg->ops->set_hw_reg(hw, |
1833 | HW_VAR_AID, NULL); |
1834 | rtl_write_byte(rtlpriv, REG_CR + 1, val8: 0x03); |
1835 | _rtl92cu_set_bcn_ctrl_reg(hw, set_bits: 0, BIT(3)); |
1836 | _rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), clear_bits: 0); |
1837 | tmp_reg422 = rtl_read_byte(rtlpriv, |
1838 | REG_FWHW_TXQ_CTRL + 2); |
1839 | if (tmp_reg422 & BIT(6)) |
1840 | recover = true; |
1841 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, |
1842 | val8: tmp_reg422 & (~BIT(6))); |
1843 | rtl92c_set_fw_rsvdpagepkt(hw, |
1844 | cmd_send_packet: &usb_cmd_send_packet); |
1845 | _rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), clear_bits: 0); |
1846 | _rtl92cu_set_bcn_ctrl_reg(hw, set_bits: 0, BIT(4)); |
1847 | if (recover) |
1848 | rtl_write_byte(rtlpriv, |
1849 | REG_FWHW_TXQ_CTRL + 2, |
1850 | val8: tmp_reg422 | BIT(6)); |
1851 | rtl_write_byte(rtlpriv, REG_CR + 1, val8: 0x02); |
1852 | } |
1853 | rtl92c_set_fw_joinbss_report_cmd(hw, mstatus: (*val)); |
1854 | break; |
1855 | } |
1856 | case HW_VAR_AID:{ |
1857 | u16 u2btmp; |
1858 | |
1859 | u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT); |
1860 | u2btmp &= 0xC000; |
1861 | rtl_write_word(rtlpriv, REG_BCN_PSR_RPT, |
1862 | val16: (u2btmp | mac->assoc_id)); |
1863 | break; |
1864 | } |
1865 | case HW_VAR_CORRECT_TSF:{ |
1866 | u8 btype_ibss = val[0]; |
1867 | |
1868 | if (btype_ibss) |
1869 | _rtl92cu_stop_tx_beacon(hw); |
1870 | _rtl92cu_set_bcn_ctrl_reg(hw, set_bits: 0, BIT(3)); |
1871 | rtl_write_dword(rtlpriv, REG_TSFTR, val32: (u32)(mac->tsf & |
1872 | 0xffffffff)); |
1873 | rtl_write_dword(rtlpriv, REG_TSFTR + 4, |
1874 | val32: (u32)((mac->tsf >> 32) & 0xffffffff)); |
1875 | _rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), clear_bits: 0); |
1876 | if (btype_ibss) |
1877 | _rtl92cu_resume_tx_beacon(hw); |
1878 | break; |
1879 | } |
1880 | case HW_VAR_MGT_FILTER: |
1881 | rtl_write_word(rtlpriv, REG_RXFLTMAP0, val16: *(u16 *)val); |
1882 | mac->rx_mgt_filter = *(u16 *)val; |
1883 | break; |
1884 | case HW_VAR_CTRL_FILTER: |
1885 | rtl_write_word(rtlpriv, REG_RXFLTMAP1, val16: *(u16 *)val); |
1886 | mac->rx_ctrl_filter = *(u16 *)val; |
1887 | break; |
1888 | case HW_VAR_DATA_FILTER: |
1889 | rtl_write_word(rtlpriv, REG_RXFLTMAP2, val16: *(u16 *)val); |
1890 | mac->rx_data_filter = *(u16 *)val; |
1891 | break; |
1892 | case HW_VAR_KEEP_ALIVE:{ |
1893 | u8 array[2]; |
1894 | |
1895 | array[0] = 0xff; |
1896 | array[1] = *((u8 *)val); |
1897 | rtl92c_fill_h2c_cmd(hw, H2C_92C_KEEP_ALIVE_CTRL, cmd_len: 2, |
1898 | p_cmdbuffer: array); |
1899 | break; |
1900 | } |
1901 | default: |
1902 | pr_err("switch case %#x not processed\n" , variable); |
1903 | break; |
1904 | } |
1905 | } |
1906 | |
1907 | static void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw, |
1908 | struct ieee80211_sta *sta) |
1909 | { |
1910 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1911 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
1912 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
1913 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
1914 | u32 ratr_value; |
1915 | u8 ratr_index = 0; |
1916 | u8 nmode = mac->ht_enable; |
1917 | u8 mimo_ps = IEEE80211_SMPS_OFF; |
1918 | u16 shortgi_rate; |
1919 | u32 tmp_ratr_value; |
1920 | u8 curtxbw_40mhz = mac->bw_40; |
1921 | u8 curshortgi_40mhz = (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? |
1922 | 1 : 0; |
1923 | u8 curshortgi_20mhz = (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? |
1924 | 1 : 0; |
1925 | enum wireless_mode wirelessmode = mac->mode; |
1926 | |
1927 | if (rtlhal->current_bandtype == BAND_ON_5G) |
1928 | ratr_value = sta->deflink.supp_rates[1] << 4; |
1929 | else |
1930 | ratr_value = sta->deflink.supp_rates[0]; |
1931 | if (mac->opmode == NL80211_IFTYPE_ADHOC) |
1932 | ratr_value = 0xfff; |
1933 | |
1934 | ratr_value |= (sta->deflink.ht_cap.mcs.rx_mask[1] << 20 | |
1935 | sta->deflink.ht_cap.mcs.rx_mask[0] << 12); |
1936 | switch (wirelessmode) { |
1937 | case WIRELESS_MODE_B: |
1938 | if (ratr_value & 0x0000000c) |
1939 | ratr_value &= 0x0000000d; |
1940 | else |
1941 | ratr_value &= 0x0000000f; |
1942 | break; |
1943 | case WIRELESS_MODE_G: |
1944 | ratr_value &= 0x00000FF5; |
1945 | break; |
1946 | case WIRELESS_MODE_N_24G: |
1947 | case WIRELESS_MODE_N_5G: |
1948 | nmode = 1; |
1949 | if (mimo_ps == IEEE80211_SMPS_STATIC) { |
1950 | ratr_value &= 0x0007F005; |
1951 | } else { |
1952 | u32 ratr_mask; |
1953 | |
1954 | if (get_rf_type(rtlphy) == RF_1T2R || |
1955 | get_rf_type(rtlphy) == RF_1T1R) |
1956 | ratr_mask = 0x000ff005; |
1957 | else |
1958 | ratr_mask = 0x0f0ff005; |
1959 | |
1960 | ratr_value &= ratr_mask; |
1961 | } |
1962 | break; |
1963 | default: |
1964 | if (rtlphy->rf_type == RF_1T2R) |
1965 | ratr_value &= 0x000ff0ff; |
1966 | else |
1967 | ratr_value &= 0x0f0ff0ff; |
1968 | |
1969 | break; |
1970 | } |
1971 | |
1972 | ratr_value &= 0x0FFFFFFF; |
1973 | |
1974 | if (nmode && ((curtxbw_40mhz && |
1975 | curshortgi_40mhz) || (!curtxbw_40mhz && |
1976 | curshortgi_20mhz))) { |
1977 | ratr_value |= 0x10000000; |
1978 | tmp_ratr_value = (ratr_value >> 12); |
1979 | |
1980 | for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { |
1981 | if ((1 << shortgi_rate) & tmp_ratr_value) |
1982 | break; |
1983 | } |
1984 | |
1985 | shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | |
1986 | (shortgi_rate << 4) | (shortgi_rate); |
1987 | } |
1988 | |
1989 | rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, val32: ratr_value); |
1990 | |
1991 | rtl_dbg(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n" , |
1992 | rtl_read_dword(rtlpriv, REG_ARFR0)); |
1993 | } |
1994 | |
1995 | static void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, |
1996 | struct ieee80211_sta *sta, |
1997 | u8 , bool update_bw) |
1998 | { |
1999 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
2000 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
2001 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
2002 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
2003 | struct rtl_sta_info *sta_entry = NULL; |
2004 | u32 ratr_bitmap; |
2005 | u8 ratr_index; |
2006 | u8 curtxbw_40mhz = (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40) ? 1 : 0; |
2007 | u8 curshortgi_40mhz = curtxbw_40mhz && |
2008 | (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? |
2009 | 1 : 0; |
2010 | u8 curshortgi_20mhz = (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? |
2011 | 1 : 0; |
2012 | enum wireless_mode wirelessmode = 0; |
2013 | bool shortgi = false; |
2014 | u8 rate_mask[5]; |
2015 | u8 macid = 0; |
2016 | u8 mimo_ps = IEEE80211_SMPS_OFF; |
2017 | |
2018 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; |
2019 | wirelessmode = sta_entry->wireless_mode; |
2020 | if (mac->opmode == NL80211_IFTYPE_STATION || |
2021 | mac->opmode == NL80211_IFTYPE_MESH_POINT) |
2022 | curtxbw_40mhz = mac->bw_40; |
2023 | else if (mac->opmode == NL80211_IFTYPE_AP || |
2024 | mac->opmode == NL80211_IFTYPE_ADHOC) |
2025 | macid = sta->aid + 1; |
2026 | |
2027 | if (rtlhal->current_bandtype == BAND_ON_5G) |
2028 | ratr_bitmap = sta->deflink.supp_rates[1] << 4; |
2029 | else |
2030 | ratr_bitmap = sta->deflink.supp_rates[0]; |
2031 | if (mac->opmode == NL80211_IFTYPE_ADHOC) |
2032 | ratr_bitmap = 0xfff; |
2033 | ratr_bitmap |= (sta->deflink.ht_cap.mcs.rx_mask[1] << 20 | |
2034 | sta->deflink.ht_cap.mcs.rx_mask[0] << 12); |
2035 | switch (wirelessmode) { |
2036 | case WIRELESS_MODE_B: |
2037 | ratr_index = RATR_INX_WIRELESS_B; |
2038 | if (ratr_bitmap & 0x0000000c) |
2039 | ratr_bitmap &= 0x0000000d; |
2040 | else |
2041 | ratr_bitmap &= 0x0000000f; |
2042 | break; |
2043 | case WIRELESS_MODE_G: |
2044 | ratr_index = RATR_INX_WIRELESS_GB; |
2045 | |
2046 | if (rssi_level == 1) |
2047 | ratr_bitmap &= 0x00000f00; |
2048 | else if (rssi_level == 2) |
2049 | ratr_bitmap &= 0x00000ff0; |
2050 | else |
2051 | ratr_bitmap &= 0x00000ff5; |
2052 | break; |
2053 | case WIRELESS_MODE_A: |
2054 | ratr_index = RATR_INX_WIRELESS_A; |
2055 | ratr_bitmap &= 0x00000ff0; |
2056 | break; |
2057 | case WIRELESS_MODE_N_24G: |
2058 | case WIRELESS_MODE_N_5G: |
2059 | ratr_index = RATR_INX_WIRELESS_NGB; |
2060 | |
2061 | if (mimo_ps == IEEE80211_SMPS_STATIC) { |
2062 | if (rssi_level == 1) |
2063 | ratr_bitmap &= 0x00070000; |
2064 | else if (rssi_level == 2) |
2065 | ratr_bitmap &= 0x0007f000; |
2066 | else |
2067 | ratr_bitmap &= 0x0007f005; |
2068 | } else { |
2069 | if (rtlphy->rf_type == RF_1T2R || |
2070 | rtlphy->rf_type == RF_1T1R) { |
2071 | if (curtxbw_40mhz) { |
2072 | if (rssi_level == 1) |
2073 | ratr_bitmap &= 0x000f0000; |
2074 | else if (rssi_level == 2) |
2075 | ratr_bitmap &= 0x000ff000; |
2076 | else |
2077 | ratr_bitmap &= 0x000ff015; |
2078 | } else { |
2079 | if (rssi_level == 1) |
2080 | ratr_bitmap &= 0x000f0000; |
2081 | else if (rssi_level == 2) |
2082 | ratr_bitmap &= 0x000ff000; |
2083 | else |
2084 | ratr_bitmap &= 0x000ff005; |
2085 | } |
2086 | } else { |
2087 | if (curtxbw_40mhz) { |
2088 | if (rssi_level == 1) |
2089 | ratr_bitmap &= 0x0f0f0000; |
2090 | else if (rssi_level == 2) |
2091 | ratr_bitmap &= 0x0f0ff000; |
2092 | else |
2093 | ratr_bitmap &= 0x0f0ff015; |
2094 | } else { |
2095 | if (rssi_level == 1) |
2096 | ratr_bitmap &= 0x0f0f0000; |
2097 | else if (rssi_level == 2) |
2098 | ratr_bitmap &= 0x0f0ff000; |
2099 | else |
2100 | ratr_bitmap &= 0x0f0ff005; |
2101 | } |
2102 | } |
2103 | } |
2104 | |
2105 | if ((curtxbw_40mhz && curshortgi_40mhz) || |
2106 | (!curtxbw_40mhz && curshortgi_20mhz)) { |
2107 | |
2108 | if (macid == 0) |
2109 | shortgi = true; |
2110 | else if (macid == 1) |
2111 | shortgi = false; |
2112 | } |
2113 | break; |
2114 | default: |
2115 | ratr_index = RATR_INX_WIRELESS_NGB; |
2116 | |
2117 | if (rtlphy->rf_type == RF_1T2R) |
2118 | ratr_bitmap &= 0x000ff0ff; |
2119 | else |
2120 | ratr_bitmap &= 0x0f0ff0ff; |
2121 | break; |
2122 | } |
2123 | sta_entry->ratr_index = ratr_index; |
2124 | |
2125 | rtl_dbg(rtlpriv, COMP_RATR, DBG_DMESG, |
2126 | "ratr_bitmap :%x\n" , ratr_bitmap); |
2127 | *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | |
2128 | (ratr_index << 28); |
2129 | rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; |
2130 | rtl_dbg(rtlpriv, COMP_RATR, DBG_DMESG, |
2131 | "Rate_index:%x, ratr_val:%x, %5phC\n" , |
2132 | ratr_index, ratr_bitmap, rate_mask); |
2133 | memcpy(rtlpriv->rate_mask, rate_mask, 5); |
2134 | /* rtl92c_fill_h2c_cmd() does USB I/O and will result in a |
2135 | * "scheduled while atomic" if called directly */ |
2136 | schedule_work(work: &rtlpriv->works.fill_h2c_cmd); |
2137 | |
2138 | if (macid != 0) |
2139 | sta_entry->ratr_index = ratr_index; |
2140 | } |
2141 | |
2142 | void rtl92cu_update_hal_rate_tbl(struct ieee80211_hw *hw, |
2143 | struct ieee80211_sta *sta, |
2144 | u8 , bool update_bw) |
2145 | { |
2146 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
2147 | |
2148 | if (rtlpriv->dm.useramask) |
2149 | rtl92cu_update_hal_rate_mask(hw, sta, rssi_level, update_bw); |
2150 | else |
2151 | rtl92cu_update_hal_rate_table(hw, sta); |
2152 | } |
2153 | |
2154 | void rtl92cu_update_channel_access_setting(struct ieee80211_hw *hw) |
2155 | { |
2156 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
2157 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
2158 | u16 sifs_timer; |
2159 | |
2160 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, |
2161 | &mac->slot_time); |
2162 | if (!mac->ht_enable) |
2163 | sifs_timer = 0x0a0a; |
2164 | else |
2165 | sifs_timer = 0x0e0e; |
2166 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); |
2167 | } |
2168 | |
2169 | bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid) |
2170 | { |
2171 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
2172 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
2173 | enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate; |
2174 | u8 u1tmp = 0; |
2175 | bool actuallyset = false; |
2176 | unsigned long flag = 0; |
2177 | /* to do - usb autosuspend */ |
2178 | u8 usb_autosuspend = 0; |
2179 | |
2180 | if (ppsc->swrf_processing) |
2181 | return false; |
2182 | spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); |
2183 | if (ppsc->rfchange_inprogress) { |
2184 | spin_unlock_irqrestore(lock: &rtlpriv->locks.rf_ps_lock, flags: flag); |
2185 | return false; |
2186 | } else { |
2187 | ppsc->rfchange_inprogress = true; |
2188 | spin_unlock_irqrestore(lock: &rtlpriv->locks.rf_ps_lock, flags: flag); |
2189 | } |
2190 | cur_rfstate = ppsc->rfpwr_state; |
2191 | if (usb_autosuspend) { |
2192 | /* to do................... */ |
2193 | } else { |
2194 | if (ppsc->pwrdown_mode) { |
2195 | u1tmp = rtl_read_byte(rtlpriv, REG_HSISR); |
2196 | e_rfpowerstate_toset = (u1tmp & BIT(7)) ? |
2197 | ERFOFF : ERFON; |
2198 | rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, |
2199 | "pwrdown, 0x5c(BIT7)=%02x\n" , u1tmp); |
2200 | } else { |
2201 | rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG, |
2202 | val8: rtl_read_byte(rtlpriv, |
2203 | REG_MAC_PINMUX_CFG) & ~(BIT(3))); |
2204 | u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL); |
2205 | e_rfpowerstate_toset = (u1tmp & BIT(3)) ? |
2206 | ERFON : ERFOFF; |
2207 | rtl_dbg(rtlpriv, COMP_POWER, DBG_DMESG, |
2208 | "GPIO_IN=%02x\n" , u1tmp); |
2209 | } |
2210 | rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, "N-SS RF =%x\n" , |
2211 | e_rfpowerstate_toset); |
2212 | } |
2213 | if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) { |
2214 | rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, |
2215 | "GPIOChangeRF - HW Radio ON, RF ON\n" ); |
2216 | ppsc->hwradiooff = false; |
2217 | actuallyset = true; |
2218 | } else if ((!ppsc->hwradiooff) && (e_rfpowerstate_toset == |
2219 | ERFOFF)) { |
2220 | rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, |
2221 | "GPIOChangeRF - HW Radio OFF\n" ); |
2222 | ppsc->hwradiooff = true; |
2223 | actuallyset = true; |
2224 | } else { |
2225 | rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, |
2226 | "pHalData->bHwRadioOff and eRfPowerStateToSet do not match: pHalData->bHwRadioOff %x, eRfPowerStateToSet %x\n" , |
2227 | ppsc->hwradiooff, e_rfpowerstate_toset); |
2228 | } |
2229 | if (actuallyset) { |
2230 | ppsc->hwradiooff = true; |
2231 | if (e_rfpowerstate_toset == ERFON) { |
2232 | if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) && |
2233 | RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM)) |
2234 | RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); |
2235 | else if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_PCI_D3) |
2236 | && RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3)) |
2237 | RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3); |
2238 | } |
2239 | spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); |
2240 | ppsc->rfchange_inprogress = false; |
2241 | spin_unlock_irqrestore(lock: &rtlpriv->locks.rf_ps_lock, flags: flag); |
2242 | /* For power down module, we need to enable register block |
2243 | * contrl reg at 0x1c. Then enable power down control bit |
2244 | * of register 0x04 BIT4 and BIT15 as 1. |
2245 | */ |
2246 | if (ppsc->pwrdown_mode && e_rfpowerstate_toset == ERFOFF) { |
2247 | /* Enable register area 0x0-0xc. */ |
2248 | rtl_write_byte(rtlpriv, REG_RSV_CTRL, val8: 0x0); |
2249 | rtl_write_word(rtlpriv, REG_APS_FSMCO, val16: 0x8812); |
2250 | } |
2251 | if (e_rfpowerstate_toset == ERFOFF) { |
2252 | if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) |
2253 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); |
2254 | else if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_PCI_D3) |
2255 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3); |
2256 | } |
2257 | } else if (e_rfpowerstate_toset == ERFOFF || cur_rfstate == ERFOFF) { |
2258 | /* Enter D3 or ASPM after GPIO had been done. */ |
2259 | if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) |
2260 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM); |
2261 | else if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_PCI_D3) |
2262 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3); |
2263 | spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); |
2264 | ppsc->rfchange_inprogress = false; |
2265 | spin_unlock_irqrestore(lock: &rtlpriv->locks.rf_ps_lock, flags: flag); |
2266 | } else { |
2267 | spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); |
2268 | ppsc->rfchange_inprogress = false; |
2269 | spin_unlock_irqrestore(lock: &rtlpriv->locks.rf_ps_lock, flags: flag); |
2270 | } |
2271 | *valid = 1; |
2272 | return !ppsc->hwradiooff; |
2273 | } |
2274 | |