mirror of
https://git.proxmox.com/git/mirror_ubuntu-kernels.git
synced 2025-12-25 16:05:55 +00:00
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>
This commit is contained in:
parent
aa79fe87c4
commit
1c7393e68b
@ -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);
|
||||
|
||||
msleep(100);
|
||||
} else {
|
||||
mt76_set(dev, MT_WF_SUBSYS_RST, 0x1);
|
||||
msleep(20);
|
||||
|
||||
mt76_clear(dev, MT_WF_SUBSYS_RST, 0x1);
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
/* wfsys reset won't clear host registers */
|
||||
mt76_clear(dev, MT_TOP_MISC, MT_TOP_MISC_FW_STATE);
|
||||
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user