drivers/net/wireless/ath/ath9k/ar9003_calib.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/ath/ath9k/ar9003_calib.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/ath/ath9k/ar9003_calib.c
Extension
.c
Size
47135 bytes
Lines
1699
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct coeff {
	int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
	int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
	int iqc_coeff[2];
};

enum ar9003_cal_types {
	IQ_MISMATCH_CAL = BIT(0),
};

static void ar9003_hw_setup_calibration(struct ath_hw *ah,
					struct ath9k_cal_list *currCal)
{
	struct ath_common *common = ath9k_hw_common(ah);

	/* Select calibration to run */
	switch (currCal->calData->calType) {
	case IQ_MISMATCH_CAL:
		/*
		 * Start calibration with
		 * 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples
		 */
		REG_RMW_FIELD(ah, AR_PHY_TIMING4,
			      AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX,
			      currCal->calData->calCountMax);
		REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);

		ath_dbg(common, CALIBRATE,
			"starting IQ Mismatch Calibration\n");

		/* Kick-off cal */
		REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
		break;
	default:
		ath_err(common, "Invalid calibration type\n");
		break;
	}
}

/*
 * Generic calibration routine.
 * Recalibrate the lower PHY chips to account for temperature/environment
 * changes.
 */
static bool ar9003_hw_per_calibration(struct ath_hw *ah,
				      struct ath9k_channel *ichan,
				      u8 rxchainmask,
				      struct ath9k_cal_list *currCal)
{
	struct ath9k_hw_cal_data *caldata = ah->caldata;
	const struct ath9k_percal_data *cur_caldata = currCal->calData;

	/* Calibration in progress. */
	if (currCal->calState == CAL_RUNNING) {
		/* Check to see if it has finished. */
		if (REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)
			return false;

		/*
		* Accumulate cal measures for active chains
		*/
		cur_caldata->calCollect(ah);
		ah->cal_samples++;

		if (ah->cal_samples >= cur_caldata->calNumSamples) {
			unsigned int i, numChains = 0;
			for (i = 0; i < AR9300_MAX_CHAINS; i++) {
				if (rxchainmask & (1 << i))
					numChains++;
			}

			/*
			* Process accumulated data
			*/
			cur_caldata->calPostProc(ah, numChains);

			/* Calibration has finished. */
			caldata->CalValid |= cur_caldata->calType;
			currCal->calState = CAL_DONE;
			return true;
		} else {
			/*
			 * Set-up collection of another sub-sample until we
			 * get desired number
			 */
			ar9003_hw_setup_calibration(ah, currCal);
		}
	} else if (!(caldata->CalValid & cur_caldata->calType)) {
		/* If current cal is marked invalid in channel, kick it off */
		ath9k_hw_reset_calibration(ah, currCal);

Annotation

Implementation Notes