xref: /linux/drivers/net/wireless/realtek/rtlwifi/rtl8192de/fw.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 "../rtl8192d/reg.h"
9 #include "../rtl8192d/def.h"
10 #include "../rtl8192d/fw_common.h"
11 #include "fw.h"
12 #include "sw.h"
13 
rtl92d_download_fw(struct ieee80211_hw * hw)14 int rtl92d_download_fw(struct ieee80211_hw *hw)
15 {
16 	struct rtl_priv *rtlpriv = rtl_priv(hw);
17 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
18 	u8 *pfwheader;
19 	u8 *pfwdata;
20 	u32 fwsize;
21 	int err;
22 	enum version_8192d version = rtlhal->version;
23 	u8 value;
24 	u32 count;
25 	bool fw_downloaded = false, fwdl_in_process = false;
26 	unsigned long flags;
27 
28 	if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware)
29 		return 1;
30 	fwsize = rtlhal->fwsize;
31 	pfwheader = rtlhal->pfirmware;
32 	pfwdata = rtlhal->pfirmware;
33 	rtlhal->fw_version = (u16) GET_FIRMWARE_HDR_VERSION(pfwheader);
34 	rtlhal->fw_subversion = (u16) GET_FIRMWARE_HDR_SUB_VER(pfwheader);
35 	rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
36 		"FirmwareVersion(%d), FirmwareSubVersion(%d), Signature(%#x)\n",
37 		rtlhal->fw_version, rtlhal->fw_subversion,
38 		GET_FIRMWARE_HDR_SIGNATURE(pfwheader));
39 	if (IS_FW_HEADER_EXIST(pfwheader)) {
40 		rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
41 			"Shift 32 bytes for FW header!!\n");
42 		pfwdata = pfwdata + 32;
43 		fwsize = fwsize - 32;
44 	}
45 
46 	spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
47 	fw_downloaded = rtl92d_is_fw_downloaded(rtlpriv);
48 	if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
49 		fwdl_in_process = true;
50 	else
51 		fwdl_in_process = false;
52 	if (fw_downloaded) {
53 		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
54 		goto exit;
55 	} else if (fwdl_in_process) {
56 		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
57 		for (count = 0; count < 5000; count++) {
58 			udelay(500);
59 			spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
60 			fw_downloaded = rtl92d_is_fw_downloaded(rtlpriv);
61 			if ((rtl_read_byte(rtlpriv, 0x1f) & BIT(5)) == BIT(5))
62 				fwdl_in_process = true;
63 			else
64 				fwdl_in_process = false;
65 			spin_unlock_irqrestore(&globalmutex_for_fwdownload,
66 					       flags);
67 			if (fw_downloaded)
68 				goto exit;
69 			else if (!fwdl_in_process)
70 				break;
71 			else
72 				rtl_dbg(rtlpriv, COMP_FW, DBG_DMESG,
73 					"Wait for another mac download fw\n");
74 		}
75 		spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
76 		value = rtl_read_byte(rtlpriv, 0x1f);
77 		value |= BIT(5);
78 		rtl_write_byte(rtlpriv, 0x1f, value);
79 		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
80 	} else {
81 		value = rtl_read_byte(rtlpriv, 0x1f);
82 		value |= BIT(5);
83 		rtl_write_byte(rtlpriv, 0x1f, value);
84 		spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
85 	}
86 
87 	/* If 8051 is running in RAM code, driver should
88 	 * inform Fw to reset by itself, or it will cause
89 	 * download Fw fail.*/
90 	/* 8051 RAM code */
91 	if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
92 		rtl92d_firmware_selfreset(hw);
93 		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
94 	}
95 	rtl92d_enable_fw_download(hw, true);
96 	rtl92d_write_fw(hw, version, pfwdata, fwsize);
97 	rtl92d_enable_fw_download(hw, false);
98 	spin_lock_irqsave(&globalmutex_for_fwdownload, flags);
99 	err = rtl92d_fw_free_to_go(hw);
100 	/* download fw over,clear 0x1f[5] */
101 	value = rtl_read_byte(rtlpriv, 0x1f);
102 	value &= (~BIT(5));
103 	rtl_write_byte(rtlpriv, 0x1f, value);
104 	spin_unlock_irqrestore(&globalmutex_for_fwdownload, flags);
105 	if (err)
106 		pr_err("fw is not ready to run!\n");
107 exit:
108 	err = rtl92d_fw_init(hw);
109 	return err;
110 }
111 
_rtl92d_cmd_send_packet(struct ieee80211_hw * hw,struct sk_buff * skb)112 static bool _rtl92d_cmd_send_packet(struct ieee80211_hw *hw,
113 				    struct sk_buff *skb)
114 {
115 	struct rtl_priv *rtlpriv = rtl_priv(hw);
116 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
117 	struct rtl8192_tx_ring *ring;
118 	struct rtl_tx_desc *pdesc;
119 	u8 idx = 0;
120 	unsigned long flags;
121 	struct sk_buff *pskb;
122 
123 	ring = &rtlpci->tx_ring[BEACON_QUEUE];
124 	pskb = __skb_dequeue(&ring->queue);
125 	kfree_skb(pskb);
126 	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
127 	pdesc = &ring->desc[idx];
128 	/* discard output from call below */
129 	rtlpriv->cfg->ops->get_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN);
130 	rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, skb);
131 	__skb_queue_tail(&ring->queue, skb);
132 	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
133 	rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
134 	return true;
135 }
136 
137 #define BEACON_PG		0	/*->1 */
138 #define PSPOLL_PG		2
139 #define NULL_PG			3
140 #define PROBERSP_PG		4	/*->5 */
141 #define TOTAL_RESERVED_PKT_LEN	768
142 
143 static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
144 	/* page 0 beacon */
145 	0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
146 	0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
147 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
148 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149 	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
150 	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
151 	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
152 	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
153 	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
154 	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
155 	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
159 	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 
162 	/* page 1 beacon */
163 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
172 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175 	0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
176 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177 	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
178 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179 
180 	/* page 2  ps-poll */
181 	0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
182 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
183 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
184 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
185 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
188 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193 	0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
194 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
195 	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 
198 	/* page 3  null */
199 	0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
200 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
201 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
202 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
207 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 	0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
212 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
213 	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215 
216 	/* page 4  probe_resp */
217 	0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
218 	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
219 	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
220 	0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
221 	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
222 	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
223 	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
224 	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
225 	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
226 	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
227 	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
230 	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
231 	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 
234 	/* page 5  probe_resp */
235 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
239 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
240 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
241 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
242 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
246 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
247 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
248 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
250 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
251 };
252 
rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw * hw,bool dl_finished)253 void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished)
254 {
255 	struct rtl_priv *rtlpriv = rtl_priv(hw);
256 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
257 	struct sk_buff *skb = NULL;
258 	u32 totalpacketlen;
259 	bool rtstatus;
260 	u8 u1rsvdpageloc[3] = { PROBERSP_PG, PSPOLL_PG, NULL_PG };
261 	bool dlok = false;
262 	u8 *beacon;
263 	u8 *p_pspoll;
264 	u8 *nullfunc;
265 	u8 *p_probersp;
266 	/*---------------------------------------------------------
267 						(1) beacon
268 	---------------------------------------------------------*/
269 	beacon = &reserved_page_packet[BEACON_PG * 128];
270 	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
271 	SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
272 	/*-------------------------------------------------------
273 						(2) ps-poll
274 	--------------------------------------------------------*/
275 	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
276 	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
277 	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
278 	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
279 	/*--------------------------------------------------------
280 						(3) null data
281 	---------------------------------------------------------*/
282 	nullfunc = &reserved_page_packet[NULL_PG * 128];
283 	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
284 	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
285 	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
286 	/*---------------------------------------------------------
287 						(4) probe response
288 	----------------------------------------------------------*/
289 	p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
290 	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
291 	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
292 	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
293 	totalpacketlen = TOTAL_RESERVED_PKT_LEN;
294 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
295 		      "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
296 		      &reserved_page_packet[0], totalpacketlen);
297 	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
298 		      "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL",
299 		      u1rsvdpageloc, 3);
300 	skb = dev_alloc_skb(totalpacketlen);
301 	if (!skb) {
302 		dlok = false;
303 	} else {
304 		skb_put_data(skb, &reserved_page_packet, totalpacketlen);
305 		rtstatus = _rtl92d_cmd_send_packet(hw, skb);
306 
307 		if (rtstatus)
308 			dlok = true;
309 	}
310 	if (dlok) {
311 		rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD,
312 			"Set RSVD page location to Fw\n");
313 		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
314 			      "H2C_RSVDPAGE", u1rsvdpageloc, 3);
315 		rtl92d_fill_h2c_cmd(hw, H2C_RSVDPAGE,
316 			sizeof(u1rsvdpageloc), u1rsvdpageloc);
317 	} else
318 		rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING,
319 			"Set RSVD page location to Fw FAIL!!!!!!\n");
320 }
321