Ejemplo n.º 1
0
/*
 * Notify Power Mgt is enabled in self-generated frames.
 * If requested, force chip awake.
 *
 * Returns A_OK if chip is awake or successfully forced awake.
 *
 * WARNING WARNING WARNING
 * There is a problem with the chip where sometimes it will not wake up.
 */
static HAL_BOOL
ar5416SetPowerModeAwake(struct ath_hal *ah, int setChip)
{
#define	POWER_UP_TIME	200000
	uint32_t val;
	int i = 0;

	if (setChip) {
		/*
		 * Do a Power-On-Reset if OWL is shutdown
		 * the NetBSD driver  power-cycles the Cardbus slot
		 * as part of the reset procedure.
		 */
		if ((OS_REG_READ(ah, AR_RTC_STATUS) 
			& AR_RTC_PM_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) {
			if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON))
				goto bad;			
			AH5416(ah)->ah_initPLL(ah, AH_NULL);
		}

		if (AR_SREV_HOWL(ah))
			OS_REG_SET_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN);

		OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
		if (AR_SREV_HOWL(ah))
			OS_DELAY(10000);
		else
			OS_DELAY(50);   /* Give chip the chance to awake */

		for (i = POWER_UP_TIME / 50; i != 0; i--) {
			val = OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
			if (val == AR_RTC_STATUS_ON)
				break;
			OS_DELAY(50);
			OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
		}		
	bad:
		if (i == 0) {
#ifdef AH_DEBUG
			ath_hal_printf(ah, "%s: Failed to wakeup in %ums\n",
				__func__, POWER_UP_TIME/1000);
#endif
			return AH_FALSE;
		}
	} 

	OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
	return AH_TRUE;
#undef POWER_UP_TIME
}
Ejemplo n.º 2
0
/*
 * Notify Power Mgt is enabled in self-generated frames.
 * If requested, force chip awake.
 *
 * Returns A_OK if chip is awake or successfully forced awake.
 *
 * WARNING WARNING WARNING
 * There is a problem with the chip where sometimes it will not wake up.
 */
HAL_BOOL
ar5416SetPowerModeAwake(struct ath_hal *ah, int set_chip)
{
#define POWER_UP_TIME   10000
    u_int32_t val;
    int i;


    if (set_chip) {
        /* Do a Power-On-Reset if OWL is shutdown */
        if ((OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) ==
                AR_RTC_STATUS_SHUTDOWN) {
            if (ar5416SetResetReg(ah, HAL_RESET_POWER_ON) != AH_TRUE) {
                HALASSERT(0);
                return AH_FALSE;
            }
            ar5416InitPLL(ah, AH_NULL);
        }

        if(AR_SREV_HOWL(ah)) /* HOWL needs this bit to set to wake up -was cleared in ar5416SetPowerModeSleep() */
            OS_REG_SET_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN);
        
        OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);

        if (AR_SREV_HOWL(ah)) {
           OS_DELAY(10000);   /* Give chip the chance to awake */
        } else {
           OS_DELAY(50);
        }

        for (i = POWER_UP_TIME / 50; i > 0; i--) {
            val = OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
            if (val == AR_RTC_STATUS_ON)
                break;
            OS_DELAY(50);
            OS_REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
        }
        if (i == 0) {
            HDPRINTF(ah, HAL_DBG_POWER_MGMT, "%s: Failed to wakeup in %uus\n",
                     __func__, POWER_UP_TIME/20);
            return AH_FALSE;
        }

    }

    OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
    return AH_TRUE;
#undef POWER_UP_TIME
}
Ejemplo n.º 3
0
/*
 * Notify Power Mgt is disabled in self-generated frames.
 * If requested, force chip to sleep.
 */
static void
ar5416SetPowerModeSleep(struct ath_hal *ah, int setChip)
{
	OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
	if (setChip) {
		/* Clear the RTC force wake bit to allow the mac to sleep */
		OS_REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN);
		if (! AR_SREV_HOWL(ah))
			OS_REG_WRITE(ah, AR_RC, AR_RC_AHB|AR_RC_HOSTIF);
		/* Shutdown chip. Active low */
		if (! AR_SREV_OWL(ah))
			OS_REG_CLR_BIT(ah, AR_RTC_RESET, AR_RTC_RESET_EN);
	}
}
Ejemplo n.º 4
0
/*
 * Checks to see if an interrupt is pending on our NIC
 *
 * Returns: TRUE    if an interrupt is pending
 *          FALSE   if not
 */
