1/* $NetBSD: arn5416.c,v 1.2 2013/04/03 14:20:02 christos Exp $ */
2/* $OpenBSD: ar5416.c,v 1.12 2012/06/10 21:23:36 kettenis Exp $ */
3
4/*-
5 * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
6 * Copyright (c) 2008-2009 Atheros Communications Inc.
7 *
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */
20
21/*
22 * Driver for Atheros 802.11a/g/n chipsets.
23 * Routines for AR5416, AR5418 and AR9160 chipsets.
24 */
25
26#include <sys/cdefs.h>
27__KERNEL_RCSID(0, "$NetBSD: arn5416.c,v 1.2 2013/04/03 14:20:02 christos Exp $");
28
29#include <sys/param.h>
30#include <sys/sockio.h>
31#include <sys/mbuf.h>
32#include <sys/kernel.h>
33#include <sys/socket.h>
34#include <sys/systm.h>
35#include <sys/malloc.h>
36#include <sys/queue.h>
37#include <sys/callout.h>
38#include <sys/conf.h>
39#include <sys/device.h>
40
41#include <sys/bus.h>
42#include <sys/endian.h>
43#include <sys/intr.h>
44
45#include <net/bpf.h>
46#include <net/if.h>
47#include <net/if_arp.h>
48#include <net/if_dl.h>
49#include <net/if_ether.h>
50#include <net/if_media.h>
51#include <net/if_types.h>
52
53#include <netinet/in.h>
54#include <netinet/in_systm.h>
55#include <netinet/in_var.h>
56#include <netinet/ip.h>
57
58#include <net80211/ieee80211_var.h>
59#include <net80211/ieee80211_amrr.h>
60#include <net80211/ieee80211_radiotap.h>
61
62#include <dev/ic/athnreg.h>
63#include <dev/ic/athnvar.h>
64
65#include <dev/ic/arn5008reg.h>
66#include <dev/ic/arn5008.h>
67#include <dev/ic/arn5416reg.h>
68#include <dev/ic/arn5416.h>
69#include <dev/ic/arn9280.h>
70
71#define Static static
72
73Static void ar5416_force_bias(struct athn_softc *,
74 struct ieee80211_channel *);
75Static void ar5416_get_pdadcs(struct athn_softc *,
76 struct ieee80211_channel *, int, int, uint8_t, uint8_t *,
77 uint8_t *);
78Static void ar5416_init_from_rom(struct athn_softc *,
79 struct ieee80211_channel *, struct ieee80211_channel *);
80Static uint8_t ar5416_reverse_bits(uint8_t, int);
81Static void ar5416_rw_bank6tpc(struct athn_softc *,
82 struct ieee80211_channel *, uint32_t *);
83Static void ar5416_rw_rfbits(uint32_t *, int, int, uint32_t, int);
84Static void ar5416_set_power_calib(struct athn_softc *,
85 struct ieee80211_channel *);
86Static int ar5416_set_synth(struct athn_softc *,
87 struct ieee80211_channel *, struct ieee80211_channel *);
88Static void ar5416_setup(struct athn_softc *);
89Static void ar5416_spur_mitigate(struct athn_softc *,
90 struct ieee80211_channel *, struct ieee80211_channel *);
91Static void ar9160_rw_addac(struct athn_softc *,
92 struct ieee80211_channel *, uint32_t *);
93
94PUBLIC int
95ar5416_attach(struct athn_softc *sc)
96{
97 sc->sc_eep_base = AR5416_EEP_START_LOC;
98 sc->sc_eep_size = sizeof(struct ar5416_eeprom);
99 sc->sc_def_nf = AR5416_PHY_CCA_MAX_GOOD_VALUE;
100 sc->sc_ngpiopins = 14;
101 sc->sc_led_pin = 1;
102 sc->sc_workaround = AR5416_WA_DEFAULT;
103 sc->sc_ops.setup = ar5416_setup;
104 sc->sc_ops.swap_rom = ar5416_swap_rom;
105 sc->sc_ops.init_from_rom = ar5416_init_from_rom;
106 sc->sc_ops.set_txpower = ar5416_set_txpower;
107 sc->sc_ops.set_synth = ar5416_set_synth;
108 sc->sc_ops.spur_mitigate = ar5416_spur_mitigate;
109 sc->sc_ops.get_spur_chans = ar5416_get_spur_chans;
110 if (AR_SREV_9160_10_OR_LATER(sc))
111 sc->sc_ini = &ar9160_ini;
112 else
113 sc->sc_ini = &ar5416_ini;
114 sc->sc_serdes = &ar5416_serdes;
115
116 return ar5008_attach(sc);
117}
118
119Static void
120ar5416_setup(struct athn_softc *sc)
121{
122 /* Select ADDAC programming. */
123 if (AR_SREV_9160_11(sc))
124 sc->sc_addac = &ar9160_1_1_addac;
125 else if (AR_SREV_9160_10_OR_LATER(sc))
126 sc->sc_addac = &ar9160_1_0_addac;
127 else if (AR_SREV_5416_22_OR_LATER(sc))
128 sc->sc_addac = &ar5416_2_2_addac;
129 else
130 sc->sc_addac = &ar5416_2_1_addac;
131}
132
133PUBLIC void
134ar5416_swap_rom(struct athn_softc *sc)
135{
136 struct ar5416_eeprom *eep = sc->sc_eep;
137 struct ar5416_modal_eep_header *modal;
138 int i, j;
139
140 for (i = 0; i < 2; i++) { /* Dual-band. */
141 modal = &eep->modalHeader[i];
142
143 modal->antCtrlCommon = bswap32(modal->antCtrlCommon);
144 for (j = 0; j < AR5416_MAX_CHAINS; j++) {
145 modal->antCtrlChain[j] =
146 bswap32(modal->antCtrlChain[j]);
147 }
148 for (j = 0; j < AR_EEPROM_MODAL_SPURS; j++) {
149 modal->spurChans[j].spurChan =
150 bswap16(modal->spurChans[j].spurChan);
151 }
152 }
153}
154
155PUBLIC const struct ar_spur_chan *
156ar5416_get_spur_chans(struct athn_softc *sc, int is2ghz)
157{
158 const struct ar5416_eeprom *eep = sc->sc_eep;
159
160 return eep->modalHeader[is2ghz].spurChans;
161}
162
163Static int
164ar5416_set_synth(struct athn_softc *sc, struct ieee80211_channel *c,
165 struct ieee80211_channel *extc)
166{
167 uint32_t phy, reg;
168 uint32_t freq = c->ic_freq;
169 uint8_t chansel;
170
171 phy = 0;
172 if (IEEE80211_IS_CHAN_2GHZ(c)) {
173 if (((freq - 2192) % 5) == 0) {
174 chansel = ((freq - 672) * 2 - 3040) / 10;
175 }
176 else if (((freq - 2224) % 5) == 0) {
177 chansel = ((freq - 704) * 2 - 3040) / 10;
178 phy |= AR5416_BMODE_SYNTH;
179 }
180 else
181 return EINVAL;
182 chansel <<= 2;
183
184 reg = AR_READ(sc, AR_PHY_CCK_TX_CTRL);
185 if (freq == 2484) /* Channel 14. */
186 reg |= AR_PHY_CCK_TX_CTRL_JAPAN;
187 else
188 reg &= ~AR_PHY_CCK_TX_CTRL_JAPAN;
189 AR_WRITE(sc, AR_PHY_CCK_TX_CTRL, reg);
190
191 /* Fix for orientation sensitivity issue. */
192 if (AR_SREV_5416(sc))
193 ar5416_force_bias(sc, c);
194 }
195 else {
196 if (freq >= 5120 && (freq % 20) == 0) {
197 chansel = (freq - 4800) / 20;
198 chansel <<= 2;
199 phy |= SM(AR5416_AMODE_REFSEL, 2);
200 }
201 else if ((freq % 10) == 0) {
202 chansel = (freq - 4800) / 10;
203 chansel <<= 1;
204 if (AR_SREV_9160_10_OR_LATER(sc))
205 phy |= SM(AR5416_AMODE_REFSEL, 1);
206 else
207 phy |= SM(AR5416_AMODE_REFSEL, 2);
208 }
209 else if ((freq % 5) == 0) {
210 chansel = (freq - 4800) / 5;
211 phy |= SM(AR5416_AMODE_REFSEL, 2);
212 }
213 else
214 return EINVAL;
215 }
216 chansel = ar5416_reverse_bits(chansel, 8);
217 phy |= chansel << 8 | 1 << 5 | 1;
218 DPRINTFN(DBG_RF, sc, "AR_PHY(0x37)=0x%08x\n", phy);
219 AR_WRITE(sc, AR_PHY(0x37), phy);
220 return 0;
221}
222
223Static void
224ar5416_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c,
225 struct ieee80211_channel *extc)
226{
227 static const uint32_t chainoffset[] = { 0x0000, 0x2000, 0x1000 };
228 const struct ar5416_eeprom *eep = sc->sc_eep;
229 const struct ar5416_modal_eep_header *modal;
230 uint32_t reg, offset;
231 uint8_t txRxAtten;
232 int i;
233
234 modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
235
236 AR_WRITE(sc, AR_PHY_SWITCH_COM, modal->antCtrlCommon);
237
238 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
239 if (AR_SREV_5416_20_OR_LATER(sc) &&
240 (sc->sc_rxchainmask == 0x5 || sc->sc_txchainmask == 0x5))
241 offset = chainoffset[i];
242 else
243 offset = i * 0x1000;
244
245 AR_WRITE(sc, AR_PHY_SWITCH_CHAIN_0 + offset,
246 modal->antCtrlChain[i]);
247
248 reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0 + offset);
249 reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
250 modal->iqCalICh[i]);
251 reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
252 modal->iqCalQCh[i]);
253 AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0 + offset, reg);
254
255 if (i > 0 && !AR_SREV_5416_20_OR_LATER(sc))
256 continue;
257
258 if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_3) {
259 reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset);
260 reg = RW(reg, AR_PHY_GAIN_2GHZ_BSW_MARGIN,
261 modal->bswMargin[i]);
262 reg = RW(reg, AR_PHY_GAIN_2GHZ_BSW_ATTEN,
263 modal->bswAtten[i]);
264 AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg);
265 }
266 if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_3)
267 txRxAtten = modal->txRxAttenCh[i];
268 else /* Workaround for ROM versions < 14.3. */
269 txRxAtten = IEEE80211_IS_CHAN_2GHZ(c) ? 23 : 44;
270 reg = AR_READ(sc, AR_PHY_RXGAIN + offset);
271 reg = RW(reg, AR_PHY_RXGAIN_TXRX_ATTEN, txRxAtten);
272 AR_WRITE(sc, AR_PHY_RXGAIN + offset, reg);
273
274 reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset);
275 reg = RW(reg, AR_PHY_GAIN_2GHZ_RXTX_MARGIN,
276 modal->rxTxMarginCh[i]);
277 AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg);
278 }
279 reg = AR_READ(sc, AR_PHY_SETTLING);
280 reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling);
281 AR_WRITE(sc, AR_PHY_SETTLING, reg);
282
283 reg = AR_READ(sc, AR_PHY_DESIRED_SZ);
284 reg = RW(reg, AR_PHY_DESIRED_SZ_ADC, modal->adcDesiredSize);
285 reg = RW(reg, AR_PHY_DESIRED_SZ_PGA, modal->pgaDesiredSize);
286 AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg);
287
288 reg = SM(AR_PHY_RF_CTL4_TX_END_XPAA_OFF, modal->txEndToXpaOff);
289 reg |= SM(AR_PHY_RF_CTL4_TX_END_XPAB_OFF, modal->txEndToXpaOff);
290 reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAA_ON, modal->txFrameToXpaOn);
291 reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAB_ON, modal->txFrameToXpaOn);
292 AR_WRITE(sc, AR_PHY_RF_CTL4, reg);
293
294 reg = AR_READ(sc, AR_PHY_RF_CTL3);
295 reg = RW(reg, AR_PHY_TX_END_TO_A2_RX_ON, modal->txEndToRxOn);
296 AR_WRITE(sc, AR_PHY_RF_CTL3, reg);
297
298 reg = AR_READ(sc, AR_PHY_CCA(0));
299 reg = RW(reg, AR_PHY_CCA_THRESH62, modal->thresh62);
300 AR_WRITE(sc, AR_PHY_CCA(0), reg);
301
302 reg = AR_READ(sc, AR_PHY_EXT_CCA(0));
303 reg = RW(reg, AR_PHY_EXT_CCA_THRESH62, modal->thresh62);
304 AR_WRITE(sc, AR_PHY_EXT_CCA(0), reg);
305
306 if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_2) {
307 reg = AR_READ(sc, AR_PHY_RF_CTL2);
308 reg = RW(reg, AR_PHY_TX_END_DATA_START,
309 modal->txFrameToDataStart);
310 reg = RW(reg, AR_PHY_TX_END_PA_ON, modal->txFrameToPaOn);
311 AR_WRITE(sc, AR_PHY_RF_CTL2, reg);
312 }
313#ifndef IEEE80211_NO_HT
314 if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_3 && extc != NULL) {
315 /* Overwrite switch settling with HT-40 value. */
316 reg = AR_READ(sc, AR_PHY_SETTLING);
317 reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->swSettleHt40);
318 AR_WRITE(sc, AR_PHY_SETTLING, reg);
319 }
320#endif
321}
322
323PUBLIC int
324ar5416_init_calib(struct athn_softc *sc, struct ieee80211_channel *c,
325 struct ieee80211_channel *extc)
326{
327 int ntries;
328
329 if (AR_SREV_9280_10_OR_LATER(sc)) {
330 /* XXX Linux tests AR9287?! */
331 AR_CLRBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
332 AR_SETBITS(sc, AR_PHY_AGC_CONTROL,
333 AR_PHY_AGC_CONTROL_FLTR_CAL);
334 }
335 /* Calibrate the AGC. */
336 AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
337 /* Poll for offset calibration completion. */
338 for (ntries = 0; ntries < 10000; ntries++) {
339 if (!(AR_READ(sc, AR_PHY_AGC_CONTROL) &
340 AR_PHY_AGC_CONTROL_CAL))
341 break;
342 DELAY(10);
343 }
344 if (ntries == 10000)
345 return ETIMEDOUT;
346 if (AR_SREV_9280_10_OR_LATER(sc)) {
347 AR_SETBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
348 AR_CLRBITS(sc, AR_PHY_AGC_CONTROL,
349 AR_PHY_AGC_CONTROL_FLTR_CAL);
350 }
351 return 0;
352}
353
354Static void
355ar5416_get_pdadcs(struct athn_softc *sc, struct ieee80211_channel *c,
356 int chain, int nxpdgains, uint8_t overlap, uint8_t *boundaries,
357 uint8_t *pdadcs)
358{
359 const struct ar5416_eeprom *eep = sc->sc_eep;
360 const struct ar5416_cal_data_per_freq *pierdata;
361 const uint8_t *pierfreq;
362 struct athn_pier lopier, hipier;
363 int16_t delta;
364 uint8_t fbin, pwroff;
365 int i, lo, hi, npiers;
366
367 if (IEEE80211_IS_CHAN_2GHZ(c)) {
368 pierfreq = eep->calFreqPier2G;
369 pierdata = eep->calPierData2G[chain];
370 npiers = AR5416_NUM_2G_CAL_PIERS;
371 }
372 else {
373 pierfreq = eep->calFreqPier5G;
374 pierdata = eep->calPierData5G[chain];
375 npiers = AR5416_NUM_5G_CAL_PIERS;
376 }
377 /* Find channel in ROM pier table. */
378 fbin = athn_chan2fbin(c);
379 athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi);
380
381 lopier.fbin = pierfreq[lo];
382 hipier.fbin = pierfreq[hi];
383 for (i = 0; i < nxpdgains; i++) {
384 lopier.pwr[i] = pierdata[lo].pwrPdg[i];
385 lopier.vpd[i] = pierdata[lo].vpdPdg[i];
386 hipier.pwr[i] = pierdata[lo].pwrPdg[i];
387 hipier.vpd[i] = pierdata[lo].vpdPdg[i];
388 }
389 ar5008_get_pdadcs(sc, fbin, &lopier, &hipier, nxpdgains,
390 AR5416_PD_GAIN_ICEPTS, overlap, boundaries, pdadcs);
391
392 if (!AR_SREV_9280_20_OR_LATER(sc))
393 return;
394
395 if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_21)
396 pwroff = eep->baseEepHeader.pwrTableOffset;
397 else
398 pwroff = AR_PWR_TABLE_OFFSET_DB;
399 delta = (pwroff - AR_PWR_TABLE_OFFSET_DB) * 2; /* In half dB. */
400
401 /* Change the original gain boundaries setting. */
402 for (i = 0; i < nxpdgains; i++) {
403 /* XXX Possible overflows? */
404 boundaries[i] -= delta;
405 if (boundaries[i] > AR_MAX_RATE_POWER - overlap)
406 boundaries[i] = AR_MAX_RATE_POWER - overlap;
407 }
408 if (delta != 0) {
409 /* Shift the PDADC table to start at the new offset. */
410 for (i = 0; i < AR_NUM_PDADC_VALUES; i++)
411 pdadcs[i] = pdadcs[MIN(i + delta,
412 AR_NUM_PDADC_VALUES - 1)];
413 }
414}
415
416Static void
417ar5416_set_power_calib(struct athn_softc *sc, struct ieee80211_channel *c)
418{
419 static const uint32_t chainoffset[] = { 0x0000, 0x2000, 0x1000 };
420 const struct ar5416_eeprom *eep = sc->sc_eep;
421 const struct ar5416_modal_eep_header *modal;
422 uint8_t boundaries[AR_PD_GAINS_IN_MASK];
423 uint8_t pdadcs[AR_NUM_PDADC_VALUES];
424 uint8_t xpdgains[AR5416_NUM_PD_GAINS];
425 uint8_t overlap, txgain;
426 uint32_t reg, offset;
427 int i, j, nxpdgains;
428
429 modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
430
431 if (sc->sc_eep_rev < AR_EEP_MINOR_VER_2) {
432 overlap = MS(AR_READ(sc, AR_PHY_TPCRG5),
433 AR_PHY_TPCRG5_PD_GAIN_OVERLAP);
434 }
435 else
436 overlap = modal->pdGainOverlap;
437
438 if ((sc->sc_flags & ATHN_FLAG_OLPC) && IEEE80211_IS_CHAN_2GHZ(c)) {
439 /* XXX not here. */
440 sc->sc_pdadc =
441 ((const struct ar_cal_data_per_freq_olpc *)
442 eep->calPierData2G[0])->vpdPdg[0][0];
443 }
444
445 nxpdgains = 0;
446 memset(xpdgains, 0, sizeof(xpdgains));
447 for (i = AR5416_PD_GAINS_IN_MASK - 1; i >= 0; i--) {
448 if (nxpdgains >= AR5416_NUM_PD_GAINS)
449 break; /* Can't happen. */
450 if (modal->xpdGain & (1 << i))
451 xpdgains[nxpdgains++] = i;
452 }
453 reg = AR_READ(sc, AR_PHY_TPCRG1);
454 reg = RW(reg, AR_PHY_TPCRG1_NUM_PD_GAIN, nxpdgains - 1);
455 reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_1, xpdgains[0]);
456 reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_2, xpdgains[1]);
457 reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_3, xpdgains[2]);
458 AR_WRITE(sc, AR_PHY_TPCRG1, reg);
459
460 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
461 if (!(sc->sc_txchainmask & (1 << i)))
462 continue;
463
464 if (AR_SREV_5416_20_OR_LATER(sc) &&
465 (sc->sc_rxchainmask == 0x5 || sc->sc_txchainmask == 0x5))
466 offset = chainoffset[i];
467 else
468 offset = i * 0x1000;
469
470 if (sc->sc_flags & ATHN_FLAG_OLPC) {
471 ar9280_olpc_get_pdadcs(sc, c, i, boundaries,
472 pdadcs, &txgain);
473
474 reg = AR_READ(sc, AR_PHY_TX_PWRCTRL6_0);
475 reg = RW(reg, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
476 AR_WRITE(sc, AR_PHY_TX_PWRCTRL6_0, reg);
477
478 reg = AR_READ(sc, AR_PHY_TX_PWRCTRL6_1);
479 reg = RW(reg, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
480 AR_WRITE(sc, AR_PHY_TX_PWRCTRL6_1, reg);
481
482 reg = AR_READ(sc, AR_PHY_TX_PWRCTRL7);
483 reg = RW(reg, AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, txgain);
484 AR_WRITE(sc, AR_PHY_TX_PWRCTRL7, reg);
485
486 overlap = 6;
487 }
488 else {
489 ar5416_get_pdadcs(sc, c, i, nxpdgains, overlap,
490 boundaries, pdadcs);
491 }
492 /* Write boundaries. */
493 if (i == 0 || AR_SREV_5416_20_OR_LATER(sc)) {
494 reg = SM(AR_PHY_TPCRG5_PD_GAIN_OVERLAP,
495 overlap);
496 reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1,
497 boundaries[0]);
498 reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2,
499 boundaries[1]);
500 reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3,
501 boundaries[2]);
502 reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4,
503 boundaries[3]);
504 AR_WRITE(sc, AR_PHY_TPCRG5 + offset, reg);
505 }
506 /* Write PDADC values. */
507 for (j = 0; j < AR_NUM_PDADC_VALUES; j += 4) {
508 AR_WRITE(sc, AR_PHY_PDADC_TBL_BASE + offset + j,
509 pdadcs[j + 0] << 0 |
510 pdadcs[j + 1] << 8 |
511 pdadcs[j + 2] << 16 |
512 pdadcs[j + 3] << 24);
513 }
514 }
515}
516
517PUBLIC void
518ar5416_set_txpower(struct athn_softc *sc, struct ieee80211_channel *c,
519 struct ieee80211_channel *extc)
520{
521 const struct ar5416_eeprom *eep = sc->sc_eep;
522 const struct ar5416_modal_eep_header *modal;
523 uint8_t tpow_cck[4], tpow_ofdm[4];
524#ifndef IEEE80211_NO_HT
525 uint8_t tpow_cck_ext[4], tpow_ofdm_ext[4];
526 uint8_t tpow_ht20[8], tpow_ht40[8];
527 uint8_t ht40inc;
528#endif
529 int16_t pwr = 0, pwroff, max_ant_gain, power[ATHN_POWER_COUNT];
530 uint8_t cckinc;
531 int i;
532
533 ar5416_set_power_calib(sc, c);
534
535 modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
536
537 /* Compute transmit power reduction due to antenna gain. */
538 max_ant_gain = MAX(modal->antennaGainCh[0], modal->antennaGainCh[1]);
539 max_ant_gain = MAX(modal->antennaGainCh[2], max_ant_gain);
540 /* XXX */
541
542 /*
543 * Reduce scaled power by number of active chains to get per-chain
544 * transmit power level.
545 */
546 if (sc->sc_ntxchains == 2)
547 pwr -= AR_PWR_DECREASE_FOR_2_CHAIN;
548 else if (sc->sc_ntxchains == 3)
549 pwr -= AR_PWR_DECREASE_FOR_3_CHAIN;
550 if (pwr < 0)
551 pwr = 0;
552
553 if (IEEE80211_IS_CHAN_2GHZ(c)) {
554 /* Get CCK target powers. */
555 ar5008_get_lg_tpow(sc, c, AR_CTL_11B, eep->calTargetPowerCck,
556 AR5416_NUM_2G_CCK_TARGET_POWERS, tpow_cck);
557
558 /* Get OFDM target powers. */
559 ar5008_get_lg_tpow(sc, c, AR_CTL_11G, eep->calTargetPower2G,
560 AR5416_NUM_2G_20_TARGET_POWERS, tpow_ofdm);
561
562#ifndef IEEE80211_NO_HT
563 /* Get HT-20 target powers. */
564 ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT20,
565 eep->calTargetPower2GHT20, AR5416_NUM_2G_20_TARGET_POWERS,
566 tpow_ht20);
567
568 if (extc != NULL) {
569 /* Get HT-40 target powers. */
570 ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT40,
571 eep->calTargetPower2GHT40,
572 AR5416_NUM_2G_40_TARGET_POWERS, tpow_ht40);
573
574 /* Get secondary channel CCK target powers. */
575 ar5008_get_lg_tpow(sc, extc, AR_CTL_11B,
576 eep->calTargetPowerCck,
577 AR5416_NUM_2G_CCK_TARGET_POWERS, tpow_cck_ext);
578
579 /* Get secondary channel OFDM target powers. */
580 ar5008_get_lg_tpow(sc, extc, AR_CTL_11G,
581 eep->calTargetPower2G,
582 AR5416_NUM_2G_20_TARGET_POWERS, tpow_ofdm_ext);
583 }
584#endif
585 }
586 else {
587 /* Get OFDM target powers. */
588 ar5008_get_lg_tpow(sc, c, AR_CTL_11A, eep->calTargetPower5G,
589 AR5416_NUM_5G_20_TARGET_POWERS, tpow_ofdm);
590
591#ifndef IEEE80211_NO_HT
592 /* Get HT-20 target powers. */
593 ar5008_get_ht_tpow(sc, c, AR_CTL_5GHT20,
594 eep->calTargetPower5GHT20, AR5416_NUM_5G_20_TARGET_POWERS,
595 tpow_ht20);
596
597 if (extc != NULL) {
598 /* Get HT-40 target powers. */
599 ar5008_get_ht_tpow(sc, c, AR_CTL_5GHT40,
600 eep->calTargetPower5GHT40,
601 AR5416_NUM_5G_40_TARGET_POWERS, tpow_ht40);
602
603 /* Get secondary channel OFDM target powers. */
604 ar5008_get_lg_tpow(sc, extc, AR_CTL_11A,
605 eep->calTargetPower5G,
606 AR5416_NUM_5G_20_TARGET_POWERS, tpow_ofdm_ext);
607 }
608#endif
609 }
610
611 /* Compute CCK/OFDM delta. */
612 cckinc = (sc->sc_flags & ATHN_FLAG_OLPC) ? -2 : 0;
613
614 memset(power, 0, sizeof(power));
615 /* Shuffle target powers accross transmit rates. */
616 power[ATHN_POWER_OFDM6 ] =
617 power[ATHN_POWER_OFDM9 ] =
618 power[ATHN_POWER_OFDM12] =
619 power[ATHN_POWER_OFDM18] =
620 power[ATHN_POWER_OFDM24] = tpow_ofdm[0];
621 power[ATHN_POWER_OFDM36] = tpow_ofdm[1];
622 power[ATHN_POWER_OFDM48] = tpow_ofdm[2];
623 power[ATHN_POWER_OFDM54] = tpow_ofdm[3];
624 power[ATHN_POWER_XR ] = tpow_ofdm[0];
625 if (IEEE80211_IS_CHAN_2GHZ(c)) {
626 power[ATHN_POWER_CCK1_LP ] = tpow_cck[0] + cckinc;
627 power[ATHN_POWER_CCK2_LP ] =
628 power[ATHN_POWER_CCK2_SP ] = tpow_cck[1] + cckinc;
629 power[ATHN_POWER_CCK55_LP] =
630 power[ATHN_POWER_CCK55_SP] = tpow_cck[2] + cckinc;
631 power[ATHN_POWER_CCK11_LP] =
632 power[ATHN_POWER_CCK11_SP] = tpow_cck[3] + cckinc;
633 }
634#ifndef IEEE80211_NO_HT
635 for (i = 0; i < nitems(tpow_ht20); i++)
636 power[ATHN_POWER_HT20(i)] = tpow_ht20[i];
637 if (extc != NULL) {
638 /* Correct PAR difference between HT40 and HT20/Legacy. */
639 if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_2)
640 ht40inc = modal->ht40PowerIncForPdadc;
641 else
642 ht40inc = AR_HT40_POWER_INC_FOR_PDADC;
643 for (i = 0; i < nitems(tpow_ht40); i++)
644 power[ATHN_POWER_HT40(i)] = tpow_ht40[i] + ht40inc;
645 power[ATHN_POWER_OFDM_DUP] = tpow_ht40[0];
646 power[ATHN_POWER_CCK_DUP ] = tpow_ht40[0] + cckinc;
647 power[ATHN_POWER_OFDM_EXT] = tpow_ofdm_ext[0];
648 if (IEEE80211_IS_CHAN_2GHZ(c))
649 power[ATHN_POWER_CCK_EXT] = tpow_cck_ext[0] + cckinc;
650 }
651#endif
652
653 if (AR_SREV_9280_10_OR_LATER(sc)) {
654 if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_21)
655 pwroff = eep->baseEepHeader.pwrTableOffset;
656 else
657 pwroff = AR_PWR_TABLE_OFFSET_DB;
658 for (i = 0; i < ATHN_POWER_COUNT; i++)
659 power[i] -= pwroff * 2; /* In half dB. */
660 }
661 for (i = 0; i < ATHN_POWER_COUNT; i++) {
662 if (power[i] > AR_MAX_RATE_POWER)
663 power[i] = AR_MAX_RATE_POWER;
664 }
665
666 /* Write transmit power values to hardware. */
667 ar5008_write_txpower(sc, power);
668
669 /*
670 * Write transmit power substraction for dynamic chain changing
671 * and per-packet transmit power.
672 */
673 AR_WRITE(sc, AR_PHY_POWER_TX_SUB,
674 (modal->pwrDecreaseFor3Chain & 0x3f) << 6 |
675 (modal->pwrDecreaseFor2Chain & 0x3f));
676}
677
678Static void
679ar5416_spur_mitigate(struct athn_softc *sc, struct ieee80211_channel *c,
680 struct ieee80211_channel *extc)
681{
682 const struct ar_spur_chan *spurchans;
683 int i, spur, bin, spur_delta_phase, spur_freq_sd;
684
685 spurchans = sc->sc_ops.get_spur_chans(sc, IEEE80211_IS_CHAN_2GHZ(c));
686 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
687 spur = spurchans[i].spurChan;
688 if (spur == AR_NO_SPUR)
689 return; /* XXX disable if it was enabled! */
690 spur -= c->ic_freq * 10;
691 /* Verify range +/-9.5MHz */
692 if (abs(spur) < 95)
693 break;
694 }
695 if (i == AR_EEPROM_MODAL_SPURS)
696 return; /* XXX disable if it was enabled! */
697 DPRINTFN(DBG_RF, sc, "enabling spur mitigation\n");
698
699 AR_SETBITS(sc, AR_PHY_TIMING_CTRL4_0,
700 AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
701 AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
702 AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
703 AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
704
705 AR_WRITE(sc, AR_PHY_SPUR_REG,
706 AR_PHY_SPUR_REG_MASK_RATE_CNTL |
707 AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
708 AR_PHY_SPUR_REG_MASK_RATE_SELECT |
709 AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
710 SM(AR_PHY_SPUR_REG_SPUR_RSSI_THRESH, AR_SPUR_RSSI_THRESH));
711
712 spur_delta_phase = (spur * 524288) / 100;
713 if (IEEE80211_IS_CHAN_2GHZ(c))
714 spur_freq_sd = (spur * 2048) / 440;
715 else
716 spur_freq_sd = (spur * 2048) / 400;
717
718 AR_WRITE(sc, AR_PHY_TIMING11,
719 AR_PHY_TIMING11_USE_SPUR_IN_AGC |
720 SM(AR_PHY_TIMING11_SPUR_FREQ_SD, spur_freq_sd) |
721 SM(AR_PHY_TIMING11_SPUR_DELTA_PHASE, spur_delta_phase));
722
723 bin = spur * 32;
724 ar5008_set_viterbi_mask(sc, bin);
725}
726
727Static uint8_t
728ar5416_reverse_bits(uint8_t v, int nbits)
729{
730 KASSERT(nbits <= 8);
731 v = ((v >> 1) & 0x55) | ((v & 0x55) << 1);
732 v = ((v >> 2) & 0x33) | ((v & 0x33) << 2);
733 v = ((v >> 4) & 0x0f) | ((v & 0x0f) << 4);
734 return v >> (8 - nbits);
735}
736
737PUBLIC uint8_t
738ar5416_get_rf_rev(struct athn_softc *sc)
739{
740 uint8_t rev, reg;
741 int i;
742
743 /* Allow access to analog chips. */
744 AR_WRITE(sc, AR_PHY(0), 0x00000007);
745
746 AR_WRITE(sc, AR_PHY(0x36), 0x00007058);
747 for (i = 0; i < 8; i++)
748 AR_WRITE(sc, AR_PHY(0x20), 0x00010000);
749 reg = (AR_READ(sc, AR_PHY(256)) >> 24) & 0xff;
750 reg = (reg & 0xf0) >> 4 | (reg & 0x0f) << 4;
751
752 rev = ar5416_reverse_bits(reg, 8);
753 if ((rev & AR_RADIO_SREV_MAJOR) == 0)
754 rev = AR_RAD5133_SREV_MAJOR;
755 return rev;
756}
757
758/*
759 * Replace bits "off" to "off+nbits-1" in column "col" with the specified
760 * value.
761 */
762Static void
763ar5416_rw_rfbits(uint32_t *buf, int col, int off, uint32_t val, int nbits)
764{
765 int idx, bit;
766
767 KASSERT(off >= 1 && col < 4 && nbits <= 32);
768
769 off--; /* Starts at 1. */
770 while (nbits-- > 0) {
771 idx = off / 8;
772 bit = off % 8;
773 buf[idx] &= ~(1 << (bit + col * 8));
774 buf[idx] |= ((val >> nbits) & 1) << (bit + col * 8);
775 off++;
776 }
777}
778
779/*
780 * Overwrite db and ob based on ROM settings.
781 */
782Static void
783ar5416_rw_bank6tpc(struct athn_softc *sc, struct ieee80211_channel *c,
784 uint32_t *rwbank6tpc)
785{
786 const struct ar5416_eeprom *eep = sc->sc_eep;
787 const struct ar5416_modal_eep_header *modal;
788
789 if (IEEE80211_IS_CHAN_5GHZ(c)) {
790 modal = &eep->modalHeader[0];
791 /* 5GHz db in column 0, bits [200-202]. */
792 ar5416_rw_rfbits(rwbank6tpc, 0, 200, modal->db, 3);
793 /* 5GHz ob in column 0, bits [203-205]. */
794 ar5416_rw_rfbits(rwbank6tpc, 0, 203, modal->ob, 3);
795 }
796 else {
797 modal = &eep->modalHeader[1];
798 /* 2GHz db in column 0, bits [194-196]. */
799 ar5416_rw_rfbits(rwbank6tpc, 0, 194, modal->db, 3);
800 /* 2GHz ob in column 0, bits [197-199]. */
801 ar5416_rw_rfbits(rwbank6tpc, 0, 197, modal->ob, 3);
802 }
803}
804
805/*
806 * Program analog RF.
807 */
808PUBLIC void
809ar5416_rf_reset(struct athn_softc *sc, struct ieee80211_channel *c)
810{
811 const uint32_t *bank6tpc;
812 int i;
813
814 /* Bank 0. */
815 AR_WRITE(sc, 0x98b0, 0x1e5795e5);
816 AR_WRITE(sc, 0x98e0, 0x02008020);
817
818 /* Bank 1. */
819 AR_WRITE(sc, 0x98b0, 0x02108421);
820 AR_WRITE(sc, 0x98ec, 0x00000008);
821
822 /* Bank 2. */
823 AR_WRITE(sc, 0x98b0, 0x0e73ff17);
824 AR_WRITE(sc, 0x98e0, 0x00000420);
825
826 /* Bank 3. */
827 if (IEEE80211_IS_CHAN_5GHZ(c))
828 AR_WRITE(sc, 0x98f0, 0x01400018);
829 else
830 AR_WRITE(sc, 0x98f0, 0x01c00018);
831
832 /* Select the Bank 6 TPC values to use. */
833 if (AR_SREV_9160_10_OR_LATER(sc))
834 bank6tpc = ar9160_bank6tpc_vals;
835 else
836 bank6tpc = ar5416_bank6tpc_vals;
837 if (sc->sc_eep_rev >= AR_EEP_MINOR_VER_2) {
838 uint32_t *rwbank6tpc = sc->sc_rwbuf;
839
840 /* Copy values from .rodata to writable buffer. */
841 memcpy(rwbank6tpc, bank6tpc, 32 * sizeof(uint32_t));
842 ar5416_rw_bank6tpc(sc, c, rwbank6tpc);
843 bank6tpc = rwbank6tpc;
844 }
845 /* Bank 6 TPC. */
846 for (i = 0; i < 32; i++)
847 AR_WRITE(sc, 0x989c, bank6tpc[i]);
848 if (IEEE80211_IS_CHAN_5GHZ(c))
849 AR_WRITE(sc, 0x98d0, 0x0000000f);
850 else
851 AR_WRITE(sc, 0x98d0, 0x0010000f);
852
853 /* Bank 7. */
854 AR_WRITE(sc, 0x989c, 0x00000500);
855 AR_WRITE(sc, 0x989c, 0x00000800);
856 AR_WRITE(sc, 0x98cc, 0x0000000e);
857}
858
859PUBLIC void
860ar5416_reset_bb_gain(struct athn_softc *sc, struct ieee80211_channel *c)
861{
862 const uint32_t *pvals;
863 int i;
864
865 if (IEEE80211_IS_CHAN_2GHZ(c))
866 pvals = ar5416_bb_rfgain_vals_2g;
867 else
868 pvals = ar5416_bb_rfgain_vals_5g;
869 for (i = 0; i < 64; i++)
870 AR_WRITE(sc, AR_PHY_BB_RFGAIN(i), pvals[i]);
871}
872
873/*
874 * Fix orientation sensitivity issue on AR5416/2GHz by increasing
875 * rf_pwd_icsyndiv.
876 */
877Static void
878ar5416_force_bias(struct athn_softc *sc, struct ieee80211_channel *c)
879{
880 uint32_t *rwbank6 = sc->sc_rwbuf;
881 uint8_t bias;
882 int i;
883
884 KASSERT(IEEE80211_IS_CHAN_2GHZ(c));
885
886 /* Copy values from .rodata to writable buffer. */
887 memcpy(rwbank6, ar5416_bank6_vals, sizeof(ar5416_bank6_vals));
888
889 if (c->ic_freq < 2412)
890 bias = 0;
891 else if (c->ic_freq < 2422)
892 bias = 1;
893 else
894 bias = 2;
895 ar5416_reverse_bits(bias, 3);
896
897 /* Overwrite "rf_pwd_icsyndiv" (column 3, bits [181-183].) */
898 ar5416_rw_rfbits(rwbank6, 3, 181, bias, 3);
899
900 /* Write Bank 6. */
901 for (i = 0; i < 32; i++)
902 AR_WRITE(sc, 0x989c, rwbank6[i]);
903 AR_WRITE(sc, 0x98d0, 0x0010000f);
904}
905
906/*
907 * Overwrite XPA bias level based on ROM setting.
908 */
909Static void
910ar9160_rw_addac(struct athn_softc *sc, struct ieee80211_channel *c,
911 uint32_t *addac)
912{
913 struct ar5416_eeprom *eep = sc->sc_eep;
914 struct ar5416_modal_eep_header *modal;
915 uint8_t fbin, bias;
916 int i;
917
918 /* XXX xpaBiasLvlFreq values have not been endian-swapped? */
919
920 /* Get the XPA bias level to use for the specified channel. */
921 modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
922 if (modal->xpaBiasLvl == 0xff) {
923 bias = modal->xpaBiasLvlFreq[0] >> 14;
924 fbin = athn_chan2fbin(c);
925 for (i = 1; i < 3; i++) {
926 if (modal->xpaBiasLvlFreq[i] == 0)
927 break;
928 if ((modal->xpaBiasLvlFreq[i] & 0xff) < fbin)
929 break;
930 bias = modal->xpaBiasLvlFreq[i] >> 14;
931 }
932 }
933 else
934 bias = modal->xpaBiasLvl & 0x3;
935
936 bias = ar5416_reverse_bits(bias, 2); /* Put in host bit-order. */
937 DPRINTFN(DBG_RF, sc, "bias level=%d\n", bias);
938 if (IEEE80211_IS_CHAN_2GHZ(c))
939 ar5416_rw_rfbits(addac, 0, 60, bias, 2);
940 else
941 ar5416_rw_rfbits(addac, 0, 55, bias, 2);
942}
943
944PUBLIC void
945ar5416_reset_addac(struct athn_softc *sc, struct ieee80211_channel *c)
946{
947 const struct athn_addac *addac = sc->sc_addac;
948 const uint32_t *pvals;
949 int i;
950
951 if (AR_SREV_9160(sc) && sc->sc_eep_rev >= AR_EEP_MINOR_VER_7) {
952 uint32_t *rwaddac = sc->sc_rwbuf;
953
954 /* Copy values from .rodata to writable buffer. */
955 memcpy(rwaddac, addac->vals, addac->nvals * sizeof(uint32_t));
956 ar9160_rw_addac(sc, c, rwaddac);
957 pvals = rwaddac;
958 }
959 else
960 pvals = addac->vals;
961 for (i = 0; i < addac->nvals; i++)
962 AR_WRITE(sc, 0x989c, pvals[i]);
963 AR_WRITE(sc, 0x98cc, 0); /* Finalize. */
964}
965