phy.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2009-2012 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. * You should have received a copy of the GNU General Public License along with
  15. * this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  17. *
  18. * The full GNU General Public License is included in this distribution in the
  19. * file called LICENSE.
  20. *
  21. * Contact Information:
  22. * wlanfae <wlanfae@realtek.com>
  23. * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
  24. * Hsinchu 300, Taiwan.
  25. *
  26. * Larry Finger <Larry.Finger@lwfinger.net>
  27. *
  28. *****************************************************************************/
  29. #include "../wifi.h"
  30. #include "../pci.h"
  31. #include "../ps.h"
  32. #include "reg.h"
  33. #include "def.h"
  34. #include "hw.h"
  35. #include "phy.h"
  36. #include "rf.h"
  37. #include "dm.h"
  38. #include "table.h"
  39. static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
  40. u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw,
  41. enum radio_path rfpath, u32 regaddr, u32 bitmask)
  42. {
  43. struct rtl_priv *rtlpriv = rtl_priv(hw);
  44. u32 original_value, readback_value, bitshift;
  45. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  46. RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
  47. "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n",
  48. regaddr, rfpath, bitmask);
  49. spin_lock(&rtlpriv->locks.rf_lock);
  50. if (rtlphy->rf_mode != RF_OP_BY_FW) {
  51. original_value = _rtl92c_phy_rf_serial_read(hw,
  52. rfpath, regaddr);
  53. } else {
  54. original_value = _rtl92c_phy_fw_rf_serial_read(hw,
  55. rfpath, regaddr);
  56. }
  57. bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
  58. readback_value = (original_value & bitmask) >> bitshift;
  59. spin_unlock(&rtlpriv->locks.rf_lock);
  60. RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
  61. "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n",
  62. regaddr, rfpath, bitmask, original_value);
  63. return readback_value;
  64. }
  65. bool rtl92c_phy_mac_config(struct ieee80211_hw *hw)
  66. {
  67. struct rtl_priv *rtlpriv = rtl_priv(hw);
  68. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  69. bool is92c = IS_92C_SERIAL(rtlhal->version);
  70. bool rtstatus = _rtl92c_phy_config_mac_with_headerfile(hw);
  71. if (is92c)
  72. rtl_write_byte(rtlpriv, 0x14, 0x71);
  73. else
  74. rtl_write_byte(rtlpriv, 0x04CA, 0x0A);
  75. return rtstatus;
  76. }
  77. bool rtl92c_phy_bb_config(struct ieee80211_hw *hw)
  78. {
  79. bool rtstatus = true;
  80. struct rtl_priv *rtlpriv = rtl_priv(hw);
  81. u16 regval;
  82. u32 regvaldw;
  83. u8 reg_hwparafile = 1;
  84. _rtl92c_phy_init_bb_rf_register_definition(hw);
  85. regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
  86. rtl_write_word(rtlpriv, REG_SYS_FUNC_EN,
  87. regval | BIT(13) | BIT(0) | BIT(1));
  88. rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83);
  89. rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb);
  90. rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB);
  91. rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN,
  92. FEN_PPLL | FEN_PCIEA | FEN_DIO_PCIE |
  93. FEN_BB_GLB_RSTn | FEN_BBRSTB);
  94. rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80);
  95. regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0);
  96. rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23));
  97. if (reg_hwparafile == 1)
  98. rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw);
  99. return rtstatus;
  100. }
  101. void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw,
  102. enum radio_path rfpath,
  103. u32 regaddr, u32 bitmask, u32 data)
  104. {
  105. struct rtl_priv *rtlpriv = rtl_priv(hw);
  106. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  107. u32 original_value, bitshift;
  108. RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
  109. "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
  110. regaddr, bitmask, data, rfpath);
  111. spin_lock(&rtlpriv->locks.rf_lock);
  112. if (rtlphy->rf_mode != RF_OP_BY_FW) {
  113. if (bitmask != RFREG_OFFSET_MASK) {
  114. original_value = _rtl92c_phy_rf_serial_read(hw,
  115. rfpath,
  116. regaddr);
  117. bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
  118. data =
  119. ((original_value & (~bitmask)) |
  120. (data << bitshift));
  121. }
  122. _rtl92c_phy_rf_serial_write(hw, rfpath, regaddr, data);
  123. } else {
  124. if (bitmask != RFREG_OFFSET_MASK) {
  125. original_value = _rtl92c_phy_fw_rf_serial_read(hw,
  126. rfpath,
  127. regaddr);
  128. bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
  129. data =
  130. ((original_value & (~bitmask)) |
  131. (data << bitshift));
  132. }
  133. _rtl92c_phy_fw_rf_serial_write(hw, rfpath, regaddr, data);
  134. }
  135. spin_unlock(&rtlpriv->locks.rf_lock);
  136. RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
  137. "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
  138. regaddr, bitmask, data, rfpath);
  139. }
  140. static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw)
  141. {
  142. struct rtl_priv *rtlpriv = rtl_priv(hw);
  143. u32 i;
  144. u32 arraylength;
  145. u32 *ptrarray;
  146. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_Array\n");
  147. arraylength = MAC_2T_ARRAYLENGTH;
  148. ptrarray = RTL8192CEMAC_2T_ARRAY;
  149. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:RTL8192CEMAC_2T_ARRAY\n");
  150. for (i = 0; i < arraylength; i = i + 2)
  151. rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]);
  152. return true;
  153. }
  154. bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
  155. u8 configtype)
  156. {
  157. int i;
  158. u32 *phy_regarray_table;
  159. u32 *agctab_array_table;
  160. u16 phy_reg_arraylen, agctab_arraylen;
  161. struct rtl_priv *rtlpriv = rtl_priv(hw);
  162. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  163. if (IS_92C_SERIAL(rtlhal->version)) {
  164. agctab_arraylen = AGCTAB_2TARRAYLENGTH;
  165. agctab_array_table = RTL8192CEAGCTAB_2TARRAY;
  166. phy_reg_arraylen = PHY_REG_2TARRAY_LENGTH;
  167. phy_regarray_table = RTL8192CEPHY_REG_2TARRAY;
  168. } else {
  169. agctab_arraylen = AGCTAB_1TARRAYLENGTH;
  170. agctab_array_table = RTL8192CEAGCTAB_1TARRAY;
  171. phy_reg_arraylen = PHY_REG_1TARRAY_LENGTH;
  172. phy_regarray_table = RTL8192CEPHY_REG_1TARRAY;
  173. }
  174. if (configtype == BASEBAND_CONFIG_PHY_REG) {
  175. for (i = 0; i < phy_reg_arraylen; i = i + 2) {
  176. if (phy_regarray_table[i] == 0xfe)
  177. mdelay(50);
  178. else if (phy_regarray_table[i] == 0xfd)
  179. mdelay(5);
  180. else if (phy_regarray_table[i] == 0xfc)
  181. mdelay(1);
  182. else if (phy_regarray_table[i] == 0xfb)
  183. udelay(50);
  184. else if (phy_regarray_table[i] == 0xfa)
  185. udelay(5);
  186. else if (phy_regarray_table[i] == 0xf9)
  187. udelay(1);
  188. rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD,
  189. phy_regarray_table[i + 1]);
  190. udelay(1);
  191. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  192. "The phy_regarray_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n",
  193. phy_regarray_table[i],
  194. phy_regarray_table[i + 1]);
  195. }
  196. } else if (configtype == BASEBAND_CONFIG_AGC_TAB) {
  197. for (i = 0; i < agctab_arraylen; i = i + 2) {
  198. rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD,
  199. agctab_array_table[i + 1]);
  200. udelay(1);
  201. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  202. "The agctab_array_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n",
  203. agctab_array_table[i],
  204. agctab_array_table[i + 1]);
  205. }
  206. }
  207. return true;
  208. }
  209. bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
  210. u8 configtype)
  211. {
  212. struct rtl_priv *rtlpriv = rtl_priv(hw);
  213. int i;
  214. u32 *phy_regarray_table_pg;
  215. u16 phy_regarray_pg_len;
  216. phy_regarray_pg_len = PHY_REG_ARRAY_PGLENGTH;
  217. phy_regarray_table_pg = RTL8192CEPHY_REG_ARRAY_PG;
  218. if (configtype == BASEBAND_CONFIG_PHY_REG) {
  219. for (i = 0; i < phy_regarray_pg_len; i = i + 3) {
  220. if (phy_regarray_table_pg[i] == 0xfe)
  221. mdelay(50);
  222. else if (phy_regarray_table_pg[i] == 0xfd)
  223. mdelay(5);
  224. else if (phy_regarray_table_pg[i] == 0xfc)
  225. mdelay(1);
  226. else if (phy_regarray_table_pg[i] == 0xfb)
  227. udelay(50);
  228. else if (phy_regarray_table_pg[i] == 0xfa)
  229. udelay(5);
  230. else if (phy_regarray_table_pg[i] == 0xf9)
  231. udelay(1);
  232. _rtl92c_store_pwrIndex_diffrate_offset(hw,
  233. phy_regarray_table_pg[i],
  234. phy_regarray_table_pg[i + 1],
  235. phy_regarray_table_pg[i + 2]);
  236. }
  237. } else {
  238. RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
  239. "configtype != BaseBand_Config_PHY_REG\n");
  240. }
  241. return true;
  242. }
  243. bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
  244. enum radio_path rfpath)
  245. {
  246. int i;
  247. u32 *radioa_array_table;
  248. u32 *radiob_array_table;
  249. u16 radioa_arraylen, radiob_arraylen;
  250. struct rtl_priv *rtlpriv = rtl_priv(hw);
  251. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  252. if (IS_92C_SERIAL(rtlhal->version)) {
  253. radioa_arraylen = RADIOA_2TARRAYLENGTH;
  254. radioa_array_table = RTL8192CERADIOA_2TARRAY;
  255. radiob_arraylen = RADIOB_2TARRAYLENGTH;
  256. radiob_array_table = RTL8192CE_RADIOB_2TARRAY;
  257. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  258. "Radio_A:RTL8192CERADIOA_2TARRAY\n");
  259. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  260. "Radio_B:RTL8192CE_RADIOB_2TARRAY\n");
  261. } else {
  262. radioa_arraylen = RADIOA_1TARRAYLENGTH;
  263. radioa_array_table = RTL8192CE_RADIOA_1TARRAY;
  264. radiob_arraylen = RADIOB_1TARRAYLENGTH;
  265. radiob_array_table = RTL8192CE_RADIOB_1TARRAY;
  266. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  267. "Radio_A:RTL8192CE_RADIOA_1TARRAY\n");
  268. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  269. "Radio_B:RTL8192CE_RADIOB_1TARRAY\n");
  270. }
  271. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Radio No %x\n", rfpath);
  272. switch (rfpath) {
  273. case RF90_PATH_A:
  274. for (i = 0; i < radioa_arraylen; i = i + 2) {
  275. if (radioa_array_table[i] == 0xfe)
  276. mdelay(50);
  277. else if (radioa_array_table[i] == 0xfd)
  278. mdelay(5);
  279. else if (radioa_array_table[i] == 0xfc)
  280. mdelay(1);
  281. else if (radioa_array_table[i] == 0xfb)
  282. udelay(50);
  283. else if (radioa_array_table[i] == 0xfa)
  284. udelay(5);
  285. else if (radioa_array_table[i] == 0xf9)
  286. udelay(1);
  287. else {
  288. rtl_set_rfreg(hw, rfpath, radioa_array_table[i],
  289. RFREG_OFFSET_MASK,
  290. radioa_array_table[i + 1]);
  291. udelay(1);
  292. }
  293. }
  294. break;
  295. case RF90_PATH_B:
  296. for (i = 0; i < radiob_arraylen; i = i + 2) {
  297. if (radiob_array_table[i] == 0xfe) {
  298. mdelay(50);
  299. } else if (radiob_array_table[i] == 0xfd)
  300. mdelay(5);
  301. else if (radiob_array_table[i] == 0xfc)
  302. mdelay(1);
  303. else if (radiob_array_table[i] == 0xfb)
  304. udelay(50);
  305. else if (radiob_array_table[i] == 0xfa)
  306. udelay(5);
  307. else if (radiob_array_table[i] == 0xf9)
  308. udelay(1);
  309. else {
  310. rtl_set_rfreg(hw, rfpath, radiob_array_table[i],
  311. RFREG_OFFSET_MASK,
  312. radiob_array_table[i + 1]);
  313. udelay(1);
  314. }
  315. }
  316. break;
  317. case RF90_PATH_C:
  318. RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
  319. "switch case not processed\n");
  320. break;
  321. case RF90_PATH_D:
  322. RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
  323. "switch case not processed\n");
  324. break;
  325. }
  326. return true;
  327. }
  328. void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw)
  329. {
  330. struct rtl_priv *rtlpriv = rtl_priv(hw);
  331. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  332. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  333. struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
  334. u8 reg_bw_opmode;
  335. u8 reg_prsr_rsc;
  336. RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "Switch to %s bandwidth\n",
  337. rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
  338. "20MHz" : "40MHz");
  339. if (is_hal_stop(rtlhal)) {
  340. rtlphy->set_bwmode_inprogress = false;
  341. return;
  342. }
  343. reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE);
  344. reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2);
  345. switch (rtlphy->current_chan_bw) {
  346. case HT_CHANNEL_WIDTH_20:
  347. reg_bw_opmode |= BW_OPMODE_20MHZ;
  348. rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
  349. break;
  350. case HT_CHANNEL_WIDTH_20_40:
  351. reg_bw_opmode &= ~BW_OPMODE_20MHZ;
  352. rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
  353. reg_prsr_rsc =
  354. (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5);
  355. rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc);
  356. break;
  357. default:
  358. RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
  359. "unknown bandwidth: %#X\n", rtlphy->current_chan_bw);
  360. break;
  361. }
  362. switch (rtlphy->current_chan_bw) {
  363. case HT_CHANNEL_WIDTH_20:
  364. rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0);
  365. rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0);
  366. rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);
  367. break;
  368. case HT_CHANNEL_WIDTH_20_40:
  369. rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1);
  370. rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1);
  371. rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND,
  372. (mac->cur_40_prime_sc >> 1));
  373. rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc);
  374. rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0);
  375. rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)),
  376. (mac->cur_40_prime_sc ==
  377. HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
  378. break;
  379. default:
  380. RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
  381. "unknown bandwidth: %#X\n", rtlphy->current_chan_bw);
  382. break;
  383. }
  384. rtl92ce_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw);
  385. rtlphy->set_bwmode_inprogress = false;
  386. RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n");
  387. }
  388. void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
  389. {
  390. u8 tmpreg;
  391. u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
  392. struct rtl_priv *rtlpriv = rtl_priv(hw);
  393. tmpreg = rtl_read_byte(rtlpriv, 0xd03);
  394. if ((tmpreg & 0x70) != 0)
  395. rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F);
  396. else
  397. rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
  398. if ((tmpreg & 0x70) != 0) {
  399. rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS);
  400. if (is2t)
  401. rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00,
  402. MASK12BITS);
  403. rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS,
  404. (rf_a_mode & 0x8FFFF) | 0x10000);
  405. if (is2t)
  406. rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
  407. (rf_b_mode & 0x8FFFF) | 0x10000);
  408. }
  409. lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS);
  410. rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000);
  411. mdelay(100);
  412. if ((tmpreg & 0x70) != 0) {
  413. rtl_write_byte(rtlpriv, 0xd03, tmpreg);
  414. rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode);
  415. if (is2t)
  416. rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
  417. rf_b_mode);
  418. } else {
  419. rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
  420. }
  421. }
  422. static void _rtl92ce_phy_set_rf_sleep(struct ieee80211_hw *hw)
  423. {
  424. u32 u4b_tmp;
  425. u8 delay = 5;
  426. struct rtl_priv *rtlpriv = rtl_priv(hw);
  427. rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
  428. rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00);
  429. rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
  430. u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK);
  431. while (u4b_tmp != 0 && delay > 0) {
  432. rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0);
  433. rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00);
  434. rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
  435. u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK);
  436. delay--;
  437. }
  438. if (delay == 0) {
  439. rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
  440. rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
  441. rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
  442. rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
  443. RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
  444. "Switch RF timeout !!!\n");
  445. return;
  446. }
  447. rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
  448. rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22);
  449. }
  450. static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
  451. enum rf_pwrstate rfpwr_state)
  452. {
  453. struct rtl_priv *rtlpriv = rtl_priv(hw);
  454. struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
  455. struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
  456. struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
  457. bool bresult = true;
  458. u8 i, queue_id;
  459. struct rtl8192_tx_ring *ring = NULL;
  460. switch (rfpwr_state) {
  461. case ERFON:{
  462. if ((ppsc->rfpwr_state == ERFOFF) &&
  463. RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
  464. bool rtstatus;
  465. u32 InitializeCount = 0;
  466. do {
  467. InitializeCount++;
  468. RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
  469. "IPS Set eRf nic enable\n");
  470. rtstatus = rtl_ps_enable_nic(hw);
  471. } while (!rtstatus && (InitializeCount < 10));
  472. RT_CLEAR_PS_LEVEL(ppsc,
  473. RT_RF_OFF_LEVL_HALT_NIC);
  474. } else {
  475. RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
  476. "Set ERFON sleeped:%d ms\n",
  477. jiffies_to_msecs(jiffies -
  478. ppsc->
  479. last_sleep_jiffies));
  480. ppsc->last_awake_jiffies = jiffies;
  481. rtl92ce_phy_set_rf_on(hw);
  482. }
  483. if (mac->link_state == MAC80211_LINKED) {
  484. rtlpriv->cfg->ops->led_control(hw,
  485. LED_CTL_LINK);
  486. } else {
  487. rtlpriv->cfg->ops->led_control(hw,
  488. LED_CTL_NO_LINK);
  489. }
  490. break;
  491. }
  492. case ERFOFF:{
  493. if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) {
  494. RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
  495. "IPS Set eRf nic disable\n");
  496. rtl_ps_disable_nic(hw);
  497. RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
  498. } else {
  499. if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) {
  500. rtlpriv->cfg->ops->led_control(hw,
  501. LED_CTL_NO_LINK);
  502. } else {
  503. rtlpriv->cfg->ops->led_control(hw,
  504. LED_CTL_POWER_OFF);
  505. }
  506. }
  507. break;
  508. }
  509. case ERFSLEEP:{
  510. if (ppsc->rfpwr_state == ERFOFF)
  511. return false;
  512. for (queue_id = 0, i = 0;
  513. queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
  514. ring = &pcipriv->dev.tx_ring[queue_id];
  515. if (skb_queue_len(&ring->queue) == 0) {
  516. queue_id++;
  517. continue;
  518. } else {
  519. RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
  520. "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n",
  521. i + 1, queue_id,
  522. skb_queue_len(&ring->queue));
  523. udelay(10);
  524. i++;
  525. }
  526. if (i >= MAX_DOZE_WAITING_TIMES_9x) {
  527. RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
  528. "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n",
  529. MAX_DOZE_WAITING_TIMES_9x,
  530. queue_id,
  531. skb_queue_len(&ring->queue));
  532. break;
  533. }
  534. }
  535. RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
  536. "Set ERFSLEEP awaked:%d ms\n",
  537. jiffies_to_msecs(jiffies -
  538. ppsc->last_awake_jiffies));
  539. ppsc->last_sleep_jiffies = jiffies;
  540. _rtl92ce_phy_set_rf_sleep(hw);
  541. break;
  542. }
  543. default:
  544. RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
  545. "switch case not processed\n");
  546. bresult = false;
  547. break;
  548. }
  549. if (bresult)
  550. ppsc->rfpwr_state = rfpwr_state;
  551. return bresult;
  552. }
  553. bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw,
  554. enum rf_pwrstate rfpwr_state)
  555. {
  556. struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
  557. bool bresult = false;
  558. if (rfpwr_state == ppsc->rfpwr_state)
  559. return bresult;
  560. bresult = _rtl92ce_phy_set_rf_power_state(hw, rfpwr_state);
  561. return bresult;
  562. }