af7e6b37584191a124f3a6bb975f79bc1d473e58
[firefly-linux-kernel-4.4.55.git] / 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 void dump_chip_info23a(struct hal_version ChipVersion)
26 {
27         int cnt = 0;
28         u8 buf[128];
29
30         cnt += sprintf((buf + cnt), "Chip Version Info: CHIP_8723A_");
31
32         cnt += sprintf((buf + cnt), "%s_", IS_NORMAL_CHIP(ChipVersion) ?
33                        "Normal_Chip" : "Test_Chip");
34         cnt += sprintf((buf + cnt), "%s_",
35                        IS_CHIP_VENDOR_TSMC(ChipVersion) ? "TSMC" : "UMC");
36         if (IS_A_CUT(ChipVersion))
37                 cnt += sprintf((buf + cnt), "A_CUT_");
38         else if (IS_B_CUT(ChipVersion))
39                 cnt += sprintf((buf + cnt), "B_CUT_");
40         else if (IS_C_CUT(ChipVersion))
41                 cnt += sprintf((buf + cnt), "C_CUT_");
42         else if (IS_D_CUT(ChipVersion))
43                 cnt += sprintf((buf + cnt), "D_CUT_");
44         else if (IS_E_CUT(ChipVersion))
45                 cnt += sprintf((buf + cnt), "E_CUT_");
46         else
47                 cnt += sprintf((buf + cnt), "UNKNOWN_CUT(%d)_",
48                                ChipVersion.CUTVersion);
49
50         if (IS_1T1R(ChipVersion))
51                 cnt += sprintf((buf + cnt), "1T1R_");
52         else if (IS_1T2R(ChipVersion))
53                 cnt += sprintf((buf + cnt), "1T2R_");
54         else if (IS_2T2R(ChipVersion))
55                 cnt += sprintf((buf + cnt), "2T2R_");
56         else
57                 cnt += sprintf((buf + cnt), "UNKNOWN_RFTYPE(%d)_",
58                                ChipVersion.RFType);
59
60         cnt += sprintf((buf + cnt), "RomVer(%d)\n", ChipVersion.ROMVer);
61
62         DBG_8723A("%s", buf);
63 }
64
65 #define EEPROM_CHANNEL_PLAN_BY_HW_MASK  0x80
66
67 /* return the final channel plan decision */
68 /* hw_channel_plan:  channel plan from HW (efuse/eeprom) */
69 /* sw_channel_plan:  channel plan from SW (registry/module param) */
70 /* def_channel_plan: channel plan used when the former two is invalid */
71 u8 hal_com_get_channel_plan23a(struct rtw_adapter *padapter, u8 hw_channel_plan,
72                             u8 sw_channel_plan, u8 def_channel_plan,
73                             bool AutoLoadFail)
74 {
75         u8 swConfig;
76         u8 chnlPlan;
77
78         swConfig = true;
79         if (!AutoLoadFail) {
80                 if (!rtw_is_channel_plan_valid(sw_channel_plan))
81                         swConfig = false;
82                 if (hw_channel_plan & EEPROM_CHANNEL_PLAN_BY_HW_MASK)
83                         swConfig = false;
84         }
85
86         if (swConfig == true)
87                 chnlPlan = sw_channel_plan;
88         else
89                 chnlPlan = hw_channel_plan & (~EEPROM_CHANNEL_PLAN_BY_HW_MASK);
90
91         if (!rtw_is_channel_plan_valid(chnlPlan))
92                 chnlPlan = def_channel_plan;
93
94         return chnlPlan;
95 }
96
97 u8 MRateToHwRate23a(u8 rate)
98 {
99         u8 ret = DESC_RATE1M;
100
101         switch (rate) {
102                 /*  CCK and OFDM non-HT rates */
103         case IEEE80211_CCK_RATE_1MB:
104                 ret = DESC_RATE1M;
105                 break;
106         case IEEE80211_CCK_RATE_2MB:
107                 ret = DESC_RATE2M;
108                 break;
109         case IEEE80211_CCK_RATE_5MB:
110                 ret = DESC_RATE5_5M;
111                 break;
112         case IEEE80211_CCK_RATE_11MB:
113                 ret = DESC_RATE11M;
114                 break;
115         case IEEE80211_OFDM_RATE_6MB:
116                 ret = DESC_RATE6M;
117                 break;
118         case IEEE80211_OFDM_RATE_9MB:
119                 ret = DESC_RATE9M;
120                 break;
121         case IEEE80211_OFDM_RATE_12MB:
122                 ret = DESC_RATE12M;
123                 break;
124         case IEEE80211_OFDM_RATE_18MB:
125                 ret = DESC_RATE18M;
126                 break;
127         case IEEE80211_OFDM_RATE_24MB:
128                 ret = DESC_RATE24M;
129                 break;
130         case IEEE80211_OFDM_RATE_36MB:
131                 ret = DESC_RATE36M;
132                 break;
133         case IEEE80211_OFDM_RATE_48MB:
134                 ret = DESC_RATE48M;
135                 break;
136         case IEEE80211_OFDM_RATE_54MB:
137                 ret = DESC_RATE54M;
138                 break;
139
140                 /*  HT rates since here */
141                 /* case MGN_MCS0:       ret = DESC_RATEMCS0;    break; */
142                 /* case MGN_MCS1:       ret = DESC_RATEMCS1;    break; */
143                 /* case MGN_MCS2:       ret = DESC_RATEMCS2;    break; */
144                 /* case MGN_MCS3:       ret = DESC_RATEMCS3;    break; */
145                 /* case MGN_MCS4:       ret = DESC_RATEMCS4;    break; */
146                 /* case MGN_MCS5:       ret = DESC_RATEMCS5;    break; */
147                 /* case MGN_MCS6:       ret = DESC_RATEMCS6;    break; */
148                 /* case MGN_MCS7:       ret = DESC_RATEMCS7;    break; */
149
150         default:
151                 break;
152         }
153         return ret;
154 }
155
156 void HalSetBrateCfg23a(struct rtw_adapter *padapter, u8 *mBratesOS)
157 {
158         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
159         u8 i, is_brate, brate;
160         u16 brate_cfg = 0;
161         u8 rate_index;
162
163         for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
164                 is_brate = mBratesOS[i] & IEEE80211_BASIC_RATE_MASK;
165                 brate = mBratesOS[i] & 0x7f;
166
167                 if (is_brate) {
168                         switch (brate) {
169                         case IEEE80211_CCK_RATE_1MB:
170                                 brate_cfg |= RATE_1M;
171                                 break;
172                         case IEEE80211_CCK_RATE_2MB:
173                                 brate_cfg |= RATE_2M;
174                                 break;
175                         case IEEE80211_CCK_RATE_5MB:
176                                 brate_cfg |= RATE_5_5M;
177                                 break;
178                         case IEEE80211_CCK_RATE_11MB:
179                                 brate_cfg |= RATE_11M;
180                                 break;
181                         case IEEE80211_OFDM_RATE_6MB:
182                                 brate_cfg |= RATE_6M;
183                                 break;
184                         case IEEE80211_OFDM_RATE_9MB:
185                                 brate_cfg |= RATE_9M;
186                                 break;
187                         case IEEE80211_OFDM_RATE_12MB:
188                                 brate_cfg |= RATE_12M;
189                                 break;
190                         case IEEE80211_OFDM_RATE_18MB:
191                                 brate_cfg |= RATE_18M;
192                                 break;
193                         case IEEE80211_OFDM_RATE_24MB:
194                                 brate_cfg |= RATE_24M;
195                                 break;
196                         case IEEE80211_OFDM_RATE_36MB:
197                                 brate_cfg |= RATE_36M;
198                                 break;
199                         case IEEE80211_OFDM_RATE_48MB:
200                                 brate_cfg |= RATE_48M;
201                                 break;
202                         case IEEE80211_OFDM_RATE_54MB:
203                                 brate_cfg |= RATE_54M;
204                                 break;
205                         }
206                 }
207         }
208
209         /*  2007.01.16, by Emily */
210         /*  Select RRSR (in Legacy-OFDM and CCK) */
211         /*  For 8190, we select only 24M, 12M, 6M, 11M, 5.5M, 2M,
212             and 1M from the Basic rate. */
213         /*  We do not use other rates. */
214         /* 2011.03.30 add by Luke Lee */
215         /* CCK 2M ACK should be disabled for some BCM and Atheros AP IOT */
216         /* because CCK 2M has poor TXEVM */
217         /* CCK 5.5M & 11M ACK should be enabled for better
218            performance */
219
220         brate_cfg = (brate_cfg | 0xd) & 0x15d;
221         pHalData->BasicRateSet = brate_cfg;
222         brate_cfg |= 0x01;      /*  default enable 1M ACK rate */
223         DBG_8723A("HW_VAR_BASIC_RATE: BrateCfg(%#x)\n", brate_cfg);
224
225         /*  Set RRSR rate table. */
226         rtl8723au_write8(padapter, REG_RRSR, brate_cfg & 0xff);
227         rtl8723au_write8(padapter, REG_RRSR + 1, (brate_cfg >> 8) & 0xff);
228         rtl8723au_write8(padapter, REG_RRSR + 2,
229                          rtl8723au_read8(padapter, REG_RRSR + 2) & 0xf0);
230
231         rate_index = 0;
232         /*  Set RTS initial rate */
233         while (brate_cfg > 0x1) {
234                 brate_cfg = (brate_cfg >> 1);
235                 rate_index++;
236         }
237                 /*  Ziv - Check */
238         rtl8723au_write8(padapter, REG_INIRTS_RATE_SEL, rate_index);
239
240         return;
241 }
242
243 static void _OneOutPipeMapping(struct rtw_adapter *pAdapter)
244 {
245         struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
246
247         pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];   /* VO */
248         pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];   /* VI */
249         pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[0];   /* BE */
250         pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0];   /* BK */
251
252         pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];   /* BCN */
253         pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];   /* MGT */
254         pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];   /* HIGH */
255         pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];   /* TXCMD */
256 }
257
258 static void _TwoOutPipeMapping(struct rtw_adapter *pAdapter, bool bWIFICfg)
259 {
260         struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
261
262         if (bWIFICfg) {         /* WMM */
263                 /*    BK,   BE,   VI,   VO,   BCN,  CMD,  MGT, HIGH, HCCA */
264                 /*     0,    1,    0,    1,     0,    0,    0,    0,    0 }; */
265                 /* 0:H, 1:L */
266                 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[1]; /* VO */
267                 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */
268                 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1]; /* BE */
269                 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0]; /* BK */
270
271                 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
272                 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
273                 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
274                 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
275         } else {                /* typical setting */
276                 /*    BK,   BE,   VI,   VO,   BCN,  CMD,  MGT, HIGH, HCCA */
277                 /*     1,    1,    0,    0,     0,    0,    0,    0,    0 }; */
278                 /* 0:H, 1:L */
279                 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */
280                 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */
281                 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1]; /* BE */
282                 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1]; /* BK */
283
284                 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
285                 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
286                 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
287                 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
288         }
289 }
290
291 static void _ThreeOutPipeMapping(struct rtw_adapter *pAdapter, bool bWIFICfg)
292 {
293         struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
294
295         if (bWIFICfg) {         /* for WMM */
296                 /*    BK,   BE,   VI,   VO,   BCN,  CMD,  MGT, HIGH, HCCA */
297                 /*     1,    2,    1,    0,     0,    0,    0,    0,    0 }; */
298                 /* 0:H, 1:N, 2:L */
299                 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */
300                 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1]; /* VI */
301                 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2]; /* BE */
302                 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1]; /* BK */
303
304                 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
305                 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
306                 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
307                 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
308         } else {                /* typical setting */
309                 /*    BK,   BE,   VI,   VO,   BCN,  CMD,  MGT, HIGH, HCCA */
310                 /*     2,    2,    1,    0,     0,    0,    0,    0,    0 }; */
311                 /* 0:H, 1:N, 2:L */
312                 pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */
313                 pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1]; /* VI */
314                 pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2]; /* BE */
315                 pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[2]; /* BK */
316
317                 pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
318                 pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
319                 pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
320                 pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
321         }
322 }
323
324 bool Hal_MappingOutPipe23a(struct rtw_adapter *pAdapter, u8 NumOutPipe)
325 {
326         struct registry_priv *pregistrypriv = &pAdapter->registrypriv;
327         bool bWIFICfg = (pregistrypriv->wifi_spec) ? true : false;
328         bool result = true;
329
330         switch (NumOutPipe) {
331         case 2:
332                 _TwoOutPipeMapping(pAdapter, bWIFICfg);
333                 break;
334         case 3:
335                 _ThreeOutPipeMapping(pAdapter, bWIFICfg);
336                 break;
337         case 1:
338                 _OneOutPipeMapping(pAdapter);
339                 break;
340         default:
341                 result = false;
342                 break;
343         }
344
345         return result;
346 }
347
348 /*
349 * C2H event format:
350 * Field  TRIGGER                CONTENT    CMD_SEQ      CMD_LEN          CMD_ID
351 * BITS   [127:120]      [119:16]      [15:8]              [7:4]            [3:0]
352 */
353
354 void c2h_evt_clear23a(struct rtw_adapter *adapter)
355 {
356         rtl8723au_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
357 }
358
359 int c2h_evt_read23a(struct rtw_adapter *adapter, u8 *buf)
360 {
361         int ret = _FAIL;
362         struct c2h_evt_hdr *c2h_evt;
363         int i;
364         u8 trigger;
365
366         if (buf == NULL)
367                 goto exit;
368
369         trigger = rtl8723au_read8(adapter, REG_C2HEVT_CLEAR);
370
371         if (trigger == C2H_EVT_HOST_CLOSE)
372                 goto exit;      /* Not ready */
373         else if (trigger != C2H_EVT_FW_CLOSE)
374                 goto clear_evt; /* Not a valid value */
375
376         c2h_evt = (struct c2h_evt_hdr *)buf;
377
378         memset(c2h_evt, 0, 16);
379
380         *buf = rtl8723au_read8(adapter, REG_C2HEVT_MSG_NORMAL);
381         *(buf + 1) = rtl8723au_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1);
382
383         RT_PRINT_DATA(_module_hal_init_c_, _drv_info_, "c2h_evt_read23a(): ",
384                       &c2h_evt, sizeof(c2h_evt));
385
386         if (0) {
387                 DBG_8723A("%s id:%u, len:%u, seq:%u, trigger:0x%02x\n",
388                           __func__, c2h_evt->id, c2h_evt->plen, c2h_evt->seq,
389                           trigger);
390         }
391
392         /* Read the content */
393         for (i = 0; i < c2h_evt->plen; i++)
394                 c2h_evt->payload[i] = rtl8723au_read8(adapter,
395                                                 REG_C2HEVT_MSG_NORMAL +
396                                                 sizeof(*c2h_evt) + i);
397
398         RT_PRINT_DATA(_module_hal_init_c_, _drv_info_,
399                       "c2h_evt_read23a(): Command Content:\n", c2h_evt->payload,
400                       c2h_evt->plen);
401
402         ret = _SUCCESS;
403
404 clear_evt:
405         /*
406          * Clear event to notify FW we have read the command.
407          * If this field isn't clear, the FW won't update the
408          * next command message.
409          */
410         c2h_evt_clear23a(adapter);
411 exit:
412         return ret;
413 }
414
415 void
416 rtl8723a_set_ampdu_min_space(struct rtw_adapter *padapter, u8 MinSpacingToSet)
417 {
418         u8 SecMinSpace;
419
420         if (MinSpacingToSet <= 7) {
421                 switch (padapter->securitypriv.dot11PrivacyAlgrthm) {
422                 case 0:
423                 case WLAN_CIPHER_SUITE_CCMP:
424                         SecMinSpace = 0;
425                         break;
426
427                 case WLAN_CIPHER_SUITE_WEP40:
428                 case WLAN_CIPHER_SUITE_WEP104:
429                 case WLAN_CIPHER_SUITE_TKIP:
430                         SecMinSpace = 6;
431                         break;
432                 default:
433                         SecMinSpace = 7;
434                         break;
435                 }
436
437                 if (MinSpacingToSet < SecMinSpace)
438                         MinSpacingToSet = SecMinSpace;
439
440                 /* RT_TRACE(COMP_MLME, DBG_LOUD,
441                    ("Set HW_VAR_AMPDU_MIN_SPACE: %#x\n",
442                    padapter->MgntInfo.MinSpaceCfg)); */
443                 MinSpacingToSet |=
444                         rtl8723au_read8(padapter, REG_AMPDU_MIN_SPACE) & 0xf8;
445                 rtl8723au_write8(padapter, REG_AMPDU_MIN_SPACE,
446                                  MinSpacingToSet);
447         }
448 }
449
450 void rtl8723a_set_ampdu_factor(struct rtw_adapter *padapter, u8 FactorToSet)
451 {
452         u8 RegToSet_Normal[4] = { 0x41, 0xa8, 0x72, 0xb9 };
453         u8 MaxAggNum;
454         u8 *pRegToSet;
455         u8 index = 0;
456
457         pRegToSet = RegToSet_Normal;    /*  0xb972a841; */
458 #ifdef CONFIG_8723AU_BT_COEXIST
459         if ((BT_IsBtDisabled(padapter) == false) &&
460             (BT_1Ant(padapter) == true)) {
461                 MaxAggNum = 0x8;
462         } else
463 #endif /*  CONFIG_8723AU_BT_COEXIST */
464         {
465                 MaxAggNum = 0xF;
466         }
467
468         if (FactorToSet <= 3) {
469                 FactorToSet = (1 << (FactorToSet + 2));
470                 if (FactorToSet > MaxAggNum)
471                         FactorToSet = MaxAggNum;
472
473                 for (index = 0; index < 4; index++) {
474                         if ((pRegToSet[index] & 0xf0) > (FactorToSet << 4))
475                                 pRegToSet[index] = (pRegToSet[index] & 0x0f) |
476                                         (FactorToSet << 4);
477
478                         if ((pRegToSet[index] & 0x0f) > FactorToSet)
479                                 pRegToSet[index] = (pRegToSet[index] & 0xf0) |
480                                         FactorToSet;
481
482                         rtl8723au_write8(padapter, REG_AGGLEN_LMT + index,
483                                          pRegToSet[index]);
484                 }
485
486                 /* RT_TRACE(COMP_MLME, DBG_LOUD,
487                    ("Set HW_VAR_AMPDU_FACTOR: %#x\n", FactorToSet)); */
488         }
489 }
490
491 void rtl8723a_set_acm_ctrl(struct rtw_adapter *padapter, u8 ctrl)
492 {
493         u8 hwctrl = 0;
494
495         if (ctrl != 0) {
496                 hwctrl |= AcmHw_HwEn;
497
498                 if (ctrl & BIT(1))      /*  BE */
499                         hwctrl |= AcmHw_BeqEn;
500
501                 if (ctrl & BIT(2))      /*  VI */
502                         hwctrl |= AcmHw_ViqEn;
503
504                 if (ctrl & BIT(3))      /*  VO */
505                         hwctrl |= AcmHw_VoqEn;
506         }
507
508         DBG_8723A("[HW_VAR_ACM_CTRL] Write 0x%02X\n", hwctrl);
509         rtl8723au_write8(padapter, REG_ACMHWCTRL, hwctrl);
510 }
511
512 void rtl8723a_set_media_status(struct rtw_adapter *padapter, u8 status)
513 {
514         u8 val8;
515
516         val8 = rtl8723au_read8(padapter, MSR) & 0x0c;
517         val8 |= status;
518         rtl8723au_write8(padapter, MSR, val8);
519 }
520
521 void rtl8723a_set_media_status1(struct rtw_adapter *padapter, u8 status)
522 {
523         u8 val8;
524
525         val8 = rtl8723au_read8(padapter, MSR) & 0x03;
526         val8 |= status << 2;
527         rtl8723au_write8(padapter, MSR, val8);
528 }
529
530 void rtl8723a_set_bcn_func(struct rtw_adapter *padapter, u8 val)
531 {
532         if (val)
533                 SetBcnCtrlReg23a(padapter, EN_BCN_FUNCTION | EN_TXBCN_RPT, 0);
534         else
535                 SetBcnCtrlReg23a(padapter, 0, EN_BCN_FUNCTION | EN_TXBCN_RPT);
536 }
537
538 void rtl8723a_check_bssid(struct rtw_adapter *padapter, u8 val)
539 {
540         u32 val32;
541         val32 = rtl8723au_read32(padapter, REG_RCR);
542         if (val)
543                 val32 |= RCR_CBSSID_DATA | RCR_CBSSID_BCN;
544         else
545                 val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
546         rtl8723au_write32(padapter, REG_RCR, val32);
547 }
548
549 void rtl8723a_mlme_sitesurvey(struct rtw_adapter *padapter, u8 flag)
550 {
551         if (flag) {     /* under sitesurvey */
552                 u32 v32;
553
554                 /*  config RCR to receive different BSSID & not
555                     to receive data frame */
556                 v32 = rtl8723au_read32(padapter, REG_RCR);
557                 v32 &= ~(RCR_CBSSID_BCN);
558                 rtl8723au_write32(padapter, REG_RCR, v32);
559                 /*  reject all data frame */
560                 rtl8723au_write16(padapter, REG_RXFLTMAP2, 0);
561
562                 /*  disable update TSF */
563                 SetBcnCtrlReg23a(padapter, DIS_TSF_UDT, 0);
564         } else {        /* sitesurvey done */
565
566                 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
567                 struct mlme_ext_info *pmlmeinfo;
568                 u32 v32;
569
570                 pmlmeinfo = &pmlmeext->mlmext_info;
571
572                 if ((is_client_associated_to_ap23a(padapter) == true) ||
573                     ((pmlmeinfo->state & 0x03) == WIFI_FW_ADHOC_STATE) ||
574                     ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
575                         /*  enable to rx data frame */
576                         rtl8723au_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
577
578                         /*  enable update TSF */
579                         SetBcnCtrlReg23a(padapter, 0, DIS_TSF_UDT);
580                 }
581
582                 v32 = rtl8723au_read32(padapter, REG_RCR);
583                 v32 |= RCR_CBSSID_BCN;
584                 rtl8723au_write32(padapter, REG_RCR, v32);
585         }
586
587 #ifdef CONFIG_8723AU_BT_COEXIST
588         BT_WifiScanNotify(padapter, flag ? true : false);
589 #endif
590 }
591
592 void rtl8723a_on_rcr_am(struct rtw_adapter *padapter)
593 {
594         rtl8723au_write32(padapter, REG_RCR,
595                     rtl8723au_read32(padapter, REG_RCR) | RCR_AM);
596         DBG_8723A("%s, %d, RCR = %x \n", __FUNCTION__, __LINE__,
597                   rtl8723au_read32(padapter, REG_RCR));
598 }
599
600 void rtl8723a_off_rcr_am(struct rtw_adapter *padapter)
601 {
602         rtl8723au_write32(padapter, REG_RCR,
603                     rtl8723au_read32(padapter, REG_RCR) & (~RCR_AM));
604         DBG_8723A("%s, %d, RCR = %x \n", __FUNCTION__, __LINE__,
605                   rtl8723au_read32(padapter, REG_RCR));
606 }
607
608 void rtl8723a_set_slot_time(struct rtw_adapter *padapter, u8 slottime)
609 {
610         u8 u1bAIFS, aSifsTime;
611         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
612         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
613
614         rtl8723au_write8(padapter, REG_SLOT, slottime);
615
616         if (pmlmeinfo->WMM_enable == 0) {
617                 if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
618                         aSifsTime = 10;
619                 else
620                         aSifsTime = 16;
621
622                 u1bAIFS = aSifsTime + (2 * pmlmeinfo->slotTime);
623
624                 /*  <Roger_EXP> Temporary removed, 2008.06.20. */
625                 rtl8723au_write8(padapter, REG_EDCA_VO_PARAM, u1bAIFS);
626                 rtl8723au_write8(padapter, REG_EDCA_VI_PARAM, u1bAIFS);
627                 rtl8723au_write8(padapter, REG_EDCA_BE_PARAM, u1bAIFS);
628                 rtl8723au_write8(padapter, REG_EDCA_BK_PARAM, u1bAIFS);
629         }
630 }
631
632 void rtl8723a_ack_preamble(struct rtw_adapter *padapter, u8 bShortPreamble)
633 {
634         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
635         u8 regTmp;
636
637         /*  Joseph marked out for Netgear 3500 TKIP
638             channel 7 issue.(Temporarily) */
639         regTmp = (pHalData->nCur40MhzPrimeSC) << 5;
640         /* regTmp = 0; */
641         if (bShortPreamble)
642                 regTmp |= 0x80;
643         rtl8723au_write8(padapter, REG_RRSR + 2, regTmp);
644 }
645
646 void rtl8723a_set_sec_cfg(struct rtw_adapter *padapter, u8 sec)
647 {
648         rtl8723au_write8(padapter, REG_SECCFG, sec);
649 }
650
651 void rtl8723a_cam_empty_entry(struct rtw_adapter *padapter, u8 ucIndex)
652 {
653         u8 i;
654         u32 ulCommand = 0;
655         u32 ulContent = 0;
656         u32 ulEncAlgo = CAM_AES;
657
658         for (i = 0; i < CAM_CONTENT_COUNT; i++) {
659                 /*  filled id in CAM config 2 byte */
660                 if (i == 0) {
661                         ulContent |= (ucIndex & 0x03) |
662                                 ((u16) (ulEncAlgo) << 2);
663                         /* ulContent |= CAM_VALID; */
664                 } else {
665                         ulContent = 0;
666                 }
667                 /*  polling bit, and No Write enable, and address */
668                 ulCommand = CAM_CONTENT_COUNT * ucIndex + i;
669                 ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE;
670                 /*  write content 0 is equall to mark invalid */
671                 /* delay_ms(40); */
672                 rtl8723au_write32(padapter, WCAMI, ulContent);
673                 /* RT_TRACE(COMP_SEC, DBG_LOUD,
674                    ("rtl8723a_cam_empty_entry(): WRITE A4: %lx \n",
675                    ulContent));*/
676                 /* delay_ms(40); */
677                 rtl8723au_write32(padapter, RWCAM, ulCommand);
678                 /* RT_TRACE(COMP_SEC, DBG_LOUD,
679                    ("rtl8723a_cam_empty_entry(): WRITE A0: %lx \n",
680                    ulCommand));*/
681         }
682 }
683
684 void rtl8723a_cam_invalid_all(struct rtw_adapter *padapter)
685 {
686         rtl8723au_write32(padapter, RWCAM, BIT(31) | BIT(30));
687 }
688
689 void rtl8723a_cam_write(struct rtw_adapter *padapter,
690                         u8 entry, u16 ctrl, const u8 *mac, const u8 *key)
691 {
692         u32 cmd;
693         unsigned int i, val, addr;
694         int j;
695
696         addr = entry << 3;
697
698         for (j = 5; j >= 0; j--) {
699                 switch (j) {
700                 case 0:
701                         val = ctrl | (mac[0] << 16) | (mac[1] << 24);
702                         break;
703                 case 1:
704                         val = mac[2] | (mac[3] << 8) |
705                                 (mac[4] << 16) | (mac[5] << 24);
706                         break;
707                 default:
708                         i = (j - 2) << 2;
709                         val = key[i] | (key[i+1] << 8) |
710                                 (key[i+2] << 16) | (key[i+3] << 24);
711                         break;
712                 }
713
714                 rtl8723au_write32(padapter, WCAMI, val);
715                 cmd = CAM_POLLINIG | CAM_WRITE | (addr + j);
716                 rtl8723au_write32(padapter, RWCAM, cmd);
717
718                 /* DBG_8723A("%s => cam write: %x, %x\n", __func__, cmd, val);*/
719         }
720 }
721
722 void rtl8723a_fifo_cleanup(struct rtw_adapter *padapter)
723 {
724 #define RW_RELEASE_EN           BIT(18)
725 #define RXDMA_IDLE              BIT(17)
726
727         struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
728         u8 trycnt = 100;
729
730         /*  pause tx */
731         rtl8723au_write8(padapter, REG_TXPAUSE, 0xff);
732
733         /*  keep sn */
734         padapter->xmitpriv.nqos_ssn = rtl8723au_read16(padapter, REG_NQOS_SEQ);
735
736         if (pwrpriv->bkeepfwalive != true) {
737                 u32 v32;
738
739                 /*  RX DMA stop */
740                 v32 = rtl8723au_read32(padapter, REG_RXPKT_NUM);
741                 v32 |= RW_RELEASE_EN;
742                 rtl8723au_write32(padapter, REG_RXPKT_NUM, v32);
743                 do {
744                         v32 = rtl8723au_read32(padapter,
745                                                REG_RXPKT_NUM) & RXDMA_IDLE;
746                         if (!v32)
747                                 break;
748                 } while (trycnt--);
749                 if (trycnt == 0) {
750                         DBG_8723A("Stop RX DMA failed......\n");
751                 }
752
753                 /*  RQPN Load 0 */
754                 rtl8723au_write16(padapter, REG_RQPN_NPQ, 0);
755                 rtl8723au_write32(padapter, REG_RQPN, 0x80000000);
756                 mdelay(10);
757         }
758 }
759
760 void rtl8723a_bcn_valid(struct rtw_adapter *padapter)
761 {
762         /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2,
763            write 1 to clear, Clear by sw */
764         rtl8723au_write8(padapter, REG_TDECTRL + 2,
765                          rtl8723au_read8(padapter, REG_TDECTRL + 2) | BIT(0));
766 }
767
768 bool rtl8723a_get_bcn_valid(struct rtw_adapter *padapter)
769 {
770         bool retval;
771
772         retval = (rtl8723au_read8(padapter, REG_TDECTRL + 2) & BIT(0)) ? true : false;
773
774         return retval;
775 }
776
777 void rtl8723a_set_beacon_interval(struct rtw_adapter *padapter, u16 interval)
778 {
779         rtl8723au_write16(padapter, REG_BCN_INTERVAL, interval);
780 }
781
782 void rtl8723a_set_resp_sifs(struct rtw_adapter *padapter,
783                             u8 r2t1, u8 r2t2, u8 t2t1, u8 t2t2)
784 {
785         /* SIFS_Timer = 0x0a0a0808; */
786         /* RESP_SIFS for CCK */
787         /*  SIFS_T2T_CCK (0x08) */
788         rtl8723au_write8(padapter, REG_R2T_SIFS, r2t1);
789         /* SIFS_R2T_CCK(0x08) */
790         rtl8723au_write8(padapter, REG_R2T_SIFS + 1, r2t2);
791         /* RESP_SIFS for OFDM */
792         /* SIFS_T2T_OFDM (0x0a) */
793         rtl8723au_write8(padapter, REG_T2T_SIFS, t2t1);
794         /* SIFS_R2T_OFDM(0x0a) */
795         rtl8723au_write8(padapter, REG_T2T_SIFS + 1, t2t2);
796 }
797
798 void rtl8723a_set_ac_param_vo(struct rtw_adapter *padapter, u32 vo)
799 {
800         rtl8723au_write32(padapter, REG_EDCA_VO_PARAM, vo);
801 }
802
803 void rtl8723a_set_ac_param_vi(struct rtw_adapter *padapter, u32 vi)
804 {
805         rtl8723au_write32(padapter, REG_EDCA_VI_PARAM, vi);
806 }
807
808 void rtl8723a_set_ac_param_be(struct rtw_adapter *padapter, u32 be)
809 {
810         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
811
812         pHalData->AcParam_BE = be;
813         rtl8723au_write32(padapter, REG_EDCA_BE_PARAM, be);
814 }
815
816 void rtl8723a_set_ac_param_bk(struct rtw_adapter *padapter, u32 bk)
817 {
818         rtl8723au_write32(padapter, REG_EDCA_BK_PARAM, bk);
819 }
820
821 void rtl8723a_set_rxdma_agg_pg_th(struct rtw_adapter *padapter, u8 val)
822 {
823         rtl8723au_write8(padapter, REG_RXDMA_AGG_PG_TH, val);
824 }
825
826 void rtl8723a_set_nav_upper(struct rtw_adapter *padapter, u32 usNavUpper)
827 {
828         if (usNavUpper > HAL_8723A_NAV_UPPER_UNIT * 0xFF) {
829                 RT_TRACE(_module_hal_init_c_, _drv_notice_,
830                          ("The setting value (0x%08X us) of NAV_UPPER "
831                           "is larger than (%d * 0xFF)!!!\n",
832                           usNavUpper, HAL_8723A_NAV_UPPER_UNIT));
833                 return;
834         }
835
836         /*  The value of ((usNavUpper + HAL_8723A_NAV_UPPER_UNIT - 1) /
837             HAL_8723A_NAV_UPPER_UNIT) */
838         /*  is getting the upper integer. */
839         usNavUpper = (usNavUpper + HAL_8723A_NAV_UPPER_UNIT - 1) /
840                 HAL_8723A_NAV_UPPER_UNIT;
841         rtl8723au_write8(padapter, REG_NAV_UPPER, (u8) usNavUpper);
842 }
843
844 void rtl8723a_set_initial_gain(struct rtw_adapter *padapter, u32 rx_gain)
845 {
846         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
847         struct dig_t *pDigTable = &pHalData->odmpriv.DM_DigTable;
848
849         if (rx_gain == 0xff)    /* restore rx gain */
850                 ODM_Write_DIG23a(&pHalData->odmpriv, pDigTable->BackupIGValue);
851         else {
852                 pDigTable->BackupIGValue = pDigTable->CurIGValue;
853                 ODM_Write_DIG23a(&pHalData->odmpriv, rx_gain);
854         }
855 }
856
857 void rtl8723a_odm_support_ability_restore(struct rtw_adapter *padapter)
858 {
859         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
860
861         pHalData->odmpriv.SupportAbility = pHalData->odmpriv.BK_SupportAbility;
862 }
863
864 void rtl8723a_odm_support_ability_backup(struct rtw_adapter *padapter)
865 {
866         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
867
868         pHalData->odmpriv.BK_SupportAbility = pHalData->odmpriv.SupportAbility;
869 }
870
871 void rtl8723a_odm_support_ability_set(struct rtw_adapter *padapter, u32 val)
872 {
873         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
874
875         if (val == DYNAMIC_ALL_FUNC_ENABLE) {
876                 pHalData->dmpriv.DMFlag = pHalData->dmpriv.InitDMFlag;
877                 pHalData->odmpriv.SupportAbility = pHalData->dmpriv.InitODMFlag;
878         } else {
879                 pHalData->odmpriv.SupportAbility |= val;
880         }
881 }
882
883 void rtl8723a_odm_support_ability_clr(struct rtw_adapter *padapter, u32 val)
884 {
885         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
886
887         pHalData->odmpriv.SupportAbility &= val;
888 }
889
890 void rtl8723a_set_rpwm(struct rtw_adapter *padapter, u8 val)
891 {
892         rtl8723au_write8(padapter, REG_USB_HRPWM, val);
893 }
894
895 u8 rtl8723a_get_rf_type(struct rtw_adapter *padapter)
896 {
897         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
898
899         return pHalData->rf_type;
900 }
901
902 bool rtl8723a_get_fwlps_rf_on(struct rtw_adapter *padapter)
903 {
904         bool retval;
905         u32 valRCR;
906
907         /*  When we halt NIC, we should check if FW LPS is leave. */
908
909         if ((padapter->bSurpriseRemoved == true) ||
910             (padapter->pwrctrlpriv.rf_pwrstate == rf_off)) {
911                 /*  If it is in HW/SW Radio OFF or IPS state, we do
912                     not check Fw LPS Leave, because Fw is unload. */
913                 retval = true;
914         } else {
915                 valRCR = rtl8723au_read32(padapter, REG_RCR);
916                 if (valRCR & 0x00070000)
917                         retval = false;
918                 else
919                         retval = true;
920         }
921
922         return retval;
923 }
924
925 bool rtl8723a_chk_hi_queue_empty(struct rtw_adapter *padapter)
926 {
927         u32 hgq;
928
929         hgq = rtl8723au_read32(padapter, REG_HGQ_INFORMATION);
930
931         return ((hgq & 0x0000ff00) == 0) ? true : false;
932 }