16c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC
26c92544dSBjoern A. Zeeb /* Copyright (C) 2021 MediaTek Inc. */
36c92544dSBjoern A. Zeeb
46c92544dSBjoern A. Zeeb #include <linux/iopoll.h>
56c92544dSBjoern A. Zeeb #include <linux/mmc/sdio_func.h>
66c92544dSBjoern A. Zeeb #include "mt7921.h"
7cbb3ec25SBjoern A. Zeeb #include "../mt76_connac2_mac.h"
86c92544dSBjoern A. Zeeb #include "../sdio.h"
96c92544dSBjoern A. Zeeb
mt7921s_enable_irq(struct mt76_dev * dev)106c92544dSBjoern A. Zeeb static void mt7921s_enable_irq(struct mt76_dev *dev)
116c92544dSBjoern A. Zeeb {
126c92544dSBjoern A. Zeeb struct mt76_sdio *sdio = &dev->sdio;
136c92544dSBjoern A. Zeeb
146c92544dSBjoern A. Zeeb sdio_claim_host(sdio->func);
156c92544dSBjoern A. Zeeb sdio_writel(sdio->func, WHLPCR_INT_EN_SET, MCR_WHLPCR, NULL);
166c92544dSBjoern A. Zeeb sdio_release_host(sdio->func);
176c92544dSBjoern A. Zeeb }
186c92544dSBjoern A. Zeeb
mt7921s_disable_irq(struct mt76_dev * dev)196c92544dSBjoern A. Zeeb static void mt7921s_disable_irq(struct mt76_dev *dev)
206c92544dSBjoern A. Zeeb {
216c92544dSBjoern A. Zeeb struct mt76_sdio *sdio = &dev->sdio;
226c92544dSBjoern A. Zeeb
236c92544dSBjoern A. Zeeb sdio_claim_host(sdio->func);
246c92544dSBjoern A. Zeeb sdio_writel(sdio->func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, NULL);
256c92544dSBjoern A. Zeeb sdio_release_host(sdio->func);
266c92544dSBjoern A. Zeeb }
276c92544dSBjoern A. Zeeb
mt7921s_read_whcr(struct mt76_dev * dev)286c92544dSBjoern A. Zeeb static u32 mt7921s_read_whcr(struct mt76_dev *dev)
296c92544dSBjoern A. Zeeb {
306c92544dSBjoern A. Zeeb return sdio_readl(dev->sdio.func, MCR_WHCR, NULL);
316c92544dSBjoern A. Zeeb }
326c92544dSBjoern A. Zeeb
mt7921s_wfsys_reset(struct mt792x_dev * dev)33cbb3ec25SBjoern A. Zeeb int mt7921s_wfsys_reset(struct mt792x_dev *dev)
346c92544dSBjoern A. Zeeb {
356c92544dSBjoern A. Zeeb struct mt76_sdio *sdio = &dev->mt76.sdio;
366c92544dSBjoern A. Zeeb u32 val, status;
376c92544dSBjoern A. Zeeb
386c92544dSBjoern A. Zeeb mt7921s_mcu_drv_pmctrl(dev);
396c92544dSBjoern A. Zeeb
406c92544dSBjoern A. Zeeb sdio_claim_host(sdio->func);
416c92544dSBjoern A. Zeeb
426c92544dSBjoern A. Zeeb val = sdio_readl(sdio->func, MCR_WHCR, NULL);
436c92544dSBjoern A. Zeeb val &= ~WF_WHOLE_PATH_RSTB;
446c92544dSBjoern A. Zeeb sdio_writel(sdio->func, val, MCR_WHCR, NULL);
456c92544dSBjoern A. Zeeb
466c92544dSBjoern A. Zeeb msleep(50);
476c92544dSBjoern A. Zeeb
486c92544dSBjoern A. Zeeb val = sdio_readl(sdio->func, MCR_WHCR, NULL);
496c92544dSBjoern A. Zeeb val &= ~WF_SDIO_WF_PATH_RSTB;
506c92544dSBjoern A. Zeeb sdio_writel(sdio->func, val, MCR_WHCR, NULL);
516c92544dSBjoern A. Zeeb
526c92544dSBjoern A. Zeeb usleep_range(1000, 2000);
536c92544dSBjoern A. Zeeb
546c92544dSBjoern A. Zeeb val = sdio_readl(sdio->func, MCR_WHCR, NULL);
556c92544dSBjoern A. Zeeb val |= WF_WHOLE_PATH_RSTB;
566c92544dSBjoern A. Zeeb sdio_writel(sdio->func, val, MCR_WHCR, NULL);
576c92544dSBjoern A. Zeeb
586c92544dSBjoern A. Zeeb readx_poll_timeout(mt7921s_read_whcr, &dev->mt76, status,
596c92544dSBjoern A. Zeeb status & WF_RST_DONE, 50000, 2000000);
606c92544dSBjoern A. Zeeb
616c92544dSBjoern A. Zeeb sdio_release_host(sdio->func);
626c92544dSBjoern A. Zeeb
636c92544dSBjoern A. Zeeb clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
646c92544dSBjoern A. Zeeb
656c92544dSBjoern A. Zeeb /* activate mt7921s again */
666c92544dSBjoern A. Zeeb mt7921s_mcu_drv_pmctrl(dev);
676c92544dSBjoern A. Zeeb mt76_clear(dev, MT_CONN_STATUS, MT_WIFI_PATCH_DL_STATE);
686c92544dSBjoern A. Zeeb mt7921s_mcu_fw_pmctrl(dev);
696c92544dSBjoern A. Zeeb mt7921s_mcu_drv_pmctrl(dev);
706c92544dSBjoern A. Zeeb
716c92544dSBjoern A. Zeeb return 0;
726c92544dSBjoern A. Zeeb }
736c92544dSBjoern A. Zeeb
mt7921s_init_reset(struct mt792x_dev * dev)74cbb3ec25SBjoern A. Zeeb int mt7921s_init_reset(struct mt792x_dev *dev)
756c92544dSBjoern A. Zeeb {
766c92544dSBjoern A. Zeeb set_bit(MT76_MCU_RESET, &dev->mphy.state);
776c92544dSBjoern A. Zeeb
786c92544dSBjoern A. Zeeb wake_up(&dev->mt76.mcu.wait);
796c92544dSBjoern A. Zeeb skb_queue_purge(&dev->mt76.mcu.res_q);
806c92544dSBjoern A. Zeeb wait_event_timeout(dev->mt76.sdio.wait,
816c92544dSBjoern A. Zeeb mt76s_txqs_empty(&dev->mt76), 5 * HZ);
826c92544dSBjoern A. Zeeb mt76_worker_disable(&dev->mt76.sdio.txrx_worker);
836c92544dSBjoern A. Zeeb
846c92544dSBjoern A. Zeeb mt7921s_disable_irq(&dev->mt76);
856c92544dSBjoern A. Zeeb mt7921s_wfsys_reset(dev);
866c92544dSBjoern A. Zeeb
876c92544dSBjoern A. Zeeb mt76_worker_enable(&dev->mt76.sdio.txrx_worker);
886c92544dSBjoern A. Zeeb clear_bit(MT76_MCU_RESET, &dev->mphy.state);
896c92544dSBjoern A. Zeeb mt7921s_enable_irq(&dev->mt76);
906c92544dSBjoern A. Zeeb
916c92544dSBjoern A. Zeeb return 0;
926c92544dSBjoern A. Zeeb }
936c92544dSBjoern A. Zeeb
mt7921s_mac_reset(struct mt792x_dev * dev)94cbb3ec25SBjoern A. Zeeb int mt7921s_mac_reset(struct mt792x_dev *dev)
956c92544dSBjoern A. Zeeb {
966c92544dSBjoern A. Zeeb int err;
976c92544dSBjoern A. Zeeb
986c92544dSBjoern A. Zeeb mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
996c92544dSBjoern A. Zeeb mt76_txq_schedule_all(&dev->mphy);
1006c92544dSBjoern A. Zeeb mt76_worker_disable(&dev->mt76.tx_worker);
1016c92544dSBjoern A. Zeeb set_bit(MT76_MCU_RESET, &dev->mphy.state);
1026c92544dSBjoern A. Zeeb wake_up(&dev->mt76.mcu.wait);
1036c92544dSBjoern A. Zeeb skb_queue_purge(&dev->mt76.mcu.res_q);
1046c92544dSBjoern A. Zeeb wait_event_timeout(dev->mt76.sdio.wait,
1056c92544dSBjoern A. Zeeb mt76s_txqs_empty(&dev->mt76), 5 * HZ);
1066c92544dSBjoern A. Zeeb mt76_worker_disable(&dev->mt76.sdio.txrx_worker);
1076c92544dSBjoern A. Zeeb mt76_worker_disable(&dev->mt76.sdio.status_worker);
1086c92544dSBjoern A. Zeeb mt76_worker_disable(&dev->mt76.sdio.net_worker);
109*8ba4d145SBjoern A. Zeeb mt76_worker_disable(&dev->mt76.sdio.stat_worker);
1106c92544dSBjoern A. Zeeb
1116c92544dSBjoern A. Zeeb mt7921s_disable_irq(&dev->mt76);
1126c92544dSBjoern A. Zeeb mt7921s_wfsys_reset(dev);
1136c92544dSBjoern A. Zeeb
1146c92544dSBjoern A. Zeeb mt76_worker_enable(&dev->mt76.sdio.txrx_worker);
1156c92544dSBjoern A. Zeeb mt76_worker_enable(&dev->mt76.sdio.status_worker);
1166c92544dSBjoern A. Zeeb mt76_worker_enable(&dev->mt76.sdio.net_worker);
117*8ba4d145SBjoern A. Zeeb mt76_worker_enable(&dev->mt76.sdio.stat_worker);
1186c92544dSBjoern A. Zeeb
1196c92544dSBjoern A. Zeeb dev->fw_assert = false;
1206c92544dSBjoern A. Zeeb clear_bit(MT76_MCU_RESET, &dev->mphy.state);
1216c92544dSBjoern A. Zeeb mt7921s_enable_irq(&dev->mt76);
1226c92544dSBjoern A. Zeeb
1236c92544dSBjoern A. Zeeb err = mt7921_run_firmware(dev);
1246c92544dSBjoern A. Zeeb if (err)
1256c92544dSBjoern A. Zeeb goto out;
1266c92544dSBjoern A. Zeeb
1276c92544dSBjoern A. Zeeb err = mt7921_mcu_set_eeprom(dev);
1286c92544dSBjoern A. Zeeb if (err)
1296c92544dSBjoern A. Zeeb goto out;
1306c92544dSBjoern A. Zeeb
1316c92544dSBjoern A. Zeeb err = mt7921_mac_init(dev);
1326c92544dSBjoern A. Zeeb if (err)
1336c92544dSBjoern A. Zeeb goto out;
1346c92544dSBjoern A. Zeeb
1356c92544dSBjoern A. Zeeb err = __mt7921_start(&dev->phy);
1366c92544dSBjoern A. Zeeb out:
1376c92544dSBjoern A. Zeeb
1386c92544dSBjoern A. Zeeb mt76_worker_enable(&dev->mt76.tx_worker);
1396c92544dSBjoern A. Zeeb
1406c92544dSBjoern A. Zeeb return err;
1416c92544dSBjoern A. Zeeb }
142