phy.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  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 "phy.h"
  35. #include "rf.h"
  36. #include "dm.h"
  37. #include "table.h"
  38. u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw,
  39. enum radio_path rfpath, u32 regaddr, u32 bitmask)
  40. {
  41. struct rtl_priv *rtlpriv = rtl_priv(hw);
  42. u32 original_value, readback_value, bitshift;
  43. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  44. RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
  45. "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n",
  46. regaddr, rfpath, bitmask);
  47. if (rtlphy->rf_mode != RF_OP_BY_FW) {
  48. original_value = _rtl92c_phy_rf_serial_read(hw,
  49. rfpath, regaddr);
  50. } else {
  51. original_value = _rtl92c_phy_fw_rf_serial_read(hw,
  52. rfpath, regaddr);
  53. }
  54. bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
  55. readback_value = (original_value & bitmask) >> bitshift;
  56. RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
  57. "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n",
  58. regaddr, rfpath, bitmask, original_value);
  59. return readback_value;
  60. }
  61. void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw,
  62. enum radio_path rfpath,
  63. u32 regaddr, u32 bitmask, u32 data)
  64. {
  65. struct rtl_priv *rtlpriv = rtl_priv(hw);
  66. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  67. u32 original_value, bitshift;
  68. RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
  69. "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
  70. regaddr, bitmask, data, rfpath);
  71. if (rtlphy->rf_mode != RF_OP_BY_FW) {
  72. if (bitmask != RFREG_OFFSET_MASK) {
  73. original_value = _rtl92c_phy_rf_serial_read(hw,
  74. rfpath,
  75. regaddr);
  76. bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
  77. data =
  78. ((original_value & (~bitmask)) |
  79. (data << bitshift));
  80. }
  81. _rtl92c_phy_rf_serial_write(hw, rfpath, regaddr, data);
  82. } else {
  83. if (bitmask != RFREG_OFFSET_MASK) {
  84. original_value = _rtl92c_phy_fw_rf_serial_read(hw,
  85. rfpath,
  86. regaddr);
  87. bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
  88. data =
  89. ((original_value & (~bitmask)) |
  90. (data << bitshift));
  91. }
  92. _rtl92c_phy_fw_rf_serial_write(hw, rfpath, regaddr, data);
  93. }
  94. RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
  95. "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
  96. regaddr, bitmask, data, rfpath);
  97. }
  98. bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw)
  99. {
  100. bool rtstatus;
  101. struct rtl_priv *rtlpriv = rtl_priv(hw);
  102. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  103. bool is92c = IS_92C_SERIAL(rtlhal->version);
  104. rtstatus = _rtl92cu_phy_config_mac_with_headerfile(hw);
  105. if (is92c && IS_HARDWARE_TYPE_8192CE(rtlhal))
  106. rtl_write_byte(rtlpriv, 0x14, 0x71);
  107. return rtstatus;
  108. }
  109. bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw)
  110. {
  111. bool rtstatus = true;
  112. struct rtl_priv *rtlpriv = rtl_priv(hw);
  113. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  114. u16 regval;
  115. u8 b_reg_hwparafile = 1;
  116. _rtl92c_phy_init_bb_rf_register_definition(hw);
  117. regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
  118. rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, regval | BIT(13) |
  119. BIT(0) | BIT(1));
  120. rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83);
  121. rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb);
  122. rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB);
  123. if (IS_HARDWARE_TYPE_8192CE(rtlhal)) {
  124. rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_PPLL | FEN_PCIEA |
  125. FEN_DIO_PCIE | FEN_BB_GLB_RSTn | FEN_BBRSTB);
  126. } else if (IS_HARDWARE_TYPE_8192CU(rtlhal)) {
  127. rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD |
  128. FEN_BB_GLB_RSTn | FEN_BBRSTB);
  129. rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f);
  130. }
  131. rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80);
  132. if (b_reg_hwparafile == 1)
  133. rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw);
  134. return rtstatus;
  135. }
  136. bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw)
  137. {
  138. struct rtl_priv *rtlpriv = rtl_priv(hw);
  139. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  140. u32 i;
  141. u32 arraylength;
  142. u32 *ptrarray;
  143. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_Array\n");
  144. arraylength = rtlphy->hwparam_tables[MAC_REG].length ;
  145. ptrarray = rtlphy->hwparam_tables[MAC_REG].pdata;
  146. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:RTL8192CEMAC_2T_ARRAY\n");
  147. for (i = 0; i < arraylength; i = i + 2)
  148. rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]);
  149. return true;
  150. }
  151. bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
  152. u8 configtype)
  153. {
  154. int i;
  155. u32 *phy_regarray_table;
  156. u32 *agctab_array_table;
  157. u16 phy_reg_arraylen, agctab_arraylen;
  158. struct rtl_priv *rtlpriv = rtl_priv(hw);
  159. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  160. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  161. if (IS_92C_SERIAL(rtlhal->version)) {
  162. agctab_arraylen = rtlphy->hwparam_tables[AGCTAB_2T].length;
  163. agctab_array_table = rtlphy->hwparam_tables[AGCTAB_2T].pdata;
  164. phy_reg_arraylen = rtlphy->hwparam_tables[PHY_REG_2T].length;
  165. phy_regarray_table = rtlphy->hwparam_tables[PHY_REG_2T].pdata;
  166. } else {
  167. agctab_arraylen = rtlphy->hwparam_tables[AGCTAB_1T].length;
  168. agctab_array_table = rtlphy->hwparam_tables[AGCTAB_1T].pdata;
  169. phy_reg_arraylen = rtlphy->hwparam_tables[PHY_REG_1T].length;
  170. phy_regarray_table = rtlphy->hwparam_tables[PHY_REG_1T].pdata;
  171. }
  172. if (configtype == BASEBAND_CONFIG_PHY_REG) {
  173. for (i = 0; i < phy_reg_arraylen; i = i + 2) {
  174. if (phy_regarray_table[i] == 0xfe)
  175. mdelay(50);
  176. else if (phy_regarray_table[i] == 0xfd)
  177. mdelay(5);
  178. else if (phy_regarray_table[i] == 0xfc)
  179. mdelay(1);
  180. else if (phy_regarray_table[i] == 0xfb)
  181. udelay(50);
  182. else if (phy_regarray_table[i] == 0xfa)
  183. udelay(5);
  184. else if (phy_regarray_table[i] == 0xf9)
  185. udelay(1);
  186. rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD,
  187. phy_regarray_table[i + 1]);
  188. udelay(1);
  189. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  190. "The phy_regarray_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n",
  191. phy_regarray_table[i],
  192. phy_regarray_table[i + 1]);
  193. }
  194. } else if (configtype == BASEBAND_CONFIG_AGC_TAB) {
  195. for (i = 0; i < agctab_arraylen; i = i + 2) {
  196. rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD,
  197. agctab_array_table[i + 1]);
  198. udelay(1);
  199. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  200. "The agctab_array_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n",
  201. agctab_array_table[i],
  202. agctab_array_table[i + 1]);
  203. }
  204. }
  205. return true;
  206. }
  207. bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
  208. u8 configtype)
  209. {
  210. struct rtl_priv *rtlpriv = rtl_priv(hw);
  211. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  212. int i;
  213. u32 *phy_regarray_table_pg;
  214. u16 phy_regarray_pg_len;
  215. rtlphy->pwrgroup_cnt = 0;
  216. phy_regarray_pg_len = rtlphy->hwparam_tables[PHY_REG_PG].length;
  217. phy_regarray_table_pg = rtlphy->hwparam_tables[PHY_REG_PG].pdata;
  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 rtl92cu_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. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  253. if (IS_92C_SERIAL(rtlhal->version)) {
  254. radioa_arraylen = rtlphy->hwparam_tables[RADIOA_2T].length;
  255. radioa_array_table = rtlphy->hwparam_tables[RADIOA_2T].pdata;
  256. radiob_arraylen = rtlphy->hwparam_tables[RADIOB_2T].length;
  257. radiob_array_table = rtlphy->hwparam_tables[RADIOB_2T].pdata;
  258. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  259. "Radio_A:RTL8192CERADIOA_2TARRAY\n");
  260. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  261. "Radio_B:RTL8192CE_RADIOB_2TARRAY\n");
  262. } else {
  263. radioa_arraylen = rtlphy->hwparam_tables[RADIOA_1T].length;
  264. radioa_array_table = rtlphy->hwparam_tables[RADIOA_1T].pdata;
  265. radiob_arraylen = rtlphy->hwparam_tables[RADIOB_1T].length;
  266. radiob_array_table = rtlphy->hwparam_tables[RADIOB_1T].pdata;
  267. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  268. "Radio_A:RTL8192CE_RADIOA_1TARRAY\n");
  269. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
  270. "Radio_B:RTL8192CE_RADIOB_1TARRAY\n");
  271. }
  272. RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Radio No %x\n", rfpath);
  273. switch (rfpath) {
  274. case RF90_PATH_A:
  275. for (i = 0; i < radioa_arraylen; i = i + 2) {
  276. if (radioa_array_table[i] == 0xfe)
  277. mdelay(50);
  278. else if (radioa_array_table[i] == 0xfd)
  279. mdelay(5);
  280. else if (radioa_array_table[i] == 0xfc)
  281. mdelay(1);
  282. else if (radioa_array_table[i] == 0xfb)
  283. udelay(50);
  284. else if (radioa_array_table[i] == 0xfa)
  285. udelay(5);
  286. else if (radioa_array_table[i] == 0xf9)
  287. udelay(1);
  288. else {
  289. rtl_set_rfreg(hw, rfpath, radioa_array_table[i],
  290. RFREG_OFFSET_MASK,
  291. radioa_array_table[i + 1]);
  292. udelay(1);
  293. }
  294. }
  295. break;
  296. case RF90_PATH_B:
  297. for (i = 0; i < radiob_arraylen; i = i + 2) {
  298. if (radiob_array_table[i] == 0xfe) {
  299. mdelay(50);
  300. } else if (radiob_array_table[i] == 0xfd)
  301. mdelay(5);
  302. else if (radiob_array_table[i] == 0xfc)
  303. mdelay(1);
  304. else if (radiob_array_table[i] == 0xfb)
  305. udelay(50);
  306. else if (radiob_array_table[i] == 0xfa)
  307. udelay(5);
  308. else if (radiob_array_table[i] == 0xf9)
  309. udelay(1);
  310. else {
  311. rtl_set_rfreg(hw, rfpath, radiob_array_table[i],
  312. RFREG_OFFSET_MASK,
  313. radiob_array_table[i + 1]);
  314. udelay(1);
  315. }
  316. }
  317. break;
  318. case RF90_PATH_C:
  319. RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
  320. "switch case not processed\n");
  321. break;
  322. case RF90_PATH_D:
  323. RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
  324. "switch case not processed\n");
  325. break;
  326. }
  327. return true;
  328. }
  329. void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw)
  330. {
  331. struct rtl_priv *rtlpriv = rtl_priv(hw);
  332. struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
  333. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  334. struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
  335. u8 reg_bw_opmode;
  336. u8 reg_prsr_rsc;
  337. RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "Switch to %s bandwidth\n",
  338. rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
  339. "20MHz" : "40MHz");
  340. if (is_hal_stop(rtlhal)) {
  341. rtlphy->set_bwmode_inprogress = false;
  342. return;
  343. }
  344. reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE);
  345. reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2);
  346. switch (rtlphy->current_chan_bw) {
  347. case HT_CHANNEL_WIDTH_20:
  348. reg_bw_opmode |= BW_OPMODE_20MHZ;
  349. rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
  350. break;
  351. case HT_CHANNEL_WIDTH_20_40:
  352. reg_bw_opmode &= ~BW_OPMODE_20MHZ;
  353. rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
  354. reg_prsr_rsc =
  355. (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5);
  356. rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc);
  357. break;
  358. default:
  359. RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
  360. "unknown bandwidth: %#X\n", rtlphy->current_chan_bw);
  361. break;
  362. }
  363. switch (rtlphy->current_chan_bw) {
  364. case HT_CHANNEL_WIDTH_20:
  365. rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0);
  366. rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0);
  367. rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);
  368. break;
  369. case HT_CHANNEL_WIDTH_20_40:
  370. rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1);
  371. rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1);
  372. rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND,
  373. (mac->cur_40_prime_sc >> 1));
  374. rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc);
  375. rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0);
  376. rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)),
  377. (mac->cur_40_prime_sc ==
  378. HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
  379. break;
  380. default:
  381. RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
  382. "unknown bandwidth: %#X\n", rtlphy->current_chan_bw);
  383. break;
  384. }
  385. rtl92cu_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw);
  386. rtlphy->set_bwmode_inprogress = false;
  387. RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n");
  388. }
  389. void rtl92cu_bb_block_on(struct ieee80211_hw *hw)
  390. {
  391. struct rtl_priv *rtlpriv = rtl_priv(hw);
  392. mutex_lock(&rtlpriv->io.bb_mutex);
  393. rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1);
  394. rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1);
  395. mutex_unlock(&rtlpriv->io.bb_mutex);
  396. }
  397. void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
  398. {
  399. u8 tmpreg;
  400. u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
  401. struct rtl_priv *rtlpriv = rtl_priv(hw);
  402. tmpreg = rtl_read_byte(rtlpriv, 0xd03);
  403. if ((tmpreg & 0x70) != 0)
  404. rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F);
  405. else
  406. rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
  407. if ((tmpreg & 0x70) != 0) {
  408. rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS);
  409. if (is2t)
  410. rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00,
  411. MASK12BITS);
  412. rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS,
  413. (rf_a_mode & 0x8FFFF) | 0x10000);
  414. if (is2t)
  415. rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
  416. (rf_b_mode & 0x8FFFF) | 0x10000);
  417. }
  418. lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS);
  419. rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000);
  420. mdelay(100);
  421. if ((tmpreg & 0x70) != 0) {
  422. rtl_write_byte(rtlpriv, 0xd03, tmpreg);
  423. rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode);
  424. if (is2t)
  425. rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
  426. rf_b_mode);
  427. } else {
  428. rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
  429. }
  430. }
  431. static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
  432. enum rf_pwrstate rfpwr_state)
  433. {
  434. struct rtl_priv *rtlpriv = rtl_priv(hw);
  435. struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
  436. struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
  437. struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
  438. bool bresult = true;
  439. u8 i, queue_id;
  440. struct rtl8192_tx_ring *ring = NULL;
  441. switch (rfpwr_state) {
  442. case ERFON:
  443. if ((ppsc->rfpwr_state == ERFOFF) &&
  444. RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
  445. bool rtstatus;
  446. u32 InitializeCount = 0;
  447. do {
  448. InitializeCount++;
  449. RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
  450. "IPS Set eRf nic enable\n");
  451. rtstatus = rtl_ps_enable_nic(hw);
  452. } while (!rtstatus && (InitializeCount < 10));
  453. RT_CLEAR_PS_LEVEL(ppsc,
  454. RT_RF_OFF_LEVL_HALT_NIC);
  455. } else {
  456. RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
  457. "Set ERFON sleeped:%d ms\n",
  458. jiffies_to_msecs(jiffies -
  459. ppsc->last_sleep_jiffies));
  460. ppsc->last_awake_jiffies = jiffies;
  461. rtl92ce_phy_set_rf_on(hw);
  462. }
  463. if (mac->link_state == MAC80211_LINKED) {
  464. rtlpriv->cfg->ops->led_control(hw,
  465. LED_CTL_LINK);
  466. } else {
  467. rtlpriv->cfg->ops->led_control(hw,
  468. LED_CTL_NO_LINK);
  469. }
  470. break;
  471. case ERFOFF:
  472. for (queue_id = 0, i = 0;
  473. queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
  474. ring = &pcipriv->dev.tx_ring[queue_id];
  475. if (skb_queue_len(&ring->queue) == 0 ||
  476. queue_id == BEACON_QUEUE) {
  477. queue_id++;
  478. continue;
  479. } else {
  480. RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
  481. "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n",
  482. i + 1,
  483. queue_id,
  484. skb_queue_len(&ring->queue));
  485. udelay(10);
  486. i++;
  487. }
  488. if (i >= MAX_DOZE_WAITING_TIMES_9x) {
  489. RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
  490. "ERFOFF: %d times TcbBusyQueue[%d] = %d !\n",
  491. MAX_DOZE_WAITING_TIMES_9x,
  492. queue_id,
  493. skb_queue_len(&ring->queue));
  494. break;
  495. }
  496. }
  497. if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) {
  498. RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
  499. "IPS Set eRf nic disable\n");
  500. rtl_ps_disable_nic(hw);
  501. RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
  502. } else {
  503. if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) {
  504. rtlpriv->cfg->ops->led_control(hw,
  505. LED_CTL_NO_LINK);
  506. } else {
  507. rtlpriv->cfg->ops->led_control(hw,
  508. LED_CTL_POWER_OFF);
  509. }
  510. }
  511. break;
  512. case ERFSLEEP:
  513. if (ppsc->rfpwr_state == ERFOFF)
  514. return false;
  515. for (queue_id = 0, i = 0;
  516. queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
  517. ring = &pcipriv->dev.tx_ring[queue_id];
  518. if (skb_queue_len(&ring->queue) == 0) {
  519. queue_id++;
  520. continue;
  521. } else {
  522. RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
  523. "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n",
  524. i + 1, queue_id,
  525. skb_queue_len(&ring->queue));
  526. udelay(10);
  527. i++;
  528. }
  529. if (i >= MAX_DOZE_WAITING_TIMES_9x) {
  530. RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
  531. "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n",
  532. MAX_DOZE_WAITING_TIMES_9x,
  533. queue_id,
  534. skb_queue_len(&ring->queue));
  535. break;
  536. }
  537. }
  538. RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
  539. "Set ERFSLEEP awaked:%d ms\n",
  540. jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies));
  541. ppsc->last_sleep_jiffies = jiffies;
  542. _rtl92c_phy_set_rf_sleep(hw);
  543. break;
  544. default:
  545. RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
  546. "switch case not processed\n");
  547. bresult = false;
  548. break;
  549. }
  550. if (bresult)
  551. ppsc->rfpwr_state = rfpwr_state;
  552. return bresult;
  553. }
  554. bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
  555. enum rf_pwrstate rfpwr_state)
  556. {
  557. struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
  558. bool bresult = false;
  559. if (rfpwr_state == ppsc->rfpwr_state)
  560. return bresult;
  561. bresult = _rtl92cu_phy_set_rf_power_state(hw, rfpwr_state);
  562. return bresult;
  563. }