Path: blob/main/sys/contrib/dev/mediatek/mt76/mt7921/sdio_mac.c
48526 views
// SPDX-License-Identifier: ISC1/* Copyright (C) 2021 MediaTek Inc. */23#include <linux/iopoll.h>4#include <linux/mmc/sdio_func.h>5#include "mt7921.h"6#include "../mt76_connac2_mac.h"7#include "../sdio.h"8#include <linux/mmc/host.h>9#include <linux/kallsyms.h>1011static void mt7921s_enable_irq(struct mt76_dev *dev)12{13struct mt76_sdio *sdio = &dev->sdio;1415sdio_claim_host(sdio->func);16sdio_writel(sdio->func, WHLPCR_INT_EN_SET, MCR_WHLPCR, NULL);17sdio_release_host(sdio->func);18}1920static void mt7921s_disable_irq(struct mt76_dev *dev)21{22struct mt76_sdio *sdio = &dev->sdio;2324sdio_claim_host(sdio->func);25sdio_writel(sdio->func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, NULL);26sdio_release_host(sdio->func);27}2829static u32 mt7921s_read_whcr(struct mt76_dev *dev)30{31return sdio_readl(dev->sdio.func, MCR_WHCR, NULL);32}3334int mt7921s_wfsys_reset(struct mt792x_dev *dev)35{36struct mt76_sdio *sdio = &dev->mt76.sdio;37u32 val, status;3839if (atomic_read(&dev->mt76.bus_hung))40return 0;4142mt7921s_mcu_drv_pmctrl(dev);4344sdio_claim_host(sdio->func);4546val = sdio_readl(sdio->func, MCR_WHCR, NULL);47val &= ~WF_WHOLE_PATH_RSTB;48sdio_writel(sdio->func, val, MCR_WHCR, NULL);4950msleep(50);5152val = sdio_readl(sdio->func, MCR_WHCR, NULL);53val &= ~WF_SDIO_WF_PATH_RSTB;54sdio_writel(sdio->func, val, MCR_WHCR, NULL);5556usleep_range(1000, 2000);5758val = sdio_readl(sdio->func, MCR_WHCR, NULL);59val |= WF_WHOLE_PATH_RSTB;60sdio_writel(sdio->func, val, MCR_WHCR, NULL);6162readx_poll_timeout(mt7921s_read_whcr, &dev->mt76, status,63status & WF_RST_DONE, 50000, 2000000);6465sdio_release_host(sdio->func);6667clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);6869/* activate mt7921s again */70mt7921s_mcu_drv_pmctrl(dev);71mt76_clear(dev, MT_CONN_STATUS, MT_WIFI_PATCH_DL_STATE);72mt7921s_mcu_fw_pmctrl(dev);73mt7921s_mcu_drv_pmctrl(dev);7475return 0;76}7778int mt7921s_init_reset(struct mt792x_dev *dev)79{80set_bit(MT76_MCU_RESET, &dev->mphy.state);8182wake_up(&dev->mt76.mcu.wait);83skb_queue_purge(&dev->mt76.mcu.res_q);84wait_event_timeout(dev->mt76.sdio.wait,85mt76s_txqs_empty(&dev->mt76), 5 * HZ);86mt76_worker_disable(&dev->mt76.sdio.txrx_worker);8788mt7921s_disable_irq(&dev->mt76);89mt7921s_wfsys_reset(dev);9091mt76_worker_enable(&dev->mt76.sdio.txrx_worker);92clear_bit(MT76_MCU_RESET, &dev->mphy.state);93mt7921s_enable_irq(&dev->mt76);9495return 0;96}9798static struct mt76_sdio *msdio;99static void mt7921s_card_reset(struct work_struct *work)100{101struct mmc_host *sdio_host = msdio->func->card->host;102103sdio_claim_host(msdio->func);104sdio_release_irq(msdio->func);105sdio_release_host(msdio->func);106107mmc_remove_host(sdio_host);108msleep(50);109mmc_add_host(sdio_host);110}111112static DECLARE_WORK(sdio_reset_work, mt7921s_card_reset);113static int mt7921s_check_bus(struct mt76_dev *dev)114{115struct mt76_sdio *sdio = &dev->sdio;116int err;117118sdio_claim_host(sdio->func);119sdio_readl(dev->sdio.func, MCR_WHCR, &err);120sdio_release_host(sdio->func);121122return err;123}124125static int mt7921s_host_reset(struct mt792x_dev *dev)126{127struct mt76_dev *mdev = &dev->mt76;128int err = -1;129130if (!atomic_read(&mdev->bus_hung))131err = mt7921s_check_bus(&dev->mt76);132133if (err) {134atomic_set(&mdev->bus_hung, true);135msdio = &dev->mt76.sdio;136dev_err(mdev->dev, "SDIO bus problem detected(%d), resetting card!!\n", err);137schedule_work(&sdio_reset_work);138return err;139}140141atomic_set(&mdev->bus_hung, false);142143return 0;144}145146int mt7921s_mac_reset(struct mt792x_dev *dev)147{148int err;149150mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);151152mt7921s_host_reset(dev);153if (atomic_read(&dev->mt76.bus_hung))154return 0;155156mt76_txq_schedule_all(&dev->mphy);157mt76_worker_disable(&dev->mt76.tx_worker);158set_bit(MT76_MCU_RESET, &dev->mphy.state);159wake_up(&dev->mt76.mcu.wait);160skb_queue_purge(&dev->mt76.mcu.res_q);161wait_event_timeout(dev->mt76.sdio.wait,162mt76s_txqs_empty(&dev->mt76), 5 * HZ);163mt76_worker_disable(&dev->mt76.sdio.txrx_worker);164mt76_worker_disable(&dev->mt76.sdio.status_worker);165mt76_worker_disable(&dev->mt76.sdio.net_worker);166mt76_worker_disable(&dev->mt76.sdio.stat_worker);167168mt7921s_disable_irq(&dev->mt76);169mt7921s_wfsys_reset(dev);170171mt76_worker_enable(&dev->mt76.sdio.txrx_worker);172mt76_worker_enable(&dev->mt76.sdio.status_worker);173mt76_worker_enable(&dev->mt76.sdio.net_worker);174mt76_worker_enable(&dev->mt76.sdio.stat_worker);175176dev->fw_assert = false;177clear_bit(MT76_MCU_RESET, &dev->mphy.state);178mt7921s_enable_irq(&dev->mt76);179180err = mt7921_run_firmware(dev);181if (err)182goto out;183184err = mt7921_mcu_set_eeprom(dev);185if (err)186goto out;187188err = mt7921_mac_init(dev);189if (err)190goto out;191192err = __mt7921_start(&dev->phy);193out:194195mt76_worker_enable(&dev->mt76.tx_worker);196197return err;198}199200201