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 "mt76x2.h" 12 #include "mcu.h" 13 #include "eeprom.h" 14 15 int mt76x2_mcu_set_channel(struct mt76x02_dev *dev, u8 channel, u8 bw, 16 u8 bw_index, bool scan) 17 { 18 struct { 19 u8 idx; 20 u8 scan; 21 u8 bw; 22 u8 _pad0; 23 24 __le16 chainmask; 25 u8 ext_chan; 26 u8 _pad1; 27 28 } __packed __aligned(4) msg = { 29 .idx = channel, 30 .scan = scan, 31 .bw = bw, 32 .chainmask = cpu_to_le16(dev->mphy.chainmask), 33 }; 34 35 /* first set the channel without the extension channel info */ 36 mt76_mcu_send_msg(&dev->mt76, CMD_SWITCH_CHANNEL_OP, &msg, 37 sizeof(msg), true); 38 39 usleep_range(5000, 10000); 40 41 msg.ext_chan = 0xe0 + bw_index; 42 return mt76_mcu_send_msg(&dev->mt76, CMD_SWITCH_CHANNEL_OP, &msg, 43 sizeof(msg), true); 44 } 45 EXPORT_SYMBOL_GPL(mt76x2_mcu_set_channel); 46 47 int mt76x2_mcu_load_cr(struct mt76x02_dev *dev, u8 type, u8 temp_level, 48 u8 channel) 49 { 50 struct { 51 u8 cr_mode; 52 u8 temp; 53 u8 ch; 54 u8 _pad0; 55 56 __le32 cfg; 57 } __packed __aligned(4) msg = { 58 .cr_mode = type, 59 .temp = temp_level, 60 .ch = channel, 61 }; 62 u32 val; 63 64 val = BIT(31); 65 val |= (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0) >> 8) & 0x00ff; 66 val |= (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1) << 8) & 0xff00; 67 msg.cfg = cpu_to_le32(val); 68 69 /* first set the channel without the extension channel info */ 70 return mt76_mcu_send_msg(&dev->mt76, CMD_LOAD_CR, &msg, sizeof(msg), 71 true); 72 } 73 EXPORT_SYMBOL_GPL(mt76x2_mcu_load_cr); 74 75 int mt76x2_mcu_init_gain(struct mt76x02_dev *dev, u8 channel, u32 gain, 76 bool force) 77 { 78 struct { 79 __le32 channel; 80 __le32 gain_val; 81 } __packed __aligned(4) msg = { 82 .channel = cpu_to_le32(channel), 83 .gain_val = cpu_to_le32(gain), 84 }; 85 86 if (force) 87 msg.channel |= cpu_to_le32(BIT(31)); 88 89 return mt76_mcu_send_msg(&dev->mt76, CMD_INIT_GAIN_OP, &msg, 90 sizeof(msg), true); 91 } 92 EXPORT_SYMBOL_GPL(mt76x2_mcu_init_gain); 93 94 int mt76x2_mcu_tssi_comp(struct mt76x02_dev *dev, 95 struct mt76x2_tssi_comp *tssi_data) 96 { 97 struct { 98 __le32 id; 99 struct mt76x2_tssi_comp data; 100 } __packed __aligned(4) msg = { 101 .id = cpu_to_le32(MCU_CAL_TSSI_COMP), 102 .data = *tssi_data, 103 }; 104 105 return mt76_mcu_send_msg(&dev->mt76, CMD_CALIBRATION_OP, &msg, 106 sizeof(msg), true); 107 } 108 EXPORT_SYMBOL_GPL(mt76x2_mcu_tssi_comp); 109