Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 26 May 2011 14:29:05 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r222308 - head/sys/dev/ath/ath_hal/ar9002
Message-ID:  <201105261429.p4QET5Im068248@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Thu May 26 14:29:05 2011
New Revision: 222308
URL: http://svn.freebsd.org/changeset/base/222308

Log:
  Flesh out the TX power calibration for the AR9287.
  
  I'm assuming for now that the AR9287 is only open-loop TX power control
  (as mine is) so I've hard-coded the attach path to fail if the NIC is
  not open-loop.
  
  This greatly simplifies the TX calibration path and the amount of code
  which needs to be ported over.
  
  This still isn't complete - the rate calculation code still needs to be
  ported and it all needs to be glued together.
  
  Obtained from:	Linux ath9k

Modified:
  head/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c
  head/sys/dev/ath/ath_hal/ar9002/ar9287_olc.c
  head/sys/dev/ath/ath_hal/ar9002/ar9287_olc.h
  head/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c

Modified: head/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c
==============================================================================
--- head/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c	Thu May 26 13:54:07 2011	(r222307)
+++ head/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c	Thu May 26 14:29:05 2011	(r222308)
@@ -276,6 +276,17 @@ ar9287Attach(uint16_t devid, HAL_SOFTC s
 		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.

Modified: head/sys/dev/ath/ath_hal/ar9002/ar9287_olc.c
==============================================================================
--- head/sys/dev/ath/ath_hal/ar9002/ar9287_olc.c	Thu May 26 13:54:07 2011	(r222307)
+++ head/sys/dev/ath/ath_hal/ar9002/ar9287_olc.c	Thu May 26 14:29:05 2011	(r222308)
@@ -30,6 +30,7 @@
 #include "ah_internal.h"
 
 #include "ah_eeprom_v14.h"
+#include "ah_eeprom_9287.h"
 
 #include "ar9002/ar9280.h"
 #include "ar5416/ar5416reg.h"
@@ -92,3 +93,74 @@ ar9287olcTemperatureCompensation(struct 
 		    AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta);
 	}
 }
+
+void
+ar9287olcGetTxGainIndex(struct ath_hal *ah,
+    const struct ieee80211_channel *chan,
+    struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop,
+    uint8_t *pCalChans,  uint16_t availPiers, int8_t *pPwr)
+{
+        uint16_t idxL = 0, idxR = 0, numPiers;
+        HAL_BOOL match;
+        CHAN_CENTERS centers;
+
+        ar5416GetChannelCenters(ah, chan, &centers);
+
+        for (numPiers = 0; numPiers < availPiers; numPiers++) {
+                if (pCalChans[numPiers] == AR5416_BCHAN_UNUSED)
+                        break;
+        }
+
+        match = ath_ee_getLowerUpperIndex(
+                (uint8_t)FREQ2FBIN(centers.synth_center, IEEE80211_IS_CHAN_2GHZ(chan)),
+                pCalChans, numPiers, &idxL, &idxR);
+
+        if (match) {
+                *pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0];
+        } else {
+                *pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] +
+                         (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
+        }
+}
+
+void
+ar9287olcSetPDADCs(struct ath_hal *ah, int32_t txPower,
+    uint16_t chain)
+{
+        uint32_t tmpVal;
+        uint32_t a;
+
+        /* Enable OLPC for chain 0 */
+
+        tmpVal = OS_REG_READ(ah, 0xa270);
+        tmpVal = tmpVal & 0xFCFFFFFF;
+        tmpVal = tmpVal | (0x3 << 24);
+        OS_REG_WRITE(ah, 0xa270, tmpVal);
+
+        /* Enable OLPC for chain 1 */
+
+        tmpVal = OS_REG_READ(ah, 0xb270);
+        tmpVal = tmpVal & 0xFCFFFFFF;
+        tmpVal = tmpVal | (0x3 << 24);
+        OS_REG_WRITE(ah, 0xb270, tmpVal);
+
+        /* Write the OLPC ref power for chain 0 */
+
+        if (chain == 0) {
+                tmpVal = OS_REG_READ(ah, 0xa398);
+                tmpVal = tmpVal & 0xff00ffff;
+                a = (txPower)&0xff;
+                tmpVal = tmpVal | (a << 16);
+                OS_REG_WRITE(ah, 0xa398, tmpVal);
+        }
+
+        /* Write the OLPC ref power for chain 1 */
+
+        if (chain == 1) {
+                tmpVal = OS_REG_READ(ah, 0xb398);
+                tmpVal = tmpVal & 0xff00ffff;
+                a = (txPower)&0xff;
+                tmpVal = tmpVal | (a << 16);
+                OS_REG_WRITE(ah, 0xb398, tmpVal);
+        }
+}

