summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/realtek
diff options
context:
space:
mode:
authorPing-Ke Shih <pkshih@realtek.com>2023-08-01 05:11:22 +0300
committerKalle Valo <kvalo@kernel.org>2023-08-03 15:04:10 +0300
commit1b073b350d24b9481f0dffea9e9dec05c838098a (patch)
tree717247a4789204c0fd033964059d25ad601fbada /drivers/net/wireless/realtek
parentcad2bd8a136cb1231e8b43996be7133ccf92ef48 (diff)
downloadlinux-1b073b350d24b9481f0dffea9e9dec05c838098a.tar.xz
wifi: rtw89: introduce v1 format of firmware header
New firmware header is used by upcoming WiFi 7 chips to have more information, so use common field w3[31:24] to determine header version, and then use corresponding function to read firmware version and commit ID: rtw89_8852be 0000:03:00.0: Firmware version 0.29.29.1 (799134c3), cmd version 1, type 5 rtw89_8852be 0000:03:00.0: Firmware version 0.29.29.1 (799134c3), cmd version 1, type 3 Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> Signed-off-by: Kalle Valo <kvalo@kernel.org> Link: https://lore.kernel.org/r/20230801021127.15919-4-pkshih@realtek.com
Diffstat (limited to 'drivers/net/wireless/realtek')
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.h3
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.c66
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.h33
3 files changed, 89 insertions, 13 deletions
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index f05086b27b26..01f79f2a8e2b 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -3563,6 +3563,7 @@ enum rtw89_fw_feature {
};
struct rtw89_fw_suit {
+ enum rtw89_fw_type type;
const u8 *data;
u32 size;
u8 major_ver;
@@ -3575,6 +3576,8 @@ struct rtw89_fw_suit {
u16 build_hour;
u16 build_min;
u8 cmd_ver;
+ u8 hdr_ver;
+ u32 commitid;
};
#define RTW89_FW_VER_CODE(major, minor, sub, idx) \
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index cbb0e953fbbf..a57d075db74a 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -196,30 +196,72 @@ found:
return 0;
}
-static void rtw89_fw_update_ver(struct rtw89_dev *rtwdev,
- enum rtw89_fw_type type,
- struct rtw89_fw_suit *fw_suit)
+static void rtw89_fw_update_ver_v0(struct rtw89_dev *rtwdev,
+ struct rtw89_fw_suit *fw_suit,
+ const struct rtw89_fw_hdr *hdr)
{
- const struct rtw89_fw_hdr *hdr = (const struct rtw89_fw_hdr *)fw_suit->data;
-
- if (type == RTW89_FW_LOGFMT)
- return;
-
fw_suit->major_ver = le32_get_bits(hdr->w1, FW_HDR_W1_MAJOR_VERSION);
fw_suit->minor_ver = le32_get_bits(hdr->w1, FW_HDR_W1_MINOR_VERSION);
fw_suit->sub_ver = le32_get_bits(hdr->w1, FW_HDR_W1_SUBVERSION);
fw_suit->sub_idex = le32_get_bits(hdr->w1, FW_HDR_W1_SUBINDEX);
+ fw_suit->commitid = le32_get_bits(hdr->w2, FW_HDR_W2_COMMITID);
fw_suit->build_year = le32_get_bits(hdr->w5, FW_HDR_W5_YEAR);
fw_suit->build_mon = le32_get_bits(hdr->w4, FW_HDR_W4_MONTH);
fw_suit->build_date = le32_get_bits(hdr->w4, FW_HDR_W4_DATE);
fw_suit->build_hour = le32_get_bits(hdr->w4, FW_HDR_W4_HOUR);
fw_suit->build_min = le32_get_bits(hdr->w4, FW_HDR_W4_MIN);
fw_suit->cmd_ver = le32_get_bits(hdr->w7, FW_HDR_W7_CMD_VERSERION);
+}
+
+static void rtw89_fw_update_ver_v1(struct rtw89_dev *rtwdev,
+ struct rtw89_fw_suit *fw_suit,
+ const struct rtw89_fw_hdr_v1 *hdr)
+{
+ fw_suit->major_ver = le32_get_bits(hdr->w1, FW_HDR_V1_W1_MAJOR_VERSION);
+ fw_suit->minor_ver = le32_get_bits(hdr->w1, FW_HDR_V1_W1_MINOR_VERSION);
+ fw_suit->sub_ver = le32_get_bits(hdr->w1, FW_HDR_V1_W1_SUBVERSION);
+ fw_suit->sub_idex = le32_get_bits(hdr->w1, FW_HDR_V1_W1_SUBINDEX);
+ fw_suit->commitid = le32_get_bits(hdr->w2, FW_HDR_V1_W2_COMMITID);
+ fw_suit->build_year = le32_get_bits(hdr->w5, FW_HDR_V1_W5_YEAR);
+ fw_suit->build_mon = le32_get_bits(hdr->w4, FW_HDR_V1_W4_MONTH);
+ fw_suit->build_date = le32_get_bits(hdr->w4, FW_HDR_V1_W4_DATE);
+ fw_suit->build_hour = le32_get_bits(hdr->w4, FW_HDR_V1_W4_HOUR);
+ fw_suit->build_min = le32_get_bits(hdr->w4, FW_HDR_V1_W4_MIN);
+ fw_suit->cmd_ver = le32_get_bits(hdr->w7, FW_HDR_V1_W3_CMD_VERSERION);
+}
+
+static int rtw89_fw_update_ver(struct rtw89_dev *rtwdev,
+ enum rtw89_fw_type type,
+ struct rtw89_fw_suit *fw_suit)
+{
+ const struct rtw89_fw_hdr *v0 = (const struct rtw89_fw_hdr *)fw_suit->data;
+ const struct rtw89_fw_hdr_v1 *v1 = (const struct rtw89_fw_hdr_v1 *)fw_suit->data;
+
+ if (type == RTW89_FW_LOGFMT)
+ return 0;
+
+ fw_suit->type = type;
+ fw_suit->hdr_ver = le32_get_bits(v0->w3, FW_HDR_W3_HDR_VER);
+
+ switch (fw_suit->hdr_ver) {
+ case 0:
+ rtw89_fw_update_ver_v0(rtwdev, fw_suit, v0);
+ break;
+ case 1:
+ rtw89_fw_update_ver_v1(rtwdev, fw_suit, v1);
+ break;
+ default:
+ rtw89_err(rtwdev, "Unknown firmware header version %u\n",
+ fw_suit->hdr_ver);
+ return -ENOENT;
+ }
rtw89_info(rtwdev,
- "Firmware version %u.%u.%u.%u, cmd version %u, type %u\n",
+ "Firmware version %u.%u.%u.%u (%08x), cmd version %u, type %u\n",
fw_suit->major_ver, fw_suit->minor_ver, fw_suit->sub_ver,
- fw_suit->sub_idex, fw_suit->cmd_ver, type);
+ fw_suit->sub_idex, fw_suit->commitid, fw_suit->cmd_ver, type);
+
+ return 0;
}
static
@@ -233,9 +275,7 @@ int __rtw89_fw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
if (ret)
return ret;
- rtw89_fw_update_ver(rtwdev, type, fw_suit);
-
- return 0;
+ return rtw89_fw_update_ver(rtwdev, type, fw_suit);
}
#define __DEF_FW_FEAT_COND(__cond, __op) \
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index ad1a621783f9..366645bcead5 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -463,7 +463,9 @@ struct rtw89_fw_hdr {
#define FW_HDR_W1_MINOR_VERSION GENMASK(15, 8)
#define FW_HDR_W1_SUBVERSION GENMASK(23, 16)
#define FW_HDR_W1_SUBINDEX GENMASK(31, 24)
+#define FW_HDR_W2_COMMITID GENMASK(31, 0)
#define FW_HDR_W3_LEN GENMASK(23, 16)
+#define FW_HDR_W3_HDR_VER GENMASK(31, 24)
#define FW_HDR_W4_MONTH GENMASK(7, 0)
#define FW_HDR_W4_DATE GENMASK(15, 8)
#define FW_HDR_W4_HOUR GENMASK(23, 16)
@@ -473,6 +475,37 @@ struct rtw89_fw_hdr {
#define FW_HDR_W7_DYN_HDR BIT(16)
#define FW_HDR_W7_CMD_VERSERION GENMASK(31, 24)
+struct rtw89_fw_hdr_v1 {
+ __le32 w0;
+ __le32 w1;
+ __le32 w2;
+ __le32 w3;
+ __le32 w4;
+ __le32 w5;
+ __le32 w6;
+ __le32 w7;
+ __le32 w8;
+ __le32 w9;
+ __le32 w10;
+ __le32 w11;
+} __packed;
+
+#define FW_HDR_V1_W1_MAJOR_VERSION GENMASK(7, 0)
+#define FW_HDR_V1_W1_MINOR_VERSION GENMASK(15, 8)
+#define FW_HDR_V1_W1_SUBVERSION GENMASK(23, 16)
+#define FW_HDR_V1_W1_SUBINDEX GENMASK(31, 24)
+#define FW_HDR_V1_W2_COMMITID GENMASK(31, 0)
+#define FW_HDR_V1_W3_CMD_VERSERION GENMASK(23, 16)
+#define FW_HDR_V1_W3_HDR_VER GENMASK(31, 24)
+#define FW_HDR_V1_W4_MONTH GENMASK(7, 0)
+#define FW_HDR_V1_W4_DATE GENMASK(15, 8)
+#define FW_HDR_V1_W4_HOUR GENMASK(23, 16)
+#define FW_HDR_V1_W4_MIN GENMASK(31, 24)
+#define FW_HDR_V1_W5_YEAR GENMASK(15, 0)
+#define FW_HDR_V1_W5_HDR_SIZE GENMASK(31, 16)
+#define FW_HDR_V1_W6_SEC_NUM GENMASK(15, 8)
+#define FW_HDR_V1_W7_DYN_HDR BIT(16)
+
static inline void SET_FW_HDR_PART_SIZE(void *fwhdr, u32 val)
{
le32p_replace_bits((__le32 *)fwhdr + 7, val, GENMASK(15, 0));