⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ar5416_cal.c

📁 最新之atheros芯片driver source code, 基于linux操作系统,內含atheros芯片HAL全部代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting * Copyright (c) 2002-2008 Atheros Communications, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * $Id: ar5416_cal.c,v 1.7 2008/11/11 17:43:23 sam Exp $ */#include "opt_ah.h"#include "ah.h"#include "ah_internal.h"#include "ah_devid.h"#include "ah_eeprom_v14.h"#include "ar5416/ar5416.h"#include "ar5416/ar5416reg.h"#include "ar5416/ar5416phy.h"/* Owl specific stuff */#define NUM_NOISEFLOOR_READINGS 6       /* 3 chains * (ctl + ext) */static void ar5416StartNFCal(struct ath_hal *ah);static void ar5416LoadNF(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *);static int16_t ar5416GetNf(struct ath_hal *, HAL_CHANNEL_INTERNAL *);/* * Determine if calibration is supported by device and channel flags */static OS_INLINE HAL_BOOLar5416IsCalSupp(struct ath_hal *ah, HAL_CHANNEL *chan, HAL_CAL_TYPE calType) {	struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;	switch (calType & cal->suppCals) {	case IQ_MISMATCH_CAL:		/* Run IQ Mismatch for non-CCK only */		return !IS_CHAN_B(chan);	case ADC_GAIN_CAL:	case ADC_DC_CAL:		/* Run ADC Gain Cal for non-CCK & non 2GHz-HT20 only */		return !IS_CHAN_B(chan) &&		    !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan));	}	return AH_FALSE;}/* * Setup HW to collect samples used for current cal */static voidar5416SetupMeasurement(struct ath_hal *ah, HAL_CAL_LIST *currCal){	/* Start 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,	    currCal->calData->calCountMax);	/* Select calibration to run */	switch (currCal->calData->calType) {	case IQ_MISMATCH_CAL:		OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);		HALDEBUG(ah, HAL_DEBUG_PERCAL,		    "%s: start IQ Mismatch calibration\n", __func__);		break;	case ADC_GAIN_CAL:		OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);		HALDEBUG(ah, HAL_DEBUG_PERCAL,		    "%s: start ADC Gain calibration\n", __func__);		break;	case ADC_DC_CAL:		OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);		HALDEBUG(ah, HAL_DEBUG_PERCAL,		    "%s: start ADC DC calibration\n", __func__);		break;	case ADC_DC_INIT_CAL:		OS_REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);		HALDEBUG(ah, HAL_DEBUG_PERCAL,		    "%s: start Init ADC DC calibration\n", __func__);		break;	}	/* Kick-off cal */	OS_REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_DO_CAL);}/* * Initialize shared data structures and prepare a cal to be run. */static voidar5416ResetMeasurement(struct ath_hal *ah, HAL_CAL_LIST *currCal){	struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;	/* Reset data structures shared between different calibrations */	OS_MEMZERO(cal->caldata, sizeof(cal->caldata));	cal->calSamples = 0;	/* Setup HW for new calibration */	ar5416SetupMeasurement(ah, currCal);	/* Change SW state to RUNNING for this calibration */	currCal->calState = CAL_RUNNING;}#if 0/* * Run non-periodic calibrations. */static HAL_BOOLar5416RunInitCals(struct ath_hal *ah, int init_cal_count){	struct ath_hal_5416 *ahp = AH5416(ah);	struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;	HAL_CHANNEL_INTERNAL ichan;	/* XXX bogus */	HAL_CAL_LIST *curCal = ahp->ah_cal_curr;	HAL_BOOL isCalDone;	int i;	if (curCal == AH_NULL)		return AH_FALSE;	ichan.calValid = 0;	for (i = 0; i < init_cal_count; i++) {		/* Reset this Cal */		ar5416ResetMeasurement(ah, curCal);		/* Poll for offset calibration complete */		if (!ath_hal_wait(ah, AR_PHY_TIMING_CTRL4, AR_PHY_TIMING_CTRL4_DO_CAL, 0)) {			HALDEBUG(ah, HAL_DEBUG_ANY,			    "%s: Cal %d failed to finish in 100ms.\n",			    __func__, curCal->calData->calType);			/* Re-initialize list pointers for periodic cals */			cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL;			return AH_FALSE;		}		/* Run this cal */		ar5416DoCalibration(ah, &ichan, ahp->ah_rxchainmask,		    curCal, &isCalDone);		if (!isCalDone)			HALDEBUG(ah, HAL_DEBUG_ANY,			    "%s: init cal %d did not complete.\n",			    __func__, curCal->calData->calType);		if (curCal->calNext != AH_NULL)			curCal = curCal->calNext;	}	/* Re-initialize list pointers for periodic cals */	cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL;	return AH_TRUE;}#endif/* * Initialize Calibration infrastructure. */HAL_BOOLar5416InitCal(struct ath_hal *ah, HAL_CHANNEL *chan){	struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;	HAL_CHANNEL_INTERNAL *ichan;	ichan = ath_hal_checkchannel(ah, chan);	HALASSERT(ichan != AH_NULL);	if (AR_SREV_MERLIN_10_OR_LATER(ah)) {		/* Enable Rx Filter Cal */		OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);		OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,		    AR_PHY_AGC_CONTROL_FLTR_CAL);		/* Clear the carrier leak cal bit */		OS_REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);		/* kick off the cal */		OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);		/* Poll for offset calibration complete */		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__);			return AH_FALSE;		}		/* Set the cl cal bit and rerun the cal a 2nd time */		/* Enable Rx Filter Cal */		OS_REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);		OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,		    AR_PHY_AGC_CONTROL_FLTR_CAL);		OS_REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);	} 		/* Calibrate the AGC */	OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL);	/* Poll for offset calibration complete */	if (!ath_hal_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {		HALDEBUG(ah, HAL_DEBUG_ANY,		    "%s: offset calibration did not complete in 1ms; "		    "noisy environment?\n", __func__);		return AH_FALSE;	}	/* 	 * Do NF calibration after DC offset and other CALs.	 * Per system engineers, noise floor value can sometimes be 20 dB	 * higher than normal value if DC offset and noise floor cal are	 * triggered at the same time.	 */	OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);	/* Initialize list pointers */	cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL;	/*	 * Enable IQ, ADC Gain, ADC DC Offset Cals	 */	if (AR_SREV_SOWL_10_OR_LATER(ah)) {		/* Setup all non-periodic, init time only calibrations */		/* XXX: Init DC Offset not working yet */#if 0		if (ar5416IsCalSupp(ah, chan, ADC_DC_INIT_CAL)) {			INIT_CAL(&cal->adcDcCalInitData);			INSERT_CAL(cal, &cal->adcDcCalInitData);		}		/* Initialize current pointer to first element in list */		cal->cal_curr = cal->cal_list;		if (cal->ah_cal_curr != AH_NULL && !ar5416RunInitCals(ah, 0))			return AH_FALSE;#endif	}	/* If Cals are supported, add them to list via INIT/INSERT_CAL */	if (ar5416IsCalSupp(ah, chan, ADC_GAIN_CAL)) {		INIT_CAL(&cal->adcGainCalData);		INSERT_CAL(cal, &cal->adcGainCalData);		HALDEBUG(ah, HAL_DEBUG_PERCAL,		    "%s: enable ADC Gain Calibration.\n", __func__);	}	if (ar5416IsCalSupp(ah, chan, ADC_DC_CAL)) {		INIT_CAL(&cal->adcDcCalData);		INSERT_CAL(cal, &cal->adcDcCalData);		HALDEBUG(ah, HAL_DEBUG_PERCAL,		    "%s: enable ADC DC Calibration.\n", __func__);	}	if (ar5416IsCalSupp(ah, chan, IQ_MISMATCH_CAL)) {		INIT_CAL(&cal->iqCalData);		INSERT_CAL(cal, &cal->iqCalData);		HALDEBUG(ah, HAL_DEBUG_PERCAL,		    "%s: enable IQ Calibration.\n", __func__);	}	/* Initialize current pointer to first element in list */	cal->cal_curr = cal->cal_list;	/* Kick off measurements for the first cal */	if (cal->cal_curr != AH_NULL)		ar5416ResetMeasurement(ah, cal->cal_curr);	/* Mark all calibrations on this channel as being invalid */	ichan->calValid = 0;	return AH_TRUE;}/* * Entry point for upper layers to restart current cal. * Reset the calibration valid bit in channel. */HAL_BOOLar5416ResetCalValid(struct ath_hal *ah, HAL_CHANNEL *chan){	struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;	HAL_CHANNEL_INTERNAL *ichan = ath_hal_checkchannel(ah, chan);	HAL_CAL_LIST *currCal = cal->cal_curr;	if (!AR_SREV_SOWL_10_OR_LATER(ah))		return AH_FALSE;	if (currCal == AH_NULL)		return AH_FALSE;	if (ichan == AH_NULL) {		HALDEBUG(ah, HAL_DEBUG_ANY,		    "%s: invalid channel %u/0x%x; no mapping\n",		    __func__, chan->channel, chan->channelFlags);		return AH_FALSE;	}	/*	 * Expected that this calibration has run before, post-reset.	 * Current state should be done	 */	if (currCal->calState != CAL_DONE) {		HALDEBUG(ah, HAL_DEBUG_ANY,		    "%s: Calibration state incorrect, %d\n",		    __func__, currCal->calState);		return AH_FALSE;	}	/* Verify Cal is supported on this channel */	if (!ar5416IsCalSupp(ah, chan, currCal->calData->calType))		return AH_FALSE;	HALDEBUG(ah, HAL_DEBUG_PERCAL,	    "%s: Resetting Cal %d state for channel %u/0x%x\n",	    __func__, currCal->calData->calType, chan->channel,	    chan->channelFlags);	/* Disable cal validity in channel */	ichan->calValid &= ~currCal->calData->calType;	currCal->calState = CAL_WAITING;	return AH_TRUE;}/* * Recalibrate the lower PHY chips to account for temperature/environment * changes. */static voidar5416DoCalibration(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *ichan,	uint8_t rxchainmask, HAL_CAL_LIST *currCal, HAL_BOOL *isCalDone){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -