fw.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2009-2014 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. * 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. #include "../wifi.h"
  26. #include "../pci.h"
  27. #include "../base.h"
  28. #include "../core.h"
  29. #include "../efuse.h"
  30. #include "reg.h"
  31. #include "def.h"
  32. #include "fw.h"
  33. #include "dm.h"
  34. static void _rtl92ee_enable_fw_download(struct ieee80211_hw *hw, bool enable)
  35. {
  36. struct rtl_priv *rtlpriv = rtl_priv(hw);
  37. u8 tmp;
  38. if (enable) {
  39. rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x05);
  40. tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
  41. rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
  42. } else {
  43. tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
  44. rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
  45. }
  46. }
  47. static void _rtl92ee_write_fw(struct ieee80211_hw *hw,
  48. enum version_8192e version,
  49. u8 *buffer, u32 size)
  50. {
  51. struct rtl_priv *rtlpriv = rtl_priv(hw);
  52. u8 *bufferptr = (u8 *)buffer;
  53. u32 pagenums, remainsize;
  54. u32 page, offset;
  55. RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "FW size is %d bytes,\n", size);
  56. rtl_fill_dummy(bufferptr, &size);
  57. pagenums = size / FW_8192C_PAGE_SIZE;
  58. remainsize = size % FW_8192C_PAGE_SIZE;
  59. if (pagenums > 8)
  60. pr_err("Page numbers should not greater then 8\n");
  61. for (page = 0; page < pagenums; page++) {
  62. offset = page * FW_8192C_PAGE_SIZE;
  63. rtl_fw_page_write(hw, page, (bufferptr + offset),
  64. FW_8192C_PAGE_SIZE);
  65. udelay(2);
  66. }
  67. if (remainsize) {
  68. offset = pagenums * FW_8192C_PAGE_SIZE;
  69. page = pagenums;
  70. rtl_fw_page_write(hw, page, (bufferptr + offset), remainsize);
  71. }
  72. }
  73. static int _rtl92ee_fw_free_to_go(struct ieee80211_hw *hw)
  74. {
  75. struct rtl_priv *rtlpriv = rtl_priv(hw);
  76. int err = -EIO;
  77. u32 counter = 0;
  78. u32 value32;
  79. do {
  80. value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
  81. } while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
  82. (!(value32 & FWDL_CHKSUM_RPT)));
  83. if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
  84. pr_err("chksum report fail! REG_MCUFWDL:0x%08x\n",
  85. value32);
  86. goto exit;
  87. }
  88. value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
  89. value32 |= MCUFWDL_RDY;
  90. value32 &= ~WINTINI_RDY;
  91. rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
  92. rtl92ee_firmware_selfreset(hw);
  93. counter = 0;
  94. do {
  95. value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
  96. if (value32 & WINTINI_RDY)
  97. return 0;
  98. udelay(FW_8192C_POLLING_DELAY*10);
  99. } while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
  100. pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x. count = %d\n",
  101. value32, counter);
  102. exit:
  103. return err;
  104. }
  105. int rtl92ee_download_fw(struct ieee80211_hw *hw, bool buse_wake_on_wlan_fw)
  106. {
  107. struct rtl_priv *rtlpriv = rtl_priv(hw);
  108. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  109. struct rtlwifi_firmware_header *pfwheader;
  110. u8 *pfwdata;
  111. u32 fwsize;
  112. int err;
  113. enum version_8192e version = rtlhal->version;
  114. if (!rtlhal->pfirmware)
  115. return 1;
  116. pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware;
  117. rtlhal->fw_version = le16_to_cpu(pfwheader->version);
  118. rtlhal->fw_subversion = pfwheader->subversion;
  119. pfwdata = (u8 *)rtlhal->pfirmware;
  120. fwsize = rtlhal->fwsize;
  121. RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
  122. "normal Firmware SIZE %d\n" , fwsize);
  123. if (IS_FW_HEADER_EXIST(pfwheader)) {
  124. RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
  125. "Firmware Version(%d), Signature(%#x),Size(%d)\n",
  126. pfwheader->version, pfwheader->signature,
  127. (int)sizeof(struct rtlwifi_firmware_header));
  128. pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header);
  129. fwsize = fwsize - sizeof(struct rtlwifi_firmware_header);
  130. } else {
  131. RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
  132. "Firmware no Header, Signature(%#x)\n",
  133. pfwheader->signature);
  134. }
  135. if (rtlhal->mac_func_enable) {
  136. if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) {
  137. rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
  138. rtl92ee_firmware_selfreset(hw);
  139. }
  140. }
  141. _rtl92ee_enable_fw_download(hw, true);
  142. _rtl92ee_write_fw(hw, version, pfwdata, fwsize);
  143. _rtl92ee_enable_fw_download(hw, false);
  144. err = _rtl92ee_fw_free_to_go(hw);
  145. return 0;
  146. }
  147. static bool _rtl92ee_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
  148. {
  149. struct rtl_priv *rtlpriv = rtl_priv(hw);
  150. u8 val_hmetfr;
  151. bool result = false;
  152. val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
  153. if (((val_hmetfr >> boxnum) & BIT(0)) == 0)
  154. result = true;
  155. return result;
  156. }
  157. static void _rtl92ee_fill_h2c_command(struct ieee80211_hw *hw, u8 element_id,
  158. u32 cmd_len, u8 *cmdbuffer)
  159. {
  160. struct rtl_priv *rtlpriv = rtl_priv(hw);
  161. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  162. struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
  163. u8 boxnum;
  164. u16 box_reg = 0, box_extreg = 0;
  165. u8 u1b_tmp;
  166. bool isfw_read = false;
  167. u8 buf_index = 0;
  168. bool bwrite_sucess = false;
  169. u8 wait_h2c_limmit = 100;
  170. u8 boxcontent[4], boxextcontent[4];
  171. u32 h2c_waitcounter = 0;
  172. unsigned long flag;
  173. u8 idx;
  174. if (ppsc->dot11_psmode != EACTIVE ||
  175. ppsc->inactive_pwrstate == ERFOFF) {
  176. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
  177. "FillH2CCommand8192E(): Return because RF is off!!!\n");
  178. return;
  179. }
  180. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "come in\n");
  181. /* 1. Prevent race condition in setting H2C cmd.
  182. * (copy from MgntActSet_RF_State().)
  183. */
  184. while (true) {
  185. spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
  186. if (rtlhal->h2c_setinprogress) {
  187. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
  188. "H2C set in progress! Wait to set..element_id(%d).\n",
  189. element_id);
  190. while (rtlhal->h2c_setinprogress) {
  191. spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
  192. flag);
  193. h2c_waitcounter++;
  194. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
  195. "Wait 100 us (%d times)...\n",
  196. h2c_waitcounter);
  197. udelay(100);
  198. if (h2c_waitcounter > 1000)
  199. return;
  200. spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
  201. flag);
  202. }
  203. spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
  204. } else {
  205. rtlhal->h2c_setinprogress = true;
  206. spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
  207. break;
  208. }
  209. }
  210. while (!bwrite_sucess) {
  211. /* 2. Find the last BOX number which has been writen. */
  212. boxnum = rtlhal->last_hmeboxnum;
  213. switch (boxnum) {
  214. case 0:
  215. box_reg = REG_HMEBOX_0;
  216. box_extreg = REG_HMEBOX_EXT_0;
  217. break;
  218. case 1:
  219. box_reg = REG_HMEBOX_1;
  220. box_extreg = REG_HMEBOX_EXT_1;
  221. break;
  222. case 2:
  223. box_reg = REG_HMEBOX_2;
  224. box_extreg = REG_HMEBOX_EXT_2;
  225. break;
  226. case 3:
  227. box_reg = REG_HMEBOX_3;
  228. box_extreg = REG_HMEBOX_EXT_3;
  229. break;
  230. default:
  231. RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
  232. "switch case %#x not processed\n", boxnum);
  233. break;
  234. }
  235. /* 3. Check if the box content is empty. */
  236. isfw_read = false;
  237. u1b_tmp = rtl_read_byte(rtlpriv, REG_CR);
  238. if (u1b_tmp != 0xea) {
  239. isfw_read = true;
  240. } else {
  241. if (rtl_read_byte(rtlpriv, REG_TXDMA_STATUS) == 0xea ||
  242. rtl_read_byte(rtlpriv, REG_TXPKT_EMPTY) == 0xea)
  243. rtl_write_byte(rtlpriv, REG_SYS_CFG1 + 3, 0xff);
  244. }
  245. if (isfw_read) {
  246. wait_h2c_limmit = 100;
  247. isfw_read = _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
  248. while (!isfw_read) {
  249. wait_h2c_limmit--;
  250. if (wait_h2c_limmit == 0) {
  251. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
  252. "Waiting too long for FW read clear HMEBox(%d)!!!\n",
  253. boxnum);
  254. break;
  255. }
  256. udelay(10);
  257. isfw_read =
  258. _rtl92ee_check_fw_read_last_h2c(hw, boxnum);
  259. u1b_tmp = rtl_read_byte(rtlpriv, 0x130);
  260. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
  261. "Waiting for FW read clear HMEBox(%d)!!! 0x130 = %2x\n",
  262. boxnum, u1b_tmp);
  263. }
  264. }
  265. /* If Fw has not read the last
  266. * H2C cmd, break and give up this H2C.
  267. */
  268. if (!isfw_read) {
  269. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
  270. "Write H2C reg BOX[%d] fail,Fw don't read.\n",
  271. boxnum);
  272. break;
  273. }
  274. /* 4. Fill the H2C cmd into box */
  275. memset(boxcontent, 0, sizeof(boxcontent));
  276. memset(boxextcontent, 0, sizeof(boxextcontent));
  277. boxcontent[0] = element_id;
  278. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
  279. "Write element_id box_reg(%4x) = %2x\n",
  280. box_reg, element_id);
  281. switch (cmd_len) {
  282. case 1:
  283. case 2:
  284. case 3:
  285. /*boxcontent[0] &= ~(BIT(7));*/
  286. memcpy((u8 *)(boxcontent) + 1,
  287. cmdbuffer + buf_index, cmd_len);
  288. for (idx = 0; idx < 4; idx++) {
  289. rtl_write_byte(rtlpriv, box_reg + idx,
  290. boxcontent[idx]);
  291. }
  292. break;
  293. case 4:
  294. case 5:
  295. case 6:
  296. case 7:
  297. /*boxcontent[0] |= (BIT(7));*/
  298. memcpy((u8 *)(boxextcontent),
  299. cmdbuffer + buf_index+3, cmd_len-3);
  300. memcpy((u8 *)(boxcontent) + 1,
  301. cmdbuffer + buf_index, 3);
  302. for (idx = 0; idx < 4; idx++) {
  303. rtl_write_byte(rtlpriv, box_extreg + idx,
  304. boxextcontent[idx]);
  305. }
  306. for (idx = 0; idx < 4; idx++) {
  307. rtl_write_byte(rtlpriv, box_reg + idx,
  308. boxcontent[idx]);
  309. }
  310. break;
  311. default:
  312. RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
  313. "switch case %#x not processed\n", cmd_len);
  314. break;
  315. }
  316. bwrite_sucess = true;
  317. rtlhal->last_hmeboxnum = boxnum + 1;
  318. if (rtlhal->last_hmeboxnum == 4)
  319. rtlhal->last_hmeboxnum = 0;
  320. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD ,
  321. "pHalData->last_hmeboxnum = %d\n",
  322. rtlhal->last_hmeboxnum);
  323. }
  324. spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
  325. rtlhal->h2c_setinprogress = false;
  326. spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
  327. RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD , "go out\n");
  328. }
  329. void rtl92ee_fill_h2c_cmd(struct ieee80211_hw *hw,
  330. u8 element_id, u32 cmd_len, u8 *cmdbuffer)
  331. {
  332. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  333. u32 tmp_cmdbuf[2];
  334. if (!rtlhal->fw_ready) {
  335. WARN_ONCE(true,
  336. "rtl8192ee: error H2C cmd because of Fw download fail!!!\n");
  337. return;
  338. }
  339. memset(tmp_cmdbuf, 0, 8);
  340. memcpy(tmp_cmdbuf, cmdbuffer, cmd_len);
  341. _rtl92ee_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
  342. }
  343. void rtl92ee_firmware_selfreset(struct ieee80211_hw *hw)
  344. {
  345. u8 u1b_tmp;
  346. struct rtl_priv *rtlpriv = rtl_priv(hw);
  347. u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
  348. rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0))));
  349. u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
  350. rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2))));
  351. udelay(50);
  352. u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1);
  353. rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0)));
  354. u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
  355. rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2)));
  356. RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD ,
  357. " _8051Reset92E(): 8051 reset success .\n");
  358. }
  359. void rtl92ee_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
  360. {
  361. struct rtl_priv *rtlpriv = rtl_priv(hw);
  362. u8 u1_h2c_set_pwrmode[H2C_92E_PWEMODE_LENGTH] = { 0 };
  363. struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
  364. u8 rlbm , power_state = 0;
  365. RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD , "FW LPS mode = %d\n", mode);
  366. SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, ((mode) ? 1 : 0));
  367. rlbm = 0;/*YJ,temp,120316. FW now not support RLBM=2.*/
  368. SET_H2CCMD_PWRMODE_PARM_RLBM(u1_h2c_set_pwrmode, rlbm);
  369. SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode,
  370. (rtlpriv->mac80211.p2p) ?
  371. ppsc->smart_ps : 1);
  372. SET_H2CCMD_PWRMODE_PARM_AWAKE_INTERVAL(u1_h2c_set_pwrmode,
  373. ppsc->reg_max_lps_awakeintvl);
  374. SET_H2CCMD_PWRMODE_PARM_ALL_QUEUE_UAPSD(u1_h2c_set_pwrmode, 0);
  375. if (mode == FW_PS_ACTIVE_MODE)
  376. power_state |= FW_PWR_STATE_ACTIVE;
  377. else
  378. power_state |= FW_PWR_STATE_RF_OFF;
  379. SET_H2CCMD_PWRMODE_PARM_PWR_STATE(u1_h2c_set_pwrmode, power_state);
  380. RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
  381. "rtl92c_set_fw_pwrmode(): u1_h2c_set_pwrmode\n",
  382. u1_h2c_set_pwrmode, H2C_92E_PWEMODE_LENGTH);
  383. rtl92ee_fill_h2c_cmd(hw, H2C_92E_SETPWRMODE, H2C_92E_PWEMODE_LENGTH,
  384. u1_h2c_set_pwrmode);
  385. }
  386. void rtl92ee_set_fw_media_status_rpt_cmd(struct ieee80211_hw *hw, u8 mstatus)
  387. {
  388. u8 parm[3] = { 0 , 0 , 0 };
  389. /* parm[0]: bit0=0-->Disconnect, bit0=1-->Connect
  390. * bit1=0-->update Media Status to MACID
  391. * bit1=1-->update Media Status from MACID to MACID_End
  392. * parm[1]: MACID, if this is INFRA_STA, MacID = 0
  393. * parm[2]: MACID_End
  394. */
  395. SET_H2CCMD_MSRRPT_PARM_OPMODE(parm, mstatus);
  396. SET_H2CCMD_MSRRPT_PARM_MACID_IND(parm, 0);
  397. rtl92ee_fill_h2c_cmd(hw, H2C_92E_MSRRPT, 3, parm);
  398. }
  399. #define BEACON_PG 0 /* ->1 */
  400. #define PSPOLL_PG 2
  401. #define NULL_PG 3
  402. #define PROBERSP_PG 4 /* ->5 */
  403. #define TOTAL_RESERVED_PKT_LEN 768
  404. static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
  405. /* page 0 beacon */
  406. 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
  407. 0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
  408. 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x20, 0x00,
  409. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  410. 0x64, 0x00, 0x10, 0x04, 0x00, 0x05, 0x54, 0x65,
  411. 0x73, 0x74, 0x32, 0x01, 0x08, 0x82, 0x84, 0x0B,
  412. 0x16, 0x24, 0x30, 0x48, 0x6C, 0x03, 0x01, 0x06,
  413. 0x06, 0x02, 0x00, 0x00, 0x2A, 0x01, 0x02, 0x32,
  414. 0x04, 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C,
  415. 0x09, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
  416. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  417. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  418. 0x00, 0x3D, 0x00, 0xDD, 0x07, 0x00, 0xE0, 0x4C,
  419. 0x02, 0x02, 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50,
  420. 0xF2, 0x01, 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04,
  421. 0x01, 0x00, 0x00, 0x50, 0xF2, 0x04, 0x01, 0x00,
  422. /* page 1 beacon */
  423. 0x00, 0x50, 0xF2, 0x02, 0x00, 0x00, 0x00, 0x00,
  424. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  425. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  426. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  427. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  428. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  429. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  430. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  431. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  432. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  433. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  434. 0x10, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
  435. 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00,
  436. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  437. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  438. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  439. /* page 2 ps-poll */
  440. 0xA4, 0x10, 0x01, 0xC0, 0xEC, 0x1A, 0x59, 0x0B,
  441. 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
  442. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  443. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  444. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  445. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  446. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  447. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  448. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  449. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  450. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  451. 0x18, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
  452. 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
  453. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  454. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  455. 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  456. /* page 3 null */
  457. 0x48, 0x01, 0x00, 0x00, 0xEC, 0x1A, 0x59, 0x0B,
  458. 0xAD, 0xD4, 0x00, 0xE0, 0x4C, 0x02, 0xB1, 0x78,
  459. 0xEC, 0x1A, 0x59, 0x0B, 0xAD, 0xD4, 0x00, 0x00,
  460. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  461. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  462. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  463. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  464. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  465. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  466. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  467. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  468. 0x72, 0x00, 0x28, 0x8C, 0x00, 0x12, 0x00, 0x00,
  469. 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
  470. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  471. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  472. 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  473. /* page 4 probe_resp */
  474. 0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
  475. 0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
  476. 0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
  477. 0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
  478. 0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
  479. 0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
  480. 0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
  481. 0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
  482. 0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
  483. 0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
  484. 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  485. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  486. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  487. 0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
  488. 0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  489. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  490. /* page 5 probe_resp */
  491. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  492. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  493. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  494. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  495. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  496. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  497. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  498. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  499. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  500. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  501. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  502. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  503. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  504. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  505. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  506. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  507. };
  508. void rtl92ee_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
  509. {
  510. struct rtl_priv *rtlpriv = rtl_priv(hw);
  511. struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
  512. struct sk_buff *skb = NULL;
  513. u32 totalpacketlen;
  514. u8 u1rsvdpageloc[5] = { 0 };
  515. bool b_dlok = false;
  516. u8 *beacon;
  517. u8 *p_pspoll;
  518. u8 *nullfunc;
  519. u8 *p_probersp;
  520. /*---------------------------------------------------------
  521. * (1) beacon
  522. *---------------------------------------------------------
  523. */
  524. beacon = &reserved_page_packet[BEACON_PG * 128];
  525. SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
  526. SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
  527. /*-------------------------------------------------------
  528. * (2) ps-poll
  529. *--------------------------------------------------------
  530. */
  531. p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
  532. SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
  533. SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
  534. SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
  535. SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1rsvdpageloc, PSPOLL_PG);
  536. /*--------------------------------------------------------
  537. * (3) null data
  538. *---------------------------------------------------------
  539. */
  540. nullfunc = &reserved_page_packet[NULL_PG * 128];
  541. SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
  542. SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
  543. SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
  544. SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1rsvdpageloc, NULL_PG);
  545. /*---------------------------------------------------------
  546. * (4) probe response
  547. *----------------------------------------------------------
  548. */
  549. p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
  550. SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
  551. SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
  552. SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
  553. SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1rsvdpageloc, PROBERSP_PG);
  554. totalpacketlen = TOTAL_RESERVED_PKT_LEN;
  555. RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
  556. "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
  557. &reserved_page_packet[0], totalpacketlen);
  558. RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
  559. "rtl92ee_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
  560. u1rsvdpageloc, 3);
  561. skb = dev_alloc_skb(totalpacketlen);
  562. memcpy((u8 *)skb_put(skb, totalpacketlen),
  563. &reserved_page_packet, totalpacketlen);
  564. b_dlok = true;
  565. if (b_dlok) {
  566. RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD ,
  567. "Set RSVD page location to Fw.\n");
  568. RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD ,
  569. "H2C_RSVDPAGE:\n", u1rsvdpageloc, 3);
  570. rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSVDPAGE,
  571. sizeof(u1rsvdpageloc), u1rsvdpageloc);
  572. } else {
  573. RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
  574. "Set RSVD page location to Fw FAIL!!!!!!.\n");
  575. }
  576. }
  577. /*Shoud check FW support p2p or not.*/
  578. static void rtl92ee_set_p2p_ctw_period_cmd(struct ieee80211_hw *hw, u8 ctwindow)
  579. {
  580. u8 u1_ctwindow_period[1] = {ctwindow};
  581. rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_CTW_CMD, 1, u1_ctwindow_period);
  582. }
  583. void rtl92ee_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state)
  584. {
  585. struct rtl_priv *rtlpriv = rtl_priv(hw);
  586. struct rtl_ps_ctl *rtlps = rtl_psc(rtl_priv(hw));
  587. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  588. struct rtl_p2p_ps_info *p2pinfo = &rtlps->p2p_ps_info;
  589. struct p2p_ps_offload_t *p2p_ps_offload = &rtlhal->p2p_ps_offload;
  590. u8 i;
  591. u16 ctwindow;
  592. u32 start_time, tsf_low;
  593. switch (p2p_ps_state) {
  594. case P2P_PS_DISABLE:
  595. RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_DISABLE\n");
  596. memset(p2p_ps_offload, 0, sizeof(*p2p_ps_offload));
  597. break;
  598. case P2P_PS_ENABLE:
  599. RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_ENABLE\n");
  600. /* update CTWindow value. */
  601. if (p2pinfo->ctwindow > 0) {
  602. p2p_ps_offload->ctwindow_en = 1;
  603. ctwindow = p2pinfo->ctwindow;
  604. rtl92ee_set_p2p_ctw_period_cmd(hw, ctwindow);
  605. }
  606. /* hw only support 2 set of NoA */
  607. for (i = 0 ; i < p2pinfo->noa_num ; i++) {
  608. /* To control the register setting for which NOA*/
  609. rtl_write_byte(rtlpriv, 0x5cf, (i << 4));
  610. if (i == 0)
  611. p2p_ps_offload->noa0_en = 1;
  612. else
  613. p2p_ps_offload->noa1_en = 1;
  614. /* config P2P NoA Descriptor Register */
  615. rtl_write_dword(rtlpriv, 0x5E0,
  616. p2pinfo->noa_duration[i]);
  617. rtl_write_dword(rtlpriv, 0x5E4,
  618. p2pinfo->noa_interval[i]);
  619. /*Get Current TSF value */
  620. tsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
  621. start_time = p2pinfo->noa_start_time[i];
  622. if (p2pinfo->noa_count_type[i] != 1) {
  623. while (start_time <= (tsf_low + (50 * 1024))) {
  624. start_time += p2pinfo->noa_interval[i];
  625. if (p2pinfo->noa_count_type[i] != 255)
  626. p2pinfo->noa_count_type[i]--;
  627. }
  628. }
  629. rtl_write_dword(rtlpriv, 0x5E8, start_time);
  630. rtl_write_dword(rtlpriv, 0x5EC,
  631. p2pinfo->noa_count_type[i]);
  632. }
  633. if ((p2pinfo->opp_ps == 1) || (p2pinfo->noa_num > 0)) {
  634. /* rst p2p circuit */
  635. rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, BIT(4));
  636. p2p_ps_offload->offload_en = 1;
  637. if (P2P_ROLE_GO == rtlpriv->mac80211.p2p) {
  638. p2p_ps_offload->role = 1;
  639. p2p_ps_offload->allstasleep = 0;
  640. } else {
  641. p2p_ps_offload->role = 0;
  642. }
  643. p2p_ps_offload->discovery = 0;
  644. }
  645. break;
  646. case P2P_PS_SCAN:
  647. RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN\n");
  648. p2p_ps_offload->discovery = 1;
  649. break;
  650. case P2P_PS_SCAN_DONE:
  651. RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD , "P2P_PS_SCAN_DONE\n");
  652. p2p_ps_offload->discovery = 0;
  653. p2pinfo->p2p_ps_state = P2P_PS_ENABLE;
  654. break;
  655. default:
  656. break;
  657. }
  658. rtl92ee_fill_h2c_cmd(hw, H2C_92E_P2P_PS_OFFLOAD, 1,
  659. (u8 *)p2p_ps_offload);
  660. }
  661. static void _rtl92ee_c2h_ra_report_handler(struct ieee80211_hw *hw,
  662. u8 *cmd_buf, u8 cmd_len)
  663. {
  664. u8 rate = cmd_buf[0] & 0x3F;
  665. bool collision_state = cmd_buf[3] & BIT(0);
  666. rtl92ee_dm_dynamic_arfb_select(hw, rate, collision_state);
  667. }
  668. void rtl92ee_c2h_content_parsing(struct ieee80211_hw *hw, u8 c2h_cmd_id,
  669. u8 c2h_cmd_len, u8 *tmp_buf)
  670. {
  671. struct rtl_priv *rtlpriv = rtl_priv(hw);
  672. switch (c2h_cmd_id) {
  673. case C2H_8192E_DBG:
  674. RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
  675. "[C2H], C2H_8723BE_DBG!!\n");
  676. break;
  677. case C2H_8192E_TXBF:
  678. RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
  679. "[C2H], C2H_8192E_TXBF!!\n");
  680. break;
  681. case C2H_8192E_TX_REPORT:
  682. RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE ,
  683. "[C2H], C2H_8723BE_TX_REPORT!\n");
  684. break;
  685. case C2H_8192E_BT_INFO:
  686. RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
  687. "[C2H], C2H_8723BE_BT_INFO!!\n");
  688. rtlpriv->btcoexist.btc_ops->btc_btinfo_notify(rtlpriv, tmp_buf,
  689. c2h_cmd_len);
  690. break;
  691. case C2H_8192E_BT_MP:
  692. RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
  693. "[C2H], C2H_8723BE_BT_MP!!\n");
  694. break;
  695. case C2H_8192E_RA_RPT:
  696. _rtl92ee_c2h_ra_report_handler(hw, tmp_buf, c2h_cmd_len);
  697. break;
  698. default:
  699. RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
  700. "[C2H], Unknown packet!! CmdId(%#X)!\n", c2h_cmd_id);
  701. break;
  702. }
  703. }
  704. void rtl92ee_c2h_packet_handler(struct ieee80211_hw *hw, u8 *buffer, u8 len)
  705. {
  706. struct rtl_priv *rtlpriv = rtl_priv(hw);
  707. u8 c2h_cmd_id = 0, c2h_cmd_seq = 0, c2h_cmd_len = 0;
  708. u8 *tmp_buf = NULL;
  709. c2h_cmd_id = buffer[0];
  710. c2h_cmd_seq = buffer[1];
  711. c2h_cmd_len = len - 2;
  712. tmp_buf = buffer + 2;
  713. RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
  714. "[C2H packet], c2hCmdId=0x%x, c2hCmdSeq=0x%x, c2hCmdLen=%d\n",
  715. c2h_cmd_id, c2h_cmd_seq, c2h_cmd_len);
  716. RT_PRINT_DATA(rtlpriv, COMP_FW, DBG_TRACE,
  717. "[C2H packet], Content Hex:\n", tmp_buf, c2h_cmd_len);
  718. switch (c2h_cmd_id) {
  719. case C2H_8192E_BT_INFO:
  720. case C2H_8192E_BT_MP:
  721. rtl_c2hcmd_enqueue(hw, c2h_cmd_id, c2h_cmd_len, tmp_buf);
  722. break;
  723. default:
  724. rtl92ee_c2h_content_parsing(hw, c2h_cmd_id, c2h_cmd_len,
  725. tmp_buf);
  726. break;
  727. }
  728. }