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