예제 #1
0
void ar9300_start_spectral_scan(struct ath_hal *ah)
{
    u_int32_t val;
    struct ath_hal_9300 *ahp = AH9300(ah);
    bool asleep = ahp->ah_chip_full_sleep;

    if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
        ar9300_set_power_mode(ah, HAL_PM_AWAKE, true);
    }

    ar9300_prep_spectral_scan(ah);

    /* activate spectral scan */
    val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
    /* This is a hardware bug fix, the enable and active bits should 
     * not be set/reset in the same write operation to the register 
     */
    if (!(val & AR_PHY_SPECTRAL_SCAN_ENABLE)) {
        val |= AR_PHY_SPECTRAL_SCAN_ENABLE;
        OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val);
        val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);
    }
    val |= AR_PHY_SPECTRAL_SCAN_ACTIVE;
    OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val);
    
    /* Reset the PHY_ERR_MASK */
    val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG);
    OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val | AR_PHY_ERR_RADAR);

    if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
        ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, true);
    }
}
예제 #2
0
/*
    function to adjust PRSSI value for CAC problem

*/
void
ar9300_dfs_cac_war(struct ath_hal *ah, u_int32_t start)
{
    u_int32_t val;
    struct ath_hal_9300 *ahp = AH9300(ah);
    bool asleep = ahp->ah_chip_full_sleep;

    if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
        ar9300_set_power_mode(ah, HAL_PM_AWAKE, true);
    }

    if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) {
        val = OS_REG_READ(ah, AR_PHY_RADAR_0);
        if (start) {
            val &= ~AR_PHY_RADAR_0_PRSSI;
            val |= SM(AR9300_DFS_PRSSI_CAC, AR_PHY_RADAR_0_PRSSI); 
        } else {
            val &= ~AR_PHY_RADAR_0_PRSSI;
            val |= SM(AR9300_DFS_PRSSI, AR_PHY_RADAR_0_PRSSI);
        }
        OS_REG_WRITE(ah, AR_PHY_RADAR_0, val | AR_PHY_RADAR_0_ENA);
        ah->ah_use_cac_prssi = start;
    }
    
    if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
        ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, true);
    }
}
예제 #3
0
u_int32_t ar9300_dfs_config_fft(struct ath_hal *ah, bool is_enable)
{
    u_int32_t val;
    struct ath_hal_9300 *ahp = AH9300(ah);
    bool asleep = ahp->ah_chip_full_sleep;

    if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
        ar9300_set_power_mode(ah, HAL_PM_AWAKE, true);
    }

    val = OS_REG_READ(ah, AR_PHY_RADAR_0);

    if (is_enable) {
        val |= AR_PHY_RADAR_0_FFT_ENA;
    } else {
        val &= ~AR_PHY_RADAR_0_FFT_ENA;
    }

    OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
    val = OS_REG_READ(ah, AR_PHY_RADAR_0);
    
    if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
        ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, true);
    }
    return val;
}
예제 #4
0
bool
ar9300_handle_radar_bb_panic(struct ath_hal *ah)
{
    u_int32_t status;
    u_int32_t val;   
    struct ath_hal_9300 *ahp = AH9300(ah);
    bool asleep = ahp->ah_chip_full_sleep;
       
    status = AH_PRIVATE(ah)->ah_bb_panic_last_status;
   
    if ( status == 0x04000539 ) { 
        if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
            ar9300_set_power_mode(ah, HAL_PM_AWAKE, true);
        } 
        /* recover from this BB panic without reset*/
        /* set AR9300_DFS_FIRPWR to -1 */
        val = OS_REG_READ(ah, AR_PHY_RADAR_0);
        val &= (~AR_PHY_RADAR_0_FIRPWR);
        val |= SM( 0x7f, AR_PHY_RADAR_0_FIRPWR);
        OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
        OS_DELAY(1);
        /* set AR9300_DFS_FIRPWR to its default value */
        val = OS_REG_READ(ah, AR_PHY_RADAR_0);
        val &= ~AR_PHY_RADAR_0_FIRPWR;
        val |= SM( AR9300_DFS_FIRPWR, AR_PHY_RADAR_0_FIRPWR);
        OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);
        if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
            ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, true);
        }   
        return true;
    } else if (status == 0x0400000a) {
        /* EV 92527 : reset required if we see this signature */
        HDPRINTF(ah, HAL_DBG_DFS, "%s: BB Panic -- 0x0400000a\n", __func__);
        return false;
    } else if (status == 0x1300000a) {
        /* EV92527: we do not need a reset if we see this signature */
        HDPRINTF(ah, HAL_DBG_DFS, "%s: BB Panic -- 0x1300000a\n", __func__);
        return true;
    } else if ((AR_SREV_WASP(ah) || AR_SREV_HONEYBEE(ah)) && (status == 0x04000409)) {
        return true;
    } else {
        if (ar9300_get_capability(ah, HAL_CAP_LDPCWAR, 0, AH_NULL) == HAL_OK &&
            (status & 0xff00000f) == 0x04000009 &&
            status != 0x04000409 &&
            status != 0x04000b09 &&
            status != 0x04000e09 &&
            (status & 0x0000ff00))
        {
            /* disable RIFS Rx */
#ifdef AH_DEBUG
            HDPRINTF(ah, HAL_DBG_UNMASKABLE, "%s: BB status=0x%08x rifs=%d - disable\n",
                     __func__, status, ahp->ah_rifs_enabled);
#endif
            ar9300_set_rifs_delay(ah, false);
        }
        return false;
    }
}
예제 #5
0
void
ar9300_get_spectral_params(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss)
{
    u_int32_t val;
    HAL_CHANNEL_INTERNAL *chan = NULL;
    const struct ieee80211_channel *c;
    int i, ichain, rx_chain_status;
    struct ath_hal_9300 *ahp = AH9300(ah);
    HAL_BOOL asleep = ahp->ah_chip_full_sleep;

    c = AH_PRIVATE(ah)->ah_curchan;
    if (c != NULL)
        chan = ath_hal_checkchannel(ah, c);

    // XXX TODO: just always wake up all chips?
    if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
        ar9300_set_power_mode(ah, HAL_PM_AWAKE, AH_TRUE);
    }

    val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);

    ss->ss_fft_period = MS(val, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD);
    ss->ss_period = MS(val, AR_PHY_SPECTRAL_SCAN_PERIOD);
    ss->ss_count = MS(val, AR_PHY_SPECTRAL_SCAN_COUNT);
    ss->ss_short_report = (val & AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT) ? 1:0;
    ss->ss_spectral_pri = ( val & AR_PHY_SPECTRAL_SCAN_PRIORITY_HI) ? 1:0;
    OS_MEMZERO(ss->ss_nf_cal, sizeof(ss->ss_nf_cal)); 
    OS_MEMZERO(ss->ss_nf_pwr, sizeof(ss->ss_nf_cal)); 
    ss->ss_nf_temp_data = 0;

    if (chan != NULL) {
        rx_chain_status = OS_REG_READ(ah, AR_PHY_RX_CHAINMASK) & 0x7;
        for (i = 0; i < HAL_NUM_NF_READINGS; i++) {
            ichain = i % 3;
            if (rx_chain_status & (1 << ichain)) {
                ss->ss_nf_cal[i] =
                    ar9300_noise_floor_get(ah, chan->channel, ichain);     
                ss->ss_nf_pwr[i] =
                    ar9300_noise_floor_power_get(ah, chan->channel, ichain);
            }
        }
        ss->ss_nf_temp_data = OS_REG_READ_FIELD(ah, AR_PHY_BB_THERM_ADC_4, AR_PHY_BB_THERM_ADC_4_LATEST_THERM);
    } else {
        HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
            "%s: chan is NULL - no ss nf values\n", __func__);
    }

    if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
        ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, AH_TRUE);
    }
}
예제 #6
0
u_int32_t ar9300_get_spectral_config(struct ath_hal *ah)
{
    u_int32_t val;
    struct ath_hal_9300 *ahp = AH9300(ah);
    bool asleep = ahp->ah_chip_full_sleep;

    if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
        ar9300_set_power_mode(ah, HAL_PM_AWAKE, true);
    }

    val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);

    if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
        ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, true);
    }
    return val;
}
예제 #7
0
void ar9300_stop_spectral_scan(struct ath_hal *ah)
{
    u_int32_t val;
    struct ath_hal_9300 *ahp = AH9300(ah);
    bool asleep = ahp->ah_chip_full_sleep;

    if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
        ar9300_set_power_mode(ah, HAL_PM_AWAKE, true);
    }
    val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);

    /* deactivate spectral scan */
    /* HW Bug fix -- Do not disable the spectral scan
     * only turn off the active bit
     */
    //val &= ~AR_PHY_SPECTRAL_SCAN_ENABLE;
    val &= ~AR_PHY_SPECTRAL_SCAN_ACTIVE;
    OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val);
    val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);

    OS_REG_RMW_FIELD(ah, AR_PHY_RADAR_1, AR_PHY_RADAR_1_CF_BIN_THRESH,
                     ahp->ah_radar1);
    OS_REG_RMW_FIELD(ah, AR_PHY_TIMING2, AR_PHY_TIMING2_DC_OFFSET,
                     ahp->ah_dc_offset);
    OS_REG_WRITE(ah, AR_PHY_ERR, 0);

    if (AH_PRIVATE(ah)->ah_curchan &&
        IS_5GHZ_FAST_CLOCK_EN(ah, AH_PRIVATE(ah)->ah_curchan))
    { /* fast clock */
        OS_REG_RMW_FIELD(ah, AR_PHY_MODE, AR_PHY_MODE_DISABLE_CCK,
                         ahp->ah_disable_cck);
    }

    val = OS_REG_READ(ah, AR_PHY_ERR);
    
    val = OS_REG_READ(ah, AR_PHY_ERR_MASK_REG) & (~AR_PHY_ERR_RADAR);
    OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, val);
    
    if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
        ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, true);
    }
}
예제 #8
0
/*
 * Get the radar parameter values and return them in the pe
 * structure
 */
