1 /******************************************************************************
3 * Copyright(c) 2016 - 2017 Realtek Corporation.
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.
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
14 *****************************************************************************/
16 #define _HCI_OPS_OS_C_
18 #include <drv_types.h> /* PADAPTER, basic_types.h and etc. */
19 #include <hal_data.h> /* HAL_DATA_TYPE, GET_HAL_DATA() and etc. */
20 #include <hal_intf.h> /* struct hal_ops */
21 #include "../rtl8821c.h"
22 #include "rtl8821ce.h"
24 static void init_bd_ring_var(_adapter *padapter)
26 struct recv_priv *r_priv = &padapter->recvpriv;
27 struct xmit_priv *t_priv = &padapter->xmitpriv;
30 for (i = 0; i < HW_QUEUE_ENTRY; i++)
31 t_priv->txringcount[i] = TX_BD_NUM_8821CE;
34 * we just alloc 2 desc for beacon queue,
35 * because we just need first desc in hw beacon.
37 t_priv->txringcount[BCN_QUEUE_INX] = TX_BD_NUM_8821CE_BCN;
38 t_priv->txringcount[TXCMD_QUEUE_INX] = TX_BD_NUM_8821CE_CMD;
41 * BE queue need more descriptor for performance consideration
42 * or, No more tx desc will happen, and may cause mac80211 mem leakage.
44 r_priv->rxbuffersize = MAX_RECVBUF_SZ;
45 r_priv->rxringcount = PCI_MAX_RX_COUNT;
48 static void rtl8821ce_reset_bd(_adapter *padapter)
51 struct xmit_priv *t_priv = &padapter->xmitpriv;
52 struct recv_priv *r_priv = &padapter->recvpriv;
53 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
54 struct xmit_buf *pxmitbuf = NULL;
59 for (rx_queue_idx = 0; rx_queue_idx < 1; rx_queue_idx++) {
60 if (r_priv->rx_ring[rx_queue_idx].buf_desc) {
62 for (i = 0; i < r_priv->rxringcount; i++) {
64 &r_priv->rx_ring[rx_queue_idx].buf_desc[i];
66 r_priv->rx_ring[rx_queue_idx].idx = 0;
70 _enter_critical(&pdvobjpriv->irq_th_lock, &irqL);
71 for (i = 0; i < PCI_MAX_TX_QUEUE_COUNT; i++) {
72 if (t_priv->tx_ring[i].buf_desc) {
73 struct rtw_tx_ring *ring = &t_priv->tx_ring[i];
76 tx_bd = (u8 *)(&ring->buf_desc[ring->idx]);
77 SET_TX_BD_OWN(tx_bd, 0);
79 if (i != BCN_QUEUE_INX)
81 (ring->idx + 1) % ring->entries;
83 pxmitbuf = rtl8821ce_dequeue_xmitbuf(ring);
85 mapping = GET_TX_BD_PHYSICAL_ADDR0_LOW(tx_bd);
86 #ifdef CONFIG_64BIT_DMA
87 mapping |= (dma_addr_t)GET_TX_BD_PHYSICAL_ADDR0_HIGH(tx_bd) << 32;
89 pci_unmap_single(pdvobjpriv->ppcidev,
91 pxmitbuf->len, PCI_DMA_TODEVICE);
92 rtw_free_xmitbuf(t_priv, pxmitbuf);
94 RTW_INFO("%s(): qlen(%d) is not zero, but have xmitbuf in pending queue\n",
95 __func__, ring->qlen);
102 _exit_critical(&pdvobjpriv->irq_th_lock, &irqL);
105 static void intf_chip_configure(PADAPTER padapter)
107 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
108 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
109 struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(pdvobjpriv);
111 /* close ASPM for AMD defaultly */
112 pdvobjpriv->const_amdpci_aspm = 0;
115 /* 0 - Disable ASPM, 1 - Enable ASPM without Clock Req, */
116 /* 2 - Enable ASPM with Clock Req, 3- Alwyas Enable ASPM with Clock Req, */
117 /* 4- Always Enable ASPM without Clock Req. */
118 /* set default to rtl8188ee:3 RTL8192E:2 */
119 pdvobjpriv->const_pci_aspm = 0;
121 /* Setting for PCI-E device */
122 pdvobjpriv->const_devicepci_aspm_setting = 0x03;
124 /* Setting for PCI-E bridge */
125 pdvobjpriv->const_hostpci_aspm_setting = 0x03;
127 /* In Hw/Sw Radio Off situation. */
128 /* 0 - Default, 1 - From ASPM setting without low Mac Pwr, */
129 /* 2 - From ASPM setting with low Mac Pwr, 3 - Bus D3 */
130 /* set default to RTL8192CE:0 RTL8192SE:2 */
131 pdvobjpriv->const_hwsw_rfoff_d3 = 0;
133 /* This setting works for those device with backdoor ASPM setting such as EPHY setting. */
134 /* 0: Not support ASPM, 1: Support ASPM, 2: According to chipset. */
135 pdvobjpriv->const_support_pciaspm = 1;
137 pwrpriv->reg_rfoff = 0;
138 pwrpriv->rfoff_reason = 0;
140 pHalData->bL1OffSupport = _FALSE;
145 * Collect all hardware information, fill "HAL_DATA_TYPE".
146 * Sometimes this would be used to read MAC address.
147 * This function will do
148 * 1. Read Efuse/EEPROM to initialize
149 * 2. Read registers to initialize
150 * 3. Other vaiables initialization
152 static u8 read_adapter_info(PADAPTER padapter)
157 * 1. Read Efuse/EEPROM to initialize
159 if (rtl8821c_read_efuse(padapter) != _SUCCESS)
163 * 2. Read registers to initialize
167 * 3. Other Initialization
176 static BOOLEAN rtl8821ce_InterruptRecognized(PADAPTER Adapter)
178 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
179 BOOLEAN bRecognized = _FALSE;
181 /* 2013.11.18 Glayrainx suggests that turn off IMR and
182 * restore after cleaning ISR.
184 rtw_write32(Adapter, REG_HIMR0, 0);
185 rtw_write32(Adapter, REG_HIMR1, 0);
186 rtw_write32(Adapter, REG_HIMR3, 0);
188 pHalData->IntArray[0] = rtw_read32(Adapter, REG_HISR0);
189 pHalData->IntArray[0] &= pHalData->IntrMask[0];
190 rtw_write32(Adapter, REG_HISR0, pHalData->IntArray[0]);
192 /* For HISR extension. Added by tynli. 2009.10.07. */
193 pHalData->IntArray[1] = rtw_read32(Adapter, REG_HISR1);
194 pHalData->IntArray[1] &= pHalData->IntrMask[1];
195 rtw_write32(Adapter, REG_HISR1, pHalData->IntArray[1]);
197 /* for H2C cmd queue */
198 pHalData->IntArray[3] = rtw_read32(Adapter, REG_HISR3);
199 pHalData->IntArray[3] &= pHalData->IntrMask[3];
200 rtw_write32(Adapter, REG_HISR3, pHalData->IntArray[3]);
202 if (((pHalData->IntArray[0]) & pHalData->IntrMask[0]) != 0 ||
203 ((pHalData->IntArray[1]) & pHalData->IntrMask[1]) != 0)
207 rtw_write32(Adapter, REG_HIMR0, pHalData->IntrMask[0] & 0xFFFFFFFF);
208 rtw_write32(Adapter, REG_HIMR1, pHalData->IntrMask[1] & 0xFFFFFFFF);
209 rtw_write32(Adapter, REG_HIMR3, pHalData->IntrMask[3] & 0xFFFFFFFF);
214 static VOID DisableInterrupt8821ce(PADAPTER Adapter)
216 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
218 rtw_write32(Adapter, REG_HIMR0, 0x0);
219 rtw_write32(Adapter, REG_HIMR1, 0x0);
220 rtw_write32(Adapter, REG_HIMR3, 0x0);
221 pdvobjpriv->irq_enabled = 0;
224 static VOID rtl8821ce_enable_interrupt(PADAPTER Adapter)
226 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
227 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
229 pdvobjpriv->irq_enabled = 1;
231 rtw_write32(Adapter, REG_HIMR0, pHalData->IntrMask[0] & 0xFFFFFFFF);
232 rtw_write32(Adapter, REG_HIMR1, pHalData->IntrMask[1] & 0xFFFFFFFF);
233 rtw_write32(Adapter, REG_HIMR3, pHalData->IntrMask[3] & 0xFFFFFFFF);
237 static VOID rtl8821ce_clear_interrupt(PADAPTER Adapter)
240 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
242 u32b = rtw_read32(Adapter, REG_HISR0_8821C);
243 rtw_write32(Adapter, REG_HISR0_8821C, u32b);
244 pHalData->IntArray[0] = 0;
246 u32b = rtw_read32(Adapter, REG_HISR1_8821C);
247 rtw_write32(Adapter, REG_HISR1_8821C, u32b);
248 pHalData->IntArray[1] = 0;
251 static VOID rtl8821ce_disable_interrupt(PADAPTER Adapter)
253 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
255 rtw_write32(Adapter, REG_HIMR0, 0x0);
256 rtw_write32(Adapter, REG_HIMR1, 0x0); /* by tynli */
257 pdvobjpriv->irq_enabled = 0;
260 VOID UpdateInterruptMask8821CE(PADAPTER Adapter, u32 AddMSR, u32 AddMSR1,
261 u32 RemoveMSR, u32 RemoveMSR1)
263 PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
265 DisableInterrupt8821ce(Adapter);
268 pHalData->IntrMask[0] |= AddMSR;
271 pHalData->IntrMask[1] |= AddMSR1;
274 pHalData->IntrMask[0] &= (~RemoveMSR);
277 pHalData->IntrMask[1] &= (~RemoveMSR1);
281 pHalData->IntrMask[3] &= (~RemoveMSR3);
284 rtl8821ce_enable_interrupt(Adapter);
287 static void rtl8821ce_bcn_handler(PADAPTER Adapter, u32 handled[])
289 PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
291 if (pHalData->IntArray[0] & BIT_TXBCN0OK_MSK) {
292 #ifdef CONFIG_BCN_ICF
295 /* Modify for MI temporary,
296 * this processor cannot apply to multi-ap
298 PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
300 if (bcn_adapter->xmitpriv.beaconDMAing) {
301 bcn_adapter->xmitpriv.beaconDMAing = _FAIL;
302 rtl8821ce_tx_isr(Adapter, BCN_QUEUE_INX);
304 #endif /* CONFIG_BCN_ICF */
305 handled[0] |= BIT_TXBCN0OK_MSK;
308 if (pHalData->IntArray[0] & BIT_TXBCN0ERR_MSK) {
309 #ifdef CONFIG_BCN_ICF
310 RTW_INFO("IMR_TXBCN0ERR isr!\n");
311 #else /* !CONFIG_BCN_ICF */
312 /* Modify for MI temporary,
313 * this processor cannot apply to multi-ap
315 PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
317 if (bcn_adapter->xmitpriv.beaconDMAing) {
318 bcn_adapter->xmitpriv.beaconDMAing = _FAIL;
319 rtl8821ce_tx_isr(Adapter, BCN_QUEUE_INX);
321 #endif /* CONFIG_BCN_ICF */
322 handled[0] |= BIT_TXBCN0ERR_MSK;
325 if (pHalData->IntArray[0] & BIT_BCNDERR0_MSK) {
326 #ifdef CONFIG_BCN_ICF
327 RTW_INFO("BIT_BCNDERR0_MSK isr!\n");
328 #else /* !CONFIG_BCN_ICF */
329 /* Release resource and re-transmit beacon to HW */
330 struct tasklet_struct *bcn_tasklet;
331 /* Modify for MI temporary,
332 * this processor cannot apply to multi-ap
334 PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
336 rtl8821ce_tx_isr(Adapter, BCN_QUEUE_INX);
337 bcn_adapter->mlmepriv.update_bcn = _TRUE;
338 bcn_tasklet = &bcn_adapter->recvpriv.irq_prepare_beacon_tasklet;
339 tasklet_hi_schedule(bcn_tasklet);
340 #endif /* CONFIG_BCN_ICF */
341 handled[0] |= BIT_BCNDERR0_MSK;
344 if (pHalData->IntArray[0] & BIT_BCNDMAINT0_MSK) {
345 struct tasklet_struct *bcn_tasklet;
346 /* Modify for MI temporary,
347 * this processor cannot apply to multi-ap
349 PADAPTER bcn_adapter = rtw_mi_get_ap_adapter(Adapter);
351 bcn_tasklet = &bcn_adapter->recvpriv.irq_prepare_beacon_tasklet;
352 tasklet_hi_schedule(bcn_tasklet);
353 handled[0] |= BIT_BCNDMAINT0_MSK;
357 static void rtl8821ce_rx_handler(PADAPTER Adapter, u32 handled[])
359 PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
361 if ((pHalData->IntArray[0] & (BIT_RXOK | BIT_RDU)) ||
362 (pHalData->IntArray[1] & (BIT_FOVW | BIT_RXERR_INT))) {
363 pHalData->IntrMask[0] &= (~(BIT_RXOK_MSK | BIT_RDU_MSK));
364 pHalData->IntrMask[1] &= (~(BIT_FOVW_MSK | BIT_RXERR_MSK));
365 rtw_write32(Adapter, REG_HIMR0, pHalData->IntrMask[0]);
366 rtw_write32(Adapter, REG_HIMR1, pHalData->IntrMask[1]);
367 tasklet_hi_schedule(&Adapter->recvpriv.recv_tasklet);
368 handled[0] |= pHalData->IntArray[0] & (BIT_RXOK | BIT_RDU);
369 handled[1] |= pHalData->IntArray[1] & (BIT_FOVW | BIT_RXERR_INT);
373 static void rtl8821ce_tx_handler(PADAPTER Adapter, u32 events[], u32 handled[])
375 PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
377 if (events[0] & BIT_MGTDOK_MSK) {
378 rtl8821ce_tx_isr(Adapter, MGT_QUEUE_INX);
379 handled[0] |= BIT_MGTDOK_MSK;
382 if (events[0] & BIT_HIGHDOK_MSK) {
383 rtl8821ce_tx_isr(Adapter, HIGH_QUEUE_INX);
384 handled[0] |= BIT_HIGHDOK_MSK;
387 if (events[0] & BIT_BKDOK_MSK) {
388 rtl8821ce_tx_isr(Adapter, BK_QUEUE_INX);
389 handled[0] |= BIT_BKDOK_MSK;
392 if (events[0] & BIT_BEDOK_MSK) {
393 rtl8821ce_tx_isr(Adapter, BE_QUEUE_INX);
394 handled[0] |= BIT_BEDOK_MSK;
397 if (events[0] & BIT_VIDOK_MSK) {
398 rtl8821ce_tx_isr(Adapter, VI_QUEUE_INX);
399 handled[0] |= BIT_VIDOK_MSK;
402 if (events[0] & BIT_VODOK_MSK) {
403 rtl8821ce_tx_isr(Adapter, VO_QUEUE_INX);
404 handled[0] |= BIT_VODOK_MSK;
408 static void rtl8821ce_cmd_handler(PADAPTER Adapter, u32 handled[])
410 PHAL_DATA_TYPE pHalData = GET_HAL_DATA(Adapter);
412 if (pHalData->IntArray[3] & BIT_SETH2CDOK_MASK) {
413 rtl8821ce_tx_isr(Adapter, TXCMD_QUEUE_INX);
414 handled[3] |= BIT_SETH2CDOK_MASK;
418 static s32 rtl8821ce_interrupt(PADAPTER Adapter)
421 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(Adapter);
422 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(Adapter);
423 struct xmit_priv *t_priv = &Adapter->xmitpriv;
425 u32 handled[4] = {0};
427 _enter_critical(&pdvobjpriv->irq_th_lock, &irqL);
429 /* read ISR: 4/8bytes */
430 if (rtl8821ce_InterruptRecognized(Adapter) == _FALSE) {
435 /* <1> beacon related */
436 rtl8821ce_bcn_handler(Adapter, handled);
439 rtl8821ce_rx_handler(Adapter, handled);
442 rtl8821ce_tx_handler(Adapter, pHalData->IntArray, handled);
444 if (pHalData->IntArray[1] & BIT_TXFOVW) {
445 /*if (printk_ratelimit())*/
446 RTW_WARN("[TXFOVW]\n");
447 handled[1] |= BIT_TXFOVW;
450 if (pHalData->IntArray[1] & BIT_PRETXERR_HANDLE_ISR) {
451 RTW_ERR("[PRE-TX HANG]\n");
452 handled[1] |= BIT_PRETXERR_HANDLE_ISR;
455 /* <4> Cmd related */
456 rtl8821ce_cmd_handler(Adapter, handled);
458 #ifdef CONFIG_LPS_LCLK
459 if (pHalData->IntArray[0] & BIT_CPWM) {
460 struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(Adapter);
462 _set_workitem(&(pwrpriv->cpwm_event));
463 handled[0] |= BIT_CPWM;
467 if ((pHalData->IntArray[0] & (~handled[0])) || (pHalData->IntArray[1] & (~handled[1])) || (pHalData->IntArray[3] & (~handled[3]))) {
468 /*if (printk_ratelimit()) */
470 RTW_WARN("Unhandled ISR = %x, %x, %x\n",
471 (pHalData->IntArray[0] & (~handled[0])),
472 (pHalData->IntArray[1] & (~handled[1])),
473 (pHalData->IntArray[3] & (~handled[3]))
478 _exit_critical(&pdvobjpriv->irq_th_lock, &irqL);
482 u32 rtl8821ce_init_bd(_adapter *padapter)
484 struct xmit_priv *t_priv = &padapter->xmitpriv;
485 int i, ret = _SUCCESS;
487 init_bd_ring_var(padapter);
488 ret = rtl8821ce_init_rxbd_ring(padapter);
493 /* general process for other queue */
494 for (i = 0; i < PCI_MAX_TX_QUEUE_COUNT; i++) {
495 ret = rtl8821ce_init_txbd_ring(padapter, i,
496 t_priv->txringcount[i]);
505 rtl8821ce_free_rxbd_ring(padapter);
507 for (i = 0; i < PCI_MAX_TX_QUEUE_COUNT; i++)
508 if (t_priv->tx_ring[i].buf_desc)
509 rtl8821ce_free_txbd_ring(padapter, i);
515 u32 rtl8821ce_free_bd(_adapter *padapter)
517 struct xmit_priv *t_priv = &padapter->xmitpriv;
521 /* free rxbd rings */
522 rtl8821ce_free_rxbd_ring(padapter);
524 /* free txbd rings */
525 for (i = 0; i < HW_QUEUE_ENTRY; i++)
526 rtl8821ce_free_txbd_ring(padapter, i);
534 hal_mdio_read_8821ce(PADAPTER Adapter, u8 Addr)
537 u1Byte tmpU1b = 0, count = 0;
539 rtw_write8(Adapter, REG_PCIE_MIX_CFG_8821C, Addr | BIT6);
540 tmpU1b = rtw_read8(Adapter, REG_PCIE_MIX_CFG_8821C) & BIT6;
542 while (tmpU1b && count < 20) {
544 tmpU1b = rtw_read8(Adapter, REG_PCIE_MIX_CFG_8821C) & BIT6;
548 ret = rtw_read16(Adapter, REG_MDIO_V1_8821C);
555 hal_mdio_write_8821ce(PADAPTER Adapter, u8 Addr, u16 Data)
557 u1Byte tmpU1b = 0, count = 0;
559 rtw_write16(Adapter, REG_MDIO_V1_8821C, Data);
560 rtw_write8(Adapter, REG_PCIE_MIX_CFG_8821C, Addr | BIT5);
561 tmpU1b = rtw_read8(Adapter, REG_PCIE_MIX_CFG_8821C) & BIT5;
563 while (tmpU1b && count < 20) {
565 tmpU1b = rtw_read8(Adapter, REG_PCIE_MIX_CFG_8821C) & BIT5;
571 static void hal_dbi_write_8821ce(PADAPTER Adapter, u16 Addr, u8 Data)
573 u1Byte tmpU1b = 0, count = 0;
574 u2Byte WriteAddr = 0, Remainder = Addr % 4;
576 /* Write DBI 1Byte Data */
577 WriteAddr = REG_DBI_WDATA_V1_8821C + Remainder;
578 rtw_write8(Adapter, WriteAddr, Data);
580 /* Write DBI 2Byte Address & Write Enable */
581 WriteAddr = (Addr & 0xfffc) | (BIT0 << (Remainder + 12));
582 rtw_write16(Adapter, REG_DBI_FLAG_V1_8821C, WriteAddr);
584 /* Write DBI Write Flag */
585 rtw_write8(Adapter, REG_DBI_FLAG_V1_8821C + 2, 0x1);
587 tmpU1b = rtw_read8(Adapter, REG_DBI_FLAG_V1_8821C + 2);
589 while (tmpU1b && count < 20) {
591 tmpU1b = rtw_read8(Adapter, REG_DBI_FLAG_V1_8821C + 2);
596 static u8 hal_dbi_read_8821ce(PADAPTER Adapter, u16 Addr)
598 u16 ReadAddr = Addr & 0xfffc;
599 u8 ret = 0, tmpU1b = 0, count = 0;
601 rtw_write16(Adapter, REG_DBI_FLAG_V1_8821C, ReadAddr);
602 rtw_write8(Adapter, REG_DBI_FLAG_V1_8821C + 2, 0x2);
603 tmpU1b = rtw_read8(Adapter, REG_DBI_FLAG_V1_8821C + 2);
605 while (tmpU1b && count < 20) {
607 tmpU1b = rtw_read8(Adapter, REG_DBI_FLAG_V1_8821C + 2);
611 ReadAddr = REG_DBI_RDATA_V1_8821C + Addr % 4;
612 ret = rtw_read8(Adapter, ReadAddr);
620 * Query setting of specified variable.
622 static u8 gethaldefvar(PADAPTER padapter, HAL_DEF_VARIABLE eVariable, PVOID pValue)
624 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
625 u8 bResult = _SUCCESS;
629 case HAL_DEF_MAX_RECVBUF_SZ:
630 *((u32 *)pValue) = MAX_RECVBUF_SZ;
633 case HW_VAR_MAX_RX_AMPDU_FACTOR:
634 *(HT_CAP_AMPDU_FACTOR *)pValue = MAX_AMPDU_FACTOR_64K;
637 bResult = rtl8821c_gethaldefvar(padapter, eVariable, pValue);
646 * Change default setting of specified variable.
648 static u8 sethaldefvar(PADAPTER adapter, HAL_DEF_VARIABLE eVariable, void *pval)
650 PHAL_DATA_TYPE hal = GET_HAL_DATA(adapter);
651 u8 bResult = _SUCCESS;
655 bResult = rtl8821c_sethaldefvar(adapter, eVariable, pval);
663 * If variable not handled here,
664 * some variables will be processed in rtl8821c_sethwreg()
666 static u8 sethwreg(PADAPTER adapter, u8 variable, u8 *val)
673 hal = GET_HAL_DATA(adapter);
682 hal_dbi_write_8821ce(adapter, pCmd[0], (u8)pCmd[1]);
690 hal_mdio_write_8821ce(adapter, (u8)pCmd[0], pCmd[1]);
693 #ifdef CONFIG_LPS_LCLK
694 case HW_VAR_SET_RPWM:
696 u8 ps_state = *((u8 *)val);
697 /* rpwm value only use BIT0(clock bit) ,BIT6(Ack bit), and BIT7(Toggle bit) for 88e. */
698 /* BIT0 value - 1: 32k, 0:40MHz. */
699 /* BIT6 value - 1: report cpwm value after success set, 0:do not report. */
700 /* BIT7 value - Toggle bit change. */
701 /* modify by Thomas. 2012/4/2. */
702 ps_state = ps_state & 0xC1;
703 /* RTW_INFO("##### Change RPWM value to = %x for switch clk #####\n",ps_state); */
704 rtw_write8(adapter, REG_PCIE_HRPWM1_V1_8821C, ps_state);
710 ret = rtl8821c_sethwreg(adapter, variable, val);
718 * If variable not handled here,
719 * some variables will be processed in GetHwReg8723B()
721 static void gethwreg(PADAPTER adapter, u8 variable, u8 *val)
726 hal = GET_HAL_DATA(adapter);
729 *val = hal_dbi_read_8821ce(adapter, *((u16 *)(val)));
732 *((u16 *)(val)) = hal_mdio_read_8821ce(adapter, *val);
734 case HW_VAR_L1OFF_NIC_SUPPORT:
738 l1off = hal_dbi_read_8821ce(adapter, 0x168);
739 if (l1off & (BIT2|BIT3))
745 case HW_VAR_L1OFF_CAPABILITY:
749 l1off = hal_dbi_read_8821ce(adapter, 0x164);
750 if (l1off & (BIT2|BIT3))
757 #ifdef CONFIG_LPS_LCLK
759 *val = rtw_read8(adapter, REG_PCIE_HCPWM1_V1_8821C);
764 rtl8821c_gethwreg(adapter, variable, val);
769 void rtl8821ce_set_hal_ops(PADAPTER padapter)
774 err = rtl8821ce_halmac_init_adapter(padapter);
776 RTW_INFO("%s: [ERROR]HALMAC initialize FAIL!\n", __func__);
780 rtl8821c_set_hal_ops(padapter);
782 ops = &padapter->hal_func;
784 ops->hal_init = rtl8821ce_hal_init;
785 ops->hal_deinit = rtl8821ce_hal_deinit;
786 ops->inirp_init = rtl8821ce_init_bd;
787 ops->inirp_deinit = rtl8821ce_free_bd;
788 ops->irp_reset = rtl8821ce_reset_bd;
789 ops->init_xmit_priv = rtl8821ce_init_xmit_priv;
790 ops->free_xmit_priv = rtl8821ce_free_xmit_priv;
791 ops->init_recv_priv = rtl8821ce_init_recv_priv;
792 ops->free_recv_priv = rtl8821ce_free_recv_priv;
794 #ifdef CONFIG_RTW_SW_LED
795 ops->InitSwLeds = rtl8821ce_InitSwLeds;
796 ops->DeInitSwLeds = rtl8821ce_DeInitSwLeds;
799 ops->init_default_value = rtl8821ce_init_default_value;
800 ops->intf_chip_configure = intf_chip_configure;
801 ops->read_adapter_info = read_adapter_info;
803 ops->enable_interrupt = rtl8821ce_enable_interrupt;
804 ops->disable_interrupt = rtl8821ce_disable_interrupt;
805 ops->interrupt_handler = rtl8821ce_interrupt;
807 * ops->check_ips_status = check_ips_status;
809 ops->clear_interrupt = rtl8821ce_clear_interrupt;
810 #if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) ||\
811 defined(CONFIG_PCI_HCI)
813 * ops->clear_interrupt = clear_interrupt_all;
817 ops->set_hw_reg_handler = sethwreg;
818 ops->GetHwRegHandler = gethwreg;
819 ops->get_hal_def_var_handler = gethaldefvar;
820 ops->SetHalDefVarHandler = sethaldefvar;
822 ops->hal_xmit = rtl8821ce_hal_xmit;
823 ops->mgnt_xmit = rtl8821ce_mgnt_xmit;
824 ops->hal_xmitframe_enqueue = rtl8821ce_hal_xmitframe_enqueue;
825 #ifdef CONFIG_HOSTAPD_MLME
826 ops->hostap_mgnt_xmit_entry = rtl8821ce_hostap_mgnt_xmit_entry;
829 #ifdef CONFIG_XMIT_THREAD_MODE
831 ops->xmit_thread_handler = rtl8821ce_xmit_buf_handler;
833 ops->hal_set_l1ssbackdoor_handler = rtw_pci_aspm_config_l1off_general;