HAL_BOOL ar5416StopTxDma(struct ath_hal*ah, a_uint32_t q)
{
	a_uint32_t i;
	
        HALASSERT(q < AH_PRIVATE(ah)->ah_caps.halTotalQueues);

        HALASSERT(AH5416(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);

        OS_REG_WRITE(ah, AR_Q_TXD, 1 << q);
        for (i = 1000; i != 0; i--) {
                if (ar5416NumTxPending(ah, q) == 0)
                        break;
                OS_DELAY(100);        /* XXX get actual value */
        }

        OS_REG_WRITE(ah, AR_Q_TXD, 0);
        return (i != 0);
}
Exemple #2
0
void
ar9130InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan)
{

	uint32_t pll;

	/*
	 * XXX TODO: support half/quarter rates
	 */
	if (chan && IEEE80211_IS_CHAN_5GHZ(chan))
		pll = 0x1450;
	else
		pll = 0x1458;

	OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
	OS_DELAY(RTC_PLL_SETTLE_DELAY);
	OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK);
}
Exemple #3
0
/*
 * Stop transmit on the specified queue
 */
HAL_BOOL
ar5211StopTxDma(struct ath_hal *ah, u_int q)
{
	int i;

	HALASSERT(q < HAL_NUM_TX_QUEUES);
	HALASSERT(AH5211(ah)->ah_txq[q].tqi_type != HAL_TX_QUEUE_INACTIVE);

	OS_REG_WRITE(ah, AR_Q_TXD, 1<<q);
	for (i = 0; i < 10000; i++) {
		if (ar5211NumTxPending(ah, q) == 0)
			break;
		OS_DELAY(10);
	}
	OS_REG_WRITE(ah, AR_Q_TXD, 0);

	return (i < 10000);
}
Exemple #4
0
/*
 * set vap pause in progress flag .
 */
static inline void 
ath_vap_pause_set_in_progress(struct ath_softc *sc)
{
    int iter_count=0;
    systime_t           start_timestamp  = OS_GET_TIMESTAMP(); 
    systime_t           cur_timestamp ; 
    
    while(atomic_read(&sc->sc_txq_use_cnt)) {
        OS_DELAY(10);                            
        ++ iter_count;                           
        if ((iter_count % 1000) == 0) {          
            cur_timestamp  = OS_GET_TIMESTAMP();    
            if (CONVERT_SYSTEM_TIME_TO_MS(cur_timestamp - start_timestamp) >= VAP_PAUSE_SYNCHRONIZATION_TIMEOUT) { 
                ASSERT(0);                         
            }                                      
        }                                        
    }
    atomic_set(&sc->sc_vap_pause_in_progress, 1);
}
Exemple #5
0
/*
 * set vap pause in progress flag .
 */
static inline void 
ath_vap_pause_set_in_progress(struct ath_softc *sc)
{
    int iter_count=0;
    systime_t           start_timestamp  = OS_GET_TIMESTAMP(); 
    systime_t           cur_timestamp ; 
    spin_lock(&(sc)->sc_vap_pause_lock);
    while(sc->sc_txq_use_cnt) {
        spin_unlock(&(sc)->sc_vap_pause_lock);
        OS_DELAY(10);                            
        ++ iter_count;                           
        if ((iter_count % 1000) == 0) {          
            cur_timestamp  = OS_GET_TIMESTAMP();    
            if (CONVERT_SYSTEM_TIME_TO_MS(cur_timestamp - start_timestamp) >= VAP_PAUSE_SYNCHRONIZATION_TIMEOUT) { 
                ASSERT(0);                         
            }                                      
        }                                        
        spin_lock(&(sc)->sc_vap_pause_lock);
    }
    sc->sc_vap_pause_in_progress=1;
    spin_unlock(&(sc)->sc_vap_pause_lock);
}
void task_i2c_get_temp_func(const struct task_item *task)
{
        uint8_t temp[2];
        int t_out, fract;

        /*
         * Wait in OS friendly way for request to run.
         */
        if (!read_temp_enabled) {
                OS_EVENT_WAIT(event, OS_EVENT_FOREVER);
        }

        /*
         * Require I2C for exclusively reading temperature from FM75 and release it after operation.
         */
        resource_acquire(RES_MASK(RES_ID_I2C1), RES_WAIT_FOREVER);

        set_target_address(FM75_ADDRESS);

        /*
         * Read actual temperature values from FM75.
         */
        fm75_read_reg(FM75_REG_TEMP, temp, sizeof(temp));

        resource_release(RES_MASK(RES_ID_I2C1));

        /*
         * Send results to UART.
         */
        t_out = convert_temp(temp, &fract);
        printf("current temperature: %d.%04d C" NEWLINE, t_out, fract);

        /*
         * Wait 1 second to get temperature again.
         */
        OS_DELAY(1000);
}
Exemple #7
0
CDF_STATUS hif_exchange_bmi_msg(struct ol_softc *scn,
		     uint8_t *bmi_request,
		     uint32_t request_length,
		     uint8_t *bmi_response,
		     uint32_t *bmi_response_lengthp, uint32_t TimeoutMS)
{
	struct HIF_CE_state *hif_state = (struct HIF_CE_state *)scn->hif_hdl;
	struct HIF_CE_pipe_info *send_pipe_info =
		&(hif_state->pipe_info[BMI_CE_NUM_TO_TARG]);
	struct CE_handle *ce_send_hdl = send_pipe_info->ce_hdl;
	cdf_dma_addr_t CE_request, CE_response = 0;
	struct BMI_transaction *transaction = NULL;
	int status = CDF_STATUS_SUCCESS;
	struct HIF_CE_pipe_info *recv_pipe_info =
		&(hif_state->pipe_info[BMI_CE_NUM_TO_HOST]);
	struct CE_handle *ce_recv = recv_pipe_info->ce_hdl;
	unsigned int mux_id = 0;
	unsigned int transaction_id = 0xffff;
	unsigned int user_flags = 0;
#ifdef BMI_RSP_POLLING
	cdf_dma_addr_t buf;
	unsigned int completed_nbytes, id, flags;
	int i;
#endif

	transaction =
		(struct BMI_transaction *)cdf_mem_malloc(sizeof(*transaction));
	if (unlikely(!transaction)) {
		HIF_ERROR("%s: no memory", __func__);
		return CDF_STATUS_E_NOMEM;
	}
	transaction_id = (mux_id & MUX_ID_MASK) |
		(transaction_id & TRANSACTION_ID_MASK);
#ifdef QCA_WIFI_3_0
	user_flags &= DESC_DATA_FLAG_MASK;
#endif
	A_TARGET_ACCESS_LIKELY(scn);

	/* Initialize bmi_transaction_sem to block */
	cdf_semaphore_init(&transaction->bmi_transaction_sem);
	cdf_semaphore_acquire(scn->cdf_dev, &transaction->bmi_transaction_sem);

	transaction->hif_state = hif_state;
	transaction->bmi_request_host = bmi_request;
	transaction->bmi_request_length = request_length;
	transaction->bmi_response_length = 0;
	transaction->bmi_timeout_ms = TimeoutMS;
	transaction->bmi_transaction_flags = 0;

	/*
	 * CE_request = dma_map_single(dev,
	 * (void *)bmi_request, request_length, DMA_TO_DEVICE);
	 */
	CE_request = scn->bmi_cmd_da;
	transaction->bmi_request_CE = CE_request;

	if (bmi_response) {

		/*
		 * CE_response = dma_map_single(dev, bmi_response,
		 * BMI_DATASZ_MAX, DMA_FROM_DEVICE);
		 */
		CE_response = scn->bmi_rsp_da;
		transaction->bmi_response_host = bmi_response;
		transaction->bmi_response_CE = CE_response;
		/* dma_cache_sync(dev, bmi_response,
		    BMI_DATASZ_MAX, DMA_FROM_DEVICE); */
		cdf_os_mem_dma_sync_single_for_device(scn->cdf_dev,
					       CE_response,
					       BMI_DATASZ_MAX,
					       DMA_FROM_DEVICE);
		ce_recv_buf_enqueue(ce_recv, transaction,
				    transaction->bmi_response_CE);
		/* NB: see HIF_BMI_recv_done */
	} else {
		transaction->bmi_response_host = NULL;
		transaction->bmi_response_CE = 0;
	}

	/* dma_cache_sync(dev, bmi_request, request_length, DMA_TO_DEVICE); */
	cdf_os_mem_dma_sync_single_for_device(scn->cdf_dev, CE_request,
				       request_length, DMA_TO_DEVICE);

	status =
		ce_send(ce_send_hdl, transaction,
			CE_request, request_length,
			transaction_id, 0, user_flags);
	ASSERT(status == CDF_STATUS_SUCCESS);
	/* NB: see hif_bmi_send_done */

	/* TBDXXX: handle timeout */

	/* Wait for BMI request/response transaction to complete */
	/* Always just wait for BMI request here if
	 * BMI_RSP_POLLING is defined */
	while (cdf_semaphore_acquire
		       (scn->cdf_dev, &transaction->bmi_transaction_sem)) {
		/*need some break out condition(time out?) */
	}

	if (bmi_response) {
#ifdef BMI_RSP_POLLING
		/* Fix EV118783, do not wait a semaphore for the BMI response
		 * since the relative interruption may be lost.
		 * poll the BMI response instead.
		 */
		i = 0;
		while (ce_completed_recv_next(
			    ce_recv, NULL, NULL, &buf,
			    &completed_nbytes, &id,
			    &flags) != CDF_STATUS_SUCCESS) {
			if (i++ > BMI_RSP_TO_MILLISEC) {
				HIF_ERROR("%s:error, can't get bmi response\n",
					__func__);
				status = CDF_STATUS_E_BUSY;
				break;
			}
			OS_DELAY(1000);
		}

		if ((status == CDF_STATUS_SUCCESS) && bmi_response_lengthp)
			*bmi_response_lengthp = completed_nbytes;
#else
		if ((status == CDF_STATUS_SUCCESS) && bmi_response_lengthp) {
			*bmi_response_lengthp =
				transaction->bmi_response_length;
		}
#endif

	}

	/* dma_unmap_single(dev, transaction->bmi_request_CE,
		request_length, DMA_TO_DEVICE); */
	/* bus_unmap_single(scn->sc_osdev,
		 transaction->bmi_request_CE,
		request_length, BUS_DMA_TODEVICE); */

	if (status != CDF_STATUS_SUCCESS) {
		cdf_dma_addr_t unused_buffer;
		unsigned int unused_nbytes;
		unsigned int unused_id;
		unsigned int toeplitz_hash_result;

		ce_cancel_send_next(ce_send_hdl,
			NULL, NULL, &unused_buffer,
			&unused_nbytes, &unused_id,
			&toeplitz_hash_result);
	}

	A_TARGET_ACCESS_UNLIKELY(scn);
	cdf_mem_free(transaction);
	return status;
}
Exemple #8
0
static void
ar9280AniSetup(struct ath_hal *ah)
{
	/*
	 * These are the parameters from the AR5416 ANI code;
	 * they likely need quite a bit of adjustment for the
	 * AR9280.
	 */
        static const struct ar5212AniParams aniparams = {
                .maxNoiseImmunityLevel  = 4,    /* levels 0..4 */
                .totalSizeDesired       = { -55, -55, -55, -55, -62 },
                .coarseHigh             = { -14, -14, -14, -14, -12 },
                .coarseLow              = { -64, -64, -64, -64, -70 },
                .firpwr                 = { -78, -78, -78, -78, -80 },
                .maxSpurImmunityLevel   = 2,
                .cycPwrThr1             = { 2, 4, 6 },
                .maxFirstepLevel        = 2,    /* levels 0..2 */
                .firstep                = { 0, 4, 8 },
                .ofdmTrigHigh           = 500,
                .ofdmTrigLow            = 200,
                .cckTrigHigh            = 200,
                .cckTrigLow             = 100,
                .rssiThrHigh            = 40,
                .rssiThrLow             = 7,
                .period                 = 100,
        };
	/* NB: disable ANI noise immmunity for reliable RIFS rx */
	AH5416(ah)->ah_ani_function &= ~(1 << HAL_ANI_NOISE_IMMUNITY_LEVEL);

        /* NB: ANI is not enabled yet */
        ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE);
}

