rtl8821ce_ops.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2015 - 2016 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. * 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. *
  19. ******************************************************************************/
  20. #define _HCI_OPS_OS_C_
  21. #include <drv_types.h> /* PADAPTER, basic_types.h and etc. */
  22. #include <hal_data.h> /* HAL_DATA_TYPE, GET_HAL_DATA() and etc. */
  23. #include <hal_intf.h> /* struct hal_ops */
  24. #include "../rtl8821c.h"
  25. #include "rtl8821ce.h"
  26. static void init_bd_ring_var(_adapter *padapter)
  27. {
  28. struct recv_priv *r_priv = &padapter->recvpriv;
  29. struct xmit_priv *t_priv = &padapter->xmitpriv;
  30. u8 i = 0;
  31. for (i = 0; i < HW_QUEUE_ENTRY; i++)
  32. t_priv->txringcount[i] = TX_BD_NUM_8821CE;
  33. /*
  34. * we just alloc 2 desc for beacon queue,
  35. * because we just need first desc in hw beacon.
  36. */
  37. t_priv->txringcount[BCN_QUEUE_INX] = TX_BD_NUM_8821CE_BCN;
  38. t_priv->txringcount[TXCMD_QUEUE_INX] = TX_BD_NUM_8821CE_CMD;
  39. /*
  40. * BE queue need more descriptor for performance consideration
  41. * or, No more tx desc will happen, and may cause mac80211 mem leakage.
  42. */
  43. r_priv->rxbuffersize = MAX_RECVBUF_SZ;
  44. r_priv->rxringcount = PCI_MAX_RX_COUNT;
  45. }
  46. static void rtl8821ce_reset_bd(_adapter *padapter)
  47. {
  48. _irqL irqL;
  49. struct xmit_priv *t_priv = &padapter->xmitpriv;
  50. struct recv_priv *r_priv = &padapter->recvpriv;
  51. struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
  52. struct xmit_buf *pxmitbuf = NULL;
  53. u8 *tx_bd, *rx_bd;
  54. int i, rx_queue_idx;
  55. for (rx_queue_idx = 0; rx_queue_idx < 1; rx_queue_idx++) {
  56. if (r_priv->rx_ring[rx_queue_idx].buf_desc) {
  57. rx_bd = NULL;
  58. for (i = 0; i < r_priv->rxringcount; i++) {
  59. rx_bd = (u8 *)
  60. &r_priv->rx_ring[rx_queue_idx].buf_desc[i];
  61. }
  62. r_priv->rx_ring[rx_queue_idx].idx = 0;
  63. }
  64. }
  65. _enter_critical(&pdvobjpriv->irq_th_lock, &irqL);
  66. for (i = 0; i < PCI_MAX_TX_QUEUE_COUNT; i++) {
  67. if (t_priv->tx_ring[i].buf_desc) {
  68. struct rtw_tx_ring *ring = &t_priv->tx_ring[i];
  69. while (ring->qlen) {
  70. tx_bd = (u8 *)(&ring->buf_desc[ring->idx]);
  71. SET_TX_BD_OWN(tx_bd, 0);
  72. if (i != BCN_QUEUE_INX)
  73. ring->idx =
  74. (ring->idx + 1) % ring->entries;
  75. pxmitbuf = rtl8821ce_dequeue_xmitbuf(ring);
  76. if (pxmitbuf) {
  77. pci_unmap_single(pdvobjpriv->ppcidev,
  78. GET_TX_BD_PHYSICAL_ADDR0_LOW(tx_bd),
  79. pxmitbuf->len, PCI_DMA_TODEVICE);
  80. rtw_free_xmitbuf(t_priv, pxmitbuf);
  81. } else {
  82. RTW_INFO("%s(): qlen(%d) is not zero, but have xmitbuf in pending queue\n",
  83. __func__, ring->qlen);
  84. break;
  85. }
  86. }
  87. ring->idx = 0;
  88. }
  89. }
  90. _exit_critical(&pdvobjpriv->irq_th_lock, &irqL);
  91. }
  92. static void intf_chip_configure(PADAPTER padapter)
  93. {
  94. }
  95. /*
  96. * Description:
  97. * Collect all hardware information, fill "HAL_DATA_TYPE".
  98. * Sometimes this would be used to read MAC address.
  99. * This function will do
  100. * 1. Read Efuse/EEPROM to initialize
  101. * 2. Read registers to initialize
  102. * 3. Other vaiables initialization
  103. */
  104. static u8 read_adapter_info(PADAPTER padapter)
  105. {
  106. /*
  107. * 1. Read Efuse/EEPROM to initialize
  108. */
  109. rtl8821c_read_efuse(padapter);
  110. /*
  111. * 2. Read registers to initialize
  112. */
  113. /*
  114. * 3. Other Initialization
  115. */
  116. return _SUCCESS;
  117. }
  118. static BOOLEAN rtl8821ce_InterruptRecognized(PADAPTER Adapter)
  119. {
  120. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
  121. BOOLEAN bRecognized = _FALSE;
  122. /* 2013.11.18 Glayrainx suggests that turn off IMR and
  123. * restore after cleaning ISR.
  124. */
  125. rtw_write32(Adapter, REG_HIMR0, 0);
  126. rtw_write32(Adapter, REG_HIMR1, 0);
  127. rtw_write32(Adapter, REG_HIMR3, 0);
  128. pHalData->IntArray[0] = rtw_read32(Adapter, REG_HISR0);
  129. pHalData->IntArray[0] &= pHalData->IntrMask[0];
  130. rtw_write32(Adapter, REG_HISR0, pHalData->IntArray[0]);
  131. /* For HISR extension. Added by tynli. 2009.10.07. */
  132. pHalData->IntArray[1] = rtw_read32(Adapter, REG_HISR1);
  133. pHalData->IntArray[1] &= pHalData->IntrMask[1];
  134. rtw_write32(Adapter, REG_HISR1, pHalData->IntArray[1]);
  135. /* for H2C cmd queue */
  136. pHalData->IntArray[3] = rtw_read32(Adapter, REG_HISR3);
  137. pHalData->IntArray[3] &= pHalData->IntrMask[3];
  138. rtw_write32(Adapter, REG_HISR3, pHalData->IntArray[3]);
  139. if (((pHalData->IntArray[0]) & pHalData->IntrMask[0]) != 0 ||
  140. ((pHalData->IntArray[1]) & pHalData->IntrMask[1]) != 0)
  141. bRecognized = _TRUE;
  142. /* restore IMR */
  143. rtw_write32(Adapter, REG_HIMR0, pHalData->IntrMask[0] & 0xFFFFFFFF);
  144. rtw_write32(Adapter, REG_HIMR1, pHalData->IntrMask[1] & 0xFFFFFFFF);
  145. rtw_write32(Adapter, REG_HIMR3, pHalData->IntrMask[3] & 0xFFFFFFFF);
  146. return bRecognized;
  147. }
  148. static VOID DisableInterrupt8821ce(PADAPTER Adapter)
  149. {
  150. struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
  151. rtw_write32(Adapter, REG_HIMR0, 0x0);
  152. rtw_write32(Adapter, REG_HIMR1, 0x0);
  153. rtw_write32(Adapter, REG_HIMR3, 0x0);
  154. pdvobjpriv->irq_enabled = 0;
  155. }
  156. static VOID rtl8821ce_enable_interrupt(PADAPTER Adapter)
  157. {
  158. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
  159. struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
  160. pdvobjpriv->irq_enabled = 1;
  161. rtw_write32(Adapter, REG_HIMR0, pHalData->IntrMask[0] & 0xFFFFFFFF);
  162. rtw_write32(Adapter, REG_HIMR1, pHalData->IntrMask[1] & 0xFFFFFFFF);
  163. rtw_write32(Adapter, REG_HIMR3, pHalData->IntrMask[3] & 0xFFFFFFFF);
  164. }
  165. static VOID rtl8821ce_clear_interrupt(PADAPTER Adapter)
  166. {
  167. u32 u32b;
  168. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
  169. u32b = rtw_read32(Adapter, REG_HISR0_8821C);
  170. rtw_write32(Adapter, REG_HISR0_8821C, u32b);
  171. pHalData->IntArray[0] = 0;
  172. u32b = rtw_read32(Adapter, REG_HISR1_8821C);
  173. rtw_write32(Adapter, REG_HISR1_8821C, u32b);
  174. pHalData->IntArray[1] = 0;
  175. }
  176. static VOID rtl8821ce_disable_interrupt(PADAPTER Adapter)
  177. {
  178. struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
  179. rtw_write32(Adapter, REG_HIMR0, 0x0);
  180. rtw_write32(Adapter, REG_HIMR1, 0x0); /* by tynli */
  181. pdvobjpriv->irq_enabled = 0;
  182. }
  183. VOID UpdateInterruptMask8821CE(PADAPTER Adapter, u32 AddMSR, u32 AddMSR1,
  184. u32 RemoveMSR, u32 RemoveMSR1)
  185. {
  186. PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
  187. DisableInterrupt8821ce(Adapter);
  188. if (AddMSR)
  189. pHalData->IntrMask[0] |= AddMSR;
  190. if (AddMSR1)
  191. pHalData->IntrMask[1] |= AddMSR1;
  192. if (RemoveMSR)
  193. pHalData->IntrMask[0] &= (~RemoveMSR);
  194. if (RemoveMSR1)
  195. pHalData->IntrMask[1] &= (~RemoveMSR1);
  196. #if 0 /* TODO */
  197. if (RemoveMSR3)
  198. pHalData->IntrMask[3] &= (~RemoveMSR3);
  199. #endif
  200. rtl8821ce_enable_interrupt(Adapter);
  201. }
  202. static void rtl8821ce_bcn_handler(PADAPTER Adapter, u32 handled[])
  203. {
  204. PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
  205. if (pHalData->IntArray[0] & BIT_TXBCN0OK_MSK) {
  206. #ifdef CONFIG_BCN_ICF
  207. /* do nothing */
  208. #else
  209. /* Modify for MI temporary,
  210. * this processor cannot apply to multi-ap
  211. */
  212. PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
  213. if (bcn_adapter->xmitpriv.beaconDMAing) {
  214. bcn_adapter->xmitpriv.beaconDMAing = _FAIL;
  215. rtl8821ce_tx_isr(Adapter, BCN_QUEUE_INX);
  216. }
  217. #endif /* CONFIG_BCN_ICF */
  218. handled[0] |= BIT_TXBCN0OK_MSK;
  219. }
  220. if (pHalData->IntArray[0] & BIT_TXBCN0ERR_MSK) {
  221. #ifdef CONFIG_BCN_ICF
  222. RTW_INFO("IMR_TXBCN0ERR isr!\n");
  223. #else /* !CONFIG_BCN_ICF */
  224. /* Modify for MI temporary,
  225. * this processor cannot apply to multi-ap
  226. */
  227. PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
  228. if (bcn_adapter->xmitpriv.beaconDMAing) {
  229. bcn_adapter->xmitpriv.beaconDMAing = _FAIL;
  230. rtl8821ce_tx_isr(Adapter, BCN_QUEUE_INX);
  231. }
  232. #endif /* CONFIG_BCN_ICF */
  233. handled[0] |= BIT_TXBCN0ERR_MSK;
  234. }
  235. if (pHalData->IntArray[0] & BIT_BCNDERR0_MSK) {
  236. #ifdef CONFIG_BCN_ICF
  237. RTW_INFO("BIT_BCNDERR0_MSK isr!\n");
  238. #else /* !CONFIG_BCN_ICF */
  239. /* Release resource and re-transmit beacon to HW */
  240. struct tasklet_struct *bcn_tasklet;
  241. /* Modify for MI temporary,
  242. * this processor cannot apply to multi-ap
  243. */
  244. PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
  245. rtl8821ce_tx_isr(Adapter, BCN_QUEUE_INX);
  246. bcn_adapter->mlmepriv.update_bcn = _TRUE;
  247. bcn_tasklet = &bcn_adapter->recvpriv.irq_prepare_beacon_tasklet;
  248. tasklet_hi_schedule(bcn_tasklet);
  249. #endif /* CONFIG_BCN_ICF */
  250. handled[0] |= BIT_BCNDERR0_MSK;
  251. }
  252. if (pHalData->IntArray[0] & BIT_BCNDMAINT0_MSK) {
  253. struct tasklet_struct *bcn_tasklet;
  254. /* Modify for MI temporary,
  255. * this processor cannot apply to multi-ap
  256. */
  257. PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
  258. bcn_tasklet = &bcn_adapter->recvpriv.irq_prepare_beacon_tasklet;
  259. tasklet_hi_schedule(bcn_tasklet);
  260. handled[0] |= BIT_BCNDMAINT0_MSK;
  261. }
  262. }
  263. static void rtl8821ce_rx_handler(PADAPTER Adapter, u32 handled[])
  264. {
  265. PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
  266. if ((pHalData->IntArray[0] & (BIT_RXOK | BIT_RDU)) ||
  267. (pHalData->IntArray[1] & (BIT_FOVW | BIT_RXERR_INT))) {
  268. pHalData->IntrMask[0] &= (~(BIT_RXOK_MSK | BIT_RDU_MSK));
  269. pHalData->IntrMask[1] &= (~(BIT_FOVW_MSK | BIT_RXERR_MSK));
  270. rtw_write32(Adapter, REG_HIMR0, pHalData->IntrMask[0]);
  271. rtw_write32(Adapter, REG_HIMR1, pHalData->IntrMask[1]);
  272. tasklet_hi_schedule(&Adapter->recvpriv.recv_tasklet);
  273. handled[0] |= pHalData->IntArray[0] & (BIT_RXOK | BIT_RDU);
  274. handled[1] |= pHalData->IntArray[1] & (BIT_FOVW | BIT_RXERR_INT);
  275. }
  276. }
  277. static void rtl8821ce_tx_handler(PADAPTER Adapter, u32 events[], u32 handled[])
  278. {
  279. PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
  280. if (events[0] & BIT_MGTDOK_MSK) {
  281. rtl8821ce_tx_isr(Adapter, MGT_QUEUE_INX);
  282. handled[0] |= BIT_MGTDOK_MSK;
  283. }
  284. if (events[0] & BIT_HIGHDOK_MSK) {
  285. rtl8821ce_tx_isr(Adapter, HIGH_QUEUE_INX);
  286. handled[0] |= BIT_HIGHDOK_MSK;
  287. }
  288. if (events[0] & BIT_BKDOK_MSK) {
  289. rtl8821ce_tx_isr(Adapter, BK_QUEUE_INX);
  290. handled[0] |= BIT_BKDOK_MSK;
  291. }
  292. if (events[0] & BIT_BEDOK_MSK) {
  293. rtl8821ce_tx_isr(Adapter, BE_QUEUE_INX);
  294. handled[0] |= BIT_BEDOK_MSK;
  295. }
  296. if (events[0] & BIT_VIDOK_MSK) {
  297. rtl8821ce_tx_isr(Adapter, VI_QUEUE_INX);
  298. handled[0] |= BIT_VIDOK_MSK;
  299. }
  300. if (events[0] & BIT_VODOK_MSK) {
  301. rtl8821ce_tx_isr(Adapter, VO_QUEUE_INX);
  302. handled[0] |= BIT_VODOK_MSK;
  303. }
  304. }
  305. static void rtl8821ce_cmd_handler(PADAPTER Adapter, u32 handled[])
  306. {
  307. PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
  308. if (pHalData->IntArray[3] & BIT_SETH2CDOK_MASK) {
  309. rtl8821ce_tx_isr(Adapter, TXCMD_QUEUE_INX);
  310. handled[3] |= BIT_SETH2CDOK_MASK;
  311. }
  312. }
  313. static s32 rtl8821ce_interrupt(PADAPTER Adapter)
  314. {
  315. _irqL irqL;
  316. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
  317. struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
  318. struct xmit_priv *t_priv = &Adapter->xmitpriv;
  319. int ret = _SUCCESS;
  320. u32 handled[4] = {0};
  321. _enter_critical(&pdvobjpriv->irq_th_lock, &irqL);
  322. /* read ISR: 4/8bytes */
  323. if (rtl8821ce_InterruptRecognized(Adapter) == _FALSE) {
  324. ret = _FAIL;
  325. goto done;
  326. }
  327. /* <1> beacon related */
  328. rtl8821ce_bcn_handler(Adapter, handled);
  329. /* <2> Rx related */
  330. rtl8821ce_rx_handler(Adapter, handled);
  331. /* <3> Tx related */
  332. rtl8821ce_tx_handler(Adapter, pHalData->IntArray, handled);
  333. if (pHalData->IntArray[1] & BIT_TXFOVW) {
  334. /*if (printk_ratelimit())*/
  335. RTW_WARN("[TXFOVW]\n");
  336. handled[1] |= BIT_TXFOVW;
  337. }
  338. /* <4> Cmd related */
  339. rtl8821ce_cmd_handler(Adapter, handled);
  340. if ((pHalData->IntArray[0] & (~handled[0])) || (pHalData->IntArray[1] & (~handled[1])) || (pHalData->IntArray[3] & (~handled[3]))) {
  341. /*if (printk_ratelimit()) */
  342. {
  343. RTW_WARN("Unhandled ISR = %x, %x, %x\n",
  344. (pHalData->IntArray[0] & (~handled[0])),
  345. (pHalData->IntArray[1] & (~handled[1])),
  346. (pHalData->IntArray[3] & (~handled[3]))
  347. );
  348. }
  349. }
  350. done:
  351. _exit_critical(&pdvobjpriv->irq_th_lock, &irqL);
  352. return ret;
  353. }
  354. u32 rtl8821ce_init_bd(_adapter *padapter)
  355. {
  356. struct xmit_priv *t_priv = &padapter->xmitpriv;
  357. int i, ret = _SUCCESS;
  358. init_bd_ring_var(padapter);
  359. ret = rtl8821ce_init_rxbd_ring(padapter);
  360. if (ret == _FAIL)
  361. return ret;
  362. /* general process for other queue */
  363. for (i = 0; i < PCI_MAX_TX_QUEUE_COUNT; i++) {
  364. ret = rtl8821ce_init_txbd_ring(padapter, i,
  365. t_priv->txringcount[i]);
  366. if (ret == _FAIL)
  367. goto err_free_rings;
  368. }
  369. return ret;
  370. err_free_rings:
  371. rtl8821ce_free_rxbd_ring(padapter);
  372. for (i = 0; i < PCI_MAX_TX_QUEUE_COUNT; i++)
  373. if (t_priv->tx_ring[i].buf_desc)
  374. rtl8821ce_free_txbd_ring(padapter, i);
  375. return ret;
  376. }
  377. u32 rtl8821ce_free_bd(_adapter *padapter)
  378. {
  379. struct xmit_priv *t_priv = &padapter->xmitpriv;
  380. u32 i;
  381. /* free rxbd rings */
  382. rtl8821ce_free_rxbd_ring(padapter);
  383. /* free txbd rings */
  384. for (i = 0; i < HW_QUEUE_ENTRY; i++)
  385. rtl8821ce_free_txbd_ring(padapter, i);
  386. return _SUCCESS;
  387. }
  388. static u16
  389. hal_mdio_read_8821ce(PADAPTER Adapter, u8 Addr)
  390. {
  391. u2Byte ret = 0;
  392. u1Byte tmpU1b = 0, count = 0;
  393. rtw_write8(Adapter, REG_PCIE_MIX_CFG_8821C, Addr | BIT6);
  394. tmpU1b = rtw_read8(Adapter, REG_PCIE_MIX_CFG_8821C) & BIT6;
  395. count = 0;
  396. while (tmpU1b && count < 20) {
  397. rtw_udelay_os(10);
  398. tmpU1b = rtw_read8(Adapter, REG_PCIE_MIX_CFG_8821C) & BIT6;
  399. count++;
  400. }
  401. if (tmpU1b == 0)
  402. ret = rtw_read16(Adapter, REG_MDIO_V1_8821C);
  403. return ret;
  404. }
  405. static VOID
  406. hal_mdio_write_8821ce(PADAPTER Adapter, u8 Addr, u16 Data)
  407. {
  408. u1Byte tmpU1b = 0, count = 0;
  409. rtw_write16(Adapter, REG_MDIO_V1_8821C, Data);
  410. rtw_write8(Adapter, REG_PCIE_MIX_CFG_8821C, Addr | BIT5);
  411. tmpU1b = rtw_read8(Adapter, REG_PCIE_MIX_CFG_8821C) & BIT5;
  412. count = 0;
  413. while (tmpU1b && count < 20) {
  414. rtw_udelay_os(10);
  415. tmpU1b = rtw_read8(Adapter, REG_PCIE_MIX_CFG_8821C) & BIT5;
  416. count++;
  417. }
  418. }
  419. static void hal_dbi_write_8821ce(PADAPTER Adapter, u16 Addr, u8 Data)
  420. {
  421. u1Byte tmpU1b = 0, count = 0;
  422. u2Byte WriteAddr = 0, Remainder = Addr % 4;
  423. /* Write DBI 1Byte Data */
  424. WriteAddr = REG_DBI_WDATA_V1_8821C + Remainder;
  425. rtw_write8(Adapter, WriteAddr, Data);
  426. /* Write DBI 2Byte Address & Write Enable */
  427. WriteAddr = (Addr & 0xfffc) | (BIT0 << (Remainder + 12));
  428. rtw_write16(Adapter, REG_DBI_FLAG_V1_8821C, WriteAddr);
  429. /* Write DBI Write Flag */
  430. rtw_write8(Adapter, REG_DBI_FLAG_V1_8821C + 2, 0x1);
  431. tmpU1b = rtw_read8(Adapter, REG_DBI_FLAG_V1_8821C + 2);
  432. count = 0;
  433. while (tmpU1b && count < 20) {
  434. rtw_udelay_os(10);
  435. tmpU1b = rtw_read8(Adapter, REG_DBI_FLAG_V1_8821C + 2);
  436. count++;
  437. }
  438. }
  439. static u8 hal_dbi_read_8821ce(PADAPTER Adapter, u16 Addr)
  440. {
  441. u16 ReadAddr = Addr & 0xfffc;
  442. u8 ret = 0, tmpU1b = 0, count = 0;
  443. rtw_write16(Adapter, REG_DBI_FLAG_V1_8821C, ReadAddr);
  444. rtw_write8(Adapter, REG_DBI_FLAG_V1_8821C + 2, 0x2);
  445. tmpU1b = rtw_read8(Adapter, REG_DBI_FLAG_V1_8821C + 2);
  446. count = 0;
  447. while (tmpU1b && count < 20) {
  448. rtw_udelay_os(10);
  449. tmpU1b = rtw_read8(Adapter, REG_DBI_FLAG_V1_8821C + 2);
  450. count++;
  451. }
  452. if (tmpU1b == 0) {
  453. ReadAddr = REG_DBI_RDATA_V1_8821C + Addr % 4;
  454. ret = rtw_read8(Adapter, ReadAddr);
  455. }
  456. return ret;
  457. }
  458. /*
  459. * Description:
  460. * Query setting of specified variable.
  461. */
  462. static u8 gethaldefvar(PADAPTER padapter, HAL_DEF_VARIABLE eVariable, PVOID pValue)
  463. {
  464. HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
  465. u8 bResult = _SUCCESS;
  466. switch (eVariable) {
  467. case HAL_DEF_MAX_RECVBUF_SZ:
  468. *((u32 *)pValue) = MAX_RECVBUF_SZ;
  469. break;
  470. case HW_VAR_MAX_RX_AMPDU_FACTOR:
  471. *(HT_CAP_AMPDU_FACTOR *)pValue = MAX_AMPDU_FACTOR_64K;
  472. break;
  473. default:
  474. bResult = rtl8821c_gethaldefvar(padapter, eVariable, pValue);
  475. break;
  476. }
  477. return bResult;
  478. }
  479. /*
  480. * Description:
  481. * Change default setting of specified variable.
  482. */
  483. static u8 sethaldefvar(PADAPTER adapter, HAL_DEF_VARIABLE eVariable, void *pval)
  484. {
  485. PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
  486. u8 bResult = _SUCCESS;
  487. switch (eVariable) {
  488. default:
  489. bResult = rtl8821c_sethaldefvar(adapter, eVariable, pval);
  490. break;
  491. }
  492. return bResult;
  493. }
  494. /*
  495. * If variable not handled here,
  496. * some variables will be processed in rtl8821c_sethwreg()
  497. */
  498. static void sethwreg(PADAPTER adapter, u8 variable, u8 *val)
  499. {
  500. PHAL_DATA_TYPE hal;
  501. u8 val8;
  502. hal = GET_HAL_DATA(adapter);
  503. switch (variable) {
  504. case HW_VAR_DBI:
  505. {
  506. u16 *pCmd;
  507. pCmd = (u16 *)val;
  508. hal_dbi_write_8821ce(adapter, pCmd[0], (u8)pCmd[1]);
  509. break;
  510. }
  511. case HW_VAR_MDIO:
  512. {
  513. u16 *pCmd;
  514. pCmd = (u16 *)val;
  515. hal_mdio_write_8821ce(adapter, (u8)pCmd[0], pCmd[1]);
  516. break;
  517. }
  518. default:
  519. rtl8821c_sethwreg(adapter, variable, val);
  520. break;
  521. }
  522. }
  523. /*
  524. * If variable not handled here,
  525. * some variables will be processed in GetHwReg8723B()
  526. */
  527. static void gethwreg(PADAPTER adapter, u8 variable, u8 *val)
  528. {
  529. PHAL_DATA_TYPE hal;
  530. hal = GET_HAL_DATA(adapter);
  531. switch (variable) {
  532. case HW_VAR_DBI:
  533. *val = hal_dbi_read_8821ce(adapter, *((u16 *)(val)));
  534. break;
  535. case HW_VAR_MDIO:
  536. *((u16 *)(val)) = hal_mdio_read_8821ce(adapter, *val);
  537. break;
  538. case HW_VAR_L1OFF_NIC_SUPPORT:
  539. {
  540. u8 l1off;
  541. l1off = hal_dbi_read_8821ce(adapter, 0x168);
  542. if (l1off & (BIT2|BIT3))
  543. *val = _TRUE;
  544. else
  545. *val = _FALSE;
  546. }
  547. break;
  548. case HW_VAR_L1OFF_CAPABILITY:
  549. {
  550. u8 l1off;
  551. l1off = hal_dbi_read_8821ce(adapter, 0x164);
  552. if (l1off & (BIT2|BIT3))
  553. *val = _TRUE;
  554. else
  555. *val = _FALSE;
  556. }
  557. break;
  558. default:
  559. rtl8821c_gethwreg(adapter, variable, val);
  560. break;
  561. }
  562. }
  563. void rtl8821ce_set_hal_ops(PADAPTER padapter)
  564. {
  565. struct hal_ops *ops;
  566. int err;
  567. err = rtl8821ce_halmac_init_adapter(padapter);
  568. if (err) {
  569. RTW_INFO("%s: [ERROR]HALMAC initialize FAIL!\n", __func__);
  570. return;
  571. }
  572. rtl8821c_set_hal_ops(padapter);
  573. ops = &padapter->hal_func;
  574. ops->hal_init = rtl8821ce_hal_init;
  575. ops->hal_deinit = rtl8821ce_hal_deinit;
  576. ops->inirp_init = rtl8821ce_init_bd;
  577. ops->inirp_deinit = rtl8821ce_free_bd;
  578. ops->irp_reset = rtl8821ce_reset_bd;
  579. ops->init_xmit_priv = rtl8821ce_init_xmit_priv;
  580. ops->free_xmit_priv = rtl8821ce_free_xmit_priv;
  581. ops->init_recv_priv = rtl8821ce_init_recv_priv;
  582. ops->free_recv_priv = rtl8821ce_free_recv_priv;
  583. #ifdef CONFIG_SW_LED
  584. ops->InitSwLeds = rtl8821ce_InitSwLeds;
  585. ops->DeInitSwLeds = rtl8821ce_DeInitSwLeds;
  586. #else /* case of hw led or no led */
  587. ops->InitSwLeds = NULL;
  588. ops->DeInitSwLeds = NULL;
  589. #endif
  590. ops->init_default_value = rtl8821ce_init_default_value;
  591. ops->intf_chip_configure = intf_chip_configure;
  592. ops->read_adapter_info = read_adapter_info;
  593. ops->enable_interrupt = rtl8821ce_enable_interrupt;
  594. ops->disable_interrupt = rtl8821ce_disable_interrupt;
  595. ops->interrupt_handler = rtl8821ce_interrupt;
  596. /*
  597. * ops->check_ips_status = check_ips_status;
  598. */
  599. ops->clear_interrupt = rtl8821ce_clear_interrupt;
  600. #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) ||\
  601. defined(CONFIG_PCI_HCI)
  602. /*
  603. * ops->clear_interrupt = clear_interrupt_all;
  604. */
  605. #endif
  606. ops->set_hw_reg_handler = sethwreg;
  607. ops->GetHwRegHandler = gethwreg;
  608. ops->get_hal_def_var_handler = gethaldefvar;
  609. ops->SetHalDefVarHandler = sethaldefvar;
  610. ops->hal_xmit = rtl8821ce_hal_xmit;
  611. ops->mgnt_xmit = rtl8821ce_mgnt_xmit;
  612. ops->hal_xmitframe_enqueue = rtl8821ce_hal_xmitframe_enqueue;
  613. #ifdef CONFIG_HOSTAPD_MLME
  614. ops->hostap_mgnt_xmit_entry = rtl8821ce_hostap_mgnt_xmit_entry;
  615. #endif
  616. #ifdef CONFIG_XMIT_THREAD_MODE
  617. /* TODO */
  618. ops->xmit_thread_handler = rtl8821ce_xmit_buf_handler;
  619. #endif
  620. ops->hal_set_l1ssbackdoor_handler = rtw_pci_aspm_config_l1off_general;
  621. }