Commit 35da599f authored by Felix Fietkau's avatar Felix Fietkau
Browse files

mt76: mt7615: implement probing and firmware loading on MT7622



MT7622 does not have a CR4 microcontroller, so it only uses its own N9
firmware.

Co-developed-by: default avatarShayne Chen <shayne.chen@mediatek.com>
Co-developed-by: default avatarRyder Lee <ryder.lee@mediatek.com>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent c3ad5e9d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6,3 +6,4 @@ CFLAGS_trace.o := -I$(src)

mt7615e-y := pci.o init.o dma.o eeprom.o main.o mcu.o mac.o mmio.o \
	     debugfs.o trace.o
mt7615e-$(CONFIG_MT7622_WMAC) += soc.o
+4 −0
Original line number Diff line number Diff line
@@ -442,6 +442,10 @@ int mt7615_register_device(struct mt7615_dev *dev)
	INIT_LIST_HEAD(&dev->sta_poll_list);
	spin_lock_init(&dev->sta_poll_lock);

	ret = mt7622_wmac_init(dev);
	if (ret)
		return ret;

	ret = mt7615_init_hardware(dev);
	if (ret)
		return ret;
+28 −0
Original line number Diff line number Diff line
@@ -732,3 +732,31 @@ const struct ieee80211_ops mt7615_ops = {
	.set_antenna = mt7615_set_antenna,
	.set_coverage_class = mt7615_set_coverage_class,
};

static int __init mt7615_init(void)
{
	int ret;

	ret = pci_register_driver(&mt7615_pci_driver);
	if (ret)
		return ret;

	if (IS_ENABLED(CONFIG_MT7622_WMAC)) {
		ret = platform_driver_register(&mt7622_wmac_driver);
		if (ret)
			pci_unregister_driver(&mt7615_pci_driver);
	}

	return ret;
}

static void __exit mt7615_exit(void)
{
	if (IS_ENABLED(CONFIG_MT7622_WMAC))
		platform_driver_unregister(&mt7622_wmac_driver);
	pci_unregister_driver(&mt7615_pci_driver);
}

module_init(mt7615_init);
module_exit(mt7615_exit);
MODULE_LICENSE("Dual BSD/GPL");
+75 −10
Original line number Diff line number Diff line
@@ -29,7 +29,8 @@ struct mt7615_fw_trailer {
	__le32 len;
} __packed;

#define MCU_PATCH_ADDRESS		0x80000
#define MT7615_PATCH_ADDRESS		0x80000
#define MT7622_PATCH_ADDRESS		0x9c000

#define N9_REGION_NUM			2
#define CR4_REGION_NUM			1
@@ -333,19 +334,50 @@ static int mt7615_mcu_start_patch(struct mt7615_dev *dev)
				   &req, sizeof(req), true);
}

static void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en)
{
	if (!is_mt7622(&dev->mt76))
		return;

	regmap_update_bits(dev->infracfg, MT_INFRACFG_MISC,
			   MT_INFRACFG_MISC_AP2CONN_WAKE,
			   !en * MT_INFRACFG_MISC_AP2CONN_WAKE);
}

static int mt7615_driver_own(struct mt7615_dev *dev)
{
	mt76_wr(dev, MT_CFG_LPCR_HOST, MT_CFG_LPCR_HOST_DRV_OWN);

	mt7622_trigger_hif_int(dev, true);
	if (!mt76_poll_msec(dev, MT_CFG_LPCR_HOST,
			    MT_CFG_LPCR_HOST_FW_OWN, 0, 500)) {
			    MT_CFG_LPCR_HOST_FW_OWN, 0, 3000)) {
		dev_err(dev->mt76.dev, "Timeout for driver own\n");
		return -EIO;
	}
	mt7622_trigger_hif_int(dev, false);

	return 0;
}

static int mt7615_load_patch(struct mt7615_dev *dev, const char *name)
static int mt7615_firmware_own(struct mt7615_dev *dev)
{
	mt7622_trigger_hif_int(dev, true);

	mt76_wr(dev, MT_CFG_LPCR_HOST, MT_CFG_LPCR_HOST_FW_OWN);

	if (is_mt7622(&dev->mt76) &&
	    !mt76_poll_msec(dev, MT_CFG_LPCR_HOST,
			    MT_CFG_LPCR_HOST_FW_OWN,
			    MT_CFG_LPCR_HOST_FW_OWN, 3000)) {
		dev_err(dev->mt76.dev, "Timeout for firmware own\n");
		return -EIO;
	}
	mt7622_trigger_hif_int(dev, false);

	return 0;
}

