NAK/Cmnt: [SRU][P][PATCH 2/4] wifi: mt76: connac: add support to load firmware for mt7990
John Cabaj
john.cabaj at canonical.com
Tue Jul 22 19:23:02 UTC 2025
On 7/16/25 3:02 AM, En-Wei Wu wrote:
> From: StanleyYP Wang <StanleyYP.Wang at mediatek.com>
>
> BugLink: https://bugs.launchpad.net/bugs/2114957
>
> Add firmware download support. Note that mt7990 does not have WA and DSP
> firmwares. This is a preliminary patch to support mt7990 chipset.
>
> Co-developed-by: Peter Chiu <chui-hao.chiu at mediatek.com>
> Signed-off-by: Peter Chiu <chui-hao.chiu at mediatek.com>
> Signed-off-by: StanleyYP Wang <StanleyYP.Wang at mediatek.com>
> Signed-off-by: Shayne Chen <shayne.chen at mediatek.com>
> Link: https://patch.msgid.link/20250409140750.724437-3-shayne.chen@mediatek.com
> Signed-off-by: Felix Fietkau <nbd at nbd.name>
> (cherry picked from commit a4e32b306a304dda5707281492d96b6dd7a91275)
This didn't cherry-pick cleanly from upstream.
> Signed-off-by: En-Wei Wu <en-wei.wu at canonical.com>
> ---
> drivers/net/wireless/mediatek/mt76/mt76_connac.h | 7 ++++++-
> .../net/wireless/mediatek/mt76/mt76_connac_mcu.c | 3 +--
> drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 23 ++++++++++++++--------
> drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 12 +++++++++++
> drivers/net/wireless/mediatek/mt76/mt7996/pci.c | 2 ++
> 5 files changed, 36 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> index 455979476d114ad874b1db051c898e00068ce8a0..192dcc374a642cad939ef2116303c7cdbeadf94f 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h
> @@ -232,9 +232,14 @@ static inline bool is_mt7992(struct mt76_dev *dev)
> return mt76_chip(dev) == 0x7992;
> }
>
> +static inline bool is_mt7990(struct mt76_dev *dev)
> +{
> + return mt76_chip(dev) == 0x7993;
> +}
> +
> static inline bool is_mt799x(struct mt76_dev *dev)
> {
> - return is_mt7996(dev) || is_mt7992(dev);
> + return is_mt7996(dev) || is_mt7992(dev) || is_mt7990(dev);
> }
>
> static inline bool is_mt7622(struct mt76_dev *dev)
> diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
> index d0e49d68c5dbf0ed4eab084d9c6f1cad230bed93..5f79a7f083d2b6522f3f66df8be4826577c79846 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
> @@ -67,8 +67,7 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,
> if ((!is_connac_v1(dev) && addr == MCU_PATCH_ADDRESS) ||
> (is_mt7921(dev) && addr == 0x900000) ||
> (is_mt7925(dev) && (addr == 0x900000 || addr == 0xe0002800)) ||
> - (is_mt7996(dev) && addr == 0x900000) ||
> - (is_mt7992(dev) && addr == 0x900000))
> + (is_mt799x(dev) && addr == 0x900000))
> cmd = MCU_CMD(PATCH_START_REQ);
> else
> cmd = MCU_CMD(TARGET_ADDRESS_LEN_REQ);
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> index 96edc4157d900e4bad05e55401911486111c7e64..dc9a40029bb8cd7e555e5cd9a258f38870acff36 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> @@ -22,6 +22,9 @@
> _fw = MT7992_##name; \
> } \
> break; \
> + case MT7990_DEVICE_ID: \
> + _fw = MT7990_##name; \
> + break; \
> case MT7996_DEVICE_ID: \
> default: \
> switch ((_dev)->var.type) { \
> @@ -265,7 +268,7 @@ mt7996_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,
>
> txd_len = cmd & __MCU_CMD_FIELD_UNI ? sizeof(*uni_txd) : sizeof(*mcu_txd);
> txd = (__le32 *)skb_push(skb, txd_len);
> - if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state))
> + if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state) && mt7996_has_wa(dev))
> qid = MT_MCUQ_WA;
> else
> qid = MT_MCUQ_WM;
> @@ -2891,6 +2894,9 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
> if (ret)
> return ret;
>
> + if (!mt7996_has_wa(dev))
> + return 0;
> +
> ret = __mt7996_load_ram(dev, "DSP", fw_name(dev, FIRMWARE_DSP),
> MT7996_RAM_TYPE_DSP);
> if (ret)
> @@ -2901,10 +2907,9 @@ static int mt7996_load_ram(struct mt7996_dev *dev)
> }
>
> static int
> -mt7996_firmware_state(struct mt7996_dev *dev, bool wa)
> +mt7996_firmware_state(struct mt7996_dev *dev, u8 fw_state)
> {
> - u32 state = FIELD_PREP(MT_TOP_MISC_FW_STATE,
> - wa ? FW_STATE_RDY : FW_STATE_FW_DOWNLOAD);
> + u32 state = FIELD_PREP(MT_TOP_MISC_FW_STATE, fw_state);
>
> if (!mt76_poll_msec(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE,
> state, 1000)) {
> @@ -2936,13 +2941,14 @@ mt7996_mcu_restart(struct mt76_dev *dev)
>
> static int mt7996_load_firmware(struct mt7996_dev *dev)
> {
> + u8 fw_state;
> int ret;
>
> /* make sure fw is download state */
> - if (mt7996_firmware_state(dev, false)) {
> + if (mt7996_firmware_state(dev, FW_STATE_FW_DOWNLOAD)) {
> /* restart firmware once */
> mt7996_mcu_restart(&dev->mt76);
> - ret = mt7996_firmware_state(dev, false);
> + ret = mt7996_firmware_state(dev, FW_STATE_FW_DOWNLOAD);
> if (ret) {
> dev_err(dev->mt76.dev,
> "Firmware is not ready for download\n");
> @@ -2958,7 +2964,8 @@ static int mt7996_load_firmware(struct mt7996_dev *dev)
> if (ret)
> return ret;
>
> - ret = mt7996_firmware_state(dev, true);
> + fw_state = mt7996_has_wa(dev) ? FW_STATE_RDY : FW_STATE_NORMAL_TRX;
> + ret = mt7996_firmware_state(dev, fw_state);
> if (ret)
> return ret;
>
> @@ -3128,7 +3135,7 @@ int mt7996_mcu_init(struct mt7996_dev *dev)
> void mt7996_mcu_exit(struct mt7996_dev *dev)
> {
> mt7996_mcu_restart(&dev->mt76);
> - if (mt7996_firmware_state(dev, false)) {
> + if (mt7996_firmware_state(dev, FW_STATE_FW_DOWNLOAD)) {
> dev_err(dev->mt76.dev, "Failed to exit mcu\n");
> goto out;
> }
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> index 046b17962ce80bff6c58b435732b124547255fec..8ddb7e1bb43a9e10d7bacd414d53f2d8f18b93d8 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> @@ -34,6 +34,8 @@
> #define MT7996_DEVICE_ID_2 0x7991
> #define MT7992_DEVICE_ID 0x7992
> #define MT7992_DEVICE_ID_2 0x799a
> +#define MT7990_DEVICE_ID 0x7993
> +#define MT7990_DEVICE_ID_2 0x799b
>
> #define MT7996_FIRMWARE_WA "mediatek/mt7996/mt7996_wa.bin"
> #define MT7996_FIRMWARE_WM "mediatek/mt7996/mt7996_wm.bin"
> @@ -55,6 +57,11 @@
> #define MT7992_FIRMWARE_DSP_23 "mediatek/mt7996/mt7992_dsp_23.bin"
> #define MT7992_ROM_PATCH_23 "mediatek/mt7996/mt7992_rom_patch_23.bin"
>
> +#define MT7990_FIRMWARE_WA ""
> +#define MT7990_FIRMWARE_WM "mediatek/mt7996/mt7990_wm.bin"
> +#define MT7990_FIRMWARE_DSP ""
> +#define MT7990_ROM_PATCH "mediatek/mt7996/mt7990_rom_patch.bin"
> +
> #define MT7996_EEPROM_DEFAULT "mediatek/mt7996/mt7996_eeprom.bin"
> #define MT7996_EEPROM_DEFAULT_INT "mediatek/mt7996/mt7996_eeprom_2i5i6i.bin"
> #define MT7996_EEPROM_DEFAULT_233 "mediatek/mt7996/mt7996_eeprom_233.bin"
> @@ -682,6 +689,11 @@ static inline u16 mt7996_rx_chainmask(struct mt7996_phy *phy)
> return tx_chainmask | (BIT(fls(tx_chainmask)) * phy->has_aux_rx);
> }
>
> +static inline bool mt7996_has_wa(struct mt7996_dev *dev)
> +{
> + return !is_mt7990(&dev->mt76);
> +}
> +
> void mt7996_mac_init(struct mt7996_dev *dev);
> u32 mt7996_mac_wtbl_lmac_addr(struct mt7996_dev *dev, u16 wcid, u8 dw);
> bool mt7996_mac_wtbl_update(struct mt7996_dev *dev, int idx, u32 mask);
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/pci.c b/drivers/net/wireless/mediatek/mt76/mt7996/pci.c
> index a4338367aaa12649101c5c76055491973e047c39..05248339a17b84c79b87a42bf525af1d3d5fb183 100644
> --- a/drivers/net/wireless/mediatek/mt76/mt7996/pci.c
> +++ b/drivers/net/wireless/mediatek/mt76/mt7996/pci.c
> @@ -257,3 +257,5 @@ MODULE_FIRMWARE(MT7992_FIRMWARE_WA);
> MODULE_FIRMWARE(MT7992_FIRMWARE_WM);
> MODULE_FIRMWARE(MT7992_FIRMWARE_DSP);
> MODULE_FIRMWARE(MT7992_ROM_PATCH);
> +MODULE_FIRMWARE(MT7990_FIRMWARE_WM);
> +MODULE_FIRMWARE(MT7990_ROM_PATCH);
>
More information about the kernel-team
mailing list