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