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