blob: 9d7b11b639573383789cb593c014af36e22d00f9 [file] [log] [blame]
Larry Fingerf7c92d22014-03-28 21:37:39 -05001/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
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 ******************************************************************************/
15#include <osdep_service.h>
16#include <drv_types.h>
17
18#include <hal_intf.h>
19#include <hal_com.h>
20#include <rtl8723a_hal.h>
Jes Sorensen050abc42014-05-16 10:05:08 +020021#include <usb_ops_linux.h>
Larry Fingerf7c92d22014-03-28 21:37:39 -050022
23#define _HAL_INIT_C_
24
Larry Fingerf7c92d22014-03-28 21:37:39 -050025#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80
26
27/* return the final channel plan decision */
28/* hw_channel_plan: channel plan from HW (efuse/eeprom) */
29/* sw_channel_plan: channel plan from SW (registry/module param) */
30/* def_channel_plan: channel plan used when the former two is invalid */
31u8 hal_com_get_channel_plan23a(struct rtw_adapter *padapter, u8 hw_channel_plan,
32 u8 sw_channel_plan, u8 def_channel_plan,
33 bool AutoLoadFail)
34{
35 u8 swConfig;
36 u8 chnlPlan;
37
38 swConfig = true;
39 if (!AutoLoadFail) {
40 if (!rtw_is_channel_plan_valid(sw_channel_plan))
41 swConfig = false;
42 if (hw_channel_plan & EEPROM_CHANNEL_PLAN_BY_HW_MASK)
43 swConfig = false;
44 }
45
46 if (swConfig == true)
47 chnlPlan = sw_channel_plan;
48 else
49 chnlPlan = hw_channel_plan & (~EEPROM_CHANNEL_PLAN_BY_HW_MASK);
50
51 if (!rtw_is_channel_plan_valid(chnlPlan))
52 chnlPlan = def_channel_plan;
53
54 return chnlPlan;
55}
56
57u8 MRateToHwRate23a(u8 rate)
58{
59 u8 ret = DESC_RATE1M;
60
61 switch (rate) {
62 /* CCK and OFDM non-HT rates */
63 case IEEE80211_CCK_RATE_1MB:
64 ret = DESC_RATE1M;
65 break;
66 case IEEE80211_CCK_RATE_2MB:
67 ret = DESC_RATE2M;
68 break;
69 case IEEE80211_CCK_RATE_5MB:
70 ret = DESC_RATE5_5M;
71 break;
72 case IEEE80211_CCK_RATE_11MB:
73 ret = DESC_RATE11M;
74 break;
75 case IEEE80211_OFDM_RATE_6MB:
76 ret = DESC_RATE6M;
77 break;
78 case IEEE80211_OFDM_RATE_9MB:
79 ret = DESC_RATE9M;
80 break;
81 case IEEE80211_OFDM_RATE_12MB:
82 ret = DESC_RATE12M;
83 break;
84 case IEEE80211_OFDM_RATE_18MB:
85 ret = DESC_RATE18M;
86 break;
87 case IEEE80211_OFDM_RATE_24MB:
88 ret = DESC_RATE24M;
89 break;
90 case IEEE80211_OFDM_RATE_36MB:
91 ret = DESC_RATE36M;
92 break;
93 case IEEE80211_OFDM_RATE_48MB:
94 ret = DESC_RATE48M;
95 break;
96 case IEEE80211_OFDM_RATE_54MB:
97 ret = DESC_RATE54M;
98 break;
99
100 /* HT rates since here */
101 /* case MGN_MCS0: ret = DESC_RATEMCS0; break; */
102 /* case MGN_MCS1: ret = DESC_RATEMCS1; break; */
103 /* case MGN_MCS2: ret = DESC_RATEMCS2; break; */
104 /* case MGN_MCS3: ret = DESC_RATEMCS3; break; */
105 /* case MGN_MCS4: ret = DESC_RATEMCS4; break; */
106 /* case MGN_MCS5: ret = DESC_RATEMCS5; break; */
107 /* case MGN_MCS6: ret = DESC_RATEMCS6; break; */
108 /* case MGN_MCS7: ret = DESC_RATEMCS7; break; */
109
110 default:
111 break;
112 }
113 return ret;
114}
115
116void HalSetBrateCfg23a(struct rtw_adapter *padapter, u8 *mBratesOS)
117{
118 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
119 u8 i, is_brate, brate;
120 u16 brate_cfg = 0;
121 u8 rate_index;
122
123 for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
124 is_brate = mBratesOS[i] & IEEE80211_BASIC_RATE_MASK;
125 brate = mBratesOS[i] & 0x7f;
126
127 if (is_brate) {
128 switch (brate) {
129 case IEEE80211_CCK_RATE_1MB:
130 brate_cfg |= RATE_1M;
131 break;
132 case IEEE80211_CCK_RATE_2MB:
133 brate_cfg |= RATE_2M;
134 break;
135 case IEEE80211_CCK_RATE_5MB:
136 brate_cfg |= RATE_5_5M;
137 break;
138 case IEEE80211_CCK_RATE_11MB:
139 brate_cfg |= RATE_11M;
140 break;
141 case IEEE80211_OFDM_RATE_6MB:
142 brate_cfg |= RATE_6M;
143 break;
144 case IEEE80211_OFDM_RATE_9MB:
145 brate_cfg |= RATE_9M;
146 break;
147 case IEEE80211_OFDM_RATE_12MB:
148 brate_cfg |= RATE_12M;
149 break;
150 case IEEE80211_OFDM_RATE_18MB:
151 brate_cfg |= RATE_18M;
152 break;
153 case IEEE80211_OFDM_RATE_24MB:
154 brate_cfg |= RATE_24M;
155 break;
156 case IEEE80211_OFDM_RATE_36MB:
157 brate_cfg |= RATE_36M;
158 break;
159 case IEEE80211_OFDM_RATE_48MB:
160 brate_cfg |= RATE_48M;
161 break;
162 case IEEE80211_OFDM_RATE_54MB:
163 brate_cfg |= RATE_54M;
164 break;
165 }
166 }
167 }
168
169 /* 2007.01.16, by Emily */
170 /* Select RRSR (in Legacy-OFDM and CCK) */
171 /* For 8190, we select only 24M, 12M, 6M, 11M, 5.5M, 2M,
172 and 1M from the Basic rate. */
173 /* We do not use other rates. */
174 /* 2011.03.30 add by Luke Lee */
175 /* CCK 2M ACK should be disabled for some BCM and Atheros AP IOT */
176 /* because CCK 2M has poor TXEVM */
177 /* CCK 5.5M & 11M ACK should be enabled for better
178 performance */
179
180 brate_cfg = (brate_cfg | 0xd) & 0x15d;
181 pHalData->BasicRateSet = brate_cfg;
182 brate_cfg |= 0x01; /* default enable 1M ACK rate */
183 DBG_8723A("HW_VAR_BASIC_RATE: BrateCfg(%#x)\n", brate_cfg);
184
185 /* Set RRSR rate table. */
Jes Sorensenedbfd672014-05-16 10:05:09 +0200186 rtl8723au_write8(padapter, REG_RRSR, brate_cfg & 0xff);
187 rtl8723au_write8(padapter, REG_RRSR + 1, (brate_cfg >> 8) & 0xff);
188 rtl8723au_write8(padapter, REG_RRSR + 2,
189 rtl8723au_read8(padapter, REG_RRSR + 2) & 0xf0);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500190
191 rate_index = 0;
192 /* Set RTS initial rate */
193 while (brate_cfg > 0x1) {
Aya Mahfouz26aab2b2015-02-26 11:29:04 +0200194 brate_cfg >>= 1;
Larry Fingerf7c92d22014-03-28 21:37:39 -0500195 rate_index++;
196 }
197 /* Ziv - Check */
Jes Sorensenedbfd672014-05-16 10:05:09 +0200198 rtl8723au_write8(padapter, REG_INIRTS_RATE_SEL, rate_index);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500199}
200
201static void _OneOutPipeMapping(struct rtw_adapter *pAdapter)
202{
203 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
204
205 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */
206 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */
207 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[0]; /* BE */
208 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0]; /* BK */
209
210 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
211 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
212 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
213 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD */
214}
215
216static void _TwoOutPipeMapping(struct rtw_adapter *pAdapter, bool bWIFICfg)
217{
218 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
219
220 if (bWIFICfg) { /* WMM */
221 /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
222 /* 0, 1, 0, 1, 0, 0, 0, 0, 0 }; */
223 /* 0:H, 1:L */
224 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[1]; /* VO */
225 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */
226 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1]; /* BE */
227 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0]; /* BK */
228
229 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
230 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
231 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
232 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
233 } else { /* typical setting */
234 /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
235 /* 1, 1, 0, 0, 0, 0, 0, 0, 0 }; */
236 /* 0:H, 1:L */
237 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */
238 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */
239 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1]; /* BE */
240 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1]; /* BK */
241
242 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
243 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
244 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
245 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
246 }
247}
248
249static void _ThreeOutPipeMapping(struct rtw_adapter *pAdapter, bool bWIFICfg)
250{
251 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
252
253 if (bWIFICfg) { /* for WMM */
254 /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
255 /* 1, 2, 1, 0, 0, 0, 0, 0, 0 }; */
256 /* 0:H, 1:N, 2:L */
257 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */
258 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1]; /* VI */
259 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2]; /* BE */
260 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1]; /* BK */
261
262 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
263 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
264 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
265 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
266 } else { /* typical setting */
267 /* BK, BE, VI, VO, BCN, CMD, MGT, HIGH, HCCA */
268 /* 2, 2, 1, 0, 0, 0, 0, 0, 0 }; */
269 /* 0:H, 1:N, 2:L */
270 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */
271 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1]; /* VI */
272 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2]; /* BE */
273 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[2]; /* BK */
274
275 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
276 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
277 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
278 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
279 }
280}
281
282bool Hal_MappingOutPipe23a(struct rtw_adapter *pAdapter, u8 NumOutPipe)
283{
284 struct registry_priv *pregistrypriv = &pAdapter->registrypriv;
285 bool bWIFICfg = (pregistrypriv->wifi_spec) ? true : false;
286 bool result = true;
287
288 switch (NumOutPipe) {
289 case 2:
290 _TwoOutPipeMapping(pAdapter, bWIFICfg);
291 break;
292 case 3:
293 _ThreeOutPipeMapping(pAdapter, bWIFICfg);
294 break;
295 case 1:
296 _OneOutPipeMapping(pAdapter);
297 break;
298 default:
299 result = false;
300 break;
301 }
302
303 return result;
304}
305
Larry Fingerf7c92d22014-03-28 21:37:39 -0500306/*
307* C2H event format:
308* Field TRIGGER CONTENT CMD_SEQ CMD_LEN CMD_ID
309* BITS [127:120] [119:16] [15:8] [7:4] [3:0]
310*/
311
312void c2h_evt_clear23a(struct rtw_adapter *adapter)
313{
Jes Sorensenedbfd672014-05-16 10:05:09 +0200314 rtl8723au_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500315}
316
Jes Sorensen18bd6df2014-05-16 10:04:50 +0200317int c2h_evt_read23a(struct rtw_adapter *adapter, u8 *buf)
Larry Fingerf7c92d22014-03-28 21:37:39 -0500318{
Jes Sorensen18bd6df2014-05-16 10:04:50 +0200319 int ret = _FAIL;
Larry Fingerf7c92d22014-03-28 21:37:39 -0500320 struct c2h_evt_hdr *c2h_evt;
321 int i;
322 u8 trigger;
323
324 if (buf == NULL)
325 goto exit;
326
Jes Sorensen050abc42014-05-16 10:05:08 +0200327 trigger = rtl8723au_read8(adapter, REG_C2HEVT_CLEAR);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500328
329 if (trigger == C2H_EVT_HOST_CLOSE)
330 goto exit; /* Not ready */
Janani Ravichandran382f0052016-02-18 17:56:53 -0500331 if (trigger != C2H_EVT_FW_CLOSE)
Larry Fingerf7c92d22014-03-28 21:37:39 -0500332 goto clear_evt; /* Not a valid value */
333
334 c2h_evt = (struct c2h_evt_hdr *)buf;
335
336 memset(c2h_evt, 0, 16);
337
Jes Sorensen050abc42014-05-16 10:05:08 +0200338 *buf = rtl8723au_read8(adapter, REG_C2HEVT_MSG_NORMAL);
339 *(buf + 1) = rtl8723au_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500340
341 RT_PRINT_DATA(_module_hal_init_c_, _drv_info_, "c2h_evt_read23a(): ",
342 &c2h_evt, sizeof(c2h_evt));
343
344 if (0) {
345 DBG_8723A("%s id:%u, len:%u, seq:%u, trigger:0x%02x\n",
346 __func__, c2h_evt->id, c2h_evt->plen, c2h_evt->seq,
347 trigger);
348 }
349
350 /* Read the content */
351 for (i = 0; i < c2h_evt->plen; i++)
Jes Sorensen050abc42014-05-16 10:05:08 +0200352 c2h_evt->payload[i] = rtl8723au_read8(adapter,
Larry Fingerf7c92d22014-03-28 21:37:39 -0500353 REG_C2HEVT_MSG_NORMAL +
354 sizeof(*c2h_evt) + i);
355
356 RT_PRINT_DATA(_module_hal_init_c_, _drv_info_,
357 "c2h_evt_read23a(): Command Content:\n", c2h_evt->payload,
358 c2h_evt->plen);
359
360 ret = _SUCCESS;
361
362clear_evt:
363 /*
364 * Clear event to notify FW we have read the command.
365 * If this field isn't clear, the FW won't update the
366 * next command message.
367 */
368 c2h_evt_clear23a(adapter);
369exit:
370 return ret;
371}
372
373void
374rtl8723a_set_ampdu_min_space(struct rtw_adapter *padapter, u8 MinSpacingToSet)
375{
376 u8 SecMinSpace;
377
378 if (MinSpacingToSet <= 7) {
379 switch (padapter->securitypriv.dot11PrivacyAlgrthm) {
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200380 case 0:
381 case WLAN_CIPHER_SUITE_CCMP:
Larry Fingerf7c92d22014-03-28 21:37:39 -0500382 SecMinSpace = 0;
383 break;
384
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200385 case WLAN_CIPHER_SUITE_WEP40:
386 case WLAN_CIPHER_SUITE_WEP104:
387 case WLAN_CIPHER_SUITE_TKIP:
Larry Fingerf7c92d22014-03-28 21:37:39 -0500388 SecMinSpace = 6;
389 break;
390 default:
391 SecMinSpace = 7;
392 break;
393 }
394
395 if (MinSpacingToSet < SecMinSpace)
396 MinSpacingToSet = SecMinSpace;
397
Larry Fingerf7c92d22014-03-28 21:37:39 -0500398 MinSpacingToSet |=
Jes Sorensen050abc42014-05-16 10:05:08 +0200399 rtl8723au_read8(padapter, REG_AMPDU_MIN_SPACE) & 0xf8;
Jes Sorensenedbfd672014-05-16 10:05:09 +0200400 rtl8723au_write8(padapter, REG_AMPDU_MIN_SPACE,
401 MinSpacingToSet);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500402 }
403}
404
405void rtl8723a_set_ampdu_factor(struct rtw_adapter *padapter, u8 FactorToSet)
406{
407 u8 RegToSet_Normal[4] = { 0x41, 0xa8, 0x72, 0xb9 };
408 u8 MaxAggNum;
409 u8 *pRegToSet;
410 u8 index = 0;
411
412 pRegToSet = RegToSet_Normal; /* 0xb972a841; */
Jes Sorensenbf2a7b92014-05-25 22:43:24 +0200413
414 if (rtl8723a_BT_enabled(padapter) &&
415 rtl8723a_BT_using_antenna_1(padapter))
Larry Fingerf7c92d22014-03-28 21:37:39 -0500416 MaxAggNum = 0x8;
Jes Sorensenbf2a7b92014-05-25 22:43:24 +0200417 else
Larry Fingerf7c92d22014-03-28 21:37:39 -0500418 MaxAggNum = 0xF;
Larry Fingerf7c92d22014-03-28 21:37:39 -0500419
420 if (FactorToSet <= 3) {
Jiayi Ye1d06bb42014-10-25 10:58:28 +0800421 FactorToSet = 1 << (FactorToSet + 2);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500422 if (FactorToSet > MaxAggNum)
423 FactorToSet = MaxAggNum;
424
425 for (index = 0; index < 4; index++) {
426 if ((pRegToSet[index] & 0xf0) > (FactorToSet << 4))
427 pRegToSet[index] = (pRegToSet[index] & 0x0f) |
428 (FactorToSet << 4);
429
430 if ((pRegToSet[index] & 0x0f) > FactorToSet)
431 pRegToSet[index] = (pRegToSet[index] & 0xf0) |
432 FactorToSet;
433
Jes Sorensenedbfd672014-05-16 10:05:09 +0200434 rtl8723au_write8(padapter, REG_AGGLEN_LMT + index,
435 pRegToSet[index]);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500436 }
Larry Fingerf7c92d22014-03-28 21:37:39 -0500437 }
438}
439
440void rtl8723a_set_acm_ctrl(struct rtw_adapter *padapter, u8 ctrl)
441{
442 u8 hwctrl = 0;
443
444 if (ctrl != 0) {
445 hwctrl |= AcmHw_HwEn;
446
447 if (ctrl & BIT(1)) /* BE */
448 hwctrl |= AcmHw_BeqEn;
449
450 if (ctrl & BIT(2)) /* VI */
451 hwctrl |= AcmHw_ViqEn;
452
453 if (ctrl & BIT(3)) /* VO */
454 hwctrl |= AcmHw_VoqEn;
455 }
456
457 DBG_8723A("[HW_VAR_ACM_CTRL] Write 0x%02X\n", hwctrl);
Jes Sorensenedbfd672014-05-16 10:05:09 +0200458 rtl8723au_write8(padapter, REG_ACMHWCTRL, hwctrl);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500459}
460
461void rtl8723a_set_media_status(struct rtw_adapter *padapter, u8 status)
462{
463 u8 val8;
464
Jes Sorensen050abc42014-05-16 10:05:08 +0200465 val8 = rtl8723au_read8(padapter, MSR) & 0x0c;
Larry Fingerf7c92d22014-03-28 21:37:39 -0500466 val8 |= status;
Jes Sorensenedbfd672014-05-16 10:05:09 +0200467 rtl8723au_write8(padapter, MSR, val8);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500468}
469
470void rtl8723a_set_media_status1(struct rtw_adapter *padapter, u8 status)
471{
472 u8 val8;
473
Jes Sorensen050abc42014-05-16 10:05:08 +0200474 val8 = rtl8723au_read8(padapter, MSR) & 0x03;
Larry Fingerf7c92d22014-03-28 21:37:39 -0500475 val8 |= status << 2;
Jes Sorensenedbfd672014-05-16 10:05:09 +0200476 rtl8723au_write8(padapter, MSR, val8);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500477}
478
479void rtl8723a_set_bcn_func(struct rtw_adapter *padapter, u8 val)
480{
481 if (val)
482 SetBcnCtrlReg23a(padapter, EN_BCN_FUNCTION | EN_TXBCN_RPT, 0);
483 else
484 SetBcnCtrlReg23a(padapter, 0, EN_BCN_FUNCTION | EN_TXBCN_RPT);
485}
486
487void rtl8723a_check_bssid(struct rtw_adapter *padapter, u8 val)
488{
489 u32 val32;
Aybuke Ozdemir57e680e2014-09-27 16:47:47 +0300490
Jes Sorensen050abc42014-05-16 10:05:08 +0200491 val32 = rtl8723au_read32(padapter, REG_RCR);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500492 if (val)
493 val32 |= RCR_CBSSID_DATA | RCR_CBSSID_BCN;
494 else
495 val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
Jes Sorensenedbfd672014-05-16 10:05:09 +0200496 rtl8723au_write32(padapter, REG_RCR, val32);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500497}
498
499void rtl8723a_mlme_sitesurvey(struct rtw_adapter *padapter, u8 flag)
500{
501 if (flag) { /* under sitesurvey */
502 u32 v32;
503
504 /* config RCR to receive different BSSID & not
505 to receive data frame */
Jes Sorensen050abc42014-05-16 10:05:08 +0200506 v32 = rtl8723au_read32(padapter, REG_RCR);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500507 v32 &= ~(RCR_CBSSID_BCN);
Jes Sorensenedbfd672014-05-16 10:05:09 +0200508 rtl8723au_write32(padapter, REG_RCR, v32);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500509 /* reject all data frame */
Jes Sorensenedbfd672014-05-16 10:05:09 +0200510 rtl8723au_write16(padapter, REG_RXFLTMAP2, 0);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500511
512 /* disable update TSF */
513 SetBcnCtrlReg23a(padapter, DIS_TSF_UDT, 0);
514 } else { /* sitesurvey done */
515
516 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
517 struct mlme_ext_info *pmlmeinfo;
518 u32 v32;
519
520 pmlmeinfo = &pmlmeext->mlmext_info;
521
522 if ((is_client_associated_to_ap23a(padapter) == true) ||
Jes Sorensen6ec26272014-07-17 22:59:46 +0200523 ((pmlmeinfo->state & 0x03) == MSR_ADHOC) ||
524 ((pmlmeinfo->state & 0x03) == MSR_AP)) {
Larry Fingerf7c92d22014-03-28 21:37:39 -0500525 /* enable to rx data frame */
Jes Sorensenedbfd672014-05-16 10:05:09 +0200526 rtl8723au_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500527
528 /* enable update TSF */
529 SetBcnCtrlReg23a(padapter, 0, DIS_TSF_UDT);
530 }
531
Jes Sorensen050abc42014-05-16 10:05:08 +0200532 v32 = rtl8723au_read32(padapter, REG_RCR);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500533 v32 |= RCR_CBSSID_BCN;
Jes Sorensenedbfd672014-05-16 10:05:09 +0200534 rtl8723au_write32(padapter, REG_RCR, v32);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500535 }
536
Jes Sorensend952e4c2014-05-25 22:43:28 +0200537 rtl8723a_BT_wifiscan_notify(padapter, flag ? true : false);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500538}
539
540void rtl8723a_on_rcr_am(struct rtw_adapter *padapter)
541{
Jes Sorensenedbfd672014-05-16 10:05:09 +0200542 rtl8723au_write32(padapter, REG_RCR,
Jes Sorensen050abc42014-05-16 10:05:08 +0200543 rtl8723au_read32(padapter, REG_RCR) | RCR_AM);
Aybuke Ozdemirf9974e72014-09-27 16:47:46 +0300544 DBG_8723A("%s, %d, RCR = %x\n", __func__, __LINE__,
Jes Sorensen050abc42014-05-16 10:05:08 +0200545 rtl8723au_read32(padapter, REG_RCR));
Larry Fingerf7c92d22014-03-28 21:37:39 -0500546}
547
548void rtl8723a_off_rcr_am(struct rtw_adapter *padapter)
549{
Jes Sorensenedbfd672014-05-16 10:05:09 +0200550 rtl8723au_write32(padapter, REG_RCR,
Jes Sorensen050abc42014-05-16 10:05:08 +0200551 rtl8723au_read32(padapter, REG_RCR) & (~RCR_AM));
Aybuke Ozdemirf9974e72014-09-27 16:47:46 +0300552 DBG_8723A("%s, %d, RCR = %x\n", __func__, __LINE__,
Jes Sorensen050abc42014-05-16 10:05:08 +0200553 rtl8723au_read32(padapter, REG_RCR));
Larry Fingerf7c92d22014-03-28 21:37:39 -0500554}
555
556void rtl8723a_set_slot_time(struct rtw_adapter *padapter, u8 slottime)
557{
558 u8 u1bAIFS, aSifsTime;
559 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
560 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
561
Jes Sorensenedbfd672014-05-16 10:05:09 +0200562 rtl8723au_write8(padapter, REG_SLOT, slottime);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500563
564 if (pmlmeinfo->WMM_enable == 0) {
565 if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
566 aSifsTime = 10;
567 else
568 aSifsTime = 16;
569
570 u1bAIFS = aSifsTime + (2 * pmlmeinfo->slotTime);
571
572 /* <Roger_EXP> Temporary removed, 2008.06.20. */
Jes Sorensenedbfd672014-05-16 10:05:09 +0200573 rtl8723au_write8(padapter, REG_EDCA_VO_PARAM, u1bAIFS);
574 rtl8723au_write8(padapter, REG_EDCA_VI_PARAM, u1bAIFS);
575 rtl8723au_write8(padapter, REG_EDCA_BE_PARAM, u1bAIFS);
576 rtl8723au_write8(padapter, REG_EDCA_BK_PARAM, u1bAIFS);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500577 }
578}
579
580void rtl8723a_ack_preamble(struct rtw_adapter *padapter, u8 bShortPreamble)
581{
582 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
583 u8 regTmp;
584
585 /* Joseph marked out for Netgear 3500 TKIP
586 channel 7 issue.(Temporarily) */
587 regTmp = (pHalData->nCur40MhzPrimeSC) << 5;
588 /* regTmp = 0; */
589 if (bShortPreamble)
590 regTmp |= 0x80;
Jes Sorensenedbfd672014-05-16 10:05:09 +0200591 rtl8723au_write8(padapter, REG_RRSR + 2, regTmp);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500592}
593
594void rtl8723a_set_sec_cfg(struct rtw_adapter *padapter, u8 sec)
595{
Jes Sorensenedbfd672014-05-16 10:05:09 +0200596 rtl8723au_write8(padapter, REG_SECCFG, sec);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500597}
598
599void rtl8723a_cam_empty_entry(struct rtw_adapter *padapter, u8 ucIndex)
600{
601 u8 i;
602 u32 ulCommand = 0;
603 u32 ulContent = 0;
604 u32 ulEncAlgo = CAM_AES;
605
606 for (i = 0; i < CAM_CONTENT_COUNT; i++) {
607 /* filled id in CAM config 2 byte */
608 if (i == 0) {
609 ulContent |= (ucIndex & 0x03) |
610 ((u16) (ulEncAlgo) << 2);
611 /* ulContent |= CAM_VALID; */
612 } else {
613 ulContent = 0;
614 }
615 /* polling bit, and No Write enable, and address */
616 ulCommand = CAM_CONTENT_COUNT * ucIndex + i;
617 ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE;
618 /* write content 0 is equall to mark invalid */
619 /* delay_ms(40); */
Jes Sorensenedbfd672014-05-16 10:05:09 +0200620 rtl8723au_write32(padapter, WCAMI, ulContent);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500621 /* delay_ms(40); */
Jes Sorensen2a3bc8a2014-07-17 22:59:53 +0200622 rtl8723au_write32(padapter, REG_CAMCMD, ulCommand);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500623 }
624}
625
Jes Sorensen2a3bc8a2014-07-17 22:59:53 +0200626void rtl8723a_cam_invalidate_all(struct rtw_adapter *padapter)
Larry Fingerf7c92d22014-03-28 21:37:39 -0500627{
Jes Sorensen2a3bc8a2014-07-17 22:59:53 +0200628 rtl8723au_write32(padapter, REG_CAMCMD, CAM_POLLINIG | BIT(30));
Larry Fingerf7c92d22014-03-28 21:37:39 -0500629}
630
Jes Sorensendc0d16a2014-04-09 23:20:29 +0200631void rtl8723a_cam_write(struct rtw_adapter *padapter,
Jes Sorensen0348dc742014-04-26 18:55:06 +0200632 u8 entry, u16 ctrl, const u8 *mac, const u8 *key)
Larry Fingerf7c92d22014-03-28 21:37:39 -0500633{
634 u32 cmd;
Jes Sorensendc0d16a2014-04-09 23:20:29 +0200635 unsigned int i, val, addr;
636 int j;
Larry Fingerf7c92d22014-03-28 21:37:39 -0500637
Jes Sorensendc0d16a2014-04-09 23:20:29 +0200638 addr = entry << 3;
Larry Fingerf7c92d22014-03-28 21:37:39 -0500639
Jes Sorensendc0d16a2014-04-09 23:20:29 +0200640 for (j = 5; j >= 0; j--) {
641 switch (j) {
642 case 0:
643 val = ctrl | (mac[0] << 16) | (mac[1] << 24);
644 break;
645 case 1:
646 val = mac[2] | (mac[3] << 8) |
647 (mac[4] << 16) | (mac[5] << 24);
648 break;
649 default:
650 i = (j - 2) << 2;
651 val = key[i] | (key[i+1] << 8) |
652 (key[i+2] << 16) | (key[i+3] << 24);
653 break;
654 }
655
Jes Sorensenedbfd672014-05-16 10:05:09 +0200656 rtl8723au_write32(padapter, WCAMI, val);
Jes Sorensendc0d16a2014-04-09 23:20:29 +0200657 cmd = CAM_POLLINIG | CAM_WRITE | (addr + j);
Jes Sorensen2a3bc8a2014-07-17 22:59:53 +0200658 rtl8723au_write32(padapter, REG_CAMCMD, cmd);
Jes Sorensendc0d16a2014-04-09 23:20:29 +0200659
660 /* DBG_8723A("%s => cam write: %x, %x\n", __func__, cmd, val);*/
661 }
Larry Fingerf7c92d22014-03-28 21:37:39 -0500662}
663
664void rtl8723a_fifo_cleanup(struct rtw_adapter *padapter)
665{
666#define RW_RELEASE_EN BIT(18)
667#define RXDMA_IDLE BIT(17)
668
669 struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
670 u8 trycnt = 100;
671
672 /* pause tx */
Jes Sorensenedbfd672014-05-16 10:05:09 +0200673 rtl8723au_write8(padapter, REG_TXPAUSE, 0xff);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500674
675 /* keep sn */
Jes Sorensen516f29e2014-10-10 21:41:32 +0200676 padapter->xmitpriv.nqos_ssn = rtl8723au_read8(padapter, REG_NQOS_SEQ);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500677
678 if (pwrpriv->bkeepfwalive != true) {
679 u32 v32;
680
681 /* RX DMA stop */
Jes Sorensen050abc42014-05-16 10:05:08 +0200682 v32 = rtl8723au_read32(padapter, REG_RXPKT_NUM);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500683 v32 |= RW_RELEASE_EN;
Jes Sorensenedbfd672014-05-16 10:05:09 +0200684 rtl8723au_write32(padapter, REG_RXPKT_NUM, v32);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500685 do {
Jes Sorensen050abc42014-05-16 10:05:08 +0200686 v32 = rtl8723au_read32(padapter,
687 REG_RXPKT_NUM) & RXDMA_IDLE;
Larry Fingerf7c92d22014-03-28 21:37:39 -0500688 if (!v32)
689 break;
690 } while (trycnt--);
Aybuke Ozdemir7b58e792014-09-27 16:47:48 +0300691 if (trycnt == 0)
Larry Fingerf7c92d22014-03-28 21:37:39 -0500692 DBG_8723A("Stop RX DMA failed......\n");
Larry Fingerf7c92d22014-03-28 21:37:39 -0500693
694 /* RQPN Load 0 */
Jes Sorensenedbfd672014-05-16 10:05:09 +0200695 rtl8723au_write16(padapter, REG_RQPN_NPQ, 0);
696 rtl8723au_write32(padapter, REG_RQPN, 0x80000000);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500697 mdelay(10);
698 }
699}
700
Larry Fingerf7c92d22014-03-28 21:37:39 -0500701void rtl8723a_bcn_valid(struct rtw_adapter *padapter)
702{
703 /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2,
704 write 1 to clear, Clear by sw */
Jes Sorensenedbfd672014-05-16 10:05:09 +0200705 rtl8723au_write8(padapter, REG_TDECTRL + 2,
706 rtl8723au_read8(padapter, REG_TDECTRL + 2) | BIT(0));
Larry Fingerf7c92d22014-03-28 21:37:39 -0500707}
708
Jes Sorensenff5d82e2014-04-09 23:20:15 +0200709bool rtl8723a_get_bcn_valid(struct rtw_adapter *padapter)
710{
711 bool retval;
712
Jes Sorensen050abc42014-05-16 10:05:08 +0200713 retval = (rtl8723au_read8(padapter, REG_TDECTRL + 2) & BIT(0)) ? true : false;
Jes Sorensenff5d82e2014-04-09 23:20:15 +0200714
715 return retval;
716}
717
Larry Fingerf7c92d22014-03-28 21:37:39 -0500718void rtl8723a_set_beacon_interval(struct rtw_adapter *padapter, u16 interval)
719{
Jes Sorensenedbfd672014-05-16 10:05:09 +0200720 rtl8723au_write16(padapter, REG_BCN_INTERVAL, interval);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500721}
722
723void rtl8723a_set_resp_sifs(struct rtw_adapter *padapter,
724 u8 r2t1, u8 r2t2, u8 t2t1, u8 t2t2)
725{
726 /* SIFS_Timer = 0x0a0a0808; */
727 /* RESP_SIFS for CCK */
728 /* SIFS_T2T_CCK (0x08) */
Jes Sorensenedbfd672014-05-16 10:05:09 +0200729 rtl8723au_write8(padapter, REG_R2T_SIFS, r2t1);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500730 /* SIFS_R2T_CCK(0x08) */
Jes Sorensenedbfd672014-05-16 10:05:09 +0200731 rtl8723au_write8(padapter, REG_R2T_SIFS + 1, r2t2);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500732 /* RESP_SIFS for OFDM */
733 /* SIFS_T2T_OFDM (0x0a) */
Jes Sorensenedbfd672014-05-16 10:05:09 +0200734 rtl8723au_write8(padapter, REG_T2T_SIFS, t2t1);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500735 /* SIFS_R2T_OFDM(0x0a) */
Jes Sorensenedbfd672014-05-16 10:05:09 +0200736 rtl8723au_write8(padapter, REG_T2T_SIFS + 1, t2t2);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500737}
738
739void rtl8723a_set_ac_param_vo(struct rtw_adapter *padapter, u32 vo)
740{
Jes Sorensenedbfd672014-05-16 10:05:09 +0200741 rtl8723au_write32(padapter, REG_EDCA_VO_PARAM, vo);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500742}
743
744void rtl8723a_set_ac_param_vi(struct rtw_adapter *padapter, u32 vi)
745{
Jes Sorensenedbfd672014-05-16 10:05:09 +0200746 rtl8723au_write32(padapter, REG_EDCA_VI_PARAM, vi);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500747}
748
749void rtl8723a_set_ac_param_be(struct rtw_adapter *padapter, u32 be)
750{
751 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
752
753 pHalData->AcParam_BE = be;
Jes Sorensenedbfd672014-05-16 10:05:09 +0200754 rtl8723au_write32(padapter, REG_EDCA_BE_PARAM, be);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500755}
756
757void rtl8723a_set_ac_param_bk(struct rtw_adapter *padapter, u32 bk)
758{
Jes Sorensenedbfd672014-05-16 10:05:09 +0200759 rtl8723au_write32(padapter, REG_EDCA_BK_PARAM, bk);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500760}
761
762void rtl8723a_set_rxdma_agg_pg_th(struct rtw_adapter *padapter, u8 val)
763{
Jes Sorensenedbfd672014-05-16 10:05:09 +0200764 rtl8723au_write8(padapter, REG_RXDMA_AGG_PG_TH, val);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500765}
766
Larry Fingerf7c92d22014-03-28 21:37:39 -0500767void rtl8723a_set_initial_gain(struct rtw_adapter *padapter, u32 rx_gain)
768{
769 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
770 struct dig_t *pDigTable = &pHalData->odmpriv.DM_DigTable;
771
772 if (rx_gain == 0xff) /* restore rx gain */
773 ODM_Write_DIG23a(&pHalData->odmpriv, pDigTable->BackupIGValue);
774 else {
775 pDigTable->BackupIGValue = pDigTable->CurIGValue;
776 ODM_Write_DIG23a(&pHalData->odmpriv, rx_gain);
777 }
778}
779
Jes Sorensena945bf32014-04-09 23:20:42 +0200780void rtl8723a_odm_support_ability_restore(struct rtw_adapter *padapter)
Larry Fingerf7c92d22014-03-28 21:37:39 -0500781{
782 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
783
Jes Sorensena945bf32014-04-09 23:20:42 +0200784 pHalData->odmpriv.SupportAbility = pHalData->odmpriv.BK_SupportAbility;
785}
786
787void rtl8723a_odm_support_ability_backup(struct rtw_adapter *padapter)
788{
789 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
790
791 pHalData->odmpriv.BK_SupportAbility = pHalData->odmpriv.SupportAbility;
Larry Fingerf7c92d22014-03-28 21:37:39 -0500792}
793
794void rtl8723a_odm_support_ability_set(struct rtw_adapter *padapter, u32 val)
795{
796 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
797
Jes Sorensen353cb502014-07-21 11:24:49 +0200798 if (val == DYNAMIC_ALL_FUNC_ENABLE)
Larry Fingerf7c92d22014-03-28 21:37:39 -0500799 pHalData->odmpriv.SupportAbility = pHalData->dmpriv.InitODMFlag;
Jes Sorensen353cb502014-07-21 11:24:49 +0200800 else
Larry Fingerf7c92d22014-03-28 21:37:39 -0500801 pHalData->odmpriv.SupportAbility |= val;
Larry Fingerf7c92d22014-03-28 21:37:39 -0500802}
803
804void rtl8723a_odm_support_ability_clr(struct rtw_adapter *padapter, u32 val)
805{
806 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
807
808 pHalData->odmpriv.SupportAbility &= val;
809}
810
811void rtl8723a_set_rpwm(struct rtw_adapter *padapter, u8 val)
812{
Jes Sorensenedbfd672014-05-16 10:05:09 +0200813 rtl8723au_write8(padapter, REG_USB_HRPWM, val);
Larry Fingerf7c92d22014-03-28 21:37:39 -0500814}
Jes Sorensenc2370e82014-04-09 23:20:53 +0200815
816u8 rtl8723a_get_rf_type(struct rtw_adapter *padapter)
817{
818 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
819
820 return pHalData->rf_type;
821}
Jes Sorensen0cee8102014-04-09 23:20:54 +0200822
823bool rtl8723a_get_fwlps_rf_on(struct rtw_adapter *padapter)
824{
825 bool retval;
826 u32 valRCR;
827
828 /* When we halt NIC, we should check if FW LPS is leave. */
829
830 if ((padapter->bSurpriseRemoved == true) ||
831 (padapter->pwrctrlpriv.rf_pwrstate == rf_off)) {
832 /* If it is in HW/SW Radio OFF or IPS state, we do
833 not check Fw LPS Leave, because Fw is unload. */
834 retval = true;
835 } else {
Jes Sorensen050abc42014-05-16 10:05:08 +0200836 valRCR = rtl8723au_read32(padapter, REG_RCR);
Jes Sorensen0cee8102014-04-09 23:20:54 +0200837 if (valRCR & 0x00070000)
838 retval = false;
839 else
840 retval = true;
841 }
842
843 return retval;
844}
Jes Sorensen8d3fd612014-04-09 23:20:55 +0200845
846bool rtl8723a_chk_hi_queue_empty(struct rtw_adapter *padapter)
847{
848 u32 hgq;
849
Jes Sorensen050abc42014-05-16 10:05:08 +0200850 hgq = rtl8723au_read32(padapter, REG_HGQ_INFORMATION);
Jes Sorensen8d3fd612014-04-09 23:20:55 +0200851
852 return ((hgq & 0x0000ff00) == 0) ? true : false;
853}