xref: /freebsd/sys/contrib/dev/mediatek/mt76/mt7921/sdio.c (revision 6c92544d7c9722a3fe6263134938d1f864c158c5)
1*6c92544dSBjoern A. Zeeb // SPDX-License-Identifier: ISC
2*6c92544dSBjoern A. Zeeb /* Copyright (C) 2021 MediaTek Inc.
3*6c92544dSBjoern A. Zeeb  *
4*6c92544dSBjoern A. Zeeb  */
5*6c92544dSBjoern A. Zeeb 
6*6c92544dSBjoern A. Zeeb #include <linux/kernel.h>
7*6c92544dSBjoern A. Zeeb #include <linux/iopoll.h>
8*6c92544dSBjoern A. Zeeb #include <linux/module.h>
9*6c92544dSBjoern A. Zeeb 
10*6c92544dSBjoern A. Zeeb #include <linux/mmc/host.h>
11*6c92544dSBjoern A. Zeeb #include <linux/mmc/sdio_ids.h>
12*6c92544dSBjoern A. Zeeb #include <linux/mmc/sdio_func.h>
13*6c92544dSBjoern A. Zeeb 
14*6c92544dSBjoern A. Zeeb #include "mt7921.h"
15*6c92544dSBjoern A. Zeeb #include "../sdio.h"
16*6c92544dSBjoern A. Zeeb #include "mac.h"
17*6c92544dSBjoern A. Zeeb #include "mcu.h"
18*6c92544dSBjoern A. Zeeb 
19*6c92544dSBjoern A. Zeeb static const struct sdio_device_id mt7921s_table[] = {
20*6c92544dSBjoern A. Zeeb 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MEDIATEK, 0x7901) },
21*6c92544dSBjoern A. Zeeb 	{ }	/* Terminating entry */
22*6c92544dSBjoern A. Zeeb };
23*6c92544dSBjoern A. Zeeb 
24*6c92544dSBjoern A. Zeeb static void mt7921s_txrx_worker(struct mt76_worker *w)
25*6c92544dSBjoern A. Zeeb {
26*6c92544dSBjoern A. Zeeb 	struct mt76_sdio *sdio = container_of(w, struct mt76_sdio,
27*6c92544dSBjoern A. Zeeb 					      txrx_worker);
28*6c92544dSBjoern A. Zeeb 	struct mt76_dev *mdev = container_of(sdio, struct mt76_dev, sdio);
29*6c92544dSBjoern A. Zeeb 	struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
30*6c92544dSBjoern A. Zeeb 
31*6c92544dSBjoern A. Zeeb 	if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) {
32*6c92544dSBjoern A. Zeeb 		queue_work(mdev->wq, &dev->pm.wake_work);
33*6c92544dSBjoern A. Zeeb 		return;
34*6c92544dSBjoern A. Zeeb 	}
35*6c92544dSBjoern A. Zeeb 
36*6c92544dSBjoern A. Zeeb 	mt76s_txrx_worker(sdio);
37*6c92544dSBjoern A. Zeeb 	mt76_connac_pm_unref(&dev->mphy, &dev->pm);
38*6c92544dSBjoern A. Zeeb }
39*6c92544dSBjoern A. Zeeb 
40*6c92544dSBjoern A. Zeeb static void mt7921s_unregister_device(struct mt7921_dev *dev)
41*6c92544dSBjoern A. Zeeb {
42*6c92544dSBjoern A. Zeeb 	struct mt76_connac_pm *pm = &dev->pm;
43*6c92544dSBjoern A. Zeeb 
44*6c92544dSBjoern A. Zeeb 	cancel_work_sync(&dev->init_work);
45*6c92544dSBjoern A. Zeeb 	mt76_unregister_device(&dev->mt76);
46*6c92544dSBjoern A. Zeeb 	cancel_delayed_work_sync(&pm->ps_work);
47*6c92544dSBjoern A. Zeeb 	cancel_work_sync(&pm->wake_work);
48*6c92544dSBjoern A. Zeeb 
49*6c92544dSBjoern A. Zeeb 	mt76s_deinit(&dev->mt76);
50*6c92544dSBjoern A. Zeeb 	mt7921s_wfsys_reset(dev);
51*6c92544dSBjoern A. Zeeb 	skb_queue_purge(&dev->mt76.mcu.res_q);
52*6c92544dSBjoern A. Zeeb 
53*6c92544dSBjoern A. Zeeb 	mt76_free_device(&dev->mt76);
54*6c92544dSBjoern A. Zeeb }
55*6c92544dSBjoern A. Zeeb 
56*6c92544dSBjoern A. Zeeb static int mt7921s_parse_intr(struct mt76_dev *dev, struct mt76s_intr *intr)
57*6c92544dSBjoern A. Zeeb {
58*6c92544dSBjoern A. Zeeb 	struct mt76_sdio *sdio = &dev->sdio;
59*6c92544dSBjoern A. Zeeb 	struct mt7921_sdio_intr *irq_data = sdio->intr_data;
60*6c92544dSBjoern A. Zeeb 	int i, err;
61*6c92544dSBjoern A. Zeeb 
62*6c92544dSBjoern A. Zeeb 	sdio_claim_host(sdio->func);
63*6c92544dSBjoern A. Zeeb 	err = sdio_readsb(sdio->func, irq_data, MCR_WHISR, sizeof(*irq_data));
64*6c92544dSBjoern A. Zeeb 	sdio_release_host(sdio->func);
65*6c92544dSBjoern A. Zeeb 
66*6c92544dSBjoern A. Zeeb 	if (err < 0)
67*6c92544dSBjoern A. Zeeb 		return err;
68*6c92544dSBjoern A. Zeeb 
69*6c92544dSBjoern A. Zeeb 	if (irq_data->rx.num[0] > 16 ||
70*6c92544dSBjoern A. Zeeb 	    irq_data->rx.num[1] > 128)
71*6c92544dSBjoern A. Zeeb 		return -EINVAL;
72*6c92544dSBjoern A. Zeeb 
73*6c92544dSBjoern A. Zeeb 	intr->isr = irq_data->isr;
74*6c92544dSBjoern A. Zeeb 	intr->rec_mb = irq_data->rec_mb;
75*6c92544dSBjoern A. Zeeb 	intr->tx.wtqcr = irq_data->tx.wtqcr;
76*6c92544dSBjoern A. Zeeb 	intr->rx.num = irq_data->rx.num;
77*6c92544dSBjoern A. Zeeb 	for (i = 0; i < 2 ; i++) {
78*6c92544dSBjoern A. Zeeb 		if (!i)
79*6c92544dSBjoern A. Zeeb 			intr->rx.len[0] = irq_data->rx.len0;
80*6c92544dSBjoern A. Zeeb 		else
81*6c92544dSBjoern A. Zeeb 			intr->rx.len[1] = irq_data->rx.len1;
82*6c92544dSBjoern A. Zeeb 	}
83*6c92544dSBjoern A. Zeeb 
84*6c92544dSBjoern A. Zeeb 	return 0;
85*6c92544dSBjoern A. Zeeb }
86*6c92544dSBjoern A. Zeeb 
87*6c92544dSBjoern A. Zeeb static int mt7921s_probe(struct sdio_func *func,
88*6c92544dSBjoern A. Zeeb 			 const struct sdio_device_id *id)
89*6c92544dSBjoern A. Zeeb {
90*6c92544dSBjoern A. Zeeb 	static const struct mt76_driver_ops drv_ops = {
91*6c92544dSBjoern A. Zeeb 		.txwi_size = MT_SDIO_TXD_SIZE,
92*6c92544dSBjoern A. Zeeb 		.survey_flags = SURVEY_INFO_TIME_TX |
93*6c92544dSBjoern A. Zeeb 				SURVEY_INFO_TIME_RX |
94*6c92544dSBjoern A. Zeeb 				SURVEY_INFO_TIME_BSS_RX,
95*6c92544dSBjoern A. Zeeb 		.tx_prepare_skb = mt7921_usb_sdio_tx_prepare_skb,
96*6c92544dSBjoern A. Zeeb 		.tx_complete_skb = mt7921_usb_sdio_tx_complete_skb,
97*6c92544dSBjoern A. Zeeb 		.tx_status_data = mt7921_usb_sdio_tx_status_data,
98*6c92544dSBjoern A. Zeeb 		.rx_skb = mt7921_queue_rx_skb,
99*6c92544dSBjoern A. Zeeb 		.rx_check = mt7921_rx_check,
100*6c92544dSBjoern A. Zeeb 		.sta_ps = mt7921_sta_ps,
101*6c92544dSBjoern A. Zeeb 		.sta_add = mt7921_mac_sta_add,
102*6c92544dSBjoern A. Zeeb 		.sta_assoc = mt7921_mac_sta_assoc,
103*6c92544dSBjoern A. Zeeb 		.sta_remove = mt7921_mac_sta_remove,
104*6c92544dSBjoern A. Zeeb 		.update_survey = mt7921_update_channel,
105*6c92544dSBjoern A. Zeeb 	};
106*6c92544dSBjoern A. Zeeb 	static const struct mt76_bus_ops mt7921s_ops = {
107*6c92544dSBjoern A. Zeeb 		.rr = mt76s_rr,
108*6c92544dSBjoern A. Zeeb 		.rmw = mt76s_rmw,
109*6c92544dSBjoern A. Zeeb 		.wr = mt76s_wr,
110*6c92544dSBjoern A. Zeeb 		.write_copy = mt76s_write_copy,
111*6c92544dSBjoern A. Zeeb 		.read_copy = mt76s_read_copy,
112*6c92544dSBjoern A. Zeeb 		.wr_rp = mt76s_wr_rp,
113*6c92544dSBjoern A. Zeeb 		.rd_rp = mt76s_rd_rp,
114*6c92544dSBjoern A. Zeeb 		.type = MT76_BUS_SDIO,
115*6c92544dSBjoern A. Zeeb 	};
116*6c92544dSBjoern A. Zeeb 	static const struct mt7921_hif_ops mt7921_sdio_ops = {
117*6c92544dSBjoern A. Zeeb 		.init_reset = mt7921s_init_reset,
118*6c92544dSBjoern A. Zeeb 		.reset = mt7921s_mac_reset,
119*6c92544dSBjoern A. Zeeb 		.mcu_init = mt7921s_mcu_init,
120*6c92544dSBjoern A. Zeeb 		.drv_own = mt7921s_mcu_drv_pmctrl,
121*6c92544dSBjoern A. Zeeb 		.fw_own = mt7921s_mcu_fw_pmctrl,
122*6c92544dSBjoern A. Zeeb 	};
123*6c92544dSBjoern A. Zeeb 
124*6c92544dSBjoern A. Zeeb 	struct mt7921_dev *dev;
125*6c92544dSBjoern A. Zeeb 	struct mt76_dev *mdev;
126*6c92544dSBjoern A. Zeeb 	int ret;
127*6c92544dSBjoern A. Zeeb 
128*6c92544dSBjoern A. Zeeb 	mdev = mt76_alloc_device(&func->dev, sizeof(*dev), &mt7921_ops,
129*6c92544dSBjoern A. Zeeb 				 &drv_ops);
130*6c92544dSBjoern A. Zeeb 	if (!mdev)
131*6c92544dSBjoern A. Zeeb 		return -ENOMEM;
132*6c92544dSBjoern A. Zeeb 
133*6c92544dSBjoern A. Zeeb 	dev = container_of(mdev, struct mt7921_dev, mt76);
134*6c92544dSBjoern A. Zeeb 	dev->hif_ops = &mt7921_sdio_ops;
135*6c92544dSBjoern A. Zeeb 
136*6c92544dSBjoern A. Zeeb 	sdio_set_drvdata(func, dev);
137*6c92544dSBjoern A. Zeeb 
138*6c92544dSBjoern A. Zeeb 	ret = mt76s_init(mdev, func, &mt7921s_ops);
139*6c92544dSBjoern A. Zeeb 	if (ret < 0)
140*6c92544dSBjoern A. Zeeb 		goto error;
141*6c92544dSBjoern A. Zeeb 
142*6c92544dSBjoern A. Zeeb 	ret = mt76s_hw_init(mdev, func, MT76_CONNAC2_SDIO);
143*6c92544dSBjoern A. Zeeb 	if (ret)
144*6c92544dSBjoern A. Zeeb 		goto error;
145*6c92544dSBjoern A. Zeeb 
146*6c92544dSBjoern A. Zeeb 	mdev->rev = (mt76_rr(dev, MT_HW_CHIPID) << 16) |
147*6c92544dSBjoern A. Zeeb 		    (mt76_rr(dev, MT_HW_REV) & 0xff);
148*6c92544dSBjoern A. Zeeb 	dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
149*6c92544dSBjoern A. Zeeb 
150*6c92544dSBjoern A. Zeeb 	mdev->sdio.parse_irq = mt7921s_parse_intr;
151*6c92544dSBjoern A. Zeeb 	mdev->sdio.intr_data = devm_kmalloc(mdev->dev,
152*6c92544dSBjoern A. Zeeb 					    sizeof(struct mt7921_sdio_intr),
153*6c92544dSBjoern A. Zeeb 					    GFP_KERNEL);
154*6c92544dSBjoern A. Zeeb 	if (!mdev->sdio.intr_data) {
155*6c92544dSBjoern A. Zeeb 		ret = -ENOMEM;
156*6c92544dSBjoern A. Zeeb 		goto error;
157*6c92544dSBjoern A. Zeeb 	}
158*6c92544dSBjoern A. Zeeb 
159*6c92544dSBjoern A. Zeeb 	ret = mt76s_alloc_rx_queue(mdev, MT_RXQ_MAIN);
160*6c92544dSBjoern A. Zeeb 	if (ret)
161*6c92544dSBjoern A. Zeeb 		goto error;
162*6c92544dSBjoern A. Zeeb 
163*6c92544dSBjoern A. Zeeb 	ret = mt76s_alloc_rx_queue(mdev, MT_RXQ_MCU);
164*6c92544dSBjoern A. Zeeb 	if (ret)
165*6c92544dSBjoern A. Zeeb 		goto error;
166*6c92544dSBjoern A. Zeeb 
167*6c92544dSBjoern A. Zeeb 	ret = mt76s_alloc_tx(mdev);
168*6c92544dSBjoern A. Zeeb 	if (ret)
169*6c92544dSBjoern A. Zeeb 		goto error;
170*6c92544dSBjoern A. Zeeb 
171*6c92544dSBjoern A. Zeeb 	ret = mt76_worker_setup(mt76_hw(dev), &mdev->sdio.txrx_worker,
172*6c92544dSBjoern A. Zeeb 				mt7921s_txrx_worker, "sdio-txrx");
173*6c92544dSBjoern A. Zeeb 	if (ret)
174*6c92544dSBjoern A. Zeeb 		goto error;
175*6c92544dSBjoern A. Zeeb 
176*6c92544dSBjoern A. Zeeb 	sched_set_fifo_low(mdev->sdio.txrx_worker.task);
177*6c92544dSBjoern A. Zeeb 
178*6c92544dSBjoern A. Zeeb 	ret = mt7921_register_device(dev);
179*6c92544dSBjoern A. Zeeb 	if (ret)
180*6c92544dSBjoern A. Zeeb 		goto error;
181*6c92544dSBjoern A. Zeeb 
182*6c92544dSBjoern A. Zeeb 	return 0;
183*6c92544dSBjoern A. Zeeb 
184*6c92544dSBjoern A. Zeeb error:
185*6c92544dSBjoern A. Zeeb 	mt76s_deinit(&dev->mt76);
186*6c92544dSBjoern A. Zeeb 	mt76_free_device(&dev->mt76);
187*6c92544dSBjoern A. Zeeb 
188*6c92544dSBjoern A. Zeeb 	return ret;
189*6c92544dSBjoern A. Zeeb }
190*6c92544dSBjoern A. Zeeb 
191*6c92544dSBjoern A. Zeeb static void mt7921s_remove(struct sdio_func *func)
192*6c92544dSBjoern A. Zeeb {
193*6c92544dSBjoern A. Zeeb 	struct mt7921_dev *dev = sdio_get_drvdata(func);
194*6c92544dSBjoern A. Zeeb 
195*6c92544dSBjoern A. Zeeb 	mt7921s_unregister_device(dev);
196*6c92544dSBjoern A. Zeeb }
197*6c92544dSBjoern A. Zeeb 
198*6c92544dSBjoern A. Zeeb static int mt7921s_suspend(struct device *__dev)
199*6c92544dSBjoern A. Zeeb {
200*6c92544dSBjoern A. Zeeb 	struct sdio_func *func = dev_to_sdio_func(__dev);
201*6c92544dSBjoern A. Zeeb 	struct mt7921_dev *dev = sdio_get_drvdata(func);
202*6c92544dSBjoern A. Zeeb 	struct mt76_connac_pm *pm = &dev->pm;
203*6c92544dSBjoern A. Zeeb 	struct mt76_dev *mdev = &dev->mt76;
204*6c92544dSBjoern A. Zeeb 	int err;
205*6c92544dSBjoern A. Zeeb 
206*6c92544dSBjoern A. Zeeb 	pm->suspended = true;
207*6c92544dSBjoern A. Zeeb 	set_bit(MT76_STATE_SUSPEND, &mdev->phy.state);
208*6c92544dSBjoern A. Zeeb 
209*6c92544dSBjoern A. Zeeb 	flush_work(&dev->reset_work);
210*6c92544dSBjoern A. Zeeb 	cancel_delayed_work_sync(&pm->ps_work);
211*6c92544dSBjoern A. Zeeb 	cancel_work_sync(&pm->wake_work);
212*6c92544dSBjoern A. Zeeb 
213*6c92544dSBjoern A. Zeeb 	err = mt7921_mcu_drv_pmctrl(dev);
214*6c92544dSBjoern A. Zeeb 	if (err < 0)
215*6c92544dSBjoern A. Zeeb 		goto restore_suspend;
216*6c92544dSBjoern A. Zeeb 
217*6c92544dSBjoern A. Zeeb 	/* always enable deep sleep during suspend to reduce
218*6c92544dSBjoern A. Zeeb 	 * power consumption
219*6c92544dSBjoern A. Zeeb 	 */
220*6c92544dSBjoern A. Zeeb 	mt76_connac_mcu_set_deep_sleep(mdev, true);
221*6c92544dSBjoern A. Zeeb 
222*6c92544dSBjoern A. Zeeb 	mt76_txq_schedule_all(&dev->mphy);
223*6c92544dSBjoern A. Zeeb 	mt76_worker_disable(&mdev->tx_worker);
224*6c92544dSBjoern A. Zeeb 	mt76_worker_disable(&mdev->sdio.status_worker);
225*6c92544dSBjoern A. Zeeb 	cancel_work_sync(&mdev->sdio.stat_work);
226*6c92544dSBjoern A. Zeeb 	clear_bit(MT76_READING_STATS, &dev->mphy.state);
227*6c92544dSBjoern A. Zeeb 	mt76_tx_status_check(mdev, true);
228*6c92544dSBjoern A. Zeeb 
229*6c92544dSBjoern A. Zeeb 	mt76_worker_schedule(&mdev->sdio.txrx_worker);
230*6c92544dSBjoern A. Zeeb 	wait_event_timeout(dev->mt76.sdio.wait,
231*6c92544dSBjoern A. Zeeb 			   mt76s_txqs_empty(&dev->mt76), 5 * HZ);
232*6c92544dSBjoern A. Zeeb 
233*6c92544dSBjoern A. Zeeb 	/* It is supposed that SDIO bus is idle at the point */
234*6c92544dSBjoern A. Zeeb 	err = mt76_connac_mcu_set_hif_suspend(mdev, true);
235*6c92544dSBjoern A. Zeeb 	if (err)
236*6c92544dSBjoern A. Zeeb 		goto restore_worker;
237*6c92544dSBjoern A. Zeeb 
238*6c92544dSBjoern A. Zeeb 	mt76_worker_disable(&mdev->sdio.txrx_worker);
239*6c92544dSBjoern A. Zeeb 	mt76_worker_disable(&mdev->sdio.net_worker);
240*6c92544dSBjoern A. Zeeb 
241*6c92544dSBjoern A. Zeeb 	err = mt7921_mcu_fw_pmctrl(dev);
242*6c92544dSBjoern A. Zeeb 	if (err)
243*6c92544dSBjoern A. Zeeb 		goto restore_txrx_worker;
244*6c92544dSBjoern A. Zeeb 
245*6c92544dSBjoern A. Zeeb 	sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
246*6c92544dSBjoern A. Zeeb 
247*6c92544dSBjoern A. Zeeb 	return 0;
248*6c92544dSBjoern A. Zeeb 
249*6c92544dSBjoern A. Zeeb restore_txrx_worker:
250*6c92544dSBjoern A. Zeeb 	mt76_worker_enable(&mdev->sdio.net_worker);
251*6c92544dSBjoern A. Zeeb 	mt76_worker_enable(&mdev->sdio.txrx_worker);
252*6c92544dSBjoern A. Zeeb 	mt76_connac_mcu_set_hif_suspend(mdev, false);
253*6c92544dSBjoern A. Zeeb 
254*6c92544dSBjoern A. Zeeb restore_worker:
255*6c92544dSBjoern A. Zeeb 	mt76_worker_enable(&mdev->tx_worker);
256*6c92544dSBjoern A. Zeeb 	mt76_worker_enable(&mdev->sdio.status_worker);
257*6c92544dSBjoern A. Zeeb 
258*6c92544dSBjoern A. Zeeb 	if (!pm->ds_enable)
259*6c92544dSBjoern A. Zeeb 		mt76_connac_mcu_set_deep_sleep(mdev, false);
260*6c92544dSBjoern A. Zeeb 
261*6c92544dSBjoern A. Zeeb restore_suspend:
262*6c92544dSBjoern A. Zeeb 	clear_bit(MT76_STATE_SUSPEND, &mdev->phy.state);
263*6c92544dSBjoern A. Zeeb 	pm->suspended = false;
264*6c92544dSBjoern A. Zeeb 
265*6c92544dSBjoern A. Zeeb 	if (err < 0)
266*6c92544dSBjoern A. Zeeb 		mt7921_reset(&dev->mt76);
267*6c92544dSBjoern A. Zeeb 
268*6c92544dSBjoern A. Zeeb 	return err;
269*6c92544dSBjoern A. Zeeb }
270*6c92544dSBjoern A. Zeeb 
271*6c92544dSBjoern A. Zeeb static int mt7921s_resume(struct device *__dev)
272*6c92544dSBjoern A. Zeeb {
273*6c92544dSBjoern A. Zeeb 	struct sdio_func *func = dev_to_sdio_func(__dev);
274*6c92544dSBjoern A. Zeeb 	struct mt7921_dev *dev = sdio_get_drvdata(func);
275*6c92544dSBjoern A. Zeeb 	struct mt76_connac_pm *pm = &dev->pm;
276*6c92544dSBjoern A. Zeeb 	struct mt76_dev *mdev = &dev->mt76;
277*6c92544dSBjoern A. Zeeb 	int err;
278*6c92544dSBjoern A. Zeeb 
279*6c92544dSBjoern A. Zeeb 	clear_bit(MT76_STATE_SUSPEND, &mdev->phy.state);
280*6c92544dSBjoern A. Zeeb 
281*6c92544dSBjoern A. Zeeb 	err = mt7921_mcu_drv_pmctrl(dev);
282*6c92544dSBjoern A. Zeeb 	if (err < 0)
283*6c92544dSBjoern A. Zeeb 		goto failed;
284*6c92544dSBjoern A. Zeeb 
285*6c92544dSBjoern A. Zeeb 	mt76_worker_enable(&mdev->tx_worker);
286*6c92544dSBjoern A. Zeeb 	mt76_worker_enable(&mdev->sdio.txrx_worker);
287*6c92544dSBjoern A. Zeeb 	mt76_worker_enable(&mdev->sdio.status_worker);
288*6c92544dSBjoern A. Zeeb 	mt76_worker_enable(&mdev->sdio.net_worker);
289*6c92544dSBjoern A. Zeeb 
290*6c92544dSBjoern A. Zeeb 	/* restore previous ds setting */
291*6c92544dSBjoern A. Zeeb 	if (!pm->ds_enable)
292*6c92544dSBjoern A. Zeeb 		mt76_connac_mcu_set_deep_sleep(mdev, false);
293*6c92544dSBjoern A. Zeeb 
294*6c92544dSBjoern A. Zeeb 	err = mt76_connac_mcu_set_hif_suspend(mdev, false);
295*6c92544dSBjoern A. Zeeb failed:
296*6c92544dSBjoern A. Zeeb 	pm->suspended = false;
297*6c92544dSBjoern A. Zeeb 
298*6c92544dSBjoern A. Zeeb 	if (err < 0)
299*6c92544dSBjoern A. Zeeb 		mt7921_reset(&dev->mt76);
300*6c92544dSBjoern A. Zeeb 
301*6c92544dSBjoern A. Zeeb 	return err;
302*6c92544dSBjoern A. Zeeb }
303*6c92544dSBjoern A. Zeeb 
304*6c92544dSBjoern A. Zeeb MODULE_DEVICE_TABLE(sdio, mt7921s_table);
305*6c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7921_FIRMWARE_WM);
306*6c92544dSBjoern A. Zeeb MODULE_FIRMWARE(MT7921_ROM_PATCH);
307*6c92544dSBjoern A. Zeeb 
308*6c92544dSBjoern A. Zeeb static DEFINE_SIMPLE_DEV_PM_OPS(mt7921s_pm_ops, mt7921s_suspend, mt7921s_resume);
309*6c92544dSBjoern A. Zeeb 
310*6c92544dSBjoern A. Zeeb static struct sdio_driver mt7921s_driver = {
311*6c92544dSBjoern A. Zeeb 	.name		= KBUILD_MODNAME,
312*6c92544dSBjoern A. Zeeb 	.probe		= mt7921s_probe,
313*6c92544dSBjoern A. Zeeb 	.remove		= mt7921s_remove,
314*6c92544dSBjoern A. Zeeb 	.id_table	= mt7921s_table,
315*6c92544dSBjoern A. Zeeb 	.drv.pm		= pm_sleep_ptr(&mt7921s_pm_ops),
316*6c92544dSBjoern A. Zeeb };
317*6c92544dSBjoern A. Zeeb module_sdio_driver(mt7921s_driver);
318*6c92544dSBjoern A. Zeeb MODULE_AUTHOR("Sean Wang <sean.wang@mediatek.com>");
319*6c92544dSBjoern A. Zeeb MODULE_LICENSE("Dual BSD/GPL");
320