/****************************************************************************** * * Copyright(c) 2019 Realtek Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * ******************************************************************************/ #include "hw.h" #include "coex.h" #include "twt.h" #include "fwofld.h" #include "rrsr.h" static struct mac_ax_host_rpr_cfg rpr_cfg_poh = { 121, /* agg */ 255, /* tmr */ 0, /* agg_def */ 0, /* tmr_def */ 0, /* rsvd */ MAC_AX_FUNC_EN, /* txok_en */ MAC_AX_FUNC_EN, /* rty_lmt_en */ MAC_AX_FUNC_EN, /* lft_drop_en */ MAC_AX_FUNC_EN /* macid_drop_en */ }; static struct mac_ax_host_rpr_cfg rpr_cfg_stf = { 121, /* agg */ 255, /* tmr */ 0, /* agg_def */ 0, /* tmr_def */ 0, /* rsvd */ MAC_AX_FUNC_DIS, /* txok_en */ MAC_AX_FUNC_DIS, /* rty_lmt_en */ MAC_AX_FUNC_DIS, /* lft_drop_en */ MAC_AX_FUNC_DIS /* macid_drop_en */ }; static void get_delay_tx_cfg(struct mac_ax_adapter *adapter, struct mac_ax_delay_tx_cfg *cfg); static void set_delay_tx_cfg(struct mac_ax_adapter *adapter, struct mac_ax_delay_tx_cfg *cfg); struct mac_ax_hw_info *mac_get_hw_info(struct mac_ax_adapter *adapter) { return adapter->hw_info->done ? adapter->hw_info : NULL; } u8 shift_mask(u32 mask) { u8 i; for (i = 0; i < 32; i++) { if ((mask >> i) & BIT0) break; } return i; } u32 get_block_tx_sel_msk(enum mac_ax_block_tx_sel src, u32 *msk) { switch (src) { case MAC_AX_CCA: *msk = B_AX_CCA_EN; break; case MAC_AX_SEC20_CCA: *msk = B_AX_SEC20_EN; break; case MAC_AX_SEC40_CCA: *msk = B_AX_SEC40_EN; break; case MAC_AX_SEC80_CCA: *msk = B_AX_SEC80_EN; break; case MAC_AX_EDCCA: *msk = B_AX_EDCCA_EN; break; case MAC_AX_BTCCA: *msk = B_AX_BTCCA_EN; break; case MAC_AX_TX_NAV: *msk = B_AX_TX_NAV_EN; break; default: return MACNOITEM; } return MACSUCCESS; } u32 cfg_block_tx(struct mac_ax_adapter *adapter, enum mac_ax_block_tx_sel src, u8 band, u8 en) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 val, msk, ret; u32 reg = band == 0 ? R_AX_CCA_CFG_0 : R_AX_CCA_CFG_0_C1; ret = check_mac_en(adapter, band, MAC_AX_CMAC_SEL); if (ret) { PLTFM_MSG_ERR("%s: CMAC%d is NOT enabled\n", __func__, band); return ret; } ret = get_block_tx_sel_msk(src, &msk); if (ret) { PLTFM_MSG_ERR("%s: %d is NOT supported\n", __func__, src); return ret; } #if MAC_AX_FW_REG_OFLD if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) { ret = MAC_REG_W_OFLD((u16)reg, msk, en ? 1 : 0, 1); if (ret != MACSUCCESS) PLTFM_MSG_ERR("%s: write offload fail %d", __func__, ret); return ret; } #endif val = MAC_REG_R32(reg); if (en) val = val | msk; else val = val & ~msk; MAC_REG_W32(reg, val); return MACSUCCESS; } u32 get_block_tx(struct mac_ax_adapter *adapter, enum mac_ax_block_tx_sel src, u8 band, u8 *en) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 val, msk, ret; u32 reg = band == 0 ? R_AX_CCA_CFG_0 : R_AX_CCA_CFG_0_C1; ret = check_mac_en(adapter, band, MAC_AX_CMAC_SEL); if (ret) { PLTFM_MSG_ERR("%s: CMAC%d is NOT enabled", __func__, band); return ret; } val = MAC_REG_R32(reg); ret = get_block_tx_sel_msk(src, &msk); if (ret) { PLTFM_MSG_ERR("%s: %d is NOT supported\n", __func__, src); return ret; } *en = !!(val & msk); return MACSUCCESS; } u32 set_enable_bb_rf(struct mac_ax_adapter *adapter, u8 enable) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 value32; u8 value8; u32 ret; u8 wl_rfc_s0, wl_rfc_s1; if (enable == 1) { value8 = MAC_REG_R8(R_AX_SYS_FUNC_EN); value8 |= B_AX_FEN_BBRSTB | B_AX_FEN_BB_GLB_RSTN; MAC_REG_W8(R_AX_SYS_FUNC_EN, value8); if (is_chip_id(adapter, MAC_AX_CHIP_ID_8852A)) { value32 = MAC_REG_R32(R_AX_WLRF_CTRL); value32 |= B_AX_WLRF1_CTRL_7 | B_AX_WLRF1_CTRL_1 | B_AX_WLRF_CTRL_7 | B_AX_WLRF_CTRL_1; MAC_REG_W32(R_AX_WLRF_CTRL, value32); value8 = PHYREG_SET_ALL_CYCLE; MAC_REG_W8(R_AX_PHYREG_SET, value8); } else if (is_chip_id(adapter, MAC_AX_CHIP_ID_8852B)) { /* 0x200[18:17] = 2'b01 */ value32 = MAC_REG_R32(R_AX_SPS_DIG_ON_CTRL0); value32 = SET_CLR_WORD(value32, 0x1, B_AX_REG_ZCDC_H); MAC_REG_W32(R_AX_SPS_DIG_ON_CTRL0, value32); /* RDC KS/BB suggest : write 1 then write 0 then write 1 */ value32 = MAC_REG_R32(R_AX_WLRF_CTRL); value32 = (value32 | B_AX_AFC_AFEDIG); MAC_REG_W32(R_AX_WLRF_CTRL, value32); value32 = MAC_REG_R32(R_AX_WLRF_CTRL); value32 = (value32 & ~B_AX_AFC_AFEDIG); MAC_REG_W32(R_AX_WLRF_CTRL, value32); value32 = MAC_REG_R32(R_AX_WLRF_CTRL); value32 = (value32 | B_AX_AFC_AFEDIG); MAC_REG_W32(R_AX_WLRF_CTRL, value32); ret = mac_read_xtal_si(adapter, XTAL_SI_WL_RFC_S0, &wl_rfc_s0); if (ret) { PLTFM_MSG_ERR("Read XTAL_SI fail!\n"); return ret; } wl_rfc_s0 = (wl_rfc_s0 | 0x07); ret = mac_write_xtal_si(adapter, XTAL_SI_WL_RFC_S0, wl_rfc_s0, FULL_BIT_MASK); if (ret) { PLTFM_MSG_ERR("Write XTAL_SI fail!\n"); return ret; } ret = mac_read_xtal_si(adapter, XTAL_SI_WL_RFC_S1, &wl_rfc_s1); if (ret) { PLTFM_MSG_ERR("Read XTAL_SI fail!\n"); return ret; } wl_rfc_s1 = (wl_rfc_s1 | 0x07); ret = mac_write_xtal_si(adapter, XTAL_SI_WL_RFC_S1, wl_rfc_s1, FULL_BIT_MASK); if (ret) { PLTFM_MSG_ERR("Write XTAL_SI fail!\n"); return ret; } value8 = PHYREG_SET_XYN_CYCLE; MAC_REG_W8(R_AX_PHYREG_SET, value8); } else if (is_chip_id(adapter, MAC_AX_CHIP_ID_8852C) || is_chip_id(adapter, MAC_AX_CHIP_ID_8192XB)) { /* RDC KS/BB suggest : write 1 then write 0 then write 1 */ value32 = MAC_REG_R32(R_AX_WLRF_CTRL); value32 = (value32 | B_AX_AFC_AFEDIG); MAC_REG_W32(R_AX_WLRF_CTRL, value32); value32 = MAC_REG_R32(R_AX_WLRF_CTRL); value32 = (value32 & ~B_AX_AFC_AFEDIG); MAC_REG_W32(R_AX_WLRF_CTRL, value32); value32 = MAC_REG_R32(R_AX_WLRF_CTRL); value32 = (value32 | B_AX_AFC_AFEDIG); MAC_REG_W32(R_AX_WLRF_CTRL, value32); ret = mac_read_xtal_si(adapter, XTAL_SI_WL_RFC_S0, &wl_rfc_s0); if (ret) { PLTFM_MSG_ERR("Read XTAL_SI fail!\n"); return ret; } wl_rfc_s0 = (wl_rfc_s0 | 0x07); ret = mac_write_xtal_si(adapter, XTAL_SI_WL_RFC_S0, wl_rfc_s0, FULL_BIT_MASK); if (ret) { PLTFM_MSG_ERR("Write XTAL_SI fail!\n"); return ret; } ret = mac_read_xtal_si(adapter, XTAL_SI_WL_RFC_S1, &wl_rfc_s1); if (ret) { PLTFM_MSG_ERR("Read XTAL_SI fail!\n"); return ret; } wl_rfc_s1 = (wl_rfc_s1 | 0x07); ret = mac_write_xtal_si(adapter, XTAL_SI_WL_RFC_S1, wl_rfc_s1, FULL_BIT_MASK); if (ret) { PLTFM_MSG_ERR("Write XTAL_SI fail!\n"); return ret; } } else { return MACCHIPID; } adapter->sm.bb0_func = MAC_AX_FUNC_ON; } else { adapter->sm.bb0_func = MAC_AX_FUNC_OFF; value8 = MAC_REG_R8(R_AX_SYS_FUNC_EN); value8 &= (~(B_AX_FEN_BBRSTB | B_AX_FEN_BB_GLB_RSTN)); MAC_REG_W8(R_AX_SYS_FUNC_EN, value8); if (is_chip_id(adapter, MAC_AX_CHIP_ID_8852A)) { value32 = MAC_REG_R32(R_AX_WLRF_CTRL); value32 &= (~(B_AX_WLRF1_CTRL_7 | B_AX_WLRF1_CTRL_1 | B_AX_WLRF_CTRL_7 | B_AX_WLRF_CTRL_1)); MAC_REG_W32(R_AX_WLRF_CTRL, value32); } else if (is_chip_id(adapter, MAC_AX_CHIP_ID_8852B)) { ret = mac_read_xtal_si(adapter, XTAL_SI_WL_RFC_S0, &wl_rfc_s0); if (ret) { PLTFM_MSG_ERR("Read XTAL_SI fail!\n"); return ret; } wl_rfc_s0 = (wl_rfc_s0 & 0xF8); ret = mac_write_xtal_si(adapter, XTAL_SI_WL_RFC_S0, wl_rfc_s0, FULL_BIT_MASK); if (ret) { PLTFM_MSG_ERR("Write XTAL_SI fail!\n"); return ret; } ret = mac_read_xtal_si(adapter, XTAL_SI_WL_RFC_S1, &wl_rfc_s1); if (ret) { PLTFM_MSG_ERR("Read XTAL_SI fail!\n"); return ret; } wl_rfc_s1 = (wl_rfc_s1 & 0xF8); ret = mac_write_xtal_si(adapter, XTAL_SI_WL_RFC_S1, wl_rfc_s1, FULL_BIT_MASK); if (ret) { PLTFM_MSG_ERR("Write XTAL_SI fail!\n"); return ret; } } else if (is_chip_id(adapter, MAC_AX_CHIP_ID_8852C) || is_chip_id(adapter, MAC_AX_CHIP_ID_8192XB)) { return MACSUCCESS; } else { return MACCHIPID; } } return MACSUCCESS; } static u32 set_append_fcs(struct mac_ax_adapter *adapter, u8 enable) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u8 value8; value8 = MAC_REG_R8(R_AX_MPDU_PROC); value8 = enable == 1 ? value8 | B_AX_APPEND_FCS : value8 & ~B_AX_APPEND_FCS; MAC_REG_W8(R_AX_MPDU_PROC, value8); return MACSUCCESS; } static u32 set_accept_icverr(struct mac_ax_adapter *adapter, u8 enable) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u8 value8; value8 = MAC_REG_R8(R_AX_MPDU_PROC); value8 = enable == 1 ? (value8 | B_AX_A_ICV_ERR) : (value8 & ~B_AX_A_ICV_ERR); MAC_REG_W8(R_AX_MPDU_PROC, value8); return MACSUCCESS; } u32 set_gt3_timer(struct mac_ax_adapter *adapter, struct mac_ax_gt3_cfg *cfg) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 val32; val32 = (cfg->count_en ? B_AX_GT3_COUNT_EN : 0) | (cfg->mode ? B_AX_GT3_MODE : 0) | (cfg->gt3_en ? B_AX_GT3_EN : 0) | (cfg->sort_en ? B_AX_GT3_SORT_EN : 0) | SET_WORD(cfg->timeout, B_AX_GT3_DATA); MAC_REG_W32(R_AX_GT3_CTRL, val32); return MACSUCCESS; } u32 set_cctl_rty_limit(struct mac_ax_adapter *adapter, struct mac_ax_cctl_rty_lmt_cfg *cfg) { #define DFLT_DATA_RTY_LIMIT 32 #define DFLT_RTS_RTY_LIMIT 15 struct rtw_hal_mac_ax_cctl_info info; struct rtw_hal_mac_ax_cctl_info mask; u32 data_rty, rts_rty; PLTFM_MEMSET(&mask, 0, sizeof(struct rtw_hal_mac_ax_cctl_info)); PLTFM_MEMSET(&info, 0, sizeof(struct rtw_hal_mac_ax_cctl_info)); data_rty = cfg->data_lmt_val == 0 ? DFLT_DATA_RTY_LIMIT : cfg->data_lmt_val; rts_rty = cfg->rts_lmt_val == 0 ? DFLT_RTS_RTY_LIMIT : cfg->rts_lmt_val; info.data_txcnt_lmt_sel = cfg->data_lmt_sel; info.data_tx_cnt_lmt = data_rty; info.rts_txcnt_lmt_sel = cfg->rts_lmt_sel; info.rts_txcnt_lmt = rts_rty; mask.data_txcnt_lmt_sel = TXCNT_LMT_MSK; mask.data_tx_cnt_lmt = FWCMD_H2C_CCTRL_DATA_TX_CNT_LMT_MSK; mask.rts_txcnt_lmt_sel = TXCNT_LMT_MSK; mask.rts_txcnt_lmt = FWCMD_H2C_CCTRL_RTS_TXCNT_LMT_MSK; mac_upd_cctl_info(adapter, &info, &mask, cfg->macid, TBL_WRITE_OP); return MACSUCCESS; } u32 get_data_rty_limit(struct mac_ax_adapter *adapter, struct mac_ax_rty_lmt *rty) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 ret = MACSUCCESS; struct mac_role_tbl *role; u32 offset; u8 band; role = mac_role_srch(adapter, rty->macid); if (!role) { PLTFM_MSG_ERR("%s: The MACID%d does not exist\n", __func__, rty->macid); return MACNOITEM; } if (role->info.c_info.data_txcnt_lmt_sel) { rty->tx_cnt = role->info.c_info.data_tx_cnt_lmt; } else { band = role->info.wmm < 2 ? 0 : 1; offset = band == 0 ? R_AX_TXCNT + 2 : R_AX_TXCNT_C1 + 2; ret = check_mac_en(adapter, band, MAC_AX_CMAC_SEL); if (ret == MACSUCCESS) rty->tx_cnt = MAC_REG_R8(offset); } return ret; } u32 set_bacam_mode(struct mac_ax_adapter *adapter, u8 mode_sel) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 val32; val32 = MAC_REG_R32(R_AX_RESPBA_CAM_CTRL) & (~B_AX_BACAM_ENT_CFG); if (mode_sel) MAC_REG_W32(R_AX_RESPBA_CAM_CTRL, val32 | B_AX_BACAM_ENT_CFG); else MAC_REG_W32(R_AX_RESPBA_CAM_CTRL, val32); return MACSUCCESS; } u32 set_xtal_aac(struct mac_ax_adapter *adapter, u8 aac_mode) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u8 val8; val8 = MAC_REG_R8(R_AX_XTAL_ON_CTRL2); val8 &= ~(0x30); val8 |= ((aac_mode & B_AX_AAC_MODE_MSK) << B_AX_AAC_MODE_SH); MAC_REG_W8(R_AX_XTAL_ON_CTRL2, val8); return MACSUCCESS; } u32 set_partial_pld_mode(struct mac_ax_adapter *adapter, u8 enable) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 val32; if (enable) { val32 = MAC_REG_R32(R_AX_SEC_ENG_CTRL); val32 |= B_AX_TX_PARTIAL_MODE; MAC_REG_W32(R_AX_SEC_ENG_CTRL, val32); } else { val32 = MAC_REG_R32(R_AX_SEC_ENG_CTRL); val32 &= ~B_AX_TX_PARTIAL_MODE; MAC_REG_W32(R_AX_SEC_ENG_CTRL, val32); } return MACSUCCESS; } u32 set_nav_padding(struct mac_ax_adapter *adapter, struct mac_ax_nav_padding *nav) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 reg_txop = nav->band ? R_AX_PROT_0_C1 : R_AX_PROT_0; u32 reg_cnt = nav->band ? R_AX_PROT_C1 : R_AX_PROT; u32 ret; u8 val8; #if MAC_AX_FW_REG_OFLD u16 tmp; #endif ret = check_mac_en(adapter, nav->band, MAC_AX_CMAC_SEL); if (ret) return ret; #if MAC_AX_FW_REG_OFLD if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) { tmp = nav->nav_pad_en ? nav->nav_padding : 0; ret = MAC_REG_W16_OFLD((u16)reg_txop, tmp, 0); if (ret != MACSUCCESS) { PLTFM_MSG_ERR("%s: write offload fail %d", __func__, ret); return ret; } ret = MAC_REG_W16_OFLD((u16)reg_cnt, tmp, 0); if (ret != MACSUCCESS) { PLTFM_MSG_ERR("%s: write offload fail %d", __func__, ret); return ret; } ret = MAC_REG_W_OFLD((u16)reg_cnt, B_AX_NAV_OVER_TXOP_EN, nav->over_txop_en ? 1 : 0, 1); if (ret != MACSUCCESS) { PLTFM_MSG_ERR("%s: write offload fail %d", __func__, ret); return ret; } return MACSUCCESS; } #endif if (nav->nav_pad_en) { MAC_REG_W16(reg_txop, nav->nav_padding); MAC_REG_W16(reg_cnt, nav->nav_padding); val8 = MAC_REG_R8(reg_cnt + 2); if (nav->over_txop_en) val8 |= BIT(0); else val8 &= ~BIT(0); MAC_REG_W8(reg_cnt + 2, val8); } else { MAC_REG_W16(reg_txop, 0); MAC_REG_W16(reg_cnt, 0); } return MACSUCCESS; } static void set_delay_tx_cfg(struct mac_ax_adapter *adapter, struct mac_ax_delay_tx_cfg *cfg) { u32 val32; struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); val32 = MAC_REG_R32(R_AX_SS_CTRL); SET_CLR_WORD(val32, cfg->en, B_AX_SS_DELAY_TX_BAND_SEL); MAC_REG_W32(R_AX_SS_CTRL, val32); val32 = SET_WORD(cfg->vovi_to_b0, B_AX_SS_VOVI_TO_0) | SET_WORD(cfg->bebk_to_b0, B_AX_SS_BEBK_TO_0) | SET_WORD(cfg->vovi_to_b1, B_AX_SS_VOVI_TO_1) | SET_WORD(cfg->bebk_to_b1, B_AX_SS_BEBK_TO_1); MAC_REG_W32(R_AX_SS_DELAYTX_TO, val32); val32 = SET_WORD(cfg->vovi_len_b0, B_AX_SS_VOVI_LEN_THR_0) | SET_WORD(cfg->bebk_len_b0, B_AX_SS_BEBK_LEN_THR_0) | SET_WORD(cfg->vovi_len_b1, B_AX_SS_VOVI_LEN_THR_1) | SET_WORD(cfg->bebk_len_b1, B_AX_SS_BEBK_LEN_THR_1); MAC_REG_W32(R_AX_SS_DELAYTX_LEN_THR, val32); } u32 set_core_swr_volt(struct mac_ax_adapter *adapter, enum mac_ax_core_swr_volt volt_sel) { u8 i, j, adjust = 0; s8 sign = 0, v, val8; struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); val8 = adapter->hw_info->core_swr_volt_sel - volt_sel; if (val8 == 0) { return MACSUCCESS; } else if (val8 > 0) { adjust = adapter->hw_info->core_swr_volt_sel - volt_sel; sign = -1; } else { adjust = volt_sel - adapter->hw_info->core_swr_volt_sel; sign = 1; } for (i = 0; i < adjust; i++) { val8 = MAC_REG_R8(R_AX_SPSLDO_ON_CTRL0); v = GET_FIELD(val8, B_AX_VOL_L1); v += sign; if (v < CORE_SWR_VOLT_MIN) v = CORE_SWR_VOLT_MIN; else if (v > CORE_SWR_VOLT_MAX) v = CORE_SWR_VOLT_MAX; val8 = SET_CLR_WORD(val8, v, B_AX_VOL_L1); MAC_REG_W8(R_AX_SPSLDO_ON_CTRL0, val8); for (j = 0; j < POLL_SWR_VOLT_CNT; j++) PLTFM_DELAY_US(POLL_SWR_VOLT_US); } if (volt_sel == MAC_AX_SWR_NORM) { val8 = MAC_REG_R8(R_AX_SPSLDO_ON_CTRL0); val8 = SET_CLR_WORD(val8, adapter->hw_info->core_swr_volt, B_AX_VOL_L1); MAC_REG_W8(R_AX_SPSLDO_ON_CTRL0, val8); } adapter->hw_info->core_swr_volt_sel = volt_sel; return MACSUCCESS; } u32 set_macid_pause(struct mac_ax_adapter *adapter, struct mac_ax_macid_pause_cfg *cfg) { u32 val32; u8 macid_sh = cfg->macid & (32 - 1); u8 macid_grp = cfg->macid >> 5; struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 ret; struct mac_ax_macid_pause_grp grp = {{0}}; ret = check_mac_en(adapter, MAC_AX_BAND_0, MAC_AX_CMAC_SEL); if (ret) return ret; if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY) { if (cfg->pause) { switch (macid_grp) { case 0: val32 = MAC_REG_R32(R_AX_MACID_SLEEP_0); MAC_REG_W32(R_AX_MACID_SLEEP_0, val32 | BIT(macid_sh)); val32 = MAC_REG_R32(R_AX_SS_MACID_PAUSE_0); MAC_REG_W32(R_AX_SS_MACID_PAUSE_0, val32 | BIT(macid_sh)); break; case 1: val32 = MAC_REG_R32(R_AX_MACID_SLEEP_1); MAC_REG_W32(R_AX_MACID_SLEEP_1, val32 | BIT(macid_sh)); val32 = MAC_REG_R32(R_AX_SS_MACID_PAUSE_1); MAC_REG_W32(R_AX_SS_MACID_PAUSE_1, val32 | BIT(macid_sh)); break; case 2: val32 = MAC_REG_R32(R_AX_MACID_SLEEP_2); MAC_REG_W32(R_AX_MACID_SLEEP_2, val32 | BIT(macid_sh)); val32 = MAC_REG_R32(R_AX_SS_MACID_PAUSE_2); MAC_REG_W32(R_AX_SS_MACID_PAUSE_2, val32 | BIT(macid_sh)); break; case 3: val32 = MAC_REG_R32(R_AX_MACID_SLEEP_3); MAC_REG_W32(R_AX_MACID_SLEEP_3, val32 | BIT(macid_sh)); val32 = MAC_REG_R32(R_AX_SS_MACID_PAUSE_3); MAC_REG_W32(R_AX_SS_MACID_PAUSE_3, val32 | BIT(macid_sh)); break; default: break; } } else { switch (macid_grp) { case 0: val32 = MAC_REG_R32(R_AX_MACID_SLEEP_0); MAC_REG_W32(R_AX_MACID_SLEEP_0, val32 & ~(BIT(macid_sh))); val32 = MAC_REG_R32(R_AX_SS_MACID_PAUSE_0); MAC_REG_W32(R_AX_SS_MACID_PAUSE_0, val32 & ~(BIT(macid_sh))); break; case 1: val32 = MAC_REG_R32(R_AX_MACID_SLEEP_1); MAC_REG_W32(R_AX_MACID_SLEEP_1, val32 & ~(BIT(macid_sh))); val32 = MAC_REG_R32(R_AX_SS_MACID_PAUSE_1); MAC_REG_W32(R_AX_SS_MACID_PAUSE_1, val32 & ~(BIT(macid_sh))); break; case 2: val32 = MAC_REG_R32(R_AX_MACID_SLEEP_2); MAC_REG_W32(R_AX_MACID_SLEEP_2, val32 & ~(BIT(macid_sh))); val32 = MAC_REG_R32(R_AX_SS_MACID_PAUSE_2); MAC_REG_W32(R_AX_SS_MACID_PAUSE_2, val32 & ~(BIT(macid_sh))); break; case 3: val32 = MAC_REG_R32(R_AX_MACID_SLEEP_3); MAC_REG_W32(R_AX_MACID_SLEEP_3, val32 & ~(BIT(macid_sh))); val32 = MAC_REG_R32(R_AX_SS_MACID_PAUSE_3); MAC_REG_W32(R_AX_SS_MACID_PAUSE_3, val32 & ~(BIT(macid_sh))); break; default: break; } } } else { grp.mask_grp[macid_grp] = BIT(macid_sh); grp.pause_grp[macid_grp] = cfg->pause << macid_sh; ret = macid_pause(adapter, &grp); if (ret) return ret; } return MACSUCCESS; } u32 macid_pause(struct mac_ax_adapter *adapter, struct mac_ax_macid_pause_grp *grp) { u32 ret, size; #if MAC_AX_PHL_H2C struct rtw_h2c_pkt *h2cb; #else struct h2c_buf *h2cb; #endif u8 *buf; ret = check_mac_en(adapter, MAC_AX_BAND_0, MAC_AX_CMAC_SEL); if (ret) return ret; if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY) return MACNOFW; size = sizeof(struct mac_ax_macid_pause_grp); h2cb = h2cb_alloc(adapter, H2CB_CLASS_CMD); if (!h2cb) return MACNPTR; buf = h2cb_put(h2cb, size); if (!buf) { ret = MACNOBUF; goto fail; } PLTFM_MEMCPY(buf, grp, size); ret = h2c_pkt_set_hdr(adapter, h2cb, FWCMD_TYPE_H2C, FWCMD_H2C_CAT_MAC, FWCMD_H2C_CL_FW_OFLD, FWCMD_H2C_FUNC_MACID_PAUSE, 1, 0); if (ret) goto fail; // return MACSUCCESS if h2c aggregation is enabled and enqueued successfully. // H2C shall be sent by mac_h2c_agg_tx. ret = h2c_agg_enqueue(adapter, h2cb); if (ret == MACSUCCESS) return MACSUCCESS; ret = h2c_pkt_build_txd(adapter, h2cb); if (ret) goto fail; #if MAC_AX_PHL_H2C ret = PLTFM_TX(h2cb); #else ret = PLTFM_TX(h2cb->data, h2cb->len); #endif if (ret) { PLTFM_MSG_ERR("[ERR]platform tx\n"); goto fail; } h2cb_free(adapter, h2cb); return MACSUCCESS; fail: h2cb_free(adapter, h2cb); return ret; } u32 set_ss_quota_mode(struct mac_ax_adapter *adapter, struct mac_ax_ss_quota_mode_ctrl *ctrl) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 val32_wmm, val32_ul, ret; val32_wmm = MAC_REG_R32(R_AX_SS_DL_QUOTA_CTRL); val32_ul = MAC_REG_R32(R_AX_SS_UL_QUOTA_CTRL); switch (ctrl->wmm) { case MAC_AX_SS_WMM0: if (ctrl->mode == MAC_AX_SS_QUOTA_MODE_CNT) MAC_REG_W32(R_AX_SS_DL_QUOTA_CTRL, val32_wmm | B_AX_SS_QUOTA_MODE_0); else MAC_REG_W32(R_AX_SS_DL_QUOTA_CTRL, val32_wmm & ~B_AX_SS_QUOTA_MODE_0); break; case MAC_AX_SS_WMM1: if (ctrl->mode == MAC_AX_SS_QUOTA_MODE_CNT) MAC_REG_W32(R_AX_SS_DL_QUOTA_CTRL, val32_wmm | B_AX_SS_QUOTA_MODE_1); else MAC_REG_W32(R_AX_SS_DL_QUOTA_CTRL, val32_wmm & ~B_AX_SS_QUOTA_MODE_1); break; case MAC_AX_SS_WMM2: if (ctrl->mode == MAC_AX_SS_QUOTA_MODE_CNT) MAC_REG_W32(R_AX_SS_DL_QUOTA_CTRL, val32_wmm | B_AX_SS_QUOTA_MODE_2); else MAC_REG_W32(R_AX_SS_DL_QUOTA_CTRL, val32_wmm & ~B_AX_SS_QUOTA_MODE_2); break; case MAC_AX_SS_WMM3: if (ctrl->mode == MAC_AX_SS_QUOTA_MODE_CNT) MAC_REG_W32(R_AX_SS_DL_QUOTA_CTRL, val32_wmm | B_AX_SS_QUOTA_MODE_3); else MAC_REG_W32(R_AX_SS_DL_QUOTA_CTRL, val32_wmm & ~B_AX_SS_QUOTA_MODE_3); break; case MAC_AX_SS_UL: if (ctrl->mode == MAC_AX_SS_QUOTA_MODE_CNT) MAC_REG_W32(R_AX_SS_UL_QUOTA_CTRL, val32_ul | B_AX_SS_QUOTA_MODE_UL); else MAC_REG_W32(R_AX_SS_UL_QUOTA_CTRL, val32_ul & ~B_AX_SS_QUOTA_MODE_UL); break; } #if MAC_AX_FW_REG_OFLD if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) { switch (ctrl->wmm) { case MAC_AX_SS_WMM0: case MAC_AX_SS_WMM1: case MAC_AX_SS_UL: ret = check_mac_en(adapter, 0, MAC_AX_CMAC_SEL); if (ret != MACSUCCESS) return ret; if (ctrl->mode == MAC_AX_SS_QUOTA_MODE_TIME) { MAC_REG_W_OFLD(R_AX_PTCL_ATM, B_AX_ATM_AIRTIME_EN, 1, 1); } break; case MAC_AX_SS_WMM2: case MAC_AX_SS_WMM3: ret = check_mac_en(adapter, 1, MAC_AX_CMAC_SEL); if (ret != MACSUCCESS) return ret; if (ctrl->mode == MAC_AX_SS_QUOTA_MODE_TIME) { MAC_REG_W_OFLD(R_AX_PTCL_ATM_C1, B_AX_ATM_AIRTIME_EN, 1, 1); } break; } return MACSUCCESS; } #endif switch (ctrl->wmm) { case MAC_AX_SS_WMM0: case MAC_AX_SS_WMM1: case MAC_AX_SS_UL: ret = check_mac_en(adapter, 0, MAC_AX_CMAC_SEL); if (ret != MACSUCCESS) return ret; val32_wmm = MAC_REG_R32(R_AX_PTCL_ATM); if (ctrl->mode == MAC_AX_SS_QUOTA_MODE_TIME) MAC_REG_W32(R_AX_PTCL_ATM, val32_wmm | B_AX_ATM_AIRTIME_EN); break; case MAC_AX_SS_WMM2: case MAC_AX_SS_WMM3: ret = check_mac_en(adapter, 1, MAC_AX_CMAC_SEL); if (ret != MACSUCCESS) return ret; val32_wmm = MAC_REG_R32(R_AX_PTCL_ATM_C1); if (ctrl->mode == MAC_AX_SS_QUOTA_MODE_TIME) MAC_REG_W32(R_AX_PTCL_ATM_C1, val32_wmm | B_AX_ATM_AIRTIME_EN); break; } return MACSUCCESS; } u32 ss_set_quotasetting(struct mac_ax_adapter *adapter, struct mac_ax_ss_quota_setting *para) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 val32; u32 cnt = 1000; if (para->ul_dl == mac_ax_issue_ul) { val32 = (B_AX_SS_OWN | SET_WORD(SS_W_QUOTA_SETTING, B_AX_SS_CMD_SEL) | BIT(23) | SET_WORD(para->val, B_AX_SS_VALUE) | para->macid); MAC_REG_W32(R_AX_SS_SRAM_CTRL_1, val32); } else { val32 = (B_AX_SS_OWN | SET_WORD(SS_W_QUOTA_SETTING, B_AX_SS_CMD_SEL) | SET_WORD(para->ac_type, B_AX_SS_AC) | SET_WORD(para->val, B_AX_SS_VALUE) | para->macid); MAC_REG_W32(R_AX_SS_SRAM_CTRL_1, val32); } while (--cnt) { val32 = MAC_REG_R32(R_AX_SS_SRAM_CTRL_1); if ((val32 & B_AX_SS_OWN) == 0) break; PLTFM_DELAY_US(1); } if (!cnt) { PLTFM_MSG_ERR("SS Set quota setting fail!!\n"); return MACPOLLTO; } return MACSUCCESS; } u32 scheduler_set_prebkf(struct mac_ax_adapter *adapter, struct mac_ax_prebkf_setting *para) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 reg, val32; #if MAC_AX_FW_REG_OFLD u32 ret; #endif reg = para->band == MAC_AX_BAND_1 ? R_AX_PREBKF_CFG_0_C1 : R_AX_PREBKF_CFG_0; #if MAC_AX_FW_REG_OFLD if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) { ret = MAC_REG_W_OFLD((u16)reg, B_AX_PREBKF_TIME_MSK, para->val, 1); if (ret != MACSUCCESS) { PLTFM_MSG_ERR("%s: config fail\n", __func__); return ret; } return MACSUCCESS; } #endif val32 = MAC_REG_R32(reg); val32 = SET_CLR_WORD(val32, para->val, B_AX_PREBKF_TIME); MAC_REG_W32(reg, val32); return MACSUCCESS; } u32 mac_get_tx_cnt(struct mac_ax_adapter *adapter, struct mac_ax_tx_cnt *cnt) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 txcnt_addr; u32 val32; u16 val16; u8 sel; if (cnt->band != 0 && cnt->band != 1) return MACNOITEM; if (check_mac_en(adapter, cnt->band, MAC_AX_CMAC_SEL)) return MACHWNOTEN; txcnt_addr = (cnt->band == MAC_AX_BAND_0) ? R_AX_TX_PPDU_CNT : R_AX_TX_PPDU_CNT_C1; for (sel = 0; sel < MAC_AX_TX_ALLTYPE; sel++) { val16 = MAC_REG_R16(txcnt_addr); val16 = SET_CLR_WORD(val16, sel, B_AX_PPDU_CNT_IDX); MAC_REG_W16(txcnt_addr, val16); PLTFM_DELAY_US(1000); val32 = MAC_REG_R32(txcnt_addr); cnt->txcnt[sel] = GET_FIELD(val32, B_AX_TX_PPDU_CNT); } return MACSUCCESS; } u32 cfg_wdt_isr_rst(struct mac_ax_adapter *adapter) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u8 val = MAC_REG_R8(R_AX_PLATFORM_ENABLE); val = val & ~B_AX_APB_WRAP_EN; MAC_REG_W8(R_AX_PLATFORM_ENABLE, val); val = val | B_AX_APB_WRAP_EN; MAC_REG_W8(R_AX_PLATFORM_ENABLE, val); return MACSUCCESS; } u32 mac_clr_tx_cnt(struct mac_ax_adapter *adapter, struct mac_ax_tx_cnt *cnt) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u16 txcnt_addr; u16 val16; u16 to; u8 i; if (cnt->band != 0 && cnt->band != 1) return MACNOITEM; if (check_mac_en(adapter, cnt->band, MAC_AX_CMAC_SEL)) return MACHWNOTEN; if (cnt->sel > MAC_AX_TX_ALLTYPE) return MACNOITEM; txcnt_addr = (cnt->band == MAC_AX_BAND_0) ? R_AX_TX_PPDU_CNT : R_AX_TX_PPDU_CNT_C1; #if MAC_AX_FW_REG_OFLD u32 ret; if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) { for (i = 0; i < MAC_AX_TX_ALLTYPE; i++) { if (cnt->sel == MAC_AX_TX_ALLTYPE || i == cnt->sel) { ret = MAC_REG_W_OFLD(txcnt_addr, B_AX_PPDU_CNT_RIDX_MSK << B_AX_PPDU_CNT_RIDX_SH, i, 0); if (ret != MACSUCCESS) { PLTFM_MSG_ERR("%s: write offload fail;" "offset: %u, ret: %u\n", __func__, txcnt_addr, ret); return ret; } ret = MAC_REG_W_OFLD(txcnt_addr, B_AX_RST_PPDU_CNT, 1, 0); if (ret != MACSUCCESS) { PLTFM_MSG_ERR("%s: write offload fail;" "offset: %u, ret: %u\n", __func__, txcnt_addr, ret); return ret; } ret = MAC_REG_P_OFLD(txcnt_addr, B_AX_RST_PPDU_CNT, 0, (cnt->sel != MAC_AX_TX_ALLTYPE || i == MAC_AX_TX_ALLTYPE - 1) ? 1 : 0); if (ret != MACSUCCESS) { PLTFM_MSG_ERR("%s: poll offload fail;" "offset: %u, ret: %u\n", __func__, txcnt_addr, ret); return ret; } } } return MACSUCCESS; } #endif to = 1000; for (i = 0; i < MAC_AX_TX_ALLTYPE; i++) { if (cnt->sel == MAC_AX_TX_ALLTYPE || i == cnt->sel) { val16 = MAC_REG_R16(txcnt_addr); val16 = SET_CLR_WORD(val16, i, B_AX_PPDU_CNT_RIDX) | B_AX_RST_PPDU_CNT; MAC_REG_W16(txcnt_addr, val16); while (to--) { val16 = MAC_REG_R16(txcnt_addr); if (!(val16 & B_AX_RST_PPDU_CNT)) break; PLTFM_DELAY_US(5); } if (to == 0) return MACPOLLTO; } } return MACSUCCESS; } u32 mac_set_hw_value(struct mac_ax_adapter *adapter, enum mac_ax_hw_id hw_id, void *val) { u32 ret = MACSUCCESS; if (!val) { PLTFM_MSG_ERR("[ERR]: the parameter is NULL in %s\n", __func__); return MACNPTR; } switch (hw_id) { case MAC_AX_HW_SETTING: break; case MAC_AX_HW_SET_ID_PAUSE: ret = set_macid_pause(adapter, (struct mac_ax_macid_pause_cfg *)val); if (ret != MACSUCCESS) return ret; break; case MAC_AX_HW_SET_MULTI_ID_PAUSE: ret = macid_pause(adapter, (struct mac_ax_macid_pause_grp *)val); if (ret != MACSUCCESS) return ret; break; case MAC_AX_HW_SET_SCH_TXEN_CFG: ret = set_hw_sch_tx_en(adapter, (struct mac_ax_sch_tx_en_cfg *)val); break; case MAC_AX_HW_SET_AMPDU_CFG: ret = set_hw_ampdu_cfg(adapter, (struct mac_ax_ampdu_cfg *)val); break; case MAC_AX_HW_SET_USR_EDCA_PARAM: ret = set_hw_usr_edca_param(adapter, (struct mac_ax_usr_edca_param *)val); break; case MAC_AX_HW_SET_USR_TX_RPT_CFG: ret = set_hw_usr_tx_rpt_cfg(adapter, (struct mac_ax_usr_tx_rpt_cfg *)val); break; case MAC_AX_HW_SET_EDCA_PARAM: ret = set_hw_edca_param(adapter, (struct mac_ax_edca_param *)val); break; case MAC_AX_HW_SET_EDCCA_PARAM: ret = set_hw_edcca_param(adapter, (struct mac_ax_edcca_param *)val); if (ret != MACSUCCESS) return ret; break; case MAC_AX_HW_SET_MUEDCA_PARAM: ret = set_hw_muedca_param(adapter, (struct mac_ax_muedca_param *)val); break; case MAC_AX_HW_SET_MUEDCA_CTRL: ret = set_hw_muedca_ctrl(adapter, (struct mac_ax_muedca_cfg *)val); break; case MAC_AX_HW_SET_TBPPDU_CTRL: ret = set_hw_tb_ppdu_ctrl(adapter, (struct mac_ax_tb_ppdu_ctrl *)val); break; case MAC_AX_HW_SET_HOST_RPR: set_host_rpr(adapter, (struct mac_ax_host_rpr_cfg *)val); break; case MAC_AX_HW_SET_DELAYTX_CFG: set_delay_tx_cfg(adapter, (struct mac_ax_delay_tx_cfg *)val); break; case MAC_AX_HW_SET_BW_CFG: ret = cfg_mac_bw(adapter, (struct mac_ax_cfg_bw *)val); break; case MAC_AX_HW_SET_CH_BUSY_STAT_CFG: ret = set_hw_ch_busy_cnt(adapter, (struct mac_ax_ch_busy_cnt_cfg *)val); if (ret != MACSUCCESS) return ret; break; case MAC_AX_HW_SET_LIFETIME_CFG: ret = set_hw_lifetime_cfg(adapter, (struct mac_ax_lifetime_cfg *)val); if (ret != MACSUCCESS) return ret; break; case MAC_AX_HW_EN_BB_RF: ret = set_enable_bb_rf(adapter, *(u8 *)val); if (ret != MACSUCCESS) return ret; break; case MAC_AX_HW_SET_APP_FCS: set_append_fcs(adapter, *(u8 *)val); break; case MAC_AX_HW_SET_RX_ICVERR: set_accept_icverr(adapter, *(u8 *)val); break; case MAC_AX_HW_SET_CCTL_RTY_LMT: set_cctl_rty_limit(adapter, (struct mac_ax_cctl_rty_lmt_cfg *)val); break; case MAC_AX_HW_SET_COEX_GNT: ret = mac_cfg_gnt(adapter, (struct mac_ax_coex_gnt *)val); break; case MAC_AX_HW_SET_SCOREBOARD: mac_cfg_sb(adapter, *(u32 *)val); break; case MAC_AX_HW_SET_POLLUTED: mac_cfg_plt(adapter, (struct mac_ax_plt *)val); break; case MAC_AX_HW_SET_COEX_CTRL: mac_cfg_ctrl_path(adapter, *(u32 *)val); break; case MAC_AX_HW_SET_CLR_TX_CNT: ret = mac_clr_tx_cnt(adapter, (struct mac_ax_tx_cnt *)val); break; case MAC_AX_HW_SET_SLOT_TIME: mac_set_slot_time(adapter, *(enum mac_ax_slot_time *)val); break; case MAC_AX_HW_SET_XTAL_AAC_MODE: set_xtal_aac(adapter, *(u8 *)val); break; case MAC_AX_HW_SET_NAV_PADDING: ret = set_nav_padding(adapter, (struct mac_ax_nav_padding *)val); break; case MAC_AX_HW_SET_MAX_TX_TIME: ret = mac_set_cctl_max_tx_time(adapter, (struct mac_ax_max_tx_time *) val); break; case MAC_AX_HW_SET_SS_QUOTA_MODE: ret = set_ss_quota_mode(adapter, (struct mac_ax_ss_quota_mode_ctrl *)val); break; case MAC_AX_HW_SET_SS_QUOTA_SETTING: ret = ss_set_quotasetting(adapter, (struct mac_ax_ss_quota_setting *)val); break; case MAC_AX_HW_SET_SCHE_PREBKF: ret = scheduler_set_prebkf(adapter, (struct mac_ax_prebkf_setting *)val); break; case MAC_AX_HW_SET_WDT_ISR_RST: ret = cfg_wdt_isr_rst(adapter); break; case MAC_AX_HW_SET_RESP_ACK: ret = set_mac_resp_ack(adapter, (u32 *)val); break; case MAC_AX_HW_SET_HW_RTS_TH: ret = mac_set_hw_rts_th(adapter, (struct mac_ax_hw_rts_th *)val); break; case MAC_AX_HW_SET_TX_RU26_TB: ret = mac_set_tx_ru26_tb(adapter, *(u8 *)val); break; case MAC_AX_HW_SET_BACAM_MODE_SEL: ret = set_bacam_mode(adapter, *(u8 *)val); break; case MAC_AX_HW_SET_CORE_SWR_VOLT: ret = set_core_swr_volt(adapter, *(enum mac_ax_core_swr_volt *)val); break; case MAC_AX_HW_SET_PARTIAL_PLD_MODE: ret = set_partial_pld_mode(adapter, *(u8 *)val); break; case MAC_AX_HW_SET_RRSR_CFG: ret = mac_set_rrsr_cfg(adapter, (struct mac_ax_rrsr_cfg *)val); break; case MAC_AX_HW_SET_CTS_RRSR_CFG: ret = mac_set_cts_rrsr_cfg(adapter, (struct mac_ax_cts_rrsr_cfg *)val); break; case MAC_AX_HW_SET_GT3_TIMER: ret = set_gt3_timer(adapter, (struct mac_ax_gt3_cfg *)val); break; #if MAC_AX_SDIO_SUPPORT case MAC_AX_HW_SDIO_INFO: set_info_sdio(adapter, (struct mac_ax_sdio_info *)val); break; case MAC_AX_HW_SDIO_TX_MODE: ret = tx_mode_cfg_sdio(adapter, *(enum mac_ax_sdio_tx_mode *)val); break; case MAC_AX_HW_SDIO_RX_AGG: rx_agg_cfg_sdio(adapter, (struct mac_ax_rx_agg_cfg *)val); break; case MAC_AX_HW_SDIO_TX_AGG: ret = tx_agg_cfg_sdio(adapter, (struct mac_ax_sdio_txagg_cfg *)val); break; case MAC_AX_HW_SDIO_AVAL_PAGE: aval_page_cfg_sdio(adapter, (struct mac_ax_aval_page_cfg *)val); break; case MAC_AX_HW_SDIO_MON_WT: set_wt_cfg_sdio(adapter, *(u8 *)val); break; #endif #if MAC_AX_PCIE_SUPPORT case MAC_AX_HW_PCIE_CFGSPC_SET: ret = cfgspc_set_pcie(adapter, (struct mac_ax_pcie_cfgspc_param *)val); break; case MAC_AX_HW_PCIE_RST_BDRAM: ret = rst_bdram_pcie(adapter, *(u8 *)val); break; case MAX_AX_HW_PCIE_LTR_SW_TRIGGER: ret = ltr_sw_trigger(adapter, *(enum mac_ax_pcie_ltr_sw_ctrl *)val); break; case MAX_AX_HW_PCIE_MIT: ret = pcie_trx_mit(adapter, (struct mac_ax_pcie_trx_mitigation *)val); break; case MAX_AX_HW_PCIE_L2_LEAVE: ret = set_pcie_l2_leave(adapter, *(u8 *)val); break; #endif default: return MACNOITEM; } return ret; } u32 get_macid_pause(struct mac_ax_adapter *adapter, struct mac_ax_macid_pause_cfg *cfg) { u32 val32 = 0; u8 macid_grp = cfg->macid >> 5; struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 ret; ret = check_mac_en(adapter, MAC_AX_BAND_0, MAC_AX_CMAC_SEL); if (ret) return ret; switch (macid_grp) { case 0: val32 = MAC_REG_R32(R_AX_SS_MACID_PAUSE_0) | MAC_REG_R32(R_AX_MACID_SLEEP_0); break; case 1: val32 = MAC_REG_R32(R_AX_SS_MACID_PAUSE_1) | MAC_REG_R32(R_AX_MACID_SLEEP_1); break; case 2: val32 = MAC_REG_R32(R_AX_SS_MACID_PAUSE_2) | MAC_REG_R32(R_AX_MACID_SLEEP_2); break; case 3: val32 = MAC_REG_R32(R_AX_SS_MACID_PAUSE_3) | MAC_REG_R32(R_AX_MACID_SLEEP_3); break; default: break; } cfg->pause = (u8)((val32 & BIT(cfg->macid & (32 - 1))) ? 1 : 0); return MACSUCCESS; } u32 get_ss_wmm_tbl(struct mac_ax_adapter *adapter, struct mac_ax_ss_wmm_tbl_ctrl *ctrl) { u32 val32; struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); val32 = MAC_REG_R32(R_AX_SS_CTRL); switch (ctrl->wmm) { case 0: ctrl->wmm_mapping = (enum mac_ax_ss_wmm_tbl)GET_FIELD(val32, B_AX_SS_WMM_SEL_0); break; case 1: ctrl->wmm_mapping = (enum mac_ax_ss_wmm_tbl)GET_FIELD(val32, B_AX_SS_WMM_SEL_1); break; case 2: ctrl->wmm_mapping = (enum mac_ax_ss_wmm_tbl)GET_FIELD(val32, B_AX_SS_WMM_SEL_2); break; case 3: ctrl->wmm_mapping = (enum mac_ax_ss_wmm_tbl)GET_FIELD(val32, B_AX_SS_WMM_SEL_3); break; default: return MACNOITEM; } return MACSUCCESS; } static void get_delay_tx_cfg(struct mac_ax_adapter *adapter, struct mac_ax_delay_tx_cfg *cfg) { u32 val32; struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); val32 = MAC_REG_R32(R_AX_SS_CTRL); cfg->en = (enum mac_ax_delay_tx_en)GET_FIELD(val32, B_AX_SS_DELAY_TX_BAND_SEL); val32 = MAC_REG_R32(R_AX_SS_DELAYTX_TO); cfg->vovi_to_b0 = GET_FIELD(val32, B_AX_SS_VOVI_TO_0); cfg->bebk_to_b0 = GET_FIELD(val32, B_AX_SS_BEBK_TO_0); cfg->vovi_to_b1 = GET_FIELD(val32, B_AX_SS_VOVI_TO_1); cfg->bebk_to_b1 = GET_FIELD(val32, B_AX_SS_BEBK_TO_1); val32 = MAC_REG_R32(R_AX_SS_DELAYTX_LEN_THR); cfg->vovi_len_b0 = GET_FIELD(val32, B_AX_SS_VOVI_LEN_THR_0); cfg->bebk_len_b0 = GET_FIELD(val32, B_AX_SS_BEBK_LEN_THR_0); cfg->vovi_len_b1 = GET_FIELD(val32, B_AX_SS_VOVI_LEN_THR_1); cfg->bebk_len_b1 = GET_FIELD(val32, B_AX_SS_BEBK_LEN_THR_1); } static u32 get_append_fcs(struct mac_ax_adapter *adapter, u8 *enable) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); *enable = MAC_REG_R8(R_AX_MPDU_PROC) & B_AX_APPEND_FCS ? 1 : 0; return MACSUCCESS; } static u32 get_accept_icverr(struct mac_ax_adapter *adapter, u8 *enable) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); *enable = MAC_REG_R8(R_AX_MPDU_PROC) & B_AX_A_ICV_ERR ? 1 : 0; return MACSUCCESS; } u32 get_bacam_mode(struct mac_ax_adapter *adapter, u8 *mode_sel) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); *mode_sel = MAC_REG_R8(R_AX_RESPBA_CAM_CTRL) & B_AX_BACAM_ENT_CFG ? 1 : 0; return MACSUCCESS; } u32 get_pwr_state(struct mac_ax_adapter *adapter, enum mac_ax_mac_pwr_st *st) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 val; val = GET_FIELD(MAC_REG_R32(R_AX_IC_PWR_STATE), B_AX_WLMAC_PWR_STE); if (val == MAC_AX_MAC_OFF) { *st = MAC_AX_MAC_OFF; adapter->mac_pwr_info.pwr_in_lps = 0; adapter->sm.fw_rst = MAC_AX_FW_RESET_IDLE; adapter->sm.pwr = MAC_AX_PWR_OFF; adapter->sm.mac_rdy = MAC_AX_MAC_NOT_RDY; PLTFM_MSG_WARN("WL MAC is in off state.\n"); } else if (val == MAC_AX_MAC_ON) { *st = MAC_AX_MAC_ON; } else if (val == MAC_AX_MAC_LPS) { *st = MAC_AX_MAC_LPS; } else { PLTFM_MSG_ERR("Unexpected MAC state = 0x%X\n", val); return MACPWRSTAT; } return MACSUCCESS; } void get_dflt_nav(struct mac_ax_adapter *adapter, u16 *nav) { /* data NAV is consist of SIFS and ACK/BA time */ /* currently, we use SIFS + 64-bitmap BA as default NAV */ /* we use OFDM-6M to estimate BA time */ /* BA time = PLCP header(20us) + 32 bytes/data_rate */ *nav = 63; } u32 mac_get_hw_value(struct mac_ax_adapter *adapter, enum mac_ax_hw_id hw_id, void *val) { u32 ret = MACSUCCESS; struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); if (!val) { PLTFM_MSG_ERR("[ERR]: the parameter is NULL in %s\n", __func__); return MACNPTR; } switch (hw_id) { case MAC_AX_HW_MAPPING: break; case MAC_AX_HW_GET_EFUSE_SIZE: *(u32 *)val = adapter->hw_info->efuse_size + adapter->hw_info->dav_efuse_size; break; case MAC_AX_HW_GET_LOGICAL_EFUSE_SIZE: *(u32 *)val = adapter->hw_info->log_efuse_size + adapter->hw_info->dav_log_efuse_size; break; case MAC_AX_HW_GET_LIMIT_LOG_EFUSE_SIZE: switch (adapter->hw_info->intf) { case MAC_AX_INTF_PCIE: *(u32 *)val = adapter->hw_info->limit_efuse_size_pcie; break; case MAC_AX_INTF_USB: *(u32 *)val = adapter->hw_info->limit_efuse_size_usb; break; case MAC_AX_INTF_SDIO: *(u32 *)val = adapter->hw_info->limit_efuse_size_sdio; break; default: *(u32 *)val = adapter->hw_info->log_efuse_size; break; } *(u32 *)val += adapter->hw_info->dav_log_efuse_size; break; case MAC_AX_HW_GET_BT_EFUSE_SIZE: *(u32 *)val = adapter->hw_info->bt_efuse_size; break; case MAC_AX_HW_GET_BT_LOGICAL_EFUSE_SIZE: *(u32 *)val = adapter->hw_info->bt_log_efuse_size; break; case MAC_AX_HW_GET_EFUSE_MASK_SIZE: *(u32 *)val = (adapter->hw_info->log_efuse_size + adapter->hw_info->dav_log_efuse_size) >> 4; break; case MAC_AX_HW_GET_LIMIT_EFUSE_MASK_SIZE: switch (adapter->hw_info->intf) { case MAC_AX_INTF_PCIE: *(u32 *)val = adapter->hw_info->limit_efuse_size_pcie; break; case MAC_AX_INTF_USB: *(u32 *)val = adapter->hw_info->limit_efuse_size_usb; break; case MAC_AX_INTF_SDIO: *(u32 *)val = adapter->hw_info->limit_efuse_size_sdio; break; default: *(u32 *)val = adapter->hw_info->log_efuse_size; break; } *(u32 *)val += adapter->hw_info->dav_log_efuse_size; *(u32 *)val = *(u32 *)val >> 4; break; case MAC_AX_HW_GET_BT_EFUSE_MASK_SIZE: *(u32 *)val = adapter->hw_info->bt_log_efuse_size >> 4; break; case MAC_AX_HW_GET_EFUSE_VERSION_SIZE: *(u32 *)val = adapter->hw_info->efuse_version_size; break; case MAC_AX_HW_GET_ID_PAUSE: ret = get_macid_pause(adapter, (struct mac_ax_macid_pause_cfg *)val); if (ret != MACSUCCESS) return ret; break; case MAC_AX_HW_GET_SCH_TXEN_STATUS: ret = get_hw_sch_tx_en(adapter, (struct mac_ax_sch_tx_en_cfg *)val); if (ret != MACSUCCESS) return ret; break; case MAC_AX_HW_GET_EDCA_PARAM: ret = get_hw_edca_param(adapter, (struct mac_ax_edca_param *)val); if (ret != MACSUCCESS) return ret; break; case MAC_AX_HW_GET_TBPPDU_CTRL: ret = get_hw_tb_ppdu_ctrl(adapter, (struct mac_ax_tb_ppdu_ctrl *)val); if (ret != MACSUCCESS) return ret; break; case MAC_AX_HW_GET_DELAYTX_CFG: get_delay_tx_cfg(adapter, (struct mac_ax_delay_tx_cfg *)val); break; case MAC_AX_HW_GET_SS_WMM_TBL: ret = get_ss_wmm_tbl(adapter, (struct mac_ax_ss_wmm_tbl_ctrl *)val); if (ret != MACSUCCESS) return ret; break; case MAC_AX_HW_GET_CH_STAT_CNT: ret = get_hw_ch_stat_cnt(adapter, (struct mac_ax_ch_stat_cnt *)val); if (ret != MACSUCCESS) return ret; break; case MAC_AX_HW_GET_LIFETIME_CFG: ret = get_hw_lifetime_cfg(adapter, (struct mac_ax_lifetime_cfg *)val); if (ret != MACSUCCESS) return ret; break; case MAC_AX_HW_GET_APP_FCS: get_append_fcs(adapter, (u8 *)val); break; case MAC_AX_HW_GET_RX_ICVERR: get_accept_icverr(adapter, (u8 *)val); break; case MAC_AX_HW_GET_PWR_STATE: get_pwr_state(adapter, (enum mac_ax_mac_pwr_st *)val); break; case MAC_AX_HW_GET_SCOREBOARD: *(u32 *)val = MAC_REG_R32(R_AX_SCOREBOARD); break; case MAC_AX_HW_GET_BACAM_MODE_SEL: get_bacam_mode(adapter, (u8 *)val); break; #if MAC_AX_SDIO_SUPPORT case MAC_AX_HW_SDIO_TX_AGG_SIZE: *(u16 *)val = adapter->sdio_info.tx_align_size; break; #endif case MAC_AX_HW_GET_WAKE_REASON: ret = get_wake_reason(adapter, (u8 *)val); if (ret != 0) return ret; break; case MAC_AX_HW_GET_COEX_GNT: ret = mac_get_gnt(adapter, (struct mac_ax_coex_gnt *)val); break; case MAC_AX_HW_GET_COEX_CTRL: mac_get_ctrl_path(adapter, (u32 *)val); break; case MAC_AX_HW_GET_TX_CNT: ret = mac_get_tx_cnt(adapter, (struct mac_ax_tx_cnt *)val); if (ret != 0) return ret; break; case MAC_AX_HW_GET_TSF: mac_get_tsf(adapter, (struct mac_ax_port_tsf *)val); break; case MAC_AX_HW_GET_MAX_TX_TIME: ret = mac_get_max_tx_time(adapter, (struct mac_ax_max_tx_time *)val); break; case MAC_AX_HW_GET_POLLUTED_CNT: mac_get_bt_polt_cnt(adapter, (struct mac_ax_bt_polt_cnt *)val); break; case MAC_AX_HW_GET_DATA_RTY_LMT: get_data_rty_limit(adapter, (struct mac_ax_rty_lmt *)val); break; case MAC_AX_HW_GET_DFLT_NAV: get_dflt_nav(adapter, (u16 *)val); break; case MAC_AX_HW_GET_FW_CAP: ret = mac_get_fw_cap(adapter, (u32 *)val); break; case MAC_AX_HW_GET_RRSR_CFG: ret = mac_get_rrsr_cfg(adapter, (struct mac_ax_rrsr_cfg *)val); break; case MAC_AX_HW_GET_CTS_RRSR_CFG: ret = mac_get_cts_rrsr_cfg(adapter, (struct mac_ax_cts_rrsr_cfg *)val); break; case MAC_AX_HW_GET_USB_STS: ret = ops->get_rx_state(adapter, (u32 *)val); break; default: return MACNOITEM; } return ret; } u32 cfg_mac_bw(struct mac_ax_adapter *adapter, struct mac_ax_cfg_bw *cfg) { u32 value32 = 0; u8 value8 = 0; u8 chk_val8 = 0; struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); struct rtw_hal_com_t *hal_com = (struct rtw_hal_com_t *)adapter->drv_adapter; u8 txsc20 = 0, txsc40 = 0, txsc80 = 0; switch (cfg->cbw) { case CHANNEL_WIDTH_160: txsc80 = rtw_hal_bb_get_txsc(hal_com, cfg->pri_ch, cfg->central_ch, cfg->cbw, CHANNEL_WIDTH_80); /* fall through */ case CHANNEL_WIDTH_80: txsc40 = rtw_hal_bb_get_txsc(hal_com, cfg->pri_ch, cfg->central_ch, cfg->cbw, CHANNEL_WIDTH_40); /* fall through */ case CHANNEL_WIDTH_40: txsc20 = rtw_hal_bb_get_txsc(hal_com, cfg->pri_ch, cfg->central_ch, cfg->cbw, CHANNEL_WIDTH_20); break; default: break; } #if MAC_AX_FW_REG_OFLD u32 ret; if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) { if (cfg->band) {//BAND1 value8 = MAC_REG_R8(R_AX_WMAC_RFMOD_C1); chk_val8 = MAC_REG_R8(R_AX_TXRATE_CHK_C1); } else {//BAND0 value8 = MAC_REG_R8(R_AX_WMAC_RFMOD); chk_val8 = MAC_REG_R8(R_AX_TXRATE_CHK); } value8 = value8 & (~(BIT(0) | BIT(1))); chk_val8 = chk_val8 & (~(BIT(0) | BIT(1))); switch (cfg->cbw) { case CHANNEL_WIDTH_160: value8 = value8 | BIT(1) | BIT(0); value32 = txsc20 | (txsc40 << 4) | (txsc80 << 8); //TXSC_160M; break; case CHANNEL_WIDTH_80: value8 = value8 | BIT(1); value32 = txsc20 | (txsc40 << 4); //TXSC_80M; break; case CHANNEL_WIDTH_40: value8 = value8 | BIT(0); value32 = txsc20; //TXSC_40M; break; case CHANNEL_WIDTH_20: value32 = 0; //TXSC_20M; break; default: break; } if (cfg->pri_ch >= CHANNEL_5G) chk_val8 |= B_AX_CHECK_CCK_EN | B_AX_RTS_LIMIT_IN_OFDM6; if (cfg->band) {//BAND1 ret = MAC_REG_W_OFLD(R_AX_WMAC_RFMOD_C1, B_AX_WMAC_RFMOD_MSK, value8, 0); if (ret != MACSUCCESS) { PLTFM_MSG_ERR("%s: config fail\n", __func__); return ret; } ret = MAC_REG_W_OFLD(R_AX_TXRATE_CHK_C1, 0x3, chk_val8, 0); if (ret != MACSUCCESS) { PLTFM_MSG_ERR("%s: config fail\n", __func__); return ret; } ret = MAC_REG_W32_OFLD(R_AX_TX_SUB_CARRIER_VALUE_C1, value32, 1); if (ret != MACSUCCESS) { PLTFM_MSG_ERR("%s: config fail\n", __func__); return ret; } } else { ret = MAC_REG_W_OFLD(R_AX_WMAC_RFMOD, B_AX_WMAC_RFMOD_MSK, value8, 0); if (ret != MACSUCCESS) { PLTFM_MSG_ERR("%s: config fail\n", __func__); return ret; } ret = MAC_REG_W_OFLD(R_AX_TXRATE_CHK, 0x3, chk_val8, 0); if (ret != MACSUCCESS) { PLTFM_MSG_ERR("%s: config fail\n", __func__); return ret; } ret = MAC_REG_W32_OFLD(R_AX_TX_SUB_CARRIER_VALUE, value32, 1); if (ret != MACSUCCESS) { PLTFM_MSG_ERR("%s: config fail\n", __func__); return ret; } } return MACSUCCESS; } #endif if (cfg->band) {//BAND1 value8 = MAC_REG_R8(R_AX_WMAC_RFMOD_C1); chk_val8 = MAC_REG_R8(R_AX_TXRATE_CHK_C1); } else {//BAND0 value8 = MAC_REG_R8(R_AX_WMAC_RFMOD); chk_val8 = MAC_REG_R8(R_AX_TXRATE_CHK); } value8 = value8 & (~(BIT(0) | BIT(1))); chk_val8 = chk_val8 & (~(BIT(0) | BIT(1))); switch (cfg->cbw) { case CHANNEL_WIDTH_160: value8 = value8 | BIT(1) | BIT(0); value32 = txsc20 | (txsc40 << 4) | (txsc80 << 8); //TXSC_160M; break; case CHANNEL_WIDTH_80: value8 = value8 | BIT(1); value32 = txsc20 | (txsc40 << 4); //TXSC_80M; break; case CHANNEL_WIDTH_40: value8 = value8 | BIT(0); value32 = txsc20; //TXSC_40M; break; case CHANNEL_WIDTH_20: value32 = 0; //TXSC_20M; break; default: break; } if (cfg->pri_ch >= CHANNEL_5G) chk_val8 |= B_AX_CHECK_CCK_EN | B_AX_RTS_LIMIT_IN_OFDM6; if (cfg->band) {//BAND1 MAC_REG_W8(R_AX_WMAC_RFMOD_C1, value8); MAC_REG_W8(R_AX_TXRATE_CHK_C1, chk_val8); MAC_REG_W32(R_AX_TX_SUB_CARRIER_VALUE_C1, value32); } else { MAC_REG_W8(R_AX_WMAC_RFMOD, value8); MAC_REG_W8(R_AX_TXRATE_CHK, chk_val8); MAC_REG_W32(R_AX_TX_SUB_CARRIER_VALUE, value32); } return MACSUCCESS; } u32 mac_write_lte(struct mac_ax_adapter *adapter, const u32 offset, u32 val) { u32 cnt; struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); #if MAC_AX_FW_REG_OFLD u32 ret; if (adapter->sm.fwdl != MAC_AX_FWDL_INIT_RDY) { cnt = 1000; while ((MAC_REG_R8(R_AX_LTE_CTRL + 3) & BIT(5)) == 0) { if (cnt == 0) { PLTFM_MSG_ERR("[ERR]lte not ready(W)\n"); return MACPOLLTO; } cnt--; PLTFM_DELAY_US(50); } PLTFM_MUTEX_LOCK(&adapter->hw_info->lte_rlock); MAC_REG_W32(R_AX_LTE_WDATA, val); MAC_REG_W32(R_AX_LTE_CTRL, 0xC00F0000 | offset); PLTFM_MUTEX_UNLOCK(&adapter->hw_info->lte_rlock); } else { ret = MAC_REG_P_OFLD(R_AX_LTE_CTRL, B_AX_LTE_RDY, 1, 0); if (ret != MACSUCCESS) return ret; ret = MAC_REG_W32_OFLD(R_AX_LTE_WDATA, val, 0); if (ret != MACSUCCESS) return ret; ret = MAC_REG_W32_OFLD(R_AX_LTE_WDATA, 0xC00F0000 | offset, 1); if (ret != MACSUCCESS) return ret; } #else cnt = 1000; while ((MAC_REG_R8(R_AX_LTE_CTRL + 3) & BIT(5)) == 0) { if (cnt == 0) { PLTFM_MSG_ERR("[ERR]lte not ready(W)\n"); return MACPOLLTO; } cnt--; PLTFM_DELAY_US(50); } PLTFM_MUTEX_LOCK(&adapter->hw_info->lte_rlock); MAC_REG_W32(R_AX_LTE_WDATA, val); MAC_REG_W32(R_AX_LTE_CTRL, 0xC00F0000 | offset); PLTFM_MUTEX_UNLOCK(&adapter->hw_info->lte_rlock); #endif return MACSUCCESS; } u32 mac_read_lte(struct mac_ax_adapter *adapter, const u32 offset, u32 *val) { u32 cnt; struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); cnt = 1000; while ((MAC_REG_R8(R_AX_LTE_CTRL + 3) & BIT(5)) == 0) { if (cnt == 0) { PLTFM_MSG_ERR("[ERR]lte not ready(W)\n"); break; } cnt--; PLTFM_DELAY_US(50); } PLTFM_MUTEX_LOCK(&adapter->hw_info->lte_rlock); MAC_REG_W32(R_AX_LTE_CTRL, 0x800F0000 | offset); *val = MAC_REG_R32(R_AX_LTE_RDATA); PLTFM_MUTEX_UNLOCK(&adapter->hw_info->lte_rlock); return MACSUCCESS; } u32 mac_write_xtal_si(struct mac_ax_adapter *adapter, u8 offset, u8 val, u8 bitmask) { u32 cnt = 0; u32 write_val = 0; struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); cnt = XTAL_SI_POLLING_CNT; write_val = SET_CLR_WORD(write_val, offset, B_AX_WL_XTAL_SI_ADDR); write_val = SET_CLR_WORD(write_val, val, B_AX_WL_XTAL_SI_DATA); write_val = SET_CLR_WORD(write_val, bitmask, B_AX_WL_XTAL_SI_BITMASK); write_val = SET_CLR_WORD(write_val, XTAL_SI_NORMAL_WRITE, B_AX_WL_XTAL_SI_MODE); write_val = (write_val | B_AX_WL_XTAL_SI_CMD_POLL); MAC_REG_W32(R_AX_WLAN_XTAL_SI_CTRL, write_val); while ((MAC_REG_R32(R_AX_WLAN_XTAL_SI_CTRL) & B_AX_WL_XTAL_SI_CMD_POLL) == B_AX_WL_XTAL_SI_CMD_POLL) { if (!cnt) { PLTFM_MSG_ERR("[ERR]xtal si not ready(W)\n"); return MACPOLLTO; } cnt--; PLTFM_DELAY_US(XTAL_SI_POLLING_DLY_US); } return MACSUCCESS; } u32 mac_read_xtal_si(struct mac_ax_adapter *adapter, u8 offset, u8 *val) { u32 cnt = 0; u32 write_val = 0; struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); cnt = XTAL_SI_POLLING_CNT; write_val = SET_CLR_WORD(write_val, offset, B_AX_WL_XTAL_SI_ADDR); write_val = SET_CLR_WORD(write_val, 0x00, B_AX_WL_XTAL_SI_DATA); write_val = SET_CLR_WORD(write_val, 0x00, B_AX_WL_XTAL_SI_BITMASK); write_val = SET_CLR_WORD(write_val, XTAL_SI_NORMAL_READ, B_AX_WL_XTAL_SI_MODE); write_val = (write_val | B_AX_WL_XTAL_SI_CMD_POLL); MAC_REG_W32(R_AX_WLAN_XTAL_SI_CTRL, write_val); while ((MAC_REG_R32(R_AX_WLAN_XTAL_SI_CTRL) & B_AX_WL_XTAL_SI_CMD_POLL) == B_AX_WL_XTAL_SI_CMD_POLL) { if (!cnt) { PLTFM_MSG_ERR("[ERR]xtal_si not ready(R)\n"); return MACPOLLTO; } cnt--; PLTFM_DELAY_US(XTAL_SI_POLLING_DLY_US); } *val = MAC_REG_R8(R_AX_WLAN_XTAL_SI_CTRL + 1); return MACSUCCESS; } u32 set_host_rpr(struct mac_ax_adapter *adapter, struct mac_ax_host_rpr_cfg *cfg) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); struct mac_ax_host_rpr_cfg *def_cfg; enum mac_ax_host_rpr_mode mode; u8 is_poh; u32 val32, nval32; u32 ret = MACSUCCESS; if (adapter->hw_info->intf == MAC_AX_INTF_PCIE) { ret = is_qta_poh(adapter, adapter->dle_info.qta_mode, &is_poh); if (ret) { PLTFM_MSG_ERR("is qta poh check fail %d\n", ret); return ret; } def_cfg = is_poh ? &rpr_cfg_poh : &rpr_cfg_stf; mode = is_poh ? MAC_AX_RPR_MODE_POH : MAC_AX_RPR_MODE_STF; } else { def_cfg = &rpr_cfg_stf; mode = MAC_AX_RPR_MODE_STF; } val32 = MAC_REG_R32(R_AX_WDRLS_CFG); nval32 = SET_CLR_WORD(val32, mode, B_AX_WDRLS_MODE); if (nval32 != val32) MAC_REG_W32(R_AX_WDRLS_CFG, nval32); val32 = MAC_REG_R32(R_AX_RLSRPT0_CFG0); nval32 = val32; if ((cfg->txok_en == MAC_AX_FUNC_DEF && def_cfg->txok_en == MAC_AX_FUNC_EN) || cfg->txok_en == MAC_AX_FUNC_EN) nval32 |= B_WDRLS_FLTR_TXOK; else nval32 &= ~B_WDRLS_FLTR_TXOK; if ((cfg->rty_lmt_en == MAC_AX_FUNC_DEF && def_cfg->rty_lmt_en == MAC_AX_FUNC_EN) || cfg->rty_lmt_en == MAC_AX_FUNC_EN) nval32 |= B_WDRLS_FLTR_RTYLMT; else nval32 &= ~B_WDRLS_FLTR_RTYLMT; if ((cfg->lft_drop_en == MAC_AX_FUNC_DEF && def_cfg->lft_drop_en == MAC_AX_FUNC_EN) || cfg->lft_drop_en == MAC_AX_FUNC_EN) nval32 |= B_WDRLS_FLTR_LIFTIM; else nval32 &= ~B_WDRLS_FLTR_LIFTIM; if ((cfg->macid_drop_en == MAC_AX_FUNC_DEF && def_cfg->macid_drop_en == MAC_AX_FUNC_EN) || cfg->macid_drop_en == MAC_AX_FUNC_EN) nval32 |= B_WDRLS_FLTR_MACID; else nval32 &= ~B_WDRLS_FLTR_MACID; if (nval32 != val32) MAC_REG_W32(R_AX_RLSRPT0_CFG0, nval32); val32 = MAC_REG_R32(R_AX_RLSRPT0_CFG1); nval32 = SET_CLR_WORD(val32, (cfg->agg_def ? def_cfg->agg : cfg->agg), B_AX_RLSRPT0_AGGNUM); nval32 = SET_CLR_WORD(nval32, (cfg->tmr_def ? def_cfg->tmr : cfg->tmr), B_AX_RLSRPT0_TO); if (nval32 != val32) MAC_REG_W32(R_AX_RLSRPT0_CFG1, nval32); return ret; } u32 set_l2_status(struct mac_ax_adapter *adapter) { adapter->sm.l2_st = MAC_AX_L2_EN; return MACSUCCESS; } u32 mac_write_pwr_ofst_mode(struct mac_ax_adapter *adapter, u8 band, struct rtw_tpu_info *tpu) { #if MAC_AX_FW_REG_OFLD u32 cr = (band == HW_BAND_0) ? R_AX_PWR_RATE_OFST_CTRL : R_AX_PWR_RATE_OFST_CTRL_C1; u32 val32 = 0; u32 ret; s8 *tmp = &tpu->pwr_ofst_mode[0]; val32 |= NIB_2_DW(0, 0, 0, tmp[4], tmp[3], tmp[2], tmp[1], tmp[0]); ret = MAC_REG_W_OFLD(cr, 0xFFFFF, val32, 1); if (ret != MACSUCCESS) { PLTFM_MSG_ERR("%s: config fail\n", __func__); return ret; } #else struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 cr = (band == HW_BAND_0) ? R_AX_PWR_RATE_OFST_CTRL : R_AX_PWR_RATE_OFST_CTRL_C1; u32 val32 = 0; s8 *tmp = &tpu->pwr_ofst_mode[0]; val32 = MAC_REG_R32(cr) & ~0xFFFFF; val32 |= NIB_2_DW(0, 0, 0, tmp[4], tmp[3], tmp[2], tmp[1], tmp[0]); MAC_REG_W32(cr, val32); #endif return MACSUCCESS; } u32 mac_write_pwr_ofst_bw(struct mac_ax_adapter *adapter, u8 band, struct rtw_tpu_info *tpu) { #if MAC_AX_FW_REG_OFLD u32 cr = (band == HW_BAND_0) ? R_AX_PWR_LMT_CTRL : R_AX_PWR_LMT_CTRL_C1; u32 val32 = 0; u32 ret; s8 *tmp = &tpu->pwr_ofst_bw[0]; val32 |= NIB_2_DW(0, 0, 0, tmp[4], tmp[3], tmp[2], tmp[1], tmp[0]); ret = MAC_REG_W_OFLD(cr, 0xFFFFF, val32, 1); if (ret != MACSUCCESS) { PLTFM_MSG_ERR("%s: config fail\n", __func__); return ret; } #else struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 cr = (band == HW_BAND_0) ? R_AX_PWR_LMT_CTRL : R_AX_PWR_LMT_CTRL_C1; u32 val32 = 0; s8 *tmp = &tpu->pwr_ofst_bw[0]; val32 = MAC_REG_R32(cr) & ~0xFFFFF; val32 |= NIB_2_DW(0, 0, 0, tmp[4], tmp[3], tmp[2], tmp[1], tmp[0]); MAC_REG_W32(cr, val32); #endif return MACSUCCESS; } u32 mac_write_pwr_ref_reg(struct mac_ax_adapter *adapter, u8 band, struct rtw_tpu_info *tpu) { #if MAC_AX_FW_REG_OFLD u32 cr = (band == HW_BAND_0) ? R_AX_PWR_RATE_CTRL : R_AX_PWR_RATE_CTRL_C1; u32 val32 = 0; u32 ret; val32 |= (((tpu->ref_pow_ofdm & 0x1ff) << 9) | ((tpu->ref_pow_cck & 0x1ff))); ret = MAC_REG_W_OFLD(cr, 0xFFFFC00, val32, 1); if (ret != MACSUCCESS) { PLTFM_MSG_ERR("%s: config fail\n", __func__); return ret; } #else struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 cr = (band == HW_BAND_0) ? R_AX_PWR_RATE_CTRL : R_AX_PWR_RATE_CTRL_C1; u32 val32 = 0; val32 = MAC_REG_R32(cr) & ~0xFFFFC00; val32 |= (((tpu->ref_pow_ofdm & 0x1ff) << 19) | ((tpu->ref_pow_cck & 0x1ff) << 10)); MAC_REG_W32(cr, val32); #endif return MACSUCCESS; } u32 mac_write_pwr_limit_en(struct mac_ax_adapter *adapter, u8 band, struct rtw_tpu_info *tpu) { #if MAC_AX_FW_REG_OFLD u32 cr = (band == HW_BAND_0) ? R_AX_PWR_LMT_CTRL : R_AX_PWR_LMT_CTRL_C1; u32 val32 = 0; u32 ret; if (tpu->pwr_lmt_en) val32 = 3; ret = MAC_REG_W_OFLD(cr, 0x300000, val32, 0); if (ret != MACSUCCESS) { PLTFM_MSG_ERR("%s: config fail\n", __func__); return ret; } val32 = 0; cr = (band == HW_BAND_0) ? R_AX_PWR_RU_LMT_CTRL : R_AX_PWR_RU_LMT_CTRL_C1; if (tpu->pwr_lmt_en) val32 = 1; ret = MAC_REG_W_OFLD(cr, 0x40000, val32, 1); if (ret != MACSUCCESS) { PLTFM_MSG_ERR("%s: config fail\n", __func__); return ret; } #else struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 cr = (band == HW_BAND_0) ? R_AX_PWR_LMT_CTRL : R_AX_PWR_LMT_CTRL_C1; u32 val32 = 0; val32 = MAC_REG_R32(cr) & ~0x300000; if (tpu->pwr_lmt_en) val32 |= 0x300000; MAC_REG_W32(cr, val32); cr = (band == HW_BAND_0) ? R_AX_PWR_RU_LMT_CTRL : R_AX_PWR_RU_LMT_CTRL_C1; val32 = MAC_REG_R32(cr) & ~BIT18; if (tpu->pwr_lmt_en) val32 |= BIT18; MAC_REG_W32(cr, val32); #endif return MACSUCCESS; } u32 mac_read_pwr_reg(struct mac_ax_adapter *adapter, u8 band, const u32 offset, u32 *val) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 ret; u32 access_offset = offset; if (offset < R_AX_PWR_RATE_CTRL || offset > 0xFFFF) { PLTFM_MSG_ERR("[ERR]offset exceed pwr ctrl reg %x\n", offset); return MACBADDR; } if (band == MAC_AX_BAND_1) access_offset = offset | BIT13; ret = mac_check_access(adapter, access_offset); if (ret) return ret; *val = MAC_REG_R32(access_offset); return MACSUCCESS; } u32 mac_write_msk_pwr_reg(struct mac_ax_adapter *adapter, u8 band, const u32 offset, u32 mask, u32 val) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 ret = MACSUCCESS; u32 access_offset = offset; u32 ori_val = 0; u8 shift; if (offset < R_AX_PWR_RATE_CTRL || offset > 0xFFFF) { PLTFM_MSG_ERR("[ERR]offset exceed pwr ctrl reg %x\n", offset); return MACBADDR; } if (band == MAC_AX_BAND_1) access_offset = offset | BIT13; ret = mac_check_access(adapter, access_offset); if (ret) { PLTFM_MSG_ERR("[ERR]check access in %x\n", access_offset); return ret; } #if MAC_AX_FW_REG_OFLD if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) { ret = MAC_REG_W_OFLD((u16)access_offset, mask, val, 1); if (ret) { PLTFM_MSG_ERR("[ERR]%s FW_OFLD in %x\n", __func__, access_offset); return ret; } return MACSUCCESS; } #endif if (mask != 0xffffffff) { shift = shift_mask(mask); ori_val = MAC_REG_R32(offset); val = ((ori_val) & (~mask)) | (((val << shift)) & mask); } MAC_REG_W32(offset, val); return MACSUCCESS; } u32 mac_write_pwr_reg(struct mac_ax_adapter *adapter, u8 band, const u32 offset, u32 val) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 ret = MACSUCCESS; u32 access_offset = offset; if (offset < R_AX_PWR_RATE_CTRL || offset > 0xFFFF) { PLTFM_MSG_ERR("[ERR]offset exceed pwr ctrl reg %x\n", offset); return MACBADDR; } if (band == MAC_AX_BAND_1) access_offset = offset | BIT13; ret = mac_check_access(adapter, access_offset); if (ret) return ret; #if MAC_AX_FW_REG_OFLD if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) { ret = MAC_REG_W32_OFLD((u16)access_offset, val, 1); if (ret) { PLTFM_MSG_ERR("[ERR]%s FW_OFLD in %x\n", __func__, access_offset); return ret; } return MACSUCCESS; } #endif MAC_REG_W32(access_offset, val); return MACSUCCESS; } u32 mac_write_pwr_limit_rua_reg(struct mac_ax_adapter *adapter, u8 band, struct rtw_tpu_info *tpu) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u16 cr = (band == HW_BAND_0) ? R_AX_PWR_RU_LMT_TABLE0 : R_AX_PWR_RU_LMT_TABLE0_C1; s8 *tmp; u8 i, j; #if MAC_AX_FW_REG_OFLD u32 ret; #endif #if MAC_AX_FW_REG_OFLD if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) { for (i = 0; i < HAL_MAX_PATH; i++) { for (j = 0; j < TPU_SIZE_RUA; j++) { tmp = &tpu->pwr_lmt_ru[i][j][0]; ret = MAC_REG_W32_OFLD(cr, BT_2_DW(tmp[3], tmp[2], tmp[1], tmp[0]), 0); if (ret) { PLTFM_MSG_ERR("[ERR]%s FW_OFLD in %x\n", __func__, cr); return ret; } cr += 4; ret = MAC_REG_W32_OFLD(cr, BT_2_DW(tmp[7], tmp[6], tmp[5], tmp[4]), 1); if (ret) { PLTFM_MSG_ERR("[ERR]%s FW_OFLD in %x\n", __func__, cr); return ret; } cr += 4; } } return MACSUCCESS; } #endif for (i = 0; i < HAL_MAX_PATH; i++) { for (j = 0; j < TPU_SIZE_RUA; j++) { tmp = &tpu->pwr_lmt_ru[i][j][0]; MAC_REG_W32(cr, BT_2_DW(tmp[3], tmp[2], tmp[1], tmp[0])); cr += 4; MAC_REG_W32(cr, BT_2_DW(tmp[7], tmp[6], tmp[5], tmp[4])); cr += 4; } } return MACSUCCESS; } u32 mac_write_pwr_limit_reg(struct mac_ax_adapter *adapter, u8 band, struct rtw_tpu_pwr_imt_info *tpu) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 base = (band == HW_BAND_0) ? R_AX_PWR_RATE_CTRL : R_AX_PWR_RATE_CTRL_C1; u32 ss_ofst = 0; u16 cr = 0; s8 *tmp, *tmp_1; u8 i, j; #if MAC_AX_FW_REG_OFLD u32 ret; #endif #if MAC_AX_FW_REG_OFLD if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) { for (i = 0; i < HAL_MAX_PATH; i++) { tmp = &tpu->pwr_lmt_cck_20m[i][0]; tmp_1 = &tpu->pwr_lmt_cck_40m[i][0]; cr = (base | PWR_LMT_CCK_OFFSET) + ss_ofst; ret = MAC_REG_W32_OFLD(cr, BT_2_DW(tmp_1[1], tmp_1[0], tmp[1], tmp[0]), 0); if (ret) { PLTFM_MSG_ERR("[ERR]%s FW_OFLD in %x\n", __func__, cr); return ret; } tmp = &tpu->pwr_lmt_lgcy_20m[i][0]; tmp_1 = &tpu->pwr_lmt_20m[i][0][0]; cr = (base | PWR_LMT_LGCY_OFFSET) + ss_ofst; ret = MAC_REG_W32_OFLD(cr, BT_2_DW(tmp_1[1], tmp_1[0], tmp[1], tmp[0]), 0); if (ret) { PLTFM_MSG_ERR("[ERR]%s FW_OFLD in %x\n", __func__, cr); return ret; } cr = (base | PWR_LMT_TBL2_OFFSET) + ss_ofst; for (j = 1; j <= 5; j += 2) { tmp = &tpu->pwr_lmt_20m[i][j][0]; tmp_1 = &tpu->pwr_lmt_20m[i][j + 1][0]; ret = MAC_REG_W32_OFLD(cr, BT_2_DW(tmp_1[1], tmp_1[0], tmp[1], tmp[0]), 0); if (ret) { PLTFM_MSG_ERR("[ERR]%s FW_OFLD in %x\n", __func__, cr); return ret; } cr += 4; } tmp = &tpu->pwr_lmt_20m[i][7][0]; tmp_1 = &tpu->pwr_lmt_40m[i][0][0]; cr = (base | PWR_LMT_TBL5_OFFSET) + ss_ofst; ret = MAC_REG_W32_OFLD(cr, BT_2_DW(tmp_1[1], tmp_1[0], tmp[1], tmp[0]), 0); if (ret) { PLTFM_MSG_ERR("[ERR]%s FW_OFLD in %x\n", __func__, cr); return ret; } tmp = &tpu->pwr_lmt_40m[i][1][0]; tmp_1 = &tpu->pwr_lmt_40m[i][2][0]; cr = (base | PWR_LMT_TBL6_OFFSET) + ss_ofst; ret = MAC_REG_W32_OFLD(cr, BT_2_DW(tmp_1[1], tmp_1[0], tmp[1], tmp[0]), 0); if (ret) { PLTFM_MSG_ERR("[ERR]%s FW_OFLD in %x\n", __func__, cr); return ret; } tmp = &tpu->pwr_lmt_40m[i][3][0]; tmp_1 = &tpu->pwr_lmt_80m[i][0][0]; cr = (base | PWR_LMT_TBL7_OFFSET) + ss_ofst; ret = MAC_REG_W32_OFLD(cr, BT_2_DW(tmp_1[1], tmp_1[0], tmp[1], tmp[0]), 0); if (ret) { PLTFM_MSG_ERR("[ERR]%s FW_OFLD in %x\n", __func__, cr); return ret; } tmp = &tpu->pwr_lmt_80m[i][1][0]; tmp_1 = &tpu->pwr_lmt_160m[i][0]; cr = (base | PWR_LMT_TBL8_OFFSET) + ss_ofst; ret = MAC_REG_W32_OFLD(cr, BT_2_DW(tmp_1[1], tmp_1[0], tmp[1], tmp[0]), 0); if (ret) { PLTFM_MSG_ERR("[ERR]%s FW_OFLD in %x\n", __func__, cr); return ret; } tmp = &tpu->pwr_lmt_40m_0p5[i][0]; tmp_1 = &tpu->pwr_lmt_40m_2p5[i][0]; cr = (base | PWR_LMT_TBL9_OFFSET) + ss_ofst; ret = MAC_REG_W32_OFLD(cr, BT_2_DW(tmp_1[1], tmp_1[0], tmp[1], tmp[0]), 1); if (ret) { PLTFM_MSG_ERR("[ERR]%s FW_OFLD in %x\n", __func__, cr); return ret; } ss_ofst += PWR_LMT_TBL_UNIT; } return MACSUCCESS; } #endif for (i = 0; i < HAL_MAX_PATH; i++) { tmp = &tpu->pwr_lmt_cck_20m[i][0]; tmp_1 = &tpu->pwr_lmt_cck_40m[i][0]; cr = (base | PWR_LMT_CCK_OFFSET) + ss_ofst; MAC_REG_W32(cr, BT_2_DW(tmp_1[1], tmp_1[0], tmp[1], tmp[0])); tmp = &tpu->pwr_lmt_lgcy_20m[i][0]; tmp_1 = &tpu->pwr_lmt_20m[i][0][0]; cr = (base | PWR_LMT_LGCY_OFFSET) + ss_ofst; MAC_REG_W32(cr, BT_2_DW(tmp_1[1], tmp_1[0], tmp[1], tmp[0])); cr = (base | PWR_LMT_TBL2_OFFSET) + ss_ofst; for (j = 1; j <= 5; j += 2) { tmp = &tpu->pwr_lmt_20m[i][j][0]; tmp_1 = &tpu->pwr_lmt_20m[i][j + 1][0]; MAC_REG_W32(cr, BT_2_DW(tmp_1[1], tmp_1[0], tmp[1], tmp[0])); cr += 4; } tmp = &tpu->pwr_lmt_20m[i][7][0]; tmp_1 = &tpu->pwr_lmt_40m[i][0][0]; cr = (base | PWR_LMT_TBL5_OFFSET) + ss_ofst; MAC_REG_W32(cr, BT_2_DW(tmp_1[1], tmp_1[0], tmp[1], tmp[0])); tmp = &tpu->pwr_lmt_40m[i][1][0]; tmp_1 = &tpu->pwr_lmt_40m[i][2][0]; cr = (base | PWR_LMT_TBL6_OFFSET) + ss_ofst; MAC_REG_W32(cr, BT_2_DW(tmp_1[1], tmp_1[0], tmp[1], tmp[0])); tmp = &tpu->pwr_lmt_40m[i][3][0]; tmp_1 = &tpu->pwr_lmt_80m[i][0][0]; cr = (base | PWR_LMT_TBL7_OFFSET) + ss_ofst; MAC_REG_W32(cr, BT_2_DW(tmp_1[1], tmp_1[0], tmp[1], tmp[0])); tmp = &tpu->pwr_lmt_80m[i][1][0]; tmp_1 = &tpu->pwr_lmt_160m[i][0]; cr = (base | PWR_LMT_TBL8_OFFSET) + ss_ofst; MAC_REG_W32(cr, BT_2_DW(tmp_1[1], tmp_1[0], tmp[1], tmp[0])); tmp = &tpu->pwr_lmt_40m_0p5[i][0]; tmp_1 = &tpu->pwr_lmt_40m_2p5[i][0]; cr = (base | PWR_LMT_TBL9_OFFSET) + ss_ofst; MAC_REG_W32(cr, BT_2_DW(tmp_1[1], tmp_1[0], tmp[1], tmp[0])); ss_ofst += PWR_LMT_TBL_UNIT; } return MACSUCCESS; } u32 mac_write_pwr_by_rate_reg(struct mac_ax_adapter *adapter, u8 band, struct rtw_tpu_pwr_by_rate_info *tpu) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 base = (band == HW_BAND_0) ? R_AX_PWR_RATE_CTRL : R_AX_PWR_RATE_CTRL_C1; u32 ss_ofst = 0; u16 cr = 0; s8 *tmp; u8 i, j; #if MAC_AX_FW_REG_OFLD u32 ret; #endif #if MAC_AX_FW_REG_OFLD if (adapter->sm.fwdl == MAC_AX_FWDL_INIT_RDY) { for (i = 0; i <= 8; i += 4) { tmp = &tpu->pwr_by_rate_lgcy[i]; cr = (base | PWR_BY_RATE_LGCY_OFFSET) + i; ret = MAC_REG_W32_OFLD(cr, BT_2_DW(tmp[3], tmp[2], tmp[1], tmp[0]), 0); if (ret) { PLTFM_MSG_ERR("[ERR]%s FW_OFLD in %x\n", __func__, cr); return ret; } } for (i = 0; i < HAL_MAX_PATH; i++) { for (j = 0; j <= 12; j += 4) { tmp = &tpu->pwr_by_rate[i][j]; cr = (base | PWR_BY_RATE_OFFSET) + j + ss_ofst; ret = MAC_REG_W32_OFLD(cr, BT_2_DW(tmp[3], tmp[2], tmp[1], tmp[0]), 0); if (ret) { PLTFM_MSG_ERR("[ERR]%s FW_OFLD in %x\n", __func__, cr); return ret; } } ss_ofst += 0x10; /*16*/ } return MACSUCCESS; } #endif for (i = 0; i <= 8; i += 4) { tmp = &tpu->pwr_by_rate_lgcy[i]; cr = (base | PWR_BY_RATE_LGCY_OFFSET) + i; MAC_REG_W32(cr, BT_2_DW(tmp[3], tmp[2], tmp[1], tmp[0])); } for (i = 0; i < HAL_MAX_PATH; i++) { for (j = 0; j <= 12; j += 4) { tmp = &tpu->pwr_by_rate[i][j]; cr = (base | PWR_BY_RATE_OFFSET) + j + ss_ofst; MAC_REG_W32(cr, BT_2_DW(tmp[3], tmp[2], tmp[1], tmp[0])); } ss_ofst += 0x10; /*16*/ } return MACSUCCESS; } u32 mac_read_xcap_reg(struct mac_ax_adapter *adapter, u8 sc_xo, u32 *val) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); if (sc_xo) { *val = (MAC_REG_R32(R_AX_XTAL_ON_CTRL0) >> B_AX_XTAL_SC_XO_SH) & B_AX_XTAL_SC_XO_MSK; } else { *val = (MAC_REG_R32(R_AX_XTAL_ON_CTRL0) >> B_AX_XTAL_SC_XI_SH) & B_AX_XTAL_SC_XI_MSK; } return MACSUCCESS; } u32 mac_write_xcap_reg(struct mac_ax_adapter *adapter, u8 sc_xo, u32 val) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 val32; if (sc_xo) { val32 = MAC_REG_R32(R_AX_XTAL_ON_CTRL0); val32 &= ~(0xFE0000); val32 |= ((val & B_AX_XTAL_SC_XO_MSK) << B_AX_XTAL_SC_XO_SH); MAC_REG_W32(R_AX_XTAL_ON_CTRL0, val32); } else { val32 = MAC_REG_R32(R_AX_XTAL_ON_CTRL0); val32 &= ~(0x1FC00); val32 = val32 | ((val & B_AX_XTAL_SC_XI_MSK) << B_AX_XTAL_SC_XI_SH); MAC_REG_W32(R_AX_XTAL_ON_CTRL0, val32); } return MACSUCCESS; } u32 mac_read_xcap_reg_dav(struct mac_ax_adapter *adapter, u8 sc_xo, u32 *val) { u8 xtal_si_value; u32 ret; if (sc_xo) { ret = mac_read_xtal_si(adapter, XTAL_SI_XTAL_SC_XO, &xtal_si_value); if (ret) { PLTFM_MSG_ERR("Read XTAL_SI fail!\n"); return ret; } *val = xtal_si_value; } else { ret = mac_read_xtal_si(adapter, XTAL_SI_XTAL_SC_XI, &xtal_si_value); if (ret) { PLTFM_MSG_ERR("Read XTAL_SI fail!\n"); return ret; } *val = xtal_si_value; } return MACSUCCESS; } u32 mac_write_xcap_reg_dav(struct mac_ax_adapter *adapter, u8 sc_xo, u32 val) { u8 xtal_si_value; u32 ret; xtal_si_value = (u8)val; if (sc_xo) { ret = mac_write_xtal_si(adapter, XTAL_SI_XTAL_SC_XO, xtal_si_value, FULL_BIT_MASK); if (ret) { PLTFM_MSG_ERR("Write XTAL_SI fail!\n"); return ret; } } else { ret = mac_write_xtal_si(adapter, XTAL_SI_XTAL_SC_XI, xtal_si_value, FULL_BIT_MASK); if (ret) { PLTFM_MSG_ERR("Write XTAL_SI fail!\n"); return ret; } } return MACSUCCESS; } u32 mac_write_bbrst_reg(struct mac_ax_adapter *adapter, u8 val) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u8 val8; val8 = MAC_REG_R8(R_AX_SYS_FUNC_EN); if (val) MAC_REG_W8(R_AX_SYS_FUNC_EN, val8 | B_AX_FEN_BBRSTB); else MAC_REG_W8(R_AX_SYS_FUNC_EN, val8 & (~B_AX_FEN_BBRSTB)); return MACSUCCESS; } static inline u32 _get_addr_range(struct mac_ax_adapter *adapter, u32 addr) { u32 addr_idx; #define IOCHKRANG(chip) do { \ if (ADDR_IS_AON_##chip(addr)) \ addr_idx = ADDR_AON; \ else if (ADDR_IS_HCI_##chip(addr)) \ addr_idx = ADDR_HCI; \ else if (ADDR_IS_DMAC_##chip(addr)) \ addr_idx = ADDR_DMAC; \ else if (ADDR_IS_CMAC0_##chip(addr)) \ addr_idx = ADDR_CMAC0; \ else if (ADDR_IS_CMAC1_##chip(addr)) \ addr_idx = ADDR_CMAC1; \ else if (ADDR_IS_BB0_##chip(addr)) \ addr_idx = ADDR_BB0; \ else if (ADDR_IS_BB1_##chip(addr)) \ addr_idx = ADDR_BB1; \ else if (ADDR_IS_RF_##chip(addr)) \ addr_idx = ADDR_RF; \ else if (ADDR_IS_IND_ACES_##chip(addr)) \ addr_idx = ADDR_IND_ACES; \ else if (ADDR_IS_RSVD_##chip(addr)) \ addr_idx = ADDR_RSVD; \ else if (ADDR_IS_PON_##chip(addr)) \ addr_idx = ADDR_PON; \ else \ addr_idx = ADDR_INVALID; \ } while (0) switch (adapter->hw_info->chip_id) { case MAC_AX_CHIP_ID_8852A: IOCHKRANG(8852A); break; case MAC_AX_CHIP_ID_8852B: IOCHKRANG(8852B); break; case MAC_AX_CHIP_ID_8852C: IOCHKRANG(8852C); break; case MAC_AX_CHIP_ID_8192XB: IOCHKRANG(8192XB); break; default: addr_idx = ADDR_INVALID; break; } #undef IOCHKRANG return addr_idx; } u32 mac_io_chk_access(struct mac_ax_adapter *adapter, u32 offset) { switch (_get_addr_range(adapter, offset)) { case ADDR_AON: case ADDR_HCI: return MACSUCCESS; case ADDR_PON: break; case ADDR_DMAC: if (adapter->sm.dmac_func != MAC_AX_FUNC_ON) return MACIOERRDMAC; break; case ADDR_CMAC0: if (adapter->sm.cmac0_func != MAC_AX_FUNC_ON) return MACIOERRCMAC0; break; case ADDR_CMAC1: if (adapter->sm.cmac1_func != MAC_AX_FUNC_ON) return MACIOERRCMAC1; if (is_chip_id(adapter, MAC_AX_CHIP_ID_8852B) || is_chip_id(adapter, MAC_AX_CHIP_ID_8192XB)) return MACHWNOSUP; break; case ADDR_BB0: #if CHK_BBRF_IO if (adapter->sm.bb0_func != MAC_AX_FUNC_ON) return MACIOERRBB0; #endif break; case ADDR_BB1: #if CHK_BBRF_IO if (adapter->sm.bb1_func != MAC_AX_FUNC_ON) return MACIOERRBB1; #endif break; case ADDR_RF: #if CHK_BBRF_IO if (adapter->sm.bb0_func != MAC_AX_FUNC_ON && adapter->sm.bb1_func != MAC_AX_FUNC_ON) return MACIOERRRF; #endif break; case ADDR_IND_ACES: if (adapter->hw_info->ind_aces_cnt > 1) PLTFM_MSG_ERR("[ERR]ind aces cnt %d ovf\n", adapter->hw_info->ind_aces_cnt); if (adapter->hw_info->ind_aces_cnt != 1) return MACIOERRIND; break; case ADDR_RSVD: return MACIOERRRSVD; case ADDR_INVALID: return MACHWNOSUP; } if (adapter->sm.pwr != MAC_AX_PWR_ON) return MACIOERRPWR; if (adapter->sm.plat != MAC_AX_PLAT_ON) return MACIOERRPLAT; if (adapter->sm.io_st == MAC_AX_IO_ST_HANG) return MACIOERRISH; if ((adapter->sm.fw_rst == MAC_AX_FW_RESET_RECV_DONE || adapter->sm.fw_rst == MAC_AX_FW_RESET_PROCESS) && ADDR_NOT_ALLOW_SERL1(offset)) return MACIOERRSERL1; if (adapter->sm.fw_rst == MAC_AX_FW_RESET_IDLE && adapter->mac_pwr_info.pwr_in_lps && ADDR_NOT_ALLOW_LPS(offset)) return MACIOERRLPS; return MACSUCCESS; } u32 mac_watchdog(struct mac_ax_adapter *adapter) { struct mac_ax_intf_ops *ops = adapter_to_intf_ops(adapter); u32 ret = MACSUCCESS; ret = ops->pcie_autok_counter_avg(adapter); if (ret != MACSUCCESS) return ret; return MACSUCCESS; }