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; 89250008Sadrian HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan); 90250003Sadrian 91250172Sadrian /* 92250172Sadrian * Put this behind AH_DEBUG_ALQ for now until the Hornet 93250172Sadrian * channel_sel code below is made to work. 94250172Sadrian */ 95250172Sadrian#ifdef AH_DEBUG_ALQ 96250008Sadrian OS_MARK(ah, AH_MARK_SETCHANNEL, ichan->channel); 97250008Sadrian#endif 98250003Sadrian 99250003Sadrian ar9300_get_channel_centers(ah, chan, ¢ers); 100250003Sadrian freq = centers.synth_center; 101250003Sadrian 102250003Sadrian 103250003Sadrian if (freq < 4800) { /* 2 GHz, fractional mode */ 104250003Sadrian b_mode = 1; /* 2 GHz */ 105250003Sadrian 106250003Sadrian if (AR_SREV_HORNET(ah)) { 107250008Sadrian#if 0 108250008Sadrian u_int32_t ichan = 109250008Sadrian ieee80211_mhz2ieee(ah, chan->ic_freq, chan->ic_flags); 110250003Sadrian HALASSERT(ichan > 0 && ichan <= 14); 111250003Sadrian if (clk_25mhz) { 112250003Sadrian channel_sel = ar9300_chansel_xtal_25M[ichan - 1]; 113250003Sadrian } else { 114250003Sadrian channel_sel = ar9300_chansel_xtal_40M[ichan - 1]; 115250003Sadrian } 116250008Sadrian#endif 117252237Sadrian uint32_t i; 118252237Sadrian 119252237Sadrian i = ath_hal_mhz2ieee_2ghz(ah, ichan); 120252237Sadrian HALASSERT(i > 0 && i <= 14); 121252237Sadrian if (clk_25mhz) { 122252237Sadrian channel_sel = ar9300_chansel_xtal_25M[i - 1]; 123252237Sadrian } else { 124252237Sadrian channel_sel = ar9300_chansel_xtal_40M[i - 1]; 125252237Sadrian } 126250003Sadrian } else if (AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) { 127250003Sadrian u_int32_t channel_frac; 128250003Sadrian /* 129250003Sadrian * freq_ref = (40 / (refdiva >> a_mode_ref_sel)); 130250003Sadrian * (where refdiva = 1 and amoderefsel = 0) 131250003Sadrian * ndiv = ((chan_mhz * 4) / 3) / freq_ref; 132250003Sadrian * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 133250003Sadrian */ 134250003Sadrian channel_sel = (freq * 4) / 120; 135250003Sadrian channel_frac = (((freq * 4) % 120) * 0x20000) / 120; 136250003Sadrian channel_sel = (channel_sel << 17) | (channel_frac); 137250003Sadrian } else if (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) { 138250003Sadrian u_int32_t channel_frac; 139250003Sadrian if (clk_25mhz) { 140250003Sadrian /* 141250003Sadrian * freq_ref = (50 / (refdiva >> a_mode_ref_sel)); 142250003Sadrian * (where refdiva = 1 and amoderefsel = 0) 143250003Sadrian * ndiv = ((chan_mhz * 4) / 3) / freq_ref; 144250003Sadrian * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 145250003Sadrian */ 146250003Sadrian if (AR_SREV_SCORPION(ah)) { 147250003Sadrian /* Doubler is off for Scorpion */ 148250003Sadrian channel_sel = (freq * 4) / 75; 149250003Sadrian channel_frac = (((freq * 4) % 75) * 0x20000) / 75; 150250003Sadrian } else { 151250003Sadrian channel_sel = (freq * 2) / 75; 152250003Sadrian channel_frac = (((freq * 2) % 75) * 0x20000) / 75; 153250003Sadrian } 154250003Sadrian } else { 155250003Sadrian /* 156250003Sadrian * freq_ref = (50 / (refdiva >> a_mode_ref_sel)); 157250003Sadrian * (where refdiva = 1 and amoderefsel = 0) 158250003Sadrian * ndiv = ((chan_mhz * 4) / 3) / freq_ref; 159250003Sadrian * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 160250003Sadrian */ 161250003Sadrian if (AR_SREV_SCORPION(ah)) { 162250003Sadrian /* Doubler is off for Scorpion */ 163250003Sadrian channel_sel = (freq * 4) / 120; 164250003Sadrian channel_frac = (((freq * 4) % 120) * 0x20000) / 120; 165250003Sadrian } else { 166250003Sadrian channel_sel = (freq * 2) / 120; 167250003Sadrian channel_frac = (((freq * 2) % 120) * 0x20000) / 120; 168250003Sadrian } 169250003Sadrian } 170250003Sadrian channel_sel = (channel_sel << 17) | (channel_frac); 171250003Sadrian } else { 172250003Sadrian channel_sel = CHANSEL_2G(freq); 173250003Sadrian } 174250003Sadrian } else { 175250003Sadrian b_mode = 0; /* 5 GHz */ 176250003Sadrian if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && clk_25mhz){ 177250003Sadrian u_int32_t channel_frac; 178250003Sadrian /* 179250003Sadrian * freq_ref = (50 / (refdiva >> amoderefsel)); 180250003Sadrian * (refdiva = 1, amoderefsel = 0) 181250003Sadrian * ndiv = ((chan_mhz * 2) / 3) / freq_ref; 182250003Sadrian * chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000 183250003Sadrian */ 184250003Sadrian channel_sel = freq / 75 ; 185250003Sadrian channel_frac = ((freq % 75) * 0x20000) / 75; 186250003Sadrian channel_sel = (channel_sel << 17) | (channel_frac); 187250003Sadrian } else { 188250003Sadrian channel_sel = CHANSEL_5G(freq); 189250003Sadrian /* Doubler is ON, so, divide channel_sel by 2. */ 190250003Sadrian channel_sel >>= 1; 191250003Sadrian } 192250003Sadrian } 193250003Sadrian 194250003Sadrian 195250003Sadrian /* Enable fractional mode for all channels */ 196250003Sadrian frac_mode = 1; 197250003Sadrian a_mode_ref_sel = 0; 198250003Sadrian load_synth_channel = 0; 199250003Sadrian 200250003Sadrian reg32 = (b_mode << 29); 201250003Sadrian OS_REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); 202250003Sadrian 203250003Sadrian /* Enable Long shift Select for Synthesizer */ 204250003Sadrian OS_REG_RMW_FIELD(ah, 205250003Sadrian AR_PHY_65NM_CH0_SYNTH4, AR_PHY_SYNTH4_LONG_SHIFT_SELECT, 1); 206250003Sadrian 207250003Sadrian /* program synth. setting */ 208250003Sadrian reg32 = 209250003Sadrian (channel_sel << 2) | 210250003Sadrian (a_mode_ref_sel << 28) | 211250003Sadrian (frac_mode << 30) | 212250003Sadrian (load_synth_channel << 31); 213250008Sadrian if (IEEE80211_IS_CHAN_QUARTER(chan)) { 214250003Sadrian reg32 += CHANSEL_5G_DOT5MHZ; 215250003Sadrian } 216250003Sadrian OS_REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32); 217250003Sadrian /* Toggle Load Synth channel bit */ 218250003Sadrian load_synth_channel = 1; 219250003Sadrian reg32 |= load_synth_channel << 31; 220250003Sadrian OS_REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32); 221250003Sadrian 222250003Sadrian 223250003Sadrian AH_PRIVATE(ah)->ah_curchan = chan; 224250003Sadrian 225250003Sadrian return AH_TRUE; 226250003Sadrian} 227250003Sadrian 228250003Sadrian 229250008Sadrian#if 0 230250003Sadrianstatic HAL_BOOL 231250003Sadrianar9300_get_chip_power_limits(struct ath_hal *ah, HAL_CHANNEL *chans, 232250003Sadrian u_int32_t nchans) 233250003Sadrian{ 234250003Sadrian int i; 235250003Sadrian 236250003Sadrian for (i = 0; i < nchans; i++) { 237250003Sadrian chans[i].max_tx_power = AR9300_MAX_RATE_POWER; 238250003Sadrian chans[i].min_tx_power = AR9300_MAX_RATE_POWER; 239250003Sadrian } 240250003Sadrian return AH_TRUE; 241250003Sadrian} 242250008Sadrian#endif 243250003Sadrian 244250008Sadrian/* XXX FreeBSD */ 245250008Sadrianstatic HAL_BOOL 246250008Sadrianar9300_get_chip_power_limits(struct ath_hal *ah, 247250008Sadrian struct ieee80211_channel *chan) 248250008Sadrian{ 249250008Sadrian /* XXX ? */ 250250008Sadrian chan->ic_minpower = 0; 251250008Sadrian chan->ic_maxpower = AR9300_MAX_RATE_POWER; 252250008Sadrian 253250008Sadrian return AH_TRUE; 254250008Sadrian} 255250008Sadrian 256250003SadrianHAL_BOOL 257250003Sadrianar9300_rf_attach(struct ath_hal *ah, HAL_STATUS *status) 258250003Sadrian{ 259250003Sadrian struct ath_hal_9300 *ahp = AH9300(ah); 260250003Sadrian 261250003Sadrian ahp->ah_rf_hal.set_channel = ar9300_set_channel; 262250003Sadrian ahp->ah_rf_hal.get_chip_power_lim = ar9300_get_chip_power_limits; 263250003Sadrian 264250003Sadrian *status = HAL_OK; 265250003Sadrian 266250003Sadrian return AH_TRUE; 267250003Sadrian} 268