HAL_BOOL
ar5416IsInterruptPending(struct ath_hal *ah)
{
    uint32_t isr;

    if (AR_SREV_HOWL(ah))
        return AH_TRUE;

    /*
     * Some platforms trigger our ISR before applying power to
     * the card, so make sure the INTPEND is really 1, not 0xffffffff.
     */
    isr = OS_REG_READ(ah, AR_INTR_ASYNC_CAUSE);
    if (isr != AR_INTR_SPURIOUS && (isr & AR_INTR_MAC_IRQ) != 0)
        return AH_TRUE;

    isr = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE);
    if (isr != AR_INTR_SPURIOUS && (isr & AR_INTR_SYNC_DEFAULT))
        return AH_TRUE;

    return AH_FALSE;
}
Ejemplo n.º 5
0
static HAL_BOOL
ar2133SetChannel(struct ath_hal *ah,  HAL_CHANNEL_INTERNAL *chan)
{
    u_int32_t channelSel  = 0;
    u_int32_t bModeSynth  = 0;
    u_int32_t aModeRefSel = 0;
    u_int32_t reg32       = 0;
    u_int16_t freq;
    CHAN_CENTERS centers;

    OS_MARK(ah, AH_MARK_SETCHANNEL, chan->channel);

    ar5416GetChannelCenters(ah, chan, &centers);
    freq = centers.synth_center;

    if (freq < 4800) {
        u_int32_t txctl;

        if (((freq - 2192) % 5) == 0) {
            channelSel = ((freq - 672) * 2 - 3040)/10;
            bModeSynth = 0;
        } else if (((freq - 2224) % 5) == 0) {
            channelSel = ((freq - 704) * 2 - 3040) / 10;
            bModeSynth = 1;
        } else {
            HDPRINTF(ah, HAL_DBG_CHANNEL, "%s: invalid channel %u MHz\n",
                __func__, freq);
            return AH_FALSE;
        }

        channelSel = (channelSel << 2) & 0xff;
        channelSel = ath_hal_reverseBits(channelSel, 8);

        txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL);
        if (freq == 2484) {
            /* Enable channel spreading for channel 14 */
            OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
                txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
        } else {
            OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
                txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN);
        }

    } else if ((freq % 20) == 0 && freq >= 5120) {
        channelSel = ath_hal_reverseBits(
            ((freq - 4800) / 20 << 2), 8);
        if (AR_SREV_HOWL(ah) || AR_SREV_SOWL_10_OR_LATER(ah))
            aModeRefSel = ath_hal_reverseBits(3, 2);
        else
            aModeRefSel = ath_hal_reverseBits(1, 2);
    } else if ((freq % 10) == 0) {
        channelSel = ath_hal_reverseBits(
            ((freq - 4800) / 10 << 1), 8);
        if (AR_SREV_HOWL(ah) || AR_SREV_SOWL_10_OR_LATER(ah))
            aModeRefSel = ath_hal_reverseBits(2, 2);
        else
            aModeRefSel = ath_hal_reverseBits(1, 2);
    } else if ((freq % 5) == 0) {
        channelSel = ath_hal_reverseBits(
            (freq - 4800) / 5, 8);
        aModeRefSel = ath_hal_reverseBits(1, 2);
    } else {
        HDPRINTF(ah, HAL_DBG_CHANNEL, "%s: invalid channel %u MHz\n",
            __func__, freq);
        return AH_FALSE;
    }

#ifdef ATH_FORCE_BIAS
    /* FOWL orientation sensitivity workaround */
    ar5416ForceBiasCurrent(ah, freq);

    /*
     * Antenna Control with forceBias.
     * This function must be called after ar5416ForceBiasCurrent() and
     * ar5416SetRfRegs() and ar5416EepromSetBoardValues().
     */
    ar5416DecreaseChainPower(ah, (HAL_CHANNEL*)chan);
