// SPDX-License-Identifier: GPL-2.0 /* Copyright(c) 2009-2012 Realtek Corporation.*/ #include "../wifi.h" #include "../efuse.h" #include "../base.h" #include "../regd.h" #include "../cam.h" #include "../ps.h" #include "../pci.h" #include "../rtl8192d/reg.h" #include "../rtl8192d/def.h" #include "../rtl8192d/dm_common.h" #include "../rtl8192d/fw_common.h" #include "../rtl8192d/hw_common.h" #include "../rtl8192d/phy_common.h" #include "phy.h" #include "dm.h" #include "fw.h" #include "led.h" #include "sw.h" #include "hw.h" u32 rtl92de_read_dword_dbi(struct ieee80211_hw *hw, u16 offset, u8 direct) { struct rtl_priv *rtlpriv = rtl_priv(hw); u32 value; rtl_write_word(rtlpriv, REG_DBI_CTRL, (offset & 0xFFC)); rtl_write_byte(rtlpriv, REG_DBI_FLAG, BIT(1) | direct); udelay(10); value = rtl_read_dword(rtlpriv, REG_DBI_RDATA); return value; } void rtl92de_write_dword_dbi(struct ieee80211_hw *hw, u16 offset, u32 value, u8 direct) { struct rtl_priv *rtlpriv = rtl_priv(hw); rtl_write_word(rtlpriv, REG_DBI_CTRL, ((offset & 0xFFC) | 0xF000)); rtl_write_dword(rtlpriv, REG_DBI_WDATA, value); rtl_write_byte(rtlpriv, REG_DBI_FLAG, BIT(0) | direct); } static void _rtl92de_set_bcn_ctrl_reg(struct ieee80211_hw *hw, u8 set_bits, u8 clear_bits) { struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_priv *rtlpriv = rtl_priv(hw); rtlpci->reg_bcn_ctrl_val |= set_bits; rtlpci->reg_bcn_ctrl_val &= ~clear_bits; rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlpci->reg_bcn_ctrl_val); } static void _rtl92de_enable_bcn_sub_func(struct ieee80211_hw *hw) { _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(1)); } static void _rtl92de_disable_bcn_sub_func(struct ieee80211_hw *hw) { _rtl92de_set_bcn_ctrl_reg(hw, BIT(1), 0); } void rtl92de_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) { struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); switch (variable) { case HW_VAR_RCR: *((u32 *) (val)) = rtlpci->receive_config; break; default: rtl92d_get_hw_reg(hw, variable, val); break; } } void rtl92de_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); switch (variable) { case HW_VAR_AC_PARAM: { u8 e_aci = *val; rtl92d_dm_init_edca_turbo(hw); if (rtlpci->acm_method != EACMWAY2_SW) rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ACM_CTRL, &e_aci); break; } case HW_VAR_ACM_CTRL: { u8 e_aci = *val; union aci_aifsn *p_aci_aifsn = (union aci_aifsn *)(&(mac->ac[0].aifs)); u8 acm = p_aci_aifsn->f.acm; u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL); acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? 0x0 : 0x1); if (acm) { switch (e_aci) { case AC0_BE: acm_ctrl |= ACMHW_BEQEN; break; case AC2_VI: acm_ctrl |= ACMHW_VIQEN; break; case AC3_VO: acm_ctrl |= ACMHW_VOQEN; break; default: rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING, "HW_VAR_ACM_CTRL acm set failed: eACI is %d\n", acm); break; } } else { switch (e_aci) { case AC0_BE: acm_ctrl &= (~ACMHW_BEQEN); break; case AC2_VI: acm_ctrl &= (~ACMHW_VIQEN); break; case AC3_VO: acm_ctrl &= (~ACMHW_VOQEN); break; default: pr_err("switch case %#x not processed\n", e_aci); break; } } rtl_dbg(rtlpriv, COMP_QOS, DBG_TRACE, "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", acm_ctrl); rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl); break; } case HW_VAR_RCR: rtl_write_dword(rtlpriv, REG_RCR, ((u32 *) (val))[0]); rtlpci->receive_config = ((u32 *) (val))[0]; break; case HW_VAR_H2C_FW_JOINBSSRPT: { u8 mstatus = (*val); u8 tmp_regcr, tmp_reg422; bool recover = false; if (mstatus == RT_MEDIA_CONNECT) { rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID, NULL); tmp_regcr = rtl_read_byte(rtlpriv, REG_CR + 1); rtl_write_byte(rtlpriv, REG_CR + 1, (tmp_regcr | BIT(0))); _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(3)); _rtl92de_set_bcn_ctrl_reg(hw, BIT(4), 0); tmp_reg422 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2); if (tmp_reg422 & BIT(6)) recover = true; rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp_reg422 & (~BIT(6))); rtl92d_set_fw_rsvdpagepkt(hw, 0); _rtl92de_set_bcn_ctrl_reg(hw, BIT(3), 0); _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(4)); if (recover) rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, tmp_reg422); rtl_write_byte(rtlpriv, REG_CR + 1, (tmp_regcr & ~(BIT(0)))); } rtl92d_set_fw_joinbss_report_cmd(hw, (*val)); break; } case HW_VAR_CORRECT_TSF: { u8 btype_ibss = val[0]; if (btype_ibss) rtl92d_stop_tx_beacon(hw); _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(3)); rtl_write_dword(rtlpriv, REG_TSFTR, (u32) (mac->tsf & 0xffffffff)); rtl_write_dword(rtlpriv, REG_TSFTR + 4, (u32) ((mac->tsf >> 32) & 0xffffffff)); _rtl92de_set_bcn_ctrl_reg(hw, BIT(3), 0); if (btype_ibss) rtl92d_resume_tx_beacon(hw); break; } case HW_VAR_INT_MIGRATION: { bool int_migration = *(bool *) (val); if (int_migration) { /* Set interrupt migration timer and * corresponding Tx/Rx counter. * timer 25ns*0xfa0=100us for 0xf packets. * 0x306:Rx, 0x307:Tx */ rtl_write_dword(rtlpriv, REG_INT_MIG, 0xfe000fa0); rtlpriv->dm.interrupt_migration = int_migration; } else { /* Reset all interrupt migration settings. */ rtl_write_dword(rtlpriv, REG_INT_MIG, 0); rtlpriv->dm.interrupt_migration = int_migration; } break; } case HW_VAR_INT_AC: { bool disable_ac_int = *((bool *) val); /* Disable four ACs interrupts. */ if (disable_ac_int) { /* Disable VO, VI, BE and BK four AC interrupts * to gain more efficient CPU utilization. * When extremely highly Rx OK occurs, * we will disable Tx interrupts. */ rtlpriv->cfg->ops->update_interrupt_mask(hw, 0, RT_AC_INT_MASKS); rtlpriv->dm.disable_tx_int = disable_ac_int; /* Enable four ACs interrupts. */ } else { rtlpriv->cfg->ops->update_interrupt_mask(hw, RT_AC_INT_MASKS, 0); rtlpriv->dm.disable_tx_int = disable_ac_int; } break; } default: rtl92d_set_hw_reg(hw, variable, val); break; } } static bool _rtl92de_llt_table_init(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); unsigned short i; u8 txpktbuf_bndy; u8 maxpage; bool status; u32 value32; /* High+low page number */ u8 value8; /* normal page number */ if (rtlpriv->rtlhal.macphymode == SINGLEMAC_SINGLEPHY) { maxpage = 255; txpktbuf_bndy = 246; value8 = 0; value32 = 0x80bf0d29; } else { maxpage = 127; txpktbuf_bndy = 123; value8 = 0; value32 = 0x80750005; } /* Set reserved page for each queue */ /* 11. RQPN 0x200[31:0] = 0x80BD1C1C */ /* load RQPN */ rtl_write_byte(rtlpriv, REG_RQPN_NPQ, value8); rtl_write_dword(rtlpriv, REG_RQPN, value32); /* 12. TXRKTBUG_PG_BNDY 0x114[31:0] = 0x27FF00F6 */ /* TXRKTBUG_PG_BNDY */ rtl_write_dword(rtlpriv, REG_TRXFF_BNDY, (rtl_read_word(rtlpriv, REG_TRXFF_BNDY + 2) << 16 | txpktbuf_bndy)); /* 13. TDECTRL[15:8] 0x209[7:0] = 0xF6 */ /* Beacon Head for TXDMA */ rtl_write_byte(rtlpriv, REG_TDECTRL + 1, txpktbuf_bndy); /* 14. BCNQ_PGBNDY 0x424[7:0] = 0xF6 */ /* BCNQ_PGBNDY */ rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy); rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy); /* 15. WMAC_LBK_BF_HD 0x45D[7:0] = 0xF6 */ /* WMAC_LBK_BF_HD */ rtl_write_byte(rtlpriv, 0x45D, txpktbuf_bndy); /* Set Tx/Rx page size (Tx must be 128 Bytes, */ /* Rx can be 64,128,256,512,1024 bytes) */ /* 16. PBP [7:0] = 0x11 */ /* TRX page size */ rtl_write_byte(rtlpriv, REG_PBP, 0x11); /* 17. DRV_INFO_SZ = 0x04 */ rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, 0x4); /* 18. LLT_table_init(Adapter); */ for (i = 0; i < (txpktbuf_bndy - 1); i++) { status = rtl92d_llt_write(hw, i, i + 1); if (!status) return status; } /* end of list */ status = rtl92d_llt_write(hw, (txpktbuf_bndy - 1), 0xFF); if (!status) return status; /* Make the other pages as ring buffer */ /* This ring buffer is used as beacon buffer if we */ /* config this MAC as two MAC transfer. */ /* Otherwise used as local loopback buffer. */ for (i = txpktbuf_bndy; i < maxpage; i++) { status = rtl92d_llt_write(hw, i, (i + 1)); if (!status) return status; } /* Let last entry point to the start entry of ring buffer */ status = rtl92d_llt_write(hw, maxpage, txpktbuf_bndy); if (!status) return status; return true; } static void _rtl92de_gen_refresh_led_state(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); enum rtl_led_pin pin0 = rtlpriv->ledctl.sw_led0; if (rtlpci->up_first_time) return; if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) rtl92de_sw_led_on(hw, pin0); else if (ppsc->rfoff_reason == RF_CHANGE_BY_INIT) rtl92de_sw_led_on(hw, pin0); else rtl92de_sw_led_off(hw, pin0); } static bool _rtl92de_init_mac(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); unsigned char bytetmp; unsigned short wordtmp; u16 retry; rtl92d_phy_set_poweron(hw); /* Add for resume sequence of power domain according * to power document V11. Chapter V.11.... */ /* 0. RSV_CTRL 0x1C[7:0] = 0x00 */ /* unlock ISO/CLK/Power control register */ rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x00); rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, 0x05); /* 1. AFE_XTAL_CTRL [7:0] = 0x0F enable XTAL */ /* 2. SPS0_CTRL 0x11[7:0] = 0x2b enable SPS into PWM mode */ /* 3. delay (1ms) this is not necessary when initially power on */ /* C. Resume Sequence */ /* a. SPS0_CTRL 0x11[7:0] = 0x2b */ rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b); /* b. AFE_XTAL_CTRL [7:0] = 0x0F */ rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0F); /* c. DRV runs power on init flow */ /* auto enable WLAN */ /* 4. APS_FSMCO 0x04[8] = 1; wait till 0x04[8] = 0 */ /* Power On Reset for MAC Block */ bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1) | BIT(0); udelay(2); rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, bytetmp); udelay(2); /* 5. Wait while 0x04[8] == 0 goto 2, otherwise goto 1 */ bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1); udelay(50); retry = 0; while ((bytetmp & BIT(0)) && retry < 1000) { retry++; bytetmp = rtl_read_byte(rtlpriv, REG_APS_FSMCO + 1); udelay(50); } /* Enable Radio off, GPIO, and LED function */ /* 6. APS_FSMCO 0x04[15:0] = 0x0012 when enable HWPDN */ rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x1012); /* release RF digital isolation */ /* 7. SYS_ISO_CTRL 0x01[1] = 0x0; */ /*Set REG_SYS_ISO_CTRL 0x1=0x82 to prevent wake# problem. */ rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x82); udelay(2); /* make sure that BB reset OK. */ /* rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3); */ /* Disable REG_CR before enable it to assure reset */ rtl_write_word(rtlpriv, REG_CR, 0x0); /* Release MAC IO register reset */ rtl_write_word(rtlpriv, REG_CR, 0x2ff); /* clear stopping tx/rx dma */ rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0x0); /* rtl_write_word(rtlpriv,REG_CR+2, 0x2); */ /* System init */ /* 18. LLT_table_init(Adapter); */ if (!_rtl92de_llt_table_init(hw)) return false; /* Clear interrupt and enable interrupt */ /* 19. HISR 0x124[31:0] = 0xffffffff; */ /* HISRE 0x12C[7:0] = 0xFF */ rtl_write_dword(rtlpriv, REG_HISR, 0xffffffff); rtl_write_byte(rtlpriv, REG_HISRE, 0xff); /* 20. HIMR 0x120[31:0] |= [enable INT mask bit map]; */ /* 21. HIMRE 0x128[7:0] = [enable INT mask bit map] */ /* The IMR should be enabled later after all init sequence * is finished. */ /* 22. PCIE configuration space configuration */ /* 23. Ensure PCIe Device 0x80[15:0] = 0x0143 (ASPM+CLKREQ), */ /* and PCIe gated clock function is enabled. */ /* PCIE configuration space will be written after * all init sequence.(Or by BIOS) */ rtl92d_phy_config_maccoexist_rfpage(hw); /* THe below section is not related to power document Vxx . */ /* This is only useful for driver and OS setting. */ /* -------------------Software Relative Setting---------------------- */ wordtmp = rtl_read_word(rtlpriv, REG_TRXDMA_CTRL); wordtmp &= 0xf; wordtmp |= 0xF771; rtl_write_word(rtlpriv, REG_TRXDMA_CTRL, wordtmp); /* Reported Tx status from HW for rate adaptive. */ /* This should be realtive to power on step 14. But in document V11 */ /* still not contain the description.!!! */ rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 1, 0x1F); /* Set Tx/Rx page size (Tx must be 128 Bytes, * Rx can be 64,128,256,512,1024 bytes) */ /* rtl_write_byte(rtlpriv,REG_PBP, 0x11); */ /* Set RCR register */ rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); /* rtl_write_byte(rtlpriv,REG_RX_DRVINFO_SZ, 4); */ /* Set TCR register */ rtl_write_dword(rtlpriv, REG_TCR, rtlpci->transmit_config); /* disable earlymode */ rtl_write_byte(rtlpriv, 0x4d0, 0x0); /* Set TX/RX descriptor physical address(from OS API). */ rtl_write_dword(rtlpriv, REG_BCNQ_DESA, rtlpci->tx_ring[BEACON_QUEUE].dma); rtl_write_dword(rtlpriv, REG_MGQ_DESA, rtlpci->tx_ring[MGNT_QUEUE].dma); rtl_write_dword(rtlpriv, REG_VOQ_DESA, rtlpci->tx_ring[VO_QUEUE].dma); rtl_write_dword(rtlpriv, REG_VIQ_DESA, rtlpci->tx_ring[VI_QUEUE].dma); rtl_write_dword(rtlpriv, REG_BEQ_DESA, rtlpci->tx_ring[BE_QUEUE].dma); rtl_write_dword(rtlpriv, REG_BKQ_DESA, rtlpci->tx_ring[BK_QUEUE].dma); rtl_write_dword(rtlpriv, REG_HQ_DESA, rtlpci->tx_ring[HIGH_QUEUE].dma); /* Set RX Desc Address */ rtl_write_dword(rtlpriv, REG_RX_DESA, rtlpci->rx_ring[RX_MPDU_QUEUE].dma); /* if we want to support 64 bit DMA, we should set it here, * but now we do not support 64 bit DMA*/ rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 3, 0x33); /* Reset interrupt migration setting when initialization */ rtl_write_dword(rtlpriv, REG_INT_MIG, 0); /* Reconsider when to do this operation after asking HWSD. */ bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL); rtl_write_byte(rtlpriv, REG_APSD_CTRL, bytetmp & ~BIT(6)); do { retry++; bytetmp = rtl_read_byte(rtlpriv, REG_APSD_CTRL); } while ((retry < 200) && !(bytetmp & BIT(7))); /* After MACIO reset,we must refresh LED state. */ _rtl92de_gen_refresh_led_state(hw); /* Reset H2C protection register */ rtl_write_dword(rtlpriv, REG_MCUTST_1, 0x0); return true; } static void _rtl92de_hw_configure(struct ieee80211_hw *hw) { struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); u8 reg_bw_opmode = BW_OPMODE_20MHZ; u32 reg_rrsr; reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8); rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode); rtl_write_dword(rtlpriv, REG_RRSR, reg_rrsr); rtl_write_byte(rtlpriv, REG_SLOT, 0x09); rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, 0x0); rtl_write_word(rtlpriv, REG_FWHW_TXQ_CTRL, 0x1F80); rtl_write_word(rtlpriv, REG_RL, 0x0707); rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x02012802); rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF); rtl_write_dword(rtlpriv, REG_DARFRC, 0x01000000); rtl_write_dword(rtlpriv, REG_DARFRC + 4, 0x07060504); rtl_write_dword(rtlpriv, REG_RARFRC, 0x01000000); rtl_write_dword(rtlpriv, REG_RARFRC + 4, 0x07060504); /* Aggregation threshold */ if (rtlhal->macphymode == DUALMAC_DUALPHY) rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb9726641); else if (rtlhal->macphymode == DUALMAC_SINGLEPHY) rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x66626641); else rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0xb972a841); rtl_write_byte(rtlpriv, REG_ATIMWND, 0x2); rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0x0a); rtlpci->reg_bcn_ctrl_val = 0x1f; rtl_write_byte(rtlpriv, REG_BCN_CTRL, rtlpci->reg_bcn_ctrl_val); rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff); rtl_write_byte(rtlpriv, REG_PIFS, 0x1C); rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16); rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0020); /* For throughput */ rtl_write_word(rtlpriv, REG_FAST_EDCA_CTRL, 0x6666); /* ACKTO for IOT issue. */ rtl_write_byte(rtlpriv, REG_ACKTO, 0x40); /* Set Spec SIFS (used in NAV) */ rtl_write_word(rtlpriv, REG_SPEC_SIFS, 0x1010); rtl_write_word(rtlpriv, REG_MAC_SPEC_SIFS, 0x1010); /* Set SIFS for CCK */ rtl_write_word(rtlpriv, REG_SIFS_CTX, 0x1010); /* Set SIFS for OFDM */ rtl_write_word(rtlpriv, REG_SIFS_TRX, 0x1010); /* Set Multicast Address. */ rtl_write_dword(rtlpriv, REG_MAR, 0xffffffff); rtl_write_dword(rtlpriv, REG_MAR + 4, 0xffffffff); switch (rtlpriv->phy.rf_type) { case RF_1T2R: case RF_1T1R: rtlhal->minspace_cfg = (MAX_MSS_DENSITY_1T << 3); break; case RF_2T2R: case RF_2T2R_GREEN: rtlhal->minspace_cfg = (MAX_MSS_DENSITY_2T << 3); break; } } static void _rtl92de_enable_aspm_back_door(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); rtl_write_byte(rtlpriv, 0x34b, 0x93); rtl_write_word(rtlpriv, 0x350, 0x870c); rtl_write_byte(rtlpriv, 0x352, 0x1); if (ppsc->support_backdoor) rtl_write_byte(rtlpriv, 0x349, 0x1b); else rtl_write_byte(rtlpriv, 0x349, 0x03); rtl_write_word(rtlpriv, 0x350, 0x2718); rtl_write_byte(rtlpriv, 0x352, 0x1); } int rtl92de_hw_init(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_phy *rtlphy = &(rtlpriv->phy); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); bool rtstatus = true; u8 tmp_u1b; int i; int err; unsigned long flags; rtlpci->being_init_adapter = true; rtlpci->init_ready = false; spin_lock_irqsave(&globalmutex_for_power_and_efuse, flags); /* we should do iqk after disable/enable */ rtl92d_phy_reset_iqk_result(hw); /* rtlpriv->intf_ops->disable_aspm(hw); */ rtstatus = _rtl92de_init_mac(hw); if (!rtstatus) { pr_err("Init MAC failed\n"); err = 1; spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags); return err; } err = rtl92d_download_fw(hw); spin_unlock_irqrestore(&globalmutex_for_power_and_efuse, flags); if (err) { rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING, "Failed to download FW. Init HW without FW..\n"); return 1; } rtlhal->last_hmeboxnum = 0; rtlpriv->psc.fw_current_inpsmode = false; tmp_u1b = rtl_read_byte(rtlpriv, 0x605); tmp_u1b = tmp_u1b | 0x30; rtl_write_byte(rtlpriv, 0x605, tmp_u1b); if (rtlhal->earlymode_enable) { rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "EarlyMode Enabled!!!\n"); tmp_u1b = rtl_read_byte(rtlpriv, 0x4d0); tmp_u1b = tmp_u1b | 0x1f; rtl_write_byte(rtlpriv, 0x4d0, tmp_u1b); rtl_write_byte(rtlpriv, 0x4d3, 0x80); tmp_u1b = rtl_read_byte(rtlpriv, 0x605); tmp_u1b = tmp_u1b | 0x40; rtl_write_byte(rtlpriv, 0x605, tmp_u1b); } if (mac->rdg_en) { rtl_write_byte(rtlpriv, REG_RD_CTRL, 0xff); rtl_write_word(rtlpriv, REG_RD_NAV_NXT, 0x200); rtl_write_byte(rtlpriv, REG_RD_RESP_PKT_TH, 0x05); } rtl92d_phy_mac_config(hw); /* because last function modify RCR, so we update * rcr var here, or TP will unstable for receive_config * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252*/ rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR); rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); rtl92d_phy_bb_config(hw); rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; /* set before initialize RF */ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf); /* config RF */ rtl92d_phy_rf_config(hw); /* After read predefined TXT, we must set BB/MAC/RF * register as our requirement */ /* After load BB,RF params,we need do more for 92D. */ rtl92d_update_bbrf_configuration(hw); /* set default value after initialize RF, */ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0); rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, RF_CHNLBW, RFREG_OFFSET_MASK); rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1, RF_CHNLBW, RFREG_OFFSET_MASK); /*---- Set CCK and OFDM Block "ON"----*/ if (rtlhal->current_bandtype == BAND_ON_2_4G) rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); if (rtlhal->interfaceindex == 0) { /* RFPGA0_ANALOGPARAMETER2: cck clock select, * set to 20MHz by default */ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10) | BIT(11), 3); } else { /* Mac1 */ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(11) | BIT(10), 3); } _rtl92de_hw_configure(hw); /* reset hw sec */ rtl_cam_reset_all_entry(hw); rtl92d_enable_hw_security_config(hw); /* Read EEPROM TX power index and PHY_REG_PG.txt to capture correct */ /* TX power index for different rate set. */ rtl92d_phy_get_hw_reg_originalvalue(hw); rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel); ppsc->rfpwr_state = ERFON; rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr); _rtl92de_enable_aspm_back_door(hw); /* rtlpriv->intf_ops->enable_aspm(hw); */ rtl92de_dm_init(hw); rtlpci->being_init_adapter = false; if (ppsc->rfpwr_state == ERFON) { rtl92d_phy_lc_calibrate(hw, IS_92D_SINGLEPHY(rtlhal->version)); /* 5G and 2.4G must wait sometime to let RF LO ready */ if (rtlhal->macphymode == DUALMAC_DUALPHY) { u32 tmp_rega; for (i = 0; i < 10000; i++) { udelay(MAX_STALL_TIME); tmp_rega = rtl_get_rfreg(hw, (enum radio_path)RF90_PATH_A, 0x2a, MASKDWORD); if (((tmp_rega & BIT(11)) == BIT(11))) break; } /* check that loop was successful. If not, exit now */ if (i == 10000) { rtlpci->init_ready = false; return 1; } } } rtlpci->init_ready = true; return err; } static int _rtl92de_set_media_status(struct ieee80211_hw *hw, enum nl80211_iftype type) { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 bt_msr = rtl_read_byte(rtlpriv, MSR); enum led_ctl_mode ledaction = LED_CTL_NO_LINK; bt_msr &= 0xfc; if (type == NL80211_IFTYPE_UNSPECIFIED || type == NL80211_IFTYPE_STATION) { rtl92d_stop_tx_beacon(hw); _rtl92de_enable_bcn_sub_func(hw); } else if (type == NL80211_IFTYPE_ADHOC || type == NL80211_IFTYPE_AP) { rtl92d_resume_tx_beacon(hw); _rtl92de_disable_bcn_sub_func(hw); } else { rtl_dbg(rtlpriv, COMP_ERR, DBG_WARNING, "Set HW_VAR_MEDIA_STATUS: No such media status(%x)\n", type); } switch (type) { case NL80211_IFTYPE_UNSPECIFIED: bt_msr |= MSR_NOLINK; ledaction = LED_CTL_LINK; rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "Set Network type to NO LINK!\n"); break; case NL80211_IFTYPE_ADHOC: bt_msr |= MSR_ADHOC; rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "Set Network type to Ad Hoc!\n"); break; case NL80211_IFTYPE_STATION: bt_msr |= MSR_INFRA; ledaction = LED_CTL_LINK; rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "Set Network type to STA!\n"); break; case NL80211_IFTYPE_AP: bt_msr |= MSR_AP; rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "Set Network type to AP!\n"); break; default: pr_err("Network type %d not supported!\n", type); return 1; } rtl_write_byte(rtlpriv, MSR, bt_msr); rtlpriv->cfg->ops->led_control(hw, ledaction); if ((bt_msr & MSR_MASK) == MSR_AP) rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00); else rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66); return 0; } void rtl92de_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) { struct rtl_priv *rtlpriv = rtl_priv(hw); u32 reg_rcr; if (rtlpriv->psc.rfpwr_state != ERFON) return; rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); if (check_bssid) { reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); _rtl92de_set_bcn_ctrl_reg(hw, 0, BIT(4)); } else if (!check_bssid) { reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); _rtl92de_set_bcn_ctrl_reg(hw, BIT(4), 0); rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); } } int rtl92de_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) { struct rtl_priv *rtlpriv = rtl_priv(hw); if (_rtl92de_set_media_status(hw, type)) return -EOPNOTSUPP; /* check bssid */ if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { if (type != NL80211_IFTYPE_AP) rtl92de_set_check_bssid(hw, true); } else { rtl92de_set_check_bssid(hw, false); } return 0; } /* do iqk or reload iqk */ /* windows just rtl92d_phy_reload_iqk_setting in set channel, * but it's very strict for time sequence so we add * rtl92d_phy_reload_iqk_setting here */ void rtl92d_linked_set_reg(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); u8 indexforchannel; u8 channel = rtlphy->current_channel; indexforchannel = rtl92d_get_rightchnlplace_for_iqk(channel); if (!rtlphy->iqk_matrix[indexforchannel].iqk_done) { rtl_dbg(rtlpriv, COMP_SCAN | COMP_INIT, DBG_DMESG, "Do IQK for channel:%d\n", channel); rtl92d_phy_iq_calibrate(hw); } } void rtl92de_enable_interrupt(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF); rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF); rtlpci->irq_enabled = true; } void rtl92de_disable_interrupt(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED); rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED); rtlpci->irq_enabled = false; } static void _rtl92de_poweroff_adapter(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 u1b_tmp; unsigned long flags; rtlpriv->intf_ops->enable_aspm(hw); rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x00); rtl_set_bbreg(hw, RFPGA0_XCD_RFPARAMETER, BIT(3), 0); rtl_set_bbreg(hw, RFPGA0_XCD_RFPARAMETER, BIT(15), 0); /* 0x20:value 05-->04 */ rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, 0x04); /* ==== Reset digital sequence ====== */ rtl92d_firmware_selfreset(hw); /* f. SYS_FUNC_EN 0x03[7:0]=0x51 reset MCU, MAC register, DCORE */ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x51); /* g. MCUFWDL 0x80[1:0]=0 reset MCU ready status */ rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); /* ==== Pull GPIO PIN to balance level and LED control ====== */ /* h. GPIO_PIN_CTRL 0x44[31:0]=0x000 */ rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00000000); /* i. Value = GPIO_PIN_CTRL[7:0] */ u1b_tmp = rtl_read_byte(rtlpriv, REG_GPIO_PIN_CTRL); /* j. GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); */ /* write external PIN level */ rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x00FF0000 | (u1b_tmp << 8)); /* k. GPIO_MUXCFG 0x42 [15:0] = 0x0780 */ rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790); /* l. LEDCFG 0x4C[15:0] = 0x8080 */ rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080); /* ==== Disable analog sequence === */ /* m. AFE_PLL_CTRL[7:0] = 0x80 disable PLL */ rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80); /* n. SPS0_CTRL 0x11[7:0] = 0x22 enter PFM mode */ rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23); /* o. AFE_XTAL_CTRL 0x24[7:0] = 0x0E disable XTAL, if No BT COEX */ rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL, 0x0e); /* p. RSV_CTRL 0x1C[7:0] = 0x0E lock ISO/CLK/Power control register */ rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0e); /* ==== interface into suspend === */ /* q. APS_FSMCO[15:8] = 0x58 PCIe suspend mode */ /* According to power document V11, we need to set this */ /* value as 0x18. Otherwise, we may not L0s sometimes. */ /* This indluences power consumption. Bases on SD1's test, */ /* set as 0x00 do not affect power current. And if it */ /* is set as 0x18, they had ever met auto load fail problem. */ rtl_write_byte(rtlpriv, REG_APS_FSMCO + 1, 0x10); rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "In PowerOff,reg0x%x=%X\n", REG_SPS0_CTRL, rtl_read_byte(rtlpriv, REG_SPS0_CTRL)); /* r. Note: for PCIe interface, PON will not turn */ /* off m-bias and BandGap in PCIe suspend mode. */ /* 0x17[7] 1b': power off in process 0b' : power off over */ if (rtlpriv->rtlhal.macphymode != SINGLEMAC_SINGLEPHY) { spin_lock_irqsave(&globalmutex_power, flags); u1b_tmp = rtl_read_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS); u1b_tmp &= (~BIT(7)); rtl_write_byte(rtlpriv, REG_POWER_OFF_IN_PROCESS, u1b_tmp); spin_unlock_irqrestore(&globalmutex_power, flags); } rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "<=======\n"); } void rtl92de_card_disable(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); enum nl80211_iftype opmode; mac->link_state = MAC80211_NOLINK; opmode = NL80211_IFTYPE_UNSPECIFIED; _rtl92de_set_media_status(hw, opmode); if (rtlpci->driver_is_goingto_unload || ppsc->rfoff_reason > RF_CHANGE_BY_PS) rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); /* Power sequence for each MAC. */ /* a. stop tx DMA */ /* b. close RF */ /* c. clear rx buf */ /* d. stop rx DMA */ /* e. reset MAC */ /* a. stop tx DMA */ rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xFE); udelay(50); /* b. TXPAUSE 0x522[7:0] = 0xFF Pause MAC TX queue */ /* c. ========RF OFF sequence========== */ /* 0x88c[23:20] = 0xf. */ rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER4, 0x00f00000, 0xf); rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00); /* APSD_CTRL 0x600[7:0] = 0x40 */ rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); /* Close antenna 0,0xc04,0xd04 */ rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0); rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, BDWORD, 0); /* SYS_FUNC_EN 0x02[7:0] = 0xE2 reset BB state machine */ rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); /* Mac0 can not do Global reset. Mac1 can do. */ /* SYS_FUNC_EN 0x02[7:0] = 0xE0 reset BB state machine */ if (rtlpriv->rtlhal.interfaceindex == 1) rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE0); udelay(50); /* d. stop tx/rx dma before disable REG_CR (0x100) to fix */ /* dma hang issue when disable/enable device. */ rtl_write_byte(rtlpriv, REG_PCIE_CTRL_REG + 1, 0xff); udelay(50); rtl_write_byte(rtlpriv, REG_CR, 0x0); rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, "==> Do power off.......\n"); if (rtl92d_phy_check_poweroff(hw)) _rtl92de_poweroff_adapter(hw); return; } void rtl92de_interrupt_recognized(struct ieee80211_hw *hw, struct rtl_int *intvec) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); intvec->inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; rtl_write_dword(rtlpriv, ISR, intvec->inta); } void rtl92de_set_beacon_related_registers(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); u16 bcn_interval, atim_window; bcn_interval = mac->beacon_interval; atim_window = 2; rtl92de_disable_interrupt(hw); rtl_write_word(rtlpriv, REG_ATIMWND, atim_window); rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660f); rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x20); if (rtlpriv->rtlhal.current_bandtype == BAND_ON_5G) rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x30); else rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x20); rtl_write_byte(rtlpriv, 0x606, 0x30); } void rtl92de_set_beacon_interval(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); u16 bcn_interval = mac->beacon_interval; rtl_dbg(rtlpriv, COMP_BEACON, DBG_DMESG, "beacon_interval:%d\n", bcn_interval); rtl92de_disable_interrupt(hw); rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval); rtl92de_enable_interrupt(hw); } void rtl92de_update_interrupt_mask(struct ieee80211_hw *hw, u32 add_msr, u32 rm_msr) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); rtl_dbg(rtlpriv, COMP_INTR, DBG_LOUD, "add_msr:%x, rm_msr:%x\n", add_msr, rm_msr); if (add_msr) rtlpci->irq_mask[0] |= add_msr; if (rm_msr) rtlpci->irq_mask[0] &= (~rm_msr); rtl92de_disable_interrupt(hw); rtl92de_enable_interrupt(hw); } void rtl92de_suspend(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); rtlpriv->rtlhal.macphyctl_reg = rtl_read_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL); } void rtl92de_resume(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); rtl_write_byte(rtlpriv, REG_MAC_PHY_CTRL_NORMAL, rtlpriv->rtlhal.macphyctl_reg); }