10e3d6777SRyder Lee // SPDX-License-Identifier: ISC
21613c621SLorenzo Bianconi /*
31613c621SLorenzo Bianconi * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
41613c621SLorenzo Bianconi * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
51613c621SLorenzo Bianconi */
61613c621SLorenzo Bianconi
71613c621SLorenzo Bianconi #include <linux/kernel.h>
81613c621SLorenzo Bianconi #include <linux/firmware.h>
91613c621SLorenzo Bianconi #include <linux/delay.h>
101613c621SLorenzo Bianconi
111613c621SLorenzo Bianconi #include "mt76x2.h"
121613c621SLorenzo Bianconi #include "mcu.h"
131613c621SLorenzo Bianconi #include "eeprom.h"
141613c621SLorenzo Bianconi
mt76x2_mcu_set_channel(struct mt76x02_dev * dev,u8 channel,u8 bw,u8 bw_index,bool scan)15e40803f2SLorenzo Bianconi int mt76x2_mcu_set_channel(struct mt76x02_dev *dev, u8 channel, u8 bw,
161613c621SLorenzo Bianconi u8 bw_index, bool scan)
171613c621SLorenzo Bianconi {
181613c621SLorenzo Bianconi struct {
191613c621SLorenzo Bianconi u8 idx;
201613c621SLorenzo Bianconi u8 scan;
211613c621SLorenzo Bianconi u8 bw;
221613c621SLorenzo Bianconi u8 _pad0;
231613c621SLorenzo Bianconi
241613c621SLorenzo Bianconi __le16 chainmask;
251613c621SLorenzo Bianconi u8 ext_chan;
261613c621SLorenzo Bianconi u8 _pad1;
271613c621SLorenzo Bianconi
281613c621SLorenzo Bianconi } __packed __aligned(4) msg = {
291613c621SLorenzo Bianconi .idx = channel,
301613c621SLorenzo Bianconi .scan = scan,
311613c621SLorenzo Bianconi .bw = bw,
32*b9027e08SLorenzo Bianconi .chainmask = cpu_to_le16(dev->mphy.chainmask),
331613c621SLorenzo Bianconi };
341613c621SLorenzo Bianconi
351613c621SLorenzo Bianconi /* first set the channel without the extension channel info */
36cb5cdd4cSFelix Fietkau mt76_mcu_send_msg(&dev->mt76, CMD_SWITCH_CHANNEL_OP, &msg,
37cb5cdd4cSFelix Fietkau sizeof(msg), true);
381613c621SLorenzo Bianconi
391613c621SLorenzo Bianconi usleep_range(5000, 10000);
401613c621SLorenzo Bianconi
411613c621SLorenzo Bianconi msg.ext_chan = 0xe0 + bw_index;
42cb5cdd4cSFelix Fietkau return mt76_mcu_send_msg(&dev->mt76, CMD_SWITCH_CHANNEL_OP, &msg,
43cb5cdd4cSFelix Fietkau sizeof(msg), true);
441613c621SLorenzo Bianconi }
451613c621SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76x2_mcu_set_channel);
461613c621SLorenzo Bianconi
mt76x2_mcu_load_cr(struct mt76x02_dev * dev,u8 type,u8 temp_level,u8 channel)47e40803f2SLorenzo Bianconi int mt76x2_mcu_load_cr(struct mt76x02_dev *dev, u8 type, u8 temp_level,
481613c621SLorenzo Bianconi u8 channel)
491613c621SLorenzo Bianconi {
501613c621SLorenzo Bianconi struct {
511613c621SLorenzo Bianconi u8 cr_mode;
521613c621SLorenzo Bianconi u8 temp;
531613c621SLorenzo Bianconi u8 ch;
541613c621SLorenzo Bianconi u8 _pad0;
551613c621SLorenzo Bianconi
561613c621SLorenzo Bianconi __le32 cfg;
571613c621SLorenzo Bianconi } __packed __aligned(4) msg = {
581613c621SLorenzo Bianconi .cr_mode = type,
591613c621SLorenzo Bianconi .temp = temp_level,
601613c621SLorenzo Bianconi .ch = channel,
611613c621SLorenzo Bianconi };
621613c621SLorenzo Bianconi u32 val;
631613c621SLorenzo Bianconi
641613c621SLorenzo Bianconi val = BIT(31);
6526a9daa6SLorenzo Bianconi val |= (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0) >> 8) & 0x00ff;
6626a9daa6SLorenzo Bianconi val |= (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1) << 8) & 0xff00;
671613c621SLorenzo Bianconi msg.cfg = cpu_to_le32(val);
681613c621SLorenzo Bianconi
691613c621SLorenzo Bianconi /* first set the channel without the extension channel info */
70cb5cdd4cSFelix Fietkau return mt76_mcu_send_msg(&dev->mt76, CMD_LOAD_CR, &msg, sizeof(msg),
71cb5cdd4cSFelix Fietkau true);
721613c621SLorenzo Bianconi }
731613c621SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76x2_mcu_load_cr);
741613c621SLorenzo Bianconi
mt76x2_mcu_init_gain(struct mt76x02_dev * dev,u8 channel,u32 gain,bool force)75e40803f2SLorenzo Bianconi int mt76x2_mcu_init_gain(struct mt76x02_dev *dev, u8 channel, u32 gain,
761613c621SLorenzo Bianconi bool force)
771613c621SLorenzo Bianconi {
781613c621SLorenzo Bianconi struct {
791613c621SLorenzo Bianconi __le32 channel;
801613c621SLorenzo Bianconi __le32 gain_val;
811613c621SLorenzo Bianconi } __packed __aligned(4) msg = {
821613c621SLorenzo Bianconi .channel = cpu_to_le32(channel),
831613c621SLorenzo Bianconi .gain_val = cpu_to_le32(gain),
841613c621SLorenzo Bianconi };
851613c621SLorenzo Bianconi
861613c621SLorenzo Bianconi if (force)
871613c621SLorenzo Bianconi msg.channel |= cpu_to_le32(BIT(31));
881613c621SLorenzo Bianconi
89cb5cdd4cSFelix Fietkau return mt76_mcu_send_msg(&dev->mt76, CMD_INIT_GAIN_OP, &msg,
90cb5cdd4cSFelix Fietkau sizeof(msg), true);
911613c621SLorenzo Bianconi }
921613c621SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76x2_mcu_init_gain);
931613c621SLorenzo Bianconi
mt76x2_mcu_tssi_comp(struct mt76x02_dev * dev,struct mt76x2_tssi_comp * tssi_data)94e40803f2SLorenzo Bianconi int mt76x2_mcu_tssi_comp(struct mt76x02_dev *dev,
951613c621SLorenzo Bianconi struct mt76x2_tssi_comp *tssi_data)
961613c621SLorenzo Bianconi {
971613c621SLorenzo Bianconi struct {
981613c621SLorenzo Bianconi __le32 id;
991613c621SLorenzo Bianconi struct mt76x2_tssi_comp data;
1001613c621SLorenzo Bianconi } __packed __aligned(4) msg = {
1011613c621SLorenzo Bianconi .id = cpu_to_le32(MCU_CAL_TSSI_COMP),
1021613c621SLorenzo Bianconi .data = *tssi_data,
1031613c621SLorenzo Bianconi };
1041613c621SLorenzo Bianconi
105cb5cdd4cSFelix Fietkau return mt76_mcu_send_msg(&dev->mt76, CMD_CALIBRATION_OP, &msg,
106cb5cdd4cSFelix Fietkau sizeof(msg), true);
1071613c621SLorenzo Bianconi }
1081613c621SLorenzo Bianconi EXPORT_SYMBOL_GPL(mt76x2_mcu_tssi_comp);
109