mirror of
https://github.com/outbackdingo/mt76.git
synced 2026-10-24 13:26:48 +00:00
mt7603: add basic mcu bringup code (currently broken)
Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
@@ -38,6 +38,8 @@ struct mt7603_mcu {
|
||||
|
||||
struct mt76_queue q_rx;
|
||||
u32 msg_seq;
|
||||
|
||||
bool running;
|
||||
};
|
||||
|
||||
struct mt7603_dev {
|
||||
@@ -67,6 +69,8 @@ int mt7603_init_hardware(struct mt7603_dev *dev);
|
||||
int mt7603_dma_init(struct mt7603_dev *dev);
|
||||
void mt7603_dma_cleanup(struct mt7603_dev *dev);
|
||||
int mt7603_mcu_init(struct mt7603_dev *dev);
|
||||
int mt7603_tx_queue_mcu(struct mt7603_dev *dev, enum mt7603_txq_id qid,
|
||||
struct sk_buff *skb);
|
||||
|
||||
void mt7603_set_irq_mask(struct mt7603_dev *dev, u32 clear, u32 set);
|
||||
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ mt7603_dma_rx_fill(struct mt7603_dev *dev, struct mt76_queue *q)
|
||||
|
||||
int
|
||||
mt7603_tx_queue_mcu(struct mt7603_dev *dev, enum mt7603_txq_id qid,
|
||||
struct sk_buff *skb, int cmd, int seq)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct mt76_queue *q = &dev->q_tx[qid];
|
||||
dma_addr_t addr;
|
||||
|
||||
@@ -37,6 +37,9 @@ int mt7603_init_hardware(struct mt7603_dev *dev)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
set_bit(MT76_STATE_INITIALIZED, &dev->mt76.state);
|
||||
mt7603_irq_enable(dev, MT_INT_RX_DONE_ALL | MT_INT_TX_DONE_ALL);
|
||||
|
||||
ret = mt7603_mcu_init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
+131
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include "mt7603.h"
|
||||
#include "mt7603_mcu.h"
|
||||
|
||||
struct mt7603_fw_trailer {
|
||||
char fw_ver[10];
|
||||
@@ -20,11 +21,137 @@ struct mt7603_fw_trailer {
|
||||
__le32 dl_len;
|
||||
} __packed;
|
||||
|
||||
static struct sk_buff *
|
||||
mt7603_mcu_msg_alloc(struct mt7603_dev *dev, const void *data, int len)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = alloc_skb(len + sizeof(struct mt7603_mcu_txd), GFP_KERNEL);
|
||||
skb_reserve(skb, sizeof(struct mt7603_mcu_txd));
|
||||
memcpy(skb_put(skb, len), data, len);
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
mt7603_mcu_get_response(struct mt7603_dev *dev, unsigned long expires)
|
||||
{
|
||||
unsigned long timeout;
|
||||
|
||||
if (!time_is_after_jiffies(expires))
|
||||
return NULL;
|
||||
|
||||
timeout = expires - jiffies;
|
||||
wait_event_timeout(dev->mcu.wait, !skb_queue_empty(&dev->mcu.res_q),
|
||||
timeout);
|
||||
return skb_dequeue(&dev->mcu.res_q);
|
||||
}
|
||||
|
||||
static int
|
||||
__mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd, int query, int *wait_seq)
|
||||
{
|
||||
int hdrlen = dev->mcu.running ? sizeof(struct mt7603_mcu_txd) : 12;
|
||||
struct mt7603_mcu_txd *txd;
|
||||
u8 seq;
|
||||
|
||||
if (!skb)
|
||||
return -EINVAL;
|
||||
|
||||
seq = ++dev->mcu.msg_seq & 0xf;
|
||||
if (!seq)
|
||||
seq = ++dev->mcu.msg_seq & 0xf;
|
||||
|
||||
txd = (struct mt7603_mcu_txd *) skb_push(skb, hdrlen);
|
||||
memset(txd, 0, hdrlen);
|
||||
|
||||
txd->len = cpu_to_le16(skb->len - hdrlen);
|
||||
if (cmd == MCU_CMD_FW_SCATTER)
|
||||
txd->pq_id = cpu_to_le16(MCU_PORT_QUEUE_FW);
|
||||
else
|
||||
txd->pq_id = cpu_to_le16(MCU_PORT_QUEUE);
|
||||
txd->pkt_type = MCU_PKT_ID;
|
||||
txd->seq = seq;
|
||||
|
||||
if (cmd < 0) {
|
||||
txd->cid = -cmd;
|
||||
} else {
|
||||
txd->cid = MCU_CMD_EXT_CID;
|
||||
txd->ext_cid = cmd;
|
||||
if (query != MCU_Q_NA)
|
||||
txd->ext_cid_ack = 1;
|
||||
|
||||
txd->set_query = query;
|
||||
}
|
||||
|
||||
if (wait_seq)
|
||||
*wait_seq = seq;
|
||||
|
||||
return mt7603_tx_queue_mcu(dev, MT_TXQ_MCU, skb);
|
||||
}
|
||||
|
||||
static int
|
||||
mt7603_mcu_msg_send(struct mt7603_dev *dev, struct sk_buff *skb, int cmd, int query)
|
||||
{
|
||||
unsigned long expires = jiffies + HZ;
|
||||
int ret, seq;
|
||||
|
||||
mutex_lock(&dev->mcu.mutex);
|
||||
|
||||
ret = __mt7603_mcu_msg_send(dev, skb, cmd, query, &seq);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
while (1) {
|
||||
bool check_seq = false;
|
||||
|
||||
skb = mt7603_mcu_get_response(dev, expires);
|
||||
if (!skb) {
|
||||
printk("MCU message %d (seq %d) timed out\n", cmd, seq);
|
||||
ret = -ETIMEDOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
rxfce = (u32 *) skb->cb;
|
||||
|
||||
if (seq == MT76_GET(MT_RX_FCE_INFO_CMD_SEQ, *rxfce))
|
||||
#endif
|
||||
check_seq = true;
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
if (check_seq)
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&dev->mcu.mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7603_mcu_init_download(struct mt7603_dev *dev, u32 addr, u32 len)
|
||||
{
|
||||
struct {
|
||||
__le32 addr;
|
||||
__le32 len;
|
||||
__le32 mode;
|
||||
} req = {
|
||||
.addr = cpu_to_le32(addr),
|
||||
.len = cpu_to_le32(len),
|
||||
.mode = cpu_to_le32(BIT(31)),
|
||||
};
|
||||
struct sk_buff *skb = mt7603_mcu_msg_alloc(dev, &req, sizeof(req));
|
||||
|
||||
return mt7603_mcu_msg_send(dev, skb, MCU_CMD_TARGET_ADDRESS_LEN_REQ, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
mt7603_load_firmware(struct mt7603_dev *dev)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
const struct mt7603_fw_trailer *hdr;
|
||||
int dl_len;
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
@@ -69,6 +196,9 @@ mt7603_load_firmware(struct mt7603_dev *dev)
|
||||
goto out;
|
||||
}
|
||||
|
||||
dl_len = le32_to_cpu(hdr->dl_len) + 4;
|
||||
ret = mt7603_mcu_init_download(dev, MCU_FIRMWARE_ADDRESS, dl_len);
|
||||
printk("init_download(%d): %d\n", dl_len, ret);
|
||||
|
||||
out:
|
||||
release_firmware(fw);
|
||||
@@ -83,5 +213,6 @@ error:
|
||||
|
||||
int mt7603_mcu_init(struct mt7603_dev *dev)
|
||||
{
|
||||
mutex_init(&dev->mcu.mutex);
|
||||
return mt7603_load_firmware(dev);
|
||||
}
|
||||
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Felix Fietkau <[email protected]>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __MT7603_MCU_H
|
||||
#define __MT7603_MCU_H
|
||||
|
||||
struct mt7603_mcu_txd {
|
||||
__le16 pq_id;
|
||||
__le16 len;
|
||||
|
||||
u8 seq;
|
||||
u8 set_query;
|
||||
u8 pkt_type;
|
||||
u8 cid;
|
||||
|
||||
u8 ext_cid_ack;
|
||||
u8 uc_d2b2_rev;
|
||||
u8 ext_cid;
|
||||
u8 uc_d2b0_rev;
|
||||
|
||||
u8 au4_d3_to_d7_rev[5];
|
||||
} __packed __aligned(4);
|
||||
|
||||
#define MCU_PKT_ID 0xa0
|
||||
#define MCU_PORT_QUEUE 0x8000
|
||||
#define MCU_PORT_QUEUE_FW 0xc000
|
||||
|
||||
#define MCU_FIRMWARE_ADDRESS 0x100000
|
||||
|
||||
enum {
|
||||
MCU_Q_QUERY,
|
||||
MCU_Q_SET,
|
||||
MCU_Q_RESERVED,
|
||||
MCU_Q_NA
|
||||
};
|
||||
|
||||
enum {
|
||||
MCU_CMD_TARGET_ADDRESS_LEN_REQ = 0x01,
|
||||
MCU_CMD_FW_START_REQ = 0x02,
|
||||
MCU_CMD_INIT_ACCESS_REG = 0x3,
|
||||
MCU_CMD_PATCH_START_REQ = 0x05,
|
||||
MCU_CMD_PATCH_FINISH_REQ = 0x07,
|
||||
MCU_CMD_PATCH_SEM_CONTROL = 0x10,
|
||||
MCU_CMD_HIF_LOOPBACK = 0x20,
|
||||
MCU_CMD_CH_PRIVILEGE = 0x20,
|
||||
MCU_CMD_ACCESS_REG = 0xC2,
|
||||
MCU_CMD_EXT_CID = 0xED,
|
||||
MCU_CMD_FW_SCATTER = 0xEE,
|
||||
MCU_CMD_RESTART_DL_REQ = 0xEF,
|
||||
};
|
||||
|
||||
enum {
|
||||
MCU_EXT_CMD_RF_REG_ACCESS = 0x02,
|
||||
MCU_EXT_CMD_RF_TEST = 0x04,
|
||||
MCU_EXT_CMD_RADIO_ON_OFF_CTRL = 0x05,
|
||||
MCU_EXT_CMD_WIFI_RX_DISABLE = 0x06,
|
||||
MCU_EXT_CMD_PM_STATE_CTRL = 0x07,
|
||||
MCU_EXT_CMD_CHANNEL_SWITCH = 0x08,
|
||||
MCU_EXT_CMD_NIC_CAPABILITY = 0x09,
|
||||
MCU_EXT_CMD_PWR_SAVING = 0x0A,
|
||||
MCU_EXT_CMD_MULTIPLE_REG_ACCESS = 0x0E,
|
||||
MCU_EXT_CMD_AP_PWR_SAVING_CAPABILITY = 0xF,
|
||||
MCU_EXT_CMD_SEC_ADDREMOVE_KEY = 0x10,
|
||||
MCU_EXT_CMD_SET_TX_POWER_CTRL=0x11,
|
||||
MCU_EXT_CMD_FW_LOG_2_HOST = 0x13,
|
||||
MCU_EXT_CMD_PS_RETRIEVE_START = 0x14,
|
||||
MCU_EXT_CMD_LED_CTRL=0x17,
|
||||
MCU_EXT_CMD_PACKET_FILTER = 0x18,
|
||||
MCU_EXT_CMD_PWR_MGT_BIT_WIFI = 0x1B,
|
||||
MCU_EXT_CMD_EFUSE_BUFFER_MODE = 0x21,
|
||||
MCU_EXT_CMD_THERMAL_PROTECT = 0x23,
|
||||
MCU_EXT_CMD_EDCA_SET = 0x27,
|
||||
MCU_EXT_CMD_SLOT_TIME_SET = 0x28,
|
||||
MCU_EXT_CMD_CONFIG_INTERNAL_SETTING = 0x29,
|
||||
MCU_EXT_CMD_NOA_OFFLOAD_CTRL = 0x2B,
|
||||
MCU_EXT_CMD_GET_THEMAL_SENSOR=0x2C,
|
||||
MCU_EXT_CMD_WAKEUP_OPTION = 0x2E,
|
||||
MCU_EXT_CMD_AC_QUEUE_CONTROL = 0x31,
|
||||
MCU_EXT_CMD_BCN_UPDATE = 0x33
|
||||
};
|
||||
|
||||
enum {
|
||||
MCU_EVENT_CMD_RESULT = 0x0,
|
||||
MCU_EVENT_RF_REG_ACCESS = 0x2,
|
||||
MCU_EVENT_MULTI_CR_ACCESS = 0x0E,
|
||||
MCU_EVENT_FW_LOG_2_HOST = 0x13,
|
||||
MCU_EVENT_BEACON_LOSS = 0x1A,
|
||||
MCU_EVENT_THERMAL_PROTECT = 0x22,
|
||||
MCU_EVENT_BCN_UPDATE = 0x31,
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user