LCOV - code coverage report
Current view: top level - dev/ic - ar5416.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 467 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 20 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: ar5416.c,v 1.20 2017/01/12 16:32:28 stsp 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 AR5416, AR5418 and AR9160 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 NBPFILTER > 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_mira.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/ar5416reg.h>
      62             : 
      63             : int     ar5416_attach(struct athn_softc *);
      64             : void    ar5416_setup(struct athn_softc *);
      65             : void    ar5416_swap_rom(struct athn_softc *);
      66             : const struct ar_spur_chan *
      67             :         ar5416_get_spur_chans(struct athn_softc *, int);
      68             : int     ar5416_set_synth(struct athn_softc *, struct ieee80211_channel *,
      69             :             struct ieee80211_channel *);
      70             : uint8_t ar5416_reverse_bits(uint8_t, int);
      71             : uint8_t ar5416_get_rf_rev(struct athn_softc *);
      72             : void    ar5416_init_from_rom(struct athn_softc *, struct ieee80211_channel *,
      73             :             struct ieee80211_channel *);
      74             : int     ar5416_init_calib(struct athn_softc *, struct ieee80211_channel *,
      75             :             struct ieee80211_channel *);
      76             : void    ar5416_set_power_calib(struct athn_softc *,
      77             :             struct ieee80211_channel *);
      78             : void    ar5416_set_txpower(struct athn_softc *, struct ieee80211_channel *,
      79             :             struct ieee80211_channel *);
      80             : void    ar5416_spur_mitigate(struct athn_softc *, struct ieee80211_channel *,
      81             :             struct ieee80211_channel *);
      82             : void    ar5416_rw_rfbits(uint32_t *, int, int, uint32_t, int);
      83             : void    ar5416_rw_bank6tpc(struct athn_softc *, struct ieee80211_channel *,
      84             :             uint32_t *);
      85             : void    ar5416_rf_reset(struct athn_softc *, struct ieee80211_channel *);
      86             : void    ar5416_reset_bb_gain(struct athn_softc *, struct ieee80211_channel *);
      87             : void    ar5416_force_bias(struct athn_softc *, struct ieee80211_channel *);
      88             : void    ar9160_rw_addac(struct athn_softc *, struct ieee80211_channel *,
      89             :             uint32_t *);
      90             : void    ar5416_reset_addac(struct athn_softc *, struct ieee80211_channel *);
      91             : void    ar5416_get_pdadcs(struct athn_softc *, struct ieee80211_channel *,
      92             :             int, int, uint8_t, uint8_t *, uint8_t *);
      93             : 
      94             : /* Extern functions. */
      95             : uint8_t athn_chan2fbin(struct ieee80211_channel *);
      96             : void    athn_get_pier_ival(uint8_t, const uint8_t *, int, int *, int *);
      97             : int     ar5008_attach(struct athn_softc *);
      98             : void    ar5008_write_txpower(struct athn_softc *, int16_t power[]);
      99             : void    ar5008_get_pdadcs(struct athn_softc *, uint8_t, struct athn_pier *,
     100             :             struct athn_pier *, int, int, uint8_t, uint8_t *, uint8_t *);
     101             : void    ar5008_set_viterbi_mask(struct athn_softc *, int);
     102             : void    ar5008_get_lg_tpow(struct athn_softc *, struct ieee80211_channel *,
     103             :             uint8_t, const struct ar_cal_target_power_leg *, int, uint8_t[]);
     104             : void    ar5008_get_ht_tpow(struct athn_softc *, struct ieee80211_channel *,
     105             :             uint8_t, const struct ar_cal_target_power_ht *, int, uint8_t[]);
     106             : void    ar9280_olpc_get_pdadcs(struct athn_softc *, struct ieee80211_channel *,
     107             :             int, uint8_t *, uint8_t *, uint8_t *);
     108             : 
     109             : 
     110             : int
     111           0 : ar5416_attach(struct athn_softc *sc)
     112             : {
     113           0 :         sc->eep_base = AR5416_EEP_START_LOC;
     114           0 :         sc->eep_size = sizeof(struct ar5416_eeprom);
     115           0 :         sc->def_nf = AR5416_PHY_CCA_MAX_GOOD_VALUE;
     116           0 :         sc->ngpiopins = 14;
     117           0 :         sc->led_pin = 1;
     118           0 :         sc->workaround = AR5416_WA_DEFAULT;
     119           0 :         sc->ops.setup = ar5416_setup;
     120           0 :         sc->ops.swap_rom = ar5416_swap_rom;
     121           0 :         sc->ops.init_from_rom = ar5416_init_from_rom;
     122           0 :         sc->ops.set_txpower = ar5416_set_txpower;
     123           0 :         sc->ops.set_synth = ar5416_set_synth;
     124           0 :         sc->ops.spur_mitigate = ar5416_spur_mitigate;
     125           0 :         sc->ops.get_spur_chans = ar5416_get_spur_chans;
     126           0 :         if (AR_SREV_9160_10_OR_LATER(sc))
     127           0 :                 sc->ini = &ar9160_ini;
     128             :         else
     129           0 :                 sc->ini = &ar5416_ini;
     130           0 :         sc->serdes = &ar5416_serdes;
     131             : 
     132           0 :         return (ar5008_attach(sc));
     133             : }
     134             : 
     135             : void
     136           0 : ar5416_setup(struct athn_softc *sc)
     137             : {
     138             :         /* Select ADDAC programming. */
     139           0 :         if (AR_SREV_9160_11(sc))
     140           0 :                 sc->addac = &ar9160_1_1_addac;
     141           0 :         else if (AR_SREV_9160_10_OR_LATER(sc))
     142           0 :                 sc->addac = &ar9160_1_0_addac;
     143           0 :         else if (AR_SREV_5416_22_OR_LATER(sc))
     144           0 :                 sc->addac = &ar5416_2_2_addac;
     145             :         else
     146           0 :                 sc->addac = &ar5416_2_1_addac;
     147           0 : }
     148             : 
     149             : void
     150           0 : ar5416_swap_rom(struct athn_softc *sc)
     151             : {
     152           0 :         struct ar5416_eeprom *eep = sc->eep;
     153             :         struct ar5416_modal_eep_header *modal;
     154             :         int i, j;
     155             : 
     156           0 :         for (i = 0; i < 2; i++) {    /* Dual-band. */
     157           0 :                 modal = &eep->modalHeader[i];
     158             : 
     159           0 :                 modal->antCtrlCommon = swap32(modal->antCtrlCommon);
     160           0 :                 for (j = 0; j < AR5416_MAX_CHAINS; j++) {
     161           0 :                         modal->antCtrlChain[j] =
     162           0 :                             swap32(modal->antCtrlChain[j]);
     163             :                 }
     164           0 :                 for (j = 0; j < AR_EEPROM_MODAL_SPURS; j++) {
     165           0 :                         modal->spurChans[j].spurChan =
     166           0 :                             swap16(modal->spurChans[j].spurChan);
     167             :                 }
     168             :         }
     169           0 : }
     170             : 
     171             : const struct ar_spur_chan *
     172           0 : ar5416_get_spur_chans(struct athn_softc *sc, int is2ghz)
     173             : {
     174           0 :         const struct ar5416_eeprom *eep = sc->eep;
     175             : 
     176           0 :         return (eep->modalHeader[is2ghz].spurChans);
     177             : }
     178             : 
     179             : int
     180           0 : ar5416_set_synth(struct athn_softc *sc, struct ieee80211_channel *c,
     181             :     struct ieee80211_channel *extc)
     182             : {
     183             :         uint32_t phy, reg;
     184           0 :         uint32_t freq = c->ic_freq;
     185             :         uint8_t chansel;
     186             : 
     187             :         phy = 0;
     188           0 :         if (IEEE80211_IS_CHAN_2GHZ(c)) {
     189           0 :                 if (((freq - 2192) % 5) == 0) {
     190           0 :                         chansel = ((freq - 672) * 2 - 3040) / 10;
     191           0 :                 } else if (((freq - 2224) % 5) == 0) {
     192           0 :                         chansel = ((freq - 704) * 2 - 3040) / 10;
     193             :                         phy |= AR5416_BMODE_SYNTH;
     194             :                 } else
     195           0 :                         return (EINVAL);
     196           0 :                 chansel <<= 2;
     197             : 
     198           0 :                 reg = AR_READ(sc, AR_PHY_CCK_TX_CTRL);
     199           0 :                 if (freq == 2484)       /* Channel 14. */
     200           0 :                         reg |= AR_PHY_CCK_TX_CTRL_JAPAN;
     201             :                 else
     202           0 :                         reg &= ~AR_PHY_CCK_TX_CTRL_JAPAN;
     203           0 :                 AR_WRITE(sc, AR_PHY_CCK_TX_CTRL, reg);
     204             : 
     205             :                 /* Fix for orientation sensitivity issue. */
     206           0 :                 if (AR_SREV_5416(sc))
     207           0 :                         ar5416_force_bias(sc, c);
     208             :         } else {
     209           0 :                 if (freq >= 5120 && (freq % 20) == 0) {
     210           0 :                         chansel = (freq - 4800) / 20;
     211           0 :                         chansel <<= 2;
     212             :                         phy |= SM(AR5416_AMODE_REFSEL, 2);
     213           0 :                 } else if ((freq % 10) == 0) {
     214           0 :                         chansel = (freq - 4800) / 10;
     215           0 :                         chansel <<= 1;
     216           0 :                         if (AR_SREV_9160_10_OR_LATER(sc))
     217           0 :                                 phy |= SM(AR5416_AMODE_REFSEL, 1);
     218             :                         else
     219             :                                 phy |= SM(AR5416_AMODE_REFSEL, 2);
     220           0 :                 } else if ((freq % 5) == 0) {
     221           0 :                         chansel = (freq - 4800) / 5;
     222             :                         phy |= SM(AR5416_AMODE_REFSEL, 2);
     223             :                 } else
     224           0 :                         return (EINVAL);
     225             :         }
     226           0 :         chansel = ar5416_reverse_bits(chansel, 8);
     227           0 :         phy |= chansel << 8 | 1 << 5 | 1;
     228             :         DPRINTFN(4, ("AR_PHY(0x37)=0x%08x\n", phy));
     229           0 :         AR_WRITE(sc, AR_PHY(0x37), phy);
     230           0 :         return (0);
     231           0 : }
     232             : 
     233             : void
     234           0 : ar5416_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c,
     235             :     struct ieee80211_channel *extc)
     236             : {
     237             :         static const uint32_t chainoffset[] = { 0x0000, 0x2000, 0x1000 };
     238           0 :         const struct ar5416_eeprom *eep = sc->eep;
     239             :         const struct ar5416_modal_eep_header *modal;
     240             :         uint32_t reg, offset;
     241             :         uint8_t txRxAtten;
     242             :         int i;
     243             : 
     244           0 :         modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
     245             : 
     246           0 :         AR_WRITE(sc, AR_PHY_SWITCH_COM, modal->antCtrlCommon);
     247             : 
     248           0 :         for (i = 0; i < AR5416_MAX_CHAINS; i++) {
     249           0 :                 if (AR_SREV_5416_20_OR_LATER(sc) &&
     250           0 :                     (sc->rxchainmask == 0x5 || sc->txchainmask == 0x5))
     251           0 :                         offset = chainoffset[i];
     252             :                 else
     253           0 :                         offset = i * 0x1000;
     254             : 
     255           0 :                 AR_WRITE(sc, AR_PHY_SWITCH_CHAIN_0 + offset,
     256             :                     modal->antCtrlChain[i]);
     257             : 
     258           0 :                 reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0 + offset);
     259           0 :                 reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
     260             :                     modal->iqCalICh[i]);
     261           0 :                 reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
     262             :                     modal->iqCalQCh[i]);
     263           0 :                 AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0 + offset, reg);
     264             : 
     265           0 :                 if (i > 0 && !AR_SREV_5416_20_OR_LATER(sc))
     266             :                         continue;
     267             : 
     268           0 :                 if (sc->eep_rev >= AR_EEP_MINOR_VER_3) {
     269           0 :                         reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset);
     270           0 :                         reg = RW(reg, AR_PHY_GAIN_2GHZ_BSW_MARGIN,
     271             :                             modal->bswMargin[i]);
     272           0 :                         reg = RW(reg, AR_PHY_GAIN_2GHZ_BSW_ATTEN,
     273             :                             modal->bswAtten[i]);
     274           0 :                         AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg);
     275           0 :                 }
     276           0 :                 if (sc->eep_rev >= AR_EEP_MINOR_VER_3)
     277           0 :                         txRxAtten = modal->txRxAttenCh[i];
     278             :                 else    /* Workaround for ROM versions < 14.3. */
     279           0 :                         txRxAtten = IEEE80211_IS_CHAN_2GHZ(c) ? 23 : 44;
     280           0 :                 reg = AR_READ(sc, AR_PHY_RXGAIN + offset);
     281           0 :                 reg = RW(reg, AR_PHY_RXGAIN_TXRX_ATTEN, txRxAtten);
     282           0 :                 AR_WRITE(sc, AR_PHY_RXGAIN + offset, reg);
     283             : 
     284           0 :                 reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset);
     285           0 :                 reg = RW(reg, AR_PHY_GAIN_2GHZ_RXTX_MARGIN,
     286             :                     modal->rxTxMarginCh[i]);
     287           0 :                 AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg);
     288           0 :         }
     289           0 :         reg = AR_READ(sc, AR_PHY_SETTLING);
     290           0 :         reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling);
     291           0 :         AR_WRITE(sc, AR_PHY_SETTLING, reg);
     292             : 
     293           0 :         reg = AR_READ(sc, AR_PHY_DESIRED_SZ);
     294           0 :         reg = RW(reg, AR_PHY_DESIRED_SZ_ADC, modal->adcDesiredSize);
     295           0 :         reg = RW(reg, AR_PHY_DESIRED_SZ_PGA, modal->pgaDesiredSize);
     296           0 :         AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg);
     297             : 
     298           0 :         reg =  SM(AR_PHY_RF_CTL4_TX_END_XPAA_OFF, modal->txEndToXpaOff);
     299           0 :         reg |= SM(AR_PHY_RF_CTL4_TX_END_XPAB_OFF, modal->txEndToXpaOff);
     300           0 :         reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAA_ON, modal->txFrameToXpaOn);
     301           0 :         reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAB_ON, modal->txFrameToXpaOn);
     302           0 :         AR_WRITE(sc, AR_PHY_RF_CTL4, reg);
     303             : 
     304           0 :         reg = AR_READ(sc, AR_PHY_RF_CTL3);
     305           0 :         reg = RW(reg, AR_PHY_TX_END_TO_A2_RX_ON, modal->txEndToRxOn);
     306           0 :         AR_WRITE(sc, AR_PHY_RF_CTL3, reg);
     307             : 
     308           0 :         reg = AR_READ(sc, AR_PHY_CCA(0));
     309           0 :         reg = RW(reg, AR_PHY_CCA_THRESH62, modal->thresh62);
     310           0 :         AR_WRITE(sc, AR_PHY_CCA(0), reg);
     311             : 
     312           0 :         reg = AR_READ(sc, AR_PHY_EXT_CCA(0));
     313           0 :         reg = RW(reg, AR_PHY_EXT_CCA_THRESH62, modal->thresh62);
     314           0 :         AR_WRITE(sc, AR_PHY_EXT_CCA(0), reg);
     315             : 
     316           0 :         if (sc->eep_rev >= AR_EEP_MINOR_VER_2) {
     317           0 :                 reg = AR_READ(sc, AR_PHY_RF_CTL2);
     318           0 :                 reg = RW(reg, AR_PHY_TX_END_DATA_START,
     319             :                     modal->txFrameToDataStart);
     320           0 :                 reg = RW(reg, AR_PHY_TX_END_PA_ON, modal->txFrameToPaOn);
     321           0 :                 AR_WRITE(sc, AR_PHY_RF_CTL2, reg);
     322           0 :         }
     323           0 :         if (sc->eep_rev >= AR_EEP_MINOR_VER_3 && extc != NULL) {
     324             :                 /* Overwrite switch settling with HT-40 value. */
     325           0 :                 reg = AR_READ(sc, AR_PHY_SETTLING);
     326           0 :                 reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->swSettleHt40);
     327           0 :                 AR_WRITE(sc, AR_PHY_SETTLING, reg);
     328           0 :         }
     329           0 : }
     330             : 
     331             : int
     332           0 : ar5416_init_calib(struct athn_softc *sc, struct ieee80211_channel *c,
     333             :     struct ieee80211_channel *extc)
     334             : {
     335             :         int ntries;
     336             : 
     337           0 :         if (AR_SREV_9280_10_OR_LATER(sc)) {
     338             :                 /* XXX Linux tests AR9287?! */
     339           0 :                 AR_CLRBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
     340           0 :                 AR_SETBITS(sc, AR_PHY_AGC_CONTROL,
     341             :                     AR_PHY_AGC_CONTROL_FLTR_CAL);
     342           0 :         }
     343             :         /* Calibrate the AGC. */
     344           0 :         AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
     345             :         /* Poll for offset calibration completion. */
     346           0 :         for (ntries = 0; ntries < 10000; ntries++) {
     347           0 :                 if (!(AR_READ(sc, AR_PHY_AGC_CONTROL) &
     348             :                     AR_PHY_AGC_CONTROL_CAL))
     349             :                         break;
     350           0 :                 DELAY(10);
     351             :         }
     352           0 :         if (ntries == 10000)
     353           0 :                 return (ETIMEDOUT);
     354           0 :         if (AR_SREV_9280_10_OR_LATER(sc)) {
     355           0 :                 AR_SETBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
     356           0 :                 AR_CLRBITS(sc, AR_PHY_AGC_CONTROL,
     357             :                     AR_PHY_AGC_CONTROL_FLTR_CAL);
     358           0 :         }
     359           0 :         return (0);
     360           0 : }
     361             : 
     362             : void
     363           0 : ar5416_get_pdadcs(struct athn_softc *sc, struct ieee80211_channel *c,
     364             :     int chain, int nxpdgains, uint8_t overlap, uint8_t *boundaries,
     365             :     uint8_t *pdadcs)
     366             : {
     367           0 :         const struct ar5416_eeprom *eep = sc->eep;
     368             :         const struct ar5416_cal_data_per_freq *pierdata;
     369             :         const uint8_t *pierfreq;
     370           0 :         struct athn_pier lopier, hipier;
     371             :         int16_t delta;
     372             :         uint8_t fbin, pwroff;
     373           0 :         int i, lo, hi, npiers;
     374             : 
     375           0 :         if (IEEE80211_IS_CHAN_2GHZ(c)) {
     376           0 :                 pierfreq = eep->calFreqPier2G;
     377           0 :                 pierdata = eep->calPierData2G[chain];
     378             :                 npiers = AR5416_NUM_2G_CAL_PIERS;
     379           0 :         } else {
     380           0 :                 pierfreq = eep->calFreqPier5G;
     381           0 :                 pierdata = eep->calPierData5G[chain];
     382             :                 npiers = AR5416_NUM_5G_CAL_PIERS;
     383             :         }
     384             :         /* Find channel in ROM pier table. */
     385           0 :         fbin = athn_chan2fbin(c);
     386           0 :         athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi);
     387             : 
     388           0 :         lopier.fbin = pierfreq[lo];
     389           0 :         hipier.fbin = pierfreq[hi];
     390           0 :         for (i = 0; i < nxpdgains; i++) {
     391           0 :                 lopier.pwr[i] = pierdata[lo].pwrPdg[i];
     392           0 :                 lopier.vpd[i] = pierdata[lo].vpdPdg[i];
     393           0 :                 hipier.pwr[i] = pierdata[lo].pwrPdg[i];
     394           0 :                 hipier.vpd[i] = pierdata[lo].vpdPdg[i];
     395             :         }
     396           0 :         ar5008_get_pdadcs(sc, fbin, &lopier, &hipier, nxpdgains,
     397             :             AR5416_PD_GAIN_ICEPTS, overlap, boundaries, pdadcs);
     398             : 
     399           0 :         if (!AR_SREV_9280_20_OR_LATER(sc))
     400           0 :                 return;
     401             : 
     402           0 :         if (sc->eep_rev >= AR_EEP_MINOR_VER_21)
     403           0 :                 pwroff = eep->baseEepHeader.pwrTableOffset;
     404             :         else
     405             :                 pwroff = AR_PWR_TABLE_OFFSET_DB;
     406           0 :         delta = (pwroff - AR_PWR_TABLE_OFFSET_DB) * 2;  /* In half dB. */
     407             : 
     408             :         /* Change the original gain boundaries setting. */
     409           0 :         for (i = 0; i < nxpdgains; i++) {
     410             :                 /* XXX Possible overflows? */
     411           0 :                 boundaries[i] -= delta;
     412           0 :                 if (boundaries[i] > AR_MAX_RATE_POWER - overlap)
     413           0 :                         boundaries[i] = AR_MAX_RATE_POWER - overlap;
     414             :         }
     415           0 :         if (delta != 0) {
     416             :                 /* Shift the PDADC table to start at the new offset. */
     417           0 :                 for (i = 0; i < AR_NUM_PDADC_VALUES; i++)
     418           0 :                         pdadcs[i] = pdadcs[MIN(i + delta,
     419             :                             AR_NUM_PDADC_VALUES - 1)];
     420             :         }
     421           0 : }
     422             : 
     423             : void
     424           0 : ar5416_set_power_calib(struct athn_softc *sc, struct ieee80211_channel *c)
     425             : {
     426             :         static const uint32_t chainoffset[] = { 0x0000, 0x2000, 0x1000 };
     427           0 :         const struct ar5416_eeprom *eep = sc->eep;
     428             :         const struct ar5416_modal_eep_header *modal;
     429           0 :         uint8_t boundaries[AR_PD_GAINS_IN_MASK];
     430           0 :         uint8_t pdadcs[AR_NUM_PDADC_VALUES];
     431           0 :         uint8_t xpdgains[AR5416_NUM_PD_GAINS];
     432           0 :         uint8_t overlap, txgain;
     433             :         uint32_t reg, offset;
     434             :         int i, j, nxpdgains;
     435             : 
     436           0 :         modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
     437             : 
     438           0 :         if (sc->eep_rev < AR_EEP_MINOR_VER_2) {
     439           0 :                 overlap = MS(AR_READ(sc, AR_PHY_TPCRG5),
     440             :                     AR_PHY_TPCRG5_PD_GAIN_OVERLAP);
     441           0 :         } else
     442           0 :                 overlap = modal->pdGainOverlap;
     443             : 
     444           0 :         if ((sc->flags & ATHN_FLAG_OLPC) && IEEE80211_IS_CHAN_2GHZ(c)) {
     445             :                 /* XXX not here. */
     446           0 :                 sc->pdadc =
     447           0 :                     ((const struct ar_cal_data_per_freq_olpc *)
     448           0 :                      eep->calPierData2G[0])->vpdPdg[0][0];
     449           0 :         }
     450             : 
     451             :         nxpdgains = 0;
     452           0 :         memset(xpdgains, 0, sizeof(xpdgains));
     453           0 :         for (i = AR5416_PD_GAINS_IN_MASK - 1; i >= 0; i--) {
     454           0 :                 if (nxpdgains >= AR5416_NUM_PD_GAINS)
     455             :                         break;  /* Can't happen. */
     456           0 :                 if (modal->xpdGain & (1 << i))
     457           0 :                         xpdgains[nxpdgains++] = i;
     458             :         }
     459           0 :         reg = AR_READ(sc, AR_PHY_TPCRG1);
     460           0 :         reg = RW(reg, AR_PHY_TPCRG1_NUM_PD_GAIN, nxpdgains - 1);
     461           0 :         reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_1, xpdgains[0]);
     462           0 :         reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_2, xpdgains[1]);
     463           0 :         reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_3, xpdgains[2]);
     464           0 :         AR_WRITE(sc, AR_PHY_TPCRG1, reg);
     465             : 
     466           0 :         for (i = 0; i < AR5416_MAX_CHAINS; i++) {
     467           0 :                 if (!(sc->txchainmask & (1 << i)))
     468             :                         continue;
     469             : 
     470           0 :                 if (AR_SREV_5416_20_OR_LATER(sc) &&
     471           0 :                     (sc->rxchainmask == 0x5 || sc->txchainmask == 0x5))
     472           0 :                         offset = chainoffset[i];
     473             :                 else
     474           0 :                         offset = i * 0x1000;
     475             : 
     476           0 :                 if (sc->flags & ATHN_FLAG_OLPC) {
     477           0 :                         ar9280_olpc_get_pdadcs(sc, c, i, boundaries,
     478           0 :                             pdadcs, &txgain);
     479             : 
     480           0 :                         reg = AR_READ(sc, AR_PHY_TX_PWRCTRL6_0);
     481           0 :                         reg = RW(reg, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
     482           0 :                         AR_WRITE(sc, AR_PHY_TX_PWRCTRL6_0, reg);
     483             : 
     484           0 :                         reg = AR_READ(sc, AR_PHY_TX_PWRCTRL6_1);
     485           0 :                         reg = RW(reg, AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
     486           0 :                         AR_WRITE(sc, AR_PHY_TX_PWRCTRL6_1, reg);
     487             : 
     488           0 :                         reg = AR_READ(sc, AR_PHY_TX_PWRCTRL7);
     489           0 :                         reg = RW(reg, AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, txgain);
     490           0 :                         AR_WRITE(sc, AR_PHY_TX_PWRCTRL7, reg);
     491             : 
     492             :                         overlap = 6;
     493           0 :                 } else {
     494           0 :                         ar5416_get_pdadcs(sc, c, i, nxpdgains, overlap,
     495           0 :                             boundaries, pdadcs);
     496             :                 }
     497             :                 /* Write boundaries. */
     498           0 :                 if (i == 0 || AR_SREV_5416_20_OR_LATER(sc)) {
     499           0 :                         reg  = SM(AR_PHY_TPCRG5_PD_GAIN_OVERLAP,
     500             :                             overlap);
     501           0 :                         reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1,
     502             :                             boundaries[0]);
     503           0 :                         reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2,
     504             :                             boundaries[1]);
     505           0 :                         reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3,
     506             :                             boundaries[2]);
     507           0 :                         reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4,
     508             :                             boundaries[3]);
     509           0 :                         AR_WRITE(sc, AR_PHY_TPCRG5 + offset, reg);
     510           0 :                 }
     511             :                 /* Write PDADC values. */
     512           0 :                 for (j = 0; j < AR_NUM_PDADC_VALUES; j += 4) {
     513           0 :                         AR_WRITE(sc, AR_PHY_PDADC_TBL_BASE + offset + j,
     514             :                             pdadcs[j + 0] <<  0 |
     515             :                             pdadcs[j + 1] <<  8 |
     516             :                             pdadcs[j + 2] << 16 |
     517             :                             pdadcs[j + 3] << 24);
     518             :                 }
     519             :         }
     520           0 : }
     521             : 
     522             : void
     523           0 : ar5416_set_txpower(struct athn_softc *sc, struct ieee80211_channel *c,
     524             :     struct ieee80211_channel *extc)
     525             : {
     526           0 :         const struct ar5416_eeprom *eep = sc->eep;
     527             :         const struct ar5416_modal_eep_header *modal;
     528           0 :         uint8_t tpow_cck[4], tpow_ofdm[4];
     529           0 :         uint8_t tpow_cck_ext[4], tpow_ofdm_ext[4];
     530           0 :         uint8_t tpow_ht20[8], tpow_ht40[8];
     531             :         uint8_t ht40inc;
     532           0 :         int16_t pwr = 0, pwroff, max_ant_gain, power[ATHN_POWER_COUNT];
     533             :         uint8_t cckinc;
     534             :         int i;
     535             : 
     536           0 :         ar5416_set_power_calib(sc, c);
     537             : 
     538           0 :         modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
     539             : 
     540             :         /* Compute transmit power reduction due to antenna gain. */
     541           0 :         max_ant_gain = MAX(modal->antennaGainCh[0], modal->antennaGainCh[1]);
     542           0 :         max_ant_gain = MAX(modal->antennaGainCh[2], max_ant_gain);
     543             :         /* XXX */
     544             : 
     545             :         /*
     546             :          * Reduce scaled power by number of active chains to get per-chain
     547             :          * transmit power level.
     548             :          */
     549           0 :         if (sc->ntxchains == 2)
     550           0 :                 pwr -= AR_PWR_DECREASE_FOR_2_CHAIN;
     551           0 :         else if (sc->ntxchains == 3)
     552           0 :                 pwr -= AR_PWR_DECREASE_FOR_3_CHAIN;
     553           0 :         if (pwr < 0)
     554           0 :                 pwr = 0;
     555             : 
     556           0 :         if (IEEE80211_IS_CHAN_2GHZ(c)) {
     557             :                 /* Get CCK target powers. */
     558           0 :                 ar5008_get_lg_tpow(sc, c, AR_CTL_11B, eep->calTargetPowerCck,
     559           0 :                     AR5416_NUM_2G_CCK_TARGET_POWERS, tpow_cck);
     560             : 
     561             :                 /* Get OFDM target powers. */
     562           0 :                 ar5008_get_lg_tpow(sc, c, AR_CTL_11G, eep->calTargetPower2G,
     563           0 :                     AR5416_NUM_2G_20_TARGET_POWERS, tpow_ofdm);
     564             : 
     565             :                 /* Get HT-20 target powers. */
     566           0 :                 ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT20,
     567           0 :                     eep->calTargetPower2GHT20, AR5416_NUM_2G_20_TARGET_POWERS,
     568           0 :                     tpow_ht20);
     569             : 
     570           0 :                 if (extc != NULL) {
     571             :                         /* Get HT-40 target powers. */
     572           0 :                         ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT40,
     573           0 :                             eep->calTargetPower2GHT40,
     574           0 :                             AR5416_NUM_2G_40_TARGET_POWERS, tpow_ht40);
     575             : 
     576             :                         /* Get secondary channel CCK target powers. */
     577           0 :                         ar5008_get_lg_tpow(sc, extc, AR_CTL_11B,
     578             :                             eep->calTargetPowerCck,
     579           0 :                             AR5416_NUM_2G_CCK_TARGET_POWERS, tpow_cck_ext);
     580             : 
     581             :                         /* Get secondary channel OFDM target powers. */
     582           0 :                         ar5008_get_lg_tpow(sc, extc, AR_CTL_11G,
     583             :                             eep->calTargetPower2G,
     584           0 :                             AR5416_NUM_2G_20_TARGET_POWERS, tpow_ofdm_ext);
     585           0 :                 }
     586             :         } else {
     587             :                 /* Get OFDM target powers. */
     588           0 :                 ar5008_get_lg_tpow(sc, c, AR_CTL_11A, eep->calTargetPower5G,
     589           0 :                     AR5416_NUM_5G_20_TARGET_POWERS, tpow_ofdm);
     590             : 
     591             :                 /* Get HT-20 target powers. */
     592           0 :                 ar5008_get_ht_tpow(sc, c, AR_CTL_5GHT20,
     593           0 :                     eep->calTargetPower5GHT20, AR5416_NUM_5G_20_TARGET_POWERS,
     594           0 :                     tpow_ht20);
     595             : 
     596           0 :                 if (extc != NULL) {
     597             :                         /* Get HT-40 target powers. */
     598           0 :                         ar5008_get_ht_tpow(sc, c, AR_CTL_5GHT40,
     599           0 :                             eep->calTargetPower5GHT40,
     600           0 :                             AR5416_NUM_5G_40_TARGET_POWERS, tpow_ht40);
     601             : 
     602             :                         /* Get secondary channel OFDM target powers. */
     603           0 :                         ar5008_get_lg_tpow(sc, extc, AR_CTL_11A,
     604             :                             eep->calTargetPower5G,
     605           0 :                             AR5416_NUM_5G_20_TARGET_POWERS, tpow_ofdm_ext);
     606           0 :                 }
     607             :         }
     608             : 
     609             :         /* Compute CCK/OFDM delta. */
     610           0 :         cckinc = (sc->flags & ATHN_FLAG_OLPC) ? -2 : 0;
     611             : 
     612           0 :         memset(power, 0, sizeof(power));
     613             :         /* Shuffle target powers accross transmit rates. */
     614           0 :         power[ATHN_POWER_OFDM6 ] =
     615           0 :         power[ATHN_POWER_OFDM9 ] =
     616           0 :         power[ATHN_POWER_OFDM12] =
     617           0 :         power[ATHN_POWER_OFDM18] =
     618           0 :         power[ATHN_POWER_OFDM24] = tpow_ofdm[0];
     619           0 :         power[ATHN_POWER_OFDM36] = tpow_ofdm[1];
     620           0 :         power[ATHN_POWER_OFDM48] = tpow_ofdm[2];
     621           0 :         power[ATHN_POWER_OFDM54] = tpow_ofdm[3];
     622           0 :         power[ATHN_POWER_XR    ] = tpow_ofdm[0];
     623           0 :         if (IEEE80211_IS_CHAN_2GHZ(c)) {
     624           0 :                 power[ATHN_POWER_CCK1_LP ] = tpow_cck[0] + cckinc;
     625           0 :                 power[ATHN_POWER_CCK2_LP ] =
     626           0 :                 power[ATHN_POWER_CCK2_SP ] = tpow_cck[1] + cckinc;
     627           0 :                 power[ATHN_POWER_CCK55_LP] =
     628           0 :                 power[ATHN_POWER_CCK55_SP] = tpow_cck[2] + cckinc;
     629           0 :                 power[ATHN_POWER_CCK11_LP] =
     630           0 :                 power[ATHN_POWER_CCK11_SP] = tpow_cck[3] + cckinc;
     631           0 :         }
     632           0 :         for (i = 0; i < nitems(tpow_ht20); i++)
     633           0 :                 power[ATHN_POWER_HT20(i)] = tpow_ht20[i];
     634           0 :         if (extc != NULL) {
     635             :                 /* Correct PAR difference between HT40 and HT20/Legacy. */
     636           0 :                 if (sc->eep_rev >= AR_EEP_MINOR_VER_2)
     637           0 :                         ht40inc = modal->ht40PowerIncForPdadc;
     638             :                 else
     639             :                         ht40inc = AR_HT40_POWER_INC_FOR_PDADC;
     640           0 :                 for (i = 0; i < nitems(tpow_ht40); i++)
     641           0 :                         power[ATHN_POWER_HT40(i)] = tpow_ht40[i] + ht40inc;
     642           0 :                 power[ATHN_POWER_OFDM_DUP] = tpow_ht40[0];
     643           0 :                 power[ATHN_POWER_CCK_DUP ] = tpow_ht40[0] + cckinc;
     644           0 :                 power[ATHN_POWER_OFDM_EXT] = tpow_ofdm_ext[0];
     645           0 :                 if (IEEE80211_IS_CHAN_2GHZ(c))
     646           0 :                         power[ATHN_POWER_CCK_EXT] = tpow_cck_ext[0] + cckinc;
     647             :         }
     648             : 
     649           0 :         if (AR_SREV_9280_10_OR_LATER(sc)) {
     650           0 :                 if (sc->eep_rev >= AR_EEP_MINOR_VER_21)
     651           0 :                         pwroff = eep->baseEepHeader.pwrTableOffset;
     652             :                 else
     653             :                         pwroff = AR_PWR_TABLE_OFFSET_DB;
     654           0 :                 for (i = 0; i < ATHN_POWER_COUNT; i++)
     655           0 :                         power[i] -= pwroff * 2; /* In half dB. */
     656             :         }
     657           0 :         for (i = 0; i < ATHN_POWER_COUNT; i++) {
     658           0 :                 if (power[i] > AR_MAX_RATE_POWER)
     659           0 :                         power[i] = AR_MAX_RATE_POWER;
     660             :         }
     661             : 
     662             :         /* Write transmit power values to hardware. */
     663           0 :         ar5008_write_txpower(sc, power);
     664             : 
     665             :         /*
     666             :          * Write transmit power substraction for dynamic chain changing
     667             :          * and per-packet transmit power.
     668             :          */
     669           0 :         AR_WRITE(sc, AR_PHY_POWER_TX_SUB,
     670             :             (modal->pwrDecreaseFor3Chain & 0x3f) << 6 |
     671             :             (modal->pwrDecreaseFor2Chain & 0x3f));
     672           0 : }
     673             : 
     674             : void
     675           0 : ar5416_spur_mitigate(struct athn_softc *sc, struct ieee80211_channel *c,
     676             :     struct ieee80211_channel *extc)
     677             : {
     678             :         const struct ar_spur_chan *spurchans;
     679             :         int i, spur, bin, spur_delta_phase, spur_freq_sd;
     680             : 
     681           0 :         spurchans = sc->ops.get_spur_chans(sc, IEEE80211_IS_CHAN_2GHZ(c));
     682           0 :         for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
     683           0 :                 spur = spurchans[i].spurChan;
     684           0 :                 if (spur == AR_NO_SPUR)
     685           0 :                         return; /* XXX disable if it was enabled! */
     686           0 :                 spur -= c->ic_freq * 10;
     687             :                 /* Verify range +/-9.5MHz */
     688           0 :                 if (abs(spur) < 95)
     689             :                         break;
     690             :         }
     691           0 :         if (i == AR_EEPROM_MODAL_SPURS)
     692           0 :                 return; /* XXX disable if it was enabled! */
     693             :         DPRINTFN(2, ("enabling spur mitigation\n"));
     694             : 
     695           0 :         AR_SETBITS(sc, AR_PHY_TIMING_CTRL4_0,
     696             :             AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
     697             :             AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
     698             :             AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
     699             :             AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
     700             : 
     701           0 :         AR_WRITE(sc, AR_PHY_SPUR_REG,
     702             :             AR_PHY_SPUR_REG_MASK_RATE_CNTL |
     703             :             AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
     704             :             AR_PHY_SPUR_REG_MASK_RATE_SELECT |
     705             :             AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
     706             :             SM(AR_PHY_SPUR_REG_SPUR_RSSI_THRESH, AR_SPUR_RSSI_THRESH));
     707             : 
     708           0 :         spur_delta_phase = (spur * 524288) / 100;
     709           0 :         if (IEEE80211_IS_CHAN_2GHZ(c))
     710           0 :                 spur_freq_sd = (spur * 2048) / 440;
     711             :         else
     712           0 :                 spur_freq_sd = (spur * 2048) / 400;
     713             : 
     714           0 :         AR_WRITE(sc, AR_PHY_TIMING11,
     715             :             AR_PHY_TIMING11_USE_SPUR_IN_AGC |
     716             :             SM(AR_PHY_TIMING11_SPUR_FREQ_SD, spur_freq_sd) |
     717             :             SM(AR_PHY_TIMING11_SPUR_DELTA_PHASE, spur_delta_phase));
     718             : 
     719           0 :         bin = spur * 32;
     720           0 :         ar5008_set_viterbi_mask(sc, bin);
     721           0 : }
     722             : 
     723             : uint8_t
     724           0 : ar5416_reverse_bits(uint8_t v, int nbits)
     725             : {
     726           0 :         KASSERT(nbits <= 8);
     727           0 :         v = ((v >> 1) & 0x55) | ((v & 0x55) << 1);
     728           0 :         v = ((v >> 2) & 0x33) | ((v & 0x33) << 2);
     729           0 :         v = ((v >> 4) & 0x0f) | ((v & 0x0f) << 4);
     730           0 :         return (v >> (8 - nbits));
     731             : }
     732             : 
     733             : uint8_t
     734           0 : ar5416_get_rf_rev(struct athn_softc *sc)
     735             : {
     736             :         uint8_t rev, reg;
     737             :         int i;
     738             : 
     739             :         /* Allow access to analog chips. */
     740           0 :         AR_WRITE(sc, AR_PHY(0), 0x00000007);
     741             : 
     742           0 :         AR_WRITE(sc, AR_PHY(0x36), 0x00007058);
     743           0 :         for (i = 0; i < 8; i++)
     744           0 :                 AR_WRITE(sc, AR_PHY(0x20), 0x00010000);
     745           0 :         reg = (AR_READ(sc, AR_PHY(256)) >> 24) & 0xff;
     746           0 :         reg = (reg & 0xf0) >> 4 | (reg & 0x0f) << 4;
     747             : 
     748           0 :         rev = ar5416_reverse_bits(reg, 8);
     749           0 :         if ((rev & AR_RADIO_SREV_MAJOR) == 0)
     750             :                 rev = AR_RAD5133_SREV_MAJOR;
     751           0 :         return (rev);
     752             : }
     753             : 
     754             : /*
     755             :  * Replace bits "off" to "off+nbits-1" in column "col" with the specified
     756             :  * value.
     757             :  */
     758             : void
     759           0 : ar5416_rw_rfbits(uint32_t *buf, int col, int off, uint32_t val, int nbits)
     760             : {
     761             :         int idx, bit;
     762             : 
     763           0 :         KASSERT(off >= 1 && col < 4 && nbits <= 32);
     764             : 
     765           0 :         off--;  /* Starts at 1. */
     766           0 :         while (nbits-- > 0) {
     767           0 :                 idx = off / 8;
     768           0 :                 bit = off % 8;
     769           0 :                 buf[idx] &= ~(1 << (bit + col * 8));
     770           0 :                 buf[idx] |= ((val >> nbits) & 1) << (bit + col * 8);
     771           0 :                 off++;
     772             :         }
     773           0 : }
     774             : 
     775             : /*
     776             :  * Overwrite db and ob based on ROM settings.
     777             :  */
     778             : void
     779           0 : ar5416_rw_bank6tpc(struct athn_softc *sc, struct ieee80211_channel *c,
     780             :     uint32_t *rwbank6tpc)
     781             : {
     782           0 :         const struct ar5416_eeprom *eep = sc->eep;
     783             :         const struct ar5416_modal_eep_header *modal;
     784             : 
     785           0 :         if (IEEE80211_IS_CHAN_5GHZ(c)) {
     786           0 :                 modal = &eep->modalHeader[0];
     787             :                 /* 5GHz db in column 0, bits [200-202]. */
     788           0 :                 ar5416_rw_rfbits(rwbank6tpc, 0, 200, modal->db, 3);
     789             :                 /* 5GHz ob in column 0, bits [203-205]. */
     790           0 :                 ar5416_rw_rfbits(rwbank6tpc, 0, 203, modal->ob, 3);
     791           0 :         } else {
     792           0 :                 modal = &eep->modalHeader[1];
     793             :                 /* 2GHz db in column 0, bits [194-196]. */
     794           0 :                 ar5416_rw_rfbits(rwbank6tpc, 0, 194, modal->db, 3);
     795             :                 /* 2GHz ob in column 0, bits [197-199]. */
     796           0 :                 ar5416_rw_rfbits(rwbank6tpc, 0, 197, modal->ob, 3);
     797             :         }
     798           0 : }
     799             : 
     800             : /*
     801             :  * Program analog RF.
     802             :  */
     803             : void
     804           0 : ar5416_rf_reset(struct athn_softc *sc, struct ieee80211_channel *c)
     805             : {
     806             :         const uint32_t *bank6tpc;
     807             :         int i;
     808             : 
     809             :         /* Bank 0. */
     810           0 :         AR_WRITE(sc, 0x98b0, 0x1e5795e5);
     811           0 :         AR_WRITE(sc, 0x98e0, 0x02008020);
     812             : 
     813             :         /* Bank 1. */
     814           0 :         AR_WRITE(sc, 0x98b0, 0x02108421);
     815           0 :         AR_WRITE(sc, 0x98ec, 0x00000008);
     816             : 
     817             :         /* Bank 2. */
     818           0 :         AR_WRITE(sc, 0x98b0, 0x0e73ff17);
     819           0 :         AR_WRITE(sc, 0x98e0, 0x00000420);
     820             : 
     821             :         /* Bank 3. */
     822           0 :         if (IEEE80211_IS_CHAN_5GHZ(c))
     823           0 :                 AR_WRITE(sc, 0x98f0, 0x01400018);
     824             :         else
     825           0 :                 AR_WRITE(sc, 0x98f0, 0x01c00018);
     826             : 
     827             :         /* Select the Bank 6 TPC values to use. */
     828           0 :         if (AR_SREV_9160_10_OR_LATER(sc))
     829           0 :                 bank6tpc = ar9160_bank6tpc_vals;
     830             :         else
     831             :                 bank6tpc = ar5416_bank6tpc_vals;
     832           0 :         if (sc->eep_rev >= AR_EEP_MINOR_VER_2) {
     833           0 :                 uint32_t *rwbank6tpc = sc->rwbuf;
     834             : 
     835             :                 /* Copy values from .rodata to writable buffer. */
     836           0 :                 memcpy(rwbank6tpc, bank6tpc, 32 * sizeof(uint32_t));
     837           0 :                 ar5416_rw_bank6tpc(sc, c, rwbank6tpc);
     838             :                 bank6tpc = rwbank6tpc;
     839           0 :         }
     840             :         /* Bank 6 TPC. */
     841           0 :         for (i = 0; i < 32; i++)
     842           0 :                 AR_WRITE(sc, 0x989c, bank6tpc[i]);
     843           0 :         if (IEEE80211_IS_CHAN_5GHZ(c))
     844           0 :                 AR_WRITE(sc, 0x98d0, 0x0000000f);
     845             :         else
     846           0 :                 AR_WRITE(sc, 0x98d0, 0x0010000f);
     847             : 
     848             :         /* Bank 7. */
     849           0 :         AR_WRITE(sc, 0x989c, 0x00000500);
     850           0 :         AR_WRITE(sc, 0x989c, 0x00000800);
     851           0 :         AR_WRITE(sc, 0x98cc, 0x0000000e);
     852           0 : }
     853             : 
     854             : void
     855           0 : ar5416_reset_bb_gain(struct athn_softc *sc, struct ieee80211_channel *c)
     856             : {
     857             :         const uint32_t *pvals;
     858             :         int i;
     859             : 
     860           0 :         if (IEEE80211_IS_CHAN_2GHZ(c))
     861           0 :                 pvals = ar5416_bb_rfgain_vals_2g;
     862             :         else
     863             :                 pvals = ar5416_bb_rfgain_vals_5g;
     864           0 :         for (i = 0; i < 64; i++)
     865           0 :                 AR_WRITE(sc, AR_PHY_BB_RFGAIN(i), pvals[i]);
     866           0 : }
     867             : 
     868             : /*
     869             :  * Fix orientation sensitivity issue on AR5416/2GHz by increasing
     870             :  * rf_pwd_icsyndiv.
     871             :  */
     872             : void
     873           0 : ar5416_force_bias(struct athn_softc *sc, struct ieee80211_channel *c)
     874             : {
     875           0 :         uint32_t *rwbank6 = sc->rwbuf;
     876             :         uint8_t bias;
     877             :         int i;
     878             : 
     879           0 :         KASSERT(IEEE80211_IS_CHAN_2GHZ(c));
     880             : 
     881             :         /* Copy values from .rodata to writable buffer. */
     882           0 :         memcpy(rwbank6, ar5416_bank6_vals, sizeof(ar5416_bank6_vals));
     883             : 
     884           0 :         if (c->ic_freq < 2412)
     885           0 :                 bias = 0;
     886           0 :         else if (c->ic_freq < 2422)
     887           0 :                 bias = 1;
     888             :         else
     889             :                 bias = 2;
     890           0 :         ar5416_reverse_bits(bias, 3);
     891             : 
     892             :         /* Overwrite "rf_pwd_icsyndiv" (column 3, bits [181-183].) */
     893           0 :         ar5416_rw_rfbits(rwbank6, 3, 181, bias, 3);
     894             : 
     895             :         /* Write Bank 6. */
     896           0 :         for (i = 0; i < 32; i++)
     897           0 :                 AR_WRITE(sc, 0x989c, rwbank6[i]);
     898           0 :         AR_WRITE(sc, 0x98d0, 0x0010000f);
     899           0 : }
     900             : 
     901             : /*
     902             :  * Overwrite XPA bias level based on ROM setting.
     903             :  */
     904             : void
     905           0 : ar9160_rw_addac(struct athn_softc *sc, struct ieee80211_channel *c,
     906             :     uint32_t *addac)
     907             : {
     908           0 :         struct ar5416_eeprom *eep = sc->eep;
     909             :         struct ar5416_modal_eep_header *modal;
     910             :         uint8_t fbin, bias;
     911             :         int i;
     912             : 
     913             :         /* XXX xpaBiasLvlFreq values have not been endian-swapped? */
     914             : 
     915             :         /* Get the XPA bias level to use for the specified channel. */
     916           0 :         modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
     917           0 :         if (modal->xpaBiasLvl == 0xff) {
     918           0 :                 bias = modal->xpaBiasLvlFreq[0] >> 14;
     919           0 :                 fbin = athn_chan2fbin(c);
     920           0 :                 for (i = 1; i < 3; i++) {
     921           0 :                         if (modal->xpaBiasLvlFreq[i] == 0)
     922             :                                 break;
     923           0 :                         if ((modal->xpaBiasLvlFreq[i] & 0xff) < fbin)
     924             :                                 break;
     925           0 :                         bias = modal->xpaBiasLvlFreq[i] >> 14;
     926             :                 }
     927             :         } else
     928           0 :                 bias = modal->xpaBiasLvl & 0x3;
     929             : 
     930           0 :         bias = ar5416_reverse_bits(bias, 2);    /* Put in host bit-order. */
     931             :         DPRINTFN(4, ("bias level=%d\n", bias));
     932           0 :         if (IEEE80211_IS_CHAN_2GHZ(c))
     933           0 :                 ar5416_rw_rfbits(addac, 0, 60, bias, 2);
     934             :         else
     935           0 :                 ar5416_rw_rfbits(addac, 0, 55, bias, 2);
     936           0 : }
     937             : 
     938             : void
     939           0 : ar5416_reset_addac(struct athn_softc *sc, struct ieee80211_channel *c)
     940             : {
     941           0 :         const struct athn_addac *addac = sc->addac;
     942             :         const uint32_t *pvals;
     943             :         int i;
     944             : 
     945           0 :         if (AR_SREV_9160(sc) && sc->eep_rev >= AR_EEP_MINOR_VER_7) {
     946           0 :                 uint32_t *rwaddac = sc->rwbuf;
     947             : 
     948             :                 /* Copy values from .rodata to writable buffer. */
     949           0 :                 memcpy(rwaddac, addac->vals, addac->nvals * sizeof(uint32_t));
     950           0 :                 ar9160_rw_addac(sc, c, rwaddac);
     951             :                 pvals = rwaddac;
     952           0 :         } else
     953           0 :                 pvals = addac->vals;
     954           0 :         for (i = 0; i < addac->nvals; i++)
     955           0 :                 AR_WRITE(sc, 0x989c, pvals[i]);
     956           0 :         AR_WRITE(sc, 0x98cc, 0);        /* Finalize. */
     957           0 : }

Generated by: LCOV version 1.13