int mt7601u_init_hardware(struct mt7601u_dev *dev) { static const u16 beacon_offsets[16] = { /* 512 byte per beacon */ 0xc000, 0xc200, 0xc400, 0xc600, 0xc800, 0xca00, 0xcc00, 0xce00, 0xd000, 0xd200, 0xd400, 0xd600, 0xd800, 0xda00, 0xdc00, 0xde00 }; int ret; dev->beacon_offsets = beacon_offsets; mt7601u_chip_onoff(dev, true, false); ret = mt7601u_wait_asic_ready(dev); if (ret) goto err; ret = mt7601u_mcu_init(dev); if (ret) goto err; if (!mt76_poll_msec(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_TX_DMA_BUSY | MT_WPDMA_GLO_CFG_RX_DMA_BUSY, 0, 100)) { ret = -EIO; goto err; } /* Wait for ASIC ready after FW load. */ ret = mt7601u_wait_asic_ready(dev); if (ret) goto err; mt7601u_reset_csr_bbp(dev); mt7601u_init_usb_dma(dev); ret = mt7601u_mcu_cmd_init(dev); if (ret) goto err; ret = mt7601u_dma_init(dev); if (ret) goto err_mcu; ret = mt7601u_write_mac_initvals(dev); if (ret) goto err_rx; if (!mt76_poll_msec(dev, MT_MAC_STATUS, MT_MAC_STATUS_TX | MT_MAC_STATUS_RX, 0, 100)) { ret = -EIO; goto err_rx; } ret = mt7601u_init_bbp(dev); if (ret) goto err_rx; ret = mt7601u_init_wcid_mem(dev); if (ret) goto err_rx; ret = mt7601u_init_key_mem(dev); if (ret) goto err_rx; ret = mt7601u_init_wcid_attr_mem(dev); if (ret) goto err_rx; 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)); mt7601u_reset_counters(dev); mt7601u_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e); mt7601u_wr(dev, MT_TXOP_CTRL_CFG, FIELD_PREP(MT_TXOP_TRUN_EN, 0x3f) | FIELD_PREP(MT_TXOP_EXT_CCA_DLY, 0x58)); ret = mt7601u_eeprom_init(dev); if (ret) goto err_rx; ret = mt7601u_phy_init(dev); if (ret) goto err_rx; mt7601u_set_rx_path(dev, 0); mt7601u_set_tx_dac(dev, 0); mt7601u_mac_set_ctrlch(dev, false); mt7601u_bbp_set_ctrlch(dev, false); mt7601u_bbp_set_bw(dev, MT_BW_20); return 0; err_rx: mt7601u_dma_cleanup(dev); err_mcu: mt7601u_mcu_cmd_deinit(dev); err: mt7601u_chip_onoff(dev, false, false); return ret; }
static int mt7601u_load_firmware(struct mt7601u_dev *dev) { const struct firmware *fw; const struct mt76_fw_header *hdr; int len, ret; u32 val; mt7601u_wr(dev, MT_USB_DMA_CFG, (MT_USB_DMA_CFG_RX_BULK_EN | MT_USB_DMA_CFG_TX_BULK_EN)); if (firmware_running(dev)) return 0; ret = request_firmware(&fw, MT7601U_FIRMWARE, dev->dev); if (ret) return ret; if (!fw || !fw->data || fw->size < sizeof(*hdr)) goto err_inv_fw; hdr = (const struct mt76_fw_header *) fw->data; if (le32_to_cpu(hdr->ilm_len) <= MT_MCU_IVB_SIZE) goto err_inv_fw; len = sizeof(*hdr); len += le32_to_cpu(hdr->ilm_len); len += le32_to_cpu(hdr->dlm_len); if (fw->size != len) goto err_inv_fw; val = le16_to_cpu(hdr->fw_ver); dev_info(dev->dev, "Firmware Version: %d.%d.%02d Build: %x Build time: %.16s\n", (val >> 12) & 0xf, (val >> 8) & 0xf, val & 0xf, le16_to_cpu(hdr->build_ver), hdr->build_time); len = le32_to_cpu(hdr->ilm_len); mt7601u_wr(dev, 0x94c, 0); mt7601u_wr(dev, MT_FCE_PSE_CTRL, 0); mt7601u_vendor_reset(dev); msleep(5); mt7601u_wr(dev, 0xa44, 0); mt7601u_wr(dev, 0x230, 0x84210); mt7601u_wr(dev, 0x400, 0x80c00); mt7601u_wr(dev, 0x800, 1); mt7601u_rmw(dev, MT_PBF_CFG, 0, (MT_PBF_CFG_TX0Q_EN | MT_PBF_CFG_TX1Q_EN | MT_PBF_CFG_TX2Q_EN | MT_PBF_CFG_TX3Q_EN)); mt7601u_wr(dev, MT_FCE_PSE_CTRL, 1); mt7601u_wr(dev, MT_USB_DMA_CFG, (MT_USB_DMA_CFG_RX_BULK_EN | MT_USB_DMA_CFG_TX_BULK_EN)); val = mt76_set(dev, MT_USB_DMA_CFG, MT_USB_DMA_CFG_TX_CLR); val &= ~MT_USB_DMA_CFG_TX_CLR; mt7601u_wr(dev, MT_USB_DMA_CFG, val); /* FCE tx_fs_base_ptr */ mt7601u_wr(dev, MT_TX_CPU_FROM_FCE_BASE_PTR, 0x400230); /* FCE tx_fs_max_cnt */ mt7601u_wr(dev, MT_TX_CPU_FROM_FCE_MAX_COUNT, 1); /* FCE pdma enable */ mt7601u_wr(dev, MT_FCE_PDMA_GLOBAL_CONF, 0x44); /* FCE skip_fs_en */ mt7601u_wr(dev, MT_FCE_SKIP_FS, 3); ret = mt7601u_upload_firmware(dev, (const struct mt76_fw *)fw->data); release_firmware(fw); return ret; err_inv_fw: dev_err(dev->dev, "Invalid firmware image\n"); release_firmware(fw); return -ENOENT; }