diff mbox series

[3/8] wifi: rtw89: efuse: read firmware secure info v0 from efuse for WiFi 6 chips

Message ID 20241030022135.11688-4-pkshih@realtek.com
State New
Headers show
Series [1/8] wifi: rtw89: efuse: move reading efuse of fw secure info to common | expand

Commit Message

Ping-Ke Shih Oct. 30, 2024, 2:21 a.m. UTC
WiFi 6 chips could program secure information in v0 or v1 format. Use
existing v1 parser or newly added v0 parser to recognize firmware key
that is going to be used.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
---
 drivers/net/wireless/realtek/rtw89/core.h  |  5 +-
 drivers/net/wireless/realtek/rtw89/efuse.c | 86 ++++++++++++++++++++++
 2 files changed, 90 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 5fa59cd138c1..ccee011c9975 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -4516,11 +4516,14 @@  enum rtw89_fw_mss_dev_type {
 };
 
 struct rtw89_fw_secure {
-	bool secure_boot;
+	bool secure_boot: 1;
+	bool can_mss_v1: 1;
+	bool can_mss_v0: 1;
 	u32 sb_sel_mgn;
 	u8 mss_dev_type;
 	u8 mss_cust_idx;
 	u8 mss_key_num;
+	u8 mss_idx; /* v0 */
 };
 
 struct rtw89_fw_info {
diff --git a/drivers/net/wireless/realtek/rtw89/efuse.c b/drivers/net/wireless/realtek/rtw89/efuse.c
index a02b04eecd05..6c6c763510af 100644
--- a/drivers/net/wireless/realtek/rtw89/efuse.c
+++ b/drivers/net/wireless/realtek/rtw89/efuse.c
@@ -16,6 +16,20 @@ 
 #define EFUSE_B2_MSSKEYNUM_MASK GENMASK(3, 0)
 #define EFUSE_B2_MSSCUSTIDX1_MASK BIT(6)
 
+#define EFUSE_EXTERNALPN_ADDR_AX 0x5EC
+#define EFUSE_CUSTOMER_ADDR_AX 0x5ED
+#define EFUSE_SERIALNUM_ADDR_AX 0x5ED
+
+#define EFUSE_B1_EXTERNALPN_MASK GENMASK(7, 0)
+#define EFUSE_B2_CUSTOMER_MASK GENMASK(3, 0)
+#define EFUSE_B2_SERIALNUM_MASK GENMASK(6, 4)
+
+#define OTP_KEY_INFO_NUM 2
+
+static const u8 otp_key_info_externalPN[OTP_KEY_INFO_NUM] = {0x0, 0x0};
+static const u8 otp_key_info_customer[OTP_KEY_INFO_NUM]   = {0x0, 0x1};
+static const u8 otp_key_info_serialNum[OTP_KEY_INFO_NUM]  = {0x0, 0x1};
+
 enum rtw89_efuse_bank {
 	RTW89_EFUSE_BANK_WIFI,
 	RTW89_EFUSE_BANK_BT,
@@ -397,24 +411,96 @@  static u8 get_mss_dev_type_idx(struct rtw89_dev *rtwdev, u8 mss_dev_type)
 
 int rtw89_efuse_recognize_mss_info_v1(struct rtw89_dev *rtwdev, u8 b1, u8 b2)
 {
+	const struct rtw89_chip_info *chip = rtwdev->chip;
 	struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
 	u8 mss_dev_type;
 
+	if (chip->chip_id == RTL8852B && b1 == 0xFF && b2 == 0x6E) {
+		mss_dev_type = MSS_DEV_TYPE_FWSEC_NONLIN_INBOX_NON_COB;
+		sec->mss_cust_idx = 0;
+		sec->mss_key_num = 0;
+
+		goto mss_dev_type;
+	}
+
 	mss_dev_type = u8_get_bits(b1, EFUSE_B1_MSSDEVTYPE_MASK);
 	sec->mss_cust_idx = 0x1F - (u8_get_bits(b1, EFUSE_B1_MSSCUSTIDX0_MASK) |
 				    u8_get_bits(b2, EFUSE_B2_MSSCUSTIDX1_MASK) << 4);
 	sec->mss_key_num = 0xF - u8_get_bits(b2, EFUSE_B2_MSSKEYNUM_MASK);
 
+mss_dev_type:
 	sec->mss_dev_type = get_mss_dev_type_idx(rtwdev, mss_dev_type);
 	if (sec->mss_dev_type == RTW89_FW_MSS_DEV_TYPE_FWSEC_INV) {
 		rtw89_warn(rtwdev, "invalid mss_dev_type %d\n", mss_dev_type);
 		return -ENOENT;
 	}
 
+	sec->can_mss_v1 = true;
+
 	return 0;
 }
 
+static
+int rtw89_efuse_recognize_mss_index_v0(struct rtw89_dev *rtwdev, u8 b1, u8 b2)
+{
+	struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
+	u8 externalPN;
+	u8 serialNum;
+	u8 customer;
+	u8 i;
+
+	externalPN = 0xFF - u8_get_bits(b1, EFUSE_B1_EXTERNALPN_MASK);
+	customer = 0xF - u8_get_bits(b2, EFUSE_B2_CUSTOMER_MASK);
+	serialNum = 0x7 - u8_get_bits(b2, EFUSE_B2_SERIALNUM_MASK);
+
+	for (i = 0; i < OTP_KEY_INFO_NUM; i++) {
+		if (externalPN == otp_key_info_externalPN[i] &&
+		    customer == otp_key_info_customer[i] &&
+		    serialNum == otp_key_info_serialNum[i]) {
+			sec->mss_idx = i;
+			sec->can_mss_v0 = true;
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+
 int rtw89_efuse_read_fw_secure_ax(struct rtw89_dev *rtwdev)
 {
+	struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
+	u32 sec_addr = EFUSE_EXTERNALPN_ADDR_AX;
+	u32 sec_size = 2;
+	u8 sec_map[2];
+	u8 b1, b2;
+	int ret;
+
+	ret = rtw89_dump_physical_efuse_map(rtwdev, sec_map,
+					    sec_addr, sec_size, false);
+	if (ret) {
+		rtw89_warn(rtwdev, "failed to dump secsel map\n");
+		return ret;
+	}
+
+	b1 = sec_map[0];
+	b2 = sec_map[1];
+
+	if (b1 == 0xFF && b2 == 0xFF)
+		return 0;
+
+	rtw89_efuse_recognize_mss_index_v0(rtwdev, b1, b2);
+	rtw89_efuse_recognize_mss_info_v1(rtwdev, b1, b2);
+	if (!sec->can_mss_v1 && !sec->can_mss_v0)
+		goto out;
+
+	sec->secure_boot = true;
+
+out:
+	rtw89_debug(rtwdev, RTW89_DBG_FW,
+		    "MSS secure_boot=%d(%d/%d) dev_type=%d cust_idx=%d key_num=%d mss_index=%d\n",
+		    sec->secure_boot, sec->can_mss_v0, sec->can_mss_v1,
+		    sec->mss_dev_type, sec->mss_cust_idx,
+		    sec->mss_key_num, sec->mss_idx);
+
 	return 0;
 }