#endif

    reg32 = (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) |
            (1 << 5) | 0x1;

    OS_REG_WRITE(ah, AR_PHY(0x37), reg32);

    AH_PRIVATE(ah)->ah_curchan = chan;

#ifdef AH_SUPPORT_DFS
    if (chan->privFlags & CHANNEL_DFS) {
        struct ar5416RadarState *rs;
        u_int8_t index;

        rs = ar5416GetRadarChanState(ah, &index);
        if (rs != AH_NULL) {
            AH5416(ah)->ah_curchanRadIndex = (int16_t) index;
        } else {
            HDPRINTF(ah, HAL_DBG_DFS, "%s: Couldn't find radar state information\n",
                 __func__);
            return AH_FALSE;
        }
    } else
#endif
        AH5416(ah)->ah_curchanRadIndex = -1;

    return AH_TRUE;
}
Ejemplo n.º 6
0
/*
 * Reads the Interrupt Status Register value from the NIC, thus deasserting
 * the interrupt line, and returns both the masked and unmasked mapped ISR
 * values.  The value returned is mapped to abstract the hw-specific bit
 * locations in the Interrupt Status Register.
 *
 * (*masked) is cleared on initial call.
 *
 * Returns: A hardware-abstracted bitmap of all non-masked-out
 *          interrupts pending, as well as an unmasked value
 */
HAL_BOOL
ar5416GetPendingInterrupts(struct ath_hal *ah, HAL_INT *masked)
{
    uint32_t isr, isr0, isr1, sync_cause = 0, o_sync_cause = 0;
    HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;

#ifdef	AH_INTERRUPT_DEBUGGING
    /*
     * Blank the interrupt debugging area regardless.
     */
    bzero(&ah->ah_intrstate, sizeof(ah->ah_intrstate));
    ah->ah_syncstate = 0;
#endif

    /*
     * Verify there's a mac interrupt and the RTC is on.
     */
    if (AR_SREV_HOWL(ah)) {
        *masked = 0;
        isr = OS_REG_READ(ah, AR_ISR);
    } else {
        if ((OS_REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) &&
                (OS_REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) == AR_RTC_STATUS_ON)
            isr = OS_REG_READ(ah, AR_ISR);
        else
            isr = 0;
#ifdef	AH_INTERRUPT_DEBUGGING
        ah->ah_syncstate =
#endif
            o_sync_cause = sync_cause = OS_REG_READ(ah, AR_INTR_SYNC_CAUSE);
        sync_cause &= AR_INTR_SYNC_DEFAULT;
        *masked = 0;

        if (isr == 0 && sync_cause == 0)
            return AH_FALSE;
    }

#ifdef	AH_INTERRUPT_DEBUGGING
    ah->ah_intrstate[0] = isr;
    ah->ah_intrstate[1] = OS_REG_READ(ah, AR_ISR_S0);
    ah->ah_intrstate[2] = OS_REG_READ(ah, AR_ISR_S1);
    ah->ah_intrstate[3] = OS_REG_READ(ah, AR_ISR_S2);
    ah->ah_intrstate[4] = OS_REG_READ(ah, AR_ISR_S3);
    ah->ah_intrstate[5] = OS_REG_READ(ah, AR_ISR_S4);
    ah->ah_intrstate[6] = OS_REG_READ(ah, AR_ISR_S5);
#endif

    if (isr != 0) {
        struct ath_hal_5212 *ahp = AH5212(ah);
        uint32_t mask2;

        mask2 = 0;
        if (isr & AR_ISR_BCNMISC) {
            uint32_t isr2 = OS_REG_READ(ah, AR_ISR_S2);
            if (isr2 & AR_ISR_S2_TIM)
                mask2 |= HAL_INT_TIM;
            if (isr2 & AR_ISR_S2_DTIM)
                mask2 |= HAL_INT_DTIM;
            if (isr2 & AR_ISR_S2_DTIMSYNC)
                mask2 |= HAL_INT_DTIMSYNC;
            if (isr2 & (AR_ISR_S2_CABEND ))
                mask2 |= HAL_INT_CABEND;
            if (isr2 & AR_ISR_S2_GTT)
                mask2 |= HAL_INT_GTT;
            if (isr2 & AR_ISR_S2_CST)
                mask2 |= HAL_INT_CST;
            if (isr2 & AR_ISR_S2_TSFOOR)
                mask2 |= HAL_INT_TSFOOR;

            /*
             * Don't mask out AR_BCNMISC; instead mask
             * out what causes it.
             */
            OS_REG_WRITE(ah, AR_ISR_S2, isr2);
            isr &= ~AR_ISR_BCNMISC;
        }

        if (isr == 0xffffffff) {
            *masked = 0;
            return AH_FALSE;
        }

        *masked = isr & HAL_INT_COMMON;

        if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
            *masked |= HAL_INT_RX;
        if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM))
            *masked |= HAL_INT_TX;

        /*
         * When doing RX interrupt mitigation, the RXOK bit is set
         * in AR_ISR even if the relevant bit in AR_IMR is clear.
         * Since this interrupt may be due to another source, don't
         * just automatically set HAL_INT_RX if it's set, otherwise
         * we could prematurely service the RX queue.
         *
         * In some cases, the driver can even handle all the RX
         * frames just before the mitigation interrupt fires.
         * The subsequent RX processing trip will then end up
         * processing 0 frames.
         */
