xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8822cs/hal/rtl8822c/sdio/rtl8822cs_ops.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2015 - 2017 Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *****************************************************************************/
15 #define _RTL8822CS_OPS_C_
16 
17 #include <drv_types.h>		/* PADAPTER, basic_types.h and etc. */
18 #include <hal_data.h>		/* HAL_DATA_TYPE, GET_HAL_DATA() and etc. */
19 #include <hal_intf.h>		/* struct hal_ops */
20 #include "../rtl8822c.h"	/* rtl8822c_sethwreg() and etc. */
21 #include "rtl8822cs.h"		/* rtl8822cs_hal_init() */
22 
intf_chip_configure(PADAPTER adapter)23 static void intf_chip_configure(PADAPTER adapter)
24 {
25 	PHAL_DATA_TYPE phal;
26 
27 	phal = GET_HAL_DATA(adapter);
28 
29 #ifdef RTW_RX_AGGREGATION
30 	phal->rxagg_mode = RX_AGG_DMA;
31 	phal->rxagg_dma_size = 0xff;
32 	phal->rxagg_dma_timeout= 0x20;
33 #endif
34 }
35 
36 /*
37  * Description:
38  *	Collect all hardware information, fill "HAL_DATA_TYPE".
39  *	Sometimes this would be used to read MAC address.
40  *	This function will do
41  *	1. Read Efuse/EEPROM to initialize
42  *	2. Read registers to initialize
43  *	3. Other vaiables initialization
44  */
read_adapter_info(PADAPTER adapter)45 static u8 read_adapter_info(PADAPTER adapter)
46 {
47 	u8 ret = _FAIL;
48 
49 	/*
50 	 * 1. Read Efuse/EEPROM to initialize
51 	 */
52 	if (rtl8822c_read_efuse(adapter) != _SUCCESS)
53 		goto exit;
54 
55 	/*
56 	 * 2. Read registers to initialize
57 	 */
58 
59 	/*
60 	 * 3. Other Initialization
61 	 */
62 
63 	ret = _SUCCESS;
64 
65 exit:
66 	return ret;
67 }
68 
rtl8822cs_get_interrupt(PADAPTER adapter,u32 * hisr,u32 * rx_len)69 void rtl8822cs_get_interrupt(PADAPTER adapter, u32 *hisr, u32 *rx_len)
70 {
71 	u8 data[8] = {0};
72 
73 
74 	rtw_read_mem(adapter, REG_SDIO_HISR_8822C, 8, data);
75 
76 	if (hisr)
77 		*hisr = le32_to_cpu(*(u32 *)data);
78 	if (rx_len)
79 		*rx_len = le32_to_cpu(*(u32 *)&data[4]);
80 }
81 
rtl8822cs_clear_interrupt(PADAPTER adapter,u32 hisr)82 void rtl8822cs_clear_interrupt(PADAPTER adapter, u32 hisr)
83 {
84 	/* Perform write one clear operation */
85 	if (hisr)
86 		rtw_write32(adapter, REG_SDIO_HISR_8822C, hisr);
87 }
88 
update_himr(PADAPTER adapter,u32 himr)89 static void update_himr(PADAPTER adapter, u32 himr)
90 {
91 	rtw_write32(adapter, REG_SDIO_HIMR_8822C, himr);
92 }
93 
94 /*
95  * Description:
96  *	Initialize SDIO Host Interrupt Mask configuration variables for future use.
97  *
98  */
init_interrupt(PADAPTER adapter)99 static void init_interrupt(PADAPTER adapter)
100 {
101 	struct hal_com_data *hal;
102 
103 
104 	hal = GET_HAL_DATA(adapter);
105 	hal->sdio_himr = (u32)(
106 				 BIT_RX_REQUEST_MSK_8822C	|
107 #ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
108 				 BIT_SDIO_AVAL_MSK_8822C		|
109 #endif /* CONFIG_SDIO_TX_ENABLE_AVAL_INT */
110 #if 0
111 				 BIT_SDIO_TXERR_MSK_8822C	|
112 				 BIT_SDIO_RXERR_MSK_8822C	|
113 				 BIT_SDIO_TXFOVW_MSK_8822C	|
114 				 BIT_SDIO_RXFOVW_MSK_8822C	|
115 				 BIT_SDIO_TXBCNOK_MSK_8822C	|
116 				 BIT_SDIO_TXBCNERR_MSK_8822C	|
117 				 BIT_SDIO_BCNERLY_INT_MSK_8822C	|
118 				 BIT_SDIO_C2HCMD_INT_MSK_8822C	|
119 #endif
120 #if defined(CONFIG_LPS_LCLK) && !defined(CONFIG_DETECT_CPWM_BY_POLLING)
121 				 BIT_SDIO_CPWM1_MSK_8822C	|
122 #if 0
123 				 BIT_SDIO_CPWM2_MSK_8822C	|
124 #endif
125 #endif /* CONFIG_LPS_LCLK && !CONFIG_DETECT_CPWM_BY_POLLING */
126 #if 0
127 				 BIT_SDIO_HSISR_IND_MSK_8822C	|
128 				 BIT_SDIO_GTINT3_MSK_8822C	|
129 				 BIT_SDIO_GTINT4_MSK_8822C	|
130 				 BIT_SDIO_PSTIMEOUT_MSK_8822C	|
131 				 BIT_SDIO_OCPINT_MSK_8822C	|
132 				 BIT_SDIIO_ATIMend_MSK_8822C	|
133 				 BIT_SDIO_ATIMend_E_MSK_8822C	|
134 				 BIT_SDIO_CTWend_MSK_8822C	|
135 				 BIT_SDIO_CRCERR_MSK_8822C	|
136 #endif
137 				 0);
138 
139 #ifdef CONFIG_SDIO_MULTI_FUNCTION_COEX
140 	if (sdio_get_num_of_func(adapter_to_dvobj(adapter)) > 1)
141 		hal->sdio_himr |= BIT_BT_INT_MASK_8822C;
142 #endif
143 }
144 
145 /*
146  * Description:
147  *	Clear corresponding SDIO Host ISR interrupt service.
148  *
149  * Assumption:
150  *	Using SDIO Local register ONLY for configuration.
151  */
152 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
clear_interrupt_all(PADAPTER adapter)153 static void clear_interrupt_all(PADAPTER adapter)
154 {
155 	PHAL_DATA_TYPE hal;
156 
157 
158 	if (rtw_is_surprise_removed(adapter))
159 		return;
160 
161 	hal = GET_HAL_DATA(adapter);
162 	rtl8822cs_clear_interrupt(adapter, 0xFFFFFFFF);
163 }
164 #endif /*#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)*/
165 /*
166  * Description:
167  *	Enalbe SDIO Host Interrupt Mask configuration on SDIO local domain.
168  *
169  * Assumption:
170  *	1. Using SDIO Local register ONLY for configuration.
171  *	2. PASSIVE LEVEL
172  */
enable_interrupt(PADAPTER adapter)173 static void enable_interrupt(PADAPTER adapter)
174 {
175 	PHAL_DATA_TYPE hal;
176 
177 
178 	hal = GET_HAL_DATA(adapter);
179 
180 	update_himr(adapter, hal->sdio_himr);
181 	RTW_INFO(FUNC_ADPT_FMT ": update SDIO HIMR=0x%08X\n",
182 		 FUNC_ADPT_ARG(adapter), hal->sdio_himr);
183 }
184 
185 /*
186  * Description:
187  *	Disable SDIO Host IMR configuration to mask unnecessary interrupt service.
188  *
189  * Assumption:
190  *	Using SDIO Local register ONLY for configuration.
191  */
disable_interrupt(PADAPTER adapter)192 static void disable_interrupt(PADAPTER adapter)
193 {
194 	PHAL_DATA_TYPE hal;
195 
196 
197 	hal = GET_HAL_DATA(adapter);
198 
199 	update_himr(adapter, 0);
200 	RTW_INFO("%s: update SDIO HIMR=0\n", __FUNCTION__);
201 }
202 
_run_thread(PADAPTER adapter)203 static void _run_thread(PADAPTER adapter)
204 {
205 #ifndef CONFIG_SDIO_TX_TASKLET
206 	struct xmit_priv *xmitpriv = &adapter->xmitpriv;
207 
208 	if (xmitpriv->SdioXmitThread == NULL) {
209 		RTW_INFO(FUNC_ADPT_FMT " start RTWHALXT\n", FUNC_ADPT_ARG(adapter));
210 		xmitpriv->SdioXmitThread = kthread_run(rtl8822cs_xmit_thread, adapter, "RTWHALXT");
211 		if (IS_ERR(xmitpriv->SdioXmitThread)) {
212 			RTW_ERR("%s: start rtl8822cs_xmit_thread FAIL!!\n", __FUNCTION__);
213 			xmitpriv->SdioXmitThread = NULL;
214 		}
215 	}
216 #endif /* !CONFIG_SDIO_TX_TASKLET */
217 }
218 
run_thread(PADAPTER adapter)219 static void run_thread(PADAPTER adapter)
220 {
221 	_run_thread(adapter);
222 	rtl8822c_run_thread(adapter);
223 }
224 
_cancel_thread(PADAPTER adapter)225 static void _cancel_thread(PADAPTER adapter)
226 {
227 #ifndef CONFIG_SDIO_TX_TASKLET
228 	struct xmit_priv *xmitpriv = &adapter->xmitpriv;
229 
230 	/* stop xmit_buf_thread */
231 	if (xmitpriv->SdioXmitThread) {
232 		_rtw_up_sema(&xmitpriv->SdioXmitSema);
233 	#ifdef SDIO_FREE_XMIT_BUF_SEMA
234 		rtw_sdio_free_xmitbuf_sema_up(xmitpriv);
235 		rtw_sdio_free_xmitbuf_sema_down(xmitpriv);
236 	#endif
237 		rtw_thread_stop(xmitpriv->SdioXmitThread);
238 		xmitpriv->SdioXmitThread = NULL;
239 	}
240 #endif /* !CONFIG_SDIO_TX_TASKLET */
241 }
242 
cancel_thread(PADAPTER adapter)243 static void cancel_thread(PADAPTER adapter)
244 {
245 	rtl8822c_cancel_thread(adapter);
246 	_cancel_thread(adapter);
247 }
248 
249 /*
250  * If variable not handled here,
251  * some variables will be processed in rtl8822c_sethwreg()
252  */
sethwreg(PADAPTER adapter,u8 variable,u8 * val)253 static u8 sethwreg(PADAPTER adapter, u8 variable, u8 *val)
254 {
255 	PHAL_DATA_TYPE hal;
256 	u8 ret = _SUCCESS;
257 	u8 val8;
258 
259 
260 	hal = GET_HAL_DATA(adapter);
261 
262 	switch (variable) {
263 	case HW_VAR_SET_RPWM:
264 		/*
265 		 * RPWM use follwoing bits:
266 		 * BIT0 - 1: 32K, 0: Normal Clock
267 		 * BIT4 - Power Gated
268 		 * BIT6 - Ack Bit
269 		 * BIT7 - Toggling Bit
270 		 */
271 		val8 = PS_STATE(*val);
272 		/*
273 		 * PS_STATE == 0 is special case for initializing,
274 		 * and keep the value to be 0
275 		 */
276 		if (val8 && (val8 < PS_STATE_S2)) {
277 			#ifdef CONFIG_LPS_PG
278 			if (adapter_to_pwrctl(adapter)->lps_level == LPS_PG)
279 				val8 = BIT_REQ_PS_8822C | BIT4;
280 			else
281 			#endif
282 				val8 = BIT_REQ_PS_8822C;
283 		} else
284 			val8 = 0;
285 
286 		if (*val & PS_ACK)
287 			val8 |= BIT_ACK_8822C;
288 		if (*val & PS_TOGGLE)
289 			val8 |= BIT_TOGGLE_8822C;
290 
291 		rtw_write8(adapter, REG_SDIO_HRPWM1_8822C, val8);
292 		break;
293 
294 	case HW_VAR_SET_REQ_FW_PS:
295 		/*
296 		 * 1. driver write 0x8f[4]=1
297 		 *    request fw ps state (only can write bit4)
298 		 */
299 	{
300 		u8 req_fw_ps = 0;
301 
302 		req_fw_ps = rtw_read8(adapter, 0x8f);
303 		req_fw_ps |= 0x10;
304 		rtw_write8(adapter, 0x8f, req_fw_ps);
305 	}
306 	break;
307 	case HW_VAR_SET_DRV_ERLY_INT:
308 		switch (*val) {
309 		#ifdef CONFIG_TDLS
310 		#ifdef CONFIG_TDLS_CH_SW
311 			case TDLS_BCN_ERLY_ON:
312 				adapter->tdlsinfo.chsw_info.bcn_early_reg_bkp = rtw_read8(adapter, REG_DRVERLYINT);
313 				rtw_write8(adapter, REG_DRVERLYINT, 20);
314 				break;
315 			case TDLS_BCN_ERLY_OFF:
316 				rtw_write8(adapter, REG_DRVERLYINT, adapter->tdlsinfo.chsw_info.bcn_early_reg_bkp);
317 				break;
318 		#endif
319 		#endif
320 		}
321 		break;
322 
323 	default:
324 		ret = rtl8822c_sethwreg(adapter, variable, val);
325 		break;
326 	}
327 
328 	return ret;
329 }
330 
331 /*
332  * If variable not handled here,
333  * some variables will be processed in GetHwReg8723B()
334  */
gethwreg(PADAPTER adapter,u8 variable,u8 * val)335 static void gethwreg(PADAPTER adapter, u8 variable, u8 *val)
336 {
337 	PHAL_DATA_TYPE hal;
338 	u8 val8;
339 
340 
341 	hal = GET_HAL_DATA(adapter);
342 
343 	switch (variable) {
344 	case HW_VAR_CPWM:
345 		val8 = rtw_read8(adapter, REG_SDIO_HCPWM1_V2_8822C);
346 
347 		if (val8 & BIT_CUR_PS_8822C)
348 			*val = PS_STATE_S0;
349 		else
350 			*val = PS_STATE_S4;
351 
352 		if (val8 & BIT_TOGGLE_8822C)
353 			*val |= PS_TOGGLE;
354 		break;
355 
356 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) || defined(CONFIG_FWLPS_IN_IPS)
357 	case HW_VAR_RPWM_TOG:
358 		*val = rtw_read8(adapter, REG_SDIO_HRPWM1_8822C);
359 		*val &= BIT_TOGGLE_8822C;
360 		break;
361 #endif
362 
363 	case HW_VAR_FW_PS_STATE:
364 		/* driver read dword 0x88 to get fw ps state */
365 		*((u16 *)val) = rtw_read16(adapter, 0x88);
366 		break;
367 
368 	default:
369 		rtl8822c_gethwreg(adapter, variable, val);
370 		break;
371 	}
372 }
373 
374 /*
375  * Description:
376  *	Query setting of specified variable.
377  */
gethaldefvar(PADAPTER adapter,HAL_DEF_VARIABLE eVariable,void * pval)378 static u8 gethaldefvar(PADAPTER adapter, HAL_DEF_VARIABLE eVariable, void *pval)
379 {
380 	PHAL_DATA_TYPE hal;
381 	u8 bResult = _SUCCESS;
382 
383 
384 	hal = GET_HAL_DATA(adapter);
385 
386 	switch (eVariable) {
387 	case HW_VAR_MAX_RX_AMPDU_FACTOR:
388 		/* Default use MAX size */
389 		*(HT_CAP_AMPDU_FACTOR *)pval = MAX_AMPDU_FACTOR_64K;
390 		break;
391 
392 	default:
393 		bResult = rtl8822c_gethaldefvar(adapter, eVariable, pval);
394 		break;
395 	}
396 
397 	return bResult;
398 }
399 
400 /*
401  * Description:
402  *	Change default setting of specified variable.
403  */
sethaldefvar(PADAPTER adapter,HAL_DEF_VARIABLE eVariable,void * pval)404 static u8 sethaldefvar(PADAPTER adapter, HAL_DEF_VARIABLE eVariable, void *pval)
405 {
406 	PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
407 	u8 bResult = _SUCCESS;
408 
409 	switch (eVariable) {
410 	default:
411 		bResult = rtl8822c_sethaldefvar(adapter, eVariable, pval);
412 		break;
413 	}
414 
415 	return bResult;
416 }
417 
rtl8822cs_set_hal_ops(PADAPTER adapter)418 void rtl8822cs_set_hal_ops(PADAPTER adapter)
419 {
420 	struct hal_ops *ops;
421 	int err;
422 
423 
424 	err = rtl8822cs_halmac_init_adapter(adapter);
425 	if (err) {
426 		RTW_INFO("%s: [ERROR]HALMAC initialize FAIL!\n", __FUNCTION__);
427 		return;
428 	}
429 
430 	rtl8822c_set_hal_ops(adapter);
431 	init_interrupt(adapter);
432 
433 	ops = &adapter->hal_func;
434 
435 	ops->init_default_value = rtl8822cs_init_default_value;
436 	ops->intf_chip_configure = intf_chip_configure;
437 	ops->read_adapter_info = read_adapter_info;
438 
439 	ops->hal_init = rtl8822cs_init;
440 	ops->hal_deinit = rtl8822cs_deinit;
441 
442 	ops->init_xmit_priv = rtl8822cs_init_xmit_priv;
443 	ops->free_xmit_priv = rtl8822cs_free_xmit_priv;
444 	ops->hal_xmit = rtl8822cs_hal_xmit;
445 	ops->mgnt_xmit = rtl8822cs_mgnt_xmit;
446 #ifdef CONFIG_RTW_MGMT_QUEUE
447 	ops->hal_mgmt_xmitframe_enqueue = rtl8822cs_hal_mgmt_xmit_enqueue;
448 #endif
449 	ops->hal_xmitframe_enqueue = rtl8822cs_hal_xmit_enqueue;
450 #ifdef CONFIG_XMIT_THREAD_MODE
451 	ops->xmit_thread_handler = rtl8822cs_xmit_buf_handler;
452 #endif
453 	ops->run_thread = run_thread;
454 	ops->cancel_thread = cancel_thread;
455 
456 	ops->init_recv_priv = rtl8822cs_init_recv_priv;
457 	ops->free_recv_priv = rtl8822cs_free_recv_priv;
458 #ifdef CONFIG_RECV_THREAD_MODE
459 	ops->recv_hdl = rtl8822cs_recv_hdl;
460 #endif
461 
462 	ops->enable_interrupt = enable_interrupt;
463 	ops->disable_interrupt = disable_interrupt;
464 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
465 	ops->clear_interrupt = clear_interrupt_all;
466 #endif
467 
468 #ifdef CONFIG_RTW_SW_LED
469 	ops->InitSwLeds = rtl8822cs_initswleds;
470 	ops->DeInitSwLeds = rtl8822cs_deinitswleds;
471 #endif
472 	ops->set_hw_reg_handler = sethwreg;
473 	ops->GetHwRegHandler = gethwreg;
474 	ops->get_hal_def_var_handler = gethaldefvar;
475 	ops->SetHalDefVarHandler = sethaldefvar;
476 }
477 
478 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
rtl8822cs_disable_interrupt_but_cpwm2(PADAPTER adapter)479 void rtl8822cs_disable_interrupt_but_cpwm2(PADAPTER adapter)
480 {
481 	u32 himr, tmp;
482 
483 	tmp = rtw_read32(adapter, REG_SDIO_HIMR);
484 	RTW_INFO("%s: Read SDIO_REG_HIMR: 0x%08x\n", __FUNCTION__, tmp);
485 
486 	himr = BIT_SDIO_CPWM2_MSK;
487 	update_himr(adapter, himr);
488 
489 	tmp = rtw_read32(adapter, REG_SDIO_HIMR);
490 	RTW_INFO("%s: Read again SDIO_REG_HIMR: 0x%08x\n", __FUNCTION__, tmp);
491 }
492 #endif /* CONFIG_WOWLAN */
493