static void ar9300_force_agc_gain(struct ath_hal *ah) { struct ath_hal_9300 *ahp = AH9300(ah); int i; static const struct { int rxtx1, rxtx2; } chn_reg[AR9300_MAX_CHAINS] = { {AR_PHY_65NM_CH0_RXTX1, AR_PHY_65NM_CH0_RXTX2}, {AR_PHY_65NM_CH1_RXTX1, AR_PHY_65NM_CH1_RXTX2}, {AR_PHY_65NM_CH2_RXTX1, AR_PHY_65NM_CH2_RXTX2} }; /* * for Osprey 1.0, force Rx gain through long shift (analog) interface * this works for Osprey 2.0 too * TODO: for Osprey 2.0, we can set gain via baseband registers */ for (i = 0; i < AR9300_MAX_CHAINS; i++) { if (ahp->ah_rx_chainmask & (1 << i)) { if (AH_PRIVATE(ah)->ah_curchan != NULL && IS_CHAN_2GHZ(AH_PRIVATE(ah)->ah_curchan)) { // For 2G band: OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, AR_PHY_RX1DB_BIQUAD_LONG_SHIFT, 0x1); // 10db=3 OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, AR_PHY_RX6DB_BIQUAD_LONG_SHIFT, 0x2); // 10db=2 OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, AR_PHY_LNAGAIN_LONG_SHIFT, 0x7); // 10db=6 OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, AR_PHY_MXRGAIN_LONG_SHIFT, 0x3); // 10db=3 OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, AR_PHY_VGAGAIN_LONG_SHIFT, 0x0); // 10db=0 OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx1, AR_PHY_SCFIR_GAIN_LONG_SHIFT, 0x1); // 10db=1 OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx1, AR_PHY_MANRXGAIN_LONG_SHIFT, 0x1); // 10db=1 /* force external LNA on to disable strong signal mechanism */ OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN(i), AR_PHY_SWITCH_TABLE_R0, 0x1); OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN(i), AR_PHY_SWITCH_TABLE_R1, 0x1); OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN(i), AR_PHY_SWITCH_TABLE_R12, 0x1); } else { // For 5G band: OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, AR_PHY_RX1DB_BIQUAD_LONG_SHIFT, 0x2); // was 3=10/15db, // 2=+1db OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, AR_PHY_RX6DB_BIQUAD_LONG_SHIFT, 0x2); // was 1 OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, AR_PHY_LNAGAIN_LONG_SHIFT, 0x7); OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, AR_PHY_MXRGAIN_LONG_SHIFT, 0x3); // was 2=15db, 3=10db OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx2, AR_PHY_VGAGAIN_LONG_SHIFT, 0x6); OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx1, AR_PHY_SCFIR_GAIN_LONG_SHIFT, 0x1); OS_REG_RMW_FIELD(ah, chn_reg[i].rxtx1, AR_PHY_MANRXGAIN_LONG_SHIFT, 0x1); /* force external LNA on to disable strong signal mechanism */ OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN(i), AR_PHY_SWITCH_TABLE_R0, 0x0); OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN(i), AR_PHY_SWITCH_TABLE_R1, 0x0); OS_REG_RMW_FIELD(ah, AR_PHY_SWITCH_CHAIN(i), AR_PHY_SWITCH_TABLE_R12, 0x0); } } } }
void ar9380_init_from_rom(struct athn_softc *sc, struct ieee80211_channel *c, struct ieee80211_channel *extc) { const struct ar9380_eeprom *eep = sc->eep; const struct ar9380_modal_eep_header *modal; uint8_t db, margin, ant_div_ctrl; uint32_t reg; int i, maxchains; if (IEEE80211_IS_CHAN_2GHZ(c)) modal = &eep->modalHeader2G; else modal = &eep->modalHeader5G; /* Apply XPA bias level. */ if (AR_SREV_9485(sc)) { reg = AR_READ(sc, AR9485_PHY_65NM_CH0_TOP2); reg = RW(reg, AR9485_PHY_65NM_CH0_TOP2_XPABIASLVL, modal->xpaBiasLvl); AR_WRITE(sc, AR9485_PHY_65NM_CH0_TOP2, reg); } else { reg = AR_READ(sc, AR_PHY_65NM_CH0_TOP); reg = RW(reg, AR_PHY_65NM_CH0_TOP_XPABIASLVL, modal->xpaBiasLvl & 0x3); AR_WRITE(sc, AR_PHY_65NM_CH0_TOP, reg); reg = AR_READ(sc, AR_PHY_65NM_CH0_THERM); reg = RW(reg, AR_PHY_65NM_CH0_THERM_XPABIASLVL_MSB, modal->xpaBiasLvl >> 2); reg |= AR_PHY_65NM_CH0_THERM_XPASHORT2GND; AR_WRITE(sc, AR_PHY_65NM_CH0_THERM, reg); } /* Apply antenna control. */ reg = AR_READ(sc, AR_PHY_SWITCH_COM); reg = RW(reg, AR_SWITCH_TABLE_COM_ALL, modal->antCtrlCommon); AR_WRITE(sc, AR_PHY_SWITCH_COM, reg); reg = AR_READ(sc, AR_PHY_SWITCH_COM_2); reg = RW(reg, AR_SWITCH_TABLE_COM_2_ALL, modal->antCtrlCommon2); AR_WRITE(sc, AR_PHY_SWITCH_COM_2, reg); maxchains = AR_SREV_9485(sc) ? 1 : AR9380_MAX_CHAINS; for (i = 0; i < maxchains; i++) { reg = AR_READ(sc, AR_PHY_SWITCH_CHAIN(i)); reg = RW(reg, AR_SWITCH_TABLE_ALL, modal->antCtrlChain[i]); AR_WRITE(sc, AR_PHY_SWITCH_CHAIN(i), reg); } if (AR_SREV_9485(sc)) { ant_div_ctrl = eep->base_ext1.ant_div_control; reg = AR_READ(sc, AR_PHY_MC_GAIN_CTRL); reg = RW(reg, AR_PHY_MC_GAIN_CTRL_ANT_DIV_CTRL_ALL, MS(ant_div_ctrl, AR_EEP_ANT_DIV_CTRL_ALL)); if (ant_div_ctrl & AR_EEP_ANT_DIV_CTRL_ANT_DIV) reg |= AR_PHY_MC_GAIN_CTRL_ENABLE_ANT_DIV; else reg &= ~AR_PHY_MC_GAIN_CTRL_ENABLE_ANT_DIV; AR_WRITE(sc, AR_PHY_MC_GAIN_CTRL, reg); reg = AR_READ(sc, AR_PHY_CCK_DETECT); if (ant_div_ctrl & AR_EEP_ANT_DIV_CTRL_FAST_DIV) reg |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; else reg &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; AR_WRITE(sc, AR_PHY_CCK_DETECT, reg); } if (eep->baseEepHeader.miscConfiguration & AR_EEP_DRIVE_STRENGTH) { /* Apply drive strength. */ reg = AR_READ(sc, AR_PHY_65NM_CH0_BIAS1); reg = RW(reg, AR_PHY_65NM_CH0_BIAS1_0, 5); reg = RW(reg, AR_PHY_65NM_CH0_BIAS1_1, 5); reg = RW(reg, AR_PHY_65NM_CH0_BIAS1_2, 5); reg = RW(reg, AR_PHY_65NM_CH0_BIAS1_3, 5); reg = RW(reg, AR_PHY_65NM_CH0_BIAS1_4, 5); reg = RW(reg, AR_PHY_65NM_CH0_BIAS1_5, 5); AR_WRITE(sc, AR_PHY_65NM_CH0_BIAS1, reg); reg = AR_READ(sc, AR_PHY_65NM_CH0_BIAS2); reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_0, 5); reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_1, 5); reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_2, 5); reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_3, 5); reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_4, 5); reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_5, 5); reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_6, 5); reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_7, 5); reg = RW(reg, AR_PHY_65NM_CH0_BIAS2_8, 5); AR_WRITE(sc, AR_PHY_65NM_CH0_BIAS2, reg); reg = AR_READ(sc, AR_PHY_65NM_CH0_BIAS4); reg = RW(reg, AR_PHY_65NM_CH0_BIAS4_0, 5); reg = RW(reg, AR_PHY_65NM_CH0_BIAS4_1, 5); reg = RW(reg, AR_PHY_65NM_CH0_BIAS4_2, 5); AR_WRITE(sc, AR_PHY_65NM_CH0_BIAS4, reg); } /* Apply attenuation settings. */ maxchains = AR_SREV_9485(sc) ? 1 : AR9380_MAX_CHAINS; for (i = 0; i < maxchains; i++) { if (IEEE80211_IS_CHAN_5GHZ(c) && eep->base_ext2.xatten1DBLow[i] != 0) { if (c->ic_freq <= 5500) { db = athn_interpolate(c->ic_freq, 5180, eep->base_ext2.xatten1DBLow[i], 5500, modal->xatten1DB[i]); } else { db = athn_interpolate(c->ic_freq, 5500, modal->xatten1DB[i], 5785, eep->base_ext2.xatten1DBHigh[i]); } } else db = modal->xatten1DB[i]; if (IEEE80211_IS_CHAN_5GHZ(c) && eep->base_ext2.xatten1MarginLow[i] != 0) { if (c->ic_freq <= 5500) { margin = athn_interpolate(c->ic_freq, 5180, eep->base_ext2.xatten1MarginLow[i], 5500, modal->xatten1Margin[i]); } else { margin = athn_interpolate(c->ic_freq, 5500, modal->xatten1Margin[i], 5785, eep->base_ext2.xatten1MarginHigh[i]); } } else margin = modal->xatten1Margin[i]; reg = AR_READ(sc, AR_PHY_EXT_ATTEN_CTL(i)); reg = RW(reg, AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB, db); reg = RW(reg, AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN, margin); AR_WRITE(sc, AR_PHY_EXT_ATTEN_CTL(i), reg); } /* Initialize switching regulator. */ if (AR_SREV_9485(sc)) ar9485_init_swreg(sc); else ar9485_init_swreg(sc); /* Apply tuning capabilities. */ if (AR_SREV_9485(sc) && (eep->baseEepHeader.featureEnable & AR_EEP_TUNING_CAPS)) { reg = AR_READ(sc, AR9485_PHY_CH0_XTAL); reg = RW(reg, AR9485_PHY_CH0_XTAL_CAPINDAC, eep->baseEepHeader.params_for_tuning_caps[0]); reg = RW(reg, AR9485_PHY_CH0_XTAL_CAPOUTDAC, eep->baseEepHeader.params_for_tuning_caps[0]); AR_WRITE(sc, AR9485_PHY_CH0_XTAL, reg); } AR_WRITE_BARRIER(sc); }