void
ar9280InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
	uint32_t pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);

	if (AR_SREV_MERLIN_20(ah) &&
	    chan != AH_NULL && IEEE80211_IS_CHAN_5GHZ(chan)) {
		/*
		 * PLL WAR for Merlin 2.0/2.1
		 * When doing fast clock, set PLL to 0x142c
		 * Else, set PLL to 0x2850 to prevent reset-to-reset variation 
		 */
		pll = IS_5GHZ_FAST_CLOCK_EN(ah, chan) ? 0x142c : 0x2850;
	} else if (AR_SREV_MERLIN_10_OR_LATER(ah)) {
		pll = SM(0x5, AR_RTC_SOWL_PLL_REFDIV);
		if (chan != AH_NULL) {
			if (IEEE80211_IS_CHAN_HALF(chan))
				pll |= SM(0x1, AR_RTC_SOWL_PLL_CLKSEL);
			else if (IEEE80211_IS_CHAN_QUARTER(chan))
				pll |= SM(0x2, AR_RTC_SOWL_PLL_CLKSEL);
			if (IEEE80211_IS_CHAN_5GHZ(chan))
				pll |= SM(0x28, AR_RTC_SOWL_PLL_DIV);
			else
				pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV);
		} else
			pll |= SM(0x2c, AR_RTC_SOWL_PLL_DIV);
	}

	OS_REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
	OS_DELAY(RTC_PLL_SETTLE_DELAY);
	OS_REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_SLEEP_DERIVED_CLK);
}
Exemple #9
0
static void
ar9280WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
	u_int modesIndex, freqIndex;
	int regWrites = 0;
	int i;
	const HAL_INI_ARRAY *ia;

	/* Setup the indices for the next set of register array writes */
	/* XXX Ignore 11n dynamic mode on the AR5416 for the moment */
	if (IEEE80211_IS_CHAN_2GHZ(chan)) {
		freqIndex = 2;
		if (IEEE80211_IS_CHAN_HT40(chan))
			modesIndex = 3;
		else if (IEEE80211_IS_CHAN_108G(chan))
			modesIndex = 5;
		else
			modesIndex = 4;
	} else {
		freqIndex = 1;
		if (IEEE80211_IS_CHAN_HT40(chan) ||
		    IEEE80211_IS_CHAN_TURBO(chan))
			modesIndex = 2;
		else
			modesIndex = 1;
	}

	/* Set correct Baseband to analog shift setting to access analog chips. */
	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
	OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);

	/*
	 * This is unwound because at the moment, there's a requirement
	 * for Merlin (and later, perhaps) to have a specific bit fixed
	 * in the AR_AN_TOP2 register before writing it.
	 */
	ia = &AH5212(ah)->ah_ini_modes;
#if 0
	regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes,
	    modesIndex, regWrites);
#endif
	HALASSERT(modesIndex < ia->cols);
	for (i = 0; i < ia->rows; i++) {
		uint32_t reg = HAL_INI_VAL(ia, i, 0);
		uint32_t val = HAL_INI_VAL(ia, i, modesIndex);

		if (reg == AR_AN_TOP2 && AH5416(ah)->ah_need_an_top2_fixup)
			val &= ~AR_AN_TOP2_PWDCLKIND;

		OS_REG_WRITE(ah, reg, val);

		/* Analog shift register delay seems needed for Merlin - PR kern/154220 */
		if (reg >= 0x7800 && reg < 0x7900)
			OS_DELAY(100);

		DMA_YIELD(regWrites);
	}

	if (AR_SREV_MERLIN_20_OR_LATER(ah)) {
		regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_rxgain,
		    modesIndex, regWrites);
		regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_txgain,
		    modesIndex, regWrites);
	}
	/* XXX Merlin 100us delay for shift registers */
	regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common,
	    1, regWrites);

	if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) {
		/* 5GHz channels w/ Fast Clock use different modal values */
		regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_xmodes,
		    modesIndex, regWrites);
	}
}
Exemple #10
0
static void
ar9287AniSetup(struct ath_hal *ah)
{
	/*
	 * These are the parameters from the AR5416 ANI code;
	 * they likely need quite a bit of adjustment for the
	 * AR9280.
	 */
        static const struct ar5212AniParams aniparams = {
                .maxNoiseImmunityLevel  = 4,    /* levels 0..4 */
                .totalSizeDesired       = { -55, -55, -55, -55, -62 },
                .coarseHigh             = { -14, -14, -14, -14, -12 },
                .coarseLow              = { -64, -64, -64, -64, -70 },
                .firpwr                 = { -78, -78, -78, -78, -80 },
                .maxSpurImmunityLevel   = 2,
                .cycPwrThr1             = { 2, 4, 6 },
                .maxFirstepLevel        = 2,    /* levels 0..2 */
                .firstep                = { 0, 4, 8 },
                .ofdmTrigHigh           = 500,
                .ofdmTrigLow            = 200,
                .cckTrigHigh            = 200,
                .cckTrigLow             = 100,
                .rssiThrHigh            = 40,
                .rssiThrLow             = 7,
                .period                 = 100,
        };
	/* NB: disable ANI noise immmunity for reliable RIFS rx */
	AH5416(ah)->ah_ani_function &= ~ HAL_ANI_NOISE_IMMUNITY_LEVEL;

        /* NB: ANI is not enabled yet */
        ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE);
}

/*
 * Attach for an AR9287 part.
 */
static struct ath_hal *
ar9287Attach(uint16_t devid, HAL_SOFTC sc,
	HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
	HAL_STATUS *status)
{
	struct ath_hal_9287 *ahp9287;
	struct ath_hal_5212 *ahp;
	struct ath_hal *ah;
	uint32_t val;
	HAL_STATUS ecode;
	HAL_BOOL rfStatus;
	int8_t pwr_table_offset;

	HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
	    __func__, sc, (void*) st, (void*) sh);

	/* NB: memory is returned zero'd */
	ahp9287 = ath_hal_malloc(sizeof (struct ath_hal_9287));
	if (ahp9287 == AH_NULL) {
		HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
		    "%s: cannot allocate memory for state block\n", __func__);
		*status = HAL_ENOMEM;
		return AH_NULL;
	}
	ahp = AH5212(ahp9287);
	ah = &ahp->ah_priv.h;

	ar5416InitState(AH5416(ah), devid, sc, st, sh, status);

	/* XXX override with 9280 specific state */
	/* override 5416 methods for our needs */
	AH5416(ah)->ah_initPLL = ar9280InitPLL;

	ah->ah_setAntennaSwitch		= ar9287SetAntennaSwitch;
	ah->ah_configPCIE		= ar9287ConfigPCIE;

	AH5416(ah)->ah_cal.iqCalData.calData = &ar9287_iq_cal;
	AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9287_adc_gain_cal;
	AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9287_adc_dc_cal;
	AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9287_adc_init_dc_cal;
	/* Better performance without ADC Gain Calibration */
	AH5416(ah)->ah_cal.suppCals = ADC_DC_CAL | IQ_MISMATCH_CAL;

	AH5416(ah)->ah_spurMitigate	= ar9280SpurMitigate;
	AH5416(ah)->ah_writeIni		= ar9287WriteIni;

	ah->ah_setTxPower		= ar9287SetTransmitPower;
	ah->ah_setBoardValues		= ar9287SetBoardValues;

	AH5416(ah)->ah_olcInit		= ar9287olcInit;
	AH5416(ah)->ah_olcTempCompensation = ar9287olcTemperatureCompensation;
	//AH5416(ah)->ah_setPowerCalTable	= ar9287SetPowerCalTable;
	AH5416(ah)->ah_cal_initcal	= ar9287InitCalHardware;
	AH5416(ah)->ah_cal_pacal	= ar9287PACal;

	/* XXX NF calibration */
	/* XXX Ini override? (IFS vars - since the kiwi mac clock is faster?) */
	/* XXX what else is kiwi-specific in the radio/calibration pathway? */

	AH5416(ah)->ah_rx_chainmask	= AR9287_DEFAULT_RXCHAINMASK;
	AH5416(ah)->ah_tx_chainmask	= AR9287_DEFAULT_TXCHAINMASK;

	if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) {
		/* reset chip */
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n",
		    __func__);
		ecode = HAL_EIO;
		goto bad;
	}

	if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n",
		    __func__);
		ecode = HAL_EIO;
		goto bad;
	}
	/* Read Revisions from Chips before taking out of reset */
	val = OS_REG_READ(ah, AR_SREV);
	HALDEBUG(ah, HAL_DEBUG_ATTACH,
	    "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n",
	    __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION),
	    MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION));
	/* NB: include chip type to differentiate from pre-Sowl versions */
	AH_PRIVATE(ah)->ah_macVersion =
	    (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S;
	AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION);
	AH_PRIVATE(ah)->ah_ispcie = (val & AR_XSREV_TYPE_HOST_MODE) == 0;

	/* Don't support Kiwi < 1.2; those are pre-release chips */
	if (! AR_SREV_KIWI_12_OR_LATER(ah)) {
		ath_hal_printf(ah, "[ath]: Kiwi < 1.2 is not supported\n");
		ecode = HAL_EIO;
		goto bad;
	}

	/* setup common ini data; rf backends handle remainder */
	HAL_INI_INIT(&ahp->ah_ini_modes, ar9287Modes_9287_1_1, 6);
	HAL_INI_INIT(&ahp->ah_ini_common, ar9287Common_9287_1_1, 2);

	/* If pcie_clock_req */
	HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes,
	    ar9287PciePhy_clkreq_always_on_L1_9287_1_1, 2);

	/* XXX WoW ini values */

	/* Else */
#if 0
	HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes,
	    ar9287PciePhy_clkreq_off_L1_9287_1_1, 2);
#endif

	/* Initialise Japan arrays */
	HAL_INI_INIT(&ahp9287->ah_ini_cckFirNormal,
	    ar9287Common_normal_cck_fir_coeff_9287_1_1, 2);
	HAL_INI_INIT(&ahp9287->ah_ini_cckFirJapan2484,
	    ar9287Common_japan_2484_cck_fir_coeff_9287_1_1, 2);

	ar5416AttachPCIE(ah);

	ecode = ath_hal_9287EepromAttach(ah);
	if (ecode != HAL_OK)
		goto bad;

	if (!ar5416ChipReset(ah, AH_NULL)) {	/* reset chip */
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
		ecode = HAL_EIO;
		goto bad;
	}

	AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);

	if (!ar5212ChipTest(ah)) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
		    __func__);
		ecode = HAL_ESELFTEST;
		goto bad;
	}

	/*
	 * Set correct Baseband to analog shift
	 * setting to access analog chips.
	 */
	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);

	/* Read Radio Chip Rev Extract */
	AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah);
	switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
        case AR_RAD2133_SREV_MAJOR:	/* Sowl: 2G/3x3 */
	case AR_RAD5133_SREV_MAJOR:	/* Sowl: 2+5G/3x3 */
		break;
	default:
		if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {
			AH_PRIVATE(ah)->ah_analog5GhzRev =
				AR_RAD5133_SREV_MAJOR;
			break;
		}
#ifdef AH_DEBUG
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: 5G Radio Chip Rev 0x%02X is not supported by "
		    "this driver\n", __func__,
		    AH_PRIVATE(ah)->ah_analog5GhzRev);
		ecode = HAL_ENOTSUPP;
		goto bad;
