iwlwifi: Add support for getting rf id with blank otp
authorMatti Gottlieb <matti.gottlieb@intel.com>
Thu, 26 Aug 2021 19:47:46 +0000 (22:47 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Fri, 22 Oct 2021 07:40:57 +0000 (10:40 +0300)
When having a blank OTP the only way to get the rf id
and the cdb info is from prph registers.

Currently there is some implementation for this, but it
is located in the wrong place in the code (should be before
trying to understand what HW is connected and not after),
and it has a partial implementation.

Signed-off-by: Matti Gottlieb <matti.gottlieb@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20210826224715.820c2ae18c2b.Iec9b2e2615ce65e6aff5ce896589227a7030f4cf@changeid
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
drivers/net/wireless/intel/iwlwifi/iwl-prph.h
drivers/net/wireless/intel/iwlwifi/pcie/drv.c

index 6dcafd0a3d4b1aaf5040ac0b6bc002a19ff8a1a5..b7f2f0662b826ca228aabe39cf17faefd5da833e 100644 (file)
@@ -2077,7 +2077,7 @@ static u32 iwl_dump_ini_info(struct iwl_fw_runtime *fwrt,
         */
        hw_type = CSR_HW_REV_TYPE(fwrt->trans->hw_rev);
        if (hw_type == IWL_AX210_HW_TYPE) {
-               u32 prph_val = iwl_read_prph(fwrt->trans, WFPM_OTP_CFG1_ADDR);
+               u32 prph_val = iwl_read_prph(fwrt->trans, WFPM_OTP_CFG1_ADDR_GEN2);
                u32 is_jacket = !!(prph_val & WFPM_OTP_CFG1_IS_JACKET_BIT);
                u32 is_cdb = !!(prph_val & WFPM_OTP_CFG1_IS_CDB_BIT);
                u32 masked_bits = is_jacket | (is_cdb << 1);
index 521ca2bb0e928a3da2e8c3c4b5b29f03bd86c50e..9036b32ec765d4650f0a564c4095dd7f4f992e05 100644 (file)
@@ -342,10 +342,6 @@ struct iwl_fw_ini_dump_cfg_name {
 #define IWL_AX210_HW_TYPE 0x42
 /* How many bits to roll when adding to the HW type of AX210 HW */
 #define IWL_AX210_HW_TYPE_ADDITION_SHIFT 12
-/* This prph is used to tell apart HW_TYPE == 0x42 NICs */
-#define WFPM_OTP_CFG1_ADDR 0xd03098
-#define WFPM_OTP_CFG1_IS_JACKET_BIT BIT(4)
-#define WFPM_OTP_CFG1_IS_CDB_BIT BIT(5)
 
 /* struct iwl_fw_ini_dump_info - ini dump information
  * @version: dump version
index d0a7d58336a9eeef6069a7b519ffac9ce5c04771..48213d61bac7c673dfb99b33d81bb1f3f25be8a7 100644 (file)
 #define RADIO_REG_SYS_MANUAL_DFT_0     0xAD4078
 #define RFIC_REG_RD                    0xAD0470
 #define WFPM_CTRL_REG                  0xA03030
+#define WFPM_CTRL_REG_GEN2             0xd03030
+#define WFPM_OTP_CFG1_ADDR             0x00a03098
+#define WFPM_OTP_CFG1_ADDR_GEN2                0x00d03098
+#define WFPM_OTP_CFG1_IS_JACKET_BIT    BIT(4)
+#define WFPM_OTP_CFG1_IS_CDB_BIT       BIT(5)
+
 #define WFPM_GP2                       0xA030B4
 
 /* DBGI SRAM Register details */
@@ -399,10 +405,39 @@ enum {
        LMPM_PAGE_PASS_NOTIF_POS = BIT(20),
 };
 
+/*
+ * CRF ID register
+ *
+ * type: bits 0-11
+ * reserved: bits 12-18
+ * slave_exist: bit 19
+ * dash: bits 20-23
+ * step: bits 24-26
+ * flavor: bits 27-31
+ */
+#define REG_CRF_ID_TYPE(val)           (((val) & 0x00000FFF) >> 0)
+#define REG_CRF_ID_SLAVE(val)          (((val) & 0x00080000) >> 19)
+#define REG_CRF_ID_DASH(val)           (((val) & 0x00F00000) >> 20)
+#define REG_CRF_ID_STEP(val)           (((val) & 0x07000000) >> 24)
+#define REG_CRF_ID_FLAVOR(val)         (((val) & 0xF8000000) >> 27)
+
 #define UREG_CHICK             (0xA05C00)
 #define UREG_CHICK_MSI_ENABLE  BIT(24)
 #define UREG_CHICK_MSIX_ENABLE BIT(25)
 
+#define SD_REG_VER             0xa29600
+#define SD_REG_VER_GEN2                0x00a2b800
+
+#define REG_CRF_ID_TYPE_JF_1                   0x201
+#define REG_CRF_ID_TYPE_JF_2                   0x202
+#define REG_CRF_ID_TYPE_HR_CDB                 0x503
+#define REG_CRF_ID_TYPE_HR_NONE_CDB            0x504
+#define REG_CRF_ID_TYPE_HR_NONE_CDB_1X1        0x501
+#define REG_CRF_ID_TYPE_HR_NONE_CDB_CCP        0x532
+#define REG_CRF_ID_TYPE_GF                     0x410
+#define REG_CRF_ID_TYPE_GF_TC                  0xF08
+#define REG_CRF_ID_TYPE_MR                     0x810
+
 #define HPM_DEBUG                      0xA03440
 #define PERSISTENCE_BIT                        BIT(12)
 #define PREG_WFPM_ACCESS               BIT(12)
index 3b974388d834d0acc17403feeb0605746ab7e1be..1a009bb047cdeb7037c3b9cc54f6159abcc6540d 100644 (file)
@@ -1191,6 +1191,92 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
 #endif /* CONFIG_IWLMVM */
 };
 
+/*
+ * In case that there is no OTP on the NIC, get the rf id and cdb info
+ * from the prph registers.
+ */
+static int get_crf_id(struct iwl_trans *iwl_trans)
+{
+       int ret = 0;
+       u32 wfpm_ctrl_addr;
+       u32 wfpm_otp_cfg_addr;
+       u32 sd_reg_ver_addr;
+       u32 cdb = 0;
+       u32 val;
+
+       if (iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+               wfpm_ctrl_addr = WFPM_CTRL_REG_GEN2;
+               wfpm_otp_cfg_addr = WFPM_OTP_CFG1_ADDR_GEN2;
+               sd_reg_ver_addr = SD_REG_VER_GEN2;
+       /* Qu/Pu families have other addresses */
+       } else {
+               wfpm_ctrl_addr = WFPM_CTRL_REG;
+               wfpm_otp_cfg_addr = WFPM_OTP_CFG1_ADDR;
+               sd_reg_ver_addr = SD_REG_VER;
+       }
+
+       if (!iwl_trans_grab_nic_access(iwl_trans)) {
+               IWL_ERR(iwl_trans, "Failed to grab nic access before reading crf id\n");
+               ret = -EIO;
+               goto out;
+       }
+
+       /* Enable access to peripheral registers */
+       val = iwl_read_umac_prph_no_grab(iwl_trans, wfpm_ctrl_addr);
+       val |= ENABLE_WFPM;
+       iwl_write_umac_prph_no_grab(iwl_trans, wfpm_ctrl_addr, val);
+
+       /* Read crf info */
+       val = iwl_read_prph_no_grab(iwl_trans, sd_reg_ver_addr);
+
+       /* Read cdb info (also contains the jacket info if needed in the future */
+       cdb = iwl_read_umac_prph_no_grab(iwl_trans, wfpm_otp_cfg_addr);
+
+       /* Map between crf id to rf id */
+       switch (REG_CRF_ID_TYPE(val)) {
+       case REG_CRF_ID_TYPE_JF_1:
+               iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_JF1 << 12);
+               break;
+       case REG_CRF_ID_TYPE_JF_2:
+               iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_JF2 << 12);
+               break;
+       case REG_CRF_ID_TYPE_HR_NONE_CDB:
+               iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_HR1 << 12);
+               break;
+       case REG_CRF_ID_TYPE_HR_CDB:
+               iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_HR2 << 12);
+               break;
+       case REG_CRF_ID_TYPE_GF:
+               iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_GF << 12);
+               break;
+       case REG_CRF_ID_TYPE_MR:
+               iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_MR << 12);
+               break;
+       default:
+               ret = -EIO;
+               IWL_ERR(iwl_trans,
+                       "Can find a correct rfid for crf id 0x%x\n",
+                       REG_CRF_ID_TYPE(val));
+               goto out_release;
+
+       }
+
+       /* Set CDB capabilities */
+       if (cdb & BIT(4)) {
+               iwl_trans->hw_rf_id += BIT(28);
+               IWL_INFO(iwl_trans, "Adding cdb to rf id\n");
+       }
+
+       IWL_INFO(iwl_trans, "Detected RF 0x%x from crf id 0x%x\n",
+                iwl_trans->hw_rf_id, REG_CRF_ID_TYPE(val));
+
+out_release:
+       iwl_trans_release_nic_access(iwl_trans);
+
+out:
+       return ret;
+}
+
 /* PCI registers */
 #define PCI_CFG_RETRY_TIMEOUT  0x041
 
@@ -1224,6 +1310,16 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        iwl_trans->hw_rf_id = iwl_read32(iwl_trans, CSR_HW_RF_ID);
 
+       /*
+        * The RF_ID is set to zero in blank OTP so read version to
+        * extract the RF_ID.
+        * This is relevant only for family 9000 and up.
+        */
+       if (iwl_trans->trans_cfg->rf_id &&
+           iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_9000 &&
+           !CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id) && get_crf_id(iwl_trans))
+               goto out_free_trans;
+
        for (i = 0; i < ARRAY_SIZE(iwl_dev_info_table); i++) {
                const struct iwl_dev_info *dev_info = &iwl_dev_info_table[i];
                if ((dev_info->device == (u16)IWL_CFG_ANY ||