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_internal.h" 21250003Sadrian 22250003Sadrian#include "ar9300/ar9300.h" 23250003Sadrian#include "ar9300/ar9300reg.h" 24250003Sadrian#include "ar9300/ar9300phy.h" 25250003Sadrian 26250003Sadrian/* chansel table, used by Hornet and Poseidon */ 27250003Sadrianstatic const u_int32_t ar9300_chansel_xtal_25M[] = { 28250003Sadrian 0x101479e, /* Freq 2412 - (128 << 17) + 83870 */ 29250003Sadrian 0x101d027, /* Freq 2417 - (128 << 17) + 118823 */ 30250003Sadrian 0x10258af, /* Freq 2422 - (129 << 17) + 22703 */ 31250003Sadrian 0x102e138, /* Freq 2427 - (129 << 17) + 57656 */ 32250003Sadrian 0x10369c0, /* Freq 2432 - (129 << 17) + 92608 */ 33250003Sadrian 0x103f249, /* Freq 2437 - (129 << 17) + 127561 */ 34250003Sadrian 0x1047ad1, /* Freq 2442 - (130 << 17) + 31441 */ 35250003Sadrian 0x105035a, /* Freq 2447 - (130 << 17) + 66394 */ 36250003Sadrian 0x1058be2, /* Freq 2452 - (130 << 17) + 101346 */ 37250003Sadrian 0x106146b, /* Freq 2457 - (131 << 17) + 5227 */ 38250003Sadrian 0x1069cf3, /* Freq 2462 - (131 << 17) + 40179 */ 39250003Sadrian 0x107257c, /* Freq 2467 - (131 << 17) + 75132 */ 40250003Sadrian 0x107ae04, /* Freq 2472 - (131 << 17) + 110084 */ 41250003Sadrian 0x108f5b2, /* Freq 2484 - (132 << 17) + 62898 */ 42250003Sadrian}; 43250003Sadrian 44250003Sadrianstatic const u_int32_t ar9300_chansel_xtal_40M[] = { 45250003Sadrian 0xa0ccbe, /* Freq 2412 - (80 << 17) + 52414 */ 46250003Sadrian 0xa12213, /* Freq 2417 - (80 << 17) + 74259 */ 47250003Sadrian 0xa17769, /* Freq 2422 - (80 << 17) + 96105 */ 48250003Sadrian 0xa1ccbe, /* Freq 2427 - (80 << 17) + 117950 */ 49250003Sadrian 0xa22213, /* Freq 2432 - (81 << 17) + 8723 */ 50250003Sadrian 0xa27769, /* Freq 2437 - (81 << 17) + 30569 */ 51250003Sadrian 0xa2ccbe, /* Freq 2442 - (81 << 17) + 52414 */ 52250003Sadrian 0xa32213, /* Freq 2447 - (81 << 17) + 74259 */ 53250003Sadrian 0xa37769, /* Freq 2452 - (81 << 17) + 96105 */ 54250003Sadrian 0xa3ccbe, /* Freq 2457 - (81 << 17) + 117950 */ 55250003Sadrian 0xa42213, /* Freq 2462 - (82 << 17) + 8723 */ 56250003Sadrian 0xa47769, /* Freq 2467 - (82 << 17) + 30569 */ 57250003Sadrian 0xa4ccbe, /* Freq 2472 - (82 << 17) + 52414 */ 58250003Sadrian 0xa5998b, /* Freq 2484 - (82 << 17) + 104843 */ 59250003Sadrian}; 60250003Sadrian 61250003Sadrian 62250003Sadrian/* 63250003Sadrian * Take the MHz channel value and set the Channel value 64250003Sadrian * 65250003Sadrian * ASSUMES: Writes enabled to analog bus 66250003Sadrian * 67250003Sadrian * Actual Expression, 68250003Sadrian * 69250003Sadrian * For 2GHz channel, 70250003Sadrian * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) 71250003Sadrian * (freq_ref = 40MHz) 72250003Sadrian * 73250003Sadrian * For 5GHz channel, 74250003Sadrian * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10) 75250003Sadrian * (freq_ref = 40MHz/(24>>amode_ref_sel)) 76250003Sadrian * 77250003Sadrian * For 5GHz channels which are 5MHz spaced, 78250003Sadrian * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) 79250003Sadrian * (freq_ref = 40MHz) 80250003Sadrian */ 81250003Sadrianstatic HAL_BOOL 82250008Sadrianar9300_set_channel(struct ath_hal *ah, struct ieee80211_channel *chan) 83250003Sadrian{ 84250003Sadrian u_int16_t b_mode, frac_mode = 0, a_mode_ref_sel = 0; 85250003Sadrian u_int32_t freq, channel_sel, reg32; 86250003Sadrian u_int8_t clk_25mhz = AH9300(ah)->clk_25mhz; 87250003Sadrian CHAN_CENTERS centers; 88250003Sadrian int load_synth_channel; 89291472Sngie#ifdef AH_DEBUG_ALQ 90250008Sadrian HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); 91291472Sngie#endif 92250003Sadrian 93250172Sadrian /* 94250172Sadrian * Put this behind AH_DEBUG_ALQ for now until the Hornet 95250172Sadrian * channel_sel code below is made to work. 96250172Sadrian */ 97250172Sadrian#ifdef AH_DEBUG_ALQ 98250008Sadrian OS_MARK(ah, AH_MARK_SETCHANNEL, ichan->channel); 99250008Sadrian#endif 100250003Sadrian 101250003Sadrian ar9300_get_channel_centers(ah, chan, ¢ers); 102250003Sadrian freq = centers.synth_center; 103250003Sadrian 104250003Sadrian if (freq < 4800) { /* 2 GHz, fractional mode */ 105250003Sadrian b_mode = 1; /* 2 GHz */ 106250003Sadrian 107250003Sadrian if (AR_SREV_HORNET(ah)) { 108250008Sadrian#if 0 109250008Sadrian u_int32_t ichan = 110250008Sadrian ieee80211_mhz2ieee(ah, chan->ic_freq, chan->ic_flags); 111250003Sadrian HALASSERT(ichan > 0 && ichan <= 14); 112250003Sadrian if (clk_25mhz) { 113250003Sadrian channel_sel = ar9300_chansel_xtal_25M[ichan - 1]; 114250003Sadrian } else { 115250003Sadrian channel_sel = ar9300_chansel_xtal_40M[ichan - 1]; 116250003Sadrian } 117250008Sadrian#endif 118252237Sadrian uint32_t i; 119252237Sadrian 120291469Sadrian /* 121291469Sadrian * Pay close attention to this bit! 122291469Sadrian * 123291469Sadrian * We need to map the actual desired synth frequency to 124291469Sadrian * one of the channel select array entries. 125291469Sadrian * 126291469Sadrian * For HT20, it'll align with the channel we select. 127291469Sadrian * 128291469Sadrian * For HT40 though it won't - the centre frequency 129291469Sadrian * will not be the frequency of chan->ic_freq or ichan->freq; 130291469Sadrian * it needs to be whatever frequency maps to 'freq'. 131291469Sadrian */ 132291469Sadrian i = ath_hal_mhz2ieee_2ghz(ah, freq); 133252237Sadrian HALASSERT(i > 0 && i <= 14); 134252237Sadrian if (clk_25mhz) { 135252237Sadrian channel_sel = ar9300_chansel_xtal_25M[i - 1]; 136252237Sadrian } else { 137252237Sadrian channel_sel = ar9300_chansel_xtal_40M[i - 1]; 138252237Sadrian } 139250003Sadrian } else if (AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) { 140250003Sadrian u_int32_t channel_frac; 141250003Sadrian /* 142250003Sadrian * freq_ref = (40 / (refdiva >> a_mode_ref_sel)); 143250003Sadrian * (where refdiva = 1 and amoderefsel = 0) 144250003Sadrian * ndiv = ((chan_mhz * 4) / 3) / freq_ref; 145250003Sadrian * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 146250003Sadrian */ 147250003Sadrian channel_sel = (freq * 4) / 120; 148250003Sadrian channel_frac = (((freq * 4) % 120) * 0x20000) / 120; 149250003Sadrian channel_sel = (channel_sel << 17) | (channel_frac); 150291437Sadrian } else if (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) { 151250003Sadrian u_int32_t channel_frac; 152250003Sadrian if (clk_25mhz) { 153250003Sadrian /* 154250003Sadrian * freq_ref = (50 / (refdiva >> a_mode_ref_sel)); 155250003Sadrian * (where refdiva = 1 and amoderefsel = 0) 156250003Sadrian * ndiv = ((chan_mhz * 4) / 3) / freq_ref; 157250003Sadrian * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 158250003Sadrian */ 159291437Sadrian if (AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) { 160250003Sadrian /* Doubler is off for Scorpion */ 161250003Sadrian channel_sel = (freq * 4) / 75; 162250003Sadrian channel_frac = (((freq * 4) % 75) * 0x20000) / 75; 163250003Sadrian } else { 164250003Sadrian channel_sel = (freq * 2) / 75; 165250003Sadrian channel_frac = (((freq * 2) % 75) * 0x20000) / 75; 166250003Sadrian } 167250003Sadrian } else { 168250003Sadrian /* 169250003Sadrian * freq_ref = (50 / (refdiva >> a_mode_ref_sel)); 170250003Sadrian * (where refdiva = 1 and amoderefsel = 0) 171250003Sadrian * ndiv = ((chan_mhz * 4) / 3) / freq_ref; 172250003Sadrian * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 173250003Sadrian */ 174250003Sadrian if (AR_SREV_SCORPION(ah)) { 175250003Sadrian /* Doubler is off for Scorpion */ 176250003Sadrian channel_sel = (freq * 4) / 120; 177250003Sadrian channel_frac = (((freq * 4) % 120) * 0x20000) / 120; 178250003Sadrian } else { 179250003Sadrian channel_sel = (freq * 2) / 120; 180250003Sadrian channel_frac = (((freq * 2) % 120) * 0x20000) / 120; 181250003Sadrian } 182250003Sadrian } 183250003Sadrian channel_sel = (channel_sel << 17) | (channel_frac); 184250003Sadrian } else { 185250003Sadrian channel_sel = CHANSEL_2G(freq); 186250003Sadrian } 187250003Sadrian } else { 188250003Sadrian b_mode = 0; /* 5 GHz */ 189250003Sadrian if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && clk_25mhz){ 190250003Sadrian u_int32_t channel_frac; 191250003Sadrian /* 192250003Sadrian * freq_ref = (50 / (refdiva >> amoderefsel)); 193250003Sadrian * (refdiva = 1, amoderefsel = 0) 194250003Sadrian * ndiv = ((chan_mhz * 2) / 3) / freq_ref; 195250003Sadrian * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 196250003Sadrian */ 197250003Sadrian channel_sel = freq / 75 ; 198250003Sadrian channel_frac = ((freq % 75) * 0x20000) / 75; 199250003Sadrian channel_sel = (channel_sel << 17) | (channel_frac); 200250003Sadrian } else { 201250003Sadrian channel_sel = CHANSEL_5G(freq); 202250003Sadrian /* Doubler is ON, so, divide channel_sel by 2. */ 203250003Sadrian channel_sel >>= 1; 204250003Sadrian } 205250003Sadrian } 206250003Sadrian 207250003Sadrian 208250003Sadrian /* Enable fractional mode for all channels */ 209250003Sadrian frac_mode = 1; 210250003Sadrian a_mode_ref_sel = 0; 211250003Sadrian load_synth_channel = 0; 212250003Sadrian 213250003Sadrian reg32 = (b_mode << 29); 214250003Sadrian OS_REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); 215250003Sadrian 216250003Sadrian /* Enable Long shift Select for Synthesizer */ 217250003Sadrian OS_REG_RMW_FIELD(ah, 218250003Sadrian AR_PHY_65NM_CH0_SYNTH4, AR_PHY_SYNTH4_LONG_SHIFT_SELECT, 1); 219250003Sadrian 220250003Sadrian /* program synth. setting */ 221250003Sadrian reg32 = 222250003Sadrian (channel_sel << 2) | 223250003Sadrian (a_mode_ref_sel << 28) | 224250003Sadrian (frac_mode << 30) | 225250003Sadrian (load_synth_channel << 31); 226250008Sadrian if (IEEE80211_IS_CHAN_QUARTER(chan)) { 227250003Sadrian reg32 += CHANSEL_5G_DOT5MHZ; 228250003Sadrian } 229250003Sadrian OS_REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32); 230250003Sadrian /* Toggle Load Synth channel bit */ 231250003Sadrian load_synth_channel = 1; 232250003Sadrian reg32 |= load_synth_channel << 31; 233250003Sadrian OS_REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32); 234250003Sadrian 235250003Sadrian 236250003Sadrian AH_PRIVATE(ah)->ah_curchan = chan; 237250003Sadrian 238250003Sadrian return AH_TRUE; 239250003Sadrian} 240250003Sadrian 241250003Sadrian 242250008Sadrian#if 0 243250003Sadrianstatic HAL_BOOL 244250003Sadrianar9300_get_chip_power_limits(struct ath_hal *ah, HAL_CHANNEL *chans, 245250003Sadrian u_int32_t nchans) 246250003Sadrian{ 247250003Sadrian int i; 248250003Sadrian 249250003Sadrian for (i = 0; i < nchans; i++) { 250250003Sadrian chans[i].max_tx_power = AR9300_MAX_RATE_POWER; 251250003Sadrian chans[i].min_tx_power = AR9300_MAX_RATE_POWER; 252250003Sadrian } 253250003Sadrian return AH_TRUE; 254250003Sadrian} 255250008Sadrian#endif 256250003Sadrian 257250008Sadrian/* XXX FreeBSD */ 258250008Sadrianstatic HAL_BOOL 259250008Sadrianar9300_get_chip_power_limits(struct ath_hal *ah, 260250008Sadrian struct ieee80211_channel *chan) 261250008Sadrian{ 262250008Sadrian /* XXX ? */ 263250008Sadrian chan->ic_minpower = 0; 264250008Sadrian chan->ic_maxpower = AR9300_MAX_RATE_POWER; 265250008Sadrian 266250008Sadrian return AH_TRUE; 267250008Sadrian} 268250008Sadrian 269250003SadrianHAL_BOOL 270250003Sadrianar9300_rf_attach(struct ath_hal *ah, HAL_STATUS *status) 271250003Sadrian{ 272250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 273250003Sadrian 274250003Sadrian ahp->ah_rf_hal.set_channel = ar9300_set_channel; 275250003Sadrian ahp->ah_rf_hal.get_chip_power_lim = ar9300_get_chip_power_limits; 276250003Sadrian 277250003Sadrian *status = HAL_OK; 278250003Sadrian 279250003Sadrian return AH_TRUE; 280250003Sadrian} 281