#endif
	}
	rfStatus = ar9287RfAttach(ah, &ecode);
	if (!rfStatus) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",
		    __func__, ecode);
		goto bad;
	}

	/*
	 * We only implement open-loop TX power control
	 * for the AR9287 in this codebase.
	 */
	if (! ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) {
		ath_hal_printf(ah, "[ath] AR9287 w/ closed-loop TX power control"
		    " isn't supported.\n");
		ecode = HAL_ENOTSUPP;
		goto bad;
	}

        /*
         * Check whether the power table offset isn't the default.
         * This can occur with eeprom minor V21 or greater on Merlin.
         */
	(void) ath_hal_eepromGet(ah, AR_EEP_PWR_TABLE_OFFSET, &pwr_table_offset);
	if (pwr_table_offset != AR5416_PWR_TABLE_OFFSET_DB)
		ath_hal_printf(ah, "[ath]: default pwr offset: %d dBm != EEPROM pwr offset: %d dBm; curves will be adjusted.\n",
		    AR5416_PWR_TABLE_OFFSET_DB, (int) pwr_table_offset);

	/* setup rxgain table */
	HAL_INI_INIT(&ahp9287->ah_ini_rxgain, ar9287Modes_rx_gain_9287_1_1, 6);

	/* setup txgain table */
	HAL_INI_INIT(&ahp9287->ah_ini_txgain, ar9287Modes_tx_gain_9287_1_1, 6);

	/*
	 * Got everything we need now to setup the capabilities.
	 */
	if (!ar9287FillCapabilityInfo(ah)) {
		ecode = HAL_EEREAD;
		goto bad;
	}

	ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
	if (ecode != HAL_OK) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: error getting mac address from EEPROM\n", __func__);
		goto bad;
        }
	/* XXX How about the serial number ? */
	/* Read Reg Domain */
	AH_PRIVATE(ah)->ah_currentRD =
	    ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL);
	AH_PRIVATE(ah)->ah_currentRDext = AR9287_RDEXT_DEFAULT;

	/*
	 * ah_miscMode is populated by ar5416FillCapabilityInfo()
	 * starting from griffin. Set here to make sure that
	 * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is
	 * placed into hardware.
	 */
	if (ahp->ah_miscMode != 0)
		OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode);

	ar9287AniSetup(ah);			/* Anti Noise Immunity */

	/* Setup noise floor min/max/nominal values */
	AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ;
	AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ;
	AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9287_2GHZ;
	AH5416(ah)->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9287_5GHZ;
	AH5416(ah)->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9287_5GHZ;
	AH5416(ah)->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9287_5GHZ;

	ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist);

	HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);

	return ah;
bad:
	if (ah != AH_NULL)
		ah->ah_detach(ah);
	if (status)
		*status = ecode;
	return AH_NULL;
}

static void
ar9287ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore)
{
	if (AH_PRIVATE(ah)->ah_ispcie && !restore) {
		ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0);
		OS_DELAY(1000);
		OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
		OS_REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT);	/* Yes, Kiwi uses the Kite PCIe PHY WA */
	}
}

static void
ar9287WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
	u_int modesIndex, freqIndex;
	int regWrites = 0;

	/* Setup the indices for the next set of register array writes */
	/* XXX Ignore 11n dynamic mode on the AR5416 for the moment */
	if (IEEE80211_IS_CHAN_2GHZ(chan)) {
		freqIndex = 2;
		if (IEEE80211_IS_CHAN_HT40(chan))
			modesIndex = 3;
		else if (IEEE80211_IS_CHAN_108G(chan))
			modesIndex = 5;
		else
			modesIndex = 4;
	} else {
		freqIndex = 1;
		if (IEEE80211_IS_CHAN_HT40(chan) ||
		    IEEE80211_IS_CHAN_TURBO(chan))
			modesIndex = 2;
		else
			modesIndex = 1;
	}

	/* Set correct Baseband to analog shift setting to access analog chips. */
	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
	OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);

	regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes, modesIndex, regWrites);
	regWrites = ath_hal_ini_write(ah, &AH9287(ah)->ah_ini_rxgain, modesIndex, regWrites);
	regWrites = ath_hal_ini_write(ah, &AH9287(ah)->ah_ini_txgain, modesIndex, regWrites);
	regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common, 1, regWrites);
}
Exemple #11
0
/*
 * Places the device in and out of reset and then places sane
 * values in the registers based on EEPROM config, initialization
 * vectors (as determined by the mode), and station configuration
 *
 * bChannelChange is used to preserve DMA/PCU registers across
 * a HW Reset during channel change.
 */
