mt76: mt7915: add firmware support for mt7916
authorBo Jiao <Bo.Jiao@mediatek.com>
Mon, 20 Dec 2021 02:17:57 +0000 (10:17 +0800)
committerFelix Fietkau <nbd@nbd.name>
Thu, 3 Feb 2022 12:57:56 +0000 (13:57 +0100)
Update firmware initialization for mt7916.
This is an intermediate patch to add mt7916 support.

Co-developed-by: Sujuan Chen <sujuan.chen@mediatek.com>
Signed-off-by: Sujuan Chen <sujuan.chen@mediatek.com>
Co-developed-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Signed-off-by: Bo Jiao <Bo.Jiao@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7915/init.c
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
drivers/net/wireless/mediatek/mt76/mt7915/pci.c
drivers/net/wireless/mediatek/mt76/mt7915/regs.h

index 2c198ee7b349e492c09126ecd13a25024585f45b..48b0cb82932afb0e624c347f02f1c6ffb2b12e77 100644 (file)
@@ -508,41 +508,50 @@ 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)
 
-       mt76_wr(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_RANDOM);
+       if (is_mt7915(&dev->mt76)) {
+               u32 val = MT_TOP_PWR_KEY | MT_TOP_PWR_SW_PWR_ON | MT_TOP_PWR_PWR_ON;
 
-       /* change to software control */
-       val |= MT_TOP_PWR_SW_RST;
-       mt76_wr(dev, MT_TOP_PWR_CTRL, val);
+               mt76_wr(dev, MT_MCU_WFDMA0_DUMMY_CR, MT_MCU_DUMMY_RANDOM);
 
-       /* reset wfsys */
-       val &= ~MT_TOP_PWR_SW_RST;
-       mt76_wr(dev, MT_TOP_PWR_CTRL, val);
+               /* change to software control */
+               val |= MT_TOP_PWR_SW_RST;
+               mt76_wr(dev, MT_TOP_PWR_CTRL, val);
 
-       /* release wfsys then mcu re-excutes romcode */
-       val |= MT_TOP_PWR_SW_RST;
-       mt76_wr(dev, MT_TOP_PWR_CTRL, val);
+               /* reset wfsys */
+               val &= ~MT_TOP_PWR_SW_RST;
+               mt76_wr(dev, MT_TOP_PWR_CTRL, val);
 
-       /* switch to hw control */
-       val &= ~MT_TOP_PWR_SW_RST;
-       val |= MT_TOP_PWR_HW_CTRL;
-       mt76_wr(dev, MT_TOP_PWR_CTRL, val);
+               /* release wfsys then mcu re-excutes romcode */
+               val |= MT_TOP_PWR_SW_RST;
+               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)) {
-               dev_err(dev->mt76.dev, "wifi subsystem reset failure\n");
-               return;
-       }
+               /* switch to hw control */
+               val &= ~MT_TOP_PWR_SW_RST;
+               val |= MT_TOP_PWR_HW_CTRL;
+               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)) {
+                       dev_err(dev->mt76.dev, "wifi subsystem reset failure\n");
+                       return;
+               }
 
-       /* wfsys reset won't clear host registers */
-       mt76_clear(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE);
+               /* wfsys reset won't clear host registers */
+               mt76_clear(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE);
 
-       msleep(100);
+               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 */
index 35728f1659506fa609382fef9b0de9aef8656d47..1c99b01cdb50996569afa53c19f55e24cbb10295 100644 (file)
@@ -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 @@ out:
        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);
 }
 
index e2e510661c5ba6e0a6adb29888f21fc414c54167..14b5164efbb79e15542a2e52569c7d7fa295fd72 100644 (file)
 #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"
 
index e4854a4e1836d1ac8ac07ff599c87cde5f946a98..5d6adcdbef3c8fc2b8a03574aa2157c621d9c02c 100644 (file)
@@ -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);
index a8e864a332659fc671c80e1f4bfaa1e8a16e12f5..1168a6260ab8e1588c40688fe4cce22851cfb3fb 100644 (file)
@@ -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