| File: | dev/ic/ar9285.c |
| Warning: | line 810, column 2 Value stored to 'max_ant_gain' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: ar9285.c,v 1.30 2022/01/09 05:42:38 jsg Exp $ */ |
| 2 | |
| 3 | /*- |
| 4 | * Copyright (c) 2009-2010 Damien Bergamini <damien.bergamini@free.fr> |
| 5 | * Copyright (c) 2008-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 AR9285 and AR9271 chipsets. |
| 23 | */ |
| 24 | |
| 25 | #include "athn_usb.h" |
| 26 | #include "bpfilter.h" |
| 27 | |
| 28 | #include <sys/param.h> |
| 29 | #include <sys/sockio.h> |
| 30 | #include <sys/mbuf.h> |
| 31 | #include <sys/kernel.h> |
| 32 | #include <sys/socket.h> |
| 33 | #include <sys/systm.h> |
| 34 | #include <sys/malloc.h> |
| 35 | #include <sys/queue.h> |
| 36 | #include <sys/timeout.h> |
| 37 | #include <sys/conf.h> |
| 38 | #include <sys/device.h> |
| 39 | #include <sys/endian.h> |
| 40 | |
| 41 | #include <machine/bus.h> |
| 42 | #include <machine/intr.h> |
| 43 | |
| 44 | #if NBPFILTER1 > 0 |
| 45 | #include <net/bpf.h> |
| 46 | #endif |
| 47 | #include <net/if.h> |
| 48 | #include <net/if_media.h> |
| 49 | |
| 50 | #include <netinet/in.h> |
| 51 | #include <netinet/if_ether.h> |
| 52 | |
| 53 | #include <net80211/ieee80211_var.h> |
| 54 | #include <net80211/ieee80211_amrr.h> |
| 55 | #include <net80211/ieee80211_ra.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/ar5008reg.h> |
| 62 | #include <dev/ic/ar9280reg.h> |
| 63 | #include <dev/ic/ar9285reg.h> |
| 64 | |
| 65 | int ar9285_attach(struct athn_softc *); |
| 66 | void ar9285_setup(struct athn_softc *); |
| 67 | void ar9285_swap_rom(struct athn_softc *); |
| 68 | const struct ar_spur_chan *ar9285_get_spur_chans(struct athn_softc *, int); |
| 69 | void ar9285_init_from_rom(struct athn_softc *, struct ieee80211_channel *, |
| 70 | struct ieee80211_channel *); |
| 71 | void ar9285_pa_calib(struct athn_softc *); |
| 72 | void ar9271_pa_calib(struct athn_softc *); |
| 73 | int ar9285_cl_cal(struct athn_softc *, struct ieee80211_channel *, |
| 74 | struct ieee80211_channel *); |
| 75 | void ar9271_load_ani(struct athn_softc *); |
| 76 | int ar9285_init_calib(struct athn_softc *, struct ieee80211_channel *, |
| 77 | struct ieee80211_channel *); |
| 78 | void ar9285_get_pdadcs(struct athn_softc *, struct ieee80211_channel *, |
| 79 | int, uint8_t, uint8_t *, uint8_t *); |
| 80 | void ar9285_set_power_calib(struct athn_softc *, |
| 81 | struct ieee80211_channel *); |
| 82 | void ar9285_set_txpower(struct athn_softc *, struct ieee80211_channel *, |
| 83 | struct ieee80211_channel *); |
| 84 | |
| 85 | /* Extern functions. */ |
| 86 | uint8_t athn_chan2fbin(struct ieee80211_channel *); |
| 87 | void athn_get_pier_ival(uint8_t, const uint8_t *, int, int *, int *); |
| 88 | int ar5008_attach(struct athn_softc *); |
| 89 | void ar5008_write_txpower(struct athn_softc *, int16_t power[]); |
| 90 | void ar5008_get_pdadcs(struct athn_softc *, uint8_t, struct athn_pier *, |
| 91 | struct athn_pier *, int, int, uint8_t, uint8_t *, uint8_t *); |
| 92 | void ar5008_get_lg_tpow(struct athn_softc *, struct ieee80211_channel *, |
| 93 | uint8_t, const struct ar_cal_target_power_leg *, int, uint8_t[]); |
| 94 | void ar5008_get_ht_tpow(struct athn_softc *, struct ieee80211_channel *, |
| 95 | uint8_t, const struct ar_cal_target_power_ht *, int, uint8_t[]); |
| 96 | int ar9280_set_synth(struct athn_softc *, struct ieee80211_channel *, |
| 97 | struct ieee80211_channel *); |
| 98 | void ar9280_spur_mitigate(struct athn_softc *, struct ieee80211_channel *, |
| 99 | struct ieee80211_channel *); |
| 100 | |
| 101 | |
| 102 | int |
| 103 | ar9285_attach(struct athn_softc *sc) |
| 104 | { |
| 105 | sc->eep_base = AR9285_EEP_START_LOC64; |
| 106 | sc->eep_size = sizeof(struct ar9285_eeprom); |
| 107 | sc->ngpiopins = (sc->flags & ATHN_FLAG_USB(1 << 1)) ? 16 : 12; |
| 108 | sc->led_pin = (sc->flags & ATHN_FLAG_USB(1 << 1)) ? 15 : 1; |
| 109 | sc->workaround = AR9285_WA_DEFAULT0x004a050b; |
| 110 | sc->ops.setup = ar9285_setup; |
| 111 | sc->ops.swap_rom = ar9285_swap_rom; |
| 112 | sc->ops.init_from_rom = ar9285_init_from_rom; |
| 113 | sc->ops.set_txpower = ar9285_set_txpower; |
| 114 | sc->ops.set_synth = ar9280_set_synth; |
| 115 | sc->ops.spur_mitigate = ar9280_spur_mitigate; |
| 116 | sc->ops.get_spur_chans = ar9285_get_spur_chans; |
| 117 | #if NATHN_USB1 > 0 |
| 118 | if (AR_SREV_9271(sc)((sc)->mac_ver == 0x140)) { |
| 119 | sc->cca_min_2g = AR9271_PHY_CCA_MIN_GOOD_VAL_2GHZ(-127); |
| 120 | sc->cca_max_2g = AR9271_PHY_CCA_MAX_GOOD_VAL_2GHZ(-116); |
| 121 | } else |
| 122 | #endif |
| 123 | { |
| 124 | sc->cca_min_2g = AR9285_PHY_CCA_MIN_GOOD_VAL_2GHZ(-127); |
| 125 | sc->cca_max_2g = AR9285_PHY_CCA_MAX_GOOD_VAL_2GHZ(-108); |
| 126 | } |
| 127 | #if NATHN_USB1 > 0 |
| 128 | if (AR_SREV_9271(sc)((sc)->mac_ver == 0x140)) |
| 129 | sc->ini = &ar9271_ini; |
| 130 | else |
| 131 | #endif |
| 132 | sc->ini = &ar9285_1_2_ini; |
| 133 | sc->serdes = &ar9280_2_0_serdes; |
| 134 | |
| 135 | return (ar5008_attach(sc)); |
| 136 | } |
| 137 | |
| 138 | void |
| 139 | ar9285_setup(struct athn_softc *sc) |
| 140 | { |
| 141 | const struct ar9285_eeprom *eep = sc->eep; |
| 142 | uint8_t type; |
| 143 | |
| 144 | /* Select initialization values based on ROM. */ |
| 145 | type = eep->baseEepHeader.txGainType; |
| 146 | DPRINTF(("Tx gain type=0x%x\n", type)); |
| 147 | #if NATHN_USB1 > 0 |
| 148 | if (AR_SREV_9271(sc)((sc)->mac_ver == 0x140)) { |
| 149 | if (type == AR_EEP_TXGAIN_HIGH_POWER1) |
| 150 | sc->tx_gain = &ar9271_tx_gain_high_power; |
| 151 | else |
| 152 | sc->tx_gain = &ar9271_tx_gain; |
| 153 | } else |
| 154 | #endif /* NATHN_USB */ |
| 155 | if ((AR_READ(sc, AR_AN_SYNTH9)(sc)->ops.read((sc), (0x7868)) & 0x7) == 0x1) { /* XE rev. */ |
| 156 | if (type == AR_EEP_TXGAIN_HIGH_POWER1) |
| 157 | sc->tx_gain = &ar9285_2_0_tx_gain_high_power; |
| 158 | else |
| 159 | sc->tx_gain = &ar9285_2_0_tx_gain; |
| 160 | } else { |
| 161 | if (type == AR_EEP_TXGAIN_HIGH_POWER1) |
| 162 | sc->tx_gain = &ar9285_1_2_tx_gain_high_power; |
| 163 | else |
| 164 | sc->tx_gain = &ar9285_1_2_tx_gain; |
| 165 | } |
| 166 | } |
| 167 | |
| 168 | void |
| 169 | ar9285_swap_rom(struct athn_softc *sc) |
| 170 | { |
| 171 | struct ar9285_eeprom *eep = sc->eep; |
| 172 | int i; |
| 173 | |
| 174 | eep->modalHeader.antCtrlCommon = |
| 175 | swap32(eep->modalHeader.antCtrlCommon)(__uint32_t)(__builtin_constant_p(eep->modalHeader.antCtrlCommon ) ? (__uint32_t)(((__uint32_t)(eep->modalHeader.antCtrlCommon ) & 0xff) << 24 | ((__uint32_t)(eep->modalHeader .antCtrlCommon) & 0xff00) << 8 | ((__uint32_t)(eep-> modalHeader.antCtrlCommon) & 0xff0000) >> 8 | ((__uint32_t )(eep->modalHeader.antCtrlCommon) & 0xff000000) >> 24) : __swap32md(eep->modalHeader.antCtrlCommon)); |
| 176 | eep->modalHeader.antCtrlChain = |
| 177 | swap32(eep->modalHeader.antCtrlChain)(__uint32_t)(__builtin_constant_p(eep->modalHeader.antCtrlChain ) ? (__uint32_t)(((__uint32_t)(eep->modalHeader.antCtrlChain ) & 0xff) << 24 | ((__uint32_t)(eep->modalHeader .antCtrlChain) & 0xff00) << 8 | ((__uint32_t)(eep-> modalHeader.antCtrlChain) & 0xff0000) >> 8 | ((__uint32_t )(eep->modalHeader.antCtrlChain) & 0xff000000) >> 24) : __swap32md(eep->modalHeader.antCtrlChain)); |
| 178 | |
| 179 | for (i = 0; i < AR_EEPROM_MODAL_SPURS5; i++) { |
| 180 | eep->modalHeader.spurChans[i].spurChan = |
| 181 | swap16(eep->modalHeader.spurChans[i].spurChan)(__uint16_t)(__builtin_constant_p(eep->modalHeader.spurChans [i].spurChan) ? (__uint16_t)(((__uint16_t)(eep->modalHeader .spurChans[i].spurChan) & 0xffU) << 8 | ((__uint16_t )(eep->modalHeader.spurChans[i].spurChan) & 0xff00U) >> 8) : __swap16md(eep->modalHeader.spurChans[i].spurChan)); |
| 182 | } |
| 183 | } |
| 184 | |
| 185 | const struct ar_spur_chan * |
| 186 | ar9285_get_spur_chans(struct athn_softc *sc, int is2ghz) |
| 187 | { |
| 188 | const struct ar9285_eeprom *eep = sc->eep; |
| 189 | |
| 190 | KASSERT(is2ghz)((is2ghz) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/ar9285.c" , 190, "is2ghz")); |
| 191 | return (eep->modalHeader.spurChans); |
| 192 | } |
| 193 | |
| 194 | void |
| 195 | ar9285_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c, |
| 196 | struct ieee80211_channel *extc) |
| 197 | { |
| 198 | const struct ar9285_eeprom *eep = sc->eep; |
| 199 | const struct ar9285_modal_eep_header *modal = &eep->modalHeader; |
| 200 | uint32_t reg, offset = 0x1000; |
| 201 | uint8_t ob[5], db1[5], db2[5]; |
| 202 | uint8_t txRxAtten; |
| 203 | |
| 204 | AR_WRITE(sc, AR_PHY_SWITCH_COM, modal->antCtrlCommon)(sc)->ops.write((sc), (0x9964), (modal->antCtrlCommon)); |
| 205 | AR_WRITE(sc, AR_PHY_SWITCH_CHAIN_0, modal->antCtrlChain)(sc)->ops.write((sc), (0x9960), (modal->antCtrlChain)); |
| 206 | |
| 207 | reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0)(sc)->ops.read((sc), (0x9920)); |
| 208 | reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, modal->iqCalI)(((reg) & ~0x000007e0) | (((uint32_t)(modal->iqCalI) << 5) & 0x000007e0)); |
| 209 | reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, modal->iqCalQ)(((reg) & ~0x0000001f) | (((uint32_t)(modal->iqCalQ) << 0) & 0x0000001f)); |
| 210 | AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0, reg)(sc)->ops.write((sc), (0x9920), (reg)); |
| 211 | |
| 212 | if (sc->eep_rev >= AR_EEP_MINOR_VER_33) { |
| 213 | reg = AR_READ(sc, AR_PHY_GAIN_2GHZ)(sc)->ops.read((sc), (0xa20c)); |
| 214 | reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,(((reg) & ~0x0001f000) | (((uint32_t)(modal->bswMargin ) << 12) & 0x0001f000)) |
| 215 | modal->bswMargin)(((reg) & ~0x0001f000) | (((uint32_t)(modal->bswMargin ) << 12) & 0x0001f000)); |
| 216 | reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,(((reg) & ~0x0000003f) | (((uint32_t)(modal->bswAtten) << 0) & 0x0000003f)) |
| 217 | modal->bswAtten)(((reg) & ~0x0000003f) | (((uint32_t)(modal->bswAtten) << 0) & 0x0000003f)); |
| 218 | reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,(((reg) & ~0x003e0000) | (((uint32_t)(modal->xatten2Margin ) << 17) & 0x003e0000)) |
| 219 | modal->xatten2Margin)(((reg) & ~0x003e0000) | (((uint32_t)(modal->xatten2Margin ) << 17) & 0x003e0000)); |
| 220 | reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_DB,(((reg) & ~0x00000fc0) | (((uint32_t)(modal->xatten2Db ) << 6) & 0x00000fc0)) |
| 221 | modal->xatten2Db)(((reg) & ~0x00000fc0) | (((uint32_t)(modal->xatten2Db ) << 6) & 0x00000fc0)); |
| 222 | AR_WRITE(sc, AR_PHY_GAIN_2GHZ, reg)(sc)->ops.write((sc), (0xa20c), (reg)); |
| 223 | |
| 224 | /* Duplicate values of chain 0 for chain 1. */ |
| 225 | reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset)(sc)->ops.read((sc), (0xa20c + offset)); |
| 226 | reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,(((reg) & ~0x0001f000) | (((uint32_t)(modal->bswMargin ) << 12) & 0x0001f000)) |
| 227 | modal->bswMargin)(((reg) & ~0x0001f000) | (((uint32_t)(modal->bswMargin ) << 12) & 0x0001f000)); |
| 228 | reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,(((reg) & ~0x0000003f) | (((uint32_t)(modal->bswAtten) << 0) & 0x0000003f)) |
| 229 | modal->bswAtten)(((reg) & ~0x0000003f) | (((uint32_t)(modal->bswAtten) << 0) & 0x0000003f)); |
| 230 | reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,(((reg) & ~0x003e0000) | (((uint32_t)(modal->xatten2Margin ) << 17) & 0x003e0000)) |
| 231 | modal->xatten2Margin)(((reg) & ~0x003e0000) | (((uint32_t)(modal->xatten2Margin ) << 17) & 0x003e0000)); |
| 232 | reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_DB,(((reg) & ~0x00000fc0) | (((uint32_t)(modal->xatten2Db ) << 6) & 0x00000fc0)) |
| 233 | modal->xatten2Db)(((reg) & ~0x00000fc0) | (((uint32_t)(modal->xatten2Db ) << 6) & 0x00000fc0)); |
| 234 | AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg)(sc)->ops.write((sc), (0xa20c + offset), (reg)); |
| 235 | } |
| 236 | if (sc->eep_rev >= AR_EEP_MINOR_VER_33) |
| 237 | txRxAtten = modal->txRxAtten; |
| 238 | else /* Workaround for ROM versions < 14.3. */ |
| 239 | txRxAtten = 23; |
| 240 | reg = AR_READ(sc, AR_PHY_RXGAIN)(sc)->ops.read((sc), (0x9848)); |
| 241 | reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAtten)(((reg) & ~0x00003f80) | (((uint32_t)(txRxAtten) << 7) & 0x00003f80)); |
| 242 | reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN, modal->rxTxMargin)(((reg) & ~0x001fc000) | (((uint32_t)(modal->rxTxMargin ) << 14) & 0x001fc000)); |
| 243 | AR_WRITE(sc, AR_PHY_RXGAIN, reg)(sc)->ops.write((sc), (0x9848), (reg)); |
| 244 | |
| 245 | /* Duplicate values of chain 0 for chain 1. */ |
| 246 | reg = AR_READ(sc, AR_PHY_RXGAIN + offset)(sc)->ops.read((sc), (0x9848 + offset)); |
| 247 | reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAtten)(((reg) & ~0x00003f80) | (((uint32_t)(txRxAtten) << 7) & 0x00003f80)); |
| 248 | reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN, modal->rxTxMargin)(((reg) & ~0x001fc000) | (((uint32_t)(modal->rxTxMargin ) << 14) & 0x001fc000)); |
| 249 | AR_WRITE(sc, AR_PHY_RXGAIN + offset, reg)(sc)->ops.write((sc), (0x9848 + offset), (reg)); |
| 250 | |
| 251 | if (modal->version >= 3) { |
| 252 | /* Setup antenna diversity from ROM. */ |
| 253 | reg = AR_READ(sc, AR_PHY_MULTICHAIN_GAIN_CTL)(sc)->ops.read((sc), (0x99ac)); |
| 254 | reg = RW(reg, AR9285_PHY_ANT_DIV_CTL_ALL, 0)(((reg) & ~0x7f000000) | (((uint32_t)(0) << 24) & 0x7f000000)); |
| 255 | reg = RW(reg, AR9285_PHY_ANT_DIV_CTL,(((reg) & ~0x01000000) | (((uint32_t)((modal->ob_234 >> 12) & 0x1) << 24) & 0x01000000)) |
| 256 | (modal->ob_234 >> 12) & 0x1)(((reg) & ~0x01000000) | (((uint32_t)((modal->ob_234 >> 12) & 0x1) << 24) & 0x01000000)); |
| 257 | reg = RW(reg, AR9285_PHY_ANT_DIV_ALT_LNACONF,(((reg) & ~0x06000000) | (((uint32_t)((modal->db1_234 >> 12) & 0x3) << 25) & 0x06000000)) |
| 258 | (modal->db1_234 >> 12) & 0x3)(((reg) & ~0x06000000) | (((uint32_t)((modal->db1_234 >> 12) & 0x3) << 25) & 0x06000000)); |
| 259 | reg = RW(reg, AR9285_PHY_ANT_DIV_MAIN_LNACONF,(((reg) & ~0x18000000) | (((uint32_t)((modal->db1_234 >> 14) & 0x3) << 27) & 0x18000000)) |
| 260 | (modal->db1_234 >> 14) & 0x3)(((reg) & ~0x18000000) | (((uint32_t)((modal->db1_234 >> 14) & 0x3) << 27) & 0x18000000)); |
| 261 | reg = RW(reg, AR9285_PHY_ANT_DIV_ALT_GAINTB,(((reg) & ~0x20000000) | (((uint32_t)((modal->ob_234 >> 13) & 0x1) << 29) & 0x20000000)) |
| 262 | (modal->ob_234 >> 13) & 0x1)(((reg) & ~0x20000000) | (((uint32_t)((modal->ob_234 >> 13) & 0x1) << 29) & 0x20000000)); |
| 263 | reg = RW(reg, AR9285_PHY_ANT_DIV_MAIN_GAINTB,(((reg) & ~0x40000000) | (((uint32_t)((modal->ob_234 >> 14) & 0x1) << 30) & 0x40000000)) |
| 264 | (modal->ob_234 >> 14) & 0x1)(((reg) & ~0x40000000) | (((uint32_t)((modal->ob_234 >> 14) & 0x1) << 30) & 0x40000000)); |
| 265 | AR_WRITE(sc, AR_PHY_MULTICHAIN_GAIN_CTL, reg)(sc)->ops.write((sc), (0x99ac), (reg)); |
| 266 | reg = AR_READ(sc, AR_PHY_MULTICHAIN_GAIN_CTL)(sc)->ops.read((sc), (0x99ac)); /* Flush. */ |
| 267 | |
| 268 | reg = AR_READ(sc, AR_PHY_CCK_DETECT)(sc)->ops.read((sc), (0xa208)); |
| 269 | if (modal->ob_234 & (1 << 15)) |
| 270 | reg |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV0x00002000; |
| 271 | else |
| 272 | reg &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV0x00002000; |
| 273 | AR_WRITE(sc, AR_PHY_CCK_DETECT, reg)(sc)->ops.write((sc), (0xa208), (reg)); |
| 274 | reg = AR_READ(sc, AR_PHY_CCK_DETECT)(sc)->ops.read((sc), (0xa208)); /* Flush. */ |
| 275 | } |
| 276 | if (modal->version >= 2) { |
| 277 | ob [0] = (modal->ob_01 >> 0) & 0xf; |
| 278 | ob [1] = (modal->ob_01 >> 4) & 0xf; |
| 279 | ob [2] = (modal->ob_234 >> 0) & 0xf; |
| 280 | ob [3] = (modal->ob_234 >> 4) & 0xf; |
| 281 | ob [4] = (modal->ob_234 >> 8) & 0xf; |
| 282 | |
| 283 | db1[0] = (modal->db1_01 >> 0) & 0xf; |
| 284 | db1[1] = (modal->db1_01 >> 4) & 0xf; |
| 285 | db1[2] = (modal->db1_234 >> 0) & 0xf; |
| 286 | db1[3] = (modal->db1_234 >> 4) & 0xf; |
| 287 | db1[4] = (modal->db1_234 >> 8) & 0xf; |
| 288 | |
| 289 | db2[0] = (modal->db2_01 >> 0) & 0xf; |
| 290 | db2[1] = (modal->db2_01 >> 4) & 0xf; |
| 291 | db2[2] = (modal->db2_234 >> 0) & 0xf; |
| 292 | db2[3] = (modal->db2_234 >> 4) & 0xf; |
| 293 | db2[4] = (modal->db2_234 >> 8) & 0xf; |
| 294 | |
| 295 | } else if (modal->version == 1) { |
| 296 | ob [0] = (modal->ob_01 >> 0) & 0xf; |
| 297 | ob [1] = (modal->ob_01 >> 4) & 0xf; |
| 298 | /* Field ob_234 does not exist, use ob_01. */ |
| 299 | ob [2] = ob [3] = ob [4] = ob [1]; |
| 300 | |
| 301 | db1[0] = (modal->db1_01 >> 0) & 0xf; |
| 302 | db1[1] = (modal->db1_01 >> 4) & 0xf; |
| 303 | /* Field db1_234 does not exist, use db1_01. */ |
| 304 | db1[2] = db1[3] = db1[4] = db1[1]; |
| 305 | |
| 306 | db2[0] = (modal->db2_01 >> 0) & 0xf; |
| 307 | db2[1] = (modal->db2_01 >> 4) & 0xf; |
| 308 | /* Field db2_234 does not exist, use db2_01. */ |
| 309 | db2[2] = db2[3] = db2[4] = db2[1]; |
| 310 | |
| 311 | } else { |
| 312 | ob [0] = modal->ob_01; |
| 313 | ob [1] = ob [2] = ob [3] = ob [4] = ob [0]; |
| 314 | |
| 315 | db1[0] = modal->db1_01; |
| 316 | db1[1] = db1[2] = db1[3] = db1[4] = db1[0]; |
| 317 | |
| 318 | /* Field db2_01 does not exist, use db1_01. */ |
| 319 | db2[0] = modal->db1_01; |
| 320 | db2[1] = db2[2] = db2[3] = db2[4] = db2[0]; |
| 321 | } |
| 322 | #if NATHN_USB1 > 0 |
| 323 | if (AR_SREV_9271(sc)((sc)->mac_ver == 0x140)) { |
| 324 | reg = AR_READ(sc, AR9285_AN_RF2G3)(sc)->ops.read((sc), (0x7828)); |
| 325 | reg = RW(reg, AR9271_AN_RF2G3_OB_CCK, ob [0])(((reg) & ~0x001c0000) | (((uint32_t)(ob [0]) << 18 ) & 0x001c0000)); |
| 326 | reg = RW(reg, AR9271_AN_RF2G3_OB_PSK, ob [1])(((reg) & ~0x00038000) | (((uint32_t)(ob [1]) << 15 ) & 0x00038000)); |
| 327 | reg = RW(reg, AR9271_AN_RF2G3_OB_QAM, ob [2])(((reg) & ~0x00007000) | (((uint32_t)(ob [2]) << 12 ) & 0x00007000)); |
| 328 | reg = RW(reg, AR9271_AN_RF2G3_DB1, db1[0])(((reg) & ~0x00e00000) | (((uint32_t)(db1[0]) << 21 ) & 0x00e00000)); |
| 329 | AR_WRITE(sc, AR9285_AN_RF2G3, reg)(sc)->ops.write((sc), (0x7828), (reg)); |
| 330 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 331 | DELAY(100)(*delay_func)(100); |
| 332 | reg = AR_READ(sc, AR9285_AN_RF2G4)(sc)->ops.read((sc), (0x782c)); |
| 333 | reg = RW(reg, AR9271_AN_RF2G4_DB2, db2[0])(((reg) & ~0xe0000000) | (((uint32_t)(db2[0]) << 29 ) & 0xe0000000)); |
| 334 | AR_WRITE(sc, AR9285_AN_RF2G4, reg)(sc)->ops.write((sc), (0x782c), (reg)); |
| 335 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 336 | DELAY(100)(*delay_func)(100); |
| 337 | } else |
| 338 | #endif /* ATHN_USB */ |
| 339 | { |
| 340 | reg = AR_READ(sc, AR9285_AN_RF2G3)(sc)->ops.read((sc), (0x7828)); |
| 341 | reg = RW(reg, AR9285_AN_RF2G3_OB_0, ob [0])(((reg) & ~0x00e00000) | (((uint32_t)(ob [0]) << 21 ) & 0x00e00000)); |
| 342 | reg = RW(reg, AR9285_AN_RF2G3_OB_1, ob [1])(((reg) & ~0x001c0000) | (((uint32_t)(ob [1]) << 18 ) & 0x001c0000)); |
| 343 | reg = RW(reg, AR9285_AN_RF2G3_OB_2, ob [2])(((reg) & ~0x00038000) | (((uint32_t)(ob [2]) << 15 ) & 0x00038000)); |
| 344 | reg = RW(reg, AR9285_AN_RF2G3_OB_3, ob [3])(((reg) & ~0x00007000) | (((uint32_t)(ob [3]) << 12 ) & 0x00007000)); |
| 345 | reg = RW(reg, AR9285_AN_RF2G3_OB_4, ob [4])(((reg) & ~0x00000e00) | (((uint32_t)(ob [4]) << 9) & 0x00000e00)); |
| 346 | reg = RW(reg, AR9285_AN_RF2G3_DB1_0, db1[0])(((reg) & ~0x000001c0) | (((uint32_t)(db1[0]) << 6) & 0x000001c0)); |
| 347 | reg = RW(reg, AR9285_AN_RF2G3_DB1_1, db1[1])(((reg) & ~0x00000038) | (((uint32_t)(db1[1]) << 3) & 0x00000038)); |
| 348 | reg = RW(reg, AR9285_AN_RF2G3_DB1_2, db1[2])(((reg) & ~0x00000007) | (((uint32_t)(db1[2]) << 0) & 0x00000007)); |
| 349 | AR_WRITE(sc, AR9285_AN_RF2G3, reg)(sc)->ops.write((sc), (0x7828), (reg)); |
| 350 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 351 | DELAY(100)(*delay_func)(100); |
| 352 | reg = AR_READ(sc, AR9285_AN_RF2G4)(sc)->ops.read((sc), (0x782c)); |
| 353 | reg = RW(reg, AR9285_AN_RF2G4_DB1_3, db1[3])(((reg) & ~0xe0000000) | (((uint32_t)(db1[3]) << 29 ) & 0xe0000000)); |
| 354 | reg = RW(reg, AR9285_AN_RF2G4_DB1_4, db1[4])(((reg) & ~0x1c000000) | (((uint32_t)(db1[4]) << 26 ) & 0x1c000000)); |
| 355 | reg = RW(reg, AR9285_AN_RF2G4_DB2_0, db2[0])(((reg) & ~0x03800000) | (((uint32_t)(db2[0]) << 23 ) & 0x03800000)); |
| 356 | reg = RW(reg, AR9285_AN_RF2G4_DB2_1, db2[1])(((reg) & ~0x00700000) | (((uint32_t)(db2[1]) << 20 ) & 0x00700000)); |
| 357 | reg = RW(reg, AR9285_AN_RF2G4_DB2_2, db2[2])(((reg) & ~0x000e0000) | (((uint32_t)(db2[2]) << 17 ) & 0x000e0000)); |
| 358 | reg = RW(reg, AR9285_AN_RF2G4_DB2_3, db2[3])(((reg) & ~0x0001c000) | (((uint32_t)(db2[3]) << 14 ) & 0x0001c000)); |
| 359 | reg = RW(reg, AR9285_AN_RF2G4_DB2_4, db2[4])(((reg) & ~0x00003800) | (((uint32_t)(db2[4]) << 11 ) & 0x00003800)); |
| 360 | AR_WRITE(sc, AR9285_AN_RF2G4, reg)(sc)->ops.write((sc), (0x782c), (reg)); |
| 361 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 362 | DELAY(100)(*delay_func)(100); |
| 363 | } |
| 364 | |
| 365 | reg = AR_READ(sc, AR_PHY_SETTLING)(sc)->ops.read((sc), (0x9844)); |
| 366 | reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling)(((reg) & ~0x00003f80) | (((uint32_t)(modal->switchSettling ) << 7) & 0x00003f80)); |
| 367 | AR_WRITE(sc, AR_PHY_SETTLING, reg)(sc)->ops.write((sc), (0x9844), (reg)); |
| 368 | |
| 369 | reg = AR_READ(sc, AR_PHY_DESIRED_SZ)(sc)->ops.read((sc), (0x9850)); |
| 370 | reg = RW(reg, AR_PHY_DESIRED_SZ_ADC, modal->adcDesiredSize)(((reg) & ~0x000000ff) | (((uint32_t)(modal->adcDesiredSize ) << 0) & 0x000000ff)); |
| 371 | AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg)(sc)->ops.write((sc), (0x9850), (reg)); |
| 372 | |
| 373 | reg = SM(AR_PHY_RF_CTL4_TX_END_XPAA_OFF, modal->txEndToXpaOff)(((uint32_t)(modal->txEndToXpaOff) << 16) & 0x00ff0000 ); |
| 374 | reg |= SM(AR_PHY_RF_CTL4_TX_END_XPAB_OFF, modal->txEndToXpaOff)(((uint32_t)(modal->txEndToXpaOff) << 24) & 0xff000000 ); |
| 375 | reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAA_ON, modal->txFrameToXpaOn)(((uint32_t)(modal->txFrameToXpaOn) << 0) & 0x000000ff ); |
| 376 | reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAB_ON, modal->txFrameToXpaOn)(((uint32_t)(modal->txFrameToXpaOn) << 8) & 0x0000ff00 ); |
| 377 | AR_WRITE(sc, AR_PHY_RF_CTL4, reg)(sc)->ops.write((sc), (0x9834), (reg)); |
| 378 | |
| 379 | reg = AR_READ(sc, AR_PHY_RF_CTL3)(sc)->ops.read((sc), (0x9828)); |
| 380 | reg = RW(reg, AR_PHY_TX_END_TO_A2_RX_ON, modal->txEndToRxOn)(((reg) & ~0x00ff0000) | (((uint32_t)(modal->txEndToRxOn ) << 16) & 0x00ff0000)); |
| 381 | AR_WRITE(sc, AR_PHY_RF_CTL3, reg)(sc)->ops.write((sc), (0x9828), (reg)); |
| 382 | |
| 383 | reg = AR_READ(sc, AR_PHY_CCA(0))(sc)->ops.read((sc), ((0x9864 + (0) * 0x1000))); |
| 384 | reg = RW(reg, AR9280_PHY_CCA_THRESH62, modal->thresh62)(((reg) & ~0x000ff000) | (((uint32_t)(modal->thresh62) << 12) & 0x000ff000)); |
| 385 | AR_WRITE(sc, AR_PHY_CCA(0), reg)(sc)->ops.write((sc), ((0x9864 + (0) * 0x1000)), (reg)); |
| 386 | |
| 387 | reg = AR_READ(sc, AR_PHY_EXT_CCA0)(sc)->ops.read((sc), (0x99b8)); |
| 388 | reg = RW(reg, AR_PHY_EXT_CCA0_THRESH62, modal->thresh62)(((reg) & ~0x000000ff) | (((uint32_t)(modal->thresh62) << 0) & 0x000000ff)); |
| 389 | AR_WRITE(sc, AR_PHY_EXT_CCA0, reg)(sc)->ops.write((sc), (0x99b8), (reg)); |
| 390 | |
| 391 | if (sc->eep_rev >= AR_EEP_MINOR_VER_22) { |
| 392 | reg = AR_READ(sc, AR_PHY_RF_CTL2)(sc)->ops.read((sc), (0x9824)); |
| 393 | reg = RW(reg, AR_PHY_TX_END_PA_ON,(((reg) & ~0x0000ff00) | (((uint32_t)(modal->txFrameToPaOn ) << 8) & 0x0000ff00)) |
| 394 | modal->txFrameToPaOn)(((reg) & ~0x0000ff00) | (((uint32_t)(modal->txFrameToPaOn ) << 8) & 0x0000ff00)); |
| 395 | reg = RW(reg, AR_PHY_TX_END_DATA_START,(((reg) & ~0x000000ff) | (((uint32_t)(modal->txFrameToDataStart ) << 0) & 0x000000ff)) |
| 396 | modal->txFrameToDataStart)(((reg) & ~0x000000ff) | (((uint32_t)(modal->txFrameToDataStart ) << 0) & 0x000000ff)); |
| 397 | AR_WRITE(sc, AR_PHY_RF_CTL2, reg)(sc)->ops.write((sc), (0x9824), (reg)); |
| 398 | } |
| 399 | if (sc->eep_rev >= AR_EEP_MINOR_VER_33 && extc != NULL((void *)0)) { |
| 400 | reg = AR_READ(sc, AR_PHY_SETTLING)(sc)->ops.read((sc), (0x9844)); |
| 401 | reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->swSettleHt40)(((reg) & ~0x00003f80) | (((uint32_t)(modal->swSettleHt40 ) << 7) & 0x00003f80)); |
| 402 | AR_WRITE(sc, AR_PHY_SETTLING, reg)(sc)->ops.write((sc), (0x9844), (reg)); |
| 403 | } |
| 404 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 405 | } |
| 406 | |
| 407 | void |
| 408 | ar9285_pa_calib(struct athn_softc *sc) |
| 409 | { |
| 410 | /* List of registers that need to be saved/restored. */ |
| 411 | static const uint16_t regs[] = { |
| 412 | AR9285_AN_TOP30x786c, |
| 413 | AR9285_AN_RXTXBB10x7854, |
| 414 | AR9285_AN_RF2G10x7820, |
| 415 | AR9285_AN_RF2G20x7824, |
| 416 | AR9285_AN_TOP20x7868, |
| 417 | AR9285_AN_RF2G80x783c, |
| 418 | AR9285_AN_RF2G70x7838 |
| 419 | }; |
| 420 | uint32_t svg[7], reg, ccomp_svg; |
| 421 | int i; |
| 422 | |
| 423 | /* No PA calibration needed for high power solutions. */ |
| 424 | if (AR_SREV_9285(sc)((sc)->mac_ver == 0x0c0) && |
| 425 | ((struct ar9285_base_eep_header *)sc->eep)->txGainType == |
| 426 | AR_EEP_TXGAIN_HIGH_POWER1) /* XXX AR9287? */ |
| 427 | return; |
| 428 | |
| 429 | /* Save registers. */ |
| 430 | for (i = 0; i < nitems(regs)(sizeof((regs)) / sizeof((regs)[0])); i++) |
| 431 | svg[i] = AR_READ(sc, regs[i])(sc)->ops.read((sc), (regs[i])); |
| 432 | |
| 433 | AR_CLRBITS(sc, AR9285_AN_RF2G6, 1)(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) & ~(1))); |
| 434 | AR_SETBITS(sc, AR_PHY(2), 1 << 27)(sc)->ops.write((sc), ((0x9800 + (2) * 4)), ((sc)->ops. read((sc), ((0x9800 + (2) * 4))) | (1 << 27))); |
| 435 | |
| 436 | AR_SETBITS(sc, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC)(sc)->ops.write((sc), (0x786c), ((sc)->ops.read((sc), ( 0x786c)) | (0x00800000))); |
| 437 | AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1)(sc)->ops.write((sc), (0x7854), ((sc)->ops.read((sc), ( 0x7854)) | (0x00000020))); |
| 438 | AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I)(sc)->ops.write((sc), (0x7854), ((sc)->ops.read((sc), ( 0x7854)) | (0x00000080))); |
| 439 | AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF)(sc)->ops.write((sc), (0x7854), ((sc)->ops.read((sc), ( 0x7854)) | (0x00000100))); |
| 440 | AR_CLRBITS(sc, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL)(sc)->ops.write((sc), (0x7824), ((sc)->ops.read((sc), ( 0x7824)) & ~(0x00001000))); |
| 441 | AR_CLRBITS(sc, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB)(sc)->ops.write((sc), (0x7838), ((sc)->ops.read((sc), ( 0x7838)) & ~(0x00000002))); |
| 442 | AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL)(sc)->ops.write((sc), (0x7820), ((sc)->ops.read((sc), ( 0x7820)) & ~(0x00000800))); |
| 443 | /* Power down PA drivers. */ |
| 444 | AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1)(sc)->ops.write((sc), (0x7820), ((sc)->ops.read((sc), ( 0x7820)) & ~(0x02000000))); |
| 445 | AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2)(sc)->ops.write((sc), (0x7820), ((sc)->ops.read((sc), ( 0x7820)) & ~(0x01000000))); |
| 446 | AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT)(sc)->ops.write((sc), (0x7820), ((sc)->ops.read((sc), ( 0x7820)) & ~(0x00800000))); |
| 447 | |
| 448 | reg = AR_READ(sc, AR9285_AN_RF2G8)(sc)->ops.read((sc), (0x783c)); |
| 449 | reg = RW(reg, AR9285_AN_RF2G8_PADRVGN2TAB0, 7)(((reg) & ~0x0001c000) | (((uint32_t)(7) << 14) & 0x0001c000)); |
| 450 | AR_WRITE(sc, AR9285_AN_RF2G8, reg)(sc)->ops.write((sc), (0x783c), (reg)); |
| 451 | |
| 452 | reg = AR_READ(sc, AR9285_AN_RF2G7)(sc)->ops.read((sc), (0x7838)); |
| 453 | reg = RW(reg, AR9285_AN_RF2G7_PADRVGN2TAB0, 0)(((reg) & ~0xe0000000) | (((uint32_t)(0) << 29) & 0xe0000000)); |
| 454 | AR_WRITE(sc, AR9285_AN_RF2G7, reg)(sc)->ops.write((sc), (0x7838), (reg)); |
| 455 | |
| 456 | reg = AR_READ(sc, AR9285_AN_RF2G6)(sc)->ops.read((sc), (0x7834)); |
| 457 | /* Save compensation capacitor value. */ |
| 458 | ccomp_svg = MS(reg, AR9285_AN_RF2G6_CCOMP)(((uint32_t)(reg) & 0x00007800) >> 11); |
| 459 | /* Program compensation capacitor for dynamic PA. */ |
| 460 | reg = RW(reg, AR9285_AN_RF2G6_CCOMP, 0xf)(((reg) & ~0x00007800) | (((uint32_t)(0xf) << 11) & 0x00007800)); |
| 461 | AR_WRITE(sc, AR9285_AN_RF2G6, reg)(sc)->ops.write((sc), (0x7834), (reg)); |
| 462 | |
| 463 | AR_WRITE(sc, AR9285_AN_TOP2, AR9285_AN_TOP2_DEFAULT)(sc)->ops.write((sc), (0x7868), (0xca0358a0)); |
| 464 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 465 | DELAY(30)(*delay_func)(30); |
| 466 | |
| 467 | /* Clear offsets 6-1. */ |
| 468 | AR_CLRBITS(sc, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS_6_1)(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) & ~(0x03f00000))); |
| 469 | /* Clear offset 0. */ |
| 470 | AR_CLRBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP)(sc)->ops.write((sc), (0x7828), ((sc)->ops.read((sc), ( 0x7828)) & ~(0x02000000))); |
| 471 | /* Set offsets 6-1. */ |
| 472 | for (i = 6; i >= 1; i--) { |
| 473 | AR_SETBITS(sc, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS(i))(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) | ((1 << (19 + (i)))))); |
| 474 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 475 | DELAY(1)(*delay_func)(1); |
| 476 | if (AR_READ(sc, AR9285_AN_RF2G9)(sc)->ops.read((sc), (0x7840)) & AR9285_AN_RXTXBB1_SPARE90x00000001) { |
| 477 | AR_SETBITS(sc, AR9285_AN_RF2G6,(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) | ((1 << (19 + (i)))))) |
| 478 | AR9285_AN_RF2G6_OFFS(i))(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) | ((1 << (19 + (i)))))); |
| 479 | } else { |
| 480 | AR_CLRBITS(sc, AR9285_AN_RF2G6,(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) & ~((1 << (19 + (i)))))) |
| 481 | AR9285_AN_RF2G6_OFFS(i))(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) & ~((1 << (19 + (i)))))); |
| 482 | } |
| 483 | } |
| 484 | /* Set offset 0. */ |
| 485 | AR_SETBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP)(sc)->ops.write((sc), (0x7828), ((sc)->ops.read((sc), ( 0x7828)) | (0x02000000))); |
| 486 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 487 | DELAY(1)(*delay_func)(1); |
| 488 | if (AR_READ(sc, AR9285_AN_RF2G9)(sc)->ops.read((sc), (0x7840)) & AR9285_AN_RXTXBB1_SPARE90x00000001) |
| 489 | AR_SETBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP)(sc)->ops.write((sc), (0x7828), ((sc)->ops.read((sc), ( 0x7828)) | (0x02000000))); |
| 490 | else |
| 491 | AR_CLRBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP)(sc)->ops.write((sc), (0x7828), ((sc)->ops.read((sc), ( 0x7828)) & ~(0x02000000))); |
| 492 | |
| 493 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 494 | |
| 495 | AR_SETBITS(sc, AR9285_AN_RF2G6, 1)(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) | (1))); |
| 496 | AR_CLRBITS(sc, AR_PHY(2), 1 << 27)(sc)->ops.write((sc), ((0x9800 + (2) * 4)), ((sc)->ops. read((sc), ((0x9800 + (2) * 4))) & ~(1 << 27))); |
| 497 | |
| 498 | /* Restore registers. */ |
| 499 | for (i = 0; i < nitems(regs)(sizeof((regs)) / sizeof((regs)[0])); i++) |
| 500 | AR_WRITE(sc, regs[i], svg[i])(sc)->ops.write((sc), (regs[i]), (svg[i])); |
| 501 | |
| 502 | /* Restore compensation capacitor value. */ |
| 503 | reg = AR_READ(sc, AR9285_AN_RF2G6)(sc)->ops.read((sc), (0x7834)); |
| 504 | reg = RW(reg, AR9285_AN_RF2G6_CCOMP, ccomp_svg)(((reg) & ~0x00007800) | (((uint32_t)(ccomp_svg) << 11) & 0x00007800)); |
| 505 | AR_WRITE(sc, AR9285_AN_RF2G6, reg)(sc)->ops.write((sc), (0x7834), (reg)); |
| 506 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 507 | } |
| 508 | |
| 509 | void |
| 510 | ar9271_pa_calib(struct athn_softc *sc) |
| 511 | { |
| 512 | #if NATHN_USB1 > 0 |
| 513 | /* List of registers that need to be saved/restored. */ |
| 514 | static const uint16_t regs[] = { |
| 515 | AR9285_AN_TOP30x786c, |
| 516 | AR9285_AN_RXTXBB10x7854, |
| 517 | AR9285_AN_RF2G10x7820, |
| 518 | AR9285_AN_RF2G20x7824, |
| 519 | AR9285_AN_TOP20x7868, |
| 520 | AR9285_AN_RF2G80x783c, |
| 521 | AR9285_AN_RF2G70x7838 |
| 522 | }; |
| 523 | uint32_t svg[7], reg, rf2g3_svg; |
| 524 | int i; |
| 525 | |
| 526 | /* Save registers. */ |
| 527 | for (i = 0; i < nitems(regs)(sizeof((regs)) / sizeof((regs)[0])); i++) |
| 528 | svg[i] = AR_READ(sc, regs[i])(sc)->ops.read((sc), (regs[i])); |
| 529 | |
| 530 | AR_CLRBITS(sc, AR9285_AN_RF2G6, 1)(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) & ~(1))); |
| 531 | AR_SETBITS(sc, AR_PHY(2), 1 << 27)(sc)->ops.write((sc), ((0x9800 + (2) * 4)), ((sc)->ops. read((sc), ((0x9800 + (2) * 4))) | (1 << 27))); |
| 532 | |
| 533 | AR_SETBITS(sc, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC)(sc)->ops.write((sc), (0x786c), ((sc)->ops.read((sc), ( 0x786c)) | (0x00800000))); |
| 534 | AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1)(sc)->ops.write((sc), (0x7854), ((sc)->ops.read((sc), ( 0x7854)) | (0x00000020))); |
| 535 | AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I)(sc)->ops.write((sc), (0x7854), ((sc)->ops.read((sc), ( 0x7854)) | (0x00000080))); |
| 536 | AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF)(sc)->ops.write((sc), (0x7854), ((sc)->ops.read((sc), ( 0x7854)) | (0x00000100))); |
| 537 | AR_CLRBITS(sc, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL)(sc)->ops.write((sc), (0x7824), ((sc)->ops.read((sc), ( 0x7824)) & ~(0x00001000))); |
| 538 | AR_CLRBITS(sc, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB)(sc)->ops.write((sc), (0x7838), ((sc)->ops.read((sc), ( 0x7838)) & ~(0x00000002))); |
| 539 | AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL)(sc)->ops.write((sc), (0x7820), ((sc)->ops.read((sc), ( 0x7820)) & ~(0x00000800))); |
| 540 | /* Power down PA drivers. */ |
| 541 | AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1)(sc)->ops.write((sc), (0x7820), ((sc)->ops.read((sc), ( 0x7820)) & ~(0x02000000))); |
| 542 | AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2)(sc)->ops.write((sc), (0x7820), ((sc)->ops.read((sc), ( 0x7820)) & ~(0x01000000))); |
| 543 | AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT)(sc)->ops.write((sc), (0x7820), ((sc)->ops.read((sc), ( 0x7820)) & ~(0x00800000))); |
| 544 | |
| 545 | reg = AR_READ(sc, AR9285_AN_RF2G8)(sc)->ops.read((sc), (0x783c)); |
| 546 | reg = RW(reg, AR9285_AN_RF2G8_PADRVGN2TAB0, 7)(((reg) & ~0x0001c000) | (((uint32_t)(7) << 14) & 0x0001c000)); |
| 547 | AR_WRITE(sc, AR9285_AN_RF2G8, reg)(sc)->ops.write((sc), (0x783c), (reg)); |
| 548 | |
| 549 | reg = AR_READ(sc, AR9285_AN_RF2G7)(sc)->ops.read((sc), (0x7838)); |
| 550 | reg = RW(reg, AR9285_AN_RF2G7_PADRVGN2TAB0, 0)(((reg) & ~0xe0000000) | (((uint32_t)(0) << 29) & 0xe0000000)); |
| 551 | AR_WRITE(sc, AR9285_AN_RF2G7, reg)(sc)->ops.write((sc), (0x7838), (reg)); |
| 552 | |
| 553 | /* Save compensation capacitor value. */ |
| 554 | reg = rf2g3_svg = AR_READ(sc, AR9285_AN_RF2G3)(sc)->ops.read((sc), (0x7828)); |
| 555 | /* Program compensation capacitor for dynamic PA. */ |
| 556 | reg = RW(reg, AR9271_AN_RF2G3_CCOMP, 0xfff)(((reg) & ~0x00000fff) | (((uint32_t)(0xfff) << 0) & 0x00000fff)); |
| 557 | AR_WRITE(sc, AR9285_AN_RF2G3, reg)(sc)->ops.write((sc), (0x7828), (reg)); |
| 558 | |
| 559 | AR_WRITE(sc, AR9285_AN_TOP2, AR9285_AN_TOP2_DEFAULT)(sc)->ops.write((sc), (0x7868), (0xca0358a0)); |
| 560 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 561 | DELAY(30)(*delay_func)(30); |
| 562 | |
| 563 | /* Clear offsets 6-0. */ |
| 564 | AR_CLRBITS(sc, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS_6_0)(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) & ~(0x07f00000))); |
| 565 | /* Set offsets 6-1. */ |
| 566 | for (i = 6; i >= 1; i--) { |
| 567 | reg = AR_READ(sc, AR9285_AN_RF2G6)(sc)->ops.read((sc), (0x7834)); |
| 568 | reg |= AR9271_AN_RF2G6_OFFS(i)(1 << (20 + (i))); |
| 569 | AR_WRITE(sc, AR9285_AN_RF2G6, reg)(sc)->ops.write((sc), (0x7834), (reg)); |
| 570 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 571 | DELAY(1)(*delay_func)(1); |
| 572 | if (!(AR_READ(sc, AR9285_AN_RF2G9)(sc)->ops.read((sc), (0x7840)) & AR9285_AN_RXTXBB1_SPARE90x00000001)) |
| 573 | reg &= ~AR9271_AN_RF2G6_OFFS(i)(1 << (20 + (i))); |
| 574 | AR_WRITE(sc, AR9285_AN_RF2G6, reg)(sc)->ops.write((sc), (0x7834), (reg)); |
| 575 | } |
| 576 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 577 | |
| 578 | AR_SETBITS(sc, AR9285_AN_RF2G6, 1)(sc)->ops.write((sc), (0x7834), ((sc)->ops.read((sc), ( 0x7834)) | (1))); |
| 579 | AR_CLRBITS(sc, AR_PHY(2), 1 << 27)(sc)->ops.write((sc), ((0x9800 + (2) * 4)), ((sc)->ops. read((sc), ((0x9800 + (2) * 4))) & ~(1 << 27))); |
| 580 | |
| 581 | /* Restore registers. */ |
| 582 | for (i = 0; i < nitems(regs)(sizeof((regs)) / sizeof((regs)[0])); i++) |
| 583 | AR_WRITE(sc, regs[i], svg[i])(sc)->ops.write((sc), (regs[i]), (svg[i])); |
| 584 | |
| 585 | /* Restore compensation capacitor value. */ |
| 586 | AR_WRITE(sc, AR9285_AN_RF2G3, rf2g3_svg)(sc)->ops.write((sc), (0x7828), (rf2g3_svg)); |
| 587 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 588 | #endif /* NATHN_USB */ |
| 589 | } |
| 590 | |
| 591 | /* |
| 592 | * Carrier Leakage Calibration. |
| 593 | */ |
| 594 | int |
| 595 | ar9285_cl_cal(struct athn_softc *sc, struct ieee80211_channel *c, |
| 596 | struct ieee80211_channel *extc) |
| 597 | { |
| 598 | int ntries; |
| 599 | |
| 600 | AR_SETBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE)(sc)->ops.write((sc), (0xa358), ((sc)->ops.read((sc), ( 0xa358)) | (0x00000002))); |
| 601 | if (0 && extc == NULL((void *)0)) { /* XXX IS_CHAN_HT20!! */ |
| 602 | AR_SETBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE)(sc)->ops.write((sc), (0xa358), ((sc)->ops.read((sc), ( 0xa358)) | (0x00000001))); |
| 603 | AR_SETBITS(sc, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN)(sc)->ops.write((sc), (0x9804), ((sc)->ops.read((sc), ( 0x9804)) | (0x00000004))); |
| 604 | AR_CLRBITS(sc, AR_PHY_AGC_CONTROL,(sc)->ops.write((sc), (0x9860), ((sc)->ops.read((sc), ( 0x9860)) & ~(0x00010000))) |
| 605 | AR_PHY_AGC_CONTROL_FLTR_CAL)(sc)->ops.write((sc), (0x9860), ((sc)->ops.read((sc), ( 0x9860)) & ~(0x00010000))); |
| 606 | AR_CLRBITS(sc, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE)(sc)->ops.write((sc), (0xa258), ((sc)->ops.read((sc), ( 0xa258)) & ~(0x00400000))); |
| 607 | AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL)(sc)->ops.write((sc), (0x9860), ((sc)->ops.read((sc), ( 0x9860)) | (0x00000001))); |
| 608 | for (ntries = 0; ntries < 10000; ntries++) { |
| 609 | if (!(AR_READ(sc, AR_PHY_AGC_CONTROL)(sc)->ops.read((sc), (0x9860)) & |
| 610 | AR_PHY_AGC_CONTROL_CAL0x00000001)) |
| 611 | break; |
| 612 | DELAY(10)(*delay_func)(10); |
| 613 | } |
| 614 | if (ntries == 10000) |
| 615 | return (ETIMEDOUT60); |
| 616 | AR_CLRBITS(sc, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN)(sc)->ops.write((sc), (0x9804), ((sc)->ops.read((sc), ( 0x9804)) & ~(0x00000004))); |
| 617 | AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE)(sc)->ops.write((sc), (0xa358), ((sc)->ops.read((sc), ( 0xa358)) & ~(0x00000001))); |
| 618 | AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE)(sc)->ops.write((sc), (0xa358), ((sc)->ops.read((sc), ( 0xa358)) & ~(0x00000002))); |
| 619 | } |
| 620 | AR_CLRBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC)(sc)->ops.write((sc), (0x982c), ((sc)->ops.read((sc), ( 0x982c)) & ~(0x00008000))); |
| 621 | AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL)(sc)->ops.write((sc), (0x9860), ((sc)->ops.read((sc), ( 0x9860)) | (0x00010000))); |
| 622 | AR_SETBITS(sc, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE)(sc)->ops.write((sc), (0xa258), ((sc)->ops.read((sc), ( 0xa258)) | (0x00400000))); |
| 623 | AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL)(sc)->ops.write((sc), (0x9860), ((sc)->ops.read((sc), ( 0x9860)) | (0x00000001))); |
| 624 | for (ntries = 0; ntries < 10000; ntries++) { |
| 625 | if (!(AR_READ(sc, AR_PHY_AGC_CONTROL)(sc)->ops.read((sc), (0x9860)) & |
| 626 | AR_PHY_AGC_CONTROL_CAL0x00000001)) |
| 627 | break; |
| 628 | DELAY(10)(*delay_func)(10); |
| 629 | } |
| 630 | if (ntries == 10000) |
| 631 | return (ETIMEDOUT60); |
| 632 | AR_SETBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC)(sc)->ops.write((sc), (0x982c), ((sc)->ops.read((sc), ( 0x982c)) | (0x00008000))); |
| 633 | AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE)(sc)->ops.write((sc), (0xa358), ((sc)->ops.read((sc), ( 0xa358)) & ~(0x00000002))); |
| 634 | AR_CLRBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL)(sc)->ops.write((sc), (0x9860), ((sc)->ops.read((sc), ( 0x9860)) & ~(0x00010000))); |
| 635 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 636 | return (0); |
| 637 | } |
| 638 | |
| 639 | void |
| 640 | ar9271_load_ani(struct athn_softc *sc) |
| 641 | { |
| 642 | #if NATHN_USB1 > 0 |
| 643 | /* Write ANI registers. */ |
| 644 | AR_WRITE(sc, AR_PHY_DESIRED_SZ, 0x6d4000e2)(sc)->ops.write((sc), (0x9850), (0x6d4000e2)); |
| 645 | AR_WRITE(sc, AR_PHY_AGC_CTL1, 0x3139605e)(sc)->ops.write((sc), (0x985c), (0x3139605e)); |
| 646 | AR_WRITE(sc, AR_PHY_FIND_SIG, 0x7ec84d2e)(sc)->ops.write((sc), (0x9858), (0x7ec84d2e)); |
| 647 | AR_WRITE(sc, AR_PHY_SFCORR_LOW, 0x06903881)(sc)->ops.write((sc), (0x986c), (0x06903881)); |
| 648 | AR_WRITE(sc, AR_PHY_SFCORR, 0x5ac640d0)(sc)->ops.write((sc), (0x9868), (0x5ac640d0)); |
| 649 | AR_WRITE(sc, AR_PHY_CCK_DETECT, 0x803e68c8)(sc)->ops.write((sc), (0xa208), (0x803e68c8)); |
| 650 | AR_WRITE(sc, AR_PHY_TIMING5, 0xd00a8007)(sc)->ops.write((sc), (0x9924), (0xd00a8007)); |
| 651 | AR_WRITE(sc, AR_PHY_SFCORR_EXT, 0x05eea6d4)(sc)->ops.write((sc), (0x99c0), (0x05eea6d4)); |
| 652 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 653 | #endif /* NATHN_USB */ |
| 654 | } |
| 655 | |
| 656 | int |
| 657 | ar9285_init_calib(struct athn_softc *sc, struct ieee80211_channel *c, |
| 658 | struct ieee80211_channel *extc) |
| 659 | { |
| 660 | uint32_t reg, mask, clcgain, rf2g5_svg; |
| 661 | int i, maxgain, nclcs, thresh, error; |
| 662 | |
| 663 | /* Do carrier leakage calibration. */ |
| 664 | if ((error = ar9285_cl_cal(sc, c, extc)) != 0) |
| 665 | return (error); |
| 666 | |
| 667 | /* Workaround for high temperature is not applicable on AR9271. */ |
| 668 | if (AR_SREV_9271(sc)((sc)->mac_ver == 0x140)) |
| 669 | return (0); |
| 670 | |
| 671 | mask = 0; |
| 672 | nclcs = 0; |
| 673 | reg = AR_READ(sc, AR_PHY_TX_PWRCTRL7)(sc)->ops.read((sc), (0xa274)); |
| 674 | maxgain = MS(reg, AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX)(((uint32_t)(reg) & 0x0007e000) >> 13); |
| 675 | for (i = 0; i <= maxgain; i++) { |
| 676 | reg = AR_READ(sc, AR_PHY_TX_GAIN_TBL(i))(sc)->ops.read((sc), ((0xa300 + (i) * 4))); |
| 677 | clcgain = MS(reg, AR_PHY_TX_GAIN_CLC)(((uint32_t)(reg) & 0x0000001e) >> 1); |
| 678 | /* NB: clcgain <= 0xf. */ |
| 679 | if (!(mask & (1 << clcgain))) { |
| 680 | mask |= 1 << clcgain; |
| 681 | nclcs++; |
| 682 | } |
| 683 | } |
| 684 | thresh = 0; |
| 685 | for (i = 0; i < nclcs; i++) { |
| 686 | reg = AR_READ(sc, AR_PHY_CLC_TBL(i))(sc)->ops.read((sc), ((0xa35c + (i) * 4))); |
| 687 | if (MS(reg, AR_PHY_CLC_I0)(((uint32_t)(reg) & 0x07ff0000) >> 16) == 0) |
| 688 | thresh++; |
| 689 | if (MS(reg, AR_PHY_CLC_Q0)(((uint32_t)(reg) & 0x0000ffd0) >> 5) == 0) |
| 690 | thresh++; |
| 691 | } |
| 692 | if (thresh <= AR9285_CL_CAL_REDO_THRESH1) |
| 693 | return (0); /* No need to redo. */ |
| 694 | |
| 695 | /* Threshold reached, redo carrier leakage calibration. */ |
| 696 | DPRINTFN(2, ("CLC threshold=%d\n", thresh)); |
| 697 | rf2g5_svg = reg = AR_READ(sc, AR9285_AN_RF2G5)(sc)->ops.read((sc), (0x7830)); |
| 698 | if ((AR_READ(sc, AR_AN_SYNTH9)(sc)->ops.read((sc), (0x7868)) & 0x7) == 0x1) /* XE rev. */ |
| 699 | reg = RW(reg, AR9285_AN_RF2G5_IC50TX, 0x5)(((reg) & ~0x00000700) | (((uint32_t)(0x5) << 8) & 0x00000700)); |
| 700 | else |
| 701 | reg = RW(reg, AR9285_AN_RF2G5_IC50TX, 0x4)(((reg) & ~0x00000700) | (((uint32_t)(0x4) << 8) & 0x00000700)); |
| 702 | AR_WRITE(sc, AR9285_AN_RF2G5, reg)(sc)->ops.write((sc), (0x7830), (reg)); |
| 703 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 704 | error = ar9285_cl_cal(sc, c, extc); |
| 705 | AR_WRITE(sc, AR9285_AN_RF2G5, rf2g5_svg)(sc)->ops.write((sc), (0x7830), (rf2g5_svg)); |
| 706 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 707 | return (error); |
| 708 | } |
| 709 | |
| 710 | void |
| 711 | ar9285_get_pdadcs(struct athn_softc *sc, struct ieee80211_channel *c, |
| 712 | int nxpdgains, uint8_t overlap, uint8_t *boundaries, uint8_t *pdadcs) |
| 713 | { |
| 714 | const struct ar9285_eeprom *eep = sc->eep; |
| 715 | const struct ar9285_cal_data_per_freq *pierdata; |
| 716 | const uint8_t *pierfreq; |
| 717 | struct athn_pier lopier, hipier; |
| 718 | uint8_t fbin; |
| 719 | int i, lo, hi, npiers; |
| 720 | |
| 721 | pierfreq = eep->calFreqPier2G; |
| 722 | pierdata = eep->calPierData2G; |
| 723 | npiers = AR9285_NUM_2G_CAL_PIERS3; |
| 724 | |
| 725 | /* Find channel in ROM pier table. */ |
| 726 | fbin = athn_chan2fbin(c); |
| 727 | athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi); |
| 728 | |
| 729 | lopier.fbin = pierfreq[lo]; |
| 730 | hipier.fbin = pierfreq[hi]; |
| 731 | for (i = 0; i < nxpdgains; i++) { |
| 732 | lopier.pwr[i] = pierdata[lo].pwrPdg[i]; |
| 733 | lopier.vpd[i] = pierdata[lo].vpdPdg[i]; |
| 734 | hipier.pwr[i] = pierdata[lo].pwrPdg[i]; |
| 735 | hipier.vpd[i] = pierdata[lo].vpdPdg[i]; |
| 736 | } |
| 737 | ar5008_get_pdadcs(sc, fbin, &lopier, &hipier, nxpdgains, |
| 738 | AR9285_PD_GAIN_ICEPTS5, overlap, boundaries, pdadcs); |
| 739 | } |
| 740 | |
| 741 | void |
| 742 | ar9285_set_power_calib(struct athn_softc *sc, struct ieee80211_channel *c) |
| 743 | { |
| 744 | const struct ar9285_eeprom *eep = sc->eep; |
| 745 | uint8_t boundaries[AR_PD_GAINS_IN_MASK4]; |
| 746 | uint8_t pdadcs[AR_NUM_PDADC_VALUES128]; |
| 747 | uint8_t xpdgains[AR9285_NUM_PD_GAINS2]; |
| 748 | uint8_t overlap; |
| 749 | uint32_t reg; |
| 750 | int i, nxpdgains; |
| 751 | |
| 752 | if (sc->eep_rev < AR_EEP_MINOR_VER_22) { |
| 753 | overlap = MS(AR_READ(sc, AR_PHY_TPCRG5),(((uint32_t)((sc)->ops.read((sc), (0xa26c))) & 0x0000000f ) >> 0) |
| 754 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP)(((uint32_t)((sc)->ops.read((sc), (0xa26c))) & 0x0000000f ) >> 0); |
| 755 | } else |
| 756 | overlap = eep->modalHeader.pdGainOverlap; |
| 757 | |
| 758 | nxpdgains = 0; |
| 759 | memset(xpdgains, 0, sizeof(xpdgains))__builtin_memset((xpdgains), (0), (sizeof(xpdgains))); |
| 760 | for (i = AR9285_PD_GAINS_IN_MASK4 - 1; i >= 0; i--) { |
| 761 | if (nxpdgains >= AR9285_NUM_PD_GAINS2) |
| 762 | break; |
| 763 | if (eep->modalHeader.xpdGain & (1 << i)) |
| 764 | xpdgains[nxpdgains++] = i; |
| 765 | } |
| 766 | reg = AR_READ(sc, AR_PHY_TPCRG1)(sc)->ops.read((sc), (0xa258)); |
| 767 | reg = RW(reg, AR_PHY_TPCRG1_NUM_PD_GAIN, nxpdgains - 1)(((reg) & ~0x0000c000) | (((uint32_t)(nxpdgains - 1) << 14) & 0x0000c000)); |
| 768 | reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_1, xpdgains[0])(((reg) & ~0x00030000) | (((uint32_t)(xpdgains[0]) << 16) & 0x00030000)); |
| 769 | reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_2, xpdgains[1])(((reg) & ~0x000c0000) | (((uint32_t)(xpdgains[1]) << 18) & 0x000c0000)); |
| 770 | AR_WRITE(sc, AR_PHY_TPCRG1, reg)(sc)->ops.write((sc), (0xa258), (reg)); |
| 771 | |
| 772 | /* NB: No open loop power control for AR9285. */ |
| 773 | ar9285_get_pdadcs(sc, c, nxpdgains, overlap, boundaries, pdadcs); |
| 774 | |
| 775 | /* Write boundaries. */ |
| 776 | reg = SM(AR_PHY_TPCRG5_PD_GAIN_OVERLAP, overlap)(((uint32_t)(overlap) << 0) & 0x0000000f); |
| 777 | reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1, boundaries[0])(((uint32_t)(boundaries[0]) << 4) & 0x000003f0); |
| 778 | reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2, boundaries[1])(((uint32_t)(boundaries[1]) << 10) & 0x0000fc00); |
| 779 | reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3, boundaries[2])(((uint32_t)(boundaries[2]) << 16) & 0x003f0000); |
| 780 | reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4, boundaries[3])(((uint32_t)(boundaries[3]) << 22) & 0x0fc00000); |
| 781 | AR_WRITE(sc, AR_PHY_TPCRG5, reg)(sc)->ops.write((sc), (0xa26c), (reg)); |
| 782 | |
| 783 | /* Write PDADC values. */ |
| 784 | for (i = 0; i < AR_NUM_PDADC_VALUES128; i += 4) { |
| 785 | AR_WRITE(sc, AR_PHY_PDADC_TBL_BASE + i,(sc)->ops.write((sc), (0xa280 + i), (pdadcs[i + 0] << 0 | pdadcs[i + 1] << 8 | pdadcs[i + 2] << 16 | pdadcs [i + 3] << 24)) |
| 786 | pdadcs[i + 0] << 0 |(sc)->ops.write((sc), (0xa280 + i), (pdadcs[i + 0] << 0 | pdadcs[i + 1] << 8 | pdadcs[i + 2] << 16 | pdadcs [i + 3] << 24)) |
| 787 | pdadcs[i + 1] << 8 |(sc)->ops.write((sc), (0xa280 + i), (pdadcs[i + 0] << 0 | pdadcs[i + 1] << 8 | pdadcs[i + 2] << 16 | pdadcs [i + 3] << 24)) |
| 788 | pdadcs[i + 2] << 16 |(sc)->ops.write((sc), (0xa280 + i), (pdadcs[i + 0] << 0 | pdadcs[i + 1] << 8 | pdadcs[i + 2] << 16 | pdadcs [i + 3] << 24)) |
| 789 | pdadcs[i + 3] << 24)(sc)->ops.write((sc), (0xa280 + i), (pdadcs[i + 0] << 0 | pdadcs[i + 1] << 8 | pdadcs[i + 2] << 16 | pdadcs [i + 3] << 24)); |
| 790 | } |
| 791 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 792 | } |
| 793 | |
| 794 | void |
| 795 | ar9285_set_txpower(struct athn_softc *sc, struct ieee80211_channel *c, |
| 796 | struct ieee80211_channel *extc) |
| 797 | { |
| 798 | const struct ar9285_eeprom *eep = sc->eep; |
| 799 | const struct ar9285_modal_eep_header *modal = &eep->modalHeader; |
| 800 | uint8_t tpow_cck[4], tpow_ofdm[4]; |
| 801 | uint8_t tpow_cck_ext[4], tpow_ofdm_ext[4]; |
| 802 | uint8_t tpow_ht20[8], tpow_ht40[8]; |
| 803 | uint8_t ht40inc; |
| 804 | int16_t max_ant_gain, power[ATHN_POWER_COUNT68]; |
| 805 | int i; |
| 806 | |
| 807 | ar9285_set_power_calib(sc, c); |
| 808 | |
| 809 | /* Compute transmit power reduction due to antenna gain. */ |
| 810 | max_ant_gain = modal->antennaGain; |
Value stored to 'max_ant_gain' is never read | |
| 811 | /* XXX */ |
| 812 | |
| 813 | /* Get CCK target powers. */ |
| 814 | ar5008_get_lg_tpow(sc, c, AR_CTL_11B1, eep->calTargetPowerCck, |
| 815 | AR9285_NUM_2G_CCK_TARGET_POWERS3, tpow_cck); |
| 816 | |
| 817 | /* Get OFDM target powers. */ |
| 818 | ar5008_get_lg_tpow(sc, c, AR_CTL_11G2, eep->calTargetPower2G, |
| 819 | AR9285_NUM_2G_20_TARGET_POWERS3, tpow_ofdm); |
| 820 | |
| 821 | /* Get HT-20 target powers. */ |
| 822 | ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT205, eep->calTargetPower2GHT20, |
| 823 | AR9285_NUM_2G_20_TARGET_POWERS3, tpow_ht20); |
| 824 | |
| 825 | if (extc != NULL((void *)0)) { |
| 826 | /* Get HT-40 target powers. */ |
| 827 | ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT407, |
| 828 | eep->calTargetPower2GHT40, AR9285_NUM_2G_40_TARGET_POWERS3, |
| 829 | tpow_ht40); |
| 830 | |
| 831 | /* Get secondary channel CCK target powers. */ |
| 832 | ar5008_get_lg_tpow(sc, extc, AR_CTL_11B1, |
| 833 | eep->calTargetPowerCck, AR9285_NUM_2G_CCK_TARGET_POWERS3, |
| 834 | tpow_cck_ext); |
| 835 | |
| 836 | /* Get secondary channel OFDM target powers. */ |
| 837 | ar5008_get_lg_tpow(sc, extc, AR_CTL_11G2, |
| 838 | eep->calTargetPower2G, AR9285_NUM_2G_20_TARGET_POWERS3, |
| 839 | tpow_ofdm_ext); |
| 840 | } |
| 841 | |
| 842 | memset(power, 0, sizeof(power))__builtin_memset((power), (0), (sizeof(power))); |
| 843 | /* Shuffle target powers across transmit rates. */ |
| 844 | power[ATHN_POWER_OFDM60 ] = |
| 845 | power[ATHN_POWER_OFDM91 ] = |
| 846 | power[ATHN_POWER_OFDM122 ] = |
| 847 | power[ATHN_POWER_OFDM183 ] = |
| 848 | power[ATHN_POWER_OFDM244 ] = tpow_ofdm[0]; |
| 849 | power[ATHN_POWER_OFDM365 ] = tpow_ofdm[1]; |
| 850 | power[ATHN_POWER_OFDM486 ] = tpow_ofdm[2]; |
| 851 | power[ATHN_POWER_OFDM547 ] = tpow_ofdm[3]; |
| 852 | power[ATHN_POWER_XR15 ] = tpow_ofdm[0]; |
| 853 | power[ATHN_POWER_CCK1_LP8 ] = tpow_cck[0]; |
| 854 | power[ATHN_POWER_CCK2_LP9 ] = |
| 855 | power[ATHN_POWER_CCK2_SP10 ] = tpow_cck[1]; |
| 856 | power[ATHN_POWER_CCK55_LP11] = |
| 857 | power[ATHN_POWER_CCK55_SP12] = tpow_cck[2]; |
| 858 | power[ATHN_POWER_CCK11_LP13] = |
| 859 | power[ATHN_POWER_CCK11_SP14] = tpow_cck[3]; |
| 860 | for (i = 0; i < nitems(tpow_ht20)(sizeof((tpow_ht20)) / sizeof((tpow_ht20)[0])); i++) |
| 861 | power[ATHN_POWER_HT20(i)(16 + (i))] = tpow_ht20[i]; |
| 862 | if (extc != NULL((void *)0)) { |
| 863 | /* Correct PAR difference between HT40 and HT20/Legacy. */ |
| 864 | if (sc->eep_rev >= AR_EEP_MINOR_VER_22) |
| 865 | ht40inc = modal->ht40PowerIncForPdadc; |
| 866 | else |
| 867 | ht40inc = AR_HT40_POWER_INC_FOR_PDADC2; |
| 868 | for (i = 0; i < nitems(tpow_ht40)(sizeof((tpow_ht40)) / sizeof((tpow_ht40)[0])); i++) |
| 869 | power[ATHN_POWER_HT40(i)(40 + (i))] = tpow_ht40[i] + ht40inc; |
| 870 | power[ATHN_POWER_OFDM_DUP65] = tpow_ht40[0]; |
| 871 | power[ATHN_POWER_CCK_DUP64 ] = tpow_ht40[0]; |
| 872 | power[ATHN_POWER_OFDM_EXT67] = tpow_ofdm_ext[0]; |
| 873 | power[ATHN_POWER_CCK_EXT66 ] = tpow_cck_ext[0]; |
| 874 | } |
| 875 | |
| 876 | for (i = 0; i < ATHN_POWER_COUNT68; i++) { |
| 877 | power[i] -= AR_PWR_TABLE_OFFSET_DB(-5) * 2; /* In half dB. */ |
| 878 | if (power[i] > AR_MAX_RATE_POWER63) |
| 879 | power[i] = AR_MAX_RATE_POWER63; |
| 880 | } |
| 881 | |
| 882 | /* Commit transmit power values to hardware. */ |
| 883 | ar5008_write_txpower(sc, power); |
| 884 | } |