int mt7601u_vendor_single_wr(struct mt7601u_dev *dev, const u8 req, const u16 offset, const u32 val) { int ret; ret = mt7601u_vendor_request(dev, req, USB_DIR_OUT, val & 0xffff, offset, NULL, 0); if (ret) return ret; return mt7601u_vendor_request(dev, req, USB_DIR_OUT, val >> 16, offset + 2, NULL, 0); }
static int mt7601u_upload_firmware(struct mt7601u_dev *dev, const struct mt76_fw *fw) { struct mt7601u_dma_buf dma_buf; void *ivb; u32 ilm_len, dlm_len; int i, ret; ivb = kmemdup(fw->ivb, sizeof(fw->ivb), GFP_KERNEL); if (!ivb || mt7601u_usb_alloc_buf(dev, MCU_FW_URB_SIZE, &dma_buf)) { ret = -ENOMEM; goto error; } ilm_len = le32_to_cpu(fw->hdr.ilm_len) - sizeof(fw->ivb); dev_dbg(dev->dev, "loading FW - ILM %u + IVB %zu\n", ilm_len, sizeof(fw->ivb)); ret = mt7601u_dma_fw(dev, &dma_buf, fw->ilm, ilm_len, sizeof(fw->ivb)); if (ret) goto error; dlm_len = le32_to_cpu(fw->hdr.dlm_len); dev_dbg(dev->dev, "loading FW - DLM %u\n", dlm_len); ret = mt7601u_dma_fw(dev, &dma_buf, fw->ilm + ilm_len, dlm_len, MT_MCU_DLM_OFFSET); if (ret) goto error; ret = mt7601u_vendor_request(dev, MT_VEND_DEV_MODE, USB_DIR_OUT, 0x12, 0, ivb, sizeof(fw->ivb)); if (ret < 0) goto error; ret = 0; for (i = 100; i && !firmware_running(dev); i--) msleep(10); if (!i) { ret = -ETIMEDOUT; goto error; } dev_dbg(dev->dev, "Firmware running!\n"); error: kfree(ivb); mt7601u_usb_free_buf(dev, &dma_buf); return ret; }
u32 mt7601u_rr(struct mt7601u_dev *dev, u32 offset) { int ret; __le32 reg; u32 val; WARN_ONCE(offset > USHRT_MAX, "read high off:%08x", offset); ret = mt7601u_vendor_request(dev, MT_VEND_MULTI_READ, USB_DIR_IN, 0, offset, ®, sizeof(reg)); val = le32_to_cpu(reg); if (ret > 0 && ret != sizeof(reg)) { dev_err(dev->dev, "Error: wrong size read:%d off:%08x\n", ret, offset); val = ~0; } trace_reg_read(dev, offset, val); return val; }
void mt7601u_vendor_reset(struct mt7601u_dev *dev) { mt7601u_vendor_request(dev, MT_VEND_DEV_MODE, USB_DIR_OUT, MT_VEND_DEV_MODE_RESET, 0, NULL, 0); }