icnss2: Add support for direct QMP to communicate with AOP

Add support for direct QMP to communicate with AOP. There
are two ways to communicate with AOP: mailbox, and direct
QMP, Based on property set in the device tree use either
direct QMP or mailbox to send messages to AOP.

Change-Id: Iae8302fd2e40181a192a2c9afaebdb807b7cf1c3
CRs-Fixed: 3571108
This commit is contained in:
Prateek Patil
2023-07-25 18:37:52 +05:30
父節點 ac9fb6837b
當前提交 882ac969c2
共有 3 個文件被更改,包括 91 次插入27 次删除

查看文件

@@ -5,9 +5,6 @@
*/
#include <linux/clk.h>
#include <linux/delay.h>
#if IS_ENABLED(CONFIG_MSM_QMP)
#include <linux/mailbox/qmp.h>
#endif
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/regulator/consumer.h>
@@ -736,7 +733,18 @@ void icnss_put_resources(struct icnss_priv *priv)
icnss_put_vreg(priv);
}
int icnss_aop_mbox_init(struct icnss_priv *priv)
#if IS_ENABLED(CONFIG_MSM_QMP)
/**
* icnss_aop_interface_init: Initialize AOP interface: either mbox channel or direct QMP
* @priv: Pointer to icnss platform data
*
* Device tree file should have either mbox or qmp configured, but not both.
* Based on device tree configuration setup mbox channel or QMP
*
* Return: 0 for success, otherwise error code
*/
int icnss_aop_interface_init(struct icnss_priv *priv)
{
struct mbox_client *mbox = &priv->mbox_client_data;
struct mbox_chan *chan;
@@ -756,19 +764,50 @@ int icnss_aop_mbox_init(struct icnss_priv *priv)
mbox->knows_txdone = false;
priv->mbox_chan = NULL;
priv->qmp = NULL;
priv->use_direct_qmp = false;
/* First try to get mbox channel, if it fails then try qmp_get
* In device tree file there should be either mboxes or qmp,
* cannot have both properties at the same time.
*/
chan = mbox_request_channel(mbox, 0);
if (IS_ERR(chan)) {
ret = PTR_ERR(chan);
icnss_pr_err("Failed to get mbox channel with err %d\n", ret);
return ret;
icnss_pr_dbg("Failed to get mbox channel with err %d\n", ret);
priv->qmp = qmp_get(&priv->pdev->dev);
if (IS_ERR(priv->qmp)) {
icnss_pr_err("Failed to get qmp\n");
return PTR_ERR(priv->qmp);
} else {
priv->use_direct_qmp = true;
icnss_pr_dbg("QMP initialized\n");
}
} else {
priv->mbox_chan = chan;
icnss_pr_dbg("Mbox channel initialized\n");
}
return ret;
}
/**
* cnss_aop_interface_deinit: Cleanup AOP interface
* @priv: Pointer to icnss platform data
*
* Cleanup mbox channel or QMP whichever was configured during initialization.
*
* Return: None
*/
void icnss_aop_interface_deinit(struct icnss_priv *priv)
{
if (!IS_ERR_OR_NULL(priv->mbox_chan))
mbox_free_channel(priv->mbox_chan);
if (!IS_ERR_OR_NULL(priv->qmp)) {
qmp_put(priv->qmp);
priv->use_direct_qmp = false;
}
priv->mbox_chan = chan;
icnss_pr_dbg("Mbox channel initialized\n");
return 0;
}
#if IS_ENABLED(CONFIG_MSM_QMP)
static int icnss_aop_set_vreg_param(struct icnss_priv *priv,
const char *vreg_name,
enum icnss_vreg_param param,
@@ -786,21 +825,38 @@ static int icnss_aop_set_vreg_param(struct icnss_priv *priv,
snprintf(mbox_msg, ICNSS_MBOX_MSG_MAX_LEN,
"{class: wlan_pdc, res: %s.%s, %s: %d}", vreg_name,
vreg_param_str[param], tcs_seq_str[seq], val);
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;
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;
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)
{
return 0;
}
void icnss_aop_interface_deinit(struct icnss_priv *priv)
{
}
static int icnss_aop_set_vreg_param(struct icnss_priv *priv,
const char *vreg_name,
enum icnss_vreg_param param,
@@ -814,8 +870,8 @@ int icnss_update_cpr_info(struct icnss_priv *priv)
{
struct icnss_cpr_info *cpr_info = &priv->cpr_info;
if (!cpr_info->vreg_ol_cpr || !priv->mbox_chan) {
icnss_pr_dbg("Mbox channel / OL CPR Vreg not configured\n");
if (!cpr_info->vreg_ol_cpr || (!priv->mbox_chan && !priv->qmp)) {
icnss_pr_dbg("Mbox channel / QMP / OL CPR Vreg not configured\n");
return 0;
}