HAL_BOOL
ar5312Reset(struct ath_hal *ah, HAL_OPMODE opmode,
	struct ieee80211_channel *chan,
	HAL_BOOL bChannelChange,
	HAL_RESET_TYPE resetType,
	HAL_STATUS *status)
{
#define	N(a)	(sizeof (a) / sizeof (a[0]))
#define	FAIL(_code)	do { ecode = _code; goto bad; } while (0)
	struct ath_hal_5212 *ahp = AH5212(ah);
	HAL_CHANNEL_INTERNAL *ichan;
	const HAL_EEPROM *ee;
	uint32_t saveFrameSeqCount, saveDefAntenna;
	uint32_t macStaId1, synthDelay, txFrm2TxDStart;
	uint16_t rfXpdGain[MAX_NUM_PDGAINS_PER_CHANNEL];
	int16_t cckOfdmPwrDelta = 0;
	u_int modesIndex, freqIndex;
	HAL_STATUS ecode;
	int i, regWrites = 0;
	uint32_t testReg;
	uint32_t saveLedState = 0;

	HALASSERT(ah->ah_magic == AR5212_MAGIC);
	ee = AH_PRIVATE(ah)->ah_eeprom;

	OS_MARK(ah, AH_MARK_RESET, bChannelChange);
	/*
	 * Map public channel to private.
	 */
	ichan = ath_hal_checkchannel(ah, chan);
	if (ichan == AH_NULL) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: invalid channel %u/0x%x; no mapping\n",
		    __func__, chan->ic_freq, chan->ic_flags);
		FAIL(HAL_EINVAL);
	}
	switch (opmode) {
	case HAL_M_STA:
	case HAL_M_IBSS:
	case HAL_M_HOSTAP:
	case HAL_M_MONITOR:
		break;
	default:
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid operating mode %u\n",
		    __func__, opmode);
		FAIL(HAL_EINVAL);
		break;
	}
	HALASSERT(ahp->ah_eeversion >= AR_EEPROM_VER3);

	/* Preserve certain DMA hardware registers on a channel change */
	if (bChannelChange) {
		/*
		 * On Venice, the TSF is almost preserved across a reset;
		 * it requires the doubling writes to the RESET_TSF
		 * bit in the AR_BEACON register; it also has the quirk
		 * of the TSF going back in time on the station (station
		 * latches onto the last beacon's tsf during a reset 50%
		 * of the times); the latter is not a problem for adhoc
		 * stations since as long as the TSF is behind, it will
		 * get resynchronized on receiving the next beacon; the
		 * TSF going backwards in time could be a problem for the
		 * sleep operation (supported on infrastructure stations
		 * only) - the best and most general fix for this situation
		 * is to resynchronize the various sleep/beacon timers on
		 * the receipt of the next beacon i.e. when the TSF itself
		 * gets resynchronized to the AP's TSF - power save is
		 * needed to be temporarily disabled until that time
		 *
		 * Need to save the sequence number to restore it after
		 * the reset!
		 */
		saveFrameSeqCount = OS_REG_READ(ah, AR_D_SEQNUM);
	} else
		saveFrameSeqCount = 0;		/* NB: silence compiler */

	/* If the channel change is across the same mode - perform a fast channel change */
	if ((IS_2413(ah) || IS_5413(ah))) {
		/*
		 * Channel change can only be used when:
		 *  -channel change requested - so it's not the initial reset.
		 *  -it's not a change to the current channel - often called when switching modes
		 *   on a channel
		 *  -the modes of the previous and requested channel are the same - some ugly code for XR
		 */
		if (bChannelChange &&
		    AH_PRIVATE(ah)->ah_curchan != AH_NULL &&
		    (chan->ic_freq != AH_PRIVATE(ah)->ah_curchan->ic_freq) &&
		    ((chan->ic_flags & IEEE80211_CHAN_ALLTURBO) ==
		     (AH_PRIVATE(ah)->ah_curchan->ic_flags & IEEE80211_CHAN_ALLTURBO))) {
			if (ar5212ChannelChange(ah, chan))
				/* If ChannelChange completed - skip the rest of reset */
				return AH_TRUE;
		}
	}

	/*
	 * Preserve the antenna on a channel change
	 */
	saveDefAntenna = OS_REG_READ(ah, AR_DEF_ANTENNA);
	if (saveDefAntenna == 0)		/* XXX magic constants */
		saveDefAntenna = 1;

	/* Save hardware flag before chip reset clears the register */
	macStaId1 = OS_REG_READ(ah, AR_STA_ID1) & 
		(AR_STA_ID1_BASE_RATE_11B | AR_STA_ID1_USE_DEFANT);

	/* Save led state from pci config register */
	if (!IS_5315(ah))
		saveLedState = OS_REG_READ(ah, AR5312_PCICFG) &
			(AR_PCICFG_LEDCTL | AR_PCICFG_LEDMODE | AR_PCICFG_LEDBLINK |
			 AR_PCICFG_LEDSLOW);

	ar5312RestoreClock(ah, opmode);		/* move to refclk operation */

	/*
	 * Adjust gain parameters before reset if
	 * there's an outstanding gain updated.
	 */
	(void) ar5212GetRfgain(ah);

	if (!ar5312ChipReset(ah, chan)) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
		FAIL(HAL_EIO);
	}

	/* Setup the indices for the next set of register array writes */
	if (IEEE80211_IS_CHAN_2GHZ(chan)) {
		freqIndex  = 2;
		modesIndex = IEEE80211_IS_CHAN_108G(chan) ? 5 :
			     IEEE80211_IS_CHAN_G(chan) ? 4 : 3;
	} else {
		freqIndex  = 1;
		modesIndex = IEEE80211_IS_CHAN_ST(chan) ? 2 : 1;
	}

	OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);

	/* Set correct Baseband to analog shift setting to access analog chips. */
	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);

	regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, 0);
	regWrites = write_common(ah, &ahp->ah_ini_common, bChannelChange,
		regWrites);
	ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites);

	OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);

	if (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan))
		ar5212SetIFSTiming(ah, chan);

	/* Overwrite INI values for revised chipsets */
	if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_2) {
		/* ADC_CTL */
		OS_REG_WRITE(ah, AR_PHY_ADC_CTL,
			     SM(2, AR_PHY_ADC_CTL_OFF_INBUFGAIN) |
			     SM(2, AR_PHY_ADC_CTL_ON_INBUFGAIN) |
			     AR_PHY_ADC_CTL_OFF_PWDDAC |
			     AR_PHY_ADC_CTL_OFF_PWDADC);
		
		/* TX_PWR_ADJ */
		if (chan->channel == 2484) {
			cckOfdmPwrDelta = SCALE_OC_DELTA(ee->ee_cckOfdmPwrDelta - ee->ee_scaledCh14FilterCckDelta);
		} else {
			cckOfdmPwrDelta = SCALE_OC_DELTA(ee->ee_cckOfdmPwrDelta);
		}
		
		if (IEEE80211_IS_CHAN_G(chan)) {
			OS_REG_WRITE(ah, AR_PHY_TXPWRADJ,
				     SM((ee->ee_cckOfdmPwrDelta*-1), AR_PHY_TXPWRADJ_CCK_GAIN_DELTA) |
				     SM((cckOfdmPwrDelta*-1), AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX));
		} else {
			OS_REG_WRITE(ah, AR_PHY_TXPWRADJ, 0);
		}
		
		/* Add barker RSSI thresh enable as disabled */
		OS_REG_CLR_BIT(ah, AR_PHY_DAG_CTRLCCK,
			       AR_PHY_DAG_CTRLCCK_EN_RSSI_THR);
		OS_REG_RMW_FIELD(ah, AR_PHY_DAG_CTRLCCK,
				 AR_PHY_DAG_CTRLCCK_RSSI_THR, 2);
		
		/* Set the mute mask to the correct default */
		OS_REG_WRITE(ah, AR_SEQ_MASK, 0x0000000F);
	}
	
	if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_3) {
		/* Clear reg to alllow RX_CLEAR line debug */
		OS_REG_WRITE(ah, AR_PHY_BLUETOOTH,  0);
	}
	if (AH_PRIVATE(ah)->ah_phyRev >= AR_PHY_CHIP_ID_REV_4) {
#ifdef notyet
		/* Enable burst prefetch for the data queues */
		OS_REG_RMW_FIELD(ah, AR_D_FPCTL, ... );
		/* Enable double-buffering */
		OS_REG_CLR_BIT(ah, AR_TXCFG, AR_TXCFG_DBL_BUF_DIS);
#endif
	}

	if (IS_5312_2_X(ah)) {
		/* ADC_CTRL */
		OS_REG_WRITE(ah, AR_PHY_SIGMA_DELTA,
			     SM(2, AR_PHY_SIGMA_DELTA_ADC_SEL) |
			     SM(4, AR_PHY_SIGMA_DELTA_FILT2) |
			     SM(0x16, AR_PHY_SIGMA_DELTA_FILT1) |
			     SM(0, AR_PHY_SIGMA_DELTA_ADC_CLIP));

		if (IEEE80211_IS_CHAN_2GHZ(chan))
			OS_REG_RMW_FIELD(ah, AR_PHY_RXGAIN, AR_PHY_RXGAIN_TXRX_RF_MAX, 0x0F);

		/* CCK Short parameter adjustment in 11B mode */
		if (IEEE80211_IS_CHAN_B(chan))
			OS_REG_RMW_FIELD(ah, AR_PHY_CCK_RXCTRL4, AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT, 12);

		/* Set ADC/DAC select values */
		OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x04);

		/* Increase 11A AGC Settling */
		if (IEEE80211_IS_CHAN_A(chan))
			OS_REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_AGC, 32);
	} else {
		/* Set ADC/DAC select values */
		OS_REG_WRITE(ah, AR_PHY_SLEEP_SCAL, 0x0e);
	}

	/* Setup the transmit power values. */
	if (!ar5212SetTransmitPower(ah, chan, rfXpdGain)) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: error init'ing transmit power\n", __func__);
		FAIL(HAL_EIO);
	}

	/* Write the analog registers */
	if (!ahp->ah_rfHal->setRfRegs(ah, chan, modesIndex, rfXpdGain)) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5212SetRfRegs failed\n",
		    __func__);
		FAIL(HAL_EIO);
	}

	/* Write delta slope for OFDM enabled modes (A, G, Turbo) */
	if (IEEE80211_IS_CHAN_OFDM(chan)) {
		if (IS_5413(ah) ||
		   AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3)
			ar5212SetSpurMitigation(ah, chan);
		ar5212SetDeltaSlope(ah, chan);
	}

	/* Setup board specific options for EEPROM version 3 */
	if (!ar5212SetBoardValues(ah, chan)) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: error setting board options\n", __func__);
		FAIL(HAL_EIO);
	}

	/* Restore certain DMA hardware registers on a channel change */
	if (bChannelChange)
		OS_REG_WRITE(ah, AR_D_SEQNUM, saveFrameSeqCount);

	OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);

	OS_REG_WRITE(ah, AR_STA_ID0, LE_READ_4(ahp->ah_macaddr));
	OS_REG_WRITE(ah, AR_STA_ID1, LE_READ_2(ahp->ah_macaddr + 4)
		| macStaId1
		| AR_STA_ID1_RTS_USE_DEF
		| ahp->ah_staId1Defaults
	);
	ar5212SetOperatingMode(ah, opmode);

	/* Set Venice BSSID mask according to current state */
	OS_REG_WRITE(ah, AR_BSSMSKL, LE_READ_4(ahp->ah_bssidmask));
	OS_REG_WRITE(ah, AR_BSSMSKU, LE_READ_2(ahp->ah_bssidmask + 4));

	/* Restore previous led state */
	if (!IS_5315(ah))
		OS_REG_WRITE(ah, AR5312_PCICFG, OS_REG_READ(ah, AR_PCICFG) | saveLedState);

	/* Restore previous antenna */
	OS_REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna);

	/* then our BSSID */
	OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid));
	OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid + 4));

	/* Restore bmiss rssi & count thresholds */
	OS_REG_WRITE(ah, AR_RSSI_THR, ahp->ah_rssiThr);

	OS_REG_WRITE(ah, AR_ISR, ~0);		/* cleared on write */

	if (!ar5212SetChannel(ah, chan))
		FAIL(HAL_EIO);

	OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);

	ar5212SetCoverageClass(ah, AH_PRIVATE(ah)->ah_coverageClass, 1);

	ar5212SetRateDurationTable(ah, chan);

	/* Set Tx frame start to tx data start delay */
	if (IS_RAD5112_ANY(ah) &&
	    (IEEE80211_IS_CHAN_HALF(chan) || IEEE80211_IS_CHAN_QUARTER(chan))) {
		txFrm2TxDStart = 
			IEEE80211_IS_CHAN_HALF(chan) ?
					TX_FRAME_D_START_HALF_RATE:
					TX_FRAME_D_START_QUARTER_RATE;
		OS_REG_RMW_FIELD(ah, AR_PHY_TX_CTL, 
			AR_PHY_TX_FRAME_TO_TX_DATA_START, txFrm2TxDStart);
	}

	/*
	 * Setup fast diversity.
	 * Fast diversity can be enabled or disabled via regadd.txt.
	 * Default is enabled.
	 * For reference,
	 *    Disable: reg        val
	 *             0x00009860 0x00009d18 (if 11a / 11g, else no change)
	 *             0x00009970 0x192bb514
	 *             0x0000a208 0xd03e4648
	 *
	 *    Enable:  0x00009860 0x00009d10 (if 11a / 11g, else no change)
	 *             0x00009970 0x192fb514
	 *             0x0000a208 0xd03e6788
	 */

	/* XXX Setup pre PHY ENABLE EAR additions */

	/* flush SCAL reg */
	if (IS_5312_2_X(ah)) {
		(void) OS_REG_READ(ah, AR_PHY_SLEEP_SCAL);
	}

	/*
	 * Wait for the frequency synth to settle (synth goes on
	 * via AR_PHY_ACTIVE_EN).  Read the phy active delay register.
	 * Value is in 100ns increments.
	 */
	synthDelay = OS_REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
	if (IEEE80211_IS_CHAN_B(chan)) {
		synthDelay = (4 * synthDelay) / 22;
	} else {
		synthDelay /= 10;
	}

	/* Activate the PHY (includes baseband activate and synthesizer on) */
	OS_REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);

	/* 
	 * There is an issue if the AP starts the calibration before
	 * the base band timeout completes.  This could result in the
	 * rx_clear false triggering.  As a workaround we add delay an
	 * extra BASE_ACTIVATE_DELAY usecs to ensure this condition
	 * does not happen.
	 */
	if (IEEE80211_IS_CHAN_HALF(chan)) {
		OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY);
	} else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
		OS_DELAY((synthDelay << 2) + BASE_ACTIVATE_DELAY);
	} else {
		OS_DELAY(synthDelay + BASE_ACTIVATE_DELAY);
	}

	/*
	 * The udelay method is not reliable with notebooks.
	 * Need to check to see if the baseband is ready
	 */
	testReg = OS_REG_READ(ah, AR_PHY_TESTCTRL);
	/* Selects the Tx hold */
	OS_REG_WRITE(ah, AR_PHY_TESTCTRL, AR_PHY_TESTCTRL_TXHOLD);
	i = 0;
	while ((i++ < 20) &&
	       (OS_REG_READ(ah, 0x9c24) & 0x10)) /* test if baseband not ready */		OS_DELAY(200);
	OS_REG_WRITE(ah, AR_PHY_TESTCTRL, testReg);

	/* Calibrate the AGC and start a NF calculation */
	OS_REG_WRITE(ah, AR_PHY_AGC_CONTROL,
		  OS_REG_READ(ah, AR_PHY_AGC_CONTROL)
		| AR_PHY_AGC_CONTROL_CAL
		| AR_PHY_AGC_CONTROL_NF);

	if (!IEEE80211_IS_CHAN_B(chan) && ahp->ah_bIQCalibration != IQ_CAL_DONE) {
		/* Start IQ calibration w/ 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples */
		OS_REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4, 
			AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
			INIT_IQCAL_LOG_COUNT_MAX);
		OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4,
			AR_PHY_TIMING_CTRL4_DO_IQCAL);
		ahp->ah_bIQCalibration = IQ_CAL_RUNNING;
	} else
		ahp->ah_bIQCalibration = IQ_CAL_INACTIVE;

	/* Setup compression registers */
	ar5212SetCompRegs(ah);

	/* Set 1:1 QCU to DCU mapping for all queues */
	for (i = 0; i < AR_NUM_DCU; i++)
		OS_REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);

	ahp->ah_intrTxqs = 0;
	for (i = 0; i < AH_PRIVATE(ah)->ah_caps.halTotalQueues; i++)
		ar5212ResetTxQueue(ah, i);

	/*
	 * Setup interrupt handling.  Note that ar5212ResetTxQueue
	 * manipulates the secondary IMR's as queues are enabled
	 * and disabled.  This is done with RMW ops to insure the
	 * settings we make here are preserved.
	 */
	ahp->ah_maskReg = AR_IMR_TXOK | AR_IMR_TXERR | AR_IMR_TXURN
			| AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXORN
			| AR_IMR_HIUERR
			;
	if (opmode == HAL_M_HOSTAP)
		ahp->ah_maskReg |= AR_IMR_MIB;
	OS_REG_WRITE(ah, AR_IMR, ahp->ah_maskReg);
	/* Enable bus errors that are OR'd to set the HIUERR bit */
	OS_REG_WRITE(ah, AR_IMR_S2,
		OS_REG_READ(ah, AR_IMR_S2)
		| AR_IMR_S2_MCABT | AR_IMR_S2_SSERR | AR_IMR_S2_DPERR);

	if (AH_PRIVATE(ah)->ah_rfkillEnabled)
		ar5212EnableRfKill(ah);

	if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: offset calibration failed to complete in 1ms;"
		    " noisy environment?\n", __func__);
	}

	/*
	 * Set clocks back to 32kHz if they had been using refClk, then
	 * use an external 32kHz crystal when sleeping, if one exists.
	 */
	ar5312SetupClock(ah, opmode);

	/*
	 * Writing to AR_BEACON will start timers. Hence it should
	 * be the last register to be written. Do not reset tsf, do
	 * not enable beacons at this point, but preserve other values
	 * like beaconInterval.
	 */
	OS_REG_WRITE(ah, AR_BEACON,
		(OS_REG_READ(ah, AR_BEACON) &~ (AR_BEACON_EN | AR_BEACON_RESET_TSF)));

	/* XXX Setup post reset EAR additions */

	/*  QoS support */
	if (AH_PRIVATE(ah)->ah_macVersion > AR_SREV_VERSION_VENICE ||
	    (AH_PRIVATE(ah)->ah_macVersion == AR_SREV_VERSION_VENICE &&
	     AH_PRIVATE(ah)->ah_macRev >= AR_SREV_GRIFFIN_LITE)) {
		OS_REG_WRITE(ah, AR_QOS_CONTROL, 0x100aa);	/* XXX magic */
		OS_REG_WRITE(ah, AR_QOS_SELECT, 0x3210);	/* XXX magic */
	}

	/* Turn on NOACK Support for QoS packets */
	OS_REG_WRITE(ah, AR_NOACK,
		     SM(2, AR_NOACK_2BIT_VALUE) |
		     SM(5, AR_NOACK_BIT_OFFSET) |
		     SM(0, AR_NOACK_BYTE_OFFSET));

	/* Restore user-specified settings */
	if (ahp->ah_miscMode != 0)
		OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
	if (ahp->ah_slottime != (u_int) -1)
		ar5212SetSlotTime(ah, ahp->ah_slottime);
	if (ahp->ah_acktimeout != (u_int) -1)
		ar5212SetAckTimeout(ah, ahp->ah_acktimeout);
	if (ahp->ah_ctstimeout != (u_int) -1)
		ar5212SetCTSTimeout(ah, ahp->ah_ctstimeout);
	if (ahp->ah_sifstime != (u_int) -1)
		ar5212SetSifsTime(ah, ahp->ah_sifstime);
	if (AH_PRIVATE(ah)->ah_diagreg != 0)
		OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg);

	AH_PRIVATE(ah)->ah_opmode = opmode;	/* record operating mode */

	if (bChannelChange && !IEEE80211_IS_CHAN_DFS(chan)) 
		chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT;

	HALDEBUG(ah, HAL_DEBUG_RESET, "%s: done\n", __func__);

	OS_MARK(ah, AH_MARK_RESET_DONE, 0);

	return AH_TRUE;
