void ath9k_hw_abort_tx_dma(struct ath_hw *ah) { int maxdelay = 1000; int i, q; if (ah->curchan) { if (IS_CHAN_HALF_RATE(ah->curchan)) maxdelay *= 2; else if (IS_CHAN_QUARTER_RATE(ah->curchan)) maxdelay *= 4; } REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M); REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF); REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF); for (q = 0; q < AR_NUM_QCU; q++) { for (i = 0; i < maxdelay; i++) { if (i) udelay(5); if (!ath9k_hw_numtxpending(ah, q)) break; } } REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF); REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF); REG_WRITE(ah, AR_Q_TXD, 0); }
static u32 ar9003_hw_compute_pll_control(struct ath_hw *ah, struct ath9k_channel *chan) { u32 pll; pll = SM(0x5, AR_RTC_9300_PLL_REFDIV); if (chan && IS_CHAN_HALF_RATE(chan)) pll |= SM(0x1, AR_RTC_9300_PLL_CLKSEL); else if (chan && IS_CHAN_QUARTER_RATE(chan)) pll |= SM(0x2, AR_RTC_9300_PLL_CLKSEL); pll |= SM(0x2c, AR_RTC_9300_PLL_DIV); return pll; }
const HAL_RATE_TABLE * ar5212GetRateTable(struct ath_hal *ah, u_int mode) { HAL_RATE_TABLE *rt; switch (mode) { case HAL_MODE_11A: rt = &ar5212_11a_table; if (AH_PRIVATE(ah)->ah_curchan) { if (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) { rt = &ar5212_11a_half_table; } else if (IS_CHAN_QUARTER_RATE( AH_PRIVATE(ah)->ah_curchan)) { rt = &ar5212_11a_quarter_table; } } break; case HAL_MODE_11B: rt = &ar5212_11b_table; break; case HAL_MODE_11G: #ifdef notdef case HAL_MODE_PUREG: #endif rt = &ar5212_11g_table; break; case HAL_MODE_TURBO: rt = &ar5212_turboa_table; break; case HAL_MODE_108G: rt = &ar5212_turbog_table; break; case HAL_MODE_XR: rt = &ar5212_xr_table; break; case HAL_MODE_11A_HALF_RATE: rt = &ar5212_11a_half_table; break; case HAL_MODE_11A_QUARTER_RATE: rt = &ar5212_11a_quarter_table; break; default: HDPRINTF(ah, HAL_DBG_CHANNEL, "%s: invalid mode 0x%x\n", __func__, mode); return AH_NULL; } ath_hal_setupratetable(ah, rt); return rt; }
/** * ar9002_hw_set_channel - set channel on single-chip device * @ah: atheros hardware structure * @chan: * * This is the function to change channel on single-chip devices, that is * all devices after ar9280. * * This function takes the channel value in MHz and sets * hardware channel value. Assumes writes have been 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)) */ static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) { u16 bMode, fracMode, aModeRefSel = 0; u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; struct chan_centers centers; u32 refDivA = 24; ath9k_hw_get_channel_centers(ah, chan, ¢ers); freq = centers.synth_center; reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL); reg32 &= 0xc0000000; if (freq < 4800) { /* 2 GHz, fractional mode */ u32 txctl; int regWrites = 0; bMode = 1; fracMode = 1; aModeRefSel = 0; channelSel = CHANSEL_2G(freq); if (AR_SREV_9287_11_OR_LATER(ah)) { if (freq == 2484) { /* Enable channel spreading for channel 14 */ REG_WRITE_ARRAY(&ah->iniCckfirJapan2484, 1, regWrites); } else { REG_WRITE_ARRAY(&ah->iniCckfirNormal, 1, regWrites); } } else { txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); if (freq == 2484) { /* Enable channel spreading for channel 14 */ REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, txctl | AR_PHY_CCK_TX_CTRL_JAPAN); } else { REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); } } } else { bMode = 0; fracMode = 0; switch (ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) { case 0: if (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) aModeRefSel = 0; else if ((freq % 20) == 0) aModeRefSel = 3; else if ((freq % 10) == 0) aModeRefSel = 2; if (aModeRefSel) break; case 1: default: aModeRefSel = 0; /* * Enable 2G (fractional) mode for channels * which are 5MHz spaced. */ fracMode = 1; refDivA = 1; channelSel = CHANSEL_5G(freq); /* RefDivA setting */ ath9k_hw_analog_shift_rmw(ah, AR_AN_SYNTH9, AR_AN_SYNTH9_REFDIVA, AR_AN_SYNTH9_REFDIVA_S, refDivA); } if (!fracMode) { ndiv = (freq * (refDivA >> aModeRefSel)) / 60; channelSel = ndiv & 0x1ff; channelFrac = (ndiv & 0xfffffe00) * 2; channelSel = (channelSel << 17) | channelFrac; } }
/* * 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, HAL_CHANNEL *chan, HAL_BOOL bChannelChange, 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); #define IS(_c,_f) (((_c)->channelFlags & _f) || 0) if ((IS(chan, CHANNEL_2GHZ) ^ IS(chan, CHANNEL_5GHZ)) == 0) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u/0x%x; not marked as 2GHz or 5GHz\n", __func__, chan->channel, chan->channelFlags); FAIL(HAL_EINVAL); } if ((IS(chan, CHANNEL_OFDM) ^ IS(chan, CHANNEL_CCK)) == 0) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u/0x%x; not marked as OFDM or CCK\n", __func__, chan->channel, chan->channelFlags); FAIL(HAL_EINVAL); } #undef IS /* * 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->channel, chan->channelFlags); 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->channel != AH_PRIVATE(ah)->ah_curchan->channel) && ((chan->channelFlags & CHANNEL_ALL) == (AH_PRIVATE(ah)->ah_curchan->channelFlags & CHANNEL_ALL))) { 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 */ switch (chan->channelFlags & CHANNEL_ALL) { case CHANNEL_A: modesIndex = 1; freqIndex = 1; break; case CHANNEL_T: modesIndex = 2; freqIndex = 1; break; case CHANNEL_B: modesIndex = 3; freqIndex = 2; break; case CHANNEL_PUREG: modesIndex = 4; freqIndex = 2; break; case CHANNEL_108G: modesIndex = 5; freqIndex = 2; break; default: HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel flags 0x%x\n", __func__, chan->channelFlags); FAIL(HAL_EINVAL); } 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 (IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(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 (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 (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 (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 ((chan->channelFlags & CHANNEL_ALL) == CHANNEL_A) 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, ichan, 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, ichan, 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 (IS_CHAN_OFDM(chan)) { if ((IS_5413(ah) || (AH_PRIVATE(ah)->ah_eeversion >= AR_EEPROM_VER5_3)) && (!IS_CHAN_B(chan))) ar5212SetSpurMitigation(ah, ichan); ar5212SetDeltaSlope(ah, chan); } /* Setup board specific options for EEPROM version 3 */ if (!ar5212SetBoardValues(ah, ichan)) { 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, ichan)) 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) && (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan) || IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan))) { txFrm2TxDStart = (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) ? 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 (IS_CHAN_CCK(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 (IS_CHAN_HALF_RATE(AH_PRIVATE(ah)->ah_curchan)) { OS_DELAY((synthDelay << 1) + BASE_ACTIVATE_DELAY); } else if (IS_CHAN_QUARTER_RATE(AH_PRIVATE(ah)->ah_curchan)) { 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 (!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) { if (!(ichan->privFlags & CHANNEL_DFS)) ichan->privFlags &= ~CHANNEL_INTERFERENCE; chan->channelFlags = ichan->channelFlags; chan->privFlags = ichan->privFlags; } 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) *status = ecode; return AH_FALSE; #undef FAIL #undef N }
/* * 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, HAL_CHANNEL *chan) { OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->channel : 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 (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) { phyPLL = AR_PHY_PLL_CTL_44_5312; } else { if (IS_CHAN_HALF_RATE(chan)) { phyPLL = AR_PHY_PLL_CTL_40_5312_HALF; } else if (IS_CHAN_QUARTER_RATE(chan)) { phyPLL = AR_PHY_PLL_CTL_40_5312_QUARTER; } else { phyPLL = AR_PHY_PLL_CTL_40_5312; } } } else { if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) phyPLL = AR_PHY_PLL_CTL_44_5112; else phyPLL = AR_PHY_PLL_CTL_40_5112; if (IS_CHAN_HALF_RATE(chan)) phyPLL |= AR_PHY_PLL_CTL_HALF; else if (IS_CHAN_QUARTER_RATE(chan)) phyPLL |= AR_PHY_PLL_CTL_QUARTER; } } else { rfMode = AR_PHY_MODE_AR5111; if (IS_CHAN_CCK(chan) || IS_CHAN_G(chan)) phyPLL = AR_PHY_PLL_CTL_44; else phyPLL = AR_PHY_PLL_CTL_40; if (IS_CHAN_HALF_RATE(chan)) phyPLL = AR_PHY_PLL_CTL_HALF; else if (IS_CHAN_QUARTER_RATE(chan)) phyPLL = AR_PHY_PLL_CTL_QUARTER; } if (IS_CHAN_OFDM(chan) && (IS_CHAN_CCK(chan) || IS_CHAN_G(chan))) rfMode |= AR_PHY_MODE_DYNAMIC; else if (IS_CHAN_OFDM(chan)) rfMode |= AR_PHY_MODE_OFDM; else rfMode |= AR_PHY_MODE_CCK; if (IS_CHAN_5GHZ(chan)) rfMode |= AR_PHY_MODE_RF5GHZ; else rfMode |= AR_PHY_MODE_RF2GHZ; turbo = 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 (IS_CHAN_CCK(chan) || IS_CHAN_G(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; }
/* * Reads EEPROM header info from device structure and programs * all rf registers * * REQUIRES: Access to the analog rf device */ static HAL_BOOL ar5111SetRfRegs(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan, u_int16_t modesIndex, u_int16_t *rfXpdGain) { struct ath_hal_5212 *ahp = AH5212(ah); u_int16_t rfXpdGainFixed, rfPloSel, rfPwdXpd, gainI; u_int16_t tempOB, tempDB; u_int32_t ob2GHz, db2GHz, rfReg[N(ar5212Bank6_5111)]; int i, regWrites = 0; /* Setup rf parameters */ switch (chan->channelFlags & CHANNEL_ALL) { case CHANNEL_A: case CHANNEL_T: if (4000 < chan->channel && chan->channel < 5260) { tempOB = ahp->ah_ob1; tempDB = ahp->ah_db1; } else if (5260 <= chan->channel && chan->channel < 5500) { tempOB = ahp->ah_ob2; tempDB = ahp->ah_db2; } else if (5500 <= chan->channel && chan->channel < 5725) { tempOB = ahp->ah_ob3; tempDB = ahp->ah_db3; } else if (chan->channel >= 5725) { tempOB = ahp->ah_ob4; tempDB = ahp->ah_db4; } else { /* XXX when does this happen??? */ tempOB = tempDB = 0; } ob2GHz = db2GHz = 0; rfXpdGainFixed = ahp->ah_xgain[headerInfo11A]; rfPloSel = ahp->ah_xpd[headerInfo11A]; rfPwdXpd = !ahp->ah_xpd[headerInfo11A]; gainI = ahp->ah_gainI[headerInfo11A]; break; case CHANNEL_B: tempOB = ahp->ah_obFor24; tempDB = ahp->ah_dbFor24; ob2GHz = ahp->ah_ob2GHz[0]; db2GHz = ahp->ah_db2GHz[0]; rfXpdGainFixed = ahp->ah_xgain[headerInfo11B]; rfPloSel = ahp->ah_xpd[headerInfo11B]; rfPwdXpd = !ahp->ah_xpd[headerInfo11B]; gainI = ahp->ah_gainI[headerInfo11B]; break; case CHANNEL_G: tempOB = ahp->ah_obFor24g; tempDB = ahp->ah_dbFor24g; ob2GHz = ahp->ah_ob2GHz[1]; db2GHz = ahp->ah_db2GHz[1]; rfXpdGainFixed = ahp->ah_xgain[headerInfo11G]; rfPloSel = ahp->ah_xpd[headerInfo11G]; rfPwdXpd = !ahp->ah_xpd[headerInfo11G]; gainI = ahp->ah_gainI[headerInfo11G]; break; default: HDPRINTF(ah, HAL_DBG_CHANNEL, "%s: invalid channel flags 0x%x\n", __func__, chan->channelFlags); return AH_FALSE; } HALASSERT(1 <= tempOB && tempOB <= 5); HALASSERT(1 <= tempDB && tempDB <= 5); /* Bank 0 Write */ for (i = 0; i < N(ar5212Bank0_5111); i++) rfReg[i] = ar5212Bank0_5111[i][modesIndex]; if (IS_CHAN_2GHZ(chan)) { ar5212ModifyRfBuffer(rfReg, ob2GHz, 3, 119, 0); ar5212ModifyRfBuffer(rfReg, db2GHz, 3, 122, 0); } for (i = 0; i < N(ar5212Bank0_5111); i++) { OS_REG_WRITE(ah, ar5212Bank0_5111[i][0], rfReg[i]); ALLOW_DMA_READ_COMPLETE(regWrites); } /* Bank 1 Write */ REG_WRITE_ARRAY(ar5212Bank1_5111, 1, regWrites); /* Bank 2 Write */ REG_WRITE_ARRAY(ar5212Bank2_5111, modesIndex, regWrites); /* Bank 3 Write */ REG_WRITE_ARRAY(ar5212Bank3_5111, modesIndex, regWrites); /* Bank 6 Write */ for (i = 0; i < N(ar5212Bank6_5111); i++) rfReg[i] = ar5212Bank6_5111[i][modesIndex]; if (IS_CHAN_A(chan)) { /* NB: CHANNEL_A | CHANNEL_T */ ar5212ModifyRfBuffer(rfReg, ahp->ah_cornerCal.pd84, 1, 51, 3); ar5212ModifyRfBuffer(rfReg, ahp->ah_cornerCal.pd90, 1, 45, 3); } ar5212ModifyRfBuffer(rfReg, rfPwdXpd, 1, 95, 0); ar5212ModifyRfBuffer(rfReg, rfXpdGainFixed, 4, 96, 0); /* Set 5212 OB & DB */ ar5212ModifyRfBuffer(rfReg, tempOB, 3, 104, 0); ar5212ModifyRfBuffer(rfReg, tempDB, 3, 107, 0); for (i = 0; i < N(ar5212Bank6_5111); i++) { OS_REG_WRITE(ah, ar5212Bank6_5111[i][0], rfReg[i]); ALLOW_DMA_READ_COMPLETE(regWrites); } /* Bank 7 Write */ for (i = 0; i < N(ar5212Bank7_5111); i++) rfReg[i] = ar5212Bank7_5111[i][modesIndex]; ar5212ModifyRfBuffer(rfReg, gainI, 6, 29, 0); ar5212ModifyRfBuffer(rfReg, rfPloSel, 1, 4, 0); if (IS_CHAN_QUARTER_RATE(chan) || IS_CHAN_HALF_RATE(chan)) { u_int32_t rfWaitI, rfWaitS, rfMaxTime; rfWaitS = 0x1f; rfWaitI = (IS_CHAN_HALF_RATE(chan)) ? 0x10 : 0x1f; rfMaxTime = 3; ar5212ModifyRfBuffer(rfReg, rfWaitS, 5, 19, 0); ar5212ModifyRfBuffer(rfReg, rfWaitI, 5, 24, 0); ar5212ModifyRfBuffer(rfReg, rfMaxTime, 2, 49, 0); } for (i = 0; i < N(ar5212Bank7_5111); i++) { OS_REG_WRITE(ah, ar5212Bank7_5111[i][0], rfReg[i]); ALLOW_DMA_READ_COMPLETE(regWrites); } /* Now that we have reprogrammed rfgain value, clear the flag. */ ahp->ah_rfgainState = HAL_RFGAIN_INACTIVE; return AH_TRUE; }