]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: rtw89: 8922d: define efuse map and read necessary fields
authorPing-Ke Shih <pkshih@realtek.com>
Tue, 24 Mar 2026 06:20:45 +0000 (14:20 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Mon, 30 Mar 2026 02:05:26 +0000 (10:05 +0800)
Define specific efuse map for RTL8922D, including TSSI, RX gain, MAC
address, RFE type and etc. The additional fields comparing to existing
chips are BT setting (define BT switch GPIO, antenna number and etc) and
gain offset2 (define more fields like existing RX gain offset).

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20260324062049.52266-4-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/rtw8922d.c
drivers/net/wireless/realtek/rtw89/rtw8922d.h

index 94e4faf70e12fe3a5078fad30e9e2f1bde7e05d9..d0ae3e15253b425469a6ad90cc1c0cf4141dbfd2 100644 (file)
@@ -3562,6 +3562,8 @@ struct rtw89_efuse {
        u8 rfe_type;
        char country_code[2];
        u8 adc_td;
+       u8 bt_setting_2;
+       u8 bt_setting_3;
 };
 
 struct rtw89_phy_rate_pattern {
@@ -5926,6 +5928,7 @@ struct rtw89_phy_efuse_gain {
        bool offset_valid;
        bool comp_valid;
        s8 offset[RF_PATH_MAX][RTW89_GAIN_OFFSET_NR]; /* S(8, 0) */
+       s8 offset2[RF_PATH_MAX][RTW89_GAIN_OFFSET_NR]; /* S(8, 0) */
        s8 offset_base[RTW89_PHY_NUM]; /* S(8, 4) */
        s8 rssi_base[RTW89_PHY_NUM]; /* S(8, 4) */
        s8 comp[RF_PATH_MAX][RTW89_SUBBAND_NR]; /* S(8, 0) */
index 194e2901232b01eb17ebebcd4475b58c602c8f41..0ae34a4f8d79bd6b66b5b5013ad4376623d4543f 100644 (file)
@@ -2,6 +2,7 @@
 /* Copyright(c) 2026  Realtek Corporation
  */
 
+#include "debug.h"
 #include "efuse.h"
 #include "mac.h"
 #include "reg.h"
@@ -468,6 +469,167 @@ static int rtw8922d_pwr_off_func(struct rtw89_dev *rtwdev)
        return 0;
 }
 
+static void rtw8922d_efuse_parsing_tssi(struct rtw89_dev *rtwdev,
+                                       struct rtw8922d_efuse *map)
+{
+       const struct rtw8922d_tssi_offset_6g * const ofst_6g[] = {
+               &map->path_a_tssi_6g,
+               &map->path_b_tssi_6g,
+       };
+       const struct rtw8922d_tssi_offset * const ofst[] = {
+               &map->path_a_tssi,
+               &map->path_b_tssi,
+       };
+       struct rtw89_tssi_info *tssi = &rtwdev->tssi;
+       u8 i, j;
+
+       tssi->thermal[RF_PATH_A] = map->path_a_therm;
+       tssi->thermal[RF_PATH_B] = map->path_b_therm;
+
+       for (i = 0; i < RF_PATH_NUM_8922D; i++) {
+               memcpy(tssi->tssi_cck[i], ofst[i]->cck_tssi, TSSI_CCK_CH_GROUP_NUM);
+
+               for (j = 0; j < TSSI_CCK_CH_GROUP_NUM; j++)
+                       rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+                                   "[TSSI][EFUSE] path=%d cck[%d]=0x%x\n",
+                                   i, j, tssi->tssi_cck[i][j]);
+
+               memcpy(tssi->tssi_mcs[i], ofst[i]->bw40_tssi,
+                      TSSI_MCS_2G_CH_GROUP_NUM);
+               memcpy(tssi->tssi_mcs[i] + TSSI_MCS_2G_CH_GROUP_NUM,
+                      ofst[i]->bw40_1s_tssi_5g, TSSI_MCS_5G_CH_GROUP_NUM);
+               memcpy(tssi->tssi_6g_mcs[i], ofst_6g[i]->bw40_1s_tssi_6g,
+                      TSSI_MCS_6G_CH_GROUP_NUM);
+
+               for (j = 0; j < TSSI_MCS_CH_GROUP_NUM; j++)
+                       rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+                                   "[TSSI][EFUSE] path=%d mcs[%d]=0x%x\n",
+                                   i, j, tssi->tssi_mcs[i][j]);
+
+               for (j = 0; j < TSSI_MCS_6G_CH_GROUP_NUM; j++)
+                       rtw89_debug(rtwdev, RTW89_DBG_TSSI,
+                                   "[TSSI][EFUSE] path=%d mcs_6g[%d]=0x%x\n",
+                                   i, j, tssi->tssi_6g_mcs[i][j]);
+       }
+}
+
+static void
+__rtw8922d_efuse_parsing_gain_offset(struct rtw89_dev *rtwdev,
+                                    s8 offset[RTW89_GAIN_OFFSET_NR],
+                                    const s8 *offset_default,
+                                    const struct rtw8922d_rx_gain *rx_gain,
+                                    const struct rtw8922d_rx_gain_6g *rx_gain_6g)
+{
+       int i;
+       u8 t;
+
+       offset[RTW89_GAIN_OFFSET_2G_CCK] = rx_gain->_2g_cck;
+       offset[RTW89_GAIN_OFFSET_2G_OFDM] = rx_gain->_2g_ofdm;
+       offset[RTW89_GAIN_OFFSET_5G_LOW] = rx_gain->_5g_low;
+       offset[RTW89_GAIN_OFFSET_5G_MID] = rx_gain->_5g_mid;
+       offset[RTW89_GAIN_OFFSET_5G_HIGH] = rx_gain->_5g_high;
+       offset[RTW89_GAIN_OFFSET_6G_L0] = rx_gain_6g->_6g_l0;
+       offset[RTW89_GAIN_OFFSET_6G_L1] = rx_gain_6g->_6g_l1;
+       offset[RTW89_GAIN_OFFSET_6G_M0] = rx_gain_6g->_6g_m0;
+       offset[RTW89_GAIN_OFFSET_6G_M1] = rx_gain_6g->_6g_m1;
+       offset[RTW89_GAIN_OFFSET_6G_H0] = rx_gain_6g->_6g_h0;
+       offset[RTW89_GAIN_OFFSET_6G_H1] = rx_gain_6g->_6g_h1;
+       offset[RTW89_GAIN_OFFSET_6G_UH0] = rx_gain_6g->_6g_uh0;
+       offset[RTW89_GAIN_OFFSET_6G_UH1] = rx_gain_6g->_6g_uh1;
+
+       for (i = 0; i < RTW89_GAIN_OFFSET_NR; i++) {
+               t = offset[i];
+               if (t == 0xff) {
+                       if (offset_default) {
+                               offset[i] = offset_default[i];
+                               continue;
+                       }
+                       t = 0;
+               }
+
+               /* transform: sign-bit + U(7,2) to S(8,2) */
+               if (t & 0x80)
+                       offset[i] = (t ^ 0x7f) + 1;
+               else
+                       offset[i] = t;
+       }
+}
+
+static void rtw8922d_efuse_parsing_gain_offset(struct rtw89_dev *rtwdev,
+                                              struct rtw8922d_efuse *map)
+{
+       struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain;
+
+       __rtw8922d_efuse_parsing_gain_offset(rtwdev, gain->offset[RF_PATH_A],
+                                            NULL,
+                                            &map->rx_gain_a, &map->rx_gain_6g_a);
+       __rtw8922d_efuse_parsing_gain_offset(rtwdev, gain->offset[RF_PATH_B],
+                                            NULL,
+                                            &map->rx_gain_b, &map->rx_gain_6g_b);
+
+       __rtw8922d_efuse_parsing_gain_offset(rtwdev, gain->offset2[RF_PATH_A],
+                                            gain->offset[RF_PATH_A],
+                                            &map->rx_gain_a_2, &map->rx_gain_6g_a_2);
+       __rtw8922d_efuse_parsing_gain_offset(rtwdev, gain->offset2[RF_PATH_B],
+                                            gain->offset[RF_PATH_B],
+                                            &map->rx_gain_b_2, &map->rx_gain_6g_b_2);
+
+       gain->offset_valid = true;
+}
+
+static int rtw8922d_read_efuse_pci_sdio(struct rtw89_dev *rtwdev, u8 *log_map)
+{
+       struct rtw89_efuse *efuse = &rtwdev->efuse;
+
+       if (rtwdev->hci.type == RTW89_HCI_TYPE_PCIE)
+               ether_addr_copy(efuse->addr, log_map + 0x4104);
+       else
+               ether_addr_copy(efuse->addr, log_map + 0x001A);
+
+       return 0;
+}
+
+static int rtw8922d_read_efuse_usb(struct rtw89_dev *rtwdev, u8 *log_map)
+{
+       struct rtw89_efuse *efuse = &rtwdev->efuse;
+
+       ether_addr_copy(efuse->addr, log_map + 0x0078);
+
+       return 0;
+}
+
+static int rtw8922d_read_efuse_rf(struct rtw89_dev *rtwdev, u8 *log_map)
+{
+       struct rtw8922d_efuse *map = (struct rtw8922d_efuse *)log_map;
+       struct rtw89_efuse *efuse = &rtwdev->efuse;
+
+       efuse->rfe_type = map->rfe_type;
+       efuse->xtal_cap = map->xtal_k;
+       efuse->country_code[0] = map->country_code[0];
+       efuse->country_code[1] = map->country_code[1];
+       efuse->bt_setting_2 = map->bt_setting_2;
+       efuse->bt_setting_3 = map->bt_setting_3;
+       rtw8922d_efuse_parsing_tssi(rtwdev, map);
+       rtw8922d_efuse_parsing_gain_offset(rtwdev, map);
+
+       return 0;
+}
+
+static int rtw8922d_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map,
+                              enum rtw89_efuse_block block)
+{
+       switch (block) {
+       case RTW89_EFUSE_BLOCK_HCI_DIG_PCIE_SDIO:
+               return rtw8922d_read_efuse_pci_sdio(rtwdev, log_map);
+       case RTW89_EFUSE_BLOCK_HCI_DIG_USB:
+               return rtw8922d_read_efuse_usb(rtwdev, log_map);
+       case RTW89_EFUSE_BLOCK_RF:
+               return rtw8922d_read_efuse_rf(rtwdev, log_map);
+       default:
+               return 0;
+       }
+}
+
 MODULE_FIRMWARE(RTW8922D_MODULE_FIRMWARE);
 MODULE_FIRMWARE(RTW8922DS_MODULE_FIRMWARE);
 MODULE_AUTHOR("Realtek Corporation");
