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
mt76x2_mcu_set_channel(struct mt76x02_dev * dev,u8 channel,u8 bw,u8 bw_index,bool scan)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
mt76x2_mcu_load_cr(struct mt76x02_dev * dev,u8 type,u8 temp_level,u8 channel)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
mt76x2_mcu_init_gain(struct mt76x02_dev * dev,u8 channel,u32 gain,bool force)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
mt76x2_mcu_tssi_comp(struct mt76x02_dev * dev,struct mt76x2_tssi_comp * tssi_data)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