wifi: ath12k: Read board id to support split-PHY QCN9274
authorGanesh Babu Jothiram <quic_gjothira@quicinc.com>
Mon, 29 Jan 2024 06:57:23 +0000 (12:27 +0530)
committerKalle Valo <quic_kvalo@quicinc.com>
Fri, 2 Feb 2024 12:32:52 +0000 (14:32 +0200)
QCN9274 can support single-PHY or split-PHY architecture. Currently,
only the single-PHY architecture is supported in ath12k.

The split-PHY QCN9274 requires different AMSS firmware binary
"amss_dualmac.bin".

Hence, add support to read board id from OTP. Based on board id
decide whether single-mac / dual-mac firmware needs to be downloaded
to the target. Also, update HW param max_radios to support split-PHY
in QCN9274.

Also, add new Firmware IE for firmware_N.bin
"ATH11K_FW_IE_AMSS_DUALMAC_IMAGE" to support dualmac QCN9274.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.1.1-00188-QCAHKSWPL_SILICONZ-1
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3

Signed-off-by: Ganesh Babu Jothiram <quic_gjothira@quicinc.com>
Co-developed-by: Raj Kumar Bhagat <quic_rajkbhag@quicinc.com>
Signed-off-by: Raj Kumar Bhagat <quic_rajkbhag@quicinc.com>
Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://msgid.link/20240129065724.2310207-13-quic_rajkbhag@quicinc.com
drivers/net/wireless/ath/ath12k/core.h
drivers/net/wireless/ath/ath12k/fw.c
drivers/net/wireless/ath/ath12k/fw.h
drivers/net/wireless/ath/ath12k/hw.c
drivers/net/wireless/ath/ath12k/hw.h
drivers/net/wireless/ath/ath12k/mac.c
drivers/net/wireless/ath/ath12k/mhi.c
drivers/net/wireless/ath/ath12k/pci.h

