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