Modified: head/sys/dev/ath/ath_hal/ar9002/ar9287_olc.h
==============================================================================
--- head/sys/dev/ath/ath_hal/ar9002/ar9287_olc.h	Thu May 26 13:54:07 2011	(r222307)
+++ head/sys/dev/ath/ath_hal/ar9002/ar9287_olc.h	Thu May 26 14:29:05 2011	(r222308)
@@ -21,5 +21,11 @@
 
 extern	void ar9287olcInit(struct ath_hal *ah);
 extern	void ar9287olcTemperatureCompensation(struct ath_hal *ah);
+extern	void ar9287olcGetTxGainIndex(struct ath_hal *ah,
+	const struct ieee80211_channel *chan,
+	struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop,
+	uint8_t *pCalChans, uint16_t availPiers, int8_t *pPwr);
+extern	void ar9287olcSetPDADCs(struct ath_hal *ah,
+	int32_t txPower, uint16_t chain);
 
 #endif	/* __AR9287_OLC_H__ */

Modified: head/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c
==============================================================================
--- head/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c	Thu May 26 13:54:07 2011	(r222307)
+++ head/sys/dev/ath/ath_hal/ar9002/ar9287_reset.c	Thu May 26 14:29:05 2011	(r222308)
@@ -33,13 +33,103 @@
 #include "ar9002/ar9287phy.h"
 #include "ar9002/ar9287an.h"
 
+#include "ar9002/ar9287_olc.h"
 #include "ar9002/ar9287_reset.h"
 
+/*
+ * Set the TX power calibration table per-chain.
+ *
+ * This only supports open-loop TX power control for the AR9287.
+ */
+static void
+ar9287SetPowerCalTable(struct ath_hal *ah,
+    const struct ieee80211_channel *chan, int16_t *pTxPowerIndexOffset)
+{
+        struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop;
+        uint8_t *pCalBChans = NULL;
+        uint16_t pdGainOverlap_t2;
+        uint16_t numPiers = 0, i;
+        uint16_t numXpdGain, xpdMask;
+        uint16_t xpdGainValues[AR5416_NUM_PD_GAINS] = {0, 0, 0, 0};
+        uint32_t regChainOffset;
+	HAL_EEPROM_9287 *ee = AH_PRIVATE(ah)->ah_eeprom;
+        struct ar9287_eeprom *pEepData = &ee->ee_base;
+
+        xpdMask = pEepData->modalHeader.xpdGain;
+
+        if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >=
+            AR9287_EEP_MINOR_VER_2)
+                pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap;
+        else
+                pdGainOverlap_t2 = (uint16_t)(MS(OS_REG_READ(ah, AR_PHY_TPCRG5),
+                                            AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+
+	/* Note: Kiwi should only be 2ghz.. */
+        if (IEEE80211_IS_CHAN_2GHZ(chan)) {
+                pCalBChans = pEepData->calFreqPier2G;
+                numPiers = AR9287_NUM_2G_CAL_PIERS;
+                pRawDatasetOpenLoop = (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[0];
+                AH5416(ah)->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0];
+        }
+        numXpdGain = 0;
+
+        /* Calculate the value of xpdgains from the xpdGain Mask */
+        for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
+                if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
+                        if (numXpdGain >= AR5416_NUM_PD_GAINS)
+                                break;
+                        xpdGainValues[numXpdGain] =
+                                (uint16_t)(AR5416_PD_GAINS_IN_MASK-i);
+                        numXpdGain++;
+                }
+        }
+
+        OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+                      (numXpdGain - 1) & 0x3);
+        OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
+                      xpdGainValues[0]);
+        OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
+                      xpdGainValues[1]);
+        OS_REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
+                      xpdGainValues[2]);
+
+        for (i = 0; i < AR9287_MAX_CHAINS; i++) {
+                regChainOffset = i * 0x1000;
+
+                if (pEepData->baseEepHeader.txMask & (1 << i)) {
+                        int8_t txPower;
+                        pRawDatasetOpenLoop =
+                        (struct cal_data_op_loop_ar9287 *)pEepData->calPierData2G[i];
+                                ar9287olcGetTxGainIndex(ah, chan,
+                                    pRawDatasetOpenLoop,
+                                    pCalBChans, numPiers,
+                                    &txPower);
+                                ar9287olcSetPDADCs(ah, txPower, i);
+                }
+        }
+
+        *pTxPowerIndexOffset = 0;
+}
+
 HAL_BOOL
 ar9287SetTransmitPower(struct ath_hal *ah,
 	const struct ieee80211_channel *chan, uint16_t *rfXpdGain)
 {
+	int16_t txPowerIndexOffset = 0;
+
 	/* XXX TODO */
+
+	/* Fetch per-rate power table for the given channel */
+
+	/* Set open-loop TX power control calibration */
+	ar9287SetPowerCalTable(ah, chan, &txPowerIndexOffset);
+
+	/* Calculate regulatory maximum power level */
+
+	/* Kiwi TX power starts at -5 dBm */
+
+	/* Write TX power registers */
+
 	return AH_TRUE;
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201105261429.p4QET5Im068248>