summaryrefslogtreecommitdiff
path: root/drivers/rpmsg/qcom_glink_smem.c
diff options
context:
space:
mode:
authorBjorn Andersson <quic_bjorande@quicinc.com>2023-02-13 07:52:13 -0800
committerBjorn Andersson <andersson@kernel.org>2023-02-14 08:19:38 -0800
commitf424d1cbe8c7ef78a4b639502fa9904c4198387b (patch)
tree874bfe240d4927f02e629e17b676f302147efa2a /drivers/rpmsg/qcom_glink_smem.c
parent178c3af447f92c58d5b1153df2cd02b755c083c8 (diff)
rpmsg: glink: Move irq and mbox handling to transports
Not all GLINK transports uses an interrupt and a mailbox instance. The interrupt for RPM needs to be IRQF_NOSUSPEND, while it seems reasonable for the SMEM interrupt to use irq_set_wake. The glink struct device is constructed in the SMEM and RPM drivers but torn down in the core driver. Move the interrupt and kick handling into the SMEM and RPM driver, to improve this and facilitate further improvements. Signed-off-by: Bjorn Andersson <quic_bjorande@quicinc.com> Reviewed-by: Chris Lew <quic_clew@quicinc.com> Signed-off-by: Bjorn Andersson <andersson@kernel.org> Link: https://lore.kernel.org/r/20230213155215.1237059-5-quic_bjorande@quicinc.com
Diffstat (limited to 'drivers/rpmsg/qcom_glink_smem.c')
-rw-r--r--drivers/rpmsg/qcom_glink_smem.c55
1 files changed, 53 insertions, 2 deletions
diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c
index a9c477df4d68..05b4fe0a7387 100644
--- a/drivers/rpmsg/qcom_glink_smem.c
+++ b/drivers/rpmsg/qcom_glink_smem.c
@@ -7,8 +7,10 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
+#include <linux/mailbox_client.h>
#include <linux/mfd/syscon.h>
#include <linux/slab.h>
#include <linux/rpmsg.h>
@@ -36,8 +38,12 @@
struct qcom_glink_smem {
struct device dev;
+ int irq;
struct qcom_glink *glink;
+ struct mbox_client mbox_client;
+ struct mbox_chan *mbox_chan;
+
u32 remote_pid;
};
@@ -186,6 +192,24 @@ static void glink_smem_tx_write(struct qcom_glink_pipe *glink_pipe,
*pipe->head = cpu_to_le32(head);
}
+static void glink_smem_tx_kick(struct qcom_glink_pipe *glink_pipe)
+{
+ struct glink_smem_pipe *pipe = to_smem_pipe(glink_pipe);
+ struct qcom_glink_smem *smem = pipe->smem;
+
+ mbox_send_message(smem->mbox_chan, NULL);
+ mbox_client_txdone(smem->mbox_chan, 0);
+}
+
+static irqreturn_t qcom_glink_smem_intr(int irq, void *data)
+{
+ struct qcom_glink_smem *smem = data;
+
+ qcom_glink_native_rx(smem->glink);
+
+ return IRQ_HANDLED;
+}
+
static void qcom_glink_smem_release(struct device *dev)
{
struct qcom_glink_smem *smem = container_of(dev, struct qcom_glink_smem, dev);
@@ -280,6 +304,24 @@ struct qcom_glink_smem *qcom_glink_smem_register(struct device *parent,
goto err_put_dev;
}
+ smem->irq = of_irq_get(smem->dev.of_node, 0);
+ ret = devm_request_irq(&smem->dev, smem->irq, qcom_glink_smem_intr,
+ IRQF_NO_SUSPEND | IRQF_NO_AUTOEN,
+ "glink-smem", smem);
+ if (ret) {
+ dev_err(&smem->dev, "failed to request IRQ\n");
+ goto err_put_dev;
+ }
+
+ smem->mbox_client.dev = &smem->dev;
+ smem->mbox_client.knows_txdone = true;
+ smem->mbox_chan = mbox_request_channel(&smem->mbox_client, 0);
+ if (IS_ERR(smem->mbox_chan)) {
+ ret = dev_err_probe(&smem->dev, PTR_ERR(smem->mbox_chan),
+ "failed to acquire IPC channel\n");
+ goto err_put_dev;
+ }
+
rx_pipe->smem = smem;
rx_pipe->native.avail = glink_smem_rx_avail;
rx_pipe->native.peak = glink_smem_rx_peak;
@@ -288,6 +330,7 @@ struct qcom_glink_smem *qcom_glink_smem_register(struct device *parent,
tx_pipe->smem = smem;
tx_pipe->native.avail = glink_smem_tx_avail;
tx_pipe->native.write = glink_smem_tx_write;
+ tx_pipe->native.kick = glink_smem_tx_kick;
*rx_pipe->tail = 0;
*tx_pipe->head = 0;
@@ -298,13 +341,17 @@ struct qcom_glink_smem *qcom_glink_smem_register(struct device *parent,
false);
if (IS_ERR(glink)) {
ret = PTR_ERR(glink);
- goto err_put_dev;
+ goto err_free_mbox;
}
smem->glink = glink;
+ enable_irq(smem->irq);
+
return smem;
+err_free_mbox:
+ mbox_free_channel(smem->mbox_chan);
err_put_dev:
device_unregister(dev);
@@ -317,8 +364,12 @@ void qcom_glink_smem_unregister(struct qcom_glink_smem *smem)
{
struct qcom_glink *glink = smem->glink;
+ disable_irq(smem->irq);
+
qcom_glink_native_remove(glink);
- qcom_glink_native_unregister(glink);
+
+ mbox_free_channel(smem->mbox_chan);
+ device_unregister(&smem->dev);
}
EXPORT_SYMBOL_GPL(qcom_glink_smem_unregister);