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; } }
int papredistortionSingleTable(struct ath_hal *ah, HAL_CHANNEL *chan, int txChainMask) { int chainNum; unsigned int PA_table[24], smallSignalGain; int status = 0, disable_papd=1, chain_fail[3]={0,0,0}; int paprd_retry_count; UserPrint("Run PA predistortion algorithm: txChainMask=0x%X.\n", txChainMask); /* * Before doing PAPRD training, we must disable pal spare of * hw greeen tx function */ ar9300_hwgreentx_set_pal_spare(AH,0);//ar9300_set_pal_spare(AH,0); LinkTransmitPAPDWarmUp(txChainMask); status= ar9300_paprd_init_table(ah, chan); if(status==-1) { ar9300_enable_paprd(ah, AH_FALSE, chan); UserPrint("Warning:: PA predistortion failed in InitTable\n"); return -1; } { struct ath_hal_9300 *ahp = AH9300(ah); UserPrint("Training power_x2 is %d, channel %d\n", ahp->paprd_training_power, chan->channel); } for(chainNum=0; chainNum<3; chainNum++) { unsigned int i, desired_gain, gain_index; if(txChainMask&(1<<chainNum)) { paprd_retry_count = 0; while (paprd_retry_count < 5) { ar9300_paprd_setup_gain_table(ah,chainNum); LinkTransmitPAPD(ah, chainNum); ar9300_paprd_is_done(ah); status = ar9300_paprd_create_curve(ah, chan, chainNum); if (status != HAL_EINPROGRESS) { if(status==0) { ar9300_populate_paprd_single_table(ah, chan, chainNum); if (!AR_SREV_HONEYBEE(ah) && !AR_SREV_DRAGONFLY(ah)) { if (txChainMask == 0x2 || txChainMask == 0x4){ ar9300_populate_paprd_single_table(ah, chan, 0); } } disable_papd = 0; } else { disable_papd = 1; chain_fail[chainNum] = 1; } break; } else { /* need re-train paprd */ paprd_retry_count++; } } if (paprd_retry_count > 5) UserPrint("Warning: ch%d PAPRD re-train fail\n", (1 << chainNum)); } } if(disable_papd==0) { ar9300_enable_paprd(ah, AH_TRUE, chan); /* * restore PAL spare of hw green tx function */ ar9300_hwgreentx_set_pal_spare(AH,1); } else { ar9300_enable_paprd(ah, AH_FALSE, chan); UserPrint("Warning:: PA predistortion failed. chain_fail_flag %d %d %d\n", chain_fail[0], chain_fail[1], chain_fail[2]); /* * restore PAL spare of hw green tx function */ ar9300_hwgreentx_set_pal_spare(AH,1); return -1; } return 0; }
/* * Take the MHz channel value and set the Channel value * * ASSUMES: Writes enabled to analog bus * * Actual Expression, * * For 2GHz channel, * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) * (freq_ref = 40MHz) * * For 5GHz channel, * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10) * (freq_ref = 40MHz/(24>>amode_ref_sel)) * * For 5GHz channels which are 5MHz spaced, * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) * (freq_ref = 40MHz) */ static HAL_BOOL ar9300_set_channel(struct ath_hal *ah, struct ieee80211_channel *chan) { u_int16_t b_mode, frac_mode = 0, a_mode_ref_sel = 0; u_int32_t freq, channel_sel, reg32; u_int8_t clk_25mhz = AH9300(ah)->clk_25mhz; CHAN_CENTERS centers; int load_synth_channel; #ifdef AH_DEBUG_ALQ HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); #endif /* * Put this behind AH_DEBUG_ALQ for now until the Hornet * channel_sel code below is made to work. */ #ifdef AH_DEBUG_ALQ OS_MARK(ah, AH_MARK_SETCHANNEL, ichan->channel); #endif ar9300_get_channel_centers(ah, chan, ¢ers); freq = centers.synth_center; if (freq < 4800) { /* 2 GHz, fractional mode */ b_mode = 1; /* 2 GHz */ if (AR_SREV_HORNET(ah)) { #if 0 u_int32_t ichan = ieee80211_mhz2ieee(ah, chan->ic_freq, chan->ic_flags); HALASSERT(ichan > 0 && ichan <= 14); if (clk_25mhz) { channel_sel = ar9300_chansel_xtal_25M[ichan - 1]; } else { channel_sel = ar9300_chansel_xtal_40M[ichan - 1]; } #endif uint32_t i; /* * Pay close attention to this bit! * * We need to map the actual desired synth frequency to * one of the channel select array entries. * * For HT20, it'll align with the channel we select. * * For HT40 though it won't - the centre frequency * will not be the frequency of chan->ic_freq or ichan->freq; * it needs to be whatever frequency maps to 'freq'. */ i = ath_hal_mhz2ieee_2ghz(ah, freq); HALASSERT(i > 0 && i <= 14); if (clk_25mhz) { channel_sel = ar9300_chansel_xtal_25M[i - 1]; } else { channel_sel = ar9300_chansel_xtal_40M[i - 1]; } } else if (AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) { u_int32_t channel_frac; /* * freq_ref = (40 / (refdiva >> a_mode_ref_sel)); * (where refdiva = 1 and amoderefsel = 0) * ndiv = ((chan_mhz * 4) / 3) / freq_ref; * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 */ channel_sel = (freq * 4) / 120; channel_frac = (((freq * 4) % 120) * 0x20000) / 120; channel_sel = (channel_sel << 17) | (channel_frac); } else if (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) { u_int32_t channel_frac; if (clk_25mhz) { /* * freq_ref = (50 / (refdiva >> a_mode_ref_sel)); * (where refdiva = 1 and amoderefsel = 0) * ndiv = ((chan_mhz * 4) / 3) / freq_ref; * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 */ if (AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) { /* Doubler is off for Scorpion */ channel_sel = (freq * 4) / 75; channel_frac = (((freq * 4) % 75) * 0x20000) / 75; } else { channel_sel = (freq * 2) / 75; channel_frac = (((freq * 2) % 75) * 0x20000) / 75; } } else { /* * freq_ref = (50 / (refdiva >> a_mode_ref_sel)); * (where refdiva = 1 and amoderefsel = 0) * ndiv = ((chan_mhz * 4) / 3) / freq_ref; * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 */ if (AR_SREV_SCORPION(ah)) { /* Doubler is off for Scorpion */ channel_sel = (freq * 4) / 120; channel_frac = (((freq * 4) % 120) * 0x20000) / 120; } else { channel_sel = (freq * 2) / 120; channel_frac = (((freq * 2) % 120) * 0x20000) / 120; } } channel_sel = (channel_sel << 17) | (channel_frac); } else { channel_sel = CHANSEL_2G(freq); } } else { b_mode = 0; /* 5 GHz */ if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && clk_25mhz){ u_int32_t channel_frac; /* * freq_ref = (50 / (refdiva >> amoderefsel)); * (refdiva = 1, amoderefsel = 0) * ndiv = ((chan_mhz * 2) / 3) / freq_ref; * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 */ channel_sel = freq / 75 ; channel_frac = ((freq % 75) * 0x20000) / 75; channel_sel = (channel_sel << 17) | (channel_frac); } else { channel_sel = CHANSEL_5G(freq); /* Doubler is ON, so, divide channel_sel by 2. */ channel_sel >>= 1; } } /* Enable fractional mode for all channels */ frac_mode = 1; a_mode_ref_sel = 0; load_synth_channel = 0; reg32 = (b_mode << 29); OS_REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); /* Enable Long shift Select for Synthesizer */ OS_REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_SYNTH4, AR_PHY_SYNTH4_LONG_SHIFT_SELECT, 1); /* program synth. setting */ reg32 = (channel_sel << 2) | (a_mode_ref_sel << 28) | (frac_mode << 30) | (load_synth_channel << 31); if (IEEE80211_IS_CHAN_QUARTER(chan)) { reg32 += CHANSEL_5G_DOT5MHZ; } OS_REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32); /* Toggle Load Synth channel bit */ load_synth_channel = 1; reg32 |= load_synth_channel << 31; OS_REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32); AH_PRIVATE(ah)->ah_curchan = chan; return AH_TRUE; }