ソースを参照

icnss2: Add support for WLAN WCN6450 device

Add corresponding driver support for WCN6450 device.
This change adds compatible dtsi entry, msi config,
v3 shadow register config and vreg regulator details
along with enabling bootup sequence for WCN6450 device.

Change-Id: I406c92cdc2815ffd1108331d382c4972befad998
CRs-Fixed: 3404702
Sandeep Singh 2 年 前
コミット
aec346c6bc
6 ファイル変更93 行追加27 行削除
  1. 1 1
      icnss2/debug.c
  2. 50 22
      icnss2/main.c
  3. 2 0
      icnss2/main.h
  4. 15 1
      icnss2/power.c
  5. 19 3
      icnss2/qmi.c
  6. 6 0
      inc/icnss2.h

+ 1 - 1
icnss2/debug.c

@@ -475,7 +475,7 @@ static int icnss_stats_show(struct seq_file *s, void *data)
 	ICNSS_STATS_DUMP(s, priv, pm_stay_awake);
 	ICNSS_STATS_DUMP(s, priv, pm_relax);
 
-	if (priv->device_id != WCN6750_DEVICE_ID) {
+	if (priv->device_id == ADRASTEA_DEVICE_ID) {
 		seq_puts(s, "\n<------------------ MSA stats ------------------->\n");
 		ICNSS_STATS_DUMP(s, priv, msa_info_req);
 		ICNSS_STATS_DUMP(s, priv, msa_info_resp);

+ 50 - 22
icnss2/main.c

@@ -896,7 +896,8 @@ static int icnss_driver_event_server_arrive(struct icnss_priv *priv,
 		}
 	}
 
-	if (priv->device_id == WCN6750_DEVICE_ID) {
+	if (priv->device_id == WCN6750_DEVICE_ID ||
+	    priv->device_id == WCN6450_DEVICE_ID) {
 		if (!icnss_get_temperature(priv, &temp)) {
 			icnss_pr_dbg("Temperature: %d\n", temp);
 			if (temp < WLAN_EN_TEMP_THRESHOLD)
@@ -938,7 +939,8 @@ static int icnss_driver_event_server_arrive(struct icnss_priv *priv,
 	if (ret)
 		goto fail;
 
-	if (priv->device_id == WCN6750_DEVICE_ID) {
+	if (priv->device_id == WCN6750_DEVICE_ID ||
+	    priv->device_id == WCN6450_DEVICE_ID) {
 		ret = wlfw_device_info_send_msg(priv);
 		if (ret < 0) {
 			ignore_assert = true;
@@ -978,7 +980,8 @@ static int icnss_driver_event_server_arrive(struct icnss_priv *priv,
 			goto device_info_failure;
 	}
 
-	if (priv->device_id == WCN6750_DEVICE_ID) {
+	if (priv->device_id == WCN6750_DEVICE_ID ||
+	    priv->device_id == WCN6450_DEVICE_ID) {
 		if (!priv->fw_soc_wake_ack_irq)
 			register_soc_wake_notif(&priv->pdev->dev);
 
@@ -1163,7 +1166,8 @@ static int icnss_driver_event_fw_ready_ind(struct icnss_priv *priv, void *data)
 	clear_bit(ICNSS_MODE_ON, &priv->state);
 	atomic_set(&priv->soc_wake_ref_count, 0);
 
-	if (priv->device_id == WCN6750_DEVICE_ID)
+	if (priv->device_id == WCN6750_DEVICE_ID ||
+	    priv->device_id == WCN6450_DEVICE_ID)
 		icnss_free_qdss_mem(priv);
 
 	icnss_pr_info("WLAN FW is ready: 0x%lx\n", priv->state);
@@ -1598,7 +1602,8 @@ static int icnss_driver_event_pd_service_down(struct icnss_priv *priv,
 	if (priv->force_err_fatal)
 		ICNSS_ASSERT(0);
 
-	if (priv->device_id == WCN6750_DEVICE_ID) {
+	if (priv->device_id == WCN6750_DEVICE_ID ||
+	    priv->device_id == WCN6450_DEVICE_ID) {
 		icnss_send_smp2p(priv, ICNSS_RESET_MSG,
 				 ICNSS_SMP2P_OUT_SOC_WAKE);
 		icnss_send_smp2p(priv, ICNSS_RESET_MSG,
@@ -2614,7 +2619,8 @@ static int icnss_register_ramdump_devices(struct icnss_priv *priv)
 		return -ENOMEM;
 	}
 
-	if (priv->device_id == WCN6750_DEVICE_ID) {
+	if (priv->device_id == WCN6750_DEVICE_ID ||
+	    priv->device_id == WCN6450_DEVICE_ID) {
 		priv->m3_dump_phyareg = icnss_create_ramdump_device(priv,
 						ICNSS_M3_SEGMENT(
 						ICNSS_M3_SEGMENT_PHYAREG));
@@ -2970,7 +2976,7 @@ out:
 }
 EXPORT_SYMBOL(icnss_unregister_driver);
 
-static struct icnss_msi_config msi_config = {
+static struct icnss_msi_config msi_config_wcn6750 = {
 	.total_vectors = 28,
 	.total_users = 2,
 	.users = (struct icnss_msi_user[]) {
@@ -2979,9 +2985,20 @@ static struct icnss_msi_config msi_config = {
 	},
 };
 
+static struct icnss_msi_config msi_config_wcn6450 = {
+	.total_vectors = 10,
+	.total_users = 1,
+	.users = (struct icnss_msi_user[]) {
+		{ .name = "CE", .num_vectors = 10, .base_vector = 0 },
+	},
+};
+
 static int icnss_get_msi_assignment(struct icnss_priv *priv)
 {
-	priv->msi_config = &msi_config;
+	if (priv->device_id == WCN6750_DEVICE_ID)
+		priv->msi_config = &msi_config_wcn6750;
+	else
+		priv->msi_config = &msi_config_wcn6450;
 
 	return 0;
 }
@@ -3918,7 +3935,7 @@ static ssize_t wlan_en_delay_store(struct device *dev,
 	struct icnss_priv *priv = dev_get_drvdata(dev);
 	uint32_t wlan_en_delay  = 0;
 
-	if (priv->device_id != WCN6750_DEVICE_ID)
+	if (priv->device_id == ADRASTEA_DEVICE_ID)
 		return count;
 
 	if (sscanf(buf, "%du", &wlan_en_delay) != 1) {
@@ -4085,7 +4102,8 @@ static int icnss_resource_parse(struct icnss_priv *priv)
 			priv->is_slate_rfa = true;
 			icnss_pr_err("SLATE rfa is enabled\n");
 		}
-	} else if (priv->device_id == WCN6750_DEVICE_ID) {
+	} else if (priv->device_id == WCN6750_DEVICE_ID ||
+		   priv->device_id == WCN6450_DEVICE_ID) {
 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 						   "msi_addr");
 		if (!res) {
@@ -4122,7 +4140,7 @@ static int icnss_resource_parse(struct icnss_priv *priv)
 			     priv->msi_base_data, int_prop);
 
 		icnss_get_msi_assignment(priv);
-		for (i = 0; i < msi_config.total_vectors; i++) {
+		for (i = 0; i < priv->msi_config->total_vectors; i++) {
 			res = platform_get_resource(priv->pdev,
 						    IORESOURCE_IRQ, i);
 			if (!res) {
@@ -4273,7 +4291,8 @@ static int icnss_smmu_dt_parse(struct icnss_priv *priv)
 		if (!ret && !strcmp("fastmap", iommu_dma_type)) {
 			icnss_pr_dbg("SMMU S1 stage enabled\n");
 			priv->smmu_s1_enable = true;
-			if (priv->device_id == WCN6750_DEVICE_ID)
+			if (priv->device_id == WCN6750_DEVICE_ID ||
+			    priv->device_id == WCN6450_DEVICE_ID)
 				iommu_set_fault_handler(priv->iommu_domain,
 						icnss_smmu_fault_handler,
 						priv);
@@ -4339,16 +4358,19 @@ void icnss_add_fw_prefix_name(struct icnss_priv *priv, char *prefix_name,
 	if (priv->device_id == ADRASTEA_DEVICE_ID)
 		scnprintf(prefix_name, ICNSS_MAX_FILE_NAME,
 			  ADRASTEA_PATH_PREFIX "%s", name);
-	else
+	else if (priv->device_id == WCN6750_DEVICE_ID)
 		scnprintf(prefix_name, ICNSS_MAX_FILE_NAME,
 			  QCA6750_PATH_PREFIX "%s", name);
-
+	else if (priv->device_id == WCN6450_DEVICE_ID)
+		scnprintf(prefix_name, ICNSS_MAX_FILE_NAME,
+			  WCN6450_PATH_PREFIX "%s", name);
 	icnss_pr_dbg("File added with prefix: %s\n", prefix_name);
 }
 
 static const struct platform_device_id icnss_platform_id_table[] = {
 	{ .name = "wcn6750", .driver_data = WCN6750_DEVICE_ID, },
 	{ .name = "adrastea", .driver_data = ADRASTEA_DEVICE_ID, },
+	{ .name = "wcn6450", .driver_data = WCN6450_DEVICE_ID, },
 	{ },
 };
 
@@ -4359,6 +4381,9 @@ static const struct of_device_id icnss_dt_match[] = {
 	{
 		.compatible = "qcom,icnss",
 		.data = (void *)&icnss_platform_id_table[1]},
+	{
+		.compatible = "qcom,wcn6450",
+		.data = (void *)&icnss_platform_id_table[2]},
 	{ },
 };
 
@@ -4532,7 +4557,8 @@ static int icnss_probe(struct platform_device *pdev)
 	if (priv->is_slate_rfa)
 		init_completion(&priv->slate_boot_complete);
 
-	if (priv->device_id == WCN6750_DEVICE_ID) {
+	if (priv->device_id == WCN6750_DEVICE_ID ||
+	    priv->device_id == WCN6450_DEVICE_ID) {
 		priv->soc_wake_wq = alloc_workqueue("icnss_soc_wake_event",
 						    WQ_UNBOUND|WQ_HIGHPRI, 1);
 		if (!priv->soc_wake_wq) {
@@ -4654,7 +4680,8 @@ static int icnss_remove(struct platform_device *pdev)
 		icnss_pdr_unregister_notifier(priv);
 	}
 
-	if (priv->device_id == WCN6750_DEVICE_ID) {
+	if (priv->device_id == WCN6750_DEVICE_ID ||
+	    priv->device_id == WCN6450_DEVICE_ID) {
 		icnss_genl_exit();
 		icnss_runtime_pm_deinit(priv);
 		if (!IS_ERR_OR_NULL(priv->mbox_chan))
@@ -4727,7 +4754,8 @@ static int icnss_pm_suspend(struct device *dev)
 	ret = priv->ops->pm_suspend(dev);
 
 	if (ret == 0) {
-		if (priv->device_id == WCN6750_DEVICE_ID) {
+		if (priv->device_id == WCN6750_DEVICE_ID ||
+		    priv->device_id == WCN6450_DEVICE_ID) {
 			if (test_bit(ICNSS_PD_RESTART, &priv->state) ||
 			    !test_bit(ICNSS_MODE_ON, &priv->state))
 				return 0;
@@ -4836,7 +4864,7 @@ static int icnss_pm_runtime_suspend(struct device *dev)
 	struct icnss_priv *priv = dev_get_drvdata(dev);
 	int ret = 0;
 
-	if (priv->device_id != WCN6750_DEVICE_ID) {
+	if (priv->device_id == ADRASTEA_DEVICE_ID) {
 		icnss_pr_err("Ignore runtime suspend:\n");
 		goto out;
 	}
@@ -4870,8 +4898,8 @@ static int icnss_pm_runtime_resume(struct device *dev)
 	struct icnss_priv *priv = dev_get_drvdata(dev);
 	int ret = 0;
 
-	if (priv->device_id != WCN6750_DEVICE_ID) {
-		icnss_pr_err("Ignore runtime resume:\n");
+	if (priv->device_id == ADRASTEA_DEVICE_ID) {
+		icnss_pr_err("Ignore runtime resume\n");
 		goto out;
 	}
 
@@ -4897,8 +4925,8 @@ static int icnss_pm_runtime_idle(struct device *dev)
 {
 	struct icnss_priv *priv = dev_get_drvdata(dev);
 
-	if (priv->device_id != WCN6750_DEVICE_ID) {
-		icnss_pr_err("Ignore runtime idle:\n");
+	if (priv->device_id == ADRASTEA_DEVICE_ID) {
+		icnss_pr_err("Ignore runtime idle\n");
 		goto out;
 	}
 

+ 2 - 0
icnss2/main.h

@@ -22,12 +22,14 @@
 #include <linux/timer.h>
 
 #define WCN6750_DEVICE_ID 0x6750
+#define WCN6450_DEVICE_ID 0x6450
 #define ADRASTEA_DEVICE_ID 0xabcd
 #define THERMAL_NAME_LENGTH 20
 #define ICNSS_SMEM_VALUE_MASK 0xFFFFFFFF
 #define ICNSS_SMEM_SEQ_NO_POS 16
 #define QCA6750_PATH_PREFIX    "qca6750/"
 #define ADRASTEA_PATH_PREFIX   "adrastea/"
+#define WCN6450_PATH_PREFIX    "wcn6450/"
 #define ICNSS_MAX_FILE_NAME      35
 #define ICNSS_PCI_EP_WAKE_OFFSET 4
 #define ICNSS_DISABLE_M3_SSR 0

+ 15 - 1
icnss2/power.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 #include <linux/clk.h>
 #include <linux/delay.h>
@@ -38,6 +39,13 @@ static struct icnss_battery_level icnss_battery_level[] = {
 	{0, 2850000},
 };
 
+static struct icnss_vreg_cfg icnss_wcn6450_vreg_list[] = {
+	{"vdd-cx-mx", 824000, 952000, 0, 0, 0, false, true},
+	{"vdd-1.8-xo", 1872000, 1872000, 0, 0, 0, false, true},
+	{"vdd-1.3-rfa", 1256000, 1352000, 0, 0, 0, false, true},
+	{"vdd-aon", 1256000, 1352000, 0, 0, 0, false, true},
+};
+
 static struct icnss_clk_cfg icnss_clk_list[] = {
 	{"rf_clk", 0, 0},
 };
@@ -48,6 +56,7 @@ static struct icnss_clk_cfg icnss_adrestea_clk_list[] = {
 
 #define ICNSS_VREG_LIST_SIZE		ARRAY_SIZE(icnss_wcn6750_vreg_list)
 #define ICNSS_VREG_ADRESTEA_LIST_SIZE	ARRAY_SIZE(icnss_adrestea_vreg_list)
+#define ICNSS_VREG_EVROS_LIST_SIZE	ARRAY_SIZE(icnss_wcn6450_vreg_list)
 #define ICNSS_CLK_LIST_SIZE		ARRAY_SIZE(icnss_clk_list)
 #define ICNSS_CLK_ADRESTEA_LIST_SIZE	ARRAY_SIZE(icnss_adrestea_clk_list)
 
@@ -311,6 +320,10 @@ static struct icnss_vreg_cfg *get_vreg_list(u32 *vreg_list_size,
 		*vreg_list_size = ICNSS_VREG_ADRESTEA_LIST_SIZE;
 		return icnss_adrestea_vreg_list;
 
+	case WCN6450_DEVICE_ID:
+		*vreg_list_size = ICNSS_VREG_EVROS_LIST_SIZE;
+		return icnss_wcn6450_vreg_list;
+
 	default:
 		icnss_pr_err("Unsupported device_id 0x%x\n", device_id);
 		*vreg_list_size = 0;
@@ -524,7 +537,8 @@ int icnss_get_clk(struct icnss_priv *priv)
 	if (priv->device_id == ADRASTEA_DEVICE_ID) {
 		clk_cfg = icnss_adrestea_clk_list;
 		clk_list_size = ICNSS_CLK_ADRESTEA_LIST_SIZE;
-	} else if (priv->device_id == WCN6750_DEVICE_ID) {
+	} else if (priv->device_id == WCN6750_DEVICE_ID ||
+		   priv->device_id == WCN6450_DEVICE_ID) {
 		clk_cfg = icnss_clk_list;
 		clk_list_size = ICNSS_CLK_LIST_SIZE;
 	}

+ 19 - 3
icnss2/qmi.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #define pr_fmt(fmt) "icnss2_qmi: " fmt
@@ -55,6 +55,9 @@
 #define DMS_MAC_NOT_PROVISIONED		16
 #define BDWLAN_SIZE			6
 #define UMC_CHIP_ID                    0x4320
+#define MAX_SHADOW_REG_RESERVED		2
+#define MAX_NUM_SHADOW_REG_V3		(QMI_WLFW_MAX_NUM_SHADOW_REG_V3_USAGE_V01 - \
+					MAX_SHADOW_REG_RESERVED)
 
 #ifdef CONFIG_ICNSS2_DEBUG
 bool ignore_fw_timeout;
@@ -546,7 +549,8 @@ int wlfw_ind_register_send_sync_msg(struct icnss_priv *priv)
 			req->rejuvenate_enable_valid = 1;
 			req->rejuvenate_enable = 1;
 		}
-	} else if (priv->device_id == WCN6750_DEVICE_ID) {
+	} else if (priv->device_id == WCN6750_DEVICE_ID ||
+		   priv->device_id == WCN6450_DEVICE_ID) {
 		req->fw_init_done_enable_valid = 1;
 		req->fw_init_done_enable = 1;
 		req->cal_done_enable_valid = 1;
@@ -2969,7 +2973,8 @@ int icnss_register_fw_service(struct icnss_priv *priv)
 	if (ret < 0)
 		return ret;
 
-	if (priv->device_id == WCN6750_DEVICE_ID)
+	if (priv->device_id == WCN6750_DEVICE_ID ||
+	    priv->device_id == WCN6450_DEVICE_ID)
 		ret = qmi_add_lookup(&priv->qmi, WLFW_SERVICE_ID_V01,
 				     WLFW_SERVICE_VERS_V01,
 				     WLFW_SERVICE_WCN_INS_ID_V01);
@@ -3060,6 +3065,17 @@ int icnss_send_wlan_enable_to_fw(struct icnss_priv *priv,
 
 		memcpy(req.shadow_reg, config->shadow_reg_cfg,
 		       sizeof(struct wlfw_msi_cfg_s_v01) * req.shadow_reg_len);
+	} else if (priv->device_id == WCN6450_DEVICE_ID) {
+		req.shadow_reg_v3_valid = 1;
+		if (config->num_shadow_reg_v3_cfg >
+			MAX_NUM_SHADOW_REG_V3)
+			req.shadow_reg_v3_len = MAX_NUM_SHADOW_REG_V3;
+		else
+			req.shadow_reg_v3_len = config->num_shadow_reg_v3_cfg;
+
+		memcpy(req.shadow_reg_v3, config->shadow_reg_v3_cfg,
+		       sizeof(struct wlfw_shadow_reg_v3_cfg_s_v01)
+		       * req.shadow_reg_v3_len);
 	}
 
 	ret = wlfw_wlan_cfg_send_sync_msg(priv, &req);

+ 6 - 0
inc/icnss2.h

@@ -95,6 +95,10 @@ struct icnss_shadow_reg_v2_cfg {
 	u32 addr;
 };
 
+struct icnss_shadow_reg_v3_cfg {
+	u32 addr;
+};
+
 struct icnss_rri_over_ddr_cfg {
 	u32 base_addr_low;
 	u32 base_addr_high;
@@ -109,6 +113,8 @@ struct icnss_wlan_enable_cfg {
 	struct icnss_shadow_reg_cfg *shadow_reg_cfg;
 	u32 num_shadow_reg_v2_cfg;
 	struct icnss_shadow_reg_v2_cfg *shadow_reg_v2_cfg;
+	u32 num_shadow_reg_v3_cfg;
+	struct icnss_shadow_reg_v3_cfg *shadow_reg_v3_cfg;
 	bool rri_over_ddr_cfg_valid;
 	struct icnss_rri_over_ddr_cfg rri_over_ddr_cfg;
 };