#ifdef	AH_AR5416_INTERRUPT_MITIGATION
        if (isr & AR_ISR_RXERR)
            *masked |= HAL_INT_RX;
#else
        if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
            *masked |= HAL_INT_RX;
#endif

        if (isr & (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
                   AR_ISR_TXEOL)) {
            *masked |= HAL_INT_TX;

            isr0 = OS_REG_READ(ah, AR_ISR_S0);
            OS_REG_WRITE(ah, AR_ISR_S0, isr0);
            isr1 = OS_REG_READ(ah, AR_ISR_S1);
            OS_REG_WRITE(ah, AR_ISR_S1, isr1);

            /*
             * Don't clear the primary ISR TX bits, clear
             * what causes them (S0/S1.)
             */
            isr &= ~(AR_ISR_TXOK | AR_ISR_TXDESC |
                     AR_ISR_TXERR | AR_ISR_TXEOL);

            ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXOK);
            ahp->ah_intrTxqs |= MS(isr0, AR_ISR_S0_QCU_TXDESC);
            ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXERR);
            ahp->ah_intrTxqs |= MS(isr1, AR_ISR_S1_QCU_TXEOL);
        }

        if ((isr & AR_ISR_GENTMR) || (! pCap->halAutoSleepSupport)) {
            uint32_t isr5;
            isr5 = OS_REG_READ(ah, AR_ISR_S5);
            OS_REG_WRITE(ah, AR_ISR_S5, isr5);
            isr &= ~AR_ISR_GENTMR;

            if (! pCap->halAutoSleepSupport)
                if (isr5 & AR_ISR_S5_TIM_TIMER)
                    *masked |= HAL_INT_TIM_TIMER;
        }
        *masked |= mask2;
    }

    /*
     * Since we're not using AR_ISR_RAC, clear the status bits
     * for handled interrupts here. For bits whose interrupt
     * source is a secondary register, those bits should've been
     * masked out - instead of those bits being written back,
     * their source (ie, the secondary status registers) should
     * be cleared. That way there are no race conditions with
     * new triggers coming in whilst they've been read/cleared.
     */
    OS_REG_WRITE(ah, AR_ISR, isr);
    /* Flush previous write */
    OS_REG_READ(ah, AR_ISR);

    if (AR_SREV_HOWL(ah))
        return AH_TRUE;

    if (sync_cause != 0) {
        HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: sync_cause=0x%x\n",
                 __func__,
                 o_sync_cause);
        if (sync_cause & (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) {
            *masked |= HAL_INT_FATAL;
        }
        if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
            HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RADM CPL timeout\n",
                     __func__);
            OS_REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
            OS_REG_WRITE(ah, AR_RC, 0);
            *masked |= HAL_INT_FATAL;
        }
        /*
         * On fatal errors collect ISR state for debugging.
         */
        if (*masked & HAL_INT_FATAL) {
            AH_PRIVATE(ah)->ah_fatalState[0] = isr;
            AH_PRIVATE(ah)->ah_fatalState[1] = sync_cause;
            HALDEBUG(ah, HAL_DEBUG_ANY,
                     "%s: fatal error, ISR_RAC 0x%x SYNC_CAUSE 0x%x\n",
                     __func__, isr, sync_cause);
        }

        OS_REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
        /* NB: flush write */
        (void) OS_REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
    }
    return AH_TRUE;
}
Ejemplo n.º 7
0
/*
 * Atomically enables NIC interrupts.  Interrupts are passed in
 * via the enumerated bitmask in ints.
 */