static int mt7615_load_patch(struct mt7615_dev *dev, u32 addr, const char *name)
{
	const struct mt7615_patch_hdr *hdr;
	const struct firmware *fw = NULL;
@@ -379,8 +411,7 @@ static int mt7615_load_patch(struct mt7615_dev *dev, const char *name)

	len = fw->size - sizeof(*hdr);

	ret = mt7615_mcu_init_download(dev, MCU_PATCH_ADDRESS, len,
				       DL_MODE_NEED_RSP);
	ret = mt7615_mcu_init_download(dev, addr, len, DL_MODE_NEED_RSP);
	if (ret) {
		dev_err(dev->mt76.dev, "Download request failed\n");
		goto out;
@@ -561,7 +592,7 @@ static int mt7615_load_firmware(struct mt7615_dev *dev)
		return -EIO;
	}

	ret = mt7615_load_patch(dev, MT7615_ROM_PATCH);
	ret = mt7615_load_patch(dev, MT7615_PATCH_ADDRESS, MT7615_ROM_PATCH);
	if (ret)
		return ret;

@@ -576,9 +607,38 @@ static int mt7615_load_firmware(struct mt7615_dev *dev)
		return -EIO;
	}

	mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false);
	return 0;
}

	dev_dbg(dev->mt76.dev, "Firmware init done\n");
static int mt7622_load_firmware(struct mt7615_dev *dev)
{
	int ret;
	u32 val;

	mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH);

	val = mt76_get_field(dev, MT_TOP_OFF_RSV, MT_TOP_OFF_RSV_FW_STATE);
	if (val != FW_STATE_FW_DOWNLOAD) {
		dev_err(dev->mt76.dev, "Firmware is not ready for download\n");
		return -EIO;
	}

	ret = mt7615_load_patch(dev, MT7622_PATCH_ADDRESS, MT7622_ROM_PATCH);
	if (ret)
		return ret;

	ret = mt7615_load_n9(dev, MT7622_FIRMWARE_N9);
	if (ret)
		return ret;

	if (!mt76_poll_msec(dev, MT_TOP_OFF_RSV, MT_TOP_OFF_RSV_FW_STATE,
			    FIELD_PREP(MT_TOP_OFF_RSV_FW_STATE,
				       FW_STATE_NORMAL_TRX), 1500)) {
		dev_err(dev->mt76.dev, "Timeout for initializing firmware\n");
		return -EIO;
	}

	mt76_clear(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_BYPASS_TX_SCH);

	return 0;
}
@@ -597,10 +657,15 @@ int mt7615_mcu_init(struct mt7615_dev *dev)
	if (ret)
		return ret;

	if (is_mt7622(&dev->mt76))
		ret = mt7622_load_firmware(dev);
	else
		ret = mt7615_load_firmware(dev);
	if (ret)
		return ret;

	mt76_queue_tx_cleanup(dev, MT_TXQ_FWDL, false);
	dev_dbg(dev->mt76.dev, "Firmware init done\n");
	set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);

	return 0;
@@ -609,7 +674,7 @@ int mt7615_mcu_init(struct mt7615_dev *dev)
void mt7615_mcu_exit(struct mt7615_dev *dev)
{
	__mt76_mcu_restart(&dev->mt76);
	mt76_wr(dev, MT_CFG_LPCR_HOST, MT_CFG_LPCR_HOST_FW_OWN);
	mt7615_firmware_own(dev);
	skb_queue_purge(&dev->mt76.mmio.mcu.res_q);
}

+19 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@

#include <linux/interrupt.h>
#include <linux/ktime.h>
#include <linux/regmap.h>
#include "../mt76.h"
#include "regs.h"

@@ -31,6 +32,9 @@
#define MT7615_FIRMWARE_N9		"mediatek/mt7615_n9.bin"
#define MT7615_ROM_PATCH		"mediatek/mt7615_rom_patch.bin"

#define MT7622_FIRMWARE_N9		"mediatek/mt7622_n9.bin"
#define MT7622_ROM_PATCH		"mediatek/mt7622_rom_patch.bin"

#define MT7615_EEPROM_SIZE		1024
#define MT7615_TOKEN_SIZE		4096

@@ -148,6 +152,8 @@ struct mt7615_dev {

	u16 chainmask;

	struct regmap *infracfg;

	struct work_struct mcu_work;

	struct list_head sta_poll_list;
@@ -241,6 +247,16 @@ mt7615_ext_phy(struct mt7615_dev *dev)

extern const struct ieee80211_ops mt7615_ops;
extern struct pci_driver mt7615_pci_driver;
extern struct platform_driver mt7622_wmac_driver;

#ifdef CONFIG_MT7622_WMAC
int mt7622_wmac_init(struct mt7615_dev *dev);
#else
static inline int mt7622_wmac_init(struct mt7615_dev *dev)
{
	return 0;
}
#endif

int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, int irq);
u32 mt7615_reg_map(struct mt7615_dev *dev, u32 addr);
@@ -295,6 +311,9 @@ int mt7615_mcu_rdd_send_pattern(struct mt7615_dev *dev);

static inline bool is_mt7622(struct mt76_dev *dev)
{
	if (!IS_ENABLED(CONFIG_MT7622_WMAC))
		return false;

	return mt76_chip(dev) == 0x7622;
}

Loading