void
ar9300_get_dfs_thresh(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
{
    u_int32_t val, temp;
    struct ath_hal_9300 *ahp = AH9300(ah);
    bool asleep = ahp->ah_chip_full_sleep;
    
    if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
        ar9300_set_power_mode(ah, HAL_PM_AWAKE, true);
    }

    val = OS_REG_READ(ah, AR_PHY_RADAR_0);
    temp = MS(val, AR_PHY_RADAR_0_FIRPWR);
    temp |= ~(AR_PHY_RADAR_0_FIRPWR >> AR_PHY_RADAR_0_FIRPWR_S);
    pe->pe_firpwr = temp;
    pe->pe_rrssi = MS(val, AR_PHY_RADAR_0_RRSSI);
    pe->pe_height = MS(val, AR_PHY_RADAR_0_HEIGHT);
    pe->pe_prssi = MS(val, AR_PHY_RADAR_0_PRSSI);
    pe->pe_inband = MS(val, AR_PHY_RADAR_0_INBAND);

    val = OS_REG_READ(ah, AR_PHY_RADAR_1);

    pe->pe_relpwr = MS(val, AR_PHY_RADAR_1_RELPWR_THRESH);
    if (val & AR_PHY_RADAR_1_RELPWR_ENA) {
        pe->pe_relpwr |= HAL_PHYERR_PARAM_ENABLE;
    }
    pe->pe_relstep = MS(val, AR_PHY_RADAR_1_RELSTEP_THRESH);
    if (val & AR_PHY_RADAR_1_RELSTEP_CHECK) {
        pe->pe_relstep |= HAL_PHYERR_PARAM_ENABLE;
    }
    pe->pe_maxlen = MS(val, AR_PHY_RADAR_1_MAXLEN);
    
    if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
        ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, true);
    }
}
예제 #9
0
void
ar9300_configure_spectral_scan(struct ath_hal *ah, HAL_SPECTRAL_PARAM *ss)
{
    u_int32_t val, i;
    struct ath_hal_9300 *ahp = AH9300(ah);
    bool asleep = ahp->ah_chip_full_sleep;
    int16_t nf_buf[NUM_NF_READINGS];

    if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
        ar9300_set_power_mode(ah, HAL_PM_AWAKE, true);
    }

    ar9300_prep_spectral_scan(ah);

    if (ss->ss_spectral_pri) {
        for (i = 0; i < NUM_NF_READINGS; i++) {
            nf_buf[i] = NOISE_PWR_DBM_2_INT(ss->ss_nf_cal[i]);
        }
        ar9300_load_nf(ah, nf_buf);
#ifdef DEMO_MODE
        ar9300_disable_strong_signal(ah);
        ar9300_disable_weak_signal(ah);
        ar9300_set_radar_dc_thresh(ah);
        ar9300_set_cca_threshold(ah, MAX_CCA_THRESH);
        /*ar9300_disable_restart(ah);*/
#endif
    }   

    val = OS_REG_READ(ah, AR_PHY_SPECTRAL_SCAN);

    if (ss->ss_fft_period != HAL_SPECTRAL_PARAM_NOVAL) {
        val &= ~AR_PHY_SPECTRAL_SCAN_FFT_PERIOD;
        val |= SM(ss->ss_fft_period, AR_PHY_SPECTRAL_SCAN_FFT_PERIOD);
    }

    if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) {
        val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD;
        val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD);
    }

    if (ss->ss_count != HAL_SPECTRAL_PARAM_NOVAL) {
        val &= ~AR_PHY_SPECTRAL_SCAN_COUNT;
        /* Remnants of a Merlin bug, 128 translates to 0 for
         * continuous scanning. Instead we do piecemeal captures
         * of 64 samples for Osprey.
         */
        if (ss->ss_count == 128) {
            val |= SM(0, AR_PHY_SPECTRAL_SCAN_COUNT);
        } else {
            val |= SM(ss->ss_count, AR_PHY_SPECTRAL_SCAN_COUNT);
        }
    }

    if (ss->ss_period != HAL_SPECTRAL_PARAM_NOVAL) {
        val &= ~AR_PHY_SPECTRAL_SCAN_PERIOD;
        val |= SM(ss->ss_period, AR_PHY_SPECTRAL_SCAN_PERIOD);
    }

    if (ss->ss_short_report == true) {
        val |= AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
    } else {
        val &= ~AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT;
    }
    
    /* if noise power cal, force high priority */
    if (ss->ss_spectral_pri) {
        val |= AR_PHY_SPECTRAL_SCAN_PRIORITY_HI;
    } else {
        val &= ~AR_PHY_SPECTRAL_SCAN_PRIORITY_HI;
    }
    
    /* enable spectral scan */
    OS_REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val | AR_PHY_SPECTRAL_SCAN_ENABLE);

    if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
        ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, true);
    }
}
예제 #10
0
/*
 * Enable radar detection and set the radar parameters per the
 * values in pe
 */
