staging: rtl8723au: Fold _BlockWrite() into _PageWrite()
[cascardo/linux.git] / drivers / staging / rtl8723au / hal / rtl8723a_hal_init.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2012 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 #define _HAL_INIT_C_
16
17 #include <linux/firmware.h>
18 #include <drv_types.h>
19 #include <rtw_efuse.h>
20
21 #include <rtl8723a_hal.h>
22 #include <usb_ops_linux.h>
23
24 static void _FWDownloadEnable(struct rtw_adapter *padapter, bool enable)
25 {
26         u8 tmp;
27
28         if (enable) {
29                 /*  8051 enable */
30                 tmp = rtl8723au_read8(padapter, REG_SYS_FUNC_EN + 1);
31                 rtl8723au_write8(padapter, REG_SYS_FUNC_EN + 1, tmp | 0x04);
32
33                 /*  MCU firmware download enable. */
34                 tmp = rtl8723au_read8(padapter, REG_MCUFWDL);
35                 rtl8723au_write8(padapter, REG_MCUFWDL, tmp | 0x01);
36
37                 /*  8051 reset */
38                 tmp = rtl8723au_read8(padapter, REG_MCUFWDL + 2);
39                 rtl8723au_write8(padapter, REG_MCUFWDL + 2, tmp & 0xf7);
40         } else {
41                 /*  MCU firmware download disable. */
42                 tmp = rtl8723au_read8(padapter, REG_MCUFWDL);
43                 rtl8723au_write8(padapter, REG_MCUFWDL, tmp & 0xfe);
44
45                 /*  Reserved for fw extension. */
46                 rtl8723au_write8(padapter, REG_MCUFWDL + 1, 0x00);
47         }
48 }
49
50 static int
51 _PageWrite(struct rtw_adapter *padapter, u32 page, void *buffer, u32 size)
52 {
53         u8 value8;
54         u8 u8Page = (u8) (page & 0x07);
55
56         if (size > MAX_PAGE_SIZE)
57                 return _FAIL;
58
59         value8 = (rtl8723au_read8(padapter, REG_MCUFWDL + 2) & 0xF8) | u8Page;
60         rtl8723au_write8(padapter, REG_MCUFWDL + 2, value8);
61
62         return rtl8723au_writeN(padapter, FW_8723A_START_ADDRESS, size, buffer);
63 }
64
65 static int _WriteFW(struct rtw_adapter *padapter, void *buffer, u32 size)
66 {
67         /*  Since we need dynamic decide method of dwonload fw, so we
68             call this function to get chip version. */
69         /*  We can remove _ReadChipVersion from ReadpadapterInfo8192C later. */
70         int ret = _SUCCESS;
71         u32 pageNums, remainSize;
72         u32 page, offset;
73         u8 *bufferPtr = (u8 *) buffer;
74
75         pageNums = size / MAX_PAGE_SIZE;
76         /* RT_ASSERT((pageNums <= 4),
77            ("Page numbers should not greater then 4 \n")); */
78         remainSize = size % MAX_PAGE_SIZE;
79
80         for (page = 0; page < pageNums; page++) {
81                 offset = page * MAX_PAGE_SIZE;
82                 ret = _PageWrite(padapter, page, bufferPtr + offset,
83                                  MAX_PAGE_SIZE);
84
85                 if (ret == _FAIL)
86                         goto exit;
87         }
88         if (remainSize) {
89                 offset = pageNums * MAX_PAGE_SIZE;
90                 page = pageNums;
91                 ret = _PageWrite(padapter, page, bufferPtr + offset,
92                                  remainSize);
93
94                 if (ret == _FAIL)
95                         goto exit;
96         }
97         RT_TRACE(_module_hal_init_c_, _drv_info_,
98                  ("_WriteFW Done- for Normal chip.\n"));
99
100 exit:
101         return ret;
102 }
103
104 static int _FWFreeToGo(struct rtw_adapter *padapter)
105 {
106         u32 counter = 0;
107         u32 value32;
108
109         /*  polling CheckSum report */
110         do {
111                 value32 = rtl8723au_read32(padapter, REG_MCUFWDL);
112                 if (value32 & FWDL_ChkSum_rpt)
113                         break;
114         } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
115
116         if (counter >= POLLING_READY_TIMEOUT_COUNT) {
117                 RT_TRACE(_module_hal_init_c_, _drv_err_,
118                          ("%s: chksum report fail! REG_MCUFWDL:0x%08x\n",
119                           __func__, value32));
120                 return _FAIL;
121         }
122         RT_TRACE(_module_hal_init_c_, _drv_info_,
123                  ("%s: Checksum report OK! REG_MCUFWDL:0x%08x\n", __func__,
124                   value32));
125
126         value32 = rtl8723au_read32(padapter, REG_MCUFWDL);
127         value32 |= MCUFWDL_RDY;
128         value32 &= ~WINTINI_RDY;
129         rtl8723au_write32(padapter, REG_MCUFWDL, value32);
130
131         /*  polling for FW ready */
132         counter = 0;
133         do {
134                 value32 = rtl8723au_read32(padapter, REG_MCUFWDL);
135                 if (value32 & WINTINI_RDY) {
136                         RT_TRACE(_module_hal_init_c_, _drv_info_,
137                                  ("%s: Polling FW ready success!! "
138                                   "REG_MCUFWDL:0x%08x\n",
139                                   __func__, value32));
140                         return _SUCCESS;
141                 }
142                 udelay(5);
143         } while (counter++ < POLLING_READY_TIMEOUT_COUNT);
144
145         RT_TRACE(_module_hal_init_c_, _drv_err_,
146                  ("%s: Polling FW ready fail!! REG_MCUFWDL:0x%08x\n",
147                   __func__, value32));
148         return _FAIL;
149 }
150
151 #define IS_FW_81xxC(padapter)   (((GET_HAL_DATA(padapter))->FirmwareSignature & 0xFFF0) == 0x88C0)
152
153 void rtl8723a_FirmwareSelfReset(struct rtw_adapter *padapter)
154 {
155         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
156         u8 u1bTmp;
157         u8 Delay = 100;
158
159         if (!(IS_FW_81xxC(padapter) &&
160               ((pHalData->FirmwareVersion < 0x21) ||
161                (pHalData->FirmwareVersion == 0x21 &&
162                 pHalData->FirmwareSubVersion < 0x01)))) {
163                 /*  after 88C Fw v33.1 */
164                 /* 0x1cf = 0x20. Inform 8051 to reset. 2009.12.25. tynli_test */
165                 rtl8723au_write8(padapter, REG_HMETFR + 3, 0x20);
166
167                 u1bTmp = rtl8723au_read8(padapter, REG_SYS_FUNC_EN + 1);
168                 while (u1bTmp & BIT(2)) {
169                         Delay--;
170                         if (Delay == 0)
171                                 break;
172                         udelay(50);
173                         u1bTmp = rtl8723au_read8(padapter, REG_SYS_FUNC_EN + 1);
174                 }
175                 RT_TRACE(_module_hal_init_c_, _drv_info_,
176                          ("-%s: 8051 reset success (%d)\n", __func__,
177                           Delay));
178
179                 if ((Delay == 0)) {
180                         /* force firmware reset */
181                         u1bTmp = rtl8723au_read8(padapter, REG_SYS_FUNC_EN + 1);
182                         rtl8723au_write8(padapter, REG_SYS_FUNC_EN + 1,
183                                          u1bTmp & ~BIT(2));
184                 }
185         }
186 }
187
188 /*  */
189 /*      Description: */
190 /*              Download 8192C firmware code. */
191 /*  */
192 /*  */
193 int rtl8723a_FirmwareDownload(struct rtw_adapter *padapter)
194 {
195         int rtStatus = _SUCCESS;
196         u8 writeFW_retry = 0;
197         unsigned long fwdl_start_time;
198         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
199         struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
200         struct device *device = dvobj_to_dev(dvobj);
201         struct rt_8723a_firmware_hdr *pFwHdr = NULL;
202         const struct firmware *fw;
203         char *fw_name;
204         u8 *firmware_buf = NULL;
205         u8 *buf;
206         int fw_size;
207         static int log_version;
208
209         RT_TRACE(_module_hal_init_c_, _drv_info_, ("+%s\n", __func__));
210
211         if (IS_8723A_A_CUT(pHalData->VersionID)) {
212                 fw_name = "rtlwifi/rtl8723aufw_A.bin";
213                 RT_TRACE(_module_hal_init_c_, _drv_info_,
214                          ("rtl8723a_FirmwareDownload: R8723FwImageArray_UMC "
215                           "for RTL8723A A CUT\n"));
216         } else if (IS_8723A_B_CUT(pHalData->VersionID)) {
217                 /*  WLAN Fw. */
218                 if (padapter->registrypriv.wifi_spec == 1) {
219                         fw_name = "rtlwifi/rtl8723aufw_B_NoBT.bin";
220                         DBG_8723A(" Rtl8723_FwUMCBCutImageArrayWithoutBT for "
221                                   "RTL8723A B CUT\n");
222                 } else {
223                         if (rtl8723a_BT_coexist(padapter)) {
224                                 fw_name = "rtlwifi/rtl8723aufw_B.bin";
225                                 DBG_8723A(" Rtl8723_FwUMCBCutImageArrayWithBT "
226                                           "for RTL8723A B CUT\n");
227                         } else {
228                                 fw_name = "rtlwifi/rtl8723aufw_B_NoBT.bin";
229                                 DBG_8723A(" Rtl8723_FwUMCBCutImageArrayWithout "
230                                           "BT for RTL8723A B CUT\n");
231                         }
232                 }
233         } else {
234                 /*  <Roger_TODO> We should download proper RAM Code here
235                     to match the ROM code. */
236                 RT_TRACE(_module_hal_init_c_, _drv_err_,
237                          ("%s: unknow version!\n", __func__));
238                 rtStatus = _FAIL;
239                 goto Exit;
240         }
241
242         pr_info("rtl8723au: Loading firmware %s\n", fw_name);
243         if (request_firmware(&fw, fw_name, device)) {
244                 pr_err("rtl8723au: request_firmware load failed\n");
245                 rtStatus = _FAIL;
246                 goto Exit;
247         }
248         if (!fw) {
249                 pr_err("rtl8723au: Firmware %s not available\n", fw_name);
250                 rtStatus = _FAIL;
251                 goto Exit;
252         }
253         firmware_buf = kmemdup(fw->data, fw->size, GFP_KERNEL);
254         if (!firmware_buf) {
255                 rtStatus = _FAIL;
256                 goto Exit;
257         }
258         buf = firmware_buf;
259         fw_size = fw->size;
260         release_firmware(fw);
261
262         /*  To Check Fw header. Added by tynli. 2009.12.04. */
263         pFwHdr = (struct rt_8723a_firmware_hdr *)firmware_buf;
264
265         pHalData->FirmwareVersion = le16_to_cpu(pFwHdr->Version);
266         pHalData->FirmwareSubVersion = pFwHdr->Subversion;
267         pHalData->FirmwareSignature = le16_to_cpu(pFwHdr->Signature);
268
269         DBG_8723A("%s: fw_ver =%d fw_subver =%d sig = 0x%x\n",
270                   __func__, pHalData->FirmwareVersion,
271                   pHalData->FirmwareSubVersion, pHalData->FirmwareSignature);
272
273         if (!log_version++)
274                 pr_info("%sFirmware Version %d, SubVersion %d, Signature "
275                         "0x%x\n", DRIVER_PREFIX, pHalData->FirmwareVersion,
276                         pHalData->FirmwareSubVersion,
277                         pHalData->FirmwareSignature);
278
279         if (IS_FW_HEADER_EXIST(pFwHdr)) {
280                 /*  Shift 32 bytes for FW header */
281                 buf = buf + 32;
282                 fw_size = fw_size - 32;
283         }
284
285         /*  Suggested by Filen. If 8051 is running in RAM code, driver should
286             inform Fw to reset by itself, */
287         /*  or it will cause download Fw fail. 2010.02.01. by tynli. */
288         if (rtl8723au_read8(padapter, REG_MCUFWDL) & RAM_DL_SEL) {
289                 /* 8051 RAM code */
290                 rtl8723a_FirmwareSelfReset(padapter);
291                 rtl8723au_write8(padapter, REG_MCUFWDL, 0x00);
292         }
293
294         _FWDownloadEnable(padapter, true);
295         fwdl_start_time = jiffies;
296         while (1) {
297                 /* reset the FWDL chksum */
298                 rtl8723au_write8(padapter, REG_MCUFWDL,
299                                  rtl8723au_read8(padapter, REG_MCUFWDL) |
300                                  FWDL_ChkSum_rpt);
301
302                 rtStatus = _WriteFW(padapter, buf, fw_size);
303
304                 if (rtStatus == _SUCCESS ||
305                     (jiffies_to_msecs(jiffies - fwdl_start_time) > 500 &&
306                      writeFW_retry++ >= 3))
307                         break;
308
309                 DBG_8723A("%s writeFW_retry:%u, time after fwdl_start_time:"
310                           "%ums\n", __func__, writeFW_retry,
311                           jiffies_to_msecs(jiffies - fwdl_start_time));
312         }
313         _FWDownloadEnable(padapter, false);
314         if (_SUCCESS != rtStatus) {
315                 DBG_8723A("DL Firmware failed!\n");
316                 goto Exit;
317         }
318
319         rtStatus = _FWFreeToGo(padapter);
320         if (_SUCCESS != rtStatus) {
321                 RT_TRACE(_module_hal_init_c_, _drv_err_,
322                          ("DL Firmware failed!\n"));
323                 goto Exit;
324         }
325         RT_TRACE(_module_hal_init_c_, _drv_info_,
326                  ("Firmware is ready to run!\n"));
327
328 Exit:
329         kfree(firmware_buf);
330         return rtStatus;
331 }
332
333 void rtl8723a_InitializeFirmwareVars(struct rtw_adapter *padapter)
334 {
335         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
336
337         /*  Init Fw LPS related. */
338         padapter->pwrctrlpriv.bFwCurrentInPSMode = false;
339
340         /*  Init H2C counter. by tynli. 2009.12.09. */
341         pHalData->LastHMEBoxNum = 0;
342 }
343
344 /*  */
345 /*                              Efuse related code */
346 /*  */
347 static u8
348 hal_EfuseSwitchToBank(struct rtw_adapter *padapter, u8 bank)
349 {
350         u8 bRet = false;
351         u32 value32 = 0;
352
353         DBG_8723A("%s: Efuse switch bank to %d\n", __func__, bank);
354         value32 = rtl8723au_read32(padapter, EFUSE_TEST);
355         bRet = true;
356         switch (bank) {
357         case 0:
358                 value32 = (value32 & ~EFUSE_SEL_MASK) |
359                         EFUSE_SEL(EFUSE_WIFI_SEL_0);
360                 break;
361         case 1:
362                 value32 = (value32 & ~EFUSE_SEL_MASK) |
363                         EFUSE_SEL(EFUSE_BT_SEL_0);
364                 break;
365         case 2:
366                 value32 = (value32 & ~EFUSE_SEL_MASK) |
367                         EFUSE_SEL(EFUSE_BT_SEL_1);
368                 break;
369         case 3:
370                 value32 = (value32 & ~EFUSE_SEL_MASK) |
371                         EFUSE_SEL(EFUSE_BT_SEL_2);
372                 break;
373         default:
374                 value32 = (value32 & ~EFUSE_SEL_MASK) |
375                         EFUSE_SEL(EFUSE_WIFI_SEL_0);
376                 bRet = false;
377                 break;
378         }
379         rtl8723au_write32(padapter, EFUSE_TEST, value32);
380
381         return bRet;
382 }
383
384 static void
385 hal_ReadEFuse_WiFi(struct rtw_adapter *padapter,
386                    u16 _offset, u16 _size_byte, u8 *pbuf)
387 {
388         u8 *efuseTbl = NULL;
389         u16 eFuse_Addr = 0;
390         u8 offset, wden;
391         u8 efuseHeader, efuseExtHdr, efuseData;
392         u16 i, total, used;
393         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
394
395         /*  Do NOT excess total size of EFuse table.
396             Added by Roger, 2008.11.10. */
397         if ((_offset + _size_byte) > EFUSE_MAP_LEN_8723A) {
398                 DBG_8723A("%s: Invalid offset(%#x) with read bytes(%#x)!!\n",
399                           __func__, _offset, _size_byte);
400                 return;
401         }
402
403         efuseTbl = kmalloc(EFUSE_MAP_LEN_8723A, GFP_KERNEL);
404         if (efuseTbl == NULL) {
405                 DBG_8723A("%s: alloc efuseTbl fail!\n", __func__);
406                 return;
407         }
408         /*  0xff will be efuse default value instead of 0x00. */
409         memset(efuseTbl, 0xFF, EFUSE_MAP_LEN_8723A);
410
411         /*  switch bank back to bank 0 for later BT and wifi use. */
412         hal_EfuseSwitchToBank(padapter, 0);
413
414         while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
415                 ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseHeader);
416                 if (efuseHeader == 0xFF) {
417                         DBG_8723A("%s: data end at address =%#x\n", __func__,
418                                   eFuse_Addr);
419                         break;
420                 }
421
422                 /*  Check PG header for section num. */
423                 if (EXT_HEADER(efuseHeader)) {  /* extended header */
424                         offset = GET_HDR_OFFSET_2_0(efuseHeader);
425
426                         ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseExtHdr);
427                         if (ALL_WORDS_DISABLED(efuseExtHdr)) {
428                                 continue;
429                         }
430
431                         offset |= ((efuseExtHdr & 0xF0) >> 1);
432                         wden = (efuseExtHdr & 0x0F);
433                 } else {
434                         offset = ((efuseHeader >> 4) & 0x0f);
435                         wden = (efuseHeader & 0x0f);
436                 }
437
438                 if (offset < EFUSE_MAX_SECTION_8723A) {
439                         u16 addr;
440                         /*  Get word enable value from PG header */
441
442                         addr = offset * PGPKT_DATA_SIZE;
443                         for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
444                                 /* Check word enable condition in the section */
445                                 if (!(wden & (0x01 << i))) {
446                                         ReadEFuseByte23a(padapter, eFuse_Addr++,
447                                                       &efuseData);
448                                         efuseTbl[addr] = efuseData;
449
450                                         ReadEFuseByte23a(padapter, eFuse_Addr++,
451                                                       &efuseData);
452                                         efuseTbl[addr + 1] = efuseData;
453                                 }
454                                 addr += 2;
455                         }
456                 } else {
457                         DBG_8723A(KERN_ERR "%s: offset(%d) is illegal!!\n",
458                                   __func__, offset);
459                         eFuse_Addr += Efuse_CalculateWordCnts23a(wden) * 2;
460                 }
461         }
462
463         /*  Copy from Efuse map to output pointer memory!!! */
464         for (i = 0; i < _size_byte; i++)
465                 pbuf[i] = efuseTbl[_offset + i];
466
467         /*  Calculate Efuse utilization */
468         EFUSE_GetEfuseDefinition23a(padapter, EFUSE_WIFI,
469                                  TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total);
470         used = eFuse_Addr - 1;
471         pHalData->EfuseUsedBytes = used;
472
473         kfree(efuseTbl);
474 }
475
476 static void
477 hal_ReadEFuse_BT(struct rtw_adapter *padapter,
478                  u16 _offset, u16 _size_byte, u8 *pbuf)
479 {
480         u8 *efuseTbl;
481         u8 bank;
482         u16 eFuse_Addr;
483         u8 efuseHeader, efuseExtHdr, efuseData;
484         u8 offset, wden;
485         u16 i, total, used;
486         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
487
488         /*  Do NOT excess total size of EFuse table.
489             Added by Roger, 2008.11.10. */
490         if ((_offset + _size_byte) > EFUSE_BT_MAP_LEN) {
491                 DBG_8723A("%s: Invalid offset(%#x) with read bytes(%#x)!!\n",
492                           __func__, _offset, _size_byte);
493                 return;
494         }
495
496         efuseTbl = kmalloc(EFUSE_BT_MAP_LEN, GFP_KERNEL);
497         if (efuseTbl == NULL) {
498                 DBG_8723A("%s: efuseTbl malloc fail!\n", __func__);
499                 return;
500         }
501         /*  0xff will be efuse default value instead of 0x00. */
502         memset(efuseTbl, 0xFF, EFUSE_BT_MAP_LEN);
503
504         EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
505                                  TYPE_AVAILABLE_EFUSE_BYTES_BANK, &total);
506
507         for (bank = 1; bank < EFUSE_MAX_BANK; bank++) {
508                 if (hal_EfuseSwitchToBank(padapter, bank) == false) {
509                         DBG_8723A("%s: hal_EfuseSwitchToBank Fail!!\n",
510                                   __func__);
511                         goto exit;
512                 }
513
514                 eFuse_Addr = 0;
515
516                 while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
517                         ReadEFuseByte23a(padapter, eFuse_Addr++, &efuseHeader);
518                         if (efuseHeader == 0xFF)
519                                 break;
520
521                         /*  Check PG header for section num. */
522                         if (EXT_HEADER(efuseHeader)) {  /* extended header */
523                                 offset = GET_HDR_OFFSET_2_0(efuseHeader);
524
525                                 ReadEFuseByte23a(padapter, eFuse_Addr++,
526                                               &efuseExtHdr);
527                                 if (ALL_WORDS_DISABLED(efuseExtHdr)) {
528                                         continue;
529                                 }
530
531                                 offset |= ((efuseExtHdr & 0xF0) >> 1);
532                                 wden = (efuseExtHdr & 0x0F);
533                         } else {
534                                 offset = ((efuseHeader >> 4) & 0x0f);
535                                 wden = (efuseHeader & 0x0f);
536                         }
537
538                         if (offset < EFUSE_BT_MAX_SECTION) {
539                                 u16 addr;
540
541                                 /*  Get word enable value from PG header */
542
543                                 addr = offset * PGPKT_DATA_SIZE;
544                                 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
545                                         /*  Check word enable condition in
546                                             the section */
547                                         if (!(wden & (0x01 << i))) {
548                                                 ReadEFuseByte23a(padapter,
549                                                               eFuse_Addr++,
550                                                               &efuseData);
551                                                 efuseTbl[addr] = efuseData;
552
553                                                 ReadEFuseByte23a(padapter,
554                                                               eFuse_Addr++,
555                                                               &efuseData);
556                                                 efuseTbl[addr + 1] = efuseData;
557                                         }
558                                         addr += 2;
559                                 }
560                         } else {
561                                 DBG_8723A(KERN_ERR
562                                           "%s: offset(%d) is illegal!!\n",
563                                           __func__, offset);
564                                 eFuse_Addr += Efuse_CalculateWordCnts23a(wden) * 2;
565                         }
566                 }
567
568                 if ((eFuse_Addr - 1) < total) {
569                         DBG_8723A("%s: bank(%d) data end at %#x\n",
570                                   __func__, bank, eFuse_Addr - 1);
571                         break;
572                 }
573         }
574
575         /*  switch bank back to bank 0 for later BT and wifi use. */
576         hal_EfuseSwitchToBank(padapter, 0);
577
578         /*  Copy from Efuse map to output pointer memory!!! */
579         for (i = 0; i < _size_byte; i++)
580                 pbuf[i] = efuseTbl[_offset + i];
581
582         /*  */
583         /*  Calculate Efuse utilization. */
584         /*  */
585         EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
586                                  TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &total);
587         used = (EFUSE_BT_REAL_BANK_CONTENT_LEN * (bank - 1)) + eFuse_Addr - 1;
588         pHalData->BTEfuseUsedBytes = used;
589
590 exit:
591         kfree(efuseTbl);
592 }
593
594 void
595 rtl8723a_readefuse(struct rtw_adapter *padapter,
596                    u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf)
597 {
598         if (efuseType == EFUSE_WIFI)
599                 hal_ReadEFuse_WiFi(padapter, _offset, _size_byte, pbuf);
600         else
601                 hal_ReadEFuse_BT(padapter, _offset, _size_byte, pbuf);
602 }
603
604 u16 rtl8723a_EfuseGetCurrentSize_WiFi(struct rtw_adapter *padapter)
605 {
606         u16 efuse_addr = 0;
607         u8 hoffset = 0, hworden = 0;
608         u8 efuse_data, word_cnts = 0;
609         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
610
611         efuse_addr = pHalData->EfuseUsedBytes;
612
613         DBG_8723A("%s: start_efuse_addr = 0x%X\n", __func__, efuse_addr);
614
615         /*  switch bank back to bank 0 for later BT and wifi use. */
616         hal_EfuseSwitchToBank(padapter, 0);
617
618         while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
619                 if (efuse_OneByteRead23a(padapter, efuse_addr, &efuse_data) ==
620                     _FAIL) {
621                         DBG_8723A(KERN_ERR "%s: efuse_OneByteRead23a Fail! "
622                                   "addr = 0x%X !!\n", __func__, efuse_addr);
623                         break;
624                 }
625
626                 if (efuse_data == 0xFF)
627                         break;
628
629                 if (EXT_HEADER(efuse_data)) {
630                         hoffset = GET_HDR_OFFSET_2_0(efuse_data);
631                         efuse_addr++;
632                         efuse_OneByteRead23a(padapter, efuse_addr, &efuse_data);
633                         if (ALL_WORDS_DISABLED(efuse_data)) {
634                                 continue;
635                         }
636
637                         hoffset |= ((efuse_data & 0xF0) >> 1);
638                         hworden = efuse_data & 0x0F;
639                 } else {
640                         hoffset = (efuse_data >> 4) & 0x0F;
641                         hworden = efuse_data & 0x0F;
642                 }
643
644                 word_cnts = Efuse_CalculateWordCnts23a(hworden);
645                 efuse_addr += (word_cnts * 2) + 1;
646         }
647
648         pHalData->EfuseUsedBytes = efuse_addr;
649
650         DBG_8723A("%s: CurrentSize =%d\n", __func__, efuse_addr);
651
652         return efuse_addr;
653 }
654
655 u16 rtl8723a_EfuseGetCurrentSize_BT(struct rtw_adapter *padapter)
656 {
657         u16 btusedbytes;
658         u16 efuse_addr;
659         u8 bank, startBank;
660         u8 hoffset = 0, hworden = 0;
661         u8 efuse_data, word_cnts = 0;
662         u16 retU2 = 0;
663         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
664
665         btusedbytes = pHalData->BTEfuseUsedBytes;
666
667         efuse_addr = (u16) ((btusedbytes % EFUSE_BT_REAL_BANK_CONTENT_LEN));
668         startBank = (u8) (1 + (btusedbytes / EFUSE_BT_REAL_BANK_CONTENT_LEN));
669
670         DBG_8723A("%s: start from bank =%d addr = 0x%X\n", __func__, startBank,
671                   efuse_addr);
672
673         EFUSE_GetEfuseDefinition23a(padapter, EFUSE_BT,
674                                  TYPE_AVAILABLE_EFUSE_BYTES_BANK, &retU2);
675
676         for (bank = startBank; bank < EFUSE_MAX_BANK; bank++) {
677                 if (hal_EfuseSwitchToBank(padapter, bank) == false) {
678                         DBG_8723A(KERN_ERR "%s: switch bank(%d) Fail!!\n",
679                                   __func__, bank);
680                         bank = EFUSE_MAX_BANK;
681                         break;
682                 }
683
684                 /*  only when bank is switched we have to reset
685                     the efuse_addr. */
686                 if (bank != startBank)
687                         efuse_addr = 0;
688
689                 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
690                         if (efuse_OneByteRead23a(padapter, efuse_addr,
691                                               &efuse_data) == _FAIL) {
692                                 DBG_8723A(KERN_ERR "%s: efuse_OneByteRead23a Fail!"
693                                           " addr = 0x%X !!\n",
694                                           __func__, efuse_addr);
695                                 bank = EFUSE_MAX_BANK;
696                                 break;
697                         }
698
699                         if (efuse_data == 0xFF)
700                                 break;
701
702                         if (EXT_HEADER(efuse_data)) {
703                                 hoffset = GET_HDR_OFFSET_2_0(efuse_data);
704                                 efuse_addr++;
705                                 efuse_OneByteRead23a(padapter, efuse_addr,
706                                                   &efuse_data);
707                                 if (ALL_WORDS_DISABLED(efuse_data)) {
708                                         efuse_addr++;
709                                         continue;
710                                 }
711
712                                 hoffset |= ((efuse_data & 0xF0) >> 1);
713                                 hworden = efuse_data & 0x0F;
714                         } else {
715                                 hoffset = (efuse_data >> 4) & 0x0F;
716                                 hworden = efuse_data & 0x0F;
717                         }
718                         word_cnts = Efuse_CalculateWordCnts23a(hworden);
719                         /* read next header */
720                         efuse_addr += (word_cnts * 2) + 1;
721                 }
722
723                 /*  Check if we need to check next bank efuse */
724                 if (efuse_addr < retU2) {
725                         break;  /*  don't need to check next bank. */
726                 }
727         }
728
729         retU2 = ((bank - 1) * EFUSE_BT_REAL_BANK_CONTENT_LEN) + efuse_addr;
730         pHalData->BTEfuseUsedBytes = retU2;
731
732         DBG_8723A("%s: CurrentSize =%d\n", __func__, retU2);
733         return retU2;
734 }
735
736 void rtl8723a_read_chip_version(struct rtw_adapter *padapter)
737 {
738         u32 value32;
739         struct hal_version ChipVersion;
740         struct hal_data_8723a *pHalData;
741
742         pHalData = GET_HAL_DATA(padapter);
743
744         value32 = rtl8723au_read32(padapter, REG_SYS_CFG);
745         ChipVersion.ICType = CHIP_8723A;
746         ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
747         ChipVersion.RFType = RF_TYPE_1T1R;
748         ChipVersion.VendorType =
749                 ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC);
750         ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK) >> CHIP_VER_RTL_SHIFT;   /*  IC version (CUT) */
751
752         /*  For regulator mode. by tynli. 2011.01.14 */
753         pHalData->RegulatorMode = ((value32 & SPS_SEL) ?
754                                    RT_LDO_REGULATOR : RT_SWITCHING_REGULATOR);
755
756         value32 = rtl8723au_read32(padapter, REG_GPIO_OUTSTS);
757         /*  ROM code version. */
758         ChipVersion.ROMVer = ((value32 & RF_RL_ID) >> 20);
759
760         /*  For multi-function consideration. Added by Roger, 2010.10.06. */
761         pHalData->MultiFunc = RT_MULTI_FUNC_NONE;
762         value32 = rtl8723au_read32(padapter, REG_MULTI_FUNC_CTRL);
763         pHalData->MultiFunc |=
764                 ((value32 & WL_FUNC_EN) ? RT_MULTI_FUNC_WIFI : 0);
765         pHalData->MultiFunc |= ((value32 & BT_FUNC_EN) ? RT_MULTI_FUNC_BT : 0);
766         pHalData->MultiFunc |=
767                 ((value32 & GPS_FUNC_EN) ? RT_MULTI_FUNC_GPS : 0);
768         pHalData->PolarityCtl =
769                 ((value32 & WL_HWPDN_SL) ? RT_POLARITY_HIGH_ACT :
770                  RT_POLARITY_LOW_ACT);
771         dump_chip_info23a(ChipVersion);
772         pHalData->VersionID = ChipVersion;
773
774         if (IS_1T2R(ChipVersion))
775                 pHalData->rf_type = RF_1T2R;
776         else if (IS_2T2R(ChipVersion))
777                 pHalData->rf_type = RF_2T2R;
778         else
779                 pHalData->rf_type = RF_1T1R;
780
781         MSG_8723A("RF_Type is %x!!\n", pHalData->rf_type);
782 }
783
784 /*  */
785 /*  */
786 /*  20100209 Joseph: */
787 /*  This function is used only for 92C to set REG_BCN_CTRL(0x550) register. */
788 /*  We just reserve the value of the register in variable
789     pHalData->RegBcnCtrlVal and then operate */
790 /*  the value of the register via atomic operation. */
791 /*  This prevents from race condition when setting this register. */
792 /*  The value of pHalData->RegBcnCtrlVal is initialized in
793     HwConfigureRTL8192CE() function. */
794 /*  */
795 void SetBcnCtrlReg23a(struct rtw_adapter *padapter, u8 SetBits, u8 ClearBits)
796 {
797         u8 val8;
798
799         val8 = rtl8723au_read8(padapter, REG_BCN_CTRL);
800         val8 |= SetBits;
801         val8 &= ~ClearBits;
802
803         rtl8723au_write8(padapter, REG_BCN_CTRL, val8);
804 }
805
806 void rtl8723a_InitBeaconParameters(struct rtw_adapter *padapter)
807 {
808         rtl8723au_write16(padapter, REG_BCN_CTRL, 0x1010);
809
810         /*  TODO: Remove these magic number */
811         rtl8723au_write16(padapter, REG_TBTT_PROHIBIT, 0x6404); /*  ms */
812         /*  Firmware will control REG_DRVERLYINT when power saving is enable, */
813         /*  so don't set this register on STA mode. */
814         if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE) == false)
815                 rtl8723au_write8(padapter, REG_DRVERLYINT,
816                                  DRIVER_EARLY_INT_TIME);
817         /*  2ms */
818         rtl8723au_write8(padapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
819
820         /*  Suggested by designer timchen. Change beacon AIFS to the
821             largest number beacause test chip does not contension before
822             sending beacon. by tynli. 2009.11.03 */
823         rtl8723au_write16(padapter, REG_BCNTCFG, 0x660F);
824 }
825
826 static void ResumeTxBeacon(struct rtw_adapter *padapter)
827 {
828         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
829
830         /*  2010.03.01. Marked by tynli. No need to call workitem beacause
831             we record the value */
832         /*  which should be read from register to a global variable. */
833
834         RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("+ResumeTxBeacon\n"));
835
836         pHalData->RegFwHwTxQCtrl |= BIT(6);
837         rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2,
838                          pHalData->RegFwHwTxQCtrl);
839         rtl8723au_write8(padapter, REG_TBTT_PROHIBIT + 1, 0xff);
840         pHalData->RegReg542 |= BIT(0);
841         rtl8723au_write8(padapter, REG_TBTT_PROHIBIT + 2, pHalData->RegReg542);
842 }
843
844 static void StopTxBeacon(struct rtw_adapter *padapter)
845 {
846         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
847
848         /*  2010.03.01. Marked by tynli. No need to call workitem beacause
849             we record the value */
850         /*  which should be read from register to a global variable. */
851
852         RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("+StopTxBeacon\n"));
853
854         pHalData->RegFwHwTxQCtrl &= ~BIT(6);
855         rtl8723au_write8(padapter, REG_FWHW_TXQ_CTRL + 2,
856                          pHalData->RegFwHwTxQCtrl);
857         rtl8723au_write8(padapter, REG_TBTT_PROHIBIT + 1, 0x64);
858         pHalData->RegReg542 &= ~BIT(0);
859         rtl8723au_write8(padapter, REG_TBTT_PROHIBIT + 2, pHalData->RegReg542);
860 }
861
862 static void _BeaconFunctionEnable(struct rtw_adapter *padapter, u8 Enable,
863                                   u8 Linked)
864 {
865         SetBcnCtrlReg23a(padapter, DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB,
866                       0);
867         rtl8723au_write8(padapter, REG_RD_CTRL + 1, 0x6F);
868 }
869
870 void rtl8723a_SetBeaconRelatedRegisters(struct rtw_adapter *padapter)
871 {
872         u32 value32;
873         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
874         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
875
876         /* reset TSF, enable update TSF, correcting TSF On Beacon */
877
878         /* REG_BCN_INTERVAL */
879         /* REG_BCNDMATIM */
880         /* REG_ATIMWND */
881         /* REG_TBTT_PROHIBIT */
882         /* REG_DRVERLYINT */
883         /* REG_BCN_MAX_ERR */
884         /* REG_BCNTCFG (0x510) */
885         /* REG_DUAL_TSF_RST */
886         /* REG_BCN_CTRL (0x550) */
887
888         /*  */
889         /*  ATIM window */
890         /*  */
891         rtl8723au_write16(padapter, REG_ATIMWND, 2);
892
893         /*  */
894         /*  Beacon interval (in unit of TU). */
895         /*  */
896         rtl8723au_write16(padapter, REG_BCN_INTERVAL, pmlmeinfo->bcn_interval);
897
898         rtl8723a_InitBeaconParameters(padapter);
899
900         rtl8723au_write8(padapter, REG_SLOT, 0x09);
901
902         /*  */
903         /*  Reset TSF Timer to zero, added by Roger. 2008.06.24 */
904         /*  */
905         value32 = rtl8723au_read32(padapter, REG_TCR);
906         value32 &= ~TSFRST;
907         rtl8723au_write32(padapter, REG_TCR, value32);
908
909         value32 |= TSFRST;
910         rtl8723au_write32(padapter, REG_TCR, value32);
911
912         /*  NOTE: Fix test chip's bug (about contention windows's randomness) */
913         if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE |
914                           WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE) == true) {
915                 rtl8723au_write8(padapter, REG_RXTSF_OFFSET_CCK, 0x50);
916                 rtl8723au_write8(padapter, REG_RXTSF_OFFSET_OFDM, 0x50);
917         }
918
919         _BeaconFunctionEnable(padapter, true, true);
920
921         ResumeTxBeacon(padapter);
922         SetBcnCtrlReg23a(padapter, DIS_BCNQ_SUB, 0);
923 }
924
925 void rtl8723a_SetHalODMVar(struct rtw_adapter *Adapter,
926                            enum hal_odm_variable eVariable,
927                            void *pValue1, bool bSet)
928 {
929         struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
930         struct dm_odm_t *podmpriv = &pHalData->odmpriv;
931         switch (eVariable) {
932         case HAL_ODM_STA_INFO:
933         {
934                 struct sta_info *psta = (struct sta_info *)pValue1;
935
936                 if (bSet) {
937                         DBG_8723A("Set STA_(%d) info\n", psta->mac_id);
938                         ODM_CmnInfoPtrArrayHook23a(podmpriv,
939                                                 ODM_CMNINFO_STA_STATUS,
940                                                 psta->mac_id, psta);
941                 } else {
942                         DBG_8723A("Clean STA_(%d) info\n", psta->mac_id);
943                                 ODM_CmnInfoPtrArrayHook23a(podmpriv,
944                                                         ODM_CMNINFO_STA_STATUS,
945                                                         psta->mac_id, NULL);
946                 }
947         }
948                 break;
949         case HAL_ODM_P2P_STATE:
950                 ODM_CmnInfoUpdate23a(podmpriv, ODM_CMNINFO_WIFI_DIRECT, bSet);
951                 break;
952         case HAL_ODM_WIFI_DISPLAY_STATE:
953                 ODM_CmnInfoUpdate23a(podmpriv, ODM_CMNINFO_WIFI_DISPLAY, bSet);
954                 break;
955         default:
956                 break;
957         }
958 }
959
960 void rtl8723a_notch_filter(struct rtw_adapter *adapter, bool enable)
961 {
962         if (enable) {
963                 DBG_8723A("Enable notch filter\n");
964                 rtl8723au_write8(adapter, rOFDM0_RxDSP + 1,
965                                  rtl8723au_read8(adapter, rOFDM0_RxDSP + 1) |
966                                  BIT(1));
967         } else {
968                 DBG_8723A("Disable notch filter\n");
969                 rtl8723au_write8(adapter, rOFDM0_RxDSP + 1,
970                            rtl8723au_read8(adapter, rOFDM0_RxDSP + 1) &
971                                  ~BIT(1));
972         }
973 }
974
975 bool c2h_id_filter_ccx_8723a(u8 id)
976 {
977         bool ret = false;
978         if (id == C2H_CCX_TX_RPT)
979                 ret = true;
980
981         return ret;
982 }
983
984 int c2h_handler_8723a(struct rtw_adapter *padapter, struct c2h_evt_hdr *c2h_evt)
985 {
986         int ret = _SUCCESS;
987         u8 i = 0;
988
989         if (c2h_evt == NULL) {
990                 DBG_8723A("%s c2h_evt is NULL\n", __func__);
991                 ret = _FAIL;
992                 goto exit;
993         }
994
995         switch (c2h_evt->id) {
996         case C2H_DBG:
997                 RT_TRACE(_module_hal_init_c_, _drv_info_,
998                          ("C2HCommandHandler: %s\n", c2h_evt->payload));
999                 break;
1000
1001         case C2H_CCX_TX_RPT:
1002                 handle_txrpt_ccx_8723a(padapter, c2h_evt->payload);
1003                 break;
1004         case C2H_EXT_RA_RPT:
1005                 break;
1006         case C2H_HW_INFO_EXCH:
1007                 RT_TRACE(_module_hal_init_c_, _drv_info_,
1008                          ("[BT], C2H_HW_INFO_EXCH\n"));
1009                 for (i = 0; i < c2h_evt->plen; i++) {
1010                         RT_TRACE(_module_hal_init_c_, _drv_info_,
1011                                  ("[BT], tmpBuf[%d]= 0x%x\n", i,
1012                                   c2h_evt->payload[i]));
1013                 }
1014                 break;
1015
1016         case C2H_C2H_H2C_TEST:
1017                 RT_TRACE(_module_hal_init_c_, _drv_info_,
1018                          ("[BT], C2H_H2C_TEST\n"));
1019                 RT_TRACE(_module_hal_init_c_, _drv_info_,
1020                          ("[BT], tmpBuf[0]/[1]/[2]/[3]/[4]= 0x%x/ 0x%x/ "
1021                           "0x%x/ 0x%x/ 0x%x\n", c2h_evt->payload[0],
1022                           c2h_evt->payload[1], c2h_evt->payload[2],
1023                           c2h_evt->payload[3], c2h_evt->payload[4]));
1024                 break;
1025
1026         case C2H_BT_INFO:
1027                 DBG_8723A("%s ,  Got  C2H_BT_INFO \n", __func__);
1028                 rtl8723a_fw_c2h_BT_info(padapter,
1029                                         c2h_evt->payload, c2h_evt->plen);
1030                 break;
1031
1032         default:
1033                 ret = _FAIL;
1034                 break;
1035         }
1036
1037 exit:
1038         return ret;
1039 }
1040
1041 void handle_txrpt_ccx_8723a(struct rtw_adapter *adapter, void *buf)
1042 {
1043         struct txrpt_ccx_8723a *txrpt_ccx = buf;
1044         struct submit_ctx *pack_tx_ops = &adapter->xmitpriv.ack_tx_ops;
1045
1046         if (txrpt_ccx->int_ccx && adapter->xmitpriv.ack_tx) {
1047                 if (txrpt_ccx->pkt_ok)
1048                         rtw23a_sctx_done_err(&pack_tx_ops,
1049                                              RTW_SCTX_DONE_SUCCESS);
1050                 else
1051                         rtw23a_sctx_done_err(&pack_tx_ops,
1052                                              RTW_SCTX_DONE_CCX_PKT_FAIL);
1053         }
1054 }
1055
1056 void rtl8723a_InitAntenna_Selection(struct rtw_adapter *padapter)
1057 {
1058         u8 val;
1059
1060         val = rtl8723au_read8(padapter, REG_LEDCFG2);
1061         /*  Let 8051 take control antenna settting */
1062         val |= BIT(7);          /*  DPDT_SEL_EN, 0x4C[23] */
1063         rtl8723au_write8(padapter, REG_LEDCFG2, val);
1064 }
1065
1066 void rtl8723a_CheckAntenna_Selection(struct rtw_adapter *padapter)
1067 {
1068         u8 val;
1069
1070         val = rtl8723au_read8(padapter, REG_LEDCFG2);
1071         /*  Let 8051 take control antenna settting */
1072         if (!(val & BIT(7))) {
1073                 val |= BIT(7);  /*  DPDT_SEL_EN, 0x4C[23] */
1074                 rtl8723au_write8(padapter, REG_LEDCFG2, val);
1075         }
1076 }
1077
1078 void rtl8723a_DeinitAntenna_Selection(struct rtw_adapter *padapter)
1079 {
1080         u8 val;
1081
1082         val = rtl8723au_read8(padapter, REG_LEDCFG2);
1083         /*  Let 8051 take control antenna settting */
1084         val &= ~BIT(7);         /*  DPDT_SEL_EN, clear 0x4C[23] */
1085         rtl8723au_write8(padapter, REG_LEDCFG2, val);
1086 }
1087
1088 void rtl8723a_init_default_value(struct rtw_adapter *padapter)
1089 {
1090         struct hal_data_8723a *pHalData;
1091         struct dm_priv *pdmpriv;
1092         u8 i;
1093
1094         pHalData = GET_HAL_DATA(padapter);
1095         pdmpriv = &pHalData->dmpriv;
1096
1097         /*  init default value */
1098         pHalData->fw_ractrl = false;
1099         pHalData->bIQKInitialized = false;
1100         if (!padapter->pwrctrlpriv.bkeepfwalive)
1101                 pHalData->LastHMEBoxNum = 0;
1102
1103         pHalData->bIQKInitialized = false;
1104
1105         /*  init dm default value */
1106         pdmpriv->TM_Trigger = 0;        /* for IQK */
1107 /*      pdmpriv->binitialized = false; */
1108 /*      pdmpriv->prv_traffic_idx = 3; */
1109 /*      pdmpriv->initialize = 0; */
1110
1111         pdmpriv->ThermalValue_HP_index = 0;
1112         for (i = 0; i < HP_THERMAL_NUM; i++)
1113                 pdmpriv->ThermalValue_HP[i] = 0;
1114
1115         /*  init Efuse variables */
1116         pHalData->EfuseUsedBytes = 0;
1117         pHalData->BTEfuseUsedBytes = 0;
1118 }
1119
1120 u8 GetEEPROMSize8723A(struct rtw_adapter *padapter)
1121 {
1122         u8 size = 0;
1123         u32 cr;
1124
1125         cr = rtl8723au_read16(padapter, REG_9346CR);
1126         /*  6: EEPROM used is 93C46, 4: boot from E-Fuse. */
1127         size = (cr & BOOT_FROM_EEPROM) ? 6 : 4;
1128
1129         MSG_8723A("EEPROM type is %s\n", size == 4 ? "E-FUSE" : "93C46");
1130
1131         return size;
1132 }
1133
1134 /*  */
1135 /*  */
1136 /*  LLT R/W/Init function */
1137 /*  */
1138 /*  */
1139 static int _LLTWrite(struct rtw_adapter *padapter, u32 address, u32 data)
1140 {
1141         int status = _SUCCESS;
1142         s32 count = 0;
1143         u32 value = _LLT_INIT_ADDR(address) | _LLT_INIT_DATA(data) |
1144                     _LLT_OP(_LLT_WRITE_ACCESS);
1145         u16 LLTReg = REG_LLT_INIT;
1146
1147         rtl8723au_write32(padapter, LLTReg, value);
1148
1149         /* polling */
1150         do {
1151                 value = rtl8723au_read32(padapter, LLTReg);
1152                 if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value)) {
1153                         break;
1154                 }
1155
1156                 if (count > POLLING_LLT_THRESHOLD) {
1157                         RT_TRACE(_module_hal_init_c_, _drv_err_,
1158                                  ("Failed to polling write LLT done at "
1159                                   "address %d!\n", address));
1160                         status = _FAIL;
1161                         break;
1162                 }
1163         } while (count++);
1164
1165         return status;
1166 }
1167
1168 int InitLLTTable23a(struct rtw_adapter *padapter, u32 boundary)
1169 {
1170         int status = _SUCCESS;
1171         u32 i;
1172         u32 txpktbuf_bndy = boundary;
1173         u32 Last_Entry_Of_TxPktBuf = LAST_ENTRY_OF_TX_PKT_BUFFER;
1174
1175         for (i = 0; i < (txpktbuf_bndy - 1); i++) {
1176                 status = _LLTWrite(padapter, i, i + 1);
1177                 if (status != _SUCCESS) {
1178                         return status;
1179                 }
1180         }
1181
1182         /*  end of list */
1183         status = _LLTWrite(padapter, (txpktbuf_bndy - 1), 0xFF);
1184         if (status != _SUCCESS) {
1185                 return status;
1186         }
1187
1188         /*  Make the other pages as ring buffer */
1189         /*  This ring buffer is used as beacon buffer if we config this
1190             MAC as two MAC transfer. */
1191         /*  Otherwise used as local loopback buffer. */
1192         for (i = txpktbuf_bndy; i < Last_Entry_Of_TxPktBuf; i++) {
1193                 status = _LLTWrite(padapter, i, (i + 1));
1194                 if (_SUCCESS != status) {
1195                         return status;
1196                 }
1197         }
1198
1199         /*  Let last entry point to the start entry of ring buffer */
1200         status = _LLTWrite(padapter, Last_Entry_Of_TxPktBuf, txpktbuf_bndy);
1201         if (status != _SUCCESS) {
1202                 return status;
1203         }
1204
1205         return status;
1206 }
1207
1208 static void _DisableGPIO(struct rtw_adapter *padapter)
1209 {
1210 /***************************************
1211 j. GPIO_PIN_CTRL 0x44[31:0]= 0x000
1212 k.Value = GPIO_PIN_CTRL[7:0]
1213 l. GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); write external PIN level
1214 m. GPIO_MUXCFG 0x42 [15:0] = 0x0780
1215 n. LEDCFG 0x4C[15:0] = 0x8080
1216 ***************************************/
1217         u32 value32;
1218         u32 u4bTmp;
1219
1220         /* 1. Disable GPIO[7:0] */
1221         rtl8723au_write16(padapter, REG_GPIO_PIN_CTRL + 2, 0x0000);
1222         value32 = rtl8723au_read32(padapter, REG_GPIO_PIN_CTRL) & 0xFFFF00FF;
1223         u4bTmp = value32 & 0x000000FF;
1224         value32 |= ((u4bTmp << 8) | 0x00FF0000);
1225         rtl8723au_write32(padapter, REG_GPIO_PIN_CTRL, value32);
1226
1227         /*  */
1228         /*  <Roger_Notes> For RTL8723u multi-function configuration which
1229             was autoload from Efuse offset 0x0a and 0x0b, */
1230         /*  WLAN HW GPIO[9], GPS HW GPIO[10] and BT HW GPIO[11]. */
1231         /*  Added by Roger, 2010.10.07. */
1232         /*  */
1233         /* 2. Disable GPIO[8] and GPIO[12] */
1234
1235         /*  Configure all pins as input mode. */
1236         rtl8723au_write16(padapter, REG_GPIO_IO_SEL_2, 0x0000);
1237         value32 = rtl8723au_read32(padapter, REG_GPIO_PIN_CTRL_2) & 0xFFFF001F;
1238         u4bTmp = value32 & 0x0000001F;
1239         /*  Set pin 8, 10, 11 and pin 12 to output mode. */
1240         value32 |= ((u4bTmp << 8) | 0x001D0000);
1241         rtl8723au_write32(padapter, REG_GPIO_PIN_CTRL_2, value32);
1242
1243         /* 3. Disable LED0 & 1 */
1244         rtl8723au_write16(padapter, REG_LEDCFG0, 0x8080);
1245 }                               /* end of _DisableGPIO() */
1246
1247 static void _DisableRFAFEAndResetBB8192C(struct rtw_adapter *padapter)
1248 {
1249 /**************************************
1250 a.      TXPAUSE 0x522[7:0] = 0xFF               Pause MAC TX queue
1251 b.      RF path 0 offset 0x00 = 0x00            disable RF
1252 c.      APSD_CTRL 0x600[7:0] = 0x40
1253 d.      SYS_FUNC_EN 0x02[7:0] = 0x16            reset BB state machine
1254 e.      SYS_FUNC_EN 0x02[7:0] = 0x14            reset BB state machine
1255 ***************************************/
1256         u8 eRFPath = 0, value8 = 0;
1257
1258         rtl8723au_write8(padapter, REG_TXPAUSE, 0xFF);
1259
1260         PHY_SetRFReg(padapter, (enum RF_RADIO_PATH) eRFPath, 0x0, bMaskByte0, 0x0);
1261
1262         value8 |= APSDOFF;
1263         rtl8723au_write8(padapter, REG_APSD_CTRL, value8);      /* 0x40 */
1264
1265         /*  Set BB reset at first */
1266         value8 = 0;
1267         value8 |= (FEN_USBD | FEN_USBA | FEN_BB_GLB_RSTn);
1268         rtl8723au_write8(padapter, REG_SYS_FUNC_EN, value8);    /* 0x16 */
1269
1270         /*  Set global reset. */
1271         value8 &= ~FEN_BB_GLB_RSTn;
1272         rtl8723au_write8(padapter, REG_SYS_FUNC_EN, value8);    /* 0x14 */
1273
1274         /*  2010/08/12 MH We need to set BB/GLBAL reset to save power
1275             for SS mode. */
1276
1277 /*      RT_TRACE(COMP_INIT, DBG_LOUD, ("======> RF off and reset BB.\n")); */
1278 }
1279
1280 static void _DisableRFAFEAndResetBB(struct rtw_adapter *padapter)
1281 {
1282         _DisableRFAFEAndResetBB8192C(padapter);
1283 }
1284
1285 static void _ResetDigitalProcedure1_92C(struct rtw_adapter *padapter,
1286                                         bool bWithoutHWSM)
1287 {
1288         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1289
1290         if (IS_FW_81xxC(padapter) && (pHalData->FirmwareVersion <= 0x20)) {
1291         /*****************************
1292         f.      MCUFWDL 0x80[7:0]= 0            reset MCU ready status
1293         g.      SYS_FUNC_EN 0x02[10]= 0         reset MCU register, (8051 reset)
1294         h.      SYS_FUNC_EN 0x02[15-12]= 5      reset MAC register, DCORE
1295         i.     SYS_FUNC_EN 0x02[10]= 1          enable MCU register,
1296                                                 (8051 enable)
1297         ******************************/
1298                 u16 valu16 = 0;
1299                 rtl8723au_write8(padapter, REG_MCUFWDL, 0);
1300
1301                 valu16 = rtl8723au_read16(padapter, REG_SYS_FUNC_EN);
1302                 /* reset MCU , 8051 */
1303                 rtl8723au_write16(padapter, REG_SYS_FUNC_EN,
1304                                   valu16 & (~FEN_CPUEN));
1305
1306                 valu16 = rtl8723au_read16(padapter, REG_SYS_FUNC_EN) & 0x0FFF;
1307                 /* reset MAC */
1308                 rtl8723au_write16(padapter, REG_SYS_FUNC_EN,
1309                                   valu16 | (FEN_HWPDN | FEN_ELDR));
1310
1311                 valu16 = rtl8723au_read16(padapter, REG_SYS_FUNC_EN);
1312                 /* enable MCU , 8051 */
1313                 rtl8723au_write16(padapter, REG_SYS_FUNC_EN,
1314                                   valu16 | FEN_CPUEN);
1315         } else {
1316                 u8 retry_cnts = 0;
1317
1318                 /*  2010/08/12 MH For USB SS, we can not stop 8051 when we
1319                     are trying to enter IPS/HW&SW radio off. For
1320                     S3/S4/S5/Disable, we can stop 8051 because */
1321                 /*  we will init FW when power on again. */
1322                 /*  If we want to SS mode, we can not reset 8051. */
1323                 if (rtl8723au_read8(padapter, REG_MCUFWDL) & BIT(1)) {
1324                         /* IF fw in RAM code, do reset */
1325                         if (padapter->bFWReady) {
1326                                 /*  2010/08/25 MH Accordign to RD alfred's
1327                                     suggestion, we need to disable other */
1328                                 /*  HRCV INT to influence 8051 reset. */
1329                                 rtl8723au_write8(padapter, REG_FWIMR, 0x20);
1330                                 /*  2011/02/15 MH According to Alex's
1331                                     suggestion, close mask to prevent
1332                                     incorrect FW write operation. */
1333                                 rtl8723au_write8(padapter, REG_FTIMR, 0x00);
1334                                 rtl8723au_write8(padapter, REG_FSIMR, 0x00);
1335
1336                                 /* 8051 reset by self */
1337                                 rtl8723au_write8(padapter, REG_HMETFR + 3,
1338                                                  0x20);
1339
1340                                 while ((retry_cnts++ < 100) &&
1341                                        (FEN_CPUEN &
1342                                         rtl8723au_read16(padapter,
1343                                                          REG_SYS_FUNC_EN))) {
1344                                         udelay(50);     /* us */
1345                                 }
1346
1347                                 if (retry_cnts >= 100) {
1348                                         /* Reset MAC and Enable 8051 */
1349                                         rtl8723au_write8(padapter,
1350                                                          REG_SYS_FUNC_EN + 1,
1351                                                          0x50);
1352                                         mdelay(10);
1353                                 }
1354                         }
1355                 }
1356                 /* Reset MAC and Enable 8051 */
1357                 rtl8723au_write8(padapter, REG_SYS_FUNC_EN + 1, 0x54);
1358                 rtl8723au_write8(padapter, REG_MCUFWDL, 0);
1359         }
1360
1361         if (bWithoutHWSM) {
1362         /*****************************
1363                 Without HW auto state machine
1364         g.      SYS_CLKR 0x08[15:0] = 0x30A3            disable MAC clock
1365         h.      AFE_PLL_CTRL 0x28[7:0] = 0x80           disable AFE PLL
1366         i.      AFE_XTAL_CTRL 0x24[15:0] = 0x880F       gated AFE DIG_CLOCK
1367         j.      SYS_ISO_CTRL 0x00[7:0] = 0xF9           isolated digital to PON
1368         ******************************/
1369                 /* modify to 0x70A3 by Scott. */
1370                 rtl8723au_write16(padapter, REG_SYS_CLKR, 0x70A3);
1371                 rtl8723au_write8(padapter, REG_AFE_PLL_CTRL, 0x80);
1372                 rtl8723au_write16(padapter, REG_AFE_XTAL_CTRL, 0x880F);
1373                 rtl8723au_write8(padapter, REG_SYS_ISO_CTRL, 0xF9);
1374         } else {
1375                 /*  Disable all RF/BB power */
1376                 rtl8723au_write8(padapter, REG_RF_CTRL, 0x00);
1377         }
1378 }
1379
1380 static void _ResetDigitalProcedure1(struct rtw_adapter *padapter,
1381                                     bool bWithoutHWSM)
1382 {
1383         _ResetDigitalProcedure1_92C(padapter, bWithoutHWSM);
1384 }
1385
1386 static void _ResetDigitalProcedure2(struct rtw_adapter *padapter)
1387 {
1388 /*****************************
1389 k.      SYS_FUNC_EN 0x03[7:0] = 0x44            disable ELDR runction
1390 l.      SYS_CLKR 0x08[15:0] = 0x3083            disable ELDR clock
1391 m.      SYS_ISO_CTRL 0x01[7:0] = 0x83           isolated ELDR to PON
1392 ******************************/
1393         /* modify to 0x70a3 by Scott. */
1394         rtl8723au_write16(padapter, REG_SYS_CLKR, 0x70a3);
1395         /* modify to 0x82 by Scott. */
1396         rtl8723au_write8(padapter, REG_SYS_ISO_CTRL + 1, 0x82);
1397 }
1398
1399 static void _DisableAnalog(struct rtw_adapter *padapter, bool bWithoutHWSM)
1400 {
1401         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1402         u16 value16 = 0;
1403         u8 value8 = 0;
1404
1405         if (bWithoutHWSM) {
1406         /*****************************
1407         n.      LDOA15_CTRL 0x20[7:0] = 0x04    disable A15 power
1408         o.      LDOV12D_CTRL 0x21[7:0] = 0x54   disable digital core power
1409         r.      When driver call disable, the ASIC will turn off remaining
1410                 clock automatically
1411         ******************************/
1412
1413                 rtl8723au_write8(padapter, REG_LDOA15_CTRL, 0x04);
1414                 /* rtl8723au_write8(padapter, REG_LDOV12D_CTRL, 0x54); */
1415
1416                 value8 = rtl8723au_read8(padapter, REG_LDOV12D_CTRL);
1417                 value8 &= (~LDV12_EN);
1418                 rtl8723au_write8(padapter, REG_LDOV12D_CTRL, value8);
1419 /*              RT_TRACE(COMP_INIT, DBG_LOUD,
1420                 (" REG_LDOV12D_CTRL Reg0x21:0x%02x.\n", value8)); */
1421         }
1422
1423         /*****************************
1424         h.      SPS0_CTRL 0x11[7:0] = 0x23              enter PFM mode
1425         i.      APS_FSMCO 0x04[15:0] = 0x4802           set USB suspend
1426         ******************************/
1427         value8 = 0x23;
1428         if (IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID))
1429                 value8 |= BIT(3);
1430
1431         rtl8723au_write8(padapter, REG_SPS0_CTRL, value8);
1432
1433         if (bWithoutHWSM) {
1434                 /* value16 |= (APDM_HOST | FSM_HSUS |/PFM_ALDN); */
1435                 /*  2010/08/31 According to Filen description, we need to
1436                     use HW to shut down 8051 automatically. */
1437                 /*  Becasue suspend operatione need the asistance of 8051
1438                     to wait for 3ms. */
1439                 value16 |= (APDM_HOST | AFSM_HSUS | PFM_ALDN);
1440         } else {
1441                 value16 |= (APDM_HOST | AFSM_HSUS | PFM_ALDN);
1442         }
1443
1444         rtl8723au_write16(padapter, REG_APS_FSMCO, value16);    /* 0x4802 */
1445
1446         rtl8723au_write8(padapter, REG_RSV_CTRL, 0x0e);
1447 }
1448
1449 /*  HW Auto state machine */
1450 int CardDisableHWSM(struct rtw_adapter *padapter, u8 resetMCU)
1451 {
1452         if (padapter->bSurpriseRemoved) {
1453                 return _SUCCESS;
1454         }
1455         /*  RF Off Sequence ==== */
1456         _DisableRFAFEAndResetBB(padapter);
1457
1458         /*   ==== Reset digital sequence   ====== */
1459         _ResetDigitalProcedure1(padapter, false);
1460
1461         /*   ==== Pull GPIO PIN to balance level and LED control ====== */
1462         _DisableGPIO(padapter);
1463
1464         /*   ==== Disable analog sequence === */
1465         _DisableAnalog(padapter, false);
1466
1467         RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
1468                  ("======> Card disable finished.\n"));
1469
1470         return _SUCCESS;
1471 }
1472
1473 /*  without HW Auto state machine */
1474 int CardDisableWithoutHWSM(struct rtw_adapter *padapter)
1475 {
1476         if (padapter->bSurpriseRemoved) {
1477                 return _SUCCESS;
1478         }
1479
1480         /*  RF Off Sequence ==== */
1481         _DisableRFAFEAndResetBB(padapter);
1482
1483         /*   ==== Reset digital sequence   ====== */
1484         _ResetDigitalProcedure1(padapter, true);
1485
1486         /*   ==== Pull GPIO PIN to balance level and LED control ====== */
1487         _DisableGPIO(padapter);
1488
1489         /*   ==== Reset digital sequence   ====== */
1490         _ResetDigitalProcedure2(padapter);
1491
1492         /*   ==== Disable analog sequence === */
1493         _DisableAnalog(padapter, true);
1494
1495         /* RT_TRACE(COMP_INIT, DBG_LOUD,
1496            ("<====== Card Disable Without HWSM .\n")); */
1497         return _SUCCESS;
1498 }
1499
1500 void Hal_InitPGData(struct rtw_adapter *padapter, u8 *PROMContent)
1501 {
1502         struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
1503
1504         if (false == pEEPROM->bautoload_fail_flag) {    /*  autoload OK. */
1505                 if (!pEEPROM->EepromOrEfuse) {
1506                         /*  Read EFUSE real map to shadow. */
1507                         EFUSE_ShadowMapUpdate23a(padapter, EFUSE_WIFI);
1508                         memcpy((void *)PROMContent,
1509                                (void *)pEEPROM->efuse_eeprom_data,
1510                                HWSET_MAX_SIZE);
1511                 }
1512         } else {                /* autoload fail */
1513                 RT_TRACE(_module_hci_hal_init_c_, _drv_notice_,
1514                          ("AutoLoad Fail reported from CR9346!!\n"));
1515 /*              pHalData->AutoloadFailFlag = true; */
1516                 /* update to default value 0xFF */
1517                 if (false == pEEPROM->EepromOrEfuse)
1518                         EFUSE_ShadowMapUpdate23a(padapter, EFUSE_WIFI);
1519                 memcpy((void *)PROMContent, (void *)pEEPROM->efuse_eeprom_data,
1520                        HWSET_MAX_SIZE);
1521         }
1522 }
1523
1524 void Hal_EfuseParseIDCode(struct rtw_adapter *padapter, u8 *hwinfo)
1525 {
1526         struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
1527 /*      struct hal_data_8723a   *pHalData = GET_HAL_DATA(padapter); */
1528         u16 EEPROMId;
1529
1530         /*  Checl 0x8129 again for making sure autoload status!! */
1531         EEPROMId = le16_to_cpu(*((u16 *) hwinfo));
1532         if (EEPROMId != RTL_EEPROM_ID) {
1533                 DBG_8723A("EEPROM ID(%#x) is invalid!!\n", EEPROMId);
1534                 pEEPROM->bautoload_fail_flag = true;
1535         } else {
1536                 pEEPROM->bautoload_fail_flag = false;
1537         }
1538
1539         RT_TRACE(_module_hal_init_c_, _drv_info_,
1540                  ("EEPROM ID = 0x%04x\n", EEPROMId));
1541 }
1542
1543 static void Hal_EEValueCheck(u8 EEType, void *pInValue, void *pOutValue)
1544 {
1545         switch (EEType) {
1546         case EETYPE_TX_PWR:
1547         {
1548                 u8 *pIn, *pOut;
1549                 pIn = (u8 *) pInValue;
1550                 pOut = (u8 *) pOutValue;
1551                 if (*pIn <= 63)
1552                         *pOut = *pIn;
1553                 else {
1554                         RT_TRACE(_module_hci_hal_init_c_, _drv_err_,
1555                                  ("EETYPE_TX_PWR, value =%d is invalid, set "
1556                                   "to default = 0x%x\n",
1557                                   *pIn, EEPROM_Default_TxPowerLevel));
1558                         *pOut = EEPROM_Default_TxPowerLevel;
1559                 }
1560         }
1561                 break;
1562         default:
1563                 break;
1564         }
1565 }
1566
1567 static void
1568 Hal_ReadPowerValueFromPROM_8723A(struct txpowerinfo *pwrInfo,
1569                                  u8 *PROMContent, bool AutoLoadFail)
1570 {
1571         u32 rfPath, eeAddr, group, rfPathMax = 1;
1572
1573         memset(pwrInfo, 0, sizeof(*pwrInfo));
1574
1575         if (AutoLoadFail) {
1576                 for (group = 0; group < MAX_CHNL_GROUP; group++) {
1577                         for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
1578                                 pwrInfo->CCKIndex[rfPath][group] =
1579                                         EEPROM_Default_TxPowerLevel;
1580                                 pwrInfo->HT40_1SIndex[rfPath][group] =
1581                                         EEPROM_Default_TxPowerLevel;
1582                                 pwrInfo->HT40_2SIndexDiff[rfPath][group] =
1583                                         EEPROM_Default_HT40_2SDiff;
1584                                 pwrInfo->HT20IndexDiff[rfPath][group] =
1585                                         EEPROM_Default_HT20_Diff;
1586                                 pwrInfo->OFDMIndexDiff[rfPath][group] =
1587                                         EEPROM_Default_LegacyHTTxPowerDiff;
1588                                 pwrInfo->HT40MaxOffset[rfPath][group] =
1589                                         EEPROM_Default_HT40_PwrMaxOffset;
1590                                 pwrInfo->HT20MaxOffset[rfPath][group] =
1591                                         EEPROM_Default_HT20_PwrMaxOffset;
1592                         }
1593                 }
1594                 pwrInfo->TSSI_A[0] = EEPROM_Default_TSSI;
1595                 return;
1596         }
1597
1598         for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
1599                 for (group = 0; group < MAX_CHNL_GROUP; group++) {
1600                         eeAddr =
1601                             EEPROM_CCK_TX_PWR_INX_8723A + (rfPath * 3) + group;
1602                         /* pwrInfo->CCKIndex[rfPath][group] =
1603                            PROMContent[eeAddr]; */
1604                         Hal_EEValueCheck(EETYPE_TX_PWR, &PROMContent[eeAddr],
1605                                          &pwrInfo->CCKIndex[rfPath][group]);
1606                         eeAddr = EEPROM_HT40_1S_TX_PWR_INX_8723A +
1607                                 (rfPath * 3) + group;
1608                         /* pwrInfo->HT40_1SIndex[rfPath][group] =
1609                            PROMContent[eeAddr]; */
1610                         Hal_EEValueCheck(EETYPE_TX_PWR, &PROMContent[eeAddr],
1611                                          &pwrInfo->HT40_1SIndex[rfPath][group]);
1612                 }
1613         }
1614
1615         for (group = 0; group < MAX_CHNL_GROUP; group++) {
1616                 for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
1617                         pwrInfo->HT40_2SIndexDiff[rfPath][group] = 0;
1618                         pwrInfo->HT20IndexDiff[rfPath][group] =
1619                                 (PROMContent
1620                                  [EEPROM_HT20_TX_PWR_INX_DIFF_8723A +
1621                                   group] >> (rfPath * 4)) & 0xF;
1622                         /* 4bit sign number to 8 bit sign number */
1623                         if (pwrInfo->HT20IndexDiff[rfPath][group] & BIT(3))
1624                                 pwrInfo->HT20IndexDiff[rfPath][group] |= 0xF0;
1625
1626                         pwrInfo->OFDMIndexDiff[rfPath][group] =
1627                                 (PROMContent[EEPROM_OFDM_TX_PWR_INX_DIFF_8723A +
1628                                              group] >> (rfPath * 4)) & 0xF;
1629
1630                         pwrInfo->HT40MaxOffset[rfPath][group] =
1631                                 (PROMContent[EEPROM_HT40_MAX_PWR_OFFSET_8723A +
1632                                              group] >> (rfPath * 4)) & 0xF;
1633
1634                         pwrInfo->HT20MaxOffset[rfPath][group] =
1635                                 (PROMContent[EEPROM_HT20_MAX_PWR_OFFSET_8723A +
1636                                              group] >> (rfPath * 4)) & 0xF;
1637                 }
1638         }
1639
1640         pwrInfo->TSSI_A[0] = PROMContent[EEPROM_TSSI_A_8723A];
1641 }
1642
1643 static u8 Hal_GetChnlGroup(u8 chnl)
1644 {
1645         u8 group = 0;
1646
1647         if (chnl < 3)           /*  Cjanel 1-3 */
1648                 group = 0;
1649         else if (chnl < 9)      /*  Channel 4-9 */
1650                 group = 1;
1651         else                    /*  Channel 10-14 */
1652                 group = 2;
1653
1654         return group;
1655 }
1656
1657 void
1658 Hal_EfuseParsetxpowerinfo_8723A(struct rtw_adapter *padapter,
1659                                 u8 *PROMContent, bool AutoLoadFail)
1660 {
1661         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1662         struct txpowerinfo pwrInfo;
1663         u8 rfPath, ch, group, rfPathMax = 1;
1664         u8 pwr, diff;
1665
1666         Hal_ReadPowerValueFromPROM_8723A(&pwrInfo, PROMContent, AutoLoadFail);
1667         for (rfPath = 0; rfPath < rfPathMax; rfPath++) {
1668                 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
1669                         group = Hal_GetChnlGroup(ch);
1670
1671                         pHalData->TxPwrLevelCck[rfPath][ch] =
1672                                 pwrInfo.CCKIndex[rfPath][group];
1673                         pHalData->TxPwrLevelHT40_1S[rfPath][ch] =
1674                                 pwrInfo.HT40_1SIndex[rfPath][group];
1675
1676                         pHalData->TxPwrHt20Diff[rfPath][ch] =
1677                                 pwrInfo.HT20IndexDiff[rfPath][group];
1678                         pHalData->TxPwrLegacyHtDiff[rfPath][ch] =
1679                                 pwrInfo.OFDMIndexDiff[rfPath][group];
1680                         pHalData->PwrGroupHT20[rfPath][ch] =
1681                                 pwrInfo.HT20MaxOffset[rfPath][group];
1682                         pHalData->PwrGroupHT40[rfPath][ch] =
1683                                 pwrInfo.HT40MaxOffset[rfPath][group];
1684
1685                         pwr = pwrInfo.HT40_1SIndex[rfPath][group];
1686                         diff = pwrInfo.HT40_2SIndexDiff[rfPath][group];
1687
1688                         pHalData->TxPwrLevelHT40_2S[rfPath][ch] =
1689                             (pwr > diff) ? (pwr - diff) : 0;
1690                 }
1691         }
1692         for (rfPath = 0; rfPath < RF_PATH_MAX; rfPath++) {
1693                 for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
1694                         RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
1695                                  ("RF(%u)-Ch(%u) [CCK / HT40_1S / HT40_2S] = "
1696                                   "[0x%x / 0x%x / 0x%x]\n",
1697                                   rfPath, ch,
1698                                   pHalData->TxPwrLevelCck[rfPath][ch],
1699                                   pHalData->TxPwrLevelHT40_1S[rfPath][ch],
1700                                   pHalData->TxPwrLevelHT40_2S[rfPath][ch]));
1701
1702                 }
1703         }
1704         for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
1705                 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
1706                          ("RF-A Ht20 to HT40 Diff[%u] = 0x%x(%d)\n", ch,
1707                           pHalData->TxPwrHt20Diff[RF_PATH_A][ch],
1708                           pHalData->TxPwrHt20Diff[RF_PATH_A][ch]));
1709         }
1710         for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++)
1711                 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
1712                          ("RF-A Legacy to Ht40 Diff[%u] = 0x%x\n", ch,
1713                           pHalData->TxPwrLegacyHtDiff[RF_PATH_A][ch]));
1714         for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++) {
1715                 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
1716                          ("RF-B Ht20 to HT40 Diff[%u] = 0x%x(%d)\n", ch,
1717                           pHalData->TxPwrHt20Diff[RF_PATH_B][ch],
1718                           pHalData->TxPwrHt20Diff[RF_PATH_B][ch]));
1719         }
1720         for (ch = 0; ch < CHANNEL_MAX_NUMBER; ch++)
1721                 RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
1722                          ("RF-B Legacy to HT40 Diff[%u] = 0x%x\n", ch,
1723                           pHalData->TxPwrLegacyHtDiff[RF_PATH_B][ch]));
1724         if (!AutoLoadFail) {
1725                 struct registry_priv *registry_par = &padapter->registrypriv;
1726                 if (registry_par->regulatory_tid == 0xff) {
1727                         if (PROMContent[RF_OPTION1_8723A] == 0xff)
1728                                 pHalData->EEPROMRegulatory = 0;
1729                         else
1730                                 pHalData->EEPROMRegulatory =
1731                                         PROMContent[RF_OPTION1_8723A] & 0x7;
1732                 } else {
1733                         pHalData->EEPROMRegulatory =
1734                             registry_par->regulatory_tid;
1735                 }
1736         } else {
1737                 pHalData->EEPROMRegulatory = 0;
1738         }
1739         RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
1740                  ("EEPROMRegulatory = 0x%x\n", pHalData->EEPROMRegulatory));
1741
1742         if (!AutoLoadFail)
1743                 pHalData->bTXPowerDataReadFromEEPORM = true;
1744 }
1745
1746 void
1747 Hal_EfuseParseBTCoexistInfo_8723A(struct rtw_adapter *padapter,
1748                                   u8 *hwinfo, bool AutoLoadFail)
1749 {
1750         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1751         u8 tempval;
1752         u32 tmpu4;
1753
1754         if (!AutoLoadFail) {
1755                 tmpu4 = rtl8723au_read32(padapter, REG_MULTI_FUNC_CTRL);
1756                 if (tmpu4 & BT_FUNC_EN)
1757                         pHalData->EEPROMBluetoothCoexist = 1;
1758                 else
1759                         pHalData->EEPROMBluetoothCoexist = 0;
1760                 pHalData->EEPROMBluetoothType = BT_RTL8723A;
1761
1762                 /*  The following need to be checked with newer version of */
1763                 /*  eeprom spec */
1764                 tempval = hwinfo[RF_OPTION4_8723A];
1765                 pHalData->EEPROMBluetoothAntNum = (tempval & 0x1);
1766                 pHalData->EEPROMBluetoothAntIsolation = ((tempval & 0x10) >> 4);
1767                 pHalData->EEPROMBluetoothRadioShared = ((tempval & 0x20) >> 5);
1768         } else {
1769                 pHalData->EEPROMBluetoothCoexist = 0;
1770                 pHalData->EEPROMBluetoothType = BT_RTL8723A;
1771                 pHalData->EEPROMBluetoothAntNum = Ant_x2;
1772                 pHalData->EEPROMBluetoothAntIsolation = 0;
1773                 pHalData->EEPROMBluetoothRadioShared = BT_Radio_Shared;
1774         }
1775
1776         rtl8723a_BT_init_hal_vars(padapter);
1777 }
1778
1779 void
1780 Hal_EfuseParseEEPROMVer(struct rtw_adapter *padapter,
1781                         u8 *hwinfo, bool AutoLoadFail)
1782 {
1783         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1784
1785         if (!AutoLoadFail)
1786                 pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_8723A];
1787         else
1788                 pHalData->EEPROMVersion = 1;
1789         RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
1790                  ("Hal_EfuseParseEEPROMVer(), EEVer = %d\n",
1791                   pHalData->EEPROMVersion));
1792 }
1793
1794 void
1795 rtl8723a_EfuseParseChnlPlan(struct rtw_adapter *padapter,
1796                             u8 *hwinfo, bool AutoLoadFail)
1797 {
1798         padapter->mlmepriv.ChannelPlan =
1799                 hal_com_get_channel_plan23a(padapter, hwinfo ?
1800                                          hwinfo[EEPROM_ChannelPlan_8723A]:0xFF,
1801                                          padapter->registrypriv.channel_plan,
1802                                          RT_CHANNEL_DOMAIN_WORLD_WIDE_13,
1803                                          AutoLoadFail);
1804
1805         DBG_8723A("mlmepriv.ChannelPlan = 0x%02x\n",
1806                   padapter->mlmepriv.ChannelPlan);
1807 }
1808
1809 void
1810 Hal_EfuseParseCustomerID(struct rtw_adapter *padapter,
1811                          u8 *hwinfo, bool AutoLoadFail)
1812 {
1813         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1814
1815         if (!AutoLoadFail) {
1816                 pHalData->EEPROMCustomerID = hwinfo[EEPROM_CustomID_8723A];
1817                 pHalData->EEPROMSubCustomerID =
1818                     hwinfo[EEPROM_SubCustomID_8723A];
1819         } else {
1820                 pHalData->EEPROMCustomerID = 0;
1821                 pHalData->EEPROMSubCustomerID = 0;
1822         }
1823         RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
1824                  ("EEPROM Customer ID: 0x%2x\n", pHalData->EEPROMCustomerID));
1825         RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
1826                  ("EEPROM SubCustomer ID: 0x%02x\n",
1827                   pHalData->EEPROMSubCustomerID));
1828 }
1829
1830 void
1831 Hal_EfuseParseAntennaDiversity(struct rtw_adapter *padapter,
1832                                u8 *hwinfo, bool AutoLoadFail)
1833 {
1834 }
1835
1836 void
1837 Hal_EfuseParseRateIndicationOption(struct rtw_adapter *padapter,
1838                                    u8 *hwinfo, bool AutoLoadFail)
1839 {
1840 }
1841
1842 void
1843 Hal_EfuseParseXtal_8723A(struct rtw_adapter *pAdapter,
1844                          u8 *hwinfo, u8 AutoLoadFail)
1845 {
1846         struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
1847
1848         if (!AutoLoadFail) {
1849                 pHalData->CrystalCap = hwinfo[EEPROM_XTAL_K_8723A];
1850                 if (pHalData->CrystalCap == 0xFF)
1851                         pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723A;
1852         } else {
1853                 pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723A;
1854         }
1855         RT_TRACE(_module_hci_hal_init_c_, _drv_info_,
1856                  ("%s: CrystalCap = 0x%2x\n", __func__,
1857                   pHalData->CrystalCap));
1858 }
1859
1860 void
1861 Hal_EfuseParseThermalMeter_8723A(struct rtw_adapter *padapter,
1862                                  u8 *PROMContent, bool AutoloadFail)
1863 {
1864         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
1865
1866         /*  */
1867         /*  ThermalMeter from EEPROM */
1868         /*  */
1869         if (!AutoloadFail)
1870                 pHalData->EEPROMThermalMeter =
1871                     PROMContent[EEPROM_THERMAL_METER_8723A];
1872         else
1873                 pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
1874
1875         if ((pHalData->EEPROMThermalMeter == 0xff) || AutoloadFail) {
1876                 pHalData->bAPKThermalMeterIgnore = true;
1877                 pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter;
1878         }
1879
1880         DBG_8723A("%s: ThermalMeter = 0x%x\n", __func__,
1881                   pHalData->EEPROMThermalMeter);
1882 }
1883
1884 static void rtl8723a_cal_txdesc_chksum(struct tx_desc *ptxdesc)
1885 {
1886         u16 *usPtr = (u16 *) ptxdesc;
1887         u32 count = 16;         /*  (32 bytes / 2 bytes per XOR) => 16 times */
1888         u32 index;
1889         u16 checksum = 0;
1890
1891         /*  Clear first */
1892         ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
1893
1894         for (index = 0; index < count; index++) {
1895                 checksum ^= le16_to_cpu(*(usPtr + index));
1896         }
1897
1898         ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff);
1899 }
1900
1901 /*
1902  *  Description: In normal chip, we should send some packet to Hw which
1903  *  will be used by Fw in FW LPS mode. The function is to fill the Tx
1904  * descriptor of this packets, then
1905  */
1906 /*                      Fw can tell Hw to send these packet derectly. */
1907 /*  Added by tynli. 2009.10.15. */
1908 /*  */
1909 void rtl8723a_fill_fake_txdesc(struct rtw_adapter *padapter, u8 *pDesc,
1910                                u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull)
1911 {
1912         struct tx_desc *ptxdesc;
1913
1914         /*  Clear all status */
1915         ptxdesc = (struct tx_desc *)pDesc;
1916         memset(pDesc, 0, TXDESC_SIZE);
1917
1918         /* offset 0 */
1919         /* own, bFirstSeg, bLastSeg; */
1920         ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
1921
1922         /* 32 bytes for TX Desc */
1923         ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) <<
1924                                        OFFSET_SHT) & 0x00ff0000);
1925
1926         /*  Buffer size + command header */
1927         ptxdesc->txdw0 |= cpu_to_le32(BufferLen & 0x0000ffff);
1928
1929         /* offset 4 */
1930         /*  Fixed queue of Mgnt queue */
1931         ptxdesc->txdw1 |= cpu_to_le32((QSLT_MGNT << QSEL_SHT) & 0x00001f00);
1932
1933         /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed
1934            to error vlaue by Hw. */
1935         if (IsPsPoll) {
1936                 ptxdesc->txdw1 |= cpu_to_le32(NAVUSEHDR);
1937         } else {
1938                 /*  Hw set sequence number */
1939                 ptxdesc->txdw4 |= cpu_to_le32(BIT(7));
1940                 /* set bit3 to 1. Suugested by TimChen. 2009.12.29. */
1941                 ptxdesc->txdw3 |= cpu_to_le32((8 << 28));
1942         }
1943
1944         if (true == IsBTQosNull) {
1945                 ptxdesc->txdw2 |= cpu_to_le32(BIT(23)); /*  BT NULL */
1946         }
1947
1948         /* offset 16 */
1949         ptxdesc->txdw4 |= cpu_to_le32(BIT(8));  /* driver uses rate */
1950
1951         /*  USB interface drop packet if the checksum of descriptor isn't
1952             correct. */
1953         /*  Using this checksum can let hardware recovery from packet bulk
1954             out error (e.g. Cancel URC, Bulk out error.). */
1955         rtl8723a_cal_txdesc_chksum(ptxdesc);
1956 }
1957
1958 void hw_var_set_opmode(struct rtw_adapter *padapter, u8 mode)
1959 {
1960         u8 val8;
1961
1962         if (mode == MSR_INFRA || mode == MSR_NOLINK) {
1963                 StopTxBeacon(padapter);
1964
1965                 /*  disable atim wnd */
1966                 val8 = DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_ATIM;
1967                 SetBcnCtrlReg23a(padapter, val8, ~val8);
1968         } else if (mode == MSR_ADHOC) {
1969                 ResumeTxBeacon(padapter);
1970
1971                 val8 = DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB;
1972                 SetBcnCtrlReg23a(padapter, val8, ~val8);
1973         } else if (mode == MSR_AP) {
1974                 /*  add NULL Data and BT NULL Data Packets to FW RSVD Page */
1975                 rtl8723a_set_BTCoex_AP_mode_FwRsvdPkt_cmd(padapter);
1976
1977                 ResumeTxBeacon(padapter);
1978
1979                 val8 = DIS_TSF_UDT | DIS_BCNQ_SUB;
1980                 SetBcnCtrlReg23a(padapter, val8, ~val8);
1981
1982                 /*  Set RCR */
1983                 /* rtl8723au_write32(padapter, REG_RCR, 0x70002a8e);
1984                    CBSSID_DATA must set to 0 */
1985                 /* CBSSID_DATA must set to 0 */
1986                 rtl8723au_write32(padapter, REG_RCR, 0x7000228e);
1987                 /*  enable to rx data frame */
1988                 rtl8723au_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
1989                 /*  enable to rx ps-poll */
1990                 rtl8723au_write16(padapter, REG_RXFLTMAP1, 0x0400);
1991
1992                 /*  Beacon Control related register for first time */
1993                 /*  2ms */
1994                 rtl8723au_write8(padapter, REG_BCNDMATIM, 0x02);
1995                 /*  5ms */
1996                 rtl8723au_write8(padapter, REG_DRVERLYINT, 0x05);
1997                 /*  10ms for port0 */
1998                 rtl8723au_write8(padapter, REG_ATIMWND, 0x0a);
1999                 rtl8723au_write16(padapter, REG_BCNTCFG, 0x00);
2000                 rtl8723au_write16(padapter, REG_TBTT_PROHIBIT, 0xff04);
2001                 /*  +32767 (~32ms) */
2002                 rtl8723au_write16(padapter, REG_TSFTR_SYN_OFFSET, 0x7fff);
2003
2004                 /*  reset TSF */
2005                 rtl8723au_write8(padapter, REG_DUAL_TSF_RST, BIT(0));
2006
2007                 /*  enable BCN Function */
2008                 /*  don't enable update TSF (due to TSF update when
2009                     beacon/probe rsp are received) */
2010                 val8 = DIS_TSF_UDT | EN_BCN_FUNCTION |
2011                        EN_TXBCN_RPT | DIS_BCNQ_SUB;
2012                 SetBcnCtrlReg23a(padapter, val8, ~val8);
2013         }
2014
2015         val8 = rtl8723au_read8(padapter, MSR);
2016         val8 = (val8 & 0xC) | mode;
2017         rtl8723au_write8(padapter, MSR, val8);
2018 }
2019
2020 void hw_var_set_macaddr(struct rtw_adapter *padapter, u8 *val)
2021 {
2022         u8 idx = 0;
2023         u32 reg_macid;
2024
2025         reg_macid = REG_MACID;
2026
2027         for (idx = 0; idx < 6; idx++)
2028                 rtl8723au_write8(padapter, (reg_macid + idx), val[idx]);
2029 }
2030
2031 void hw_var_set_bssid(struct rtw_adapter *padapter, u8 *val)
2032 {
2033         u8 idx = 0;
2034         u32 reg_bssid;
2035
2036         reg_bssid = REG_BSSID;
2037
2038         for (idx = 0; idx < 6; idx++)
2039                 rtl8723au_write8(padapter, (reg_bssid + idx), val[idx]);
2040 }
2041
2042 void hw_var_set_correct_tsf(struct rtw_adapter *padapter)
2043 {
2044         u64 tsf;
2045         u32 reg_tsftr;
2046         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2047         struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
2048
2049         /* tsf = pmlmeext->TSFValue - ((u32)pmlmeext->TSFValue %
2050            (pmlmeinfo->bcn_interval*1024)) - 1024; us */
2051         tsf = pmlmeext->TSFValue -
2052                 do_div(pmlmeext->TSFValue,
2053                        (pmlmeinfo->bcn_interval * 1024)) - 1024;        /* us */
2054
2055         if (((pmlmeinfo->state & 0x03) == MSR_ADHOC) ||
2056             ((pmlmeinfo->state & 0x03) == MSR_AP)) {
2057                 /* pHalData->RegTxPause |= STOP_BCNQ;BIT(6) */
2058                 /* rtl8723au_write8(padapter, REG_TXPAUSE,
2059                    (rtl8723au_read8(Adapter, REG_TXPAUSE)|BIT(6))); */
2060                 StopTxBeacon(padapter);
2061         }
2062
2063         reg_tsftr = REG_TSFTR;
2064
2065         /*  disable related TSF function */
2066         SetBcnCtrlReg23a(padapter, 0, EN_BCN_FUNCTION);
2067
2068         rtl8723au_write32(padapter, reg_tsftr, tsf);
2069         rtl8723au_write32(padapter, reg_tsftr + 4, tsf >> 32);
2070
2071         /* enable related TSF function */
2072         SetBcnCtrlReg23a(padapter, EN_BCN_FUNCTION, 0);
2073
2074         if (((pmlmeinfo->state & 0x03) == MSR_ADHOC) ||
2075             ((pmlmeinfo->state & 0x03) == MSR_AP))
2076                 ResumeTxBeacon(padapter);
2077 }
2078
2079 void hw_var_set_mlme_disconnect(struct rtw_adapter *padapter)
2080 {
2081         /*  reject all data frames */
2082         rtl8723au_write16(padapter, REG_RXFLTMAP2, 0);
2083
2084         /*  reset TSF */
2085         rtl8723au_write8(padapter, REG_DUAL_TSF_RST, BIT(0));
2086
2087         /*  disable update TSF */
2088         SetBcnCtrlReg23a(padapter, DIS_TSF_UDT, 0);
2089 }
2090
2091 void hw_var_set_mlme_join(struct rtw_adapter *padapter, u8 type)
2092 {
2093         u8 RetryLimit = 0x30;
2094
2095         struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
2096         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2097
2098         if (type == 0) {        /*  prepare to join */
2099                 u32 v32;
2100
2101                 /*  enable to rx data frame.Accept all data frame */
2102                 /* rtl8723au_write32(padapter, REG_RCR,
2103                    rtl8723au_read32(padapter, REG_RCR)|RCR_ADF); */
2104                 rtl8723au_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
2105
2106                 v32 = rtl8723au_read32(padapter, REG_RCR);
2107                 v32 |= RCR_CBSSID_DATA | RCR_CBSSID_BCN;
2108                 rtl8723au_write32(padapter, REG_RCR, v32);
2109
2110                 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
2111                         RetryLimit =
2112                             (pHalData->CustomerID == RT_CID_CCX) ? 7 : 48;
2113                 else            /*  Ad-hoc Mode */
2114                         RetryLimit = 0x7;
2115         } else if (type == 1) { /*  joinbss_event callback when join res < 0 */
2116                 /*  config RCR to receive different BSSID & not to
2117                     receive data frame during linking */
2118                 rtl8723au_write16(padapter, REG_RXFLTMAP2, 0);
2119         } else if (type == 2) { /*  sta add event callback */
2120                 /*  enable update TSF */
2121                 SetBcnCtrlReg23a(padapter, 0, DIS_TSF_UDT);
2122
2123                 if (check_fwstate(pmlmepriv,
2124                                   WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) {
2125                         /*  fixed beacon issue for 8191su........... */
2126                         rtl8723au_write8(padapter, 0x542, 0x02);
2127                         RetryLimit = 0x7;
2128                 }
2129         }
2130
2131         rtl8723au_write16(padapter, REG_RL,
2132                           RetryLimit << RETRY_LIMIT_SHORT_SHIFT | RetryLimit <<
2133                           RETRY_LIMIT_LONG_SHIFT);
2134
2135         switch (type) {
2136         case 0:
2137                 /*  prepare to join */
2138                 rtl8723a_BT_wifiassociate_notify(padapter, true);
2139                 break;
2140         case 1:
2141                 /*  joinbss_event callback when join res < 0 */
2142                 rtl8723a_BT_wifiassociate_notify(padapter, false);
2143                 break;
2144         case 2:
2145                 /*  sta add event callback */
2146 /*              BT_WifiMediaStatusNotify(padapter, RT_MEDIA_CONNECT); */
2147                 break;
2148         }
2149 }