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