]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/contrib/dev/ath/ath_hal/ar9300/ar9300_radio.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / contrib / dev / ath / ath_hal / ar9300 / ar9300_radio.c
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     HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);
90
91     /*
92      * Put this behind AH_DEBUG_ALQ for now until the Hornet
93      * channel_sel code below is made to work.
94      */
95 #ifdef  AH_DEBUG_ALQ
96     OS_MARK(ah, AH_MARK_SETCHANNEL, ichan->channel);
97 #endif
98
99     ar9300_get_channel_centers(ah, chan, &centers);
100     freq = centers.synth_center;
101
102
103     if (freq < 4800) {     /* 2 GHz, fractional mode */
104         b_mode = 1; /* 2 GHz */
105
106         if (AR_SREV_HORNET(ah)) {
107 #if 0
108             u_int32_t ichan =
109               ieee80211_mhz2ieee(ah, chan->ic_freq, chan->ic_flags);
110             HALASSERT(ichan > 0 && ichan <= 14);
111             if (clk_25mhz) {
112                 channel_sel = ar9300_chansel_xtal_25M[ichan - 1];
113             } else {
114                 channel_sel = ar9300_chansel_xtal_40M[ichan - 1];
115             }
116 #endif
117             uint32_t i;
118
119             i = ath_hal_mhz2ieee_2ghz(ah, ichan);
120             HALASSERT(i > 0 && i <= 14);
121             if (clk_25mhz) {
122                 channel_sel = ar9300_chansel_xtal_25M[i - 1];
123             } else {
124                 channel_sel = ar9300_chansel_xtal_40M[i - 1];
125             }
126         } else if (AR_SREV_POSEIDON(ah) || AR_SREV_APHRODITE(ah)) {
127             u_int32_t channel_frac;
128             /* 
129              * freq_ref = (40 / (refdiva >> a_mode_ref_sel));
130              *     (where refdiva = 1 and amoderefsel = 0)
131              * ndiv = ((chan_mhz * 4) / 3) / freq_ref;
132              * chansel = int(ndiv),  chanfrac = (ndiv - chansel) * 0x20000
133              */
134             channel_sel = (freq * 4) / 120;
135             channel_frac = (((freq * 4) % 120) * 0x20000) / 120;
136             channel_sel = (channel_sel << 17) | (channel_frac);
137         } else if (AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) {
138             u_int32_t channel_frac;
139             if (clk_25mhz) {
140                 /* 
141                  * freq_ref = (50 / (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) * 0x20000
145                  */
146                 if (AR_SREV_SCORPION(ah)) {
147                     /* Doubler is off for Scorpion */
148                     channel_sel = (freq * 4) / 75;
149                     channel_frac = (((freq * 4) % 75) * 0x20000) / 75;
150                 } else {
151                     channel_sel = (freq * 2) / 75;
152                     channel_frac = (((freq * 2) % 75) * 0x20000) / 75;
153                 }
154             } else {
155                 /* 
156                  * freq_ref = (50 / (refdiva >> a_mode_ref_sel));
157                  *     (where refdiva = 1 and amoderefsel = 0)
158                  * ndiv = ((chan_mhz * 4) / 3) / freq_ref;
159                  * chansel = int(ndiv),  chanfrac = (ndiv - chansel) * 0x20000
160                  */
161                 if (AR_SREV_SCORPION(ah)) {
162                     /* Doubler is off for Scorpion */
163                     channel_sel = (freq * 4) / 120;
164                     channel_frac = (((freq * 4) % 120) * 0x20000) / 120;
165                 } else {
166                     channel_sel = (freq * 2) / 120;
167                     channel_frac = (((freq * 2) % 120) * 0x20000) / 120;
168                 }
169             }
170             channel_sel = (channel_sel << 17) | (channel_frac);
171         } else {
172             channel_sel = CHANSEL_2G(freq);
173         }
174     } else {
175         b_mode = 0; /* 5 GHz */
176         if ((AR_SREV_WASP(ah) || AR_SREV_SCORPION(ah)) && clk_25mhz){
177             u_int32_t channel_frac;
178             /* 
179              * freq_ref = (50 / (refdiva >> amoderefsel));
180              *     (refdiva = 1, amoderefsel = 0)
181              * ndiv = ((chan_mhz * 2) / 3) / freq_ref;
182              * chansel = int(ndiv),  chanfrac = (ndiv - chansel) * 0x20000
183              */
184             channel_sel = freq / 75 ;
185             channel_frac = ((freq % 75) * 0x20000) / 75;
186             channel_sel = (channel_sel << 17) | (channel_frac);
187         } else {
188             channel_sel = CHANSEL_5G(freq);
189             /* Doubler is ON, so, divide channel_sel by 2. */
190             channel_sel >>= 1;
191         }
192     }
193
194
195         /* Enable fractional mode for all channels */
196     frac_mode = 1;
197     a_mode_ref_sel = 0;
198     load_synth_channel = 0;
199     
200     reg32 = (b_mode << 29);
201     OS_REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32);
202
203         /* Enable Long shift Select for Synthesizer */
204     OS_REG_RMW_FIELD(ah,
205         AR_PHY_65NM_CH0_SYNTH4, AR_PHY_SYNTH4_LONG_SHIFT_SELECT, 1);
206
207     /* program synth. setting */
208     reg32 =
209         (channel_sel       <<  2) |
210         (a_mode_ref_sel      << 28) |
211         (frac_mode         << 30) |
212         (load_synth_channel << 31);
213     if (IEEE80211_IS_CHAN_QUARTER(chan)) {
214         reg32 += CHANSEL_5G_DOT5MHZ;
215     }
216     OS_REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32);
217     /* Toggle Load Synth channel bit */
218     load_synth_channel = 1;
219     reg32 |= load_synth_channel << 31;
220     OS_REG_WRITE(ah, AR_PHY_65NM_CH0_SYNTH7, reg32);
221
222
223     AH_PRIVATE(ah)->ah_curchan = chan;
224
225     return AH_TRUE;
226 }
227
228
229 #if 0
230 static HAL_BOOL
231 ar9300_get_chip_power_limits(struct ath_hal *ah, HAL_CHANNEL *chans,
232                          u_int32_t nchans)
233 {
234     int i;
235
236     for (i = 0; i < nchans; i++) {
237         chans[i].max_tx_power = AR9300_MAX_RATE_POWER;
238         chans[i].min_tx_power = AR9300_MAX_RATE_POWER;
239     }
240     return AH_TRUE;
241 }
242 #endif
243
244 /* XXX FreeBSD */
245 static HAL_BOOL
246 ar9300_get_chip_power_limits(struct ath_hal *ah,
247     struct ieee80211_channel *chan)
248 {
249         /* XXX ? */
250         chan->ic_minpower = 0;
251         chan->ic_maxpower = AR9300_MAX_RATE_POWER;
252
253         return AH_TRUE;
254 }
255
256 HAL_BOOL
257 ar9300_rf_attach(struct ath_hal *ah, HAL_STATUS *status)
258 {
259     struct ath_hal_9300 *ahp = AH9300(ah);
260
261     ahp->ah_rf_hal.set_channel    = ar9300_set_channel;
262     ahp->ah_rf_hal.get_chip_power_lim   = ar9300_get_chip_power_limits;
263
264     *status = HAL_OK;
265
266     return AH_TRUE;
267 }