HAL_INT
ar5416SetInterrupts(struct ath_hal *ah, HAL_INT ints)
{
    struct ath_hal_5212 *ahp = AH5212(ah);
    uint32_t omask = ahp->ah_maskReg;
    uint32_t mask, mask2;

    HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: 0x%x => 0x%x\n",
             __func__, omask, ints);

    if (omask & HAL_INT_GLOBAL) {
        HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: disable IER\n", __func__);
        OS_REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
        (void) OS_REG_READ(ah, AR_IER);

        if (! AR_SREV_HOWL(ah)) {
            OS_REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
            (void) OS_REG_READ(ah, AR_INTR_ASYNC_ENABLE);

            OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
            (void) OS_REG_READ(ah, AR_INTR_SYNC_ENABLE);
        }
    }

    mask = ints & HAL_INT_COMMON;
    mask2 = 0;

#ifdef	AH_AR5416_INTERRUPT_MITIGATION
    /*
     * Overwrite default mask if Interrupt mitigation
     * is specified for AR5416
     */
    if (ints & HAL_INT_RX)
        mask |= AR_IMR_RXERR | AR_IMR_RXMINTR | AR_IMR_RXINTM;
#else
    if (ints & HAL_INT_RX)
        mask |= AR_IMR_RXOK | AR_IMR_RXERR | AR_IMR_RXDESC;
