MAINTAINERS: Remove Noralf Trønnes as driver maintainer
[drm/drm-misc.git] / drivers / net / wireless / mediatek / mt76 / mt7921 / sdio_mac.c
blob1f77cf71ca701a65b2f02e060d8c39963fcb705a
1 // SPDX-License-Identifier: ISC
2 /* Copyright (C) 2021 MediaTek Inc. */
4 #include <linux/iopoll.h>
5 #include <linux/mmc/sdio_func.h>
6 #include "mt7921.h"
7 #include "../mt76_connac2_mac.h"
8 #include "../sdio.h"
10 static void mt7921s_enable_irq(struct mt76_dev *dev)
12 struct mt76_sdio *sdio = &dev->sdio;
14 sdio_claim_host(sdio->func);
15 sdio_writel(sdio->func, WHLPCR_INT_EN_SET, MCR_WHLPCR, NULL);
16 sdio_release_host(sdio->func);
19 static void mt7921s_disable_irq(struct mt76_dev *dev)
21 struct mt76_sdio *sdio = &dev->sdio;
23 sdio_claim_host(sdio->func);
24 sdio_writel(sdio->func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, NULL);
25 sdio_release_host(sdio->func);
28 static u32 mt7921s_read_whcr(struct mt76_dev *dev)
30 return sdio_readl(dev->sdio.func, MCR_WHCR, NULL);
33 int mt7921s_wfsys_reset(struct mt792x_dev *dev)
35 struct mt76_sdio *sdio = &dev->mt76.sdio;
36 u32 val, status;
38 mt7921s_mcu_drv_pmctrl(dev);
40 sdio_claim_host(sdio->func);
42 val = sdio_readl(sdio->func, MCR_WHCR, NULL);
43 val &= ~WF_WHOLE_PATH_RSTB;
44 sdio_writel(sdio->func, val, MCR_WHCR, NULL);
46 msleep(50);
48 val = sdio_readl(sdio->func, MCR_WHCR, NULL);
49 val &= ~WF_SDIO_WF_PATH_RSTB;
50 sdio_writel(sdio->func, val, MCR_WHCR, NULL);
52 usleep_range(1000, 2000);
54 val = sdio_readl(sdio->func, MCR_WHCR, NULL);
55 val |= WF_WHOLE_PATH_RSTB;
56 sdio_writel(sdio->func, val, MCR_WHCR, NULL);
58 readx_poll_timeout(mt7921s_read_whcr, &dev->mt76, status,
59 status & WF_RST_DONE, 50000, 2000000);
61 sdio_release_host(sdio->func);
63 clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
65 /* activate mt7921s again */
66 mt7921s_mcu_drv_pmctrl(dev);
67 mt76_clear(dev, MT_CONN_STATUS, MT_WIFI_PATCH_DL_STATE);
68 mt7921s_mcu_fw_pmctrl(dev);
69 mt7921s_mcu_drv_pmctrl(dev);
71 return 0;
74 int mt7921s_init_reset(struct mt792x_dev *dev)
76 set_bit(MT76_MCU_RESET, &dev->mphy.state);
78 wake_up(&dev->mt76.mcu.wait);
79 skb_queue_purge(&dev->mt76.mcu.res_q);
80 wait_event_timeout(dev->mt76.sdio.wait,
81 mt76s_txqs_empty(&dev->mt76), 5 * HZ);
82 mt76_worker_disable(&dev->mt76.sdio.txrx_worker);
84 mt7921s_disable_irq(&dev->mt76);
85 mt7921s_wfsys_reset(dev);
87 mt76_worker_enable(&dev->mt76.sdio.txrx_worker);
88 clear_bit(MT76_MCU_RESET, &dev->mphy.state);
89 mt7921s_enable_irq(&dev->mt76);
91 return 0;
94 int mt7921s_mac_reset(struct mt792x_dev *dev)
96 int err;
98 mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
99 mt76_txq_schedule_all(&dev->mphy);
100 mt76_worker_disable(&dev->mt76.tx_worker);
101 set_bit(MT76_MCU_RESET, &dev->mphy.state);
102 wake_up(&dev->mt76.mcu.wait);
103 skb_queue_purge(&dev->mt76.mcu.res_q);
104 wait_event_timeout(dev->mt76.sdio.wait,
105 mt76s_txqs_empty(&dev->mt76), 5 * HZ);
106 mt76_worker_disable(&dev->mt76.sdio.txrx_worker);
107 mt76_worker_disable(&dev->mt76.sdio.status_worker);
108 mt76_worker_disable(&dev->mt76.sdio.net_worker);
109 mt76_worker_disable(&dev->mt76.sdio.stat_worker);
111 mt7921s_disable_irq(&dev->mt76);
112 mt7921s_wfsys_reset(dev);
114 mt76_worker_enable(&dev->mt76.sdio.txrx_worker);
115 mt76_worker_enable(&dev->mt76.sdio.status_worker);
116 mt76_worker_enable(&dev->mt76.sdio.net_worker);
117 mt76_worker_enable(&dev->mt76.sdio.stat_worker);
119 dev->fw_assert = false;
120 clear_bit(MT76_MCU_RESET, &dev->mphy.state);
121 mt7921s_enable_irq(&dev->mt76);
123 err = mt7921_run_firmware(dev);
124 if (err)
125 goto out;
127 err = mt7921_mcu_set_eeprom(dev);
128 if (err)
129 goto out;
131 err = mt7921_mac_init(dev);
132 if (err)
133 goto out;
135 err = __mt7921_start(&dev->phy);
136 out:
138 mt76_worker_enable(&dev->mt76.tx_worker);
140 return err;