Commit 1c7393e6 authored by Bo Jiao's avatar Bo Jiao Committed by Felix Fietkau
Browse files

mt76: mt7915: add firmware support for mt7916



Update firmware initialization for mt7916.
This is an intermediate patch to add mt7916 support.

Co-developed-by: default avatarSujuan Chen <sujuan.chen@mediatek.com>
Signed-off-by: default avatarSujuan Chen <sujuan.chen@mediatek.com>
Co-developed-by: default avatarRyder Lee <ryder.lee@mediatek.com>
Signed-off-by: default avatarRyder Lee <ryder.lee@mediatek.com>
Signed-off-by: default avatarBo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent aa79fe87
Loading
Loading
Loading
Loading
+34 −34
Original line number Diff line number Diff line
@@ -508,11 +508,12 @@ static void mt7915_init_work(struct work_struct *work)

static void mt7915_wfsys_reset(struct mt7915_dev *dev)
{
	u32 val = MT_TOP_PWR_KEY | MT_TOP_PWR_SW_PWR_ON | MT_TOP_PWR_PWR_ON;

#define MT_MCU_DUMMY_RANDOM	GENMASK(15, 0)
#define MT_MCU_DUMMY_DEFAULT	GENMASK(31, 16)

	if (is_mt7915(&dev->mt76)) {
		u32 val = MT_TOP_PWR_KEY | MT_TOP_PWR_SW_PWR_ON | MT_TOP_PWR_PWR_ON;

		mt76_wr(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_RANDOM);

		/* change to software control */
@@ -533,8 +534,9 @@ static void mt7915_wfsys_reset(struct mt7915_dev *dev)
		mt76_wr(dev, MT_TOP_PWR_CTRL, val);

		/* check whether mcu resets to default */
	if (!mt76_poll_msec(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_DEFAULT,
			    MT_MCU_DUMMY_DEFAULT, 1000)) {
		if (!mt76_poll_msec(dev, MT_MCU_WFDMA0_DUMMY_CR,
				    MT_MCU_DUMMY_DEFAULT, MT_MCU_DUMMY_DEFAULT,
				    1000)) {
			dev_err(dev->mt76.dev, "wifi subsystem reset failure\n");
			return;
		}
@@ -543,6 +545,13 @@ static void mt7915_wfsys_reset(struct mt7915_dev *dev)
		mt76_clear(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE);

		msleep(100);
	} else {
		mt76_set(dev, MT_WF_SUBSYS_RST, 0x1);
		msleep(20);

		mt76_clear(dev, MT_WF_SUBSYS_RST, 0x1);
		msleep(20);
	}
}

static int mt7915_init_hardware(struct mt7915_dev *dev)
@@ -565,15 +574,6 @@ static int mt7915_init_hardware(struct mt7915_dev *dev)

	set_bit(MT76_STATE_INITIALIZED, &dev->mphy.state);

	/*
	 * force firmware operation mode into normal state,
	 * which should be set before firmware download stage.
	 */
	if (is_mt7915(&dev->mt76))
		mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
	else
		mt76_wr(dev, MT_SWDEF_MODE_MT7916, MT_SWDEF_NORMAL_MODE);

	ret = mt7915_mcu_init(dev);
	if (ret) {
		/* Reset and try again */
+64 −17
Original line number Diff line number Diff line
@@ -2693,15 +2693,19 @@ static int mt7915_mcu_start_patch(struct mt7915_dev *dev)
				 sizeof(req), true);
}

