static void ar9003_hw_spur_ofdm(struct ath_hw *ah, int freq_offset, int spur_freq_sd, int spur_delta_phase, int spur_subchannel_sd) { int mask_index = 0; /* OFDM Spur mitigation */ REG_RMW_FIELD(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_SPUR_FILTER, 0x1); REG_RMW_FIELD(ah, AR_PHY_TIMING11, AR_PHY_TIMING11_SPUR_FREQ_SD, spur_freq_sd); REG_RMW_FIELD(ah, AR_PHY_TIMING11, AR_PHY_TIMING11_SPUR_DELTA_PHASE, spur_delta_phase); REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD, spur_subchannel_sd); REG_RMW_FIELD(ah, AR_PHY_TIMING11, AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC, 0x1); REG_RMW_FIELD(ah, AR_PHY_TIMING11, AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR, 0x1); REG_RMW_FIELD(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_SPUR_RSSI, 0x1); REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH, 34); REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 1); if (REG_READ_FIELD(ah, AR_PHY_MODE, AR_PHY_MODE_DYNAMIC) == 0x1) REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 1); mask_index = (freq_offset << 4) / 5; if (mask_index < 0) mask_index = mask_index - 1; mask_index = mask_index & 0x7f; REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_ENABLE_MASK_PPM, 0x1); REG_RMW_FIELD(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_PILOT_MASK, 0x1); REG_RMW_FIELD(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_ENABLE_CHAN_MASK, 0x1); REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK, AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A, mask_index); REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A, AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A, mask_index); REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK, AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A, mask_index); REG_RMW_FIELD(ah, AR_PHY_PILOT_SPUR_MASK, AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A, 0xc); REG_RMW_FIELD(ah, AR_PHY_CHAN_SPUR_MASK, AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A, 0xc); REG_RMW_FIELD(ah, AR_PHY_SPUR_MASK_A, AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A, 0xa0); REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_MASK_RATE_CNTL, 0xff); }
/* reset device */ void dwc_device_reset(dwc_dev_t *dev) { /* start reset */ REG_WRITE_FIELD(dev, DCTL, CSFTRST, 1); /* wait until done */ while(REG_READ_FIELD(dev, DCTL, CSFTRST)); }
static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah, struct ath9k_channel *chan, int freq_offset) { int spur_freq_sd = 0; int spur_subchannel_sd = 0; int spur_delta_phase = 0; if (IS_CHAN_HT40(chan)) { if (freq_offset < 0) { if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL, AR_PHY_GC_DYN2040_PRI_CH) == 0x0) spur_subchannel_sd = 1; else spur_subchannel_sd = 0; spur_freq_sd = ((freq_offset + 10) << 9) / 11; } else { if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL, AR_PHY_GC_DYN2040_PRI_CH) == 0x0) spur_subchannel_sd = 0; else spur_subchannel_sd = 1; spur_freq_sd = ((freq_offset - 10) << 9) / 11; } spur_delta_phase = (freq_offset << 17) / 5; } else { spur_subchannel_sd = 0; spur_freq_sd = (freq_offset << 9) /11; spur_delta_phase = (freq_offset << 18) / 5; } spur_freq_sd = spur_freq_sd & 0x3ff; spur_delta_phase = spur_delta_phase & 0xfffff; ar9003_hw_spur_ofdm(ah, freq_offset, spur_freq_sd, spur_delta_phase, spur_subchannel_sd); }
/* generic api to send device command */ static void dwc_device_cmd(dwc_dev_t *dev, dwc_device_cmd_t *cmd) { uint8_t active = REG_READ_FIELD(dev, DGCMD, CMDACT); ASSERT(active); REG_WRITE(dev, DGCMDPAR, cmd->param); REG_WRITE_FIELD(dev, DGCMD, CMDTYP, cmd->cmd); /* wait until active field is cleared. */ while(!REG_READ_FIELD(dev, DGCMD, CMDACT)); if(REG_READ_FIELD(dev, DGCMD, CMDSTATUS)) { ERR("\n\n device command failed. \n\n"); ASSERT(0); } }
/* Spur mitigation for OFDM */ static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah, struct ath9k_channel *chan) { int synth_freq; int range = 10; int freq_offset = 0; int mode; u8* spurChansPtr; unsigned int i; struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; if (IS_CHAN_5GHZ(chan)) { spurChansPtr = &(eep->modalHeader5G.spurChans[0]); mode = 0; } else { spurChansPtr = &(eep->modalHeader2G.spurChans[0]); mode = 1; } if (spurChansPtr[0] == 0) return; /* No spur in the mode */ if (IS_CHAN_HT40(chan)) { range = 19; if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL, AR_PHY_GC_DYN2040_PRI_CH) == 0x0) synth_freq = chan->channel - 10; else synth_freq = chan->channel + 10; } else { range = 10; synth_freq = chan->channel; } ar9003_hw_spur_ofdm_clear(ah); for (i = 0; spurChansPtr[i] && i < 5; i++) { freq_offset = FBIN2FREQ(spurChansPtr[i], mode) - synth_freq; if (abs(freq_offset) < range) { ar9003_hw_spur_ofdm_work(ah, chan, freq_offset); break; } } }
static void ar9003_hw_patch_rtt(struct ath_hw *ah, int index, int chain) { int agc, caldac; if (!test_bit(SW_PKDET_DONE, &ah->caldata->cal_flags)) return; if ((index != 5) || (chain >= 2)) return; agc = REG_READ_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), AR_PHY_65NM_RXRF_AGC_AGC_OVERRIDE); if (!agc) return; caldac = ah->caldata->caldac[chain]; ah->caldata->rtt_table[chain][index] &= 0xFFFF05FF; caldac = (caldac & 0x20) | ((caldac & 0x1F) << 7); ah->caldata->rtt_table[chain][index] |= (caldac << 4); }
static void ar9003_mci_prep_interface(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; u32 saved_mci_int_en; u32 mci_timeout = 150; mci->bt_state = MCI_BT_SLEEP; saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN); REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0); REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW)); REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, REG_READ(ah, AR_MCI_INTERRUPT_RAW)); ar9003_mci_remote_reset(ah, true); ar9003_mci_send_req_wake(ah, true); if (!ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500)) goto clear_redunt; mci->bt_state = MCI_BT_AWAKE; /* * we don't need to send more remote_reset at this moment. * If BT receive first remote_reset, then BT HW will * be cleaned up and will be able to receive req_wake * and BT HW will respond sys_waking. * In this case, WLAN will receive BT's HW sys_waking. * Otherwise, if BT SW missed initial remote_reset, * that remote_reset will still clean up BT MCI RX, * and the req_wake will wake BT up, * and BT SW will respond this req_wake with a remote_reset and * sys_waking. In this case, WLAN will receive BT's SW * sys_waking. In either case, BT's RX is cleaned up. So we * don't need to reply BT's remote_reset now, if any. * Similarly, if in any case, WLAN can receive BT's sys_waking, * that means WLAN's RX is also fine. */ ar9003_mci_send_sys_waking(ah, true); udelay(10); /* * Set BT priority interrupt value to be 0xff to * avoid having too many BT PRIORITY interrupts. */ REG_WRITE(ah, AR_MCI_BT_PRI0, 0xFFFFFFFF); REG_WRITE(ah, AR_MCI_BT_PRI1, 0xFFFFFFFF); REG_WRITE(ah, AR_MCI_BT_PRI2, 0xFFFFFFFF); REG_WRITE(ah, AR_MCI_BT_PRI3, 0xFFFFFFFF); REG_WRITE(ah, AR_MCI_BT_PRI, 0X000000FF); /* * A contention reset will be received after send out * sys_waking. Also BT priority interrupt bits will be set. * Clear those bits before the next step. */ REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, AR_MCI_INTERRUPT_RX_MSG_CONT_RST); REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_BT_PRI); if (mci->is_2g) { ar9003_mci_send_lna_transfer(ah, true); udelay(5); } if ((mci->is_2g && !mci->update_2g5g)) { if (ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, AR_MCI_INTERRUPT_RX_MSG_LNA_INFO, mci_timeout)) ath_dbg(common, MCI, "MCI WLAN has control over the LNA & BT obeys it\n"); else ath_dbg(common, MCI, "MCI BT didn't respond to LNA_TRANS\n"); } clear_redunt: /* Clear the extra redundant SYS_WAKING from BT */ if ((mci->bt_state == MCI_BT_AWAKE) && (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) && (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) == 0)) { REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING); REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE); } REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en); }
/* read the current connection speed. */ uint8_t dwc_connectspeed(dwc_dev_t *dev) { return REG_READ_FIELD(dev, DSTS, CONNECTSPD); }
/* is device running? */ uint8_t dwc_device_run_status(dwc_dev_t *dev) { return REG_READ_FIELD(dev, DCTL, RUN_STOP); }
static void ar9003_mci_prep_interface(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; u32 saved_mci_int_en; u32 mci_timeout = 150; mci->bt_state = MCI_BT_SLEEP; saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN); REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0); REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW)); REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, REG_READ(ah, AR_MCI_INTERRUPT_RAW)); ar9003_mci_remote_reset(ah, true); ar9003_mci_send_req_wake(ah, true); if (ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING, 500)) { mci->bt_state = MCI_BT_AWAKE; ar9003_mci_send_sys_waking(ah, true); udelay(10); REG_WRITE(ah, AR_MCI_BT_PRI0, 0xFFFFFFFF); REG_WRITE(ah, AR_MCI_BT_PRI1, 0xFFFFFFFF); REG_WRITE(ah, AR_MCI_BT_PRI2, 0xFFFFFFFF); REG_WRITE(ah, AR_MCI_BT_PRI3, 0xFFFFFFFF); REG_WRITE(ah, AR_MCI_BT_PRI, 0X000000FF); REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, AR_MCI_INTERRUPT_RX_MSG_CONT_RST); REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_BT_PRI); if (mci->is_2g) { ar9003_mci_send_lna_transfer(ah, true); udelay(5); } if ((mci->is_2g && !mci->update_2g5g)) { if (ar9003_mci_wait_for_interrupt(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, AR_MCI_INTERRUPT_RX_MSG_LNA_INFO, mci_timeout)) ath_dbg(common, MCI, "MCI WLAN has control over the LNA & BT obeys it\n"); else ath_dbg(common, MCI, "MCI BT didn't respond to LNA_TRANS\n"); } } if ((mci->bt_state == MCI_BT_AWAKE) && (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING)) && (REG_READ_FIELD(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, AR_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) == 0)) { REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW, AR_MCI_INTERRUPT_RX_MSG_SYS_WAKING); REG_WRITE(ah, AR_MCI_INTERRUPT_RAW, AR_MCI_INTERRUPT_REMOTE_SLEEP_UPDATE); } REG_WRITE(ah, AR_MCI_INTERRUPT_EN, saved_mci_int_en); }