#endif
    if (ints & HAL_INT_TX) {
        if (ahp->ah_txOkInterruptMask)
            mask |= AR_IMR_TXOK;
        if (ahp->ah_txErrInterruptMask)
            mask |= AR_IMR_TXERR;
        if (ahp->ah_txDescInterruptMask)
            mask |= AR_IMR_TXDESC;
        if (ahp->ah_txEolInterruptMask)
            mask |= AR_IMR_TXEOL;
    }
    if (ints & (HAL_INT_BMISC)) {
        mask |= AR_IMR_BCNMISC;
        if (ints & HAL_INT_TIM)
            mask2 |= AR_IMR_S2_TIM;
        if (ints & HAL_INT_DTIM)
            mask2 |= AR_IMR_S2_DTIM;
        if (ints & HAL_INT_DTIMSYNC)
            mask2 |= AR_IMR_S2_DTIMSYNC;
        if (ints & HAL_INT_CABEND)
            mask2 |= (AR_IMR_S2_CABEND );
        if (ints & HAL_INT_CST)
            mask2 |= AR_IMR_S2_CST;
        if (ints & HAL_INT_TSFOOR)
            mask2 |= AR_IMR_S2_TSFOOR;
    }

    if (ints & (HAL_INT_GTT | HAL_INT_CST)) {
        mask |= AR_IMR_BCNMISC;
        if (ints & HAL_INT_GTT)
            mask2 |= AR_IMR_S2_GTT;
        if (ints & HAL_INT_CST)
            mask2 |= AR_IMR_S2_CST;
    }

    /* Write the new IMR and store off our SW copy. */
    HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: new IMR 0x%x\n", __func__, mask);
    OS_REG_WRITE(ah, AR_IMR, mask);
    mask = OS_REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM |
                                          AR_IMR_S2_DTIM |
                                          AR_IMR_S2_DTIMSYNC |
                                          AR_IMR_S2_CABEND |
                                          AR_IMR_S2_CABTO  |
                                          AR_IMR_S2_TSFOOR |
                                          AR_IMR_S2_GTT |
                                          AR_IMR_S2_CST);
    OS_REG_WRITE(ah, AR_IMR_S2, mask | mask2);

    ahp->ah_maskReg = ints;

    /* Re-enable interrupts if they were enabled before. */
    if (ints & HAL_INT_GLOBAL) {
        HALDEBUG(ah, HAL_DEBUG_INTERRUPT, "%s: enable IER\n", __func__);
        OS_REG_WRITE(ah, AR_IER, AR_IER_ENABLE);

        if (! AR_SREV_HOWL(ah)) {
            mask = AR_INTR_MAC_IRQ;
            if (ints & HAL_INT_GPIO)
                mask |= SM(AH5416(ah)->ah_gpioMask,
                           AR_INTR_ASYNC_MASK_GPIO);
            OS_REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, mask);
            OS_REG_WRITE(ah, AR_INTR_ASYNC_MASK, mask);

            mask = AR_INTR_SYNC_DEFAULT;
            if (ints & HAL_INT_GPIO)
                mask |= SM(AH5416(ah)->ah_gpioMask,
                           AR_INTR_SYNC_MASK_GPIO);
            OS_REG_WRITE(ah, AR_INTR_SYNC_ENABLE, mask);
            OS_REG_WRITE(ah, AR_INTR_SYNC_MASK, mask);
        }
    }

    return omask;
}
Ejemplo n.º 8
0
HAL_BOOL
ar5416InitCal(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
	struct ar5416PerCal *cal = &AH5416(ah)->ah_cal;
	HAL_CHANNEL_INTERNAL *ichan;

	ichan = ath_hal_checkchannel(ah, chan);
	HALASSERT(ichan != AH_NULL);

	/* Do initial chipset-specific calibration */
	if (! AH5416(ah)->ah_cal_initcal(ah, chan)) {
		HALDEBUG(ah, HAL_DEBUG_ANY,
		    "%s: initial chipset calibration did "
		    "not complete in time; noisy environment?\n", __func__);
		return AH_FALSE;
	}

	/* If there's PA Cal, do it */
	if (AH5416(ah)->ah_cal_pacal)
		AH5416(ah)->ah_cal_pacal(ah, AH_TRUE);

	/* 
	 * Do NF calibration after DC offset and other CALs.
	 * Per system engineers, noise floor value can sometimes be 20 dB
	 * higher than normal value if DC offset and noise floor cal are
	 * triggered at the same time.
	 */
	OS_REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);

	/*
	 * This may take a while to run; make sure subsequent
	 * calibration routines check that this has completed
	 * before reading the value and triggering a subsequent
	 * calibration.
	 */

	/* Initialize list pointers */
	cal->cal_list = cal->cal_last = cal->cal_curr = AH_NULL;

	/*
	 * Enable IQ, ADC Gain, ADC DC Offset Cals
	 */
	if (AR_SREV_HOWL(ah) || AR_SREV_SOWL_10_OR_LATER(ah)) {
		/* Setup all non-periodic, init time only calibrations */
		/* XXX: Init DC Offset not working yet */
#if 0
		if (ar5416IsCalSupp(ah, chan, ADC_DC_INIT_CAL)) {
			INIT_CAL(&cal->adcDcCalInitData);
			INSERT_CAL(cal, &cal->adcDcCalInitData);
		}
		/* Initialize current pointer to first element in list */
		cal->cal_curr = cal->cal_list;

		if (cal->ah_cal_curr != AH_NULL && !ar5416RunInitCals(ah, 0))
			return AH_FALSE;
#endif
	}

	/* If Cals are supported, add them to list via INIT/INSERT_CAL */
	if (ar5416IsCalSupp(ah, chan, ADC_GAIN_CAL)) {
		INIT_CAL(&cal->adcGainCalData);
		INSERT_CAL(cal, &cal->adcGainCalData);
		HALDEBUG(ah, HAL_DEBUG_PERCAL,
		    "%s: enable ADC Gain Calibration.\n", __func__);
	}
	if (ar5416IsCalSupp(ah, chan, ADC_DC_CAL)) {
		INIT_CAL(&cal->adcDcCalData);
		INSERT_CAL(cal, &cal->adcDcCalData);
		HALDEBUG(ah, HAL_DEBUG_PERCAL,
		    "%s: enable ADC DC Calibration.\n", __func__);
	}
	if (ar5416IsCalSupp(ah, chan, IQ_MISMATCH_CAL)) {
		INIT_CAL(&cal->iqCalData);
		INSERT_CAL(cal, &cal->iqCalData);
		HALDEBUG(ah, HAL_DEBUG_PERCAL,
		    "%s: enable IQ Calibration.\n", __func__);
	}
	/* Initialize current pointer to first element in list */
	cal->cal_curr = cal->cal_list;

	/* Kick off measurements for the first cal */
	if (cal->cal_curr != AH_NULL)
		ar5416ResetMeasurement(ah, cal->cal_curr);

	/* Mark all calibrations on this channel as being invalid */
	ichan->calValid = 0;

	return AH_TRUE;
