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