1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2020 MediaTek Inc. 3 * 4 * Author: Felix Fietkau <nbd@nbd.name> 5 * Lorenzo Bianconi <lorenzo@kernel.org> 6 * Sean Wang <sean.wang@mediatek.com> 7 */ 8 #include <linux/kernel.h> 9 #include <linux/mmc/sdio_func.h> 10 #include <linux/module.h> 11 #include <linux/iopoll.h> 12 13 #include "mt7615.h" 14 #include "mac.h" 15 #include "mcu.h" 16 #include "regs.h" 17 #include "sdio.h" 18 19 static int mt7663s_mcu_init_sched(struct mt7615_dev *dev) 20 { 21 struct mt76_sdio *sdio = &dev->mt76.sdio; 22 u32 pse0, ple, pse1, txdwcnt; 23 24 pse0 = mt76_get_field(dev, MT_PSE_PG_HIF0_GROUP, MT_HIF0_MIN_QUOTA); 25 pse1 = mt76_get_field(dev, MT_PSE_PG_HIF1_GROUP, MT_HIF1_MIN_QUOTA); 26 ple = mt76_get_field(dev, MT_PLE_PG_HIF0_GROUP, MT_HIF0_MIN_QUOTA); 27 txdwcnt = mt76_get_field(dev, MT_PP_TXDWCNT, 28 MT_PP_TXDWCNT_TX1_ADD_DW_CNT); 29 30 mutex_lock(&sdio->sched.lock); 31 32 sdio->sched.pse_data_quota = pse0; 33 sdio->sched.ple_data_quota = ple; 34 sdio->sched.pse_mcu_quota = pse1; 35 sdio->sched.deficit = txdwcnt << 2; 36 37 mutex_unlock(&sdio->sched.lock); 38 39 return 0; 40 } 41 42 static int 43 mt7663s_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb, 44 int cmd, bool wait_resp) 45 { 46 struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); 47 int ret, seq; 48 49 mutex_lock(&mdev->mcu.mutex); 50 51 mt7615_mcu_fill_msg(dev, skb, cmd, &seq); 52 ret = mt76_tx_queue_skb_raw(dev, MT_TXQ_MCU, skb, 0); 53 if (ret) 54 goto out; 55 56 mt76_queue_kick(dev, mdev->q_tx[MT_TXQ_MCU].q); 57 if (wait_resp) 58 ret = mt7615_mcu_wait_response(dev, cmd, seq); 59 60 out: 61 mutex_unlock(&mdev->mcu.mutex); 62 63 return ret; 64 } 65 66 int mt7663s_driver_own(struct mt7615_dev *dev) 67 { 68 struct sdio_func *func = dev->mt76.sdio.func; 69 struct mt76_phy *mphy = &dev->mt76.phy; 70 u32 status; 71 int ret; 72 73 if (!test_and_clear_bit(MT76_STATE_PM, &mphy->state)) 74 goto out; 75 76 sdio_claim_host(func); 77 78 sdio_writel(func, WHLPCR_FW_OWN_REQ_CLR, MCR_WHLPCR, 0); 79 80 ret = readx_poll_timeout(mt7663s_read_pcr, dev, status, 81 status & WHLPCR_IS_DRIVER_OWN, 2000, 1000000); 82 if (ret < 0) { 83 dev_err(dev->mt76.dev, "Cannot get ownership from device"); 84 set_bit(MT76_STATE_PM, &mphy->state); 85 sdio_release_host(func); 86 87 return ret; 88 } 89 90 sdio_release_host(func); 91 92 out: 93 dev->pm.last_activity = jiffies; 94 95 return 0; 96 } 97 98 int mt7663s_firmware_own(struct mt7615_dev *dev) 99 { 100 struct sdio_func *func = dev->mt76.sdio.func; 101 struct mt76_phy *mphy = &dev->mt76.phy; 102 u32 status; 103 int ret; 104 105 if (test_and_set_bit(MT76_STATE_PM, &mphy->state)) 106 return 0; 107 108 sdio_claim_host(func); 109 110 sdio_writel(func, WHLPCR_FW_OWN_REQ_SET, MCR_WHLPCR, 0); 111 112 ret = readx_poll_timeout(mt7663s_read_pcr, dev, status, 113 !(status & WHLPCR_IS_DRIVER_OWN), 2000, 1000000); 114 if (ret < 0) { 115 dev_err(dev->mt76.dev, "Cannot set ownership to device"); 116 clear_bit(MT76_STATE_PM, &mphy->state); 117 } 118 119 sdio_release_host(func); 120 121 return ret; 122 } 123 124 int mt7663s_mcu_init(struct mt7615_dev *dev) 125 { 126 static const struct mt76_mcu_ops mt7663s_mcu_ops = { 127 .headroom = sizeof(struct mt7615_mcu_txd), 128 .tailroom = MT_USB_TAIL_SIZE, 129 .mcu_skb_send_msg = mt7663s_mcu_send_message, 130 .mcu_send_msg = mt7615_mcu_msg_send, 131 .mcu_restart = mt7615_mcu_restart, 132 .mcu_rr = mt7615_mcu_reg_rr, 133 .mcu_wr = mt7615_mcu_reg_wr, 134 }; 135 int ret; 136 137 ret = mt7663s_driver_own(dev); 138 if (ret) 139 return ret; 140 141 dev->mt76.mcu_ops = &mt7663s_mcu_ops, 142 143 ret = mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY); 144 if (ret) { 145 mt7615_mcu_restart(&dev->mt76); 146 if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, 147 MT_TOP_MISC2_FW_N9_RDY, 0, 500)) 148 return -EIO; 149 } 150 151 ret = __mt7663_load_firmware(dev); 152 if (ret) 153 return ret; 154 155 ret = mt7663s_mcu_init_sched(dev); 156 if (ret) 157 return ret; 158 159 set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state); 160 161 return 0; 162 } 163