162306a36Sopenharmony_ci// SPDX-License-Identifier: ISC
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
462306a36Sopenharmony_ci * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/kernel.h>
862306a36Sopenharmony_ci#include <linux/firmware.h>
962306a36Sopenharmony_ci#include <linux/delay.h>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include "mt76x2.h"
1262306a36Sopenharmony_ci#include "mcu.h"
1362306a36Sopenharmony_ci#include "eeprom.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ciint mt76x2_mcu_set_channel(struct mt76x02_dev *dev, u8 channel, u8 bw,
1662306a36Sopenharmony_ci			   u8 bw_index, bool scan)
1762306a36Sopenharmony_ci{
1862306a36Sopenharmony_ci	struct {
1962306a36Sopenharmony_ci		u8 idx;
2062306a36Sopenharmony_ci		u8 scan;
2162306a36Sopenharmony_ci		u8 bw;
2262306a36Sopenharmony_ci		u8 _pad0;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci		__le16 chainmask;
2562306a36Sopenharmony_ci		u8 ext_chan;
2662306a36Sopenharmony_ci		u8 _pad1;
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	} __packed __aligned(4) msg = {
2962306a36Sopenharmony_ci		.idx = channel,
3062306a36Sopenharmony_ci		.scan = scan,
3162306a36Sopenharmony_ci		.bw = bw,
3262306a36Sopenharmony_ci		.chainmask = cpu_to_le16(dev->mphy.chainmask),
3362306a36Sopenharmony_ci	};
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	/* first set the channel without the extension channel info */
3662306a36Sopenharmony_ci	mt76_mcu_send_msg(&dev->mt76, CMD_SWITCH_CHANNEL_OP, &msg,
3762306a36Sopenharmony_ci			  sizeof(msg), true);
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	usleep_range(5000, 10000);
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	msg.ext_chan = 0xe0 + bw_index;
4262306a36Sopenharmony_ci	return mt76_mcu_send_msg(&dev->mt76, CMD_SWITCH_CHANNEL_OP, &msg,
4362306a36Sopenharmony_ci				 sizeof(msg), true);
4462306a36Sopenharmony_ci}
4562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt76x2_mcu_set_channel);
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ciint mt76x2_mcu_load_cr(struct mt76x02_dev *dev, u8 type, u8 temp_level,
4862306a36Sopenharmony_ci		       u8 channel)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	struct {
5162306a36Sopenharmony_ci		u8 cr_mode;
5262306a36Sopenharmony_ci		u8 temp;
5362306a36Sopenharmony_ci		u8 ch;
5462306a36Sopenharmony_ci		u8 _pad0;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci		__le32 cfg;
5762306a36Sopenharmony_ci	} __packed __aligned(4) msg = {
5862306a36Sopenharmony_ci		.cr_mode = type,
5962306a36Sopenharmony_ci		.temp = temp_level,
6062306a36Sopenharmony_ci		.ch = channel,
6162306a36Sopenharmony_ci	};
6262306a36Sopenharmony_ci	u32 val;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	val = BIT(31);
6562306a36Sopenharmony_ci	val |= (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0) >> 8) & 0x00ff;
6662306a36Sopenharmony_ci	val |= (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1) << 8) & 0xff00;
6762306a36Sopenharmony_ci	msg.cfg = cpu_to_le32(val);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	/* first set the channel without the extension channel info */
7062306a36Sopenharmony_ci	return mt76_mcu_send_msg(&dev->mt76, CMD_LOAD_CR, &msg, sizeof(msg),
7162306a36Sopenharmony_ci				 true);
7262306a36Sopenharmony_ci}
7362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt76x2_mcu_load_cr);
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ciint mt76x2_mcu_init_gain(struct mt76x02_dev *dev, u8 channel, u32 gain,
7662306a36Sopenharmony_ci			 bool force)
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci	struct {
7962306a36Sopenharmony_ci		__le32 channel;
8062306a36Sopenharmony_ci		__le32 gain_val;
8162306a36Sopenharmony_ci	} __packed __aligned(4) msg = {
8262306a36Sopenharmony_ci		.channel = cpu_to_le32(channel),
8362306a36Sopenharmony_ci		.gain_val = cpu_to_le32(gain),
8462306a36Sopenharmony_ci	};
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	if (force)
8762306a36Sopenharmony_ci		msg.channel |= cpu_to_le32(BIT(31));
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	return mt76_mcu_send_msg(&dev->mt76, CMD_INIT_GAIN_OP, &msg,
9062306a36Sopenharmony_ci				 sizeof(msg), true);
9162306a36Sopenharmony_ci}
9262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt76x2_mcu_init_gain);
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ciint mt76x2_mcu_tssi_comp(struct mt76x02_dev *dev,
9562306a36Sopenharmony_ci			 struct mt76x2_tssi_comp *tssi_data)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	struct {
9862306a36Sopenharmony_ci		__le32 id;
9962306a36Sopenharmony_ci		struct mt76x2_tssi_comp data;
10062306a36Sopenharmony_ci	} __packed __aligned(4) msg = {
10162306a36Sopenharmony_ci		.id = cpu_to_le32(MCU_CAL_TSSI_COMP),
10262306a36Sopenharmony_ci		.data = *tssi_data,
10362306a36Sopenharmony_ci	};
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	return mt76_mcu_send_msg(&dev->mt76, CMD_CALIBRATION_OP, &msg,
10662306a36Sopenharmony_ci				 sizeof(msg), true);
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt76x2_mcu_tssi_comp);
109