index 67bf8d840b003e029f7a8240e415606c17a2c93d..f0a319ea57c1d47d28358c870320a56fbcd13ba9 100644 (file)
@@ -832,6 +832,8 @@ struct ath12k_base {
                const struct firmware *fw;
                const u8 *amss_data;
                size_t amss_len;
+               const u8 *amss_dualmac_data;
+               size_t amss_dualmac_len;
                const u8 *m3_data;
                size_t m3_len;
 
index fbcf40c97792c8fae48bf0db256453704ace2ba3..5be4b2d4a19d8920042b7b05460aecf380490c4f 100644 (file)
@@ -119,6 +119,13 @@ static int ath12k_fw_request_firmware_api_n(struct ath12k_base *ab,
                        ab->fw.m3_data = data;
                        ab->fw.m3_len = ie_len;
                        break;
+               case ATH12K_FW_IE_AMSS_DUALMAC_IMAGE:
+                       ath12k_dbg(ab, ATH12K_DBG_BOOT,
+                                  "found dualmac fw image ie (%zd B)\n",
+                                  ie_len);
+                       ab->fw.amss_dualmac_data = data;
+                       ab->fw.amss_dualmac_len = ie_len;
+                       break;
                default:
                        ath12k_warn(ab, "Unknown FW IE: %u\n", ie_id);
                        break;
index 28dc1423df70aea61931fc98161d5cb0ce629721..3ff041f15fa0efd5c12b6dbc41a7ca02bb3360b5 100644 (file)
@@ -14,6 +14,7 @@ enum ath12k_fw_ie_type {
        ATH12K_FW_IE_FEATURES = 1,
        ATH12K_FW_IE_AMSS_IMAGE = 2,
        ATH12K_FW_IE_M3_IMAGE = 3,
+       ATH12K_FW_IE_AMSS_DUALMAC_IMAGE = 4,
 };
 
 enum ath12k_fw_features {
index f399511746a87ad31cb3024a12559beb4fd3896c..a9adb547c83d25a6b6c0494851e9d9ba4d67617c 100644 (file)
@@ -916,6 +916,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
 
                .def_num_link = 0,
                .max_mlo_peer = 256,
+
+               .otp_board_id_register = QCN9274_QFPROM_RAW_RFA_PDET_ROW13_LSB,
        },
        {
                .name = "wcn7850 hw2.0",
@@ -982,6 +984,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
 
                .def_num_link = 2,
                .max_mlo_peer = 32,
+
+               .otp_board_id_register = 0,
        },
        {
                .name = "qcn9274 hw2.0",
@@ -991,7 +995,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
                        .board_size = 256 * 1024,
                        .cal_offset = 128 * 1024,
                },
-               .max_radios = 1,
+               .max_radios = 2,
                .single_pdev_only = false,
                .qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9274,
                .internal_sleep_clock = false,
@@ -1046,6 +1050,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = {
 
                .def_num_link = 0,
                .max_mlo_peer = 256,
+
+               .otp_board_id_register = QCN9274_QFPROM_RAW_RFA_PDET_ROW13_LSB,
        },
 };
 
index 987188f56b291d72f3cc891b569eac18ffd0850a..2e9c3b05d75ac53d8e803c9845c582d21b8ced28 100644 (file)
@@ -207,6 +207,8 @@ struct ath12k_hw_params {
 
        u8 def_num_link;
        u16 max_mlo_peer;
+
+       u32 otp_board_id_register;
 };
 
 struct ath12k_hw_ops {
index 046bb466a391f30fb3c1ee931f84ac3d389684ea..6ef55876e7dfae80dffa9ef569160f62c30c1e32 100644 (file)
@@ -563,7 +563,8 @@ struct ath12k_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab,
 
        for (i = 0; i < ab->num_radios; i++) {
                pdev = rcu_dereference(ab->pdevs_active[i]);
-               if (pdev && pdev->ar) {
+               if (pdev && pdev->ar &&
+                   (pdev->ar->allocated_vdev_map & (1LL << vdev_id))) {
                        arvif = ath12k_mac_get_arvif(pdev->ar, vdev_id);
                        if (arvif)
                                return arvif;
index b7b31978a434d795f9eec944c4ad0360f51fd157..50b9e44504f78d345e5fe8190532f1959462e069 100644 (file)
@@ -14,6 +14,8 @@
 #include "pci.h"
 
 #define MHI_TIMEOUT_DEFAULT_MS 90000
+#define OTP_INVALID_BOARD_ID   0xFFFF
+#define OTP_VALID_DUALMAC_BOARD_ID_MASK                0x1000
 
 static const struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = {
        {
@@ -359,7 +361,9 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci)
 {
        struct ath12k_base *ab = ab_pci->ab;
        struct mhi_controller *mhi_ctrl;
+       unsigned int board_id;
        int ret;
+       bool dualmac = false;
 
        mhi_ctrl = mhi_alloc_controller();
        if (!mhi_ctrl)
@@ -371,16 +375,43 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci)
        mhi_ctrl->reg_len = ab->mem_len;
        mhi_ctrl->rddm_size = ab->hw_params->rddm_size;
 
-       if (ab->fw.amss_data && ab->fw.amss_len > 0) {
-               /* use MHI firmware file from firmware-N.bin */
-               mhi_ctrl->fw_data = ab->fw.amss_data;
-               mhi_ctrl->fw_sz = ab->fw.amss_len;
+       if (ab->hw_params->otp_board_id_register) {
+               board_id =
+                       ath12k_pci_read32(ab, ab->hw_params->otp_board_id_register);
+               board_id = u32_get_bits(board_id, OTP_BOARD_ID_MASK);
+
+               if (!board_id || (board_id == OTP_INVALID_BOARD_ID)) {
+                       ath12k_dbg(ab, ATH12K_DBG_BOOT,
+                                  "failed to read board id\n");
+               } else if (board_id & OTP_VALID_DUALMAC_BOARD_ID_MASK) {
+                       dualmac = true;
+                       ath12k_dbg(ab, ATH12K_DBG_BOOT,
+                                  "dualmac fw selected for board id: %x\n", board_id);
+               }
+       }
+
+       if (dualmac) {
+               if (ab->fw.amss_dualmac_data && ab->fw.amss_dualmac_len > 0) {
+                       /* use MHI firmware file from firmware-N.bin */
+                       mhi_ctrl->fw_data = ab->fw.amss_dualmac_data;
+                       mhi_ctrl->fw_sz = ab->fw.amss_dualmac_len;
+               } else {
+                       ath12k_warn(ab, "dualmac firmware IE not present in firmware-N.bin\n");
+                       ret = -ENOENT;
+                       goto free_controller;
+               }
        } else {
-               /* use the old separate mhi.bin MHI firmware file */
-               ath12k_core_create_firmware_path(ab, ATH12K_AMSS_FILE,
-                                                ab_pci->amss_path,
-                                                sizeof(ab_pci->amss_path));
-               mhi_ctrl->fw_image = ab_pci->amss_path;
+               if (ab->fw.amss_data && ab->fw.amss_len > 0) {
+                       /* use MHI firmware file from firmware-N.bin */
+                       mhi_ctrl->fw_data = ab->fw.amss_data;
+                       mhi_ctrl->fw_sz = ab->fw.amss_len;
+               } else {
+                       /* use the old separate mhi.bin MHI firmware file */
+                       ath12k_core_create_firmware_path(ab, ATH12K_AMSS_FILE,
+                                                        ab_pci->amss_path,
+                                                        sizeof(ab_pci->amss_path));
+                       mhi_ctrl->fw_image = ab_pci->amss_path;
+               }
        }
 
        ret = ath12k_mhi_get_msi(ab_pci);
index 023616928f03e3c95786f9e5ccd1c9667ff1804a..ca93693ba4e948ebbc153955d24115855307a2bb 100644 (file)
@@ -53,6 +53,9 @@
 #define WLAON_QFPROM_PWR_CTRL_REG              0x01f8031c
 #define QFPROM_PWR_CTRL_VDD4BLOW_MASK          0x4
 
+#define QCN9274_QFPROM_RAW_RFA_PDET_ROW13_LSB  0x1E20338
+#define OTP_BOARD_ID_MASK                      GENMASK(15, 0)
+
 #define PCI_BAR_WINDOW0_BASE   0x1E00000
 #define PCI_BAR_WINDOW0_END    0x1E7FFFC
 #define PCI_SOC_RANGE_MASK     0x3FFF