Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / rtl8723au / hal / hal_com.c
1 /******************************************************************************
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>
21 #include <usb_ops_linux.h>
22
23 #define _HAL_INIT_C_
24
25 #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 */
31 u8 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
57 u8 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
116 void 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. */
186         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);
190
191         rate_index = 0;
192         /*  Set RTS initial rate */
193         while (brate_cfg > 0x1) {
194                 brate_cfg >>= 1;
195                 rate_index++;
196         }
197                 /*  Ziv - Check */
198         rtl8723au_write8(padapter, REG_INIRTS_RATE_SEL, rate_index);
199 }
200
201 static 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
216 static 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
249 static 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
282 bool 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
306 /*
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
312 void c2h_evt_clear23a(struct rtw_adapter *adapter)
313 {
314         rtl8723au_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
315 }
316
317 int c2h_evt_read23a(struct rtw_adapter *adapter, u8 *buf)
318 {
319         int ret = _FAIL;
320         struct c2h_evt_hdr *c2h_evt;
321         int i;
322         u8 trigger;
323
324         if (buf == NULL)
325                 goto exit;
326
327         trigger = rtl8723au_read8(adapter, REG_C2HEVT_CLEAR);
328
329         if (trigger == C2H_EVT_HOST_CLOSE)
330                 goto exit;      /* Not ready */
331         else if (trigger != C2H_EVT_FW_CLOSE)
332                 goto clear_evt; /* Not a valid value */
333
334         c2h_evt = (struct c2h_evt_hdr *)buf;
335
336         memset(c2h_evt, 0, 16);
337
338         *buf = rtl8723au_read8(adapter, REG_C2HEVT_MSG_NORMAL);
339         *(buf + 1) = rtl8723au_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1);
340
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++)
352                 c2h_evt->payload[i] = rtl8723au_read8(adapter,
353                                                 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
362 clear_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);
369 exit:
370         return ret;
371 }
372
373 void
374 rtl8723a_set_ampdu_min_space(struct rtw_adapter *padapter, u8 MinSpacingToSet)
375 {
376         u8 SecMinSpace;
377
378         if (MinSpacingToSet <= 7) {
379                 switch (padapter->securitypriv.dot11PrivacyAlgrthm) {
380                 case 0:
381                 case WLAN_CIPHER_SUITE_CCMP:
382                         SecMinSpace = 0;
383                         break;
384
385                 case WLAN_CIPHER_SUITE_WEP40:
386                 case WLAN_CIPHER_SUITE_WEP104:
387                 case WLAN_CIPHER_SUITE_TKIP:
388                         SecMinSpace = 6;
389                         break;
390                 default:
391                         SecMinSpace = 7;
392                         break;
393                 }
394
395                 if (MinSpacingToSet < SecMinSpace)
396                         MinSpacingToSet = SecMinSpace;
397
398                 MinSpacingToSet |=
399                         rtl8723au_read8(padapter, REG_AMPDU_MIN_SPACE) & 0xf8;
400                 rtl8723au_write8(padapter, REG_AMPDU_MIN_SPACE,
401                                  MinSpacingToSet);
402         }
403 }
404
405 void 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; */
413
414         if (rtl8723a_BT_enabled(padapter) &&
415             rtl8723a_BT_using_antenna_1(padapter))
416                 MaxAggNum = 0x8;
417         else
418                 MaxAggNum = 0xF;
419
420         if (FactorToSet <= 3) {
421                 FactorToSet = 1 << (FactorToSet + 2);
422                 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
434                         rtl8723au_write8(padapter, REG_AGGLEN_LMT + index,
435                                          pRegToSet[index]);
436                 }
437         }
438 }
439
440 void 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);
458         rtl8723au_write8(padapter, REG_ACMHWCTRL, hwctrl);
459 }
460
461 void rtl8723a_set_media_status(struct rtw_adapter *padapter, u8 status)
462 {
463         u8 val8;
464
465         val8 = rtl8723au_read8(padapter, MSR) & 0x0c;
466         val8 |= status;
467         rtl8723au_write8(padapter, MSR, val8);
468 }
469
470 void rtl8723a_set_media_status1(struct rtw_adapter *padapter, u8 status)
471 {
472         u8 val8;
473
474         val8 = rtl8723au_read8(padapter, MSR) & 0x03;
475         val8 |= status << 2;
476         rtl8723au_write8(padapter, MSR, val8);
477 }
478
479 void 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
487 void rtl8723a_check_bssid(struct rtw_adapter *padapter, u8 val)
488 {
489         u32 val32;
490
491         val32 = rtl8723au_read32(padapter, REG_RCR);
492         if (val)
493                 val32 |= RCR_CBSSID_DATA | RCR_CBSSID_BCN;
494         else
495                 val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
496         rtl8723au_write32(padapter, REG_RCR, val32);
497 }
498
499 void 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 */
506                 v32 = rtl8723au_read32(padapter, REG_RCR);
507                 v32 &= ~(RCR_CBSSID_BCN);
508                 rtl8723au_write32(padapter, REG_RCR, v32);
509                 /*  reject all data frame */
510                 rtl8723au_write16(padapter, REG_RXFLTMAP2, 0);
511
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) ||
523                     ((pmlmeinfo->state & 0x03) == MSR_ADHOC) ||
524                     ((pmlmeinfo->state & 0x03) == MSR_AP)) {
525                         /*  enable to rx data frame */
526                         rtl8723au_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
527
528                         /*  enable update TSF */
529                         SetBcnCtrlReg23a(padapter, 0, DIS_TSF_UDT);
530                 }
531
532                 v32 = rtl8723au_read32(padapter, REG_RCR);
533                 v32 |= RCR_CBSSID_BCN;
534                 rtl8723au_write32(padapter, REG_RCR, v32);
535         }
536
537         rtl8723a_BT_wifiscan_notify(padapter, flag ? true : false);
538 }
539
540 void rtl8723a_on_rcr_am(struct rtw_adapter *padapter)
541 {
542         rtl8723au_write32(padapter, REG_RCR,
543                     rtl8723au_read32(padapter, REG_RCR) | RCR_AM);
544         DBG_8723A("%s, %d, RCR = %x\n", __func__, __LINE__,
545                   rtl8723au_read32(padapter, REG_RCR));
546 }
547
548 void rtl8723a_off_rcr_am(struct rtw_adapter *padapter)
549 {
550         rtl8723au_write32(padapter, REG_RCR,
551                     rtl8723au_read32(padapter, REG_RCR) & (~RCR_AM));
552         DBG_8723A("%s, %d, RCR = %x\n", __func__, __LINE__,
553                   rtl8723au_read32(padapter, REG_RCR));
554 }
555
556 void 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
562         rtl8723au_write8(padapter, REG_SLOT, slottime);
563
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. */
573                 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);
577         }
578 }
579
580 void 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;
591         rtl8723au_write8(padapter, REG_RRSR + 2, regTmp);
592 }
593
594 void rtl8723a_set_sec_cfg(struct rtw_adapter *padapter, u8 sec)
595 {
596         rtl8723au_write8(padapter, REG_SECCFG, sec);
597 }
598
599 void 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); */
620                 rtl8723au_write32(padapter, WCAMI, ulContent);
621                 /* delay_ms(40); */
622                 rtl8723au_write32(padapter, REG_CAMCMD, ulCommand);
623         }
624 }
625
626 void rtl8723a_cam_invalidate_all(struct rtw_adapter *padapter)
627 {
628         rtl8723au_write32(padapter, REG_CAMCMD, CAM_POLLINIG | BIT(30));
629 }
630
631 void rtl8723a_cam_write(struct rtw_adapter *padapter,
632                         u8 entry, u16 ctrl, const u8 *mac, const u8 *key)
633 {
634         u32 cmd;
635         unsigned int i, val, addr;
636         int j;
637
638         addr = entry << 3;
639
640         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
656                 rtl8723au_write32(padapter, WCAMI, val);
657                 cmd = CAM_POLLINIG | CAM_WRITE | (addr + j);
658                 rtl8723au_write32(padapter, REG_CAMCMD, cmd);
659
660                 /* DBG_8723A("%s => cam write: %x, %x\n", __func__, cmd, val);*/
661         }
662 }
663
664 void 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 */
673         rtl8723au_write8(padapter, REG_TXPAUSE, 0xff);
674
675         /*  keep sn */
676         padapter->xmitpriv.nqos_ssn = rtl8723au_read8(padapter, REG_NQOS_SEQ);
677
678         if (pwrpriv->bkeepfwalive != true) {
679                 u32 v32;
680
681                 /*  RX DMA stop */
682                 v32 = rtl8723au_read32(padapter, REG_RXPKT_NUM);
683                 v32 |= RW_RELEASE_EN;
684                 rtl8723au_write32(padapter, REG_RXPKT_NUM, v32);
685                 do {
686                         v32 = rtl8723au_read32(padapter,
687                                                REG_RXPKT_NUM) & RXDMA_IDLE;
688                         if (!v32)
689                                 break;
690                 } while (trycnt--);
691                 if (trycnt == 0)
692                         DBG_8723A("Stop RX DMA failed......\n");
693
694                 /*  RQPN Load 0 */
695                 rtl8723au_write16(padapter, REG_RQPN_NPQ, 0);
696                 rtl8723au_write32(padapter, REG_RQPN, 0x80000000);
697                 mdelay(10);
698         }
699 }
700
701 void 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 */
705         rtl8723au_write8(padapter, REG_TDECTRL + 2,
706                          rtl8723au_read8(padapter, REG_TDECTRL + 2) | BIT(0));
707 }
708
709 bool rtl8723a_get_bcn_valid(struct rtw_adapter *padapter)
710 {
711         bool retval;
712
713         retval = (rtl8723au_read8(padapter, REG_TDECTRL + 2) & BIT(0)) ? true : false;
714
715         return retval;
716 }
717
718 void rtl8723a_set_beacon_interval(struct rtw_adapter *padapter, u16 interval)
719 {
720         rtl8723au_write16(padapter, REG_BCN_INTERVAL, interval);
721 }
722
723 void 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) */
729         rtl8723au_write8(padapter, REG_R2T_SIFS, r2t1);
730         /* SIFS_R2T_CCK(0x08) */
731         rtl8723au_write8(padapter, REG_R2T_SIFS + 1, r2t2);
732         /* RESP_SIFS for OFDM */
733         /* SIFS_T2T_OFDM (0x0a) */
734         rtl8723au_write8(padapter, REG_T2T_SIFS, t2t1);
735         /* SIFS_R2T_OFDM(0x0a) */
736         rtl8723au_write8(padapter, REG_T2T_SIFS + 1, t2t2);
737 }
738
739 void rtl8723a_set_ac_param_vo(struct rtw_adapter *padapter, u32 vo)
740 {
741         rtl8723au_write32(padapter, REG_EDCA_VO_PARAM, vo);
742 }
743
744 void rtl8723a_set_ac_param_vi(struct rtw_adapter *padapter, u32 vi)
745 {
746         rtl8723au_write32(padapter, REG_EDCA_VI_PARAM, vi);
747 }
748
749 void 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;
754         rtl8723au_write32(padapter, REG_EDCA_BE_PARAM, be);
755 }
756
757 void rtl8723a_set_ac_param_bk(struct rtw_adapter *padapter, u32 bk)
758 {
759         rtl8723au_write32(padapter, REG_EDCA_BK_PARAM, bk);
760 }
761
762 void rtl8723a_set_rxdma_agg_pg_th(struct rtw_adapter *padapter, u8 val)
763 {
764         rtl8723au_write8(padapter, REG_RXDMA_AGG_PG_TH, val);
765 }
766
767 void 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
780 void rtl8723a_odm_support_ability_restore(struct rtw_adapter *padapter)
781 {
782         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
783
784         pHalData->odmpriv.SupportAbility = pHalData->odmpriv.BK_SupportAbility;
785 }
786
787 void 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;
792 }
793
794 void rtl8723a_odm_support_ability_set(struct rtw_adapter *padapter, u32 val)
795 {
796         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
797
798         if (val == DYNAMIC_ALL_FUNC_ENABLE)
799                 pHalData->odmpriv.SupportAbility = pHalData->dmpriv.InitODMFlag;
800         else
801                 pHalData->odmpriv.SupportAbility |= val;
802 }
803
804 void 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
811 void rtl8723a_set_rpwm(struct rtw_adapter *padapter, u8 val)
812 {
813         rtl8723au_write8(padapter, REG_USB_HRPWM, val);
814 }
815
816 u8 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 }
822
823 bool 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 {
836                 valRCR = rtl8723au_read32(padapter, REG_RCR);
837                 if (valRCR & 0x00070000)
838                         retval = false;
839                 else
840                         retval = true;
841         }
842
843         return retval;
844 }
845
846 bool rtl8723a_chk_hi_queue_empty(struct rtw_adapter *padapter)
847 {
848         u32 hgq;
849
850         hgq = rtl8723au_read32(padapter, REG_HGQ_INFORMATION);
851
852         return ((hgq & 0x0000ff00) == 0) ? true : false;
853 }