static void ar9003_hw_rtt_load_hist_entry(struct ath_hw *ah, u8 chain, u32 index, u32 data28) { u32 val; val = SM(data28, AR_PHY_RTT_SW_RTT_TABLE_DATA); REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_1_B(chain), val); val = SM(0, AR_PHY_RTT_SW_RTT_TABLE_ACCESS) | SM(1, AR_PHY_RTT_SW_RTT_TABLE_WRITE) | SM(index, AR_PHY_RTT_SW_RTT_TABLE_ADDR); REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val); udelay(1); val |= SM(1, AR_PHY_RTT_SW_RTT_TABLE_ACCESS); REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val); udelay(1); if (!ath9k_hw_wait(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), AR_PHY_RTT_SW_RTT_TABLE_ACCESS, 0, RTT_ACCESS_TIMEOUT)) return; val &= ~SM(1, AR_PHY_RTT_SW_RTT_TABLE_WRITE); REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val); udelay(1); ath9k_hw_wait(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), AR_PHY_RTT_SW_RTT_TABLE_ACCESS, 0, RTT_ACCESS_TIMEOUT); }
/* * This can stop or re-enables RX. * * If bool is set this will kill any frame which is currently being * transferred between the MAC and baseband and also prevent any new * frames from getting started. */ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) { u32 reg; if (set) { REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, 0, AH_WAIT_TIMEOUT)) { REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); reg = REG_READ(ah, AR_OBS_BUS_1); ath_err(ath9k_hw_common(ah), "RX failed to go idle in 10 ms RXSM=0x%x\n", reg); return false; } } else { REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); } return true; }
static int ar9003_hw_rtt_fill_hist_entry(struct ath_hw *ah, u8 chain, u32 index) { u32 val; val = SM(0, AR_PHY_RTT_SW_RTT_TABLE_ACCESS) | SM(0, AR_PHY_RTT_SW_RTT_TABLE_WRITE) | SM(index, AR_PHY_RTT_SW_RTT_TABLE_ADDR); REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val); udelay(1); val |= SM(1, AR_PHY_RTT_SW_RTT_TABLE_ACCESS); REG_WRITE(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), val); udelay(1); if (!ath9k_hw_wait(ah, AR_PHY_RTT_TABLE_SW_INTF_B(chain), AR_PHY_RTT_SW_RTT_TABLE_ACCESS, 0, RTT_ACCESS_TIMEOUT)) return RTT_BAD_VALUE; val = MS(REG_READ(ah, AR_PHY_RTT_TABLE_SW_INTF_1_B(chain)), AR_PHY_RTT_SW_RTT_TABLE_DATA); return val; }
static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data) { struct ath_softc *sc = (struct ath_softc *) common->priv; struct ath9k_platform_data *pdata = sc->dev->platform_data; if (pdata) { if (off >= (ARRAY_SIZE(pdata->eeprom_data))) { ath_err(common, "%s: eeprom read failed, offset %08x is out of range\n", __func__, off); } *data = pdata->eeprom_data[off]; } else { struct ath_hw *ah = (struct ath_hw *) common->ah; common->ops->read(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); if (!ath9k_hw_wait(ah, AR_EEPROM_STATUS_DATA, AR_EEPROM_STATUS_DATA_BUSY | AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, AH_WAIT_TIMEOUT)) { return false; } *data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA), AR_EEPROM_STATUS_DATA_VAL); } return true; }
bool ar9003_hw_rtt_force_restore(struct ath_hw *ah) { if (!ath9k_hw_wait(ah, AR_PHY_RTT_CTRL, AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE, 0, RTT_RESTORE_TIMEOUT)) return false; REG_RMW_FIELD(ah, AR_PHY_RTT_CTRL, AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE, 1); if (!ath9k_hw_wait(ah, AR_PHY_RTT_CTRL, AR_PHY_RTT_CTRL_FORCE_RADIO_RESTORE, 0, RTT_RESTORE_TIMEOUT)) return false; return true; }
bool ath9k_hw_init_cal(struct ath_hal *ah, struct ath9k_channel *chan) { struct ath_hal_5416 *ahp = AH5416(ah); struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan); REG_WRITE(ah, AR_PHY_AGC_CONTROL, REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL); if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) { DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration failed to complete in 1ms; " "noisy environment?\n"); return false; } if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah)) ath9k_hw_9285_pa_cal(ah); REG_WRITE(ah, AR_PHY_AGC_CONTROL, REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL; if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { if (ath9k_hw_iscal_supported(ah, chan, ADC_GAIN_CAL)) { INIT_CAL(&ahp->ah_adcGainCalData); INSERT_CAL(ahp, &ahp->ah_adcGainCalData); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "enabling ADC Gain Calibration.\n"); } if (ath9k_hw_iscal_supported(ah, chan, ADC_DC_CAL)) { INIT_CAL(&ahp->ah_adcDcCalData); INSERT_CAL(ahp, &ahp->ah_adcDcCalData); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "enabling ADC DC Calibration.\n"); } if (ath9k_hw_iscal_supported(ah, chan, IQ_MISMATCH_CAL)) { INIT_CAL(&ahp->ah_iqCalData); INSERT_CAL(ahp, &ahp->ah_iqCalData); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "enabling IQ Calibration.\n"); } ahp->ah_cal_list_curr = ahp->ah_cal_list; if (ahp->ah_cal_list_curr) ath9k_hw_reset_calibration(ah, ahp->ah_cal_list_curr); } ichan->CalValid = 0; return true; }
static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) { REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); if (IS_CHAN_HT20(chan)) { REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset " "calibration failed to complete in " "1ms; noisy ??\n"); return false; } REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); } REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration " "failed to complete in 1ms; noisy ??\n"); return false; } REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); return true; }
static bool ath_pci_eeprom_read(struct ath_hw *ah, u32 off, u16 *data) { (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); if (!ath9k_hw_wait(ah, AR_EEPROM_STATUS_DATA, AR_EEPROM_STATUS_DATA_BUSY | AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, AH_WAIT_TIMEOUT)) { return false; } *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA), AR_EEPROM_STATUS_DATA_VAL); return true; }
static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data) { struct ath_hw *ah = (struct ath_hw *) common->ah; common->ops->read(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); if (!ath9k_hw_wait(ah, AR_EEPROM_STATUS_DATA, AR_EEPROM_STATUS_DATA_BUSY | AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, AH_WAIT_TIMEOUT)) { return false; } *data = MS(common->ops->read(ah, AR_EEPROM_STATUS_DATA), AR_EEPROM_STATUS_DATA_VAL); return true; }
bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) { if (AR_SREV_9285_12_OR_LATER(ah)) { if (!ar9285_clc(ah, chan)) return false; } else { if (AR_SREV_9280_10_OR_LATER(ah)) { if (!AR_SREV_9287_10_OR_LATER(ah)) REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); } /* Calibrate the AGC */ REG_WRITE(ah, AR_PHY_AGC_CONTROL, REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_CAL); /* Poll for offset calibration complete */ if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration failed to complete in 1ms; " "noisy environment?\n"); return false; } if (AR_SREV_9280_10_OR_LATER(ah)) { if (!AR_SREV_9287_10_OR_LATER(ah)) REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); } } /* Do PA Calibration */ if (AR_SREV_9285_11_OR_LATER(ah)) ath9k_hw_9285_pa_cal(ah, true); /* Do NF Calibration after DC offset and other calibrations */ REG_WRITE(ah, AR_PHY_AGC_CONTROL, REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; /* Enable IQ, ADC Gain and ADC DC offset CALs */ if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) { INIT_CAL(&ah->adcgain_caldata); INSERT_CAL(ah, &ah->adcgain_caldata); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "enabling ADC Gain Calibration.\n"); } if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { INIT_CAL(&ah->adcdc_caldata); INSERT_CAL(ah, &ah->adcdc_caldata); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "enabling ADC DC Calibration.\n"); } if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { INIT_CAL(&ah->iq_caldata); INSERT_CAL(ah, &ah->iq_caldata); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "enabling IQ Calibration.\n"); } ah->cal_list_curr = ah->cal_list; if (ah->cal_list_curr) ath9k_hw_reset_calibration(ah, ah->cal_list_curr); } chan->CalValid = 0; return true; }