int ar9380_set_synth(struct athn_softc *sc, struct ieee80211_channel *c, struct ieee80211_channel *extc) { uint32_t freq = c->ic_freq; uint32_t chansel, phy; if (IEEE80211_IS_CHAN_2GHZ(c)) { if (AR_SREV_9485(sc)) chansel = ((freq << 16) - 215) / 15; else chansel = (freq << 16) / 15; AR_WRITE(sc, AR_PHY_SYNTH_CONTROL, AR9380_BMODE); } else { chansel = (freq << 15) / 15; chansel >>= 1; AR_WRITE(sc, AR_PHY_SYNTH_CONTROL, 0); } /* Enable Long Shift Select for synthesizer. */ AR_SETBITS(sc, AR_PHY_65NM_CH0_SYNTH4, AR_PHY_SYNTH4_LONG_SHIFT_SELECT); AR_WRITE_BARRIER(sc); /* Program synthesizer. */ phy = (chansel << 2) | AR9380_FRACMODE; DPRINTFN(4, ("AR_PHY_65NM_CH0_SYNTH7=0x%08x\n", phy)); AR_WRITE(sc, AR_PHY_65NM_CH0_SYNTH7, phy); AR_WRITE_BARRIER(sc); /* Toggle Load Synth Channel bit. */ AR_WRITE(sc, AR_PHY_65NM_CH0_SYNTH7, phy | AR9380_LOAD_SYNTH); AR_WRITE_BARRIER(sc); return (0); }
static void ath_fill_led_pin(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; /* Set default led pin if invalid */ if (ah->led_pin < 0) { if (AR_SREV_9287(ah)) ah->led_pin = ATH_LED_PIN_9287; else if (AR_SREV_9485(ah)) ah->led_pin = ATH_LED_PIN_9485; else if (AR_SREV_9300(ah)) ah->led_pin = ATH_LED_PIN_9300; else if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) ah->led_pin = ATH_LED_PIN_9462; else ah->led_pin = ATH_LED_PIN_DEF; } /* Configure gpio for output */ ath9k_hw_gpio_request_out(ah, ah->led_pin, "ath9k-led", AR_GPIO_OUTPUT_MUX_AS_OUTPUT); /* LED off, active low */ ath9k_hw_set_gpio(ah, ah->led_pin, ah->config.led_active_high ? 0 : 1); }
int ar9380_attach(struct athn_softc *sc) { sc->ngpiopins = 17; sc->ops.setup = ar9380_setup; sc->ops.get_rom_template = ar9380_get_rom_template; sc->ops.swap_rom = ar9380_swap_rom; sc->ops.init_from_rom = ar9380_init_from_rom; sc->ops.set_txpower = ar9380_set_txpower; sc->ops.set_synth = ar9380_set_synth; sc->ops.spur_mitigate = ar9380_spur_mitigate; sc->ops.get_paprd_masks = ar9380_get_paprd_masks; sc->cca_min_2g = AR9380_PHY_CCA_MIN_GOOD_VAL_2GHZ; sc->cca_max_2g = AR9380_PHY_CCA_MAX_GOOD_VAL_2GHZ; sc->cca_min_5g = AR9380_PHY_CCA_MIN_GOOD_VAL_5GHZ; sc->cca_max_5g = AR9380_PHY_CCA_MAX_GOOD_VAL_5GHZ; if (AR_SREV_9485(sc)) { sc->ini = &ar9485_1_1_ini; sc->serdes = &ar9485_1_1_serdes; } else { sc->ini = &ar9380_2_2_ini; sc->serdes = &ar9380_2_2_serdes; } return (ar9003_attach(sc)); }
static void setup_ht_cap(struct ath_softc *sc, struct ieee80211_sta_ht_cap *ht_info) { struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); u8 tx_streams, rx_streams; int i, max_streams; ht_info->ht_supported = true; ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_SM_PS | IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_DSSSCCK40; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_LDPC) ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20) ht_info->cap |= IEEE80211_HT_CAP_SGI_20; ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) max_streams = 1; else if (AR_SREV_9462(ah)) max_streams = 2; else if (AR_SREV_9300_20_OR_LATER(ah)) max_streams = 3; else max_streams = 2; if (AR_SREV_9280_20_OR_LATER(ah)) { if (max_streams >= 2) ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); } /* set up supported mcs set */ memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); tx_streams = ath9k_cmn_count_streams(ah->txchainmask, max_streams); rx_streams = ath9k_cmn_count_streams(ah->rxchainmask, max_streams); ath_dbg(common, CONFIG, "TX streams %d, RX streams: %d\n", tx_streams, rx_streams); if (tx_streams != rx_streams) { ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; ht_info->mcs.tx_params |= ((tx_streams - 1) << IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); } for (i = 0; i < rx_streams; i++) ht_info->mcs.rx_mask[i] = 0xff; ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; }
void ath_hw_pll_work(struct work_struct *work) { struct ath_softc *sc = container_of(work, struct ath_softc, hw_pll_work.work); u32 pll_sqsum; if (AR_SREV_9485(sc->sc_ah)) { ath9k_ps_wakeup(sc); pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah); ath9k_ps_restore(sc); ath_hw_pll_rx_hang_check(sc, pll_sqsum); ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5); } }
/* * Set the ANI settings to match an CCK level. */ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel, bool scan) { struct ar5416AniState *aniState = &ah->ani; struct ath_common *common = ath9k_hw_common(ah); const struct ani_ofdm_level_entry *entry_ofdm; const struct ani_cck_level_entry *entry_cck; ath_dbg(common, ANI, "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", aniState->cckNoiseImmunityLevel, immunityLevel, BEACON_RSSI(ah), ATH9K_ANI_RSSI_THR_LOW, ATH9K_ANI_RSSI_THR_HIGH); if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_CCK_DEF_LEVEL) immunityLevel = ATH9K_ANI_CCK_DEF_LEVEL; if (ah->opmode == NL80211_IFTYPE_STATION && BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_LOW && immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI) immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI; if (!scan) aniState->cckNoiseImmunityLevel = immunityLevel; entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; if (aniState->firstepLevel != entry_cck->fir_step_level && entry_cck->fir_step_level >= entry_ofdm->fir_step_level) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, entry_cck->fir_step_level); /* Skip MRC CCK for pre AR9003 families */ if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah) || AR_SREV_9565(ah) || AR_SREV_9561(ah)) return; if (aniState->mrcCCK != entry_cck->mrc_cck_on) ath9k_hw_ani_control(ah, ATH9K_ANI_MRC_CCK, entry_cck->mrc_cck_on); }
void ath_init_leds(struct ath_softc *sc) { int ret; if (AR_SREV_9100(sc->sc_ah)) return; if (sc->sc_ah->led_pin < 0) { if (AR_SREV_9287(sc->sc_ah)) sc->sc_ah->led_pin = ATH_LED_PIN_9287; else if (AR_SREV_9485(sc->sc_ah)) sc->sc_ah->led_pin = ATH_LED_PIN_9485; else if (AR_SREV_9300(sc->sc_ah)) sc->sc_ah->led_pin = ATH_LED_PIN_9300; else if (AR_SREV_9462(sc->sc_ah)) sc->sc_ah->led_pin = ATH_LED_PIN_9462; else sc->sc_ah->led_pin = ATH_LED_PIN_DEF; } /* Configure gpio 1 for output */ ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); /* LED off, active low */ ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); if (!led_blink) sc->led_cdev.default_trigger = ieee80211_get_radio_led_name(sc->hw); snprintf(sc->led_name, sizeof(sc->led_name), "ath9k-%s", wiphy_name(sc->hw->wiphy)); sc->led_cdev.name = sc->led_name; sc->led_cdev.brightness_set = ath_led_brightness; ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev); if (ret < 0) return; sc->led_registered = true; }
/* * Set the ANI settings to match an CCK level. */ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel) { struct ar5416AniState *aniState = &ah->curchan->ani; struct ath_common *common = ath9k_hw_common(ah); const struct ani_ofdm_level_entry *entry_ofdm; const struct ani_cck_level_entry *entry_cck; aniState->noiseFloor = BEACON_RSSI(ah); ath_dbg(common, ATH_DBG_ANI, "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n", aniState->cckNoiseImmunityLevel, immunityLevel, aniState->noiseFloor, aniState->rssiThrLow, aniState->rssiThrHigh); if ((ah->opmode == NL80211_IFTYPE_STATION || ah->opmode == NL80211_IFTYPE_ADHOC) && aniState->noiseFloor <= aniState->rssiThrLow && immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI) immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI; if (aniState->update_ani) aniState->cckNoiseImmunityLevel = immunityLevel; entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel]; entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel]; if (aniState->firstepLevel != entry_cck->fir_step_level && entry_cck->fir_step_level >= entry_ofdm->fir_step_level) ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, entry_cck->fir_step_level); /* Skip MRC CCK for pre AR9003 families */ if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah)) return; if (aniState->mrcCCKOff == entry_cck->mrc_cck_on) ath9k_hw_ani_control(ah, ATH9K_ANI_MRC_CCK, entry_cck->mrc_cck_on); }
void ath_fill_led_pin(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; if (AR_SREV_9100(ah) || (ah->led_pin >= 0)) return; if (AR_SREV_9287(ah)) ah->led_pin = ATH_LED_PIN_9287; else if (AR_SREV_9485(sc->sc_ah)) ah->led_pin = ATH_LED_PIN_9485; else if (AR_SREV_9300(sc->sc_ah)) ah->led_pin = ATH_LED_PIN_9300; else if (AR_SREV_9462(sc->sc_ah) || AR_SREV_9565(sc->sc_ah)) ah->led_pin = ATH_LED_PIN_9462; else ah->led_pin = ATH_LED_PIN_DEF; /* Configure gpio 1 for output */ ath9k_hw_cfg_output(ah, ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); /* LED off, active low */ ath9k_hw_set_gpio(ah, ah->led_pin, 1); }
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); }
void ar9380_setup(struct athn_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; struct ar9380_eeprom *eep = sc->eep; struct ar9380_base_eep_hdr *base = &eep->baseEepHeader; uint8_t type; if (base->opFlags & AR_OPFLAGS_11A) sc->flags |= ATHN_FLAG_11A; if (base->opFlags & AR_OPFLAGS_11G) sc->flags |= ATHN_FLAG_11G; if (base->opFlags & AR_OPFLAGS_11N) sc->flags |= ATHN_FLAG_11N; IEEE80211_ADDR_COPY(ic->ic_myaddr, eep->macAddr); sc->led_pin = base->wlanLedGpio; /* Check if we have a hardware radio switch. */ if (base->rfSilent & AR_EEP_RFSILENT_ENABLED) { sc->flags |= ATHN_FLAG_RFSILENT; /* Get GPIO pin used by hardware radio switch. */ sc->rfsilent_pin = base->wlanDisableGpio; } /* Set the number of HW key cache entries. */ sc->kc_entries = AR_KEYTABLE_SIZE; sc->txchainmask = MS(base->txrxMask, AR_EEP_TX_MASK); sc->rxchainmask = MS(base->txrxMask, AR_EEP_RX_MASK); /* Fast PLL clock is always supported. */ sc->flags |= ATHN_FLAG_FAST_PLL_CLOCK; /* Enable PA predistortion if supported. */ if (base->featureEnable & AR_EEP_PAPRD) sc->flags |= ATHN_FLAG_PAPRD; /* * Some 3-stream chips may exceed the PCIe power requirements, * requiring to reduce the number of Tx chains in some cases. */ if ((base->miscConfiguration & AR_EEP_CHAIN_MASK_REDUCE) && sc->txchainmask == 0x7) sc->flags |= ATHN_FLAG_3TREDUCE_CHAIN; /* Select initialization values based on ROM. */ type = MS(eep->baseEepHeader.txrxgain, AR_EEP_RX_GAIN); if (!AR_SREV_9485(sc)) { if (type == AR_EEP_RX_GAIN_WO_XLNA) sc->rx_gain = &ar9380_2_2_rx_gain_wo_xlna; else sc->rx_gain = &ar9380_2_2_rx_gain; } else sc->rx_gain = &ar9485_1_0_rx_gain; /* Select initialization values based on ROM. */ type = MS(eep->baseEepHeader.txrxgain, AR_EEP_TX_GAIN); if (!AR_SREV_9485(sc)) { if (type == AR_EEP_TX_GAIN_HIGH_OB_DB) sc->tx_gain = &ar9380_2_2_tx_gain_high_ob_db; else if (type == AR_EEP_TX_GAIN_LOW_OB_DB) sc->tx_gain = &ar9380_2_2_tx_gain_low_ob_db; else if (type == AR_EEP_TX_GAIN_HIGH_POWER) sc->tx_gain = &ar9380_2_2_tx_gain_high_power; else sc->tx_gain = &ar9380_2_2_tx_gain; } else sc->tx_gain = &ar9485_1_0_tx_gain; }