Search Linux Wireless

[PATCH] ath11k: Check supported hardware version

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Read register TCSR_SOC_HW_VERSION for hardware version. This register
is present in all hardwares. Check whether the hardware version is
supported. Returns error if the hardware is unsupported.
This handling is already done for QCA6390 and WCN6855.

Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1-00729-QCAHKSWPL_SILICONZ-3
Tested-on: IPQ6018 hw2.0 AHB WLAN.HK.2.5.0.1-00729-QCAHKSWPL_SILICONZ-3
Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.5.0.1-00729-QCAHKSWPL_SILICONZ-3

Signed-off-by: Seevalamuthu Mariappan <quic_seevalam@xxxxxxxxxxx>
---
 drivers/net/wireless/ath/ath11k/ahb.c  | 46 ++++++++++++++++++++++++++++++++++
 drivers/net/wireless/ath/ath11k/core.h | 13 ++++++++++
 drivers/net/wireless/ath/ath11k/pci.c  | 32 ++++++++++++++++-------
 3 files changed, 82 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c
index 8c9c781..be56787 100644
--- a/drivers/net/wireless/ath/ath11k/ahb.c
+++ b/drivers/net/wireless/ath/ath11k/ahb.c
@@ -13,6 +13,10 @@
 #include "hif.h"
 #include <linux/remoteproc.h>
 
