Home | History | Annotate | Line # | Download | only in ar5210
      1  1.1     alc /*
      2  1.1     alc  * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
      3  1.1     alc  * Copyright (c) 2002-2004 Atheros Communications, Inc.
      4  1.1     alc  *
      5  1.1     alc  * Permission to use, copy, modify, and/or distribute this software for any
      6  1.1     alc  * purpose with or without fee is hereby granted, provided that the above
      7  1.1     alc  * copyright notice and this permission notice appear in all copies.
      8  1.1     alc  *
      9  1.1     alc  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     10  1.1     alc  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     11  1.1     alc  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     12  1.1     alc  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     13  1.1     alc  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     14  1.1     alc  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     15  1.1     alc  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     16  1.1     alc  *
     17  1.7   jklos  * $Id: ar5210_reset.c,v 1.7 2015/11/24 08:48:25 jklos Exp $
     18  1.1     alc  */
     19  1.1     alc #include "opt_ah.h"
     20  1.1     alc 
     21  1.1     alc #include "ah.h"
     22  1.1     alc #include "ah_internal.h"
     23  1.1     alc 
     24  1.1     alc #include "ar5210/ar5210.h"
     25  1.1     alc #include "ar5210/ar5210reg.h"
     26  1.1     alc #include "ar5210/ar5210phy.h"
     27  1.1     alc 
     28  1.1     alc #include "ah_eeprom_v1.h"
     29  1.1     alc 
     30  1.1     alc typedef struct {
     31  1.1     alc 	uint32_t	Offset;
     32  1.1     alc 	uint32_t	Value;
     33  1.1     alc } REGISTER_VAL;
     34  1.1     alc 
     35  1.1     alc static const REGISTER_VAL ar5k0007_init[] = {
     36  1.1     alc #include "ar5210/ar5k_0007.ini"
     37  1.1     alc };
     38  1.1     alc 
     39  1.1     alc /* Default Power Settings for channels outside of EEPROM range */
     40  1.1     alc static const uint8_t ar5k0007_pwrSettings[17] = {
     41  1.1     alc /*	gain delta			pc dac */
     42  1.1     alc /* 54  48  36  24  18  12   9   54  48  36  24  18  12   9   6  ob  db	  */
     43  1.1     alc     9,  9,  0,  0,  0,  0,  0,   2,  2,  6,  6,  6,  6,  6,  6,  2,  2
     44  1.1     alc };
     45  1.1     alc 
     46  1.1     alc /*
     47  1.1     alc  * The delay, in usecs, between writing AR_RC with a reset
     48  1.1     alc  * request and waiting for the chip to settle.  If this is
     49  1.1     alc  * too short then the chip does not come out of sleep state.
     50  1.1     alc  * Note this value was empirically derived and may be dependent
     51  1.1     alc  * on the host machine (don't know--the problem was identified
     52  1.1     alc  * on an IBM 570e laptop; 10us delays worked on other systems).
     53  1.1     alc  */
     54  1.1     alc #define	AR_RC_SETTLE_TIME	20000
     55  1.1     alc 
     56  1.1     alc static HAL_BOOL ar5210SetResetReg(struct ath_hal *,
     57  1.2     alc 		uint32_t resetMask, u_int waitTime);
     58  1.1     alc static HAL_BOOL ar5210SetChannel(struct ath_hal *, HAL_CHANNEL_INTERNAL *);
     59  1.1     alc static void ar5210SetOperatingMode(struct ath_hal *, int opmode);
     60  1.1     alc 
     61  1.1     alc /*
     62  1.1     alc  * Places the device in and out of reset and then places sane
     63  1.1     alc  * values in the registers based on EEPROM config, initialization
     64  1.1     alc  * vectors (as determined by the mode), and station configuration
     65  1.1     alc  *
     66  1.1     alc  * bChannelChange is used to preserve DMA/PCU registers across
     67  1.1     alc  * a HW Reset during channel change.
     68  1.1     alc  */
     69  1.1     alc HAL_BOOL
     70  1.1     alc ar5210Reset(struct ath_hal *ah, HAL_OPMODE opmode,
     71  1.1     alc 	HAL_CHANNEL *chan, HAL_BOOL bChannelChange, HAL_STATUS *status)
     72  1.1     alc {
     73  1.1     alc #define	N(a)	(sizeof (a) /sizeof (a[0]))
     74  1.1     alc #define	FAIL(_code)	do { ecode = _code; goto bad; } while (0)
     75  1.1     alc 	struct ath_hal_5210 *ahp = AH5210(ah);
     76  1.1     alc 	const HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom;
     77  1.1     alc 	HAL_CHANNEL_INTERNAL *ichan;
     78  1.1     alc 	HAL_STATUS ecode;
     79  1.1     alc 	uint32_t ledstate;
     80  1.1     alc 	int i, q;
     81  1.1     alc 
     82  1.1     alc 	HALDEBUG(ah, HAL_DEBUG_RESET,
     83  1.1     alc 	    "%s: opmode %u channel %u/0x%x %s channel\n", __func__,
     84  1.1     alc 	    opmode, chan->channel, chan->channelFlags,
     85  1.1     alc 	    bChannelChange ? "change" : "same");
     86  1.1     alc 
     87  1.1     alc 	if ((chan->channelFlags & CHANNEL_5GHZ) == 0) {
     88  1.1     alc 		/* Only 11a mode */
     89  1.1     alc 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: channel not 5Ghz\n", __func__);
     90  1.1     alc 		FAIL(HAL_EINVAL);
     91  1.1     alc 	}
     92  1.1     alc 	/*
     93  1.1     alc 	 * Map public channel to private.
     94  1.1     alc 	 */
     95  1.1     alc 	ichan = ath_hal_checkchannel(ah, chan);
     96  1.1     alc 	if (ichan == AH_NULL) {
     97  1.1     alc 		HALDEBUG(ah, HAL_DEBUG_ANY,
     98  1.1     alc 		    "%s: invalid channel %u/0x%x; no mapping\n",
     99  1.1     alc 		    __func__, chan->channel, chan->channelFlags);
    100  1.1     alc 		FAIL(HAL_EINVAL);
    101  1.1     alc 	}
    102  1.1     alc 	switch (opmode) {
    103  1.1     alc 	case HAL_M_STA:
    104  1.1     alc 	case HAL_M_IBSS:
    105  1.1     alc 	case HAL_M_HOSTAP:
    106  1.1     alc 	case HAL_M_MONITOR:
    107  1.1     alc 		break;
    108  1.1     alc 	default:
    109  1.1     alc 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n",
    110  1.1     alc 		    __func__, opmode);
    111  1.1     alc 		FAIL(HAL_EINVAL);
    112  1.1     alc 		break;
    113  1.1     alc 	}
    114  1.1     alc 
    115  1.1     alc 	ledstate = OS_REG_READ(ah, AR_PCICFG) &
    116  1.1     alc 		(AR_PCICFG_LED_PEND | AR_PCICFG_LED_ACT);
    117  1.1     alc 
    118  1.1     alc 	if (!ar5210ChipReset(ah, chan)) {
    119  1.1     alc 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n",
    120  1.1     alc 		    __func__);
    121  1.1     alc 		FAIL(HAL_EIO);
    122  1.1     alc 	}
    123  1.1     alc 
    124  1.1     alc 	OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr));
    125  1.1     alc 	OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4));
    126  1.1     alc 	ar5210SetOperatingMode(ah, opmode);
    127  1.1     alc 
    128  1.1     alc 	switch (opmode) {
    129  1.1     alc 	case HAL_M_HOSTAP:
    130  1.1     alc 		OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG);
    131  1.1     alc 		OS_REG_WRITE(ah, AR_PCICFG,
    132  1.1     alc 			AR_PCICFG_LED_ACT | AR_PCICFG_LED_BCTL);
    133  1.1     alc 		break;
    134  1.1     alc 	case HAL_M_IBSS:
    135  1.1     alc 		OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG | AR_BCR_BCMD);
    136  1.1     alc 		OS_REG_WRITE(ah, AR_PCICFG,
    137  1.1     alc 			AR_PCICFG_CLKRUNEN | AR_PCICFG_LED_PEND | AR_PCICFG_LED_BCTL);
    138  1.1     alc 		break;
    139  1.1     alc 	case HAL_M_STA:
    140  1.1     alc 		OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG);
    141  1.1     alc 		OS_REG_WRITE(ah, AR_PCICFG,
    142  1.1     alc 			AR_PCICFG_CLKRUNEN | AR_PCICFG_LED_PEND | AR_PCICFG_LED_BCTL);
    143  1.1     alc 		break;
    144  1.1     alc 	case HAL_M_MONITOR:
    145  1.1     alc 		OS_REG_WRITE(ah, AR_BCR, INIT_BCON_CNTRL_REG);
    146  1.1     alc 		OS_REG_WRITE(ah, AR_PCICFG,
    147  1.1     alc 			AR_PCICFG_LED_ACT | AR_PCICFG_LED_BCTL);
    148  1.1     alc 		break;
    149  1.1     alc 	}
    150  1.1     alc 
    151  1.1     alc 	/* Restore previous led state */
    152  1.1     alc 	OS_REG_WRITE(ah, AR_PCICFG, OS_REG_READ(ah, AR_PCICFG) | ledstate);
    153  1.1     alc 
    154  1.1     alc 	OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
    155  1.1     alc 	OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4));
    156  1.1     alc 
    157  1.1     alc 	OS_REG_WRITE(ah, AR_TXDP0, 0);
    158  1.1     alc 	OS_REG_WRITE(ah, AR_TXDP1, 0);
    159  1.1     alc 	OS_REG_WRITE(ah, AR_RXDP, 0);
    160  1.1     alc 
    161  1.1     alc 	/*
    162  1.1     alc 	 * Initialize interrupt state.
    163  1.1     alc 	 */
    164  1.1     alc 	(void) OS_REG_READ(ah, AR_ISR);		/* cleared on read */
    165  1.1     alc 	OS_REG_WRITE(ah, AR_IMR, 0);
    166  1.1     alc 	OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
    167  1.1     alc 	ahp->ah_maskReg = 0;
    168  1.1     alc 
    169  1.1     alc 	(void) OS_REG_READ(ah, AR_BSR);		/* cleared on read */
    170  1.1     alc 	OS_REG_WRITE(ah, AR_TXCFG, AR_DMASIZE_128B);
    171  1.1     alc 	OS_REG_WRITE(ah, AR_RXCFG, AR_DMASIZE_128B);
    172  1.1     alc 
    173  1.1     alc 	OS_REG_WRITE(ah, AR_TOPS, 8);		/* timeout prescale */
    174  1.1     alc 	OS_REG_WRITE(ah, AR_RXNOFRM, 8);	/* RX no frame timeout */
    175  1.1     alc 	OS_REG_WRITE(ah, AR_RPGTO, 0);		/* RX frame gap timeout */
    176  1.1     alc 	OS_REG_WRITE(ah, AR_TXNOFRM, 0);	/* TX no frame timeout */
    177  1.1     alc 
    178  1.1     alc 	OS_REG_WRITE(ah, AR_SFR, 0);
    179  1.1     alc 	OS_REG_WRITE(ah, AR_MIBC, 0);		/* unfreeze ctrs + clr state */
    180  1.1     alc 	OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);
    181  1.1     alc 	OS_REG_WRITE(ah, AR_CFP_DUR, 0);
    182  1.1     alc 
    183  1.1     alc 	ar5210SetRxFilter(ah, 0);		/* nothing for now */
    184  1.1     alc 	OS_REG_WRITE(ah, AR_MCAST_FIL0, 0);	/* multicast filter */
    185  1.1     alc 	OS_REG_WRITE(ah, AR_MCAST_FIL1, 0);	/* XXX was 2 */
    186  1.1     alc 
    187  1.1     alc 	OS_REG_WRITE(ah, AR_TX_MASK0, 0);
    188  1.1     alc 	OS_REG_WRITE(ah, AR_TX_MASK1, 0);
    189  1.1     alc 	OS_REG_WRITE(ah, AR_CLR_TMASK, 1);
    190  1.1     alc 	OS_REG_WRITE(ah, AR_TRIG_LEV, 1);	/* minimum */
    191  1.1     alc 
    192  1.1     alc 	OS_REG_WRITE(ah, AR_DIAG_SW, 0);
    193  1.1     alc 
    194  1.1     alc 	OS_REG_WRITE(ah, AR_CFP_PERIOD, 0);
    195  1.1     alc 	OS_REG_WRITE(ah, AR_TIMER0, 0);		/* next beacon time */
    196  1.1     alc 	OS_REG_WRITE(ah, AR_TSF_L32, 0);	/* local clock */
    197  1.1     alc 	OS_REG_WRITE(ah, AR_TIMER1, ~0);	/* next DMA beacon alert */
    198  1.1     alc 	OS_REG_WRITE(ah, AR_TIMER2, ~0);	/* next SW beacon alert */
    199  1.1     alc 	OS_REG_WRITE(ah, AR_TIMER3, 1);		/* next ATIM window */
    200  1.1     alc 
    201  1.1     alc 	/* Write the INI values for PHYreg initialization */
    202  1.1     alc 	for (i = 0; i < N(ar5k0007_init); i++) {
    203  1.1     alc 		uint32_t reg = ar5k0007_init[i].Offset;
    204  1.1     alc 		/* On channel change, don't reset the PCU registers */
    205  1.1     alc 		if (!(bChannelChange && (0x8000 <= reg && reg < 0x9000)))
    206  1.1     alc 			OS_REG_WRITE(ah, reg, ar5k0007_init[i].Value);
    207  1.1     alc 	}
    208  1.1     alc 
    209  1.1     alc 	/* Setup the transmit power values for cards since 0x0[0-2]05 */
    210  1.1     alc 	if (!ar5210SetTransmitPower(ah, chan)) {
    211  1.1     alc 		HALDEBUG(ah, HAL_DEBUG_ANY,
    212  1.1     alc 		    "%s: error init'ing transmit power\n", __func__);
    213  1.1     alc 		FAIL(HAL_EIO);
    214  1.1     alc 	}
    215  1.1     alc 
    216  1.1     alc 	OS_REG_WRITE(ah, AR_PHY(10),
    217  1.1     alc 		(OS_REG_READ(ah, AR_PHY(10)) & 0xFFFF00FF) |
    218  1.1     alc 		(ee->ee_xlnaOn << 8));
    219  1.1     alc 	OS_REG_WRITE(ah, AR_PHY(13),
    220  1.1     alc 		(ee->ee_xpaOff << 24) | (ee->ee_xpaOff << 16) |
    221  1.1     alc 		(ee->ee_xpaOn << 8) | ee->ee_xpaOn);
    222  1.1     alc 	OS_REG_WRITE(ah, AR_PHY(17),
    223  1.1     alc 		(OS_REG_READ(ah, AR_PHY(17)) & 0xFFFFC07F) |
    224  1.1     alc 		((ee->ee_antenna >> 1) & 0x3F80));
    225  1.1     alc 	OS_REG_WRITE(ah, AR_PHY(18),
    226  1.1     alc 		(OS_REG_READ(ah, AR_PHY(18)) & 0xFFFC0FFF) |
    227  1.1     alc 		((ee->ee_antenna << 10) & 0x3F000));
    228  1.1     alc 	OS_REG_WRITE(ah, AR_PHY(25),
    229  1.1     alc 		(OS_REG_READ(ah, AR_PHY(25)) & 0xFFF80FFF) |
    230  1.1     alc 		((ee->ee_thresh62 << 12) & 0x7F000));
    231  1.1     alc 	OS_REG_WRITE(ah, AR_PHY(68),
    232  1.1     alc 		(OS_REG_READ(ah, AR_PHY(68)) & 0xFFFFFFFC) |
    233  1.1     alc 		(ee->ee_antenna & 0x3));
    234  1.1     alc 
    235  1.1     alc 	if (!ar5210SetChannel(ah, ichan)) {
    236  1.1     alc 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unable to set channel\n",
    237  1.1     alc 		    __func__);
    238  1.1     alc 		FAIL(HAL_EIO);
    239  1.1     alc 	}
    240  1.1     alc 	if (bChannelChange) {
    241  1.1     alc 		if (!(ichan->privFlags & CHANNEL_DFS))
    242  1.1     alc 			ichan->privFlags &= ~CHANNEL_INTERFERENCE;
    243  1.1     alc 		chan->channelFlags = ichan->channelFlags;
    244  1.1     alc 		chan->privFlags = ichan->privFlags;
    245  1.1     alc 	}
    246  1.1     alc 
    247  1.1     alc 	/* Activate the PHY */
    248  1.1     alc 	OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ENABLE);
    249  1.1     alc 
    250  1.1     alc 	OS_DELAY(1000);		/* Wait a bit (1 msec) */
    251  1.1     alc 
    252  1.1     alc 	/* calibrate the HW and poll the bit going to 0 for completion */
    253  1.1     alc 	OS_REG_WRITE(ah, AR_PHY_AGCCTL,
    254  1.1     alc 		OS_REG_READ(ah, AR_PHY_AGCCTL) | AR_PHY_AGC_CAL);
    255  1.1     alc 	(void) ath_hal_wait(ah, AR_PHY_AGCCTL, AR_PHY_AGC_CAL, 0);
    256  1.1     alc 
    257  1.1     alc 	/* Perform noise floor calibration and set status */
    258  1.1     alc 	if (!ar5210CalNoiseFloor(ah, ichan)) {
    259  1.1     alc 		chan->channelFlags |= CHANNEL_CW_INT;
    260  1.1     alc 		HALDEBUG(ah, HAL_DEBUG_ANY,
    261  1.1     alc 		    "%s: noise floor calibration failed\n", __func__);
    262  1.1     alc 		FAIL(HAL_EIO);
    263  1.1     alc 	}
    264  1.1     alc 
    265  1.1     alc 	for (q = 0; q < HAL_NUM_TX_QUEUES; q++)
    266  1.1     alc 		ar5210ResetTxQueue(ah, q);
    267  1.1     alc 
    268  1.1     alc 	if (AH_PRIVATE(ah)->ah_rfkillEnabled)
    269  1.1     alc 		ar5210EnableRfKill(ah);
    270  1.1     alc 
    271  1.1     alc 	/*
    272  1.1     alc 	 * Writing to AR_BEACON will start timers. Hence it should be
    273  1.1     alc 	 * the last register to be written. Do not reset tsf, do not
    274  1.1     alc 	 * enable beacons at this point, but preserve other values
    275  1.1     alc 	 * like beaconInterval.
    276  1.1     alc 	 */
    277  1.1     alc 	OS_REG_WRITE(ah, AR_BEACON,
    278  1.1     alc 		(OS_REG_READ(ah, AR_BEACON) &
    279  1.1     alc 			~(AR_BEACON_EN | AR_BEACON_RESET_TSF)));
    280  1.1     alc 
    281  1.1     alc 	/* Restore user-specified slot time and timeouts */
    282  1.1     alc 	if (ahp->ah_sifstime != (u_int) -1)
    283  1.1     alc 		ar5210SetSifsTime(ah, ahp->ah_sifstime);
    284  1.1     alc 	if (ahp->ah_slottime != (u_int) -1)
    285  1.1     alc 		ar5210SetSlotTime(ah, ahp->ah_slottime);
    286  1.1     alc 	if (ahp->ah_acktimeout != (u_int) -1)
    287  1.1     alc 		ar5210SetAckTimeout(ah, ahp->ah_acktimeout);
    288  1.1     alc 	if (ahp->ah_ctstimeout != (u_int) -1)
    289  1.1     alc 		ar5210SetCTSTimeout(ah, ahp->ah_ctstimeout);
    290  1.1     alc 	if (AH_PRIVATE(ah)->ah_diagreg != 0)
    291  1.1     alc 		OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);
    292  1.1     alc 
    293  1.1     alc 	AH_PRIVATE(ah)->ah_opmode = opmode;	/* record operating mode */
    294  1.1     alc 
    295  1.1     alc 	HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__);
    296  1.1     alc 
    297  1.1     alc 	return AH_TRUE;
    298  1.1     alc bad:
    299  1.5  cegger 	if (status != AH_NULL)
    300  1.1     alc 		*status = ecode;
    301  1.1     alc 	return AH_FALSE;
    302  1.1     alc #undef FAIL
    303  1.1     alc #undef N
    304  1.1     alc }
    305  1.1     alc 
    306  1.1     alc static void
    307  1.1     alc ar5210SetOperatingMode(struct ath_hal *ah, int opmode)
    308  1.1     alc {
    309  1.1     alc 	struct ath_hal_5210 *ahp = AH5210(ah);
    310  1.1     alc 	uint32_t val;
    311  1.1     alc 
    312  1.1     alc 	val = OS_REG_READ(ah, AR_STA_ID1) & 0xffff;
    313  1.1     alc 	switch (opmode) {
    314  1.1     alc 	case HAL_M_HOSTAP:
    315  1.1     alc 		OS_REG_WRITE(ah, AR_STA_ID1, val
    316  1.1     alc 			| AR_STA_ID1_AP
    317  1.1     alc 			| AR_STA_ID1_NO_PSPOLL
    318  1.1     alc 			| AR_STA_ID1_DESC_ANTENNA
    319  1.1     alc 			| ahp->ah_staId1Defaults);
    320  1.1     alc 		break;
    321  1.1     alc 	case HAL_M_IBSS:
    322  1.1     alc 		OS_REG_WRITE(ah, AR_STA_ID1, val
    323  1.1     alc 			| AR_STA_ID1_ADHOC
    324  1.1     alc 			| AR_STA_ID1_NO_PSPOLL
    325  1.1     alc 			| AR_STA_ID1_DESC_ANTENNA
    326  1.1     alc 			| ahp->ah_staId1Defaults);
    327  1.1     alc 		break;
    328  1.1     alc 	case HAL_M_STA:
    329  1.1     alc 		OS_REG_WRITE(ah, AR_STA_ID1, val
    330  1.1     alc 			| AR_STA_ID1_NO_PSPOLL
    331  1.1     alc 			| AR_STA_ID1_PWR_SV
    332  1.1     alc 			| ahp->ah_staId1Defaults);
    333  1.1     alc 		break;
    334  1.1     alc 	case HAL_M_MONITOR:
    335  1.1     alc 		OS_REG_WRITE(ah, AR_STA_ID1, val
    336  1.1     alc 			| AR_STA_ID1_NO_PSPOLL
    337  1.1     alc 			| ahp->ah_staId1Defaults);
    338  1.1     alc 		break;
    339  1.1     alc 	}
    340  1.1     alc }
    341  1.1     alc 
    342  1.1     alc void
    343  1.1     alc ar5210SetPCUConfig(struct ath_hal *ah)
    344  1.1     alc {
    345  1.1     alc 	ar5210SetOperatingMode(ah, AH_PRIVATE(ah)->ah_opmode);
    346  1.1     alc }
    347  1.1     alc 
    348  1.1     alc /*
    349  1.1     alc  * Places the PHY and Radio chips into reset.  A full reset
    350  1.1     alc  * must be called to leave this state.  The PCI/MAC/PCU are
    351  1.1     alc  * not placed into reset as we must receive interrupt to
    352  1.1     alc  * re-enable the hardware.
    353  1.1     alc  */
    354  1.1     alc HAL_BOOL
    355  1.1     alc ar5210PhyDisable(struct ath_hal *ah)
    356  1.1     alc {
    357  1.1     alc 	return ar5210SetResetReg(ah, AR_RC_RPHY, 10);
    358  1.1     alc }
    359  1.1     alc 
    360  1.1     alc /*
    361  1.1     alc  * Places all of hardware into reset
    362  1.1     alc  */
    363  1.1     alc HAL_BOOL
    364  1.1     alc ar5210Disable(struct ath_hal *ah)
    365  1.1     alc {
    366  1.1     alc #define	AR_RC_HW (AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC)
    367  1.1     alc 	if (!ar5210SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
    368  1.1     alc 		return AH_FALSE;
    369  1.1     alc 
    370  1.1     alc 	/*
    371  1.1     alc 	 * Reset the HW - PCI must be reset after the rest of the
    372  1.1     alc 	 * device has been reset
    373  1.1     alc 	 */
    374  1.1     alc 	if (!ar5210SetResetReg(ah, AR_RC_HW, AR_RC_SETTLE_TIME))
    375  1.1     alc 		return AH_FALSE;
    376  1.1     alc 	OS_DELAY(1000);
    377  1.1     alc 	(void) ar5210SetResetReg(ah, AR_RC_HW | AR_RC_RPCI, AR_RC_SETTLE_TIME);
    378  1.1     alc 	OS_DELAY(2100);   /* 8245 @ 96Mhz hangs with 2000us. */
    379  1.1     alc 
    380  1.1     alc 	return AH_TRUE;
    381  1.1     alc #undef AR_RC_HW
    382  1.1     alc }
    383  1.1     alc 
    384  1.1     alc /*
    385  1.1     alc  * Places the hardware into reset and then pulls it out of reset
    386  1.1     alc  */
    387  1.1     alc HAL_BOOL
    388  1.1     alc ar5210ChipReset(struct ath_hal *ah, HAL_CHANNEL *chan)
    389  1.1     alc {
    390  1.1     alc #define	AR_RC_HW (AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC)
    391  1.1     alc 
    392  1.1     alc 	HALDEBUG(ah, HAL_DEBUG_RESET, "%s turbo %s\n", __func__,
    393  1.1     alc 		chan && IS_CHAN_TURBO(chan) ? "enabled" : "disabled");
    394  1.1     alc 
    395  1.1     alc 	if (!ar5210SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
    396  1.1     alc 		return AH_FALSE;
    397  1.1     alc 
    398  1.1     alc 	/* Place chip in turbo before reset to cleanly reset clocks */
    399  1.1     alc 	OS_REG_WRITE(ah, AR_PHY_FRCTL,
    400  1.1     alc 		chan && IS_CHAN_TURBO(chan) ? AR_PHY_TURBO_MODE : 0);
    401  1.1     alc 
    402  1.1     alc 	/*
    403  1.1     alc 	 * Reset the HW.
    404  1.1     alc 	 * PCI must be reset after the rest of the device has been reset.
    405  1.1     alc 	 */
    406  1.1     alc 	if (!ar5210SetResetReg(ah, AR_RC_HW, AR_RC_SETTLE_TIME))
    407  1.1     alc 		return AH_FALSE;
    408  1.1     alc 	OS_DELAY(1000);
    409  1.1     alc 	if (!ar5210SetResetReg(ah, AR_RC_HW | AR_RC_RPCI, AR_RC_SETTLE_TIME))
    410  1.1     alc 		return AH_FALSE;
    411  1.1     alc 	OS_DELAY(2100);   /* 8245 @ 96Mhz hangs with 2000us. */
    412  1.1     alc 
    413  1.1     alc 	/*
    414  1.1     alc 	 * Bring out of sleep mode (AGAIN)
    415  1.1     alc 	 *
    416  1.1     alc 	 * WARNING WARNING WARNING
    417  1.1     alc 	 *
    418  1.1     alc 	 * There is a problem with the chip where it doesn't always indicate
    419  1.1     alc 	 * that it's awake, so initializePowerUp() will fail.
    420  1.1     alc 	 */
    421  1.1     alc 	if (!ar5210SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE))
    422  1.1     alc 		return AH_FALSE;
    423  1.1     alc 
    424  1.1     alc 	/* Clear warm reset reg */
    425  1.1     alc 	return ar5210SetResetReg(ah, 0, 10);
    426  1.1     alc #undef AR_RC_HW
    427  1.1     alc }
    428  1.1     alc 
    429  1.1     alc enum {
    430  1.1     alc 	FIRPWR_M	= 0x03fc0000,
    431  1.1     alc 	FIRPWR_S	= 18,
    432  1.1     alc 	KCOARSEHIGH_M   = 0x003f8000,
    433  1.1     alc 	KCOARSEHIGH_S   = 15,
    434  1.1     alc 	KCOARSELOW_M	= 0x00007f80,
    435  1.1     alc 	KCOARSELOW_S	= 7,
    436  1.1     alc 	ADCSAT_ICOUNT_M	= 0x0001f800,
    437  1.1     alc 	ADCSAT_ICOUNT_S	= 11,
    438  1.1     alc 	ADCSAT_THRESH_M	= 0x000007e0,
    439  1.1     alc 	ADCSAT_THRESH_S	= 5
    440  1.1     alc };
    441  1.1     alc 
    442  1.1     alc /*
    443  1.1     alc  * Recalibrate the lower PHY chips to account for temperature/environment
    444  1.1     alc  * changes.
    445  1.1     alc  */
    446  1.1     alc HAL_BOOL
    447  1.1     alc ar5210PerCalibrationN(struct ath_hal *ah,  HAL_CHANNEL *chan, u_int chainMask,
    448  1.1     alc 	HAL_BOOL longCal, HAL_BOOL *isCalDone)
    449  1.1     alc {
    450  1.1     alc 	uint32_t regBeacon;
    451  1.1     alc 	uint32_t reg9858, reg985c, reg9868;
    452  1.1     alc 	HAL_CHANNEL_INTERNAL *ichan;
    453  1.1     alc 
    454  1.1     alc 	ichan = ath_hal_checkchannel(ah, chan);
    455  1.1     alc 	if (ichan == AH_NULL) {
    456  1.1     alc 		HALDEBUG(ah, HAL_DEBUG_ANY,
    457  1.1     alc 		    "%s: invalid channel %u/0x%x; no mapping\n",
    458  1.1     alc 		    __func__, chan->channel, chan->channelFlags);
    459  1.1     alc 		return AH_FALSE;
    460  1.1     alc 	}
    461  1.1     alc 	/* Disable tx and rx */
    462  1.1     alc 	OS_REG_WRITE(ah, AR_DIAG_SW,
    463  1.1     alc 		OS_REG_READ(ah, AR_DIAG_SW) | (AR_DIAG_SW_DIS_TX | AR_DIAG_SW_DIS_RX));
    464  1.1     alc 
    465  1.1     alc 	/* Disable Beacon Enable */
    466  1.1     alc 	regBeacon = OS_REG_READ(ah, AR_BEACON);
    467  1.1     alc 	OS_REG_WRITE(ah, AR_BEACON, regBeacon & ~AR_BEACON_EN);
    468  1.1     alc 
    469  1.1     alc 	/* Delay 4ms to ensure that all tx and rx activity has ceased */
    470  1.1     alc 	OS_DELAY(4000);
    471  1.1     alc 
    472  1.1     alc 	/* Disable AGC to radio traffic */
    473  1.1     alc 	OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) | 0x08000000);
    474  1.1     alc 	/* Wait for the AGC traffic to cease. */
    475  1.1     alc 	OS_DELAY(10);
    476  1.1     alc 
    477  1.1     alc 	/* Change Channel to relock synth */
    478  1.1     alc 	if (!ar5210SetChannel(ah, ichan))
    479  1.1     alc 		return AH_FALSE;
    480  1.1     alc 
    481  1.1     alc 	/* wait for the synthesizer lock to stabilize */
    482  1.1     alc 	OS_DELAY(1000);
    483  1.1     alc 
    484  1.1     alc 	/* Re-enable AGC to radio traffic */
    485  1.1     alc 	OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) & (~0x08000000));
    486  1.1     alc 
    487  1.1     alc 	/*
    488  1.1     alc 	 * Configure the AGC so that it is highly unlikely (if not
    489  1.1     alc 	 * impossible) for it to send any gain changes to the analog
    490  1.1     alc 	 * chip.  We store off the current values so that they can
    491  1.1     alc 	 * be rewritten below. Setting the following values:
    492  1.1     alc 	 * firpwr	 = -1
    493  1.1     alc 	 * Kcoursehigh   = -1
    494  1.1     alc 	 * Kcourselow	 = -127
    495  1.1     alc 	 * ADCsat_icount = 2
    496  1.1     alc 	 * ADCsat_thresh = 12
    497  1.1     alc 	 */
    498  1.1     alc 	reg9858 = OS_REG_READ(ah, 0x9858);
    499  1.1     alc 	reg985c = OS_REG_READ(ah, 0x985c);
    500  1.1     alc 	reg9868 = OS_REG_READ(ah, 0x9868);
    501  1.1     alc 
    502  1.1     alc 	OS_REG_WRITE(ah, 0x9858, (reg9858 & ~FIRPWR_M) |
    503  1.6   joerg 					 ((~0U << FIRPWR_S) & FIRPWR_M));
    504  1.1     alc 	OS_REG_WRITE(ah, 0x985c,
    505  1.1     alc 		 (reg985c & ~(KCOARSEHIGH_M | KCOARSELOW_M)) |
    506  1.6   joerg 		 ((~0U << KCOARSEHIGH_S) & KCOARSEHIGH_M) |
    507  1.7   jklos 		 ((((~0U << 7) + 1) << KCOARSELOW_S) & KCOARSELOW_M));
    508  1.1     alc 	OS_REG_WRITE(ah, 0x9868,
    509  1.1     alc 		 (reg9868 & ~(ADCSAT_ICOUNT_M | ADCSAT_THRESH_M)) |
    510  1.1     alc 		 ((2 << ADCSAT_ICOUNT_S) & ADCSAT_ICOUNT_M) |
    511  1.1     alc 		 ((12 << ADCSAT_THRESH_S) & ADCSAT_THRESH_M));
    512  1.1     alc 
    513  1.1     alc 	/* Wait for AGC changes to be enacted */
    514  1.1     alc 	OS_DELAY(20);
    515  1.1     alc 
    516  1.1     alc 	/*
    517  1.1     alc 	 * We disable RF mix/gain stages for the PGA to avoid a
    518  1.1     alc 	 * race condition that will occur with receiving a frame
    519  1.1     alc 	 * and performing the AGC calibration.  This will be
    520  1.1     alc 	 * re-enabled at the end of offset cal.  We turn off AGC
    521  1.1     alc 	 * writes during this write as it will go over the analog bus.
    522  1.1     alc 	 */
    523  1.1     alc 	OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) | 0x08000000);
    524  1.1     alc 	OS_DELAY(10);		 /* wait for the AGC traffic to cease */
    525  1.1     alc 	OS_REG_WRITE(ah, 0x98D4, 0x21);
    526  1.1     alc 	OS_REG_WRITE(ah, 0x9808, OS_REG_READ(ah, 0x9808) & (~0x08000000));
    527  1.1     alc 
    528  1.1     alc 	/* wait to make sure that additional AGC traffic has quiesced */
    529  1.1     alc 	OS_DELAY(1000);
    530  1.1     alc 
    531  1.1     alc 	/* AGC calibration (this was added to make the NF threshold check work) */
    532  1.1     alc 	OS_REG_WRITE(ah, AR_PHY_AGCCTL,
    533  1.1     alc 		 OS_REG_READ(ah, AR_PHY_AGCCTL) | AR_PHY_AGC_CAL);
    534  1.3     alc 	if (!ath_hal_wait(ah, AR_PHY_AGCCTL, AR_PHY_AGC_CAL, 0)) {
    535  1.1     alc 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: AGC calibration timeout\n",
    536  1.1     alc 		    __func__);
    537  1.3     alc 	}
    538  1.1     alc 
    539  1.1     alc 	/* Rewrite our AGC values we stored off earlier (return AGC to normal operation) */
    540  1.1     alc 	OS_REG_WRITE(ah, 0x9858, reg9858);
    541  1.1     alc 	OS_REG_WRITE(ah, 0x985c, reg985c);
    542  1.1     alc 	OS_REG_WRITE(ah, 0x9868, reg9868);
    543  1.1     alc 
    544  1.1     alc 	/* Perform noise floor and set status */
    545  1.1     alc 	if (!ar5210CalNoiseFloor(ah, ichan)) {
    546  1.1     alc 		/*
    547  1.1     alc 		 * Delay 5ms before retrying the noise floor -
    548  1.1     alc 		 * just to make sure.  We're in an error
    549  1.1     alc 		 * condition here
    550  1.1     alc 		 */
    551  1.1     alc 		HALDEBUG(ah, HAL_DEBUG_NFCAL | HAL_DEBUG_PERCAL,
    552  1.1     alc 		    "%s: Performing 2nd Noise Cal\n", __func__);
    553  1.1     alc 		OS_DELAY(5000);
    554  1.1     alc 		if (!ar5210CalNoiseFloor(ah, ichan))
    555  1.1     alc 			chan->channelFlags |= CHANNEL_CW_INT;
    556  1.1     alc 	}
    557  1.1     alc 
    558  1.1     alc 	/* Clear tx and rx disable bit */
    559  1.1     alc 	OS_REG_WRITE(ah, AR_DIAG_SW,
    560  1.1     alc 		 OS_REG_READ(ah, AR_DIAG_SW) & ~(AR_DIAG_SW_DIS_TX | AR_DIAG_SW_DIS_RX));
    561  1.1     alc 
    562  1.1     alc 	/* Re-enable Beacons */
    563  1.1     alc 	OS_REG_WRITE(ah, AR_BEACON, regBeacon);
    564  1.1     alc 
    565  1.1     alc 	*isCalDone = AH_TRUE;
    566  1.1     alc 
    567  1.1     alc 	return AH_TRUE;
    568  1.1     alc }
    569  1.1     alc 
    570  1.1     alc HAL_BOOL
    571  1.1     alc ar5210PerCalibration(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_BOOL *isIQdone)
    572  1.1     alc {
    573  1.1     alc 	return ar5210PerCalibrationN(ah,  chan, 0x1, AH_TRUE, isIQdone);
    574  1.1     alc }
    575  1.1     alc 
    576  1.1     alc HAL_BOOL
    577  1.1     alc ar5210ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan)
    578  1.1     alc {
    579  1.1     alc 	return AH_TRUE;
    580  1.1     alc }
    581  1.1     alc 
    582  1.1     alc /*
    583  1.1     alc  * Writes the given reset bit mask into the reset register
    584  1.1     alc  */
    585  1.1     alc static HAL_BOOL
    586  1.2     alc ar5210SetResetReg(struct ath_hal *ah, uint32_t resetMask, u_int waitTime)
    587  1.1     alc {
    588  1.1     alc 	uint32_t mask = resetMask ? resetMask : ~0;
    589  1.1     alc 	HAL_BOOL rt;
    590  1.1     alc 
    591  1.1     alc 	OS_REG_WRITE(ah, AR_RC, resetMask);
    592  1.1     alc 	/* need to wait at least 128 clocks when reseting PCI before read */
    593  1.2     alc 	OS_DELAY(waitTime);
    594  1.1     alc 
    595  1.1     alc 	resetMask &= AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC;
    596  1.1     alc 	mask &= AR_RC_RPCU | AR_RC_RDMA | AR_RC_RPHY | AR_RC_RMAC;
    597  1.1     alc 	rt = ath_hal_wait(ah, AR_RC, mask, resetMask);
    598  1.1     alc         if ((resetMask & AR_RC_RMAC) == 0) {
    599  1.1     alc 		if (isBigEndian()) {
    600  1.1     alc 			/*
    601  1.1     alc 			 * Set CFG, little-endian for register
    602  1.1     alc 			 * and descriptor accesses.
    603  1.1     alc 			 */
    604  1.1     alc 			mask = INIT_CONFIG_STATUS |
    605  1.1     alc 				AR_CFG_SWTD | AR_CFG_SWRD | AR_CFG_SWRG;
    606  1.1     alc 			OS_REG_WRITE(ah, AR_CFG, LE_READ_4(&mask));
    607  1.1     alc 		} else
    608  1.1     alc 			OS_REG_WRITE(ah, AR_CFG, INIT_CONFIG_STATUS);
    609  1.1     alc 	}
    610  1.1     alc 	return rt;
    611  1.1     alc }
    612  1.1     alc 
    613  1.1     alc 
    614  1.1     alc /*
    615  1.1     alc  * Returns: the pcdac value
    616  1.1     alc  */
    617  1.1     alc static uint8_t
    618  1.1     alc getPcdac(struct ath_hal *ah, const struct tpcMap *pRD, uint8_t dBm)
    619  1.1     alc {
    620  1.1     alc 	int32_t	 i;
    621  1.1     alc 	int useNextEntry = AH_FALSE;
    622  1.1     alc 	uint32_t interp;
    623  1.1     alc 
    624  1.1     alc 	for (i = AR_TP_SCALING_ENTRIES - 1; i >= 0; i--) {
    625  1.1     alc 		/* Check for exact entry */
    626  1.1     alc 		if (dBm == AR_I2DBM(i)) {
    627  1.1     alc 			if (pRD->pcdac[i] != 63)
    628  1.1     alc 				return pRD->pcdac[i];
    629  1.1     alc 			useNextEntry = AH_TRUE;
    630  1.1     alc 		} else if (dBm + 1 == AR_I2DBM(i) && i > 0) {
    631  1.1     alc 			/* Interpolate for between entry with a logish scale */
    632  1.1     alc 			if (pRD->pcdac[i] != 63 && pRD->pcdac[i-1] != 63) {
    633  1.1     alc 				interp = (350 * (pRD->pcdac[i] - pRD->pcdac[i-1])) + 999;
    634  1.1     alc 				interp = (interp / 1000) + pRD->pcdac[i-1];
    635  1.1     alc 				return interp;
    636  1.1     alc 			}
    637  1.1     alc 			useNextEntry = AH_TRUE;
    638  1.1     alc 		} else if (useNextEntry == AH_TRUE) {
    639  1.1     alc 			/* Grab the next lowest */
    640  1.1     alc 			if (pRD->pcdac[i] != 63)
    641  1.1     alc 				return pRD->pcdac[i];
    642  1.1     alc 		}
    643  1.1     alc 	}
    644  1.1     alc 
    645  1.1     alc 	/* Return the lowest Entry if we haven't returned */
    646  1.1     alc 	for (i = 0; i < AR_TP_SCALING_ENTRIES; i++)
    647  1.1     alc 		if (pRD->pcdac[i] != 63)
    648  1.1     alc 			return pRD->pcdac[i];
    649  1.1     alc 
    650  1.1     alc 	/* No value to return from table */
    651  1.1     alc #ifdef AH_DEBUG
    652  1.1     alc 	ath_hal_printf(ah, "%s: empty transmit power table?\n", __func__);
    653  1.1     alc #endif
    654  1.1     alc 	return 1;
    655  1.1     alc }
    656  1.1     alc 
    657  1.1     alc /*
    658  1.1     alc  * Find or interpolates the gainF value from the table ptr.
    659  1.1     alc  */
    660  1.1     alc static uint8_t
    661  1.1     alc getGainF(struct ath_hal *ah, const struct tpcMap *pRD,
    662  1.1     alc 	uint8_t pcdac, uint8_t *dBm)
    663  1.1     alc {
    664  1.1     alc 	uint32_t interp;
    665  1.1     alc 	int low, high, i;
    666  1.1     alc 
    667  1.1     alc 	low = high = -1;
    668  1.1     alc 
    669  1.1     alc 	for (i = 0; i < AR_TP_SCALING_ENTRIES; i++) {
    670  1.1     alc 		if(pRD->pcdac[i] == 63)
    671  1.1     alc 			continue;
    672  1.1     alc 		if (pcdac == pRD->pcdac[i]) {
    673  1.1     alc 			*dBm = AR_I2DBM(i);
    674  1.1     alc 			return pRD->gainF[i];  /* Exact Match */
    675  1.1     alc 		}
    676  1.1     alc 		if (pcdac > pRD->pcdac[i])
    677  1.1     alc 			low = i;
    678  1.1     alc 		if (pcdac < pRD->pcdac[i]) {
    679  1.1     alc 			high = i;
    680  1.1     alc 			if (low == -1) {
    681  1.1     alc 				*dBm = AR_I2DBM(i);
    682  1.1     alc 				/* PCDAC is lower than lowest setting */
    683  1.1     alc 				return pRD->gainF[i];
    684  1.1     alc 			}
    685  1.1     alc 			break;
    686  1.1     alc 		}
    687  1.1     alc 	}
    688  1.1     alc 	if (i >= AR_TP_SCALING_ENTRIES && low == -1) {
    689  1.1     alc 		/* No settings were found */
    690  1.1     alc #ifdef AH_DEBUG
    691  1.1     alc 		ath_hal_printf(ah,
    692  1.1     alc 			"%s: no valid entries in the pcdac table: %d\n",
    693  1.1     alc 			__func__, pcdac);
    694  1.1     alc #endif
    695  1.1     alc 		return 63;
    696  1.1     alc 	}
    697  1.1     alc 	if (i >= AR_TP_SCALING_ENTRIES) {
    698  1.1     alc 		/* PCDAC setting was above the max setting in the table */
    699  1.1     alc 		*dBm = AR_I2DBM(low);
    700  1.1     alc 		return pRD->gainF[low];
    701  1.1     alc 	}
    702  1.1     alc 	/* Only exact if table has no missing entries */
    703  1.1     alc 	*dBm = (low + high) + 3;
    704  1.1     alc 
    705  1.1     alc 	/*
    706  1.1     alc 	 * Perform interpolation between low and high values to find gainF
    707  1.1     alc 	 * linearly scale the pcdac between low and high
    708  1.1     alc 	 */
    709  1.1     alc 	interp = ((pcdac - pRD->pcdac[low]) * 1000) /
    710  1.1     alc 		  (pRD->pcdac[high] - pRD->pcdac[low]);
    711  1.1     alc 	/*
    712  1.1     alc 	 * Multiply the scale ratio by the gainF difference
    713  1.1     alc 	 * (plus a rnd up factor)
    714  1.1     alc 	 */
    715  1.1     alc 	interp = ((interp * (pRD->gainF[high] - pRD->gainF[low])) + 999) / 1000;
    716  1.1     alc 
    717  1.1     alc 	/* Add ratioed gain_f to low gain_f value */
    718  1.1     alc 	return interp + pRD->gainF[low];
    719  1.1     alc }
    720  1.1     alc 
    721  1.1     alc HAL_BOOL
    722  1.1     alc ar5210SetTxPowerLimit(struct ath_hal *ah, uint32_t limit)
    723  1.1     alc {
    724  1.1     alc 	AH_PRIVATE(ah)->ah_powerLimit = AH_MIN(limit, AR5210_MAX_RATE_POWER);
    725  1.1     alc 	/* XXX flush to h/w */
    726  1.1     alc 	return AH_TRUE;
    727  1.1     alc }
    728  1.1     alc 
    729  1.1     alc /*
    730  1.1     alc  * Get TXPower values and set them in the radio
    731  1.1     alc  */
    732  1.1     alc static HAL_BOOL
    733  1.1     alc setupPowerSettings(struct ath_hal *ah, HAL_CHANNEL *chan, uint8_t cp[17])
    734  1.1     alc {
    735  1.1     alc 	const HAL_EEPROM_v1 *ee = AH_PRIVATE(ah)->ah_eeprom;
    736  1.1     alc 	uint8_t gainFRD, gainF36, gainF48, gainF54;
    737  1.4     mrg 	uint8_t dBmRD = 0, dBm36 = 0, dBm48 = 0, dBm54 = 0, dontcare;
    738  1.1     alc 	uint32_t rd, group;
    739  1.1     alc 	const struct tpcMap  *pRD;
    740  1.1     alc 
    741  1.1     alc 	/* Set OB/DB Values regardless of channel */
    742  1.1     alc 	cp[15] = (ee->ee_biasCurrents >> 4) & 0x7;
    743  1.1     alc 	cp[16] = ee->ee_biasCurrents & 0x7;
    744  1.1     alc 
    745  1.1     alc 	if (chan->channel < 5170 || chan->channel > 5320) {
    746  1.1     alc 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u\n",
    747  1.1     alc 		    __func__, chan->channel);
    748  1.1     alc 		return AH_FALSE;
    749  1.1     alc 	}
    750  1.1     alc 
    751  1.1     alc 	HALASSERT(ee->ee_version >= AR_EEPROM_VER1 &&
    752  1.1     alc 	    ee->ee_version < AR_EEPROM_VER3);
    753  1.1     alc 
    754  1.1     alc 	/* Match regulatory domain */
    755  1.1     alc 	for (rd = 0; rd < AR_REG_DOMAINS_MAX; rd++)
    756  1.1     alc 		if (AH_PRIVATE(ah)->ah_currentRD == ee->ee_regDomain[rd])
    757  1.1     alc 			break;
    758  1.1     alc 	if (rd == AR_REG_DOMAINS_MAX) {
    759  1.1     alc #ifdef AH_DEBUG
    760  1.1     alc 		ath_hal_printf(ah,
    761  1.1     alc 			"%s: no calibrated regulatory domain matches the "
    762  1.1     alc 			"current regularly domain (0x%0x)\n", __func__,
    763  1.1     alc 			AH_PRIVATE(ah)->ah_currentRD);
    764  1.1     alc #endif
    765  1.1     alc 		return AH_FALSE;
    766  1.1     alc 	}
    767  1.1     alc 	group = ((chan->channel - 5170) / 10);
    768  1.1     alc 
    769  1.1     alc 	if (group > 11) {
    770  1.1     alc 		/* Pull 5.29 into the 5.27 group */
    771  1.1     alc 		group--;
    772  1.1     alc 	}
    773  1.1     alc 
    774  1.1     alc 	/* Integer divide will set group from 0 to 4 */
    775  1.1     alc 	group = group / 3;
    776  1.1     alc 	pRD   = &ee->ee_tpc[group];
    777  1.1     alc 
    778  1.1     alc 	/* Set PC DAC Values */
    779  1.1     alc 	cp[14] = pRD->regdmn[rd];
    780  1.1     alc 	cp[9]  = AH_MIN(pRD->regdmn[rd], pRD->rate36);
    781  1.1     alc 	cp[8]  = AH_MIN(pRD->regdmn[rd], pRD->rate48);
    782  1.1     alc 	cp[7]  = AH_MIN(pRD->regdmn[rd], pRD->rate54);
    783  1.1     alc 
    784  1.1     alc 	/* Find Corresponding gainF values for RD, 36, 48, 54 */
    785  1.1     alc 	gainFRD = getGainF(ah, pRD, pRD->regdmn[rd], &dBmRD);
    786  1.1     alc 	gainF36 = getGainF(ah, pRD, cp[9], &dBm36);
    787  1.1     alc 	gainF48 = getGainF(ah, pRD, cp[8], &dBm48);
    788  1.1     alc 	gainF54 = getGainF(ah, pRD, cp[7], &dBm54);
    789  1.1     alc 
    790  1.1     alc 	/* Power Scale if requested */
    791  1.1     alc 	if (AH_PRIVATE(ah)->ah_tpScale != HAL_TP_SCALE_MAX) {
    792  1.1     alc 		static const uint16_t tpcScaleReductionTable[5] =
    793  1.1     alc 			{ 0, 3, 6, 9, AR5210_MAX_RATE_POWER };
    794  1.1     alc 		uint16_t tpScale;
    795  1.1     alc 
    796  1.1     alc 		tpScale = tpcScaleReductionTable[AH_PRIVATE(ah)->ah_tpScale];
    797  1.1     alc 		if (dBmRD < tpScale+3)
    798  1.1     alc 			dBmRD = 3;		/* min */
    799  1.1     alc 		else
    800  1.1     alc 			dBmRD -= tpScale;
    801  1.1     alc 		cp[14]  = getPcdac(ah, pRD, dBmRD);
    802  1.1     alc 		gainFRD = getGainF(ah, pRD, cp[14], &dontcare);
    803  1.1     alc 		dBm36   = AH_MIN(dBm36, dBmRD);
    804  1.1     alc 		cp[9]   = getPcdac(ah, pRD, dBm36);
    805  1.1     alc 		gainF36 = getGainF(ah, pRD, cp[9], &dontcare);
    806  1.1     alc 		dBm48   = AH_MIN(dBm48, dBmRD);
    807  1.1     alc 		cp[8]   = getPcdac(ah, pRD, dBm48);
    808  1.1     alc 		gainF48 = getGainF(ah, pRD, cp[8], &dontcare);
    809  1.1     alc 		dBm54   = AH_MIN(dBm54, dBmRD);
    810  1.1     alc 		cp[7]   = getPcdac(ah, pRD, dBm54);
    811  1.1     alc 		gainF54 = getGainF(ah, pRD, cp[7], &dontcare);
    812  1.1     alc 	}
    813  1.1     alc 	/* Record current dBm at rate 6 */
    814  1.1     alc 	AH_PRIVATE(ah)->ah_maxPowerLevel = 2*dBmRD;
    815  1.1     alc 
    816  1.1     alc 	cp[13] = cp[12] = cp[11] = cp[10] = cp[14];
    817  1.1     alc 
    818  1.1     alc 	/* Set GainF Values */
    819  1.1     alc 	cp[0] = gainFRD - gainF54;
    820  1.1     alc 	cp[1] = gainFRD - gainF48;
    821  1.1     alc 	cp[2] = gainFRD - gainF36;
    822  1.1     alc 	/* 9, 12, 18, 24 have no gain_delta from 6 */
    823  1.1     alc 	cp[3] = cp[4] = cp[5] = cp[6] = 0;
    824  1.1     alc 	return AH_TRUE;
    825  1.1     alc }
    826  1.1     alc 
    827  1.1     alc /*
    828  1.1     alc  * Places the device in and out of reset and then places sane
    829  1.1     alc  * values in the registers based on EEPROM config, initialization
    830  1.1     alc  * vectors (as determined by the mode), and station configuration
    831  1.1     alc  */
    832  1.1     alc HAL_BOOL
    833  1.1     alc ar5210SetTransmitPower(struct ath_hal *ah, HAL_CHANNEL *chan)
    834  1.1     alc {
    835  1.1     alc #define	N(a)	(sizeof (a) / sizeof (a[0]))
    836  1.1     alc 	static const uint32_t pwr_regs_start[17] = {
    837  1.1     alc 		0x00000000, 0x00000000, 0x00000000,
    838  1.1     alc 		0x00000000, 0x00000000, 0xf0000000,
    839  1.1     alc 		0xcc000000, 0x00000000, 0x00000000,
    840  1.1     alc 		0x00000000, 0x0a000000, 0x000000e2,
    841  1.1     alc 		0x0a000020, 0x01000002, 0x01000018,
    842  1.1     alc 		0x40000000, 0x00000418
    843  1.1     alc 	};
    844  1.1     alc 	uint16_t i;
    845  1.1     alc 	uint8_t cp[sizeof(ar5k0007_pwrSettings)];
    846  1.1     alc 	uint32_t pwr_regs[17];
    847  1.1     alc 
    848  1.1     alc 	OS_MEMCPY(pwr_regs, pwr_regs_start, sizeof(pwr_regs));
    849  1.1     alc 	OS_MEMCPY(cp, ar5k0007_pwrSettings, sizeof(cp));
    850  1.1     alc 
    851  1.1     alc 	/* Check the EEPROM tx power calibration settings */
    852  1.1     alc 	if (!setupPowerSettings(ah, chan, cp)) {
    853  1.1     alc #ifdef AH_DEBUG
    854  1.1     alc 		ath_hal_printf(ah, "%s: unable to setup power settings\n",
    855  1.1     alc 			__func__);
    856  1.1     alc #endif
    857  1.1     alc 		return AH_FALSE;
    858  1.1     alc 	}
    859  1.1     alc 	if (cp[15] < 1 || cp[15] > 5) {
    860  1.1     alc #ifdef AH_DEBUG
    861  1.1     alc 		ath_hal_printf(ah, "%s: OB out of range (%u)\n",
    862  1.1     alc 			__func__, cp[15]);
    863  1.1     alc #endif
    864  1.1     alc 		return AH_FALSE;
    865  1.1     alc 	}
    866  1.1     alc 	if (cp[16] < 1 || cp[16] > 5) {
    867  1.1     alc #ifdef AH_DEBUG
    868  1.1     alc 		ath_hal_printf(ah, "%s: DB out of range (%u)\n",
    869  1.1     alc 			__func__, cp[16]);
    870  1.1     alc #endif
    871  1.1     alc 		return AH_FALSE;
    872  1.1     alc 	}
    873  1.1     alc 
    874  1.1     alc 	/* reverse bits of the transmit power array */
    875  1.1     alc 	for (i = 0; i < 7; i++)
    876  1.1     alc 		cp[i] = ath_hal_reverseBits(cp[i], 5);
    877  1.1     alc 	for (i = 7; i < 15; i++)
    878  1.1     alc 		cp[i] = ath_hal_reverseBits(cp[i], 6);
    879  1.1     alc 
    880  1.1     alc 	/* merge transmit power values into the register - quite gross */
    881  1.1     alc 	pwr_regs[0] |= ((cp[1] << 5) & 0xE0) | (cp[0] & 0x1F);
    882  1.1     alc 	pwr_regs[1] |= ((cp[3] << 7) & 0x80) | ((cp[2] << 2) & 0x7C) |
    883  1.1     alc 			((cp[1] >> 3) & 0x03);
    884  1.1     alc 	pwr_regs[2] |= ((cp[4] << 4) & 0xF0) | ((cp[3] >> 1) & 0x0F);
    885  1.1     alc 	pwr_regs[3] |= ((cp[6] << 6) & 0xC0) | ((cp[5] << 1) & 0x3E) |
    886  1.1     alc 		       ((cp[4] >> 4) & 0x01);
    887  1.1     alc 	pwr_regs[4] |= ((cp[7] << 3) & 0xF8) | ((cp[6] >> 2) & 0x07);
    888  1.1     alc 	pwr_regs[5] |= ((cp[9] << 7) & 0x80) | ((cp[8] << 1) & 0x7E) |
    889  1.1     alc 			((cp[7] >> 5) & 0x01);
    890  1.1     alc 	pwr_regs[6] |= ((cp[10] << 5) & 0xE0) | ((cp[9] >> 1) & 0x1F);
    891  1.1     alc 	pwr_regs[7] |= ((cp[11] << 3) & 0xF8) | ((cp[10] >> 3) & 0x07);
    892  1.1     alc 	pwr_regs[8] |= ((cp[12] << 1) & 0x7E) | ((cp[11] >> 5) & 0x01);
    893  1.1     alc 	pwr_regs[9] |= ((cp[13] << 5) & 0xE0);
    894  1.1     alc 	pwr_regs[10] |= ((cp[14] << 3) & 0xF8) | ((cp[13] >> 3) & 0x07);
    895  1.1     alc 	pwr_regs[11] |= ((cp[14] >> 5) & 0x01);
    896  1.1     alc 
    897  1.1     alc 	/* Set OB */
    898  1.1     alc 	pwr_regs[8] |=  (ath_hal_reverseBits(cp[15], 3) << 7) & 0x80;
    899  1.1     alc 	pwr_regs[9] |=  (ath_hal_reverseBits(cp[15], 3) >> 1) & 0x03;
    900  1.1     alc 
    901  1.1     alc 	/* Set DB */
    902  1.1     alc 	pwr_regs[9] |=  (ath_hal_reverseBits(cp[16], 3) << 2) & 0x1C;
    903  1.1     alc 
    904  1.1     alc 	/* Write the registers */
    905  1.1     alc 	for (i = 0; i < N(pwr_regs)-1; i++)
    906  1.1     alc 		OS_REG_WRITE(ah, 0x0000989c, pwr_regs[i]);
    907  1.1     alc 	/* last write is a flush */
    908  1.1     alc 	OS_REG_WRITE(ah, 0x000098d4, pwr_regs[i]);
    909  1.1     alc 
    910  1.1     alc 	return AH_TRUE;
    911  1.1     alc #undef N
    912  1.1     alc }
    913  1.1     alc 
    914  1.1     alc /*
    915  1.1     alc  * Takes the MHz channel value and sets the Channel value
    916  1.1     alc  *
    917  1.1     alc  * ASSUMES: Writes enabled to analog bus before AGC is active
    918  1.1     alc  *   or by disabling the AGC.
    919  1.1     alc  */
    920  1.1     alc static HAL_BOOL
    921  1.1     alc ar5210SetChannel(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
    922  1.1     alc {
    923  1.1     alc 	uint32_t data;
    924  1.1     alc 
    925  1.1     alc 	/* Set the Channel */
    926  1.1     alc 	data = ath_hal_reverseBits((chan->channel - 5120)/10, 5);
    927  1.1     alc 	data = (data << 1) | 0x41;
    928  1.1     alc 	OS_REG_WRITE(ah, AR_PHY(0x27), data);
    929  1.1     alc 	OS_REG_WRITE(ah, AR_PHY(0x30), 0);
    930  1.1     alc 	AH_PRIVATE(ah)->ah_curchan = chan;
    931  1.1     alc 	return AH_TRUE;
    932  1.1     alc }
    933  1.1     alc 
    934  1.1     alc int16_t
    935  1.1     alc ar5210GetNoiseFloor(struct ath_hal *ah)
    936  1.1     alc {
    937  1.1     alc 	int16_t nf;
    938  1.1     alc 
    939  1.1     alc 	nf = (OS_REG_READ(ah, AR_PHY(25)) >> 19) & 0x1ff;
    940  1.1     alc 	if (nf & 0x100)
    941  1.1     alc 		nf = 0 - ((nf ^ 0x1ff) + 1);
    942  1.1     alc 	return nf;
    943  1.1     alc }
    944  1.1     alc 
    945  1.1     alc #define NORMAL_NF_THRESH (-72)
    946  1.1     alc /*
    947  1.1     alc  * Peform the noisefloor calibration and check for
    948  1.1     alc  * any constant channel interference
    949  1.1     alc  *
    950  1.1     alc  * Returns: TRUE for a successful noise floor calibration; else FALSE
    951  1.1     alc  */
    952  1.1     alc HAL_BOOL
    953  1.1     alc ar5210CalNoiseFloor(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
    954  1.1     alc {
    955  1.1     alc 	int32_t nf, nfLoops;
    956  1.1     alc 
    957  1.1     alc 	/* Calibrate the noise floor */
    958  1.1     alc 	OS_REG_WRITE(ah, AR_PHY_AGCCTL,
    959  1.1     alc 		OS_REG_READ(ah, AR_PHY_AGCCTL) | AR_PHY_AGC_NF);
    960  1.1     alc 
    961  1.1     alc 	/* Do not read noise floor until it has done the first update */
    962  1.1     alc 	if (!ath_hal_wait(ah, AR_PHY_AGCCTL, AR_PHY_AGC_NF, 0)) {
    963  1.1     alc #ifdef ATH_HAL_DEBUG
    964  1.1     alc 		ath_hal_printf(ah, " -PHY NF Reg state: 0x%x\n",
    965  1.1     alc 			OS_REG_READ(ah, AR_PHY_AGCCTL));
    966  1.1     alc 		ath_hal_printf(ah, " -MAC Reset Reg state: 0x%x\n",
    967  1.1     alc 			OS_REG_READ(ah, AR_RC));
    968  1.1     alc 		ath_hal_printf(ah, " -PHY Active Reg state: 0x%x\n",
    969  1.1     alc 			OS_REG_READ(ah, AR_PHY_ACTIVE));
    970  1.1     alc #endif /* ATH_HAL_DEBUG */
    971  1.1     alc 		return AH_FALSE;
    972  1.1     alc 	}
    973  1.1     alc 
    974  1.1     alc 	nf = 0;
    975  1.1     alc 	/* Keep checking until the floor is below the threshold or the nf is done */
    976  1.1     alc 	for (nfLoops = 0; ((nfLoops < 21) && (nf > NORMAL_NF_THRESH)); nfLoops++) {
    977  1.1     alc 		OS_DELAY(1000); /* Sleep for 1 ms */
    978  1.1     alc 		nf = ar5210GetNoiseFloor(ah);
    979  1.1     alc 	}
    980  1.1     alc 
    981  1.1     alc 	if (nf > NORMAL_NF_THRESH) {
    982  1.1     alc 		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: Bad noise cal %d\n",
    983  1.1     alc 		    __func__, nf);
    984  1.1     alc 		chan->rawNoiseFloor = 0;
    985  1.1     alc 		return AH_FALSE;
    986  1.1     alc 	}
    987  1.1     alc 	chan->rawNoiseFloor = nf;
    988  1.1     alc 	return AH_TRUE;
    989  1.1     alc }
    990  1.1     alc 
    991  1.1     alc /*
    992  1.1     alc  * Adjust NF based on statistical values for 5GHz frequencies.
    993  1.1     alc  */
    994  1.1     alc int16_t
    995  1.1     alc ar5210GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c)
    996  1.1     alc {
    997  1.1     alc 	return 0;
    998  1.1     alc }
    999  1.1     alc 
   1000  1.1     alc HAL_RFGAIN
   1001  1.1     alc ar5210GetRfgain(struct ath_hal *ah)
   1002  1.1     alc {
   1003  1.1     alc 	return HAL_RFGAIN_INACTIVE;
   1004  1.1     alc }
   1005