From: Sowmiya Sree Elavalagan <quic_ssreeela@xxxxxxxxxxx> Currently, ath12k AHB (in IPQ5332) uses SCM calls to authenticate the firmware image to bring up userpd. From IPQ5424 onwards, Q6 firmware can directly communicate with the Trusted Management Engine - Lite (TME-L), eliminating the need for SCM calls for userpd bring-up. Hence, to enable IPQ5424 device support, use qcom_mdt_load_no_init() and skip the SCM call as Q6 will directly authenticate the userpd firmware. Tested-on: IPQ5424 hw1.0 AHB WLAN.WBE.1.5-01053-QCAHKSWPL_SILICONZ-1 Tested-on: IPQ5332 hw1.0 AHB WLAN.WBE.1.3.1-00130-QCAHKSWPL_SILICONZ-1 Signed-off-by: Sowmiya Sree Elavalagan <quic_ssreeela@xxxxxxxxxxx> Co-developed-by: Saravanakumar Duraisamy <quic_saradura@xxxxxxxxxxx> Signed-off-by: Saravanakumar Duraisamy <quic_saradura@xxxxxxxxxxx> Co-developed-by: Raj Kumar Bhagat <quic_rajkbhag@xxxxxxxxxxx> Signed-off-by: Raj Kumar Bhagat <quic_rajkbhag@xxxxxxxxxxx> --- drivers/net/wireless/ath/ath12k/ahb.c | 114 +++++++++++++++++++++------------- drivers/net/wireless/ath/ath12k/ahb.h | 17 ++++- 2 files changed, 86 insertions(+), 45 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/ahb.c b/drivers/net/wireless/ath/ath12k/ahb.c index 40690cef7e57d121c6c41765048d8e64c9320b02..f5a2c176d03d6eebb119165a7fa1a394cf3ef3b2 100644 --- a/drivers/net/wireless/ath/ath12k/ahb.c +++ b/drivers/net/wireless/ath/ath12k/ahb.c @@ -16,15 +16,6 @@ #include "debug.h" #include "hif.h" -static const struct of_device_id ath12k_ahb_of_match[] = { - { .compatible = "qcom,ipq5332-wifi", - .data = (void *)ATH12K_HW_IPQ5332_HW10, - }, - { } -}; - -MODULE_DEVICE_TABLE(of, ath12k_ahb_of_match); - #define ATH12K_IRQ_CE0_OFFSET 4 #define ATH12K_MAX_UPDS 1 #define ATH12K_UPD_IRQ_WRD_LEN 18 @@ -348,9 +339,9 @@ static int ath12k_ahb_power_up(struct ath12k_base *ab) struct reserved_mem *rmem = NULL; unsigned long time_left; phys_addr_t mem_phys; + u32 pasid, userpd_id; void *mem_region; size_t mem_size; - u32 pasid; int ret; rmem = ath12k_core_get_reserved_mem(ab, 0); @@ -366,8 +357,9 @@ static int ath12k_ahb_power_up(struct ath12k_base *ab) return PTR_ERR(mem_region); } + userpd_id = ab_ahb->ahb_data->userpd_id; snprintf(fw_name, sizeof(fw_name), "%s/%s/%s%d%s", ATH12K_FW_DIR, - ab->hw_params->fw.dir, ATH12K_AHB_FW_PREFIX, ab_ahb->userpd_id, + ab->hw_params->fw.dir, ATH12K_AHB_FW_PREFIX, userpd_id, ATH12K_AHB_FW_SUFFIX); ret = request_firmware(&fw, fw_name, dev); @@ -385,12 +377,12 @@ static int ath12k_ahb_power_up(struct ath12k_base *ab) goto err_fw; } - pasid = (u32_encode_bits(ab_ahb->userpd_id, ATH12K_USERPD_ID_MASK)) | + pasid = (u32_encode_bits(userpd_id, ATH12K_USERPD_ID_MASK)) | ATH12K_AHB_UPD_SWID; /* Load FW image to a reserved memory location */ - ret = qcom_mdt_load(dev, fw, fw_name, pasid, mem_region, mem_phys, mem_size, - &mem_phys); + ret = ab_ahb->ahb_data->ahb_ops->mdt_load(dev, fw, fw_name, pasid, mem_region, + mem_phys, mem_size, &mem_phys); if (ret) { ath12k_err(ab, "Failed to load MDT segments: %d\n", ret); goto err_fw; @@ -421,11 +413,13 @@ static int ath12k_ahb_power_up(struct ath12k_base *ab) goto err_fw2; } - /* Authenticate FW image using peripheral ID */ - ret = qcom_scm_pas_auth_and_reset(pasid); - if (ret) { - ath12k_err(ab, "failed to boot the remote processor %d\n", ret); - goto err_fw2; + if (ab_ahb->ahb_data->scm_auth_enabled) { + /* Authenticate FW image using peripheral ID */ + ret = qcom_scm_pas_auth_and_reset(pasid); + if (ret) { + ath12k_err(ab, "failed to boot the remote processor %d\n", ret); + goto err_fw2; + } } /* Instruct Q6 to spawn userPD thread */ @@ -454,7 +448,7 @@ static int ath12k_ahb_power_up(struct ath12k_base *ab) qcom_smem_state_update_bits(ab_ahb->spawn_state, BIT(ab_ahb->spawn_bit), 0); - ath12k_dbg(ab, ATH12K_DBG_AHB, "UserPD%d is now UP\n", ab_ahb->userpd_id); + ath12k_dbg(ab, ATH12K_DBG_AHB, "UserPD%d is now UP\n", userpd_id); err_fw2: release_firmware(fw2); @@ -467,7 +461,7 @@ static void ath12k_ahb_power_down(struct ath12k_base *ab, bool is_suspend) { struct ath12k_ahb *ab_ahb = ath12k_ab_to_ahb(ab); unsigned long time_left; - u32 pasid; + u32 pasid, userpd_id; int ret; qcom_smem_state_update_bits(ab_ahb->stop_state, BIT(ab_ahb->stop_bit), @@ -482,13 +476,16 @@ static void ath12k_ahb_power_down(struct ath12k_base *ab, bool is_suspend) qcom_smem_state_update_bits(ab_ahb->stop_state, BIT(ab_ahb->stop_bit), 0); - pasid = (u32_encode_bits(ab_ahb->userpd_id, ATH12K_USERPD_ID_MASK)) | - ATH12K_AHB_UPD_SWID; - /* Release the firmware */ - ret = qcom_scm_pas_shutdown(pasid); - if (ret) - ath12k_err(ab, "scm pas shutdown failed for userPD%d: %d\n", - ab_ahb->userpd_id, ret); + if (ab_ahb->ahb_data->scm_auth_enabled) { + userpd_id = ab_ahb->ahb_data->userpd_id; + pasid = (u32_encode_bits(userpd_id, ATH12K_USERPD_ID_MASK)) | + ATH12K_AHB_UPD_SWID; + /* Release the firmware */ + ret = qcom_scm_pas_shutdown(pasid); + if (ret) + ath12k_err(ab, "scm pas shutdown failed for userPD%d\n", + userpd_id); + } } static void ath12k_ahb_init_qmi_ce_config(struct ath12k_base *ab) @@ -698,6 +695,14 @@ static int ath12k_ahb_map_service_to_pipe(struct ath12k_base *ab, u16 service_id return 0; } +static const struct ath12k_ahb_ops ahb_ops_ipq5332 = { + .mdt_load = qcom_mdt_load, +}; + +static const struct ath12k_ahb_ops ahb_ops_ipq5424 = { + .mdt_load = qcom_mdt_load_no_init, +}; + static const struct ath12k_hif_ops ath12k_ahb_hif_ops_ipq5332 = { .start = ath12k_ahb_start, .stop = ath12k_ahb_stop, @@ -747,7 +752,7 @@ static int ath12k_ahb_config_rproc_irq(struct ath12k_base *ab) return -ENOMEM; scnprintf(upd_irq_name, ATH12K_UPD_IRQ_WRD_LEN, "UserPD%u-%s", - ab_ahb->userpd_id, ath12k_userpd_irq[i]); + ab_ahb->ahb_data->userpd_id, ath12k_userpd_irq[i]); ret = devm_request_threaded_irq(&ab->pdev->dev, ab_ahb->userpd_irq_num[i], NULL, ath12k_userpd_irq_handler, IRQF_TRIGGER_RISING | IRQF_ONESHOT, @@ -991,10 +996,8 @@ static void ath12k_ahb_resource_deinit(struct ath12k_base *ab) static int ath12k_ahb_probe(struct platform_device *pdev) { struct ath12k_base *ab; - const struct ath12k_hif_ops *hif_ops; struct ath12k_ahb *ab_ahb; - enum ath12k_hw_rev hw_rev; - u32 addr, userpd_id; + u32 addr; int ret; ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); @@ -1008,24 +1011,19 @@ static int ath12k_ahb_probe(struct platform_device *pdev) if (!ab) return -ENOMEM; - hw_rev = (enum ath12k_hw_rev)(kernel_ulong_t)of_device_get_match_data(&pdev->dev); - switch (hw_rev) { - case ATH12K_HW_IPQ5332_HW10: - hif_ops = &ath12k_ahb_hif_ops_ipq5332; - userpd_id = ATH12K_IPQ5332_USERPD_ID; - break; - default: + ab_ahb = ath12k_ab_to_ahb(ab); + ab_ahb->ab = ab; + ab_ahb->ahb_data = + (struct ath12k_ahb_probe_data *)of_device_get_match_data(&pdev->dev); + if (!ab_ahb->ahb_data) { ret = -EOPNOTSUPP; goto err_core_free; } - ab->hif.ops = hif_ops; + ab->hif.ops = ab_ahb->ahb_data->hif_ops; + ab->hw_rev = ab_ahb->ahb_data->hw_rev; ab->pdev = pdev; - ab->hw_rev = hw_rev; platform_set_drvdata(pdev, ab); - ab_ahb = ath12k_ab_to_ahb(ab); - ab_ahb->ab = ab; - ab_ahb->userpd_id = userpd_id; /* Set fixed_mem_region to true for platforms that support fixed memory * reservation from DT. If memory is reserved from DT for FW, ath12k driver @@ -1136,6 +1134,34 @@ static void ath12k_ahb_remove(struct platform_device *pdev) ath12k_ahb_free_resources(ab); } +static const struct ath12k_ahb_probe_data ath12k_ahb_ipq5332 = { + .hw_rev = ATH12K_HW_IPQ5332_HW10, + .userpd_id = ATH12K_IPQ5332_USERPD_ID, + .scm_auth_enabled = true, + .ahb_ops = &ahb_ops_ipq5332, + .hif_ops = &ath12k_ahb_hif_ops_ipq5332, +}; + +static const struct ath12k_ahb_probe_data ath12k_ahb_ipq5424 = { + .hw_rev = ATH12K_HW_IPQ5424_HW10, + .userpd_id = ATH12K_IPQ5332_USERPD_ID, + .scm_auth_enabled = false, + .ahb_ops = &ahb_ops_ipq5424, + .hif_ops = &ath12k_ahb_hif_ops_ipq5332, +}; + +static const struct of_device_id ath12k_ahb_of_match[] = { + { .compatible = "qcom,ipq5332-wifi", + .data = (void *)&ath12k_ahb_ipq5332, + }, + { .compatible = "qcom,ipq5424-wifi", + .data = (void *)&ath12k_ahb_ipq5424, + }, + { } +}; + +MODULE_DEVICE_TABLE(of, ath12k_ahb_of_match); + static struct platform_driver ath12k_ahb_driver = { .driver = { .name = "ath12k_ahb", diff --git a/drivers/net/wireless/ath/ath12k/ahb.h b/drivers/net/wireless/ath/ath12k/ahb.h index d56244b20a6a667cf3730dc1ce38a22b0e86ffca..84415008331a3d719573d4f88e1596f460b1522c 100644 --- a/drivers/net/wireless/ath/ath12k/ahb.h +++ b/drivers/net/wireless/ath/ath12k/ahb.h @@ -43,6 +43,21 @@ enum ath12k_ahb_userpd_irq { struct ath12k_base; +struct ath12k_ahb_ops { + int (*mdt_load)(struct device *dev, const struct firmware *fw, + const char *firmware, int pas_id, void *mem_region, + phys_addr_t mem_phys, size_t mem_size, + phys_addr_t *reloc_base); +}; + +struct ath12k_ahb_probe_data { + enum ath12k_hw_rev hw_rev; + u32 userpd_id; + bool scm_auth_enabled; + const struct ath12k_ahb_ops *ahb_ops; + const struct ath12k_hif_ops *hif_ops; +}; + struct ath12k_ahb { struct ath12k_base *ab; struct rproc *tgt_rproc; @@ -55,10 +70,10 @@ struct ath12k_ahb { struct completion userpd_spawned; struct completion userpd_ready; struct completion userpd_stopped; - u32 userpd_id; u32 spawn_bit; u32 stop_bit; int userpd_irq_num[ATH12K_USERPD_MAX_IRQ]; + const struct ath12k_ahb_probe_data *ahb_data; }; static inline struct ath12k_ahb *ath12k_ab_to_ahb(struct ath12k_base *ab) -- 2.34.1