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); }
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); }
/* * 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); }
/* * 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); }
/* * 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); }
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; }
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); }
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 }
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); }
/* * 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; }
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 }
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); } }
/* * 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; }
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); }
/* * 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 }
/* * 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 }
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); } }
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; }