1250003Sadrian/* 2250003Sadrian * Copyright (c) 2013 Qualcomm Atheros, Inc. 3250003Sadrian * 4250003Sadrian * Permission to use, copy, modify, and/or distribute this software for any 5250003Sadrian * purpose with or without fee is hereby granted, provided that the above 6250003Sadrian * copyright notice and this permission notice appear in all copies. 7250003Sadrian * 8250003Sadrian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9250003Sadrian * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10250003Sadrian * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11250003Sadrian * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12250003Sadrian * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 13250003Sadrian * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14250003Sadrian * PERFORMANCE OF THIS SOFTWARE. 15250003Sadrian */ 16250003Sadrian 17250003Sadrian#include "opt_ah.h" 18250003Sadrian 19250003Sadrian#include "ah.h" 20250003Sadrian#include "ah_desc.h" 21250003Sadrian#include "ah_internal.h" 22250003Sadrian 23250003Sadrian#include "ar9300/ar9300.h" 24250003Sadrian#include "ar9300/ar9300reg.h" 25250003Sadrian#include "ar9300/ar9300desc.h" 26250003Sadrian 27250003Sadrian/* 28250003Sadrian * Get the RXDP. 29250003Sadrian */ 30250003Sadrianu_int32_t 31250003Sadrianar9300_get_rx_dp(struct ath_hal *ath, HAL_RX_QUEUE qtype) 32250003Sadrian{ 33250003Sadrian if (qtype == HAL_RX_QUEUE_HP) { 34250003Sadrian return OS_REG_READ(ath, AR_HP_RXDP); 35250003Sadrian } else { 36250003Sadrian return OS_REG_READ(ath, AR_LP_RXDP); 37250003Sadrian } 38250003Sadrian} 39250003Sadrian 40250003Sadrian/* 41250003Sadrian * Set the rx_dp. 42250003Sadrian */ 43250003Sadrianvoid 44250003Sadrianar9300_set_rx_dp(struct ath_hal *ah, u_int32_t rxdp, HAL_RX_QUEUE qtype) 45250003Sadrian{ 46250003Sadrian HALASSERT((qtype == HAL_RX_QUEUE_HP) || (qtype == HAL_RX_QUEUE_LP)); 47250003Sadrian 48250003Sadrian if (qtype == HAL_RX_QUEUE_HP) { 49250003Sadrian OS_REG_WRITE(ah, AR_HP_RXDP, rxdp); 50250003Sadrian } else { 51250003Sadrian OS_REG_WRITE(ah, AR_LP_RXDP, rxdp); 52250003Sadrian } 53250003Sadrian} 54250003Sadrian 55250003Sadrian/* 56250003Sadrian * Set Receive Enable bits. 57250003Sadrian */ 58250003Sadrianvoid 59250003Sadrianar9300_enable_receive(struct ath_hal *ah) 60250003Sadrian{ 61250003Sadrian OS_REG_WRITE(ah, AR_CR, 0); 62250003Sadrian} 63250003Sadrian 64250003Sadrian/* 65250003Sadrian * Set the RX abort bit. 66250003Sadrian */ 67250003SadrianHAL_BOOL 68250003Sadrianar9300_set_rx_abort(struct ath_hal *ah, HAL_BOOL set) 69250003Sadrian{ 70250003Sadrian if (set) { 71250003Sadrian /* Set the force_rx_abort bit */ 72250003Sadrian OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); 73250003Sadrian 74250008Sadrian if ( AH9300(ah)->ah_reset_reason == HAL_RESET_BBPANIC ){ 75250003Sadrian /* depending upon the BB panic status, rx state may not return to 0, 76250003Sadrian * so skipping the wait for BB panic reset */ 77250003Sadrian OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); 78250008Sadrian return AH_FALSE; 79250003Sadrian } else { 80250003Sadrian HAL_BOOL okay; 81250003Sadrian okay = ath_hal_wait( 82250008Sadrian ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, 0); 83250003Sadrian /* Wait for Rx state to return to 0 */ 84250003Sadrian if (!okay) { 85250003Sadrian /* abort: chip rx failed to go idle in 10 ms */ 86250003Sadrian OS_REG_CLR_BIT(ah, AR_DIAG_SW, 87250003Sadrian (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); 88250003Sadrian 89250003Sadrian HALDEBUG(ah, HAL_DEBUG_RX, 90250003Sadrian "%s: rx failed to go idle in 10 ms RXSM=0x%x\n", 91250003Sadrian __func__, OS_REG_READ(ah, AR_OBS_BUS_1)); 92250003Sadrian 93250003Sadrian return AH_FALSE; /* failure */ 94250003Sadrian } 95250003Sadrian } 96250003Sadrian } else { 97250003Sadrian OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); 98250003Sadrian } 99250003Sadrian 100250003Sadrian return AH_TRUE; /* success */ 101250003Sadrian} 102250003Sadrian 103250003Sadrian/* 104250003Sadrian * Stop Receive at the DMA engine 105250003Sadrian */ 106250003SadrianHAL_BOOL 107250003Sadrianar9300_stop_dma_receive(struct ath_hal *ah, u_int timeout) 108250003Sadrian{ 109250003Sadrian int wait; 110250003Sadrian HAL_BOOL status, okay; 111250003Sadrian u_int32_t org_value; 112250003Sadrian 113250003Sadrian#define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ 114250003Sadrian#define AH_TIME_QUANTUM 100 /* usec */ 115250003Sadrian 116269793Sadrian OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_DMA_STOP); 117269793Sadrian 118250003Sadrian if (timeout == 0) { 119250003Sadrian timeout = AH_RX_STOP_DMA_TIMEOUT; 120250003Sadrian } 121250003Sadrian 122250003Sadrian org_value = OS_REG_READ(ah, AR_MACMISC); 123250003Sadrian 124250003Sadrian OS_REG_WRITE(ah, AR_MACMISC, 125250003Sadrian ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | 126250003Sadrian (AR_MACMISC_MISC_OBS_BUS_1 << AR_MACMISC_MISC_OBS_BUS_MSB_S))); 127250003Sadrian 128250003Sadrian okay = ath_hal_wait( 129250008Sadrian ah, AR_DMADBG_7, AR_DMADBG_RX_STATE, 0); 130250003Sadrian /* wait for Rx DMA state machine to become idle */ 131250003Sadrian if (!okay) { 132250003Sadrian HALDEBUG(ah, HAL_DEBUG_RX, 133250003Sadrian "reg AR_DMADBG_7 is not 0, instead 0x%08x\n", 134250003Sadrian OS_REG_READ(ah, AR_DMADBG_7)); 135250003Sadrian } 136250003Sadrian 137250003Sadrian /* Set receive disable bit */ 138250003Sadrian OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); 139250003Sadrian 140250003Sadrian /* Wait for rx enable bit to go low */ 141250003Sadrian for (wait = timeout / AH_TIME_QUANTUM; wait != 0; wait--) { 142250003Sadrian if ((OS_REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) { 143250003Sadrian break; 144250003Sadrian } 145250003Sadrian OS_DELAY(AH_TIME_QUANTUM); 146250003Sadrian } 147250003Sadrian 148250003Sadrian if (wait == 0) { 149250003Sadrian HALDEBUG(ah, HAL_DEBUG_RX, "%s: dma failed to stop in %d ms\n" 150250003Sadrian "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n", 151250003Sadrian __func__, 152250003Sadrian timeout / 1000, 153250003Sadrian OS_REG_READ(ah, AR_CR), 154250003Sadrian OS_REG_READ(ah, AR_DIAG_SW)); 155250003Sadrian status = AH_FALSE; 156250003Sadrian } else { 157250003Sadrian status = AH_TRUE; 158250003Sadrian } 159250003Sadrian 160250003Sadrian OS_REG_WRITE(ah, AR_MACMISC, org_value); 161250003Sadrian 162269793Sadrian OS_MARK(ah, AH_MARK_RX_CTL, 163269793Sadrian status ? AH_MARK_RX_CTL_DMA_STOP_OK : AH_MARK_RX_CTL_DMA_STOP_ERR); 164269793Sadrian 165250003Sadrian return status; 166250003Sadrian#undef AH_RX_STOP_DMA_TIMEOUT 167250003Sadrian#undef AH_TIME_QUANTUM 168250003Sadrian} 169250003Sadrian 170250003Sadrian/* 171250003Sadrian * Start Transmit at the PCU engine (unpause receive) 172250003Sadrian */ 173250003Sadrianvoid 174250003Sadrianar9300_start_pcu_receive(struct ath_hal *ah, HAL_BOOL is_scanning) 175250003Sadrian{ 176250003Sadrian ar9300_enable_mib_counters(ah); 177250003Sadrian ar9300_ani_reset(ah, is_scanning); 178250003Sadrian /* Clear RX_DIS and RX_ABORT after enabling phy errors in ani_reset */ 179250003Sadrian OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); 180250003Sadrian} 181250003Sadrian 182250003Sadrian/* 183250003Sadrian * Stop Transmit at the PCU engine (pause receive) 184250003Sadrian */ 185250003Sadrianvoid 186250003Sadrianar9300_stop_pcu_receive(struct ath_hal *ah) 187250003Sadrian{ 188250003Sadrian OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); 189250003Sadrian ar9300_disable_mib_counters(ah); 190250003Sadrian} 191250003Sadrian 192250003Sadrian/* 193250003Sadrian * Set multicast filter 0 (lower 32-bits) 194250003Sadrian * filter 1 (upper 32-bits) 195250003Sadrian */ 196250003Sadrianvoid 197250003Sadrianar9300_set_multicast_filter( 198250003Sadrian struct ath_hal *ah, 199250003Sadrian u_int32_t filter0, 200250003Sadrian u_int32_t filter1) 201250003Sadrian{ 202250003Sadrian OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0); 203250003Sadrian OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1); 204250003Sadrian} 205250003Sadrian 206250003Sadrian/* 207250003Sadrian * Get the receive filter. 208250003Sadrian */ 209250003Sadrianu_int32_t 210250003Sadrianar9300_get_rx_filter(struct ath_hal *ah) 211250003Sadrian{ 212250003Sadrian u_int32_t bits = OS_REG_READ(ah, AR_RX_FILTER); 213250003Sadrian u_int32_t phybits = OS_REG_READ(ah, AR_PHY_ERR); 214250003Sadrian if (phybits & AR_PHY_ERR_RADAR) { 215250003Sadrian bits |= HAL_RX_FILTER_PHYRADAR; 216250003Sadrian } 217250003Sadrian if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING)) { 218250003Sadrian bits |= HAL_RX_FILTER_PHYERR; 219250003Sadrian } 220250003Sadrian return bits; 221250003Sadrian} 222250003Sadrian 223250003Sadrian/* 224250003Sadrian * Set the receive filter. 225250003Sadrian */ 226250003Sadrianvoid 227250003Sadrianar9300_set_rx_filter(struct ath_hal *ah, u_int32_t bits) 228250003Sadrian{ 229250003Sadrian u_int32_t phybits; 230250003Sadrian 231291437Sadrian if (AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) { 232250003Sadrian /* Enable Rx for 4 address frames */ 233250003Sadrian bits |= AR_RX_4ADDRESS; 234250003Sadrian } 235250003Sadrian if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { 236250003Sadrian /* HW fix for rx hang and corruption. */ 237250003Sadrian bits |= AR_RX_CONTROL_WRAPPER; 238250003Sadrian } 239250003Sadrian OS_REG_WRITE(ah, AR_RX_FILTER, 240250003Sadrian bits | AR_RX_UNCOM_BA_BAR | AR_RX_COMPR_BAR); 241250003Sadrian phybits = 0; 242250003Sadrian if (bits & HAL_RX_FILTER_PHYRADAR) { 243250003Sadrian phybits |= AR_PHY_ERR_RADAR; 244250003Sadrian } 245250003Sadrian if (bits & HAL_RX_FILTER_PHYERR) { 246250003Sadrian phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING; 247250003Sadrian } 248250003Sadrian OS_REG_WRITE(ah, AR_PHY_ERR, phybits); 249250003Sadrian if (phybits) { 250250003Sadrian OS_REG_WRITE(ah, AR_RXCFG, 251250003Sadrian OS_REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA); 252250003Sadrian } else { 253250003Sadrian OS_REG_WRITE(ah, AR_RXCFG, 254250003Sadrian OS_REG_READ(ah, AR_RXCFG) &~ AR_RXCFG_ZLFDMA); 255250003Sadrian } 256250003Sadrian} 257250003Sadrian 258250003Sadrian/* 259250003Sadrian * Select to pass PLCP headr or EVM data. 260250003Sadrian */ 261250003SadrianHAL_BOOL 262250003Sadrianar9300_set_rx_sel_evm(struct ath_hal *ah, HAL_BOOL sel_evm, HAL_BOOL just_query) 263250003Sadrian{ 264250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 265250003Sadrian HAL_BOOL old_value = ahp->ah_get_plcp_hdr == 0; 266250003Sadrian 267250003Sadrian if (just_query) { 268250003Sadrian return old_value; 269250003Sadrian } 270250003Sadrian if (sel_evm) { 271250003Sadrian OS_REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_SEL_EVM); 272250003Sadrian } else { 273250003Sadrian OS_REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_SEL_EVM); 274250003Sadrian } 275250003Sadrian 276250003Sadrian ahp->ah_get_plcp_hdr = !sel_evm; 277250003Sadrian 278250003Sadrian return old_value; 279250003Sadrian} 280250003Sadrian 281250003Sadrianvoid ar9300_promisc_mode(struct ath_hal *ah, HAL_BOOL enable) 282250003Sadrian{ 283250003Sadrian u_int32_t reg_val = 0; 284250003Sadrian reg_val = OS_REG_READ(ah, AR_RX_FILTER); 285250003Sadrian if (enable){ 286250003Sadrian reg_val |= AR_RX_PROM; 287250003Sadrian } else{ /*Disable promisc mode */ 288250003Sadrian reg_val &= ~AR_RX_PROM; 289250003Sadrian } 290250003Sadrian OS_REG_WRITE(ah, AR_RX_FILTER, reg_val); 291250003Sadrian} 292250003Sadrian 293250003Sadrianvoid 294250003Sadrianar9300_read_pktlog_reg( 295250003Sadrian struct ath_hal *ah, 296250003Sadrian u_int32_t *rxfilter_val, 297250003Sadrian u_int32_t *rxcfg_val, 298250003Sadrian u_int32_t *phy_err_mask_val, 299250003Sadrian u_int32_t *mac_pcu_phy_err_regval) 300250003Sadrian{ 301250003Sadrian *rxfilter_val = OS_REG_READ(ah, AR_RX_FILTER); 302250003Sadrian *rxcfg_val = OS_REG_READ(ah, AR_RXCFG); 303250003Sadrian *phy_err_mask_val = OS_REG_READ(ah, AR_PHY_ERR); 304250003Sadrian *mac_pcu_phy_err_regval = OS_REG_READ(ah, 0x8338); 305250003Sadrian HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, 306250003Sadrian "%s[%d] rxfilter_val 0x%08x , rxcfg_val 0x%08x, " 307250003Sadrian "phy_err_mask_val 0x%08x mac_pcu_phy_err_regval 0x%08x\n", 308250003Sadrian __func__, __LINE__, 309250003Sadrian *rxfilter_val, *rxcfg_val, *phy_err_mask_val, *mac_pcu_phy_err_regval); 310250003Sadrian} 311250003Sadrian 312250003Sadrianvoid 313250003Sadrianar9300_write_pktlog_reg( 314250003Sadrian struct ath_hal *ah, 315250003Sadrian HAL_BOOL enable, 316250003Sadrian u_int32_t rxfilter_val, 317250003Sadrian u_int32_t rxcfg_val, 318250003Sadrian u_int32_t phy_err_mask_val, 319250003Sadrian u_int32_t mac_pcu_phy_err_reg_val) 320250003Sadrian{ 321250003Sadrian if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { 322250003Sadrian /* HW fix for rx hang and corruption. */ 323250003Sadrian rxfilter_val |= AR_RX_CONTROL_WRAPPER; 324250003Sadrian } 325250003Sadrian if (enable) { /* Enable pktlog phyerr setting */ 326250003Sadrian OS_REG_WRITE(ah, AR_RX_FILTER, 0xffff | AR_RX_COMPR_BAR | rxfilter_val); 327250003Sadrian OS_REG_WRITE(ah, AR_PHY_ERR, 0xFFFFFFFF); 328250003Sadrian OS_REG_WRITE(ah, AR_RXCFG, rxcfg_val | AR_RXCFG_ZLFDMA); 329250003Sadrian OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, mac_pcu_phy_err_reg_val | 0xFF); 330250003Sadrian } else { /* Disable phyerr and Restore regs */ 331250003Sadrian OS_REG_WRITE(ah, AR_RX_FILTER, rxfilter_val); 332250003Sadrian OS_REG_WRITE(ah, AR_PHY_ERR, phy_err_mask_val); 333250003Sadrian OS_REG_WRITE(ah, AR_RXCFG, rxcfg_val); 334250003Sadrian OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, mac_pcu_phy_err_reg_val); 335250003Sadrian } 336250003Sadrian HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, 337250003Sadrian "%s[%d] ena %d rxfilter_val 0x%08x , rxcfg_val 0x%08x, " 338250003Sadrian "phy_err_mask_val 0x%08x mac_pcu_phy_err_regval 0x%08x\n", 339250003Sadrian __func__, __LINE__, 340250003Sadrian enable, rxfilter_val, rxcfg_val, 341250003Sadrian phy_err_mask_val, mac_pcu_phy_err_reg_val); 342250003Sadrian} 343