Browse Source

icnss2: Add PDC init table support for WLAN device

Send PDC init table as configured in DT for WLAN device.

Change-Id: I75ce3182e844787bb78646df4a6dad023520a94d
CRs-Fixed: 3672179
Prateek Patil 1 year ago
parent
commit
2dec17eda3
3 changed files with 98 additions and 7 deletions
  1. 1 0
      icnss2/main.c
  2. 4 0
      icnss2/main.h
  3. 93 7
      icnss2/power.c

+ 1 - 0
icnss2/main.c

@@ -4815,6 +4815,7 @@ static int icnss_probe(struct platform_device *pdev)
 		icnss_pr_err("fw service registration failed: %d\n", ret);
 		goto out_destroy_wq;
 	}
+	icnss_power_misc_params_init(priv);
 
 	icnss_enable_recovery(priv);
 

+ 4 - 0
icnss2/main.h

@@ -492,6 +492,8 @@ struct icnss_priv {
 	struct qmp *qmp;
 #endif
 	bool use_direct_qmp;
+	const char **pdc_init_table;
+	int pdc_init_table_len;
 	u32 wlan_en_delay_ms;
 	u32 wlan_en_delay_ms_user;
 	struct class *icnss_ramdump_class;
@@ -552,6 +554,8 @@ void icnss_add_fw_prefix_name(struct icnss_priv *priv, char *prefix_name,
 			      char *name);
 int icnss_aop_interface_init(struct icnss_priv *priv);
 void icnss_aop_interface_deinit(struct icnss_priv *priv);
+int icnss_aop_pdc_reconfig(struct icnss_priv *priv);
+void icnss_power_misc_params_init(struct icnss_priv *priv);
 void icnss_recovery_timeout_hdlr(struct timer_list *t);
 void icnss_wpss_ssr_timeout_hdlr(struct timer_list *t);
 #endif

+ 93 - 7
icnss2/power.c

@@ -751,13 +751,14 @@ int icnss_aop_interface_init(struct icnss_priv *priv)
 {
 	struct mbox_client *mbox = &priv->mbox_client_data;
 	struct mbox_chan *chan;
-	int ret = 0;
+	int ret = 0, ol_cpr = 0;
 
-	ret = of_property_read_string(priv->pdev->dev.of_node,
-				      "qcom,vreg_ol_cpr",
-				      &priv->cpr_info.vreg_ol_cpr);
-	if (ret) {
-		icnss_pr_dbg("Vreg for OL CPR not configured\n");
+	ol_cpr = of_property_read_string(priv->pdev->dev.of_node,
+					 "qcom,vreg_ol_cpr",
+					 &priv->cpr_info.vreg_ol_cpr);
+
+	if (ol_cpr && !priv->pdc_init_table) {
+		icnss_pr_dbg("Vreg for OL CPR and pdc_init table not configured\n");
 		return -EINVAL;
 	}
 
@@ -789,11 +790,15 @@ int icnss_aop_interface_init(struct icnss_priv *priv)
 		priv->mbox_chan = chan;
 		icnss_pr_dbg("Mbox channel initialized\n");
 	}
+	ret = icnss_aop_pdc_reconfig(priv);
+	if (ret)
+		icnss_pr_err("Failed to reconfig WLAN PDC, err = %d\n", ret);
+
 	return ret;
 }
 
 /**
- * cnss_aop_interface_deinit: Cleanup AOP interface
+ * icnss_aop_interface_deinit: Cleanup AOP interface
  * @priv: Pointer to icnss platform data
  *
  * Cleanup mbox channel or QMP whichever was configured during initialization.
@@ -850,6 +855,53 @@ static int icnss_aop_set_vreg_param(struct icnss_priv *priv,
 
 	return ret;
 }
+
+/* icnss_aop_pdc_reconfig: Send AOP msg to configure PDC table for WLAN device
+ * @priv: Pointer to icnss platform data
+ *
+ * Send AOP QMP or Mbox msg to configure PDC table for WLAN device
+ *
+ * Return: 0 for success, otherwise error code
+ */
+int icnss_aop_pdc_reconfig(struct icnss_priv *priv)
+{
+	u32 i;
+	int ret;
+	char *mbox_msg;
+	struct qmp_pkt pkt;
+
+	if (priv->pdc_init_table_len <= 0 || !priv->pdc_init_table)
+		return 0;
+
+	icnss_pr_dbg("Setting PDC defaults for device ID: (0x%x)\n",
+		     priv->device_id);
+	for (i = 0; i < priv->pdc_init_table_len; i++) {
+		mbox_msg = (char *)priv->pdc_init_table[i];
+		if (priv->use_direct_qmp) {
+			icnss_pr_dbg("Sending AOP QMP msg: %s\n", mbox_msg);
+			ret = qmp_send(priv->qmp, mbox_msg,
+				       ICNSS_MBOX_MSG_MAX_LEN);
+			if (ret < 0)
+				icnss_pr_err("Failed to send AOP QMP msg: %s\n",
+					     mbox_msg);
+			else
+				ret = 0;
+		} else {
+			icnss_pr_dbg("Sending AOP Mbox msg: %s\n", mbox_msg);
+			pkt.size = ICNSS_MBOX_MSG_MAX_LEN;
+			pkt.data = mbox_msg;
+
+			ret = mbox_send_message(priv->mbox_chan, &pkt);
+			if (ret < 0)
+				icnss_pr_err("Failed to send AOP mbox msg: %s,ret: %d\n",
+					     mbox_msg, ret);
+			else
+				ret = 0;
+		}
+	}
+	return ret;
+}
+
 #else
 int icnss_aop_interface_init(struct icnss_priv *priv)
 {
@@ -867,8 +919,42 @@ static int icnss_aop_set_vreg_param(struct icnss_priv *priv,
 {
 	return 0;
 }
+
+int icnss_aop_pdc_reconfig(struct icnss_priv *priv)
+{
+	return 0;
+}
+
 #endif
 
+void icnss_power_misc_params_init(struct icnss_priv *priv)
+{
+	struct device *dev = &priv->pdev->dev;
+	int ret;
+
+	/* common DT Entries */
+	priv->pdc_init_table_len =
+				of_property_count_strings(dev->of_node,
+							  "qcom,pdc_init_table");
+	if (priv->pdc_init_table_len > 0) {
+		priv->pdc_init_table =
+			kcalloc(priv->pdc_init_table_len,
+				sizeof(char *), GFP_KERNEL);
+		if (priv->pdc_init_table) {
+			ret = of_property_read_string_array(dev->of_node,
+						"qcom,pdc_init_table",
+						priv->pdc_init_table,
+						priv->pdc_init_table_len);
+			if (ret < 0)
+				icnss_pr_err("Failed to get PDC Init Table\n");
+		} else {
+			icnss_pr_err("Failed to alloc PDC Init Table mem\n");
+		}
+	} else {
+		icnss_pr_dbg("PDC Init Table not configured\n");
+	}
+}
+
 int icnss_update_cpr_info(struct icnss_priv *priv)
 {
 	struct icnss_cpr_info *cpr_info = &priv->cpr_info;