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