1 // SPDX-License-Identifier: ISC 2 /* 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 5 */ 6 7 #include <linux/kernel.h> 8 #include <linux/firmware.h> 9 #include <linux/delay.h> 10 11 #include "mt76x02_mcu.h" 12 13 int mt76x02_mcu_msg_send(struct mt76_dev *mdev, int cmd, const void *data, 14 int len, bool wait_resp) 15 { 16 struct mt76x02_dev *dev = container_of(mdev, struct mt76x02_dev, mt76); 17 unsigned long expires = jiffies + HZ; 18 struct sk_buff *skb; 19 u32 tx_info; 20 int ret; 21 u8 seq; 22 23 if (dev->mcu_timeout) 24 return -EIO; 25 26 skb = mt76_mcu_msg_alloc(mdev, data, len); 27 if (!skb) 28 return -ENOMEM; 29 30 mutex_lock(&mdev->mcu.mutex); 31 32 seq = ++mdev->mcu.msg_seq & 0xf; 33 if (!seq) 34 seq = ++mdev->mcu.msg_seq & 0xf; 35 36 tx_info = MT_MCU_MSG_TYPE_CMD | 37 FIELD_PREP(MT_MCU_MSG_CMD_TYPE, cmd) | 38 FIELD_PREP(MT_MCU_MSG_CMD_SEQ, seq) | 39 FIELD_PREP(MT_MCU_MSG_PORT, CPU_TX_PORT) | 40 FIELD_PREP(MT_MCU_MSG_LEN, skb->len); 41 42 ret = mt76_tx_queue_skb_raw(dev, MT_TXQ_MCU, skb, tx_info); 43 if (ret) 44 goto out; 45 46 while (wait_resp) { 47 u32 *rxfce; 48 bool check_seq = false; 49 50 skb = mt76_mcu_get_response(&dev->mt76, expires); 51 if (!skb) { 52 dev_err(mdev->dev, 53 "MCU message %d (seq %d) timed out\n", cmd, 54 seq); 55 ret = -ETIMEDOUT; 56 dev->mcu_timeout = 1; 57 break; 58 } 59 60 rxfce = (u32 *)skb->cb; 61 62 if (seq == FIELD_GET(MT_RX_FCE_INFO_CMD_SEQ, *rxfce)) 63 check_seq = true; 64 65 dev_kfree_skb(skb); 66 if (check_seq) 67 break; 68 } 69 70 out: 71 mutex_unlock(&mdev->mcu.mutex); 72 73 return ret; 74 } 75 EXPORT_SYMBOL_GPL(mt76x02_mcu_msg_send); 76 77 int mt76x02_mcu_function_select(struct mt76x02_dev *dev, enum mcu_function func, 78 u32 val) 79 { 80 struct { 81 __le32 id; 82 __le32 value; 83 } __packed __aligned(4) msg = { 84 .id = cpu_to_le32(func), 85 .value = cpu_to_le32(val), 86 }; 87 bool wait = false; 88 89 if (func != Q_SELECT) 90 wait = true; 91 92 return mt76_mcu_send_msg(dev, CMD_FUN_SET_OP, &msg, sizeof(msg), wait); 93 } 94 EXPORT_SYMBOL_GPL(mt76x02_mcu_function_select); 95 96 int mt76x02_mcu_set_radio_state(struct mt76x02_dev *dev, bool on) 97 { 98 struct { 99 __le32 mode; 100 __le32 level; 101 } __packed __aligned(4) msg = { 102 .mode = cpu_to_le32(on ? RADIO_ON : RADIO_OFF), 103 .level = cpu_to_le32(0), 104 }; 105 106 return mt76_mcu_send_msg(dev, CMD_POWER_SAVING_OP, &msg, sizeof(msg), 107 false); 108 } 109 EXPORT_SYMBOL_GPL(mt76x02_mcu_set_radio_state); 110 111 int mt76x02_mcu_calibrate(struct mt76x02_dev *dev, int type, u32 param) 112 { 113 struct { 114 __le32 id; 115 __le32 value; 116 } __packed __aligned(4) msg = { 117 .id = cpu_to_le32(type), 118 .value = cpu_to_le32(param), 119 }; 120 bool is_mt76x2e = mt76_is_mmio(&dev->mt76) && is_mt76x2(dev); 121 int ret; 122 123 if (is_mt76x2e) 124 mt76_rmw(dev, MT_MCU_COM_REG0, BIT(31), 0); 125 126 ret = mt76_mcu_send_msg(dev, CMD_CALIBRATION_OP, &msg, sizeof(msg), 127 true); 128 if (ret) 129 return ret; 130 131 if (is_mt76x2e && 132 WARN_ON(!mt76_poll_msec(dev, MT_MCU_COM_REG0, 133 BIT(31), BIT(31), 100))) 134 return -ETIMEDOUT; 135 136 return 0; 137 } 138 EXPORT_SYMBOL_GPL(mt76x02_mcu_calibrate); 139 140 int mt76x02_mcu_cleanup(struct mt76x02_dev *dev) 141 { 142 struct sk_buff *skb; 143 144 mt76_wr(dev, MT_MCU_INT_LEVEL, 1); 145 usleep_range(20000, 30000); 146 147 while ((skb = skb_dequeue(&dev->mt76.mcu.res_q)) != NULL) 148 dev_kfree_skb(skb); 149 150 return 0; 151 } 152 EXPORT_SYMBOL_GPL(mt76x02_mcu_cleanup); 153 154 void mt76x02_set_ethtool_fwver(struct mt76x02_dev *dev, 155 const struct mt76x02_fw_header *h) 156 { 157 u16 bld = le16_to_cpu(h->build_ver); 158 u16 ver = le16_to_cpu(h->fw_ver); 159 160 snprintf(dev->mt76.hw->wiphy->fw_version, 161 sizeof(dev->mt76.hw->wiphy->fw_version), 162 "%d.%d.%02d-b%x", 163 (ver >> 12) & 0xf, (ver >> 8) & 0xf, ver & 0xf, bld); 164 } 165 EXPORT_SYMBOL_GPL(mt76x02_set_ethtool_fwver); 166