halmac_mimo_88xx.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2016 - 2018 Realtek Corporation. All rights reserved.
  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. ******************************************************************************/
  15. #include "halmac_mimo_88xx.h"
  16. #include "halmac_88xx_cfg.h"
  17. #include "halmac_common_88xx.h"
  18. #include "halmac_init_88xx.h"
  19. #if HALMAC_88XX_SUPPORT
  20. #define TXBF_CTRL_CFG (BIT_R_ENABLE_NDPA | BIT_USE_NDPA_PARAMETER | \
  21. BIT_R_EN_NDPA_INT | BIT_DIS_NDP_BFEN)
  22. static void
  23. cfg_mu_bfee_88xx(struct halmac_adapter *adapter,
  24. struct halmac_cfg_mumimo_para *param);
  25. static void
  26. cfg_mu_bfer_88xx(struct halmac_adapter *adapter,
  27. struct halmac_cfg_mumimo_para *param);
  28. static enum halmac_cmd_construct_state
  29. fw_snding_cmd_cnstr_state_88xx(struct halmac_adapter *adapter);
  30. static enum halmac_ret_status
  31. cnv_fw_snding_state_88xx(struct halmac_adapter *adapter,
  32. enum halmac_cmd_construct_state dest_state);
  33. static u8
  34. snding_pkt_chk_88xx(struct halmac_adapter *adapter, u8 *pkt);
  35. /**
  36. * cfg_txbf_88xx() - enable/disable specific user's txbf
  37. * @adapter : the adapter of halmac
  38. * @userid : su bfee userid = 0 or 1 to apply TXBF
  39. * @bw : the sounding bandwidth
  40. * @txbf_en : 0: disable TXBF, 1: enable TXBF
  41. * Author : chunchu
  42. * Return : enum halmac_ret_status
  43. * More details of status code can be found in prototype document
  44. */
  45. enum halmac_ret_status
  46. cfg_txbf_88xx(struct halmac_adapter *adapter, u8 userid, enum halmac_bw bw,
  47. u8 txbf_en)
  48. {
  49. u16 tmp42c = 0;
  50. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  51. if (txbf_en) {
  52. switch (bw) {
  53. case HALMAC_BW_80:
  54. tmp42c |= BIT_R_TXBF0_80M;
  55. __attribute__((__fallthrough__));
  56. case HALMAC_BW_40:
  57. tmp42c |= BIT_R_TXBF0_40M;
  58. __attribute__((__fallthrough__));
  59. case HALMAC_BW_20:
  60. tmp42c |= BIT_R_TXBF0_20M;
  61. break;
  62. default:
  63. return HALMAC_RET_INVALID_SOUNDING_SETTING;
  64. }
  65. }
  66. switch (userid) {
  67. case 0:
  68. tmp42c |= HALMAC_REG_R16(REG_TXBF_CTRL) &
  69. ~(BIT_R_TXBF0_20M | BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
  70. HALMAC_REG_W16(REG_TXBF_CTRL, tmp42c);
  71. break;
  72. case 1:
  73. tmp42c |= HALMAC_REG_R16(REG_TXBF_CTRL + 2) &
  74. ~(BIT_R_TXBF0_20M | BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
  75. HALMAC_REG_W16(REG_TXBF_CTRL + 2, tmp42c);
  76. break;
  77. default:
  78. return HALMAC_RET_INVALID_SOUNDING_SETTING;
  79. }
  80. PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
  81. return HALMAC_RET_SUCCESS;
  82. }
  83. /**
  84. * cfg_mumimo_88xx() -config mumimo
  85. * @adapter : the adapter of halmac
  86. * @param : parameters to configure MU PPDU Tx/Rx
  87. * Author : chunchu
  88. * Return : enum halmac_ret_status
  89. * More details of status code can be found in prototype document
  90. */
  91. enum halmac_ret_status
  92. cfg_mumimo_88xx(struct halmac_adapter *adapter,
  93. struct halmac_cfg_mumimo_para *param)
  94. {
  95. if (param->role == HAL_BFEE)
  96. cfg_mu_bfee_88xx(adapter, param);
  97. else
  98. cfg_mu_bfer_88xx(adapter, param);
  99. PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
  100. return HALMAC_RET_SUCCESS;
  101. }
  102. static void
  103. cfg_mu_bfee_88xx(struct halmac_adapter *adapter,
  104. struct halmac_cfg_mumimo_para *param)
  105. {
  106. u8 mu_tbl_sel;
  107. u8 tmp14c0;
  108. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  109. tmp14c0 = HALMAC_REG_R8(REG_MU_TX_CTL) & ~BIT_MASK_R_MU_TABLE_VALID;
  110. HALMAC_REG_W8(REG_MU_TX_CTL, (tmp14c0 | BIT(0) | BIT(1)) & ~(BIT(7)));
  111. /*config GID valid table and user position table*/
  112. mu_tbl_sel = HALMAC_REG_R8(REG_MU_TX_CTL + 1) & 0xF8;
  113. HALMAC_REG_W8(REG_MU_TX_CTL + 1, mu_tbl_sel);
  114. HALMAC_REG_W32(REG_MU_STA_GID_VLD, param->given_gid_tab[0]);
  115. HALMAC_REG_W32(REG_MU_STA_USER_POS_INFO, param->given_user_pos[0]);
  116. HALMAC_REG_W32(REG_MU_STA_USER_POS_INFO + 4, param->given_user_pos[1]);
  117. HALMAC_REG_W8(REG_MU_TX_CTL + 1, mu_tbl_sel | 1);
  118. HALMAC_REG_W32(REG_MU_STA_GID_VLD, param->given_gid_tab[1]);
  119. HALMAC_REG_W32(REG_MU_STA_USER_POS_INFO, param->given_user_pos[2]);
  120. HALMAC_REG_W32(REG_MU_STA_USER_POS_INFO + 4, param->given_user_pos[3]);
  121. }
  122. static void
  123. cfg_mu_bfer_88xx(struct halmac_adapter *adapter,
  124. struct halmac_cfg_mumimo_para *param)
  125. {
  126. u8 i;
  127. u8 idx;
  128. u8 id0;
  129. u8 id1;
  130. u8 gid;
  131. u8 mu_tbl_sel;
  132. u8 mu_tbl_valid = 0;
  133. u32 gid_valid[6] = {0};
  134. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  135. if (param->mu_tx_en == 0) {
  136. HALMAC_REG_W8(REG_MU_TX_CTL,
  137. HALMAC_REG_R8(REG_MU_TX_CTL) & ~(BIT(7)));
  138. return;
  139. }
  140. for (idx = 0; idx < 15; idx++) {
  141. if (idx < 5) {
  142. /*grouping_bitmap bit0~4, MU_STA0 with MUSTA1~5*/
  143. id0 = 0;
  144. id1 = (u8)(idx + 1);
  145. } else if (idx < 9) {
  146. /*grouping_bitmap bit5~8, MU_STA1 with MUSTA2~5*/
  147. id0 = 1;
  148. id1 = (u8)(idx - 3);
  149. } else if (idx < 12) {
  150. /*grouping_bitmap bit9~11, MU_STA2 with MUSTA3~5*/
  151. id0 = 2;
  152. id1 = (u8)(idx - 6);
  153. } else if (idx < 14) {
  154. /*grouping_bitmap bit12~13, MU_STA3 with MUSTA4~5*/
  155. id0 = 3;
  156. id1 = (u8)(idx - 8);
  157. } else {
  158. /*grouping_bitmap bit14, MU_STA4 with MUSTA5*/
  159. id0 = 4;
  160. id1 = (u8)(idx - 9);
  161. }
  162. if (param->grouping_bitmap & BIT(idx)) {
  163. /*Pair 1*/
  164. gid = (idx << 1) + 1;
  165. gid_valid[id0] |= (BIT(gid));
  166. gid_valid[id1] |= (BIT(gid));
  167. /*Pair 2*/
  168. gid += 1;
  169. gid_valid[id0] |= (BIT(gid));
  170. gid_valid[id1] |= (BIT(gid));
  171. } else {
  172. /*Pair 1*/
  173. gid = (idx << 1) + 1;
  174. gid_valid[id0] &= ~(BIT(gid));
  175. gid_valid[id1] &= ~(BIT(gid));
  176. /*Pair 2*/
  177. gid += 1;
  178. gid_valid[id0] &= ~(BIT(gid));
  179. gid_valid[id1] &= ~(BIT(gid));
  180. }
  181. }
  182. /*set MU STA GID valid TABLE*/
  183. mu_tbl_sel = HALMAC_REG_R8(REG_MU_TX_CTL + 1) & 0xF8;
  184. for (idx = 0; idx < 6; idx++) {
  185. HALMAC_REG_W8(REG_MU_TX_CTL + 1, idx | mu_tbl_sel);
  186. HALMAC_REG_W32(REG_MU_STA_GID_VLD, gid_valid[idx]);
  187. }
  188. /*To validate the sounding successful MU STA and enable MU TX*/
  189. for (i = 0; i < 6; i++) {
  190. if (param->sounding_sts[i] == 1)
  191. mu_tbl_valid |= BIT(i);
  192. }
  193. HALMAC_REG_W8(REG_MU_TX_CTL, mu_tbl_valid | BIT(7));
  194. }
  195. /**
  196. * cfg_sounding_88xx() - configure general sounding
  197. * @adapter : the adapter of halmac
  198. * @role : driver's role, BFer or BFee
  199. * @rate : set ndpa tx rate if driver is BFer,
  200. * or set csi response rate if driver is BFee
  201. * Author : chunchu
  202. * Return : enum halmac_ret_status
  203. * More details of status code can be found in prototype document
  204. */
  205. enum halmac_ret_status
  206. cfg_sounding_88xx(struct halmac_adapter *adapter, enum halmac_snd_role role,
  207. enum halmac_data_rate rate)
  208. {
  209. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  210. u32 tmp6dc = 0;
  211. u8 csi_rsc = 0x1;
  212. /*use ndpa rx rate to decide csi rate*/
  213. tmp6dc = HALMAC_REG_R32(REG_BBPSF_CTRL) | BIT_WMAC_USE_NDPARATE
  214. | (csi_rsc << 13);
  215. switch (role) {
  216. case HAL_BFER:
  217. HALMAC_REG_W32_SET(REG_TXBF_CTRL, TXBF_CTRL_CFG);
  218. HALMAC_REG_W8(REG_NDPA_RATE, rate);
  219. HALMAC_REG_W8_CLR(REG_NDPA_OPT_CTRL, BIT(0) | BIT(1));
  220. HALMAC_REG_W8(REG_SND_PTCL_CTRL + 1, 0x2 | BIT(7));
  221. HALMAC_REG_W8(REG_SND_PTCL_CTRL + 2, 0x2);
  222. break;
  223. case HAL_BFEE:
  224. HALMAC_REG_W8(REG_SND_PTCL_CTRL, 0xDB);
  225. HALMAC_REG_W8(REG_SND_PTCL_CTRL + 3, 0x26);
  226. HALMAC_REG_W8_CLR(REG_RXFLTMAP1, BIT(4));
  227. HALMAC_REG_W8_CLR(REG_RXFLTMAP4, BIT(4));
  228. break;
  229. default:
  230. return HALMAC_RET_INVALID_SOUNDING_SETTING;
  231. }
  232. /*AP mode set tx gid to 63*/
  233. /*STA mode set tx gid to 0*/
  234. if (BIT_GET_NETYPE0(HALMAC_REG_R32(REG_CR)) == 0x3)
  235. HALMAC_REG_W32(REG_BBPSF_CTRL, tmp6dc | BIT(12));
  236. else
  237. HALMAC_REG_W32(REG_BBPSF_CTRL, tmp6dc & ~(BIT(12)));
  238. PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
  239. return HALMAC_RET_SUCCESS;
  240. }
  241. /**
  242. * del_sounding_88xx() - reset general sounding
  243. * @adapter : the adapter of halmac
  244. * @role : driver's role, BFer or BFee
  245. * Author : chunchu
  246. * Return : enum halmac_ret_status
  247. * More details of status code can be found in prototype document
  248. */
  249. enum halmac_ret_status
  250. del_sounding_88xx(struct halmac_adapter *adapter, enum halmac_snd_role role)
  251. {
  252. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  253. switch (role) {
  254. case HAL_BFER:
  255. HALMAC_REG_W8(REG_TXBF_CTRL + 3, 0);
  256. break;
  257. case HAL_BFEE:
  258. HALMAC_REG_W8(REG_SND_PTCL_CTRL, 0);
  259. break;
  260. default:
  261. return HALMAC_RET_INVALID_SOUNDING_SETTING;
  262. }
  263. PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
  264. return HALMAC_RET_SUCCESS;
  265. }
  266. /**
  267. * su_bfee_entry_init_88xx() - config SU beamformee's registers
  268. * @adapter : the adapter of halmac
  269. * @userid : SU bfee userid = 0 or 1 to be added
  270. * @paid : partial AID of this bfee
  271. * Author : chunchu
  272. * Return : enum halmac_ret_status
  273. * More details of status code can be found in prototype document
  274. */
  275. enum halmac_ret_status
  276. su_bfee_entry_init_88xx(struct halmac_adapter *adapter, u8 userid, u16 paid)
  277. {
  278. u16 tmp42c = 0;
  279. u16 tmp168x = 0;
  280. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  281. switch (userid) {
  282. case 0:
  283. tmp42c = HALMAC_REG_R16(REG_TXBF_CTRL) &
  284. ~(BIT_MASK_R_TXBF0_AID | BIT_R_TXBF0_20M |
  285. BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
  286. HALMAC_REG_W16(REG_TXBF_CTRL, tmp42c | paid);
  287. HALMAC_REG_W16(REG_ASSOCIATED_BFMEE_SEL, paid);
  288. #if HALMAC_8822C_SUPPORT
  289. if (adapter->chip_id == HALMAC_CHIP_ID_8822C)
  290. HALMAC_REG_W16(REG_ASSOCIATED_BFMEE_SEL, paid | BIT(9));
  291. #endif
  292. break;
  293. case 1:
  294. tmp42c = HALMAC_REG_R16(REG_TXBF_CTRL + 2) &
  295. ~(BIT_MASK_R_TXBF1_AID | BIT_R_TXBF0_20M |
  296. BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
  297. HALMAC_REG_W16(REG_TXBF_CTRL + 2, tmp42c | paid);
  298. HALMAC_REG_W16(REG_ASSOCIATED_BFMEE_SEL + 2, paid | BIT(9));
  299. break;
  300. case 2:
  301. tmp168x = HALMAC_REG_R16(REG_WMAC_ASSOCIATED_MU_BFMEE2);
  302. tmp168x = BIT_CLEAR_WMAC_MU_BFEE2_AID(tmp168x);
  303. tmp168x |= (paid | BIT(9));
  304. HALMAC_REG_W16(REG_WMAC_ASSOCIATED_MU_BFMEE2, tmp168x);
  305. break;
  306. case 3:
  307. tmp168x = HALMAC_REG_R16(REG_WMAC_ASSOCIATED_MU_BFMEE3);
  308. tmp168x = BIT_CLEAR_WMAC_MU_BFEE3_AID(tmp168x);
  309. tmp168x |= (paid | BIT(9));
  310. HALMAC_REG_W16(REG_WMAC_ASSOCIATED_MU_BFMEE3, tmp168x);
  311. break;
  312. case 4:
  313. tmp168x = HALMAC_REG_R16(REG_WMAC_ASSOCIATED_MU_BFMEE4);
  314. tmp168x = BIT_CLEAR_WMAC_MU_BFEE4_AID(tmp168x);
  315. tmp168x |= (paid | BIT(9));
  316. HALMAC_REG_W16(REG_WMAC_ASSOCIATED_MU_BFMEE4, tmp168x);
  317. break;
  318. case 5:
  319. tmp168x = HALMAC_REG_R16(REG_WMAC_ASSOCIATED_MU_BFMEE5);
  320. tmp168x = BIT_CLEAR_WMAC_MU_BFEE5_AID(tmp168x);
  321. tmp168x |= (paid | BIT(9));
  322. HALMAC_REG_W16(REG_WMAC_ASSOCIATED_MU_BFMEE5, tmp168x);
  323. break;
  324. default:
  325. return HALMAC_RET_INVALID_SOUNDING_SETTING;
  326. }
  327. PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
  328. return HALMAC_RET_SUCCESS;
  329. }
  330. /**
  331. * su_bfee_entry_init_88xx() - config SU beamformer's registers
  332. * @adapter : the adapter of halmac
  333. * @param : parameters to configure SU BFER entry
  334. * Author : chunchu
  335. * Return : enum halmac_ret_status
  336. * More details of status code can be found in prototype document
  337. */
  338. enum halmac_ret_status
  339. su_bfer_entry_init_88xx(struct halmac_adapter *adapter,
  340. struct halmac_su_bfer_init_para *param)
  341. {
  342. u16 mac_addr_h;
  343. u32 mac_addr_l;
  344. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  345. mac_addr_l = rtk_le32_to_cpu(param->bfer_address.addr_l_h.low);
  346. mac_addr_h = rtk_le16_to_cpu(param->bfer_address.addr_l_h.high);
  347. switch (param->userid) {
  348. case 0:
  349. HALMAC_REG_W32(REG_ASSOCIATED_BFMER0_INFO, mac_addr_l);
  350. HALMAC_REG_W16(REG_ASSOCIATED_BFMER0_INFO + 4, mac_addr_h);
  351. HALMAC_REG_W16(REG_ASSOCIATED_BFMER0_INFO + 6, param->paid);
  352. HALMAC_REG_W16(REG_TX_CSI_RPT_PARAM_BW20, param->csi_para);
  353. break;
  354. case 1:
  355. HALMAC_REG_W32(REG_ASSOCIATED_BFMER1_INFO, mac_addr_l);
  356. HALMAC_REG_W16(REG_ASSOCIATED_BFMER1_INFO + 4, mac_addr_h);
  357. HALMAC_REG_W16(REG_ASSOCIATED_BFMER1_INFO + 6, param->paid);
  358. HALMAC_REG_W16(REG_TX_CSI_RPT_PARAM_BW20 + 2, param->csi_para);
  359. break;
  360. default:
  361. return HALMAC_RET_INVALID_SOUNDING_SETTING;
  362. }
  363. PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
  364. return HALMAC_RET_SUCCESS;
  365. }
  366. /**
  367. * mu_bfee_entry_init_88xx() - config MU beamformee's registers
  368. * @adapter : the adapter of halmac
  369. * @param : parameters to configure MU BFEE entry
  370. * Author : chunchu
  371. * Return : enum halmac_ret_status
  372. * More details of status code can be found in prototype document
  373. */
  374. enum halmac_ret_status
  375. mu_bfee_entry_init_88xx(struct halmac_adapter *adapter,
  376. struct halmac_mu_bfee_init_para *param)
  377. {
  378. u16 tmp168x = 0;
  379. u16 tmp14c0;
  380. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  381. tmp168x |= param->paid | BIT(9);
  382. HALMAC_REG_W16((0x1680 + param->userid * 2), tmp168x);
  383. tmp14c0 = HALMAC_REG_R16(REG_MU_TX_CTL) & ~(BIT(8) | BIT(9) | BIT(10));
  384. HALMAC_REG_W16(REG_MU_TX_CTL, tmp14c0 | ((param->userid - 2) << 8));
  385. HALMAC_REG_W32(REG_MU_STA_GID_VLD, 0);
  386. HALMAC_REG_W32(REG_MU_STA_USER_POS_INFO, param->user_position_l);
  387. HALMAC_REG_W32(REG_MU_STA_USER_POS_INFO + 4, param->user_position_h);
  388. PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
  389. return HALMAC_RET_SUCCESS;
  390. }
  391. /**
  392. * mu_bfer_entry_init_88xx() - config MU beamformer's registers
  393. * @adapter : the adapter of halmac
  394. * @param : parameters to configure MU BFER entry
  395. * Author : chunchu
  396. * Return : enum halmac_ret_status
  397. * More details of status code can be found in prototype document
  398. */
  399. enum halmac_ret_status
  400. mu_bfer_entry_init_88xx(struct halmac_adapter *adapter,
  401. struct halmac_mu_bfer_init_para *param)
  402. {
  403. u16 tmp1680 = 0;
  404. u16 mac_addr_h;
  405. u32 mac_addr_l;
  406. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  407. mac_addr_l = rtk_le32_to_cpu(param->bfer_address.addr_l_h.low);
  408. mac_addr_h = rtk_le16_to_cpu(param->bfer_address.addr_l_h.high);
  409. HALMAC_REG_W32(REG_ASSOCIATED_BFMER0_INFO, mac_addr_l);
  410. HALMAC_REG_W16(REG_ASSOCIATED_BFMER0_INFO + 4, mac_addr_h);
  411. HALMAC_REG_W16(REG_ASSOCIATED_BFMER0_INFO + 6, param->paid);
  412. HALMAC_REG_W16(REG_TX_CSI_RPT_PARAM_BW20, param->csi_para);
  413. tmp1680 = HALMAC_REG_R16(0x1680) & 0xC000;
  414. tmp1680 |= param->my_aid | (param->csi_length_sel << 12);
  415. HALMAC_REG_W16(0x1680, tmp1680);
  416. PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
  417. return HALMAC_RET_SUCCESS;
  418. }
  419. /**
  420. * su_bfee_entry_del_88xx() - reset SU beamformee's registers
  421. * @adapter : the adapter of halmac
  422. * @userid : the SU BFee userid to be deleted
  423. * Author : chunchu
  424. * Return : enum halmac_ret_status
  425. * More details of status code can be found in prototype document
  426. */
  427. enum halmac_ret_status
  428. su_bfee_entry_del_88xx(struct halmac_adapter *adapter, u8 userid)
  429. {
  430. u16 value16;
  431. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  432. switch (userid) {
  433. case 0:
  434. value16 = HALMAC_REG_R16(REG_TXBF_CTRL);
  435. value16 &= ~(BIT_MASK_R_TXBF0_AID | BIT_R_TXBF0_20M |
  436. BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
  437. HALMAC_REG_W16(REG_TXBF_CTRL, value16);
  438. HALMAC_REG_W16(REG_ASSOCIATED_BFMEE_SEL, 0);
  439. break;
  440. case 1:
  441. value16 = HALMAC_REG_R16(REG_TXBF_CTRL + 2);
  442. value16 &= ~(BIT_MASK_R_TXBF1_AID | BIT_R_TXBF0_20M |
  443. BIT_R_TXBF0_40M | BIT_R_TXBF0_80M);
  444. HALMAC_REG_W16(REG_TXBF_CTRL + 2, value16);
  445. HALMAC_REG_W16(REG_ASSOCIATED_BFMEE_SEL + 2, 0);
  446. break;
  447. case 2:
  448. HALMAC_REG_W16(REG_WMAC_ASSOCIATED_MU_BFMEE2, 0);
  449. break;
  450. case 3:
  451. HALMAC_REG_W16(REG_WMAC_ASSOCIATED_MU_BFMEE3, 0);
  452. break;
  453. case 4:
  454. HALMAC_REG_W16(REG_WMAC_ASSOCIATED_MU_BFMEE4, 0);
  455. break;
  456. case 5:
  457. HALMAC_REG_W16(REG_WMAC_ASSOCIATED_MU_BFMEE5, 0);
  458. break;
  459. default:
  460. return HALMAC_RET_INVALID_SOUNDING_SETTING;
  461. }
  462. PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
  463. return HALMAC_RET_SUCCESS;
  464. }
  465. /**
  466. * su_bfee_entry_del_88xx() - reset SU beamformer's registers
  467. * @adapter : the adapter of halmac
  468. * @userid : the SU BFer userid to be deleted
  469. * Author : chunchu
  470. * Return : enum halmac_ret_status
  471. * More details of status code can be found in prototype document
  472. */
  473. enum halmac_ret_status
  474. su_bfer_entry_del_88xx(struct halmac_adapter *adapter, u8 userid)
  475. {
  476. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  477. switch (userid) {
  478. case 0:
  479. HALMAC_REG_W32(REG_ASSOCIATED_BFMER0_INFO, 0);
  480. HALMAC_REG_W32(REG_ASSOCIATED_BFMER0_INFO + 4, 0);
  481. break;
  482. case 1:
  483. HALMAC_REG_W32(REG_ASSOCIATED_BFMER1_INFO, 0);
  484. HALMAC_REG_W32(REG_ASSOCIATED_BFMER1_INFO + 4, 0);
  485. break;
  486. default:
  487. return HALMAC_RET_INVALID_SOUNDING_SETTING;
  488. }
  489. PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
  490. return HALMAC_RET_SUCCESS;
  491. }
  492. /**
  493. * mu_bfee_entry_del_88xx() - reset MU beamformee's registers
  494. * @adapter : the adapter of halmac
  495. * @userid : the MU STA userid to be deleted
  496. * Author : chunchu
  497. * Return : enum halmac_ret_status
  498. * More details of status code can be found in prototype document
  499. */
  500. enum halmac_ret_status
  501. mu_bfee_entry_del_88xx(struct halmac_adapter *adapter, u8 userid)
  502. {
  503. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  504. HALMAC_REG_W16(0x1680 + userid * 2, 0);
  505. HALMAC_REG_W8_CLR(REG_MU_TX_CTL, BIT(userid - 2));
  506. PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
  507. return HALMAC_RET_SUCCESS;
  508. }
  509. /**
  510. * mu_bfer_entry_del_88xx() -reset MU beamformer's registers
  511. * @adapter : the adapter of halmac
  512. * Author : chunchu
  513. * Return : enum halmac_ret_status
  514. * More details of status code can be found in prototype document
  515. */
  516. enum halmac_ret_status
  517. mu_bfer_entry_del_88xx(struct halmac_adapter *adapter)
  518. {
  519. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  520. HALMAC_REG_W32(REG_ASSOCIATED_BFMER0_INFO, 0);
  521. HALMAC_REG_W32(REG_ASSOCIATED_BFMER0_INFO + 4, 0);
  522. HALMAC_REG_W16(0x1680, 0);
  523. HALMAC_REG_W8(REG_MU_TX_CTL, 0);
  524. PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
  525. return HALMAC_RET_SUCCESS;
  526. }
  527. /**
  528. * cfg_csi_rate_88xx() - config CSI frame Tx rate
  529. * @adapter : the adapter of halmac
  530. * @rssi : rssi in decimal value
  531. * @cur_rate : current CSI frame rate
  532. * @fixrate_en : enable to fix CSI frame in VHT rate, otherwise legacy OFDM rate
  533. * @new_rate : API returns the final CSI frame rate
  534. * Author : chunchu
  535. * Return : enum halmac_ret_status
  536. * More details of status code can be found in prototype document
  537. */
  538. enum halmac_ret_status
  539. cfg_csi_rate_88xx(struct halmac_adapter *adapter, u8 rssi, u8 cur_rate,
  540. u8 fixrate_en, u8 *new_rate)
  541. {
  542. u32 csi_cfg;
  543. u16 cur_rrsr;
  544. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  545. PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
  546. #if HALMAC_8821C_SUPPORT
  547. if (adapter->chip_id == HALMAC_CHIP_ID_8821C && fixrate_en) {
  548. csi_cfg = HALMAC_REG_R32(REG_BBPSF_CTRL) & ~BITS_WMAC_CSI_RATE;
  549. HALMAC_REG_W32(REG_BBPSF_CTRL,
  550. csi_cfg | BIT_CSI_FORCE_RATE_EN |
  551. BIT_CSI_RSC(1) |
  552. BIT_WMAC_CSI_RATE(HALMAC_VHT_NSS1_MCS3));
  553. *new_rate = HALMAC_VHT_NSS1_MCS3;
  554. return HALMAC_RET_SUCCESS;
  555. }
  556. csi_cfg = HALMAC_REG_R32(REG_BBPSF_CTRL) & ~BITS_WMAC_CSI_RATE &
  557. ~BIT_CSI_FORCE_RATE_EN;
  558. #else
  559. csi_cfg = HALMAC_REG_R32(REG_BBPSF_CTRL) & ~BITS_WMAC_CSI_RATE;
  560. #endif
  561. cur_rrsr = HALMAC_REG_R16(REG_RRSR);
  562. if (rssi >= 40) {
  563. if (cur_rate != HALMAC_OFDM54) {
  564. cur_rrsr |= BIT(HALMAC_OFDM54);
  565. csi_cfg |= BIT_WMAC_CSI_RATE(HALMAC_OFDM54);
  566. HALMAC_REG_W16(REG_RRSR, cur_rrsr);
  567. HALMAC_REG_W32(REG_BBPSF_CTRL, csi_cfg);
  568. }
  569. *new_rate = HALMAC_OFDM54;
  570. } else {
  571. if (cur_rate != HALMAC_OFDM24) {
  572. cur_rrsr &= ~(BIT(HALMAC_OFDM54));
  573. csi_cfg |= BIT_WMAC_CSI_RATE(HALMAC_OFDM24);
  574. HALMAC_REG_W16(REG_RRSR, cur_rrsr);
  575. HALMAC_REG_W32(REG_BBPSF_CTRL, csi_cfg);
  576. }
  577. *new_rate = HALMAC_OFDM24;
  578. }
  579. return HALMAC_RET_SUCCESS;
  580. }
  581. /**
  582. * fw_snding_88xx() - fw sounding control
  583. * @adapter : the adapter of halmac
  584. * @su_info :
  585. * su0_en : enable/disable fw sounding
  586. * su0_ndpa_pkt : ndpa pkt, shall include txdesc
  587. * su0_pkt_sz : ndpa pkt size, shall include txdesc
  588. * @mu_info : currently not in use, input NULL is acceptable
  589. * @period : sounding period, unit is 5ms
  590. * Author : Ivan Lin
  591. * Return : enum halmac_ret_status
  592. * More details of status code can be found in prototype document
  593. */
  594. enum halmac_ret_status
  595. fw_snding_88xx(struct halmac_adapter *adapter,
  596. struct halmac_su_snding_info *su_info,
  597. struct halmac_mu_snding_info *mu_info, u8 period)
  598. {
  599. u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
  600. u16 seq_num;
  601. u16 snding_info_addr;
  602. struct halmac_h2c_header_info hdr_info;
  603. enum halmac_cmd_process_status *proc_status;
  604. enum halmac_ret_status status;
  605. proc_status = &adapter->halmac_state.fw_snding_state.proc_status;
  606. if (adapter->chip_id == HALMAC_CHIP_ID_8821C)
  607. return HALMAC_RET_NOT_SUPPORT;
  608. if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
  609. return HALMAC_RET_NO_DLFW;
  610. if (adapter->fw_ver.h2c_version < 9)
  611. return HALMAC_RET_FW_NO_SUPPORT;
  612. if (*proc_status == HALMAC_CMD_PROCESS_SENDING) {
  613. PLTFM_MSG_TRACE("[TRACE]Wait event(snd)\n");
  614. return HALMAC_RET_BUSY_STATE;
  615. }
  616. if (su_info->su0_en == 1) {
  617. if (!su_info->su0_ndpa_pkt)
  618. return HALMAC_RET_NULL_POINTER;
  619. if (su_info->su0_pkt_sz > (u32)SU0_SNDING_PKT_RSVDPG_SIZE -
  620. adapter->hw_cfg_info.txdesc_size)
  621. return HALMAC_RET_DATA_SIZE_INCORRECT;
  622. if (!snding_pkt_chk_88xx(adapter, su_info->su0_ndpa_pkt))
  623. return HALMAC_RET_TXDESC_SET_FAIL;
  624. if (fw_snding_cmd_cnstr_state_88xx(adapter) !=
  625. HALMAC_CMD_CNSTR_IDLE) {
  626. PLTFM_MSG_ERR("[ERR]Not idle(snd)\n");
  627. return HALMAC_RET_ERROR_STATE;
  628. }
  629. snding_info_addr = adapter->txff_alloc.rsvd_h2c_sta_info_addr +
  630. SU0_SNDING_PKT_OFFSET;
  631. status = dl_rsvd_page_88xx(adapter, snding_info_addr,
  632. su_info->su0_ndpa_pkt,
  633. su_info->su0_pkt_sz);
  634. if (status != HALMAC_RET_SUCCESS) {
  635. PLTFM_MSG_ERR("[ERR]dl rsvd page\n");
  636. return status;
  637. }
  638. FW_SNDING_SET_SU0(h2c_buf, 1);
  639. FW_SNDING_SET_PERIOD(h2c_buf, period);
  640. FW_SNDING_SET_NDPA0_HEAD_PG(h2c_buf, snding_info_addr -
  641. adapter->txff_alloc.rsvd_boundary);
  642. } else {
  643. if (fw_snding_cmd_cnstr_state_88xx(adapter) !=
  644. HALMAC_CMD_CNSTR_BUSY) {
  645. PLTFM_MSG_ERR("[ERR]Not snd(snd)\n");
  646. return HALMAC_RET_ERROR_STATE;
  647. }
  648. FW_SNDING_SET_SU0(h2c_buf, 0);
  649. }
  650. *proc_status = HALMAC_CMD_PROCESS_SENDING;
  651. hdr_info.sub_cmd_id = SUB_CMD_ID_FW_SNDING;
  652. hdr_info.content_size = 8;
  653. hdr_info.ack = 1;
  654. set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
  655. adapter->halmac_state.fw_snding_state.seq_num = seq_num;
  656. status = send_h2c_pkt_88xx(adapter, h2c_buf);
  657. if (status != HALMAC_RET_SUCCESS) {
  658. PLTFM_MSG_ERR("[ERR]send h2c\n");
  659. reset_ofld_feature_88xx(adapter, HALMAC_FEATURE_FW_SNDING);
  660. return status;
  661. }
  662. if (cnv_fw_snding_state_88xx(adapter, su_info->su0_en == 1 ?
  663. HALMAC_CMD_CNSTR_BUSY :
  664. HALMAC_CMD_CNSTR_IDLE)
  665. != HALMAC_RET_SUCCESS)
  666. return HALMAC_RET_ERROR_STATE;
  667. return HALMAC_RET_SUCCESS;
  668. }
  669. static u8
  670. snding_pkt_chk_88xx(struct halmac_adapter *adapter, u8 *pkt)
  671. {
  672. u8 data_rate;
  673. if (GET_TX_DESC_NDPA(pkt) == 0) {
  674. PLTFM_MSG_ERR("[ERR]txdesc ndpa = 0\n");
  675. return 0;
  676. }
  677. data_rate = (u8)GET_TX_DESC_DATARATE(pkt);
  678. if (!(data_rate >= HALMAC_VHT_NSS2_MCS0 &&
  679. data_rate <= HALMAC_VHT_NSS2_MCS9)) {
  680. if (!(data_rate >= HALMAC_MCS8 && data_rate <= HALMAC_MCS15)) {
  681. PLTFM_MSG_ERR("[ERR]txdesc rate\n");
  682. return 0;
  683. }
  684. }
  685. if (GET_TX_DESC_NAVUSEHDR(pkt) == 0) {
  686. PLTFM_MSG_ERR("[ERR]txdesc navusehdr = 0\n");
  687. return 0;
  688. }
  689. if (GET_TX_DESC_USE_RATE(pkt) == 0) {
  690. PLTFM_MSG_ERR("[ERR]txdesc userate = 0\n");
  691. return 0;
  692. }
  693. return 1;
  694. }
  695. static enum halmac_cmd_construct_state
  696. fw_snding_cmd_cnstr_state_88xx(struct halmac_adapter *adapter)
  697. {
  698. return adapter->halmac_state.fw_snding_state.cmd_cnstr_state;
  699. }
  700. enum halmac_ret_status
  701. get_h2c_ack_fw_snding_88xx(struct halmac_adapter *adapter, u8 *buf, u32 size)
  702. {
  703. u8 seq_num = 0;
  704. u8 fw_rc;
  705. struct halmac_fw_snding_state *state;
  706. enum halmac_cmd_process_status proc_status;
  707. state = &adapter->halmac_state.fw_snding_state;
  708. seq_num = (u8)H2C_ACK_HDR_GET_H2C_SEQ(buf);
  709. PLTFM_MSG_TRACE("[TRACE]Seq num:h2c->%d c2h->%d\n",
  710. state->seq_num, seq_num);
  711. if (seq_num != state->seq_num) {
  712. PLTFM_MSG_ERR("[ERR]Seq num mismatch:h2c->%d c2h->%d\n",
  713. state->seq_num, seq_num);
  714. return HALMAC_RET_SUCCESS;
  715. }
  716. if (state->proc_status != HALMAC_CMD_PROCESS_SENDING) {
  717. PLTFM_MSG_ERR("[ERR]not sending(snd)\n");
  718. return HALMAC_RET_SUCCESS;
  719. }
  720. fw_rc = (u8)H2C_ACK_HDR_GET_H2C_RETURN_CODE(buf);
  721. state->fw_rc = fw_rc;
  722. if ((enum halmac_h2c_return_code)fw_rc == HALMAC_H2C_RETURN_SUCCESS) {
  723. proc_status = HALMAC_CMD_PROCESS_DONE;
  724. state->proc_status = proc_status;
  725. PLTFM_EVENT_SIG(HALMAC_FEATURE_FW_SNDING, proc_status,
  726. NULL, 0);
  727. } else {
  728. proc_status = HALMAC_CMD_PROCESS_ERROR;
  729. state->proc_status = proc_status;
  730. PLTFM_EVENT_SIG(HALMAC_FEATURE_FW_SNDING, proc_status,
  731. &fw_rc, 1);
  732. }
  733. return HALMAC_RET_SUCCESS;
  734. }
  735. enum halmac_ret_status
  736. get_fw_snding_status_88xx(struct halmac_adapter *adapter,
  737. enum halmac_cmd_process_status *proc_status)
  738. {
  739. *proc_status = adapter->halmac_state.fw_snding_state.proc_status;
  740. return HALMAC_RET_SUCCESS;
  741. }
  742. static enum halmac_ret_status
  743. cnv_fw_snding_state_88xx(struct halmac_adapter *adapter,
  744. enum halmac_cmd_construct_state dest_state)
  745. {
  746. struct halmac_fw_snding_state *state;
  747. state = &adapter->halmac_state.fw_snding_state;
  748. if (state->cmd_cnstr_state != HALMAC_CMD_CNSTR_IDLE &&
  749. state->cmd_cnstr_state != HALMAC_CMD_CNSTR_BUSY)
  750. return HALMAC_RET_ERROR_STATE;
  751. if (dest_state == HALMAC_CMD_CNSTR_IDLE) {
  752. if (state->cmd_cnstr_state == HALMAC_CMD_CNSTR_IDLE)
  753. return HALMAC_RET_ERROR_STATE;
  754. } else if (dest_state == HALMAC_CMD_CNSTR_BUSY) {
  755. if (state->cmd_cnstr_state == HALMAC_CMD_CNSTR_BUSY)
  756. return HALMAC_RET_ERROR_STATE;
  757. }
  758. state->cmd_cnstr_state = dest_state;
  759. return HALMAC_RET_SUCCESS;
  760. }
  761. #endif /* HALMAC_88XX_SUPPORT */