| File: | dev/ic/ar9287.c |
| Warning: | line 463, column 3 Value stored to 'pwr' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: ar9287.c,v 1.30 2022/01/09 05:42:38 jsg Exp $ */ |
| 2 | |
| 3 | /*- |
| 4 | * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr> |
| 5 | * Copyright (c) 2008-2009 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 AR9227 and AR9287 chipsets. |
| 23 | */ |
| 24 | |
| 25 | #include "bpfilter.h" |
| 26 | |
| 27 | #include <sys/param.h> |
| 28 | #include <sys/sockio.h> |
| 29 | #include <sys/mbuf.h> |
| 30 | #include <sys/kernel.h> |
| 31 | #include <sys/socket.h> |
| 32 | #include <sys/systm.h> |
| 33 | #include <sys/malloc.h> |
| 34 | #include <sys/queue.h> |
| 35 | #include <sys/timeout.h> |
| 36 | #include <sys/conf.h> |
| 37 | #include <sys/device.h> |
| 38 | #include <sys/endian.h> |
| 39 | |
| 40 | #include <machine/bus.h> |
| 41 | #include <machine/intr.h> |
| 42 | |
| 43 | #if NBPFILTER1 > 0 |
| 44 | #include <net/bpf.h> |
| 45 | #endif |
| 46 | #include <net/if.h> |
| 47 | #include <net/if_media.h> |
| 48 | |
| 49 | #include <netinet/in.h> |
| 50 | #include <netinet/if_ether.h> |
| 51 | |
| 52 | #include <net80211/ieee80211_var.h> |
| 53 | #include <net80211/ieee80211_amrr.h> |
| 54 | #include <net80211/ieee80211_ra.h> |
| 55 | #include <net80211/ieee80211_radiotap.h> |
| 56 | |
| 57 | #include <dev/ic/athnreg.h> |
| 58 | #include <dev/ic/athnvar.h> |
| 59 | |
| 60 | #include <dev/ic/ar5008reg.h> |
| 61 | #include <dev/ic/ar9280reg.h> |
| 62 | #include <dev/ic/ar9287reg.h> |
| 63 | |
| 64 | int ar9287_attach(struct athn_softc *); |
| 65 | void ar9287_setup(struct athn_softc *); |
| 66 | void ar9287_swap_rom(struct athn_softc *); |
| 67 | const struct ar_spur_chan *ar9287_get_spur_chans(struct athn_softc *, int); |
| 68 | void ar9287_init_from_rom(struct athn_softc *, struct ieee80211_channel *, |
| 69 | struct ieee80211_channel *); |
| 70 | void ar9287_get_pdadcs(struct athn_softc *, struct ieee80211_channel *, |
| 71 | int, int, uint8_t, uint8_t *, uint8_t *); |
| 72 | void ar9287_olpc_get_pdgain(struct athn_softc *, struct ieee80211_channel *, |
| 73 | int, int8_t *); |
| 74 | void ar9287_set_power_calib(struct athn_softc *, |
| 75 | struct ieee80211_channel *); |
| 76 | void ar9287_set_txpower(struct athn_softc *, struct ieee80211_channel *, |
| 77 | struct ieee80211_channel *); |
| 78 | void ar9287_olpc_init(struct athn_softc *); |
| 79 | void ar9287_olpc_temp_compensation(struct athn_softc *); |
| 80 | void ar9287_1_3_enable_async_fifo(struct athn_softc *); |
| 81 | void ar9287_1_3_setup_async_fifo(struct athn_softc *); |
| 82 | |
| 83 | /* Extern functions. */ |
| 84 | uint8_t athn_chan2fbin(struct ieee80211_channel *); |
| 85 | void athn_get_pier_ival(uint8_t, const uint8_t *, int, int *, int *); |
| 86 | int ar5008_attach(struct athn_softc *); |
| 87 | void ar5008_write_txpower(struct athn_softc *, int16_t power[]); |
| 88 | void ar5008_get_pdadcs(struct athn_softc *, uint8_t, struct athn_pier *, |
| 89 | struct athn_pier *, int, int, uint8_t, uint8_t *, uint8_t *); |
| 90 | void ar5008_get_lg_tpow(struct athn_softc *, struct ieee80211_channel *, |
| 91 | uint8_t, const struct ar_cal_target_power_leg *, int, uint8_t[]); |
| 92 | void ar5008_get_ht_tpow(struct athn_softc *, struct ieee80211_channel *, |
| 93 | uint8_t, const struct ar_cal_target_power_ht *, int, uint8_t[]); |
| 94 | int ar9280_set_synth(struct athn_softc *, struct ieee80211_channel *, |
| 95 | struct ieee80211_channel *); |
| 96 | void ar9280_spur_mitigate(struct athn_softc *, struct ieee80211_channel *, |
| 97 | struct ieee80211_channel *); |
| 98 | |
| 99 | |
| 100 | int |
| 101 | ar9287_attach(struct athn_softc *sc) |
| 102 | { |
| 103 | sc->eep_base = (sc->flags & ATHN_FLAG_USB(1 << 1)) ? |
| 104 | AR9287_HTC_EEP_START_LOC256 : AR9287_EEP_START_LOC128; |
| 105 | sc->eep_size = sizeof(struct ar9287_eeprom); |
| 106 | sc->ngpiopins = (sc->flags & ATHN_FLAG_USB(1 << 1)) ? 16 : 11; |
| 107 | sc->led_pin = (sc->flags & ATHN_FLAG_USB(1 << 1)) ? 10 : 8; |
| 108 | sc->workaround = AR9285_WA_DEFAULT0x004a050b; |
| 109 | sc->ops.setup = ar9287_setup; |
| 110 | sc->ops.swap_rom = ar9287_swap_rom; |
| 111 | sc->ops.init_from_rom = ar9287_init_from_rom; |
| 112 | sc->ops.set_txpower = ar9287_set_txpower; |
| 113 | sc->ops.set_synth = ar9280_set_synth; |
| 114 | sc->ops.spur_mitigate = ar9280_spur_mitigate; |
| 115 | sc->ops.get_spur_chans = ar9287_get_spur_chans; |
| 116 | sc->ops.olpc_init = ar9287_olpc_init; |
| 117 | sc->ops.olpc_temp_compensation = ar9287_olpc_temp_compensation; |
| 118 | sc->cca_min_2g = AR9287_PHY_CCA_MIN_GOOD_VAL_2GHZ(-127); |
| 119 | sc->cca_max_2g = AR9287_PHY_CCA_MAX_GOOD_VAL_2GHZ(-97); |
| 120 | sc->ini = &ar9287_1_1_ini; |
| 121 | sc->serdes = &ar9280_2_0_serdes; |
| 122 | |
| 123 | return (ar5008_attach(sc)); |
| 124 | } |
| 125 | |
| 126 | void |
| 127 | ar9287_setup(struct athn_softc *sc) |
| 128 | { |
| 129 | const struct ar9287_eeprom *eep = sc->eep; |
| 130 | |
| 131 | /* Determine if open loop power control should be used. */ |
| 132 | if (eep->baseEepHeader.openLoopPwrCntl) |
| 133 | sc->flags |= ATHN_FLAG_OLPC(1 << 2); |
| 134 | |
| 135 | sc->rx_gain = &ar9287_1_1_rx_gain; |
| 136 | sc->tx_gain = &ar9287_1_1_tx_gain; |
| 137 | } |
| 138 | |
| 139 | void |
| 140 | ar9287_swap_rom(struct athn_softc *sc) |
| 141 | { |
| 142 | struct ar9287_eeprom *eep = sc->eep; |
| 143 | int i; |
| 144 | |
| 145 | eep->modalHeader.antCtrlCommon = |
| 146 | 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)); |
| 147 | |
| 148 | for (i = 0; i < AR9287_MAX_CHAINS2; i++) { |
| 149 | eep->modalHeader.antCtrlChain[i] = |
| 150 | swap32(eep->modalHeader.antCtrlChain[i])(__uint32_t)(__builtin_constant_p(eep->modalHeader.antCtrlChain [i]) ? (__uint32_t)(((__uint32_t)(eep->modalHeader.antCtrlChain [i]) & 0xff) << 24 | ((__uint32_t)(eep->modalHeader .antCtrlChain[i]) & 0xff00) << 8 | ((__uint32_t)(eep ->modalHeader.antCtrlChain[i]) & 0xff0000) >> 8 | ((__uint32_t)(eep->modalHeader.antCtrlChain[i]) & 0xff000000 ) >> 24) : __swap32md(eep->modalHeader.antCtrlChain[ i])); |
| 151 | } |
| 152 | for (i = 0; i < AR_EEPROM_MODAL_SPURS5; i++) { |
| 153 | eep->modalHeader.spurChans[i].spurChan = |
| 154 | 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)); |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | const struct ar_spur_chan * |
| 159 | ar9287_get_spur_chans(struct athn_softc *sc, int is2ghz) |
| 160 | { |
| 161 | const struct ar9287_eeprom *eep = sc->eep; |
| 162 | |
| 163 | KASSERT(is2ghz)((is2ghz) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/ic/ar9287.c" , 163, "is2ghz")); |
| 164 | return (eep->modalHeader.spurChans); |
| 165 | } |
| 166 | |
| 167 | void |
| 168 | ar9287_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c, |
| 169 | struct ieee80211_channel *extc) |
| 170 | { |
| 171 | const struct ar9287_eeprom *eep = sc->eep; |
| 172 | const struct ar9287_modal_eep_header *modal = &eep->modalHeader; |
| 173 | uint32_t reg, offset; |
| 174 | int i; |
| 175 | |
| 176 | AR_WRITE(sc, AR_PHY_SWITCH_COM, modal->antCtrlCommon)(sc)->ops.write((sc), (0x9964), (modal->antCtrlCommon)); |
| 177 | |
| 178 | for (i = 0; i < AR9287_MAX_CHAINS2; i++) { |
| 179 | offset = i * 0x1000; |
| 180 | |
| 181 | AR_WRITE(sc, AR_PHY_SWITCH_CHAIN_0 + offset,(sc)->ops.write((sc), (0x9960 + offset), (modal->antCtrlChain [i])) |
| 182 | modal->antCtrlChain[i])(sc)->ops.write((sc), (0x9960 + offset), (modal->antCtrlChain [i])); |
| 183 | |
| 184 | reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0 + offset)(sc)->ops.read((sc), (0x9920 + offset)); |
| 185 | reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,(((reg) & ~0x000007e0) | (((uint32_t)(modal->iqCalICh[ i]) << 5) & 0x000007e0)) |
| 186 | modal->iqCalICh[i])(((reg) & ~0x000007e0) | (((uint32_t)(modal->iqCalICh[ i]) << 5) & 0x000007e0)); |
| 187 | reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,(((reg) & ~0x0000001f) | (((uint32_t)(modal->iqCalQCh[ i]) << 0) & 0x0000001f)) |
| 188 | modal->iqCalQCh[i])(((reg) & ~0x0000001f) | (((uint32_t)(modal->iqCalQCh[ i]) << 0) & 0x0000001f)); |
| 189 | AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0 + offset, reg)(sc)->ops.write((sc), (0x9920 + offset), (reg)); |
| 190 | |
| 191 | reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset)(sc)->ops.read((sc), (0xa20c + offset)); |
| 192 | reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,(((reg) & ~0x0001f000) | (((uint32_t)(modal->bswMargin [i]) << 12) & 0x0001f000)) |
| 193 | modal->bswMargin[i])(((reg) & ~0x0001f000) | (((uint32_t)(modal->bswMargin [i]) << 12) & 0x0001f000)); |
| 194 | reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,(((reg) & ~0x0000003f) | (((uint32_t)(modal->bswAtten[ i]) << 0) & 0x0000003f)) |
| 195 | modal->bswAtten[i])(((reg) & ~0x0000003f) | (((uint32_t)(modal->bswAtten[ i]) << 0) & 0x0000003f)); |
| 196 | AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg)(sc)->ops.write((sc), (0xa20c + offset), (reg)); |
| 197 | |
| 198 | reg = AR_READ(sc, AR_PHY_RXGAIN + offset)(sc)->ops.read((sc), (0x9848 + offset)); |
| 199 | reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN,(((reg) & ~0x001fc000) | (((uint32_t)(modal->rxTxMarginCh [i]) << 14) & 0x001fc000)) |
| 200 | modal->rxTxMarginCh[i])(((reg) & ~0x001fc000) | (((uint32_t)(modal->rxTxMarginCh [i]) << 14) & 0x001fc000)); |
| 201 | reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN,(((reg) & ~0x00003f80) | (((uint32_t)(modal->txRxAttenCh [i]) << 7) & 0x00003f80)) |
| 202 | modal->txRxAttenCh[i])(((reg) & ~0x00003f80) | (((uint32_t)(modal->txRxAttenCh [i]) << 7) & 0x00003f80)); |
| 203 | AR_WRITE(sc, AR_PHY_RXGAIN + offset, reg)(sc)->ops.write((sc), (0x9848 + offset), (reg)); |
| 204 | } |
| 205 | |
| 206 | reg = AR_READ(sc, AR_PHY_SETTLING)(sc)->ops.read((sc), (0x9844)); |
| 207 | if (extc != NULL((void *)0)) |
| 208 | reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->swSettleHt40)(((reg) & ~0x00003f80) | (((uint32_t)(modal->swSettleHt40 ) << 7) & 0x00003f80)); |
| 209 | else |
| 210 | reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling)(((reg) & ~0x00003f80) | (((uint32_t)(modal->switchSettling ) << 7) & 0x00003f80)); |
| 211 | AR_WRITE(sc, AR_PHY_SETTLING, reg)(sc)->ops.write((sc), (0x9844), (reg)); |
| 212 | |
| 213 | reg = AR_READ(sc, AR_PHY_DESIRED_SZ)(sc)->ops.read((sc), (0x9850)); |
| 214 | reg = RW(reg, AR_PHY_DESIRED_SZ_ADC, modal->adcDesiredSize)(((reg) & ~0x000000ff) | (((uint32_t)(modal->adcDesiredSize ) << 0) & 0x000000ff)); |
| 215 | AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg)(sc)->ops.write((sc), (0x9850), (reg)); |
| 216 | |
| 217 | reg = SM(AR_PHY_RF_CTL4_TX_END_XPAA_OFF, modal->txEndToXpaOff)(((uint32_t)(modal->txEndToXpaOff) << 16) & 0x00ff0000 ); |
| 218 | reg |= SM(AR_PHY_RF_CTL4_TX_END_XPAB_OFF, modal->txEndToXpaOff)(((uint32_t)(modal->txEndToXpaOff) << 24) & 0xff000000 ); |
| 219 | reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAA_ON, modal->txFrameToXpaOn)(((uint32_t)(modal->txFrameToXpaOn) << 0) & 0x000000ff ); |
| 220 | reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAB_ON, modal->txFrameToXpaOn)(((uint32_t)(modal->txFrameToXpaOn) << 8) & 0x0000ff00 ); |
| 221 | AR_WRITE(sc, AR_PHY_RF_CTL4, reg)(sc)->ops.write((sc), (0x9834), (reg)); |
| 222 | |
| 223 | reg = AR_READ(sc, AR_PHY_RF_CTL3)(sc)->ops.read((sc), (0x9828)); |
| 224 | reg = RW(reg, AR_PHY_TX_END_TO_A2_RX_ON, modal->txEndToRxOn)(((reg) & ~0x00ff0000) | (((uint32_t)(modal->txEndToRxOn ) << 16) & 0x00ff0000)); |
| 225 | AR_WRITE(sc, AR_PHY_RF_CTL3, reg)(sc)->ops.write((sc), (0x9828), (reg)); |
| 226 | |
| 227 | reg = AR_READ(sc, AR_PHY_CCA(0))(sc)->ops.read((sc), ((0x9864 + (0) * 0x1000))); |
| 228 | reg = RW(reg, AR9280_PHY_CCA_THRESH62, modal->thresh62)(((reg) & ~0x000ff000) | (((uint32_t)(modal->thresh62) << 12) & 0x000ff000)); |
| 229 | AR_WRITE(sc, AR_PHY_CCA(0), reg)(sc)->ops.write((sc), ((0x9864 + (0) * 0x1000)), (reg)); |
| 230 | |
| 231 | reg = AR_READ(sc, AR_PHY_EXT_CCA0)(sc)->ops.read((sc), (0x99b8)); |
| 232 | reg = RW(reg, AR_PHY_EXT_CCA0_THRESH62, modal->thresh62)(((reg) & ~0x000000ff) | (((uint32_t)(modal->thresh62) << 0) & 0x000000ff)); |
| 233 | AR_WRITE(sc, AR_PHY_EXT_CCA0, reg)(sc)->ops.write((sc), (0x99b8), (reg)); |
| 234 | |
| 235 | reg = AR_READ(sc, AR9287_AN_RF2G3_CH0)(sc)->ops.read((sc), (0x7808)); |
| 236 | reg = RW(reg, AR9287_AN_RF2G3_DB1, modal->db1)(((reg) & ~0xe0000000) | (((uint32_t)(modal->db1) << 29) & 0xe0000000)); |
| 237 | reg = RW(reg, AR9287_AN_RF2G3_DB2, modal->db2)(((reg) & ~0x1c000000) | (((uint32_t)(modal->db2) << 26) & 0x1c000000)); |
| 238 | reg = RW(reg, AR9287_AN_RF2G3_OB_CCK, modal->ob_cck)(((reg) & ~0x03800000) | (((uint32_t)(modal->ob_cck) << 23) & 0x03800000)); |
| 239 | reg = RW(reg, AR9287_AN_RF2G3_OB_PSK, modal->ob_psk)(((reg) & ~0x00700000) | (((uint32_t)(modal->ob_psk) << 20) & 0x00700000)); |
| 240 | reg = RW(reg, AR9287_AN_RF2G3_OB_QAM, modal->ob_qam)(((reg) & ~0x000e0000) | (((uint32_t)(modal->ob_qam) << 17) & 0x000e0000)); |
| 241 | reg = RW(reg, AR9287_AN_RF2G3_OB_PAL_OFF, modal->ob_pal_off)(((reg) & ~0x0001c000) | (((uint32_t)(modal->ob_pal_off ) << 14) & 0x0001c000)); |
| 242 | AR_WRITE(sc, AR9287_AN_RF2G3_CH0, reg)(sc)->ops.write((sc), (0x7808), (reg)); |
| 243 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 244 | DELAY(100)(*delay_func)(100); |
| 245 | |
| 246 | reg = AR_READ(sc, AR9287_AN_RF2G3_CH1)(sc)->ops.read((sc), (0x785c)); |
| 247 | reg = RW(reg, AR9287_AN_RF2G3_DB1, modal->db1)(((reg) & ~0xe0000000) | (((uint32_t)(modal->db1) << 29) & 0xe0000000)); |
| 248 | reg = RW(reg, AR9287_AN_RF2G3_DB2, modal->db2)(((reg) & ~0x1c000000) | (((uint32_t)(modal->db2) << 26) & 0x1c000000)); |
| 249 | reg = RW(reg, AR9287_AN_RF2G3_OB_CCK, modal->ob_cck)(((reg) & ~0x03800000) | (((uint32_t)(modal->ob_cck) << 23) & 0x03800000)); |
| 250 | reg = RW(reg, AR9287_AN_RF2G3_OB_PSK, modal->ob_psk)(((reg) & ~0x00700000) | (((uint32_t)(modal->ob_psk) << 20) & 0x00700000)); |
| 251 | reg = RW(reg, AR9287_AN_RF2G3_OB_QAM, modal->ob_qam)(((reg) & ~0x000e0000) | (((uint32_t)(modal->ob_qam) << 17) & 0x000e0000)); |
| 252 | reg = RW(reg, AR9287_AN_RF2G3_OB_PAL_OFF, modal->ob_pal_off)(((reg) & ~0x0001c000) | (((uint32_t)(modal->ob_pal_off ) << 14) & 0x0001c000)); |
| 253 | AR_WRITE(sc, AR9287_AN_RF2G3_CH1, reg)(sc)->ops.write((sc), (0x785c), (reg)); |
| 254 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 255 | DELAY(100)(*delay_func)(100); |
| 256 | |
| 257 | reg = AR_READ(sc, AR_PHY_RF_CTL2)(sc)->ops.read((sc), (0x9824)); |
| 258 | reg = RW(reg, AR_PHY_TX_END_DATA_START, modal->txFrameToDataStart)(((reg) & ~0x000000ff) | (((uint32_t)(modal->txFrameToDataStart ) << 0) & 0x000000ff)); |
| 259 | reg = RW(reg, AR_PHY_TX_END_PA_ON, modal->txFrameToPaOn)(((reg) & ~0x0000ff00) | (((uint32_t)(modal->txFrameToPaOn ) << 8) & 0x0000ff00)); |
| 260 | AR_WRITE(sc, AR_PHY_RF_CTL2, reg)(sc)->ops.write((sc), (0x9824), (reg)); |
| 261 | |
| 262 | reg = AR_READ(sc, AR9287_AN_TOP2)(sc)->ops.read((sc), (0x78b4)); |
| 263 | reg = RW(reg, AR9287_AN_TOP2_XPABIAS_LVL, modal->xpaBiasLvl)(((reg) & ~0xc0000000) | (((uint32_t)(modal->xpaBiasLvl ) << 30) & 0xc0000000)); |
| 264 | AR_WRITE(sc, AR9287_AN_TOP2, reg)(sc)->ops.write((sc), (0x78b4), (reg)); |
| 265 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 266 | DELAY(100)(*delay_func)(100); |
| 267 | } |
| 268 | |
| 269 | void |
| 270 | ar9287_get_pdadcs(struct athn_softc *sc, struct ieee80211_channel *c, |
| 271 | int chain, int nxpdgains, uint8_t overlap, uint8_t *boundaries, |
| 272 | uint8_t *pdadcs) |
| 273 | { |
| 274 | const struct ar9287_eeprom *eep = sc->eep; |
| 275 | const struct ar9287_cal_data_per_freq *pierdata; |
| 276 | const uint8_t *pierfreq; |
| 277 | struct athn_pier lopier, hipier; |
| 278 | int16_t delta; |
| 279 | uint8_t fbin; |
| 280 | int i, lo, hi, npiers; |
| 281 | |
| 282 | pierfreq = eep->calFreqPier2G; |
| 283 | pierdata = (const struct ar9287_cal_data_per_freq *) |
| 284 | eep->calPierData2G[chain]; |
| 285 | npiers = AR9287_NUM_2G_CAL_PIERS3; |
| 286 | |
| 287 | /* Find channel in ROM pier table. */ |
| 288 | fbin = athn_chan2fbin(c); |
| 289 | athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi); |
| 290 | |
| 291 | lopier.fbin = pierfreq[lo]; |
| 292 | hipier.fbin = pierfreq[hi]; |
| 293 | for (i = 0; i < nxpdgains; i++) { |
| 294 | lopier.pwr[i] = pierdata[lo].pwrPdg[i]; |
| 295 | lopier.vpd[i] = pierdata[lo].vpdPdg[i]; |
| 296 | hipier.pwr[i] = pierdata[lo].pwrPdg[i]; |
| 297 | hipier.vpd[i] = pierdata[lo].vpdPdg[i]; |
| 298 | } |
| 299 | ar5008_get_pdadcs(sc, fbin, &lopier, &hipier, nxpdgains, |
| 300 | AR9287_PD_GAIN_ICEPTS1, overlap, boundaries, pdadcs); |
| 301 | |
| 302 | delta = (eep->baseEepHeader.pwrTableOffset - |
| 303 | AR_PWR_TABLE_OFFSET_DB(-5)) * 2; /* In half dB. */ |
| 304 | if (delta != 0) { |
| 305 | /* Shift the PDADC table to start at the new offset. */ |
| 306 | /* XXX Our padding value differs from Linux. */ |
| 307 | for (i = 0; i < AR_NUM_PDADC_VALUES128; i++) |
| 308 | pdadcs[i] = pdadcs[MIN(i + delta,(((i + delta)<(128 - 1))?(i + delta):(128 - 1)) |
| 309 | AR_NUM_PDADC_VALUES - 1)(((i + delta)<(128 - 1))?(i + delta):(128 - 1))]; |
| 310 | } |
| 311 | } |
| 312 | |
| 313 | void |
| 314 | ar9287_olpc_get_pdgain(struct athn_softc *sc, struct ieee80211_channel *c, |
| 315 | int chain, int8_t *pwr) |
| 316 | { |
| 317 | const struct ar9287_eeprom *eep = sc->eep; |
| 318 | const struct ar_cal_data_per_freq_olpc *pierdata; |
| 319 | const uint8_t *pierfreq; |
| 320 | uint8_t fbin; |
| 321 | int lo, hi, npiers; |
| 322 | |
| 323 | pierfreq = eep->calFreqPier2G; |
| 324 | pierdata = (const struct ar_cal_data_per_freq_olpc *) |
| 325 | eep->calPierData2G[chain]; |
| 326 | npiers = AR9287_NUM_2G_CAL_PIERS3; |
| 327 | |
| 328 | /* Find channel in ROM pier table. */ |
| 329 | fbin = athn_chan2fbin(c); |
| 330 | athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi); |
| 331 | |
| 332 | #if 0 |
| 333 | *pwr = athn_interpolate(fbin, |
| 334 | pierfreq[lo], pierdata[lo].pwrPdg[0][0], |
| 335 | pierfreq[hi], pierdata[hi].pwrPdg[0][0]); |
| 336 | #else |
| 337 | *pwr = (pierdata[lo].pwrPdg[0][0] + pierdata[hi].pwrPdg[0][0]) / 2; |
| 338 | #endif |
| 339 | } |
| 340 | |
| 341 | void |
| 342 | ar9287_set_power_calib(struct athn_softc *sc, struct ieee80211_channel *c) |
| 343 | { |
| 344 | const struct ar9287_eeprom *eep = sc->eep; |
| 345 | uint8_t boundaries[AR_PD_GAINS_IN_MASK4]; |
| 346 | uint8_t pdadcs[AR_NUM_PDADC_VALUES128]; |
| 347 | uint8_t xpdgains[AR9287_NUM_PD_GAINS4]; |
| 348 | int8_t txpower; |
| 349 | uint8_t overlap; |
| 350 | uint32_t reg, offset; |
| 351 | int i, j, nxpdgains; |
| 352 | |
| 353 | if (sc->eep_rev < AR_EEP_MINOR_VER_22) { |
| 354 | overlap = MS(AR_READ(sc, AR_PHY_TPCRG5),(((uint32_t)((sc)->ops.read((sc), (0xa26c))) & 0x0000000f ) >> 0) |
| 355 | AR_PHY_TPCRG5_PD_GAIN_OVERLAP)(((uint32_t)((sc)->ops.read((sc), (0xa26c))) & 0x0000000f ) >> 0); |
| 356 | } else |
| 357 | overlap = eep->modalHeader.pdGainOverlap; |
| 358 | |
| 359 | if (sc->flags & ATHN_FLAG_OLPC(1 << 2)) { |
| 360 | /* XXX not here. */ |
| 361 | sc->pdadc = |
| 362 | ((const struct ar_cal_data_per_freq_olpc *) |
| 363 | eep->calPierData2G[0])->vpdPdg[0][0]; |
| 364 | } |
| 365 | |
| 366 | nxpdgains = 0; |
| 367 | memset(xpdgains, 0, sizeof(xpdgains))__builtin_memset((xpdgains), (0), (sizeof(xpdgains))); |
| 368 | for (i = AR9287_PD_GAINS_IN_MASK4 - 1; i >= 0; i--) { |
| 369 | if (nxpdgains >= AR9287_NUM_PD_GAINS4) |
| 370 | break; /* Can't happen. */ |
| 371 | if (eep->modalHeader.xpdGain & (1 << i)) |
| 372 | xpdgains[nxpdgains++] = i; |
| 373 | } |
| 374 | reg = AR_READ(sc, AR_PHY_TPCRG1)(sc)->ops.read((sc), (0xa258)); |
| 375 | reg = RW(reg, AR_PHY_TPCRG1_NUM_PD_GAIN, nxpdgains - 1)(((reg) & ~0x0000c000) | (((uint32_t)(nxpdgains - 1) << 14) & 0x0000c000)); |
| 376 | reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_1, xpdgains[0])(((reg) & ~0x00030000) | (((uint32_t)(xpdgains[0]) << 16) & 0x00030000)); |
| 377 | reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_2, xpdgains[1])(((reg) & ~0x000c0000) | (((uint32_t)(xpdgains[1]) << 18) & 0x000c0000)); |
| 378 | AR_WRITE(sc, AR_PHY_TPCRG1, reg)(sc)->ops.write((sc), (0xa258), (reg)); |
| 379 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 380 | |
| 381 | for (i = 0; i < AR9287_MAX_CHAINS2; i++) { |
| 382 | if (!(sc->txchainmask & (1 << i))) |
| 383 | continue; |
| 384 | |
| 385 | offset = i * 0x1000; |
| 386 | |
| 387 | if (sc->flags & ATHN_FLAG_OLPC(1 << 2)) { |
| 388 | ar9287_olpc_get_pdgain(sc, c, i, &txpower); |
| 389 | |
| 390 | reg = AR_READ(sc, AR_PHY_TX_PWRCTRL6_0)(sc)->ops.read((sc), (0xa270)); |
| 391 | reg = RW(reg, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3)(((reg) & ~0x03000000) | (((uint32_t)(3) << 24) & 0x03000000)); |
| 392 | AR_WRITE(sc, AR_PHY_TX_PWRCTRL6_0, reg)(sc)->ops.write((sc), (0xa270), (reg)); |
| 393 | |
| 394 | reg = AR_READ(sc, AR_PHY_TX_PWRCTRL6_1)(sc)->ops.read((sc), (0xb270)); |
| 395 | reg = RW(reg, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3)(((reg) & ~0x03000000) | (((uint32_t)(3) << 24) & 0x03000000)); |
| 396 | AR_WRITE(sc, AR_PHY_TX_PWRCTRL6_1, reg)(sc)->ops.write((sc), (0xb270), (reg)); |
| 397 | |
| 398 | /* NB: txpower is in half dB. */ |
| 399 | reg = AR_READ(sc, AR_PHY_CH0_TX_PWRCTRL11 + offset)(sc)->ops.read((sc), (0xa398 + offset)); |
| 400 | reg = RW(reg, AR_PHY_TX_PWRCTRL_OLPC_PWR, txpower)(((reg) & ~0x00ff0000) | (((uint32_t)(txpower) << 16 ) & 0x00ff0000)); |
| 401 | AR_WRITE(sc, AR_PHY_CH0_TX_PWRCTRL11 + offset, reg)(sc)->ops.write((sc), (0xa398 + offset), (reg)); |
| 402 | |
| 403 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 404 | continue; /* That's it for open loop mode. */ |
| 405 | } |
| 406 | |
| 407 | /* Closed loop power control. */ |
| 408 | ar9287_get_pdadcs(sc, c, i, nxpdgains, overlap, |
| 409 | boundaries, pdadcs); |
| 410 | |
| 411 | /* Write boundaries. */ |
| 412 | if (i == 0) { |
| 413 | reg = SM(AR_PHY_TPCRG5_PD_GAIN_OVERLAP,(((uint32_t)(overlap) << 0) & 0x0000000f) |
| 414 | overlap)(((uint32_t)(overlap) << 0) & 0x0000000f); |
| 415 | reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1,(((uint32_t)(boundaries[0]) << 4) & 0x000003f0) |
| 416 | boundaries[0])(((uint32_t)(boundaries[0]) << 4) & 0x000003f0); |
| 417 | reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2,(((uint32_t)(boundaries[1]) << 10) & 0x0000fc00) |
| 418 | boundaries[1])(((uint32_t)(boundaries[1]) << 10) & 0x0000fc00); |
| 419 | reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3,(((uint32_t)(boundaries[2]) << 16) & 0x003f0000) |
| 420 | boundaries[2])(((uint32_t)(boundaries[2]) << 16) & 0x003f0000); |
| 421 | reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4,(((uint32_t)(boundaries[3]) << 22) & 0x0fc00000) |
| 422 | boundaries[3])(((uint32_t)(boundaries[3]) << 22) & 0x0fc00000); |
| 423 | AR_WRITE(sc, AR_PHY_TPCRG5 + offset, reg)(sc)->ops.write((sc), (0xa26c + offset), (reg)); |
| 424 | } |
| 425 | /* Write PDADC values. */ |
| 426 | for (j = 0; j < AR_NUM_PDADC_VALUES128; j += 4) { |
| 427 | AR_WRITE(sc, AR_PHY_PDADC_TBL_BASE + offset + j,(sc)->ops.write((sc), (0xa280 + offset + j), (pdadcs[j + 0 ] << 0 | pdadcs[j + 1] << 8 | pdadcs[j + 2] << 16 | pdadcs[j + 3] << 24)) |
| 428 | pdadcs[j + 0] << 0 |(sc)->ops.write((sc), (0xa280 + offset + j), (pdadcs[j + 0 ] << 0 | pdadcs[j + 1] << 8 | pdadcs[j + 2] << 16 | pdadcs[j + 3] << 24)) |
| 429 | pdadcs[j + 1] << 8 |(sc)->ops.write((sc), (0xa280 + offset + j), (pdadcs[j + 0 ] << 0 | pdadcs[j + 1] << 8 | pdadcs[j + 2] << 16 | pdadcs[j + 3] << 24)) |
| 430 | pdadcs[j + 2] << 16 |(sc)->ops.write((sc), (0xa280 + offset + j), (pdadcs[j + 0 ] << 0 | pdadcs[j + 1] << 8 | pdadcs[j + 2] << 16 | pdadcs[j + 3] << 24)) |
| 431 | pdadcs[j + 3] << 24)(sc)->ops.write((sc), (0xa280 + offset + j), (pdadcs[j + 0 ] << 0 | pdadcs[j + 1] << 8 | pdadcs[j + 2] << 16 | pdadcs[j + 3] << 24)); |
| 432 | } |
| 433 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 434 | } |
| 435 | } |
| 436 | |
| 437 | void |
| 438 | ar9287_set_txpower(struct athn_softc *sc, struct ieee80211_channel *c, |
| 439 | struct ieee80211_channel *extc) |
| 440 | { |
| 441 | const struct ar9287_eeprom *eep = sc->eep; |
| 442 | const struct ar9287_modal_eep_header *modal = &eep->modalHeader; |
| 443 | uint8_t tpow_cck[4], tpow_ofdm[4]; |
| 444 | uint8_t tpow_cck_ext[4], tpow_ofdm_ext[4]; |
| 445 | uint8_t tpow_ht20[8], tpow_ht40[8]; |
| 446 | uint8_t ht40inc; |
| 447 | int16_t pwr = 0, max_ant_gain, power[ATHN_POWER_COUNT68]; |
| 448 | int i; |
| 449 | |
| 450 | ar9287_set_power_calib(sc, c); |
| 451 | |
| 452 | /* Compute transmit power reduction due to antenna gain. */ |
| 453 | max_ant_gain = MAX(modal->antennaGainCh[0], modal->antennaGainCh[1])(((modal->antennaGainCh[0])>(modal->antennaGainCh[1] ))?(modal->antennaGainCh[0]):(modal->antennaGainCh[1])); |
| 454 | /* XXX */ |
| 455 | |
| 456 | /* |
| 457 | * Reduce scaled power by number of active chains to get per-chain |
| 458 | * transmit power level. |
| 459 | */ |
| 460 | if (sc->ntxchains == 2) |
| 461 | pwr -= AR_PWR_DECREASE_FOR_2_CHAIN6; |
| 462 | if (pwr < 0) |
| 463 | pwr = 0; |
Value stored to 'pwr' is never read | |
| 464 | |
| 465 | /* Get CCK target powers. */ |
| 466 | ar5008_get_lg_tpow(sc, c, AR_CTL_11B1, eep->calTargetPowerCck, |
| 467 | AR9287_NUM_2G_CCK_TARGET_POWERS3, tpow_cck); |
| 468 | |
| 469 | /* Get OFDM target powers. */ |
| 470 | ar5008_get_lg_tpow(sc, c, AR_CTL_11G2, eep->calTargetPower2G, |
| 471 | AR9287_NUM_2G_20_TARGET_POWERS3, tpow_ofdm); |
| 472 | |
| 473 | /* Get HT-20 target powers. */ |
| 474 | ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT205, eep->calTargetPower2GHT20, |
| 475 | AR9287_NUM_2G_20_TARGET_POWERS3, tpow_ht20); |
| 476 | |
| 477 | if (extc != NULL((void *)0)) { |
| 478 | /* Get HT-40 target powers. */ |
| 479 | ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT407, |
| 480 | eep->calTargetPower2GHT40, AR9287_NUM_2G_40_TARGET_POWERS3, |
| 481 | tpow_ht40); |
| 482 | |
| 483 | /* Get secondary channel CCK target powers. */ |
| 484 | ar5008_get_lg_tpow(sc, extc, AR_CTL_11B1, |
| 485 | eep->calTargetPowerCck, AR9287_NUM_2G_CCK_TARGET_POWERS3, |
| 486 | tpow_cck_ext); |
| 487 | |
| 488 | /* Get secondary channel OFDM target powers. */ |
| 489 | ar5008_get_lg_tpow(sc, extc, AR_CTL_11G2, |
| 490 | eep->calTargetPower2G, AR9287_NUM_2G_20_TARGET_POWERS3, |
| 491 | tpow_ofdm_ext); |
| 492 | } |
| 493 | |
| 494 | memset(power, 0, sizeof(power))__builtin_memset((power), (0), (sizeof(power))); |
| 495 | /* Shuffle target powers across transmit rates. */ |
| 496 | power[ATHN_POWER_OFDM60 ] = |
| 497 | power[ATHN_POWER_OFDM91 ] = |
| 498 | power[ATHN_POWER_OFDM122 ] = |
| 499 | power[ATHN_POWER_OFDM183 ] = |
| 500 | power[ATHN_POWER_OFDM244 ] = tpow_ofdm[0]; |
| 501 | power[ATHN_POWER_OFDM365 ] = tpow_ofdm[1]; |
| 502 | power[ATHN_POWER_OFDM486 ] = tpow_ofdm[2]; |
| 503 | power[ATHN_POWER_OFDM547 ] = tpow_ofdm[3]; |
| 504 | power[ATHN_POWER_XR15 ] = tpow_ofdm[0]; |
| 505 | power[ATHN_POWER_CCK1_LP8 ] = tpow_cck[0]; |
| 506 | power[ATHN_POWER_CCK2_LP9 ] = |
| 507 | power[ATHN_POWER_CCK2_SP10 ] = tpow_cck[1]; |
| 508 | power[ATHN_POWER_CCK55_LP11] = |
| 509 | power[ATHN_POWER_CCK55_SP12] = tpow_cck[2]; |
| 510 | power[ATHN_POWER_CCK11_LP13] = |
| 511 | power[ATHN_POWER_CCK11_SP14] = tpow_cck[3]; |
| 512 | for (i = 0; i < nitems(tpow_ht20)(sizeof((tpow_ht20)) / sizeof((tpow_ht20)[0])); i++) |
| 513 | power[ATHN_POWER_HT20(i)(16 + (i))] = tpow_ht20[i]; |
| 514 | if (extc != NULL((void *)0)) { |
| 515 | /* Correct PAR difference between HT40 and HT20/Legacy. */ |
| 516 | if (sc->eep_rev >= AR_EEP_MINOR_VER_22) |
| 517 | ht40inc = modal->ht40PowerIncForPdadc; |
| 518 | else |
| 519 | ht40inc = AR_HT40_POWER_INC_FOR_PDADC2; |
| 520 | for (i = 0; i < nitems(tpow_ht40)(sizeof((tpow_ht40)) / sizeof((tpow_ht40)[0])); i++) |
| 521 | power[ATHN_POWER_HT40(i)(40 + (i))] = tpow_ht40[i] + ht40inc; |
| 522 | power[ATHN_POWER_OFDM_DUP65] = tpow_ht40[0]; |
| 523 | power[ATHN_POWER_CCK_DUP64 ] = tpow_ht40[0]; |
| 524 | power[ATHN_POWER_OFDM_EXT67] = tpow_ofdm_ext[0]; |
| 525 | if (IEEE80211_IS_CHAN_2GHZ(c)(((c)->ic_flags & 0x0080) != 0)) |
| 526 | power[ATHN_POWER_CCK_EXT66] = tpow_cck_ext[0]; |
| 527 | } |
| 528 | |
| 529 | for (i = 0; i < ATHN_POWER_COUNT68; i++) { |
| 530 | power[i] -= AR_PWR_TABLE_OFFSET_DB(-5) * 2; /* In half dB. */ |
| 531 | if (power[i] > AR_MAX_RATE_POWER63) |
| 532 | power[i] = AR_MAX_RATE_POWER63; |
| 533 | } |
| 534 | /* Commit transmit power values to hardware. */ |
| 535 | ar5008_write_txpower(sc, power); |
| 536 | } |
| 537 | |
| 538 | void |
| 539 | ar9287_olpc_init(struct athn_softc *sc) |
| 540 | { |
| 541 | uint32_t reg; |
| 542 | |
| 543 | AR_SETBITS(sc, AR_PHY_TX_PWRCTRL9, AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL)(sc)->ops.write((sc), (0xa27c), ((sc)->ops.read((sc), ( 0xa27c)) | (0x80000000))); |
| 544 | |
| 545 | reg = AR_READ(sc, AR9287_AN_TXPC0)(sc)->ops.read((sc), (0x7898)); |
| 546 | reg = RW(reg, AR9287_AN_TXPC0_TXPCMODE,(((reg) & ~0x0000c000) | (((uint32_t)(2) << 14) & 0x0000c000)) |
| 547 | AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE)(((reg) & ~0x0000c000) | (((uint32_t)(2) << 14) & 0x0000c000)); |
| 548 | AR_WRITE(sc, AR9287_AN_TXPC0, reg)(sc)->ops.write((sc), (0x7898), (reg)); |
| 549 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 550 | DELAY(100)(*delay_func)(100); |
| 551 | } |
| 552 | |
| 553 | void |
| 554 | ar9287_olpc_temp_compensation(struct athn_softc *sc) |
| 555 | { |
| 556 | const struct ar9287_eeprom *eep = sc->eep; |
| 557 | int8_t pdadc, slope, tcomp; |
| 558 | uint32_t reg; |
| 559 | |
| 560 | reg = AR_READ(sc, AR_PHY_TX_PWRCTRL4)(sc)->ops.read((sc), (0xa264)); |
| 561 | pdadc = MS(reg, AR_PHY_TX_PWRCTRL_PD_AVG_OUT)(((uint32_t)(reg) & 0x000001fe) >> 1); |
| 562 | DPRINTFN(3, ("PD Avg Out=%d\n", pdadc)); |
| 563 | |
| 564 | if (sc->pdadc == 0 || pdadc == 0) |
| 565 | return; /* No frames transmitted yet. */ |
| 566 | |
| 567 | /* Compute Tx gain temperature compensation. */ |
| 568 | if (sc->eep_rev >= AR_EEP_MINOR_VER_22) |
| 569 | slope = eep->baseEepHeader.tempSensSlope; |
| 570 | else |
| 571 | slope = 0; |
| 572 | if (slope != 0) /* Prevents division by zero. */ |
| 573 | tcomp = ((pdadc - sc->pdadc) * 4) / slope; |
| 574 | else |
| 575 | tcomp = 0; |
| 576 | DPRINTFN(3, ("OLPC temp compensation=%d\n", tcomp)); |
| 577 | |
| 578 | /* Write compensation value for both Tx chains. */ |
| 579 | reg = AR_READ(sc, AR_PHY_CH0_TX_PWRCTRL11)(sc)->ops.read((sc), (0xa398)); |
| 580 | reg = RW(reg, AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, tcomp)(((reg) & ~0x0000fc00) | (((uint32_t)(tcomp) << 10) & 0x0000fc00)); |
| 581 | AR_WRITE(sc, AR_PHY_CH0_TX_PWRCTRL11, reg)(sc)->ops.write((sc), (0xa398), (reg)); |
| 582 | |
| 583 | reg = AR_READ(sc, AR_PHY_CH1_TX_PWRCTRL11)(sc)->ops.read((sc), (0xb398)); |
| 584 | reg = RW(reg, AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, tcomp)(((reg) & ~0x0000fc00) | (((uint32_t)(tcomp) << 10) & 0x0000fc00)); |
| 585 | AR_WRITE(sc, AR_PHY_CH1_TX_PWRCTRL11, reg)(sc)->ops.write((sc), (0xb398), (reg)); |
| 586 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 587 | } |
| 588 | |
| 589 | void |
| 590 | ar9287_1_3_enable_async_fifo(struct athn_softc *sc) |
| 591 | { |
| 592 | /* Enable ASYNC FIFO. */ |
| 593 | AR_SETBITS(sc, AR_MAC_PCU_ASYNC_FIFO_REG3,(sc)->ops.write((sc), (0x8358), ((sc)->ops.read((sc), ( 0x8358)) | (0x00000400))) |
| 594 | AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL)(sc)->ops.write((sc), (0x8358), ((sc)->ops.read((sc), ( 0x8358)) | (0x00000400))); |
| 595 | AR_SETBITS(sc, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO)(sc)->ops.write((sc), (0xa200), ((sc)->ops.read((sc), ( 0xa200)) | (0x00000080))); |
| 596 | AR_CLRBITS(sc, AR_MAC_PCU_ASYNC_FIFO_REG3,(sc)->ops.write((sc), (0x8358), ((sc)->ops.read((sc), ( 0x8358)) & ~(0x80000000))) |
| 597 | AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET)(sc)->ops.write((sc), (0x8358), ((sc)->ops.read((sc), ( 0x8358)) & ~(0x80000000))); |
| 598 | AR_SETBITS(sc, AR_MAC_PCU_ASYNC_FIFO_REG3,(sc)->ops.write((sc), (0x8358), ((sc)->ops.read((sc), ( 0x8358)) | (0x80000000))) |
| 599 | AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET)(sc)->ops.write((sc), (0x8358), ((sc)->ops.read((sc), ( 0x8358)) | (0x80000000))); |
| 600 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 601 | } |
| 602 | |
| 603 | void |
| 604 | ar9287_1_3_setup_async_fifo(struct athn_softc *sc) |
| 605 | { |
| 606 | uint32_t reg; |
| 607 | |
| 608 | /* |
| 609 | * MAC runs at 117MHz (instead of 88/44MHz) when ASYNC FIFO is |
| 610 | * enabled, so the following counters have to be changed. |
| 611 | */ |
| 612 | AR_WRITE(sc, AR_D_GBL_IFS_SIFS, AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR)(sc)->ops.write((sc), (0x1030), (0x000003ab)); |
| 613 | AR_WRITE(sc, AR_D_GBL_IFS_SLOT, AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR)(sc)->ops.write((sc), (0x1070), (0x00000420)); |
| 614 | AR_WRITE(sc, AR_D_GBL_IFS_EIFS, AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR)(sc)->ops.write((sc), (0x10b0), (0x0000a5eb)); |
| 615 | |
| 616 | AR_WRITE(sc, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR)(sc)->ops.write((sc), (0x8014), (0x16001d56)); |
| 617 | AR_WRITE(sc, AR_USEC, AR_USEC_ASYNC_FIFO_DUR)(sc)->ops.write((sc), (0x801c), (0x12e00074)); |
| 618 | |
| 619 | AR_SETBITS(sc, AR_MAC_PCU_LOGIC_ANALYZER,(sc)->ops.write((sc), (0x8264), ((sc)->ops.read((sc), ( 0x8264)) | (0x20000000))) |
| 620 | AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768)(sc)->ops.write((sc), (0x8264), ((sc)->ops.read((sc), ( 0x8264)) | (0x20000000))); |
| 621 | |
| 622 | reg = AR_READ(sc, AR_AHB_MODE)(sc)->ops.read((sc), (0x4024)); |
| 623 | reg = RW(reg, AR_AHB_CUSTOM_BURST, AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL)(((reg) & ~0x000000c0) | (((uint32_t)(3) << 6) & 0x000000c0)); |
| 624 | AR_WRITE(sc, AR_AHB_MODE, reg)(sc)->ops.write((sc), (0x4024), (reg)); |
| 625 | |
| 626 | AR_SETBITS(sc, AR_PCU_MISC_MODE2, AR_PCU_MISC_MODE2_ENABLE_AGGWEP)(sc)->ops.write((sc), (0x8344), ((sc)->ops.read((sc), ( 0x8344)) | (0x00020000))); |
| 627 | AR_WRITE_BARRIER(sc)(sc)->ops.write_barrier((sc)); |
| 628 | } |