drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c
Extension
.c
Size
6375 bytes
Lines
256
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
 */

#include <linux/firmware.h>

#include "mt76x2u.h"
#include "eeprom.h"
#include "../mt76x02_usb.h"

#define MT_CMD_HDR_LEN			4

#define MCU_FW_URB_MAX_PAYLOAD		0x3900
#define MCU_ROM_PATCH_MAX_PAYLOAD	2048

#define MT76U_MCU_ILM_OFFSET		0x80000
#define MT76U_MCU_DLM_OFFSET		0x110000
#define MT76U_MCU_ROM_PATCH_OFFSET	0x90000

static void mt76x2u_mcu_load_ivb(struct mt76x02_dev *dev)
{
	mt76u_vendor_request(&dev->mt76, MT_VEND_DEV_MODE,
			     USB_DIR_OUT | USB_TYPE_VENDOR,
			     0x12, 0, NULL, 0);
}

static void mt76x2u_mcu_enable_patch(struct mt76x02_dev *dev)
{
	struct mt76_usb *usb = &dev->mt76.usb;
	static const u8 data[] = {
		0x6f, 0xfc, 0x08, 0x01,
		0x20, 0x04, 0x00, 0x00,
		0x00, 0x09, 0x00,
	};

	memcpy(usb->data, data, sizeof(data));
	mt76u_vendor_request(&dev->mt76, MT_VEND_DEV_MODE,
			     USB_DIR_OUT | USB_TYPE_CLASS,
			     0x12, 0, usb->data, sizeof(data));
}

static void mt76x2u_mcu_reset_wmt(struct mt76x02_dev *dev)
{
	struct mt76_usb *usb = &dev->mt76.usb;
	u8 data[] = {
		0x6f, 0xfc, 0x05, 0x01,
		0x07, 0x01, 0x00, 0x04
	};

	memcpy(usb->data, data, sizeof(data));
	mt76u_vendor_request(&dev->mt76, MT_VEND_DEV_MODE,
			     USB_DIR_OUT | USB_TYPE_CLASS,
			     0x12, 0, usb->data, sizeof(data));
}

static int mt76x2u_mcu_load_rom_patch(struct mt76x02_dev *dev)
{
	bool rom_protect = !is_mt7612(dev);
	struct mt76x02_patch_header *hdr;
	u32 val, patch_mask, patch_reg;
	const struct firmware *fw;
	int err;

	if (rom_protect &&
	    !mt76_poll_msec(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");
		return 0;
	}

	err = request_firmware(&fw, MT7662_ROM_PATCH, dev->mt76.dev);
	if (err < 0)
		return err;

	if (!fw || !fw->data || fw->size <= sizeof(*hdr)) {
		dev_err(dev->mt76.dev, "failed to load firmware\n");

Annotation

Implementation Notes