bad:
	OS_MARK(ah, AH_MARK_RESET_DONE, ecode);
	if (status != AH_NULL)
		*status = ecode;
	return AH_FALSE;
#undef FAIL
#undef N
}
Exemple #12
0
HAL_BOOL
ar5312MacReset(struct ath_hal *ah, unsigned int RCMask)
{
	int wlanNum = AR5312_UNIT(ah);
	uint32_t resetBB, resetBits, regMask;
	uint32_t reg;

	if (RCMask == 0)
		return(AH_FALSE);
#if ( AH_SUPPORT_2316 || AH_SUPPORT_2317 )
	    if (IS_5315(ah)) {
			switch(wlanNum) {
			case 0:
				resetBB = AR5315_RC_BB0_CRES | AR5315_RC_WBB0_RES; 
				/* Warm and cold reset bits for wbb */
				resetBits = AR5315_RC_WMAC0_RES;
				break;
			case 1:
				resetBB = AR5315_RC_BB1_CRES | AR5315_RC_WBB1_RES; 
				/* Warm and cold reset bits for wbb */
				resetBits = AR5315_RC_WMAC1_RES;
				break;
			default:
				return(AH_FALSE);
			}		
			regMask = ~(resetBB | resetBits);

			/* read before */
			reg = OS_REG_READ(ah, 
							  (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh) + AR5315_RESET));

			if (RCMask == AR_RC_BB) {
				/* Put baseband in reset */
				reg |= resetBB;    /* Cold and warm reset the baseband bits */
			} else {
				/*
				 * Reset the MAC and baseband.  This is a bit different than
				 * the PCI version, but holding in reset causes problems.
				 */
				reg &= regMask;
				reg |= (resetBits | resetBB) ;
			}
			OS_REG_WRITE(ah, 
						 (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5315_RESET),
						 reg);
			/* read after */
			OS_REG_READ(ah, 
						(AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh) +AR5315_RESET));
			OS_DELAY(100);

			/* Bring MAC and baseband out of reset */
			reg &= regMask;
			/* read before */
			OS_REG_READ(ah, 
						(AR5315_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5315_RESET));
			OS_REG_WRITE(ah, 
						 (AR5315_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5315_RESET),
						 reg);
			/* read after */
			OS_REG_READ(ah,
						(AR5315_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5315_RESET));


		} 
        else 
#endif
		{

			switch(wlanNum) {
			case 0:
				resetBB = AR5312_RC_BB0_CRES | AR5312_RC_WBB0_RES;
				/* Warm and cold reset bits for wbb */
				resetBits = AR5312_RC_WMAC0_RES;
				break;
			case 1:
				resetBB = AR5312_RC_BB1_CRES | AR5312_RC_WBB1_RES;
				/* Warm and cold reset bits for wbb */
				resetBits = AR5312_RC_WMAC1_RES;
				break;
			default:
				return(AH_FALSE);
			}
			regMask = ~(resetBB | resetBits);

			/* read before */
			reg = OS_REG_READ(ah,
							  (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh) + AR5312_RESET));

			if (RCMask == AR_RC_BB) {
				/* Put baseband in reset */
				reg |= resetBB;    /* Cold and warm reset the baseband bits */
			} else {
				/*
				 * Reset the MAC and baseband.  This is a bit different than
				 * the PCI version, but holding in reset causes problems.
				 */
				reg &= regMask;
				reg |= (resetBits | resetBB) ;
			}
			OS_REG_WRITE(ah,
						 (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5312_RESET),
						 reg);
			/* read after */
			OS_REG_READ(ah,
						(AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh) +AR5312_RESET));
			OS_DELAY(100);

			/* Bring MAC and baseband out of reset */
			reg &= regMask;
			/* read before */
			OS_REG_READ(ah,
						(AR5312_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5312_RESET));
			OS_REG_WRITE(ah,
						 (AR5312_RSTIMER_BASE - ((uint32_t) ah->ah_sh)+AR5312_RESET),
						 reg);
			/* read after */
			OS_REG_READ(ah,
						(AR5312_RSTIMER_BASE- ((uint32_t) ah->ah_sh) +AR5312_RESET));
		}
	return(AH_TRUE);
}
Exemple #13
0
/*
 * Places the hardware into reset and then pulls it out of reset
 *
 * TODO: Only write the PLL if we're changing to or from CCK mode
 * 
 * WARNING: The order of the PLL and mode registers must be correct.
 */
HAL_BOOL
ar5312ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan)
{

	OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->ic_freq : 0);

	/*
	 * Reset the HW 
	 */
	if (!ar5312SetResetReg(ah, AR_RC_MAC | AR_RC_BB)) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n",
		    __func__);
		return AH_FALSE;
	}

	/* Bring out of sleep mode (AGAIN) */
	if (!ar5312SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetPowerMode failed\n",
		    __func__);
		return AH_FALSE;
	}

	/* Clear warm reset register */
	if (!ar5312SetResetReg(ah, 0)) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: ar5312SetResetReg failed\n",
		    __func__);
		return AH_FALSE;
	}

	/*
	 * Perform warm reset before the mode/PLL/turbo registers
	 * are changed in order to deactivate the radio.  Mode changes
	 * with an active radio can result in corrupted shifts to the
	 * radio device.
	 */

	/*
	 * Set CCK and Turbo modes correctly.
	 */
	if (chan != AH_NULL) {		/* NB: can be null during attach */
		uint32_t rfMode, phyPLL = 0, curPhyPLL, turbo;

		if (IS_RAD5112_ANY(ah)) {
			rfMode = AR_PHY_MODE_AR5112;
			if (!IS_5315(ah)) {
				if (IEEE80211_IS_CHAN_CCK(chan)) {
					phyPLL = AR_PHY_PLL_CTL_44_5312;
				} else {
					if (IEEE80211_IS_CHAN_HALF(chan)) {
						phyPLL = AR_PHY_PLL_CTL_40_5312_HALF;
					} else if (IEEE80211_IS_CHAN_QUARTER(chan)) {
						phyPLL = AR_PHY_PLL_CTL_40_5312_QUARTER;
					} else {
						phyPLL = AR_PHY_PLL_CTL_40_5312;
					}
				}
			} else {
				if (IEEE80211_IS_CHAN_CCK(chan))
					phyPLL = AR_PHY_PLL_CTL_44_5112;
				else
					phyPLL = AR_PHY_PLL_CTL_40_5112;
				if (IEEE80211_IS_CHAN_HALF(chan))
					phyPLL |= AR_PHY_PLL_CTL_HALF;
				else if (IEEE80211_IS_CHAN_QUARTER(chan))
					phyPLL |= AR_PHY_PLL_CTL_QUARTER;
			}
		} else {
			rfMode = AR_PHY_MODE_AR5111;
			if (IEEE80211_IS_CHAN_CCK(chan))
				phyPLL = AR_PHY_PLL_CTL_44;
			else
				phyPLL = AR_PHY_PLL_CTL_40;
			if (IEEE80211_IS_CHAN_HALF(chan))
				phyPLL = AR_PHY_PLL_CTL_HALF;
			else if (IEEE80211_IS_CHAN_QUARTER(chan))
				phyPLL = AR_PHY_PLL_CTL_QUARTER;
		}
		if (IEEE80211_IS_CHAN_G(chan))
			rfMode |= AR_PHY_MODE_DYNAMIC;
		else if (IEEE80211_IS_CHAN_OFDM(chan))
			rfMode |= AR_PHY_MODE_OFDM;
		else
			rfMode |= AR_PHY_MODE_CCK;
		if (IEEE80211_IS_CHAN_5GHZ(chan))
			rfMode |= AR_PHY_MODE_RF5GHZ;
		else
			rfMode |= AR_PHY_MODE_RF2GHZ;
		turbo = IEEE80211_IS_CHAN_TURBO(chan) ?
			(AR_PHY_FC_TURBO_MODE | AR_PHY_FC_TURBO_SHORT) : 0;
		curPhyPLL = OS_REG_READ(ah, AR_PHY_PLL_CTL);
		/*
		 * PLL, Mode, and Turbo values must be written in the correct
		 * order to ensure:
		 * - The PLL cannot be set to 44 unless the CCK or DYNAMIC
		 *   mode bit is set
		 * - Turbo cannot be set at the same time as CCK or DYNAMIC
		 */
		if (IEEE80211_IS_CHAN_CCK(chan)) {
			OS_REG_WRITE(ah, AR_PHY_TURBO, turbo);
			OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
			if (curPhyPLL != phyPLL) {
				OS_REG_WRITE(ah,  AR_PHY_PLL_CTL,  phyPLL);
				/* Wait for the PLL to settle */
				OS_DELAY(PLL_SETTLE_DELAY);
			}
		} else {
			if (curPhyPLL != phyPLL) {
				OS_REG_WRITE(ah,  AR_PHY_PLL_CTL,  phyPLL);
				/* Wait for the PLL to settle */
				OS_DELAY(PLL_SETTLE_DELAY);
			}
			OS_REG_WRITE(ah, AR_PHY_TURBO, turbo);
			OS_REG_WRITE(ah, AR_PHY_MODE, rfMode);
		}
	}
	return AH_TRUE;
}
Exemple #14
0
static void
ar9280ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off)
{
	uint32_t val;

	if (AH_PRIVATE(ah)->ah_ispcie && !restore) {
		ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0);
		OS_DELAY(1000);
	}


	/*
	 * Set PCIe workaround bits
	 *
	 * NOTE:
	 *
	 * In Merlin and Kite, bit 14 in WA register (disable L1) should only
	 * be set when device enters D3 and be cleared when device comes back
	 * to D0.
	 */
	if (power_off) {		/* Power-off */
		OS_REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);

		val = OS_REG_READ(ah, AR_WA);

		/*
		 * Disable bit 6 and 7 before entering D3 to prevent
		 * system hang.
		 */
		val &= ~(AR_WA_BIT6 | AR_WA_BIT7);

		/*
		 * XXX Not sure, is specified in the reference HAL.
		 */
		val |= AR_WA_BIT22;

		/*
		 * See above: set AR_WA_D3_L1_DISABLE when entering D3 state.
		 *
		 * XXX The reference HAL does it this way - it only sets
		 * AR_WA_D3_L1_DISABLE if it's set in AR9280_WA_DEFAULT,
		 * which it (currently) isn't.  So the following statement
		 * is currently a NOP.
		 */
		if (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE)
			val |= AR_WA_D3_L1_DISABLE;

		OS_REG_WRITE(ah, AR_WA, val);
	} else {			/* Power-on */
		val = AR9280_WA_DEFAULT;

		/*
		 * See note above: make sure L1_DISABLE is not set.
		 */
		val &= (~AR_WA_D3_L1_DISABLE);
		OS_REG_WRITE(ah, AR_WA, val);

		/* set bit 19 to allow forcing of pcie core into L1 state */
		OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
	}
}
static void
ar9300_shutdown_rx(struct ath_hal *ah)
{
    int wait;

#define AH_RX_STOP_TIMEOUT 100000   /* usec */
#define AH_TIME_QUANTUM       100   /* usec */

    /*ath_hal_printf(ah, "%s: called\n", __func__);*/

    /* (1) Set (RX_ABORT | RX_DIS) bits to reg MAC_DIAG_SW. */
    OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);

    /*
     * (2) Poll (reg MAC_OBS_BUS_1[24:20] == 0) for 100ms
     * and if it doesn't become 0x0, print reg MAC_OBS_BUS_1.
     * Wait for Rx PCU state machine to become idle.
     */
    for (wait = AH_RX_STOP_TIMEOUT / AH_TIME_QUANTUM; wait != 0; wait--) {
        u_int32_t obs1 = OS_REG_READ(ah, AR_OBS_BUS_1);
        /* (MAC_PCU_OBS_BUS_1[24:20] == 0x0) - Check pcu_rxsm == IDLE */
        if ((obs1 & 0x01F00000) == 0) {
            break;
        }
        OS_DELAY(AH_TIME_QUANTUM);
    }

    /*
     * If bit 24:20 doesn't go to 0 within 100ms, print the value of
     * MAC_OBS_BUS_1 register on debug log.
     */
    if (wait == 0) {
        ath_hal_printf(ah,
            "%s: rx failed to go idle in %d us\n AR_OBS_BUS_1=0x%08x\n",
            __func__,
            AH_RX_STOP_TIMEOUT,
            OS_REG_READ(ah, AR_OBS_BUS_1));
    }

    /* (3) Set MACMISC reg = 0x8100 to configure debug bus */
    OS_REG_WRITE(ah, AR_MACMISC, 0x8100);

    /*
     * (4) Poll (AR_DMADBG_7 reg bits [11:8] == 0x0) for 100ms
     * wait for Rx DMA state machine to become idle
     */
    for (wait = AH_RX_STOP_TIMEOUT / AH_TIME_QUANTUM; wait != 0; wait--) {
        if ((OS_REG_READ(ah, AR_DMADBG_7) & AR_DMADBG_RX_STATE) == 0) {
            break;
        }
        OS_DELAY(AH_TIME_QUANTUM);
    }

    if (wait == 0) {
        ath_hal_printf(ah,
            "AR_DMADBG_7 reg [11:8] is not 0, instead AR_DMADBG_7 reg=0x%08x\n",
            OS_REG_READ(ah, AR_DMADBG_7));
        /* MAC_RXDP_SIZE register (0x70) */
        ath_hal_printf(ah, "AR_RXDP_SIZE=0x%08x\n",
            OS_REG_READ(ah, AR_RXDP_SIZE));
    }

    /* (5) Set RXD bit to reg MAC_CR */
    OS_REG_WRITE(ah, AR_CR, AR_CR_RXD);

    /* (6) Poll MAC_CR.RXE = 0x0 for 100ms or until RXE goes low */
    for (wait = AH_RX_STOP_TIMEOUT / AH_TIME_QUANTUM; wait != 0; wait--) {
        if ((OS_REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) {
            break;
        }
        OS_DELAY(AH_TIME_QUANTUM);
    }

    /* (7) If (RXE_LP|RXE_HP) doesn't go low within 100ms */
    if (wait == 0) {
        ath_hal_printf(ah,
            "%s: RXE_LP of MAC_CR reg failed to go low in %d us\n",
            __func__, AH_RX_STOP_TIMEOUT);
    }

    /* (8) Clear reg MAC_PCU_RX_FILTER */
    ar9300_set_rx_filter(ah, 0);

#undef AH_RX_STOP_TIMEOUT
#undef AH_TIME_QUANTUM
}
Exemple #16
0
static void
ar9285AniSetup(struct ath_hal *ah)
{
	/*
	 * These are the parameters from the AR5416 ANI code;
	 * they likely need quite a bit of adjustment for the
	 * AR9285.
	 */
        static const struct ar5212AniParams aniparams = {
                .maxNoiseImmunityLevel  = 4,    /* levels 0..4 */
                .totalSizeDesired       = { -55, -55, -55, -55, -62 },
                .coarseHigh             = { -14, -14, -14, -14, -12 },
                .coarseLow              = { -64, -64, -64, -64, -70 },
                .firpwr                 = { -78, -78, -78, -78, -80 },
                .maxSpurImmunityLevel   = 7,
                .cycPwrThr1             = { 2, 4, 6, 8, 10, 12, 14, 16 },
                .maxFirstepLevel        = 2,    /* levels 0..2 */
                .firstep                = { 0, 4, 8 },
                .ofdmTrigHigh           = 500,
                .ofdmTrigLow            = 200,
                .cckTrigHigh            = 200,
                .cckTrigLow             = 100,
                .rssiThrHigh            = 40,
                .rssiThrLow             = 7,
                .period                 = 100,
        };
	/* NB: disable ANI noise immmunity for reliable RIFS rx */
	AH5416(ah)->ah_ani_function &= ~(1 << HAL_ANI_NOISE_IMMUNITY_LEVEL);

        ar5416AniAttach(ah, &aniparams, &aniparams, AH_TRUE);
}

