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

          Line data    Source code
       1             : /*      $OpenBSD: ar9285.c,v 1.27 2017/01/12 16:32:28 stsp Exp $        */
       2             : 
       3             : /*-
       4             :  * Copyright (c) 2009-2010 Damien Bergamini <damien.bergamini@free.fr>
       5             :  * Copyright (c) 2008-2010 Atheros Communications Inc.
       6             :  *
       7             :  * Permission to use, copy, modify, and/or distribute this software for any
       8             :  * purpose with or without fee is hereby granted, provided that the above
       9             :  * copyright notice and this permission notice appear in all copies.
      10             :  *
      11             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      12             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      13             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      14             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      15             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      16             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      17             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      18             :  */
      19             : 
      20             : /*
      21             :  * Driver for Atheros 802.11a/g/n chipsets.
      22             :  * Routines for AR9285 and AR9271 chipsets.
      23             :  */
      24             : 
      25             : #include "athn_usb.h"
      26             : #include "bpfilter.h"
      27             : 
      28             : #include <sys/param.h>
      29             : #include <sys/sockio.h>
      30             : #include <sys/mbuf.h>
      31             : #include <sys/kernel.h>
      32             : #include <sys/socket.h>
      33             : #include <sys/systm.h>
      34             : #include <sys/malloc.h>
      35             : #include <sys/queue.h>
      36             : #include <sys/timeout.h>
      37             : #include <sys/conf.h>
      38             : #include <sys/device.h>
      39             : #include <sys/endian.h>
      40             : 
      41             : #include <machine/bus.h>
      42             : #include <machine/intr.h>
      43             : 
      44             : #if NBPFILTER > 0
      45             : #include <net/bpf.h>
      46             : #endif
      47             : #include <net/if.h>
      48             : #include <net/if_media.h>
      49             : 
      50             : #include <netinet/in.h>
      51             : #include <netinet/if_ether.h>
      52             : 
      53             : #include <net80211/ieee80211_var.h>
      54             : #include <net80211/ieee80211_amrr.h>
      55             : #include <net80211/ieee80211_mira.h>
      56             : #include <net80211/ieee80211_radiotap.h>
      57             : 
      58             : #include <dev/ic/athnreg.h>
      59             : #include <dev/ic/athnvar.h>
      60             : 
      61             : #include <dev/ic/ar5008reg.h>
      62             : #include <dev/ic/ar9280reg.h>
      63             : #include <dev/ic/ar9285reg.h>
      64             : 
      65             : int     ar9285_attach(struct athn_softc *);
      66             : void    ar9285_setup(struct athn_softc *);
      67             : void    ar9285_swap_rom(struct athn_softc *);
      68             : const   struct ar_spur_chan *ar9285_get_spur_chans(struct athn_softc *, int);
      69             : void    ar9285_init_from_rom(struct athn_softc *, struct ieee80211_channel *,
      70             :             struct ieee80211_channel *);
      71             : void    ar9285_pa_calib(struct athn_softc *);
      72             : void    ar9271_pa_calib(struct athn_softc *);
      73             : int     ar9285_cl_cal(struct athn_softc *, struct ieee80211_channel *,
      74             :             struct ieee80211_channel *);
      75             : void    ar9271_load_ani(struct athn_softc *);
      76             : int     ar9285_init_calib(struct athn_softc *, struct ieee80211_channel *,
      77             :             struct ieee80211_channel *);
      78             : void    ar9285_get_pdadcs(struct athn_softc *, struct ieee80211_channel *,
      79             :             int, uint8_t, uint8_t *, uint8_t *);
      80             : void    ar9285_set_power_calib(struct athn_softc *,
      81             :             struct ieee80211_channel *);
      82             : void    ar9285_set_txpower(struct athn_softc *, struct ieee80211_channel *,
      83             :             struct ieee80211_channel *);
      84             : 
      85             : /* Extern functions. */
      86             : uint8_t athn_chan2fbin(struct ieee80211_channel *);
      87             : void    athn_get_pier_ival(uint8_t, const uint8_t *, int, int *, int *);
      88             : int     ar5008_attach(struct athn_softc *);
      89             : void    ar5008_write_txpower(struct athn_softc *, int16_t power[]);
      90             : void    ar5008_get_pdadcs(struct athn_softc *, uint8_t, struct athn_pier *,
      91             :             struct athn_pier *, int, int, uint8_t, uint8_t *, uint8_t *);
      92             : void    ar5008_get_lg_tpow(struct athn_softc *, struct ieee80211_channel *,
      93             :             uint8_t, const struct ar_cal_target_power_leg *, int, uint8_t[]);
      94             : void    ar5008_get_ht_tpow(struct athn_softc *, struct ieee80211_channel *,
      95             :             uint8_t, const struct ar_cal_target_power_ht *, int, uint8_t[]);
      96             : int     ar9280_set_synth(struct athn_softc *, struct ieee80211_channel *,
      97             :             struct ieee80211_channel *);
      98             : void    ar9280_spur_mitigate(struct athn_softc *, struct ieee80211_channel *,
      99             :             struct ieee80211_channel *);
     100             : 
     101             : 
     102             : int
     103           0 : ar9285_attach(struct athn_softc *sc)
     104             : {
     105           0 :         sc->eep_base = AR9285_EEP_START_LOC;
     106           0 :         sc->eep_size = sizeof(struct ar9285_eeprom);
     107           0 :         sc->def_nf = AR9285_PHY_CCA_MAX_GOOD_VALUE;
     108           0 :         sc->ngpiopins = (sc->flags & ATHN_FLAG_USB) ? 16 : 12;
     109           0 :         sc->led_pin = (sc->flags & ATHN_FLAG_USB) ? 15 : 1;
     110           0 :         sc->workaround = AR9285_WA_DEFAULT;
     111           0 :         sc->ops.setup = ar9285_setup;
     112           0 :         sc->ops.swap_rom = ar9285_swap_rom;
     113           0 :         sc->ops.init_from_rom = ar9285_init_from_rom;
     114           0 :         sc->ops.set_txpower = ar9285_set_txpower;
     115           0 :         sc->ops.set_synth = ar9280_set_synth;
     116           0 :         sc->ops.spur_mitigate = ar9280_spur_mitigate;
     117           0 :         sc->ops.get_spur_chans = ar9285_get_spur_chans;
     118             : #if NATHN_USB > 0
     119           0 :         if (AR_SREV_9271(sc))
     120           0 :                 sc->ini = &ar9271_ini;
     121             :         else
     122             : #endif
     123           0 :                 sc->ini = &ar9285_1_2_ini;
     124           0 :         sc->serdes = &ar9280_2_0_serdes;
     125             : 
     126           0 :         return (ar5008_attach(sc));
     127             : }
     128             : 
     129             : void
     130           0 : ar9285_setup(struct athn_softc *sc)
     131             : {
     132           0 :         const struct ar9285_eeprom *eep = sc->eep;
     133             :         uint8_t type;
     134             : 
     135             :         /* Select initialization values based on ROM. */
     136           0 :         type = eep->baseEepHeader.txGainType;
     137             :         DPRINTF(("Tx gain type=0x%x\n", type));
     138             : #if NATHN_USB > 0
     139           0 :         if (AR_SREV_9271(sc)) {
     140           0 :                 if (type == AR_EEP_TXGAIN_HIGH_POWER)
     141           0 :                         sc->tx_gain = &ar9271_tx_gain_high_power;
     142             :                 else
     143           0 :                         sc->tx_gain = &ar9271_tx_gain;
     144             :         } else
     145             : #endif  /* NATHN_USB */
     146           0 :         if ((AR_READ(sc, AR_AN_SYNTH9) & 0x7) == 0x1) {     /* XE rev. */
     147           0 :                 if (type == AR_EEP_TXGAIN_HIGH_POWER)
     148           0 :                         sc->tx_gain = &ar9285_2_0_tx_gain_high_power;
     149             :                 else
     150           0 :                         sc->tx_gain = &ar9285_2_0_tx_gain;
     151             :         } else {
     152           0 :                 if (type == AR_EEP_TXGAIN_HIGH_POWER)
     153           0 :                         sc->tx_gain = &ar9285_1_2_tx_gain_high_power;
     154             :                 else
     155           0 :                         sc->tx_gain = &ar9285_1_2_tx_gain;
     156             :         }
     157           0 : }
     158             : 
     159             : void
     160           0 : ar9285_swap_rom(struct athn_softc *sc)
     161             : {
     162           0 :         struct ar9285_eeprom *eep = sc->eep;
     163             :         int i;
     164             : 
     165           0 :         eep->modalHeader.antCtrlCommon =
     166           0 :             swap32(eep->modalHeader.antCtrlCommon);
     167           0 :         eep->modalHeader.antCtrlChain =
     168           0 :             swap32(eep->modalHeader.antCtrlChain);
     169             : 
     170           0 :         for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
     171           0 :                 eep->modalHeader.spurChans[i].spurChan =
     172           0 :                     swap16(eep->modalHeader.spurChans[i].spurChan);
     173             :         }
     174           0 : }
     175             : 
     176             : const struct ar_spur_chan *
     177           0 : ar9285_get_spur_chans(struct athn_softc *sc, int is2ghz)
     178             : {
     179           0 :         const struct ar9285_eeprom *eep = sc->eep;
     180             : 
     181           0 :         KASSERT(is2ghz);
     182           0 :         return (eep->modalHeader.spurChans);
     183             : }
     184             : 
     185             : void
     186           0 : ar9285_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c,
     187             :     struct ieee80211_channel *extc)
     188             : {
     189           0 :         const struct ar9285_eeprom *eep = sc->eep;
     190           0 :         const struct ar9285_modal_eep_header *modal = &eep->modalHeader;
     191             :         uint32_t reg, offset = 0x1000;
     192             :         uint8_t ob[5], db1[5], db2[5];
     193             :         uint8_t txRxAtten;
     194             : 
     195           0 :         AR_WRITE(sc, AR_PHY_SWITCH_COM, modal->antCtrlCommon);
     196           0 :         AR_WRITE(sc, AR_PHY_SWITCH_CHAIN_0, modal->antCtrlChain);
     197             : 
     198           0 :         reg = AR_READ(sc, AR_PHY_TIMING_CTRL4_0);
     199           0 :         reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, modal->iqCalI);
     200           0 :         reg = RW(reg, AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, modal->iqCalQ);
     201           0 :         AR_WRITE(sc, AR_PHY_TIMING_CTRL4_0, reg);
     202             : 
     203           0 :         if (sc->eep_rev >= AR_EEP_MINOR_VER_3) {
     204           0 :                 reg = AR_READ(sc, AR_PHY_GAIN_2GHZ);
     205           0 :                 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
     206             :                     modal->bswMargin);
     207           0 :                 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,
     208             :                     modal->bswAtten);
     209           0 :                 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
     210             :                     modal->xatten2Margin);
     211           0 :                 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_DB,
     212             :                     modal->xatten2Db);
     213           0 :                 AR_WRITE(sc, AR_PHY_GAIN_2GHZ, reg);
     214             : 
     215             :                 /* Duplicate values of chain 0 for chain 1. */
     216           0 :                 reg = AR_READ(sc, AR_PHY_GAIN_2GHZ + offset);
     217           0 :                 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
     218             :                     modal->bswMargin);
     219           0 :                 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN1_DB,
     220             :                     modal->bswAtten);
     221           0 :                 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
     222             :                     modal->xatten2Margin);
     223           0 :                 reg = RW(reg, AR_PHY_GAIN_2GHZ_XATTEN2_DB,
     224             :                     modal->xatten2Db);
     225           0 :                 AR_WRITE(sc, AR_PHY_GAIN_2GHZ + offset, reg);
     226           0 :         }
     227           0 :         if (sc->eep_rev >= AR_EEP_MINOR_VER_3)
     228           0 :                 txRxAtten = modal->txRxAtten;
     229             :         else    /* Workaround for ROM versions < 14.3. */
     230             :                 txRxAtten = 23;
     231           0 :         reg = AR_READ(sc, AR_PHY_RXGAIN);
     232           0 :         reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAtten);
     233           0 :         reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN, modal->rxTxMargin);
     234           0 :         AR_WRITE(sc, AR_PHY_RXGAIN, reg);
     235             : 
     236             :         /* Duplicate values of chain 0 for chain 1. */
     237           0 :         reg = AR_READ(sc, AR_PHY_RXGAIN + offset);
     238           0 :         reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAtten);
     239           0 :         reg = RW(reg, AR9280_PHY_RXGAIN_TXRX_MARGIN, modal->rxTxMargin);
     240           0 :         AR_WRITE(sc, AR_PHY_RXGAIN + offset, reg);
     241             : 
     242           0 :         if (modal->version >= 3) {
     243             :                 /* Setup antenna diversity from ROM. */
     244           0 :                 reg = AR_READ(sc, AR_PHY_MULTICHAIN_GAIN_CTL);
     245           0 :                 reg = RW(reg, AR9285_PHY_ANT_DIV_CTL_ALL, 0);
     246           0 :                 reg = RW(reg, AR9285_PHY_ANT_DIV_CTL,
     247             :                     (modal->ob_234  >> 12) & 0x1);
     248           0 :                 reg = RW(reg, AR9285_PHY_ANT_DIV_ALT_LNACONF,
     249             :                     (modal->db1_234 >> 12) & 0x3);
     250           0 :                 reg = RW(reg, AR9285_PHY_ANT_DIV_MAIN_LNACONF,
     251             :                     (modal->db1_234 >> 14) & 0x3);
     252           0 :                 reg = RW(reg, AR9285_PHY_ANT_DIV_ALT_GAINTB,
     253             :                     (modal->ob_234  >> 13) & 0x1);
     254           0 :                 reg = RW(reg, AR9285_PHY_ANT_DIV_MAIN_GAINTB,
     255             :                     (modal->ob_234  >> 14) & 0x1);
     256           0 :                 AR_WRITE(sc, AR_PHY_MULTICHAIN_GAIN_CTL, reg);
     257           0 :                 reg = AR_READ(sc, AR_PHY_MULTICHAIN_GAIN_CTL);  /* Flush. */
     258             : 
     259           0 :                 reg = AR_READ(sc, AR_PHY_CCK_DETECT);
     260           0 :                 if (modal->ob_234 & (1 << 15))
     261           0 :                         reg |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
     262             :                 else
     263           0 :                         reg &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
     264           0 :                 AR_WRITE(sc, AR_PHY_CCK_DETECT, reg);
     265           0 :                 reg = AR_READ(sc, AR_PHY_CCK_DETECT);           /* Flush. */
     266           0 :         }
     267           0 :         if (modal->version >= 2) {
     268           0 :                 ob [0] = (modal->ob_01   >> 0) & 0xf;
     269           0 :                 ob [1] = (modal->ob_01   >> 4) & 0xf;
     270           0 :                 ob [2] = (modal->ob_234  >> 0) & 0xf;
     271           0 :                 ob [3] = (modal->ob_234  >> 4) & 0xf;
     272           0 :                 ob [4] = (modal->ob_234  >> 8) & 0xf;
     273             : 
     274           0 :                 db1[0] = (modal->db1_01  >> 0) & 0xf;
     275           0 :                 db1[1] = (modal->db1_01  >> 4) & 0xf;
     276           0 :                 db1[2] = (modal->db1_234 >> 0) & 0xf;
     277           0 :                 db1[3] = (modal->db1_234 >> 4) & 0xf;
     278           0 :                 db1[4] = (modal->db1_234 >> 8) & 0xf;
     279             : 
     280           0 :                 db2[0] = (modal->db2_01  >> 0) & 0xf;
     281           0 :                 db2[1] = (modal->db2_01  >> 4) & 0xf;
     282           0 :                 db2[2] = (modal->db2_234 >> 0) & 0xf;
     283           0 :                 db2[3] = (modal->db2_234 >> 4) & 0xf;
     284           0 :                 db2[4] = (modal->db2_234 >> 8) & 0xf;
     285             : 
     286           0 :         } else if (modal->version == 1) {
     287           0 :                 ob [0] = (modal->ob_01   >> 0) & 0xf;
     288           0 :                 ob [1] = (modal->ob_01   >> 4) & 0xf;
     289             :                 /* Field ob_234 does not exist, use ob_01. */
     290             :                 ob [2] = ob [3] = ob [4] = ob [1];
     291             : 
     292           0 :                 db1[0] = (modal->db1_01  >> 0) & 0xf;
     293           0 :                 db1[1] = (modal->db1_01  >> 4) & 0xf;
     294             :                 /* Field db1_234 does not exist, use db1_01. */
     295             :                 db1[2] = db1[3] = db1[4] = db1[1];
     296             : 
     297           0 :                 db2[0] = (modal->db2_01  >> 0) & 0xf;
     298           0 :                 db2[1] = (modal->db2_01  >> 4) & 0xf;
     299             :                 /* Field db2_234 does not exist, use db2_01. */
     300             :                 db2[2] = db2[3] = db2[4] = db2[1];
     301             : 
     302           0 :         } else {
     303             :                 ob [0] = modal->ob_01;
     304             :                 ob [1] = ob [2] = ob [3] = ob [4] = ob [0];
     305             : 
     306           0 :                 db1[0] = modal->db1_01;
     307             :                 db1[1] = db1[2] = db1[3] = db1[4] = db1[0];
     308             : 
     309             :                 /* Field db2_01 does not exist, use db1_01. */
     310             :                 db2[0] = modal->db1_01;
     311             :                 db2[1] = db2[2] = db2[3] = db2[4] = db2[0];
     312             :         }
     313             : #if NATHN_USB > 0
     314           0 :         if (AR_SREV_9271(sc)) {
     315             :                 reg = AR_READ(sc, AR9285_AN_RF2G3);
     316           0 :                 reg = RW(reg, AR9271_AN_RF2G3_OB_CCK, ob [0]);
     317           0 :                 reg = RW(reg, AR9271_AN_RF2G3_OB_PSK, ob [1]);
     318           0 :                 reg = RW(reg, AR9271_AN_RF2G3_OB_QAM, ob [2]);
     319           0 :                 reg = RW(reg, AR9271_AN_RF2G3_DB1,    db1[0]);
     320           0 :                 AR_WRITE(sc, AR9285_AN_RF2G3, reg);
     321           0 :                 AR_WRITE_BARRIER(sc);
     322           0 :                 DELAY(100);
     323           0 :                 reg = AR_READ(sc, AR9285_AN_RF2G4);
     324           0 :                 reg = RW(reg, AR9271_AN_RF2G4_DB2,    db2[0]);
     325           0 :                 AR_WRITE(sc, AR9285_AN_RF2G4, reg);
     326           0 :                 AR_WRITE_BARRIER(sc);
     327           0 :                 DELAY(100);
     328           0 :         } else
     329             : #endif  /* ATHN_USB */
     330             :         {
     331             :                 reg = AR_READ(sc, AR9285_AN_RF2G3);
     332           0 :                 reg = RW(reg, AR9285_AN_RF2G3_OB_0,  ob [0]);
     333           0 :                 reg = RW(reg, AR9285_AN_RF2G3_OB_1,  ob [1]);
     334           0 :                 reg = RW(reg, AR9285_AN_RF2G3_OB_2,  ob [2]);
     335           0 :                 reg = RW(reg, AR9285_AN_RF2G3_OB_3,  ob [3]);
     336           0 :                 reg = RW(reg, AR9285_AN_RF2G3_OB_4,  ob [4]);
     337           0 :                 reg = RW(reg, AR9285_AN_RF2G3_DB1_0, db1[0]);
     338           0 :                 reg = RW(reg, AR9285_AN_RF2G3_DB1_1, db1[1]);
     339           0 :                 reg = RW(reg, AR9285_AN_RF2G3_DB1_2, db1[2]);
     340           0 :                 AR_WRITE(sc, AR9285_AN_RF2G3, reg);
     341           0 :                 AR_WRITE_BARRIER(sc);
     342           0 :                 DELAY(100);
     343           0 :                 reg = AR_READ(sc, AR9285_AN_RF2G4);
     344           0 :                 reg = RW(reg, AR9285_AN_RF2G4_DB1_3, db1[3]);
     345           0 :                 reg = RW(reg, AR9285_AN_RF2G4_DB1_4, db1[4]);
     346           0 :                 reg = RW(reg, AR9285_AN_RF2G4_DB2_0, db2[0]);
     347           0 :                 reg = RW(reg, AR9285_AN_RF2G4_DB2_1, db2[1]);
     348           0 :                 reg = RW(reg, AR9285_AN_RF2G4_DB2_2, db2[2]);
     349           0 :                 reg = RW(reg, AR9285_AN_RF2G4_DB2_3, db2[3]);
     350           0 :                 reg = RW(reg, AR9285_AN_RF2G4_DB2_4, db2[4]);
     351           0 :                 AR_WRITE(sc, AR9285_AN_RF2G4, reg);
     352           0 :                 AR_WRITE_BARRIER(sc);
     353           0 :                 DELAY(100);
     354             :         }
     355             : 
     356           0 :         reg = AR_READ(sc, AR_PHY_SETTLING);
     357           0 :         reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->switchSettling);
     358           0 :         AR_WRITE(sc, AR_PHY_SETTLING, reg);
     359             : 
     360           0 :         reg = AR_READ(sc, AR_PHY_DESIRED_SZ);
     361           0 :         reg = RW(reg, AR_PHY_DESIRED_SZ_ADC, modal->adcDesiredSize);
     362           0 :         AR_WRITE(sc, AR_PHY_DESIRED_SZ, reg);
     363             : 
     364           0 :         reg =  SM(AR_PHY_RF_CTL4_TX_END_XPAA_OFF, modal->txEndToXpaOff);
     365           0 :         reg |= SM(AR_PHY_RF_CTL4_TX_END_XPAB_OFF, modal->txEndToXpaOff);
     366           0 :         reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAA_ON, modal->txFrameToXpaOn);
     367           0 :         reg |= SM(AR_PHY_RF_CTL4_FRAME_XPAB_ON, modal->txFrameToXpaOn);
     368           0 :         AR_WRITE(sc, AR_PHY_RF_CTL4, reg);
     369             : 
     370           0 :         reg = AR_READ(sc, AR_PHY_RF_CTL3);
     371           0 :         reg = RW(reg, AR_PHY_TX_END_TO_A2_RX_ON, modal->txEndToRxOn);
     372           0 :         AR_WRITE(sc, AR_PHY_RF_CTL3, reg);
     373             : 
     374           0 :         reg = AR_READ(sc, AR_PHY_CCA(0));
     375           0 :         reg = RW(reg, AR9280_PHY_CCA_THRESH62, modal->thresh62);
     376           0 :         AR_WRITE(sc, AR_PHY_CCA(0), reg);
     377             : 
     378           0 :         reg = AR_READ(sc, AR_PHY_EXT_CCA0);
     379           0 :         reg = RW(reg, AR_PHY_EXT_CCA0_THRESH62, modal->thresh62);
     380           0 :         AR_WRITE(sc, AR_PHY_EXT_CCA0, reg);
     381             : 
     382           0 :         if (sc->eep_rev >= AR_EEP_MINOR_VER_2) {
     383           0 :                 reg = AR_READ(sc, AR_PHY_RF_CTL2);
     384           0 :                 reg = RW(reg, AR_PHY_TX_END_PA_ON,
     385             :                     modal->txFrameToPaOn);
     386           0 :                 reg = RW(reg, AR_PHY_TX_END_DATA_START,
     387             :                     modal->txFrameToDataStart);
     388           0 :                 AR_WRITE(sc, AR_PHY_RF_CTL2, reg);
     389           0 :         }
     390           0 :         if (sc->eep_rev >= AR_EEP_MINOR_VER_3 && extc != NULL) {
     391           0 :                 reg = AR_READ(sc, AR_PHY_SETTLING);
     392           0 :                 reg = RW(reg, AR_PHY_SETTLING_SWITCH, modal->swSettleHt40);
     393           0 :                 AR_WRITE(sc, AR_PHY_SETTLING, reg);
     394           0 :         }
     395           0 :         AR_WRITE_BARRIER(sc);
     396           0 : }
     397             : 
     398             : void
     399           0 : ar9285_pa_calib(struct athn_softc *sc)
     400             : {
     401             :         /* List of registers that need to be saved/restored. */
     402             :         static const uint16_t regs[] = {
     403             :                 AR9285_AN_TOP3,
     404             :                 AR9285_AN_RXTXBB1,
     405             :                 AR9285_AN_RF2G1,
     406             :                 AR9285_AN_RF2G2,
     407             :                 AR9285_AN_TOP2,
     408             :                 AR9285_AN_RF2G8,
     409             :                 AR9285_AN_RF2G7
     410             :         };
     411           0 :         uint32_t svg[7], reg, ccomp_svg;
     412             :         int i;
     413             : 
     414             :         /* No PA calibration needed for high power solutions. */
     415           0 :         if (AR_SREV_9285(sc) &&
     416           0 :             ((struct ar9285_base_eep_header *)sc->eep)->txGainType ==
     417             :              AR_EEP_TXGAIN_HIGH_POWER)  /* XXX AR9287? */
     418           0 :                 return;
     419             : 
     420             :         /* Save registers. */
     421           0 :         for (i = 0; i < nitems(regs); i++)
     422           0 :                 svg[i] = AR_READ(sc, regs[i]);
     423             : 
     424           0 :         AR_CLRBITS(sc, AR9285_AN_RF2G6, 1);
     425           0 :         AR_SETBITS(sc, AR_PHY(2), 1 << 27);
     426             : 
     427           0 :         AR_SETBITS(sc, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC);
     428           0 :         AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1);
     429           0 :         AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I);
     430           0 :         AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF);
     431           0 :         AR_CLRBITS(sc, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL);
     432           0 :         AR_CLRBITS(sc, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB);
     433           0 :         AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL);
     434             :         /* Power down PA drivers. */
     435           0 :         AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1);
     436           0 :         AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2);
     437           0 :         AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT);
     438             : 
     439           0 :         reg = AR_READ(sc, AR9285_AN_RF2G8);
     440           0 :         reg = RW(reg, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
     441           0 :         AR_WRITE(sc, AR9285_AN_RF2G8, reg);
     442             : 
     443           0 :         reg = AR_READ(sc, AR9285_AN_RF2G7);
     444           0 :         reg = RW(reg, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
     445           0 :         AR_WRITE(sc, AR9285_AN_RF2G7, reg);
     446             : 
     447           0 :         reg = AR_READ(sc, AR9285_AN_RF2G6);
     448             :         /* Save compensation capacitor value. */
     449           0 :         ccomp_svg = MS(reg, AR9285_AN_RF2G6_CCOMP);
     450             :         /* Program compensation capacitor for dynamic PA. */
     451           0 :         reg = RW(reg, AR9285_AN_RF2G6_CCOMP, 0xf);
     452           0 :         AR_WRITE(sc, AR9285_AN_RF2G6, reg);
     453             : 
     454           0 :         AR_WRITE(sc, AR9285_AN_TOP2, AR9285_AN_TOP2_DEFAULT);
     455           0 :         AR_WRITE_BARRIER(sc);
     456           0 :         DELAY(30);
     457             : 
     458             :         /* Clear offsets 6-1. */
     459           0 :         AR_CLRBITS(sc, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS_6_1);
     460             :         /* Clear offset 0. */
     461           0 :         AR_CLRBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP);
     462             :         /* Set offsets 6-1. */
     463           0 :         for (i = 6; i >= 1; i--) {
     464           0 :                 AR_SETBITS(sc, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS(i));
     465           0 :                 AR_WRITE_BARRIER(sc);
     466           0 :                 DELAY(1);
     467           0 :                 if (AR_READ(sc, AR9285_AN_RF2G9) & AR9285_AN_RXTXBB1_SPARE9) {
     468           0 :                         AR_SETBITS(sc, AR9285_AN_RF2G6,
     469             :                             AR9285_AN_RF2G6_OFFS(i));
     470           0 :                 } else {
     471           0 :                         AR_CLRBITS(sc, AR9285_AN_RF2G6,
     472             :                             AR9285_AN_RF2G6_OFFS(i));
     473             :                 }
     474             :         }
     475             :         /* Set offset 0. */
     476           0 :         AR_SETBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP);
     477           0 :         AR_WRITE_BARRIER(sc);
     478           0 :         DELAY(1);
     479           0 :         if (AR_READ(sc, AR9285_AN_RF2G9) & AR9285_AN_RXTXBB1_SPARE9)
     480           0 :                 AR_SETBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP);
     481             :         else
     482           0 :                 AR_CLRBITS(sc, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP);
     483             : 
     484           0 :         AR_WRITE_BARRIER(sc);
     485             : 
     486           0 :         AR_SETBITS(sc, AR9285_AN_RF2G6, 1);
     487           0 :         AR_CLRBITS(sc, AR_PHY(2), 1 << 27);
     488             : 
     489             :         /* Restore registers. */
     490           0 :         for (i = 0; i < nitems(regs); i++)
     491           0 :                 AR_WRITE(sc, regs[i], svg[i]);
     492             : 
     493             :         /* Restore compensation capacitor value. */
     494           0 :         reg = AR_READ(sc, AR9285_AN_RF2G6);
     495           0 :         reg = RW(reg, AR9285_AN_RF2G6_CCOMP, ccomp_svg);
     496           0 :         AR_WRITE(sc, AR9285_AN_RF2G6, reg);
     497           0 :         AR_WRITE_BARRIER(sc);
     498           0 : }
     499             : 
     500             : void
     501           0 : ar9271_pa_calib(struct athn_softc *sc)
     502             : {
     503             : #if NATHN_USB > 0
     504             :         /* List of registers that need to be saved/restored. */
     505             :         static const uint16_t regs[] = {
     506             :                 AR9285_AN_TOP3,
     507             :                 AR9285_AN_RXTXBB1,
     508             :                 AR9285_AN_RF2G1,
     509             :                 AR9285_AN_RF2G2,
     510             :                 AR9285_AN_TOP2,
     511             :                 AR9285_AN_RF2G8,
     512             :                 AR9285_AN_RF2G7
     513             :         };
     514           0 :         uint32_t svg[7], reg, rf2g3_svg;
     515             :         int i;
     516             : 
     517             :         /* Save registers. */
     518           0 :         for (i = 0; i < nitems(regs); i++)
     519           0 :                 svg[i] = AR_READ(sc, regs[i]);
     520             : 
     521           0 :         AR_CLRBITS(sc, AR9285_AN_RF2G6, 1);
     522           0 :         AR_SETBITS(sc, AR_PHY(2), 1 << 27);
     523             : 
     524           0 :         AR_SETBITS(sc, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC);
     525           0 :         AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1);
     526           0 :         AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I);
     527           0 :         AR_SETBITS(sc, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF);
     528           0 :         AR_CLRBITS(sc, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL);
     529           0 :         AR_CLRBITS(sc, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB);
     530           0 :         AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL);
     531             :         /* Power down PA drivers. */
     532           0 :         AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1);
     533           0 :         AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2);
     534           0 :         AR_CLRBITS(sc, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT);
     535             : 
     536           0 :         reg = AR_READ(sc, AR9285_AN_RF2G8);
     537           0 :         reg = RW(reg, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
     538           0 :         AR_WRITE(sc, AR9285_AN_RF2G8, reg);
     539             : 
     540           0 :         reg = AR_READ(sc, AR9285_AN_RF2G7);
     541           0 :         reg = RW(reg, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
     542           0 :         AR_WRITE(sc, AR9285_AN_RF2G7, reg);
     543             : 
     544             :         /* Save compensation capacitor value. */
     545           0 :         reg = rf2g3_svg = AR_READ(sc, AR9285_AN_RF2G3);
     546             :         /* Program compensation capacitor for dynamic PA. */
     547           0 :         reg = RW(reg, AR9271_AN_RF2G3_CCOMP, 0xfff);
     548           0 :         AR_WRITE(sc, AR9285_AN_RF2G3, reg);
     549             : 
     550           0 :         AR_WRITE(sc, AR9285_AN_TOP2, AR9285_AN_TOP2_DEFAULT);
     551           0 :         AR_WRITE_BARRIER(sc);
     552           0 :         DELAY(30);
     553             : 
     554             :         /* Clear offsets 6-0. */
     555           0 :         AR_CLRBITS(sc, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS_6_0);
     556             :         /* Set offsets 6-1. */
     557           0 :         for (i = 6; i >= 1; i--) {
     558           0 :                 reg = AR_READ(sc, AR9285_AN_RF2G6);
     559           0 :                 reg |= AR9271_AN_RF2G6_OFFS(i);
     560           0 :                 AR_WRITE(sc, AR9285_AN_RF2G6, reg);
     561           0 :                 AR_WRITE_BARRIER(sc);
     562           0 :                 DELAY(1);
     563           0 :                 if (!(AR_READ(sc, AR9285_AN_RF2G9) & AR9285_AN_RXTXBB1_SPARE9))
     564           0 :                         reg &= ~AR9271_AN_RF2G6_OFFS(i);
     565           0 :                 AR_WRITE(sc, AR9285_AN_RF2G6, reg);
     566             :         }
     567           0 :         AR_WRITE_BARRIER(sc);
     568             : 
     569           0 :         AR_SETBITS(sc, AR9285_AN_RF2G6, 1);
     570           0 :         AR_CLRBITS(sc, AR_PHY(2), 1 << 27);
     571             : 
     572             :         /* Restore registers. */
     573           0 :         for (i = 0; i < nitems(regs); i++)
     574           0 :                 AR_WRITE(sc, regs[i], svg[i]);
     575             : 
     576             :         /* Restore compensation capacitor value. */
     577           0 :         AR_WRITE(sc, AR9285_AN_RF2G3, rf2g3_svg);
     578           0 :         AR_WRITE_BARRIER(sc);
     579             : #endif  /* NATHN_USB */
     580           0 : }
     581             : 
     582             : /*
     583             :  * Carrier Leakage Calibration.
     584             :  */
     585             : int
     586           0 : ar9285_cl_cal(struct athn_softc *sc, struct ieee80211_channel *c,
     587             :     struct ieee80211_channel *extc)
     588             : {
     589             :         int ntries;
     590             : 
     591           0 :         AR_SETBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
     592             :         if (0 && extc == NULL) {        /* XXX IS_CHAN_HT20!! */
     593             :                 AR_SETBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
     594             :                 AR_SETBITS(sc, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
     595             :                 AR_CLRBITS(sc, AR_PHY_AGC_CONTROL,
     596             :                     AR_PHY_AGC_CONTROL_FLTR_CAL);
     597             :                 AR_CLRBITS(sc, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
     598             :                 AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
     599             :                 for (ntries = 0; ntries < 10000; ntries++) {
     600             :                         if (!(AR_READ(sc, AR_PHY_AGC_CONTROL) &
     601             :                             AR_PHY_AGC_CONTROL_CAL))
     602             :                                 break;
     603             :                         DELAY(10);
     604             :                 }
     605             :                 if (ntries == 10000)
     606             :                         return (ETIMEDOUT);
     607             :                 AR_CLRBITS(sc, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
     608             :                 AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
     609             :                 AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
     610             :         }
     611           0 :         AR_CLRBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
     612           0 :         AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
     613           0 :         AR_SETBITS(sc, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE);
     614           0 :         AR_SETBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);
     615           0 :         for (ntries = 0; ntries < 10000; ntries++) {
     616           0 :                 if (!(AR_READ(sc, AR_PHY_AGC_CONTROL) &
     617             :                     AR_PHY_AGC_CONTROL_CAL))
     618             :                         break;
     619           0 :                 DELAY(10);
     620             :         }
     621           0 :         if (ntries == 10000)
     622           0 :                 return (ETIMEDOUT);
     623           0 :         AR_SETBITS(sc, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
     624           0 :         AR_CLRBITS(sc, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
     625           0 :         AR_CLRBITS(sc, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
     626           0 :         AR_WRITE_BARRIER(sc);
     627           0 :         return (0);
     628           0 : }
     629             : 
     630             : void
     631           0 : ar9271_load_ani(struct athn_softc *sc)
     632             : {
     633             : #if NATHN_USB > 0
     634             :         /* Write ANI registers. */
     635           0 :         AR_WRITE(sc, AR_PHY_DESIRED_SZ, 0x6d4000e2);
     636           0 :         AR_WRITE(sc, AR_PHY_AGC_CTL1,   0x3139605e);
     637           0 :         AR_WRITE(sc, AR_PHY_FIND_SIG,   0x7ec84d2e);
     638           0 :         AR_WRITE(sc, AR_PHY_SFCORR_LOW, 0x06903881);
     639           0 :         AR_WRITE(sc, AR_PHY_SFCORR,     0x5ac640d0);
     640           0 :         AR_WRITE(sc, AR_PHY_CCK_DETECT, 0x803e68c8);
     641           0 :         AR_WRITE(sc, AR_PHY_TIMING5,    0xd00a8007);
     642           0 :         AR_WRITE(sc, AR_PHY_SFCORR_EXT, 0x05eea6d4);
     643           0 :         AR_WRITE_BARRIER(sc);
     644             : #endif  /* NATHN_USB */
     645           0 : }
     646             : 
     647             : int
     648           0 : ar9285_init_calib(struct athn_softc *sc, struct ieee80211_channel *c,
     649             :     struct ieee80211_channel *extc)
     650             : {
     651             :         uint32_t reg, mask, clcgain, rf2g5_svg;
     652             :         int i, maxgain, nclcs, thresh, error;
     653             : 
     654             :         /* Do carrier leakage calibration. */
     655           0 :         if ((error = ar9285_cl_cal(sc, c, extc)) != 0)
     656           0 :                 return (error);
     657             : 
     658             :         /* Workaround for high temperature is not applicable on AR9271. */
     659           0 :         if (AR_SREV_9271(sc))
     660           0 :                 return (0);
     661             : 
     662             :         mask = 0;
     663             :         nclcs = 0;
     664           0 :         reg = AR_READ(sc, AR_PHY_TX_PWRCTRL7);
     665           0 :         maxgain = MS(reg, AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX);
     666           0 :         for (i = 0; i <= maxgain; i++) {
     667           0 :                 reg = AR_READ(sc, AR_PHY_TX_GAIN_TBL(i));
     668           0 :                 clcgain = MS(reg, AR_PHY_TX_GAIN_CLC);
     669             :                 /* NB: clcgain <= 0xf. */
     670           0 :                 if (!(mask & (1 << clcgain))) {
     671           0 :                         mask |= 1 << clcgain;
     672           0 :                         nclcs++;
     673           0 :                 }
     674             :         }
     675             :         thresh = 0;
     676           0 :         for (i = 0; i < nclcs; i++) {
     677           0 :                 reg = AR_READ(sc, AR_PHY_CLC_TBL(i));
     678           0 :                 if (MS(reg, AR_PHY_CLC_I0) == 0)
     679           0 :                         thresh++;
     680           0 :                 if (MS(reg, AR_PHY_CLC_Q0) == 0)
     681           0 :                         thresh++;
     682             :         }
     683           0 :         if (thresh <= AR9285_CL_CAL_REDO_THRESH)
     684           0 :                 return (0);     /* No need to redo. */
     685             : 
     686             :         /* Threshold reached, redo carrier leakage calibration. */
     687             :         DPRINTFN(2, ("CLC threshold=%d\n", thresh));
     688           0 :         rf2g5_svg = reg = AR_READ(sc, AR9285_AN_RF2G5);
     689           0 :         if ((AR_READ(sc, AR_AN_SYNTH9) & 0x7) == 0x1)       /* XE rev. */
     690           0 :                 reg = RW(reg, AR9285_AN_RF2G5_IC50TX, 0x5);
     691             :         else
     692           0 :                 reg = RW(reg, AR9285_AN_RF2G5_IC50TX, 0x4);
     693           0 :         AR_WRITE(sc, AR9285_AN_RF2G5, reg);
     694           0 :         AR_WRITE_BARRIER(sc);
     695           0 :         error = ar9285_cl_cal(sc, c, extc);
     696           0 :         AR_WRITE(sc, AR9285_AN_RF2G5, rf2g5_svg);
     697           0 :         AR_WRITE_BARRIER(sc);
     698           0 :         return (error);
     699           0 : }
     700             : 
     701             : void
     702           0 : ar9285_get_pdadcs(struct athn_softc *sc, struct ieee80211_channel *c,
     703             :     int nxpdgains, uint8_t overlap, uint8_t *boundaries, uint8_t *pdadcs)
     704             : {
     705           0 :         const struct ar9285_eeprom *eep = sc->eep;
     706             :         const struct ar9285_cal_data_per_freq *pierdata;
     707             :         const uint8_t *pierfreq;
     708           0 :         struct athn_pier lopier, hipier;
     709             :         uint8_t fbin;
     710           0 :         int i, lo, hi, npiers;
     711             : 
     712           0 :         pierfreq = eep->calFreqPier2G;
     713           0 :         pierdata = eep->calPierData2G;
     714             :         npiers = AR9285_NUM_2G_CAL_PIERS;
     715             : 
     716             :         /* Find channel in ROM pier table. */
     717           0 :         fbin = athn_chan2fbin(c);
     718           0 :         athn_get_pier_ival(fbin, pierfreq, npiers, &lo, &hi);
     719             : 
     720           0 :         lopier.fbin = pierfreq[lo];
     721           0 :         hipier.fbin = pierfreq[hi];
     722           0 :         for (i = 0; i < nxpdgains; i++) {
     723           0 :                 lopier.pwr[i] = pierdata[lo].pwrPdg[i];
     724           0 :                 lopier.vpd[i] = pierdata[lo].vpdPdg[i];
     725           0 :                 hipier.pwr[i] = pierdata[lo].pwrPdg[i];
     726           0 :                 hipier.vpd[i] = pierdata[lo].vpdPdg[i];
     727             :         }
     728           0 :         ar5008_get_pdadcs(sc, fbin, &lopier, &hipier, nxpdgains,
     729             :             AR9285_PD_GAIN_ICEPTS, overlap, boundaries, pdadcs);
     730           0 : }
     731             : 
     732             : void
     733           0 : ar9285_set_power_calib(struct athn_softc *sc, struct ieee80211_channel *c)
     734             : {
     735           0 :         const struct ar9285_eeprom *eep = sc->eep;
     736           0 :         uint8_t boundaries[AR_PD_GAINS_IN_MASK];
     737           0 :         uint8_t pdadcs[AR_NUM_PDADC_VALUES];
     738           0 :         uint8_t xpdgains[AR9285_NUM_PD_GAINS];
     739             :         uint8_t overlap;
     740             :         uint32_t reg;
     741             :         int i, nxpdgains;
     742             : 
     743           0 :         if (sc->eep_rev < AR_EEP_MINOR_VER_2) {
     744           0 :                 overlap = MS(AR_READ(sc, AR_PHY_TPCRG5),
     745             :                     AR_PHY_TPCRG5_PD_GAIN_OVERLAP);
     746           0 :         } else
     747           0 :                 overlap = eep->modalHeader.pdGainOverlap;
     748             : 
     749             :         nxpdgains = 0;
     750           0 :         memset(xpdgains, 0, sizeof(xpdgains));
     751           0 :         for (i = AR9285_PD_GAINS_IN_MASK - 1; i >= 0; i--) {
     752           0 :                 if (nxpdgains >= AR9285_NUM_PD_GAINS)
     753             :                         break;
     754           0 :                 if (eep->modalHeader.xpdGain & (1 << i))
     755           0 :                         xpdgains[nxpdgains++] = i;
     756             :         }
     757           0 :         reg = AR_READ(sc, AR_PHY_TPCRG1);
     758           0 :         reg = RW(reg, AR_PHY_TPCRG1_NUM_PD_GAIN, nxpdgains - 1);
     759           0 :         reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_1, xpdgains[0]);
     760           0 :         reg = RW(reg, AR_PHY_TPCRG1_PD_GAIN_2, xpdgains[1]);
     761           0 :         AR_WRITE(sc, AR_PHY_TPCRG1, reg);
     762             : 
     763             :         /* NB: No open loop power control for AR9285. */
     764           0 :         ar9285_get_pdadcs(sc, c, nxpdgains, overlap, boundaries, pdadcs);
     765             : 
     766             :         /* Write boundaries. */
     767           0 :         reg  = SM(AR_PHY_TPCRG5_PD_GAIN_OVERLAP, overlap);
     768           0 :         reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1, boundaries[0]);
     769           0 :         reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2, boundaries[1]);
     770           0 :         reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3, boundaries[2]);
     771           0 :         reg |= SM(AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4, boundaries[3]);
     772           0 :         AR_WRITE(sc, AR_PHY_TPCRG5, reg);
     773             : 
     774             :         /* Write PDADC values. */
     775           0 :         for (i = 0; i < AR_NUM_PDADC_VALUES; i += 4) {
     776           0 :                 AR_WRITE(sc, AR_PHY_PDADC_TBL_BASE + i,
     777             :                     pdadcs[i + 0] <<  0 |
     778             :                     pdadcs[i + 1] <<  8 |
     779             :                     pdadcs[i + 2] << 16 |
     780             :                     pdadcs[i + 3] << 24);
     781             :         }
     782           0 :         AR_WRITE_BARRIER(sc);
     783           0 : }
     784             : 
     785             : void
     786           0 : ar9285_set_txpower(struct athn_softc *sc, struct ieee80211_channel *c,
     787             :     struct ieee80211_channel *extc)
     788             : {
     789           0 :         const struct ar9285_eeprom *eep = sc->eep;
     790           0 :         const struct ar9285_modal_eep_header *modal = &eep->modalHeader;
     791           0 :         uint8_t tpow_cck[4], tpow_ofdm[4];
     792           0 :         uint8_t tpow_cck_ext[4], tpow_ofdm_ext[4];
     793           0 :         uint8_t tpow_ht20[8], tpow_ht40[8];
     794             :         uint8_t ht40inc;
     795           0 :         int16_t max_ant_gain, power[ATHN_POWER_COUNT];
     796             :         int i;
     797             : 
     798           0 :         ar9285_set_power_calib(sc, c);
     799             : 
     800             :         /* Compute transmit power reduction due to antenna gain. */
     801           0 :         max_ant_gain = modal->antennaGain;
     802             :         /* XXX */
     803             : 
     804             :         /* Get CCK target powers. */
     805           0 :         ar5008_get_lg_tpow(sc, c, AR_CTL_11B, eep->calTargetPowerCck,
     806           0 :             AR9285_NUM_2G_CCK_TARGET_POWERS, tpow_cck);
     807             : 
     808             :         /* Get OFDM target powers. */
     809           0 :         ar5008_get_lg_tpow(sc, c, AR_CTL_11G, eep->calTargetPower2G,
     810           0 :             AR9285_NUM_2G_20_TARGET_POWERS, tpow_ofdm);
     811             : 
     812             :         /* Get HT-20 target powers. */
     813           0 :         ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT20, eep->calTargetPower2GHT20,
     814           0 :             AR9285_NUM_2G_20_TARGET_POWERS, tpow_ht20);
     815             : 
     816           0 :         if (extc != NULL) {
     817             :                 /* Get HT-40 target powers. */
     818           0 :                 ar5008_get_ht_tpow(sc, c, AR_CTL_2GHT40,
     819           0 :                     eep->calTargetPower2GHT40, AR9285_NUM_2G_40_TARGET_POWERS,
     820           0 :                     tpow_ht40);
     821             : 
     822             :                 /* Get secondary channel CCK target powers. */
     823           0 :                 ar5008_get_lg_tpow(sc, extc, AR_CTL_11B,
     824             :                     eep->calTargetPowerCck, AR9285_NUM_2G_CCK_TARGET_POWERS,
     825           0 :                     tpow_cck_ext);
     826             : 
     827             :                 /* Get secondary channel OFDM target powers. */
     828           0 :                 ar5008_get_lg_tpow(sc, extc, AR_CTL_11G,
     829             :                     eep->calTargetPower2G, AR9285_NUM_2G_20_TARGET_POWERS,
     830           0 :                     tpow_ofdm_ext);
     831           0 :         }
     832             : 
     833           0 :         memset(power, 0, sizeof(power));
     834             :         /* Shuffle target powers accross transmit rates. */
     835           0 :         power[ATHN_POWER_OFDM6   ] =
     836           0 :         power[ATHN_POWER_OFDM9   ] =
     837           0 :         power[ATHN_POWER_OFDM12  ] =
     838           0 :         power[ATHN_POWER_OFDM18  ] =
     839           0 :         power[ATHN_POWER_OFDM24  ] = tpow_ofdm[0];
     840           0 :         power[ATHN_POWER_OFDM36  ] = tpow_ofdm[1];
     841           0 :         power[ATHN_POWER_OFDM48  ] = tpow_ofdm[2];
     842           0 :         power[ATHN_POWER_OFDM54  ] = tpow_ofdm[3];
     843           0 :         power[ATHN_POWER_XR      ] = tpow_ofdm[0];
     844           0 :         power[ATHN_POWER_CCK1_LP ] = tpow_cck[0];
     845           0 :         power[ATHN_POWER_CCK2_LP ] =
     846           0 :         power[ATHN_POWER_CCK2_SP ] = tpow_cck[1];
     847           0 :         power[ATHN_POWER_CCK55_LP] =
     848           0 :         power[ATHN_POWER_CCK55_SP] = tpow_cck[2];
     849           0 :         power[ATHN_POWER_CCK11_LP] =
     850           0 :         power[ATHN_POWER_CCK11_SP] = tpow_cck[3];
     851           0 :         for (i = 0; i < nitems(tpow_ht20); i++)
     852           0 :                 power[ATHN_POWER_HT20(i)] = tpow_ht20[i];
     853           0 :         if (extc != NULL) {
     854             :                 /* Correct PAR difference between HT40 and HT20/Legacy. */
     855           0 :                 if (sc->eep_rev >= AR_EEP_MINOR_VER_2)
     856           0 :                         ht40inc = modal->ht40PowerIncForPdadc;
     857             :                 else
     858             :                         ht40inc = AR_HT40_POWER_INC_FOR_PDADC;
     859           0 :                 for (i = 0; i < nitems(tpow_ht40); i++)
     860           0 :                         power[ATHN_POWER_HT40(i)] = tpow_ht40[i] + ht40inc;
     861           0 :                 power[ATHN_POWER_OFDM_DUP] = tpow_ht40[0];
     862           0 :                 power[ATHN_POWER_CCK_DUP ] = tpow_ht40[0];
     863           0 :                 power[ATHN_POWER_OFDM_EXT] = tpow_ofdm_ext[0];
     864           0 :                 power[ATHN_POWER_CCK_EXT ] = tpow_cck_ext[0];
     865           0 :         }
     866             : 
     867           0 :         for (i = 0; i < ATHN_POWER_COUNT; i++) {
     868           0 :                 power[i] -= AR_PWR_TABLE_OFFSET_DB * 2; /* In half dB. */
     869           0 :                 if (power[i] > AR_MAX_RATE_POWER)
     870           0 :                         power[i] = AR_MAX_RATE_POWER;
     871             :         }
     872             : 
     873             :         /* Commit transmit power values to hardware. */
     874           0 :         ar5008_write_txpower(sc, power);
     875           0 : }

Generated by: LCOV version 1.13