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