static const char * ar9285_lna_conf[] = {
	"LNA1-LNA2",
	"LNA2",
	"LNA1",
	"LNA1+LNA2",
};

static void
ar9285_eeprom_print_diversity_settings(struct ath_hal *ah)
{
	const HAL_EEPROM_v4k *ee = AH_PRIVATE(ah)->ah_eeprom;
	const MODAL_EEP4K_HEADER *pModal = &ee->ee_base.modalHeader;

	ath_hal_printf(ah, "[ath] AR9285 Main LNA config: %s\n",
	    ar9285_lna_conf[(pModal->antdiv_ctl2 >> 2) & 0x3]);
	ath_hal_printf(ah, "[ath] AR9285 Alt LNA config: %s\n",
	    ar9285_lna_conf[pModal->antdiv_ctl2 & 0x3]);
	ath_hal_printf(ah, "[ath] LNA diversity %s, Diversity %s\n",
	    ((pModal->antdiv_ctl1 & 0x1) ? "enabled" : "disabled"),
	    ((pModal->antdiv_ctl1 & 0x8) ? "enabled" : "disabled"));
}

/*
 * Attach for an AR9285 part.
 */
static struct ath_hal *
ar9285Attach(uint16_t devid, HAL_SOFTC sc,
	HAL_BUS_TAG st, HAL_BUS_HANDLE sh, uint16_t *eepromdata,
	HAL_STATUS *status)
{
	struct ath_hal_9285 *ahp9285;
	struct ath_hal_5212 *ahp;
	struct ath_hal *ah;
	uint32_t val;
	HAL_STATUS ecode;
	HAL_BOOL rfStatus;

	HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
	    __func__, sc, (void*) st, (void*) sh);

	/* NB: memory is returned zero'd */
	ahp9285 = ath_hal_malloc(sizeof (struct ath_hal_9285));
	if (ahp9285 == AH_NULL) {
		HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
		    "%s: cannot allocate memory for state block\n", __func__);
		*status = HAL_ENOMEM;
		return AH_NULL;
	}
	ahp = AH5212(ahp9285);
	ah = &ahp->ah_priv.h;

	ar5416InitState(AH5416(ah), devid, sc, st, sh, status);

	/*
	 * Use the "local" EEPROM data given to us by the higher layers.
	 * This is a private copy out of system flash. The Linux ath9k
	 * commit for the initial AR9130 support mentions MMIO flash
	 * access is "unreliable." -adrian
	 */
	if (eepromdata != AH_NULL) {
		AH_PRIVATE(ah)->ah_eepromRead = ath_hal_EepromDataRead;
		AH_PRIVATE(ah)->ah_eepromWrite = NULL;
		ah->ah_eepromdata = eepromdata;
	}

	/* override with 9285 specific state */
	AH5416(ah)->ah_initPLL = ar9280InitPLL;
	AH5416(ah)->ah_btCoexSetDiversity = ar9285BTCoexAntennaDiversity;

	ah->ah_setAntennaSwitch		= ar9285SetAntennaSwitch;
	ah->ah_configPCIE		= ar9285ConfigPCIE;
	ah->ah_disablePCIE		= ar9285DisablePCIE;
	ah->ah_setTxPower		= ar9285SetTransmitPower;
	ah->ah_setBoardValues		= ar9285SetBoardValues;
	ah->ah_btCoexSetParameter	= ar9285BTCoexSetParameter;
	ah->ah_divLnaConfGet		= ar9285_antdiv_comb_conf_get;
	ah->ah_divLnaConfSet		= ar9285_antdiv_comb_conf_set;

	AH5416(ah)->ah_cal.iqCalData.calData = &ar9280_iq_cal;
	AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9280_adc_gain_cal;
	AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9280_adc_dc_cal;
	AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9280_adc_init_dc_cal;
	AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;

	AH5416(ah)->ah_spurMitigate	= ar9280SpurMitigate;
	AH5416(ah)->ah_writeIni		= ar9285WriteIni;
	AH5416(ah)->ah_rx_chainmask	= AR9285_DEFAULT_RXCHAINMASK;
	AH5416(ah)->ah_tx_chainmask	= AR9285_DEFAULT_TXCHAINMASK;
	
	ahp->ah_maxTxTrigLev		= MAX_TX_FIFO_THRESHOLD >> 1;

	if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) {
		/* reset chip */
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n",
		    __func__);
		ecode = HAL_EIO;
		goto bad;
	}

	if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n",
		    __func__);
		ecode = HAL_EIO;
		goto bad;
	}
	/* Read Revisions from Chips before taking out of reset */
	val = OS_REG_READ(ah, AR_SREV);
	HALDEBUG(ah, HAL_DEBUG_ATTACH,
	    "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n",
	    __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION),
	    MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION));
	/* NB: include chip type to differentiate from pre-Sowl versions */
	AH_PRIVATE(ah)->ah_macVersion =
	    (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S;
	AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION);
	AH_PRIVATE(ah)->ah_ispcie = (val & AR_XSREV_TYPE_HOST_MODE) == 0;

	/* setup common ini data; rf backends handle remainder */
	if (AR_SREV_KITE_12_OR_LATER(ah)) {
		HAL_INI_INIT(&ahp->ah_ini_modes, ar9285Modes_v2, 6);
		HAL_INI_INIT(&ahp->ah_ini_common, ar9285Common_v2, 2);
		HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes,
		    ar9285PciePhy_clkreq_always_on_L1_v2, 2);
	} else {
		HAL_INI_INIT(&ahp->ah_ini_modes, ar9285Modes, 6);
		HAL_INI_INIT(&ahp->ah_ini_common, ar9285Common, 2);
		HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes,
		    ar9285PciePhy_clkreq_always_on_L1, 2);
	}
	ar5416AttachPCIE(ah);

	/* Attach methods that require MAC version/revision info */
	if (AR_SREV_KITE_12_OR_LATER(ah))
		AH5416(ah)->ah_cal_initcal      = ar9285InitCalHardware;
	if (AR_SREV_KITE_11_OR_LATER(ah))
		AH5416(ah)->ah_cal_pacal        = ar9002_hw_pa_cal;

	ecode = ath_hal_v4kEepromAttach(ah);
	if (ecode != HAL_OK)
		goto bad;

	if (!ar5416ChipReset(ah, AH_NULL)) {	/* reset chip */
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n",
		    __func__);
		ecode = HAL_EIO;
		goto bad;
	}

	AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);

	if (!ar5212ChipTest(ah)) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
		    __func__);
		ecode = HAL_ESELFTEST;
		goto bad;
	}

	/*
	 * Set correct Baseband to analog shift
	 * setting to access analog chips.
	 */
	OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);

	/* Read Radio Chip Rev Extract */
	AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah);
	switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
        case AR_RAD2133_SREV_MAJOR:	/* Sowl: 2G/3x3 */
	case AR_RAD5133_SREV_MAJOR:	/* Sowl: 2+5G/3x3 */
		break;
	default:
		if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {
			AH_PRIVATE(ah)->ah_analog5GhzRev =
				AR_RAD5133_SREV_MAJOR;
			break;
		}
#ifdef AH_DEBUG
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: 5G Radio Chip Rev 0x%02X is not supported by "
		    "this driver\n", __func__,
		    AH_PRIVATE(ah)->ah_analog5GhzRev);
		ecode = HAL_ENOTSUPP;
		goto bad;
