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_HALINIT_C_
16
17 #include <drv_types.h> /* PADAPTER, basic_types.h and etc. */
18 #include <hal_data.h> /* HAL_DATA_TYPE */
19 #include "../../hal_halmac.h" /* rtw_halmac_query_tx_page_num() */
20 #include "../rtl8822b.h" /* rtl8822b_hal_init(), rtl8822b_phy_init_haldm() and etc. */
21
22
23 #ifdef CONFIG_FWLPS_IN_IPS
fw_ips_leave(struct _ADAPTER * a)24 static u8 fw_ips_leave(struct _ADAPTER *a)
25 {
26 struct sreset_priv *psrtpriv = &GET_HAL_DATA(a)->srestpriv;
27 struct debug_priv *pdbgpriv = &adapter_to_dvobj(a)->drv_dbg;
28 struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(a);
29 systime start_time;
30 u8 cpwm_orig, cpwm_now, rpwm;
31 u8 bMacPwrCtrlOn = _TRUE;
32
33
34 if ((pwrctl->bips_processing == _FALSE)
35 || (psrtpriv->silent_reset_inprogress == _TRUE)
36 || (GET_HAL_DATA(a)->bFWReady == _FALSE)
37 || (pwrctl->pre_ips_type != 0))
38 return _FAIL;
39
40 RTW_INFO("%s: Leaving FW_IPS\n", __func__);
41
42 /* for polling cpwm */
43 cpwm_orig = 0;
44 rtw_hal_get_hwreg(a, HW_VAR_CPWM, &cpwm_orig);
45
46 /* set rpwm */
47 #if 1
48 rtw_hal_get_hwreg(a, HW_VAR_RPWM_TOG, &rpwm);
49 rpwm += 0x80;
50 #else
51 rpwm = pwrctl->tog;
52 #endif
53 rpwm |= PS_ACK;
54 rtw_hal_set_hwreg(a, HW_VAR_SET_RPWM, (u8 *)(&rpwm));
55 RTW_INFO("%s: write rpwm=%02x\n", __FUNCTION__, rpwm);
56
57 pwrctl->tog = (rpwm + 0x80) & 0x80;
58
59 /* do polling cpwm */
60 start_time = rtw_get_current_time();
61 do {
62 rtw_mdelay_os(1);
63
64 rtw_hal_get_hwreg(a, HW_VAR_CPWM, &cpwm_now);
65 if ((cpwm_orig ^ cpwm_now) & 0x80) {
66 #ifdef DBG_CHECK_FW_PS_STATE
67 RTW_INFO("%s: polling cpwm ok when leaving IPS in FWLPS state,"
68 " cost %d ms,"
69 " cpwm_orig=0x%02x, cpwm_now=0x%02x, 0x100=0x%x\n",
70 __FUNCTION__,
71 rtw_get_passing_time_ms(start_time),
72 cpwm_orig, cpwm_now, rtw_read8(a, REG_CR_8822B));
73 #endif /* DBG_CHECK_FW_PS_STATE */
74 break;
75 }
76
77 if (rtw_get_passing_time_ms(start_time) > 100) {
78 RTW_ERR("%s: polling cpwm timeout when leaving IPS in FWLPS state\n", __FUNCTION__);
79 break;
80 }
81 } while (1);
82
83 rtl8822b_set_FwPwrModeInIPS_cmd(a, 0);
84
85 rtw_hal_set_hwreg(a, HW_VAR_APFM_ON_MAC, &bMacPwrCtrlOn);
86
87 #ifdef DBG_CHECK_FW_PS_STATE
88 if (rtw_fw_ps_state(a) == _FAIL) {
89 RTW_INFO("after hal init, fw ps state in 32k\n");
90 pdbgpriv->dbg_ips_drvopen_fail_cnt++;
91 }
92 #endif /* DBG_CHECK_FW_PS_STATE */
93
94 return _SUCCESS;
95 }
96
fw_ips_enter(struct _ADAPTER * a)97 static u8 fw_ips_enter(struct _ADAPTER *a)
98 {
99 struct sreset_priv *psrtpriv = &GET_HAL_DATA(a)->srestpriv;
100 struct debug_priv *pdbgpriv = &adapter_to_dvobj(a)->drv_dbg;
101 struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(a);
102 systime start_time;
103 int cnt = 0;
104 u8 val8 = 0, rpwm;
105
106
107 if ((pwrctl->bips_processing == _FALSE)
108 || (psrtpriv->silent_reset_inprogress == _TRUE)
109 || (GET_HAL_DATA(a)->bFWReady == _FALSE)
110 || (a->netif_up == _FALSE)) {
111 pdbgpriv->dbg_carddisable_cnt++;
112 pwrctl->pre_ips_type = 1;
113
114 return _FAIL;
115 }
116
117 RTW_INFO("%s: issue H2C to FW when entering IPS\n", __FUNCTION__);
118 rtl8822b_set_FwPwrModeInIPS_cmd(a, 0x1);
119
120 /*
121 * poll 0x1cc to make sure H2C command already finished by FW;
122 * MAC_0x1cc=0 means H2C done by FW.
123 */
124 start_time = rtw_get_current_time();
125 do {
126 rtw_mdelay_os(10);
127 val8 = rtw_read8(a, REG_HMETFR_8822B);
128 cnt++;
129 if (!val8)
130 break;
131
132 if (rtw_get_passing_time_ms(start_time) > 100) {
133 RTW_ERR("%s: fail to wait H2C, REG_HMETFR=0x%x, cnt=%d\n",
134 __FUNCTION__, val8, cnt);
135 #ifdef DBG_CHECK_FW_PS_STATE
136 RTW_WARN("MAC_1C0=0x%08x, MAC_1C4=0x%08x, MAC_1C8=0x%08x, MAC_1CC=0x%08x\n",
137 rtw_read32(a, 0x1c0), rtw_read32(a, 0x1c4),
138 rtw_read32(a, 0x1c8), rtw_read32(a, REG_HMETFR_8822B));
139 #endif /* DBG_CHECK_FW_PS_STATE */
140 goto exit;
141 }
142 } while (1);
143
144 /* H2C done, enter 32k */
145 /* set rpwm to enter 32k */
146 #if 1
147 rtw_hal_get_hwreg(a, HW_VAR_RPWM_TOG, &rpwm);
148 rpwm += 0x80;
149 #else
150 rpwm = pwrctl->tog;
151 #endif
152 rpwm |= PS_STATE_S0;
153 rtw_hal_set_hwreg(a, HW_VAR_SET_RPWM, &rpwm);
154 RTW_INFO("%s: write rpwm=%02x\n", __FUNCTION__, rpwm);
155 pwrctl->tog = (rpwm + 0x80) & 0x80;
156
157 cnt = val8 = 0;
158 start_time = rtw_get_current_time();
159 do {
160 val8 = rtw_read8(a, REG_CR_8822B);
161 cnt++;
162 RTW_INFO("%s: polling 0x100=0x%x, cnt=%d\n",
163 __FUNCTION__, val8, cnt);
164 if (val8 == 0xEA) {
165 RTW_INFO("%s: polling 0x100=0xEA, cnt=%d, cost %d ms\n",
166 __FUNCTION__, cnt,
167 rtw_get_passing_time_ms(start_time));
168 break;
169 }
170
171 if (rtw_get_passing_time_ms(start_time) > 100) {
172 RTW_ERR("%s: polling polling 0x100=0xEA timeout! cnt=%d\n",
173 __FUNCTION__, cnt);
174 #ifdef DBG_CHECK_FW_PS_STATE
175 RTW_WARN("MAC_1C0=0x%08x, MAC_1C4=0x%08x, MAC_1C8=0x%08x, MAC_1CC=0x%08x\n",
176 rtw_read32(a, 0x1c0), rtw_read32(a, 0x1c4),
177 rtw_read32(a, 0x1c8), rtw_read32(a, REG_HMETFR_8822B));
178 #endif /* DBG_CHECK_FW_PS_STATE */
179 break;
180 }
181
182 rtw_mdelay_os(10);
183 } while (1);
184
185 exit:
186 RTW_INFO("polling done when entering IPS, check result: 0x100=0x%02x, cnt=%d, MAC_1cc=0x%02x\n",
187 rtw_read8(a, REG_CR_8822B), cnt, rtw_read8(a, REG_HMETFR_8822B));
188
189 pwrctl->pre_ips_type = 0;
190
191 return _SUCCESS;
192 }
193 #endif /* CONFIG_FWLPS_IN_IPS */
194
rtl8822bs_init(PADAPTER adapter)195 u32 rtl8822bs_init(PADAPTER adapter)
196 {
197 u8 ok = _TRUE;
198 PHAL_DATA_TYPE hal;
199
200
201 hal = GET_HAL_DATA(adapter);
202
203 #ifdef CONFIG_FWLPS_IN_IPS
204 if (fw_ips_leave(adapter) == _SUCCESS)
205 return _SUCCESS;
206 #endif
207 ok = rtl8822b_hal_init(adapter);
208 if (_FALSE == ok)
209 return _FAIL;
210
211 rtw_halmac_query_tx_page_num(adapter_to_dvobj(adapter));
212
213 rtl8822b_mac_verify(adapter);
214
215 rtl8822b_phy_init_haldm(adapter);
216 #ifdef CONFIG_BEAMFORMING
217 rtl8822b_phy_bf_init(adapter);
218 #endif
219
220 #ifdef CONFIG_FW_MULTI_PORT_SUPPORT
221 /*HW /FW init*/
222 rtw_hal_set_default_port_id_cmd(adapter, 0);
223 #endif
224
225 #ifdef CONFIG_BT_COEXIST
226 /* Init BT hw config. */
227 if (hal->EEPROMBluetoothCoexist == _TRUE) {
228 rtw_btcoex_HAL_Initialize(adapter, _FALSE);
229 #ifdef CONFIG_FW_MULTI_PORT_SUPPORT
230 rtw_hal_set_wifi_btc_port_id_cmd(adapter);
231 #endif
232 } else
233 #endif /* CONFIG_BT_COEXIST */
234 rtw_btcoex_wifionly_hw_config(adapter);
235
236 rtl8822b_init_misc(adapter);
237
238 return _SUCCESS;
239 }
240
rtl8822bs_deinit(PADAPTER adapter)241 u32 rtl8822bs_deinit(PADAPTER adapter)
242 {
243 #ifdef CONFIG_FWLPS_IN_IPS
244 if (fw_ips_enter(adapter) == _SUCCESS)
245 return _SUCCESS;
246 #endif
247
248 return rtl8822b_deinit(adapter);
249 }
250
rtl8822bs_init_default_value(PADAPTER adapter)251 void rtl8822bs_init_default_value(PADAPTER adapter)
252 {
253 PHAL_DATA_TYPE hal;
254
255
256 hal = GET_HAL_DATA(adapter);
257
258 rtl8822b_init_default_value(adapter);
259
260 /* interface related variable */
261 hal->SdioRxFIFOCnt = 0;
262 }
263