+#define CORE_TOP_CSR_OFFSET		0x01900000
+#define CORE_TOP_CSR_SIZE		0x100000
+#define TCSR_SOC_HW_VERSION		0x4D000
+
 static const struct of_device_id ath11k_ahb_of_match[] = {
 	/* TODO: Should we change the compatible string to something similar
 	 * to one that ath10k uses?
@@ -650,6 +654,44 @@ static int ath11k_core_get_rproc(struct ath11k_base *ab)
 	return 0;
 }
 
+static int ath11k_check_hw_version(struct ath11k_base *ab)
+{
+	void __iomem *mem_core;
+	u32 soc_hw_version, soc_hw_version_major, soc_hw_version_minor;
+
+	switch (ab->hw_rev) {
+	case ATH11K_HW_IPQ8074:
+	case ATH11K_HW_IPQ6018_HW10:
+		/* CORE_TOP_CSR register is out of wcss */
+		mem_core = ioremap(CORE_TOP_CSR_OFFSET, CORE_TOP_CSR_SIZE);
+		if (IS_ERR(mem_core)) {
+			ath11k_err(ab, "core_top_csr ioremap error\n");
+			return -ENOMEM;
+		}
+		soc_hw_version = ioread32(mem_core + TCSR_SOC_HW_VERSION);
+		iounmap(mem_core);
+		soc_hw_version_major = FIELD_GET(TCSR_SOC_HW_VERSION_MAJOR_MASK,
+						 soc_hw_version);
+		soc_hw_version_minor = FIELD_GET(TCSR_SOC_HW_VERSION_MINOR_MASK,
+						 soc_hw_version);
+
+		ath11k_dbg(ab, ATH11K_DBG_AHB, "tcsr_soc_hw_version major %u minor %u\n",
+			   soc_hw_version_major,
+			   soc_hw_version_minor);
+
+		if (soc_hw_version_major != ath11k_hw_version[ab->hw_rev]) {
+			ath11k_err(ab, "Unsupported SOC hardware version: %u\n",
+				   soc_hw_version_major);
+			return -EOPNOTSUPP;
+		}
+		break;
+	default:
+		ath11k_err(ab, "Unknown hw_ver: %u\n", ab->hw_rev);
+		return -EOPNOTSUPP;
+	}
+	return 0;
+}
+
 static int ath11k_ahb_probe(struct platform_device *pdev)
 {
 	struct ath11k_base *ab;
@@ -691,6 +733,10 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
 	ab->mem_len = resource_size(mem_res);
 	platform_set_drvdata(pdev, ab);
 
+	ret = ath11k_check_hw_version(ab);
+	if (ret)
+		goto err_core_free;
+
 	ret = ath11k_core_pre_init(ab);
 	if (ret)
 		goto err_core_free;
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 2f1e10b..3b93a5d 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -916,6 +916,19 @@ struct ath11k_fw_stats_bcn {
 	u32 tx_bcn_outage_cnt;
 };
 
+#define TCSR_SOC_HW_VERSION_MAJOR_MASK	GENMASK(15, 8)
+#define TCSR_SOC_HW_VERSION_MINOR_MASK	GENMASK(7, 0)
+#define ATH11K_HW_VERSION_HW10		1
+#define ATH11K_HW_VERSION_HW20		2
+
+static const u32 ath11k_hw_version[] = {
+	[ATH11K_HW_IPQ8074] = ATH11K_HW_VERSION_HW20,
+	[ATH11K_HW_QCA6390_HW20] = ATH11K_HW_VERSION_HW20,
+	[ATH11K_HW_IPQ6018_HW10] = ATH11K_HW_VERSION_HW10,
+	[ATH11K_HW_QCN9074_HW10] = ATH11K_HW_VERSION_HW10,
+	[ATH11K_HW_WCN6855_HW20] = ATH11K_HW_VERSION_HW20,
+};
+
 extern const struct ce_pipe_config ath11k_target_ce_config_wlan_ipq8074[];
 extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq8074[];
 extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq6018[];
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index 3d353e7..fb001b7 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -25,8 +25,7 @@
 #define WINDOW_RANGE_MASK		GENMASK(18, 0)
 
 #define TCSR_SOC_HW_VERSION		0x0224
-#define TCSR_SOC_HW_VERSION_MAJOR_MASK	GENMASK(16, 8)
-#define TCSR_SOC_HW_VERSION_MINOR_MASK	GENMASK(7, 0)
+#define QCN9074_TCSR_SOC_HW_VERSION	0x1B00000
 
 /* BAR0 + 4k is always accessible, and no
  * need to force wakeup.
@@ -1206,11 +1205,12 @@ static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
 	.get_ce_msi_idx = ath11k_pci_get_ce_msi_idx,
 };
 
-static void ath11k_pci_read_hw_version(struct ath11k_base *ab, u32 *major, u32 *minor)
+static void ath11k_pci_read_hw_version(struct ath11k_base *ab, u32 offset,
+				       u32 *major, u32 *minor)
 {
 	u32 soc_hw_version;
 
-	soc_hw_version = ath11k_pci_read32(ab, TCSR_SOC_HW_VERSION);
+	soc_hw_version = ath11k_pci_read32(ab, offset);
 	*major = FIELD_GET(TCSR_SOC_HW_VERSION_MAJOR_MASK,
 			   soc_hw_version);
 	*minor = FIELD_GET(TCSR_SOC_HW_VERSION_MINOR_MASK,
@@ -1253,10 +1253,11 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
 
 	switch (pci_dev->device) {
 	case QCA6390_DEVICE_ID:
-		ath11k_pci_read_hw_version(ab, &soc_hw_version_major,
+		ath11k_pci_read_hw_version(ab, TCSR_SOC_HW_VERSION,
+					   &soc_hw_version_major,
 					   &soc_hw_version_minor);
 		switch (soc_hw_version_major) {
-		case 2:
+		case ATH11K_HW_VERSION_HW20:
 			ab->hw_rev = ATH11K_HW_QCA6390_HW20;
 			break;
 		default:
@@ -1268,15 +1269,28 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
 		ab_pci->msi_config = &ath11k_msi_config[0];
 		break;
 	case QCN9074_DEVICE_ID:
+		ath11k_pci_read_hw_version(ab, QCN9074_TCSR_SOC_HW_VERSION,
+					   &soc_hw_version_major,
+					   &soc_hw_version_minor);
+		switch (soc_hw_version_major) {
+		case ATH11K_HW_VERSION_HW10:
+			ab->hw_rev = ATH11K_HW_QCN9074_HW10;
+			break;
+		default:
+			dev_err(&pdev->dev, "Unsupported QCN9074 SOC hardware version: %d %d\n",
+				soc_hw_version_major, soc_hw_version_minor);
+			ret = -EOPNOTSUPP;
+			goto err_pci_free_region;
+		}
 		ab_pci->msi_config = &ath11k_msi_config[1];
 		ab->bus_params.static_window_map = true;
-		ab->hw_rev = ATH11K_HW_QCN9074_HW10;
 		break;
 	case WCN6855_DEVICE_ID:
-		ath11k_pci_read_hw_version(ab, &soc_hw_version_major,
+		ath11k_pci_read_hw_version(ab, TCSR_SOC_HW_VERSION,
+					   &soc_hw_version_major,
 					   &soc_hw_version_minor);
 		switch (soc_hw_version_major) {
-		case 2:
+		case ATH11K_HW_VERSION_HW20:
 			ab->hw_rev = ATH11K_HW_WCN6855_HW20;
 			break;
 		default:
-- 
2.7.4




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux