static void ar9285WriteIni(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 */ freqIndex = 2; if (IEEE80211_IS_CHAN_HT40(chan)) modesIndex = 3; else if (IEEE80211_IS_CHAN_108G(chan)) modesIndex = 5; else modesIndex = 4; /* 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); if (AR_SREV_KITE_12_OR_LATER(ah)) { regWrites = ath_hal_ini_write(ah, &AH9285(ah)->ah_ini_txgain, modesIndex, regWrites); } regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common, 1, regWrites); }
static void ar9280WriteIni(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); /* XXX Merlin ini fixups */ /* XXX Merlin 100us delay for shift registers */ regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes, modesIndex, 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); } }
static void ar9287WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex, int writes) { (void) ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_bb_rfgain, freqIndex, writes); }
static void ar9285ConfigPCIE(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); } }
static void ar9285WriteIni(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *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 */ freqIndex = 2; if (IS_CHAN_HT40(chan)) modesIndex = 3; else if (IS_CHAN_108G(chan)) modesIndex = 5; else modesIndex = 4; /* 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); if (AR_SREV_KITE_12_OR_LATER(ah)) { regWrites = ath_hal_ini_write(ah, &AH9285(ah)->ah_ini_txgain, modesIndex, regWrites); } regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common, 1, regWrites); OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); if (AR_SREV_MERLIN_10_OR_LATER(ah)) { uint32_t val; val = OS_REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_PCU_MISC_MODE2_HWWAR1); OS_REG_WRITE(ah, AR_PCU_MISC_MODE2, val); OS_REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); } }
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); } }
/* * Take the MHz channel value and set the Channel value * * ASSUMES: Writes enabled to analog bus * * Actual Expression, * * For 2GHz channel, * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) * (freq_ref = 40MHz) * * For 5GHz channel, * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10) * (freq_ref = 40MHz/(24>>amodeRefSel)) * * For 5GHz channels which are 5MHz spaced, * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17) * (freq_ref = 40MHz) */ static HAL_BOOL ar9287SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan) { uint16_t bMode, fracMode, aModeRefSel = 0; uint32_t freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; CHAN_CENTERS centers; uint32_t refDivA = 24; OS_MARK(ah, AH_MARK_SETCHANNEL, chan->ic_freq); ar5416GetChannelCenters(ah, chan, ¢ers); freq = centers.synth_center; reg32 = OS_REG_READ(ah, AR_PHY_SYNTH_CONTROL); reg32 &= 0xc0000000; if (freq < 4800) { /* 2 GHz, fractional mode */ uint32_t txctl; int regWrites = 0; bMode = 1; fracMode = 1; aModeRefSel = 0; channelSel = (freq * 0x10000)/15; if (AR_SREV_KIWI_11_OR_LATER(ah)) { if (freq == 2484) { ath_hal_ini_write(ah, &AH9287(ah)->ah_ini_cckFirJapan2484, 1, regWrites); } else { ath_hal_ini_write(ah, &AH9287(ah)->ah_ini_cckFirNormal, 1, regWrites); } } txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL); if (freq == 2484) { /* Enable channel spreading for channel 14 */ OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, txctl | AR_PHY_CCK_TX_CTRL_JAPAN); } else { OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN); } } else { bMode = 0; fracMode = 0; if ((freq % 20) == 0) { aModeRefSel = 3; } else if ((freq % 10) == 0) { aModeRefSel = 2; } else { aModeRefSel = 0; /* * Enable 2G (fractional) mode for channels which * are 5MHz spaced */ fracMode = 1; refDivA = 1; channelSel = (freq * 0x8000)/15; /* RefDivA setting */ OS_A_REG_RMW_FIELD(ah, AR_AN_SYNTH9, AR_AN_SYNTH9_REFDIVA, refDivA); } if (!fracMode) { ndiv = (freq * (refDivA >> aModeRefSel))/60; channelSel = ndiv & 0x1ff; channelFrac = (ndiv & 0xfffffe00) * 2; channelSel = (channelSel << 17) | channelFrac; } }
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); } }
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); }
/* * 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 }
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); } }