1 /******************************************************************************
2 *
3 * Copyright(c) 2015 - 2019 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 _RTL8822BS_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 "../rtl8822b.h" /* rtl8822b_sethwreg() and etc. */
21 #include "rtl8822bs.h" /* rtl8822bs_hal_init() */
22
intf_chip_configure(PADAPTER adapter)23 static void intf_chip_configure(PADAPTER adapter)
24 {
25 }
26
27 /*
28 * Description:
29 * Collect all hardware information, fill "HAL_DATA_TYPE".
30 * Sometimes this would be used to read MAC address.
31 * This function will do
32 * 1. Read Efuse/EEPROM to initialize
33 * 2. Read registers to initialize
34 * 3. Other vaiables initialization
35 */
read_adapter_info(PADAPTER adapter)36 static u8 read_adapter_info(PADAPTER adapter)
37 {
38 u8 ret = _FAIL;
39
40 /*
41 * 1. Read Efuse/EEPROM to initialize
42 */
43 if (rtl8822b_read_efuse(adapter) != _SUCCESS)
44 goto exit;
45
46 /*
47 * 2. Read registers to initialize
48 */
49
50 /*
51 * 3. Other Initialization
52 */
53
54 ret = _SUCCESS;
55
56 exit:
57 return ret;
58 }
59
rtl8822bs_get_interrupt(PADAPTER adapter,u32 * hisr,u16 * rx_len)60 void rtl8822bs_get_interrupt(PADAPTER adapter, u32 *hisr, u16 *rx_len)
61 {
62 u8 data[8] = {0};
63
64
65 rtw_read_mem(adapter, REG_SDIO_HISR_8822B, 8, data);
66
67 if (hisr)
68 *hisr = le32_to_cpu(*(u32 *)data);
69 if (rx_len)
70 *rx_len = le16_to_cpu(*(u16 *)&data[4]);
71 }
72
rtl8822bs_clear_interrupt(PADAPTER adapter,u32 hisr)73 void rtl8822bs_clear_interrupt(PADAPTER adapter, u32 hisr)
74 {
75 /* Perform write one clear operation */
76 if (hisr)
77 rtw_write32(adapter, REG_SDIO_HISR_8822B, hisr);
78 }
79
update_himr(PADAPTER adapter,u32 himr)80 static void update_himr(PADAPTER adapter, u32 himr)
81 {
82 rtw_write32(adapter, REG_SDIO_HIMR_8822B, himr);
83 }
84
85 /*
86 * Description:
87 * Initialize SDIO Host Interrupt Mask configuration variables for future use.
88 *
89 */
init_interrupt(PADAPTER adapter)90 static void init_interrupt(PADAPTER adapter)
91 {
92 struct hal_com_data *hal;
93
94
95 hal = GET_HAL_DATA(adapter);
96 hal->sdio_himr = (u32)(
97 BIT_RX_REQUEST_MSK_8822B |
98 #ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
99 BIT_SDIO_AVAL_MSK_8822B |
100 #endif /* CONFIG_SDIO_TX_ENABLE_AVAL_INT */
101 #if 0
102 BIT_SDIO_TXERR_MSK_8822B |
103 BIT_SDIO_RXERR_MSK_8822B |
104 BIT_SDIO_TXFOVW_MSK_8822B |
105 BIT_SDIO_RXFOVW_MSK_8822B |
106 BIT_SDIO_TXBCNOK_MSK_8822B |
107 BIT_SDIO_TXBCNERR_MSK_8822B |
108 BIT_SDIO_BCNERLY_INT_MSK_8822B |
109 BIT_SDIO_C2HCMD_INT_MSK_8822B |
110 #endif
111 #if defined(CONFIG_LPS_LCLK) && !defined(CONFIG_DETECT_CPWM_BY_POLLING)
112 BIT_SDIO_CPWM1_MSK_8822B |
113 #if 0
114 BIT_SDIO_CPWM2_MSK_8822B |
115 #endif
116 #endif /* CONFIG_LPS_LCLK && !CONFIG_DETECT_CPWM_BY_POLLING */
117 #if 0
118 BIT_SDIO_HSISR_IND_MSK_8822B |
119 BIT_SDIO_GTINT3_MSK_8822B |
120 BIT_SDIO_GTINT4_MSK_8822B |
121 BIT_SDIO_PSTIMEOUT_MSK_8822B |
122 BIT_SDIO_OCPINT_MSK_8822B |
123 BIT_SDIIO_ATIMend_MSK_8822B |
124 BIT_SDIO_ATIMend_E_MSK_8822B |
125 BIT_SDIO_CTWend_MSK_8822B |
126 BIT_SDIO_CRCERR_MSK_8822B |
127 #endif
128 0);
129 }
130
131 /*
132 * Description:
133 * Clear corresponding SDIO Host ISR interrupt service.
134 *
135 * Assumption:
136 * Using SDIO Local register ONLY for configuration.
137 */
138 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
clear_interrupt_all(PADAPTER adapter)139 static void clear_interrupt_all(PADAPTER adapter)
140 {
141 PHAL_DATA_TYPE hal;
142
143
144 if (rtw_is_surprise_removed(adapter))
145 return;
146
147 hal = GET_HAL_DATA(adapter);
148 rtl8822bs_clear_interrupt(adapter, 0xFFFFFFFF);
149 }
150 #endif /*#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)*/
151 /*
152 * Description:
153 * Enalbe SDIO Host Interrupt Mask configuration on SDIO local domain.
154 *
155 * Assumption:
156 * 1. Using SDIO Local register ONLY for configuration.
157 * 2. PASSIVE LEVEL
158 */
enable_interrupt(PADAPTER adapter)159 static void enable_interrupt(PADAPTER adapter)
160 {
161 PHAL_DATA_TYPE hal;
162
163
164 hal = GET_HAL_DATA(adapter);
165
166 update_himr(adapter, hal->sdio_himr);
167 RTW_INFO(FUNC_ADPT_FMT ": update SDIO HIMR=0x%08X\n",
168 FUNC_ADPT_ARG(adapter), hal->sdio_himr);
169 }
170
171 /*
172 * Description:
173 * Disable SDIO Host IMR configuration to mask unnecessary interrupt service.
174 *
175 * Assumption:
176 * Using SDIO Local register ONLY for configuration.
177 */
disable_interrupt(PADAPTER adapter)178 static void disable_interrupt(PADAPTER adapter)
179 {
180 PHAL_DATA_TYPE hal;
181
182
183 hal = GET_HAL_DATA(adapter);
184
185 update_himr(adapter, 0);
186 RTW_INFO("%s: update SDIO HIMR=0\n", __FUNCTION__);
187 }
188
_run_thread(PADAPTER adapter)189 static void _run_thread(PADAPTER adapter)
190 {
191 #ifndef CONFIG_SDIO_TX_TASKLET
192 struct xmit_priv *xmitpriv = &adapter->xmitpriv;
193
194 if (xmitpriv->SdioXmitThread == NULL) {
195 RTW_INFO(FUNC_ADPT_FMT " start RTWHALXT\n", FUNC_ADPT_ARG(adapter));
196 xmitpriv->SdioXmitThread = kthread_run(rtl8822bs_xmit_thread, adapter, "RTWHALXT");
197 if (IS_ERR(xmitpriv->SdioXmitThread)) {
198 RTW_ERR("%s: start rtl8822bs_xmit_thread FAIL!!\n", __FUNCTION__);
199 xmitpriv->SdioXmitThread = NULL;
200 }
201 }
202 #endif /* !CONFIG_SDIO_TX_TASKLET */
203 }
204
run_thread(PADAPTER adapter)205 static void run_thread(PADAPTER adapter)
206 {
207 _run_thread(adapter);
208 rtl8822b_run_thread(adapter);
209 }
210
_cancel_thread(PADAPTER adapter)211 static void _cancel_thread(PADAPTER adapter)
212 {
213 #ifndef CONFIG_SDIO_TX_TASKLET
214 struct xmit_priv *xmitpriv = &adapter->xmitpriv;
215
216 /* stop xmit_buf_thread */
217 if (xmitpriv->SdioXmitThread) {
218 _rtw_up_sema(&xmitpriv->SdioXmitSema);
219 rtw_thread_stop(xmitpriv->SdioXmitThread);
220 xmitpriv->SdioXmitThread = NULL;
221 }
222 #endif /* !CONFIG_SDIO_TX_TASKLET */
223 }
224
cancel_thread(PADAPTER adapter)225 static void cancel_thread(PADAPTER adapter)
226 {
227 rtl8822b_cancel_thread(adapter);
228 _cancel_thread(adapter);
229 }
230
231 /*
232 * If variable not handled here,
233 * some variables will be processed in rtl8822b_sethwreg()
234 */
sethwreg(PADAPTER adapter,u8 variable,u8 * val)235 static u8 sethwreg(PADAPTER adapter, u8 variable, u8 *val)
236 {
237 PHAL_DATA_TYPE hal;
238 u8 ret = _SUCCESS;
239 u8 val8;
240
241
242 hal = GET_HAL_DATA(adapter);
243
244 switch (variable) {
245 case HW_VAR_SET_RPWM:
246 /*
247 * RPWM use follwoing bits:
248 * BIT0 - 1: 32K, 0: Normal Clock
249 * BIT6 - Ack Bit
250 * BIT7 - Toggling Bit
251 */
252 val8 = PS_STATE(*val);
253 /*
254 * PS_STATE == 0 is special case for initializing,
255 * and keep the value to be 0
256 */
257 if (val8 && (val8 < PS_STATE_S2))
258 val8 = BIT_REQ_PS_8822B;
259 else
260 val8 = 0;
261
262 if (*val & PS_ACK)
263 val8 |= BIT_ACK_8822B;
264 if (*val & PS_TOGGLE)
265 val8 |= BIT_TOGGLE_8822B;
266
267 rtw_write8(adapter, REG_SDIO_HRPWM1_8822B, val8);
268 break;
269
270 default:
271 ret = rtl8822b_sethwreg(adapter, variable, val);
272 break;
273 }
274
275 return ret;
276 }
277
278 /*
279 * If variable not handled here,
280 * some variables will be processed in GetHwReg8723B()
281 */
gethwreg(PADAPTER adapter,u8 variable,u8 * val)282 static void gethwreg(PADAPTER adapter, u8 variable, u8 *val)
283 {
284 PHAL_DATA_TYPE hal;
285 u8 val8;
286
287
288 hal = GET_HAL_DATA(adapter);
289
290 switch (variable) {
291 case HW_VAR_CPWM:
292 val8 = rtw_read8(adapter, REG_SDIO_HCPWM1_V2_8822B);
293
294 if (val8 & BIT_CUR_PS_8822B)
295 *val = PS_STATE_S0;
296 else
297 *val = PS_STATE_S4;
298
299 if (val8 & BIT_TOGGLE_8822B)
300 *val |= PS_TOGGLE;
301 break;
302
303 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) || defined(CONFIG_FWLPS_IN_IPS)
304 case HW_VAR_RPWM_TOG:
305 *val = rtw_read8(adapter, REG_SDIO_HRPWM1_8822B);
306 *val &= BIT_TOGGLE_8822B;
307 break;
308 #endif
309
310 default:
311 rtl8822b_gethwreg(adapter, variable, val);
312 break;
313 }
314 }
315
316 /*
317 * Description:
318 * Query setting of specified variable.
319 */
gethaldefvar(PADAPTER adapter,HAL_DEF_VARIABLE eVariable,void * pval)320 static u8 gethaldefvar(PADAPTER adapter, HAL_DEF_VARIABLE eVariable, void *pval)
321 {
322 PHAL_DATA_TYPE hal;
323 u8 bResult = _SUCCESS;
324
325
326 hal = GET_HAL_DATA(adapter);
327
328 switch (eVariable) {
329 case HW_VAR_MAX_RX_AMPDU_FACTOR:
330 if (check_fwstate(&adapter->mlmepriv, WIFI_AP_STATE) == _TRUE)
331 /* Set AMPDU Factor 32K for AP mode */
332 *(HT_CAP_AMPDU_FACTOR *)pval = MAX_AMPDU_FACTOR_32K;
333 else
334 /* Default use MAX size */
335 *(HT_CAP_AMPDU_FACTOR *)pval = MAX_AMPDU_FACTOR_64K;
336 break;
337
338 default:
339 bResult = rtl8822b_gethaldefvar(adapter, eVariable, pval);
340 break;
341 }
342
343 return bResult;
344 }
345
346 /*
347 * Description:
348 * Change default setting of specified variable.
349 */
sethaldefvar(PADAPTER adapter,HAL_DEF_VARIABLE eVariable,void * pval)350 static u8 sethaldefvar(PADAPTER adapter, HAL_DEF_VARIABLE eVariable, void *pval)
351 {
352 PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
353 u8 bResult = _SUCCESS;
354
355 switch (eVariable) {
356 default:
357 bResult = rtl8822b_sethaldefvar(adapter, eVariable, pval);
358 break;
359 }
360
361 return bResult;
362 }
363
rtl8822bs_set_hal_ops(PADAPTER adapter)364 void rtl8822bs_set_hal_ops(PADAPTER adapter)
365 {
366 struct hal_ops *ops;
367 int err;
368
369
370 err = rtl8822bs_halmac_init_adapter(adapter);
371 if (err) {
372 RTW_INFO("%s: [ERROR]HALMAC initialize FAIL!\n", __FUNCTION__);
373 return;
374 }
375
376 rtl8822b_set_hal_ops(adapter);
377 init_interrupt(adapter);
378
379 ops = &adapter->hal_func;
380
381 ops->init_default_value = rtl8822bs_init_default_value;
382 ops->intf_chip_configure = intf_chip_configure;
383 ops->read_adapter_info = read_adapter_info;
384
385 ops->hal_init = rtl8822bs_init;
386 ops->hal_deinit = rtl8822bs_deinit;
387
388 ops->init_xmit_priv = rtl8822bs_init_xmit_priv;
389 ops->free_xmit_priv = rtl8822bs_free_xmit_priv;
390 ops->hal_xmit = rtl8822bs_hal_xmit;
391 ops->mgnt_xmit = rtl8822bs_mgnt_xmit;
392 ops->hal_xmitframe_enqueue = rtl8822bs_hal_xmit_enqueue;
393 #ifdef CONFIG_XMIT_THREAD_MODE
394 ops->xmit_thread_handler = rtl8822bs_xmit_buf_handler;
395 #endif
396 ops->run_thread = run_thread;
397 ops->cancel_thread = cancel_thread;
398
399 ops->init_recv_priv = rtl8822bs_init_recv_priv;
400 ops->free_recv_priv = rtl8822bs_free_recv_priv;
401 #ifdef CONFIG_RECV_THREAD_MODE
402 ops->recv_hdl = rtl8822bs_recv_hdl;
403 #endif
404
405 ops->enable_interrupt = enable_interrupt;
406 ops->disable_interrupt = disable_interrupt;
407 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
408 ops->clear_interrupt = clear_interrupt_all;
409 #endif
410
411 #ifdef CONFIG_RTW_SW_LED
412 ops->InitSwLeds = rtl8822bs_initswleds;
413 ops->DeInitSwLeds = rtl8822bs_deinitswleds;
414 #endif
415 ops->set_hw_reg_handler = sethwreg;
416 ops->GetHwRegHandler = gethwreg;
417 ops->get_hal_def_var_handler = gethaldefvar;
418 ops->SetHalDefVarHandler = sethaldefvar;
419 }
420
421 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
rtl8822bs_disable_interrupt_but_cpwm2(PADAPTER adapter)422 void rtl8822bs_disable_interrupt_but_cpwm2(PADAPTER adapter)
423 {
424 u32 himr, tmp;
425
426 tmp = rtw_read32(adapter, REG_SDIO_HIMR);
427 RTW_INFO("%s: Read SDIO_REG_HIMR: 0x%08x\n", __FUNCTION__, tmp);
428
429 himr = BIT_SDIO_CPWM2_MSK;
430 update_himr(adapter, himr);
431
432 tmp = rtw_read32(adapter, REG_SDIO_HIMR);
433 RTW_INFO("%s: Read again SDIO_REG_HIMR: 0x%08x\n", __FUNCTION__, tmp);
434 }
435 #endif /* CONFIG_WOWLAN */
436