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