void
ar9300_enable_dfs(struct ath_hal *ah, HAL_PHYERR_PARAM *pe)
{
    u_int32_t val;
    struct ath_hal_private  *ahp = AH_PRIVATE(ah);
    HAL_CHANNEL_INTERNAL *ichan = ahp->ah_curchan;
    struct ath_hal_9300 *ah9300 = AH9300(ah);
    bool asleep = ah9300->ah_chip_full_sleep;
    int reg_writes = 0;

    if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
        ar9300_set_power_mode(ah, HAL_PM_AWAKE, true);
    }

    val = OS_REG_READ(ah, AR_PHY_RADAR_0);
    val |= AR_PHY_RADAR_0_FFT_ENA | AR_PHY_RADAR_0_ENA;
    if (pe->pe_firpwr != HAL_PHYERR_PARAM_NOVAL) {
        val &= ~AR_PHY_RADAR_0_FIRPWR;
        val |= SM(pe->pe_firpwr, AR_PHY_RADAR_0_FIRPWR);
    }
    if (pe->pe_rrssi != HAL_PHYERR_PARAM_NOVAL) {
        val &= ~AR_PHY_RADAR_0_RRSSI;
        val |= SM(pe->pe_rrssi, AR_PHY_RADAR_0_RRSSI);
    }
    if (pe->pe_height != HAL_PHYERR_PARAM_NOVAL) {
        val &= ~AR_PHY_RADAR_0_HEIGHT;
        val |= SM(pe->pe_height, AR_PHY_RADAR_0_HEIGHT);
    }
    if (pe->pe_prssi != HAL_PHYERR_PARAM_NOVAL) {
        val &= ~AR_PHY_RADAR_0_PRSSI;
        if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) {
            if (ah->ah_use_cac_prssi) {
                val |= SM(AR9300_DFS_PRSSI_CAC, AR_PHY_RADAR_0_PRSSI);
            } else {
                val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI);
            }
        } else {
            val |= SM(pe->pe_prssi, AR_PHY_RADAR_0_PRSSI);
        }
    }
    if (pe->pe_inband != HAL_PHYERR_PARAM_NOVAL) {
        val &= ~AR_PHY_RADAR_0_INBAND;
        val |= SM(pe->pe_inband, AR_PHY_RADAR_0_INBAND);
    }
    OS_REG_WRITE(ah, AR_PHY_RADAR_0, val);

    val = OS_REG_READ(ah, AR_PHY_RADAR_1);
    val |= AR_PHY_RADAR_1_MAX_RRSSI | AR_PHY_RADAR_1_BLOCK_CHECK;
    if (pe->pe_maxlen != HAL_PHYERR_PARAM_NOVAL) {
        val &= ~AR_PHY_RADAR_1_MAXLEN;
        val |= SM(pe->pe_maxlen, AR_PHY_RADAR_1_MAXLEN);
    }
    if (pe->pe_relstep != HAL_PHYERR_PARAM_NOVAL) {
        val &= ~AR_PHY_RADAR_1_RELSTEP_THRESH;
        val |= SM(pe->pe_relstep, AR_PHY_RADAR_1_RELSTEP_THRESH);
    }
    if (pe->pe_relpwr != HAL_PHYERR_PARAM_NOVAL) {
        val &= ~AR_PHY_RADAR_1_RELPWR_THRESH;
        val |= SM(pe->pe_relpwr, AR_PHY_RADAR_1_RELPWR_THRESH);
    }
    OS_REG_WRITE(ah, AR_PHY_RADAR_1, val);

    if (ath_hal_getcapability(ah, HAL_CAP_EXT_CHAN_DFS, 0, 0) == HAL_OK) {
        val = OS_REG_READ(ah, AR_PHY_RADAR_EXT);
        if (IS_CHAN_HT40(ichan)) {
            /* Enable extension channel radar detection */
            OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val | AR_PHY_RADAR_EXT_ENA);
        } else {
            /* HT20 mode, disable extension channel radar detect */
            OS_REG_WRITE(ah, AR_PHY_RADAR_EXT, val & ~AR_PHY_RADAR_EXT_ENA);
        }
    }
    /*
        apply DFS postamble array from INI
        column 0 is register ID, column 1 is  HT20 value, colum2 is HT40 value
    */

    if (AR_SREV_AR9580(ah) || AR_SREV_WASP(ah) || AR_SREV_OSPREY_22(ah) || AR_SREV_SCORPION(ah)) {
        REG_WRITE_ARRAY(&ah9300->ah_ini_dfs,IS_CHAN_HT40(ichan)? 2:1, reg_writes);
    }
#ifdef ATH_HAL_DFS_CHIRPING_FIX_APH128
    HDPRINTF(ah, HAL_DBG_DFS,"DFS change the timing value\n");
    if (AR_SREV_AR9580(ah) && IS_CHAN_HT40(ichan)) {
        OS_REG_WRITE(ah, AR_PHY_TIMING6, 0x3140c00a);	
    }
#endif
    if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && asleep) {
        ar9300_set_power_mode(ah, HAL_PM_FULL_SLEEP, true);
    }
}