1 // SPDX-License-Identifier: ISC 2 /* Copyright (C) 2021 MediaTek Inc. */ 3 4 #include <linux/kernel.h> 5 #include <linux/mmc/sdio_func.h> 6 #include <linux/module.h> 7 #include <linux/iopoll.h> 8 9 #include "mt7921.h" 10 #include "../sdio.h" 11 #include "mac.h" 12 #include "mcu.h" 13 #include "regs.h" 14 15 static int 16 mt7921s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, 17 int cmd, int *seq) 18 { 19 struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76); 20 enum mt7921_sdio_pkt_type type = MT7921_SDIO_CMD; 21 enum mt76_mcuq_id txq = MT_MCUQ_WM; 22 int ret, pad; 23 24 /* We just return in case firmware assertion to avoid blocking the 25 * common workqueue to run, for example, the coredump work might be 26 * blocked by mt7921_mac_work that is excuting register access via sdio 27 * bus. 28 */ 29 if (dev->fw_assert) 30 return -EBUSY; 31 32 ret = mt7921_mcu_fill_message(mdev, skb, cmd, seq); 33 if (ret) 34 return ret; 35 36 if (cmd == MCU_CMD(FW_SCATTER)) 37 type = MT7921_SDIO_FWDL; 38 39 mt7921_skb_add_usb_sdio_hdr(dev, skb, type); 40 pad = round_up(skb->len, 4) - skb->len; 41 __skb_put_zero(skb, pad); 42 43 ret = mt76_tx_queue_skb_raw(dev, mdev->q_mcu[txq], skb, 0); 44 if (ret) 45 return ret; 46 47 mt76_queue_kick(dev, mdev->q_mcu[txq]); 48 49 return ret; 50 } 51 52 static u32 mt7921s_read_rm3r(struct mt7921_dev *dev) 53 { 54 struct mt76_sdio *sdio = &dev->mt76.sdio; 55 56 return sdio_readl(sdio->func, MCR_D2HRM3R, NULL); 57 } 58 59 static u32 mt7921s_clear_rm3r_drv_own(struct mt7921_dev *dev) 60 { 61 struct mt76_sdio *sdio = &dev->mt76.sdio; 62 u32 val; 63 64 val = sdio_readl(sdio->func, MCR_D2HRM3R, NULL); 65 if (val) 66 sdio_writel(sdio->func, H2D_SW_INT_CLEAR_MAILBOX_ACK, 67 MCR_WSICR, NULL); 68 69 return val; 70 } 71 72 int mt7921s_mcu_init(struct mt7921_dev *dev) 73 { 74 static const struct mt76_mcu_ops mt7921s_mcu_ops = { 75 .headroom = MT_SDIO_HDR_SIZE + sizeof(struct mt7921_mcu_txd), 76 .tailroom = MT_SDIO_TAIL_SIZE, 77 .mcu_skb_send_msg = mt7921s_mcu_send_message, 78 .mcu_parse_response = mt7921_mcu_parse_response, 79 .mcu_rr = mt76_connac_mcu_reg_rr, 80 .mcu_wr = mt76_connac_mcu_reg_wr, 81 }; 82 int ret; 83 84 mt7921s_mcu_drv_pmctrl(dev); 85 86 dev->mt76.mcu_ops = &mt7921s_mcu_ops; 87 88 ret = mt7921_run_firmware(dev); 89 if (ret) 90 return ret; 91 92 set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); 93 94 return 0; 95 } 96 97 int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev) 98 { 99 struct sdio_func *func = dev->mt76.sdio.func; 100 struct mt76_phy *mphy = &dev->mt76.phy; 101 struct mt76_connac_pm *pm = &dev->pm; 102 int err = 0; 103 u32 status; 104 105 sdio_claim_host(func); 106 107 sdio_writel(func, WHLPCR_FW_OWN_REQ_CLR, MCR_WHLPCR, NULL); 108 109 err = readx_poll_timeout(mt76s_read_pcr, &dev->mt76, status, 110 status & WHLPCR_IS_DRIVER_OWN, 2000, 1000000); 111 112 if (!err && test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) 113 err = readx_poll_timeout(mt7921s_read_rm3r, dev, status, 114 status & D2HRM3R_IS_DRIVER_OWN, 115 2000, 1000000); 116 117 sdio_release_host(func); 118 119 if (err < 0) { 120 dev_err(dev->mt76.dev, "driver own failed\n"); 121 err = -EIO; 122 goto out; 123 } 124 125 clear_bit(MT76_STATE_PM, &mphy->state); 126 127 pm->stats.last_wake_event = jiffies; 128 pm->stats.doze_time += pm->stats.last_wake_event - 129 pm->stats.last_doze_event; 130 out: 131 return err; 132 } 133 134 int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev) 135 { 136 struct sdio_func *func = dev->mt76.sdio.func; 137 struct mt76_phy *mphy = &dev->mt76.phy; 138 struct mt76_connac_pm *pm = &dev->pm; 139 int err = 0; 140 u32 status; 141 142 sdio_claim_host(func); 143 144 if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) { 145 err = readx_poll_timeout(mt7921s_clear_rm3r_drv_own, 146 dev, status, 147 !(status & D2HRM3R_IS_DRIVER_OWN), 148 2000, 1000000); 149 if (err < 0) { 150 dev_err(dev->mt76.dev, "mailbox ACK not cleared\n"); 151 goto err; 152 } 153 } 154 155 sdio_writel(func, WHLPCR_FW_OWN_REQ_SET, MCR_WHLPCR, NULL); 156 157 err = readx_poll_timeout(mt76s_read_pcr, &dev->mt76, status, 158 !(status & WHLPCR_IS_DRIVER_OWN), 2000, 1000000); 159 sdio_release_host(func); 160 161 err: 162 if (err < 0) { 163 dev_err(dev->mt76.dev, "firmware own failed\n"); 164 clear_bit(MT76_STATE_PM, &mphy->state); 165 err = -EIO; 166 } 167 168 pm->stats.last_doze_event = jiffies; 169 pm->stats.awake_time += pm->stats.last_doze_event - 170 pm->stats.last_wake_event; 171 172 return err; 173 } 174