• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  ******************************************************************************/
15 #include <osdep_service.h>
16 #include <drv_types.h>
17 
18 #include <hal_intf.h>
19 #include <hal_com.h>
20 #include <rtl8723a_hal.h>
21 #include <usb_ops_linux.h>
22 
23 #define _HAL_INIT_C_
24 
25 #define	EEPROM_CHANNEL_PLAN_BY_HW_MASK	0x80
26 
27 /* return the final channel plan decision */
28 /* hw_channel_plan:  channel plan from HW (efuse/eeprom) */
29 /* sw_channel_plan:  channel plan from SW (registry/module param) */
30 /* def_channel_plan: channel plan used when the former two is invalid */
hal_com_get_channel_plan23a(struct rtw_adapter * padapter,u8 hw_channel_plan,u8 sw_channel_plan,u8 def_channel_plan,bool AutoLoadFail)31 u8 hal_com_get_channel_plan23a(struct rtw_adapter *padapter, u8 hw_channel_plan,
32 			    u8 sw_channel_plan, u8 def_channel_plan,
33 			    bool AutoLoadFail)
34 {
35 	u8 swConfig;
36 	u8 chnlPlan;
37 
38 	swConfig = true;
39 	if (!AutoLoadFail) {
40 		if (!rtw_is_channel_plan_valid(sw_channel_plan))
41 			swConfig = false;
42 		if (hw_channel_plan & EEPROM_CHANNEL_PLAN_BY_HW_MASK)
43 			swConfig = false;
44 	}
45 
46 	if (swConfig == true)
47 		chnlPlan = sw_channel_plan;
48 	else
49 		chnlPlan = hw_channel_plan & (~EEPROM_CHANNEL_PLAN_BY_HW_MASK);
50 
51 	if (!rtw_is_channel_plan_valid(chnlPlan))
52 		chnlPlan = def_channel_plan;
53 
54 	return chnlPlan;
55 }
56 
MRateToHwRate23a(u8 rate)57 u8 MRateToHwRate23a(u8 rate)
58 {
59 	u8 ret = DESC_RATE1M;
60 
61 	switch (rate) {
62 		/*  CCK and OFDM non-HT rates */
63 	case IEEE80211_CCK_RATE_1MB:
64 		ret = DESC_RATE1M;
65 		break;
66 	case IEEE80211_CCK_RATE_2MB:
67 		ret = DESC_RATE2M;
68 		break;
69 	case IEEE80211_CCK_RATE_5MB:
70 		ret = DESC_RATE5_5M;
71 		break;
72 	case IEEE80211_CCK_RATE_11MB:
73 		ret = DESC_RATE11M;
74 		break;
75 	case IEEE80211_OFDM_RATE_6MB:
76 		ret = DESC_RATE6M;
77 		break;
78 	case IEEE80211_OFDM_RATE_9MB:
79 		ret = DESC_RATE9M;
80 		break;
81 	case IEEE80211_OFDM_RATE_12MB:
82 		ret = DESC_RATE12M;
83 		break;
84 	case IEEE80211_OFDM_RATE_18MB:
85 		ret = DESC_RATE18M;
86 		break;
87 	case IEEE80211_OFDM_RATE_24MB:
88 		ret = DESC_RATE24M;
89 		break;
90 	case IEEE80211_OFDM_RATE_36MB:
91 		ret = DESC_RATE36M;
92 		break;
93 	case IEEE80211_OFDM_RATE_48MB:
94 		ret = DESC_RATE48M;
95 		break;
96 	case IEEE80211_OFDM_RATE_54MB:
97 		ret = DESC_RATE54M;
98 		break;
99 
100 		/*  HT rates since here */
101 		/* case MGN_MCS0:	ret = DESC_RATEMCS0;    break; */
102 		/* case MGN_MCS1:	ret = DESC_RATEMCS1;    break; */
103 		/* case MGN_MCS2:	ret = DESC_RATEMCS2;    break; */
104 		/* case MGN_MCS3:	ret = DESC_RATEMCS3;    break; */
105 		/* case MGN_MCS4:	ret = DESC_RATEMCS4;    break; */
106 		/* case MGN_MCS5:	ret = DESC_RATEMCS5;    break; */
107 		/* case MGN_MCS6:	ret = DESC_RATEMCS6;    break; */
108 		/* case MGN_MCS7:	ret = DESC_RATEMCS7;    break; */
109 
110 	default:
111 		break;
112 	}
113 	return ret;
114 }
115 
HalSetBrateCfg23a(struct rtw_adapter * padapter,u8 * mBratesOS)116 void HalSetBrateCfg23a(struct rtw_adapter *padapter, u8 *mBratesOS)
117 {
118 	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
119 	u8 i, is_brate, brate;
120 	u16 brate_cfg = 0;
121 	u8 rate_index;
122 
123 	for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
124 		is_brate = mBratesOS[i] & IEEE80211_BASIC_RATE_MASK;
125 		brate = mBratesOS[i] & 0x7f;
126 
127 		if (is_brate) {
128 			switch (brate) {
129 			case IEEE80211_CCK_RATE_1MB:
130 				brate_cfg |= RATE_1M;
131 				break;
132 			case IEEE80211_CCK_RATE_2MB:
133 				brate_cfg |= RATE_2M;
134 				break;
135 			case IEEE80211_CCK_RATE_5MB:
136 				brate_cfg |= RATE_5_5M;
137 				break;
138 			case IEEE80211_CCK_RATE_11MB:
139 				brate_cfg |= RATE_11M;
140 				break;
141 			case IEEE80211_OFDM_RATE_6MB:
142 				brate_cfg |= RATE_6M;
143 				break;
144 			case IEEE80211_OFDM_RATE_9MB:
145 				brate_cfg |= RATE_9M;
146 				break;
147 			case IEEE80211_OFDM_RATE_12MB:
148 				brate_cfg |= RATE_12M;
149 				break;
150 			case IEEE80211_OFDM_RATE_18MB:
151 				brate_cfg |= RATE_18M;
152 				break;
153 			case IEEE80211_OFDM_RATE_24MB:
154 				brate_cfg |= RATE_24M;
155 				break;
156 			case IEEE80211_OFDM_RATE_36MB:
157 				brate_cfg |= RATE_36M;
158 				break;
159 			case IEEE80211_OFDM_RATE_48MB:
160 				brate_cfg |= RATE_48M;
161 				break;
162 			case IEEE80211_OFDM_RATE_54MB:
163 				brate_cfg |= RATE_54M;
164 				break;
165 			}
166 		}
167 	}
168 
169 	/*  2007.01.16, by Emily */
170 	/*  Select RRSR (in Legacy-OFDM and CCK) */
171 	/*  For 8190, we select only 24M, 12M, 6M, 11M, 5.5M, 2M,
172 	    and 1M from the Basic rate. */
173 	/*  We do not use other rates. */
174 	/* 2011.03.30 add by Luke Lee */
175 	/* CCK 2M ACK should be disabled for some BCM and Atheros AP IOT */
176 	/* because CCK 2M has poor TXEVM */
177 	/* CCK 5.5M & 11M ACK should be enabled for better
178 	   performance */
179 
180 	brate_cfg = (brate_cfg | 0xd) & 0x15d;
181 	pHalData->BasicRateSet = brate_cfg;
182 	brate_cfg |= 0x01;	/*  default enable 1M ACK rate */
183 	DBG_8723A("HW_VAR_BASIC_RATE: BrateCfg(%#x)\n", brate_cfg);
184 
185 	/*  Set RRSR rate table. */
186 	rtl8723au_write8(padapter, REG_RRSR, brate_cfg & 0xff);
187 	rtl8723au_write8(padapter, REG_RRSR + 1, (brate_cfg >> 8) & 0xff);
188 	rtl8723au_write8(padapter, REG_RRSR + 2,
189 			 rtl8723au_read8(padapter, REG_RRSR + 2) & 0xf0);
190 
191 	rate_index = 0;
192 	/*  Set RTS initial rate */
193 	while (brate_cfg > 0x1) {
194 		brate_cfg >>= 1;
195 		rate_index++;
196 	}
197 		/*  Ziv - Check */
198 	rtl8723au_write8(padapter, REG_INIRTS_RATE_SEL, rate_index);
199 }
200 
_OneOutPipeMapping(struct rtw_adapter * pAdapter)201 static void _OneOutPipeMapping(struct rtw_adapter *pAdapter)
202 {
203 	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
204 
205 	pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0];	/* VO */
206 	pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0];	/* VI */
207 	pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[0];	/* BE */
208 	pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0];	/* BK */
209 
210 	pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0];	/* BCN */
211 	pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0];	/* MGT */
212 	pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0];	/* HIGH */
213 	pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0];	/* TXCMD */
214 }
215 
_TwoOutPipeMapping(struct rtw_adapter * pAdapter,bool bWIFICfg)216 static void _TwoOutPipeMapping(struct rtw_adapter *pAdapter, bool bWIFICfg)
217 {
218 	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
219 
220 	if (bWIFICfg) {		/* WMM */
221 		/*    BK,   BE,   VI,   VO,   BCN,  CMD,  MGT, HIGH, HCCA */
222 		/*     0,    1,    0,    1,     0,    0,    0,    0,    0 }; */
223 		/* 0:H, 1:L */
224 		pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[1]; /* VO */
225 		pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */
226 		pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1]; /* BE */
227 		pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[0]; /* BK */
228 
229 		pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
230 		pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
231 		pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
232 		pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
233 	} else {		/* typical setting */
234 		/*    BK,   BE,   VI,   VO,   BCN,  CMD,  MGT, HIGH, HCCA */
235 		/*     1,    1,    0,    0,     0,    0,    0,    0,    0 }; */
236 		/* 0:H, 1:L */
237 		pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */
238 		pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[0]; /* VI */
239 		pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[1]; /* BE */
240 		pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1]; /* BK */
241 
242 		pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
243 		pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
244 		pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
245 		pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
246 	}
247 }
248 
_ThreeOutPipeMapping(struct rtw_adapter * pAdapter,bool bWIFICfg)249 static void _ThreeOutPipeMapping(struct rtw_adapter *pAdapter, bool bWIFICfg)
250 {
251 	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(pAdapter);
252 
253 	if (bWIFICfg) {		/* for WMM */
254 		/*    BK,   BE,   VI,   VO,   BCN,  CMD,  MGT, HIGH, HCCA */
255 		/*     1,    2,    1,    0,     0,    0,    0,    0,    0 }; */
256 		/* 0:H, 1:N, 2:L */
257 		pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */
258 		pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1]; /* VI */
259 		pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2]; /* BE */
260 		pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[1]; /* BK */
261 
262 		pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
263 		pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
264 		pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
265 		pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
266 	} else {		/* typical setting */
267 		/*    BK,   BE,   VI,   VO,   BCN,  CMD,  MGT, HIGH, HCCA */
268 		/*     2,    2,    1,    0,     0,    0,    0,    0,    0 }; */
269 		/* 0:H, 1:N, 2:L */
270 		pdvobjpriv->Queue2Pipe[0] = pdvobjpriv->RtOutPipe[0]; /* VO */
271 		pdvobjpriv->Queue2Pipe[1] = pdvobjpriv->RtOutPipe[1]; /* VI */
272 		pdvobjpriv->Queue2Pipe[2] = pdvobjpriv->RtOutPipe[2]; /* BE */
273 		pdvobjpriv->Queue2Pipe[3] = pdvobjpriv->RtOutPipe[2]; /* BK */
274 
275 		pdvobjpriv->Queue2Pipe[4] = pdvobjpriv->RtOutPipe[0]; /* BCN */
276 		pdvobjpriv->Queue2Pipe[5] = pdvobjpriv->RtOutPipe[0]; /* MGT */
277 		pdvobjpriv->Queue2Pipe[6] = pdvobjpriv->RtOutPipe[0]; /* HIGH */
278 		pdvobjpriv->Queue2Pipe[7] = pdvobjpriv->RtOutPipe[0]; /* TXCMD*/
279 	}
280 }
281 
Hal_MappingOutPipe23a(struct rtw_adapter * pAdapter,u8 NumOutPipe)282 bool Hal_MappingOutPipe23a(struct rtw_adapter *pAdapter, u8 NumOutPipe)
283 {
284 	struct registry_priv *pregistrypriv = &pAdapter->registrypriv;
285 	bool bWIFICfg = (pregistrypriv->wifi_spec) ? true : false;
286 	bool result = true;
287 
288 	switch (NumOutPipe) {
289 	case 2:
290 		_TwoOutPipeMapping(pAdapter, bWIFICfg);
291 		break;
292 	case 3:
293 		_ThreeOutPipeMapping(pAdapter, bWIFICfg);
294 		break;
295 	case 1:
296 		_OneOutPipeMapping(pAdapter);
297 		break;
298 	default:
299 		result = false;
300 		break;
301 	}
302 
303 	return result;
304 }
305 
306 /*
307 * C2H event format:
308 * Field	 TRIGGER		CONTENT	   CMD_SEQ	CMD_LEN		 CMD_ID
309 * BITS	 [127:120]	[119:16]      [15:8]		  [7:4]		   [3:0]
310 */
311 
c2h_evt_clear23a(struct rtw_adapter * adapter)312 void c2h_evt_clear23a(struct rtw_adapter *adapter)
313 {
314 	rtl8723au_write8(adapter, REG_C2HEVT_CLEAR, C2H_EVT_HOST_CLOSE);
315 }
316 
c2h_evt_read23a(struct rtw_adapter * adapter,u8 * buf)317 int c2h_evt_read23a(struct rtw_adapter *adapter, u8 *buf)
318 {
319 	int ret = _FAIL;
320 	struct c2h_evt_hdr *c2h_evt;
321 	int i;
322 	u8 trigger;
323 
324 	if (buf == NULL)
325 		goto exit;
326 
327 	trigger = rtl8723au_read8(adapter, REG_C2HEVT_CLEAR);
328 
329 	if (trigger == C2H_EVT_HOST_CLOSE)
330 		goto exit;	/* Not ready */
331 	else if (trigger != C2H_EVT_FW_CLOSE)
332 		goto clear_evt;	/* Not a valid value */
333 
334 	c2h_evt = (struct c2h_evt_hdr *)buf;
335 
336 	memset(c2h_evt, 0, 16);
337 
338 	*buf = rtl8723au_read8(adapter, REG_C2HEVT_MSG_NORMAL);
339 	*(buf + 1) = rtl8723au_read8(adapter, REG_C2HEVT_MSG_NORMAL + 1);
340 
341 	RT_PRINT_DATA(_module_hal_init_c_, _drv_info_, "c2h_evt_read23a(): ",
342 		      &c2h_evt, sizeof(c2h_evt));
343 
344 	if (0) {
345 		DBG_8723A("%s id:%u, len:%u, seq:%u, trigger:0x%02x\n",
346 			  __func__, c2h_evt->id, c2h_evt->plen, c2h_evt->seq,
347 			  trigger);
348 	}
349 
350 	/* Read the content */
351 	for (i = 0; i < c2h_evt->plen; i++)
352 		c2h_evt->payload[i] = rtl8723au_read8(adapter,
353 						REG_C2HEVT_MSG_NORMAL +
354 						sizeof(*c2h_evt) + i);
355 
356 	RT_PRINT_DATA(_module_hal_init_c_, _drv_info_,
357 		      "c2h_evt_read23a(): Command Content:\n", c2h_evt->payload,
358 		      c2h_evt->plen);
359 
360 	ret = _SUCCESS;
361 
362 clear_evt:
363 	/*
364 	 * Clear event to notify FW we have read the command.
365 	 * If this field isn't clear, the FW won't update the
366 	 * next command message.
367 	 */
368 	c2h_evt_clear23a(adapter);
369 exit:
370 	return ret;
371 }
372 
373 void
rtl8723a_set_ampdu_min_space(struct rtw_adapter * padapter,u8 MinSpacingToSet)374 rtl8723a_set_ampdu_min_space(struct rtw_adapter *padapter, u8 MinSpacingToSet)
375 {
376 	u8 SecMinSpace;
377 
378 	if (MinSpacingToSet <= 7) {
379 		switch (padapter->securitypriv.dot11PrivacyAlgrthm) {
380 		case 0:
381 		case WLAN_CIPHER_SUITE_CCMP:
382 			SecMinSpace = 0;
383 			break;
384 
385 		case WLAN_CIPHER_SUITE_WEP40:
386 		case WLAN_CIPHER_SUITE_WEP104:
387 		case WLAN_CIPHER_SUITE_TKIP:
388 			SecMinSpace = 6;
389 			break;
390 		default:
391 			SecMinSpace = 7;
392 			break;
393 		}
394 
395 		if (MinSpacingToSet < SecMinSpace)
396 			MinSpacingToSet = SecMinSpace;
397 
398 		MinSpacingToSet |=
399 			rtl8723au_read8(padapter, REG_AMPDU_MIN_SPACE) & 0xf8;
400 		rtl8723au_write8(padapter, REG_AMPDU_MIN_SPACE,
401 				 MinSpacingToSet);
402 	}
403 }
404 
rtl8723a_set_ampdu_factor(struct rtw_adapter * padapter,u8 FactorToSet)405 void rtl8723a_set_ampdu_factor(struct rtw_adapter *padapter, u8 FactorToSet)
406 {
407 	u8 RegToSet_Normal[4] = { 0x41, 0xa8, 0x72, 0xb9 };
408 	u8 MaxAggNum;
409 	u8 *pRegToSet;
410 	u8 index = 0;
411 
412 	pRegToSet = RegToSet_Normal;	/*  0xb972a841; */
413 
414 	if (rtl8723a_BT_enabled(padapter) &&
415 	    rtl8723a_BT_using_antenna_1(padapter))
416 		MaxAggNum = 0x8;
417 	else
418 		MaxAggNum = 0xF;
419 
420 	if (FactorToSet <= 3) {
421 		FactorToSet = 1 << (FactorToSet + 2);
422 		if (FactorToSet > MaxAggNum)
423 			FactorToSet = MaxAggNum;
424 
425 		for (index = 0; index < 4; index++) {
426 			if ((pRegToSet[index] & 0xf0) > (FactorToSet << 4))
427 				pRegToSet[index] = (pRegToSet[index] & 0x0f) |
428 					(FactorToSet << 4);
429 
430 			if ((pRegToSet[index] & 0x0f) > FactorToSet)
431 				pRegToSet[index] = (pRegToSet[index] & 0xf0) |
432 					FactorToSet;
433 
434 			rtl8723au_write8(padapter, REG_AGGLEN_LMT + index,
435 					 pRegToSet[index]);
436 		}
437 	}
438 }
439 
rtl8723a_set_acm_ctrl(struct rtw_adapter * padapter,u8 ctrl)440 void rtl8723a_set_acm_ctrl(struct rtw_adapter *padapter, u8 ctrl)
441 {
442 	u8 hwctrl = 0;
443 
444 	if (ctrl != 0) {
445 		hwctrl |= AcmHw_HwEn;
446 
447 		if (ctrl & BIT(1))	/*  BE */
448 			hwctrl |= AcmHw_BeqEn;
449 
450 		if (ctrl & BIT(2))	/*  VI */
451 			hwctrl |= AcmHw_ViqEn;
452 
453 		if (ctrl & BIT(3))	/*  VO */
454 			hwctrl |= AcmHw_VoqEn;
455 	}
456 
457 	DBG_8723A("[HW_VAR_ACM_CTRL] Write 0x%02X\n", hwctrl);
458 	rtl8723au_write8(padapter, REG_ACMHWCTRL, hwctrl);
459 }
460 
rtl8723a_set_media_status(struct rtw_adapter * padapter,u8 status)461 void rtl8723a_set_media_status(struct rtw_adapter *padapter, u8 status)
462 {
463 	u8 val8;
464 
465 	val8 = rtl8723au_read8(padapter, MSR) & 0x0c;
466 	val8 |= status;
467 	rtl8723au_write8(padapter, MSR, val8);
468 }
469 
rtl8723a_set_media_status1(struct rtw_adapter * padapter,u8 status)470 void rtl8723a_set_media_status1(struct rtw_adapter *padapter, u8 status)
471 {
472 	u8 val8;
473 
474 	val8 = rtl8723au_read8(padapter, MSR) & 0x03;
475 	val8 |= status << 2;
476 	rtl8723au_write8(padapter, MSR, val8);
477 }
478 
rtl8723a_set_bcn_func(struct rtw_adapter * padapter,u8 val)479 void rtl8723a_set_bcn_func(struct rtw_adapter *padapter, u8 val)
480 {
481 	if (val)
482 		SetBcnCtrlReg23a(padapter, EN_BCN_FUNCTION | EN_TXBCN_RPT, 0);
483 	else
484 		SetBcnCtrlReg23a(padapter, 0, EN_BCN_FUNCTION | EN_TXBCN_RPT);
485 }
486 
rtl8723a_check_bssid(struct rtw_adapter * padapter,u8 val)487 void rtl8723a_check_bssid(struct rtw_adapter *padapter, u8 val)
488 {
489 	u32 val32;
490 
491 	val32 = rtl8723au_read32(padapter, REG_RCR);
492 	if (val)
493 		val32 |= RCR_CBSSID_DATA | RCR_CBSSID_BCN;
494 	else
495 		val32 &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
496 	rtl8723au_write32(padapter, REG_RCR, val32);
497 }
498 
rtl8723a_mlme_sitesurvey(struct rtw_adapter * padapter,u8 flag)499 void rtl8723a_mlme_sitesurvey(struct rtw_adapter *padapter, u8 flag)
500 {
501 	if (flag) {	/* under sitesurvey */
502 		u32 v32;
503 
504 		/*  config RCR to receive different BSSID & not
505 		    to receive data frame */
506 		v32 = rtl8723au_read32(padapter, REG_RCR);
507 		v32 &= ~(RCR_CBSSID_BCN);
508 		rtl8723au_write32(padapter, REG_RCR, v32);
509 		/*  reject all data frame */
510 		rtl8723au_write16(padapter, REG_RXFLTMAP2, 0);
511 
512 		/*  disable update TSF */
513 		SetBcnCtrlReg23a(padapter, DIS_TSF_UDT, 0);
514 	} else {	/* sitesurvey done */
515 
516 		struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
517 		struct mlme_ext_info *pmlmeinfo;
518 		u32 v32;
519 
520 		pmlmeinfo = &pmlmeext->mlmext_info;
521 
522 		if ((is_client_associated_to_ap23a(padapter) == true) ||
523 		    ((pmlmeinfo->state & 0x03) == MSR_ADHOC) ||
524 		    ((pmlmeinfo->state & 0x03) == MSR_AP)) {
525 			/*  enable to rx data frame */
526 			rtl8723au_write16(padapter, REG_RXFLTMAP2, 0xFFFF);
527 
528 			/*  enable update TSF */
529 			SetBcnCtrlReg23a(padapter, 0, DIS_TSF_UDT);
530 		}
531 
532 		v32 = rtl8723au_read32(padapter, REG_RCR);
533 		v32 |= RCR_CBSSID_BCN;
534 		rtl8723au_write32(padapter, REG_RCR, v32);
535 	}
536 
537 	rtl8723a_BT_wifiscan_notify(padapter, flag ? true : false);
538 }
539 
rtl8723a_on_rcr_am(struct rtw_adapter * padapter)540 void rtl8723a_on_rcr_am(struct rtw_adapter *padapter)
541 {
542 	rtl8723au_write32(padapter, REG_RCR,
543 		    rtl8723au_read32(padapter, REG_RCR) | RCR_AM);
544 	DBG_8723A("%s, %d, RCR = %x\n", __func__, __LINE__,
545 		  rtl8723au_read32(padapter, REG_RCR));
546 }
547 
rtl8723a_off_rcr_am(struct rtw_adapter * padapter)548 void rtl8723a_off_rcr_am(struct rtw_adapter *padapter)
549 {
550 	rtl8723au_write32(padapter, REG_RCR,
551 		    rtl8723au_read32(padapter, REG_RCR) & (~RCR_AM));
552 	DBG_8723A("%s, %d, RCR = %x\n", __func__, __LINE__,
553 		  rtl8723au_read32(padapter, REG_RCR));
554 }
555 
rtl8723a_set_slot_time(struct rtw_adapter * padapter,u8 slottime)556 void rtl8723a_set_slot_time(struct rtw_adapter *padapter, u8 slottime)
557 {
558 	u8 u1bAIFS, aSifsTime;
559 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
560 	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
561 
562 	rtl8723au_write8(padapter, REG_SLOT, slottime);
563 
564 	if (pmlmeinfo->WMM_enable == 0) {
565 		if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
566 			aSifsTime = 10;
567 		else
568 			aSifsTime = 16;
569 
570 		u1bAIFS = aSifsTime + (2 * pmlmeinfo->slotTime);
571 
572 		/*  <Roger_EXP> Temporary removed, 2008.06.20. */
573 		rtl8723au_write8(padapter, REG_EDCA_VO_PARAM, u1bAIFS);
574 		rtl8723au_write8(padapter, REG_EDCA_VI_PARAM, u1bAIFS);
575 		rtl8723au_write8(padapter, REG_EDCA_BE_PARAM, u1bAIFS);
576 		rtl8723au_write8(padapter, REG_EDCA_BK_PARAM, u1bAIFS);
577 	}
578 }
579 
rtl8723a_ack_preamble(struct rtw_adapter * padapter,u8 bShortPreamble)580 void rtl8723a_ack_preamble(struct rtw_adapter *padapter, u8 bShortPreamble)
581 {
582 	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
583 	u8 regTmp;
584 
585 	/*  Joseph marked out for Netgear 3500 TKIP
586 	    channel 7 issue.(Temporarily) */
587 	regTmp = (pHalData->nCur40MhzPrimeSC) << 5;
588 	/* regTmp = 0; */
589 	if (bShortPreamble)
590 		regTmp |= 0x80;
591 	rtl8723au_write8(padapter, REG_RRSR + 2, regTmp);
592 }
593 
rtl8723a_set_sec_cfg(struct rtw_adapter * padapter,u8 sec)594 void rtl8723a_set_sec_cfg(struct rtw_adapter *padapter, u8 sec)
595 {
596 	rtl8723au_write8(padapter, REG_SECCFG, sec);
597 }
598 
rtl8723a_cam_empty_entry(struct rtw_adapter * padapter,u8 ucIndex)599 void rtl8723a_cam_empty_entry(struct rtw_adapter *padapter, u8 ucIndex)
600 {
601 	u8 i;
602 	u32 ulCommand = 0;
603 	u32 ulContent = 0;
604 	u32 ulEncAlgo = CAM_AES;
605 
606 	for (i = 0; i < CAM_CONTENT_COUNT; i++) {
607 		/*  filled id in CAM config 2 byte */
608 		if (i == 0) {
609 			ulContent |= (ucIndex & 0x03) |
610 				((u16) (ulEncAlgo) << 2);
611 			/* ulContent |= CAM_VALID; */
612 		} else {
613 			ulContent = 0;
614 		}
615 		/*  polling bit, and No Write enable, and address */
616 		ulCommand = CAM_CONTENT_COUNT * ucIndex + i;
617 		ulCommand = ulCommand | CAM_POLLINIG | CAM_WRITE;
618 		/*  write content 0 is equall to mark invalid */
619 		/* delay_ms(40); */
620 		rtl8723au_write32(padapter, WCAMI, ulContent);
621 		/* delay_ms(40); */
622 		rtl8723au_write32(padapter, REG_CAMCMD, ulCommand);
623 	}
624 }
625 
rtl8723a_cam_invalidate_all(struct rtw_adapter * padapter)626 void rtl8723a_cam_invalidate_all(struct rtw_adapter *padapter)
627 {
628 	rtl8723au_write32(padapter, REG_CAMCMD, CAM_POLLINIG | BIT(30));
629 }
630 
rtl8723a_cam_write(struct rtw_adapter * padapter,u8 entry,u16 ctrl,const u8 * mac,const u8 * key)631 void rtl8723a_cam_write(struct rtw_adapter *padapter,
632 			u8 entry, u16 ctrl, const u8 *mac, const u8 *key)
633 {
634 	u32 cmd;
635 	unsigned int i, val, addr;
636 	int j;
637 
638 	addr = entry << 3;
639 
640 	for (j = 5; j >= 0; j--) {
641 		switch (j) {
642 		case 0:
643 			val = ctrl | (mac[0] << 16) | (mac[1] << 24);
644 			break;
645 		case 1:
646 			val = mac[2] | (mac[3] << 8) |
647 				(mac[4] << 16) | (mac[5] << 24);
648 			break;
649 		default:
650 			i = (j - 2) << 2;
651 			val = key[i] | (key[i+1] << 8) |
652 				(key[i+2] << 16) | (key[i+3] << 24);
653 			break;
654 		}
655 
656 		rtl8723au_write32(padapter, WCAMI, val);
657 		cmd = CAM_POLLINIG | CAM_WRITE | (addr + j);
658 		rtl8723au_write32(padapter, REG_CAMCMD, cmd);
659 
660 		/* DBG_8723A("%s => cam write: %x, %x\n", __func__, cmd, val);*/
661 	}
662 }
663 
rtl8723a_fifo_cleanup(struct rtw_adapter * padapter)664 void rtl8723a_fifo_cleanup(struct rtw_adapter *padapter)
665 {
666 #define RW_RELEASE_EN		BIT(18)
667 #define RXDMA_IDLE		BIT(17)
668 
669 	struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
670 	u8 trycnt = 100;
671 
672 	/*  pause tx */
673 	rtl8723au_write8(padapter, REG_TXPAUSE, 0xff);
674 
675 	/*  keep sn */
676 	padapter->xmitpriv.nqos_ssn = rtl8723au_read8(padapter, REG_NQOS_SEQ);
677 
678 	if (pwrpriv->bkeepfwalive != true) {
679 		u32 v32;
680 
681 		/*  RX DMA stop */
682 		v32 = rtl8723au_read32(padapter, REG_RXPKT_NUM);
683 		v32 |= RW_RELEASE_EN;
684 		rtl8723au_write32(padapter, REG_RXPKT_NUM, v32);
685 		do {
686 			v32 = rtl8723au_read32(padapter,
687 					       REG_RXPKT_NUM) & RXDMA_IDLE;
688 			if (!v32)
689 				break;
690 		} while (trycnt--);
691 		if (trycnt == 0)
692 			DBG_8723A("Stop RX DMA failed......\n");
693 
694 		/*  RQPN Load 0 */
695 		rtl8723au_write16(padapter, REG_RQPN_NPQ, 0);
696 		rtl8723au_write32(padapter, REG_RQPN, 0x80000000);
697 		mdelay(10);
698 	}
699 }
700 
rtl8723a_bcn_valid(struct rtw_adapter * padapter)701 void rtl8723a_bcn_valid(struct rtw_adapter *padapter)
702 {
703 	/* BCN_VALID, BIT16 of REG_TDECTRL = BIT0 of REG_TDECTRL+2,
704 	   write 1 to clear, Clear by sw */
705 	rtl8723au_write8(padapter, REG_TDECTRL + 2,
706 			 rtl8723au_read8(padapter, REG_TDECTRL + 2) | BIT(0));
707 }
708 
rtl8723a_get_bcn_valid(struct rtw_adapter * padapter)709 bool rtl8723a_get_bcn_valid(struct rtw_adapter *padapter)
710 {
711 	bool retval;
712 
713 	retval = (rtl8723au_read8(padapter, REG_TDECTRL + 2) & BIT(0)) ? true : false;
714 
715 	return retval;
716 }
717 
rtl8723a_set_beacon_interval(struct rtw_adapter * padapter,u16 interval)718 void rtl8723a_set_beacon_interval(struct rtw_adapter *padapter, u16 interval)
719 {
720 	rtl8723au_write16(padapter, REG_BCN_INTERVAL, interval);
721 }
722 
rtl8723a_set_resp_sifs(struct rtw_adapter * padapter,u8 r2t1,u8 r2t2,u8 t2t1,u8 t2t2)723 void rtl8723a_set_resp_sifs(struct rtw_adapter *padapter,
724 			    u8 r2t1, u8 r2t2, u8 t2t1, u8 t2t2)
725 {
726 	/* SIFS_Timer = 0x0a0a0808; */
727 	/* RESP_SIFS for CCK */
728 	/*  SIFS_T2T_CCK (0x08) */
729 	rtl8723au_write8(padapter, REG_R2T_SIFS, r2t1);
730 	/* SIFS_R2T_CCK(0x08) */
731 	rtl8723au_write8(padapter, REG_R2T_SIFS + 1, r2t2);
732 	/* RESP_SIFS for OFDM */
733 	/* SIFS_T2T_OFDM (0x0a) */
734 	rtl8723au_write8(padapter, REG_T2T_SIFS, t2t1);
735 	/* SIFS_R2T_OFDM(0x0a) */
736 	rtl8723au_write8(padapter, REG_T2T_SIFS + 1, t2t2);
737 }
738 
rtl8723a_set_ac_param_vo(struct rtw_adapter * padapter,u32 vo)739 void rtl8723a_set_ac_param_vo(struct rtw_adapter *padapter, u32 vo)
740 {
741 	rtl8723au_write32(padapter, REG_EDCA_VO_PARAM, vo);
742 }
743 
rtl8723a_set_ac_param_vi(struct rtw_adapter * padapter,u32 vi)744 void rtl8723a_set_ac_param_vi(struct rtw_adapter *padapter, u32 vi)
745 {
746 	rtl8723au_write32(padapter, REG_EDCA_VI_PARAM, vi);
747 }
748 
rtl8723a_set_ac_param_be(struct rtw_adapter * padapter,u32 be)749 void rtl8723a_set_ac_param_be(struct rtw_adapter *padapter, u32 be)
750 {
751 	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
752 
753 	pHalData->AcParam_BE = be;
754 	rtl8723au_write32(padapter, REG_EDCA_BE_PARAM, be);
755 }
756 
rtl8723a_set_ac_param_bk(struct rtw_adapter * padapter,u32 bk)757 void rtl8723a_set_ac_param_bk(struct rtw_adapter *padapter, u32 bk)
758 {
759 	rtl8723au_write32(padapter, REG_EDCA_BK_PARAM, bk);
760 }
761 
rtl8723a_set_rxdma_agg_pg_th(struct rtw_adapter * padapter,u8 val)762 void rtl8723a_set_rxdma_agg_pg_th(struct rtw_adapter *padapter, u8 val)
763 {
764 	rtl8723au_write8(padapter, REG_RXDMA_AGG_PG_TH, val);
765 }
766 
rtl8723a_set_initial_gain(struct rtw_adapter * padapter,u32 rx_gain)767 void rtl8723a_set_initial_gain(struct rtw_adapter *padapter, u32 rx_gain)
768 {
769 	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
770 	struct dig_t *pDigTable = &pHalData->odmpriv.DM_DigTable;
771 
772 	if (rx_gain == 0xff)	/* restore rx gain */
773 		ODM_Write_DIG23a(&pHalData->odmpriv, pDigTable->BackupIGValue);
774 	else {
775 		pDigTable->BackupIGValue = pDigTable->CurIGValue;
776 		ODM_Write_DIG23a(&pHalData->odmpriv, rx_gain);
777 	}
778 }
779 
rtl8723a_odm_support_ability_restore(struct rtw_adapter * padapter)780 void rtl8723a_odm_support_ability_restore(struct rtw_adapter *padapter)
781 {
782 	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
783 
784 	pHalData->odmpriv.SupportAbility = pHalData->odmpriv.BK_SupportAbility;
785 }
786 
rtl8723a_odm_support_ability_backup(struct rtw_adapter * padapter)787 void rtl8723a_odm_support_ability_backup(struct rtw_adapter *padapter)
788 {
789 	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
790 
791 	pHalData->odmpriv.BK_SupportAbility = pHalData->odmpriv.SupportAbility;
792 }
793 
rtl8723a_odm_support_ability_set(struct rtw_adapter * padapter,u32 val)794 void rtl8723a_odm_support_ability_set(struct rtw_adapter *padapter, u32 val)
795 {
796 	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
797 
798 	if (val == DYNAMIC_ALL_FUNC_ENABLE)
799 		pHalData->odmpriv.SupportAbility = pHalData->dmpriv.InitODMFlag;
800 	else
801 		pHalData->odmpriv.SupportAbility |= val;
802 }
803 
rtl8723a_odm_support_ability_clr(struct rtw_adapter * padapter,u32 val)804 void rtl8723a_odm_support_ability_clr(struct rtw_adapter *padapter, u32 val)
805 {
806 	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
807 
808 	pHalData->odmpriv.SupportAbility &= val;
809 }
810 
rtl8723a_set_rpwm(struct rtw_adapter * padapter,u8 val)811 void rtl8723a_set_rpwm(struct rtw_adapter *padapter, u8 val)
812 {
813 	rtl8723au_write8(padapter, REG_USB_HRPWM, val);
814 }
815 
rtl8723a_get_rf_type(struct rtw_adapter * padapter)816 u8 rtl8723a_get_rf_type(struct rtw_adapter *padapter)
817 {
818 	struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
819 
820 	return pHalData->rf_type;
821 }
822 
rtl8723a_get_fwlps_rf_on(struct rtw_adapter * padapter)823 bool rtl8723a_get_fwlps_rf_on(struct rtw_adapter *padapter)
824 {
825 	bool retval;
826 	u32 valRCR;
827 
828 	/*  When we halt NIC, we should check if FW LPS is leave. */
829 
830 	if ((padapter->bSurpriseRemoved == true) ||
831 	    (padapter->pwrctrlpriv.rf_pwrstate == rf_off)) {
832 		/*  If it is in HW/SW Radio OFF or IPS state, we do
833 		    not check Fw LPS Leave, because Fw is unload. */
834 		retval = true;
835 	} else {
836 		valRCR = rtl8723au_read32(padapter, REG_RCR);
837 		if (valRCR & 0x00070000)
838 			retval = false;
839 		else
840 			retval = true;
841 	}
842 
843 	return retval;
844 }
845 
rtl8723a_chk_hi_queue_empty(struct rtw_adapter * padapter)846 bool rtl8723a_chk_hi_queue_empty(struct rtw_adapter *padapter)
847 {
848 	u32 hgq;
849 
850 	hgq = rtl8723au_read32(padapter, REG_HGQ_INFORMATION);
851 
852 	return ((hgq & 0x0000ff00) == 0) ? true : false;
853 }
854