static int mt7915_driver_own(struct mt7915_dev *dev)
static int mt7915_driver_own(struct mt7915_dev *dev, u8 band)
{
	mt76_wr(dev, MT_TOP_LPCR_HOST_BAND0, MT_TOP_LPCR_HOST_DRV_OWN);
	if (!mt76_poll_msec(dev, MT_TOP_LPCR_HOST_BAND0,
	mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(band), MT_TOP_LPCR_HOST_DRV_OWN);
	if (!mt76_poll_msec(dev, MT_TOP_LPCR_HOST_BAND(band),
			    MT_TOP_LPCR_HOST_FW_OWN_STAT, 0, 500)) {
		dev_err(dev->mt76.dev, "Timeout for driver own\n");
		return -EIO;
	}

	/* clear irq when the driver own success */
	mt76_wr(dev, MT_TOP_LPCR_HOST_BAND_IRQ_STAT(band),
		MT_TOP_LPCR_HOST_BAND_STAT);

	return 0;
}

@@ -2731,6 +2735,7 @@ static int mt7915_load_patch(struct mt7915_dev *dev)
{
	const struct mt7915_patch_hdr *hdr;
	const struct firmware *fw = NULL;
	const char *patch;
	int i, ret, sem;

	sem = mt7915_mcu_patch_sem_ctrl(dev, 1);
@@ -2744,7 +2749,8 @@ static int mt7915_load_patch(struct mt7915_dev *dev)
		return -EAGAIN;
	}

	ret = request_firmware(&fw, MT7915_ROM_PATCH, dev->mt76.dev);
	patch = is_mt7915(&dev->mt76) ? MT7915_ROM_PATCH : MT7916_ROM_PATCH;
	ret = request_firmware(&fw, patch, dev->mt76.dev);
	if (ret)
		goto out;

@@ -2875,9 +2881,11 @@ static int mt7915_load_ram(struct mt7915_dev *dev)
{
	const struct mt7915_fw_trailer *hdr;
	const struct firmware *fw;
	const char *mcu;
	int ret;

	ret = request_firmware(&fw, MT7915_FIRMWARE_WM, dev->mt76.dev);
	mcu = is_mt7915(&dev->mt76) ? MT7915_FIRMWARE_WM : MT7916_FIRMWARE_WM;
	ret = request_firmware(&fw, mcu, dev->mt76.dev);
	if (ret)
		return ret;

@@ -2901,7 +2909,8 @@ static int mt7915_load_ram(struct mt7915_dev *dev)

	release_firmware(fw);

	ret = request_firmware(&fw, MT7915_FIRMWARE_WA, dev->mt76.dev);
	mcu = is_mt7915(&dev->mt76) ? MT7915_FIRMWARE_WA : MT7916_FIRMWARE_WA;
	ret = request_firmware(&fw, mcu, dev->mt76.dev);
	if (ret)
		return ret;

@@ -2933,10 +2942,36 @@ static int mt7915_load_ram(struct mt7915_dev *dev)
	return ret;
}

static int
mt7915_firmware_state(struct mt7915_dev *dev, bool wa)
{
	u32 state = FIELD_PREP(MT_TOP_MISC_FW_STATE,
			       wa ? FW_STATE_RDY : FW_STATE_FW_DOWNLOAD);

	if (!mt76_poll_msec(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE,
			    state, 1000)) {
		dev_err(dev->mt76.dev, "Timeout for initializing firmware\n");
		return -EIO;
	}
	return 0;
}

static int mt7915_load_firmware(struct mt7915_dev *dev)
{
	int ret;

	/* make sure fw is download state */
	if (mt7915_firmware_state(dev, false)) {
		/* restart firmware once */
		__mt76_mcu_restart(&dev->mt76);
		ret = mt7915_firmware_state(dev, false);
		if (ret) {
			dev_err(dev->mt76.dev,
				"Firmware is not ready for download\n");
			return ret;
		}
	}

	ret = mt7915_load_patch(dev);
	if (ret)
		return ret;
@@ -2945,12 +2980,9 @@ static int mt7915_load_firmware(struct mt7915_dev *dev)
	if (ret)
		return ret;

	if (!mt76_poll_msec(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE,
			    FIELD_PREP(MT_TOP_MISC_FW_STATE,
				       FW_STATE_RDY), 1000)) {
		dev_err(dev->mt76.dev, "Timeout for initializing firmware\n");
		return -EIO;
	}
	ret = mt7915_firmware_state(dev, true);
	if (ret)
		return ret;

	mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false);

@@ -3116,9 +3148,23 @@ int mt7915_mcu_init(struct mt7915_dev *dev)

	dev->mt76.mcu_ops = &mt7915_mcu_ops;

	ret = mt7915_driver_own(dev);
	/* force firmware operation mode into normal state,
	 * which should be set before firmware download stage.
	 */
	if (is_mt7915(&dev->mt76))
		mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
	else
		mt76_wr(dev, MT_SWDEF_MODE_MT7916, MT_SWDEF_NORMAL_MODE);

	ret = mt7915_driver_own(dev, 0);
	if (ret)
		return ret;
	/* set driver own for band1 when two hif exist */
	if (dev->hif2) {
		ret = mt7915_driver_own(dev, 1);
		if (ret)
			return ret;
	}

	ret = mt7915_load_firmware(dev);
	if (ret)
@@ -3153,14 +3199,15 @@ int mt7915_mcu_init(struct mt7915_dev *dev)
void mt7915_mcu_exit(struct mt7915_dev *dev)
{
	__mt76_mcu_restart(&dev->mt76);
	if (!mt76_poll_msec(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE,
			    FIELD_PREP(MT_TOP_MISC_FW_STATE,
				       FW_STATE_FW_DOWNLOAD), 1000)) {
	if (mt7915_firmware_state(dev, false)) {
		dev_err(dev->mt76.dev, "Failed to exit mcu\n");
		return;
	}

	mt76_wr(dev, MT_TOP_LPCR_HOST_BAND0, MT_TOP_LPCR_HOST_FW_OWN);
	mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(0), MT_TOP_LPCR_HOST_FW_OWN);
	if (dev->hif2)
		mt76_wr(dev, MT_TOP_LPCR_HOST_BAND(1),
			MT_TOP_LPCR_HOST_FW_OWN);
	skb_queue_purge(&dev->mt76.mcu.res_q);
}

+4 −0
Original line number Diff line number Diff line
@@ -30,6 +30,10 @@
#define MT7915_FIRMWARE_WM		"mediatek/mt7915_wm.bin"
#define MT7915_ROM_PATCH		"mediatek/mt7915_rom_patch.bin"

#define MT7916_FIRMWARE_WA		"mediatek/mt7916_wa.bin"
#define MT7916_FIRMWARE_WM		"mediatek/mt7916_wm.bin"
#define MT7916_ROM_PATCH		"mediatek/mt7916_rom_patch.bin"

#define MT7915_EEPROM_DEFAULT		"mediatek/mt7915_eeprom.bin"
#define MT7915_EEPROM_DEFAULT_DBDC	"mediatek/mt7915_eeprom_dbdc.bin"

+3 −0
Original line number Diff line number Diff line
@@ -167,3 +167,6 @@ MODULE_DEVICE_TABLE(pci, mt7915_hif_device_table);
MODULE_FIRMWARE(MT7915_FIRMWARE_WA);
MODULE_FIRMWARE(MT7915_FIRMWARE_WM);
MODULE_FIRMWARE(MT7915_ROM_PATCH);
MODULE_FIRMWARE(MT7916_FIRMWARE_WA);
MODULE_FIRMWARE(MT7916_FIRMWARE_WM);
MODULE_FIRMWARE(MT7916_ROM_PATCH);
+5 −1
Original line number Diff line number Diff line
@@ -729,17 +729,21 @@ enum offs_rev {
#define MT_TOP_BASE			0x18060000
#define MT_TOP(ofs)			(MT_TOP_BASE + (ofs))

#define MT_TOP_LPCR_HOST_BAND0		MT_TOP(0x10)
#define MT_TOP_LPCR_HOST_BAND(_band)	MT_TOP(0x10 + ((_band) * 0x10))
#define MT_TOP_LPCR_HOST_FW_OWN		BIT(0)
#define MT_TOP_LPCR_HOST_DRV_OWN	BIT(1)
#define MT_TOP_LPCR_HOST_FW_OWN_STAT	BIT(2)

#define MT_TOP_LPCR_HOST_BAND_IRQ_STAT(_band)	MT_TOP(0x14 + ((_band) * 0x10))
#define MT_TOP_LPCR_HOST_BAND_STAT	BIT(0)

#define MT_TOP_MISC			MT_TOP(0xf0)
#define MT_TOP_MISC_FW_STATE		GENMASK(2, 0)

#define MT_HW_BOUND			0x70010020
#define MT_HW_CHIPID			0x70010200
#define MT_HW_REV			0x70010204
#define MT_WF_SUBSYS_RST		0x70002600

/* PCIE MAC */
#define MT_PCIE_MAC_BASE		0x74030000