1 // SPDX-License-Identifier: ISC
2 /* Copyright (C) 2021 MediaTek Inc. */
3
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"
9 #include <linux/mmc/host.h>
10 #include <linux/kallsyms.h>
11
mt7921s_enable_irq(struct mt76_dev * dev)12 static void mt7921s_enable_irq(struct mt76_dev *dev)
13 {
14 struct mt76_sdio *sdio = &dev->sdio;
15
16 sdio_claim_host(sdio->func);
17 sdio_writel(sdio->func, WHLPCR_INT_EN_SET, MCR_WHLPCR, NULL);
18 sdio_release_host(sdio->func);
19 }
20
mt7921s_disable_irq(struct mt76_dev * dev)21 static void mt7921s_disable_irq(struct mt76_dev *dev)
22 {
23 struct mt76_sdio *sdio = &dev->sdio;
24
25 sdio_claim_host(sdio->func);
26 sdio_writel(sdio->func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, NULL);
27 sdio_release_host(sdio->func);
28 }
29
mt7921s_read_whcr(struct mt76_dev * dev)30 static u32 mt7921s_read_whcr(struct mt76_dev *dev)
31 {
32 return sdio_readl(dev->sdio.func, MCR_WHCR, NULL);
33 }
34
mt7921s_wfsys_reset(struct mt792x_dev * dev)35 int mt7921s_wfsys_reset(struct mt792x_dev *dev)
36 {
37 struct mt76_sdio *sdio = &dev->mt76.sdio;
38 u32 val, status;
39
40 if (atomic_read(&dev->mt76.bus_hung))
41 return 0;
42
43 mt7921s_mcu_drv_pmctrl(dev);
44
45 sdio_claim_host(sdio->func);
46
47 val = sdio_readl(sdio->func, MCR_WHCR, NULL);
48 val &= ~WF_WHOLE_PATH_RSTB;
49 sdio_writel(sdio->func, val, MCR_WHCR, NULL);
50
51 msleep(50);
52
53 val = sdio_readl(sdio->func, MCR_WHCR, NULL);
54 val &= ~WF_SDIO_WF_PATH_RSTB;
55 sdio_writel(sdio->func, val, MCR_WHCR, NULL);
56
57 usleep_range(1000, 2000);
58
59 val = sdio_readl(sdio->func, MCR_WHCR, NULL);
60 val |= WF_WHOLE_PATH_RSTB;
61 sdio_writel(sdio->func, val, MCR_WHCR, NULL);
62
63 readx_poll_timeout(mt7921s_read_whcr, &dev->mt76, status,
64 status & WF_RST_DONE, 50000, 2000000);
65
66 sdio_release_host(sdio->func);
67
68 clear_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
69
70 /* activate mt7921s again */
71 mt7921s_mcu_drv_pmctrl(dev);
72 mt76_clear(dev, MT_CONN_STATUS, MT_WIFI_PATCH_DL_STATE);
73 mt7921s_mcu_fw_pmctrl(dev);
74 mt7921s_mcu_drv_pmctrl(dev);
75
76 return 0;
77 }
78
mt7921s_init_reset(struct mt792x_dev * dev)79 int mt7921s_init_reset(struct mt792x_dev *dev)
80 {
81 set_bit(MT76_MCU_RESET, &dev->mphy.state);
82
83 wake_up(&dev->mt76.mcu.wait);
84 skb_queue_purge(&dev->mt76.mcu.res_q);
85 wait_event_timeout(dev->mt76.sdio.wait,
86 mt76s_txqs_empty(&dev->mt76), 5 * HZ);
87 mt76_worker_disable(&dev->mt76.sdio.txrx_worker);
88
89 mt7921s_disable_irq(&dev->mt76);
90 mt7921s_wfsys_reset(dev);
91
92 mt76_worker_enable(&dev->mt76.sdio.txrx_worker);
93 clear_bit(MT76_MCU_RESET, &dev->mphy.state);
94 mt7921s_enable_irq(&dev->mt76);
95
96 return 0;
97 }
98
99 static struct mt76_sdio *msdio;
mt7921s_card_reset(struct work_struct * work)100 static void mt7921s_card_reset(struct work_struct *work)
101 {
102 struct mmc_host *sdio_host = msdio->func->card->host;
103
104 sdio_claim_host(msdio->func);
105 sdio_release_irq(msdio->func);
106 sdio_release_host(msdio->func);
107
108 mmc_remove_host(sdio_host);
109 msleep(50);
110 mmc_add_host(sdio_host);
111 }
112
113 static DECLARE_WORK(sdio_reset_work, mt7921s_card_reset);
mt7921s_check_bus(struct mt76_dev * dev)114 static int mt7921s_check_bus(struct mt76_dev *dev)
115 {
116 struct mt76_sdio *sdio = &dev->sdio;
117 int err;
118
119 sdio_claim_host(sdio->func);
120 sdio_readl(dev->sdio.func, MCR_WHCR, &err);
121 sdio_release_host(sdio->func);
122
123 return err;
124 }
125
mt7921s_host_reset(struct mt792x_dev * dev)126 static int mt7921s_host_reset(struct mt792x_dev *dev)
127 {
128 struct mt76_dev *mdev = &dev->mt76;
129 int err = -1;
130
131 if (!atomic_read(&mdev->bus_hung))
132 err = mt7921s_check_bus(&dev->mt76);
133
134 if (err) {
135 atomic_set(&mdev->bus_hung, true);
136 msdio = &dev->mt76.sdio;
137 dev_err(mdev->dev, "SDIO bus problem detected(%d), resetting card!!\n", err);
138 schedule_work(&sdio_reset_work);
139 return err;
140 }
141
142 atomic_set(&mdev->bus_hung, false);
143
144 return 0;
145 }
146
mt7921s_mac_reset(struct mt792x_dev * dev)147 int mt7921s_mac_reset(struct mt792x_dev *dev)
148 {
149 int err;
150
151 mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);
152
153 mt7921s_host_reset(dev);
154 if (atomic_read(&dev->mt76.bus_hung))
155 return 0;
156
157 mt76_txq_schedule_all(&dev->mphy);
158 mt76_worker_disable(&dev->mt76.tx_worker);
159 set_bit(MT76_MCU_RESET, &dev->mphy.state);
160 wake_up(&dev->mt76.mcu.wait);
161 skb_queue_purge(&dev->mt76.mcu.res_q);
162 wait_event_timeout(dev->mt76.sdio.wait,
163 mt76s_txqs_empty(&dev->mt76), 5 * HZ);
164 mt76_worker_disable(&dev->mt76.sdio.txrx_worker);
165 mt76_worker_disable(&dev->mt76.sdio.status_worker);
166 mt76_worker_disable(&dev->mt76.sdio.net_worker);
167 mt76_worker_disable(&dev->mt76.sdio.stat_worker);
168
169 mt7921s_disable_irq(&dev->mt76);
170 mt7921s_wfsys_reset(dev);
171
172 mt76_worker_enable(&dev->mt76.sdio.txrx_worker);
173 mt76_worker_enable(&dev->mt76.sdio.status_worker);
174 mt76_worker_enable(&dev->mt76.sdio.net_worker);
175 mt76_worker_enable(&dev->mt76.sdio.stat_worker);
176
177 dev->fw_assert = false;
178 clear_bit(MT76_MCU_RESET, &dev->mphy.state);
179 mt7921s_enable_irq(&dev->mt76);
180
181 err = mt7921_run_firmware(dev);
182 if (err)
183 goto out;
184
185 err = mt7921_mcu_set_eeprom(dev);
186 if (err)
187 goto out;
188
189 err = mt7921_mac_init(dev);
190 if (err)
191 goto out;
192
193 err = __mt7921_start(&dev->phy);
194 out:
195
196 mt76_worker_enable(&dev->mt76.tx_worker);
197
198 return err;
199 }
200