1 /* $OpenBSD: ar9380.c,v 1.28 2022/01/09 05:42:38 jsg Exp $ */
2
3 /*-
4 * Copyright (c) 2011 Damien Bergamini <damien.bergamini@free.fr>
5 * Copyright (c) 2010 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 AR9380 and AR9485 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/conf.h>
36 #include <sys/device.h>
37 #include <sys/endian.h>
38
39 #include <machine/bus.h>
40
41 #if NBPFILTER > 0
42 #include <net/bpf.h>
43 #endif
44 #include <net/if.h>
45 #include <net/if_media.h>
46
47 #include <netinet/in.h>
48 #include <netinet/if_ether.h>
49
50 #include <net80211/ieee80211_var.h>
51 #include <net80211/ieee80211_amrr.h>
52 #include <net80211/ieee80211_ra.h>
53 #include <net80211/ieee80211_radiotap.h>
54
55 #include <dev/ic/athnreg.h>
56 #include <dev/ic/athnvar.h>
57
58 #include <dev/ic/ar9003reg.h>
59 #include <dev/ic/ar9380reg.h>
60
61 int ar9380_attach(struct athn_softc *);
62 void ar9380_setup(struct athn_softc *);
63 const uint8_t *ar9380_get_rom_template(struct athn_softc *, uint8_t);
64 void ar9380_swap_rom(struct athn_softc *);
65 int ar9380_set_synth(struct athn_softc *, struct ieee80211_channel *,
66 struct ieee80211_channel *);
67 void ar9380_get_paprd_masks(struct athn_softc *, struct ieee80211_channel *,
68 uint32_t *, uint32_t *);
69 void ar9380_init_from_rom(struct athn_softc *, struct ieee80211_channel *,
70 struct ieee80211_channel *);
71 void ar9380_init_swreg(struct athn_softc *);
72 int ar9485_pmu_write(struct athn_softc *, uint32_t, uint32_t);
73 void ar9485_init_swreg(struct athn_softc *);
74 void ar9380_spur_mitigate_cck(struct athn_softc *,
75 struct ieee80211_channel *, struct ieee80211_channel *);
76 void ar9380_spur_mitigate_ofdm(struct athn_softc *,
77 struct ieee80211_channel *, struct ieee80211_channel *);
78 void ar9380_spur_mitigate(struct athn_softc *, struct ieee80211_channel *,
79 struct ieee80211_channel *);
80 void ar9380_set_txpower(struct athn_softc *, struct ieee80211_channel *,
81 struct ieee80211_channel *);
82 void ar9380_get_correction(struct athn_softc *, struct ieee80211_channel *,
83 int, int *, int *);
84 void ar9380_set_correction(struct athn_softc *, struct ieee80211_channel *);
85
86 /* Extern functions. */
87 int athn_interpolate(int, int, int, int, int);
88 uint8_t athn_chan2fbin(struct ieee80211_channel *);
89 void athn_get_pier_ival(uint8_t, const uint8_t *, int, int *, int *);
90 int ar9003_attach(struct athn_softc *);
91 void ar9003_write_txpower(struct athn_softc *, int16_t power[]);
92 void ar9003_get_lg_tpow(struct athn_softc *, struct ieee80211_channel *,
93 uint8_t, const uint8_t *, const struct ar_cal_target_power_leg *,
94 int, uint8_t[]);
95 void ar9003_get_ht_tpow(struct athn_softc *, struct ieee80211_channel *,
96 uint8_t, const uint8_t *, const struct ar_cal_target_power_ht *,
97 int, uint8_t[]);
98
99
100 int
ar9380_attach(struct athn_softc * sc)101 ar9380_attach(struct athn_softc *sc)
102 {
103 sc->ngpiopins = 17;
104 sc->ops.setup = ar9380_setup;
105 sc->ops.get_rom_template = ar9380_get_rom_template;
106 sc->ops.swap_rom = ar9380_swap_rom;
107 sc->ops.init_from_rom = ar9380_init_from_rom;
108 sc->ops.set_txpower = ar9380_set_txpower;
109 sc->ops.set_synth = ar9380_set_synth;
110 sc->ops.spur_mitigate = ar9380_spur_mitigate;
111 sc->ops.get_paprd_masks = ar9380_get_paprd_masks;
112 sc->cca_min_2g = AR9380_PHY_CCA_MIN_GOOD_VAL_2GHZ;
113 sc->cca_max_2g = AR9380_PHY_CCA_MAX_GOOD_VAL_2GHZ;
114 sc->cca_min_5g = AR9380_PHY_CCA_MIN_GOOD_VAL_5GHZ;
115 sc->cca_max_5g = AR9380_PHY_CCA_MAX_GOOD_VAL_5GHZ;
116 if (AR_SREV_9485(sc)) {
117 sc->ini = &ar9485_1_1_ini;
118 sc->serdes = &ar9485_1_1_serdes;
119 } else {
120 sc->ini = &ar9380_2_2_ini;
121 sc->serdes = &ar9380_2_2_serdes;
122 }
123
124 return (ar9003_attach(sc));
125 }
126
127 void
ar9380_setup(struct athn_softc * sc)128 ar9380_setup(struct athn_softc *sc)
129 {
130 struct ieee80211com *ic = &sc->sc_ic;
131 struct ar9380_eeprom *eep = sc->eep;
132 struct ar9380_base_eep_hdr *base = &eep->baseEepHeader;
133 uint8_t type;
134
135 if (base->opFlags & AR_OPFLAGS_11A)
136 sc->flags |= ATHN_FLAG_11A;
137 if (base->opFlags & AR_OPFLAGS_11G)
138 sc->flags |= ATHN_FLAG_11G;
139 if (base->opFlags & AR_OPFLAGS_11N)
140 sc->flags |= ATHN_FLAG_11N;
141
142 IEEE80211_ADDR_COPY(ic->ic_myaddr, eep->macAddr);
143 sc->led_pin = base->wlanLedGpio;
144
145 /* Check if we have a hardware radio switch. */
146 if (base->rfSilent & AR_EEP_RFSILENT_ENABLED) {
147 sc->flags |= ATHN_FLAG_RFSILENT;
148 /* Get GPIO pin used by hardware radio switch. */
149 sc->rfsilent_pin = MS(base->rfSilent,
150 AR_EEP_RFSILENT_GPIO_SEL);
151 /* Get polarity of hardware radio switch. */
152 if (base->rfSilent & AR_EEP_RFSILENT_POLARITY)
153 sc->flags |= ATHN_FLAG_RFSILENT_REVERSED;
154 }
155
156 /* Set the number of HW key cache entries. */
157 sc->kc_entries = AR_KEYTABLE_SIZE;
158
159 sc->txchainmask = MS(base->txrxMask, AR_EEP_TX_MASK);
160 sc->rxchainmask = MS(base->txrxMask, AR_EEP_RX_MASK);
161
162 /* Fast PLL clock is always supported. */
163 sc->flags |= ATHN_FLAG_FAST_PLL_CLOCK;
164
165 /* Enable PA predistortion if supported. */
166 if (base->featureEnable & AR_EEP_PAPRD)
167 sc->flags |= ATHN_FLAG_PAPRD;
168 /*
169 * Some 3-stream chips may exceed the PCIe power requirements,
170 * requiring to reduce the number of Tx chains in some cases.
171 */
172 if ((base->miscConfiguration & AR_EEP_CHAIN_MASK_REDUCE) &&
173 sc->txchainmask == 0x7)
174 sc->flags |= ATHN_FLAG_3TREDUCE_CHAIN;
175
176 /* Select initialization values based on ROM. */
177 type = MS(eep->baseEepHeader.txrxgain, AR_EEP_RX_GAIN);
178 if (!AR_SREV_9485(sc)) {
179 if (type == AR_EEP_RX_GAIN_WO_XLNA)
180 sc->rx_gain = &ar9380_2_2_rx_gain_wo_xlna;
181 else
182 sc->rx_gain = &ar9380_2_2_rx_gain;
183 } else
184 sc->rx_gain = &ar9485_1_1_rx_gain;
185
186 /* Select initialization values based on ROM. */
187 type = MS(eep->baseEepHeader.txrxgain, AR_EEP_TX_GAIN);
188 if (!AR_SREV_9485(sc)) {
189 if (type == AR_EEP_TX_GAIN_HIGH_OB_DB)
190 sc->tx_gain = &ar9380_2_2_tx_gain_high_ob_db;
191 else if (type == AR_EEP_TX_GAIN_LOW_OB_DB)
192 sc->tx_gain = &ar9380_2_2_tx_gain_low_ob_db;
193 else if (type == AR_EEP_TX_GAIN_HIGH_POWER)
194 sc->tx_gain = &ar9380_2_2_tx_gain_high_power;
195 else
196 sc->tx_gain = &ar9380_2_2_tx_gain;
197 } else
198 sc->tx_gain = &ar9485_1_1_tx_gain;
199 }
200
201 const uint8_t *
ar9380_get_rom_template(struct athn_softc * sc,uint8_t ref)202 ar9380_get_rom_template(struct athn_softc *sc, uint8_t ref)
203 {
204 int i;
205
206 /* Retrieve template ROM image for given reference. */
207 for (i = 0; i < nitems(ar9380_rom_templates); i++)
208 if (ar9380_rom_templates[i][1] == ref)
209 return (ar9380_rom_templates[i]);
210 return (NULL);
211 }
212
213 void
ar9380_swap_rom(struct athn_softc * sc)214 ar9380_swap_rom(struct athn_softc *sc)
215 {
216 #if BYTE_ORDER == BIG_ENDIAN
217 struct ar9380_eeprom *eep = sc->eep;
218 struct ar9380_base_eep_hdr *base = &eep->baseEepHeader;
219 struct ar9380_modal_eep_header *modal;
220 int i;
221
222 base->regDmn[0] = swap16(base->regDmn[0]);
223 base->regDmn[1] = swap16(base->regDmn[1]);
224 base->swreg = swap32(base->swreg);
225
226 modal = &eep->modalHeader2G;
227 modal->antCtrlCommon = swap32(modal->antCtrlCommon);
228 modal->antCtrlCommon2 = swap32(modal->antCtrlCommon2);
229 modal->papdRateMaskHt20 = swap32(modal->papdRateMaskHt20);
230 modal->papdRateMaskHt40 = swap32(modal->papdRateMaskHt40);
231 for (i = 0; i < AR9380_MAX_CHAINS; i++)
232 modal->antCtrlChain[i] = swap16(modal->antCtrlChain[i]);
233
234 modal = &eep->modalHeader5G;
235 modal->antCtrlCommon = swap32(modal->antCtrlCommon);
236 modal->antCtrlCommon2 = swap32(modal->antCtrlCommon2);
237 modal->papdRateMaskHt20 = swap32(modal->papdRateMaskHt20);
238 modal->papdRateMaskHt40 = swap32(modal->papdRateMaskHt40);
239 for (i = 0; i < AR9380_MAX_CHAINS; i++)
240 modal->antCtrlChain[i] = swap16(modal->antCtrlChain[i]);
241 #endif
242 }
243
244 void
ar9380_get_paprd_masks(struct athn_softc * sc,struct ieee80211_channel * c,uint32_t * ht20mask,uint32_t * ht40mask)245 ar9380_get_paprd_masks(struct athn_softc *sc, struct ieee80211_channel *c,
246 uint32_t *ht20mask, uint32_t *ht40mask)
247 {
248 const struct ar9380_eeprom *eep = sc->eep;
249 const struct ar9380_modal_eep_header *modal;
250
251 if (IEEE80211_IS_CHAN_2GHZ(c))
252 modal = &eep->modalHeader2G;
253 else
254 modal = &eep->modalHeader5G;
255 *ht20mask = modal->papdRateMaskHt20;
256 *ht40mask = modal->papdRateMaskHt40;
257 }
258
259 int
ar9380_set_synth(struct athn_softc * sc,struct ieee80211_channel * c,struct ieee80211_channel * extc)260 ar9380_set_synth(struct athn_softc *sc, struct ieee80211_channel *c,
261 struct ieee80211_channel *extc)
262 {
263 uint32_t freq = c->ic_freq;
264 uint32_t chansel, phy;
265
266 if (IEEE80211_IS_CHAN_2GHZ(c)) {
267 if (AR_SREV_9485(sc))
268 chansel = ((freq << 16) - 215) / 15;
269 else
270 chansel = (freq << 16) / 15;
271 AR_WRITE(sc, AR_PHY_SYNTH_CONTROL, AR9380_BMODE);
272 } else {
273 chansel = (freq << 15) / 15;
274 chansel >>= 1;
275 AR_WRITE(sc, AR_PHY_SYNTH_CONTROL, 0);
276 }
277
278 /* Enable Long Shift Select for synthesizer. */
279 AR_SETBITS(sc, AR_PHY_65NM_CH0_SYNTH4,
280 AR_PHY_SYNTH4_LONG_SHIFT_SELECT);
281 AR_WRITE_BARRIER(sc);
282
283 /* Program synthesizer. */
284 phy = (chansel << 2) | AR9380_FRACMODE;
285 DPRINTFN(4, ("AR_PHY_65NM_CH0_SYNTH7=0x%08x\n", phy));
286 AR_WRITE(sc, AR_PHY_65NM_CH0_SYNTH7, phy);
287 AR_WRITE_BARRIER(sc);
288 /* Toggle Load Synth Channel bit. */
289 AR_WRITE(sc, AR_PHY_65NM_CH0_SYNTH7, phy | AR9380_LOAD_SYNTH);
290 AR_WRITE_BARRIER(sc);
291 return (0);
292 }
293
294 void
ar9380_init_from_rom(struct athn_softc * sc,struct ieee80211_channel * c,struct ieee80211_channel * extc)295 ar9380_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c,
296 struct ieee80211_channel *extc)
297 {
298 const struct ar9380_eeprom *eep = sc->eep;
299 const struct ar9380_modal_eep_header *modal;
300 uint8_t db, margin, ant_div_ctrl;
301 uint32_t reg;
302 int i, maxchains;
303
304 if (IEEE80211_IS_CHAN_2GHZ(c))
305 modal = &eep->modalHeader2G;
306 else
307 modal = &eep->modalHeader5G;
308
309 /* Apply XPA bias level. */
310 if (AR_SREV_9485(sc)) {
311 reg = AR_READ(sc, AR9485_PHY_65NM_CH0_TOP2);
312 reg = RW(reg, AR9485_PHY_65NM_CH0_TOP2_XPABIASLVL,
313 modal->xpaBiasLvl);
314 AR_WRITE(sc, AR9485_PHY_65NM_CH0_TOP2, reg);
315 } else {
316 reg = AR_READ(sc, AR_PHY_65NM_CH0_TOP);
317 reg = RW(reg, AR_PHY_65NM_CH0_TOP_XPABIASLVL,
318 modal->xpaBiasLvl & 0x3);
319 AR_WRITE(sc, AR_PHY_65NM_CH0_TOP, reg);
320 reg = AR_READ(sc, AR_PHY_65NM_CH0_THERM);
321 reg = RW(reg, AR_PHY_65NM_CH0_THERM_XPABIASLVL_MSB,
322 modal->xpaBiasLvl >> 2);
323 reg |= AR_PHY_65NM_CH0_THERM_XPASHORT2GND;
324 AR_WRITE(sc, AR_PHY_65NM_CH0_THERM, reg);
325 }
326
327 /* Apply antenna control. */
328 reg = AR_READ(sc, AR_PHY_SWITCH_COM);
329 reg = RW(reg, AR_SWITCH_TABLE_COM_ALL, modal->antCtrlCommon);
330 AR_WRITE(sc, AR_PHY_SWITCH_COM, reg);
331 reg = AR_READ(sc, AR_PHY_SWITCH_COM_2);
332 reg = RW(reg, AR_SWITCH_TABLE_COM_2_ALL, modal->antCtrlCommon2);
333 AR_WRITE(sc, AR_PHY_SWITCH_COM_2, reg);
334
335 maxchains = AR_SREV_9485(sc) ? 1 : AR9380_MAX_CHAINS;
336 for (i = 0; i < maxchains; i++) {
337 reg = AR_READ(sc, AR_PHY_SWITCH_CHAIN(i));
338 reg = RW(reg, AR_SWITCH_TABLE_ALL, modal->antCtrlChain[i]);
339 AR_WRITE(sc, AR_PHY_SWITCH_CHAIN(i), reg);
340 }
341
342 if (AR_SREV_9485(sc)) {
343 ant_div_ctrl = eep->base_ext1.ant_div_control;
344 reg = AR_READ(sc, AR_PHY_MC_GAIN_CTRL);
345 reg = RW(reg, AR_PHY_MC_GAIN_CTRL_ANT_DIV_CTRL_ALL,
346 MS(ant_div_ctrl, AR_EEP_ANT_DIV_CTRL_ALL));
347 if (ant_div_ctrl & AR_EEP_ANT_DIV_CTRL_ANT_DIV)
348 reg |= AR_PHY_MC_GAIN_CTRL_ENABLE_ANT_DIV;
349 else
350 reg &= ~AR_PHY_MC_GAIN_CTRL_ENABLE_ANT_DIV;
351 AR_WRITE(sc, AR_PHY_MC_GAIN_CTRL, reg);
352 reg = AR_READ(sc, AR_PHY_CCK_DETECT);
353 if (ant_div_ctrl & AR_EEP_ANT_DIV_CTRL_FAST_DIV)
354 reg |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
355 else
356 reg &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
357 AR_WRITE(sc, AR_PHY_CCK_DETECT, reg);
358 }
359
360 if (eep->baseEepHeader.miscConfiguration & AR_EEP_DRIVE_STRENGTH) {
361 /* Apply drive strength. */
362 reg = AR_READ(sc, AR_PHY_65NM_CH0_BIAS1);
363 reg = RW(reg, AR_PHY_65NM_CH0_BIAS1_0, 5);
364 reg = RW(reg, AR_PHY_65NM_CH0_BIAS1_1, 5);
365 reg = RW(reg, AR_PHY_65NM_CH0_BIAS1_2, 5);
366 reg = RW(reg, AR_PHY_65NM_CH0_BIAS1_3, 5);
367 reg = RW(reg, AR_PHY_65NM_CH0_BIAS1_4, 5);
368 reg = RW(reg, AR_PHY_65NM_CH0_BIAS1_5, 5);
369 AR_WRITE(sc, AR_PHY_65NM_CH0_BIAS1, reg);
370
371 reg = AR_READ(sc, AR_PHY_65NM_CH0_BIAS2);
372 reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_0, 5);
373 reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_1, 5);
374 reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_2, 5);
375 reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_3, 5);
376 reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_4, 5);
377 reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_5, 5);
378 reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_6, 5);
379 reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_7, 5);
380 reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_8, 5);
381 AR_WRITE(sc, AR_PHY_65NM_CH0_BIAS2, reg);
382
383 reg = AR_READ(sc, AR_PHY_65NM_CH0_BIAS4);
384 reg = RW(reg, AR_PHY_65NM_CH0_BIAS4_0, 5);
385 reg = RW(reg, AR_PHY_65NM_CH0_BIAS4_1, 5);
386 reg = RW(reg, AR_PHY_65NM_CH0_BIAS4_2, 5);
387 AR_WRITE(sc, AR_PHY_65NM_CH0_BIAS4, reg);
388 }
389
390 /* Apply attenuation settings. */
391 maxchains = AR_SREV_9485(sc) ? 1 : AR9380_MAX_CHAINS;
392 for (i = 0; i < maxchains; i++) {
393 if (IEEE80211_IS_CHAN_5GHZ(c) &&
394 eep->base_ext2.xatten1DBLow[i] != 0) {
395 if (c->ic_freq <= 5500) {
396 db = athn_interpolate(c->ic_freq,
397 5180, eep->base_ext2.xatten1DBLow[i],
398 5500, modal->xatten1DB[i]);
399 } else {
400 db = athn_interpolate(c->ic_freq,
401 5500, modal->xatten1DB[i],
402 5785, eep->base_ext2.xatten1DBHigh[i]);
403 }
404 } else
405 db = modal->xatten1DB[i];
406 if (IEEE80211_IS_CHAN_5GHZ(c) &&
407 eep->base_ext2.xatten1MarginLow[i] != 0) {
408 if (c->ic_freq <= 5500) {
409 margin = athn_interpolate(c->ic_freq,
410 5180, eep->base_ext2.xatten1MarginLow[i],
411 5500, modal->xatten1Margin[i]);
412 } else {
413 margin = athn_interpolate(c->ic_freq,
414 5500, modal->xatten1Margin[i],
415 5785, eep->base_ext2.xatten1MarginHigh[i]);
416 }
417 } else
418 margin = modal->xatten1Margin[i];
419 reg = AR_READ(sc, AR_PHY_EXT_ATTEN_CTL(i));
420 reg = RW(reg, AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, db);
421 reg = RW(reg, AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, margin);
422 AR_WRITE(sc, AR_PHY_EXT_ATTEN_CTL(i), reg);
423 }
424
425 /* Initialize switching regulator. */
426 if (AR_SREV_9485(sc))
427 ar9485_init_swreg(sc);
428 else
429 ar9380_init_swreg(sc);
430
431 /* Apply tuning capabilities. */
432 if (AR_SREV_9485(sc) &&
433 (eep->baseEepHeader.featureEnable & AR_EEP_TUNING_CAPS)) {
434 reg = AR_READ(sc, AR9485_PHY_CH0_XTAL);
435 reg = RW(reg, AR9485_PHY_CH0_XTAL_CAPINDAC,
436 eep->baseEepHeader.params_for_tuning_caps[0]);
437 reg = RW(reg, AR9485_PHY_CH0_XTAL_CAPOUTDAC,
438 eep->baseEepHeader.params_for_tuning_caps[0]);
439 AR_WRITE(sc, AR9485_PHY_CH0_XTAL, reg);
440 }
441 AR_WRITE_BARRIER(sc);
442 }
443
444 void
ar9380_init_swreg(struct athn_softc * sc)445 ar9380_init_swreg(struct athn_softc *sc)
446 {
447 const struct ar9380_eeprom *eep = sc->eep;
448
449 if (eep->baseEepHeader.featureEnable & AR_EEP_INTERNAL_REGULATOR) {
450 /* Internal regulator is ON. */
451 AR_CLRBITS(sc, AR_RTC_REG_CONTROL1,
452 AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
453 AR_WRITE(sc, AR_RTC_REG_CONTROL0, eep->baseEepHeader.swreg);
454 AR_SETBITS(sc, AR_RTC_REG_CONTROL1,
455 AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
456 } else
457 AR_SETBITS(sc, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_SWREG_PRD);
458 AR_WRITE_BARRIER(sc);
459 }
460
461 int
ar9485_pmu_write(struct athn_softc * sc,uint32_t addr,uint32_t val)462 ar9485_pmu_write(struct athn_softc *sc, uint32_t addr, uint32_t val)
463 {
464 int ntries;
465
466 AR_WRITE(sc, addr, val);
467 /* Wait for write to complete. */
468 for (ntries = 0; ntries < 100; ntries++) {
469 if (AR_READ(sc, addr) == val)
470 return (0);
471 AR_WRITE(sc, addr, val); /* Insist. */
472 AR_WRITE_BARRIER(sc);
473 DELAY(10);
474 }
475 return (ETIMEDOUT);
476 }
477
478 #define ar9486_pmu_read AR_READ
479
480 void
ar9485_init_swreg(struct athn_softc * sc)481 ar9485_init_swreg(struct athn_softc *sc)
482 {
483 const struct ar9380_eeprom *eep = sc->eep;
484 uint32_t reg;
485
486 ar9485_pmu_write(sc, AR_PHY_PMU2,
487 ar9486_pmu_read(sc, AR_PHY_PMU2) & ~AR_PHY_PMU2_PGM);
488
489 if (eep->baseEepHeader.featureEnable & AR_EEP_INTERNAL_REGULATOR) {
490 ar9485_pmu_write(sc, AR_PHY_PMU1, 0x131dc17a);
491
492 reg = ar9486_pmu_read(sc, AR_PHY_PMU2);
493 reg = (reg & ~0xffc00000) | 0x10000000;
494 ar9485_pmu_write(sc, AR_PHY_PMU2, reg);
495 } else {
496 ar9485_pmu_write(sc, AR_PHY_PMU1,
497 ar9486_pmu_read(sc, AR_PHY_PMU1) | AR_PHY_PMU1_PWD);
498 }
499
500 ar9485_pmu_write(sc, AR_PHY_PMU2,
501 ar9486_pmu_read(sc, AR_PHY_PMU2) | AR_PHY_PMU2_PGM);
502 }
503
504 void
ar9380_spur_mitigate_cck(struct athn_softc * sc,struct ieee80211_channel * c,struct ieee80211_channel * extc)505 ar9380_spur_mitigate_cck(struct athn_softc *sc, struct ieee80211_channel *c,
506 struct ieee80211_channel *extc)
507 {
508 /* NB: It is safe to call this function for 5GHz channels. */
509 static const int16_t freqs[] = { 2420, 2440, 2464, 2480 };
510 int i, spur, freq;
511 uint32_t reg;
512
513 for (i = 0; i < nitems(freqs); i++) {
514 spur = freqs[i] - c->ic_freq;
515 if (abs(spur) < 10) /* +/- 10MHz range. */
516 break;
517 }
518 if (i == nitems(freqs)) {
519 /* Disable CCK spur mitigation. */
520 reg = AR_READ(sc, AR_PHY_AGC_CONTROL);
521 reg = RW(reg, AR_PHY_AGC_CONTROL_YCOK_MAX, 0x5);
522 AR_WRITE(sc, AR_PHY_AGC_CONTROL, reg);
523 reg = AR_READ(sc, AR_PHY_CCK_SPUR_MIT);
524 reg = RW(reg, AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ, 0);
525 reg &= ~AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT;
526 AR_WRITE(sc, AR_PHY_CCK_SPUR_MIT, reg);
527 AR_WRITE_BARRIER(sc);
528 return;
529 }
530 freq = (spur * 524288) / 11;
531
532 reg = AR_READ(sc, AR_PHY_AGC_CONTROL);
533 reg = RW(reg, AR_PHY_AGC_CONTROL_YCOK_MAX, 0x7);
534 AR_WRITE(sc, AR_PHY_AGC_CONTROL, reg);
535
536 reg = AR_READ(sc, AR_PHY_CCK_SPUR_MIT);
537 reg = RW(reg, AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ, freq);
538 reg = RW(reg, AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR, 0x7f);
539 reg = RW(reg, AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE, 0x2);
540 reg |= AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT;
541 AR_WRITE(sc, AR_PHY_CCK_SPUR_MIT, reg);
542 AR_WRITE_BARRIER(sc);
543 }
544
545 void
ar9380_spur_mitigate_ofdm(struct athn_softc * sc,struct ieee80211_channel * c,struct ieee80211_channel * extc)546 ar9380_spur_mitigate_ofdm(struct athn_softc *sc, struct ieee80211_channel *c,
547 struct ieee80211_channel *extc)
548 {
549 const struct ar9380_eeprom *eep = sc->eep;
550 const uint8_t *spurchans;
551 uint32_t reg;
552 int idx, spur_delta_phase, spur_off, range, i;
553 int freq, spur, spur_freq_sd, spur_subchannel_sd;
554
555 if (IEEE80211_IS_CHAN_2GHZ(c))
556 spurchans = eep->modalHeader2G.spurChans;
557 else
558 spurchans = eep->modalHeader5G.spurChans;
559 if (spurchans[0] == 0)
560 return;
561
562 /* Disable OFDM spur mitigation. */
563 AR_CLRBITS(sc, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_SPUR_FILTER);
564
565 reg = AR_READ(sc, AR_PHY_TIMING11);
566 reg = RW(reg, AR_PHY_TIMING11_SPUR_FREQ_SD, 0);
567 reg = RW(reg, AR_PHY_TIMING11_SPUR_DELTA_PHASE, 0);
568 reg &= ~AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC;
569 reg &= ~AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR;
570 AR_WRITE(sc, AR_PHY_TIMING11, reg);
571
572 AR_CLRBITS(sc, AR_PHY_SFCORR_EXT,
573 AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD);
574
575 AR_CLRBITS(sc, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_SPUR_RSSI);
576
577 reg = AR_READ(sc, AR_PHY_SPUR_REG);
578 reg = RW(reg, AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0);
579 reg &= ~AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI;
580 reg &= ~AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT;
581 reg &= ~AR_PHY_SPUR_REG_ENABLE_MASK_PPM;
582 AR_WRITE(sc, AR_PHY_SPUR_REG, reg);
583 AR_WRITE_BARRIER(sc);
584
585 freq = c->ic_freq;
586 if (extc != NULL) {
587 range = 19; /* +/- 19MHz range. */
588 if (AR_READ(sc, AR_PHY_GEN_CTRL) & AR_PHY_GC_DYN2040_PRI_CH)
589 freq += 10;
590 else
591 freq -= 10;
592 } else
593 range = 10; /* +/- 10MHz range. */
594 for (i = 0; i < AR9380_EEPROM_MODAL_SPURS; i++) {
595 spur = spurchans[i];
596 if (spur == 0)
597 return;
598 /* Convert to frequency. */
599 if (IEEE80211_IS_CHAN_2GHZ(c))
600 spur = 2300 + spur;
601 else
602 spur = 4900 + (spur * 5);
603 spur -= freq;
604 if (abs(spur) < range)
605 break;
606 }
607 if (i == AR9380_EEPROM_MODAL_SPURS)
608 return;
609
610 /* Enable OFDM spur mitigation. */
611 if (extc != NULL) {
612 spur_delta_phase = (spur * 131072) / 5;
613 reg = AR_READ(sc, AR_PHY_GEN_CTRL);
614 if (spur < 0) {
615 spur_subchannel_sd =
616 (reg & AR_PHY_GC_DYN2040_PRI_CH) == 0;
617 spur_off = spur + 10;
618 } else {
619 spur_subchannel_sd =
620 (reg & AR_PHY_GC_DYN2040_PRI_CH) != 0;
621 spur_off = spur - 10;
622 }
623 } else {
624 spur_delta_phase = (spur * 262144) / 5;
625 spur_subchannel_sd = 0;
626 spur_off = spur;
627 }
628 spur_freq_sd = (spur_off * 512) / 11;
629
630 AR_SETBITS(sc, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_SPUR_FILTER);
631
632 reg = AR_READ(sc, AR_PHY_TIMING11);
633 reg = RW(reg, AR_PHY_TIMING11_SPUR_FREQ_SD, spur_freq_sd);
634 reg = RW(reg, AR_PHY_TIMING11_SPUR_DELTA_PHASE, spur_delta_phase);
635 reg |= AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC;
636 reg |= AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR;
637 AR_WRITE(sc, AR_PHY_TIMING11, reg);
638
639 reg = AR_READ(sc, AR_PHY_SFCORR_EXT);
640 if (spur_subchannel_sd)
641 reg |= AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD;
642 else
643 reg &= ~AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD;
644 AR_WRITE(sc, AR_PHY_SFCORR_EXT, reg);
645
646 AR_SETBITS(sc, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_SPUR_RSSI);
647
648 reg = AR_READ(sc, AR_PHY_SPUR_REG);
649 reg = RW(reg, AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0xff);
650 reg = RW(reg, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH, 34);
651 reg |= AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI;
652 if (AR_READ(sc, AR_PHY_MODE) & AR_PHY_MODE_DYNAMIC)
653 reg |= AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT;
654 reg |= AR_PHY_SPUR_REG_ENABLE_MASK_PPM;
655 AR_WRITE(sc, AR_PHY_SPUR_REG, reg);
656
657 idx = (spur * 16) / 5;
658 if (idx < 0)
659 idx--;
660
661 /* Write pilot mask. */
662 AR_SETBITS(sc, AR_PHY_TIMING4,
663 AR_PHY_TIMING4_ENABLE_PILOT_MASK |
664 AR_PHY_TIMING4_ENABLE_CHAN_MASK);
665
666 reg = AR_READ(sc, AR_PHY_PILOT_SPUR_MASK);
667 reg = RW(reg, AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A, idx);
668 reg = RW(reg, AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A, 0x0c);
669 AR_WRITE(sc, AR_PHY_PILOT_SPUR_MASK, reg);
670
671 reg = AR_READ(sc, AR_PHY_SPUR_MASK_A);
672 reg = RW(reg, AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A, idx);
673 reg = RW(reg, AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A, 0xa0);
674 AR_WRITE(sc, AR_PHY_SPUR_MASK_A, reg);
675
676 reg = AR_READ(sc, AR_PHY_CHAN_SPUR_MASK);
677 reg = RW(reg, AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A, idx);
678 reg = RW(reg, AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A, 0x0c);
679 AR_WRITE(sc, AR_PHY_CHAN_SPUR_MASK, reg);
680 AR_WRITE_BARRIER(sc);
681 }
682
683 void
ar9380_spur_mitigate(struct athn_softc * sc,struct ieee80211_channel * c,struct ieee80211_channel * extc)684 ar9380_spur_mitigate(struct athn_softc *sc, struct ieee80211_channel *c,
685 struct ieee80211_channel *extc)
686 {
687 /* NB: We call spur_mitigate_cck for 5GHz too, just to disable it. */
688 ar9380_spur_mitigate_cck(sc, c, extc);
689 ar9380_spur_mitigate_ofdm(sc, c, extc);
690 }
691
692 void
ar9380_set_txpower(struct athn_softc * sc,struct ieee80211_channel * c,struct ieee80211_channel * extc)693 ar9380_set_txpower(struct athn_softc *sc, struct ieee80211_channel *c,
694 struct ieee80211_channel *extc)
695 {
696 const struct ar9380_eeprom *eep = sc->eep;
697 uint8_t tpow_cck[4], tpow_ofdm[4];
698 uint8_t tpow_ht20[14], tpow_ht40[14];
699 int16_t power[ATHN_POWER_COUNT];
700
701 if (IEEE80211_IS_CHAN_2GHZ(c)) {
702 /* Get CCK target powers. */
703 ar9003_get_lg_tpow(sc, c, AR_CTL_11B,
704 eep->calTargetFbinCck, eep->calTargetPowerCck,
705 AR9380_NUM_2G_CCK_TARGET_POWERS, tpow_cck);
706
707 /* Get OFDM target powers. */
708 ar9003_get_lg_tpow(sc, c, AR_CTL_11G,
709 eep->calTargetFbin2G, eep->calTargetPower2G,
710 AR9380_NUM_2G_20_TARGET_POWERS, tpow_ofdm);
711
712 /* Get HT-20 target powers. */
713 ar9003_get_ht_tpow(sc, c, AR_CTL_2GHT20,
714 eep->calTargetFbin2GHT20, eep->calTargetPower2GHT20,
715 AR9380_NUM_2G_20_TARGET_POWERS, tpow_ht20);
716
717 if (extc != NULL) {
718 /* Get HT-40 target powers. */
719 ar9003_get_ht_tpow(sc, c, AR_CTL_2GHT40,
720 eep->calTargetFbin2GHT40,
721 eep->calTargetPower2GHT40,
722 AR9380_NUM_2G_40_TARGET_POWERS, tpow_ht40);
723 }
724 } else {
725 /* Get OFDM target powers. */
726 ar9003_get_lg_tpow(sc, c, AR_CTL_11A,
727 eep->calTargetFbin5G, eep->calTargetPower5G,
728 AR9380_NUM_5G_20_TARGET_POWERS, tpow_ofdm);
729
730 /* Get HT-20 target powers. */
731 ar9003_get_ht_tpow(sc, c, AR_CTL_5GHT20,
732 eep->calTargetFbin5GHT20, eep->calTargetPower5GHT20,
733 AR9380_NUM_5G_20_TARGET_POWERS, tpow_ht20);
734
735 if (extc != NULL) {
736 /* Get HT-40 target powers. */
737 ar9003_get_ht_tpow(sc, c, AR_CTL_5GHT40,
738 eep->calTargetFbin5GHT40,
739 eep->calTargetPower5GHT40,
740 AR9380_NUM_5G_40_TARGET_POWERS, tpow_ht40);
741 }
742 }
743
744 memset(power, 0, sizeof(power));
745 /* Shuffle target powers across transmit rates. */
746 power[ATHN_POWER_OFDM6 ] =
747 power[ATHN_POWER_OFDM9 ] =
748 power[ATHN_POWER_OFDM12] =
749 power[ATHN_POWER_OFDM18] =
750 power[ATHN_POWER_OFDM24] = tpow_ofdm[0];
751 power[ATHN_POWER_OFDM36] = tpow_ofdm[1];
752 power[ATHN_POWER_OFDM48] = tpow_ofdm[2];
753 power[ATHN_POWER_OFDM54] = tpow_ofdm[3];
754 if (IEEE80211_IS_CHAN_2GHZ(c)) {
755 power[ATHN_POWER_CCK1_LP ] =
756 power[ATHN_POWER_CCK2_LP ] =
757 power[ATHN_POWER_CCK2_SP ] =
758 power[ATHN_POWER_CCK55_LP] = tpow_cck[0];
759 power[ATHN_POWER_CCK55_SP] = tpow_cck[1];
760 power[ATHN_POWER_CCK11_LP] = tpow_cck[2];
761 power[ATHN_POWER_CCK11_SP] = tpow_cck[3];
762 }
763 /* Next entry covers MCS0, MCS8 and MCS16. */
764 power[ATHN_POWER_HT20( 0)] = tpow_ht20[ 0];
765 /* Next entry covers MCS1-3, MCS9-11 and MCS17-19. */
766 power[ATHN_POWER_HT20( 1)] = tpow_ht20[ 1];
767 power[ATHN_POWER_HT20( 4)] = tpow_ht20[ 2];
768 power[ATHN_POWER_HT20( 5)] = tpow_ht20[ 3];
769 power[ATHN_POWER_HT20( 6)] = tpow_ht20[ 4];
770 power[ATHN_POWER_HT20( 7)] = tpow_ht20[ 5];
771 power[ATHN_POWER_HT20(12)] = tpow_ht20[ 6];
772 power[ATHN_POWER_HT20(13)] = tpow_ht20[ 7];
773 power[ATHN_POWER_HT20(14)] = tpow_ht20[ 8];
774 power[ATHN_POWER_HT20(15)] = tpow_ht20[ 9];
775 power[ATHN_POWER_HT20(20)] = tpow_ht20[10];
776 power[ATHN_POWER_HT20(21)] = tpow_ht20[11];
777 power[ATHN_POWER_HT20(22)] = tpow_ht20[12];
778 power[ATHN_POWER_HT20(23)] = tpow_ht20[13];
779 if (extc != NULL) {
780 /* Next entry covers MCS0, MCS8 and MCS16. */
781 power[ATHN_POWER_HT40( 0)] = tpow_ht40[ 0];
782 /* Next entry covers MCS1-3, MCS9-11 and MCS17-19. */
783 power[ATHN_POWER_HT40( 1)] = tpow_ht40[ 1];
784 power[ATHN_POWER_HT40( 4)] = tpow_ht40[ 2];
785 power[ATHN_POWER_HT40( 5)] = tpow_ht40[ 3];
786 power[ATHN_POWER_HT40( 6)] = tpow_ht40[ 4];
787 power[ATHN_POWER_HT40( 7)] = tpow_ht40[ 5];
788 power[ATHN_POWER_HT40(12)] = tpow_ht40[ 6];
789 power[ATHN_POWER_HT40(13)] = tpow_ht40[ 7];
790 power[ATHN_POWER_HT40(14)] = tpow_ht40[ 8];
791 power[ATHN_POWER_HT40(15)] = tpow_ht40[ 9];
792 power[ATHN_POWER_HT40(20)] = tpow_ht40[10];
793 power[ATHN_POWER_HT40(21)] = tpow_ht40[11];
794 power[ATHN_POWER_HT40(22)] = tpow_ht40[12];
795 power[ATHN_POWER_HT40(23)] = tpow_ht40[13];
796 }
797
798 /* Write transmit power values to hardware. */
799 ar9003_write_txpower(sc, power);
800
801 /* Apply transmit power correction. */
802 ar9380_set_correction(sc, c);
803 }
804
805 void
ar9380_get_correction(struct athn_softc * sc,struct ieee80211_channel * c,int chain,int * corr,int * temp)806 ar9380_get_correction(struct athn_softc *sc, struct ieee80211_channel *c,
807 int chain, int *corr, int *temp)
808 {
809 const struct ar9380_eeprom *eep = sc->eep;
810 const struct ar9380_cal_data_per_freq_op_loop *pierdata;
811 const uint8_t *pierfreq;
812 uint8_t fbin;
813 int lo, hi, npiers;
814
815 if (IEEE80211_IS_CHAN_2GHZ(c)) {
816 pierfreq = eep->calFreqPier2G;
817 pierdata = eep->calPierData2G[chain];
818 npiers = AR9380_NUM_2G_CAL_PIERS;
819 } else {
820 pierfreq = eep->calFreqPier5G;
821 pierdata = eep->calPierData5G[chain];
822 npiers = AR9380_NUM_5G_CAL_PIERS;
823 }
824 /* Find channel in ROM pier table. */
825 fbin = athn_chan2fbin(c);
826 athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi);
827
828 *corr = athn_interpolate(fbin,
829 pierfreq[lo], pierdata[lo].refPower,
830 pierfreq[hi], pierdata[hi].refPower);
831 *temp = athn_interpolate(fbin,
832 pierfreq[lo], pierdata[lo].tempMeas,
833 pierfreq[hi], pierdata[hi].tempMeas);
834 }
835
836 void
ar9380_set_correction(struct athn_softc * sc,struct ieee80211_channel * c)837 ar9380_set_correction(struct athn_softc *sc, struct ieee80211_channel *c)
838 {
839 const struct ar9380_eeprom *eep = sc->eep;
840 const struct ar9380_modal_eep_header *modal;
841 uint32_t reg;
842 int8_t slope;
843 int i, corr, temp, temp0;
844
845 if (IEEE80211_IS_CHAN_2GHZ(c))
846 modal = &eep->modalHeader2G;
847 else
848 modal = &eep->modalHeader5G;
849
850 for (i = 0; i < AR9380_MAX_CHAINS; i++) {
851 ar9380_get_correction(sc, c, i, &corr, &temp);
852 if (i == 0)
853 temp0 = temp;
854
855 reg = AR_READ(sc, AR_PHY_TPC_11_B(i));
856 reg = RW(reg, AR_PHY_TPC_11_OLPC_GAIN_DELTA, corr);
857 AR_WRITE(sc, AR_PHY_TPC_11_B(i), reg);
858
859 /* Enable open loop power control. */
860 reg = AR_READ(sc, AR_PHY_TPC_6_B(i));
861 reg = RW(reg, AR_PHY_TPC_6_ERROR_EST_MODE, 3);
862 AR_WRITE(sc, AR_PHY_TPC_6_B(i), reg);
863 }
864
865 /* Enable temperature compensation. */
866 if (IEEE80211_IS_CHAN_5GHZ(c) &&
867 eep->base_ext2.tempSlopeLow != 0) {
868 if (c->ic_freq <= 5500) {
869 slope = athn_interpolate(c->ic_freq,
870 5180, eep->base_ext2.tempSlopeLow,
871 5500, modal->tempSlope);
872 } else {
873 slope = athn_interpolate(c->ic_freq,
874 5500, modal->tempSlope,
875 5785, eep->base_ext2.tempSlopeHigh);
876 }
877 } else
878 slope = modal->tempSlope;
879
880 reg = AR_READ(sc, AR_PHY_TPC_19);
881 reg = RW(reg, AR_PHY_TPC_19_ALPHA_THERM, slope);
882 AR_WRITE(sc, AR_PHY_TPC_19, reg);
883
884 reg = AR_READ(sc, AR_PHY_TPC_18);
885 reg = RW(reg, AR_PHY_TPC_18_THERM_CAL, temp0);
886 AR_WRITE(sc, AR_PHY_TPC_18, reg);
887 AR_WRITE_BARRIER(sc);
888 }
889