#endif
	}
	rfStatus = ar9285RfAttach(ah, &ecode);
	if (!rfStatus) {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",
		    __func__, ecode);
		goto bad;
	}

	HAL_INI_INIT(&ahp9285->ah_ini_rxgain, ar9280Modes_original_rxgain_v2,
	    6);

	if (AR_SREV_9285E_20(ah))
		ath_hal_printf(ah, "[ath] AR9285E_20 detected; using XE TX gain tables\n");

	/* setup txgain table */
	switch (ath_hal_eepromGet(ah, AR_EEP_TXGAIN_TYPE, AH_NULL)) {
	case AR5416_EEP_TXGAIN_HIGH_POWER:
		if (AR_SREV_9285E_20(ah))
			HAL_INI_INIT(&ahp9285->ah_ini_txgain,
			    ar9285Modes_XE2_0_high_power, 6);
		else
			HAL_INI_INIT(&ahp9285->ah_ini_txgain,
			    ar9285Modes_high_power_tx_gain_v2, 6);
		break;
	case AR5416_EEP_TXGAIN_ORIG:
		if (AR_SREV_9285E_20(ah))
			HAL_INI_INIT(&ahp9285->ah_ini_txgain,
			    ar9285Modes_XE2_0_normal_power, 6);
		else
			HAL_INI_INIT(&ahp9285->ah_ini_txgain,
			    ar9285Modes_original_tx_gain_v2, 6);
		break;
	default:
		HALASSERT(AH_FALSE);
		goto bad;		/* XXX ? try to continue */
	}

	/*
	 * Got everything we need now to setup the capabilities.
	 */
	if (!ar9285FillCapabilityInfo(ah)) {
		ecode = HAL_EEREAD;
		goto bad;
	}

	/*
	 * Print out the EEPROM antenna configuration mapping.
	 * Some devices have a hard-coded LNA configuration profile;
	 * others enable diversity.
	 */
	ar9285_eeprom_print_diversity_settings(ah);

	/* Print out whether the EEPROM settings enable AR9285 diversity */
	if (ar9285_check_div_comb(ah)) {
		ath_hal_printf(ah, "[ath] Enabling diversity for Kite\n");
	}

	/* Disable 11n for the AR2427 */
	if (devid == AR2427_DEVID_PCIE)
		AH_PRIVATE(ah)->ah_caps.halHTSupport = AH_FALSE;

	ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
	if (ecode != HAL_OK) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: error getting mac address from EEPROM\n", __func__);
		goto bad;
        }
	/* XXX How about the serial number ? */
	/* Read Reg Domain */
	AH_PRIVATE(ah)->ah_currentRD =
	    ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL);
	/*
         * For Kite and later chipsets, the following bits are not
	 * programmed in EEPROM and so are set as enabled always.
	 */
	AH_PRIVATE(ah)->ah_currentRDext = AR9285_RDEXT_DEFAULT;

	/*
	 * ah_miscMode is populated by ar5416FillCapabilityInfo()
	 * starting from griffin. Set here to make sure that
	 * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is
	 * placed into hardware.
	 */
	if (ahp->ah_miscMode != 0)
		OS_REG_WRITE(ah, AR_MISC_MODE, OS_REG_READ(ah, AR_MISC_MODE) | ahp->ah_miscMode);

	ar9285AniSetup(ah);			/* Anti Noise Immunity */

	/* Setup noise floor min/max/nominal values */
	AH5416(ah)->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ;
	AH5416(ah)->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ;
	AH5416(ah)->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9285_2GHZ;
	/* XXX no 5ghz values? */

	ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist);

	HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);

	return ah;
bad:
	if (ah != AH_NULL)
		ah->ah_detach(ah);
	if (status)
		*status = ecode;
	return AH_NULL;
}

static void
ar9285ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore, HAL_BOOL power_off)
{
	uint32_t val;

	/*
	 * This workaround needs some integration work with the HAL
	 * config parameters and the if_ath_pci.c glue.
	 * Specifically, read the value of the PCI register 0x70c
	 * (4 byte PCI config space register) and store it in ath_hal_war70c.
	 * Then if it's non-zero, the below WAR would override register
	 * 0x570c upon suspend/resume.
	 */
#if 0
	if (AR_SREV_9285E_20(ah)) {
		val = AH_PRIVATE(ah)->ah_config.ath_hal_war70c;
		if (val) {
			val &= 0xffff00ff;
			val |= 0x6f00;
			OS_REG_WRITE(ah, 0x570c, val);
		}
	}
#endif

	if (AH_PRIVATE(ah)->ah_ispcie && !restore) {
		ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0);
		OS_DELAY(1000);
	}

	/*
	 * Set PCIe workaround bits
	 *
	 * NOTE:
	 *
	 * In Merlin and Kite, bit 14 in WA register (disable L1) should only
	 * be set when device enters D3 and be cleared when device comes back
	 * to D0.
	 */
	if (power_off) {                /* Power-off */
		OS_REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);

		val = OS_REG_READ(ah, AR_WA);

		/*
		 * Disable bit 6 and 7 before entering D3 to prevent
		 * system hang.
		 */
		val &= ~(AR_WA_BIT6 | AR_WA_BIT7);

		/*
		 * See above: set AR_WA_D3_L1_DISABLE when entering D3 state.
		 *
		 * XXX The reference HAL does it this way - it only sets
		 * AR_WA_D3_L1_DISABLE if it's set in AR9280_WA_DEFAULT,
		 * which it (currently) isn't.  So the following statement
		 * is currently a NOP.
		 */
		if (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)
			val |= AR_WA_D3_L1_DISABLE;

		if (AR_SREV_9285E_20(ah))
			val |= AR_WA_BIT23;

		OS_REG_WRITE(ah, AR_WA, val);
	} else {			/* Power-on */
		val = AR9285_WA_DEFAULT;
		/*
		 * See note above: make sure L1_DISABLE is not set.
		 */
		val &= (~AR_WA_D3_L1_DISABLE);

		/* Software workaroud for ASPM system hang. */
		val |= (AR_WA_BIT6 | AR_WA_BIT7);

		if (AR_SREV_9285E_20(ah))
			val |= AR_WA_BIT23;

		OS_REG_WRITE(ah, AR_WA, val);

		/* set bit 19 to allow forcing of pcie core into L1 state */
		OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
	}
}
Exemple #17
0
/*
 * Start continuous transmit operation.
 */
