1 /* $OpenBSD: ar9280.c,v 1.28 2021/04/15 18:25:43 stsp Exp $ */
2
3 /*-
4 * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
5 * Copyright (c) 2008-2009 Atheros Communications Inc.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /*
21 * Driver for Atheros 802.11a/g/n chipsets.
22 * Routines for AR9220, AR9223, AR9280 and AR9281 chipsets.
23 */
24
25 #include "bpfilter.h"
26
27 #include <sys/param.h>
28 #include <sys/sockio.h>
29 #include <sys/mbuf.h>
30 #include <sys/kernel.h>
31 #include <sys/socket.h>
32 #include <sys/systm.h>
33 #include <sys/malloc.h>
34 #include <sys/queue.h>
35 #include <sys/timeout.h>
36 #include <sys/conf.h>
37 #include <sys/device.h>
38 #include <sys/endian.h>
39
40 #include <machine/bus.h>
41 #include <machine/intr.h>
42
43 #if NBPFILTER > 0
44 #include <net/bpf.h>
45 #endif
46 #include <net/if.h>
47 #include <net/if_media.h>
48
49 #include <netinet/in.h>
50 #include <netinet/if_ether.h>
51
52 #include <net80211/ieee80211_var.h>
53 #include <net80211/ieee80211_amrr.h>
54 #include <net80211/ieee80211_ra.h>
55 #include <net80211/ieee80211_radiotap.h>
56
57 #include <dev/ic/athnreg.h>
58 #include <dev/ic/athnvar.h>
59
60 #include <dev/ic/ar5008reg.h>
61 #include <dev/ic/ar5416reg.h> /* We share the ROM layout. */
62 #include <dev/ic/ar9280reg.h>
63
64 int ar9280_attach(struct athn_softc *);
65 void ar9280_setup(struct athn_softc *);
66 int ar9280_set_synth(struct athn_softc *, struct ieee80211_channel *,
67 struct ieee80211_channel *);
68 void ar9280_init_from_rom(struct athn_softc *, struct ieee80211_channel *,
69 struct ieee80211_channel *);
70 void ar9280_spur_mitigate(struct athn_softc *, struct ieee80211_channel *,
71 struct ieee80211_channel *);
72 void ar9280_olpc_get_pdadcs(struct athn_softc *,
73 struct ieee80211_channel *, int, uint8_t *, uint8_t *, uint8_t *);
74 void ar9280_reset_rx_gain(struct athn_softc *, struct ieee80211_channel *);
75 void ar9280_reset_tx_gain(struct athn_softc *, struct ieee80211_channel *);
76 void ar9280_olpc_init(struct athn_softc *);
77 void ar9280_olpc_temp_compensation(struct athn_softc *);
78
79 /* Extern functions. */
80 uint8_t athn_chan2fbin(struct ieee80211_channel *);
81 void athn_get_pier_ival(uint8_t, const uint8_t *, int, int *, int *);
82 int ar5008_attach(struct athn_softc *);
83 void ar5008_set_viterbi_mask(struct athn_softc *, int);
84 void ar5416_swap_rom(struct athn_softc *);
85 void ar5416_set_txpower(struct athn_softc *, struct ieee80211_channel *,
86 struct ieee80211_channel *);
87 const struct ar_spur_chan *
88 ar5416_get_spur_chans(struct athn_softc *, int);
89
90
91 int
ar9280_attach(struct athn_softc * sc)92 ar9280_attach(struct athn_softc *sc)
93 {
94 sc->eep_base = AR5416_EEP_START_LOC;
95 sc->eep_size = sizeof(struct ar5416_eeprom);
96 sc->ngpiopins = (sc->flags & ATHN_FLAG_USB) ? 16 : 10;
97 sc->led_pin = 1;
98 sc->workaround = AR9280_WA_DEFAULT;
99 sc->ops.setup = ar9280_setup;
100 sc->ops.swap_rom = ar5416_swap_rom;
101 sc->ops.init_from_rom = ar9280_init_from_rom;
102 sc->ops.set_txpower = ar5416_set_txpower;
103 sc->ops.set_synth = ar9280_set_synth;
104 sc->ops.spur_mitigate = ar9280_spur_mitigate;
105 sc->ops.get_spur_chans = ar5416_get_spur_chans;
106 sc->ops.olpc_init = ar9280_olpc_init;
107 sc->ops.olpc_temp_compensation = ar9280_olpc_temp_compensation;
108 sc->cca_min_2g = AR9280_PHY_CCA_MIN_GOOD_VAL_2GHZ;
109 sc->cca_max_2g = AR9280_PHY_CCA_MAX_GOOD_VAL_2GHZ;
110 sc->cca_min_5g = AR9280_PHY_CCA_MIN_GOOD_VAL_5GHZ;
111 sc->cca_max_5g = AR9280_PHY_CCA_MAX_GOOD_VAL_5GHZ;
112 sc->ini = &ar9280_2_0_ini;
113 sc->serdes = &ar9280_2_0_serdes;
114
115 return (ar5008_attach(sc));
116 }
117
118 void
ar9280_setup(struct athn_softc * sc)119 ar9280_setup(struct athn_softc *sc)
120 {
121 const struct ar5416_eeprom *eep = sc->eep;
122 uint8_t type;
123
124 /* Determine if open loop power control should be used. */
125 if (sc->eep_rev >= AR_EEP_MINOR_VER_19 &&
126 eep->baseEepHeader.openLoopPwrCntl)
127 sc->flags |= ATHN_FLAG_OLPC;
128
129 /* Determine if fast PLL clock is supported. */
130 if (AR_SREV_9280_20(sc) &&
131 (sc->eep_rev <= AR_EEP_MINOR_VER_16 ||
132 eep->baseEepHeader.fastClk5g))
133 sc->flags |= ATHN_FLAG_FAST_PLL_CLOCK;
134
135 /*
136 * Determine if initialization value for AR_AN_TOP2 must be fixed.
137 * This is required for some AR9220 devices such as Ubiquiti SR71-12.
138 */
139 if (AR_SREV_9280_20(sc) &&
140 sc->eep_rev > AR_EEP_MINOR_VER_10 &&
141 !eep->baseEepHeader.pwdclkind) {
142 DPRINTF(("AR_AN_TOP2 fixup required\n"));
143 sc->flags |= ATHN_FLAG_AN_TOP2_FIXUP;
144 }
145
146 if (AR_SREV_9280_20(sc)) {
147 /* Check if we have a valid rxGainType field in ROM. */
148 if (sc->eep_rev >= AR_EEP_MINOR_VER_17) {
149 /* Select initialization values based on ROM. */
150 type = eep->baseEepHeader.rxGainType;
151 DPRINTF(("Rx gain type=0x%x\n", type));
152 if (type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
153 sc->rx_gain = &ar9280_2_0_rx_gain_23db_backoff;
154 else if (type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
155 sc->rx_gain = &ar9280_2_0_rx_gain_13db_backoff;
156 else
157 sc->rx_gain = &ar9280_2_0_rx_gain;
158 } else
159 sc->rx_gain = &ar9280_2_0_rx_gain;
160
161 /* Check if we have a valid txGainType field in ROM. */
162 if (sc->eep_rev >= AR_EEP_MINOR_VER_19) {
163 /* Select initialization values based on ROM. */
164 type = eep->baseEepHeader.txGainType;
165 DPRINTF(("Tx gain type=0x%x\n", type));
166 if (type == AR_EEP_TXGAIN_HIGH_POWER)
167 sc->tx_gain = &ar9280_2_0_tx_gain_high_power;
168 else
169 sc->tx_gain = &ar9280_2_0_tx_gain;
170 } else
171 sc->tx_gain = &ar9280_2_0_tx_gain;
172 }
173 }
174
175 int
ar9280_set_synth(struct athn_softc * sc,struct ieee80211_channel * c,struct ieee80211_channel * extc)176 ar9280_set_synth(struct athn_softc *sc, struct ieee80211_channel *c,
177 struct ieee80211_channel *extc)
178 {
179 uint32_t phy, reg, ndiv = 0;
180 uint32_t freq = c->ic_freq;
181
182 phy = AR_READ(sc, AR9280_PHY_SYNTH_CONTROL) & ~0x3fffffff;
183
184 if (IEEE80211_IS_CHAN_2GHZ(c)) {
185 phy |= (freq << 16) / 15;
186 phy |= AR9280_BMODE | AR9280_FRACMODE;
187
188 if (AR_SREV_9287_11_OR_LATER(sc)) {
189 /* NB: Magic values from the Linux driver. */
190 if (freq == 2484) { /* Channel 14. */
191 /* Japanese regulatory requirements. */
192 AR_WRITE(sc, AR_PHY(637), 0x00000000);
193 AR_WRITE(sc, AR_PHY(638), 0xefff0301);
194 AR_WRITE(sc, AR_PHY(639), 0xca9228ee);
195 } else {
196 AR_WRITE(sc, AR_PHY(637), 0x00fffeff);
197 AR_WRITE(sc, AR_PHY(638), 0x00f5f9ff);
198 AR_WRITE(sc, AR_PHY(639), 0xb79f6427);
199 }
200 } else {
201 reg = AR_READ(sc, AR_PHY_CCK_TX_CTRL);
202 if (freq == 2484) /* Channel 14. */
203 reg |= AR_PHY_CCK_TX_CTRL_JAPAN;
204 else
205 reg &= ~AR_PHY_CCK_TX_CTRL_JAPAN;
206 AR_WRITE(sc, AR_PHY_CCK_TX_CTRL, reg);
207 }
208 } else {
209 if (AR_SREV_9285_10_OR_LATER(sc) ||
210 sc->eep_rev < AR_EEP_MINOR_VER_22 ||
211 !((struct ar5416_base_eep_header *)sc->eep)->frac_n_5g) {
212 if ((freq % 20) == 0) {
213 ndiv = (freq * 3) / 60;
214 phy |= SM(AR9280_AMODE_REFSEL, 3);
215 } else if ((freq % 10) == 0) {
216 ndiv = (freq * 6) / 60;
217 phy |= SM(AR9280_AMODE_REFSEL, 2);
218 }
219 }
220 if (ndiv != 0) {
221 phy |= (ndiv & 0x1ff) << 17;
222 phy |= (ndiv & ~0x1ff) * 2;
223 } else {
224 phy |= (freq << 15) / 15;
225 phy |= AR9280_FRACMODE;
226
227 reg = AR_READ(sc, AR_AN_SYNTH9);
228 reg = RW(reg, AR_AN_SYNTH9_REFDIVA, 1);
229 AR_WRITE(sc, AR_AN_SYNTH9, reg);
230 }
231 }
232 AR_WRITE_BARRIER(sc);
233 DPRINTFN(4, ("AR9280_PHY_SYNTH_CONTROL=0x%08x\n", phy));
234 AR_WRITE(sc, AR9280_PHY_SYNTH_CONTROL, phy);
235 AR_WRITE_BARRIER(sc);
236 return (0);
237 }
238
239 void
ar9280_init_from_rom(struct athn_softc * sc,struct ieee80211_channel * c,struct ieee80211_channel * extc)240 ar9280_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c,
241 struct ieee80211_channel *extc)
242 {
243 static const uint32_t chainoffset[] = { 0x0000, 0x2000, 0x1000 };
244 const struct ar5416_eeprom *eep = sc->eep;
245 const struct ar5416_modal_eep_header *modal;
246 uint32_t reg, offset;
247 uint8_t txRxAtten;
248 int i;
249
250 modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
251
252 AR_WRITE(sc, AR_PHY_SWITCH_COM, modal->antCtrlCommon);
253
254 for (i = 0; i < AR9280_MAX_CHAINS; i++) {
255 if (sc->rxchainmask == 0x5 || sc->txchainmask == 0x5)
256 offset = chainoffset[i];
257 else
258 offset = i * 0x1000;
259
260 AR_WRITE(sc, AR_PHY_SWITCH_CHAIN_0 + offset,
261 modal->antCtrlChain[i]);
262
263 reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0 + offset);
264 reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
265 modal->iqCalICh[i]);
266 reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
267 modal->iqCalQCh[i]);
268 AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0 + offset, reg);
269
270 if (sc->eep_rev >= AR_EEP_MINOR_VER_3) {
271 reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset);
272 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
273 modal->bswMargin[i]);
274 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,
275 modal->bswAtten[i]);
276 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
277 modal->xatten2Margin[i]);
278 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_DB,
279 modal->xatten2Db[i]);
280 AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg);
281 }
282 if (sc->eep_rev >= AR_EEP_MINOR_VER_3)
283 txRxAtten = modal->txRxAttenCh[i];
284 else /* Workaround for ROM versions < 14.3. */
285 txRxAtten = IEEE80211_IS_CHAN_2GHZ(c) ? 23 : 44;
286 reg = AR_READ(sc, AR_PHY_RXGAIN + offset);
287 reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN,
288 txRxAtten);
289 reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN,
290 modal->rxTxMarginCh[i]);
291 AR_WRITE(sc, AR_PHY_RXGAIN + offset, reg);
292 }
293 if (IEEE80211_IS_CHAN_2GHZ(c)) {
294 reg = AR_READ(sc, AR_AN_RF2G1_CH0);
295 reg = RW(reg, AR_AN_RF2G1_CH0_OB, modal->ob);
296 reg = RW(reg, AR_AN_RF2G1_CH0_DB, modal->db);
297 AR_WRITE(sc, AR_AN_RF2G1_CH0, reg);
298 AR_WRITE_BARRIER(sc);
299 DELAY(100);
300
301 reg = AR_READ(sc, AR_AN_RF2G1_CH1);
302 reg = RW(reg, AR_AN_RF2G1_CH1_OB, modal->ob_ch1);
303 reg = RW(reg, AR_AN_RF2G1_CH1_DB, modal->db_ch1);
304 AR_WRITE(sc, AR_AN_RF2G1_CH1, reg);
305 AR_WRITE_BARRIER(sc);
306 DELAY(100);
307 } else {
308 reg = AR_READ(sc, AR_AN_RF5G1_CH0);
309 reg = RW(reg, AR_AN_RF5G1_CH0_OB5, modal->ob);
310 reg = RW(reg, AR_AN_RF5G1_CH0_DB5, modal->db);
311 AR_WRITE(sc, AR_AN_RF5G1_CH0, reg);
312 AR_WRITE_BARRIER(sc);
313 DELAY(100);
314
315 reg = AR_READ(sc, AR_AN_RF5G1_CH1);
316 reg = RW(reg, AR_AN_RF5G1_CH1_OB5, modal->ob_ch1);
317 reg = RW(reg, AR_AN_RF5G1_CH1_DB5, modal->db_ch1);
318 AR_WRITE(sc, AR_AN_RF5G1_CH1, reg);
319 AR_WRITE_BARRIER(sc);
320 DELAY(100);
321 }
322 reg = AR_READ(sc, AR_AN_TOP2);
323 if ((sc->flags & ATHN_FLAG_USB) && IEEE80211_IS_CHAN_5GHZ(c)) {
324 /*
325 * Hardcode the output voltage of x-PA bias LDO to the
326 * lowest value for UB94 such that the card doesn't get
327 * too hot.
328 */
329 reg = RW(reg, AR_AN_TOP2_XPABIAS_LVL, 0);
330 } else
331 reg = RW(reg, AR_AN_TOP2_XPABIAS_LVL, modal->xpaBiasLvl);
332 if (modal->flagBits & AR5416_EEP_FLAG_LOCALBIAS)
333 reg |= AR_AN_TOP2_LOCALBIAS;
334 else
335 reg &= ~AR_AN_TOP2_LOCALBIAS;
336 AR_WRITE(sc, AR_AN_TOP2, reg);
337 AR_WRITE_BARRIER(sc);
338 DELAY(100);
339
340 reg = AR_READ(sc, AR_PHY_XPA_CFG);
341 if (modal->flagBits & AR5416_EEP_FLAG_FORCEXPAON)
342 reg |= AR_PHY_FORCE_XPA_CFG;
343 else
344 reg &= ~AR_PHY_FORCE_XPA_CFG;
345 AR_WRITE(sc, AR_PHY_XPA_CFG, reg);
346
347 reg = AR_READ(sc, AR_PHY_SETTLING);
348 reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling);
349 AR_WRITE(sc, AR_PHY_SETTLING, reg);
350
351 reg = AR_READ(sc, AR_PHY_DESIRED_SZ);
352 reg = RW(reg, AR_PHY_DESIRED_SZ_ADC, modal->adcDesiredSize);
353 AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg);
354
355 reg = SM(AR_PHY_RF_CTL4_TX_END_XPAA_OFF, modal->txEndToXpaOff);
356 reg |= SM(AR_PHY_RF_CTL4_TX_END_XPAB_OFF, modal->txEndToXpaOff);
357 reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAA_ON, modal->txFrameToXpaOn);
358 reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAB_ON, modal->txFrameToXpaOn);
359 AR_WRITE(sc, AR_PHY_RF_CTL4, reg);
360
361 reg = AR_READ(sc, AR_PHY_RF_CTL3);
362 reg = RW(reg, AR_PHY_TX_END_TO_A2_RX_ON, modal->txEndToRxOn);
363 AR_WRITE(sc, AR_PHY_RF_CTL3, reg);
364
365 reg = AR_READ(sc, AR_PHY_CCA(0));
366 reg = RW(reg, AR9280_PHY_CCA_THRESH62, modal->thresh62);
367 AR_WRITE(sc, AR_PHY_CCA(0), reg);
368
369 reg = AR_READ(sc, AR_PHY_EXT_CCA0);
370 reg = RW(reg, AR_PHY_EXT_CCA0_THRESH62, modal->thresh62);
371 AR_WRITE(sc, AR_PHY_EXT_CCA0, reg);
372
373 if (sc->eep_rev >= AR_EEP_MINOR_VER_2) {
374 reg = AR_READ(sc, AR_PHY_RF_CTL2);
375 reg = RW(reg, AR_PHY_TX_END_DATA_START,
376 modal->txFrameToDataStart);
377 reg = RW(reg, AR_PHY_TX_END_PA_ON, modal->txFrameToPaOn);
378 AR_WRITE(sc, AR_PHY_RF_CTL2, reg);
379 }
380 if (sc->eep_rev >= AR_EEP_MINOR_VER_3 && extc != NULL) {
381 /* Overwrite switch settling with HT-40 value. */
382 reg = AR_READ(sc, AR_PHY_SETTLING);
383 reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->swSettleHt40);
384 AR_WRITE(sc, AR_PHY_SETTLING, reg);
385 }
386 if (sc->eep_rev >= AR_EEP_MINOR_VER_19) {
387 reg = AR_READ(sc, AR_PHY_CCK_TX_CTRL);
388 reg = RW(reg, AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
389 MS(modal->miscBits, AR5416_EEP_MISC_TX_DAC_SCALE_CCK));
390 AR_WRITE(sc, AR_PHY_CCK_TX_CTRL, reg);
391 }
392 if (AR_SREV_9280_20(sc) &&
393 sc->eep_rev >= AR_EEP_MINOR_VER_20) {
394 reg = AR_READ(sc, AR_AN_TOP1);
395 if (eep->baseEepHeader.dacLpMode &&
396 (IEEE80211_IS_CHAN_2GHZ(c) ||
397 !eep->baseEepHeader.dacHiPwrMode_5G))
398 reg |= AR_AN_TOP1_DACLPMODE;
399 else
400 reg &= ~AR_AN_TOP1_DACLPMODE;
401 AR_WRITE(sc, AR_AN_TOP1, reg);
402 AR_WRITE_BARRIER(sc);
403 DELAY(100);
404
405 reg = AR_READ(sc, AR_PHY_FRAME_CTL);
406 reg = RW(reg, AR_PHY_FRAME_CTL_TX_CLIP,
407 MS(modal->miscBits, AR5416_EEP_MISC_TX_CLIP));
408 AR_WRITE(sc, AR_PHY_FRAME_CTL, reg);
409
410 reg = AR_READ(sc, AR_PHY_TX_PWRCTRL9);
411 reg = RW(reg, AR_PHY_TX_DESIRED_SCALE_CCK,
412 eep->baseEepHeader.desiredScaleCCK);
413 AR_WRITE(sc, AR_PHY_TX_PWRCTRL9, reg);
414 }
415 AR_WRITE_BARRIER(sc);
416 }
417
418 void
ar9280_olpc_get_pdadcs(struct athn_softc * sc,struct ieee80211_channel * c,int chain,uint8_t * boundaries,uint8_t * pdadcs,uint8_t * txgain)419 ar9280_olpc_get_pdadcs(struct athn_softc *sc, struct ieee80211_channel *c,
420 int chain, uint8_t *boundaries, uint8_t *pdadcs, uint8_t *txgain)
421 {
422 const struct ar5416_eeprom *eep = sc->eep;
423 const struct ar_cal_data_per_freq_olpc *pierdata;
424 const uint8_t *pierfreq;
425 uint8_t fbin, pcdac, pwr, idx;
426 int i, lo, hi, npiers;
427
428 if (IEEE80211_IS_CHAN_2GHZ(c)) {
429 pierfreq = eep->calFreqPier2G;
430 pierdata = (const struct ar_cal_data_per_freq_olpc *)
431 eep->calPierData2G[chain];
432 npiers = AR5416_NUM_2G_CAL_PIERS;
433 } else {
434 pierfreq = eep->calFreqPier5G;
435 pierdata = (const struct ar_cal_data_per_freq_olpc *)
436 eep->calPierData5G[chain];
437 npiers = AR5416_NUM_5G_CAL_PIERS;
438 }
439 /* Find channel in ROM pier table. */
440 fbin = athn_chan2fbin(c);
441 athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi);
442
443 /* Get average. */
444 pwr = (pierdata[lo].pwrPdg[0][0] + pierdata[hi].pwrPdg[0][0]) / 2;
445 pwr /= 2; /* Convert to dB. */
446
447 /* Find power control digital-to-analog converter (PCDAC) value. */
448 pcdac = pierdata[hi].pcdac[0][0];
449 for (idx = 0; idx < AR9280_TX_GAIN_TABLE_SIZE - 1; idx++)
450 if (pcdac <= sc->tx_gain_tbl[idx])
451 break;
452 *txgain = idx;
453
454 DPRINTFN(3, ("fbin=%d lo=%d hi=%d pwr=%d pcdac=%d txgain=%d\n",
455 fbin, lo, hi, pwr, pcdac, idx));
456
457 /* Fill phase domain analog-to-digital converter (PDADC) table. */
458 for (i = 0; i < AR_NUM_PDADC_VALUES; i++)
459 pdadcs[i] = (i < pwr) ? 0x00 : 0xff;
460
461 for (i = 0; i < AR_PD_GAINS_IN_MASK; i++)
462 boundaries[i] = AR9280_PD_GAIN_BOUNDARY_DEFAULT;
463 }
464
465 void
ar9280_spur_mitigate(struct athn_softc * sc,struct ieee80211_channel * c,struct ieee80211_channel * extc)466 ar9280_spur_mitigate(struct athn_softc *sc, struct ieee80211_channel *c,
467 struct ieee80211_channel *extc)
468 {
469 const struct ar_spur_chan *spurchans;
470 int spur, bin, spur_delta_phase, spur_freq_sd, spur_subchannel_sd;
471 int spur_off, range, i;
472
473 /* NB: Always clear. */
474 AR_CLRBITS(sc, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
475
476 range = (extc != NULL) ? 19 : 10;
477
478 spurchans = sc->ops.get_spur_chans(sc, IEEE80211_IS_CHAN_2GHZ(c));
479 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
480 spur = spurchans[i].spurChan;
481 if (spur == AR_NO_SPUR)
482 return; /* XXX disable if it was enabled! */
483 spur /= 10;
484 if (IEEE80211_IS_CHAN_2GHZ(c))
485 spur += AR_BASE_FREQ_2GHZ;
486 else
487 spur += AR_BASE_FREQ_5GHZ;
488 spur -= c->ic_freq;
489 if (abs(spur) < range)
490 break;
491 }
492 if (i == AR_EEPROM_MODAL_SPURS)
493 return; /* XXX disable if it was enabled! */
494 DPRINTFN(2, ("enabling spur mitigation\n"));
495
496 AR_SETBITS(sc, AR_PHY_TIMING_CTRL4_0,
497 AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
498 AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
499 AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
500 AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
501
502 AR_WRITE(sc, AR_PHY_SPUR_REG,
503 AR_PHY_SPUR_REG_MASK_RATE_CNTL |
504 AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
505 AR_PHY_SPUR_REG_MASK_RATE_SELECT |
506 AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
507 SM(AR_PHY_SPUR_REG_SPUR_RSSI_THRESH, AR_SPUR_RSSI_THRESH));
508
509 if (extc != NULL) {
510 spur_delta_phase = (spur * 262144) / 10;
511 if (spur < 0) {
512 spur_subchannel_sd = 1;
513 spur_off = spur + 10;
514 } else {
515 spur_subchannel_sd = 0;
516 spur_off = spur - 10;
517 }
518 } else {
519 spur_delta_phase = (spur * 524288) / 10;
520 spur_subchannel_sd = 0;
521 spur_off = spur;
522 }
523 if (IEEE80211_IS_CHAN_2GHZ(c))
524 spur_freq_sd = (spur_off * 2048) / 44;
525 else
526 spur_freq_sd = (spur_off * 2048) / 40;
527
528 AR_WRITE(sc, AR_PHY_TIMING11,
529 AR_PHY_TIMING11_USE_SPUR_IN_AGC |
530 SM(AR_PHY_TIMING11_SPUR_FREQ_SD, spur_freq_sd) |
531 SM(AR_PHY_TIMING11_SPUR_DELTA_PHASE, spur_delta_phase));
532
533 AR_WRITE(sc, AR_PHY_SFCORR_EXT,
534 SM(AR_PHY_SFCORR_SPUR_SUBCHNL_SD, spur_subchannel_sd));
535 AR_WRITE_BARRIER(sc);
536
537 bin = spur * 320;
538 ar5008_set_viterbi_mask(sc, bin);
539 }
540
541 void
ar9280_reset_rx_gain(struct athn_softc * sc,struct ieee80211_channel * c)542 ar9280_reset_rx_gain(struct athn_softc *sc, struct ieee80211_channel *c)
543 {
544 const struct athn_gain *prog = sc->rx_gain;
545 const uint32_t *pvals;
546 int i;
547
548 if (IEEE80211_IS_CHAN_2GHZ(c))
549 pvals = prog->vals_2g;
550 else
551 pvals = prog->vals_5g;
552 for (i = 0; i < prog->nregs; i++)
553 AR_WRITE(sc, prog->regs[i], pvals[i]);
554 }
555
556 void
ar9280_reset_tx_gain(struct athn_softc * sc,struct ieee80211_channel * c)557 ar9280_reset_tx_gain(struct athn_softc *sc, struct ieee80211_channel *c)
558 {
559 const struct athn_gain *prog = sc->tx_gain;
560 const uint32_t *pvals;
561 int i;
562
563 if (IEEE80211_IS_CHAN_2GHZ(c))
564 pvals = prog->vals_2g;
565 else
566 pvals = prog->vals_5g;
567 for (i = 0; i < prog->nregs; i++)
568 AR_WRITE(sc, prog->regs[i], pvals[i]);
569 }
570
571 void
ar9280_olpc_init(struct athn_softc * sc)572 ar9280_olpc_init(struct athn_softc *sc)
573 {
574 uint32_t reg;
575 int i;
576
577 /* Save original Tx gain values. */
578 for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
579 reg = AR_READ(sc, AR_PHY_TX_GAIN_TBL(i));
580 sc->tx_gain_tbl[i] = MS(reg, AR_PHY_TX_GAIN);
581 }
582 /* Initial Tx gain temperature compensation. */
583 sc->tcomp = 0;
584 }
585
586 void
ar9280_olpc_temp_compensation(struct athn_softc * sc)587 ar9280_olpc_temp_compensation(struct athn_softc *sc)
588 {
589 const struct ar5416_eeprom *eep = sc->eep;
590 int8_t pdadc, txgain, tcomp;
591 uint32_t reg;
592 int i;
593
594 reg = AR_READ(sc, AR_PHY_TX_PWRCTRL4);
595 pdadc = MS(reg, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
596 DPRINTFN(3, ("PD Avg Out=%d\n", pdadc));
597
598 if (sc->pdadc == 0 || pdadc == 0)
599 return; /* No frames transmitted yet. */
600
601 /* Compute Tx gain temperature compensation. */
602 if (sc->eep_rev >= AR_EEP_MINOR_VER_20 &&
603 eep->baseEepHeader.dacHiPwrMode_5G)
604 tcomp = (pdadc - sc->pdadc + 4) / 8;
605 else
606 tcomp = (pdadc - sc->pdadc + 5) / 10;
607 DPRINTFN(3, ("OLPC temp compensation=%d\n", tcomp));
608
609 if (tcomp == sc->tcomp)
610 return; /* Don't rewrite the same values. */
611 sc->tcomp = tcomp;
612
613 /* Adjust Tx gain values. */
614 for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
615 txgain = sc->tx_gain_tbl[i] - tcomp;
616 if (txgain < 0)
617 txgain = 0;
618 reg = AR_READ(sc, AR_PHY_TX_GAIN_TBL(i));
619 reg = RW(reg, AR_PHY_TX_GAIN, txgain);
620 AR_WRITE(sc, AR_PHY_TX_GAIN_TBL(i), reg);
621 }
622 AR_WRITE_BARRIER(sc);
623 }
624