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