#undef	MAX_CAL_CHECK
}
Ejemplo n.º 9
0
/*
 * Take the MHz channel value and set the Channel value
 *
 * ASSUMES: Writes enabled to analog bus
 */
static HAL_BOOL
ar2133SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
	uint32_t channelSel  = 0;
	uint32_t bModeSynth  = 0;
	uint32_t aModeRefSel = 0;
	uint32_t reg32       = 0;
	uint16_t freq;
	CHAN_CENTERS centers;
    
	OS_MARK(ah, AH_MARK_SETCHANNEL, chan->ic_freq);
    
	ar5416GetChannelCenters(ah, chan, &centers);
	freq = centers.synth_center;

	if (freq < 4800) {
		uint32_t txctl;

		if (((freq - 2192) % 5) == 0) {
			channelSel = ((freq - 672) * 2 - 3040)/10;
			bModeSynth = 0;
		} else if (((freq - 2224) % 5) == 0) {
			channelSel = ((freq - 704) * 2 - 3040) / 10;
			bModeSynth = 1;
		} else {
			HALDEBUG(ah, HAL_DEBUG_ANY,
			    "%s: invalid channel %u MHz\n", __func__, freq);
			return AH_FALSE;
		}

		channelSel = (channelSel << 2) & 0xff;
		channelSel = ath_hal_reverseBits(channelSel, 8);

		txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL);
		if (freq == 2484) {
			/* Enable channel spreading for channel 14 */
			OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
				txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
		} else {
			OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
 			txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN);
		}
	} else if ((freq % 20) == 0 && freq >= 5120) {
		channelSel = ath_hal_reverseBits(((freq - 4800) / 20 << 2), 8);
		if (AR_SREV_HOWL(ah) || AR_SREV_SOWL_10_OR_LATER(ah))
			aModeRefSel = ath_hal_reverseBits(3, 2);
		else
			aModeRefSel = ath_hal_reverseBits(1, 2);
	} else if ((freq % 10) == 0) {
		channelSel = ath_hal_reverseBits(((freq - 4800) / 10 << 1), 8);
		if (AR_SREV_HOWL(ah) || AR_SREV_SOWL_10_OR_LATER(ah))
			aModeRefSel = ath_hal_reverseBits(2, 2);
		else
			aModeRefSel = ath_hal_reverseBits(1, 2);
	} else if ((freq % 5) == 0) {
		channelSel = ath_hal_reverseBits((freq - 4800) / 5, 8);
		aModeRefSel = ath_hal_reverseBits(1, 2);
	} else {
		HALDEBUG(ah, HAL_DEBUG_ANY, "%s: invalid channel %u MHz\n",
		    __func__, freq);
		return AH_FALSE;
	}

	/* Workaround for hw bug - AR5416 specific */
	if (AR_SREV_OWL(ah) && ah->ah_config.ah_ar5416_biasadj)
		ar2133ForceBias(ah, freq);

	reg32 = (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) |
		(1 << 5) | 0x1;

	OS_REG_WRITE(ah, AR_PHY(0x37), reg32);

	AH_PRIVATE(ah)->ah_curchan = chan;
	return AH_TRUE;

}