static int
tx99_start(struct ath_softc *sc)
{
    static struct ath_tx99_tgt tx99_tgt;
    struct ath_tx99 *tx99 = sc->sc_tx99;
    struct ath_hal *ah = sc->sc_ah;
    int is2GHz = 0;
    wbuf_t 	wbuf;
    HAL_CHANNEL *chan = NULL;
	
    if(tx99->recv)
    {
        ath_hal_phydisable(ah);
        DPRINTF(sc, ATH_DEBUG_TX99, "%s: tx99 continuous receive mode, return!\n", __func__);
        return 0;
    }

    /* check tx99 running state */
    if(tx99->tx99_state){		/* already active */
        DPRINTF(sc, ATH_DEBUG_TX99, "%s: already running, return!\n", __func__);
        return 0;
    }

    OS_DELAY(10000);
	
    /* set tx99 state active */
    tx99->tx99_state = 1;
    /* allocate diag packet buffer */
    if (tx99->wbuf == NULL) {
        tx99->wbuf = wbuf_alloc(sc->sc_osdev, WBUF_TX_DATA, 2000);
        if (tx99->wbuf == NULL) {
            DPRINTF(sc, ATH_DEBUG_TX99, "%s: unable to allocate wbuf!\n", __func__);
            tx99->tx99_state = 0;
            return -ENOMEM;
        }
    } else {
        DPRINTF(sc, ATH_DEBUG_TX99, "%s: wbuf was allocated before!\n", __func__);
    }
    wbuf = tx99->wbuf;
    /* drain all tx queue */
    ath_drain_txq(sc);
    /*
     * Setup channel using configured frequency+flags.
     */
    if (tx99_channel_setup(sc)) {
        DPRINTF(sc, ATH_DEBUG_TX99, "%s: unable to setup channel!\n", __func__);
		/* recover the default channel and mode */
        tx99->txfreq = 2412;/* ieee channel frequecy */
        tx99->htmode = 0;
        tx99->htext = 0;
		
        goto bad;
    }
    /*
     * Setup tx power limit
     */ 
    chan = &sc->sc_curchan; 
    is2GHz = TX99_IS_CHAN_2GHZ(chan);
    ath_hal_settxpowlimit(ah,tx99->txpower,0,is2GHz);
    /* set tx99 enable */
    tx99_tgt.txrate = htonl(tx99->txrate);
    tx99_tgt.txrc = htonl(tx99->txrc);
    tx99_tgt.txpower = htonl(tx99->txpower);
    tx99_tgt.txchain = htonl(tx99->chanmask);
    tx99_tgt.htmode = htonl(tx99->htmode);
    tx99_tgt.type = htonl(tx99->type);
    tx99_tgt.chtype = htonl(TX99_IS_CHAN_5GHZ(chan));
    tx99_tgt.txantenna = htonl(0);
	
    if( tx99->txpower < 60 ) /* only update channel pwr if not default MAX power */
        ath_hal_tx99_channel_pwr_update(ah, chan, tx99->txpower);
	
#ifdef ATH_SUPPORT_HTC
    ah_tx99_start(ah, (u_int8_t *)&tx99_tgt);
	
    /* send diag packet */
    {
        struct  ath_txep *txep;
        A_STATUS ret;
		
        adf_nbuf_put_tail(skb, 1500);
        txep = sc->sc_ac2ep[WME_AC_VO];
        /* send packet to target */
        ret = HTCSendPkt(sc->sc_host_htc_handle, NULL ,skb, sc->sc_data_VO_ep);
        if(ret)
        {
            DPRINTF(sc, ATH_DEBUG_TX99, "%s: tx99 fail!\n", __func__);
            tx99_stop(sc, 0);
        }	
    }
#else
    if (ath_tx99_tgt_start(sc, tx99_tgt.chtype) != EOK) {
        goto bad;
    }
#endif
	
    /* wait a while to make sure target setting ready */
    OS_DELAY(50000);
    DPRINTF(sc, ATH_DEBUG_TX99, "%s: continuous transmit started!\n", __func__);
    return 0;
bad:
    tx99_stop(sc, 0);
    return -EIO;
}
Exemple #18
0
static void
ar9285_hw_pa_cal(struct ath_hal *ah, HAL_BOOL is_reset)
{
	uint32_t regVal;
	int i, offset, offs_6_1, offs_0;
	uint32_t ccomp_org, reg_field;
	uint32_t regList[][2] = {
		{ 0x786c, 0 },
		{ 0x7854, 0 },
		{ 0x7820, 0 },
		{ 0x7824, 0 },
		{ 0x7868, 0 },
		{ 0x783c, 0 },
		{ 0x7838, 0 },
	};

	/* PA CAL is not needed for high power solution */
	if (ath_hal_eepromGet(ah, AR_EEP_TXGAIN_TYPE, AH_NULL) ==
	    AR5416_EEP_TXGAIN_HIGH_POWER)
		return;

	HALDEBUG(ah, HAL_DEBUG_PERCAL, "Running PA Calibration\n");

	for (i = 0; i < N(regList); i++)
		regList[i][1] = OS_REG_READ(ah, regList[i][0]);

	regVal = OS_REG_READ(ah, 0x7834);
	regVal &= (~(0x1));
	OS_REG_WRITE(ah, 0x7834, regVal);
	regVal = OS_REG_READ(ah, 0x9808);
	regVal |= (0x1 << 27);
	OS_REG_WRITE(ah, 0x9808, regVal);

	OS_REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
	OS_REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
	OS_REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
	OS_REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
	OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
	OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
	OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
	OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0);
	OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
	OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
	OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
	OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
	ccomp_org = MS(OS_REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
	OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf);

	OS_REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
	OS_DELAY(30);
	OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
	OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);

	for (i = 6; i > 0; i--) {
		regVal = OS_REG_READ(ah, 0x7834);
		regVal |= (1 << (19 + i));
		OS_REG_WRITE(ah, 0x7834, regVal);
		OS_DELAY(1);
		regVal = OS_REG_READ(ah, 0x7834);
		regVal &= (~(0x1 << (19 + i)));
		reg_field = MS(OS_REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
		regVal |= (reg_field << (19 + i));
		OS_REG_WRITE(ah, 0x7834, regVal);
	}

	OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
	OS_DELAY(1);
	reg_field = MS(OS_REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
	OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
	offs_6_1 = MS(OS_REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
	offs_0   = MS(OS_REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);

	offset = (offs_6_1<<1) | offs_0;
	offset = offset - 0;
	offs_6_1 = offset>>1;
	offs_0 = offset & 1;

	if ((!is_reset) && (AH9285(ah)->pacal_info.prev_offset == offset)) {
		if (AH9285(ah)->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
			AH9285(ah)->pacal_info.max_skipcount =
				2 * AH9285(ah)->pacal_info.max_skipcount;
		AH9285(ah)->pacal_info.skipcount = AH9285(ah)->pacal_info.max_skipcount;
	} else {
		AH9285(ah)->pacal_info.max_skipcount = 1;
		AH9285(ah)->pacal_info.skipcount = 0;
		AH9285(ah)->pacal_info.prev_offset = offset;
	}

	OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
	OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);

	regVal = OS_REG_READ(ah, 0x7834);
	regVal |= 0x1;
	OS_REG_WRITE(ah, 0x7834, regVal);
	regVal = OS_REG_READ(ah, 0x9808);
	regVal &= (~(0x1 << 27));
	OS_REG_WRITE(ah, 0x9808, regVal);

	for (i = 0; i < N(regList); i++)
		OS_REG_WRITE(ah, regList[i][0], regList[i][1]);

	OS_REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
}
Exemple #19
0
/*
 * Stop Receive at the DMA engine
 */
HAL_BOOL
ar9300StopDmaReceive(struct ath_hal *ah, u_int timeout)
{
    int wait;
    int cnt = 0, fail_cnt = 0;
    HAL_BOOL status, okay;

#define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
#define AH_TIME_QUANTUM        100     /* usec */

#ifdef AR9300_EMULATION
    timeout = 100000;
#else
    if (timeout == 0) {
        timeout = AH_RX_STOP_DMA_TIMEOUT;
    }
#endif

    OS_REG_WRITE(ah, AR_MACMISC, 
        ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | 
         (AR_MACMISC_MISC_OBS_BUS_1 << AR_MACMISC_MISC_OBS_BUS_MSB_S)));

    while (cnt < 3 && fail_cnt < 5) {
        okay = ath_hal_wait(
            ah, AR_DMADBG_7, AR_DMADBG_RX_STATE, 0, AH_WAIT_TIMEOUT);
        // wait for Rx DMA state machine to become idle
        if (!okay) {
            HDPRINTF(ah, HAL_DBG_RX,
                "reg AR_DMADBG_7 is not 0, instead 0x%08x\n",
                OS_REG_READ(ah, AR_DMADBG_7));
            fail_cnt++;
            cnt = 0;
        }
        cnt++;
    }

    /* Set receive disable bit */
    OS_REG_WRITE(ah, AR_CR, AR_CR_RXD);

    /* Wait for rx enable bit to go low */
    for (wait = timeout / AH_TIME_QUANTUM; wait != 0; wait--) {
        if ((OS_REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) {
            break;
        }
        OS_DELAY(AH_TIME_QUANTUM);
    }

    if (wait == 0) {
        HDPRINTF(ah, HAL_DBG_RX, "%s: dma failed to stop in %d ms\n"
                "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n",
                __func__,
                timeout / 1000,
                OS_REG_READ(ah, AR_CR),
                OS_REG_READ(ah, AR_DIAG_SW));
        status = AH_FALSE;
    } else {
        status = AH_TRUE;
    }

    return status;
#undef AH_RX_STOP_DMA_TIMEOUT
#undef AH_TIME_QUANTUM
}
Exemple #20
0
/*
 * WAR for Bug 33276: In certain systems, the RfKill signal is slow to
 * stabilize when waking up from power suspend. The RfKill is an
 * active-low GPIO signal that could be slow to rise from 0V to VCC.
 * Due to this slow transition after a power resume, the driver might 
 * wrongly read the RfKill is active.
 * For this workaround, when the power resumes and the RfKill is found to be
 * active and its previous state before sleep is inactive, then we will
 * delayed implementing the new RfKill state and poll for up to 1.0 secs.
 *
 * WARNING: Be careful when calling this routine since it will stall the
 * CPU for up to 1 seconds. Ideally, you should call this routine at the
 * PASSIVE level.
 */
void
ath_rfkill_delay_detect(struct ath_softc *sc)
{
    int wait_time = 0;
    HAL_BOOL first_time_after_attach;

    /* 
     * MAX_RFKILL_DELAY_WAIT_TIME is max. time to wait for the RfKill to 
     * transition from ON to OFF. Units is microsec.
     */
    #define MAX_RFKILL_DELAY_WAIT_TIME      1000000
    /* Time interval to check RfKill. Units is microsec. */
    #define RFKILL_PERIODIC_CHK_TIME        20000

    first_time_after_attach = !sc->sc_rfkill.delay_chk_start;
    sc->sc_rfkill.delay_chk_start = AH_TRUE;
    
    /*
     * Workaround not possible or required for any of the following reasons:
     * 1) The hardware can generate the RfKill interrupt,
     * 2) First time after system boot,
     * 3) Last known hardware state is already OFF,
     * 4) Current hardware state is ON (RfKill is disabled).
     */
    if (ath_rfkill_hasint(sc) ||
        first_time_after_attach ||
        !sc->sc_hw_phystate ||
        !ath_get_rfkill(sc)) {
        return;
    }

    /* Assumed that the RfKill Poll is not active */
    ASSERT(!ath_timer_is_initialized(&sc->sc_rfkill.rf_timer) || 
           !ath_timer_is_active(&sc->sc_rfkill.rf_timer));

    /*
     * Wait for the RfKill to switch back to active
     */
    while (ath_get_rfkill(sc)) {
        /*
         * Bad! We are stalling the CPU for long period of time. Please make
         * sure your OSes can handle this.
         */
        OS_DELAY(RFKILL_PERIODIC_CHK_TIME);
        wait_time += RFKILL_PERIODIC_CHK_TIME;
        if (wait_time >= MAX_RFKILL_DELAY_WAIT_TIME) {
            /*
             * Waited too long. Assumed that the RfKill has stabilized.
             */
            DPRINTF(sc, ATH_DEBUG_ANY, 
                    "%s: RfKill state did not changed after delay of %d millisec.\n",
                   __func__, (wait_time/1000));
            return;
        }
    }
    /*
     * The RfKill has changed. Update the sw phy state.
     */
    DPRINTF(sc, ATH_DEBUG_ANY, 
            "%s: Warning: RfKill state has switch to OFF after delay of %d millisec.\n",
           __func__, (wait_time/1000));

    return;

#undef MAX_RFKILL_DELAY_WAIT_TIME
#undef RFKILL_PERIODIC_CHK_TIME
}
Exemple #21
0
static void
ar5416LoadNF(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
	static const uint32_t ar5416_cca_regs[] = {
		AR_PHY_CCA,
		AR_PHY_CH1_CCA,
		AR_PHY_CH2_CCA,
		AR_PHY_EXT_CCA,
		AR_PHY_CH1_EXT_CCA,
		AR_PHY_CH2_EXT_CCA
	};
	struct ar5212NfCalHist *h;
	int i, j;
	int32_t val;
	uint8_t chainmask;

	/*
	 * Force NF calibration for all chains.
	 */
	if (AR_SREV_KITE(ah)) {
		/* Kite has only one chain */
		chainmask = 0x9;
	} else if (AR_SREV_MERLIN(ah)) {
		/* Merlin has only two chains */
		chainmask = 0x1B;
	} else {
		chainmask = 0x3F;
	}

	/*
	 * Write filtered NF values into maxCCApwr register parameter
	 * so we can load below.
	 */
	h = AH5416(ah)->ah_cal.nfCalHist;
	for (i = 0; i < AR5416_NUM_NF_READINGS; i ++)
		if (chainmask & (1 << i)) { 
			val = OS_REG_READ(ah, ar5416_cca_regs[i]);
			val &= 0xFFFFFE00;
			val |= (((uint32_t)(h[i].privNF) << 1) & 0x1ff);
			OS_REG_WRITE(ah, ar5416_cca_regs[i], val);
		}

	/* Load software filtered NF value into baseband internal minCCApwr variable. */
	OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_ENABLE_NF);
	OS_REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
	OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);

	/* Wait for load to complete, should be fast, a few 10s of us. */
	for (j = 0; j < 1000; j++) {
		if ((OS_REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) == 0)
			break;
		OS_DELAY(10);
	}

	/*
	 * Restore maxCCAPower register parameter again so that we're not capped
	 * by the median we just loaded.  This will be initial (and max) value
	 * of next noise floor calibration the baseband does.  
	 */
	for (i = 0; i < AR5416_NUM_NF_READINGS; i ++)
		if (chainmask & (1 << i)) {	
			val = OS_REG_READ(ah, ar5416_cca_regs[i]);
			val &= 0xFFFFFE00;
			val |= (((uint32_t)(-50) << 1) & 0x1ff);
			OS_REG_WRITE(ah, ar5416_cca_regs[i], val);
		}
}
Exemple #22
0
void MMI_ProcessSleep(void) {
    /* Delay for 1000 ms */
    OS_DELAY(1000);
}
/*
 * Deregister a callback.
 */
int
ieee80211_vap_ath_info_dereg_notify(
    ieee80211_vap_ath_info_notify_t h_notify)
{
    int                         ret_val = EOK;
    int                         i;
    wlan_if_t                   vap;
    ieee80211_vap_ath_info_t    h_mgr;

    if (h_notify == NULL) {
        printk("%s: Error: not attached.\n", __func__);
        return EINVAL;
    }

    h_mgr = h_notify->h_mgr;
    ASSERT(h_mgr);
    vap = h_mgr->vap;

    spin_lock(&(h_mgr->lock));

    ASSERT(h_notify->used);
    ASSERT(h_mgr->num_registered > 0);

    ASSERT(!h_notify->callback_inprog);

    h_mgr->num_registered--;

    OS_MEMZERO(h_notify, sizeof(struct ieee80211_vap_ath_info_notify));

    /* Re-calculate the interested information */
    h_mgr->all_interested_types = 0;
    for (i = 0; i < MAX_VAP_ATH_INFO_NOTIFY; i++) {
        if (!h_mgr->notify[i].used) {
            break;
        }
        h_mgr->all_interested_types |= h_mgr->notify[i].interested_types;
    }

    if (h_mgr->num_registered == 0) {
        /* Last one, deregistered with the ATH callbacks. */
        #define MAX_NUM_TRIES       20
        int     sanity_count = 0;

        ASSERT(h_mgr->all_interested_types == 0);
        while (true) {
            ret_val = vap->iv_dereg_vap_ath_info_notify(vap);
            if (ret_val == 1) {
                /* Interface is busy. Try again. */
                IEEE80211_DPRINTF(vap, IEEE80211_MSG_VAP_ATH_INFO, 
                        "%s: Interface Busy. Try %d of %d\n", __func__, sanity_count, MAX_NUM_TRIES);
                OS_DELAY(10);   // wait for 10 microseconds
                sanity_count++;
                if (sanity_count >= MAX_NUM_TRIES) {
                    IEEE80211_DPRINTF(vap, IEEE80211_MSG_VAP_ATH_INFO, 
                                      "%s: Error: waiting too long for "
                                      "iv_dereg_vap_ath_info_notify to complete.\n", __func__);
                    break;
                }
                continue;
            }
            else if (ret_val != 0) {
                IEEE80211_DPRINTF(vap, IEEE80211_MSG_VAP_ATH_INFO, 
                        "%s: Error calling iv_vap_info_get. ret=%d\n", __func__, ret_val);
                ret_val = EINVAL;
            }
            break;
        }
        #undef  MAX_NUM_TRIES
    }
    else {
        ret_val = vap->iv_vap_ath_info_update_notify(vap, h_mgr->all_interested_types);
        if (ret_val != 0) {
            IEEE80211_DPRINTF(vap, IEEE80211_MSG_VAP_ATH_INFO, 
                "%s: ERROR: Unabled to update registration callback from ATH. ret=%d\n", __func__, ret_val);
            ret_val = EINVAL;
        }
    }
    spin_unlock(&(h_mgr->lock));

    return ret_val;
}