wifi: rtw89: introduce v1 format of firmware header
authorPing-Ke Shih <pkshih@realtek.com>
Tue, 1 Aug 2023 02:11:22 +0000 (10:11 +0800)
committerKalle Valo <kvalo@kernel.org>
Thu, 3 Aug 2023 12:04:10 +0000 (15:04 +0300)
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
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/fw.c
drivers/net/wireless/realtek/rtw89/fw.h

index f05086b27b2669c6b8ddb3a1390974c7f1341807..01f79f2a8e2b6b238c1b0c53b262de4e05fbd7ab 100644 (file)
@@ -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)      \
index cbb0e953fbbfe4fdd96ee78df4545e611ffb233d..a57d075db74a0d5242ae5aa388fe622714385021 100644 (file)
@@ -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) \
index ad1a621783f904693191a300b3a6a39e6e04d8c4..366645bcead5fdc485affd08f0936173fdecf9c5 100644 (file)
@@ -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));