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