Commit e07419a7 authored by Ryder Lee's avatar Ryder Lee Committed by Felix Fietkau

mt76: mt7915: add wifi subsystem reset

Reset wifi subsystem when MCU is already running.
Fixes firmware download failure after soft reboot on systems where the PCIe
reset could not be performed properly.
Signed-off-by: default avatarRyder Lee <ryder.lee@mediatek.com>
Co-developed-by: default avatarFelix Fietkau <nbd@nbd.name>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent ac15f9b6
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include "mt7915.h" #include "mt7915.h"
#include "mac.h" #include "mac.h"
#include "mcu.h"
#include "eeprom.h" #include "eeprom.h"
#define CCK_RATE(_idx, _rate) { \ #define CCK_RATE(_idx, _rate) { \
...@@ -295,9 +296,50 @@ static void mt7915_init_work(struct work_struct *work) ...@@ -295,9 +296,50 @@ static void mt7915_init_work(struct work_struct *work)
mt7915_txbf_init(dev); mt7915_txbf_init(dev);
} }
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;
u32 reg = mt7915_reg_map_l1(dev, MT_TOP_MISC);
#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);
/* change to software control */
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);
/* release wfsys then mcu re-excutes romcode */
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);
/* 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, reg, MT_TOP_MISC_FW_STATE);
msleep(100);
}
static int mt7915_init_hardware(struct mt7915_dev *dev) static int mt7915_init_hardware(struct mt7915_dev *dev)
{ {
int ret, idx; int ret, idx;
u32 val;
mt76_wr(dev, MT_INT_SOURCE_CSR, ~0); mt76_wr(dev, MT_INT_SOURCE_CSR, ~0);
...@@ -307,6 +349,12 @@ static int mt7915_init_hardware(struct mt7915_dev *dev) ...@@ -307,6 +349,12 @@ static int mt7915_init_hardware(struct mt7915_dev *dev)
dev->dbdc_support = !!(mt7915_l1_rr(dev, MT_HW_BOUND) & BIT(5)); dev->dbdc_support = !!(mt7915_l1_rr(dev, MT_HW_BOUND) & BIT(5));
val = mt76_rr(dev, mt7915_reg_map_l1(dev, MT_TOP_MISC));
/* If MCU was already running, it is likely in a bad state */
if (FIELD_GET(MT_TOP_MISC_FW_STATE, val) > FW_STATE_FW_DOWNLOAD)
mt7915_wfsys_reset(dev);
ret = mt7915_dma_init(dev); ret = mt7915_dma_init(dev);
if (ret) if (ret)
return ret; return ret;
...@@ -319,9 +367,15 @@ static int mt7915_init_hardware(struct mt7915_dev *dev) ...@@ -319,9 +367,15 @@ static int mt7915_init_hardware(struct mt7915_dev *dev)
*/ */
mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE); mt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);
ret = mt7915_mcu_init(dev);
if (ret) {
/* Reset and try again */
mt7915_wfsys_reset(dev);
ret = mt7915_mcu_init(dev); ret = mt7915_mcu_init(dev);
if (ret) if (ret)
return ret; return ret;
}
ret = mt7915_eeprom_init(dev); ret = mt7915_eeprom_init(dev);
if (ret < 0) if (ret < 0)
......
...@@ -2784,21 +2784,8 @@ static int mt7915_load_ram(struct mt7915_dev *dev) ...@@ -2784,21 +2784,8 @@ static int mt7915_load_ram(struct mt7915_dev *dev)
static int mt7915_load_firmware(struct mt7915_dev *dev) static int mt7915_load_firmware(struct mt7915_dev *dev)
{ {
u32 reg = mt7915_reg_map_l1(dev, MT_TOP_MISC);
int ret; int ret;
u32 val, reg = mt7915_reg_map_l1(dev, MT_TOP_MISC);
val = FIELD_PREP(MT_TOP_MISC_FW_STATE, FW_STATE_FW_DOWNLOAD);
if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE, val, 1000)) {
/* restart firmware once */
__mt76_mcu_restart(&dev->mt76);
if (!mt76_poll_msec(dev, reg, MT_TOP_MISC_FW_STATE,
val, 1000)) {
dev_err(dev->mt76.dev,
"Firmware is not ready for download\n");
return -EIO;
}
}
ret = mt7915_load_patch(dev); ret = mt7915_load_patch(dev);
if (ret) if (ret)
......
...@@ -4,6 +4,11 @@ ...@@ -4,6 +4,11 @@
#ifndef __MT7915_REGS_H #ifndef __MT7915_REGS_H
#define __MT7915_REGS_H #define __MT7915_REGS_H
/* MCU WFDMA0 */
#define MT_MCU_WFDMA0_BASE 0x2000
#define MT_MCU_WFDMA0(ofs) (MT_MCU_WFDMA0_BASE + (ofs))
#define MT_MCU_WFDMA0_DUMMY_CR MT_MCU_WFDMA0(0x120)
/* MCU WFDMA1 */ /* MCU WFDMA1 */
#define MT_MCU_WFDMA1_BASE 0x3000 #define MT_MCU_WFDMA1_BASE 0x3000
#define MT_MCU_WFDMA1(ofs) (MT_MCU_WFDMA1_BASE + (ofs)) #define MT_MCU_WFDMA1(ofs) (MT_MCU_WFDMA1_BASE + (ofs))
...@@ -396,6 +401,14 @@ ...@@ -396,6 +401,14 @@
#define MT_WFDMA1_PCIE1_BUSY_ENA_TX_FIFO1 BIT(1) #define MT_WFDMA1_PCIE1_BUSY_ENA_TX_FIFO1 BIT(1)
#define MT_WFDMA1_PCIE1_BUSY_ENA_RX_FIFO BIT(2) #define MT_WFDMA1_PCIE1_BUSY_ENA_RX_FIFO BIT(2)
#define MT_TOP_RGU_BASE 0xf0000
#define MT_TOP_PWR_CTRL (MT_TOP_RGU_BASE + (0x0))
#define MT_TOP_PWR_KEY (0x5746 << 16)
#define MT_TOP_PWR_SW_RST BIT(0)
#define MT_TOP_PWR_SW_PWR_ON GENMASK(3, 2)
#define MT_TOP_PWR_HW_CTRL BIT(4)
#define MT_TOP_PWR_PWR_ON BIT(7)
#define MT_INFRA_CFG_BASE 0xf1000 #define MT_INFRA_CFG_BASE 0xf1000
#define MT_INFRA(ofs) (MT_INFRA_CFG_BASE + (ofs)) #define MT_INFRA(ofs) (MT_INFRA_CFG_BASE + (ofs))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment