1 /* 2 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com> 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <linux/kernel.h> 19 #include <linux/firmware.h> 20 #include <linux/delay.h> 21 22 #include "mt76x2.h" 23 #include "mcu.h" 24 #include "eeprom.h" 25 26 int mt76x2_mcu_set_channel(struct mt76x02_dev *dev, u8 channel, u8 bw, 27 u8 bw_index, bool scan) 28 { 29 struct { 30 u8 idx; 31 u8 scan; 32 u8 bw; 33 u8 _pad0; 34 35 __le16 chainmask; 36 u8 ext_chan; 37 u8 _pad1; 38 39 } __packed __aligned(4) msg = { 40 .idx = channel, 41 .scan = scan, 42 .bw = bw, 43 .chainmask = cpu_to_le16(dev->mt76.chainmask), 44 }; 45 46 /* first set the channel without the extension channel info */ 47 mt76_mcu_send_msg(dev, CMD_SWITCH_CHANNEL_OP, &msg, sizeof(msg), true); 48 49 usleep_range(5000, 10000); 50 51 msg.ext_chan = 0xe0 + bw_index; 52 return mt76_mcu_send_msg(dev, CMD_SWITCH_CHANNEL_OP, &msg, sizeof(msg), 53 true); 54 } 55 EXPORT_SYMBOL_GPL(mt76x2_mcu_set_channel); 56 57 int mt76x2_mcu_load_cr(struct mt76x02_dev *dev, u8 type, u8 temp_level, 58 u8 channel) 59 { 60 struct { 61 u8 cr_mode; 62 u8 temp; 63 u8 ch; 64 u8 _pad0; 65 66 __le32 cfg; 67 } __packed __aligned(4) msg = { 68 .cr_mode = type, 69 .temp = temp_level, 70 .ch = channel, 71 }; 72 u32 val; 73 74 val = BIT(31); 75 val |= (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0) >> 8) & 0x00ff; 76 val |= (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1) << 8) & 0xff00; 77 msg.cfg = cpu_to_le32(val); 78 79 /* first set the channel without the extension channel info */ 80 return mt76_mcu_send_msg(dev, CMD_LOAD_CR, &msg, sizeof(msg), true); 81 } 82 EXPORT_SYMBOL_GPL(mt76x2_mcu_load_cr); 83 84 int mt76x2_mcu_init_gain(struct mt76x02_dev *dev, u8 channel, u32 gain, 85 bool force) 86 { 87 struct { 88 __le32 channel; 89 __le32 gain_val; 90 } __packed __aligned(4) msg = { 91 .channel = cpu_to_le32(channel), 92 .gain_val = cpu_to_le32(gain), 93 }; 94 95 if (force) 96 msg.channel |= cpu_to_le32(BIT(31)); 97 98 return mt76_mcu_send_msg(dev, CMD_INIT_GAIN_OP, &msg, sizeof(msg), 99 true); 100 } 101 EXPORT_SYMBOL_GPL(mt76x2_mcu_init_gain); 102 103 int mt76x2_mcu_tssi_comp(struct mt76x02_dev *dev, 104 struct mt76x2_tssi_comp *tssi_data) 105 { 106 struct { 107 __le32 id; 108 struct mt76x2_tssi_comp data; 109 } __packed __aligned(4) msg = { 110 .id = cpu_to_le32(MCU_CAL_TSSI_COMP), 111 .data = *tssi_data, 112 }; 113 114 return mt76_mcu_send_msg(dev, CMD_CALIBRATION_OP, &msg, sizeof(msg), 115 true); 116 } 117 EXPORT_SYMBOL_GPL(mt76x2_mcu_tssi_comp); 118