index 7ef3f263274e2f0d060c881417f141a403081fd7..a3b98ad6636c46b167b1efa588c47b440a83eec7 100644 (file)
@@ -7,4 +7,74 @@
 
 #include "core.h"
 
+#define RF_PATH_NUM_8922D 2
+#define BB_PATH_NUM_8922D 2
+
+struct rtw8922d_tssi_offset {
+       u8 cck_tssi[TSSI_CCK_CH_GROUP_NUM];
+       u8 bw40_tssi[TSSI_MCS_2G_CH_GROUP_NUM];
+       u8 rsvd[7];
+       u8 bw40_1s_tssi_5g[TSSI_MCS_5G_CH_GROUP_NUM];
+       u8 bw_diff_5g[10];
+} __packed;
+
+struct rtw8922d_tssi_offset_6g {
+       u8 bw40_1s_tssi_6g[TSSI_MCS_6G_CH_GROUP_NUM];
+       u8 rsvd[0xa];
+} __packed;
+
+struct rtw8922d_rx_gain {
+       u8 _2g_ofdm;
+       u8 _2g_cck;
+       u8 _5g_low;
+       u8 _5g_mid;
+       u8 _5g_high;
+} __packed;
+
+struct rtw8922d_rx_gain_6g {
+       u8 _6g_l0;
+       u8 _6g_l1;
+       u8 _6g_m0;
+       u8 _6g_m1;
+       u8 _6g_h0;
+       u8 _6g_h1;
+       u8 _6g_uh0;
+       u8 _6g_uh1;
+} __packed;
+
+struct rtw8922d_efuse {
+       u8 country_code[2];
+       u8 rsvd[0xe];
+       struct rtw8922d_tssi_offset path_a_tssi;
+       struct rtw8922d_tssi_offset path_b_tssi;
+       u8 rsvd1[0x54];
+       u8 channel_plan;
+       u8 xtal_k;
+       u8 rsvd2[0x7];
+       u8 board_info;
+       u8 rsvd3[0x8];
+       u8 rfe_type;
+       u8 rsvd4[2];
+       u8 bt_setting_2;
+       u8 bt_setting_3;
+       u8 rsvd4_2;
+       u8 path_a_therm;
+       u8 path_b_therm;
+       u8 rsvd5[0x2];
+       struct rtw8922d_rx_gain rx_gain_a;
+       struct rtw8922d_rx_gain rx_gain_b;
+       u8 rsvd6[0x18];
+       struct rtw8922d_rx_gain rx_gain_a_2;
+       struct rtw8922d_rx_gain rx_gain_b_2;
+       struct rtw8922d_tssi_offset_6g path_a_tssi_6g;
+       struct rtw8922d_tssi_offset_6g path_b_tssi_6g;
+       struct rtw8922d_tssi_offset_6g path_c_tssi_6g;
+       struct rtw8922d_tssi_offset_6g path_d_tssi_6g;
+       struct rtw8922d_rx_gain_6g rx_gain_6g_a;
+       struct rtw8922d_rx_gain_6g rx_gain_6g_b;
+       u8 rsvd7[0x5a];
+       struct rtw8922d_rx_gain_6g rx_gain_6g_a_2;
+       struct rtw8922d_rx_gain_6g rx_gain_6g_b_2;
+} __packed;
+
 #endif