ar9280_attach.c revision 221603
138032Speter/*
2132943Sgshapiro * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting
364562Sgshapiro * Copyright (c) 2008 Atheros Communications, Inc.
438032Speter *
538032Speter * Permission to use, copy, modify, and/or distribute this software for any
638032Speter * purpose with or without fee is hereby granted, provided that the above
738032Speter * copyright notice and this permission notice appear in all copies.
838032Speter *
938032Speter * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1038032Speter * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1138032Speter * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1238032Speter * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1338032Speter * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1464562Sgshapiro * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1564562Sgshapiro * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16132943Sgshapiro *
1738032Speter * $FreeBSD: head/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c 221603 2011-05-07 15:30:23Z adrian $
1890792Sgshapiro */
1938032Speter#include "opt_ah.h"
2090792Sgshapiro
2190792Sgshapiro#include "ah.h"
2290792Sgshapiro#include "ah_internal.h"
23120256Sgshapiro#include "ah_devid.h"
2490792Sgshapiro
25125820Sgshapiro#include "ah_eeprom_v14.h"		/* XXX for tx/rx gain */
26125820Sgshapiro
27125820Sgshapiro#include "ar9002/ar9280.h"
28125820Sgshapiro#include "ar5416/ar5416reg.h"
29125820Sgshapiro#include "ar5416/ar5416phy.h"
30125820Sgshapiro
31120256Sgshapiro#include "ar9002/ar9280v1.ini"
32125820Sgshapiro#include "ar9002/ar9280v2.ini"
33125820Sgshapiro#include "ar9002/ar9280_olc.h"
34125820Sgshapiro
35125820Sgshapirostatic const HAL_PERCAL_DATA ar9280_iq_cal = {		/* single sample */
3690792Sgshapiro	.calName = "IQ", .calType = IQ_MISMATCH_CAL,
3790792Sgshapiro	.calNumSamples	= MIN_CAL_SAMPLES,
38120256Sgshapiro	.calCountMax	= PER_MAX_LOG_COUNT,
39120256Sgshapiro	.calCollect	= ar5416IQCalCollect,
40132943Sgshapiro	.calPostProc	= ar5416IQCalibration
41132943Sgshapiro};
42132943Sgshapirostatic const HAL_PERCAL_DATA ar9280_adc_gain_cal = {	/* single sample */
4390792Sgshapiro	.calName = "ADC Gain", .calType = ADC_GAIN_CAL,
4490792Sgshapiro	.calNumSamples	= MIN_CAL_SAMPLES,
45132943Sgshapiro	.calCountMax	= PER_MIN_LOG_COUNT,
46132943Sgshapiro	.calCollect	= ar5416AdcGainCalCollect,
4790792Sgshapiro	.calPostProc	= ar5416AdcGainCalibration
4890792Sgshapiro};
4964562Sgshapirostatic const HAL_PERCAL_DATA ar9280_adc_dc_cal = {	/* single sample */
5090792Sgshapiro	.calName = "ADC DC", .calType = ADC_DC_CAL,
5190792Sgshapiro	.calNumSamples	= MIN_CAL_SAMPLES,
5238032Speter	.calCountMax	= PER_MIN_LOG_COUNT,
5338032Speter	.calCollect	= ar5416AdcDcCalCollect,
5438032Speter	.calPostProc	= ar5416AdcDcCalibration
5538032Speter};
5638032Speterstatic const HAL_PERCAL_DATA ar9280_adc_init_dc_cal = {
5738032Speter	.calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL,
5838032Speter	.calNumSamples	= MIN_CAL_SAMPLES,
5938032Speter	.calCountMax	= INIT_LOG_COUNT,
6038032Speter	.calCollect	= ar5416AdcDcCalCollect,
6138032Speter	.calPostProc	= ar5416AdcDcCalibration
6238032Speter};
6390792Sgshapiro
6490792Sgshapirostatic void ar9280ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore);
6590792Sgshapirostatic HAL_BOOL ar9280FillCapabilityInfo(struct ath_hal *ah);
6690792Sgshapirostatic void ar9280WriteIni(struct ath_hal *ah,
6738032Speter	const struct ieee80211_channel *chan);
6838032Speter
6938032Speterstatic void
7038032Speterar9280AniSetup(struct ath_hal *ah)
7138032Speter{
7290792Sgshapiro	/*
7390792Sgshapiro	 * These are the parameters from the AR5416 ANI code;
74120256Sgshapiro	 * they likely need quite a bit of adjustment for the
7538032Speter	 * AR9280.
76120256Sgshapiro	 */
77120256Sgshapiro        static const struct ar5212AniParams aniparams = {
78120256Sgshapiro                .maxNoiseImmunityLevel  = 4,    /* levels 0..4 */
79120256Sgshapiro                .totalSizeDesired       = { -55, -55, -55, -55, -62 },
80120256Sgshapiro                .coarseHigh             = { -14, -14, -14, -14, -12 },
81120256Sgshapiro                .coarseLow              = { -64, -64, -64, -64, -70 },
82120256Sgshapiro                .firpwr                 = { -78, -78, -78, -78, -80 },
83120256Sgshapiro                .maxSpurImmunityLevel   = 2,
84120256Sgshapiro                .cycPwrThr1             = { 2, 4, 6 },
85120256Sgshapiro                .maxFirstepLevel        = 2,    /* levels 0..2 */
86120256Sgshapiro                .firstep                = { 0, 4, 8 },
87120256Sgshapiro                .ofdmTrigHigh           = 500,
88120256Sgshapiro                .ofdmTrigLow            = 200,
89120256Sgshapiro                .cckTrigHigh            = 200,
9090792Sgshapiro                .cckTrigLow             = 100,
9194334Sgshapiro                .rssiThrHigh            = 40,
9294334Sgshapiro                .rssiThrLow             = 7,
9390792Sgshapiro                .period                 = 100,
9490792Sgshapiro        };
95111823Sgshapiro	/* NB: disable ANI noise immmunity for reliable RIFS rx */
9690792Sgshapiro	AH5416(ah)->ah_ani_function &= ~ HAL_ANI_NOISE_IMMUNITY_LEVEL;
9790792Sgshapiro
9890792Sgshapiro        /* NB: ANI is not enabled yet */
9990792Sgshapiro        ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE);
10090792Sgshapiro}
10190792Sgshapiro
10290792Sgshapiro/*
10390792Sgshapiro * Attach for an AR9280 part.
10490792Sgshapiro */
10590792Sgshapirostatic struct ath_hal *
10690792Sgshapiroar9280Attach(uint16_t devid, HAL_SOFTC sc,
10790792Sgshapiro	HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
10890792Sgshapiro	HAL_STATUS *status)
10990792Sgshapiro{
11090792Sgshapiro	struct ath_hal_9280 *ahp9280;
11190792Sgshapiro	struct ath_hal_5212 *ahp;
11290792Sgshapiro	struct ath_hal *ah;
11390792Sgshapiro	uint32_t val;
11490792Sgshapiro	HAL_STATUS ecode;
11590792Sgshapiro	HAL_BOOL rfStatus;
11690792Sgshapiro	int8_t pwr_table_offset;
11790792Sgshapiro	uint8_t pwr;
11890792Sgshapiro
11990792Sgshapiro	HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
12090792Sgshapiro	    __func__, sc, (void*) st, (void*) sh);
12190792Sgshapiro
12290792Sgshapiro	/* NB: memory is returned zero'd */
12390792Sgshapiro	ahp9280 = ath_hal_malloc(sizeof (struct ath_hal_9280));
12490792Sgshapiro	if (ahp9280 == AH_NULL) {
12590792Sgshapiro		HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
12690792Sgshapiro		    "%s: cannot allocate memory for state block\n", __func__);
12790792Sgshapiro		*status = HAL_ENOMEM;
12890792Sgshapiro		return AH_NULL;
12990792Sgshapiro	}
13090792Sgshapiro	ahp = AH5212(ahp9280);
13190792Sgshapiro	ah = &ahp->ah_priv.h;
13290792Sgshapiro
13390792Sgshapiro	ar5416InitState(AH5416(ah), devid, sc, st, sh, status);
13490792Sgshapiro
13590792Sgshapiro	/* XXX override with 9280 specific state */
13690792Sgshapiro	/* override 5416 methods for our needs */
13790792Sgshapiro	ah->ah_setAntennaSwitch		= ar9280SetAntennaSwitch;
13890792Sgshapiro	ah->ah_configPCIE		= ar9280ConfigPCIE;
13990792Sgshapiro
14090792Sgshapiro	AH5416(ah)->ah_cal.iqCalData.calData = &ar9280_iq_cal;
14190792Sgshapiro	AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9280_adc_gain_cal;
14294334Sgshapiro	AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9280_adc_dc_cal;
14364562Sgshapiro	AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9280_adc_init_dc_cal;
14490792Sgshapiro	AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
14590792Sgshapiro
14690792Sgshapiro	AH5416(ah)->ah_spurMitigate	= ar9280SpurMitigate;
14790792Sgshapiro	AH5416(ah)->ah_writeIni		= ar9280WriteIni;
14890792Sgshapiro	AH5416(ah)->ah_olcInit		= ar9280olcInit;
14964562Sgshapiro	AH5416(ah)->ah_olcTempCompensation = ar9280olcTemperatureCompensation;
15064562Sgshapiro	AH5416(ah)->ah_setPowerCalTable	= ar9280SetPowerCalTable;
15164562Sgshapiro
15264562Sgshapiro	AH5416(ah)->ah_rx_chainmask	= AR9280_DEFAULT_RXCHAINMASK;
15364562Sgshapiro	AH5416(ah)->ah_tx_chainmask	= AR9280_DEFAULT_TXCHAINMASK;
154110560Sgshapiro
15590792Sgshapiro	if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) {
15690792Sgshapiro		/* reset chip */
15790792Sgshapiro		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n",
15890792Sgshapiro		    __func__);
15990792Sgshapiro		ecode = HAL_EIO;
16038032Speter		goto bad;
16190792Sgshapiro	}
16290792Sgshapiro
16390792Sgshapiro	if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
16490792Sgshapiro		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n",
16590792Sgshapiro		    __func__);
16690792Sgshapiro		ecode = HAL_EIO;
16780785Sgshapiro		goto bad;
16890792Sgshapiro	}
16990792Sgshapiro	/* Read Revisions from Chips before taking out of reset */
17090792Sgshapiro	val = OS_REG_READ(ah, AR_SREV);
17190792Sgshapiro	HALDEBUG(ah, HAL_DEBUG_ATTACH,
17290792Sgshapiro	    "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n",
17390792Sgshapiro	    __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION),
17490792Sgshapiro	    MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION));
17590792Sgshapiro	/* NB: include chip type to differentiate from pre-Sowl versions */
17690792Sgshapiro	AH_PRIVATE(ah)->ah_macVersion =
17790792Sgshapiro	    (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S;
17890792Sgshapiro	AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION);
17990792Sgshapiro	AH_PRIVATE(ah)->ah_ispcie = (val & AR_XSREV_TYPE_HOST_MODE) == 0;
18090792Sgshapiro
18190792Sgshapiro	/* setup common ini data; rf backends handle remainder */
18290792Sgshapiro	if (AR_SREV_MERLIN_20_OR_LATER(ah)) {
18390792Sgshapiro		HAL_INI_INIT(&ahp->ah_ini_modes, ar9280Modes_v2, 6);
18490792Sgshapiro		HAL_INI_INIT(&ahp->ah_ini_common, ar9280Common_v2, 2);
18590792Sgshapiro		HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes,
18690792Sgshapiro		    ar9280PciePhy_clkreq_always_on_L1_v2, 2);
18790792Sgshapiro		HAL_INI_INIT(&ahp9280->ah_ini_xmodes,
18890792Sgshapiro		    ar9280Modes_fast_clock_v2, 3);
18990792Sgshapiro	} else {
19090792Sgshapiro		HAL_INI_INIT(&ahp->ah_ini_modes, ar9280Modes_v1, 6);
19190792Sgshapiro		HAL_INI_INIT(&ahp->ah_ini_common, ar9280Common_v1, 2);
19290792Sgshapiro		HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes,
19390792Sgshapiro		    ar9280PciePhy_v1, 2);
19490792Sgshapiro	}
19590792Sgshapiro	ar5416AttachPCIE(ah);
19690792Sgshapiro
19790792Sgshapiro	ecode = ath_hal_v14EepromAttach(ah);
19890792Sgshapiro	if (ecode != HAL_OK)
19990792Sgshapiro		goto bad;
20090792Sgshapiro
20190792Sgshapiro	if (!ar5416ChipReset(ah, AH_NULL)) {	/* reset chip */
20290792Sgshapiro		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
20390792Sgshapiro		ecode = HAL_EIO;
20490792Sgshapiro		goto bad;
20590792Sgshapiro	}
20690792Sgshapiro
20790792Sgshapiro	AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);
20890792Sgshapiro
20990792Sgshapiro	if (!ar5212ChipTest(ah)) {
21090792Sgshapiro		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
21190792Sgshapiro		    __func__);
21290792Sgshapiro		ecode = HAL_ESELFTEST;
21390792Sgshapiro		goto bad;
21490792Sgshapiro	}
21590792Sgshapiro
21690792Sgshapiro	/*
21790792Sgshapiro	 * Set correct Baseband to analog shift
21890792Sgshapiro	 * setting to access analog chips.
219110560Sgshapiro	 */
22090792Sgshapiro	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
22190792Sgshapiro
22290792Sgshapiro	/* Read Radio Chip Rev Extract */
22390792Sgshapiro	AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah);
22490792Sgshapiro	switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
22590792Sgshapiro        case AR_RAD2133_SREV_MAJOR:	/* Sowl: 2G/3x3 */
22690792Sgshapiro	case AR_RAD5133_SREV_MAJOR:	/* Sowl: 2+5G/3x3 */
22790792Sgshapiro		break;
22890792Sgshapiro	default:
22990792Sgshapiro		if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {
23090792Sgshapiro			AH_PRIVATE(ah)->ah_analog5GhzRev =
23190792Sgshapiro				AR_RAD5133_SREV_MAJOR;
23290792Sgshapiro			break;
23390792Sgshapiro		}
23490792Sgshapiro#ifdef AH_DEBUG
23590792Sgshapiro		HALDEBUG(ah, HAL_DEBUG_ANY,
23690792Sgshapiro		    "%s: 5G Radio Chip Rev 0x%02X is not supported by "
23790792Sgshapiro		    "this driver\n", __func__,
23890792Sgshapiro		    AH_PRIVATE(ah)->ah_analog5GhzRev);
23990792Sgshapiro		ecode = HAL_ENOTSUPP;
24090792Sgshapiro		goto bad;
241112810Sgshapiro#endif
24290792Sgshapiro	}
24390792Sgshapiro	rfStatus = ar9280RfAttach(ah, &ecode);
24490792Sgshapiro	if (!rfStatus) {
24590792Sgshapiro		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",
24690792Sgshapiro		    __func__, ecode);
24790792Sgshapiro		goto bad;
24890792Sgshapiro	}
24990792Sgshapiro
25090792Sgshapiro	/* Enable fixup for AR_AN_TOP2 if necessary */
25190792Sgshapiro	/*
25290792Sgshapiro	 * The v14 EEPROM layer returns HAL_EIO if PWDCLKIND isn't supported
25390792Sgshapiro	 * by the EEPROM version.
25490792Sgshapiro	 *
25590792Sgshapiro	 * ath9k checks the EEPROM minor version is >= 0x0a here, instead of
25690792Sgshapiro	 * the abstracted EEPROM access layer.
25790792Sgshapiro	 */
25890792Sgshapiro	ecode = ath_hal_eepromGet(ah, AR_EEP_PWDCLKIND, &pwr);
25990792Sgshapiro	if (AR_SREV_MERLIN_20_OR_LATER(ah) && ecode == HAL_OK && pwr == 0) {
26090792Sgshapiro		printf("[ath] enabling AN_TOP2_FIXUP\n");
26190792Sgshapiro		AH5416(ah)->ah_need_an_top2_fixup = 1;
26290792Sgshapiro	}
26390792Sgshapiro
26490792Sgshapiro        /*
26590792Sgshapiro         * Check whether the power table offset isn't the default.
26690792Sgshapiro         * This can occur with eeprom minor V21 or greater on Merlin.
26790792Sgshapiro         */
26890792Sgshapiro	(void) ath_hal_eepromGet(ah, AR_EEP_PWR_TABLE_OFFSET, &pwr_table_offset);
26990792Sgshapiro	if (pwr_table_offset != AR5416_PWR_TABLE_OFFSET_DB)
27090792Sgshapiro		ath_hal_printf(ah, "[ath]: default pwr offset: %d dBm != EEPROM pwr offset: %d dBm; curves will be adjusted.\n",
27190792Sgshapiro		    AR5416_PWR_TABLE_OFFSET_DB, (int) pwr_table_offset);
27290792Sgshapiro
27390792Sgshapiro	if (AR_SREV_MERLIN_20_OR_LATER(ah)) {
27490792Sgshapiro		/* setup rxgain table */
27590792Sgshapiro		switch (ath_hal_eepromGet(ah, AR_EEP_RXGAIN_TYPE, AH_NULL)) {
27690792Sgshapiro		case AR5416_EEP_RXGAIN_13dB_BACKOFF:
277110560Sgshapiro			HAL_INI_INIT(&ahp9280->ah_ini_rxgain,
27890792Sgshapiro			    ar9280Modes_backoff_13db_rxgain_v2, 6);
27990792Sgshapiro			break;
28090792Sgshapiro		case AR5416_EEP_RXGAIN_23dB_BACKOFF:
28190792Sgshapiro			HAL_INI_INIT(&ahp9280->ah_ini_rxgain,
28290792Sgshapiro			    ar9280Modes_backoff_23db_rxgain_v2, 6);
28390792Sgshapiro			break;
28490792Sgshapiro		case AR5416_EEP_RXGAIN_ORIG:
28590792Sgshapiro			HAL_INI_INIT(&ahp9280->ah_ini_rxgain,
28690792Sgshapiro			    ar9280Modes_original_rxgain_v2, 6);
28790792Sgshapiro			break;
288110560Sgshapiro		default:
28990792Sgshapiro			HALASSERT(AH_FALSE);
29080785Sgshapiro			goto bad;		/* XXX ? try to continue */
29180785Sgshapiro		}
29280785Sgshapiro	}
29380785Sgshapiro	if (AR_SREV_MERLIN_20_OR_LATER(ah)) {
29480785Sgshapiro		/* setp txgain table */
29580785Sgshapiro		switch (ath_hal_eepromGet(ah, AR_EEP_TXGAIN_TYPE, AH_NULL)) {
29690792Sgshapiro		case AR5416_EEP_TXGAIN_HIGH_POWER:
29780785Sgshapiro			HAL_INI_INIT(&ahp9280->ah_ini_txgain,
29880785Sgshapiro			    ar9280Modes_high_power_tx_gain_v2, 6);
299132943Sgshapiro			break;
30080785Sgshapiro		case AR5416_EEP_TXGAIN_ORIG:
30180785Sgshapiro			HAL_INI_INIT(&ahp9280->ah_ini_txgain,
30280785Sgshapiro			    ar9280Modes_original_tx_gain_v2, 6);
30380785Sgshapiro			break;
30498841Sgshapiro		default:
30580785Sgshapiro			HALASSERT(AH_FALSE);
30680785Sgshapiro			goto bad;		/* XXX ? try to continue */
307132943Sgshapiro		}
30880785Sgshapiro	}
30990792Sgshapiro
31080785Sgshapiro	/*
31180785Sgshapiro	 * Got everything we need now to setup the capabilities.
31280785Sgshapiro	 */
31380785Sgshapiro	if (!ar9280FillCapabilityInfo(ah)) {
31490792Sgshapiro		ecode = HAL_EEREAD;
315132943Sgshapiro		goto bad;
31680785Sgshapiro	}
31790792Sgshapiro
31880785Sgshapiro	ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
31980785Sgshapiro	if (ecode != HAL_OK) {
32080785Sgshapiro		HALDEBUG(ah, HAL_DEBUG_ANY,
32180785Sgshapiro		    "%s: error getting mac address from EEPROM\n", __func__);
32290792Sgshapiro		goto bad;
32338032Speter        }
32438032Speter	/* XXX How about the serial number ? */
32538032Speter	/* Read Reg Domain */
32638032Speter	AH_PRIVATE(ah)->ah_currentRD =
32790792Sgshapiro	    ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL);
32890792Sgshapiro	AH_PRIVATE(ah)->ah_currentRDext =
32938032Speter	    ath_hal_eepromGet(ah, AR_EEP_REGDMN_1, AH_NULL);
33038032Speter
33138032Speter	/*
33238032Speter	 * ah_miscMode is populated by ar5416FillCapabilityInfo()
33338032Speter	 * starting from griffin. Set here to make sure that
33490792Sgshapiro	 * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is
33538032Speter	 * placed into hardware.
33638032Speter	 */
33738032Speter	if (ahp->ah_miscMode != 0)
33838032Speter		OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode);
33990792Sgshapiro
34038032Speter	ar9280AniSetup(ah);			/* Anti Noise Immunity */
34138032Speter
34290792Sgshapiro	/* Setup noise floor min/max/nominal values */
34338032Speter	AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ;
34490792Sgshapiro	AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ;
34538032Speter	AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9280_2GHZ;
34638032Speter	AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ;
34764562Sgshapiro	AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ;
34838032Speter	AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9280_5GHZ;
34938032Speter
35038032Speter	ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist);
35138032Speter
35238032Speter	HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
35390792Sgshapiro
35464562Sgshapiro	return ah;
35590792Sgshapirobad:
35638032Speter	if (ah != AH_NULL)
35738032Speter		ah->ah_detach(ah);
35838032Speter	if (status)
35938032Speter		*status = ecode;
36038032Speter	return AH_NULL;
36138032Speter}
362125820Sgshapiro
363125820Sgshapirostatic void
364125820Sgshapiroar9280ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore)
365125820Sgshapiro{
366125820Sgshapiro	if (AH_PRIVATE(ah)->ah_ispcie && !restore) {
367125820Sgshapiro		ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0);
368125820Sgshapiro		OS_DELAY(1000);
369125820Sgshapiro		OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
370125820Sgshapiro		OS_REG_WRITE(ah, AR_WA, AR9280_WA_DEFAULT);
371125820Sgshapiro	}
372125820Sgshapiro}
373125820Sgshapiro
37438032Speterstatic void
37590792Sgshapiroar9280WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan)
37638032Speter{
377120256Sgshapiro	u_int modesIndex, freqIndex;
378120256Sgshapiro	int regWrites = 0;
379120256Sgshapiro	int i;
380120256Sgshapiro	const HAL_INI_ARRAY *ia;
381120256Sgshapiro
382120256Sgshapiro	/* Setup the indices for the next set of register array writes */
383120256Sgshapiro	/* XXX Ignore 11n dynamic mode on the AR5416 for the moment */
38438032Speter	if (IEEE80211_IS_CHAN_2GHZ(chan)) {
385120256Sgshapiro		freqIndex = 2;
386125820Sgshapiro		if (IEEE80211_IS_CHAN_HT40(chan))
387120256Sgshapiro			modesIndex = 3;
388125820Sgshapiro		else if (IEEE80211_IS_CHAN_108G(chan))
389120256Sgshapiro			modesIndex = 5;
390125820Sgshapiro		else
391120256Sgshapiro			modesIndex = 4;
392132943Sgshapiro	} else {
393120256Sgshapiro		freqIndex = 1;
394120256Sgshapiro		if (IEEE80211_IS_CHAN_HT40(chan) ||
395120256Sgshapiro		    IEEE80211_IS_CHAN_TURBO(chan))
396120256Sgshapiro			modesIndex = 2;
397120256Sgshapiro		else
398120256Sgshapiro			modesIndex = 1;
399132943Sgshapiro	}
400132943Sgshapiro
401120256Sgshapiro	/* Set correct Baseband to analog shift setting to access analog chips. */
402120256Sgshapiro	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
403120256Sgshapiro	OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
404120256Sgshapiro
405120256Sgshapiro	/*
40690792Sgshapiro	 * This is unwound because at the moment, there's a requirement
40738032Speter	 * for Merlin (and later, perhaps) to have a specific bit fixed
40838032Speter	 * in the AR_AN_TOP2 register before writing it.
40938032Speter	 */
41038032Speter	ia = &AH5212(ah)->ah_ini_modes;
41138032Speter#if 0
41264562Sgshapiro	regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes,
41338032Speter	    modesIndex, regWrites);
414125820Sgshapiro#endif
41564562Sgshapiro	HALASSERT(modesIndex < ia->cols);
41664562Sgshapiro	for (i = 0; i < ia->rows; i++) {
41764562Sgshapiro		uint32_t reg = HAL_INI_VAL(ia, i, 0);
41864562Sgshapiro		uint32_t val = HAL_INI_VAL(ia, i, modesIndex);
41964562Sgshapiro
42064562Sgshapiro		if (reg == AR_AN_TOP2 && AH5416(ah)->ah_need_an_top2_fixup)
42164562Sgshapiro			val &= ~AR_AN_TOP2_PWDCLKIND;
42298121Sgshapiro
42390792Sgshapiro		OS_REG_WRITE(ah, reg, val);
42464562Sgshapiro
425125820Sgshapiro		/* Analog shift register delay seems needed for Merlin - PR kern/154220 */
426125820Sgshapiro		if (reg >= 0x7800 && reg < 0x78a0)
427125820Sgshapiro			OS_DELAY(100);
428125820Sgshapiro
42938032Speter		DMA_YIELD(regWrites);
43064562Sgshapiro	}
43138032Speter
432125820Sgshapiro	if (AR_SREV_MERLIN_20_OR_LATER(ah)) {
433125820Sgshapiro		regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_rxgain,
434125820Sgshapiro		    modesIndex, regWrites);
435125820Sgshapiro		regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_txgain,
43664562Sgshapiro		    modesIndex, regWrites);
43738032Speter	}
438125820Sgshapiro	/* XXX Merlin 100us delay for shift registers */
439125820Sgshapiro	regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common,
440125820Sgshapiro	    1, regWrites);
44138032Speter
44264562Sgshapiro	if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) {
44390792Sgshapiro		/* 5GHz channels w/ Fast Clock use different modal values */
44464562Sgshapiro		regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_xmodes,
44564562Sgshapiro		    modesIndex, regWrites);
44664562Sgshapiro	}
44764562Sgshapiro}
44864562Sgshapiro
44938032Speter#define	AR_BASE_FREQ_2GHZ	2300
45038032Speter#define	AR_BASE_FREQ_5GHZ	4900
45138032Speter#define	AR_SPUR_FEEQ_BOUND_HT40	19
45238032Speter#define	AR_SPUR_FEEQ_BOUND_HT20	10
45338032Speter
45464562Sgshapirovoid
45538032Speterar9280SpurMitigate(struct ath_hal *ah, const struct ieee80211_channel *chan)
45638032Speter{
45764562Sgshapiro    static const int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
45838032Speter                AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 };
45990792Sgshapiro    static const int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
460120256Sgshapiro                AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 };
46190792Sgshapiro    static int inc[4] = { 0, 100, 0, 0 };
46238032Speter
46364562Sgshapiro    int bb_spur = AR_NO_SPUR;
46464562Sgshapiro    int freq;
46590792Sgshapiro    int bin, cur_bin;
46664562Sgshapiro    int bb_spur_off, spur_subchannel_sd;
46738032Speter    int spur_freq_sd;
46898121Sgshapiro    int spur_delta_phase;
46938032Speter    int denominator;
47038032Speter    int upper, lower, cur_vit_mask;
47138032Speter    int tmp, newVal;
47238032Speter    int i;
47390792Sgshapiro    CHAN_CENTERS centers;
47490792Sgshapiro
47590792Sgshapiro    int8_t mask_m[123];
47690792Sgshapiro    int8_t mask_p[123];
47738032Speter    int8_t mask_amt;
47838032Speter    int tmp_mask;
47990792Sgshapiro    int cur_bb_spur;
48038032Speter    HAL_BOOL is2GHz = IEEE80211_IS_CHAN_2GHZ(chan);
48138032Speter
48238032Speter    OS_MEMZERO(&mask_m, sizeof(int8_t) * 123);
48338032Speter    OS_MEMZERO(&mask_p, sizeof(int8_t) * 123);
48490792Sgshapiro
485132943Sgshapiro    ar5416GetChannelCenters(ah, chan, &centers);
48638032Speter    freq = centers.synth_center;
48738032Speter
48838032Speter    /*
48990792Sgshapiro     * Need to verify range +/- 9.38 for static ht20 and +/- 18.75 for ht40,
49090792Sgshapiro     * otherwise spur is out-of-band and can be ignored.
49190792Sgshapiro     */
49238032Speter    for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
49390792Sgshapiro        cur_bb_spur = ath_hal_getSpurChan(ah, i, is2GHz);
49438032Speter        /* Get actual spur freq in MHz from EEPROM read value */
49590792Sgshapiro        if (is2GHz) {
49690792Sgshapiro            cur_bb_spur =  (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
49738032Speter        } else {
49838032Speter            cur_bb_spur =  (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
49938032Speter        }
50038032Speter
50138032Speter        if (AR_NO_SPUR == cur_bb_spur)
50238032Speter            break;
50390792Sgshapiro        cur_bb_spur = cur_bb_spur - freq;
50464562Sgshapiro
50538032Speter        if (IEEE80211_IS_CHAN_HT40(chan)) {
50690792Sgshapiro            if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
50790792Sgshapiro                (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
508132943Sgshapiro                bb_spur = cur_bb_spur;
50990792Sgshapiro                break;
51090792Sgshapiro            }
51190792Sgshapiro        } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
51264562Sgshapiro                   (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
51398121Sgshapiro            bb_spur = cur_bb_spur;
51490792Sgshapiro            break;
51590792Sgshapiro        }
51690792Sgshapiro    }
51790792Sgshapiro
51890792Sgshapiro    if (AR_NO_SPUR == bb_spur) {
51990792Sgshapiro#if 1
52090792Sgshapiro        /*
52190792Sgshapiro         * MRC CCK can interfere with beacon detection and cause deaf/mute.
52290792Sgshapiro         * Disable MRC CCK for now.
52390792Sgshapiro         */
52490792Sgshapiro        OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
52590792Sgshapiro#else
52690792Sgshapiro        /* Enable MRC CCK if no spur is found in this channel. */
52790792Sgshapiro        OS_REG_SET_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
52890792Sgshapiro#endif
52990792Sgshapiro        return;
53090792Sgshapiro    } else {
53190792Sgshapiro        /*
53290792Sgshapiro         * For Merlin, spur can break CCK MRC algorithm. Disable CCK MRC if spur
53364562Sgshapiro         * is found in this channel.
53464562Sgshapiro         */
53564562Sgshapiro        OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
53664562Sgshapiro    }
53790792Sgshapiro
53890792Sgshapiro    bin = bb_spur * 320;
53938032Speter
54038032Speter    tmp = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0));
54190792Sgshapiro
54290792Sgshapiro    newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
54364562Sgshapiro        AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
54464562Sgshapiro        AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
54590792Sgshapiro        AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
54690792Sgshapiro    OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), newVal);
547120256Sgshapiro
548120256Sgshapiro    newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
54990792Sgshapiro        AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
55090792Sgshapiro        AR_PHY_SPUR_REG_MASK_RATE_SELECT |
55190792Sgshapiro        AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
552120256Sgshapiro        SM(AR5416_SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
55390792Sgshapiro    OS_REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
55438032Speter
55598121Sgshapiro    /* Pick control or extn channel to cancel the spur */
55664562Sgshapiro    if (IEEE80211_IS_CHAN_HT40(chan)) {
55738032Speter        if (bb_spur < 0) {
55838032Speter            spur_subchannel_sd = 1;
55938032Speter            bb_spur_off = bb_spur + 10;
56038032Speter        } else {
56190792Sgshapiro            spur_subchannel_sd = 0;
56238032Speter            bb_spur_off = bb_spur - 10;
56338032Speter        }
56464562Sgshapiro    } else {
56538032Speter        spur_subchannel_sd = 0;
56638032Speter        bb_spur_off = bb_spur;
56738032Speter    }
56890792Sgshapiro
56990792Sgshapiro    /*
570132943Sgshapiro     * spur_delta_phase = bb_spur/40 * 2**21 for static ht20,
57190792Sgshapiro     * /80 for dyn2040.
57290792Sgshapiro     */
57390792Sgshapiro    if (IEEE80211_IS_CHAN_HT40(chan))
57490792Sgshapiro        spur_delta_phase = ((bb_spur * 262144) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
57590792Sgshapiro    else
57690792Sgshapiro        spur_delta_phase = ((bb_spur * 524288) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
57790792Sgshapiro
57890792Sgshapiro    /*
57990792Sgshapiro     * in 11A mode the denominator of spur_freq_sd should be 40 and
58090792Sgshapiro     * it should be 44 in 11G
58190792Sgshapiro     */
58290792Sgshapiro    denominator = IEEE80211_IS_CHAN_2GHZ(chan) ? 44 : 40;
58390792Sgshapiro    spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
58490792Sgshapiro
58590792Sgshapiro    newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
58690792Sgshapiro        SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
58790792Sgshapiro        SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
58890792Sgshapiro    OS_REG_WRITE(ah, AR_PHY_TIMING11, newVal);
58964562Sgshapiro
59098121Sgshapiro    /* Choose to cancel between control and extension channels */
59138032Speter    newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
59238032Speter    OS_REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
59338032Speter
59438032Speter    /*
59538032Speter     * ============================================
59638032Speter     * Set Pilot and Channel Masks
59790792Sgshapiro     *
59838032Speter     * pilot mask 1 [31:0] = +6..-26, no 0 bin
59938032Speter     * pilot mask 2 [19:0] = +26..+7
60038032Speter     *
60190792Sgshapiro     * channel mask 1 [31:0] = +6..-26, no 0 bin
60238032Speter     * channel mask 2 [19:0] = +26..+7
60338032Speter     */
60490792Sgshapiro    cur_bin = -6000;
60538032Speter    upper = bin + 100;
60638032Speter    lower = bin - 100;
60790792Sgshapiro
60838032Speter    for (i = 0; i < 4; i++) {
60938032Speter        int pilot_mask = 0;
61090792Sgshapiro        int chan_mask  = 0;
61138032Speter        int bp         = 0;
61238032Speter        for (bp = 0; bp < 30; bp++) {
61390792Sgshapiro            if ((cur_bin > lower) && (cur_bin < upper)) {
61438032Speter                pilot_mask = pilot_mask | 0x1 << bp;
61590792Sgshapiro                chan_mask  = chan_mask | 0x1 << bp;
61690792Sgshapiro            }
61790792Sgshapiro            cur_bin += 100;
61890792Sgshapiro        }
61990792Sgshapiro        cur_bin += inc[i];
62090792Sgshapiro        OS_REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
62190792Sgshapiro        OS_REG_WRITE(ah, chan_mask_reg[i], chan_mask);
62290792Sgshapiro    }
62390792Sgshapiro
62490792Sgshapiro    /* =================================================
62590792Sgshapiro     * viterbi mask 1 based on channel magnitude
62638032Speter     * four levels 0-3
62738032Speter     *  - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c)
62838032Speter     *      [1 2 2 1] for -9.6 or [1 2 1] for +16
62938032Speter     *  - enable_mask_ppm, all bins move with freq
63090792Sgshapiro     *
63190792Sgshapiro     *  - mask_select,    8 bits for rates (reg 67,0x990c)
63290792Sgshapiro     *  - mask_rate_cntl, 8 bits for rates (reg 67,0x990c)
63390792Sgshapiro     *      choose which mask to use mask or mask2
63438032Speter     */
63538032Speter
63638032Speter    /*
63738032Speter     * viterbi mask 2  2nd set for per data rate puncturing
63890792Sgshapiro     * four levels 0-3
63990792Sgshapiro     *  - mask_select, 8 bits for rates (reg 67)
64038032Speter     *  - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994)
64190792Sgshapiro     *      [1 2 2 1] for -9.6 or [1 2 1] for +16
64290792Sgshapiro     */
64390792Sgshapiro    cur_vit_mask = 6100;
64490792Sgshapiro    upper        = bin + 120;
64538032Speter    lower        = bin - 120;
64638032Speter
64738032Speter    for (i = 0; i < 123; i++) {
64890792Sgshapiro        if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
64990792Sgshapiro            if ((abs(cur_vit_mask - bin)) < 75) {
65038032Speter                mask_amt = 1;
65138032Speter            } else {
65238032Speter                mask_amt = 0;
65338032Speter            }
65438032Speter            if (cur_vit_mask < 0) {
65538032Speter                mask_m[abs(cur_vit_mask / 100)] = mask_amt;
65638032Speter            } else {
65738032Speter                mask_p[cur_vit_mask / 100] = mask_amt;
65838032Speter            }
65938032Speter        }
66038032Speter        cur_vit_mask -= 100;
66138032Speter    }
66238032Speter
66338032Speter    tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
66438032Speter          | (mask_m[48] << 26) | (mask_m[49] << 24)
66590792Sgshapiro          | (mask_m[50] << 22) | (mask_m[51] << 20)
66690792Sgshapiro          | (mask_m[52] << 18) | (mask_m[53] << 16)
66738032Speter          | (mask_m[54] << 14) | (mask_m[55] << 12)
66838032Speter          | (mask_m[56] << 10) | (mask_m[57] <<  8)
66990792Sgshapiro          | (mask_m[58] <<  6) | (mask_m[59] <<  4)
67038032Speter          | (mask_m[60] <<  2) | (mask_m[61] <<  0);
67164562Sgshapiro    OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
67290792Sgshapiro    OS_REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
67338032Speter
67438032Speter    tmp_mask =             (mask_m[31] << 28)
67538032Speter          | (mask_m[32] << 26) | (mask_m[33] << 24)
67638032Speter          | (mask_m[34] << 22) | (mask_m[35] << 20)
67738032Speter          | (mask_m[36] << 18) | (mask_m[37] << 16)
67838032Speter          | (mask_m[48] << 14) | (mask_m[39] << 12)
67990792Sgshapiro          | (mask_m[40] << 10) | (mask_m[41] <<  8)
68090792Sgshapiro          | (mask_m[42] <<  6) | (mask_m[43] <<  4)
68138032Speter          | (mask_m[44] <<  2) | (mask_m[45] <<  0);
68238032Speter    OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
68338032Speter    OS_REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
68490792Sgshapiro
68590792Sgshapiro    tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
68638032Speter          | (mask_m[18] << 26) | (mask_m[18] << 24)
68764562Sgshapiro          | (mask_m[20] << 22) | (mask_m[20] << 20)
68864562Sgshapiro          | (mask_m[22] << 18) | (mask_m[22] << 16)
68990792Sgshapiro          | (mask_m[24] << 14) | (mask_m[24] << 12)
69090792Sgshapiro          | (mask_m[25] << 10) | (mask_m[26] <<  8)
69190792Sgshapiro          | (mask_m[27] <<  6) | (mask_m[28] <<  4)
69290792Sgshapiro          | (mask_m[29] <<  2) | (mask_m[30] <<  0);
69390792Sgshapiro    OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
69464562Sgshapiro    OS_REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
69538032Speter
69638032Speter    tmp_mask = (mask_m[ 0] << 30) | (mask_m[ 1] << 28)
69738032Speter          | (mask_m[ 2] << 26) | (mask_m[ 3] << 24)
69838032Speter          | (mask_m[ 4] << 22) | (mask_m[ 5] << 20)
69964562Sgshapiro          | (mask_m[ 6] << 18) | (mask_m[ 7] << 16)
70038032Speter          | (mask_m[ 8] << 14) | (mask_m[ 9] << 12)
70164562Sgshapiro          | (mask_m[10] << 10) | (mask_m[11] <<  8)
70290792Sgshapiro          | (mask_m[12] <<  6) | (mask_m[13] <<  4)
70390792Sgshapiro          | (mask_m[14] <<  2) | (mask_m[15] <<  0);
70490792Sgshapiro    OS_REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
70590792Sgshapiro    OS_REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
70690792Sgshapiro
70790792Sgshapiro    tmp_mask =             (mask_p[15] << 28)
70838032Speter          | (mask_p[14] << 26) | (mask_p[13] << 24)
70938032Speter          | (mask_p[12] << 22) | (mask_p[11] << 20)
71090792Sgshapiro          | (mask_p[10] << 18) | (mask_p[ 9] << 16)
71190792Sgshapiro          | (mask_p[ 8] << 14) | (mask_p[ 7] << 12)
71290792Sgshapiro          | (mask_p[ 6] << 10) | (mask_p[ 5] <<  8)
71390792Sgshapiro          | (mask_p[ 4] <<  6) | (mask_p[ 3] <<  4)
71490792Sgshapiro          | (mask_p[ 2] <<  2) | (mask_p[ 1] <<  0);
71590792Sgshapiro    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
71690792Sgshapiro    OS_REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
71790792Sgshapiro
71838032Speter    tmp_mask =             (mask_p[30] << 28)
71990792Sgshapiro          | (mask_p[29] << 26) | (mask_p[28] << 24)
72038032Speter          | (mask_p[27] << 22) | (mask_p[26] << 20)
72190792Sgshapiro          | (mask_p[25] << 18) | (mask_p[24] << 16)
72238032Speter          | (mask_p[23] << 14) | (mask_p[22] << 12)
72390792Sgshapiro          | (mask_p[21] << 10) | (mask_p[20] <<  8)
72438032Speter          | (mask_p[19] <<  6) | (mask_p[18] <<  4)
72590792Sgshapiro          | (mask_p[17] <<  2) | (mask_p[16] <<  0);
72638032Speter    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
72790792Sgshapiro    OS_REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
72871345Sgshapiro
72971345Sgshapiro    tmp_mask =             (mask_p[45] << 28)
73090792Sgshapiro          | (mask_p[44] << 26) | (mask_p[43] << 24)
73190792Sgshapiro          | (mask_p[42] << 22) | (mask_p[41] << 20)
73290792Sgshapiro          | (mask_p[40] << 18) | (mask_p[39] << 16)
73390792Sgshapiro          | (mask_p[38] << 14) | (mask_p[37] << 12)
73438032Speter          | (mask_p[36] << 10) | (mask_p[35] <<  8)
73538032Speter          | (mask_p[34] <<  6) | (mask_p[33] <<  4)
73690792Sgshapiro          | (mask_p[32] <<  2) | (mask_p[31] <<  0);
73790792Sgshapiro    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
73890792Sgshapiro    OS_REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
73990792Sgshapiro
74090792Sgshapiro    tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
74138032Speter          | (mask_p[59] << 26) | (mask_p[58] << 24)
74290792Sgshapiro          | (mask_p[57] << 22) | (mask_p[56] << 20)
74338032Speter          | (mask_p[55] << 18) | (mask_p[54] << 16)
74464562Sgshapiro          | (mask_p[53] << 14) | (mask_p[52] << 12)
74590792Sgshapiro          | (mask_p[51] << 10) | (mask_p[50] <<  8)
74638032Speter          | (mask_p[49] <<  6) | (mask_p[48] <<  4)
74738032Speter          | (mask_p[47] <<  2) | (mask_p[46] <<  0);
74838032Speter    OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
74938032Speter    OS_REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
75090792Sgshapiro}
751132943Sgshapiro
75238032Speter/*
75338032Speter * Fill all software cached or static hardware state information.
75438032Speter * Return failure if capabilities are to come from EEPROM and
75538032Speter * cannot be read.
75638032Speter */
75738032Speterstatic HAL_BOOL
75838032Speterar9280FillCapabilityInfo(struct ath_hal *ah)
75938032Speter{
76038032Speter	HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
76138032Speter
76238032Speter	if (!ar5416FillCapabilityInfo(ah))
76338032Speter		return AH_FALSE;
76438032Speter	pCap->halNumGpioPins = 10;
76564562Sgshapiro	pCap->halWowSupport = AH_TRUE;
76638032Speter	pCap->halWowMatchPatternExact = AH_TRUE;
76738032Speter#if 0
76838032Speter	pCap->halWowMatchPatternDword = AH_TRUE;
76964562Sgshapiro#endif
77038032Speter	/* AR9280 is a 2x2 stream device */
77138032Speter	pCap->halTxStreams = 2;
77238032Speter	pCap->halRxStreams = 2;
77390792Sgshapiro
77438032Speter	pCap->halCSTSupport = AH_TRUE;
77538032Speter	pCap->halRifsRxSupport = AH_TRUE;
77643730Speter	pCap->halRifsTxSupport = AH_TRUE;
77738032Speter	pCap->halRtsAggrLimit = 64*1024;	/* 802.11n max */
77838032Speter	pCap->halExtChanDfsSupport = AH_TRUE;
77938032Speter#if 0
78064562Sgshapiro	/* XXX bluetooth */
78164562Sgshapiro	pCap->halBtCoexSupport = AH_TRUE;
78238032Speter#endif
78338032Speter	pCap->halAutoSleepSupport = AH_FALSE;	/* XXX? */
78438032Speter	pCap->hal4kbSplitTransSupport = AH_FALSE;
78538032Speter	/* Disable this so Block-ACK works correctly */
78638032Speter	pCap->halHasRxSelfLinkedTail = AH_FALSE;
78738032Speter	pCap->halMbssidAggrSupport = AH_TRUE;
78838032Speter	pCap->hal4AddrAggrSupport = AH_TRUE;
78938032Speter
79038032Speter	if (AR_SREV_MERLIN_20_OR_LATER(ah))
79138032Speter		pCap->halPSPollBroken = AH_FALSE;
79238032Speter	pCap->halRxStbcSupport = 1;
79390792Sgshapiro	pCap->halTxStbcSupport = 1;
79438032Speter
79564562Sgshapiro	return AH_TRUE;
79664562Sgshapiro}
79738032Speter
79864562Sgshapiro/*
79990792Sgshapiro * This has been disabled - having the HAL flip chainmasks on/off
80090792Sgshapiro * when attempting to implement 11n disrupts things. For now, just
80190792Sgshapiro * leave this flipped off and worry about implementing TX diversity
80264562Sgshapiro * for legacy and MCS0-7 when 11n is fully functioning.
80390792Sgshapiro */
80490792SgshapiroHAL_BOOL
80564562Sgshapiroar9280SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
80664562Sgshapiro{
80764562Sgshapiro#define ANTENNA0_CHAINMASK    0x1
80864562Sgshapiro#define ANTENNA1_CHAINMASK    0x2
80938032Speter#if 0
81038032Speter	struct ath_hal_5416 *ahp = AH5416(ah);
81164562Sgshapiro
81238032Speter	/* Antenna selection is done by setting the tx/rx chainmasks approp. */
81338032Speter	switch (settings) {
81490792Sgshapiro	case HAL_ANT_FIXED_A:
81590792Sgshapiro		/* Enable first antenna only */
81638032Speter		ahp->ah_tx_chainmask = ANTENNA0_CHAINMASK;
81790792Sgshapiro		ahp->ah_rx_chainmask = ANTENNA0_CHAINMASK;
81838032Speter		break;
81938032Speter	case HAL_ANT_FIXED_B:
82064562Sgshapiro		/* Enable second antenna only, after checking capability */
82164562Sgshapiro		if (AH_PRIVATE(ah)->ah_caps.halTxChainMask > ANTENNA1_CHAINMASK)
82238032Speter			ahp->ah_tx_chainmask = ANTENNA1_CHAINMASK;
82390792Sgshapiro		ahp->ah_rx_chainmask = ANTENNA1_CHAINMASK;
82490792Sgshapiro		break;
82590792Sgshapiro	case HAL_ANT_VARIABLE:
82638032Speter		/* Restore original chainmask settings */
82764562Sgshapiro		/* XXX */
82864562Sgshapiro		ahp->ah_tx_chainmask = AR9280_DEFAULT_TXCHAINMASK;
82938032Speter		ahp->ah_rx_chainmask = AR9280_DEFAULT_RXCHAINMASK;
83038032Speter		break;
83190792Sgshapiro	}
83238032Speter
83338032Speter	HALDEBUG(ah, HAL_DEBUG_ANY, "%s: settings=%d, tx/rx chainmask=%d/%d\n",
83438032Speter	    __func__, settings, ahp->ah_tx_chainmask, ahp->ah_rx_chainmask);
83538032Speter
83690792Sgshapiro#endif
83738032Speter	return AH_TRUE;
83838032Speter#undef ANTENNA0_CHAINMASK
83938032Speter#undef ANTENNA1_CHAINMASK
84038032Speter}
84138032Speter
84238032Speterstatic const char*
84338032Speterar9280Probe(uint16_t vendorid, uint16_t devid)
84490792Sgshapiro{
84590792Sgshapiro	if (vendorid == ATHEROS_VENDOR_ID &&
84690792Sgshapiro	    (devid == AR9280_DEVID_PCI || devid == AR9280_DEVID_PCIE))
84790792Sgshapiro		return "Atheros 9280";
84838032Speter	return AH_NULL;
84938032Speter}
85038032SpeterAH_CHIP(AR9280, ar9280Probe, ar9280Attach);
85138032Speter