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