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 116250003Sadrian if (timeout == 0) { 117250003Sadrian timeout = AH_RX_STOP_DMA_TIMEOUT; 118250003Sadrian } 119250003Sadrian 120250003Sadrian org_value = OS_REG_READ(ah, AR_MACMISC); 121250003Sadrian 122250003Sadrian OS_REG_WRITE(ah, AR_MACMISC, 123250003Sadrian ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | 124250003Sadrian (AR_MACMISC_MISC_OBS_BUS_1 << AR_MACMISC_MISC_OBS_BUS_MSB_S))); 125250003Sadrian 126250003Sadrian okay = ath_hal_wait( 127250008Sadrian ah, AR_DMADBG_7, AR_DMADBG_RX_STATE, 0); 128250003Sadrian /* wait for Rx DMA state machine to become idle */ 129250003Sadrian if (!okay) { 130250003Sadrian HALDEBUG(ah, HAL_DEBUG_RX, 131250003Sadrian "reg AR_DMADBG_7 is not 0, instead 0x%08x\n", 132250003Sadrian OS_REG_READ(ah, AR_DMADBG_7)); 133250003Sadrian } 134250003Sadrian 135250003Sadrian /* Set receive disable bit */ 136250003Sadrian OS_REG_WRITE(ah, AR_CR, AR_CR_RXD); 137250003Sadrian 138250003Sadrian /* Wait for rx enable bit to go low */ 139250003Sadrian for (wait = timeout / AH_TIME_QUANTUM; wait != 0; wait--) { 140250003Sadrian if ((OS_REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) { 141250003Sadrian break; 142250003Sadrian } 143250003Sadrian OS_DELAY(AH_TIME_QUANTUM); 144250003Sadrian } 145250003Sadrian 146250003Sadrian if (wait == 0) { 147250003Sadrian HALDEBUG(ah, HAL_DEBUG_RX, "%s: dma failed to stop in %d ms\n" 148250003Sadrian "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n", 149250003Sadrian __func__, 150250003Sadrian timeout / 1000, 151250003Sadrian OS_REG_READ(ah, AR_CR), 152250003Sadrian OS_REG_READ(ah, AR_DIAG_SW)); 153250003Sadrian status = AH_FALSE; 154250003Sadrian } else { 155250003Sadrian status = AH_TRUE; 156250003Sadrian } 157250003Sadrian 158250003Sadrian OS_REG_WRITE(ah, AR_MACMISC, org_value); 159250003Sadrian 160250003Sadrian return status; 161250003Sadrian#undef AH_RX_STOP_DMA_TIMEOUT 162250003Sadrian#undef AH_TIME_QUANTUM 163250003Sadrian} 164250003Sadrian 165250003Sadrian/* 166250003Sadrian * Start Transmit at the PCU engine (unpause receive) 167250003Sadrian */ 168250003Sadrianvoid 169250003Sadrianar9300_start_pcu_receive(struct ath_hal *ah, HAL_BOOL is_scanning) 170250003Sadrian{ 171250003Sadrian ar9300_enable_mib_counters(ah); 172250003Sadrian ar9300_ani_reset(ah, is_scanning); 173250003Sadrian /* Clear RX_DIS and RX_ABORT after enabling phy errors in ani_reset */ 174250003Sadrian OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); 175250003Sadrian} 176250003Sadrian 177250003Sadrian/* 178250003Sadrian * Stop Transmit at the PCU engine (pause receive) 179250003Sadrian */ 180250003Sadrianvoid 181250003Sadrianar9300_stop_pcu_receive(struct ath_hal *ah) 182250003Sadrian{ 183250003Sadrian OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); 184250003Sadrian ar9300_disable_mib_counters(ah); 185250003Sadrian} 186250003Sadrian 187250003Sadrian/* 188250003Sadrian * Set multicast filter 0 (lower 32-bits) 189250003Sadrian * filter 1 (upper 32-bits) 190250003Sadrian */ 191250003Sadrianvoid 192250003Sadrianar9300_set_multicast_filter( 193250003Sadrian struct ath_hal *ah, 194250003Sadrian u_int32_t filter0, 195250003Sadrian u_int32_t filter1) 196250003Sadrian{ 197250003Sadrian OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0); 198250003Sadrian OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1); 199250003Sadrian} 200250003Sadrian 201250003Sadrian/* 202250003Sadrian * Get the receive filter. 203250003Sadrian */ 204250003Sadrianu_int32_t 205250003Sadrianar9300_get_rx_filter(struct ath_hal *ah) 206250003Sadrian{ 207250003Sadrian u_int32_t bits = OS_REG_READ(ah, AR_RX_FILTER); 208250003Sadrian u_int32_t phybits = OS_REG_READ(ah, AR_PHY_ERR); 209250003Sadrian if (phybits & AR_PHY_ERR_RADAR) { 210250003Sadrian bits |= HAL_RX_FILTER_PHYRADAR; 211250003Sadrian } 212250003Sadrian if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING)) { 213250003Sadrian bits |= HAL_RX_FILTER_PHYERR; 214250003Sadrian } 215250003Sadrian return bits; 216250003Sadrian} 217250003Sadrian 218250003Sadrian/* 219250003Sadrian * Set the receive filter. 220250003Sadrian */ 221250003Sadrianvoid 222250003Sadrianar9300_set_rx_filter(struct ath_hal *ah, u_int32_t bits) 223250003Sadrian{ 224250003Sadrian u_int32_t phybits; 225250003Sadrian 226250003Sadrian if (AR_SREV_SCORPION(ah)) { 227250003Sadrian /* Enable Rx for 4 address frames */ 228250003Sadrian bits |= AR_RX_4ADDRESS; 229250003Sadrian } 230250003Sadrian if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { 231250003Sadrian /* HW fix for rx hang and corruption. */ 232250003Sadrian bits |= AR_RX_CONTROL_WRAPPER; 233250003Sadrian } 234250003Sadrian OS_REG_WRITE(ah, AR_RX_FILTER, 235250003Sadrian bits | AR_RX_UNCOM_BA_BAR | AR_RX_COMPR_BAR); 236250003Sadrian phybits = 0; 237250003Sadrian if (bits & HAL_RX_FILTER_PHYRADAR) { 238250003Sadrian phybits |= AR_PHY_ERR_RADAR; 239250003Sadrian } 240250003Sadrian if (bits & HAL_RX_FILTER_PHYERR) { 241250003Sadrian phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING; 242250003Sadrian } 243250003Sadrian OS_REG_WRITE(ah, AR_PHY_ERR, phybits); 244250003Sadrian if (phybits) { 245250003Sadrian OS_REG_WRITE(ah, AR_RXCFG, 246250003Sadrian OS_REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA); 247250003Sadrian } else { 248250003Sadrian OS_REG_WRITE(ah, AR_RXCFG, 249250003Sadrian OS_REG_READ(ah, AR_RXCFG) &~ AR_RXCFG_ZLFDMA); 250250003Sadrian } 251250003Sadrian} 252250003Sadrian 253250003Sadrian/* 254250003Sadrian * Select to pass PLCP headr or EVM data. 255250003Sadrian */ 256250003SadrianHAL_BOOL 257250003Sadrianar9300_set_rx_sel_evm(struct ath_hal *ah, HAL_BOOL sel_evm, HAL_BOOL just_query) 258250003Sadrian{ 259250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 260250003Sadrian HAL_BOOL old_value = ahp->ah_get_plcp_hdr == 0; 261250003Sadrian 262250003Sadrian if (just_query) { 263250003Sadrian return old_value; 264250003Sadrian } 265250003Sadrian if (sel_evm) { 266250003Sadrian OS_REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_SEL_EVM); 267250003Sadrian } else { 268250003Sadrian OS_REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_SEL_EVM); 269250003Sadrian } 270250003Sadrian 271250003Sadrian ahp->ah_get_plcp_hdr = !sel_evm; 272250003Sadrian 273250003Sadrian return old_value; 274250003Sadrian} 275250003Sadrian 276250003Sadrianvoid ar9300_promisc_mode(struct ath_hal *ah, HAL_BOOL enable) 277250003Sadrian{ 278250003Sadrian u_int32_t reg_val = 0; 279250003Sadrian reg_val = OS_REG_READ(ah, AR_RX_FILTER); 280250003Sadrian if (enable){ 281250003Sadrian reg_val |= AR_RX_PROM; 282250003Sadrian } else{ /*Disable promisc mode */ 283250003Sadrian reg_val &= ~AR_RX_PROM; 284250003Sadrian } 285250003Sadrian OS_REG_WRITE(ah, AR_RX_FILTER, reg_val); 286250003Sadrian} 287250003Sadrian 288250003Sadrianvoid 289250003Sadrianar9300_read_pktlog_reg( 290250003Sadrian struct ath_hal *ah, 291250003Sadrian u_int32_t *rxfilter_val, 292250003Sadrian u_int32_t *rxcfg_val, 293250003Sadrian u_int32_t *phy_err_mask_val, 294250003Sadrian u_int32_t *mac_pcu_phy_err_regval) 295250003Sadrian{ 296250003Sadrian *rxfilter_val = OS_REG_READ(ah, AR_RX_FILTER); 297250003Sadrian *rxcfg_val = OS_REG_READ(ah, AR_RXCFG); 298250003Sadrian *phy_err_mask_val = OS_REG_READ(ah, AR_PHY_ERR); 299250003Sadrian *mac_pcu_phy_err_regval = OS_REG_READ(ah, 0x8338); 300250003Sadrian HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, 301250003Sadrian "%s[%d] rxfilter_val 0x%08x , rxcfg_val 0x%08x, " 302250003Sadrian "phy_err_mask_val 0x%08x mac_pcu_phy_err_regval 0x%08x\n", 303250003Sadrian __func__, __LINE__, 304250003Sadrian *rxfilter_val, *rxcfg_val, *phy_err_mask_val, *mac_pcu_phy_err_regval); 305250003Sadrian} 306250003Sadrian 307250003Sadrianvoid 308250003Sadrianar9300_write_pktlog_reg( 309250003Sadrian struct ath_hal *ah, 310250003Sadrian HAL_BOOL enable, 311250003Sadrian u_int32_t rxfilter_val, 312250003Sadrian u_int32_t rxcfg_val, 313250003Sadrian u_int32_t phy_err_mask_val, 314250003Sadrian u_int32_t mac_pcu_phy_err_reg_val) 315250003Sadrian{ 316250003Sadrian if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { 317250003Sadrian /* HW fix for rx hang and corruption. */ 318250003Sadrian rxfilter_val |= AR_RX_CONTROL_WRAPPER; 319250003Sadrian } 320250003Sadrian if (enable) { /* Enable pktlog phyerr setting */ 321250003Sadrian OS_REG_WRITE(ah, AR_RX_FILTER, 0xffff | AR_RX_COMPR_BAR | rxfilter_val); 322250003Sadrian OS_REG_WRITE(ah, AR_PHY_ERR, 0xFFFFFFFF); 323250003Sadrian OS_REG_WRITE(ah, AR_RXCFG, rxcfg_val | AR_RXCFG_ZLFDMA); 324250003Sadrian OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, mac_pcu_phy_err_reg_val | 0xFF); 325250003Sadrian } else { /* Disable phyerr and Restore regs */ 326250003Sadrian OS_REG_WRITE(ah, AR_RX_FILTER, rxfilter_val); 327250003Sadrian OS_REG_WRITE(ah, AR_PHY_ERR, phy_err_mask_val); 328250003Sadrian OS_REG_WRITE(ah, AR_RXCFG, rxcfg_val); 329250003Sadrian OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, mac_pcu_phy_err_reg_val); 330250003Sadrian } 331250003Sadrian HALDEBUG(ah, HAL_DEBUG_UNMASKABLE, 332250003Sadrian "%s[%d] ena %d rxfilter_val 0x%08x , rxcfg_val 0x%08x, " 333250003Sadrian "phy_err_mask_val 0x%08x mac_pcu_phy_err_regval 0x%08x\n", 334250003Sadrian __func__, __LINE__, 335250003Sadrian enable, rxfilter_val, rxcfg_val, 336250003Sadrian phy_err_mask_val, mac_pcu_phy_err_reg_val); 337250003Sadrian} 338