xref: /linux/drivers/net/wireless/realtek/rtlwifi/rtl8192d/fw_common.c (revision 621cde16e49b3ecf7d59a8106a20aaebfb4a59a9)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2009-2012  Realtek Corporation.*/
3 
4 #include "../wifi.h"
5 #include "../pci.h"
6 #include "../base.h"
7 #include "../efuse.h"
8 #include "def.h"
9 #include "reg.h"
10 #include "fw_common.h"
11 
rtl92d_is_fw_downloaded(struct rtl_priv * rtlpriv)12 bool rtl92d_is_fw_downloaded(struct rtl_priv *rtlpriv)
13 {
14 	return !!(rtl_read_dword(rtlpriv, REG_MCUFWDL) & MCUFWDL_RDY);
15 }
16 EXPORT_SYMBOL_GPL(rtl92d_is_fw_downloaded);
17 
rtl92d_enable_fw_download(struct ieee80211_hw * hw,bool enable)18 void rtl92d_enable_fw_download(struct ieee80211_hw *hw, bool enable)
19 {
20 	struct rtl_priv *rtlpriv = rtl_priv(hw);
21 	u8 tmp;
22 
23 	if (enable) {
24 		tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
25 		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmp | 0x04);
26 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
27 		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
28 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
29 		rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
30 	} else {
31 		tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
32 		rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
33 		/* Reserved for fw extension.
34 		 * 0x81[7] is used for mac0 status ,
35 		 * so don't write this reg here
36 		 * rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
37 		 */
38 	}
39 }
40 EXPORT_SYMBOL_GPL(rtl92d_enable_fw_download);
41 
rtl92d_write_fw(struct ieee80211_hw * hw,enum version_8192d version,u8 * buffer,u32 size)42 void rtl92d_write_fw(struct ieee80211_hw *hw,
43 		     enum version_8192d version, u8 *buffer, u32 size)
44 {
45 	struct rtl_priv *rtlpriv = rtl_priv(hw);
46 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
47 	u8 *bufferptr = buffer;
48 	u32 pagenums, remainsize;
49 	u32 page, offset;
50 
51 	rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size);
52 
53 	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE)
54 		rtl_fill_dummy(bufferptr, &size);
55 
56 	pagenums = size / FW_8192D_PAGE_SIZE;
57 	remainsize = size % FW_8192D_PAGE_SIZE;
58 
59 	if (pagenums > 8)
60 		pr_err("Page numbers should not greater then 8\n");
61 
62 	for (page = 0; page < pagenums; page++) {
63 		offset = page * FW_8192D_PAGE_SIZE;
64 		rtl_fw_page_write(hw, page, (bufferptr + offset),
65 				  FW_8192D_PAGE_SIZE);
66 	}
67 
68 	if (remainsize) {
69 		offset = pagenums * FW_8192D_PAGE_SIZE;
70 		page = pagenums;
71 		rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize);
72 	}
73 }
74 EXPORT_SYMBOL_GPL(rtl92d_write_fw);
75 
rtl92d_fw_free_to_go(struct ieee80211_hw * hw)76 int rtl92d_fw_free_to_go(struct ieee80211_hw *hw)
77 {
78 	struct rtl_priv *rtlpriv = rtl_priv(hw);
79 	u32 counter = 0;
80 	u32 value32;
81 
82 	do {
83 		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
84 	} while ((counter++ < FW_8192D_POLLING_TIMEOUT_COUNT) &&
85 		 (!(value32 & FWDL_CHKSUM_RPT)));
86 
87 	if (counter >= FW_8192D_POLLING_TIMEOUT_COUNT) {
88 		pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n",
89 		       value32);
90 		return -EIO;
91 	}
92 
93 	value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
94 	value32 |= MCUFWDL_RDY;
95 	rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
96 
97 	return 0;
98 }
99 EXPORT_SYMBOL_GPL(rtl92d_fw_free_to_go);
100 
101 #define RTL_USB_DELAY_FACTOR		60
102 
rtl92d_firmware_selfreset(struct ieee80211_hw * hw)103 void rtl92d_firmware_selfreset(struct ieee80211_hw *hw)
104 {
105 	struct rtl_priv *rtlpriv = rtl_priv(hw);
106 	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
107 	u8 u1b_tmp;
108 	u8 delay = 100;
109 
110 	if (rtlhal->interface == INTF_USB) {
111 		delay *= RTL_USB_DELAY_FACTOR;
112 
113 		rtl_write_byte(rtlpriv, REG_FSIMR, 0);
114 
115 		/* We need to disable other HRCV INT to influence 8051 reset. */
116 		rtl_write_byte(rtlpriv, REG_FWIMR, 0x20);
117 
118 		/* Close mask to prevent incorrect FW write operation. */
119 		rtl_write_byte(rtlpriv, REG_FTIMR, 0);
120 	}
121 
122 	/* Set (REG_HMETFR + 3) to  0x20 is reset 8051 */
123 	rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
124 
125 	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
126 
127 	while (u1b_tmp & (FEN_CPUEN >> 8)) {
128 		delay--;
129 		if (delay == 0)
130 			break;
131 		udelay(50);
132 		u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
133 	}
134 
135 	if (rtlhal->interface == INTF_USB) {
136 		if ((u1b_tmp & (FEN_CPUEN >> 8)) && delay == 0)
137 			rtl_write_byte(rtlpriv, REG_FWIMR, 0);
138 	}
139 
140 	WARN_ONCE((delay <= 0), "rtl8192de: 8051 reset failed!\n");
141 	rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
142 		"=====> 8051 reset success (%d)\n", delay);
143 }
144 EXPORT_SYMBOL_GPL(rtl92d_firmware_selfreset);
145 
rtl92d_fw_init(struct ieee80211_hw * hw)146 int rtl92d_fw_init(struct ieee80211_hw *hw)
147 {
148 	struct rtl_priv *rtlpriv = rtl_priv(hw);
149 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
150 	u32 counter;
151 
152 	rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG, "FW already have download\n");
153 	/* polling for FW ready */
154 	counter = 0;
155 	do {
156 		if (rtlhal->interfaceindex == 0) {
157 			if (rtl_read_byte(rtlpriv, FW_MAC0_READY) &
158 			    MAC0_READY) {
159 				rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
160 					"Polling FW ready success!! REG_MCUFWDL: 0x%x\n",
161 					rtl_read_byte(rtlpriv,
162 						      FW_MAC0_READY));
163 				return 0;
164 			}
165 			udelay(5);
166 		} else {
167 			if (rtl_read_byte(rtlpriv, FW_MAC1_READY) &
168 			    MAC1_READY) {
169 				rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
170 					"Polling FW ready success!! REG_MCUFWDL: 0x%x\n",
171 					rtl_read_byte(rtlpriv,
172 						      FW_MAC1_READY));
173 				return 0;
174 			}
175 			udelay(5);
176 		}
177 	} while (counter++ < POLLING_READY_TIMEOUT_COUNT);
178 
179 	if (rtlhal->interfaceindex == 0) {
180 		rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
181 			"Polling FW ready fail!! MAC0 FW init not ready: 0x%x\n",
182 			rtl_read_byte(rtlpriv, FW_MAC0_READY));
183 	} else {
184 		rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
185 			"Polling FW ready fail!! MAC1 FW init not ready: 0x%x\n",
186 			rtl_read_byte(rtlpriv, FW_MAC1_READY));
187 	}
188 	rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
189 		"Polling FW ready fail!! REG_MCUFWDL:0x%08x\n",
190 		rtl_read_dword(rtlpriv, REG_MCUFWDL));
191 	return -1;
192 }
193 EXPORT_SYMBOL_GPL(rtl92d_fw_init);
194 
_rtl92d_check_fw_read_last_h2c(struct ieee80211_hw * hw,u8 boxnum)195 static bool _rtl92d_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
196 {
197 	struct rtl_priv *rtlpriv = rtl_priv(hw);
198 	u8 val_hmetfr;
199 	bool result = false;
200 
201 	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
202 	if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
203 		result = true;
204 	return result;
205 }
206 
rtl92d_fill_h2c_cmd(struct ieee80211_hw * hw,u8 element_id,u32 cmd_len,u8 * cmdbuffer)207 void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw,
208 			 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
209 {
210 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
211 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
212 	struct rtl_priv *rtlpriv = rtl_priv(hw);
213 	u8 boxcontent[4], boxextcontent[2];
214 	u16 box_reg = 0, box_extreg = 0;
215 	u8 wait_writeh2c_limmit = 100;
216 	bool bwrite_success = false;
217 	u8 wait_h2c_limmit = 100;
218 	u32 h2c_waitcounter = 0;
219 	bool isfw_read = false;
220 	unsigned long flag;
221 	u8 u1b_tmp;
222 	u8 boxnum;
223 	u8 idx;
224 
225 	if (ppsc->rfpwr_state == ERFOFF || ppsc->inactive_pwrstate == ERFOFF) {
226 		rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
227 			"Return as RF is off!!!\n");
228 		return;
229 	}
230 
231 	rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
232 
233 	while (true) {
234 		spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
235 		if (rtlhal->h2c_setinprogress) {
236 			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
237 				"H2C set in progress! Wait to set..element_id(%d)\n",
238 				element_id);
239 
240 			while (rtlhal->h2c_setinprogress) {
241 				spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
242 						       flag);
243 				h2c_waitcounter++;
244 				rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
245 					"Wait 100 us (%d times)...\n",
246 					h2c_waitcounter);
247 				udelay(100);
248 
249 				if (h2c_waitcounter > 1000)
250 					return;
251 
252 				spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
253 						  flag);
254 			}
255 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
256 		} else {
257 			rtlhal->h2c_setinprogress = true;
258 			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
259 			break;
260 		}
261 	}
262 
263 	while (!bwrite_success) {
264 		wait_writeh2c_limmit--;
265 		if (wait_writeh2c_limmit == 0) {
266 			pr_err("Write H2C fail because no trigger for FW INT!\n");
267 			break;
268 		}
269 
270 		boxnum = rtlhal->last_hmeboxnum;
271 		if (boxnum > 3) {
272 			pr_err("boxnum %#x too big\n", boxnum);
273 			break;
274 		}
275 
276 		box_reg = REG_HMEBOX_0 + boxnum * SIZE_OF_REG_HMEBOX;
277 		box_extreg = REG_HMEBOX_EXT_0 + boxnum * SIZE_OF_REG_HMEBOX_EXT;
278 
279 		isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
280 		while (!isfw_read) {
281 			wait_h2c_limmit--;
282 			if (wait_h2c_limmit == 0) {
283 				rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
284 					"Waiting too long for FW read clear HMEBox(%d)!\n",
285 					boxnum);
286 				break;
287 			}
288 
289 			udelay(10);
290 
291 			isfw_read = _rtl92d_check_fw_read_last_h2c(hw, boxnum);
292 			u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
293 			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
294 				"Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n",
295 				boxnum, u1b_tmp);
296 		}
297 
298 		if (!isfw_read) {
299 			rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
300 				"Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
301 				boxnum);
302 			break;
303 		}
304 
305 		memset(boxcontent, 0, sizeof(boxcontent));
306 		memset(boxextcontent, 0, sizeof(boxextcontent));
307 		boxcontent[0] = element_id;
308 
309 		rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
310 			"Write element_id box_reg(%4x) = %2x\n",
311 			box_reg, element_id);
312 
313 		switch (cmd_len) {
314 		case 1 ... 3:
315 			/* BOX:      | ID | A0 | A1 | A2 |
316 			 * BOX_EXT:  --- N/A ------
317 			 */
318 			boxcontent[0] &= ~BIT(7);
319 			memcpy(boxcontent + 1, cmdbuffer, cmd_len);
320 
321 			for (idx = 0; idx < 4; idx++)
322 				rtl_write_byte(rtlpriv, box_reg + idx,
323 					       boxcontent[idx]);
324 			break;
325 		case 4 ... 5:
326 			/* * ID ext = ID | BIT(7)
327 			 * BOX:      | ID ext | A2 | A3 | A4 |
328 			 * BOX_EXT:  | A0     | A1 |
329 			 */
330 			boxcontent[0] |= BIT(7);
331 			memcpy(boxextcontent, cmdbuffer, 2);
332 			memcpy(boxcontent + 1, cmdbuffer + 2, cmd_len - 2);
333 
334 			for (idx = 0; idx < 2; idx++)
335 				rtl_write_byte(rtlpriv, box_extreg + idx,
336 					       boxextcontent[idx]);
337 
338 			for (idx = 0; idx < 4; idx++)
339 				rtl_write_byte(rtlpriv, box_reg + idx,
340 					       boxcontent[idx]);
341 			break;
342 		default:
343 			pr_err("switch case %#x not processed\n", cmd_len);
344 			break;
345 		}
346 
347 		bwrite_success = true;
348 		rtlhal->last_hmeboxnum = boxnum + 1;
349 		if (rtlhal->last_hmeboxnum == 4)
350 			rtlhal->last_hmeboxnum = 0;
351 
352 		rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD,
353 			"pHalData->last_hmeboxnum  = %d\n",
354 			rtlhal->last_hmeboxnum);
355 	}
356 	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
357 	rtlhal->h2c_setinprogress = false;
358 	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
359 	rtl_dbg(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
360 }
361 EXPORT_SYMBOL_GPL(rtl92d_fill_h2c_cmd);
362 
rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw * hw,u8 mstatus)363 void rtl92d_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
364 {
365 	u8 u1_joinbssrpt_parm[1] = {0};
366 
367 	u1_joinbssrpt_parm[0] = mstatus;
368 	rtl92d_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
369 }
370 EXPORT_SYMBOL_GPL(rtl92d_set_fw_joinbss_report_cmd);
371