Path: blob/main/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_radio.c
48525 views
/*1* Copyright (c) 2013 Qualcomm Atheros, Inc.2*3* Permission to use, copy, modify, and/or distribute this software for any4* purpose with or without fee is hereby granted, provided that the above5* copyright notice and this permission notice appear in all copies.6*7* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH8* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY9* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,10* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM11* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR12* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR13* PERFORMANCE OF THIS SOFTWARE.14*/1516#include "opt_ah.h"1718#include "ah.h"19#include "ah_internal.h"2021#include "ar9300/ar9300.h"22#include "ar9300/ar9300reg.h"23#include "ar9300/ar9300phy.h"2425/* chansel table, used by Hornet and Poseidon */26static const u_int32_t ar9300_chansel_xtal_25M[] = {270x101479e, /* Freq 2412 - (128 << 17) + 83870 */280x101d027, /* Freq 2417 - (128 << 17) + 118823 */290x10258af, /* Freq 2422 - (129 << 17) + 22703 */300x102e138, /* Freq 2427 - (129 << 17) + 57656 */310x10369c0, /* Freq 2432 - (129 << 17) + 92608 */320x103f249, /* Freq 2437 - (129 << 17) + 127561 */330x1047ad1, /* Freq 2442 - (130 << 17) + 31441 */340x105035a, /* Freq 2447 - (130 << 17) + 66394 */350x1058be2, /* Freq 2452 - (130 << 17) + 101346 */360x106146b, /* Freq 2457 - (131 << 17) + 5227 */370x1069cf3, /* Freq 2462 - (131 << 17) + 40179 */380x107257c, /* Freq 2467 - (131 << 17) + 75132 */390x107ae04, /* Freq 2472 - (131 << 17) + 110084 */400x108f5b2, /* Freq 2484 - (132 << 17) + 62898 */41};4243static const u_int32_t ar9300_chansel_xtal_40M[] = {440xa0ccbe, /* Freq 2412 - (80 << 17) + 52414 */450xa12213, /* Freq 2417 - (80 << 17) + 74259 */460xa17769, /* Freq 2422 - (80 << 17) + 96105 */470xa1ccbe, /* Freq 2427 - (80 << 17) + 117950 */480xa22213, /* Freq 2432 - (81 << 17) + 8723 */490xa27769, /* Freq 2437 - (81 << 17) + 30569 */500xa2ccbe, /* Freq 2442 - (81 << 17) + 52414 */510xa32213, /* Freq 2447 - (81 << 17) + 74259 */520xa37769, /* Freq 2452 - (81 << 17) + 96105 */530xa3ccbe, /* Freq 2457 - (81 << 17) + 117950 */540xa42213, /* Freq 2462 - (82 << 17) + 8723 */550xa47769, /* Freq 2467 - (82 << 17) + 30569 */560xa4ccbe, /* Freq 2472 - (82 << 17) + 52414 */570xa5998b, /* Freq 2484 - (82 << 17) + 104843 */58};596061/*62* Take the MHz channel value and set the Channel value63*64* ASSUMES: Writes enabled to analog bus65*66* Actual Expression,67*68* For 2GHz channel,69* Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)70* (freq_ref = 40MHz)71*72* For 5GHz channel,73* Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10)74* (freq_ref = 40MHz/(24>>amode_ref_sel))75*76* For 5GHz channels which are 5MHz spaced,77* Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)78* (freq_ref = 40MHz)79*/80static HAL_BOOL81ar9300_set_channel(struct ath_hal *ah, struct ieee80211_channel *chan)82{83u_int16_t b_mode, frac_mode = 0, a_mode_ref_sel = 0;84u_int32_t freq, channel_sel, reg32;85u_int8_t clk_25mhz = AH9300(ah)->clk_25mhz;86CHAN_CENTERS centers;87int load_synth_channel;88#ifdef AH_DEBUG_ALQ89HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);90#endif9192/*93* Put this behind AH_DEBUG_ALQ for now until the Hornet94* channel_sel code below is made to work.95*/96#ifdef AH_DEBUG_ALQ97OS_MARK(ah, AH_MARK_SETCHANNEL, ichan->channel);98#endif99100ar9300_get_channel_centers(ah, chan, ¢ers);101freq = centers.synth_center;102103if (freq < 4800) { /* 2 GHz, fractional mode */104b_mode = 1; /* 2 GHz */105106if (AR_SREV_HORNET(ah)) {107#if 0108u_int32_t ichan =109ieee80211_mhz2ieee(ah, chan->ic_freq, chan->ic_flags);110HALASSERT(ichan > 0 && ichan <= 14);111if (clk_25mhz) {112channel_sel = ar9300_chansel_xtal_25M[ichan - 1];113} else {114channel_sel = ar9300_chansel_xtal_40M[ichan - 1];115}116#endif117uint32_t i;118119/*120* Pay close attention to this bit!121*122* We need to map the actual desired synth frequency to123* one of the channel select array entries.124*125* For HT20, it'll align with the channel we select.126*127* For HT40 though it won't - the centre frequency128* will not be the frequency of chan->ic_freq or ichan->freq;129* it needs to be whatever frequency maps to 'freq'.130*/131i = ath_hal_mhz2ieee_2ghz(ah, freq);132HALASSERT(i > 0 && i <= 14);133if (clk_25mhz) {134channel_sel = ar9300_chansel_xtal_25M[i - 1];135} else {136channel_sel = ar9300_chansel_xtal_40M[i - 1];137}138} else if (AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) {139u_int32_t channel_frac;140/*141* freq_ref = (40 / (refdiva >> a_mode_ref_sel));142* (where refdiva = 1 and amoderefsel = 0)143* ndiv = ((chan_mhz * 4) / 3) / freq_ref;144* chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000145*/146channel_sel = (freq * 4) / 120;147channel_frac = (((freq * 4) % 120) * 0x20000) / 120;148channel_sel = (channel_sel << 17) | (channel_frac);149} else if (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) {150u_int32_t channel_frac;151if (clk_25mhz) {152/*153* freq_ref = (50 / (refdiva >> a_mode_ref_sel));154* (where refdiva = 1 and amoderefsel = 0)155* ndiv = ((chan_mhz * 4) / 3) / freq_ref;156* chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000157*/158if (AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) {159/* Doubler is off for Scorpion */160channel_sel = (freq * 4) / 75;161channel_frac = (((freq * 4) % 75) * 0x20000) / 75;162} else {163channel_sel = (freq * 2) / 75;164channel_frac = (((freq * 2) % 75) * 0x20000) / 75;165}166} else {167/*168* freq_ref = (50 / (refdiva >> a_mode_ref_sel));169* (where refdiva = 1 and amoderefsel = 0)170* ndiv = ((chan_mhz * 4) / 3) / freq_ref;171* chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000172*/173if (AR_SREV_SCORPION(ah)) {174/* Doubler is off for Scorpion */175channel_sel = (freq * 4) / 120;176channel_frac = (((freq * 4) % 120) * 0x20000) / 120;177} else {178channel_sel = (freq * 2) / 120;179channel_frac = (((freq * 2) % 120) * 0x20000) / 120;180}181}182channel_sel = (channel_sel << 17) | (channel_frac);183} else {184channel_sel = CHANSEL_2G(freq);185}186} else {187b_mode = 0; /* 5 GHz */188if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && clk_25mhz){189u_int32_t channel_frac;190/*191* freq_ref = (50 / (refdiva >> amoderefsel));192* (refdiva = 1, amoderefsel = 0)193* ndiv = ((chan_mhz * 2) / 3) / freq_ref;194* chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000195*/196channel_sel = freq / 75 ;197channel_frac = ((freq % 75) * 0x20000) / 75;198channel_sel = (channel_sel << 17) | (channel_frac);199} else {200channel_sel = CHANSEL_5G(freq);201/* Doubler is ON, so, divide channel_sel by 2. */202channel_sel >>= 1;203}204}205206207/* Enable fractional mode for all channels */208frac_mode = 1;209a_mode_ref_sel = 0;210load_synth_channel = 0;211212reg32 = (b_mode << 29);213OS_REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32);214215/* Enable Long shift Select for Synthesizer */216OS_REG_RMW_FIELD(ah,217AR_PHY_65NM_CH0_SYNTH4, AR_PHY_SYNTH4_LONG_SHIFT_SELECT, 1);218219/* program synth. setting */220reg32 =221(channel_sel << 2) |222(a_mode_ref_sel << 28) |223(frac_mode << 30) |224(load_synth_channel << 31);225if (IEEE80211_IS_CHAN_QUARTER(chan)) {226reg32 += CHANSEL_5G_DOT5MHZ;227}228OS_REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32);229/* Toggle Load Synth channel bit */230load_synth_channel = 1;231reg32 |= load_synth_channel << 31;232OS_REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32);233234235AH_PRIVATE(ah)->ah_curchan = chan;236237return AH_TRUE;238}239240241#if 0242static HAL_BOOL243ar9300_get_chip_power_limits(struct ath_hal *ah, HAL_CHANNEL *chans,244u_int32_t nchans)245{246int i;247248for (i = 0; i < nchans; i++) {249chans[i].max_tx_power = AR9300_MAX_RATE_POWER;250chans[i].min_tx_power = AR9300_MAX_RATE_POWER;251}252return AH_TRUE;253}254#endif255256/* XXX FreeBSD */257static HAL_BOOL258ar9300_get_chip_power_limits(struct ath_hal *ah,259struct ieee80211_channel *chan)260{261/* XXX ? */262chan->ic_minpower = 0;263chan->ic_maxpower = AR9300_MAX_RATE_POWER;264265return AH_TRUE;266}267268HAL_BOOL269ar9300_rf_attach(struct ath_hal *ah, HAL_STATUS *status)270{271struct ath_hal_9300 *ahp = AH9300(ah);272273ahp->ah_rf_hal.set_channel = ar9300_set_channel;274ahp->ah_rf_hal.get_chip_power_lim = ar9300_get_chip_power_limits;275276*status = HAL_OK;277278return AH_TRUE;279}280281282