linux/drivers/net/wireless/mediatek/mt76/mt76x2/mcu.c
<<
>>
Prefs
   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
  15int 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->chainmask),
  33        };
  34
  35        /* first set the channel without the extension channel info */
  36        mt76_mcu_send_msg(dev, CMD_SWITCH_CHANNEL_OP, &msg, sizeof(msg), true);
  37
  38        usleep_range(5000, 10000);
  39
  40        msg.ext_chan = 0xe0 + bw_index;
  41        return mt76_mcu_send_msg(dev, CMD_SWITCH_CHANNEL_OP, &msg, sizeof(msg),
  42                                 true);
  43}
  44EXPORT_SYMBOL_GPL(mt76x2_mcu_set_channel);
  45
  46int mt76x2_mcu_load_cr(struct mt76x02_dev *dev, u8 type, u8 temp_level,
  47                       u8 channel)
  48{
  49        struct {
  50                u8 cr_mode;
  51                u8 temp;
  52                u8 ch;
  53                u8 _pad0;
  54
  55                __le32 cfg;
  56        } __packed __aligned(4) msg = {
  57                .cr_mode = type,
  58                .temp = temp_level,
  59                .ch = channel,
  60        };
  61        u32 val;
  62
  63        val = BIT(31);
  64        val |= (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0) >> 8) & 0x00ff;
  65        val |= (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1) << 8) & 0xff00;
  66        msg.cfg = cpu_to_le32(val);
  67
  68        /* first set the channel without the extension channel info */
  69        return mt76_mcu_send_msg(dev, CMD_LOAD_CR, &msg, sizeof(msg), true);
  70}
  71EXPORT_SYMBOL_GPL(mt76x2_mcu_load_cr);
  72
  73int mt76x2_mcu_init_gain(struct mt76x02_dev *dev, u8 channel, u32 gain,
  74                         bool force)
  75{
  76        struct {
  77                __le32 channel;
  78                __le32 gain_val;
  79        } __packed __aligned(4) msg = {
  80                .channel = cpu_to_le32(channel),
  81                .gain_val = cpu_to_le32(gain),
  82        };
  83
  84        if (force)
  85                msg.channel |= cpu_to_le32(BIT(31));
  86
  87        return mt76_mcu_send_msg(dev, CMD_INIT_GAIN_OP, &msg, sizeof(msg),
  88                                 true);
  89}
  90EXPORT_SYMBOL_GPL(mt76x2_mcu_init_gain);
  91
  92int mt76x2_mcu_tssi_comp(struct mt76x02_dev *dev,
  93                         struct mt76x2_tssi_comp *tssi_data)
  94{
  95        struct {
  96                __le32 id;
  97                struct mt76x2_tssi_comp data;
  98        } __packed __aligned(4) msg = {
  99                .id = cpu_to_le32(MCU_CAL_TSSI_COMP),
 100                .data = *tssi_data,
 101        };
 102
 103        return mt76_mcu_send_msg(dev, CMD_CALIBRATION_OP, &msg, sizeof(msg),
 104                                 true);
 105}
 106EXPORT_SYMBOL_GPL(mt76x2_mcu_tssi_comp);
 107