blob: 43fcb25c885f15d691b6ddb1300599cd0cf6b347 [file] [log] [blame]
Larry Finger0c817332010-12-08 11:12:31 -06001/******************************************************************************
2 *
Larry Fingerfc616852012-01-07 20:46:43 -06003 * Copyright(c) 2009-2012 Realtek Corporation.
Larry Finger0c817332010-12-08 11:12:31 -06004 *
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 *
Larry Finger0c817332010-12-08 11:12:31 -060014 * The full GNU General Public License is included in this distribution in the
15 * file called LICENSE.
16 *
17 * Contact Information:
18 * wlanfae <wlanfae@realtek.com>
19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20 * Hsinchu 300, Taiwan.
21 *
22 * Larry Finger <Larry.Finger@lwfinger.net>
23 *
24 *****************************************************************************/
25
Larry Finger0c817332010-12-08 11:12:31 -060026#include "../wifi.h"
27#include "../pci.h"
28#include "../base.h"
Larry Finger557f9332014-09-26 16:40:27 -050029#include "../core.h"
Larry Finger1472d3a2011-02-23 10:24:58 -060030#include "../rtl8192ce/reg.h"
31#include "../rtl8192ce/def.h"
32#include "fw_common.h"
Larry Fingerd273bb22012-01-27 13:59:25 -060033#include <linux/export.h>
Larry Fingerf11bbfd2012-04-13 13:57:43 -050034#include <linux/kmemleak.h>
Larry Finger0c817332010-12-08 11:12:31 -060035
36static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
37{
38 struct rtl_priv *rtlpriv = rtl_priv(hw);
39 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
40
41 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) {
42 u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
43 if (enable)
44 value32 |= MCUFWDL_EN;
45 else
46 value32 &= ~MCUFWDL_EN;
47 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
48 } else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) {
49 u8 tmp;
50 if (enable) {
51
52 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
53 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1,
54 tmp | 0x04);
55
56 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
57 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
58
59 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
60 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
61 } else {
62
63 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
64 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
65
66 rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
67 }
68 }
69}
70
71static void _rtl92c_fw_block_write(struct ieee80211_hw *hw,
72 const u8 *buffer, u32 size)
73{
74 struct rtl_priv *rtlpriv = rtl_priv(hw);
Larry Finger9f087a92014-09-26 16:40:26 -050075 u32 blocksize = sizeof(u32);
76 u8 *bufferptr = (u8 *)buffer;
77 u32 *pu4byteptr = (u32 *)buffer;
78 u32 i, offset, blockcount, remainsize;
Larry Finger0c817332010-12-08 11:12:31 -060079
Larry Finger9f087a92014-09-26 16:40:26 -050080 blockcount = size / blocksize;
81 remainsize = size % blocksize;
Larry Finger0c817332010-12-08 11:12:31 -060082
Larry Finger9f087a92014-09-26 16:40:26 -050083 for (i = 0; i < blockcount; i++) {
84 offset = i * blocksize;
Larry Finger0c817332010-12-08 11:12:31 -060085 rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
Larry Finger9f087a92014-09-26 16:40:26 -050086 *(pu4byteptr + i));
87 }
88
89 if (remainsize) {
90 offset = blockcount * blocksize;
91 bufferptr += offset;
92 for (i = 0; i < remainsize; i++) {
93 rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS +
94 offset + i), *(bufferptr + i));
95 }
Larry Finger0c817332010-12-08 11:12:31 -060096 }
97}
98
99static void _rtl92c_fw_page_write(struct ieee80211_hw *hw,
100 u32 page, const u8 *buffer, u32 size)
101{
102 struct rtl_priv *rtlpriv = rtl_priv(hw);
103 u8 value8;
104 u8 u8page = (u8) (page & 0x07);
105
106 value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
107
108 rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
109 _rtl92c_fw_block_write(hw, buffer, size);
110}
111
112static void _rtl92c_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
113{
114 u32 fwlen = *pfwlen;
115 u8 remain = (u8) (fwlen % 4);
116
117 remain = (remain == 0) ? 0 : (4 - remain);
118
119 while (remain > 0) {
120 pfwbuf[fwlen] = 0;
121 fwlen++;
122 remain--;
123 }
124
125 *pfwlen = fwlen;
126}
127
128static void _rtl92c_write_fw(struct ieee80211_hw *hw,
129 enum version_8192c version, u8 *buffer, u32 size)
130{
131 struct rtl_priv *rtlpriv = rtl_priv(hw);
132 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
Larry Finger9f087a92014-09-26 16:40:26 -0500133 bool is_version_b;
134 u8 *bufferptr = (u8 *)buffer;
Larry Finger0c817332010-12-08 11:12:31 -0600135
Larry Finger9f087a92014-09-26 16:40:26 -0500136 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size);
137 is_version_b = IS_NORMAL_CHIP(version);
138 if (is_version_b) {
139 u32 pageNums, remainsize;
Larry Finger0c817332010-12-08 11:12:31 -0600140 u32 page, offset;
141
Larry Finger9f087a92014-09-26 16:40:26 -0500142 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE)
143 _rtl92c_fill_dummy(bufferptr, &size);
Larry Finger0c817332010-12-08 11:12:31 -0600144
145 pageNums = size / FW_8192C_PAGE_SIZE;
Larry Finger9f087a92014-09-26 16:40:26 -0500146 remainsize = size % FW_8192C_PAGE_SIZE;
Larry Finger0c817332010-12-08 11:12:31 -0600147
148 if (pageNums > 4) {
149 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
Joe Perchesf30d7502012-01-04 19:40:41 -0800150 "Page numbers should not greater then 4\n");
Larry Finger0c817332010-12-08 11:12:31 -0600151 }
152
153 for (page = 0; page < pageNums; page++) {
154 offset = page * FW_8192C_PAGE_SIZE;
Larry Finger9f087a92014-09-26 16:40:26 -0500155 _rtl92c_fw_page_write(hw, page, (bufferptr + offset),
Larry Finger0c817332010-12-08 11:12:31 -0600156 FW_8192C_PAGE_SIZE);
157 }
158
Larry Finger9f087a92014-09-26 16:40:26 -0500159 if (remainsize) {
Larry Finger0c817332010-12-08 11:12:31 -0600160 offset = pageNums * FW_8192C_PAGE_SIZE;
161 page = pageNums;
Larry Finger9f087a92014-09-26 16:40:26 -0500162 _rtl92c_fw_page_write(hw, page, (bufferptr + offset),
163 remainsize);
Larry Finger0c817332010-12-08 11:12:31 -0600164 }
165 } else {
166 _rtl92c_fw_block_write(hw, buffer, size);
167 }
168}
169
170static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw)
171{
172 struct rtl_priv *rtlpriv = rtl_priv(hw);
Larry Finger9f087a92014-09-26 16:40:26 -0500173 int err = -EIO;
Larry Finger0c817332010-12-08 11:12:31 -0600174 u32 counter = 0;
175 u32 value32;
176
177 do {
178 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
179 } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
180 (!(value32 & FWDL_ChkSum_rpt)));
181
182 if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
183 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
Larry Finger9f087a92014-09-26 16:40:26 -0500184 "chksum report faill ! REG_MCUFWDL:0x%08x .\n",
185 value32);
186 goto exit;
Larry Finger0c817332010-12-08 11:12:31 -0600187 }
188
189 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
Larry Finger9f087a92014-09-26 16:40:26 -0500190 "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32);
Larry Finger0c817332010-12-08 11:12:31 -0600191
192 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
193 value32 |= MCUFWDL_RDY;
194 value32 &= ~WINTINI_RDY;
195 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
196
197 counter = 0;
198
199 do {
200 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
201 if (value32 & WINTINI_RDY) {
202 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
Larry Finger9f087a92014-09-26 16:40:26 -0500203 "Polling FW ready success!! REG_MCUFWDL:0x%08x .\n",
204 value32);
205 err = 0;
206 goto exit;
Larry Finger0c817332010-12-08 11:12:31 -0600207 }
208
209 mdelay(FW_8192C_POLLING_DELAY);
210
211 } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
212
213 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
Larry Finger9f087a92014-09-26 16:40:26 -0500214 "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32);
215
216exit:
217 return err;
Larry Finger0c817332010-12-08 11:12:31 -0600218}
219
220int rtl92c_download_fw(struct ieee80211_hw *hw)
221{
222 struct rtl_priv *rtlpriv = rtl_priv(hw);
223 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
Larry Fingere41c5132015-08-03 15:56:11 -0500224 struct rtlwifi_firmware_header *pfwheader;
Larry Finger0c817332010-12-08 11:12:31 -0600225 u8 *pfwdata;
226 u32 fwsize;
Larry Finger9f087a92014-09-26 16:40:26 -0500227 int err;
Larry Finger0c817332010-12-08 11:12:31 -0600228 enum version_8192c version = rtlhal->version;
229
Larry Finger9f087a92014-09-26 16:40:26 -0500230 if (!rtlhal->pfirmware)
Larry Finger0c817332010-12-08 11:12:31 -0600231 return 1;
Larry Finger0c817332010-12-08 11:12:31 -0600232
Larry Fingere41c5132015-08-03 15:56:11 -0500233 pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
Larry Finger9f087a92014-09-26 16:40:26 -0500234 pfwdata = (u8 *)rtlhal->pfirmware;
Chaoming_Li3ac5e262011-04-25 12:53:40 -0500235 fwsize = rtlhal->fwsize;
Larry Finger0c817332010-12-08 11:12:31 -0600236 if (IS_FW_HEADER_EXIST(pfwheader)) {
237 RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
Joe Perchesf30d7502012-01-04 19:40:41 -0800238 "Firmware Version(%d), Signature(%#x),Size(%d)\n",
Larry Finger9f087a92014-09-26 16:40:26 -0500239 pfwheader->version, pfwheader->signature,
Larry Fingere41c5132015-08-03 15:56:11 -0500240 (int)sizeof(struct rtlwifi_firmware_header));
Larry Finger0c817332010-12-08 11:12:31 -0600241
Larry Fingere41c5132015-08-03 15:56:11 -0500242 rtlhal->fw_version = le16_to_cpu(pfwheader->version);
Taehee Yooe996db62015-06-07 22:33:36 +0900243 rtlhal->fw_subversion = pfwheader->subversion;
Larry Fingere41c5132015-08-03 15:56:11 -0500244 pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
245 fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
Larry Finger0c817332010-12-08 11:12:31 -0600246 }
247
248 _rtl92c_enable_fw_download(hw, true);
249 _rtl92c_write_fw(hw, version, pfwdata, fwsize);
250 _rtl92c_enable_fw_download(hw, false);
251
Larry Finger9f087a92014-09-26 16:40:26 -0500252 err = _rtl92c_fw_free_to_go(hw);
253 if (err) {
Larry Finger0c817332010-12-08 11:12:31 -0600254 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
Joe Perchesf30d7502012-01-04 19:40:41 -0800255 "Firmware is not ready to run!\n");
Larry Finger0c817332010-12-08 11:12:31 -0600256 } else {
257 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
Joe Perchesf30d7502012-01-04 19:40:41 -0800258 "Firmware is ready to run!\n");
Larry Finger0c817332010-12-08 11:12:31 -0600259 }
260
261 return 0;
262}
Larry Finger1472d3a2011-02-23 10:24:58 -0600263EXPORT_SYMBOL(rtl92c_download_fw);
Larry Finger0c817332010-12-08 11:12:31 -0600264
265static bool _rtl92c_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
266{
267 struct rtl_priv *rtlpriv = rtl_priv(hw);
268 u8 val_hmetfr, val_mcutst_1;
269 bool result = false;
270
271 val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
272 val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
273
274 if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
275 result = true;
276 return result;
277}
278
279static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw,
Larry Finger9f087a92014-09-26 16:40:26 -0500280 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
Larry Finger0c817332010-12-08 11:12:31 -0600281{
282 struct rtl_priv *rtlpriv = rtl_priv(hw);
283 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
284 u8 boxnum;
Larry Finger9f219bd2011-04-13 21:00:02 -0500285 u16 box_reg = 0, box_extreg = 0;
Larry Finger0c817332010-12-08 11:12:31 -0600286 u8 u1b_tmp;
287 bool isfw_read = false;
Larry Finger9f087a92014-09-26 16:40:26 -0500288 u8 buf_index = 0;
289 bool bwrite_sucess = false;
Larry Finger0c817332010-12-08 11:12:31 -0600290 u8 wait_h2c_limmit = 100;
291 u8 wait_writeh2c_limmit = 100;
292 u8 boxcontent[4], boxextcontent[2];
293 u32 h2c_waitcounter = 0;
294 unsigned long flag;
295 u8 idx;
296
Joe Perchesf30d7502012-01-04 19:40:41 -0800297 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "come in\n");
Larry Finger0c817332010-12-08 11:12:31 -0600298
299 while (true) {
300 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
Larry Finger7ea47242011-02-19 16:28:57 -0600301 if (rtlhal->h2c_setinprogress) {
Larry Finger0c817332010-12-08 11:12:31 -0600302 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
Larry Finger9f087a92014-09-26 16:40:26 -0500303 "H2C set in progress! Wait to set..element_id(%d).\n",
Joe Perchesf30d7502012-01-04 19:40:41 -0800304 element_id);
Larry Finger7ea47242011-02-19 16:28:57 -0600305 while (rtlhal->h2c_setinprogress) {
Larry Finger0c817332010-12-08 11:12:31 -0600306 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
307 flag);
308 h2c_waitcounter++;
309 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800310 "Wait 100 us (%d times)...\n",
Larry Finger9f087a92014-09-26 16:40:26 -0500311 h2c_waitcounter);
Larry Finger0c817332010-12-08 11:12:31 -0600312 udelay(100);
313
314 if (h2c_waitcounter > 1000)
315 return;
316 spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
317 flag);
318 }
319 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
320 } else {
Larry Finger7ea47242011-02-19 16:28:57 -0600321 rtlhal->h2c_setinprogress = true;
Larry Finger0c817332010-12-08 11:12:31 -0600322 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
323 break;
324 }
325 }
326
Larry Finger9f087a92014-09-26 16:40:26 -0500327 while (!bwrite_sucess) {
Larry Finger0c817332010-12-08 11:12:31 -0600328 wait_writeh2c_limmit--;
329 if (wait_writeh2c_limmit == 0) {
330 RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
Joe Perchesf30d7502012-01-04 19:40:41 -0800331 "Write H2C fail because no trigger for FW INT!\n");
Larry Finger0c817332010-12-08 11:12:31 -0600332 break;
333 }
334
335 boxnum = rtlhal->last_hmeboxnum;
336 switch (boxnum) {
337 case 0:
338 box_reg = REG_HMEBOX_0;
339 box_extreg = REG_HMEBOX_EXT_0;
340 break;
341 case 1:
342 box_reg = REG_HMEBOX_1;
343 box_extreg = REG_HMEBOX_EXT_1;
344 break;
345 case 2:
346 box_reg = REG_HMEBOX_2;
347 box_extreg = REG_HMEBOX_EXT_2;
348 break;
349 case 3:
350 box_reg = REG_HMEBOX_3;
351 box_extreg = REG_HMEBOX_EXT_3;
352 break;
353 default:
Larry Finger9f087a92014-09-26 16:40:26 -0500354 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
355 "switch case not process\n");
Larry Finger0c817332010-12-08 11:12:31 -0600356 break;
357 }
358
359 isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
360 while (!isfw_read) {
Larry Finger0c817332010-12-08 11:12:31 -0600361 wait_h2c_limmit--;
362 if (wait_h2c_limmit == 0) {
363 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800364 "Waiting too long for FW read clear HMEBox(%d)!\n",
365 boxnum);
Larry Finger0c817332010-12-08 11:12:31 -0600366 break;
367 }
368
369 udelay(10);
370
371 isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
372 u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
373 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800374 "Waiting for FW read clear HMEBox(%d)!!! 0x1BF = %2x\n",
375 boxnum, u1b_tmp);
Larry Finger0c817332010-12-08 11:12:31 -0600376 }
377
378 if (!isfw_read) {
379 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
Larry Finger9f087a92014-09-26 16:40:26 -0500380 "Write H2C register BOX[%d] fail!!!!! Fw do not read.\n",
Joe Perchesf30d7502012-01-04 19:40:41 -0800381 boxnum);
Larry Finger0c817332010-12-08 11:12:31 -0600382 break;
383 }
384
385 memset(boxcontent, 0, sizeof(boxcontent));
386 memset(boxextcontent, 0, sizeof(boxextcontent));
387 boxcontent[0] = element_id;
388 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800389 "Write element_id box_reg(%4x) = %2x\n",
Larry Finger9f087a92014-09-26 16:40:26 -0500390 box_reg, element_id);
Larry Finger0c817332010-12-08 11:12:31 -0600391
392 switch (cmd_len) {
393 case 1:
394 boxcontent[0] &= ~(BIT(7));
Larry Finger9f087a92014-09-26 16:40:26 -0500395 memcpy((u8 *)(boxcontent) + 1,
396 cmdbuffer + buf_index, 1);
Larry Finger0c817332010-12-08 11:12:31 -0600397
398 for (idx = 0; idx < 4; idx++) {
399 rtl_write_byte(rtlpriv, box_reg + idx,
400 boxcontent[idx]);
401 }
402 break;
403 case 2:
404 boxcontent[0] &= ~(BIT(7));
Larry Finger9f087a92014-09-26 16:40:26 -0500405 memcpy((u8 *)(boxcontent) + 1,
406 cmdbuffer + buf_index, 2);
Larry Finger0c817332010-12-08 11:12:31 -0600407
408 for (idx = 0; idx < 4; idx++) {
409 rtl_write_byte(rtlpriv, box_reg + idx,
410 boxcontent[idx]);
411 }
412 break;
413 case 3:
414 boxcontent[0] &= ~(BIT(7));
Larry Finger9f087a92014-09-26 16:40:26 -0500415 memcpy((u8 *)(boxcontent) + 1,
416 cmdbuffer + buf_index, 3);
Larry Finger0c817332010-12-08 11:12:31 -0600417
418 for (idx = 0; idx < 4; idx++) {
419 rtl_write_byte(rtlpriv, box_reg + idx,
420 boxcontent[idx]);
421 }
422 break;
423 case 4:
424 boxcontent[0] |= (BIT(7));
Larry Finger9f087a92014-09-26 16:40:26 -0500425 memcpy((u8 *)(boxextcontent),
426 cmdbuffer + buf_index, 2);
427 memcpy((u8 *)(boxcontent) + 1,
428 cmdbuffer + buf_index + 2, 2);
Larry Finger0c817332010-12-08 11:12:31 -0600429
430 for (idx = 0; idx < 2; idx++) {
431 rtl_write_byte(rtlpriv, box_extreg + idx,
432 boxextcontent[idx]);
433 }
434
435 for (idx = 0; idx < 4; idx++) {
436 rtl_write_byte(rtlpriv, box_reg + idx,
437 boxcontent[idx]);
438 }
439 break;
440 case 5:
441 boxcontent[0] |= (BIT(7));
Larry Finger9f087a92014-09-26 16:40:26 -0500442 memcpy((u8 *)(boxextcontent),
443 cmdbuffer + buf_index, 2);
444 memcpy((u8 *)(boxcontent) + 1,
445 cmdbuffer + buf_index + 2, 3);
Larry Finger0c817332010-12-08 11:12:31 -0600446
447 for (idx = 0; idx < 2; idx++) {
448 rtl_write_byte(rtlpriv, box_extreg + idx,
449 boxextcontent[idx]);
450 }
451
452 for (idx = 0; idx < 4; idx++) {
453 rtl_write_byte(rtlpriv, box_reg + idx,
454 boxcontent[idx]);
455 }
456 break;
457 default:
Larry Finger9f087a92014-09-26 16:40:26 -0500458 RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
459 "switch case not process\n");
Larry Finger0c817332010-12-08 11:12:31 -0600460 break;
461 }
462
Larry Finger9f087a92014-09-26 16:40:26 -0500463 bwrite_sucess = true;
Larry Finger0c817332010-12-08 11:12:31 -0600464
465 rtlhal->last_hmeboxnum = boxnum + 1;
466 if (rtlhal->last_hmeboxnum == 4)
467 rtlhal->last_hmeboxnum = 0;
468
469 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
Joe Perchesf30d7502012-01-04 19:40:41 -0800470 "pHalData->last_hmeboxnum = %d\n",
Larry Finger9f087a92014-09-26 16:40:26 -0500471 rtlhal->last_hmeboxnum);
Larry Finger0c817332010-12-08 11:12:31 -0600472 }
473
474 spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
Larry Finger7ea47242011-02-19 16:28:57 -0600475 rtlhal->h2c_setinprogress = false;
Larry Finger0c817332010-12-08 11:12:31 -0600476 spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
477
Joe Perchesf30d7502012-01-04 19:40:41 -0800478 RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, "go out\n");
Larry Finger0c817332010-12-08 11:12:31 -0600479}
480
481void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
Larry Finger9f087a92014-09-26 16:40:26 -0500482 u8 element_id, u32 cmd_len, u8 *cmdbuffer)
Larry Finger0c817332010-12-08 11:12:31 -0600483{
Larry Finger9f087a92014-09-26 16:40:26 -0500484 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
Larry Finger0c817332010-12-08 11:12:31 -0600485 u32 tmp_cmdbuf[2];
486
Larry Finger9f087a92014-09-26 16:40:26 -0500487 if (!rtlhal->fw_ready) {
488 RT_ASSERT(false,
489 "return H2C cmd because of Fw download fail!!!\n");
490 return;
491 }
492
Larry Finger0c817332010-12-08 11:12:31 -0600493 memset(tmp_cmdbuf, 0, 8);
Larry Finger9f087a92014-09-26 16:40:26 -0500494 memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
Larry Finger0c817332010-12-08 11:12:31 -0600495 _rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
496
497 return;
498}
Larry Finger1472d3a2011-02-23 10:24:58 -0600499EXPORT_SYMBOL(rtl92c_fill_h2c_cmd);
Larry Finger0c817332010-12-08 11:12:31 -0600500
501void rtl92c_firmware_selfreset(struct ieee80211_hw *hw)
502{
503 u8 u1b_tmp;
504 u8 delay = 100;
505 struct rtl_priv *rtlpriv = rtl_priv(hw);
506
507 rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
508 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
509
510 while (u1b_tmp & BIT(2)) {
511 delay--;
512 if (delay == 0) {
Larry Finger9f087a92014-09-26 16:40:26 -0500513 RT_ASSERT(false, "8051 reset fail.\n");
Larry Finger0c817332010-12-08 11:12:31 -0600514 break;
515 }
516 udelay(50);
517 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
518 }
519}
Larry Finger1472d3a2011-02-23 10:24:58 -0600520EXPORT_SYMBOL(rtl92c_firmware_selfreset);
Larry Finger0c817332010-12-08 11:12:31 -0600521
522void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
523{
524 struct rtl_priv *rtlpriv = rtl_priv(hw);
Larry Finger9f087a92014-09-26 16:40:26 -0500525 u8 u1_h2c_set_pwrmode[3] = { 0 };
Larry Finger0c817332010-12-08 11:12:31 -0600526 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
527
Joe Perchesf30d7502012-01-04 19:40:41 -0800528 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, "FW LPS mode = %d\n", mode);
Larry Finger0c817332010-12-08 11:12:31 -0600529
530 SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
Larry Finger3a16b412013-03-24 22:06:40 -0500531 SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
Larry Finger9f087a92014-09-26 16:40:26 -0500532 (rtlpriv->mac80211.p2p) ? ppsc->smart_ps : 1);
Larry Finger0c817332010-12-08 11:12:31 -0600533 SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
534 ppsc->reg_max_lps_awakeintvl);
535
536 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
Larry Finger9f087a92014-09-26 16:40:26 -0500537 "rtl92c_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
Larry Finger0c817332010-12-08 11:12:31 -0600538 u1_h2c_set_pwrmode, 3);
539 rtl92c_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
Larry Finger0c817332010-12-08 11:12:31 -0600540}
Larry Finger1472d3a2011-02-23 10:24:58 -0600541EXPORT_SYMBOL(rtl92c_set_fw_pwrmode_cmd);
Larry Finger0c817332010-12-08 11:12:31 -0600542
Larry Finger0c817332010-12-08 11:12:31 -0600543#define BEACON_PG 0 /*->1*/
544#define PSPOLL_PG 2
545#define NULL_PG 3
546#define PROBERSP_PG 4 /*->5*/
547
548#define TOTAL_RESERVED_PKT_LEN 768
549
550static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
551 /* page 0 beacon */
552 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
553 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
554 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
555 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
556 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
557 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
558 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
559 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
560 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
561 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
562 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
565 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
566 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
568
569 /* page 1 beacon */
570 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582 0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
583 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586
587 /* page 2 ps-poll */
588 0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
589 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
590 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600 0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
602 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
604
605 /* page 3 null */
606 0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
607 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
608 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
611 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
617 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
618 0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
619 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
620 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
622
623 /* page 4 probe_resp */
624 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
625 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
626 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
627 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
628 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
629 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
630 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
631 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
632 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
633 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
634 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
638 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640
641 /* page 5 probe_resp */
642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
651 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
652 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
653 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
655 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
656 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
657 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
658};
659
Karsten Wiese4f2b2442014-10-22 15:47:34 +0200660void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
661 bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *))
Larry Finger0c817332010-12-08 11:12:31 -0600662{
663 struct rtl_priv *rtlpriv = rtl_priv(hw);
664 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
665 struct sk_buff *skb = NULL;
666
667 u32 totalpacketlen;
668 bool rtstatus;
Larry Finger9f087a92014-09-26 16:40:26 -0500669 u8 u1rsvdpageloc[3] = { 0 };
670 bool b_dlok = false;
Larry Finger0c817332010-12-08 11:12:31 -0600671
672 u8 *beacon;
Larry Finger9f087a92014-09-26 16:40:26 -0500673 u8 *p_pspoll;
Larry Finger0c817332010-12-08 11:12:31 -0600674 u8 *nullfunc;
Larry Finger9f087a92014-09-26 16:40:26 -0500675 u8 *p_probersp;
Larry Finger0c817332010-12-08 11:12:31 -0600676 /*---------------------------------------------------------
677 (1) beacon
678 ---------------------------------------------------------*/
679 beacon = &reserved_page_packet[BEACON_PG * 128];
680 SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
681 SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
682
683 /*-------------------------------------------------------
684 (2) ps-poll
685 --------------------------------------------------------*/
Larry Finger9f087a92014-09-26 16:40:26 -0500686 p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
687 SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
688 SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
689 SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
Larry Finger0c817332010-12-08 11:12:31 -0600690
Larry Finger9f087a92014-09-26 16:40:26 -0500691 SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
Larry Finger0c817332010-12-08 11:12:31 -0600692
693 /*--------------------------------------------------------
694 (3) null data
695 ---------------------------------------------------------*/
696 nullfunc = &reserved_page_packet[NULL_PG * 128];
697 SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
698 SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
699 SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
700
Larry Finger9f087a92014-09-26 16:40:26 -0500701 SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
Larry Finger0c817332010-12-08 11:12:31 -0600702
703 /*---------------------------------------------------------
704 (4) probe response
705 ----------------------------------------------------------*/
Larry Finger9f087a92014-09-26 16:40:26 -0500706 p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
707 SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
708 SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
709 SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
Larry Finger0c817332010-12-08 11:12:31 -0600710
Larry Finger9f087a92014-09-26 16:40:26 -0500711 SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
Larry Finger0c817332010-12-08 11:12:31 -0600712
713 totalpacketlen = TOTAL_RESERVED_PKT_LEN;
714
715 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
Larry Finger9f087a92014-09-26 16:40:26 -0500716 "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
Larry Finger0c817332010-12-08 11:12:31 -0600717 &reserved_page_packet[0], totalpacketlen);
718 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
Larry Finger9f087a92014-09-26 16:40:26 -0500719 "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
720 u1rsvdpageloc, 3);
Larry Finger0c817332010-12-08 11:12:31 -0600721
722
723 skb = dev_alloc_skb(totalpacketlen);
Larry Finger9f087a92014-09-26 16:40:26 -0500724 memcpy((u8 *)skb_put(skb, totalpacketlen),
Larry Finger0c817332010-12-08 11:12:31 -0600725 &reserved_page_packet, totalpacketlen);
726
Karsten Wiese4f2b2442014-10-22 15:47:34 +0200727 if (cmd_send_packet)
728 rtstatus = cmd_send_packet(hw, skb);
729 else
730 rtstatus = rtl_cmd_send_packet(hw, skb);
Larry Finger0c817332010-12-08 11:12:31 -0600731
732 if (rtstatus)
Larry Finger9f087a92014-09-26 16:40:26 -0500733 b_dlok = true;
Larry Finger0c817332010-12-08 11:12:31 -0600734
Larry Finger9f087a92014-09-26 16:40:26 -0500735 if (b_dlok) {
Larry Finger0c817332010-12-08 11:12:31 -0600736 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
Larry Finger9f087a92014-09-26 16:40:26 -0500737 "Set RSVD page location to Fw.\n");
Larry Finger0c817332010-12-08 11:12:31 -0600738 RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
Larry Finger9f087a92014-09-26 16:40:26 -0500739 "H2C_RSVDPAGE:\n",
740 u1rsvdpageloc, 3);
Larry Finger0c817332010-12-08 11:12:31 -0600741 rtl92c_fill_h2c_cmd(hw, H2C_RSVDPAGE,
Larry Finger9f087a92014-09-26 16:40:26 -0500742 sizeof(u1rsvdpageloc), u1rsvdpageloc);
Larry Finger0c817332010-12-08 11:12:31 -0600743 } else
744 RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
Larry Finger9f087a92014-09-26 16:40:26 -0500745 "Set RSVD page location to Fw FAIL!!!!!!.\n");
Larry Finger0c817332010-12-08 11:12:31 -0600746}
Larry Finger1472d3a2011-02-23 10:24:58 -0600747EXPORT_SYMBOL(rtl92c_set_fw_rsvdpagepkt);
Larry Finger0c817332010-12-08 11:12:31 -0600748
749void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
750{
Larry Finger9f087a92014-09-26 16:40:26 -0500751 u8 u1_joinbssrpt_parm[1] = { 0 };
Larry Finger0c817332010-12-08 11:12:31 -0600752
753 SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
754
755 rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
756}
Larry Finger1472d3a2011-02-23 10:24:58 -0600757EXPORT_SYMBOL(rtl92c_set_fw_joinbss_report_cmd);
Larry Finger3a16b412013-03-24 22:06:40 -0500758
759static void rtl92c_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
760{
Larry Finger9f087a92014-09-26 16:40:26 -0500761 u8 u1_ctwindow_period[1] = { ctwindow};
Larry Finger3a16b412013-03-24 22:06:40 -0500762
763 rtl92c_fill_h2c_cmd(hw, H2C_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
764}
765
Larry Finger9f087a92014-09-26 16:40:26 -0500766/* refactored routine */
767static void set_noa_data(struct rtl_priv *rtlpriv,
768 struct rtl_p2p_ps_info *p2pinfo,
769 struct p2p_ps_offload_t *p2p_ps_offload)
770{
771 int i;
772 u32 start_time, tsf_low;
773
774 /* hw only support 2 set of NoA */
775 for (i = 0 ; i < p2pinfo->noa_num ; i++) {
776 /* To control the reg setting for which NOA*/
777 rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
778 if (i == 0)
779 p2p_ps_offload->noa0_en = 1;
780 else
781 p2p_ps_offload->noa1_en = 1;
782
783 /* config P2P NoA Descriptor Register */
784 rtl_write_dword(rtlpriv, 0x5E0,
785 p2pinfo->noa_duration[i]);
786 rtl_write_dword(rtlpriv, 0x5E4,
787 p2pinfo->noa_interval[i]);
788
789 /*Get Current TSF value */
790 tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
791
792 start_time = p2pinfo->noa_start_time[i];
793 if (p2pinfo->noa_count_type[i] != 1) {
794 while (start_time <= (tsf_low+(50*1024))) {
795 start_time += p2pinfo->noa_interval[i];
796 if (p2pinfo->noa_count_type[i] != 255)
797 p2pinfo->noa_count_type[i]--;
798 }
799 }
800 rtl_write_dword(rtlpriv, 0x5E8, start_time);
801 rtl_write_dword(rtlpriv, 0x5EC,
802 p2pinfo->noa_count_type[i]);
803 }
804}
805
Larry Finger3a16b412013-03-24 22:06:40 -0500806void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
807{
808 struct rtl_priv *rtlpriv = rtl_priv(hw);
809 struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
810 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
811 struct rtl_p2p_ps_info *p2pinfo = &(rtlps->p2p_ps_info);
812 struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
Larry Finger3a16b412013-03-24 22:06:40 -0500813 u16 ctwindow;
Larry Finger3a16b412013-03-24 22:06:40 -0500814
815 switch (p2p_ps_state) {
816 case P2P_PS_DISABLE:
Larry Finger9f087a92014-09-26 16:40:26 -0500817 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
818 "P2P_PS_DISABLE\n");
819 memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
820 break;
Larry Finger3a16b412013-03-24 22:06:40 -0500821 case P2P_PS_ENABLE:
Larry Finger9f087a92014-09-26 16:40:26 -0500822 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
823 "P2P_PS_ENABLE\n");
824 /* update CTWindow value. */
825 if (p2pinfo->ctwindow > 0) {
826 p2p_ps_offload->ctwindow_en = 1;
827 ctwindow = p2pinfo->ctwindow;
828 rtl92c_set_p2p_ctw_period_cmd(hw, ctwindow);
829 }
830 /* call refactored routine */
831 set_noa_data(rtlpriv, p2pinfo, p2p_ps_offload);
Larry Finger3a16b412013-03-24 22:06:40 -0500832
Larry Finger9f087a92014-09-26 16:40:26 -0500833 if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
834 /* rst p2p circuit */
835 rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST,
836 BIT(4));
Larry Finger3a16b412013-03-24 22:06:40 -0500837
Larry Finger9f087a92014-09-26 16:40:26 -0500838 p2p_ps_offload->offload_en = 1;
Larry Finger3a16b412013-03-24 22:06:40 -0500839
Larry Finger9f087a92014-09-26 16:40:26 -0500840 if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
841 p2p_ps_offload->role = 1;
842 p2p_ps_offload->allstasleep = 0;
843 } else {
844 p2p_ps_offload->role = 0;
Larry Finger3a16b412013-03-24 22:06:40 -0500845 }
Larry Finger9f087a92014-09-26 16:40:26 -0500846
847 p2p_ps_offload->discovery = 0;
Larry Finger3a16b412013-03-24 22:06:40 -0500848 }
Larry Finger9f087a92014-09-26 16:40:26 -0500849 break;
Larry Finger3a16b412013-03-24 22:06:40 -0500850 case P2P_PS_SCAN:
Larry Finger9f087a92014-09-26 16:40:26 -0500851 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, "P2P_PS_SCAN\n");
852 p2p_ps_offload->discovery = 1;
853 break;
Larry Finger3a16b412013-03-24 22:06:40 -0500854 case P2P_PS_SCAN_DONE:
Larry Finger9f087a92014-09-26 16:40:26 -0500855 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD,
856 "P2P_PS_SCAN_DONE\n");
857 p2p_ps_offload->discovery = 0;
858 p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
859 break;
Larry Finger3a16b412013-03-24 22:06:40 -0500860 default:
Larry Finger9f087a92014-09-26 16:40:26 -0500861 break;
Larry Finger3a16b412013-03-24 22:06:40 -0500862 }
863
864 rtl92c_fill_h2c_cmd(hw, H2C_P2P_PS_OFFLOAD, 1, (u8 *)p2p_ps_offload);
Larry Finger9f087a92014-09-26 16:40:26 -0500865
Larry Finger3a16b412013-03-24 22:06:40 -0500866}
867EXPORT_SYMBOL_GPL(rtl92c_set_p2p_ps_offload_cmd);