1// SPDX-License-Identifier: GPL-2.0
2/******************************************************************************
3 *
4 * Copyright(c) 2007 - 2013 Realtek Corporation. All rights reserved.
5 *
6 ******************************************************************************/
7
8#include <linux/firmware.h>
9#include <linux/slab.h>
10#include <drv_types.h>
11#include <rtw_debug.h>
12#include <rtl8723b_hal.h>
13#include "hal_com_h2c.h"
14
15static void _FWDownloadEnable(struct adapter *padapter, bool enable)
16{
17 u8 tmp, count = 0;
18
19 if (enable) {
20 /* 8051 enable */
21 tmp = rtw_read8(adapter: padapter, REG_SYS_FUNC_EN+1);
22 rtw_write8(adapter: padapter, REG_SYS_FUNC_EN+1, val: tmp|0x04);
23
24 tmp = rtw_read8(adapter: padapter, REG_MCUFWDL);
25 rtw_write8(adapter: padapter, REG_MCUFWDL, val: tmp|0x01);
26
27 do {
28 tmp = rtw_read8(adapter: padapter, REG_MCUFWDL);
29 if (tmp & 0x01)
30 break;
31 rtw_write8(adapter: padapter, REG_MCUFWDL, val: tmp|0x01);
32 msleep(msecs: 1);
33 } while (count++ < 100);
34
35 /* 8051 reset */
36 tmp = rtw_read8(adapter: padapter, REG_MCUFWDL+2);
37 rtw_write8(adapter: padapter, REG_MCUFWDL+2, val: tmp&0xf7);
38 } else {
39 /* MCU firmware download disable. */
40 tmp = rtw_read8(adapter: padapter, REG_MCUFWDL);
41 rtw_write8(adapter: padapter, REG_MCUFWDL, val: tmp&0xfe);
42 }
43}
44
45static int _BlockWrite(struct adapter *padapter, void *buffer, u32 buffSize)
46{
47 int ret = _SUCCESS;
48
49 u32 blockSize_p1 = 4; /* (Default) Phase #1 : PCI muse use 4-byte write to download FW */
50 u32 blockSize_p2 = 8; /* Phase #2 : Use 8-byte, if Phase#1 use big size to write FW. */
51 u32 blockSize_p3 = 1; /* Phase #3 : Use 1-byte, the remnant of FW image. */
52 u32 blockCount_p1 = 0, blockCount_p2 = 0, blockCount_p3 = 0;
53 u32 remainSize_p1 = 0, remainSize_p2 = 0;
54 u8 *bufferPtr = buffer;
55 u32 i = 0, offset = 0;
56
57/* printk("====>%s %d\n", __func__, __LINE__); */
58
59 /* 3 Phase #1 */
60 blockCount_p1 = buffSize / blockSize_p1;
61 remainSize_p1 = buffSize % blockSize_p1;
62
63 for (i = 0; i < blockCount_p1; i++) {
64 ret = rtw_write32(adapter: padapter, addr: (FW_8723B_START_ADDRESS + i * blockSize_p1), val: *((u32 *)(bufferPtr + i * blockSize_p1)));
65 if (ret == _FAIL) {
66 printk("====>%s %d i:%d\n", __func__, __LINE__, i);
67 goto exit;
68 }
69 }
70
71 /* 3 Phase #2 */
72 if (remainSize_p1) {
73 offset = blockCount_p1 * blockSize_p1;
74
75 blockCount_p2 = remainSize_p1/blockSize_p2;
76 remainSize_p2 = remainSize_p1%blockSize_p2;
77 }
78
79 /* 3 Phase #3 */
80 if (remainSize_p2) {
81 offset = (blockCount_p1 * blockSize_p1) + (blockCount_p2 * blockSize_p2);
82
83 blockCount_p3 = remainSize_p2 / blockSize_p3;
84
85 for (i = 0; i < blockCount_p3; i++) {
86 ret = rtw_write8(adapter: padapter, addr: (FW_8723B_START_ADDRESS + offset + i), val: *(bufferPtr + offset + i));
87
88 if (ret == _FAIL) {
89 printk("====>%s %d i:%d\n", __func__, __LINE__, i);
90 goto exit;
91 }
92 }
93 }
94exit:
95 return ret;
96}
97
98static int _PageWrite(
99 struct adapter *padapter,
100 u32 page,
101 void *buffer,
102 u32 size
103)
104{
105 u8 value8;
106 u8 u8Page = (u8) (page & 0x07);
107
108 value8 = (rtw_read8(adapter: padapter, REG_MCUFWDL+2) & 0xF8) | u8Page;
109 rtw_write8(adapter: padapter, REG_MCUFWDL+2, val: value8);
110
111 return _BlockWrite(padapter, buffer, buffSize: size);
112}
113
114static int _WriteFW(struct adapter *padapter, void *buffer, u32 size)
115{
116 /* Since we need dynamic decide method of dwonload fw, so we call this function to get chip version. */
117 /* We can remove _ReadChipVersion from ReadpadapterInfo8192C later. */
118 int ret = _SUCCESS;
119 u32 pageNums, remainSize;
120 u32 page, offset;
121 u8 *bufferPtr = buffer;
122
123 pageNums = size / MAX_DLFW_PAGE_SIZE;
124 remainSize = size % MAX_DLFW_PAGE_SIZE;
125
126 for (page = 0; page < pageNums; page++) {
127 offset = page * MAX_DLFW_PAGE_SIZE;
128 ret = _PageWrite(padapter, page, buffer: bufferPtr+offset, MAX_DLFW_PAGE_SIZE);
129
130 if (ret == _FAIL) {
131 printk("====>%s %d\n", __func__, __LINE__);
132 goto exit;
133 }
134 }
135
136 if (remainSize) {
137 offset = pageNums * MAX_DLFW_PAGE_SIZE;
138 page = pageNums;
139 ret = _PageWrite(padapter, page, buffer: bufferPtr+offset, size: remainSize);
140
141 if (ret == _FAIL) {
142 printk("====>%s %d\n", __func__, __LINE__);
143 goto exit;
144 }
145 }
146
147exit:
148 return ret;
149}
150
151void _8051Reset8723(struct adapter *padapter)
152{
153 u8 cpu_rst;
154 u8 io_rst;
155
156
157 /* Reset 8051(WLMCU) IO wrapper */
158 /* 0x1c[8] = 0 */
159 /* Suggested by Isaac@SD1 and Gimmy@SD1, coding by Lucas@20130624 */
160 io_rst = rtw_read8(adapter: padapter, REG_RSV_CTRL+1);
161 io_rst &= ~BIT(0);
162 rtw_write8(adapter: padapter, REG_RSV_CTRL+1, val: io_rst);
163
164 cpu_rst = rtw_read8(adapter: padapter, REG_SYS_FUNC_EN+1);
165 cpu_rst &= ~BIT(2);
166 rtw_write8(adapter: padapter, REG_SYS_FUNC_EN+1, val: cpu_rst);
167
168 /* Enable 8051 IO wrapper */
169 /* 0x1c[8] = 1 */
170 io_rst = rtw_read8(adapter: padapter, REG_RSV_CTRL+1);
171 io_rst |= BIT(0);
172 rtw_write8(adapter: padapter, REG_RSV_CTRL+1, val: io_rst);
173
174 cpu_rst = rtw_read8(adapter: padapter, REG_SYS_FUNC_EN+1);
175 cpu_rst |= BIT(2);
176 rtw_write8(adapter: padapter, REG_SYS_FUNC_EN+1, val: cpu_rst);
177}
178
179u8 g_fwdl_chksum_fail;
180
181static s32 polling_fwdl_chksum(
182 struct adapter *adapter, u32 min_cnt, u32 timeout_ms
183)
184{
185 s32 ret = _FAIL;
186 u32 value32;
187 unsigned long start = jiffies;
188 u32 cnt = 0;
189
190 /* polling CheckSum report */
191 do {
192 cnt++;
193 value32 = rtw_read32(adapter, REG_MCUFWDL);
194 if (value32 & FWDL_ChkSum_rpt || adapter->bSurpriseRemoved || adapter->bDriverStopped)
195 break;
196 yield();
197 } while (jiffies_to_msecs(j: jiffies-start) < timeout_ms || cnt < min_cnt);
198
199 if (!(value32 & FWDL_ChkSum_rpt)) {
200 goto exit;
201 }
202
203 if (g_fwdl_chksum_fail) {
204 g_fwdl_chksum_fail--;
205 goto exit;
206 }
207
208 ret = _SUCCESS;
209
210exit:
211
212 return ret;
213}
214
215u8 g_fwdl_wintint_rdy_fail;
216
217static s32 _FWFreeToGo(struct adapter *adapter, u32 min_cnt, u32 timeout_ms)
218{
219 s32 ret = _FAIL;
220 u32 value32;
221 unsigned long start = jiffies;
222 u32 cnt = 0;
223
224 value32 = rtw_read32(adapter, REG_MCUFWDL);
225 value32 |= MCUFWDL_RDY;
226 value32 &= ~WINTINI_RDY;
227 rtw_write32(adapter, REG_MCUFWDL, val: value32);
228
229 _8051Reset8723(padapter: adapter);
230
231 /* polling for FW ready */
232 do {
233 cnt++;
234 value32 = rtw_read32(adapter, REG_MCUFWDL);
235 if (value32 & WINTINI_RDY || adapter->bSurpriseRemoved || adapter->bDriverStopped)
236 break;
237 yield();
238 } while (jiffies_to_msecs(j: jiffies - start) < timeout_ms || cnt < min_cnt);
239
240 if (!(value32 & WINTINI_RDY)) {
241 goto exit;
242 }
243
244 if (g_fwdl_wintint_rdy_fail) {
245 g_fwdl_wintint_rdy_fail--;
246 goto exit;
247 }
248
249 ret = _SUCCESS;
250
251exit:
252
253 return ret;
254}
255
256#define IS_FW_81xxC(padapter) (((GET_HAL_DATA(padapter))->FirmwareSignature & 0xFFF0) == 0x88C0)
257
258void rtl8723b_FirmwareSelfReset(struct adapter *padapter)
259{
260 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
261 u8 u1bTmp;
262 u8 Delay = 100;
263
264 if (
265 !(IS_FW_81xxC(padapter) && ((pHalData->FirmwareVersion < 0x21) || (pHalData->FirmwareVersion == 0x21 && pHalData->FirmwareSubVersion < 0x01)))
266 ) { /* after 88C Fw v33.1 */
267 /* 0x1cf = 0x20. Inform 8051 to reset. 2009.12.25. tynli_test */
268 rtw_write8(adapter: padapter, REG_HMETFR+3, val: 0x20);
269
270 u1bTmp = rtw_read8(adapter: padapter, REG_SYS_FUNC_EN+1);
271 while (u1bTmp & BIT2) {
272 Delay--;
273 if (Delay == 0)
274 break;
275 udelay(50);
276 u1bTmp = rtw_read8(adapter: padapter, REG_SYS_FUNC_EN+1);
277 }
278
279 if (Delay == 0) {
280 /* force firmware reset */
281 u1bTmp = rtw_read8(adapter: padapter, REG_SYS_FUNC_EN+1);
282 rtw_write8(adapter: padapter, REG_SYS_FUNC_EN+1, val: u1bTmp&(~BIT2));
283 }
284 }
285}
286
287/* */
288/* Description: */
289/* Download 8192C firmware code. */
290/* */
291/* */
292s32 rtl8723b_FirmwareDownload(struct adapter *padapter, bool bUsedWoWLANFw)
293{
294 s32 rtStatus = _SUCCESS;
295 u8 write_fw = 0;
296 unsigned long fwdl_start_time;
297 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
298 struct rt_firmware *pFirmware;
299 struct rt_firmware *pBTFirmware;
300 struct rt_firmware_hdr *pFwHdr = NULL;
301 u8 *pFirmwareBuf;
302 u32 FirmwareLen;
303 const struct firmware *fw;
304 struct device *device = dvobj_to_dev(dvobj: padapter->dvobj);
305 u8 *fwfilepath;
306 struct dvobj_priv *psdpriv = padapter->dvobj;
307 struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
308 u8 tmp_ps;
309
310 pFirmware = kzalloc(size: sizeof(struct rt_firmware), GFP_KERNEL);
311 if (!pFirmware)
312 return _FAIL;
313 pBTFirmware = kzalloc(size: sizeof(struct rt_firmware), GFP_KERNEL);
314 if (!pBTFirmware) {
315 kfree(objp: pFirmware);
316 return _FAIL;
317 }
318 tmp_ps = rtw_read8(adapter: padapter, addr: 0xa3);
319 tmp_ps &= 0xf8;
320 tmp_ps |= 0x02;
321 /* 1. write 0xA3[:2:0] = 3b'010 */
322 rtw_write8(adapter: padapter, addr: 0xa3, val: tmp_ps);
323 /* 2. read power_state = 0xA0[1:0] */
324 tmp_ps = rtw_read8(adapter: padapter, addr: 0xa0);
325 tmp_ps &= 0x03;
326 if (tmp_ps != 0x01)
327 pdbgpriv->dbg_downloadfw_pwr_state_cnt++;
328
329 fwfilepath = "rtlwifi/rtl8723bs_nic.bin";
330
331 pr_info("rtl8723bs: acquire FW from file:%s\n", fwfilepath);
332
333 rtStatus = request_firmware(fw: &fw, name: fwfilepath, device);
334 if (rtStatus) {
335 pr_err("Request firmware failed with error 0x%x\n", rtStatus);
336 rtStatus = _FAIL;
337 goto exit;
338 }
339
340 if (!fw) {
341 pr_err("Firmware %s not available\n", fwfilepath);
342 rtStatus = _FAIL;
343 goto exit;
344 }
345
346 if (fw->size > FW_8723B_SIZE) {
347 rtStatus = _FAIL;
348 goto exit;
349 }
350
351 pFirmware->fw_buffer_sz = kmemdup(p: fw->data, size: fw->size, GFP_KERNEL);
352 if (!pFirmware->fw_buffer_sz) {
353 rtStatus = _FAIL;
354 goto exit;
355 }
356
357 pFirmware->fw_length = fw->size;
358 release_firmware(fw);
359 if (pFirmware->fw_length > FW_8723B_SIZE) {
360 rtStatus = _FAIL;
361 netdev_emerg(dev: padapter->pnetdev,
362 format: "Firmware size:%u exceed %u\n",
363 pFirmware->fw_length, FW_8723B_SIZE);
364 goto release_fw1;
365 }
366
367 pFirmwareBuf = pFirmware->fw_buffer_sz;
368 FirmwareLen = pFirmware->fw_length;
369
370 /* To Check Fw header. Added by tynli. 2009.12.04. */
371 pFwHdr = (struct rt_firmware_hdr *)pFirmwareBuf;
372
373 pHalData->FirmwareVersion = le16_to_cpu(pFwHdr->version);
374 pHalData->FirmwareSubVersion = le16_to_cpu(pFwHdr->subversion);
375 pHalData->FirmwareSignature = le16_to_cpu(pFwHdr->signature);
376
377 if (IS_FW_HEADER_EXIST_8723B(pFwHdr)) {
378 /* Shift 32 bytes for FW header */
379 pFirmwareBuf = pFirmwareBuf + 32;
380 FirmwareLen = FirmwareLen - 32;
381 }
382
383 /* Suggested by Filen. If 8051 is running in RAM code, driver should inform Fw to reset by itself, */
384 /* or it will cause download Fw fail. 2010.02.01. by tynli. */
385 if (rtw_read8(adapter: padapter, REG_MCUFWDL) & RAM_DL_SEL) { /* 8051 RAM code */
386 rtw_write8(adapter: padapter, REG_MCUFWDL, val: 0x00);
387 rtl8723b_FirmwareSelfReset(padapter);
388 }
389
390 _FWDownloadEnable(padapter, enable: true);
391 fwdl_start_time = jiffies;
392 while (
393 !padapter->bDriverStopped &&
394 !padapter->bSurpriseRemoved &&
395 (write_fw++ < 3 || jiffies_to_msecs(j: jiffies - fwdl_start_time) < 500)
396 ) {
397 /* reset FWDL chksum */
398 rtw_write8(adapter: padapter, REG_MCUFWDL, val: rtw_read8(adapter: padapter, REG_MCUFWDL)|FWDL_ChkSum_rpt);
399
400 rtStatus = _WriteFW(padapter, buffer: pFirmwareBuf, size: FirmwareLen);
401 if (rtStatus != _SUCCESS)
402 continue;
403
404 rtStatus = polling_fwdl_chksum(adapter: padapter, min_cnt: 5, timeout_ms: 50);
405 if (rtStatus == _SUCCESS)
406 break;
407 }
408 _FWDownloadEnable(padapter, enable: false);
409 if (_SUCCESS != rtStatus)
410 goto fwdl_stat;
411
412 rtStatus = _FWFreeToGo(adapter: padapter, min_cnt: 10, timeout_ms: 200);
413 if (_SUCCESS != rtStatus)
414 goto fwdl_stat;
415
416fwdl_stat:
417
418exit:
419 kfree(objp: pFirmware->fw_buffer_sz);
420 kfree(objp: pFirmware);
421release_fw1:
422 kfree(objp: pBTFirmware);
423 return rtStatus;
424}
425
426void rtl8723b_InitializeFirmwareVars(struct adapter *padapter)
427{
428 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
429
430 /* Init Fw LPS related. */
431 adapter_to_pwrctl(padapter)->fw_current_in_ps_mode = false;
432
433 /* Init H2C cmd. */
434 rtw_write8(adapter: padapter, REG_HMETFR, val: 0x0f);
435
436 /* Init H2C counter. by tynli. 2009.12.09. */
437 pHalData->LastHMEBoxNum = 0;
438/* pHalData->H2CQueueHead = 0; */
439/* pHalData->H2CQueueTail = 0; */
440/* pHalData->H2CStopInsertQueue = false; */
441}
442
443static void rtl8723b_free_hal_data(struct adapter *padapter)
444{
445}
446
447/* */
448/* Efuse related code */
449/* */
450static u8 hal_EfuseSwitchToBank(
451 struct adapter *padapter, u8 bank, bool bPseudoTest
452)
453{
454 u8 bRet = false;
455 u32 value32 = 0;
456#ifdef HAL_EFUSE_MEMORY
457 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
458 struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
459#endif
460
461
462 if (bPseudoTest) {
463#ifdef HAL_EFUSE_MEMORY
464 pEfuseHal->fakeEfuseBank = bank;
465#else
466 fakeEfuseBank = bank;
467#endif
468 bRet = true;
469 } else {
470 value32 = rtw_read32(adapter: padapter, EFUSE_TEST);
471 bRet = true;
472 switch (bank) {
473 case 0:
474 value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0);
475 break;
476 case 1:
477 value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_BT_SEL_0);
478 break;
479 case 2:
480 value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_BT_SEL_1);
481 break;
482 case 3:
483 value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_BT_SEL_2);
484 break;
485 default:
486 value32 = (value32 & ~EFUSE_SEL_MASK) | EFUSE_SEL(EFUSE_WIFI_SEL_0);
487 bRet = false;
488 break;
489 }
490 rtw_write32(adapter: padapter, EFUSE_TEST, val: value32);
491 }
492
493 return bRet;
494}
495
496static void Hal_GetEfuseDefinition(
497 struct adapter *padapter,
498 u8 efuseType,
499 u8 type,
500 void *pOut,
501 bool bPseudoTest
502)
503{
504 switch (type) {
505 case TYPE_EFUSE_MAX_SECTION:
506 {
507 u8 *pMax_section;
508 pMax_section = pOut;
509
510 if (efuseType == EFUSE_WIFI)
511 *pMax_section = EFUSE_MAX_SECTION_8723B;
512 else
513 *pMax_section = EFUSE_BT_MAX_SECTION;
514 }
515 break;
516
517 case TYPE_EFUSE_REAL_CONTENT_LEN:
518 {
519 u16 *pu2Tmp;
520 pu2Tmp = pOut;
521
522 if (efuseType == EFUSE_WIFI)
523 *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723B;
524 else
525 *pu2Tmp = EFUSE_BT_REAL_CONTENT_LEN;
526 }
527 break;
528
529 case TYPE_AVAILABLE_EFUSE_BYTES_BANK:
530 {
531 u16 *pu2Tmp;
532 pu2Tmp = pOut;
533
534 if (efuseType == EFUSE_WIFI)
535 *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723B-EFUSE_OOB_PROTECT_BYTES);
536 else
537 *pu2Tmp = (EFUSE_BT_REAL_BANK_CONTENT_LEN-EFUSE_PROTECT_BYTES_BANK);
538 }
539 break;
540
541 case TYPE_AVAILABLE_EFUSE_BYTES_TOTAL:
542 {
543 u16 *pu2Tmp;
544 pu2Tmp = pOut;
545
546 if (efuseType == EFUSE_WIFI)
547 *pu2Tmp = (EFUSE_REAL_CONTENT_LEN_8723B-EFUSE_OOB_PROTECT_BYTES);
548 else
549 *pu2Tmp = (EFUSE_BT_REAL_CONTENT_LEN-(EFUSE_PROTECT_BYTES_BANK*3));
550 }
551 break;
552
553 case TYPE_EFUSE_MAP_LEN:
554 {
555 u16 *pu2Tmp;
556 pu2Tmp = pOut;
557
558 if (efuseType == EFUSE_WIFI)
559 *pu2Tmp = EFUSE_MAX_MAP_LEN;
560 else
561 *pu2Tmp = EFUSE_BT_MAP_LEN;
562 }
563 break;
564
565 case TYPE_EFUSE_PROTECT_BYTES_BANK:
566 {
567 u8 *pu1Tmp;
568 pu1Tmp = pOut;
569
570 if (efuseType == EFUSE_WIFI)
571 *pu1Tmp = EFUSE_OOB_PROTECT_BYTES;
572 else
573 *pu1Tmp = EFUSE_PROTECT_BYTES_BANK;
574 }
575 break;
576
577 case TYPE_EFUSE_CONTENT_LEN_BANK:
578 {
579 u16 *pu2Tmp;
580 pu2Tmp = pOut;
581
582 if (efuseType == EFUSE_WIFI)
583 *pu2Tmp = EFUSE_REAL_CONTENT_LEN_8723B;
584 else
585 *pu2Tmp = EFUSE_BT_REAL_BANK_CONTENT_LEN;
586 }
587 break;
588
589 default:
590 {
591 u8 *pu1Tmp;
592 pu1Tmp = pOut;
593 *pu1Tmp = 0;
594 }
595 break;
596 }
597}
598
599#define VOLTAGE_V25 0x03
600
601/* */
602/* The following is for compile ok */
603/* That should be merged with the original in the future */
604/* */
605#define EFUSE_ACCESS_ON_8723 0x69 /* For RTL8723 only. */
606#define REG_EFUSE_ACCESS_8723 0x00CF /* Efuse access protection for RTL8723 */
607
608/* */
609static void Hal_BT_EfusePowerSwitch(
610 struct adapter *padapter, u8 bWrite, u8 PwrState
611)
612{
613 u8 tempval;
614 if (PwrState) {
615 /* enable BT power cut */
616 /* 0x6A[14] = 1 */
617 tempval = rtw_read8(adapter: padapter, addr: 0x6B);
618 tempval |= BIT(6);
619 rtw_write8(adapter: padapter, addr: 0x6B, val: tempval);
620
621 /* Attention!! Between 0x6A[14] and 0x6A[15] setting need 100us delay */
622 /* So don't write 0x6A[14]= 1 and 0x6A[15]= 0 together! */
623 msleep(msecs: 1);
624 /* disable BT output isolation */
625 /* 0x6A[15] = 0 */
626 tempval = rtw_read8(adapter: padapter, addr: 0x6B);
627 tempval &= ~BIT(7);
628 rtw_write8(adapter: padapter, addr: 0x6B, val: tempval);
629 } else {
630 /* enable BT output isolation */
631 /* 0x6A[15] = 1 */
632 tempval = rtw_read8(adapter: padapter, addr: 0x6B);
633 tempval |= BIT(7);
634 rtw_write8(adapter: padapter, addr: 0x6B, val: tempval);
635
636 /* Attention!! Between 0x6A[14] and 0x6A[15] setting need 100us delay */
637 /* So don't write 0x6A[14]= 1 and 0x6A[15]= 0 together! */
638
639 /* disable BT power cut */
640 /* 0x6A[14] = 1 */
641 tempval = rtw_read8(adapter: padapter, addr: 0x6B);
642 tempval &= ~BIT(6);
643 rtw_write8(adapter: padapter, addr: 0x6B, val: tempval);
644 }
645
646}
647static void Hal_EfusePowerSwitch(
648 struct adapter *padapter, u8 bWrite, u8 PwrState
649)
650{
651 u8 tempval;
652 u16 tmpV16;
653
654
655 if (PwrState) {
656 /* To avoid cannot access efuse registers after disable/enable several times during DTM test. */
657 /* Suggested by SD1 IsaacHsu. 2013.07.08, added by tynli. */
658 tempval = rtw_read8(adapter: padapter, SDIO_LOCAL_BASE|SDIO_REG_HSUS_CTRL);
659 if (tempval & BIT(0)) { /* SDIO local register is suspend */
660 u8 count = 0;
661
662
663 tempval &= ~BIT(0);
664 rtw_write8(adapter: padapter, SDIO_LOCAL_BASE|SDIO_REG_HSUS_CTRL, val: tempval);
665
666 /* check 0x86[1:0]= 10'2h, wait power state to leave suspend */
667 do {
668 tempval = rtw_read8(adapter: padapter, SDIO_LOCAL_BASE|SDIO_REG_HSUS_CTRL);
669 tempval &= 0x3;
670 if (tempval == 0x02)
671 break;
672
673 count++;
674 if (count >= 100)
675 break;
676
677 mdelay(10);
678 } while (1);
679 }
680
681 rtw_write8(adapter: padapter, REG_EFUSE_ACCESS_8723, EFUSE_ACCESS_ON_8723);
682
683 /* Reset: 0x0000h[28], default valid */
684 tmpV16 = rtw_read16(adapter: padapter, REG_SYS_FUNC_EN);
685 if (!(tmpV16 & FEN_ELDR)) {
686 tmpV16 |= FEN_ELDR;
687 rtw_write16(adapter: padapter, REG_SYS_FUNC_EN, val: tmpV16);
688 }
689
690 /* Clock: Gated(0x0008h[5]) 8M(0x0008h[1]) clock from ANA, default valid */
691 tmpV16 = rtw_read16(adapter: padapter, REG_SYS_CLKR);
692 if ((!(tmpV16 & LOADER_CLK_EN)) || (!(tmpV16 & ANA8M))) {
693 tmpV16 |= (LOADER_CLK_EN | ANA8M);
694 rtw_write16(adapter: padapter, REG_SYS_CLKR, val: tmpV16);
695 }
696
697 if (bWrite) {
698 /* Enable LDO 2.5V before read/write action */
699 tempval = rtw_read8(adapter: padapter, EFUSE_TEST+3);
700 tempval &= 0x0F;
701 tempval |= (VOLTAGE_V25 << 4);
702 rtw_write8(adapter: padapter, EFUSE_TEST+3, val: (tempval | 0x80));
703
704 /* rtw_write8(padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_ON); */
705 }
706 } else {
707 rtw_write8(adapter: padapter, REG_EFUSE_ACCESS, EFUSE_ACCESS_OFF);
708
709 if (bWrite) {
710 /* Disable LDO 2.5V after read/write action */
711 tempval = rtw_read8(adapter: padapter, EFUSE_TEST+3);
712 rtw_write8(adapter: padapter, EFUSE_TEST+3, val: (tempval & 0x7F));
713 }
714
715 }
716}
717
718static void hal_ReadEFuse_WiFi(
719 struct adapter *padapter,
720 u16 _offset,
721 u16 _size_byte,
722 u8 *pbuf,
723 bool bPseudoTest
724)
725{
726#ifdef HAL_EFUSE_MEMORY
727 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
728 struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
729#endif
730 u8 *efuseTbl = NULL;
731 u16 eFuse_Addr = 0;
732 u8 offset, wden;
733 u8 efuseHeader, efuseExtHdr, efuseData;
734 u16 i, total, used;
735 u8 efuse_usage = 0;
736
737 /* */
738 /* Do NOT excess total size of EFuse table. Added by Roger, 2008.11.10. */
739 /* */
740 if ((_offset + _size_byte) > EFUSE_MAX_MAP_LEN)
741 return;
742
743 efuseTbl = rtw_malloc(EFUSE_MAX_MAP_LEN);
744 if (!efuseTbl)
745 return;
746
747 /* 0xff will be efuse default value instead of 0x00. */
748 memset(efuseTbl, 0xFF, EFUSE_MAX_MAP_LEN);
749
750 /* switch bank back to bank 0 for later BT and wifi use. */
751 hal_EfuseSwitchToBank(padapter, bank: 0, bPseudoTest);
752
753 while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
754 efuse_OneByteRead(padapter, addr: eFuse_Addr++, data: &efuseHeader, bPseudoTest);
755 if (efuseHeader == 0xFF)
756 break;
757
758 /* Check PG header for section num. */
759 if (EXT_HEADER(efuseHeader)) { /* extended header */
760 offset = GET_HDR_OFFSET_2_0(efuseHeader);
761
762 efuse_OneByteRead(padapter, addr: eFuse_Addr++, data: &efuseExtHdr, bPseudoTest);
763 if (ALL_WORDS_DISABLED(efuseExtHdr))
764 continue;
765
766 offset |= ((efuseExtHdr & 0xF0) >> 1);
767 wden = (efuseExtHdr & 0x0F);
768 } else {
769 offset = ((efuseHeader >> 4) & 0x0f);
770 wden = (efuseHeader & 0x0f);
771 }
772
773 if (offset < EFUSE_MAX_SECTION_8723B) {
774 u16 addr;
775 /* Get word enable value from PG header */
776
777 addr = offset * PGPKT_DATA_SIZE;
778 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
779 /* Check word enable condition in the section */
780 if (!(wden & (0x01<<i))) {
781 efuse_OneByteRead(padapter, addr: eFuse_Addr++, data: &efuseData, bPseudoTest);
782 efuseTbl[addr] = efuseData;
783
784 efuse_OneByteRead(padapter, addr: eFuse_Addr++, data: &efuseData, bPseudoTest);
785 efuseTbl[addr+1] = efuseData;
786 }
787 addr += 2;
788 }
789 } else {
790 eFuse_Addr += Efuse_CalculateWordCnts(word_en: wden)*2;
791 }
792 }
793
794 /* Copy from Efuse map to output pointer memory!!! */
795 for (i = 0; i < _size_byte; i++)
796 pbuf[i] = efuseTbl[_offset+i];
797
798 /* Calculate Efuse utilization */
799 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, type: TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, pOut: &total, bPseudoTest);
800 used = eFuse_Addr - 1;
801 efuse_usage = (u8)((used*100)/total);
802 if (bPseudoTest) {
803#ifdef HAL_EFUSE_MEMORY
804 pEfuseHal->fakeEfuseUsedBytes = used;
805#else
806 fakeEfuseUsedBytes = used;
807#endif
808 } else {
809 rtw_hal_set_hwreg(padapter, variable: HW_VAR_EFUSE_BYTES, val: (u8 *)&used);
810 rtw_hal_set_hwreg(padapter, variable: HW_VAR_EFUSE_USAGE, val: (u8 *)&efuse_usage);
811 }
812
813 kfree(objp: efuseTbl);
814}
815
816static void hal_ReadEFuse_BT(
817 struct adapter *padapter,
818 u16 _offset,
819 u16 _size_byte,
820 u8 *pbuf,
821 bool bPseudoTest
822)
823{
824#ifdef HAL_EFUSE_MEMORY
825 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
826 struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
827#endif
828 u8 *efuseTbl;
829 u8 bank;
830 u16 eFuse_Addr;
831 u8 efuseHeader, efuseExtHdr, efuseData;
832 u8 offset, wden;
833 u16 i, total, used;
834 u8 efuse_usage;
835
836
837 /* */
838 /* Do NOT excess total size of EFuse table. Added by Roger, 2008.11.10. */
839 /* */
840 if ((_offset + _size_byte) > EFUSE_BT_MAP_LEN)
841 return;
842
843 efuseTbl = rtw_malloc(EFUSE_BT_MAP_LEN);
844 if (!efuseTbl)
845 return;
846
847 /* 0xff will be efuse default value instead of 0x00. */
848 memset(efuseTbl, 0xFF, EFUSE_BT_MAP_LEN);
849
850 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, type: TYPE_AVAILABLE_EFUSE_BYTES_BANK, pOut: &total, bPseudoTest);
851
852 for (bank = 1; bank < 3; bank++) { /* 8723b Max bake 0~2 */
853 if (hal_EfuseSwitchToBank(padapter, bank, bPseudoTest) == false)
854 goto exit;
855
856 eFuse_Addr = 0;
857
858 while (AVAILABLE_EFUSE_ADDR(eFuse_Addr)) {
859 efuse_OneByteRead(padapter, addr: eFuse_Addr++, data: &efuseHeader, bPseudoTest);
860 if (efuseHeader == 0xFF)
861 break;
862
863 /* Check PG header for section num. */
864 if (EXT_HEADER(efuseHeader)) { /* extended header */
865 offset = GET_HDR_OFFSET_2_0(efuseHeader);
866
867 efuse_OneByteRead(padapter, addr: eFuse_Addr++, data: &efuseExtHdr, bPseudoTest);
868 if (ALL_WORDS_DISABLED(efuseExtHdr))
869 continue;
870
871
872 offset |= ((efuseExtHdr & 0xF0) >> 1);
873 wden = (efuseExtHdr & 0x0F);
874 } else {
875 offset = ((efuseHeader >> 4) & 0x0f);
876 wden = (efuseHeader & 0x0f);
877 }
878
879 if (offset < EFUSE_BT_MAX_SECTION) {
880 u16 addr;
881
882 addr = offset * PGPKT_DATA_SIZE;
883 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
884 /* Check word enable condition in the section */
885 if (!(wden & (0x01<<i))) {
886 efuse_OneByteRead(padapter, addr: eFuse_Addr++, data: &efuseData, bPseudoTest);
887 efuseTbl[addr] = efuseData;
888
889 efuse_OneByteRead(padapter, addr: eFuse_Addr++, data: &efuseData, bPseudoTest);
890 efuseTbl[addr+1] = efuseData;
891 }
892 addr += 2;
893 }
894 } else {
895 eFuse_Addr += Efuse_CalculateWordCnts(word_en: wden)*2;
896 }
897 }
898
899 if ((eFuse_Addr - 1) < total)
900 break;
901
902 }
903
904 /* switch bank back to bank 0 for later BT and wifi use. */
905 hal_EfuseSwitchToBank(padapter, bank: 0, bPseudoTest);
906
907 /* Copy from Efuse map to output pointer memory!!! */
908 for (i = 0; i < _size_byte; i++)
909 pbuf[i] = efuseTbl[_offset+i];
910
911 /* */
912 /* Calculate Efuse utilization. */
913 /* */
914 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, type: TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, pOut: &total, bPseudoTest);
915 used = (EFUSE_BT_REAL_BANK_CONTENT_LEN*(bank-1)) + eFuse_Addr - 1;
916 efuse_usage = (u8)((used*100)/total);
917 if (bPseudoTest) {
918#ifdef HAL_EFUSE_MEMORY
919 pEfuseHal->fakeBTEfuseUsedBytes = used;
920#else
921 fakeBTEfuseUsedBytes = used;
922#endif
923 } else {
924 rtw_hal_set_hwreg(padapter, variable: HW_VAR_EFUSE_BT_BYTES, val: (u8 *)&used);
925 rtw_hal_set_hwreg(padapter, variable: HW_VAR_EFUSE_BT_USAGE, val: (u8 *)&efuse_usage);
926 }
927
928exit:
929 kfree(objp: efuseTbl);
930}
931
932static void Hal_ReadEFuse(
933 struct adapter *padapter,
934 u8 efuseType,
935 u16 _offset,
936 u16 _size_byte,
937 u8 *pbuf,
938 bool bPseudoTest
939)
940{
941 if (efuseType == EFUSE_WIFI)
942 hal_ReadEFuse_WiFi(padapter, _offset, _size_byte, pbuf, bPseudoTest);
943 else
944 hal_ReadEFuse_BT(padapter, _offset, _size_byte, pbuf, bPseudoTest);
945}
946
947static u16 hal_EfuseGetCurrentSize_WiFi(
948 struct adapter *padapter, bool bPseudoTest
949)
950{
951#ifdef HAL_EFUSE_MEMORY
952 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
953 struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
954#endif
955 u16 efuse_addr = 0;
956 u16 start_addr = 0; /* for debug */
957 u8 hworden = 0;
958 u8 efuse_data, word_cnts = 0;
959 u32 count = 0; /* for debug */
960
961
962 if (bPseudoTest) {
963#ifdef HAL_EFUSE_MEMORY
964 efuse_addr = (u16)pEfuseHal->fakeEfuseUsedBytes;
965#else
966 efuse_addr = (u16)fakeEfuseUsedBytes;
967#endif
968 } else
969 rtw_hal_get_hwreg(padapter, variable: HW_VAR_EFUSE_BYTES, val: (u8 *)&efuse_addr);
970
971 start_addr = efuse_addr;
972
973 /* switch bank back to bank 0 for later BT and wifi use. */
974 hal_EfuseSwitchToBank(padapter, bank: 0, bPseudoTest);
975
976 count = 0;
977 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
978 if (efuse_OneByteRead(padapter, addr: efuse_addr, data: &efuse_data, bPseudoTest) == false)
979 goto error;
980
981 if (efuse_data == 0xFF)
982 break;
983
984 if ((start_addr != 0) && (efuse_addr == start_addr)) {
985 count++;
986
987 efuse_data = 0xFF;
988 if (count < 4) {
989 /* try again! */
990
991 if (count > 2) {
992 /* try again form address 0 */
993 efuse_addr = 0;
994 start_addr = 0;
995 }
996
997 continue;
998 }
999
1000 goto error;
1001 }
1002
1003 if (EXT_HEADER(efuse_data)) {
1004 efuse_addr++;
1005 efuse_OneByteRead(padapter, addr: efuse_addr, data: &efuse_data, bPseudoTest);
1006 if (ALL_WORDS_DISABLED(efuse_data))
1007 continue;
1008
1009 hworden = efuse_data & 0x0F;
1010 } else {
1011 hworden = efuse_data & 0x0F;
1012 }
1013
1014 word_cnts = Efuse_CalculateWordCnts(word_en: hworden);
1015 efuse_addr += (word_cnts*2)+1;
1016 }
1017
1018 if (bPseudoTest) {
1019#ifdef HAL_EFUSE_MEMORY
1020 pEfuseHal->fakeEfuseUsedBytes = efuse_addr;
1021#else
1022 fakeEfuseUsedBytes = efuse_addr;
1023#endif
1024 } else
1025 rtw_hal_set_hwreg(padapter, variable: HW_VAR_EFUSE_BYTES, val: (u8 *)&efuse_addr);
1026
1027 goto exit;
1028
1029error:
1030 /* report max size to prevent write efuse */
1031 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, type: TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, pOut: &efuse_addr, bPseudoTest);
1032
1033exit:
1034
1035 return efuse_addr;
1036}
1037
1038static u16 hal_EfuseGetCurrentSize_BT(struct adapter *padapter, u8 bPseudoTest)
1039{
1040#ifdef HAL_EFUSE_MEMORY
1041 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1042 struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
1043#endif
1044 u16 btusedbytes;
1045 u16 efuse_addr;
1046 u8 bank, startBank;
1047 u8 hworden = 0;
1048 u8 efuse_data, word_cnts = 0;
1049 u16 retU2 = 0;
1050
1051 if (bPseudoTest) {
1052#ifdef HAL_EFUSE_MEMORY
1053 btusedbytes = pEfuseHal->fakeBTEfuseUsedBytes;
1054#else
1055 btusedbytes = fakeBTEfuseUsedBytes;
1056#endif
1057 } else
1058 rtw_hal_get_hwreg(padapter, variable: HW_VAR_EFUSE_BT_BYTES, val: (u8 *)&btusedbytes);
1059
1060 efuse_addr = (u16)((btusedbytes%EFUSE_BT_REAL_BANK_CONTENT_LEN));
1061 startBank = (u8)(1+(btusedbytes/EFUSE_BT_REAL_BANK_CONTENT_LEN));
1062
1063 EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, type: TYPE_AVAILABLE_EFUSE_BYTES_BANK, pOut: &retU2, bPseudoTest);
1064
1065 for (bank = startBank; bank < 3; bank++) {
1066 if (hal_EfuseSwitchToBank(padapter, bank, bPseudoTest) == false)
1067 /* bank = EFUSE_MAX_BANK; */
1068 break;
1069
1070 /* only when bank is switched we have to reset the efuse_addr. */
1071 if (bank != startBank)
1072 efuse_addr = 0;
1073#if 1
1074
1075 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
1076 if (efuse_OneByteRead(padapter, addr: efuse_addr,
1077 data: &efuse_data, bPseudoTest) == false)
1078 /* bank = EFUSE_MAX_BANK; */
1079 break;
1080
1081 if (efuse_data == 0xFF)
1082 break;
1083
1084 if (EXT_HEADER(efuse_data)) {
1085 efuse_addr++;
1086 efuse_OneByteRead(padapter, addr: efuse_addr, data: &efuse_data, bPseudoTest);
1087
1088 if (ALL_WORDS_DISABLED(efuse_data)) {
1089 efuse_addr++;
1090 continue;
1091 }
1092
1093 hworden = efuse_data & 0x0F;
1094 } else {
1095 hworden = efuse_data & 0x0F;
1096 }
1097
1098 word_cnts = Efuse_CalculateWordCnts(word_en: hworden);
1099 /* read next header */
1100 efuse_addr += (word_cnts*2)+1;
1101 }
1102#else
1103 while (
1104 bContinual &&
1105 efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest) &&
1106 AVAILABLE_EFUSE_ADDR(efuse_addr)
1107 ) {
1108 if (efuse_data != 0xFF) {
1109 if ((efuse_data&0x1F) == 0x0F) { /* extended header */
1110 efuse_addr++;
1111 efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest);
1112 if ((efuse_data & 0x0F) == 0x0F) {
1113 efuse_addr++;
1114 continue;
1115 } else {
1116 hworden = efuse_data & 0x0F;
1117 }
1118 } else {
1119 hworden = efuse_data & 0x0F;
1120 }
1121 word_cnts = Efuse_CalculateWordCnts(hworden);
1122 /* read next header */
1123 efuse_addr = efuse_addr + (word_cnts*2)+1;
1124 } else
1125 bContinual = false;
1126 }
1127#endif
1128
1129
1130 /* Check if we need to check next bank efuse */
1131 if (efuse_addr < retU2)
1132 break; /* don't need to check next bank. */
1133 }
1134
1135 retU2 = ((bank-1)*EFUSE_BT_REAL_BANK_CONTENT_LEN)+efuse_addr;
1136 if (bPseudoTest) {
1137 pEfuseHal->fakeBTEfuseUsedBytes = retU2;
1138 } else {
1139 pEfuseHal->BTEfuseUsedBytes = retU2;
1140 }
1141
1142 return retU2;
1143}
1144
1145static u16 Hal_EfuseGetCurrentSize(
1146 struct adapter *padapter, u8 efuseType, bool bPseudoTest
1147)
1148{
1149 u16 ret = 0;
1150
1151 if (efuseType == EFUSE_WIFI)
1152 ret = hal_EfuseGetCurrentSize_WiFi(padapter, bPseudoTest);
1153 else
1154 ret = hal_EfuseGetCurrentSize_BT(padapter, bPseudoTest);
1155
1156 return ret;
1157}
1158
1159static u8 Hal_EfuseWordEnableDataWrite(
1160 struct adapter *padapter,
1161 u16 efuse_addr,
1162 u8 word_en,
1163 u8 *data,
1164 bool bPseudoTest
1165)
1166{
1167 u16 tmpaddr = 0;
1168 u16 start_addr = efuse_addr;
1169 u8 badworden = 0x0F;
1170 u8 tmpdata[PGPKT_DATA_SIZE];
1171
1172 memset(tmpdata, 0xFF, PGPKT_DATA_SIZE);
1173
1174 if (!(word_en & BIT(0))) {
1175 tmpaddr = start_addr;
1176 efuse_OneByteWrite(padapter, addr: start_addr++, data: data[0], bPseudoTest);
1177 efuse_OneByteWrite(padapter, addr: start_addr++, data: data[1], bPseudoTest);
1178
1179 efuse_OneByteRead(padapter, addr: tmpaddr, data: &tmpdata[0], bPseudoTest);
1180 efuse_OneByteRead(padapter, addr: tmpaddr+1, data: &tmpdata[1], bPseudoTest);
1181 if ((data[0] != tmpdata[0]) || (data[1] != tmpdata[1])) {
1182 badworden &= (~BIT(0));
1183 }
1184 }
1185 if (!(word_en & BIT(1))) {
1186 tmpaddr = start_addr;
1187 efuse_OneByteWrite(padapter, addr: start_addr++, data: data[2], bPseudoTest);
1188 efuse_OneByteWrite(padapter, addr: start_addr++, data: data[3], bPseudoTest);
1189
1190 efuse_OneByteRead(padapter, addr: tmpaddr, data: &tmpdata[2], bPseudoTest);
1191 efuse_OneByteRead(padapter, addr: tmpaddr+1, data: &tmpdata[3], bPseudoTest);
1192 if ((data[2] != tmpdata[2]) || (data[3] != tmpdata[3])) {
1193 badworden &= (~BIT(1));
1194 }
1195 }
1196
1197 if (!(word_en & BIT(2))) {
1198 tmpaddr = start_addr;
1199 efuse_OneByteWrite(padapter, addr: start_addr++, data: data[4], bPseudoTest);
1200 efuse_OneByteWrite(padapter, addr: start_addr++, data: data[5], bPseudoTest);
1201
1202 efuse_OneByteRead(padapter, addr: tmpaddr, data: &tmpdata[4], bPseudoTest);
1203 efuse_OneByteRead(padapter, addr: tmpaddr+1, data: &tmpdata[5], bPseudoTest);
1204 if ((data[4] != tmpdata[4]) || (data[5] != tmpdata[5])) {
1205 badworden &= (~BIT(2));
1206 }
1207 }
1208
1209 if (!(word_en & BIT(3))) {
1210 tmpaddr = start_addr;
1211 efuse_OneByteWrite(padapter, addr: start_addr++, data: data[6], bPseudoTest);
1212 efuse_OneByteWrite(padapter, addr: start_addr++, data: data[7], bPseudoTest);
1213
1214 efuse_OneByteRead(padapter, addr: tmpaddr, data: &tmpdata[6], bPseudoTest);
1215 efuse_OneByteRead(padapter, addr: tmpaddr+1, data: &tmpdata[7], bPseudoTest);
1216 if ((data[6] != tmpdata[6]) || (data[7] != tmpdata[7])) {
1217 badworden &= (~BIT(3));
1218 }
1219 }
1220
1221 return badworden;
1222}
1223
1224static s32 Hal_EfusePgPacketRead(
1225 struct adapter *padapter,
1226 u8 offset,
1227 u8 *data,
1228 bool bPseudoTest
1229)
1230{
1231 u8 efuse_data, word_cnts = 0;
1232 u16 efuse_addr = 0;
1233 u8 hoffset = 0, hworden = 0;
1234 u8 i;
1235 u8 max_section = 0;
1236 s32 ret;
1237
1238
1239 if (!data)
1240 return false;
1241
1242 EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, type: TYPE_EFUSE_MAX_SECTION, pOut: &max_section, bPseudoTest);
1243 if (offset > max_section)
1244 return false;
1245
1246 memset(data, 0xFF, PGPKT_DATA_SIZE);
1247 ret = true;
1248
1249 /* */
1250 /* <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */
1251 /* Skip dummy parts to prevent unexpected data read from Efuse. */
1252 /* By pass right now. 2009.02.19. */
1253 /* */
1254 while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
1255 if (efuse_OneByteRead(padapter, addr: efuse_addr++, data: &efuse_data, bPseudoTest) == false) {
1256 ret = false;
1257 break;
1258 }
1259
1260 if (efuse_data == 0xFF)
1261 break;
1262
1263 if (EXT_HEADER(efuse_data)) {
1264 hoffset = GET_HDR_OFFSET_2_0(efuse_data);
1265 efuse_OneByteRead(padapter, addr: efuse_addr++, data: &efuse_data, bPseudoTest);
1266 if (ALL_WORDS_DISABLED(efuse_data))
1267 continue;
1268
1269 hoffset |= ((efuse_data & 0xF0) >> 1);
1270 hworden = efuse_data & 0x0F;
1271 } else {
1272 hoffset = (efuse_data>>4) & 0x0F;
1273 hworden = efuse_data & 0x0F;
1274 }
1275
1276 if (hoffset == offset) {
1277 for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
1278 /* Check word enable condition in the section */
1279 if (!(hworden & (0x01<<i))) {
1280 efuse_OneByteRead(padapter, addr: efuse_addr++, data: &efuse_data, bPseudoTest);
1281 data[i*2] = efuse_data;
1282
1283 efuse_OneByteRead(padapter, addr: efuse_addr++, data: &efuse_data, bPseudoTest);
1284 data[(i*2)+1] = efuse_data;
1285 }
1286 }
1287 } else {
1288 word_cnts = Efuse_CalculateWordCnts(word_en: hworden);
1289 efuse_addr += word_cnts*2;
1290 }
1291 }
1292
1293 return ret;
1294}
1295
1296static u8 hal_EfusePgCheckAvailableAddr(
1297 struct adapter *padapter, u8 efuseType, u8 bPseudoTest
1298)
1299{
1300 u16 max_available = 0;
1301 u16 current_size;
1302
1303
1304 EFUSE_GetEfuseDefinition(padapter, efuseType, type: TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, pOut: &max_available, bPseudoTest);
1305
1306 current_size = Efuse_GetCurrentSize(padapter, efuseType, bPseudoTest);
1307 if (current_size >= max_available)
1308 return false;
1309
1310 return true;
1311}
1312
1313static void hal_EfuseConstructPGPkt(
1314 u8 offset,
1315 u8 word_en,
1316 u8 *pData,
1317 struct pgpkt_struct *pTargetPkt
1318)
1319{
1320 memset(pTargetPkt->data, 0xFF, PGPKT_DATA_SIZE);
1321 pTargetPkt->offset = offset;
1322 pTargetPkt->word_en = word_en;
1323 efuse_WordEnableDataRead(word_en, sourdata: pData, targetdata: pTargetPkt->data);
1324 pTargetPkt->word_cnts = Efuse_CalculateWordCnts(word_en: pTargetPkt->word_en);
1325}
1326
1327static u8 hal_EfusePartialWriteCheck(
1328 struct adapter *padapter,
1329 u8 efuseType,
1330 u16 *pAddr,
1331 struct pgpkt_struct *pTargetPkt,
1332 u8 bPseudoTest
1333)
1334{
1335 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1336 struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
1337 u8 bRet = false;
1338 u16 startAddr = 0, efuse_max_available_len = 0, efuse_max = 0;
1339 u8 efuse_data = 0;
1340
1341 EFUSE_GetEfuseDefinition(padapter, efuseType, type: TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, pOut: &efuse_max_available_len, bPseudoTest);
1342 EFUSE_GetEfuseDefinition(padapter, efuseType, type: TYPE_EFUSE_CONTENT_LEN_BANK, pOut: &efuse_max, bPseudoTest);
1343
1344 if (efuseType == EFUSE_WIFI) {
1345 if (bPseudoTest) {
1346#ifdef HAL_EFUSE_MEMORY
1347 startAddr = (u16)pEfuseHal->fakeEfuseUsedBytes;
1348#else
1349 startAddr = (u16)fakeEfuseUsedBytes;
1350#endif
1351 } else
1352 rtw_hal_get_hwreg(padapter, variable: HW_VAR_EFUSE_BYTES, val: (u8 *)&startAddr);
1353 } else {
1354 if (bPseudoTest) {
1355#ifdef HAL_EFUSE_MEMORY
1356 startAddr = (u16)pEfuseHal->fakeBTEfuseUsedBytes;
1357#else
1358 startAddr = (u16)fakeBTEfuseUsedBytes;
1359#endif
1360 } else
1361 rtw_hal_get_hwreg(padapter, variable: HW_VAR_EFUSE_BT_BYTES, val: (u8 *)&startAddr);
1362 }
1363 startAddr %= efuse_max;
1364
1365 while (1) {
1366 if (startAddr >= efuse_max_available_len) {
1367 bRet = false;
1368 break;
1369 }
1370
1371 if (efuse_OneByteRead(padapter, addr: startAddr, data: &efuse_data, bPseudoTest) && (efuse_data != 0xFF)) {
1372#if 1
1373 bRet = false;
1374 break;
1375#else
1376 if (EXT_HEADER(efuse_data)) {
1377 cur_header = efuse_data;
1378 startAddr++;
1379 efuse_OneByteRead(padapter, startAddr, &efuse_data, bPseudoTest);
1380 if (ALL_WORDS_DISABLED(efuse_data)) {
1381 bRet = false;
1382 break;
1383 } else {
1384 curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
1385 curPkt.word_en = efuse_data & 0x0F;
1386 }
1387 } else {
1388 cur_header = efuse_data;
1389 curPkt.offset = (cur_header>>4) & 0x0F;
1390 curPkt.word_en = cur_header & 0x0F;
1391 }
1392
1393 curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en);
1394 /* if same header is found but no data followed */
1395 /* write some part of data followed by the header. */
1396 if (
1397 (curPkt.offset == pTargetPkt->offset) &&
1398 (hal_EfuseCheckIfDatafollowed(padapter, curPkt.word_cnts, startAddr+1, bPseudoTest) == false) &&
1399 wordEnMatched(pTargetPkt, &curPkt, &matched_wden) == true
1400 ) {
1401 /* Here to write partial data */
1402 badworden = Efuse_WordEnableDataWrite(padapter, startAddr+1, matched_wden, pTargetPkt->data, bPseudoTest);
1403 if (badworden != 0x0F) {
1404 u32 PgWriteSuccess = 0;
1405 /* if write fail on some words, write these bad words again */
1406 if (efuseType == EFUSE_WIFI)
1407 PgWriteSuccess = Efuse_PgPacketWrite(padapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest);
1408 else
1409 PgWriteSuccess = Efuse_PgPacketWrite_BT(padapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest);
1410
1411 if (!PgWriteSuccess) {
1412 bRet = false; /* write fail, return */
1413 break;
1414 }
1415 }
1416 /* partial write ok, update the target packet for later use */
1417 for (i = 0; i < 4; i++) {
1418 if ((matched_wden & (0x1<<i)) == 0) { /* this word has been written */
1419 pTargetPkt->word_en |= (0x1<<i); /* disable the word */
1420 }
1421 }
1422 pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
1423 }
1424 /* read from next header */
1425 startAddr = startAddr + (curPkt.word_cnts*2) + 1;
1426#endif
1427 } else {
1428 /* not used header, 0xff */
1429 *pAddr = startAddr;
1430 bRet = true;
1431 break;
1432 }
1433 }
1434
1435 return bRet;
1436}
1437
1438static u8 hal_EfusePgPacketWrite1ByteHeader(
1439 struct adapter *padapter,
1440 u8 efuseType,
1441 u16 *pAddr,
1442 struct pgpkt_struct *pTargetPkt,
1443 u8 bPseudoTest
1444)
1445{
1446 u8 pg_header = 0, tmp_header = 0;
1447 u16 efuse_addr = *pAddr;
1448 u8 repeatcnt = 0;
1449
1450 pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
1451
1452 do {
1453 efuse_OneByteWrite(padapter, addr: efuse_addr, data: pg_header, bPseudoTest);
1454 efuse_OneByteRead(padapter, addr: efuse_addr, data: &tmp_header, bPseudoTest);
1455 if (tmp_header != 0xFF)
1456 break;
1457 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
1458 return false;
1459
1460 } while (1);
1461
1462 if (tmp_header != pg_header)
1463 return false;
1464
1465 *pAddr = efuse_addr;
1466
1467 return true;
1468}
1469
1470static u8 hal_EfusePgPacketWrite2ByteHeader(
1471 struct adapter *padapter,
1472 u8 efuseType,
1473 u16 *pAddr,
1474 struct pgpkt_struct *pTargetPkt,
1475 u8 bPseudoTest
1476)
1477{
1478 u16 efuse_addr, efuse_max_available_len = 0;
1479 u8 pg_header = 0, tmp_header = 0;
1480 u8 repeatcnt = 0;
1481
1482 EFUSE_GetEfuseDefinition(padapter, efuseType, type: TYPE_AVAILABLE_EFUSE_BYTES_BANK, pOut: &efuse_max_available_len, bPseudoTest);
1483
1484 efuse_addr = *pAddr;
1485 if (efuse_addr >= efuse_max_available_len)
1486 return false;
1487
1488 pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
1489
1490 do {
1491 efuse_OneByteWrite(padapter, addr: efuse_addr, data: pg_header, bPseudoTest);
1492 efuse_OneByteRead(padapter, addr: efuse_addr, data: &tmp_header, bPseudoTest);
1493 if (tmp_header != 0xFF)
1494 break;
1495 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
1496 return false;
1497
1498 } while (1);
1499
1500 if (tmp_header != pg_header)
1501 return false;
1502
1503 /* to write ext_header */
1504 efuse_addr++;
1505 pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
1506
1507 do {
1508 efuse_OneByteWrite(padapter, addr: efuse_addr, data: pg_header, bPseudoTest);
1509 efuse_OneByteRead(padapter, addr: efuse_addr, data: &tmp_header, bPseudoTest);
1510 if (tmp_header != 0xFF)
1511 break;
1512 if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
1513 return false;
1514
1515 } while (1);
1516
1517 if (tmp_header != pg_header) /* offset PG fail */
1518 return false;
1519
1520 *pAddr = efuse_addr;
1521
1522 return true;
1523}
1524
1525static u8 hal_EfusePgPacketWriteHeader(
1526 struct adapter *padapter,
1527 u8 efuseType,
1528 u16 *pAddr,
1529 struct pgpkt_struct *pTargetPkt,
1530 u8 bPseudoTest
1531)
1532{
1533 u8 bRet = false;
1534
1535 if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE)
1536 bRet = hal_EfusePgPacketWrite2ByteHeader(padapter, efuseType, pAddr, pTargetPkt, bPseudoTest);
1537 else
1538 bRet = hal_EfusePgPacketWrite1ByteHeader(padapter, efuseType, pAddr, pTargetPkt, bPseudoTest);
1539
1540 return bRet;
1541}
1542
1543static u8 hal_EfusePgPacketWriteData(
1544 struct adapter *padapter,
1545 u8 efuseType,
1546 u16 *pAddr,
1547 struct pgpkt_struct *pTargetPkt,
1548 u8 bPseudoTest
1549)
1550{
1551 u16 efuse_addr;
1552 u8 badworden;
1553
1554
1555 efuse_addr = *pAddr;
1556 badworden = Efuse_WordEnableDataWrite(padapter, efuse_addr: efuse_addr+1, word_en: pTargetPkt->word_en, data: pTargetPkt->data, bPseudoTest);
1557 if (badworden != 0x0F)
1558 return false;
1559
1560 return true;
1561}
1562
1563static s32 Hal_EfusePgPacketWrite(
1564 struct adapter *padapter,
1565 u8 offset,
1566 u8 word_en,
1567 u8 *pData,
1568 bool bPseudoTest
1569)
1570{
1571 struct pgpkt_struct targetPkt;
1572 u16 startAddr = 0;
1573 u8 efuseType = EFUSE_WIFI;
1574
1575 if (!hal_EfusePgCheckAvailableAddr(padapter, efuseType, bPseudoTest))
1576 return false;
1577
1578 hal_EfuseConstructPGPkt(offset, word_en, pData, pTargetPkt: &targetPkt);
1579
1580 if (!hal_EfusePartialWriteCheck(padapter, efuseType, pAddr: &startAddr, pTargetPkt: &targetPkt, bPseudoTest))
1581 return false;
1582
1583 if (!hal_EfusePgPacketWriteHeader(padapter, efuseType, pAddr: &startAddr, pTargetPkt: &targetPkt, bPseudoTest))
1584 return false;
1585
1586 if (!hal_EfusePgPacketWriteData(padapter, efuseType, pAddr: &startAddr, pTargetPkt: &targetPkt, bPseudoTest))
1587 return false;
1588
1589 return true;
1590}
1591
1592static bool Hal_EfusePgPacketWrite_BT(
1593 struct adapter *padapter,
1594 u8 offset,
1595 u8 word_en,
1596 u8 *pData,
1597 bool bPseudoTest
1598)
1599{
1600 struct pgpkt_struct targetPkt;
1601 u16 startAddr = 0;
1602 u8 efuseType = EFUSE_BT;
1603
1604 if (!hal_EfusePgCheckAvailableAddr(padapter, efuseType, bPseudoTest))
1605 return false;
1606
1607 hal_EfuseConstructPGPkt(offset, word_en, pData, pTargetPkt: &targetPkt);
1608
1609 if (!hal_EfusePartialWriteCheck(padapter, efuseType, pAddr: &startAddr, pTargetPkt: &targetPkt, bPseudoTest))
1610 return false;
1611
1612 if (!hal_EfusePgPacketWriteHeader(padapter, efuseType, pAddr: &startAddr, pTargetPkt: &targetPkt, bPseudoTest))
1613 return false;
1614
1615 if (!hal_EfusePgPacketWriteData(padapter, efuseType, pAddr: &startAddr, pTargetPkt: &targetPkt, bPseudoTest))
1616 return false;
1617
1618 return true;
1619}
1620
1621static struct hal_version ReadChipVersion8723B(struct adapter *padapter)
1622{
1623 u32 value32;
1624 struct hal_version ChipVersion;
1625 struct hal_com_data *pHalData;
1626
1627/* YJ, TODO, move read chip type here */
1628 pHalData = GET_HAL_DATA(padapter);
1629
1630 value32 = rtw_read32(adapter: padapter, REG_SYS_CFG);
1631 ChipVersion.ICType = CHIP_8723B;
1632 ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
1633 ChipVersion.VendorType = ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC);
1634 ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK)>>CHIP_VER_RTL_SHIFT; /* IC version (CUT) */
1635
1636 /* For regulator mode. by tynli. 2011.01.14 */
1637 pHalData->RegulatorMode = ((value32 & SPS_SEL) ? RT_LDO_REGULATOR : RT_SWITCHING_REGULATOR);
1638
1639 value32 = rtw_read32(adapter: padapter, REG_GPIO_OUTSTS);
1640 ChipVersion.ROMVer = ((value32 & RF_RL_ID) >> 20); /* ROM code version. */
1641
1642 /* For multi-function consideration. Added by Roger, 2010.10.06. */
1643 pHalData->MultiFunc = RT_MULTI_FUNC_NONE;
1644 value32 = rtw_read32(adapter: padapter, REG_MULTI_FUNC_CTRL);
1645 pHalData->MultiFunc |= ((value32 & WL_FUNC_EN) ? RT_MULTI_FUNC_WIFI : 0);
1646 pHalData->MultiFunc |= ((value32 & BT_FUNC_EN) ? RT_MULTI_FUNC_BT : 0);
1647 pHalData->MultiFunc |= ((value32 & GPS_FUNC_EN) ? RT_MULTI_FUNC_GPS : 0);
1648 pHalData->PolarityCtl = ((value32 & WL_HWPDN_SL) ? RT_POLARITY_HIGH_ACT : RT_POLARITY_LOW_ACT);
1649#if 1
1650 dump_chip_info(ChipVersion);
1651#endif
1652 pHalData->VersionID = ChipVersion;
1653
1654 return ChipVersion;
1655}
1656
1657static void rtl8723b_read_chip_version(struct adapter *padapter)
1658{
1659 ReadChipVersion8723B(padapter);
1660}
1661
1662void rtl8723b_InitBeaconParameters(struct adapter *padapter)
1663{
1664 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1665 u16 val16;
1666 u8 val8;
1667
1668
1669 val8 = DIS_TSF_UDT;
1670 val16 = val8 | (val8 << 8); /* port0 and port1 */
1671
1672 /* Enable prot0 beacon function for PSTDMA */
1673 val16 |= EN_BCN_FUNCTION;
1674
1675 rtw_write16(adapter: padapter, REG_BCN_CTRL, val: val16);
1676
1677 /* TODO: Remove these magic number */
1678 rtw_write16(adapter: padapter, REG_TBTT_PROHIBIT, val: 0x6404);/* ms */
1679 /* Firmware will control REG_DRVERLYINT when power saving is enable, */
1680 /* so don't set this register on STA mode. */
1681 if (check_fwstate(pmlmepriv: &padapter->mlmepriv, WIFI_STATION_STATE) == false)
1682 rtw_write8(adapter: padapter, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME_8723B); /* 5ms */
1683 rtw_write8(adapter: padapter, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME_8723B); /* 2ms */
1684
1685 /* Suggested by designer timchen. Change beacon AIFS to the largest number */
1686 /* because test chip does not contension before sending beacon. by tynli. 2009.11.03 */
1687 rtw_write16(adapter: padapter, REG_BCNTCFG, val: 0x660F);
1688
1689 pHalData->RegBcnCtrlVal = rtw_read8(adapter: padapter, REG_BCN_CTRL);
1690 pHalData->RegTxPause = rtw_read8(adapter: padapter, REG_TXPAUSE);
1691 pHalData->RegFwHwTxQCtrl = rtw_read8(adapter: padapter, REG_FWHW_TXQ_CTRL+2);
1692 pHalData->RegReg542 = rtw_read8(adapter: padapter, REG_TBTT_PROHIBIT+2);
1693 pHalData->RegCR_1 = rtw_read8(adapter: padapter, REG_CR+1);
1694}
1695
1696void _InitBurstPktLen_8723BS(struct adapter *Adapter)
1697{
1698 struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
1699
1700 rtw_write8(adapter: Adapter, addr: 0x4c7, val: rtw_read8(adapter: Adapter, addr: 0x4c7)|BIT(7)); /* enable single pkt ampdu */
1701 rtw_write8(adapter: Adapter, REG_RX_PKT_LIMIT_8723B, val: 0x18); /* for VHT packet length 11K */
1702 rtw_write8(adapter: Adapter, REG_MAX_AGGR_NUM_8723B, val: 0x1F);
1703 rtw_write8(adapter: Adapter, REG_PIFS_8723B, val: 0x00);
1704 rtw_write8(adapter: Adapter, REG_FWHW_TXQ_CTRL_8723B, val: rtw_read8(adapter: Adapter, REG_FWHW_TXQ_CTRL)&(~BIT(7)));
1705 if (pHalData->AMPDUBurstMode)
1706 rtw_write8(adapter: Adapter, REG_AMPDU_BURST_MODE_8723B, val: 0x5F);
1707 rtw_write8(adapter: Adapter, REG_AMPDU_MAX_TIME_8723B, val: 0x70);
1708
1709 /* ARFB table 9 for 11ac 5G 2SS */
1710 rtw_write32(adapter: Adapter, REG_ARFR0_8723B, val: 0x00000010);
1711 if (IS_NORMAL_CHIP(pHalData->VersionID))
1712 rtw_write32(adapter: Adapter, REG_ARFR0_8723B+4, val: 0xfffff000);
1713 else
1714 rtw_write32(adapter: Adapter, REG_ARFR0_8723B+4, val: 0x3e0ff000);
1715
1716 /* ARFB table 10 for 11ac 5G 1SS */
1717 rtw_write32(adapter: Adapter, REG_ARFR1_8723B, val: 0x00000010);
1718 rtw_write32(adapter: Adapter, REG_ARFR1_8723B+4, val: 0x003ff000);
1719}
1720
1721static void ResumeTxBeacon(struct adapter *padapter)
1722{
1723 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1724
1725 pHalData->RegFwHwTxQCtrl |= BIT(6);
1726 rtw_write8(adapter: padapter, REG_FWHW_TXQ_CTRL+2, val: pHalData->RegFwHwTxQCtrl);
1727 rtw_write8(adapter: padapter, REG_TBTT_PROHIBIT+1, val: 0xff);
1728 pHalData->RegReg542 |= BIT(0);
1729 rtw_write8(adapter: padapter, REG_TBTT_PROHIBIT+2, val: pHalData->RegReg542);
1730}
1731
1732static void StopTxBeacon(struct adapter *padapter)
1733{
1734 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1735
1736 pHalData->RegFwHwTxQCtrl &= ~BIT(6);
1737 rtw_write8(adapter: padapter, REG_FWHW_TXQ_CTRL+2, val: pHalData->RegFwHwTxQCtrl);
1738 rtw_write8(adapter: padapter, REG_TBTT_PROHIBIT+1, val: 0x64);
1739 pHalData->RegReg542 &= ~BIT(0);
1740 rtw_write8(adapter: padapter, REG_TBTT_PROHIBIT+2, val: pHalData->RegReg542);
1741
1742 CheckFwRsvdPageContent(padapter); /* 2010.06.23. Added by tynli. */
1743}
1744
1745static void _BeaconFunctionEnable(struct adapter *padapter, u8 Enable, u8 Linked)
1746{
1747 rtw_write8(adapter: padapter, REG_BCN_CTRL, DIS_TSF_UDT | EN_BCN_FUNCTION | DIS_BCNQ_SUB);
1748 rtw_write8(adapter: padapter, REG_RD_CTRL+1, val: 0x6F);
1749}
1750
1751static void rtl8723b_SetBeaconRelatedRegisters(struct adapter *padapter)
1752{
1753 u8 val8;
1754 u32 value32;
1755 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1756 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
1757 u32 bcn_ctrl_reg;
1758
1759 /* reset TSF, enable update TSF, correcting TSF On Beacon */
1760
1761 /* REG_BCN_INTERVAL */
1762 /* REG_BCNDMATIM */
1763 /* REG_ATIMWND */
1764 /* REG_TBTT_PROHIBIT */
1765 /* REG_DRVERLYINT */
1766 /* REG_BCN_MAX_ERR */
1767 /* REG_BCNTCFG (0x510) */
1768 /* REG_DUAL_TSF_RST */
1769 /* REG_BCN_CTRL (0x550) */
1770
1771
1772 bcn_ctrl_reg = REG_BCN_CTRL;
1773
1774 /* */
1775 /* ATIM window */
1776 /* */
1777 rtw_write16(adapter: padapter, REG_ATIMWND, val: 2);
1778
1779 /* */
1780 /* Beacon interval (in unit of TU). */
1781 /* */
1782 rtw_write16(adapter: padapter, REG_BCN_INTERVAL, val: pmlmeinfo->bcn_interval);
1783
1784 rtl8723b_InitBeaconParameters(padapter);
1785
1786 rtw_write8(adapter: padapter, REG_SLOT, val: 0x09);
1787
1788 /* */
1789 /* Reset TSF Timer to zero, added by Roger. 2008.06.24 */
1790 /* */
1791 value32 = rtw_read32(adapter: padapter, REG_TCR);
1792 value32 &= ~TSFRST;
1793 rtw_write32(adapter: padapter, REG_TCR, val: value32);
1794
1795 value32 |= TSFRST;
1796 rtw_write32(adapter: padapter, REG_TCR, val: value32);
1797
1798 /* NOTE: Fix test chip's bug (about contention windows's randomness) */
1799 if (check_fwstate(pmlmepriv: &padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE) == true) {
1800 rtw_write8(adapter: padapter, REG_RXTSF_OFFSET_CCK, val: 0x50);
1801 rtw_write8(adapter: padapter, REG_RXTSF_OFFSET_OFDM, val: 0x50);
1802 }
1803
1804 _BeaconFunctionEnable(padapter, Enable: true, Linked: true);
1805
1806 ResumeTxBeacon(padapter);
1807 val8 = rtw_read8(adapter: padapter, addr: bcn_ctrl_reg);
1808 val8 |= DIS_BCNQ_SUB;
1809 rtw_write8(adapter: padapter, addr: bcn_ctrl_reg, val: val8);
1810}
1811
1812static void rtl8723b_GetHalODMVar(
1813 struct adapter *Adapter,
1814 enum hal_odm_variable eVariable,
1815 void *pValue1,
1816 void *pValue2
1817)
1818{
1819 GetHalODMVar(Adapter, eVariable, pValue1, pValue2);
1820}
1821
1822static void rtl8723b_SetHalODMVar(
1823 struct adapter *Adapter,
1824 enum hal_odm_variable eVariable,
1825 void *pValue1,
1826 bool bSet
1827)
1828{
1829 SetHalODMVar(Adapter, eVariable, pValue1, bSet);
1830}
1831
1832static void hal_notch_filter_8723b(struct adapter *adapter, bool enable)
1833{
1834 if (enable)
1835 rtw_write8(adapter, rOFDM0_RxDSP+1, val: rtw_read8(adapter, rOFDM0_RxDSP+1) | BIT1);
1836 else
1837 rtw_write8(adapter, rOFDM0_RxDSP+1, val: rtw_read8(adapter, rOFDM0_RxDSP+1) & ~BIT1);
1838}
1839
1840static void UpdateHalRAMask8723B(struct adapter *padapter, u32 mac_id, u8 rssi_level)
1841{
1842 u32 mask, rate_bitmap;
1843 u8 shortGIrate = false;
1844 struct sta_info *psta;
1845 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
1846 struct dm_priv *pdmpriv = &pHalData->dmpriv;
1847 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1848 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1849
1850 if (mac_id >= NUM_STA) /* CAM_SIZE */
1851 return;
1852
1853 psta = pmlmeinfo->FW_sta_info[mac_id].psta;
1854 if (!psta)
1855 return;
1856
1857 shortGIrate = query_ra_short_GI(psta);
1858
1859 mask = psta->ra_mask;
1860
1861 rate_bitmap = 0xffffffff;
1862 rate_bitmap = ODM_Get_Rate_Bitmap(pDM_Odm: &pHalData->odmpriv, macid: mac_id, ra_mask: mask, rssi_level);
1863
1864 mask &= rate_bitmap;
1865
1866 rate_bitmap = hal_btcoex_GetRaMask(padapter);
1867 mask &= ~rate_bitmap;
1868
1869 if (pHalData->fw_ractrl) {
1870 rtl8723b_set_FwMacIdConfig_cmd(padapter, mac_id, raid: psta->raid, bw: psta->bw_mode, sgi: shortGIrate, mask);
1871 }
1872
1873 /* set correct initial date rate for each mac_id */
1874 pdmpriv->INIDATA_RATE[mac_id] = psta->init_rate;
1875}
1876
1877
1878void rtl8723b_set_hal_ops(struct hal_ops *pHalFunc)
1879{
1880 pHalFunc->free_hal_data = &rtl8723b_free_hal_data;
1881
1882 pHalFunc->dm_init = &rtl8723b_init_dm_priv;
1883
1884 pHalFunc->read_chip_version = &rtl8723b_read_chip_version;
1885
1886 pHalFunc->UpdateRAMaskHandler = &UpdateHalRAMask8723B;
1887
1888 pHalFunc->set_bwmode_handler = &PHY_SetBWMode8723B;
1889 pHalFunc->set_channel_handler = &PHY_SwChnl8723B;
1890 pHalFunc->set_chnl_bw_handler = &PHY_SetSwChnlBWMode8723B;
1891
1892 pHalFunc->set_tx_power_level_handler = &PHY_SetTxPowerLevel8723B;
1893 pHalFunc->get_tx_power_level_handler = &PHY_GetTxPowerLevel8723B;
1894
1895 pHalFunc->hal_dm_watchdog = &rtl8723b_HalDmWatchDog;
1896 pHalFunc->hal_dm_watchdog_in_lps = &rtl8723b_HalDmWatchDog_in_LPS;
1897
1898
1899 pHalFunc->SetBeaconRelatedRegistersHandler = &rtl8723b_SetBeaconRelatedRegisters;
1900
1901 pHalFunc->Add_RateATid = &rtl8723b_Add_RateATid;
1902
1903 pHalFunc->run_thread = &rtl8723b_start_thread;
1904 pHalFunc->cancel_thread = &rtl8723b_stop_thread;
1905
1906 pHalFunc->read_bbreg = &PHY_QueryBBReg_8723B;
1907 pHalFunc->write_bbreg = &PHY_SetBBReg_8723B;
1908 pHalFunc->read_rfreg = &PHY_QueryRFReg_8723B;
1909 pHalFunc->write_rfreg = &PHY_SetRFReg_8723B;
1910
1911 /* Efuse related function */
1912 pHalFunc->BTEfusePowerSwitch = &Hal_BT_EfusePowerSwitch;
1913 pHalFunc->EfusePowerSwitch = &Hal_EfusePowerSwitch;
1914 pHalFunc->ReadEFuse = &Hal_ReadEFuse;
1915 pHalFunc->EFUSEGetEfuseDefinition = &Hal_GetEfuseDefinition;
1916 pHalFunc->EfuseGetCurrentSize = &Hal_EfuseGetCurrentSize;
1917 pHalFunc->Efuse_PgPacketRead = &Hal_EfusePgPacketRead;
1918 pHalFunc->Efuse_PgPacketWrite = &Hal_EfusePgPacketWrite;
1919 pHalFunc->Efuse_WordEnableDataWrite = &Hal_EfuseWordEnableDataWrite;
1920 pHalFunc->Efuse_PgPacketWrite_BT = &Hal_EfusePgPacketWrite_BT;
1921
1922 pHalFunc->GetHalODMVarHandler = &rtl8723b_GetHalODMVar;
1923 pHalFunc->SetHalODMVarHandler = &rtl8723b_SetHalODMVar;
1924
1925 pHalFunc->xmit_thread_handler = &hal_xmit_handler;
1926 pHalFunc->hal_notch_filter = &hal_notch_filter_8723b;
1927
1928 pHalFunc->c2h_handler = c2h_handler_8723b;
1929 pHalFunc->c2h_id_filter_ccx = c2h_id_filter_ccx_8723b;
1930
1931 pHalFunc->fill_h2c_cmd = &FillH2CCmd8723B;
1932}
1933
1934void rtl8723b_InitAntenna_Selection(struct adapter *padapter)
1935{
1936 u8 val;
1937
1938 val = rtw_read8(adapter: padapter, REG_LEDCFG2);
1939 /* Let 8051 take control antenna setting */
1940 val |= BIT(7); /* DPDT_SEL_EN, 0x4C[23] */
1941 rtw_write8(adapter: padapter, REG_LEDCFG2, val);
1942}
1943
1944void rtl8723b_init_default_value(struct adapter *padapter)
1945{
1946 struct hal_com_data *pHalData;
1947 struct dm_priv *pdmpriv;
1948 u8 i;
1949
1950
1951 pHalData = GET_HAL_DATA(padapter);
1952 pdmpriv = &pHalData->dmpriv;
1953
1954 padapter->registrypriv.wireless_mode = WIRELESS_11BG_24N;
1955
1956 /* init default value */
1957 pHalData->fw_ractrl = false;
1958 pHalData->bIQKInitialized = false;
1959 if (!adapter_to_pwrctl(padapter)->bkeepfwalive)
1960 pHalData->LastHMEBoxNum = 0;
1961
1962 pHalData->bIQKInitialized = false;
1963
1964 /* init dm default value */
1965 pdmpriv->TM_Trigger = 0;/* for IQK */
1966/* pdmpriv->binitialized = false; */
1967/* pdmpriv->prv_traffic_idx = 3; */
1968/* pdmpriv->initialize = 0; */
1969
1970 pdmpriv->ThermalValue_HP_index = 0;
1971 for (i = 0; i < HP_THERMAL_NUM; i++)
1972 pdmpriv->ThermalValue_HP[i] = 0;
1973
1974 /* init Efuse variables */
1975 pHalData->EfuseUsedBytes = 0;
1976 pHalData->EfuseUsedPercentage = 0;
1977#ifdef HAL_EFUSE_MEMORY
1978 pHalData->EfuseHal.fakeEfuseBank = 0;
1979 pHalData->EfuseHal.fakeEfuseUsedBytes = 0;
1980 memset(pHalData->EfuseHal.fakeEfuseContent, 0xFF, EFUSE_MAX_HW_SIZE);
1981 memset(pHalData->EfuseHal.fakeEfuseInitMap, 0xFF, EFUSE_MAX_MAP_LEN);
1982 memset(pHalData->EfuseHal.fakeEfuseModifiedMap, 0xFF, EFUSE_MAX_MAP_LEN);
1983 pHalData->EfuseHal.BTEfuseUsedBytes = 0;
1984 pHalData->EfuseHal.BTEfuseUsedPercentage = 0;
1985 memset(pHalData->EfuseHal.BTEfuseContent, 0xFF, EFUSE_MAX_BT_BANK*EFUSE_MAX_HW_SIZE);
1986 memset(pHalData->EfuseHal.BTEfuseInitMap, 0xFF, EFUSE_BT_MAX_MAP_LEN);
1987 memset(pHalData->EfuseHal.BTEfuseModifiedMap, 0xFF, EFUSE_BT_MAX_MAP_LEN);
1988 pHalData->EfuseHal.fakeBTEfuseUsedBytes = 0;
1989 memset(pHalData->EfuseHal.fakeBTEfuseContent, 0xFF, EFUSE_MAX_BT_BANK*EFUSE_MAX_HW_SIZE);
1990 memset(pHalData->EfuseHal.fakeBTEfuseInitMap, 0xFF, EFUSE_BT_MAX_MAP_LEN);
1991 memset(pHalData->EfuseHal.fakeBTEfuseModifiedMap, 0xFF, EFUSE_BT_MAX_MAP_LEN);
1992#endif
1993}
1994
1995u8 GetEEPROMSize8723B(struct adapter *padapter)
1996{
1997 u8 size = 0;
1998 u32 cr;
1999
2000 cr = rtw_read16(adapter: padapter, REG_9346CR);
2001 /* 6: EEPROM used is 93C46, 4: boot from E-Fuse. */
2002 size = (cr & BOOT_FROM_EEPROM) ? 6 : 4;
2003
2004 return size;
2005}
2006
2007/* */
2008/* */
2009/* LLT R/W/Init function */
2010/* */
2011/* */
2012s32 rtl8723b_InitLLTTable(struct adapter *padapter)
2013{
2014 unsigned long start, passing_time;
2015 u32 val32;
2016 s32 ret;
2017
2018
2019 ret = _FAIL;
2020
2021 val32 = rtw_read32(adapter: padapter, REG_AUTO_LLT);
2022 val32 |= BIT_AUTO_INIT_LLT;
2023 rtw_write32(adapter: padapter, REG_AUTO_LLT, val: val32);
2024
2025 start = jiffies;
2026
2027 do {
2028 val32 = rtw_read32(adapter: padapter, REG_AUTO_LLT);
2029 if (!(val32 & BIT_AUTO_INIT_LLT)) {
2030 ret = _SUCCESS;
2031 break;
2032 }
2033
2034 passing_time = jiffies_to_msecs(j: jiffies - start);
2035 if (passing_time > 1000)
2036 break;
2037
2038 msleep(msecs: 1);
2039 } while (1);
2040
2041 return ret;
2042}
2043
2044static void hal_get_chnl_group_8723b(u8 channel, u8 *group)
2045{
2046 if (1 <= channel && channel <= 2)
2047 *group = 0;
2048 else if (3 <= channel && channel <= 5)
2049 *group = 1;
2050 else if (6 <= channel && channel <= 8)
2051 *group = 2;
2052 else if (9 <= channel && channel <= 11)
2053 *group = 3;
2054 else if (12 <= channel && channel <= 14)
2055 *group = 4;
2056}
2057
2058void Hal_InitPGData(struct adapter *padapter, u8 *PROMContent)
2059{
2060 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
2061
2062 if (!pEEPROM->bautoload_fail_flag) { /* autoload OK. */
2063 if (!pEEPROM->EepromOrEfuse) {
2064 /* Read EFUSE real map to shadow. */
2065 EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI, bPseudoTest: false);
2066 memcpy((void *)PROMContent, (void *)pEEPROM->efuse_eeprom_data, HWSET_MAX_SIZE_8723B);
2067 }
2068 } else {/* autoload fail */
2069 if (!pEEPROM->EepromOrEfuse)
2070 EFUSE_ShadowMapUpdate(padapter, EFUSE_WIFI, bPseudoTest: false);
2071 memcpy((void *)PROMContent, (void *)pEEPROM->efuse_eeprom_data, HWSET_MAX_SIZE_8723B);
2072 }
2073}
2074
2075void Hal_EfuseParseIDCode(struct adapter *padapter, u8 *hwinfo)
2076{
2077 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
2078/* struct hal_com_data *pHalData = GET_HAL_DATA(padapter); */
2079 u16 EEPROMId;
2080
2081
2082 /* Check 0x8129 again for making sure autoload status!! */
2083 EEPROMId = le16_to_cpu(*((__le16 *)hwinfo));
2084 if (EEPROMId != RTL_EEPROM_ID) {
2085 pEEPROM->bautoload_fail_flag = true;
2086 } else
2087 pEEPROM->bautoload_fail_flag = false;
2088}
2089
2090static void Hal_ReadPowerValueFromPROM_8723B(
2091 struct adapter *Adapter,
2092 struct TxPowerInfo24G *pwrInfo24G,
2093 u8 *PROMContent,
2094 bool AutoLoadFail
2095)
2096{
2097 struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
2098 u32 rfPath, eeAddr = EEPROM_TX_PWR_INX_8723B, group, TxCount = 0;
2099
2100 memset(pwrInfo24G, 0, sizeof(struct TxPowerInfo24G));
2101
2102 if (0xFF == PROMContent[eeAddr+1])
2103 AutoLoadFail = true;
2104
2105 if (AutoLoadFail) {
2106 for (rfPath = 0; rfPath < MAX_RF_PATH; rfPath++) {
2107 /* 2.4G default value */
2108 for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
2109 pwrInfo24G->IndexCCK_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
2110 pwrInfo24G->IndexBW40_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
2111 }
2112
2113 for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
2114 if (TxCount == 0) {
2115 pwrInfo24G->BW20_Diff[rfPath][0] = EEPROM_DEFAULT_24G_HT20_DIFF;
2116 pwrInfo24G->OFDM_Diff[rfPath][0] = EEPROM_DEFAULT_24G_OFDM_DIFF;
2117 } else {
2118 pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
2119 pwrInfo24G->BW40_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
2120 pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
2121 pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
2122 }
2123 }
2124 }
2125
2126 return;
2127 }
2128
2129 pHalData->bTXPowerDataReadFromEEPORM = true; /* YJ, move, 120316 */
2130
2131 for (rfPath = 0; rfPath < MAX_RF_PATH; rfPath++) {
2132 /* 2 2.4G default value */
2133 for (group = 0; group < MAX_CHNL_GROUP_24G; group++) {
2134 pwrInfo24G->IndexCCK_Base[rfPath][group] = PROMContent[eeAddr++];
2135 if (pwrInfo24G->IndexCCK_Base[rfPath][group] == 0xFF)
2136 pwrInfo24G->IndexCCK_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
2137 }
2138
2139 for (group = 0; group < MAX_CHNL_GROUP_24G-1; group++) {
2140 pwrInfo24G->IndexBW40_Base[rfPath][group] = PROMContent[eeAddr++];
2141 if (pwrInfo24G->IndexBW40_Base[rfPath][group] == 0xFF)
2142 pwrInfo24G->IndexBW40_Base[rfPath][group] = EEPROM_DEFAULT_24G_INDEX;
2143 }
2144
2145 for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
2146 if (TxCount == 0) {
2147 pwrInfo24G->BW40_Diff[rfPath][TxCount] = 0;
2148 if (PROMContent[eeAddr] == 0xFF)
2149 pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_HT20_DIFF;
2150 else {
2151 pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
2152 if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
2153 pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
2154 }
2155
2156 if (PROMContent[eeAddr] == 0xFF)
2157 pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_24G_OFDM_DIFF;
2158 else {
2159 pwrInfo24G->OFDM_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0x0f);
2160 if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
2161 pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
2162 }
2163 pwrInfo24G->CCK_Diff[rfPath][TxCount] = 0;
2164 eeAddr++;
2165 } else {
2166 if (PROMContent[eeAddr] == 0xFF)
2167 pwrInfo24G->BW40_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
2168 else {
2169 pwrInfo24G->BW40_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
2170 if (pwrInfo24G->BW40_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
2171 pwrInfo24G->BW40_Diff[rfPath][TxCount] |= 0xF0;
2172 }
2173
2174 if (PROMContent[eeAddr] == 0xFF)
2175 pwrInfo24G->BW20_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
2176 else {
2177 pwrInfo24G->BW20_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0x0f);
2178 if (pwrInfo24G->BW20_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
2179 pwrInfo24G->BW20_Diff[rfPath][TxCount] |= 0xF0;
2180 }
2181 eeAddr++;
2182
2183 if (PROMContent[eeAddr] == 0xFF)
2184 pwrInfo24G->OFDM_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
2185 else {
2186 pwrInfo24G->OFDM_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0xf0)>>4;
2187 if (pwrInfo24G->OFDM_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
2188 pwrInfo24G->OFDM_Diff[rfPath][TxCount] |= 0xF0;
2189 }
2190
2191 if (PROMContent[eeAddr] == 0xFF)
2192 pwrInfo24G->CCK_Diff[rfPath][TxCount] = EEPROM_DEFAULT_DIFF;
2193 else {
2194 pwrInfo24G->CCK_Diff[rfPath][TxCount] = (PROMContent[eeAddr]&0x0f);
2195 if (pwrInfo24G->CCK_Diff[rfPath][TxCount] & BIT3) /* 4bit sign number to 8 bit sign number */
2196 pwrInfo24G->CCK_Diff[rfPath][TxCount] |= 0xF0;
2197 }
2198 eeAddr++;
2199 }
2200 }
2201 }
2202}
2203
2204
2205void Hal_EfuseParseTxPowerInfo_8723B(
2206 struct adapter *padapter, u8 *PROMContent, bool AutoLoadFail
2207)
2208{
2209 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
2210 struct TxPowerInfo24G pwrInfo24G;
2211 u8 rfPath, ch, TxCount = 1;
2212
2213 Hal_ReadPowerValueFromPROM_8723B(Adapter: padapter, pwrInfo24G: &pwrInfo24G, PROMContent, AutoLoadFail);
2214 for (rfPath = 0 ; rfPath < MAX_RF_PATH ; rfPath++) {
2215 for (ch = 0 ; ch < CHANNEL_MAX_NUMBER; ch++) {
2216 u8 group = 0;
2217
2218 hal_get_chnl_group_8723b(channel: ch + 1, group: &group);
2219
2220 if (ch == 14-1) {
2221 pHalData->Index24G_CCK_Base[rfPath][ch] = pwrInfo24G.IndexCCK_Base[rfPath][5];
2222 pHalData->Index24G_BW40_Base[rfPath][ch] = pwrInfo24G.IndexBW40_Base[rfPath][group];
2223 } else {
2224 pHalData->Index24G_CCK_Base[rfPath][ch] = pwrInfo24G.IndexCCK_Base[rfPath][group];
2225 pHalData->Index24G_BW40_Base[rfPath][ch] = pwrInfo24G.IndexBW40_Base[rfPath][group];
2226 }
2227 }
2228
2229 for (TxCount = 0; TxCount < MAX_TX_COUNT; TxCount++) {
2230 pHalData->CCK_24G_Diff[rfPath][TxCount] = pwrInfo24G.CCK_Diff[rfPath][TxCount];
2231 pHalData->OFDM_24G_Diff[rfPath][TxCount] = pwrInfo24G.OFDM_Diff[rfPath][TxCount];
2232 pHalData->BW20_24G_Diff[rfPath][TxCount] = pwrInfo24G.BW20_Diff[rfPath][TxCount];
2233 pHalData->BW40_24G_Diff[rfPath][TxCount] = pwrInfo24G.BW40_Diff[rfPath][TxCount];
2234 }
2235 }
2236
2237 /* 2010/10/19 MH Add Regulator recognize for CU. */
2238 if (!AutoLoadFail) {
2239 pHalData->EEPROMRegulatory = (PROMContent[EEPROM_RF_BOARD_OPTION_8723B]&0x7); /* bit0~2 */
2240 if (PROMContent[EEPROM_RF_BOARD_OPTION_8723B] == 0xFF)
2241 pHalData->EEPROMRegulatory = (EEPROM_DEFAULT_BOARD_OPTION&0x7); /* bit0~2 */
2242 } else
2243 pHalData->EEPROMRegulatory = 0;
2244}
2245
2246void Hal_EfuseParseBTCoexistInfo_8723B(
2247 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
2248)
2249{
2250 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
2251 u8 tempval;
2252 u32 tmpu4;
2253
2254 if (!AutoLoadFail) {
2255 tmpu4 = rtw_read32(adapter: padapter, REG_MULTI_FUNC_CTRL);
2256 if (tmpu4 & BT_FUNC_EN)
2257 pHalData->EEPROMBluetoothCoexist = true;
2258 else
2259 pHalData->EEPROMBluetoothCoexist = false;
2260
2261 pHalData->EEPROMBluetoothType = BT_RTL8723B;
2262
2263 tempval = hwinfo[EEPROM_RF_BT_SETTING_8723B];
2264 if (tempval != 0xFF) {
2265 pHalData->EEPROMBluetoothAntNum = tempval & BIT(0);
2266 /* EFUSE_0xC3[6] == 0, S1(Main)-RF_PATH_A; */
2267 /* EFUSE_0xC3[6] == 1, S0(Aux)-RF_PATH_B */
2268 if (tempval & BIT(6))
2269 pHalData->ant_path = RF_PATH_B;
2270 else
2271 pHalData->ant_path = RF_PATH_A;
2272 } else {
2273 pHalData->EEPROMBluetoothAntNum = Ant_x1;
2274 if (pHalData->PackageType == PACKAGE_QFN68)
2275 pHalData->ant_path = RF_PATH_B;
2276 else
2277 pHalData->ant_path = RF_PATH_A;
2278 }
2279 } else {
2280 pHalData->EEPROMBluetoothCoexist = false;
2281 pHalData->EEPROMBluetoothType = BT_RTL8723B;
2282 pHalData->EEPROMBluetoothAntNum = Ant_x1;
2283 pHalData->ant_path = RF_PATH_A;
2284 }
2285
2286 if (padapter->registrypriv.ant_num > 0) {
2287 switch (padapter->registrypriv.ant_num) {
2288 case 1:
2289 pHalData->EEPROMBluetoothAntNum = Ant_x1;
2290 break;
2291 case 2:
2292 pHalData->EEPROMBluetoothAntNum = Ant_x2;
2293 break;
2294 default:
2295 break;
2296 }
2297 }
2298
2299 hal_btcoex_SetBTCoexist(padapter, bBtExist: pHalData->EEPROMBluetoothCoexist);
2300 hal_btcoex_SetPgAntNum(padapter, antNum: pHalData->EEPROMBluetoothAntNum == Ant_x2 ? 2 : 1);
2301 if (pHalData->EEPROMBluetoothAntNum == Ant_x1)
2302 hal_btcoex_SetSingleAntPath(padapter, singleAntPath: pHalData->ant_path);
2303}
2304
2305void Hal_EfuseParseEEPROMVer_8723B(
2306 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
2307)
2308{
2309 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
2310
2311 if (!AutoLoadFail)
2312 pHalData->EEPROMVersion = hwinfo[EEPROM_VERSION_8723B];
2313 else
2314 pHalData->EEPROMVersion = 1;
2315}
2316
2317
2318
2319void Hal_EfuseParsePackageType_8723B(
2320 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
2321)
2322{
2323 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
2324 u8 package;
2325 u8 efuseContent;
2326
2327 Efuse_PowerSwitch(padapter, bWrite: false, PwrState: true);
2328 efuse_OneByteRead(padapter, addr: 0x1FB, data: &efuseContent, bPseudoTest: false);
2329 Efuse_PowerSwitch(padapter, bWrite: false, PwrState: false);
2330
2331 package = efuseContent & 0x7;
2332 switch (package) {
2333 case 0x4:
2334 pHalData->PackageType = PACKAGE_TFBGA79;
2335 break;
2336 case 0x5:
2337 pHalData->PackageType = PACKAGE_TFBGA90;
2338 break;
2339 case 0x6:
2340 pHalData->PackageType = PACKAGE_QFN68;
2341 break;
2342 case 0x7:
2343 pHalData->PackageType = PACKAGE_TFBGA80;
2344 break;
2345
2346 default:
2347 pHalData->PackageType = PACKAGE_DEFAULT;
2348 break;
2349 }
2350}
2351
2352
2353void Hal_EfuseParseVoltage_8723B(
2354 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
2355)
2356{
2357 struct eeprom_priv *pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
2358
2359 /* memcpy(pEEPROM->adjuseVoltageVal, &hwinfo[EEPROM_Voltage_ADDR_8723B], 1); */
2360 pEEPROM->adjuseVoltageVal = (hwinfo[EEPROM_Voltage_ADDR_8723B] & 0xf0) >> 4;
2361}
2362
2363void Hal_EfuseParseChnlPlan_8723B(
2364 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
2365)
2366{
2367 padapter->mlmepriv.ChannelPlan = hal_com_config_channel_plan(
2368 padapter,
2369 hw_channel_plan: hwinfo ? hwinfo[EEPROM_ChannelPlan_8723B] : 0xFF,
2370 sw_channel_plan: padapter->registrypriv.channel_plan,
2371 def_channel_plan: RT_CHANNEL_DOMAIN_WORLD_NULL,
2372 AutoLoadFail
2373 );
2374
2375 Hal_ChannelPlanToRegulation(Adapter: padapter, ChannelPlan: padapter->mlmepriv.ChannelPlan);
2376}
2377
2378void Hal_EfuseParseCustomerID_8723B(
2379 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
2380)
2381{
2382 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
2383
2384 if (!AutoLoadFail)
2385 pHalData->EEPROMCustomerID = hwinfo[EEPROM_CustomID_8723B];
2386 else
2387 pHalData->EEPROMCustomerID = 0;
2388}
2389
2390void Hal_EfuseParseAntennaDiversity_8723B(
2391 struct adapter *padapter,
2392 u8 *hwinfo,
2393 bool AutoLoadFail
2394)
2395{
2396}
2397
2398void Hal_EfuseParseXtal_8723B(
2399 struct adapter *padapter, u8 *hwinfo, bool AutoLoadFail
2400)
2401{
2402 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
2403
2404 if (!AutoLoadFail) {
2405 pHalData->CrystalCap = hwinfo[EEPROM_XTAL_8723B];
2406 if (pHalData->CrystalCap == 0xFF)
2407 pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723B; /* what value should 8812 set? */
2408 } else
2409 pHalData->CrystalCap = EEPROM_Default_CrystalCap_8723B;
2410}
2411
2412
2413void Hal_EfuseParseThermalMeter_8723B(
2414 struct adapter *padapter, u8 *PROMContent, u8 AutoLoadFail
2415)
2416{
2417 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
2418
2419 /* */
2420 /* ThermalMeter from EEPROM */
2421 /* */
2422 if (!AutoLoadFail)
2423 pHalData->EEPROMThermalMeter = PROMContent[EEPROM_THERMAL_METER_8723B];
2424 else
2425 pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_8723B;
2426
2427 if ((pHalData->EEPROMThermalMeter == 0xff) || AutoLoadFail) {
2428 pHalData->bAPKThermalMeterIgnore = true;
2429 pHalData->EEPROMThermalMeter = EEPROM_Default_ThermalMeter_8723B;
2430 }
2431}
2432
2433
2434void Hal_ReadRFGainOffset(
2435 struct adapter *Adapter, u8 *PROMContent, bool AutoloadFail
2436)
2437{
2438 /* */
2439 /* BB_RF Gain Offset from EEPROM */
2440 /* */
2441
2442 if (!AutoloadFail) {
2443 Adapter->eeprompriv.EEPROMRFGainOffset = PROMContent[EEPROM_RF_GAIN_OFFSET];
2444 Adapter->eeprompriv.EEPROMRFGainVal = EFUSE_Read1Byte(padapter: Adapter, EEPROM_RF_GAIN_VAL);
2445 } else {
2446 Adapter->eeprompriv.EEPROMRFGainOffset = 0;
2447 Adapter->eeprompriv.EEPROMRFGainVal = 0xFF;
2448 }
2449}
2450
2451u8 BWMapping_8723B(struct adapter *Adapter, struct pkt_attrib *pattrib)
2452{
2453 u8 BWSettingOfDesc = 0;
2454 struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
2455
2456 if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) {
2457 if (pattrib->bwmode == CHANNEL_WIDTH_40)
2458 BWSettingOfDesc = 1;
2459 else
2460 BWSettingOfDesc = 0;
2461 } else
2462 BWSettingOfDesc = 0;
2463
2464 /* if (pTcb->bBTTxPacket) */
2465 /* BWSettingOfDesc = 0; */
2466
2467 return BWSettingOfDesc;
2468}
2469
2470u8 SCMapping_8723B(struct adapter *Adapter, struct pkt_attrib *pattrib)
2471{
2472 u8 SCSettingOfDesc = 0;
2473 struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
2474
2475 if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_40) {
2476 if (pattrib->bwmode == CHANNEL_WIDTH_40) {
2477 SCSettingOfDesc = HT_DATA_SC_DONOT_CARE;
2478 } else if (pattrib->bwmode == CHANNEL_WIDTH_20) {
2479 if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_UPPER) {
2480 SCSettingOfDesc = HT_DATA_SC_20_UPPER_OF_40MHZ;
2481 } else if (pHalData->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) {
2482 SCSettingOfDesc = HT_DATA_SC_20_LOWER_OF_40MHZ;
2483 } else {
2484 SCSettingOfDesc = HT_DATA_SC_DONOT_CARE;
2485 }
2486 }
2487 } else {
2488 SCSettingOfDesc = HT_DATA_SC_DONOT_CARE;
2489 }
2490
2491 return SCSettingOfDesc;
2492}
2493
2494static void rtl8723b_cal_txdesc_chksum(struct tx_desc *ptxdesc)
2495{
2496 u16 *usPtr = (u16 *)ptxdesc;
2497 u32 count;
2498 u32 index;
2499 u16 checksum = 0;
2500
2501
2502 /* Clear first */
2503 ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
2504
2505 /* checksum is always calculated by first 32 bytes, */
2506 /* and it doesn't depend on TX DESC length. */
2507 /* Thomas, Lucas@SD4, 20130515 */
2508 count = 16;
2509
2510 for (index = 0; index < count; index++) {
2511 checksum |= le16_to_cpu(*(__le16 *)(usPtr + index));
2512 }
2513
2514 ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff);
2515}
2516
2517static u8 fill_txdesc_sectype(struct pkt_attrib *pattrib)
2518{
2519 u8 sectype = 0;
2520 if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
2521 switch (pattrib->encrypt) {
2522 /* SEC_TYPE */
2523 case _WEP40_:
2524 case _WEP104_:
2525 case _TKIP_:
2526 case _TKIP_WTMIC_:
2527 sectype = 1;
2528 break;
2529
2530 case _AES_:
2531 sectype = 3;
2532 break;
2533
2534 case _NO_PRIVACY_:
2535 default:
2536 break;
2537 }
2538 }
2539 return sectype;
2540}
2541
2542static void fill_txdesc_vcs_8723b(struct adapter *padapter, struct pkt_attrib *pattrib, struct txdesc_8723b *ptxdesc)
2543{
2544 if (pattrib->vcs_mode) {
2545 switch (pattrib->vcs_mode) {
2546 case RTS_CTS:
2547 ptxdesc->rtsen = 1;
2548 /* ENABLE HW RTS */
2549 ptxdesc->hw_rts_en = 1;
2550 break;
2551
2552 case CTS_TO_SELF:
2553 ptxdesc->cts2self = 1;
2554 break;
2555
2556 case NONE_VCS:
2557 default:
2558 break;
2559 }
2560
2561 ptxdesc->rtsrate = 8; /* RTS Rate =24M */
2562 ptxdesc->rts_ratefb_lmt = 0xF;
2563
2564 if (padapter->mlmeextpriv.mlmext_info.preamble_mode == PREAMBLE_SHORT)
2565 ptxdesc->rts_short = 1;
2566
2567 /* Set RTS BW */
2568 if (pattrib->ht_en)
2569 ptxdesc->rts_sc = SCMapping_8723B(Adapter: padapter, pattrib);
2570 }
2571}
2572
2573static void fill_txdesc_phy_8723b(struct adapter *padapter, struct pkt_attrib *pattrib, struct txdesc_8723b *ptxdesc)
2574{
2575 if (pattrib->ht_en) {
2576 ptxdesc->data_bw = BWMapping_8723B(Adapter: padapter, pattrib);
2577
2578 ptxdesc->data_sc = SCMapping_8723B(Adapter: padapter, pattrib);
2579 }
2580}
2581
2582static void rtl8723b_fill_default_txdesc(
2583 struct xmit_frame *pxmitframe, u8 *pbuf
2584)
2585{
2586 struct adapter *padapter;
2587 struct hal_com_data *pHalData;
2588 struct mlme_ext_priv *pmlmeext;
2589 struct mlme_ext_info *pmlmeinfo;
2590 struct pkt_attrib *pattrib;
2591 struct txdesc_8723b *ptxdesc;
2592 s32 bmcst;
2593
2594 memset(pbuf, 0, TXDESC_SIZE);
2595
2596 padapter = pxmitframe->padapter;
2597 pHalData = GET_HAL_DATA(padapter);
2598 pmlmeext = &padapter->mlmeextpriv;
2599 pmlmeinfo = &(pmlmeext->mlmext_info);
2600
2601 pattrib = &pxmitframe->attrib;
2602 bmcst = is_multicast_ether_addr(addr: pattrib->ra);
2603
2604 ptxdesc = (struct txdesc_8723b *)pbuf;
2605
2606 if (pxmitframe->frame_tag == DATA_FRAMETAG) {
2607 u8 drv_userate = 0;
2608
2609 ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
2610 ptxdesc->rate_id = pattrib->raid;
2611 ptxdesc->qsel = pattrib->qsel;
2612 ptxdesc->seq = pattrib->seqnum;
2613
2614 ptxdesc->sectype = fill_txdesc_sectype(pattrib);
2615 fill_txdesc_vcs_8723b(padapter, pattrib, ptxdesc);
2616
2617 if (pattrib->icmp_pkt == 1 && padapter->registrypriv.wifi_spec == 1)
2618 drv_userate = 1;
2619
2620 if (
2621 (pattrib->ether_type != 0x888e) &&
2622 (pattrib->ether_type != 0x0806) &&
2623 (pattrib->ether_type != 0x88B4) &&
2624 (pattrib->dhcp_pkt != 1) &&
2625 (drv_userate != 1)
2626 ) {
2627 /* Non EAP & ARP & DHCP type data packet */
2628
2629 if (pattrib->ampdu_en) {
2630 ptxdesc->agg_en = 1; /* AGG EN */
2631 ptxdesc->max_agg_num = 0x1f;
2632 ptxdesc->ampdu_density = pattrib->ampdu_spacing;
2633 } else
2634 ptxdesc->bk = 1; /* AGG BK */
2635
2636 fill_txdesc_phy_8723b(padapter, pattrib, ptxdesc);
2637
2638 ptxdesc->data_ratefb_lmt = 0x1F;
2639
2640 if (!pHalData->fw_ractrl) {
2641 ptxdesc->userate = 1;
2642
2643 if (pHalData->dmpriv.INIDATA_RATE[pattrib->mac_id] & BIT(7))
2644 ptxdesc->data_short = 1;
2645
2646 ptxdesc->datarate = pHalData->dmpriv.INIDATA_RATE[pattrib->mac_id] & 0x7F;
2647 }
2648
2649 if (padapter->fix_rate != 0xFF) { /* modify data rate by iwpriv */
2650 ptxdesc->userate = 1;
2651 if (padapter->fix_rate & BIT(7))
2652 ptxdesc->data_short = 1;
2653
2654 ptxdesc->datarate = (padapter->fix_rate & 0x7F);
2655 ptxdesc->disdatafb = 1;
2656 }
2657
2658 if (pattrib->ldpc)
2659 ptxdesc->data_ldpc = 1;
2660 if (pattrib->stbc)
2661 ptxdesc->data_stbc = 1;
2662 } else {
2663 /* EAP data packet and ARP packet. */
2664 /* Use the 1M data rate to send the EAP/ARP packet. */
2665 /* This will maybe make the handshake smooth. */
2666
2667 ptxdesc->bk = 1; /* AGG BK */
2668 ptxdesc->userate = 1; /* driver uses rate */
2669 if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
2670 ptxdesc->data_short = 1;/* DATA_SHORT */
2671 ptxdesc->datarate = MRateToHwRate(rate: pmlmeext->tx_rate);
2672 }
2673
2674 ptxdesc->usb_txagg_num = pxmitframe->agg_num;
2675 } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) {
2676 ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
2677 ptxdesc->qsel = pattrib->qsel;
2678 ptxdesc->rate_id = pattrib->raid; /* Rate ID */
2679 ptxdesc->seq = pattrib->seqnum;
2680 ptxdesc->userate = 1; /* driver uses rate, 1M */
2681
2682 ptxdesc->mbssid = pattrib->mbssid & 0xF;
2683
2684 ptxdesc->rty_lmt_en = 1; /* retry limit enable */
2685 if (pattrib->retry_ctrl) {
2686 ptxdesc->data_rt_lmt = 6;
2687 } else {
2688 ptxdesc->data_rt_lmt = 12;
2689 }
2690
2691 ptxdesc->datarate = MRateToHwRate(rate: pmlmeext->tx_rate);
2692
2693 /* CCX-TXRPT ack for xmit mgmt frames. */
2694 if (pxmitframe->ack_report) {
2695 ptxdesc->spe_rpt = 1;
2696 ptxdesc->sw_define = (u8)(GET_PRIMARY_ADAPTER(padapter)->xmitpriv.seq_no);
2697 }
2698 } else {
2699 ptxdesc->macid = pattrib->mac_id; /* CAM_ID(MAC_ID) */
2700 ptxdesc->rate_id = pattrib->raid; /* Rate ID */
2701 ptxdesc->qsel = pattrib->qsel;
2702 ptxdesc->seq = pattrib->seqnum;
2703 ptxdesc->userate = 1; /* driver uses rate */
2704 ptxdesc->datarate = MRateToHwRate(rate: pmlmeext->tx_rate);
2705 }
2706
2707 ptxdesc->pktlen = pattrib->last_txcmdsz;
2708 ptxdesc->offset = TXDESC_SIZE + OFFSET_SZ;
2709
2710 if (bmcst)
2711 ptxdesc->bmc = 1;
2712
2713 /* 2009.11.05. tynli_test. Suggested by SD4 Filen for FW LPS.
2714 * (1) The sequence number of each non-Qos frame / broadcast /
2715 * multicast / mgnt frame should be controlled by Hw because Fw
2716 * will also send null data which we cannot control when Fw LPS
2717 * enable.
2718 * --> default enable non-Qos data sequence number. 2010.06.23.
2719 * by tynli.
2720 * (2) Enable HW SEQ control for beacon packet, because we use
2721 * Hw beacon.
2722 * (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos
2723 * packets.
2724 * 2010.06.23. Added by tynli.
2725 */
2726 if (!pattrib->qos_en) /* Hw set sequence number */
2727 ptxdesc->en_hwseq = 1; /* HWSEQ_EN */
2728}
2729
2730/* Description:
2731 *
2732 * Parameters:
2733 * pxmitframe xmitframe
2734 * pbuf where to fill tx desc
2735 */
2736void rtl8723b_update_txdesc(struct xmit_frame *pxmitframe, u8 *pbuf)
2737{
2738 struct tx_desc *pdesc;
2739
2740 rtl8723b_fill_default_txdesc(pxmitframe, pbuf);
2741 pdesc = (struct tx_desc *)pbuf;
2742 rtl8723b_cal_txdesc_chksum(ptxdesc: pdesc);
2743}
2744
2745/* */
2746/* Description: In normal chip, we should send some packet to Hw which will be used by Fw */
2747/* in FW LPS mode. The function is to fill the Tx descriptor of this packets, then */
2748/* Fw can tell Hw to send these packet derectly. */
2749/* Added by tynli. 2009.10.15. */
2750/* */
2751/* type1:pspoll, type2:null */
2752void rtl8723b_fill_fake_txdesc(
2753 struct adapter *padapter,
2754 u8 *pDesc,
2755 u32 BufferLen,
2756 u8 IsPsPoll,
2757 u8 IsBTQosNull,
2758 u8 bDataFrame
2759)
2760{
2761 /* Clear all status */
2762 memset(pDesc, 0, TXDESC_SIZE);
2763
2764 SET_TX_DESC_FIRST_SEG_8723B(pDesc, 1); /* bFirstSeg; */
2765 SET_TX_DESC_LAST_SEG_8723B(pDesc, 1); /* bLastSeg; */
2766
2767 SET_TX_DESC_OFFSET_8723B(pDesc, 0x28); /* Offset = 32 */
2768
2769 SET_TX_DESC_PKT_SIZE_8723B(pDesc, BufferLen); /* Buffer size + command header */
2770 SET_TX_DESC_QUEUE_SEL_8723B(pDesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */
2771
2772 /* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error value by Hw. */
2773 if (IsPsPoll) {
2774 SET_TX_DESC_NAV_USE_HDR_8723B(pDesc, 1);
2775 } else {
2776 SET_TX_DESC_HWSEQ_EN_8723B(pDesc, 1); /* Hw set sequence number */
2777 SET_TX_DESC_HWSEQ_SEL_8723B(pDesc, 0);
2778 }
2779
2780 if (IsBTQosNull) {
2781 SET_TX_DESC_BT_INT_8723B(pDesc, 1);
2782 }
2783
2784 SET_TX_DESC_USE_RATE_8723B(pDesc, 1); /* use data rate which is set by Sw */
2785 SET_TX_DESC_OWN_8723B((u8 *)pDesc, 1);
2786
2787 SET_TX_DESC_TX_RATE_8723B(pDesc, DESC8723B_RATE1M);
2788
2789 /* */
2790 /* Encrypt the data frame if under security mode excepct null data. Suggested by CCW. */
2791 /* */
2792 if (bDataFrame) {
2793 u32 EncAlg;
2794
2795 EncAlg = padapter->securitypriv.dot11PrivacyAlgrthm;
2796 switch (EncAlg) {
2797 case _NO_PRIVACY_:
2798 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x0);
2799 break;
2800 case _WEP40_:
2801 case _WEP104_:
2802 case _TKIP_:
2803 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x1);
2804 break;
2805 case _SMS4_:
2806 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x2);
2807 break;
2808 case _AES_:
2809 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x3);
2810 break;
2811 default:
2812 SET_TX_DESC_SEC_TYPE_8723B(pDesc, 0x0);
2813 break;
2814 }
2815 }
2816
2817 /* USB interface drop packet if the checksum of descriptor isn't correct. */
2818 /* Using this checksum can let hardware recovery from packet bulk out error (e.g. Cancel URC, Bulk out error.). */
2819 rtl8723b_cal_txdesc_chksum(ptxdesc: (struct tx_desc *)pDesc);
2820}
2821
2822static void hw_var_set_opmode(struct adapter *padapter, u8 variable, u8 *val)
2823{
2824 u8 val8;
2825 u8 mode = *((u8 *)val);
2826
2827 {
2828 /* disable Port0 TSF update */
2829 val8 = rtw_read8(adapter: padapter, REG_BCN_CTRL);
2830 val8 |= DIS_TSF_UDT;
2831 rtw_write8(adapter: padapter, REG_BCN_CTRL, val: val8);
2832
2833 /* set net_type */
2834 Set_MSR(padapter, type: mode);
2835
2836 if ((mode == _HW_STATE_STATION_) || (mode == _HW_STATE_NOLINK_)) {
2837 {
2838 StopTxBeacon(padapter);
2839 }
2840
2841 /* disable atim wnd */
2842 rtw_write8(adapter: padapter, REG_BCN_CTRL, DIS_TSF_UDT|EN_BCN_FUNCTION|DIS_ATIM);
2843 /* rtw_write8(padapter, REG_BCN_CTRL, 0x18); */
2844 } else if (mode == _HW_STATE_ADHOC_) {
2845 ResumeTxBeacon(padapter);
2846 rtw_write8(adapter: padapter, REG_BCN_CTRL, DIS_TSF_UDT|EN_BCN_FUNCTION|DIS_BCNQ_SUB);
2847 } else if (mode == _HW_STATE_AP_) {
2848
2849 ResumeTxBeacon(padapter);
2850
2851 rtw_write8(adapter: padapter, REG_BCN_CTRL, DIS_TSF_UDT|DIS_BCNQ_SUB);
2852
2853 /* Set RCR */
2854 rtw_write32(adapter: padapter, REG_RCR, val: 0x7000208e);/* CBSSID_DATA must set to 0, reject ICV_ERR packet */
2855 /* enable to rx data frame */
2856 rtw_write16(adapter: padapter, REG_RXFLTMAP2, val: 0xFFFF);
2857 /* enable to rx ps-poll */
2858 rtw_write16(adapter: padapter, REG_RXFLTMAP1, val: 0x0400);
2859
2860 /* Beacon Control related register for first time */
2861 rtw_write8(adapter: padapter, REG_BCNDMATIM, val: 0x02); /* 2ms */
2862
2863 /* rtw_write8(padapter, REG_BCN_MAX_ERR, 0xFF); */
2864 rtw_write8(adapter: padapter, REG_ATIMWND, val: 0x0a); /* 10ms */
2865 rtw_write16(adapter: padapter, REG_BCNTCFG, val: 0x00);
2866 rtw_write16(adapter: padapter, REG_TBTT_PROHIBIT, val: 0xff04);
2867 rtw_write16(adapter: padapter, REG_TSFTR_SYN_OFFSET, val: 0x7fff);/* +32767 (~32ms) */
2868
2869 /* reset TSF */
2870 rtw_write8(adapter: padapter, REG_DUAL_TSF_RST, BIT(0));
2871
2872 /* enable BCN0 Function for if1 */
2873 /* don't enable update TSF0 for if1 (due to TSF update when beacon/probe rsp are received) */
2874 rtw_write8(adapter: padapter, REG_BCN_CTRL, val: (DIS_TSF_UDT|EN_BCN_FUNCTION|EN_TXBCN_RPT|DIS_BCNQ_SUB));
2875
2876 /* SW_BCN_SEL - Port0 */
2877 /* rtw_write8(Adapter, REG_DWBCN1_CTRL_8192E+2, rtw_read8(Adapter, REG_DWBCN1_CTRL_8192E+2) & ~BIT4); */
2878 rtw_hal_set_hwreg(padapter, variable: HW_VAR_DL_BCN_SEL, NULL);
2879
2880 /* select BCN on port 0 */
2881 rtw_write8(
2882 adapter: padapter,
2883 REG_CCK_CHECK_8723B,
2884 val: (rtw_read8(adapter: padapter, REG_CCK_CHECK_8723B)&~BIT_BCN_PORT_SEL)
2885 );
2886
2887 /* dis BCN1 ATIM WND if if2 is station */
2888 val8 = rtw_read8(adapter: padapter, REG_BCN_CTRL_1);
2889 val8 |= DIS_ATIM;
2890 rtw_write8(adapter: padapter, REG_BCN_CTRL_1, val: val8);
2891 }
2892 }
2893}
2894
2895static void hw_var_set_macaddr(struct adapter *padapter, u8 variable, u8 *val)
2896{
2897 u8 idx = 0;
2898 u32 reg_macid;
2899
2900 reg_macid = REG_MACID;
2901
2902 for (idx = 0 ; idx < 6; idx++)
2903 rtw_write8(GET_PRIMARY_ADAPTER(padapter), addr: (reg_macid+idx), val: val[idx]);
2904}
2905
2906static void hw_var_set_bssid(struct adapter *padapter, u8 variable, u8 *val)
2907{
2908 u8 idx = 0;
2909 u32 reg_bssid;
2910
2911 reg_bssid = REG_BSSID;
2912
2913 for (idx = 0 ; idx < 6; idx++)
2914 rtw_write8(adapter: padapter, addr: (reg_bssid+idx), val: val[idx]);
2915}
2916
2917static void hw_var_set_bcn_func(struct adapter *padapter, u8 variable, u8 *val)
2918{
2919 u32 bcn_ctrl_reg;
2920
2921 bcn_ctrl_reg = REG_BCN_CTRL;
2922
2923 if (*(u8 *)val)
2924 rtw_write8(adapter: padapter, addr: bcn_ctrl_reg, val: (EN_BCN_FUNCTION | EN_TXBCN_RPT));
2925 else {
2926 u8 val8;
2927 val8 = rtw_read8(adapter: padapter, addr: bcn_ctrl_reg);
2928 val8 &= ~(EN_BCN_FUNCTION | EN_TXBCN_RPT);
2929
2930 /* Always enable port0 beacon function for PSTDMA */
2931 if (REG_BCN_CTRL == bcn_ctrl_reg)
2932 val8 |= EN_BCN_FUNCTION;
2933
2934 rtw_write8(adapter: padapter, addr: bcn_ctrl_reg, val: val8);
2935 }
2936}
2937
2938static void hw_var_set_correct_tsf(struct adapter *padapter, u8 variable, u8 *val)
2939{
2940 u8 val8;
2941 u64 tsf;
2942 struct mlme_ext_priv *pmlmeext;
2943 struct mlme_ext_info *pmlmeinfo;
2944
2945
2946 pmlmeext = &padapter->mlmeextpriv;
2947 pmlmeinfo = &pmlmeext->mlmext_info;
2948
2949 tsf = pmlmeext->TSFValue-do_div(pmlmeext->TSFValue, (pmlmeinfo->bcn_interval*1024))-1024; /* us */
2950
2951 if (
2952 ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) ||
2953 ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
2954 )
2955 StopTxBeacon(padapter);
2956
2957 {
2958 /* disable related TSF function */
2959 val8 = rtw_read8(adapter: padapter, REG_BCN_CTRL);
2960 val8 &= ~EN_BCN_FUNCTION;
2961 rtw_write8(adapter: padapter, REG_BCN_CTRL, val: val8);
2962
2963 rtw_write32(adapter: padapter, REG_TSFTR, val: tsf);
2964 rtw_write32(adapter: padapter, REG_TSFTR+4, val: tsf>>32);
2965
2966 /* enable related TSF function */
2967 val8 = rtw_read8(adapter: padapter, REG_BCN_CTRL);
2968 val8 |= EN_BCN_FUNCTION;
2969 rtw_write8(adapter: padapter, REG_BCN_CTRL, val: val8);
2970 }
2971
2972 if (
2973 ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) ||
2974 ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
2975 )
2976 ResumeTxBeacon(padapter);
2977}
2978
2979static void hw_var_set_mlme_disconnect(struct adapter *padapter, u8 variable, u8 *val)
2980{
2981 u8 val8;
2982
2983 /* Set RCR to not to receive data frame when NO LINK state */
2984 /* rtw_write32(padapter, REG_RCR, rtw_read32(padapter, REG_RCR) & ~RCR_ADF); */
2985 /* reject all data frames */
2986 rtw_write16(adapter: padapter, REG_RXFLTMAP2, val: 0);
2987
2988 /* reset TSF */
2989 rtw_write8(adapter: padapter, REG_DUAL_TSF_RST, BIT(0));
2990
2991 /* disable update TSF */
2992 val8 = rtw_read8(adapter: padapter, REG_BCN_CTRL);
2993 val8 |= DIS_TSF_UDT;
2994 rtw_write8(adapter: padapter, REG_BCN_CTRL, val: val8);
2995}
2996
2997static void hw_var_set_mlme_sitesurvey(struct adapter *padapter, u8 variable, u8 *val)
2998{
2999 u32 value_rcr, rcr_clear_bit, reg_bcn_ctl;
3000 u16 value_rxfltmap2;
3001 u8 val8;
3002 struct hal_com_data *pHalData;
3003 struct mlme_priv *pmlmepriv;
3004
3005
3006 pHalData = GET_HAL_DATA(padapter);
3007 pmlmepriv = &padapter->mlmepriv;
3008
3009 reg_bcn_ctl = REG_BCN_CTRL;
3010
3011 rcr_clear_bit = RCR_CBSSID_BCN;
3012
3013 /* config RCR to receive different BSSID & not to receive data frame */
3014 value_rxfltmap2 = 0;
3015
3016 if ((check_fwstate(pmlmepriv, WIFI_AP_STATE) == true))
3017 rcr_clear_bit = RCR_CBSSID_BCN;
3018
3019 value_rcr = rtw_read32(adapter: padapter, REG_RCR);
3020
3021 if (*((u8 *)val)) {
3022 /* under sitesurvey */
3023 value_rcr &= ~(rcr_clear_bit);
3024 rtw_write32(adapter: padapter, REG_RCR, val: value_rcr);
3025
3026 rtw_write16(adapter: padapter, REG_RXFLTMAP2, val: value_rxfltmap2);
3027
3028 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) {
3029 /* disable update TSF */
3030 val8 = rtw_read8(adapter: padapter, addr: reg_bcn_ctl);
3031 val8 |= DIS_TSF_UDT;
3032 rtw_write8(adapter: padapter, addr: reg_bcn_ctl, val: val8);
3033 }
3034
3035 /* Save original RRSR setting. */
3036 pHalData->RegRRSR = rtw_read16(adapter: padapter, REG_RRSR);
3037 } else {
3038 /* sitesurvey done */
3039 if (check_fwstate(pmlmepriv, state: (_FW_LINKED|WIFI_AP_STATE)))
3040 /* enable to rx data frame */
3041 rtw_write16(adapter: padapter, REG_RXFLTMAP2, val: 0xFFFF);
3042
3043 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) {
3044 /* enable update TSF */
3045 val8 = rtw_read8(adapter: padapter, addr: reg_bcn_ctl);
3046 val8 &= ~DIS_TSF_UDT;
3047 rtw_write8(adapter: padapter, addr: reg_bcn_ctl, val: val8);
3048 }
3049
3050 value_rcr |= rcr_clear_bit;
3051 rtw_write32(adapter: padapter, REG_RCR, val: value_rcr);
3052
3053 /* Restore original RRSR setting. */
3054 rtw_write16(adapter: padapter, REG_RRSR, val: pHalData->RegRRSR);
3055 }
3056}
3057
3058static void hw_var_set_mlme_join(struct adapter *padapter, u8 variable, u8 *val)
3059{
3060 u8 val8;
3061 u16 val16;
3062 u32 val32;
3063 u8 RetryLimit;
3064 u8 type;
3065 struct mlme_priv *pmlmepriv;
3066 struct eeprom_priv *pEEPROM;
3067
3068
3069 RetryLimit = 0x30;
3070 type = *(u8 *)val;
3071 pmlmepriv = &padapter->mlmepriv;
3072 pEEPROM = GET_EEPROM_EFUSE_PRIV(padapter);
3073
3074 if (type == 0) { /* prepare to join */
3075 /* enable to rx data frame.Accept all data frame */
3076 /* rtw_write32(padapter, REG_RCR, rtw_read32(padapter, REG_RCR)|RCR_ADF); */
3077 rtw_write16(adapter: padapter, REG_RXFLTMAP2, val: 0xFFFF);
3078
3079 val32 = rtw_read32(adapter: padapter, REG_RCR);
3080 if (padapter->in_cta_test)
3081 val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);/* RCR_ADF */
3082 else
3083 val32 |= RCR_CBSSID_DATA|RCR_CBSSID_BCN;
3084 rtw_write32(adapter: padapter, REG_RCR, val: val32);
3085
3086 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
3087 RetryLimit = (pEEPROM->CustomerID == RT_CID_CCX) ? 7 : 48;
3088 else /* Ad-hoc Mode */
3089 RetryLimit = 0x7;
3090 } else if (type == 1) /* joinbss_event call back when join res < 0 */
3091 rtw_write16(adapter: padapter, REG_RXFLTMAP2, val: 0x00);
3092 else if (type == 2) { /* sta add event call back */
3093 /* enable update TSF */
3094 val8 = rtw_read8(adapter: padapter, REG_BCN_CTRL);
3095 val8 &= ~DIS_TSF_UDT;
3096 rtw_write8(adapter: padapter, REG_BCN_CTRL, val: val8);
3097
3098 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE))
3099 RetryLimit = 0x7;
3100 }
3101
3102 val16 = (RetryLimit << RETRY_LIMIT_SHORT_SHIFT) | (RetryLimit << RETRY_LIMIT_LONG_SHIFT);
3103 rtw_write16(adapter: padapter, REG_RL, val: val16);
3104}
3105
3106void CCX_FwC2HTxRpt_8723b(struct adapter *padapter, u8 *pdata, u8 len)
3107{
3108
3109#define GET_8723B_C2H_TX_RPT_LIFE_TIME_OVER(_Header) LE_BITS_TO_1BYTE((_Header + 0), 6, 1)
3110#define GET_8723B_C2H_TX_RPT_RETRY_OVER(_Header) LE_BITS_TO_1BYTE((_Header + 0), 7, 1)
3111
3112 if (GET_8723B_C2H_TX_RPT_RETRY_OVER(pdata) | GET_8723B_C2H_TX_RPT_LIFE_TIME_OVER(pdata)) {
3113 rtw_ack_tx_done(pxmitpriv: &padapter->xmitpriv, status: RTW_SCTX_DONE_CCX_PKT_FAIL);
3114 }
3115/*
3116 else if (seq_no != padapter->xmitpriv.seq_no) {
3117 rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_CCX_PKT_FAIL);
3118 }
3119*/
3120 else
3121 rtw_ack_tx_done(pxmitpriv: &padapter->xmitpriv, status: RTW_SCTX_DONE_SUCCESS);
3122}
3123
3124s32 c2h_id_filter_ccx_8723b(u8 *buf)
3125{
3126 struct c2h_evt_hdr_88xx *c2h_evt = (struct c2h_evt_hdr_88xx *)buf;
3127 s32 ret = false;
3128 if (c2h_evt->id == C2H_CCX_TX_RPT)
3129 ret = true;
3130
3131 return ret;
3132}
3133
3134
3135s32 c2h_handler_8723b(struct adapter *padapter, u8 *buf)
3136{
3137 struct c2h_evt_hdr_88xx *pC2hEvent = (struct c2h_evt_hdr_88xx *)buf;
3138 s32 ret = _SUCCESS;
3139
3140 if (!pC2hEvent) {
3141 ret = _FAIL;
3142 goto exit;
3143 }
3144
3145 switch (pC2hEvent->id) {
3146 case C2H_AP_RPT_RSP:
3147 break;
3148 case C2H_DBG:
3149 {
3150 }
3151 break;
3152
3153 case C2H_CCX_TX_RPT:
3154/* CCX_FwC2HTxRpt(padapter, QueueID, pC2hEvent->payload); */
3155 break;
3156
3157 case C2H_EXT_RA_RPT:
3158/* C2HExtRaRptHandler(padapter, pC2hEvent->payload, C2hEvent.CmdLen); */
3159 break;
3160
3161 case C2H_HW_INFO_EXCH:
3162 break;
3163
3164 case C2H_8723B_BT_INFO:
3165 hal_btcoex_BtInfoNotify(padapter, length: pC2hEvent->plen, tmpBuf: pC2hEvent->payload);
3166 break;
3167
3168 default:
3169 break;
3170 }
3171
3172 /* Clear event to notify FW we have read the command. */
3173 /* Note: */
3174 /* If this field isn't clear, the FW won't update the next command message. */
3175/* rtw_write8(padapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE); */
3176exit:
3177 return ret;
3178}
3179
3180static void process_c2h_event(struct adapter *padapter, struct c2h_evt_hdr_t *pC2hEvent, u8 *c2hBuf)
3181{
3182 if (!c2hBuf)
3183 return;
3184
3185 switch (pC2hEvent->CmdID) {
3186 case C2H_AP_RPT_RSP:
3187 break;
3188 case C2H_DBG:
3189 {
3190 }
3191 break;
3192
3193 case C2H_CCX_TX_RPT:
3194/* CCX_FwC2HTxRpt(padapter, QueueID, tmpBuf); */
3195 break;
3196
3197 case C2H_EXT_RA_RPT:
3198/* C2HExtRaRptHandler(padapter, tmpBuf, C2hEvent.CmdLen); */
3199 break;
3200
3201 case C2H_HW_INFO_EXCH:
3202 break;
3203
3204 case C2H_8723B_BT_INFO:
3205 hal_btcoex_BtInfoNotify(padapter, length: pC2hEvent->CmdLen, tmpBuf: c2hBuf);
3206 break;
3207
3208 default:
3209 break;
3210 }
3211}
3212
3213void C2HPacketHandler_8723B(struct adapter *padapter, u8 *pbuffer, u16 length)
3214{
3215 struct c2h_evt_hdr_t C2hEvent;
3216 u8 *tmpBuf = NULL;
3217 C2hEvent.CmdID = pbuffer[0];
3218 C2hEvent.CmdSeq = pbuffer[1];
3219 C2hEvent.CmdLen = length-2;
3220 tmpBuf = pbuffer+2;
3221
3222 process_c2h_event(padapter, pC2hEvent: &C2hEvent, c2hBuf: tmpBuf);
3223 /* c2h_handler_8723b(padapter,&C2hEvent); */
3224}
3225
3226void SetHwReg8723B(struct adapter *padapter, u8 variable, u8 *val)
3227{
3228 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
3229 u8 val8;
3230 u32 val32;
3231
3232 switch (variable) {
3233 case HW_VAR_MEDIA_STATUS:
3234 val8 = rtw_read8(adapter: padapter, MSR) & 0x0c;
3235 val8 |= *val;
3236 rtw_write8(adapter: padapter, MSR, val: val8);
3237 break;
3238
3239 case HW_VAR_MEDIA_STATUS1:
3240 val8 = rtw_read8(adapter: padapter, MSR) & 0x03;
3241 val8 |= *val << 2;
3242 rtw_write8(adapter: padapter, MSR, val: val8);
3243 break;
3244
3245 case HW_VAR_SET_OPMODE:
3246 hw_var_set_opmode(padapter, variable, val);
3247 break;
3248
3249 case HW_VAR_MAC_ADDR:
3250 hw_var_set_macaddr(padapter, variable, val);
3251 break;
3252
3253 case HW_VAR_BSSID:
3254 hw_var_set_bssid(padapter, variable, val);
3255 break;
3256
3257 case HW_VAR_BASIC_RATE:
3258 {
3259 struct mlme_ext_info *mlmext_info = &padapter->mlmeextpriv.mlmext_info;
3260 u16 BrateCfg = 0;
3261 u16 rrsr_2g_force_mask = (RRSR_11M|RRSR_5_5M|RRSR_1M);
3262 u16 rrsr_2g_allow_mask = (RRSR_24M|RRSR_12M|RRSR_6M|RRSR_CCK_RATES);
3263
3264 HalSetBrateCfg(Adapter: padapter, mBratesOS: val, pBrateCfg: &BrateCfg);
3265
3266 /* apply force and allow mask */
3267 BrateCfg |= rrsr_2g_force_mask;
3268 BrateCfg &= rrsr_2g_allow_mask;
3269
3270 /* IOT consideration */
3271 if (mlmext_info->assoc_AP_vendor == HT_IOT_PEER_CISCO) {
3272 /* if peer is cisco and didn't use ofdm rate, we enable 6M ack */
3273 if ((BrateCfg & (RRSR_24M|RRSR_12M|RRSR_6M)) == 0)
3274 BrateCfg |= RRSR_6M;
3275 }
3276
3277 pHalData->BasicRateSet = BrateCfg;
3278
3279 /* Set RRSR rate table. */
3280 rtw_write16(adapter: padapter, REG_RRSR, val: BrateCfg);
3281 rtw_write8(adapter: padapter, REG_RRSR+2, val: rtw_read8(adapter: padapter, REG_RRSR+2)&0xf0);
3282 }
3283 break;
3284
3285 case HW_VAR_TXPAUSE:
3286 rtw_write8(adapter: padapter, REG_TXPAUSE, val: *val);
3287 break;
3288
3289 case HW_VAR_BCN_FUNC:
3290 hw_var_set_bcn_func(padapter, variable, val);
3291 break;
3292
3293 case HW_VAR_CORRECT_TSF:
3294 hw_var_set_correct_tsf(padapter, variable, val);
3295 break;
3296
3297 case HW_VAR_CHECK_BSSID:
3298 {
3299 u32 val32;
3300 val32 = rtw_read32(adapter: padapter, REG_RCR);
3301 if (*val)
3302 val32 |= RCR_CBSSID_DATA|RCR_CBSSID_BCN;
3303 else
3304 val32 &= ~(RCR_CBSSID_DATA|RCR_CBSSID_BCN);
3305 rtw_write32(adapter: padapter, REG_RCR, val: val32);
3306 }
3307 break;
3308
3309 case HW_VAR_MLME_DISCONNECT:
3310 hw_var_set_mlme_disconnect(padapter, variable, val);
3311 break;
3312
3313 case HW_VAR_MLME_SITESURVEY:
3314 hw_var_set_mlme_sitesurvey(padapter, variable, val);
3315
3316 hal_btcoex_ScanNotify(padapter, type: *val?true:false);
3317 break;
3318
3319 case HW_VAR_MLME_JOIN:
3320 hw_var_set_mlme_join(padapter, variable, val);
3321
3322 switch (*val) {
3323 case 0:
3324 /* prepare to join */
3325 hal_btcoex_ConnectNotify(padapter, action: true);
3326 break;
3327 case 1:
3328 /* joinbss_event callback when join res < 0 */
3329 hal_btcoex_ConnectNotify(padapter, action: false);
3330 break;
3331 case 2:
3332 /* sta add event callback */
3333/* rtw_btcoex_MediaStatusNotify(padapter, RT_MEDIA_CONNECT); */
3334 break;
3335 }
3336 break;
3337
3338 case HW_VAR_ON_RCR_AM:
3339 val32 = rtw_read32(adapter: padapter, REG_RCR);
3340 val32 |= RCR_AM;
3341 rtw_write32(adapter: padapter, REG_RCR, val: val32);
3342 break;
3343
3344 case HW_VAR_OFF_RCR_AM:
3345 val32 = rtw_read32(adapter: padapter, REG_RCR);
3346 val32 &= ~RCR_AM;
3347 rtw_write32(adapter: padapter, REG_RCR, val: val32);
3348 break;
3349
3350 case HW_VAR_BEACON_INTERVAL:
3351 rtw_write16(adapter: padapter, REG_BCN_INTERVAL, val: *((u16 *)val));
3352 break;
3353
3354 case HW_VAR_SLOT_TIME:
3355 rtw_write8(adapter: padapter, REG_SLOT, val: *val);
3356 break;
3357
3358 case HW_VAR_RESP_SIFS:
3359 /* SIFS_Timer = 0x0a0a0808; */
3360 /* RESP_SIFS for CCK */
3361 rtw_write8(adapter: padapter, REG_RESP_SIFS_CCK, val: val[0]); /* SIFS_T2T_CCK (0x08) */
3362 rtw_write8(adapter: padapter, REG_RESP_SIFS_CCK+1, val: val[1]); /* SIFS_R2T_CCK(0x08) */
3363 /* RESP_SIFS for OFDM */
3364 rtw_write8(adapter: padapter, REG_RESP_SIFS_OFDM, val: val[2]); /* SIFS_T2T_OFDM (0x0a) */
3365 rtw_write8(adapter: padapter, REG_RESP_SIFS_OFDM+1, val: val[3]); /* SIFS_R2T_OFDM(0x0a) */
3366 break;
3367
3368 case HW_VAR_ACK_PREAMBLE:
3369 {
3370 u8 regTmp;
3371 u8 bShortPreamble = *val;
3372
3373 /* Joseph marked out for Netgear 3500 TKIP channel 7 issue.(Temporarily) */
3374 /* regTmp = (pHalData->nCur40MhzPrimeSC)<<5; */
3375 regTmp = 0;
3376 if (bShortPreamble)
3377 regTmp |= 0x80;
3378 rtw_write8(adapter: padapter, REG_RRSR+2, val: regTmp);
3379 }
3380 break;
3381
3382 case HW_VAR_CAM_EMPTY_ENTRY:
3383 {
3384 u8 ucIndex = *val;
3385 u8 i;
3386 u32 ulCommand = 0;
3387 u32 ulContent = 0;
3388 u32 ulEncAlgo = CAM_AES;
3389
3390 for (i = 0; i < CAM_CONTENT_COUNT; i++) {
3391 /* filled id in CAM config 2 byte */
3392 if (i == 0) {
3393 ulContent |= (ucIndex & 0x03) | ((u16)(ulEncAlgo)<<2);
3394 /* ulContent |= CAM_VALID; */
3395 } else
3396 ulContent = 0;
3397
3398 /* polling bit, and No Write enable, and address */
3399 ulCommand = CAM_CONTENT_COUNT*ucIndex+i;
3400 ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE;
3401 /* write content 0 is equal to mark as invalid */
3402 rtw_write32(adapter: padapter, WCAMI, val: ulContent); /* mdelay(40); */
3403 rtw_write32(adapter: padapter, RWCAM, val: ulCommand); /* mdelay(40); */
3404 }
3405 }
3406 break;
3407
3408 case HW_VAR_CAM_INVALID_ALL:
3409 rtw_write32(adapter: padapter, RWCAM, BIT(31)|BIT(30));
3410 break;
3411
3412 case HW_VAR_CAM_WRITE:
3413 {
3414 u32 cmd;
3415 u32 *cam_val = (u32 *)val;
3416
3417 rtw_write32(adapter: padapter, WCAMI, val: cam_val[0]);
3418
3419 cmd = CAM_POLLINIG | CAM_WRITE | cam_val[1];
3420 rtw_write32(adapter: padapter, RWCAM, val: cmd);
3421 }
3422 break;
3423
3424 case HW_VAR_AC_PARAM_VO:
3425 rtw_write32(adapter: padapter, REG_EDCA_VO_PARAM, val: *((u32 *)val));
3426 break;
3427
3428 case HW_VAR_AC_PARAM_VI:
3429 rtw_write32(adapter: padapter, REG_EDCA_VI_PARAM, val: *((u32 *)val));
3430 break;
3431
3432 case HW_VAR_AC_PARAM_BE:
3433 pHalData->AcParam_BE = ((u32 *)(val))[0];
3434 rtw_write32(adapter: padapter, REG_EDCA_BE_PARAM, val: *((u32 *)val));
3435 break;
3436
3437 case HW_VAR_AC_PARAM_BK:
3438 rtw_write32(adapter: padapter, REG_EDCA_BK_PARAM, val: *((u32 *)val));
3439 break;
3440
3441 case HW_VAR_ACM_CTRL:
3442 {
3443 u8 ctrl = *((u8 *)val);
3444 u8 hwctrl = 0;
3445
3446 if (ctrl != 0) {
3447 hwctrl |= AcmHw_HwEn;
3448
3449 if (ctrl & BIT(1)) /* BE */
3450 hwctrl |= AcmHw_BeqEn;
3451
3452 if (ctrl & BIT(2)) /* VI */
3453 hwctrl |= AcmHw_ViqEn;
3454
3455 if (ctrl & BIT(3)) /* VO */
3456 hwctrl |= AcmHw_VoqEn;
3457 }
3458
3459 rtw_write8(adapter: padapter, REG_ACMHWCTRL, val: hwctrl);
3460 }
3461 break;
3462
3463 case HW_VAR_AMPDU_FACTOR:
3464 {
3465 u32 AMPDULen = (*((u8 *)val));
3466
3467 if (AMPDULen < HT_AGG_SIZE_32K)
3468 AMPDULen = (0x2000 << (*((u8 *)val)))-1;
3469 else
3470 AMPDULen = 0x7fff;
3471
3472 rtw_write32(adapter: padapter, REG_AMPDU_MAX_LENGTH_8723B, val: AMPDULen);
3473 }
3474 break;
3475
3476 case HW_VAR_H2C_FW_PWRMODE:
3477 {
3478 u8 psmode = *val;
3479
3480 /* Forece leave RF low power mode for 1T1R to prevent conficting setting in Fw power */
3481 /* saving sequence. 2010.06.07. Added by tynli. Suggested by SD3 yschang. */
3482 if (psmode != PS_MODE_ACTIVE) {
3483 ODM_RF_Saving(pDM_VOID: &pHalData->odmpriv, bForceInNormal: true);
3484 }
3485
3486 /* if (psmode != PS_MODE_ACTIVE) { */
3487 /* rtl8723b_set_lowpwr_lps_cmd(padapter, true); */
3488 /* else { */
3489 /* rtl8723b_set_lowpwr_lps_cmd(padapter, false); */
3490 /* */
3491 rtl8723b_set_FwPwrMode_cmd(padapter, Mode: psmode);
3492 }
3493 break;
3494 case HW_VAR_H2C_PS_TUNE_PARAM:
3495 rtl8723b_set_FwPsTuneParam_cmd(padapter);
3496 break;
3497
3498 case HW_VAR_H2C_FW_JOINBSSRPT:
3499 rtl8723b_set_FwJoinBssRpt_cmd(padapter, mstatus: *val);
3500 break;
3501
3502 case HW_VAR_INITIAL_GAIN:
3503 {
3504 struct dig_t *pDigTable = &pHalData->odmpriv.DM_DigTable;
3505 u32 rx_gain = *(u32 *)val;
3506
3507 if (rx_gain == 0xff) {/* restore rx gain */
3508 ODM_Write_DIG(pDM_VOID: &pHalData->odmpriv, CurrentIGI: pDigTable->BackupIGValue);
3509 } else {
3510 pDigTable->BackupIGValue = pDigTable->CurIGValue;
3511 ODM_Write_DIG(pDM_VOID: &pHalData->odmpriv, CurrentIGI: rx_gain);
3512 }
3513 }
3514 break;
3515
3516 case HW_VAR_EFUSE_USAGE:
3517 pHalData->EfuseUsedPercentage = *val;
3518 break;
3519
3520 case HW_VAR_EFUSE_BYTES:
3521 pHalData->EfuseUsedBytes = *((u16 *)val);
3522 break;
3523
3524 case HW_VAR_EFUSE_BT_USAGE:
3525#ifdef HAL_EFUSE_MEMORY
3526 pHalData->EfuseHal.BTEfuseUsedPercentage = *val;
3527#endif
3528 break;
3529
3530 case HW_VAR_EFUSE_BT_BYTES:
3531#ifdef HAL_EFUSE_MEMORY
3532 pHalData->EfuseHal.BTEfuseUsedBytes = *((u16 *)val);
3533#else
3534 BTEfuseUsedBytes = *((u16 *)val);
3535#endif
3536 break;
3537
3538 case HW_VAR_FIFO_CLEARN_UP:
3539 {
3540 #define RW_RELEASE_EN BIT(18)
3541 #define RXDMA_IDLE BIT(17)
3542
3543 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
3544 u8 trycnt = 100;
3545
3546 /* pause tx */
3547 rtw_write8(adapter: padapter, REG_TXPAUSE, val: 0xff);
3548
3549 /* keep sn */
3550 padapter->xmitpriv.nqos_ssn = rtw_read16(adapter: padapter, REG_NQOS_SEQ);
3551
3552 if (!pwrpriv->bkeepfwalive) {
3553 /* RX DMA stop */
3554 val32 = rtw_read32(adapter: padapter, REG_RXPKT_NUM);
3555 val32 |= RW_RELEASE_EN;
3556 rtw_write32(adapter: padapter, REG_RXPKT_NUM, val: val32);
3557 do {
3558 val32 = rtw_read32(adapter: padapter, REG_RXPKT_NUM);
3559 val32 &= RXDMA_IDLE;
3560 if (val32)
3561 break;
3562 } while (--trycnt);
3563
3564 /* RQPN Load 0 */
3565 rtw_write16(adapter: padapter, REG_RQPN_NPQ, val: 0);
3566 rtw_write32(adapter: padapter, REG_RQPN, val: 0x80000000);
3567 mdelay(2);
3568 }
3569 }
3570 break;
3571
3572 case HW_VAR_APFM_ON_MAC:
3573 pHalData->bMacPwrCtrlOn = *val;
3574 break;
3575
3576 case HW_VAR_NAV_UPPER:
3577 {
3578 u32 usNavUpper = *((u32 *)val);
3579
3580 if (usNavUpper > HAL_NAV_UPPER_UNIT_8723B * 0xFF)
3581 break;
3582
3583 usNavUpper = DIV_ROUND_UP(usNavUpper,
3584 HAL_NAV_UPPER_UNIT_8723B);
3585 rtw_write8(adapter: padapter, REG_NAV_UPPER, val: (u8)usNavUpper);
3586 }
3587 break;
3588
3589 case HW_VAR_H2C_MEDIA_STATUS_RPT:
3590 {
3591 u16 mstatus_rpt = (*(u16 *)val);
3592 u8 mstatus, macId;
3593
3594 mstatus = (u8) (mstatus_rpt & 0xFF);
3595 macId = (u8)(mstatus_rpt >> 8);
3596 rtl8723b_set_FwMediaStatusRpt_cmd(padapter, mstatus, macid: macId);
3597 }
3598 break;
3599 case HW_VAR_BCN_VALID:
3600 {
3601 /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2, write 1 to clear, Clear by sw */
3602 val8 = rtw_read8(adapter: padapter, REG_TDECTRL+2);
3603 val8 |= BIT(0);
3604 rtw_write8(adapter: padapter, REG_TDECTRL+2, val: val8);
3605 }
3606 break;
3607
3608 case HW_VAR_DL_BCN_SEL:
3609 {
3610 /* SW_BCN_SEL - Port0 */
3611 val8 = rtw_read8(adapter: padapter, REG_DWBCN1_CTRL_8723B+2);
3612 val8 &= ~BIT(4);
3613 rtw_write8(adapter: padapter, REG_DWBCN1_CTRL_8723B+2, val: val8);
3614 }
3615 break;
3616
3617 case HW_VAR_DO_IQK:
3618 pHalData->bNeedIQK = true;
3619 break;
3620
3621 case HW_VAR_DL_RSVD_PAGE:
3622 if (check_fwstate(pmlmepriv: &padapter->mlmepriv, WIFI_AP_STATE) == true)
3623 rtl8723b_download_BTCoex_AP_mode_rsvd_page(padapter);
3624 else
3625 rtl8723b_download_rsvd_page(padapter, mstatus: RT_MEDIA_CONNECT);
3626 break;
3627
3628 case HW_VAR_MACID_SLEEP:
3629 /* Input is MACID */
3630 val32 = *(u32 *)val;
3631 if (val32 > 31)
3632 break;
3633
3634 val8 = (u8)val32; /* macid is between 0~31 */
3635
3636 val32 = rtw_read32(adapter: padapter, REG_MACID_SLEEP);
3637 if (val32 & BIT(val8))
3638 break;
3639 val32 |= BIT(val8);
3640 rtw_write32(adapter: padapter, REG_MACID_SLEEP, val: val32);
3641 break;
3642
3643 case HW_VAR_MACID_WAKEUP:
3644 /* Input is MACID */
3645 val32 = *(u32 *)val;
3646 if (val32 > 31)
3647 break;
3648
3649 val8 = (u8)val32; /* macid is between 0~31 */
3650
3651 val32 = rtw_read32(adapter: padapter, REG_MACID_SLEEP);
3652 if (!(val32 & BIT(val8)))
3653 break;
3654 val32 &= ~BIT(val8);
3655 rtw_write32(adapter: padapter, REG_MACID_SLEEP, val: val32);
3656 break;
3657
3658 default:
3659 SetHwReg(padapter, variable, val);
3660 break;
3661 }
3662}
3663
3664void GetHwReg8723B(struct adapter *padapter, u8 variable, u8 *val)
3665{
3666 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
3667 u8 val8;
3668 u16 val16;
3669
3670 switch (variable) {
3671 case HW_VAR_TXPAUSE:
3672 *val = rtw_read8(adapter: padapter, REG_TXPAUSE);
3673 break;
3674
3675 case HW_VAR_BCN_VALID:
3676 {
3677 /* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2 */
3678 val8 = rtw_read8(adapter: padapter, REG_TDECTRL+2);
3679 *val = (BIT(0) & val8) ? true : false;
3680 }
3681 break;
3682
3683 case HW_VAR_FWLPS_RF_ON:
3684 {
3685 /* When we halt NIC, we should check if FW LPS is leave. */
3686 u32 valRCR;
3687
3688 if (
3689 padapter->bSurpriseRemoved ||
3690 (adapter_to_pwrctl(padapter)->rf_pwrstate == rf_off)
3691 ) {
3692 /* If it is in HW/SW Radio OFF or IPS state, we do not check Fw LPS Leave, */
3693 /* because Fw is unload. */
3694 *val = true;
3695 } else {
3696 valRCR = rtw_read32(adapter: padapter, REG_RCR);
3697 valRCR &= 0x00070000;
3698 if (valRCR)
3699 *val = false;
3700 else
3701 *val = true;
3702 }
3703 }
3704 break;
3705
3706 case HW_VAR_EFUSE_USAGE:
3707 *val = pHalData->EfuseUsedPercentage;
3708 break;
3709
3710 case HW_VAR_EFUSE_BYTES:
3711 *((u16 *)val) = pHalData->EfuseUsedBytes;
3712 break;
3713
3714 case HW_VAR_EFUSE_BT_USAGE:
3715#ifdef HAL_EFUSE_MEMORY
3716 *val = pHalData->EfuseHal.BTEfuseUsedPercentage;
3717#endif
3718 break;
3719
3720 case HW_VAR_EFUSE_BT_BYTES:
3721#ifdef HAL_EFUSE_MEMORY
3722 *((u16 *)val) = pHalData->EfuseHal.BTEfuseUsedBytes;
3723#else
3724 *((u16 *)val) = BTEfuseUsedBytes;
3725#endif
3726 break;
3727
3728 case HW_VAR_APFM_ON_MAC:
3729 *val = pHalData->bMacPwrCtrlOn;
3730 break;
3731 case HW_VAR_CHK_HI_QUEUE_EMPTY:
3732 val16 = rtw_read16(adapter: padapter, REG_TXPKT_EMPTY);
3733 *val = (val16 & BIT(10)) ? true:false;
3734 break;
3735 default:
3736 GetHwReg(padapter, variable, val);
3737 break;
3738 }
3739}
3740
3741/* Description:
3742 * Change default setting of specified variable.
3743 */
3744u8 SetHalDefVar8723B(struct adapter *padapter, enum hal_def_variable variable, void *pval)
3745{
3746 u8 bResult;
3747
3748 bResult = _SUCCESS;
3749
3750 switch (variable) {
3751 default:
3752 bResult = SetHalDefVar(adapter: padapter, variable, value: pval);
3753 break;
3754 }
3755
3756 return bResult;
3757}
3758
3759/* Description:
3760 * Query setting of specified variable.
3761 */
3762u8 GetHalDefVar8723B(struct adapter *padapter, enum hal_def_variable variable, void *pval)
3763{
3764 u8 bResult;
3765
3766 bResult = _SUCCESS;
3767
3768 switch (variable) {
3769 case HAL_DEF_MAX_RECVBUF_SZ:
3770 *((u32 *)pval) = MAX_RECVBUF_SZ;
3771 break;
3772
3773 case HAL_DEF_RX_PACKET_OFFSET:
3774 *((u32 *)pval) = RXDESC_SIZE + DRVINFO_SZ*8;
3775 break;
3776
3777 case HW_VAR_MAX_RX_AMPDU_FACTOR:
3778 /* Stanley@BB.SD3 suggests 16K can get stable performance */
3779 /* The experiment was done on SDIO interface */
3780 /* coding by Lucas@20130730 */
3781 *(u32 *)pval = IEEE80211_HT_MAX_AMPDU_16K;
3782 break;
3783 case HAL_DEF_TX_LDPC:
3784 case HAL_DEF_RX_LDPC:
3785 *((u8 *)pval) = false;
3786 break;
3787 case HAL_DEF_TX_STBC:
3788 *((u8 *)pval) = 0;
3789 break;
3790 case HAL_DEF_RX_STBC:
3791 *((u8 *)pval) = 1;
3792 break;
3793 case HAL_DEF_EXPLICIT_BEAMFORMER:
3794 case HAL_DEF_EXPLICIT_BEAMFORMEE:
3795 *((u8 *)pval) = false;
3796 break;
3797
3798 case HW_DEF_RA_INFO_DUMP:
3799 {
3800 u8 mac_id = *(u8 *)pval;
3801 u32 cmd;
3802
3803 cmd = 0x40000100 | mac_id;
3804 rtw_write32(adapter: padapter, REG_HMEBOX_DBG_2_8723B, val: cmd);
3805 msleep(msecs: 10);
3806 rtw_read32(adapter: padapter, addr: 0x2F0); // info 1
3807
3808 cmd = 0x40000400 | mac_id;
3809 rtw_write32(adapter: padapter, REG_HMEBOX_DBG_2_8723B, val: cmd);
3810 msleep(msecs: 10);
3811 rtw_read32(adapter: padapter, addr: 0x2F0); // info 1
3812 rtw_read32(adapter: padapter, addr: 0x2F4); // info 2
3813 rtw_read32(adapter: padapter, addr: 0x2F8); // rate mask 1
3814 rtw_read32(adapter: padapter, addr: 0x2FC); // rate mask 2
3815 }
3816 break;
3817
3818 case HAL_DEF_TX_PAGE_BOUNDARY:
3819 if (!padapter->registrypriv.wifi_spec) {
3820 *(u8 *)pval = TX_PAGE_BOUNDARY_8723B;
3821 } else {
3822 *(u8 *)pval = WMM_NORMAL_TX_PAGE_BOUNDARY_8723B;
3823 }
3824 break;
3825
3826 case HAL_DEF_MACID_SLEEP:
3827 *(u8 *)pval = true; /* support macid sleep */
3828 break;
3829
3830 default:
3831 bResult = GetHalDefVar(adapter: padapter, variable, value: pval);
3832 break;
3833 }
3834
3835 return bResult;
3836}
3837
3838void rtl8723b_start_thread(struct adapter *padapter)
3839{
3840 struct xmit_priv *xmitpriv = &padapter->xmitpriv;
3841
3842 xmitpriv->SdioXmitThread = kthread_run(rtl8723bs_xmit_thread, padapter, "RTWHALXT");
3843}
3844
3845void rtl8723b_stop_thread(struct adapter *padapter)
3846{
3847 struct xmit_priv *xmitpriv = &padapter->xmitpriv;
3848
3849 /* stop xmit_buf_thread */
3850 if (xmitpriv->SdioXmitThread) {
3851 complete(&xmitpriv->SdioXmitStart);
3852 wait_for_completion(&xmitpriv->SdioXmitTerminate);
3853 xmitpriv->SdioXmitThread = NULL;
3854 }
3855}
3856

source code of linux/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c