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

          Line data    Source code
       1             : /*      $OpenBSD: ar9280.c,v 1.26 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 AR9220, AR9223, AR9280 and AR9281 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>     /* We share the ROM layout. */
      62             : #include <dev/ic/ar9280reg.h>
      63             : 
      64             : int     ar9280_attach(struct athn_softc *);
      65             : void    ar9280_setup(struct athn_softc *);
      66             : int     ar9280_set_synth(struct athn_softc *, struct ieee80211_channel *,
      67             :             struct ieee80211_channel *);
      68             : void    ar9280_init_from_rom(struct athn_softc *, struct ieee80211_channel *,
      69             :             struct ieee80211_channel *);
      70             : void    ar9280_spur_mitigate(struct athn_softc *, struct ieee80211_channel *,
      71             :             struct ieee80211_channel *);
      72             : void    ar9280_olpc_get_pdadcs(struct athn_softc *,
      73             :             struct ieee80211_channel *, int, uint8_t *, uint8_t *, uint8_t *);
      74             : void    ar9280_reset_rx_gain(struct athn_softc *, struct ieee80211_channel *);
      75             : void    ar9280_reset_tx_gain(struct athn_softc *, struct ieee80211_channel *);
      76             : void    ar9280_olpc_init(struct athn_softc *);
      77             : void    ar9280_olpc_temp_compensation(struct athn_softc *);
      78             : 
      79             : /* Extern functions. */
      80             : uint8_t athn_chan2fbin(struct ieee80211_channel *);
      81             : void    athn_get_pier_ival(uint8_t, const uint8_t *, int, int *, int *);
      82             : int     ar5008_attach(struct athn_softc *);
      83             : void    ar5008_set_viterbi_mask(struct athn_softc *, int);
      84             : void    ar5416_swap_rom(struct athn_softc *);
      85             : void    ar5416_set_txpower(struct athn_softc *, struct ieee80211_channel *,
      86             :             struct ieee80211_channel *);
      87             : const struct ar_spur_chan *
      88             :         ar5416_get_spur_chans(struct athn_softc *, int);
      89             : 
      90             : 
      91             : int
      92           0 : ar9280_attach(struct athn_softc *sc)
      93             : {
      94           0 :         sc->eep_base = AR5416_EEP_START_LOC;
      95           0 :         sc->eep_size = sizeof(struct ar5416_eeprom);
      96           0 :         sc->def_nf = AR9280_PHY_CCA_MAX_GOOD_VALUE;
      97           0 :         sc->ngpiopins = (sc->flags & ATHN_FLAG_USB) ? 16 : 10;
      98           0 :         sc->led_pin = 1;
      99           0 :         sc->workaround = AR9280_WA_DEFAULT;
     100           0 :         sc->ops.setup = ar9280_setup;
     101           0 :         sc->ops.swap_rom = ar5416_swap_rom;
     102           0 :         sc->ops.init_from_rom = ar9280_init_from_rom;
     103           0 :         sc->ops.set_txpower = ar5416_set_txpower;
     104           0 :         sc->ops.set_synth = ar9280_set_synth;
     105           0 :         sc->ops.spur_mitigate = ar9280_spur_mitigate;
     106           0 :         sc->ops.get_spur_chans = ar5416_get_spur_chans;
     107           0 :         sc->ops.olpc_init = ar9280_olpc_init;
     108           0 :         sc->ops.olpc_temp_compensation = ar9280_olpc_temp_compensation;
     109           0 :         sc->ini = &ar9280_2_0_ini;
     110           0 :         sc->serdes = &ar9280_2_0_serdes;
     111             : 
     112           0 :         return (ar5008_attach(sc));
     113             : }
     114             : 
     115             : void
     116           0 : ar9280_setup(struct athn_softc *sc)
     117             : {
     118           0 :         const struct ar5416_eeprom *eep = sc->eep;
     119             :         uint8_t type;
     120             : 
     121             :         /* Determine if open loop power control should be used. */
     122           0 :         if (sc->eep_rev >= AR_EEP_MINOR_VER_19 &&
     123           0 :             eep->baseEepHeader.openLoopPwrCntl)
     124           0 :                 sc->flags |= ATHN_FLAG_OLPC;
     125             : 
     126             :         /* Determine if fast PLL clock is supported. */
     127           0 :         if (AR_SREV_9280_20(sc) &&
     128           0 :             (sc->eep_rev <= AR_EEP_MINOR_VER_16 ||
     129           0 :              eep->baseEepHeader.fastClk5g))
     130           0 :                 sc->flags |= ATHN_FLAG_FAST_PLL_CLOCK;
     131             : 
     132             :         /*
     133             :          * Determine if initialization value for AR_AN_TOP2 must be fixed.
     134             :          * This is required for some AR9220 devices such as Ubiquiti SR71-12.
     135             :          */
     136           0 :         if (AR_SREV_9280_20(sc) &&
     137           0 :             sc->eep_rev > AR_EEP_MINOR_VER_10 &&
     138           0 :             !eep->baseEepHeader.pwdclkind) {
     139             :                 DPRINTF(("AR_AN_TOP2 fixup required\n"));
     140           0 :                 sc->flags |= ATHN_FLAG_AN_TOP2_FIXUP;
     141           0 :         }
     142             : 
     143           0 :         if (AR_SREV_9280_20(sc)) {
     144             :                 /* Check if we have a valid rxGainType field in ROM. */
     145           0 :                 if (sc->eep_rev >= AR_EEP_MINOR_VER_17) {
     146             :                         /* Select initialization values based on ROM. */
     147           0 :                         type = eep->baseEepHeader.rxGainType;
     148             :                         DPRINTF(("Rx gain type=0x%x\n", type));
     149           0 :                         if (type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
     150           0 :                                 sc->rx_gain = &ar9280_2_0_rx_gain_23db_backoff;
     151           0 :                         else if (type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
     152           0 :                                 sc->rx_gain = &ar9280_2_0_rx_gain_13db_backoff;
     153             :                         else
     154           0 :                                 sc->rx_gain = &ar9280_2_0_rx_gain;
     155             :                 } else
     156           0 :                         sc->rx_gain = &ar9280_2_0_rx_gain;
     157             : 
     158             :                 /* Check if we have a valid txGainType field in ROM. */
     159           0 :                 if (sc->eep_rev >= AR_EEP_MINOR_VER_19) {
     160             :                         /* Select initialization values based on ROM. */
     161           0 :                         type = eep->baseEepHeader.txGainType;
     162             :                         DPRINTF(("Tx gain type=0x%x\n", type));
     163           0 :                         if (type == AR_EEP_TXGAIN_HIGH_POWER)
     164           0 :                                 sc->tx_gain = &ar9280_2_0_tx_gain_high_power;
     165             :                         else
     166           0 :                                 sc->tx_gain = &ar9280_2_0_tx_gain;
     167             :                 } else
     168           0 :                         sc->tx_gain = &ar9280_2_0_tx_gain;
     169             :         }
     170           0 : }
     171             : 
     172             : int
     173           0 : ar9280_set_synth(struct athn_softc *sc, struct ieee80211_channel *c,
     174             :     struct ieee80211_channel *extc)
     175             : {
     176             :         uint32_t phy, reg, ndiv = 0;
     177           0 :         uint32_t freq = c->ic_freq;
     178             : 
     179           0 :         phy = AR_READ(sc, AR9280_PHY_SYNTH_CONTROL) & ~0x3fffffff;
     180             : 
     181           0 :         if (IEEE80211_IS_CHAN_2GHZ(c)) {
     182           0 :                 phy |= (freq << 16) / 15;
     183           0 :                 phy |= AR9280_BMODE | AR9280_FRACMODE;
     184             : 
     185           0 :                 if (AR_SREV_9287_11_OR_LATER(sc)) {
     186             :                         /* NB: Magic values from the Linux driver. */
     187           0 :                         if (freq == 2484) {     /* Channel 14. */
     188             :                                 /* Japanese regulatory requirements. */
     189           0 :                                 AR_WRITE(sc, AR_PHY(637), 0x00000000);
     190           0 :                                 AR_WRITE(sc, AR_PHY(638), 0xefff0301);
     191           0 :                                 AR_WRITE(sc, AR_PHY(639), 0xca9228ee);
     192           0 :                         } else {
     193           0 :                                 AR_WRITE(sc, AR_PHY(637), 0x00fffeff);
     194           0 :                                 AR_WRITE(sc, AR_PHY(638), 0x00f5f9ff);
     195           0 :                                 AR_WRITE(sc, AR_PHY(639), 0xb79f6427);
     196             :                         }
     197             :                 } else {
     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             :         } else {
     206           0 :                 if (AR_SREV_9285_10_OR_LATER(sc) ||
     207           0 :                     sc->eep_rev < AR_EEP_MINOR_VER_22 ||
     208           0 :                     !((struct ar5416_base_eep_header *)sc->eep)->frac_n_5g) {
     209           0 :                         if ((freq % 20) == 0) {
     210           0 :                                 ndiv = (freq * 3) / 60;
     211           0 :                                 phy |= SM(AR9280_AMODE_REFSEL, 3);
     212           0 :                         } else if ((freq % 10) == 0) {
     213           0 :                                 ndiv = (freq * 6) / 60;
     214           0 :                                 phy |= SM(AR9280_AMODE_REFSEL, 2);
     215           0 :                         }
     216             :                 }
     217           0 :                 if (ndiv != 0) {
     218           0 :                         phy |= (ndiv & 0x1ff) << 17;
     219           0 :                         phy |= (ndiv & ~0x1ff) * 2;
     220           0 :                 } else {
     221           0 :                         phy |= (freq << 15) / 15;
     222           0 :                         phy |= AR9280_FRACMODE;
     223             : 
     224           0 :                         reg = AR_READ(sc, AR_AN_SYNTH9);
     225           0 :                         reg = RW(reg, AR_AN_SYNTH9_REFDIVA, 1);
     226           0 :                         AR_WRITE(sc, AR_AN_SYNTH9, reg);
     227             :                 }
     228             :         }
     229           0 :         AR_WRITE_BARRIER(sc);
     230             :         DPRINTFN(4, ("AR9280_PHY_SYNTH_CONTROL=0x%08x\n", phy));
     231           0 :         AR_WRITE(sc, AR9280_PHY_SYNTH_CONTROL, phy);
     232           0 :         AR_WRITE_BARRIER(sc);
     233           0 :         return (0);
     234             : }
     235             : 
     236             : void
     237           0 : ar9280_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c,
     238             :     struct ieee80211_channel *extc)
     239             : {
     240             :         static const uint32_t chainoffset[] = { 0x0000, 0x2000, 0x1000 };
     241           0 :         const struct ar5416_eeprom *eep = sc->eep;
     242             :         const struct ar5416_modal_eep_header *modal;
     243             :         uint32_t reg, offset;
     244             :         uint8_t txRxAtten;
     245             :         int i;
     246             : 
     247           0 :         modal = &eep->modalHeader[IEEE80211_IS_CHAN_2GHZ(c)];
     248             : 
     249           0 :         AR_WRITE(sc, AR_PHY_SWITCH_COM, modal->antCtrlCommon);
     250             : 
     251           0 :         for (i = 0; i < AR9280_MAX_CHAINS; i++) {
     252           0 :                 if (sc->rxchainmask == 0x5 || sc->txchainmask == 0x5)
     253           0 :                         offset = chainoffset[i];
     254             :                 else
     255           0 :                         offset = i * 0x1000;
     256             : 
     257           0 :                 AR_WRITE(sc, AR_PHY_SWITCH_CHAIN_0 + offset,
     258             :                     modal->antCtrlChain[i]);
     259             : 
     260           0 :                 reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0 + offset);
     261           0 :                 reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
     262             :                     modal->iqCalICh[i]);
     263           0 :                 reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
     264             :                     modal->iqCalQCh[i]);
     265           0 :                 AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0 + offset, reg);
     266             : 
     267           0 :                 if (sc->eep_rev >= AR_EEP_MINOR_VER_3) {
     268           0 :                         reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset);
     269           0 :                         reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
     270             :                             modal->bswMargin[i]);
     271           0 :                         reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,
     272             :                             modal->bswAtten[i]);
     273           0 :                         reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
     274             :                             modal->xatten2Margin[i]);
     275           0 :                         reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_DB,
     276             :                             modal->xatten2Db[i]);
     277           0 :                         AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg);
     278           0 :                 }
     279           0 :                 if (sc->eep_rev >= AR_EEP_MINOR_VER_3)
     280           0 :                         txRxAtten = modal->txRxAttenCh[i];
     281             :                 else    /* Workaround for ROM versions < 14.3. */
     282           0 :                         txRxAtten = IEEE80211_IS_CHAN_2GHZ(c) ? 23 : 44;
     283           0 :                 reg = AR_READ(sc, AR_PHY_RXGAIN + offset);
     284           0 :                 reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN,
     285             :                     txRxAtten);
     286           0 :                 reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN,
     287             :                     modal->rxTxMarginCh[i]);
     288           0 :                 AR_WRITE(sc, AR_PHY_RXGAIN + offset, reg);
     289             :         }
     290           0 :         if (IEEE80211_IS_CHAN_2GHZ(c)) {
     291           0 :                 reg = AR_READ(sc, AR_AN_RF2G1_CH0);
     292           0 :                 reg = RW(reg, AR_AN_RF2G1_CH0_OB, modal->ob);
     293           0 :                 reg = RW(reg, AR_AN_RF2G1_CH0_DB, modal->db);
     294           0 :                 AR_WRITE(sc, AR_AN_RF2G1_CH0, reg);
     295           0 :                 AR_WRITE_BARRIER(sc);
     296           0 :                 DELAY(100);
     297             : 
     298           0 :                 reg = AR_READ(sc, AR_AN_RF2G1_CH1);
     299           0 :                 reg = RW(reg, AR_AN_RF2G1_CH1_OB, modal->ob_ch1);
     300           0 :                 reg = RW(reg, AR_AN_RF2G1_CH1_DB, modal->db_ch1);
     301           0 :                 AR_WRITE(sc, AR_AN_RF2G1_CH1, reg);
     302           0 :                 AR_WRITE_BARRIER(sc);
     303           0 :                 DELAY(100);
     304           0 :         } else {
     305           0 :                 reg = AR_READ(sc, AR_AN_RF5G1_CH0);
     306           0 :                 reg = RW(reg, AR_AN_RF5G1_CH0_OB5, modal->ob);
     307           0 :                 reg = RW(reg, AR_AN_RF5G1_CH0_DB5, modal->db);
     308           0 :                 AR_WRITE(sc, AR_AN_RF5G1_CH0, reg);
     309           0 :                 AR_WRITE_BARRIER(sc);
     310           0 :                 DELAY(100);
     311             : 
     312           0 :                 reg = AR_READ(sc, AR_AN_RF5G1_CH1);
     313           0 :                 reg = RW(reg, AR_AN_RF5G1_CH1_OB5, modal->ob_ch1);
     314           0 :                 reg = RW(reg, AR_AN_RF5G1_CH1_DB5, modal->db_ch1);
     315           0 :                 AR_WRITE(sc, AR_AN_RF5G1_CH1, reg);
     316           0 :                 AR_WRITE_BARRIER(sc);
     317           0 :                 DELAY(100);
     318             :         }
     319           0 :         reg = AR_READ(sc, AR_AN_TOP2);
     320           0 :         if ((sc->flags & ATHN_FLAG_USB) && IEEE80211_IS_CHAN_5GHZ(c)) {
     321             :                 /*
     322             :                  * Hardcode the output voltage of x-PA bias LDO to the
     323             :                  * lowest value for UB94 such that the card doesn't get
     324             :                  * too hot.
     325             :                  */
     326           0 :                 reg = RW(reg, AR_AN_TOP2_XPABIAS_LVL, 0);
     327           0 :         } else
     328           0 :                 reg = RW(reg, AR_AN_TOP2_XPABIAS_LVL, modal->xpaBiasLvl);
     329           0 :         if (modal->flagBits & AR5416_EEP_FLAG_LOCALBIAS)
     330           0 :                 reg |= AR_AN_TOP2_LOCALBIAS;
     331             :         else
     332           0 :                 reg &= ~AR_AN_TOP2_LOCALBIAS;
     333           0 :         AR_WRITE(sc, AR_AN_TOP2, reg);
     334           0 :         AR_WRITE_BARRIER(sc);
     335           0 :         DELAY(100);
     336             : 
     337           0 :         reg = AR_READ(sc, AR_PHY_XPA_CFG);
     338           0 :         if (modal->flagBits & AR5416_EEP_FLAG_FORCEXPAON)
     339           0 :                 reg |= AR_PHY_FORCE_XPA_CFG;
     340             :         else
     341           0 :                 reg &= ~AR_PHY_FORCE_XPA_CFG;
     342           0 :         AR_WRITE(sc, AR_PHY_XPA_CFG, reg);
     343             : 
     344           0 :         reg = AR_READ(sc, AR_PHY_SETTLING);
     345           0 :         reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling);
     346           0 :         AR_WRITE(sc, AR_PHY_SETTLING, reg);
     347             : 
     348           0 :         reg = AR_READ(sc, AR_PHY_DESIRED_SZ);
     349           0 :         reg = RW(reg, AR_PHY_DESIRED_SZ_ADC, modal->adcDesiredSize);
     350           0 :         AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg);
     351             : 
     352           0 :         reg =  SM(AR_PHY_RF_CTL4_TX_END_XPAA_OFF, modal->txEndToXpaOff);
     353           0 :         reg |= SM(AR_PHY_RF_CTL4_TX_END_XPAB_OFF, modal->txEndToXpaOff);
     354           0 :         reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAA_ON, modal->txFrameToXpaOn);
     355           0 :         reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAB_ON, modal->txFrameToXpaOn);
     356           0 :         AR_WRITE(sc, AR_PHY_RF_CTL4, reg);
     357             : 
     358           0 :         reg = AR_READ(sc, AR_PHY_RF_CTL3);
     359           0 :         reg = RW(reg, AR_PHY_TX_END_TO_A2_RX_ON, modal->txEndToRxOn);
     360           0 :         AR_WRITE(sc, AR_PHY_RF_CTL3, reg);
     361             : 
     362           0 :         reg = AR_READ(sc, AR_PHY_CCA(0));
     363           0 :         reg = RW(reg, AR9280_PHY_CCA_THRESH62, modal->thresh62);
     364           0 :         AR_WRITE(sc, AR_PHY_CCA(0), reg);
     365             : 
     366           0 :         reg = AR_READ(sc, AR_PHY_EXT_CCA0);
     367           0 :         reg = RW(reg, AR_PHY_EXT_CCA0_THRESH62, modal->thresh62);
     368           0 :         AR_WRITE(sc, AR_PHY_EXT_CCA0, reg);
     369             : 
     370           0 :         if (sc->eep_rev >= AR_EEP_MINOR_VER_2) {
     371           0 :                 reg = AR_READ(sc, AR_PHY_RF_CTL2);
     372           0 :                 reg = RW(reg, AR_PHY_TX_END_DATA_START,
     373             :                     modal->txFrameToDataStart);
     374           0 :                 reg = RW(reg, AR_PHY_TX_END_PA_ON, modal->txFrameToPaOn);
     375           0 :                 AR_WRITE(sc, AR_PHY_RF_CTL2, reg);
     376           0 :         }
     377           0 :         if (sc->eep_rev >= AR_EEP_MINOR_VER_3 && extc != NULL) {
     378             :                 /* Overwrite switch settling with HT-40 value. */
     379           0 :                 reg = AR_READ(sc, AR_PHY_SETTLING);
     380           0 :                 reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->swSettleHt40);
     381           0 :                 AR_WRITE(sc, AR_PHY_SETTLING, reg);
     382           0 :         }
     383           0 :         if (sc->eep_rev >= AR_EEP_MINOR_VER_19) {
     384           0 :                 reg = AR_READ(sc, AR_PHY_CCK_TX_CTRL);
     385           0 :                 reg = RW(reg, AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
     386             :                     MS(modal->miscBits, AR5416_EEP_MISC_TX_DAC_SCALE_CCK));
     387           0 :                 AR_WRITE(sc, AR_PHY_CCK_TX_CTRL, reg);
     388           0 :         }
     389           0 :         if (AR_SREV_9280_20(sc) &&
     390           0 :             sc->eep_rev >= AR_EEP_MINOR_VER_20) {
     391           0 :                 reg = AR_READ(sc, AR_AN_TOP1);
     392           0 :                 if (eep->baseEepHeader.dacLpMode &&
     393           0 :                     (IEEE80211_IS_CHAN_2GHZ(c) ||
     394           0 :                      !eep->baseEepHeader.dacHiPwrMode_5G))
     395           0 :                         reg |= AR_AN_TOP1_DACLPMODE;
     396             :                 else
     397           0 :                         reg &= ~AR_AN_TOP1_DACLPMODE;
     398           0 :                 AR_WRITE(sc, AR_AN_TOP1, reg);
     399           0 :                 AR_WRITE_BARRIER(sc);
     400           0 :                 DELAY(100);
     401             : 
     402           0 :                 reg = AR_READ(sc, AR_PHY_FRAME_CTL);
     403           0 :                 reg = RW(reg, AR_PHY_FRAME_CTL_TX_CLIP,
     404             :                     MS(modal->miscBits, AR5416_EEP_MISC_TX_CLIP));
     405           0 :                 AR_WRITE(sc, AR_PHY_FRAME_CTL, reg);
     406             : 
     407           0 :                 reg = AR_READ(sc, AR_PHY_TX_PWRCTRL9);
     408           0 :                 reg = RW(reg, AR_PHY_TX_DESIRED_SCALE_CCK,
     409             :                     eep->baseEepHeader.desiredScaleCCK);
     410           0 :                 AR_WRITE(sc, AR_PHY_TX_PWRCTRL9, reg);
     411           0 :         }
     412           0 :         AR_WRITE_BARRIER(sc);
     413           0 : }
     414             : 
     415             : void
     416           0 : ar9280_olpc_get_pdadcs(struct athn_softc *sc, struct ieee80211_channel *c,
     417             :     int chain, uint8_t *boundaries, uint8_t *pdadcs, uint8_t *txgain)
     418             : {
     419           0 :         const struct ar5416_eeprom *eep = sc->eep;
     420             :         const struct ar_cal_data_per_freq_olpc *pierdata;
     421             :         const uint8_t *pierfreq;
     422             :         uint8_t fbin, pcdac, pwr, idx;
     423           0 :         int i, lo, hi, npiers;
     424             : 
     425           0 :         if (IEEE80211_IS_CHAN_2GHZ(c)) {
     426           0 :                 pierfreq = eep->calFreqPier2G;
     427           0 :                 pierdata = (const struct ar_cal_data_per_freq_olpc *)
     428           0 :                     eep->calPierData2G[chain];
     429             :                 npiers = AR5416_NUM_2G_CAL_PIERS;
     430           0 :         } else {
     431           0 :                 pierfreq = eep->calFreqPier5G;
     432           0 :                 pierdata = (const struct ar_cal_data_per_freq_olpc *)
     433           0 :                     eep->calPierData5G[chain];
     434             :                 npiers = AR5416_NUM_5G_CAL_PIERS;
     435             :         }
     436             :         /* Find channel in ROM pier table. */
     437           0 :         fbin = athn_chan2fbin(c);
     438           0 :         athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi);
     439             : 
     440             :         /* Get average. */
     441           0 :         pwr = (pierdata[lo].pwrPdg[0][0] + pierdata[hi].pwrPdg[0][0]) / 2;
     442           0 :         pwr /= 2;       /* Convert to dB. */
     443             : 
     444             :         /* Find power control digital-to-analog converter (PCDAC) value. */
     445           0 :         pcdac = pierdata[hi].pcdac[0][0];
     446           0 :         for (idx = 0; idx < AR9280_TX_GAIN_TABLE_SIZE - 1; idx++)
     447           0 :                 if (pcdac <= sc->tx_gain_tbl[idx])
     448             :                         break;
     449           0 :         *txgain = idx;
     450             : 
     451             :         DPRINTFN(3, ("fbin=%d lo=%d hi=%d pwr=%d pcdac=%d txgain=%d\n",
     452             :             fbin, lo, hi, pwr, pcdac, idx));
     453             : 
     454             :         /* Fill phase domain analog-to-digital converter (PDADC) table. */
     455           0 :         for (i = 0; i < AR_NUM_PDADC_VALUES; i++)
     456           0 :                 pdadcs[i] = (i < pwr) ? 0x00 : 0xff;
     457             : 
     458           0 :         for (i = 0; i < AR_PD_GAINS_IN_MASK; i++)
     459           0 :                 boundaries[i] = AR9280_PD_GAIN_BOUNDARY_DEFAULT;
     460           0 : }
     461             : 
     462             : void
     463           0 : ar9280_spur_mitigate(struct athn_softc *sc, struct ieee80211_channel *c,
     464             :     struct ieee80211_channel *extc)
     465             : {
     466             :         const struct ar_spur_chan *spurchans;
     467             :         int spur, bin, spur_delta_phase, spur_freq_sd, spur_subchannel_sd;
     468             :         int spur_off, range, i;
     469             : 
     470             :         /* NB: Always clear. */
     471           0 :         AR_CLRBITS(sc, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
     472             : 
     473           0 :         range = (extc != NULL) ? 19 : 10;
     474             : 
     475           0 :         spurchans = sc->ops.get_spur_chans(sc, IEEE80211_IS_CHAN_2GHZ(c));
     476           0 :         for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
     477           0 :                 spur = spurchans[i].spurChan;
     478           0 :                 if (spur == AR_NO_SPUR)
     479           0 :                         return; /* XXX disable if it was enabled! */
     480           0 :                 spur /= 10;
     481           0 :                 if (IEEE80211_IS_CHAN_2GHZ(c))
     482           0 :                         spur += AR_BASE_FREQ_2GHZ;
     483             :                 else
     484           0 :                         spur += AR_BASE_FREQ_5GHZ;
     485           0 :                 spur -= c->ic_freq;
     486           0 :                 if (abs(spur) < range)
     487             :                         break;
     488             :         }
     489           0 :         if (i == AR_EEPROM_MODAL_SPURS)
     490           0 :                 return; /* XXX disable if it was enabled! */
     491             :         DPRINTFN(2, ("enabling spur mitigation\n"));
     492             : 
     493           0 :         AR_SETBITS(sc, AR_PHY_TIMING_CTRL4_0,
     494             :             AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
     495             :             AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
     496             :             AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
     497             :             AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
     498             : 
     499           0 :         AR_WRITE(sc, AR_PHY_SPUR_REG,
     500             :             AR_PHY_SPUR_REG_MASK_RATE_CNTL |
     501             :             AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
     502             :             AR_PHY_SPUR_REG_MASK_RATE_SELECT |
     503             :             AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
     504             :             SM(AR_PHY_SPUR_REG_SPUR_RSSI_THRESH, AR_SPUR_RSSI_THRESH));
     505             : 
     506           0 :         if (extc != NULL) {
     507           0 :                 spur_delta_phase = (spur * 262144) / 10;
     508           0 :                 if (spur < 0) {
     509             :                         spur_subchannel_sd = 1;
     510           0 :                         spur_off = spur + 10;
     511           0 :                 } else {
     512             :                         spur_subchannel_sd = 0;
     513           0 :                         spur_off = spur - 10;
     514             :                 }
     515             :         } else {
     516           0 :                 spur_delta_phase = (spur * 524288) / 10;
     517             :                 spur_subchannel_sd = 0;
     518             :                 spur_off = spur;
     519             :         }
     520           0 :         if (IEEE80211_IS_CHAN_2GHZ(c))
     521           0 :                 spur_freq_sd = (spur_off * 2048) / 44;
     522             :         else
     523           0 :                 spur_freq_sd = (spur_off * 2048) / 40;
     524             : 
     525           0 :         AR_WRITE(sc, AR_PHY_TIMING11,
     526             :             AR_PHY_TIMING11_USE_SPUR_IN_AGC |
     527             :             SM(AR_PHY_TIMING11_SPUR_FREQ_SD, spur_freq_sd) |
     528             :             SM(AR_PHY_TIMING11_SPUR_DELTA_PHASE, spur_delta_phase));
     529             : 
     530           0 :         AR_WRITE(sc, AR_PHY_SFCORR_EXT,
     531             :             SM(AR_PHY_SFCORR_SPUR_SUBCHNL_SD, spur_subchannel_sd));
     532           0 :         AR_WRITE_BARRIER(sc);
     533             : 
     534           0 :         bin = spur * 320;
     535           0 :         ar5008_set_viterbi_mask(sc, bin);
     536           0 : }
     537             : 
     538             : void
     539           0 : ar9280_reset_rx_gain(struct athn_softc *sc, struct ieee80211_channel *c)
     540             : {
     541           0 :         const struct athn_gain *prog = sc->rx_gain;
     542             :         const uint32_t *pvals;
     543             :         int i;
     544             : 
     545           0 :         if (IEEE80211_IS_CHAN_2GHZ(c))
     546           0 :                 pvals = prog->vals_2g;
     547             :         else
     548           0 :                 pvals = prog->vals_5g;
     549           0 :         for (i = 0; i < prog->nregs; i++)
     550           0 :                 AR_WRITE(sc, prog->regs[i], pvals[i]);
     551           0 : }
     552             : 
     553             : void
     554           0 : ar9280_reset_tx_gain(struct athn_softc *sc, struct ieee80211_channel *c)
     555             : {
     556           0 :         const struct athn_gain *prog = sc->tx_gain;
     557             :         const uint32_t *pvals;
     558             :         int i;
     559             : 
     560           0 :         if (IEEE80211_IS_CHAN_2GHZ(c))
     561           0 :                 pvals = prog->vals_2g;
     562             :         else
     563           0 :                 pvals = prog->vals_5g;
     564           0 :         for (i = 0; i < prog->nregs; i++)
     565           0 :                 AR_WRITE(sc, prog->regs[i], pvals[i]);
     566           0 : }
     567             : 
     568             : void
     569           0 : ar9280_olpc_init(struct athn_softc *sc)
     570             : {
     571             :         uint32_t reg;
     572             :         int i;
     573             : 
     574             :         /* Save original Tx gain values. */
     575           0 :         for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
     576           0 :                 reg = AR_READ(sc, AR_PHY_TX_GAIN_TBL(i));
     577           0 :                 sc->tx_gain_tbl[i] = MS(reg, AR_PHY_TX_GAIN);
     578             :         }
     579             :         /* Initial Tx gain temperature compensation. */
     580           0 :         sc->tcomp = 0;
     581           0 : }
     582             : 
     583             : void
     584           0 : ar9280_olpc_temp_compensation(struct athn_softc *sc)
     585             : {
     586           0 :         const struct ar5416_eeprom *eep = sc->eep;
     587             :         int8_t pdadc, txgain, tcomp;
     588             :         uint32_t reg;
     589             :         int i;
     590             : 
     591           0 :         reg = AR_READ(sc, AR_PHY_TX_PWRCTRL4);
     592           0 :         pdadc = MS(reg, AR_PHY_TX_PWRCTRL_PD_AVG_OUT);
     593             :         DPRINTFN(3, ("PD Avg Out=%d\n", pdadc));
     594             : 
     595           0 :         if (sc->pdadc == 0 || pdadc == 0)
     596           0 :                 return; /* No frames transmitted yet. */
     597             : 
     598             :         /* Compute Tx gain temperature compensation. */
     599           0 :         if (sc->eep_rev >= AR_EEP_MINOR_VER_20 &&
     600           0 :             eep->baseEepHeader.dacHiPwrMode_5G)
     601           0 :                 tcomp = (pdadc - sc->pdadc + 4) / 8;
     602             :         else
     603           0 :                 tcomp = (pdadc - sc->pdadc + 5) / 10;
     604             :         DPRINTFN(3, ("OLPC temp compensation=%d\n", tcomp));
     605             : 
     606           0 :         if (tcomp == sc->tcomp)
     607           0 :                 return; /* Don't rewrite the same values. */
     608           0 :         sc->tcomp = tcomp;
     609             : 
     610             :         /* Adjust Tx gain values. */
     611           0 :         for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) {
     612           0 :                 txgain = sc->tx_gain_tbl[i] - tcomp;
     613           0 :                 if (txgain < 0)
     614             :                         txgain = 0;
     615           0 :                 reg = AR_READ(sc, AR_PHY_TX_GAIN_TBL(i));
     616           0 :                 reg = RW(reg, AR_PHY_TX_GAIN, txgain);
     617           0 :                 AR_WRITE(sc, AR_PHY_TX_GAIN_TBL(i), reg);
     618             :         }
     619           0 :         AR_WRITE_BARRIER(sc);
     620           0 : }

Generated by: LCOV version 1.13