The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/dev/ath/ath_hal/ar9300/ar9300_radio.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2013 Qualcomm Atheros, Inc.
    3  *
    4  * Permission to use, copy, modify, and/or distribute this software for any
    5  * purpose with or without fee is hereby granted, provided that the above
    6  * copyright notice and this permission notice appear in all copies.
    7  *
    8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
   10  * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
   11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
   12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
   13  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
   14  * PERFORMANCE OF THIS SOFTWARE.
   15  */
   16 
   17 #include "opt_ah.h"
   18 
   19 #include "ah.h"
   20 #include "ah_internal.h"
   21 
   22 #include "ar9300/ar9300.h"
   23 #include "ar9300/ar9300reg.h"
   24 #include "ar9300/ar9300phy.h"
   25 
   26 /* chansel table, used by Hornet and Poseidon */
   27 static const u_int32_t ar9300_chansel_xtal_25M[] = {
   28     0x101479e, /* Freq 2412 - (128 << 17) + 83870  */
   29     0x101d027, /* Freq 2417 - (128 << 17) + 118823 */
   30     0x10258af, /* Freq 2422 - (129 << 17) + 22703  */
   31     0x102e138, /* Freq 2427 - (129 << 17) + 57656  */
   32     0x10369c0, /* Freq 2432 - (129 << 17) + 92608  */
   33     0x103f249, /* Freq 2437 - (129 << 17) + 127561 */
   34     0x1047ad1, /* Freq 2442 - (130 << 17) + 31441  */
   35     0x105035a, /* Freq 2447 - (130 << 17) + 66394  */
   36     0x1058be2, /* Freq 2452 - (130 << 17) + 101346 */
   37     0x106146b, /* Freq 2457 - (131 << 17) + 5227   */
   38     0x1069cf3, /* Freq 2462 - (131 << 17) + 40179  */
   39     0x107257c, /* Freq 2467 - (131 << 17) + 75132  */
   40     0x107ae04, /* Freq 2472 - (131 << 17) + 110084 */
   41     0x108f5b2, /* Freq 2484 - (132 << 17) + 62898  */
   42 };
   43 
   44 static const u_int32_t ar9300_chansel_xtal_40M[] = {
   45     0xa0ccbe, /* Freq 2412 - (80 << 17) + 52414  */
   46     0xa12213, /* Freq 2417 - (80 << 17) + 74259  */
   47     0xa17769, /* Freq 2422 - (80 << 17) + 96105  */
   48     0xa1ccbe, /* Freq 2427 - (80 << 17) + 117950 */
   49     0xa22213, /* Freq 2432 - (81 << 17) + 8723   */
   50     0xa27769, /* Freq 2437 - (81 << 17) + 30569  */
   51     0xa2ccbe, /* Freq 2442 - (81 << 17) + 52414  */
   52     0xa32213, /* Freq 2447 - (81 << 17) + 74259  */
   53     0xa37769, /* Freq 2452 - (81 << 17) + 96105  */
   54     0xa3ccbe, /* Freq 2457 - (81 << 17) + 117950 */
   55     0xa42213, /* Freq 2462 - (82 << 17) + 8723   */
   56     0xa47769, /* Freq 2467 - (82 << 17) + 30569  */
   57     0xa4ccbe, /* Freq 2472 - (82 << 17) + 52414  */
   58     0xa5998b, /* Freq 2484 - (82 << 17) + 104843 */
   59 };
   60 
   61 
   62 /*
   63  * Take the MHz channel value and set the Channel value
   64  *
   65  * ASSUMES: Writes enabled to analog bus
   66  *
   67  * Actual Expression,
   68  *
   69  * For 2GHz channel,
   70  * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
   71  * (freq_ref = 40MHz)
   72  *
   73  * For 5GHz channel,
   74  * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10)
   75  * (freq_ref = 40MHz/(24>>amode_ref_sel))
   76  *
   77  * For 5GHz channels which are 5MHz spaced,
   78  * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
   79  * (freq_ref = 40MHz)
   80  */
   81 static HAL_BOOL
   82 ar9300_set_channel(struct ath_hal *ah, struct ieee80211_channel *chan)
   83 {
   84     u_int16_t b_mode, frac_mode = 0, a_mode_ref_sel = 0;
   85     u_int32_t freq, channel_sel, reg32;
   86     u_int8_t clk_25mhz = AH9300(ah)->clk_25mhz;
   87     CHAN_CENTERS centers;
   88     int load_synth_channel;
   89 #ifdef  AH_DEBUG_ALQ
   90     HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
   91 #endif
   92 
   93     /*
   94      * Put this behind AH_DEBUG_ALQ for now until the Hornet
   95      * channel_sel code below is made to work.
   96      */
   97 #ifdef  AH_DEBUG_ALQ
   98     OS_MARK(ah, AH_MARK_SETCHANNEL, ichan->channel);
   99 #endif
  100 
  101     ar9300_get_channel_centers(ah, chan, &centers);
  102     freq = centers.synth_center;
  103 
  104     if (freq < 4800) {     /* 2 GHz, fractional mode */
  105         b_mode = 1; /* 2 GHz */
  106 
  107         if (AR_SREV_HORNET(ah)) {
  108 #if 0
  109             u_int32_t ichan =
  110               ieee80211_mhz2ieee(ah, chan->ic_freq, chan->ic_flags);
  111             HALASSERT(ichan > 0 && ichan <= 14);
  112             if (clk_25mhz) {
  113                 channel_sel = ar9300_chansel_xtal_25M[ichan - 1];
  114             } else {
  115                 channel_sel = ar9300_chansel_xtal_40M[ichan - 1];
  116             }
  117 #endif
  118             uint32_t i;
  119 
  120             /*
  121              * Pay close attention to this bit!
  122              *
  123              * We need to map the actual desired synth frequency to
  124              * one of the channel select array entries.
  125              *
  126              * For HT20, it'll align with the channel we select.
  127              *
  128              * For HT40 though it won't - the centre frequency
  129              * will not be the frequency of chan->ic_freq or ichan->freq;
  130              * it needs to be whatever frequency maps to 'freq'.
  131              */
  132             i = ath_hal_mhz2ieee_2ghz(ah, freq);
  133             HALASSERT(i > 0 && i <= 14);
  134             if (clk_25mhz) {
  135                 channel_sel = ar9300_chansel_xtal_25M[i - 1];
  136             } else {
  137                 channel_sel = ar9300_chansel_xtal_40M[i - 1];
  138             }
  139         } else if (AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) {
  140             u_int32_t channel_frac;
  141             /* 
  142              * freq_ref = (40 / (refdiva >> a_mode_ref_sel));
  143              *     (where refdiva = 1 and amoderefsel = 0)
  144              * ndiv = ((chan_mhz * 4) / 3) / freq_ref;
  145              * chansel = int(ndiv),  chanfrac = (ndiv - chansel) * 0x20000
  146              */
  147             channel_sel = (freq * 4) / 120;
  148             channel_frac = (((freq * 4) % 120) * 0x20000) / 120;
  149             channel_sel = (channel_sel << 17) | (channel_frac);
  150         } else if (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) {
  151             u_int32_t channel_frac;
  152             if (clk_25mhz) {
  153                 /* 
  154                  * freq_ref = (50 / (refdiva >> a_mode_ref_sel));
  155                  *     (where refdiva = 1 and amoderefsel = 0)
  156                  * ndiv = ((chan_mhz * 4) / 3) / freq_ref;
  157                  * chansel = int(ndiv),  chanfrac = (ndiv - chansel) * 0x20000
  158                  */
  159                 if (AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) {
  160                     /* Doubler is off for Scorpion */
  161                     channel_sel = (freq * 4) / 75;
  162                     channel_frac = (((freq * 4) % 75) * 0x20000) / 75;
  163                 } else {
  164                     channel_sel = (freq * 2) / 75;
  165                     channel_frac = (((freq * 2) % 75) * 0x20000) / 75;
  166                 }
  167             } else {
  168                 /* 
  169                  * freq_ref = (50 / (refdiva >> a_mode_ref_sel));
  170                  *     (where refdiva = 1 and amoderefsel = 0)
  171                  * ndiv = ((chan_mhz * 4) / 3) / freq_ref;
  172                  * chansel = int(ndiv),  chanfrac = (ndiv - chansel) * 0x20000
  173                  */
  174                 if (AR_SREV_SCORPION(ah)) {
  175                     /* Doubler is off for Scorpion */
  176                     channel_sel = (freq * 4) / 120;
  177                     channel_frac = (((freq * 4) % 120) * 0x20000) / 120;
  178                 } else {
  179                     channel_sel = (freq * 2) / 120;
  180                     channel_frac = (((freq * 2) % 120) * 0x20000) / 120;
  181                 }
  182             }
  183             channel_sel = (channel_sel << 17) | (channel_frac);
  184         } else {
  185             channel_sel = CHANSEL_2G(freq);
  186         }
  187     } else {
  188         b_mode = 0; /* 5 GHz */
  189         if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && clk_25mhz){
  190             u_int32_t channel_frac;
  191             /* 
  192              * freq_ref = (50 / (refdiva >> amoderefsel));
  193              *     (refdiva = 1, amoderefsel = 0)
  194              * ndiv = ((chan_mhz * 2) / 3) / freq_ref;
  195              * chansel = int(ndiv),  chanfrac = (ndiv - chansel) * 0x20000
  196              */
  197             channel_sel = freq / 75 ;
  198             channel_frac = ((freq % 75) * 0x20000) / 75;
  199             channel_sel = (channel_sel << 17) | (channel_frac);
  200         } else {
  201             channel_sel = CHANSEL_5G(freq);
  202             /* Doubler is ON, so, divide channel_sel by 2. */
  203             channel_sel >>= 1;
  204         }
  205     }
  206 
  207 
  208         /* Enable fractional mode for all channels */
  209     frac_mode = 1;
  210     a_mode_ref_sel = 0;
  211     load_synth_channel = 0;
  212     
  213     reg32 = (b_mode << 29);
  214     OS_REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32);
  215 
  216         /* Enable Long shift Select for Synthesizer */
  217     OS_REG_RMW_FIELD(ah,
  218         AR_PHY_65NM_CH0_SYNTH4, AR_PHY_SYNTH4_LONG_SHIFT_SELECT, 1);
  219 
  220     /* program synth. setting */
  221     reg32 =
  222         (channel_sel       <<  2) |
  223         (a_mode_ref_sel      << 28) |
  224         (frac_mode         << 30) |
  225         (load_synth_channel << 31);
  226     if (IEEE80211_IS_CHAN_QUARTER(chan)) {
  227         reg32 += CHANSEL_5G_DOT5MHZ;
  228     }
  229     OS_REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32);
  230     /* Toggle Load Synth channel bit */
  231     load_synth_channel = 1;
  232     reg32 |= load_synth_channel << 31;
  233     OS_REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32);
  234 
  235 
  236     AH_PRIVATE(ah)->ah_curchan = chan;
  237 
  238     return AH_TRUE;
  239 }
  240 
  241 
  242 #if 0
  243 static HAL_BOOL
  244 ar9300_get_chip_power_limits(struct ath_hal *ah, HAL_CHANNEL *chans,
  245                          u_int32_t nchans)
  246 {
  247     int i;
  248 
  249     for (i = 0; i < nchans; i++) {
  250         chans[i].max_tx_power = AR9300_MAX_RATE_POWER;
  251         chans[i].min_tx_power = AR9300_MAX_RATE_POWER;
  252     }
  253     return AH_TRUE;
  254 }
  255 #endif
  256 
  257 /* XXX FreeBSD */
  258 static HAL_BOOL
  259 ar9300_get_chip_power_limits(struct ath_hal *ah,
  260     struct ieee80211_channel *chan)
  261 {
  262         /* XXX ? */
  263         chan->ic_minpower = 0;
  264         chan->ic_maxpower = AR9300_MAX_RATE_POWER;
  265 
  266         return AH_TRUE;
  267 }
  268 
  269 HAL_BOOL
  270 ar9300_rf_attach(struct ath_hal *ah, HAL_STATUS *status)
  271 {
  272     struct ath_hal_9300 *ahp = AH9300(ah);
  273 
  274     ahp->ah_rf_hal.set_channel    = ar9300_set_channel;
  275     ahp->ah_rf_hal.get_chip_power_lim   = ar9300_get_chip_power_limits;
  276 
  277     *status = HAL_OK;
  278 
  279     return AH_TRUE;
  280 }

Cache object: 2fd030a1f40c5127287d394dec03114e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.