xref: /linux/drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c (revision 8be4d31cb8aaeea27bde4b7ddb26e28a89062ebf)
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