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 = mt76_connac2_mcu_fill_message(mdev, skb, cmd, seq); 33 if (ret) 34 return ret; 35 36 mdev->mcu.timeout = 3 * HZ; 37 38 if (cmd == MCU_CMD(FW_SCATTER)) 39 type = MT7921_SDIO_FWDL; 40 41 mt7921_skb_add_usb_sdio_hdr(dev, skb, type); 42 pad = round_up(skb->len, 4) - skb->len; 43 __skb_put_zero(skb, pad); 44 45 ret = mt76_tx_queue_skb_raw(dev, mdev->q_mcu[txq], skb, 0); 46 if (ret) 47 return ret; 48 49 mt76_queue_kick(dev, mdev->q_mcu[txq]); 50 51 return ret; 52 } 53 54 static u32 mt7921s_read_rm3r(struct mt7921_dev *dev) 55 { 56 struct mt76_sdio *sdio = &dev->mt76.sdio; 57 58 return sdio_readl(sdio->func, MCR_D2HRM3R, NULL); 59 } 60 61 static u32 mt7921s_clear_rm3r_drv_own(struct mt7921_dev *dev) 62 { 63 struct mt76_sdio *sdio = &dev->mt76.sdio; 64 u32 val; 65 66 val = sdio_readl(sdio->func, MCR_D2HRM3R, NULL); 67 if (val) 68 sdio_writel(sdio->func, H2D_SW_INT_CLEAR_MAILBOX_ACK, 69 MCR_WSICR, NULL); 70 71 return val; 72 } 73 74 int mt7921s_mcu_init(struct mt7921_dev *dev) 75 { 76 static const struct mt76_mcu_ops mt7921s_mcu_ops = { 77 .headroom = MT_SDIO_HDR_SIZE + 78 sizeof(struct mt76_connac2_mcu_txd), 79 .tailroom = MT_SDIO_TAIL_SIZE, 80 .mcu_skb_send_msg = mt7921s_mcu_send_message, 81 .mcu_parse_response = mt7921_mcu_parse_response, 82 .mcu_rr = mt76_connac_mcu_reg_rr, 83 .mcu_wr = mt76_connac_mcu_reg_wr, 84 }; 85 int ret; 86 87 mt7921s_mcu_drv_pmctrl(dev); 88 89 dev->mt76.mcu_ops = &mt7921s_mcu_ops; 90 91 ret = mt7921_run_firmware(dev); 92 if (ret) 93 return ret; 94 95 set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); 96 97 return 0; 98 } 99 100 int mt7921s_mcu_drv_pmctrl(struct mt7921_dev *dev) 101 { 102 struct sdio_func *func = dev->mt76.sdio.func; 103 struct mt76_phy *mphy = &dev->mt76.phy; 104 struct mt76_connac_pm *pm = &dev->pm; 105 u32 status; 106 int err; 107 108 sdio_claim_host(func); 109 110 sdio_writel(func, WHLPCR_FW_OWN_REQ_CLR, MCR_WHLPCR, NULL); 111 112 err = readx_poll_timeout(mt76s_read_pcr, &dev->mt76, status, 113 status & WHLPCR_IS_DRIVER_OWN, 2000, 1000000); 114 115 if (!err && test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) 116 err = readx_poll_timeout(mt7921s_read_rm3r, dev, status, 117 status & D2HRM3R_IS_DRIVER_OWN, 118 2000, 1000000); 119 120 sdio_release_host(func); 121 122 if (err < 0) { 123 dev_err(dev->mt76.dev, "driver own failed\n"); 124 return -EIO; 125 } 126 127 clear_bit(MT76_STATE_PM, &mphy->state); 128 129 pm->stats.last_wake_event = jiffies; 130 pm->stats.doze_time += pm->stats.last_wake_event - 131 pm->stats.last_doze_event; 132 133 return 0; 134 } 135 136 int mt7921s_mcu_fw_pmctrl(struct mt7921_dev *dev) 137 { 138 struct sdio_func *func = dev->mt76.sdio.func; 139 struct mt76_phy *mphy = &dev->mt76.phy; 140 struct mt76_connac_pm *pm = &dev->pm; 141 u32 status; 142 int err; 143 144 sdio_claim_host(func); 145 146 if (test_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state)) { 147 err = readx_poll_timeout(mt7921s_clear_rm3r_drv_own, 148 dev, status, 149 !(status & D2HRM3R_IS_DRIVER_OWN), 150 2000, 1000000); 151 if (err < 0) { 152 dev_err(dev->mt76.dev, "mailbox ACK not cleared\n"); 153 goto out; 154 } 155 } 156 157 sdio_writel(func, WHLPCR_FW_OWN_REQ_SET, MCR_WHLPCR, NULL); 158 159 err = readx_poll_timeout(mt76s_read_pcr, &dev->mt76, status, 160 !(status & WHLPCR_IS_DRIVER_OWN), 2000, 1000000); 161 out: 162 sdio_release_host(func); 163 164 if (err < 0) { 165 dev_err(dev->mt76.dev, "firmware own failed\n"); 166 clear_bit(MT76_STATE_PM, &mphy->state); 167 return -EIO; 168 } 169 170 pm->stats.last_doze_event = jiffies; 171 pm->stats.awake_time += pm->stats.last_doze_event - 172 pm->stats.last_wake_event; 173 174 return 0; 175 } 176