int mt76_mac_start(struct mt76_dev *dev) { int i; for (i = 0; i < 16; i++) mt76_rr(dev, MT_TX_AGG_CNT(i)); for (i = 0; i < 16; i++) mt76_rr(dev, MT_TX_STAT_FIFO); memset(dev->aggr_stats, 0, sizeof(dev->aggr_stats)); mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX); wait_for_wpdma(dev); udelay(50); mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_EN | MT_WPDMA_GLO_CFG_RX_DMA_EN); mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE); mt76_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter); mt76_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX); mt76_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL | MT_INT_TX_STAT); return 0; }
static int mt76x2_efuse_read(struct mt76x2_dev *dev, u16 addr, u8 *data) { u32 val; int i; val = mt76_rr(dev, MT_EFUSE_CTRL); val &= ~(MT_EFUSE_CTRL_AIN | MT_EFUSE_CTRL_MODE); val |= MT76_SET(MT_EFUSE_CTRL_AIN, addr & ~0xf); val |= MT_EFUSE_CTRL_KICK; mt76_wr(dev, MT_EFUSE_CTRL, val); if (!mt76_poll(dev, MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000)) return -ETIMEDOUT; udelay(2); val = mt76_rr(dev, MT_EFUSE_CTRL); if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT) { memset(data, 0xff, 16); return 0; } for (i = 0; i < 4; i++) { val = mt76_rr(dev, MT_EFUSE_DATA(i)); put_unaligned_le32(val, data + 4 * i); } return 0; }
void mt76_mac_stop(struct mt76_dev *dev, bool force) { bool stopped = false; u32 rts_cfg; int i; mt76_wr(dev, MT_MAC_SYS_CTRL, 0); rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG); mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg & ~MT_TX_RTS_CFG_RETRY_LIMIT); /* Wait for MAC to become idle */ for (i = 0; i < 300; i++) { if (mt76_rr(dev, MT_MAC_STATUS) & (MT_MAC_STATUS_RX | MT_MAC_STATUS_TX)) continue; if (mt76_rr(dev, MT_BBP(IBI, 12))) continue; stopped = true; break; } if (force && !stopped) { mt76_set(dev, MT_BBP(CORE, 4), BIT(2)); mt76_clear(dev, MT_BBP(CORE, 4), BIT(2)); mt76_set(dev, MT_BBP(CORE, 4), BIT(1)); mt76_clear(dev, MT_BBP(CORE, 4), BIT(1)); } mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg); }
static int mt76x2_set_channel(struct mt76x2_dev *dev, struct cfg80211_chan_def *chandef) { int ret; cancel_delayed_work_sync(&dev->cal_work); set_bit(MT76_RESET, &dev->mt76.state); mt76_set_channel(&dev->mt76); tasklet_disable(&dev->pre_tbtt_tasklet); tasklet_disable(&dev->dfs_pd.dfs_tasklet); mt76x2_mac_stop(dev, true); ret = mt76x2_phy_set_channel(dev, chandef); /* channel cycle counters read-and-clear */ mt76_rr(dev, MT_CH_IDLE); mt76_rr(dev, MT_CH_BUSY); mt76x2_dfs_init_params(dev); mt76x2_mac_resume(dev); tasklet_enable(&dev->dfs_pd.dfs_tasklet); tasklet_enable(&dev->pre_tbtt_tasklet); clear_bit(MT76_RESET, &dev->mt76.state); mt76_txq_schedule_all(&dev->mt76); return ret; }
int mt76x2_mac_start(struct mt76x02_dev *dev) { int i; for (i = 0; i < 16; i++) mt76_rr(dev, MT_TX_AGG_CNT(i)); for (i = 0; i < 16; i++) mt76_rr(dev, MT_TX_STAT_FIFO); memset(dev->aggr_stats, 0, sizeof(dev->aggr_stats)); mt76x02_mac_start(dev); return 0; }
static int mt76_wmac_probe(struct platform_device *pdev) { struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); struct mt7603_dev *dev; void __iomem *mem_base; struct mt76_dev *mdev; int irq; int ret; irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "Failed to get device IRQ\n"); return irq; } mem_base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(mem_base)) { dev_err(&pdev->dev, "Failed to get memory resource\n"); return PTR_ERR(mem_base); } mdev = mt76_alloc_device(&pdev->dev, sizeof(*dev), &mt7603_ops, &mt7603_drv_ops); if (!mdev) return -ENOMEM; dev = container_of(mdev, struct mt7603_dev, mt76); mt76_mmio_init(mdev, mem_base); mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | (mt76_rr(dev, MT_HW_REV) & 0xff); dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev); ret = devm_request_irq(mdev->dev, irq, mt7603_irq_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (ret) goto error; ret = mt7603_register_device(dev); if (ret) goto error; return 0; error: ieee80211_free_hw(mt76_hw(dev)); return ret; }
void mt76x2_reset_wlan(struct mt76x02_dev *dev, bool enable) { u32 val; if (!enable) goto out; val = mt76_rr(dev, MT_WLAN_FUN_CTRL); val &= ~MT_WLAN_FUN_CTRL_FRC_WL_ANT_SEL; if (val & MT_WLAN_FUN_CTRL_WLAN_EN) { val |= MT_WLAN_FUN_CTRL_WLAN_RESET_RF; mt76_wr(dev, MT_WLAN_FUN_CTRL, val); udelay(20); val &= ~MT_WLAN_FUN_CTRL_WLAN_RESET_RF; } mt76_wr(dev, MT_WLAN_FUN_CTRL, val); udelay(20); out: mt76x2_set_wlan_state(dev, enable); }
void mt76x2_update_channel(struct mt76_dev *mdev) { struct mt76x2_dev *dev = container_of(mdev, struct mt76x2_dev, mt76); struct mt76_channel_state *state; u32 active, busy; state = mt76_channel_state(&dev->mt76, dev->mt76.chandef.chan); busy = mt76_rr(dev, MT_CH_BUSY); active = busy + mt76_rr(dev, MT_CH_IDLE); spin_lock_bh(&dev->mt76.cc_lock); state->cc_busy += busy; state->cc_active += active; spin_unlock_bh(&dev->mt76.cc_lock); }
static int mt76x2_init_hardware(struct mt76x02_dev *dev) { int ret; mt76x02_dma_disable(dev); mt76x2_reset_wlan(dev, true); mt76x2_power_on(dev); ret = mt76x2_eeprom_init(dev); if (ret) return ret; ret = mt76x2_mac_reset(dev, true); if (ret) return ret; dev->mt76.rxfilter = mt76_rr(dev, MT_RX_FILTR_CFG); ret = mt76x02_dma_init(dev); if (ret) return ret; set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state); ret = mt76x2_mac_start(dev); if (ret) return ret; ret = mt76x2_mcu_init(dev); if (ret) return ret; mt76x2_mac_stop(dev, false); return 0; }
static int mt76x2u_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(intf); struct mt76x02_dev *dev; int err; dev = mt76x2u_alloc_device(&intf->dev); if (!dev) return -ENOMEM; udev = usb_get_dev(udev); usb_reset_device(udev); mt76x02u_init_mcu(&dev->mt76); err = mt76u_init(&dev->mt76, intf); if (err < 0) goto err; dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION); dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev); err = mt76x2u_register_device(dev); if (err < 0) goto err; return 0; err: ieee80211_free_hw(mt76_hw(dev)); usb_set_intfdata(intf, NULL); usb_put_dev(udev); return err; }
void mt76x02_mac_wcid_sync_pn(struct mt76x02_dev *dev, u8 idx, struct ieee80211_key_conf *key) { enum mt76x02_cipher_type cipher; u8 key_data[32]; u32 iv, eiv; u64 pn; cipher = mt76x02_mac_get_key_info(key, key_data); iv = mt76_rr(dev, MT_WCID_IV(idx)); eiv = mt76_rr(dev, MT_WCID_IV(idx) + 4); pn = (u64)eiv << 16; if (cipher == MT_CIPHER_TKIP) { pn |= (iv >> 16) & 0xff; pn |= (iv & 0xff) << 8; } else if (cipher >= MT_CIPHER_AES_CCMP) {
static int mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct mt7603_dev *dev; int ret; ret = pcim_enable_device(pdev); if (ret) return ret; ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev)); if (ret) return ret; pci_set_master(pdev); ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (ret) return ret; dev = mt7603_alloc_device(&pdev->dev); if (!dev) return -ENOMEM; mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); pci_set_drvdata(pdev, dev); dev->mt76.rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) | (mt76_rr(dev, MT_HW_REV) & 0xff); dev_printk(KERN_INFO, dev->mt76.dev, "ASIC revision: %04x\n", dev->mt76.rev); ret = devm_request_irq(dev->mt76.dev, pdev->irq, mt7603_irq_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (ret) goto error; ret = mt7603_register_device(dev); if (ret) goto error; return 0; error: ieee80211_free_hw(mt76_hw(dev)); return ret; }
static void mt76x2_adjust_agc_gain(struct mt76x02_dev *dev, int reg, s8 offset) { s8 gain; gain = FIELD_GET(MT_BBP_AGC_GAIN, mt76_rr(dev, MT_BBP(AGC, reg))); gain += offset; mt76_rmw_field(dev, MT_BBP(AGC, reg), MT_BBP_AGC_GAIN, gain); }
static void mt76_adjust_lna_gain(struct mt76_dev *dev, int reg, s8 offset) { s8 gain; gain = MT76_GET(MT_BBP_AGC_LNA_GAIN, mt76_rr(dev, MT_BBP(AGC, reg))); gain -= offset / 2; mt76_rmw_field(dev, MT_BBP(AGC, reg), MT_BBP_AGC_LNA_GAIN, gain); }
static int __maybe_unused mt76_phy_rf_read(struct mt76_dev *dev, bool idx, u16 offset, u32 *val) { if (!mt76_phy_rf_op(dev, idx, offset, false)) return -ETIMEDOUT; *val = mt76_rr(dev, MT_RF_DATA_READ); return 0; }
static void mt76x2_adjust_high_lna_gain(struct mt76x02_dev *dev, int reg, s8 offset) { s8 gain; gain = FIELD_GET(MT_BBP_AGC_LNA_HIGH_GAIN, mt76_rr(dev, MT_BBP(AGC, reg))); gain -= offset / 2; mt76_rmw_field(dev, MT_BBP(AGC, reg), MT_BBP_AGC_LNA_HIGH_GAIN, gain); }
static int mt7603_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, const struct ieee80211_tx_queue_params *params) { struct mt7603_dev *dev = hw->priv; u16 cw_min = (1 << 5) - 1; u16 cw_max = (1 << 10) - 1; u32 val; queue = dev->mt76.q_tx[queue].hw_idx; if (params->cw_min) cw_min = params->cw_min; if (params->cw_max) cw_max = params->cw_max; mutex_lock(&dev->mutex); mt7603_mac_stop(dev); val = mt76_rr(dev, MT_WMM_TXOP(queue)); val &= ~(MT_WMM_TXOP_MASK << MT_WMM_TXOP_SHIFT(queue)); val |= params->txop << MT_WMM_TXOP_SHIFT(queue); mt76_wr(dev, MT_WMM_TXOP(queue), val); val = mt76_rr(dev, MT_WMM_AIFSN); val &= ~(MT_WMM_AIFSN_MASK << MT_WMM_AIFSN_SHIFT(queue)); val |= params->aifs << MT_WMM_AIFSN_SHIFT(queue); mt76_wr(dev, MT_WMM_AIFSN, val); val = mt76_rr(dev, MT_WMM_CWMIN); val &= ~(MT_WMM_CWMIN_MASK << MT_WMM_CWMIN_SHIFT(queue)); val |= cw_min << MT_WMM_CWMIN_SHIFT(queue); mt76_wr(dev, MT_WMM_CWMIN, val); val = mt76_rr(dev, MT_WMM_CWMAX(queue)); val &= ~(MT_WMM_CWMAX_MASK << MT_WMM_CWMAX_SHIFT(queue)); val |= cw_max << MT_WMM_CWMAX_SHIFT(queue); mt76_wr(dev, MT_WMM_CWMAX(queue), val); mt7603_mac_start(dev); mutex_unlock(&dev->mutex); return 0; }
static int mt76x2_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, const struct ieee80211_tx_queue_params *params) { struct mt76x2_dev *dev = hw->priv; u8 cw_min = 5, cw_max = 10, qid; u32 val; qid = dev->mt76.q_tx[queue].hw_idx; if (params->cw_min) cw_min = fls(params->cw_min); if (params->cw_max) cw_max = fls(params->cw_max); val = FIELD_PREP(MT_EDCA_CFG_TXOP, params->txop) | FIELD_PREP(MT_EDCA_CFG_AIFSN, params->aifs) | FIELD_PREP(MT_EDCA_CFG_CWMIN, cw_min) | FIELD_PREP(MT_EDCA_CFG_CWMAX, cw_max); mt76_wr(dev, MT_EDCA_CFG_AC(qid), val); val = mt76_rr(dev, MT_WMM_TXOP(qid)); val &= ~(MT_WMM_TXOP_MASK << MT_WMM_TXOP_SHIFT(qid)); val |= params->txop << MT_WMM_TXOP_SHIFT(qid); mt76_wr(dev, MT_WMM_TXOP(qid), val); val = mt76_rr(dev, MT_WMM_AIFSN); val &= ~(MT_WMM_AIFSN_MASK << MT_WMM_AIFSN_SHIFT(qid)); val |= params->aifs << MT_WMM_AIFSN_SHIFT(qid); mt76_wr(dev, MT_WMM_AIFSN, val); val = mt76_rr(dev, MT_WMM_CWMIN); val &= ~(MT_WMM_CWMIN_MASK << MT_WMM_CWMIN_SHIFT(qid)); val |= cw_min << MT_WMM_CWMIN_SHIFT(qid); mt76_wr(dev, MT_WMM_CWMIN, val); val = mt76_rr(dev, MT_WMM_CWMAX); val &= ~(MT_WMM_CWMAX_MASK << MT_WMM_CWMAX_SHIFT(qid)); val |= cw_max << MT_WMM_CWMAX_SHIFT(qid); mt76_wr(dev, MT_WMM_CWMAX, val); return 0; }
static int mt76pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct mt76x2_dev *dev; int ret; ret = pcim_enable_device(pdev); if (ret) return ret; ret = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev)); if (ret) return ret; pci_set_master(pdev); ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (ret) return ret; dev = mt76x2_alloc_device(&pdev->dev); if (!dev) return -ENOMEM; mt76_mmio_init(&dev->mt76, pcim_iomap_table(pdev)[0]); dev->mt76.rev = mt76_rr(dev, MT_ASIC_VERSION); dev_info(dev->mt76.dev, "ASIC revision: %08x\n", dev->mt76.rev); ret = devm_request_irq(dev->mt76.dev, pdev->irq, mt76x2_irq_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (ret) goto error; ret = mt76x2_register_device(dev); if (ret) goto error; /* Fix up ASPM configuration */ /* RG_SSUSB_G1_CDR_BIR_LTR = 0x9 */ mt76_rmw_field(dev, 0x15a10, 0x1f << 16, 0x9); /* RG_SSUSB_G1_CDR_BIC_LTR = 0xf */ mt76_rmw_field(dev, 0x15a0c, 0xf << 28, 0xf); /* RG_SSUSB_CDR_BR_PE1D = 0x3 */ mt76_rmw_field(dev, 0x15c58, 0x3 << 6, 0x3); return 0; error: ieee80211_free_hw(mt76_hw(dev)); return ret; }
irqreturn_t mt7603_irq_handler(int irq, void *dev_instance) { struct mt7603_dev *dev = dev_instance; u32 intr; intr = mt76_rr(dev, MT_INT_SOURCE_CSR); mt76_wr(dev, MT_INT_SOURCE_CSR, intr); if (!test_bit(MT76_STATE_INITIALIZED, &dev->mt76.state)) return IRQ_NONE; intr &= dev->mt76.mmio.irqmask; if (intr & MT_INT_MAC_IRQ3) { u32 hwintr = mt76_rr(dev, MT_HW_INT_STATUS(3)); mt76_wr(dev, MT_HW_INT_STATUS(3), hwintr); if (hwintr & MT_HW_INT3_PRE_TBTT0) tasklet_schedule(&dev->pre_tbtt_tasklet); if ((hwintr & MT_HW_INT3_TBTT0) && dev->mt76.csa_complete) mt76_csa_finish(&dev->mt76); } if (intr & MT_INT_TX_DONE_ALL) { mt7603_irq_disable(dev, MT_INT_TX_DONE_ALL); tasklet_schedule(&dev->tx_tasklet); } if (intr & MT_INT_RX_DONE(0)) { mt7603_irq_disable(dev, MT_INT_RX_DONE(0)); napi_schedule(&dev->mt76.napi[0]); } if (intr & MT_INT_RX_DONE(1)) { mt7603_irq_disable(dev, MT_INT_RX_DONE(1)); napi_schedule(&dev->mt76.napi[1]); } return IRQ_HANDLED; }
static int mt76_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, const struct ieee80211_tx_queue_params *params) { struct mt76_dev *dev = hw->priv; u8 cw_min = 5, cw_max = 10; u32 val; if (params->cw_min) cw_min = fls(params->cw_min); if (params->cw_max) cw_max = fls(params->cw_max); val = MT76_SET(MT_EDCA_CFG_TXOP, params->txop) | MT76_SET(MT_EDCA_CFG_AIFSN, params->aifs) | MT76_SET(MT_EDCA_CFG_CWMIN, cw_min) | MT76_SET(MT_EDCA_CFG_CWMAX, cw_max); mt76_wr(dev, MT_EDCA_CFG_AC(queue), val); val = mt76_rr(dev, MT_WMM_TXOP(queue)); val &= ~(MT_WMM_TXOP_MASK << MT_WMM_TXOP_SHIFT(queue)); val |= params->txop << MT_WMM_TXOP_SHIFT(queue); mt76_wr(dev, MT_WMM_TXOP(queue), val); val = mt76_rr(dev, MT_WMM_AIFSN); val &= ~(MT_WMM_AIFSN_MASK << MT_WMM_AIFSN_SHIFT(queue)); val |= params->aifs << MT_WMM_AIFSN_SHIFT(queue); mt76_wr(dev, MT_WMM_AIFSN, val); val = mt76_rr(dev, MT_WMM_CWMIN); val &= ~(MT_WMM_CWMIN_MASK << MT_WMM_CWMIN_SHIFT(queue)); val |= cw_min << MT_WMM_CWMIN_SHIFT(queue); mt76_wr(dev, MT_WMM_CWMIN, val); val = mt76_rr(dev, MT_WMM_CWMAX); val &= ~(MT_WMM_CWMAX_MASK << MT_WMM_CWMAX_SHIFT(queue)); val |= cw_max << MT_WMM_CWMAX_SHIFT(queue); mt76_wr(dev, MT_WMM_CWMAX, val); return 0; }
static void mt76_set_rx_chains(struct mt76_dev *dev) { u32 val; val = mt76_rr(dev, MT_BBP(AGC, 0)); val &= ~(BIT(3) | BIT(4)); if (dev->chainmask & BIT(1)) val |= BIT(3); mt76_wr(dev, MT_BBP(AGC, 0), val); }
static int __mt76x02u_mcu_fw_send_data(struct mt76x02_dev *dev, struct mt76u_buf *buf, const void *fw_data, int len, u32 dst_addr) { u8 *data = sg_virt(&buf->urb->sg[0]); DECLARE_COMPLETION_ONSTACK(cmpl); __le32 info; u32 val; int err; info = cpu_to_le32(FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) | FIELD_PREP(MT_MCU_MSG_LEN, len) | MT_MCU_MSG_TYPE_CMD); memcpy(data, &info, sizeof(info)); memcpy(data + sizeof(info), fw_data, len); memset(data + sizeof(info) + len, 0, 4); mt76u_single_wr(&dev->mt76, MT_VEND_WRITE_FCE, MT_FCE_DMA_ADDR, dst_addr); len = roundup(len, 4); mt76u_single_wr(&dev->mt76, MT_VEND_WRITE_FCE, MT_FCE_DMA_LEN, len << 16); buf->len = MT_CMD_HDR_LEN + len + sizeof(info); err = mt76u_submit_buf(&dev->mt76, USB_DIR_OUT, MT_EP_OUT_INBAND_CMD, buf, GFP_KERNEL, mt76u_mcu_complete_urb, &cmpl); if (err < 0) return err; if (!wait_for_completion_timeout(&cmpl, msecs_to_jiffies(1000))) { dev_err(dev->mt76.dev, "firmware upload timed out\n"); usb_kill_urb(buf->urb); return -ETIMEDOUT; } if (mt76u_urb_error(buf->urb)) { dev_err(dev->mt76.dev, "firmware upload failed: %d\n", buf->urb->status); return buf->urb->status; } val = mt76_rr(dev, MT_TX_CPU_FROM_FCE_CPU_DESC_IDX); val++; mt76_wr(dev, MT_TX_CPU_FROM_FCE_CPU_DESC_IDX, val); return 0; }
static void mt76_phy_update_channel_gain(struct mt76_dev *dev) { u32 val = mt76_rr(dev, MT_BBP(AGC, 20)); int rssi0 = (s8) MT76_GET(MT_BBP_AGC20_RSSI0, val); int rssi1 = (s8) MT76_GET(MT_BBP_AGC20_RSSI1, val); bool low_gain; u8 gain[2], gain_delta; dev->cal.avg_rssi[0] = (dev->cal.avg_rssi[0] * 15) / 16 + (rssi0 << 8); dev->cal.avg_rssi[1] = (dev->cal.avg_rssi[0] * 15) / 16 + (rssi1 << 8); dev->cal.avg_rssi_all = (dev->cal.avg_rssi[0] + dev->cal.avg_rssi[1]) / 512; low_gain = dev->cal.avg_rssi_all > mt76_get_rssi_gain_thresh(dev); if (dev->cal.low_gain == low_gain) return; dev->cal.low_gain = low_gain; if (dev->chandef.width >= NL80211_CHAN_WIDTH_40) val = 0x1e42 << 16; else val = 0x1836 << 16; mt76_get_agc_gain(dev, gain); val |= 0xf8; if (dev->chandef.width == NL80211_CHAN_WIDTH_80) mt76_wr(dev, MT_BBP(RXO, 14), 0x00560411); else mt76_wr(dev, MT_BBP(RXO, 14), 0x00560423); if (low_gain) { mt76_wr(dev, MT_BBP(AGC, 35), 0x08080808); mt76_wr(dev, MT_BBP(AGC, 37), 0x08080808); if (mt76_has_ext_lna(dev)) gain_delta = 10; else gain_delta = 14; } else { mt76_wr(dev, MT_BBP(AGC, 35), 0x11111116); mt76_wr(dev, MT_BBP(AGC, 37), 0x1010161C); gain_delta = 0; } mt76_wr(dev, MT_BBP(AGC, 8), val | MT76_SET(MT_BBP_AGC_GAIN, gain[0] - gain_delta)); mt76_wr(dev, MT_BBP(AGC, 9), val | MT76_SET(MT_BBP_AGC_GAIN, gain[1] - gain_delta)); }
void mt76x2_mac_stop(struct mt76x02_dev *dev, bool force) { bool stopped = false; u32 rts_cfg; int i; mt76_clear(dev, MT_TXOP_CTRL_CFG, MT_TXOP_ED_CCA_EN); mt76_clear(dev, MT_TXOP_HLDR_ET, MT_TXOP_HLDR_TX40M_BLK_EN); mt76_wr(dev, MT_MAC_SYS_CTRL, 0); rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG); mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg & ~MT_TX_RTS_CFG_RETRY_LIMIT); /* Wait for MAC to become idle */ for (i = 0; i < 300; i++) { if ((mt76_rr(dev, MT_MAC_STATUS) & (MT_MAC_STATUS_RX | MT_MAC_STATUS_TX)) || mt76_rr(dev, MT_BBP(IBI, 12))) { udelay(1); continue; } stopped = true; break; } if (force && !stopped) { mt76_set(dev, MT_BBP(CORE, 4), BIT(1)); mt76_clear(dev, MT_BBP(CORE, 4), BIT(1)); mt76_set(dev, MT_BBP(CORE, 4), BIT(0)); mt76_clear(dev, MT_BBP(CORE, 4), BIT(0)); } mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg); }
static void mt76x2u_mac_reset_counters(struct mt76x02_dev *dev) { mt76_rr(dev, MT_RX_STAT_0); mt76_rr(dev, MT_RX_STAT_1); mt76_rr(dev, MT_RX_STAT_2); mt76_rr(dev, MT_TX_STA_0); mt76_rr(dev, MT_TX_STA_1); mt76_rr(dev, MT_TX_STA_2); }
static void mt76_set_wlan_state(struct mt76_dev *dev, bool enable) { u32 val = mt76_rr(dev, MT_WLAN_FUN_CTRL); if (enable) val |= (MT_WLAN_FUN_CTRL_WLAN_EN | MT_WLAN_FUN_CTRL_WLAN_CLK_EN); else val &= ~(MT_WLAN_FUN_CTRL_WLAN_EN | MT_WLAN_FUN_CTRL_WLAN_CLK_EN); mt76_wr(dev, MT_WLAN_FUN_CTRL, val); udelay(20); }
void mt76x2_mac_work(struct work_struct *work) { struct mt76x2_dev *dev = container_of(work, struct mt76x2_dev, mac_work.work); int i, idx; mt76x2_update_channel(&dev->mt76); for (i = 0, idx = 0; i < 16; i++) { u32 val = mt76_rr(dev, MT_TX_AGG_CNT(i)); dev->aggr_stats[idx++] += val & 0xffff; dev->aggr_stats[idx++] += val >> 16; } ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mac_work, MT_CALIBRATE_INTERVAL); }
void mt76x2_phy_set_antenna(struct mt76x02_dev *dev) { u32 val; val = mt76_rr(dev, MT_BBP(AGC, 0)); val &= ~(BIT(4) | BIT(1)); switch (dev->mt76.antenna_mask) { case 1: /* disable mac DAC control */ mt76_clear(dev, MT_BBP(IBI, 9), BIT(11)); mt76_clear(dev, MT_BBP(TXBE, 5), 3); mt76_rmw_field(dev, MT_TX_PIN_CFG, MT_TX_PIN_CFG_TXANT, 0x3); mt76_rmw_field(dev, MT_BBP(CORE, 32), GENMASK(21, 20), 2); /* disable DAC 1 */ mt76_rmw_field(dev, MT_BBP(CORE, 33), GENMASK(12, 9), 4); val &= ~(BIT(3) | BIT(0)); break; case 2: /* disable mac DAC control */ mt76_clear(dev, MT_BBP(IBI, 9), BIT(11)); mt76_rmw_field(dev, MT_BBP(TXBE, 5), 3, 1); mt76_rmw_field(dev, MT_TX_PIN_CFG, MT_TX_PIN_CFG_TXANT, 0xc); mt76_rmw_field(dev, MT_BBP(CORE, 32), GENMASK(21, 20), 1); /* disable DAC 0 */ mt76_rmw_field(dev, MT_BBP(CORE, 33), GENMASK(12, 9), 1); val &= ~BIT(3); val |= BIT(0); break; case 3: default: /* enable mac DAC control */ mt76_set(dev, MT_BBP(IBI, 9), BIT(11)); mt76_set(dev, MT_BBP(TXBE, 5), 3); mt76_rmw_field(dev, MT_TX_PIN_CFG, MT_TX_PIN_CFG_TXANT, 0xf); mt76_clear(dev, MT_BBP(CORE, 32), GENMASK(21, 20)); mt76_clear(dev, MT_BBP(CORE, 33), GENMASK(12, 9)); val &= ~BIT(0); val |= BIT(3); break; } mt76_wr(dev, MT_BBP(AGC, 0), val); }
static bool mt76_wait_for_mac(struct mt76_dev *dev) { int i; for (i = 0; i < 500; i++) { switch (mt76_rr(dev, MT_MAC_CSR0)) { case 0: case ~0: break; default: return true; } msleep(5); } return false; }