halmac_fw_88xx.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167
  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_fw_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 DLFW_RESTORE_REG_NUM 6
  21. #define ILLEGAL_KEY_GROUP 0xFAAAAA00
  22. /* Max dlfw size can not over 31K, due to SDIO HW limitation */
  23. #define DLFW_PKT_SIZE_LIMIT 31744
  24. #define ID_INFORM_DLEMEM_RDY 0x80
  25. #define ID_INFORM_ENETR_CPU_SLEEP 0x20
  26. #define ID_CHECK_DLEMEM_RDY 0x80
  27. #define ID_CHECK_ENETR_CPU_SLEEP 0x05
  28. #define FW_STATUS_CHK_FATAL (BIT(1) | BIT(20))
  29. #define FW_STATUS_CHK_ERR (BIT(4) | BIT(5) | BIT(6) | BIT(7) | BIT(8) | \
  30. BIT(9) | BIT(12) | BIT(14) | BIT(15) | \
  31. BIT(16) | BIT(17) | BIT(18) | BIT(19) | \
  32. BIT(21) | BIT(22) | BIT(25))
  33. #define FW_STATUS_CHK_WARN ~(FW_STATUS_CHK_FATAL | FW_STATUS_CHK_ERR)
  34. struct halmac_backup_info {
  35. u32 mac_register;
  36. u32 value;
  37. u8 length;
  38. };
  39. static enum halmac_ret_status
  40. update_fw_info_88xx(struct halmac_adapter *adapter, u8 *fw_bin);
  41. static void
  42. restore_mac_reg_88xx(struct halmac_adapter *adapter,
  43. struct halmac_backup_info *info, u32 num);
  44. static enum halmac_ret_status
  45. dlfw_to_mem_88xx(struct halmac_adapter *adapter, u8 *fw_bin, u32 src, u32 dest,
  46. u32 size);
  47. static enum halmac_ret_status
  48. dlfw_end_flow_88xx(struct halmac_adapter *adapter);
  49. static enum halmac_ret_status
  50. free_dl_fw_end_flow_88xx(struct halmac_adapter *adapter);
  51. static enum halmac_ret_status
  52. send_fwpkt_88xx(struct halmac_adapter *adapter, u16 pg_addr, u8 *fw_bin,
  53. u32 size);
  54. static enum halmac_ret_status
  55. iddma_dlfw_88xx(struct halmac_adapter *adapter, u32 src, u32 dest, u32 len,
  56. u8 first);
  57. static enum halmac_ret_status
  58. iddma_en_88xx(struct halmac_adapter *adapter, u32 src, u32 dest, u32 ctrl);
  59. static enum halmac_ret_status
  60. check_fw_chksum_88xx(struct halmac_adapter *adapter, u32 mem_addr);
  61. static void
  62. fw_fatal_status_debug_88xx(struct halmac_adapter *adapter);
  63. static enum halmac_ret_status
  64. start_dlfw_88xx(struct halmac_adapter *adapter, u8 *fw_bin, u32 size,
  65. u32 dl_addr, u8 emem_only);
  66. static enum halmac_ret_status
  67. chk_fw_size_88xx(struct halmac_adapter *adapter, u8 *fw_bin, u32 size);
  68. static void
  69. chk_h2c_ver_88xx(struct halmac_adapter *adapter, u8 *fw_bin);
  70. static void
  71. wlan_cpu_en_88xx(struct halmac_adapter *adapter, u8 enable);
  72. static void
  73. pltfm_reset_88xx(struct halmac_adapter *adapter);
  74. static enum halmac_ret_status
  75. proc_send_general_info_88xx(struct halmac_adapter *adapter,
  76. struct halmac_general_info *info);
  77. static enum halmac_ret_status
  78. proc_send_phydm_info_88xx(struct halmac_adapter *adapter,
  79. struct halmac_general_info *info);
  80. /**
  81. * download_firmware_88xx() - download Firmware
  82. * @adapter : the adapter of halmac
  83. * @fw_bin : firmware bin
  84. * @size : firmware size
  85. * Author : KaiYuan Chang/Ivan Lin
  86. * Return : enum halmac_ret_status
  87. * More details of status code can be found in prototype document
  88. */
  89. enum halmac_ret_status
  90. download_firmware_88xx(struct halmac_adapter *adapter, u8 *fw_bin, u32 size)
  91. {
  92. u8 value8;
  93. u32 bckp_idx = 0;
  94. u32 lte_coex_backup = 0;
  95. struct halmac_backup_info bckp[DLFW_RESTORE_REG_NUM];
  96. enum halmac_ret_status status;
  97. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  98. if (adapter->halmac_state.mac_pwr == HALMAC_MAC_POWER_OFF)
  99. return HALMAC_RET_POWER_STATE_INVALID;
  100. PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
  101. status = chk_fw_size_88xx(adapter, fw_bin, size);
  102. if (status != HALMAC_RET_SUCCESS)
  103. return status;
  104. chk_h2c_ver_88xx(adapter, fw_bin);
  105. if (adapter->halmac_state.wlcpu_mode == HALMAC_WLCPU_ENTER_SLEEP)
  106. PLTFM_MSG_WARN("[WARN]Enter Sleep..zZZ\n");
  107. adapter->halmac_state.dlfw_state = HALMAC_DLFW_NONE;
  108. status = ltecoex_reg_read_88xx(adapter, 0x38, &lte_coex_backup);
  109. if (status != HALMAC_RET_SUCCESS)
  110. return status;
  111. wlan_cpu_en_88xx(adapter, 0);
  112. /* set HIQ to hi priority */
  113. bckp[bckp_idx].length = 1;
  114. bckp[bckp_idx].mac_register = REG_TXDMA_PQ_MAP + 1;
  115. bckp[bckp_idx].value = HALMAC_REG_R8(REG_TXDMA_PQ_MAP + 1);
  116. bckp_idx++;
  117. value8 = HALMAC_DMA_MAPPING_HIGH << 6;
  118. HALMAC_REG_W8(REG_TXDMA_PQ_MAP + 1, value8);
  119. /* DLFW only use HIQ, map HIQ to hi priority */
  120. adapter->pq_map[HALMAC_PQ_MAP_HI] = HALMAC_DMA_MAPPING_HIGH;
  121. bckp[bckp_idx].length = 1;
  122. bckp[bckp_idx].mac_register = REG_CR;
  123. bckp[bckp_idx].value = HALMAC_REG_R8(REG_CR);
  124. bckp_idx++;
  125. bckp[bckp_idx].length = 4;
  126. bckp[bckp_idx].mac_register = REG_H2CQ_CSR;
  127. bckp[bckp_idx].value = BIT(31);
  128. bckp_idx++;
  129. value8 = BIT_HCI_TXDMA_EN | BIT_TXDMA_EN;
  130. HALMAC_REG_W8(REG_CR, value8);
  131. HALMAC_REG_W32(REG_H2CQ_CSR, BIT(31));
  132. /* Config hi priority queue and public priority queue page number */
  133. bckp[bckp_idx].length = 2;
  134. bckp[bckp_idx].mac_register = REG_FIFOPAGE_INFO_1;
  135. bckp[bckp_idx].value = HALMAC_REG_R16(REG_FIFOPAGE_INFO_1);
  136. bckp_idx++;
  137. bckp[bckp_idx].length = 4;
  138. bckp[bckp_idx].mac_register = REG_RQPN_CTRL_2;
  139. bckp[bckp_idx].value = HALMAC_REG_R32(REG_RQPN_CTRL_2) | BIT(31);
  140. bckp_idx++;
  141. HALMAC_REG_W16(REG_FIFOPAGE_INFO_1, 0x200);
  142. HALMAC_REG_W32(REG_RQPN_CTRL_2, bckp[bckp_idx - 1].value);
  143. /* Disable beacon related functions */
  144. value8 = HALMAC_REG_R8(REG_BCN_CTRL);
  145. bckp[bckp_idx].length = 1;
  146. bckp[bckp_idx].mac_register = REG_BCN_CTRL;
  147. bckp[bckp_idx].value = value8;
  148. bckp_idx++;
  149. value8 = (u8)((value8 & (~BIT(3))) | BIT(4));
  150. HALMAC_REG_W8(REG_BCN_CTRL, value8);
  151. if (adapter->intf == HALMAC_INTERFACE_SDIO)
  152. HALMAC_REG_R32(REG_SDIO_FREE_TXPG);
  153. pltfm_reset_88xx(adapter);
  154. status = start_dlfw_88xx(adapter, fw_bin, size, 0, 0);
  155. restore_mac_reg_88xx(adapter, bckp, DLFW_RESTORE_REG_NUM);
  156. if (status != HALMAC_RET_SUCCESS)
  157. goto DLFW_FAIL;
  158. status = dlfw_end_flow_88xx(adapter);
  159. if (status != HALMAC_RET_SUCCESS)
  160. goto DLFW_FAIL;
  161. status = ltecoex_reg_write_88xx(adapter, 0x38, lte_coex_backup);
  162. if (status != HALMAC_RET_SUCCESS)
  163. return status;
  164. adapter->halmac_state.dlfw_state = HALMAC_DLFW_DONE;
  165. PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
  166. return HALMAC_RET_SUCCESS;
  167. DLFW_FAIL:
  168. /* Disable FWDL_EN */
  169. value8 = HALMAC_REG_R8(REG_MCUFW_CTRL);
  170. value8 &= ~BIT(0);
  171. HALMAC_REG_W8(REG_MCUFW_CTRL, value8);
  172. value8 = HALMAC_REG_R8(REG_SYS_FUNC_EN + 1);
  173. value8 |= BIT(2);
  174. HALMAC_REG_W8(REG_SYS_FUNC_EN + 1, value8);
  175. if (ltecoex_reg_write_88xx(adapter, 0x38, lte_coex_backup) !=
  176. HALMAC_RET_SUCCESS)
  177. return HALMAC_RET_LTECOEX_READY_FAIL;
  178. return status;
  179. }
  180. static enum halmac_ret_status
  181. start_dlfw_88xx(struct halmac_adapter *adapter, u8 *fw_bin, u32 size,
  182. u32 dl_addr, u8 emem_only)
  183. {
  184. u8 *cur_fw;
  185. u16 value16;
  186. u32 imem_size;
  187. u32 dmem_size;
  188. u32 emem_size = 0;
  189. u32 addr;
  190. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  191. enum halmac_ret_status status;
  192. dmem_size =
  193. rtk_le32_to_cpu(*((__le32 *)(fw_bin + WLAN_FW_HDR_DMEM_SIZE)));
  194. imem_size =
  195. rtk_le32_to_cpu(*((__le32 *)(fw_bin + WLAN_FW_HDR_IMEM_SIZE)));
  196. if (0 != ((*(fw_bin + WLAN_FW_HDR_MEM_USAGE)) & BIT(4)))
  197. emem_size =
  198. rtk_le32_to_cpu(*((__le32 *)(fw_bin + WLAN_FW_HDR_EMEM_SIZE)));
  199. dmem_size += WLAN_FW_HDR_CHKSUM_SIZE;
  200. imem_size += WLAN_FW_HDR_CHKSUM_SIZE;
  201. if (emem_size != 0)
  202. emem_size += WLAN_FW_HDR_CHKSUM_SIZE;
  203. if (emem_only == 1) {
  204. if (!emem_size)
  205. return HALMAC_RET_SUCCESS;
  206. goto DLFW_EMEM;
  207. }
  208. value16 = (u16)(HALMAC_REG_R16(REG_MCUFW_CTRL) & 0x3800);
  209. value16 |= BIT(0);
  210. HALMAC_REG_W16(REG_MCUFW_CTRL, value16);
  211. cur_fw = fw_bin + WLAN_FW_HDR_SIZE;
  212. addr = rtk_le32_to_cpu(*((__le32 *)(fw_bin + WLAN_FW_HDR_DMEM_ADDR)));
  213. addr &= ~BIT(31);
  214. status = dlfw_to_mem_88xx(adapter, cur_fw, 0, addr, dmem_size);
  215. if (status != HALMAC_RET_SUCCESS)
  216. return status;
  217. cur_fw = fw_bin + WLAN_FW_HDR_SIZE + dmem_size;
  218. addr = rtk_le32_to_cpu(*((__le32 *)(fw_bin + WLAN_FW_HDR_IMEM_ADDR)));
  219. addr &= ~BIT(31);
  220. status = dlfw_to_mem_88xx(adapter, cur_fw, 0, addr, imem_size);
  221. if (status != HALMAC_RET_SUCCESS)
  222. return status;
  223. DLFW_EMEM:
  224. if (emem_size) {
  225. cur_fw = fw_bin + WLAN_FW_HDR_SIZE +
  226. dmem_size + imem_size;
  227. addr = rtk_le32_to_cpu(*((__le32 *)(fw_bin +
  228. WLAN_FW_HDR_EMEM_ADDR)));
  229. addr &= ~BIT(31);
  230. status = dlfw_to_mem_88xx(adapter, cur_fw, dl_addr << 7, addr,
  231. emem_size);
  232. if (status != HALMAC_RET_SUCCESS)
  233. return status;
  234. if (emem_only == 1)
  235. return HALMAC_RET_SUCCESS;
  236. }
  237. update_fw_info_88xx(adapter, fw_bin);
  238. init_ofld_feature_state_machine_88xx(adapter);
  239. return HALMAC_RET_SUCCESS;
  240. }
  241. static void
  242. chk_h2c_ver_88xx(struct halmac_adapter *adapter, u8 *fw_bin)
  243. {
  244. u16 halmac_h2c_ver;
  245. u16 fw_h2c_ver;
  246. fw_h2c_ver = rtk_le16_to_cpu(*((__le16 *)(fw_bin +
  247. WLAN_FW_HDR_H2C_FMT_VER)));
  248. halmac_h2c_ver = H2C_FORMAT_VERSION;
  249. PLTFM_MSG_TRACE("[TRACE]halmac h2c ver = %x, fw h2c ver = %x!!\n",
  250. halmac_h2c_ver, fw_h2c_ver);
  251. }
  252. static enum halmac_ret_status
  253. chk_fw_size_88xx(struct halmac_adapter *adapter, u8 *fw_bin, u32 size)
  254. {
  255. u32 imem_size;
  256. u32 dmem_size;
  257. u32 emem_size = 0;
  258. u32 real_size;
  259. if (size < WLAN_FW_HDR_SIZE) {
  260. PLTFM_MSG_ERR("[ERR]FW size error!\n");
  261. return HALMAC_RET_FW_SIZE_ERR;
  262. }
  263. dmem_size =
  264. rtk_le32_to_cpu(*((__le32 *)(fw_bin + WLAN_FW_HDR_DMEM_SIZE)));
  265. imem_size =
  266. rtk_le32_to_cpu(*((__le32 *)(fw_bin + WLAN_FW_HDR_IMEM_SIZE)));
  267. if (0 != ((*(fw_bin + WLAN_FW_HDR_MEM_USAGE)) & BIT(4)))
  268. emem_size =
  269. rtk_le32_to_cpu(*((__le32 *)(fw_bin + WLAN_FW_HDR_EMEM_SIZE)));
  270. dmem_size += WLAN_FW_HDR_CHKSUM_SIZE;
  271. imem_size += WLAN_FW_HDR_CHKSUM_SIZE;
  272. if (emem_size != 0)
  273. emem_size += WLAN_FW_HDR_CHKSUM_SIZE;
  274. real_size = WLAN_FW_HDR_SIZE + dmem_size + imem_size + emem_size;
  275. if (size != real_size) {
  276. PLTFM_MSG_ERR("[ERR]size != real size!\n");
  277. return HALMAC_RET_FW_SIZE_ERR;
  278. }
  279. return HALMAC_RET_SUCCESS;
  280. }
  281. static void
  282. wlan_cpu_en_88xx(struct halmac_adapter *adapter, u8 enable)
  283. {
  284. u8 value8;
  285. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  286. if (enable == 1) {
  287. /* cpu io interface enable or disable */
  288. value8 = HALMAC_REG_R8(REG_RSV_CTRL + 1);
  289. value8 |= BIT(0);
  290. HALMAC_REG_W8(REG_RSV_CTRL + 1, value8);
  291. /* cpu enable or disable */
  292. value8 = HALMAC_REG_R8(REG_SYS_FUNC_EN + 1);
  293. value8 |= BIT(2);
  294. HALMAC_REG_W8(REG_SYS_FUNC_EN + 1, value8);
  295. } else {
  296. /* cpu enable or disable */
  297. value8 = HALMAC_REG_R8(REG_SYS_FUNC_EN + 1);
  298. value8 &= ~BIT(2);
  299. HALMAC_REG_W8(REG_SYS_FUNC_EN + 1, value8);
  300. /* cpu io interface enable or disable */
  301. value8 = HALMAC_REG_R8(REG_RSV_CTRL + 1);
  302. value8 &= ~BIT(0);
  303. HALMAC_REG_W8(REG_RSV_CTRL + 1, value8);
  304. }
  305. }
  306. static void
  307. pltfm_reset_88xx(struct halmac_adapter *adapter)
  308. {
  309. u8 value8;
  310. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  311. value8 = HALMAC_REG_R8(REG_CPU_DMEM_CON + 2) & ~BIT(0);
  312. HALMAC_REG_W8(REG_CPU_DMEM_CON + 2, value8);
  313. /* For 8822B & 8821C clock sync issue */
  314. if (adapter->chip_id == HALMAC_CHIP_ID_8821C ||
  315. adapter->chip_id == HALMAC_CHIP_ID_8822B) {
  316. value8 = HALMAC_REG_R8(REG_SYS_CLK_CTRL + 1) & ~BIT(6);
  317. HALMAC_REG_W8(REG_SYS_CLK_CTRL + 1, value8);
  318. }
  319. value8 = HALMAC_REG_R8(REG_CPU_DMEM_CON + 2) | BIT(0);
  320. HALMAC_REG_W8(REG_CPU_DMEM_CON + 2, value8);
  321. if (adapter->chip_id == HALMAC_CHIP_ID_8821C ||
  322. adapter->chip_id == HALMAC_CHIP_ID_8822B) {
  323. value8 = HALMAC_REG_R8(REG_SYS_CLK_CTRL + 1) | BIT(6);
  324. HALMAC_REG_W8(REG_SYS_CLK_CTRL + 1, value8);
  325. }
  326. }
  327. /**
  328. * free_download_firmware_88xx() - download specific memory firmware
  329. * @adapter
  330. * @mem_sel : memory selection
  331. * @fw_bin : firmware bin
  332. * @size : firmware size
  333. * Author : KaiYuan Chang/Ivan Lin
  334. * Return : enum halmac_ret_status
  335. */
  336. enum halmac_ret_status
  337. free_download_firmware_88xx(struct halmac_adapter *adapter,
  338. enum halmac_dlfw_mem mem_sel, u8 *fw_bin, u32 size)
  339. {
  340. u8 tx_pause_bckp;
  341. u32 dl_addr;
  342. u32 dlfw_size_bckp;
  343. enum halmac_ret_status status;
  344. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  345. if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
  346. return HALMAC_RET_NO_DLFW;
  347. PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
  348. status = chk_fw_size_88xx(adapter, fw_bin, size);
  349. if (status != HALMAC_RET_SUCCESS)
  350. return status;
  351. if (((*(fw_bin + WLAN_FW_HDR_MEM_USAGE)) & BIT(4)) == 0)
  352. return HALMAC_RET_SUCCESS;
  353. dlfw_size_bckp = adapter->dlfw_pkt_size;
  354. if (mem_sel == HALMAC_DLFW_MEM_EMEM) {
  355. dl_addr = 0;
  356. } else {
  357. dl_addr = adapter->txff_alloc.rsvd_h2c_info_addr;
  358. adapter->dlfw_pkt_size = (dlfw_size_bckp > DLFW_RSVDPG_SIZE) ?
  359. DLFW_RSVDPG_SIZE : dlfw_size_bckp;
  360. }
  361. tx_pause_bckp = HALMAC_REG_R8(REG_TXPAUSE);
  362. HALMAC_REG_W8(REG_TXPAUSE, tx_pause_bckp | BIT(7));
  363. status = start_dlfw_88xx(adapter, fw_bin, size, dl_addr, 1);
  364. if (status != HALMAC_RET_SUCCESS)
  365. goto DL_FREE_FW_END;
  366. status = free_dl_fw_end_flow_88xx(adapter);
  367. DL_FREE_FW_END:
  368. HALMAC_REG_W8(REG_TXPAUSE, tx_pause_bckp);
  369. adapter->dlfw_pkt_size = dlfw_size_bckp;
  370. PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
  371. return status;
  372. }
  373. /**
  374. * get_fw_version_88xx() - get FW version
  375. * @adapter : the adapter of halmac
  376. * @ver : fw version info
  377. * Author : Ivan Lin
  378. * Return : enum halmac_ret_status
  379. * More details of status code can be found in prototype document
  380. */
  381. enum halmac_ret_status
  382. get_fw_version_88xx(struct halmac_adapter *adapter,
  383. struct halmac_fw_version *ver)
  384. {
  385. struct halmac_fw_version *info = &adapter->fw_ver;
  386. if (!ver)
  387. return HALMAC_RET_NULL_POINTER;
  388. if (adapter->halmac_state.dlfw_state == HALMAC_DLFW_NONE)
  389. return HALMAC_RET_NO_DLFW;
  390. ver->version = info->version;
  391. ver->sub_version = info->sub_version;
  392. ver->sub_index = info->sub_index;
  393. ver->h2c_version = info->h2c_version;
  394. ver->build_time.month = info->build_time.month;
  395. ver->build_time.date = info->build_time.date;
  396. ver->build_time.hour = info->build_time.hour;
  397. ver->build_time.min = info->build_time.min;
  398. ver->build_time.year = info->build_time.year;
  399. return HALMAC_RET_SUCCESS;
  400. }
  401. static enum halmac_ret_status
  402. update_fw_info_88xx(struct halmac_adapter *adapter, u8 *fw_bin)
  403. {
  404. struct halmac_fw_version *info = &adapter->fw_ver;
  405. info->version =
  406. rtk_le16_to_cpu(*((__le16 *)(fw_bin + WLAN_FW_HDR_VERSION)));
  407. info->sub_version = *(fw_bin + WLAN_FW_HDR_SUBVERSION);
  408. info->sub_index = *(fw_bin + WLAN_FW_HDR_SUBINDEX);
  409. info->h2c_version = rtk_le16_to_cpu(*((__le16 *)(fw_bin +
  410. WLAN_FW_HDR_H2C_FMT_VER)));
  411. info->build_time.month = *(fw_bin + WLAN_FW_HDR_MONTH);
  412. info->build_time.date = *(fw_bin + WLAN_FW_HDR_DATE);
  413. info->build_time.hour = *(fw_bin + WLAN_FW_HDR_HOUR);
  414. info->build_time.min = *(fw_bin + WLAN_FW_HDR_MIN);
  415. info->build_time.year =
  416. rtk_le16_to_cpu(*((__le16 *)(fw_bin + WLAN_FW_HDR_YEAR)));
  417. PLTFM_MSG_TRACE("[TRACE]=== FW info ===\n");
  418. PLTFM_MSG_TRACE("[TRACE]ver : %X\n", info->version);
  419. PLTFM_MSG_TRACE("[TRACE]sub-ver : %X\n",
  420. info->sub_version);
  421. PLTFM_MSG_TRACE("[TRACE]sub-idx : %X\n",
  422. info->sub_index);
  423. PLTFM_MSG_TRACE("[TRACE]build : %d/%d/%d %d:%d\n",
  424. info->build_time.year, info->build_time.month,
  425. info->build_time.date, info->build_time.hour,
  426. info->build_time.min);
  427. return HALMAC_RET_SUCCESS;
  428. }
  429. static enum halmac_ret_status
  430. dlfw_to_mem_88xx(struct halmac_adapter *adapter, u8 *fw_bin, u32 src, u32 dest,
  431. u32 size)
  432. {
  433. u8 first_part;
  434. u32 mem_offset;
  435. u32 residue_size;
  436. u32 pkt_size;
  437. enum halmac_ret_status status;
  438. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  439. mem_offset = 0;
  440. first_part = 1;
  441. residue_size = size;
  442. HALMAC_REG_W32_SET(REG_DDMA_CH0CTRL, BIT_DDMACH0_RESET_CHKSUM_STS);
  443. while (residue_size != 0) {
  444. if (residue_size >= adapter->dlfw_pkt_size)
  445. pkt_size = adapter->dlfw_pkt_size;
  446. else
  447. pkt_size = residue_size;
  448. status = send_fwpkt_88xx(adapter, (u16)(src >> 7),
  449. fw_bin + mem_offset, pkt_size);
  450. if (status != HALMAC_RET_SUCCESS) {
  451. PLTFM_MSG_ERR("[ERR]send fw pkt!!\n");
  452. return status;
  453. }
  454. status = iddma_dlfw_88xx(adapter,
  455. OCPBASE_TXBUF_88XX +
  456. src + adapter->hw_cfg_info.txdesc_size,
  457. dest + mem_offset, pkt_size,
  458. first_part);
  459. if (status != HALMAC_RET_SUCCESS) {
  460. PLTFM_MSG_ERR("[ERR]iddma dlfw!!\n");
  461. return status;
  462. }
  463. first_part = 0;
  464. mem_offset += pkt_size;
  465. residue_size -= pkt_size;
  466. }
  467. status = check_fw_chksum_88xx(adapter, dest);
  468. if (status != HALMAC_RET_SUCCESS) {
  469. PLTFM_MSG_ERR("[ERR]chk fw chksum!!\n");
  470. return status;
  471. }
  472. return HALMAC_RET_SUCCESS;
  473. }
  474. static void
  475. restore_mac_reg_88xx(struct halmac_adapter *adapter,
  476. struct halmac_backup_info *info, u32 num)
  477. {
  478. u8 len;
  479. u32 i;
  480. u32 reg;
  481. u32 value;
  482. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  483. struct halmac_backup_info *curr_info = info;
  484. for (i = 0; i < num; i++) {
  485. reg = curr_info->mac_register;
  486. value = curr_info->value;
  487. len = curr_info->length;
  488. if (len == 1)
  489. HALMAC_REG_W8(reg, (u8)value);
  490. else if (len == 2)
  491. HALMAC_REG_W16(reg, (u16)value);
  492. else if (len == 4)
  493. HALMAC_REG_W32(reg, value);
  494. curr_info++;
  495. }
  496. }
  497. static enum halmac_ret_status
  498. dlfw_end_flow_88xx(struct halmac_adapter *adapter)
  499. {
  500. u16 fw_ctrl;
  501. u32 cnt;
  502. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  503. HALMAC_REG_W32(REG_TXDMA_STATUS, BIT(2));
  504. /* Check IMEM & DMEM checksum is OK or not */
  505. fw_ctrl = HALMAC_REG_R16(REG_MCUFW_CTRL);
  506. if ((fw_ctrl & 0x50) != 0x50)
  507. return HALMAC_RET_IDMEM_CHKSUM_FAIL;
  508. HALMAC_REG_W16(REG_MCUFW_CTRL, (fw_ctrl | BIT_FW_DW_RDY) & ~BIT(0));
  509. wlan_cpu_en_88xx(adapter, 1);
  510. PLTFM_MSG_TRACE("[TRACE]Dlfw OK, enable CPU\n");
  511. cnt = 5000;
  512. while (HALMAC_REG_R16(REG_MCUFW_CTRL) != 0xC078) {
  513. if (cnt == 0) {
  514. PLTFM_MSG_ERR("[ERR]Check 0x80 = 0xC078 fail\n");
  515. if ((HALMAC_REG_R32(REG_FW_DBG7) & 0xFFFFFF00) ==
  516. ILLEGAL_KEY_GROUP) {
  517. PLTFM_MSG_ERR("[ERR]Key!!\n");
  518. return HALMAC_RET_ILLEGAL_KEY_FAIL;
  519. }
  520. return HALMAC_RET_FW_READY_CHK_FAIL;
  521. }
  522. cnt--;
  523. PLTFM_DELAY_US(50);
  524. }
  525. PLTFM_MSG_TRACE("[TRACE]0x80=0xC078, cnt=%d\n", cnt);
  526. return HALMAC_RET_SUCCESS;
  527. }
  528. static enum halmac_ret_status
  529. free_dl_fw_end_flow_88xx(struct halmac_adapter *adapter)
  530. {
  531. u32 cnt;
  532. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  533. cnt = 100;
  534. while (HALMAC_REG_R8(REG_HMETFR + 3) != 0) {
  535. cnt--;
  536. if (cnt == 0) {
  537. PLTFM_MSG_ERR("[ERR]0x1CF != 0\n");
  538. return HALMAC_RET_DLFW_FAIL;
  539. }
  540. PLTFM_DELAY_US(50);
  541. }
  542. HALMAC_REG_W8(REG_HMETFR + 3, ID_INFORM_DLEMEM_RDY);
  543. cnt = 10000;
  544. while (HALMAC_REG_R8(REG_MCU_TST_CFG) != ID_CHECK_DLEMEM_RDY) {
  545. cnt--;
  546. if (cnt == 0) {
  547. PLTFM_MSG_ERR("[ERR]0x84 != 0x80\n");
  548. return HALMAC_RET_DLFW_FAIL;
  549. }
  550. PLTFM_DELAY_US(50);
  551. }
  552. HALMAC_REG_W8(REG_MCU_TST_CFG, 0);
  553. return HALMAC_RET_SUCCESS;
  554. }
  555. static enum halmac_ret_status
  556. send_fwpkt_88xx(struct halmac_adapter *adapter, u16 pg_addr, u8 *fw_bin,
  557. u32 size)
  558. {
  559. u8 *fw_add_dum = NULL;
  560. enum halmac_ret_status status;
  561. if (adapter->intf == HALMAC_INTERFACE_USB &&
  562. !((size + TX_DESC_SIZE_88XX) & (512 - 1))) {
  563. fw_add_dum = (u8 *)PLTFM_MALLOC(size + 1);
  564. if (!fw_add_dum) {
  565. PLTFM_MSG_ERR("[ERR]fw bin malloc!!\n");
  566. return HALMAC_RET_MALLOC_FAIL;
  567. }
  568. PLTFM_MEMCPY(fw_add_dum, fw_bin, size);
  569. status = dl_rsvd_page_88xx(adapter, pg_addr,
  570. fw_add_dum, size + 1);
  571. if (status != HALMAC_RET_SUCCESS)
  572. PLTFM_MSG_ERR("[ERR]dl rsvd page - dum!!\n");
  573. PLTFM_FREE(fw_add_dum, size + 1);
  574. return status;
  575. }
  576. status = dl_rsvd_page_88xx(adapter, pg_addr, fw_bin, size);
  577. if (status != HALMAC_RET_SUCCESS)
  578. PLTFM_MSG_ERR("[ERR]dl rsvd page!!\n");
  579. return status;
  580. }
  581. static enum halmac_ret_status
  582. iddma_dlfw_88xx(struct halmac_adapter *adapter, u32 src, u32 dest, u32 len,
  583. u8 first)
  584. {
  585. u32 cnt;
  586. u32 ch0_ctrl = (u32)(BIT_DDMACH0_CHKSUM_EN | BIT_DDMACH0_OWN);
  587. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  588. cnt = HALMC_DDMA_POLLING_COUNT;
  589. while (HALMAC_REG_R32(REG_DDMA_CH0CTRL) & BIT_DDMACH0_OWN) {
  590. cnt--;
  591. if (cnt == 0) {
  592. PLTFM_MSG_ERR("[ERR]ch0 ready!!\n");
  593. return HALMAC_RET_DDMA_FAIL;
  594. }
  595. }
  596. ch0_ctrl |= (len & BIT_MASK_DDMACH0_DLEN);
  597. if (first == 0)
  598. ch0_ctrl |= BIT_DDMACH0_CHKSUM_CONT;
  599. if (iddma_en_88xx(adapter, src, dest, ch0_ctrl) !=
  600. HALMAC_RET_SUCCESS) {
  601. PLTFM_MSG_ERR("[ERR]iddma en!!\n");
  602. return HALMAC_RET_DDMA_FAIL;
  603. }
  604. return HALMAC_RET_SUCCESS;
  605. }
  606. static enum halmac_ret_status
  607. iddma_en_88xx(struct halmac_adapter *adapter, u32 src, u32 dest, u32 ctrl)
  608. {
  609. u32 cnt = HALMC_DDMA_POLLING_COUNT;
  610. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  611. HALMAC_REG_W32(REG_DDMA_CH0SA, src);
  612. HALMAC_REG_W32(REG_DDMA_CH0DA, dest);
  613. HALMAC_REG_W32(REG_DDMA_CH0CTRL, ctrl);
  614. while (HALMAC_REG_R32(REG_DDMA_CH0CTRL) & BIT_DDMACH0_OWN) {
  615. cnt--;
  616. if (cnt == 0)
  617. return HALMAC_RET_DDMA_FAIL;
  618. }
  619. return HALMAC_RET_SUCCESS;
  620. }
  621. static enum halmac_ret_status
  622. check_fw_chksum_88xx(struct halmac_adapter *adapter, u32 mem_addr)
  623. {
  624. u8 fw_ctrl;
  625. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  626. fw_ctrl = HALMAC_REG_R8(REG_MCUFW_CTRL);
  627. if (HALMAC_REG_R32(REG_DDMA_CH0CTRL) & BIT_DDMACH0_CHKSUM_STS) {
  628. if (mem_addr < OCPBASE_DMEM_88XX) {
  629. fw_ctrl |= BIT_IMEM_DW_OK;
  630. fw_ctrl &= ~BIT_IMEM_CHKSUM_OK;
  631. HALMAC_REG_W8(REG_MCUFW_CTRL, fw_ctrl);
  632. } else {
  633. fw_ctrl |= BIT_DMEM_DW_OK;
  634. fw_ctrl &= ~BIT_DMEM_CHKSUM_OK;
  635. HALMAC_REG_W8(REG_MCUFW_CTRL, fw_ctrl);
  636. }
  637. PLTFM_MSG_ERR("[ERR]fw chksum!!\n");
  638. return HALMAC_RET_FW_CHECKSUM_FAIL;
  639. }
  640. if (mem_addr < OCPBASE_DMEM_88XX) {
  641. fw_ctrl |= (BIT_IMEM_DW_OK | BIT_IMEM_CHKSUM_OK);
  642. HALMAC_REG_W8(REG_MCUFW_CTRL, fw_ctrl);
  643. } else {
  644. fw_ctrl |= (BIT_DMEM_DW_OK | BIT_DMEM_CHKSUM_OK);
  645. HALMAC_REG_W8(REG_MCUFW_CTRL, fw_ctrl);
  646. }
  647. return HALMAC_RET_SUCCESS;
  648. }
  649. /**
  650. * check_fw_status_88xx() -check fw status
  651. * @adapter : the adapter of halmac
  652. * @status : fw status
  653. * Author : KaiYuan Chang/Ivan Lin
  654. * Return : enum halmac_ret_status
  655. * More details of status code can be found in prototype document
  656. */
  657. enum halmac_ret_status
  658. check_fw_status_88xx(struct halmac_adapter *adapter, u8 *fw_status)
  659. {
  660. u32 cnt;
  661. u32 fw_dbg6;
  662. u32 fw_pc;
  663. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  664. enum halmac_ret_status status = HALMAC_RET_SUCCESS;
  665. PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
  666. *fw_status = 1;
  667. fw_dbg6 = HALMAC_REG_R32(REG_FW_DBG6);
  668. if (fw_dbg6 != 0) {
  669. PLTFM_MSG_ERR("[ERR]REG_FW_DBG6 !=0\n");
  670. if ((fw_dbg6 & FW_STATUS_CHK_WARN) != 0)
  671. PLTFM_MSG_WARN("[WARN]fw status(warn):%X\n", fw_dbg6);
  672. if ((fw_dbg6 & FW_STATUS_CHK_ERR) != 0)
  673. PLTFM_MSG_ERR("[ERR]fw status(err):%X\n", fw_dbg6);
  674. if ((fw_dbg6 & FW_STATUS_CHK_FATAL) != 0) {
  675. PLTFM_MSG_ERR("[ERR]fw status(fatal):%X\n", fw_dbg6);
  676. fw_fatal_status_debug_88xx(adapter);
  677. *fw_status = 0;
  678. return status;
  679. }
  680. }
  681. fw_pc = HALMAC_REG_R32(REG_FW_DBG7);
  682. cnt = 10;
  683. while (HALMAC_REG_R32(REG_FW_DBG7) == fw_pc) {
  684. cnt--;
  685. if (cnt == 0)
  686. break;
  687. }
  688. if (cnt == 0) {
  689. cnt = 200;
  690. while (HALMAC_REG_R32(REG_FW_DBG7) == fw_pc) {
  691. cnt--;
  692. if (cnt == 0) {
  693. PLTFM_MSG_ERR("[ERR]fw pc\n");
  694. *fw_status = 0;
  695. return status;
  696. }
  697. PLTFM_DELAY_US(50);
  698. }
  699. }
  700. PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
  701. return status;
  702. }
  703. static void
  704. fw_fatal_status_debug_88xx(struct halmac_adapter *adapter)
  705. {
  706. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  707. PLTFM_MSG_ERR("[ERR]0x%X = %X\n",
  708. REG_FW_DBG6, HALMAC_REG_R32(REG_FW_DBG6));
  709. PLTFM_MSG_ERR("[ERR]0x%X = %X\n",
  710. REG_ARFR5, HALMAC_REG_R32(REG_ARFR5));
  711. PLTFM_MSG_ERR("[ERR]0x%X = %X\n",
  712. REG_MCUTST_I, HALMAC_REG_R32(REG_MCUTST_I));
  713. }
  714. enum halmac_ret_status
  715. dump_fw_dmem_88xx(struct halmac_adapter *adapter, u8 *dmem, u32 *size)
  716. {
  717. return HALMAC_RET_SUCCESS;
  718. }
  719. /**
  720. * cfg_max_dl_size_88xx() - config max download FW size
  721. * @adapter : the adapter of halmac
  722. * @size : max download fw size
  723. *
  724. * Halmac uses this setting to set max packet size for
  725. * download FW.
  726. * If user has not called this API, halmac use default
  727. * setting for download FW
  728. * Note1 : size need multiple of 2
  729. * Note2 : max size is 31K
  730. *
  731. * Author : Ivan Lin/KaiYuan Chang
  732. * Return : enum halmac_ret_status
  733. * More details of status code can be found in prototype document
  734. */
  735. enum halmac_ret_status
  736. cfg_max_dl_size_88xx(struct halmac_adapter *adapter, u32 size)
  737. {
  738. PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
  739. if (size > DLFW_PKT_SIZE_LIMIT) {
  740. PLTFM_MSG_ERR("[ERR]size > max dl size!\n");
  741. return HALMAC_RET_CFG_DLFW_SIZE_FAIL;
  742. }
  743. if ((size & (2 - 1)) != 0) {
  744. PLTFM_MSG_ERR("[ERR]not multiple of 2!\n");
  745. return HALMAC_RET_CFG_DLFW_SIZE_FAIL;
  746. }
  747. adapter->dlfw_pkt_size = size;
  748. PLTFM_MSG_TRACE("[TRACE]Cfg max size:%X\n", size);
  749. PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
  750. return HALMAC_RET_SUCCESS;
  751. }
  752. /**
  753. * enter_cpu_sleep_mode_88xx() -wlan cpu enter sleep mode
  754. * @adapter : the adapter of halmac
  755. * Author : Ivan Lin
  756. * Return : enum halmac_ret_status
  757. * More details of status code can be found in prototype document
  758. */
  759. enum halmac_ret_status
  760. enter_cpu_sleep_mode_88xx(struct halmac_adapter *adapter)
  761. {
  762. u32 cnt;
  763. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  764. enum halmac_wlcpu_mode *cur_mode = &adapter->halmac_state.wlcpu_mode;
  765. if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
  766. return HALMAC_RET_NO_DLFW;
  767. if (*cur_mode != HALMAC_WLCPU_ACTIVE)
  768. return HALMAC_RET_ERROR_STATE;
  769. cnt = 100;
  770. while (HALMAC_REG_R8(REG_HMETFR + 3) != 0) {
  771. cnt--;
  772. if (cnt == 0) {
  773. PLTFM_MSG_ERR("[ERR]0x1CF != 0\n");
  774. return HALMAC_RET_STATE_INCORRECT;
  775. }
  776. PLTFM_DELAY_US(50);
  777. }
  778. HALMAC_REG_W8(REG_HMETFR + 3, ID_INFORM_ENETR_CPU_SLEEP);
  779. *cur_mode = HALMAC_WLCPU_ENTER_SLEEP;
  780. return HALMAC_RET_SUCCESS;
  781. }
  782. /**
  783. * get_cpu_mode_88xx() -get wlcpu mode
  784. * @adapter : the adapter of halmac
  785. * @mode : cpu mode
  786. * Author : Ivan Lin
  787. * Return : enum halmac_ret_status
  788. * More details of status code can be found in prototype document
  789. */
  790. enum halmac_ret_status
  791. get_cpu_mode_88xx(struct halmac_adapter *adapter,
  792. enum halmac_wlcpu_mode *mode)
  793. {
  794. struct halmac_api *api = (struct halmac_api *)adapter->halmac_api;
  795. enum halmac_wlcpu_mode *cur_mode = &adapter->halmac_state.wlcpu_mode;
  796. if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
  797. return HALMAC_RET_NO_DLFW;
  798. if (*cur_mode == HALMAC_WLCPU_ACTIVE) {
  799. *mode = HALMAC_WLCPU_ACTIVE;
  800. return HALMAC_RET_SUCCESS;
  801. }
  802. if (*cur_mode == HALMAC_WLCPU_SLEEP) {
  803. *mode = HALMAC_WLCPU_SLEEP;
  804. return HALMAC_RET_SUCCESS;
  805. }
  806. if (HALMAC_REG_R8(REG_MCU_TST_CFG) == ID_CHECK_ENETR_CPU_SLEEP) {
  807. *mode = HALMAC_WLCPU_SLEEP;
  808. HALMAC_REG_W8(REG_MCU_TST_CFG, 0);
  809. } else {
  810. *mode = HALMAC_WLCPU_ENTER_SLEEP;
  811. }
  812. return HALMAC_RET_SUCCESS;
  813. }
  814. /**
  815. * send_general_info_88xx() -send general information to FW
  816. * @adapter : the adapter of halmac
  817. * @info : general information
  818. * Author : KaiYuan Chang/Ivan Lin
  819. * Return : enum halmac_ret_status
  820. * More details of status code can be found in prototype document
  821. */
  822. enum halmac_ret_status
  823. send_general_info_88xx(struct halmac_adapter *adapter,
  824. struct halmac_general_info *info)
  825. {
  826. u8 h2cq_ele[4] = {0};
  827. u32 h2cq_addr;
  828. enum halmac_ret_status status = HALMAC_RET_SUCCESS;
  829. if (halmac_fw_validate(adapter) != HALMAC_RET_SUCCESS)
  830. return HALMAC_RET_NO_DLFW;
  831. if (adapter->fw_ver.h2c_version < 4)
  832. return HALMAC_RET_FW_NO_SUPPORT;
  833. PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
  834. if (adapter->halmac_state.dlfw_state == HALMAC_DLFW_NONE) {
  835. PLTFM_MSG_ERR("[ERR]no dl fw!!\n");
  836. return HALMAC_RET_NO_DLFW;
  837. }
  838. status = proc_send_general_info_88xx(adapter, info);
  839. if (status != HALMAC_RET_SUCCESS) {
  840. PLTFM_MSG_ERR("[ERR]send gen info!!\n");
  841. return status;
  842. }
  843. status = proc_send_phydm_info_88xx(adapter, info);
  844. if (status != HALMAC_RET_SUCCESS) {
  845. PLTFM_MSG_ERR("[ERR]send phydm info\n");
  846. return status;
  847. }
  848. h2cq_addr = adapter->txff_alloc.rsvd_h2cq_addr;
  849. h2cq_addr <<= TX_PAGE_SIZE_SHIFT_88XX;
  850. status = dump_fifo_88xx(adapter, HAL_FIFO_SEL_TX,
  851. h2cq_addr, 4, h2cq_ele);
  852. if (status != HALMAC_RET_SUCCESS) {
  853. PLTFM_MSG_ERR("[ERR]dump h2cq!!\n");
  854. return status;
  855. }
  856. if ((h2cq_ele[0] & 0x7F) != 0x01 || h2cq_ele[1] != 0xFF) {
  857. PLTFM_MSG_ERR("[ERR]h2cq compare!!\n");
  858. return HALMAC_RET_SEND_H2C_FAIL;
  859. }
  860. if (adapter->halmac_state.dlfw_state == HALMAC_DLFW_DONE)
  861. adapter->halmac_state.dlfw_state = HALMAC_GEN_INFO_SENT;
  862. PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
  863. return HALMAC_RET_SUCCESS;
  864. }
  865. static enum halmac_ret_status
  866. proc_send_general_info_88xx(struct halmac_adapter *adapter,
  867. struct halmac_general_info *info)
  868. {
  869. u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
  870. u16 seq_num = 0;
  871. struct halmac_h2c_header_info hdr_info;
  872. enum halmac_ret_status status = HALMAC_RET_SUCCESS;
  873. PLTFM_MSG_TRACE("[TRACE]%s\n", __func__);
  874. GENERAL_INFO_SET_FW_TX_BOUNDARY(h2c_buf,
  875. adapter->txff_alloc.rsvd_fw_txbuf_addr -
  876. adapter->txff_alloc.rsvd_boundary);
  877. hdr_info.sub_cmd_id = SUB_CMD_ID_GENERAL_INFO;
  878. hdr_info.content_size = 4;
  879. hdr_info.ack = 0;
  880. set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
  881. status = send_h2c_pkt_88xx(adapter, h2c_buf);
  882. if (status != HALMAC_RET_SUCCESS)
  883. PLTFM_MSG_ERR("[ERR]send h2c!!\n");
  884. return status;
  885. }
  886. static enum halmac_ret_status
  887. proc_send_phydm_info_88xx(struct halmac_adapter *adapter,
  888. struct halmac_general_info *info)
  889. {
  890. u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
  891. u16 seq_num = 0;
  892. struct halmac_h2c_header_info hdr_info;
  893. enum halmac_ret_status status = HALMAC_RET_SUCCESS;
  894. PLTFM_MSG_TRACE("[TRACE]%s\n", __func__);
  895. PHYDM_INFO_SET_REF_TYPE(h2c_buf, info->rfe_type);
  896. PHYDM_INFO_SET_RF_TYPE(h2c_buf, info->rf_type);
  897. PHYDM_INFO_SET_CUT_VER(h2c_buf, adapter->chip_ver);
  898. PHYDM_INFO_SET_RX_ANT_STATUS(h2c_buf, info->rx_ant_status);
  899. PHYDM_INFO_SET_TX_ANT_STATUS(h2c_buf, info->tx_ant_status);
  900. hdr_info.sub_cmd_id = SUB_CMD_ID_PHYDM_INFO;
  901. hdr_info.content_size = 8;
  902. hdr_info.ack = 0;
  903. set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
  904. status = send_h2c_pkt_88xx(adapter, h2c_buf);
  905. if (status != HALMAC_RET_SUCCESS)
  906. PLTFM_MSG_ERR("[ERR]send h2c!!\n");
  907. return status;
  908. }
  909. /**
  910. * drv_fwctrl_88xx() - send drv-defined h2c pkt
  911. * @adapter : the adapter of halmac
  912. * @payload : no include offload pkt h2c header
  913. * @size : no include offload pkt h2c header
  914. * Author : Ivan Lin
  915. * Return : enum halmac_ret_status
  916. * More details of status code can be found in prototype document
  917. */
  918. enum halmac_ret_status
  919. drv_fwctrl_88xx(struct halmac_adapter *adapter, u8 *payload, u32 size, u8 ack)
  920. {
  921. u8 h2c_buf[H2C_PKT_SIZE_88XX] = { 0 };
  922. u16 seq_num = 0;
  923. struct halmac_h2c_header_info hdr_info;
  924. enum halmac_ret_status status = HALMAC_RET_SUCCESS;
  925. PLTFM_MSG_TRACE("[TRACE]%s ===>\n", __func__);
  926. if (!payload)
  927. return HALMAC_RET_DATA_BUF_NULL;
  928. if (size > H2C_PKT_SIZE_88XX - H2C_PKT_HDR_SIZE_88XX)
  929. return HALMAC_RET_DATA_SIZE_INCORRECT;
  930. PLTFM_MEMCPY(h2c_buf + H2C_PKT_HDR_SIZE_88XX, payload, size);
  931. hdr_info.sub_cmd_id = SUB_CMD_ID_FW_FWCTRL;
  932. hdr_info.content_size = (u16)size;
  933. hdr_info.ack = ack;
  934. set_h2c_pkt_hdr_88xx(adapter, h2c_buf, &hdr_info, &seq_num);
  935. status = send_h2c_pkt_88xx(adapter, h2c_buf);
  936. if (status != HALMAC_RET_SUCCESS)
  937. PLTFM_MSG_ERR("[ERR]send h2c!!\n");
  938. PLTFM_MSG_TRACE("[TRACE]%s <===\n", __func__);
  939. return status;
  940. }
  941. #endif /* HALMAC_88XX_SUPPORT */