ath11k: enable internal sleep clock
authorCarl Huang <cjhuang@codeaurora.org>
Fri, 14 Aug 2020 07:10:29 +0000 (10:10 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Mon, 17 Aug 2020 10:18:35 +0000 (13:18 +0300)
On x86 and other non-qcom platforms, host needs to explicitly tell the firmware
to use the internal sleep clock. Some QCA6390 modules have OTP burnt with
external sleep clock selected, and these modules can't work expectedly unless
firmware selects internal sleep clock.

Add a field to hw_params to support this difference.

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.1.0.1-01238-QCAHKSWPL_SILICONZ-2

Signed-off-by: Carl Huang <cjhuang@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/1597389030-13887-11-git-send-email-kvalo@codeaurora.org
drivers/net/wireless/ath/ath11k/core.c
drivers/net/wireless/ath/ath11k/hw.h
drivers/net/wireless/ath/ath11k/qmi.c

index a3a53debc24f16fd40d06755308b6c992a6bb6fa..f1c07583836fcc62b5af15f1ce9292a365c08e07 100644 (file)
@@ -31,6 +31,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                .bdf_addr = 0x4B0C0000,
                .hw_ops = &ipq8074_ops,
                .ring_mask = &ath11k_hw_ring_mask_ipq8074,
+               .internal_sleep_clock = false,
        },
        {
                .name = "qca6390 hw2.0",
@@ -44,6 +45,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                .bdf_addr = 0x4B0C0000,
                .hw_ops = &qca6390_ops,
                .ring_mask = &ath11k_hw_ring_mask_ipq8074,
+               .internal_sleep_clock = true,
        },
 };
 
index 5b443a212c850b8b82095a47f336a5b17b7a0c7a..aacd092dbddbf4ba31198bd8ffac4bee60ef384e 100644 (file)
@@ -133,6 +133,8 @@ struct ath11k_hw_params {
        const struct ath11k_hw_ops *hw_ops;
 
        const struct ath11k_hw_ring_mask *ring_mask;
+
+       bool internal_sleep_clock;
 };
 
 extern const struct ath11k_hw_ops ipq8074_ops;
index 12991a835b8b841bc667e77dacbb15abd4bf22af..b81897131f0a6f59d4762863dab131a422406bd7 100644 (file)
@@ -9,6 +9,9 @@
 #include <linux/of.h>
 #include <linux/firmware.h>
 
+#define SLEEP_CLOCK_SELECT_INTERNAL_BIT        0x02
+#define HOST_CSTATE_BIT                        0x04
+
 static struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = {
        {
                .data_type      = QMI_OPT_FLAG,
@@ -1531,6 +1534,20 @@ static int ath11k_qmi_host_cap_send(struct ath11k_base *ab)
        req.cal_done_valid = 1;
        req.cal_done = ab->qmi.cal_done;
 
+       if (ab->hw_params.internal_sleep_clock) {
+               req.nm_modem_valid = 1;
+
+               /* Notify firmware that this is non-qualcomm platform. */
+               req.nm_modem |= HOST_CSTATE_BIT;
+
+               /* Notify firmware about the sleep clock selection,
+                * nm_modem_bit[1] is used for this purpose. Host driver on
+                * non-qualcomm platforms should select internal sleep
+                * clock.
+                */
+               req.nm_modem |= SLEEP_CLOCK_SELECT_INTERNAL_BIT;
+       }
+
        ret = qmi_txn_init(&ab->qmi.handle, &txn,
                           qmi_wlanfw_host_cap_resp_msg_v01_ei, &resp);
        if (ret < 0)