int mt7601u_mac_start(struct mt7601u_dev *dev) { mt7601u_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX); if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY | MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 200000)) return -ETIMEDOUT; dev->rxfilter = MT_RX_FILTR_CFG_CRC_ERR | MT_RX_FILTR_CFG_PHY_ERR | MT_RX_FILTR_CFG_PROMISC | MT_RX_FILTR_CFG_VER_ERR | MT_RX_FILTR_CFG_DUP | MT_RX_FILTR_CFG_CFACK | MT_RX_FILTR_CFG_CFEND | MT_RX_FILTR_CFG_ACK | MT_RX_FILTR_CFG_CTS | MT_RX_FILTR_CFG_RTS | MT_RX_FILTR_CFG_PSPOLL | MT_RX_FILTR_CFG_BA | MT_RX_FILTR_CFG_CTRL_RSV; mt7601u_wr(dev, MT_RX_FILTR_CFG, dev->rxfilter); mt7601u_wr(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_TX | MT_MAC_SYS_CTRL_ENABLE_RX); if (!mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY | MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 50)) return -ETIMEDOUT; return 0; }
static void mt76_power_on(struct mt76_dev *dev) { u32 val; /* Turn on WL MTCMOS */ mt76_set(dev, MT_WLAN_MTC_CTRL, MT_WLAN_MTC_CTRL_MTCMOS_PWR_UP); val = MT_WLAN_MTC_CTRL_STATE_UP | MT_WLAN_MTC_CTRL_PWR_ACK | MT_WLAN_MTC_CTRL_PWR_ACK_S; mt76_poll(dev, MT_WLAN_MTC_CTRL, val, val, 1000); mt76_clear(dev, MT_WLAN_MTC_CTRL, 0x7f << 16); udelay(10); mt76_clear(dev, MT_WLAN_MTC_CTRL, 0xf << 24); udelay(10); mt76_set(dev, MT_WLAN_MTC_CTRL, 0xf << 24); mt76_clear(dev, MT_WLAN_MTC_CTRL, 0xfff); /* Turn on AD/DA power down */ mt76_clear(dev, 0x11204, BIT(3)); /* WLAN function enable */ mt76_set(dev, 0x10080, BIT(0)); /* Release BBP software reset */ mt76_clear(dev, 0x10064, BIT(18)); mt76_power_on_rf(dev, 0); mt76_power_on_rf(dev, 1); }
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; }
static void mt7601u_mac_stop_hw(struct mt7601u_dev *dev) { int i, ok; if (test_bit(MT7601U_STATE_REMOVED, &dev->state)) return; mt76_clear(dev, MT_BEACON_TIME_CFG, MT_BEACON_TIME_CFG_TIMER_EN | MT_BEACON_TIME_CFG_SYNC_MODE | MT_BEACON_TIME_CFG_TBTT_EN | MT_BEACON_TIME_CFG_BEACON_TX); if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_BUSY, 0, 1000)) dev_warn(dev->dev, "Warning: TX DMA did not stop!\n"); /* Page count on TxQ */ i = 200; while (i-- && ((mt76_rr(dev, 0x0438) & 0xffffffff) || (mt76_rr(dev, 0x0a30) & 0x000000ff) || (mt76_rr(dev, 0x0a34) & 0x00ff00ff))) msleep(10); if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_TX, 0, 1000)) dev_warn(dev->dev, "Warning: MAC TX did not stop!\n"); mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_RX | MT_MAC_SYS_CTRL_ENABLE_TX); /* Page count on RxQ */ ok = 0; i = 200; while (i--) { if ((mt76_rr(dev, 0x0430) & 0x00ff0000) || (mt76_rr(dev, 0x0a30) & 0xffffffff) || (mt76_rr(dev, 0x0a34) & 0xffffffff)) ok++; if (ok > 6) break; msleep(1); } if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_RX, 0, 1000)) dev_warn(dev->dev, "Warning: MAC RX did not stop!\n"); if (!mt76_poll(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_RX_BUSY, 0, 1000)) dev_warn(dev->dev, "Warning: RX DMA did not stop!\n"); }
static bool wait_for_wpdma(struct mt76_dev *dev) { return mt76_poll(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY | MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 1000); }
static bool mt76_phy_rf_op(struct mt76_dev *dev, bool idx, u16 offset, bool write) { u32 val = MT76_SET(MT_RF_CTRL_ADDR, offset); if (idx) val |= MT_RF_CTRL_IDX; if (write) val |= MT_RF_CTRL_WRITE; mt76_wr(dev, MT_RF_CTRL, val); return mt76_poll(dev, MT_RF_CTRL, MT_RF_CTRL_BUSY, 0, 2000); }
int mt76x2u_mac_stop(struct mt76x02_dev *dev) { int i, count = 0, val; bool stopped = false; u32 rts_cfg; if (test_bit(MT76_REMOVED, &dev->mt76.state)) return -EIO; rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG); mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg & ~MT_TX_RTS_CFG_RETRY_LIMIT); mt76_clear(dev, MT_TXOP_CTRL_CFG, BIT(20)); mt76_clear(dev, MT_TXOP_HLDR_ET, BIT(1)); /* wait tx dma to stop */ for (i = 0; i < 2000; i++) { val = mt76_rr(dev, MT_VEND_ADDR(CFG, MT_USB_U3DMA_CFG)); if (!(val & MT_USB_DMA_CFG_TX_BUSY) && i > 10) break; usleep_range(50, 100); } /* page count on TxQ */ for (i = 0; i < 200; i++) { if (!(mt76_rr(dev, 0x0438) & 0xffffffff) && !(mt76_rr(dev, 0x0a30) & 0x000000ff) && !(mt76_rr(dev, 0x0a34) & 0xff00ff00)) break; usleep_range(10, 20); } /* disable tx-rx */ mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_ENABLE_RX | MT_MAC_SYS_CTRL_ENABLE_TX); /* Wait for MAC to become idle */ for (i = 0; i < 1000; i++) { if (!(mt76_rr(dev, MT_MAC_STATUS) & MT_MAC_STATUS_TX) && !mt76_rr(dev, MT_BBP(IBI, 12))) { stopped = true; break; } usleep_range(10, 20); } if (!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)); } /* page count on RxQ */ for (i = 0; i < 200; i++) { if (!(mt76_rr(dev, 0x0430) & 0x00ff0000) && !(mt76_rr(dev, 0x0a30) & 0xffffffff) && !(mt76_rr(dev, 0x0a34) & 0xffffffff) && ++count > 10) break; msleep(50); } if (!mt76_poll(dev, MT_MAC_STATUS, MT_MAC_STATUS_RX, 0, 2000)) dev_warn(dev->mt76.dev, "MAC RX failed to stop\n"); /* wait rx dma to stop */ for (i = 0; i < 2000; i++) { val = mt76_rr(dev, MT_VEND_ADDR(CFG, MT_USB_U3DMA_CFG)); if (!(val & MT_USB_DMA_CFG_RX_BUSY) && i > 10) break; usleep_range(50, 100); } mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg); return 0; }
static int mt76pci_load_rom_patch(struct mt76x02_dev *dev) { const struct firmware *fw = NULL; struct mt76x02_patch_header *hdr; bool rom_protect = !is_mt7612(dev); int len, ret = 0; __le32 *cur; u32 patch_mask, patch_reg; if (rom_protect && !mt76_poll(dev, MT_MCU_SEMAPHORE_03, 1, 1, 600)) { dev_err(dev->mt76.dev, "Could not get hardware semaphore for ROM PATCH\n"); return -ETIMEDOUT; } if (mt76xx_rev(dev) >= MT76XX_REV_E3) { patch_mask = BIT(0); patch_reg = MT_MCU_CLOCK_CTL; } else { patch_mask = BIT(1); patch_reg = MT_MCU_COM_REG0; } if (rom_protect && (mt76_rr(dev, patch_reg) & patch_mask)) { dev_info(dev->mt76.dev, "ROM patch already applied\n"); goto out; } ret = request_firmware(&fw, MT7662_ROM_PATCH, dev->mt76.dev); if (ret) goto out; if (!fw || !fw->data || fw->size <= sizeof(*hdr)) { ret = -EIO; dev_err(dev->mt76.dev, "Failed to load firmware\n"); goto out; } hdr = (struct mt76x02_patch_header *)fw->data; dev_info(dev->mt76.dev, "ROM patch build: %.15s\n", hdr->build_time); mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, MT_MCU_ROM_PATCH_OFFSET); cur = (__le32 *) (fw->data + sizeof(*hdr)); len = fw->size - sizeof(*hdr); mt76_wr_copy(dev, MT_MCU_ROM_PATCH_ADDR, cur, len); mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, 0); /* Trigger ROM */ mt76_wr(dev, MT_MCU_INT_LEVEL, 4); if (!mt76_poll_msec(dev, patch_reg, patch_mask, patch_mask, 2000)) { dev_err(dev->mt76.dev, "Failed to load ROM patch\n"); ret = -ETIMEDOUT; } out: /* release semaphore */ if (rom_protect) mt76_wr(dev, MT_MCU_SEMAPHORE_03, 1); release_firmware(fw); return ret; }