diff options
author | Bo Jiao <Bo.Jiao@mediatek.com> | 2021-12-20 10:17:57 +0800 |
---|---|---|
committer | Felix Fietkau <nbd@nbd.name> | 2022-02-03 13:57:56 +0100 |
commit | 1c7393e68ba4c8265185763dfee841ee067d558e (patch) | |
tree | 701a936489af82563421a10456d841e2c8d8bf14 | |
parent | aa79fe87c467d7ea7aa7a3c0b0af8350d08f930e (diff) |
mt76: mt7915: add firmware support for mt7916
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>
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7915/init.c | 68 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 81 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7915/pci.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7915/regs.h | 6 |
5 files changed, 110 insertions, 52 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 2c198ee7b349..48b0cb82932a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -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 */ diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 35728f165950..1c99b01cdb50 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -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); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index e2e510661c5b..14b5164efbb7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -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" diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c index e4854a4e1836..5d6adcdbef3c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c @@ -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); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h index a8e864a33265..1168a6260ab8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h @@ -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 |