mirror of
https://github.com/torvalds/linux.git
synced 2026-05-24 23:22:31 +02:00
mt76: connac: move mt76_connac2_load_patch in connac module
Move mt76_connac2_load_patch utility routine in mt76_connac module since it is shared between mt7921 and mt7915. This is a preliminary patch to support mt7902e driver. Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
b9ec27102a
commit
28fec923d2
|
|
@ -2919,5 +2919,118 @@ int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac2_load_ram);
|
||||
|
||||
static u32 mt76_connac2_get_data_mode(struct mt76_dev *dev, u32 info)
|
||||
{
|
||||
u32 mode = DL_MODE_NEED_RSP;
|
||||
|
||||
if (!is_mt7921(dev) || info == PATCH_SEC_NOT_SUPPORT)
|
||||
return mode;
|
||||
|
||||
switch (FIELD_GET(PATCH_SEC_ENC_TYPE_MASK, info)) {
|
||||
case PATCH_SEC_ENC_TYPE_PLAIN:
|
||||
break;
|
||||
case PATCH_SEC_ENC_TYPE_AES:
|
||||
mode |= DL_MODE_ENCRYPT;
|
||||
mode |= FIELD_PREP(DL_MODE_KEY_IDX,
|
||||
(info & PATCH_SEC_ENC_AES_KEY_MASK)) & DL_MODE_KEY_IDX;
|
||||
mode |= DL_MODE_RESET_SEC_IV;
|
||||
break;
|
||||
case PATCH_SEC_ENC_TYPE_SCRAMBLE:
|
||||
mode |= DL_MODE_ENCRYPT;
|
||||
mode |= DL_CONFIG_ENCRY_MODE_SEL;
|
||||
mode |= DL_MODE_RESET_SEC_IV;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev->dev, "Encryption type not support!\n");
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
int mt76_connac2_load_patch(struct mt76_dev *dev, const char *fw_name)
|
||||
{
|
||||
int i, ret, sem, max_len = mt76_is_sdio(dev) ? 2048 : 4096;
|
||||
const struct mt76_connac2_patch_hdr *hdr;
|
||||
const struct firmware *fw = NULL;
|
||||
|
||||
sem = mt76_connac_mcu_patch_sem_ctrl(dev, true);
|
||||
switch (sem) {
|
||||
case PATCH_IS_DL:
|
||||
return 0;
|
||||
case PATCH_NOT_DL_SEM_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
dev_err(dev->dev, "Failed to get patch semaphore\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
ret = request_firmware(&fw, fw_name, dev->dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
|
||||
dev_err(dev->dev, "Invalid firmware\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdr = (const void *)fw->data;
|
||||
dev_info(dev->dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",
|
||||
be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);
|
||||
|
||||
for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) {
|
||||
struct mt76_connac2_patch_sec *sec;
|
||||
u32 len, addr, mode;
|
||||
const u8 *dl;
|
||||
u32 sec_info;
|
||||
|
||||
sec = (void *)(fw->data + sizeof(*hdr) + i * sizeof(*sec));
|
||||
if ((be32_to_cpu(sec->type) & PATCH_SEC_TYPE_MASK) !=
|
||||
PATCH_SEC_TYPE_INFO) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
addr = be32_to_cpu(sec->info.addr);
|
||||
len = be32_to_cpu(sec->info.len);
|
||||
dl = fw->data + be32_to_cpu(sec->offs);
|
||||
sec_info = be32_to_cpu(sec->info.sec_key_idx);
|
||||
mode = mt76_connac2_get_data_mode(dev, sec_info);
|
||||
|
||||
ret = mt76_connac_mcu_init_download(dev, addr, len, mode);
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "Download request failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = __mt76_mcu_send_firmware(dev, MCU_CMD(FW_SCATTER),
|
||||
dl, len, max_len);
|
||||
if (ret) {
|
||||
dev_err(dev->dev, "Failed to send patch\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mt76_connac_mcu_start_patch(dev);
|
||||
if (ret)
|
||||
dev_err(dev->dev, "Failed to start patch\n");
|
||||
|
||||
out:
|
||||
sem = mt76_connac_mcu_patch_sem_ctrl(dev, false);
|
||||
switch (sem) {
|
||||
case PATCH_REL_SEM_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
ret = -EAGAIN;
|
||||
dev_err(dev->dev, "Failed to release patch semaphore\n");
|
||||
break;
|
||||
}
|
||||
|
||||
release_firmware(fw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mt76_connac2_load_patch);
|
||||
|
||||
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
|
|
|||
|
|
@ -26,6 +26,13 @@
|
|||
#define PATCH_SEC_TYPE_MASK GENMASK(15, 0)
|
||||
#define PATCH_SEC_TYPE_INFO 0x2
|
||||
|
||||
#define PATCH_SEC_ENC_TYPE_MASK GENMASK(31, 24)
|
||||
#define PATCH_SEC_ENC_TYPE_PLAIN 0x00
|
||||
#define PATCH_SEC_ENC_TYPE_AES 0x01
|
||||
#define PATCH_SEC_ENC_TYPE_SCRAMBLE 0x02
|
||||
#define PATCH_SEC_ENC_SCRAMBLE_INFO_MASK GENMASK(15, 0)
|
||||
#define PATCH_SEC_ENC_AES_KEY_MASK GENMASK(7, 0)
|
||||
|
||||
struct mt76_connac2_patch_hdr {
|
||||
char build_date[16];
|
||||
char platform[4];
|
||||
|
|
@ -1711,4 +1718,5 @@ int mt76_connac_mcu_rdd_cmd(struct mt76_dev *dev, int cmd, u8 index,
|
|||
u8 rx_sel, u8 val);
|
||||
int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm,
|
||||
const char *fw_wa);
|
||||
int mt76_connac2_load_patch(struct mt76_dev *dev, const char *fw_name);
|
||||
#endif /* __MT76_CONNAC_MCU_H */
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2020 MediaTek Inc. */
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/fs.h>
|
||||
#include "mt7915.h"
|
||||
#include "mcu.h"
|
||||
|
|
@ -2078,89 +2077,6 @@ static int mt7915_driver_own(struct mt7915_dev *dev, u8 band)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mt7915_load_patch(struct mt7915_dev *dev)
|
||||
{
|
||||
const struct mt76_connac2_patch_hdr *hdr;
|
||||
const struct firmware *fw = NULL;
|
||||
int i, ret, sem;
|
||||
|
||||
sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, 1);
|
||||
switch (sem) {
|
||||
case PATCH_IS_DL:
|
||||
return 0;
|
||||
case PATCH_NOT_DL_SEM_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
dev_err(dev->mt76.dev, "Failed to get patch semaphore\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
ret = request_firmware(&fw, fw_name_var(dev, ROM_PATCH),
|
||||
dev->mt76.dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
|
||||
dev_err(dev->mt76.dev, "Invalid firmware\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdr = (const struct mt76_connac2_patch_hdr *)fw->data;
|
||||
|
||||
dev_info(dev->mt76.dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",
|
||||
be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);
|
||||
|
||||
for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) {
|
||||
struct mt76_connac2_patch_sec *sec;
|
||||
const u8 *dl;
|
||||
u32 len, addr;
|
||||
|
||||
sec = (void *)(fw->data + sizeof(*hdr) + i * sizeof(*sec));
|
||||
if ((be32_to_cpu(sec->type) & PATCH_SEC_TYPE_MASK) !=
|
||||
PATCH_SEC_TYPE_INFO) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
addr = be32_to_cpu(sec->info.addr);
|
||||
len = be32_to_cpu(sec->info.len);
|
||||
dl = fw->data + be32_to_cpu(sec->offs);
|
||||
|
||||
ret = mt76_connac_mcu_init_download(&dev->mt76, addr, len,
|
||||
DL_MODE_NEED_RSP);
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev, "Download request failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = __mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),
|
||||
dl, len, 4096);
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev, "Failed to send patch\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mt76_connac_mcu_start_patch(&dev->mt76);
|
||||
if (ret)
|
||||
dev_err(dev->mt76.dev, "Failed to start patch\n");
|
||||
|
||||
out:
|
||||
sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, 0);
|
||||
switch (sem) {
|
||||
case PATCH_REL_SEM_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
ret = -EAGAIN;
|
||||
dev_err(dev->mt76.dev, "Failed to release patch semaphore\n");
|
||||
break;
|
||||
}
|
||||
release_firmware(fw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mt7915_firmware_state(struct mt7915_dev *dev, bool wa)
|
||||
{
|
||||
|
|
@ -2191,7 +2107,7 @@ static int mt7915_load_firmware(struct mt7915_dev *dev)
|
|||
}
|
||||
}
|
||||
|
||||
ret = mt7915_load_patch(dev);
|
||||
ret = mt76_connac2_load_patch(&dev->mt76, fw_name_var(dev, ROM_PATCH));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
// SPDX-License-Identifier: ISC
|
||||
/* Copyright (C) 2020 MediaTek Inc. */
|
||||
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/fs.h>
|
||||
#include "mt7921.h"
|
||||
#include "mt7921_trace.h"
|
||||
|
|
@ -11,13 +10,6 @@
|
|||
#define MT_STA_BFER BIT(0)
|
||||
#define MT_STA_BFEE BIT(1)
|
||||
|
||||
#define PATCH_SEC_ENC_TYPE_MASK GENMASK(31, 24)
|
||||
#define PATCH_SEC_ENC_TYPE_PLAIN 0x00
|
||||
#define PATCH_SEC_ENC_TYPE_AES 0x01
|
||||
#define PATCH_SEC_ENC_TYPE_SCRAMBLE 0x02
|
||||
#define PATCH_SEC_ENC_SCRAMBLE_INFO_MASK GENMASK(15, 0)
|
||||
#define PATCH_SEC_ENC_AES_KEY_MASK GENMASK(7, 0)
|
||||
|
||||
static int
|
||||
mt7921_mcu_parse_eeprom(struct mt76_dev *dev, struct sk_buff *skb)
|
||||
{
|
||||
|
|
@ -414,34 +406,6 @@ int mt7921_mcu_uni_rx_ba(struct mt7921_dev *dev,
|
|||
enable, false);
|
||||
}
|
||||
|
||||
static u32 mt7921_get_data_mode(struct mt7921_dev *dev, u32 info)
|
||||
{
|
||||
u32 mode = DL_MODE_NEED_RSP;
|
||||
|
||||
if (info == PATCH_SEC_NOT_SUPPORT)
|
||||
return mode;
|
||||
|
||||
switch (FIELD_GET(PATCH_SEC_ENC_TYPE_MASK, info)) {
|
||||
case PATCH_SEC_ENC_TYPE_PLAIN:
|
||||
break;
|
||||
case PATCH_SEC_ENC_TYPE_AES:
|
||||
mode |= DL_MODE_ENCRYPT;
|
||||
mode |= FIELD_PREP(DL_MODE_KEY_IDX,
|
||||
(info & PATCH_SEC_ENC_AES_KEY_MASK)) & DL_MODE_KEY_IDX;
|
||||
mode |= DL_MODE_RESET_SEC_IV;
|
||||
break;
|
||||
case PATCH_SEC_ENC_TYPE_SCRAMBLE:
|
||||
mode |= DL_MODE_ENCRYPT;
|
||||
mode |= DL_CONFIG_ENCRY_MODE_SEL;
|
||||
mode |= DL_MODE_RESET_SEC_IV;
|
||||
break;
|
||||
default:
|
||||
dev_err(dev->mt76.dev, "Encryption type not support!\n");
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static char *mt7921_patch_name(struct mt7921_dev *dev)
|
||||
{
|
||||
char *ret;
|
||||
|
|
@ -454,94 +418,6 @@ static char *mt7921_patch_name(struct mt7921_dev *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int mt7921_load_patch(struct mt7921_dev *dev)
|
||||
{
|
||||
const struct mt76_connac2_patch_hdr *hdr;
|
||||
const struct firmware *fw = NULL;
|
||||
int i, ret, sem, max_len;
|
||||
|
||||
max_len = mt76_is_sdio(&dev->mt76) ? 2048 : 4096;
|
||||
|
||||
sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, true);
|
||||
switch (sem) {
|
||||
case PATCH_IS_DL:
|
||||
return 0;
|
||||
case PATCH_NOT_DL_SEM_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
dev_err(dev->mt76.dev, "Failed to get patch semaphore\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
ret = request_firmware(&fw, mt7921_patch_name(dev), dev->mt76.dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
|
||||
dev_err(dev->mt76.dev, "Invalid firmware\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
hdr = (const struct mt76_connac2_patch_hdr *)fw->data;
|
||||
|
||||
dev_info(dev->mt76.dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",
|
||||
be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);
|
||||
|
||||
for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) {
|
||||
struct mt76_connac2_patch_sec *sec;
|
||||
const u8 *dl;
|
||||
u32 len, addr, mode;
|
||||
u32 sec_info = 0;
|
||||
|
||||
sec = (void *)(fw->data + sizeof(*hdr) + i * sizeof(*sec));
|
||||
if ((be32_to_cpu(sec->type) & PATCH_SEC_TYPE_MASK) !=
|
||||
PATCH_SEC_TYPE_INFO) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
addr = be32_to_cpu(sec->info.addr);
|
||||
len = be32_to_cpu(sec->info.len);
|
||||
dl = fw->data + be32_to_cpu(sec->offs);
|
||||
sec_info = be32_to_cpu(sec->info.sec_key_idx);
|
||||
mode = mt7921_get_data_mode(dev, sec_info);
|
||||
|
||||
ret = mt76_connac_mcu_init_download(&dev->mt76, addr, len,
|
||||
mode);
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev, "Download request failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = __mt76_mcu_send_firmware(&dev->mt76, MCU_CMD(FW_SCATTER),
|
||||
dl, len, max_len);
|
||||
if (ret) {
|
||||
dev_err(dev->mt76.dev, "Failed to send patch\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mt76_connac_mcu_start_patch(&dev->mt76);
|
||||
if (ret)
|
||||
dev_err(dev->mt76.dev, "Failed to start patch\n");
|
||||
|
||||
out:
|
||||
sem = mt76_connac_mcu_patch_sem_ctrl(&dev->mt76, false);
|
||||
switch (sem) {
|
||||
case PATCH_REL_SEM_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
ret = -EAGAIN;
|
||||
dev_err(dev->mt76.dev, "Failed to release patch semaphore\n");
|
||||
break;
|
||||
}
|
||||
|
||||
release_firmware(fw);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *mt7921_ram_name(struct mt7921_dev *dev)
|
||||
{
|
||||
char *ret;
|
||||
|
|
@ -564,7 +440,7 @@ static int mt7921_load_firmware(struct mt7921_dev *dev)
|
|||
goto fw_loaded;
|
||||
}
|
||||
|
||||
ret = mt7921_load_patch(dev);
|
||||
ret = mt76_connac2_load_patch(&dev->mt76, mt7921_patch_name(dev));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user