1 // SPDX-License-Identifier: ISC
3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
4 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
7 #include <linux/kernel.h>
8 #include <linux/firmware.h>
9 #include <linux/delay.h>
11 #include "mt76x02_mcu.h"
13 int mt76x02_mcu_msg_send(struct mt76_dev
*mdev
, int cmd
, const void *data
,
14 int len
, bool wait_resp
)
16 struct mt76x02_dev
*dev
= container_of(mdev
, struct mt76x02_dev
, mt76
);
17 unsigned long expires
= jiffies
+ HZ
;
23 skb
= mt76x02_mcu_msg_alloc(data
, len
);
27 mutex_lock(&mdev
->mmio
.mcu
.mutex
);
29 seq
= ++mdev
->mmio
.mcu
.msg_seq
& 0xf;
31 seq
= ++mdev
->mmio
.mcu
.msg_seq
& 0xf;
33 tx_info
= MT_MCU_MSG_TYPE_CMD
|
34 FIELD_PREP(MT_MCU_MSG_CMD_TYPE
, cmd
) |
35 FIELD_PREP(MT_MCU_MSG_CMD_SEQ
, seq
) |
36 FIELD_PREP(MT_MCU_MSG_PORT
, CPU_TX_PORT
) |
37 FIELD_PREP(MT_MCU_MSG_LEN
, skb
->len
);
39 ret
= mt76_tx_queue_skb_raw(dev
, MT_TXQ_MCU
, skb
, tx_info
);
45 bool check_seq
= false;
47 skb
= mt76_mcu_get_response(&dev
->mt76
, expires
);
50 "MCU message %d (seq %d) timed out\n", cmd
,
57 rxfce
= (u32
*)skb
->cb
;
59 if (seq
== FIELD_GET(MT_RX_FCE_INFO_CMD_SEQ
, *rxfce
))
68 mutex_unlock(&mdev
->mmio
.mcu
.mutex
);
72 EXPORT_SYMBOL_GPL(mt76x02_mcu_msg_send
);
74 int mt76x02_mcu_function_select(struct mt76x02_dev
*dev
, enum mcu_function func
,
80 } __packed
__aligned(4) msg
= {
81 .id
= cpu_to_le32(func
),
82 .value
= cpu_to_le32(val
),
89 return mt76_mcu_send_msg(dev
, CMD_FUN_SET_OP
, &msg
, sizeof(msg
), wait
);
91 EXPORT_SYMBOL_GPL(mt76x02_mcu_function_select
);
93 int mt76x02_mcu_set_radio_state(struct mt76x02_dev
*dev
, bool on
)
98 } __packed
__aligned(4) msg
= {
99 .mode
= cpu_to_le32(on
? RADIO_ON
: RADIO_OFF
),
100 .level
= cpu_to_le32(0),
103 return mt76_mcu_send_msg(dev
, CMD_POWER_SAVING_OP
, &msg
, sizeof(msg
),
106 EXPORT_SYMBOL_GPL(mt76x02_mcu_set_radio_state
);
108 int mt76x02_mcu_calibrate(struct mt76x02_dev
*dev
, int type
, u32 param
)
113 } __packed
__aligned(4) msg
= {
114 .id
= cpu_to_le32(type
),
115 .value
= cpu_to_le32(param
),
117 bool is_mt76x2e
= mt76_is_mmio(&dev
->mt76
) && is_mt76x2(dev
);
121 mt76_rmw(dev
, MT_MCU_COM_REG0
, BIT(31), 0);
123 ret
= mt76_mcu_send_msg(dev
, CMD_CALIBRATION_OP
, &msg
, sizeof(msg
),
129 WARN_ON(!mt76_poll_msec(dev
, MT_MCU_COM_REG0
,
130 BIT(31), BIT(31), 100)))
135 EXPORT_SYMBOL_GPL(mt76x02_mcu_calibrate
);
137 int mt76x02_mcu_cleanup(struct mt76x02_dev
*dev
)
141 mt76_wr(dev
, MT_MCU_INT_LEVEL
, 1);
142 usleep_range(20000, 30000);
144 while ((skb
= skb_dequeue(&dev
->mt76
.mmio
.mcu
.res_q
)) != NULL
)
149 EXPORT_SYMBOL_GPL(mt76x02_mcu_cleanup
);
151 void mt76x02_set_ethtool_fwver(struct mt76x02_dev
*dev
,
152 const struct mt76x02_fw_header
*h
)
154 u16 bld
= le16_to_cpu(h
->build_ver
);
155 u16 ver
= le16_to_cpu(h
->fw_ver
);
157 snprintf(dev
->mt76
.hw
->wiphy
->fw_version
,
158 sizeof(dev
->mt76
.hw
->wiphy
->fw_version
),
160 (ver
>> 12) & 0xf, (ver
>> 8) & 0xf, ver
& 0xf, bld
);
162 EXPORT_SYMBOL_GPL(mt76x02_set_ethtool_fwver
);