blob: 349042945b435619401d6007c5788b7486407372 [file] [log] [blame]
Patrick Williams864cc432023-02-09 14:54:44 -06001From 9fb971c23d423f593620ed82fb69a7e2cd35986a Mon Sep 17 00:00:00 2001
Patrick Williams8dd68482022-10-04 07:57:18 -05002From: Emekcan <emekcan.aras@arm.com>
3Date: Wed, 17 Aug 2022 14:21:42 +0100
Patrick Williams864cc432023-02-09 14:54:44 -06004Subject: [PATCH 3/6] Add rpmsg driver for corstone1000
Patrick Williams8dd68482022-10-04 07:57:18 -05005
Patrick Williams2194f502022-10-16 14:26:09 -05006Adds rpmsg driver to communicate with external
Patrick Williams8dd68482022-10-04 07:57:18 -05007system in corstone1000 platform.
8
Patrick Williams864cc432023-02-09 14:54:44 -06009Upstream-Status: Pending
Patrick Williams8dd68482022-10-04 07:57:18 -050010Signed-off-by: Emekcan Aras <emekcan.aras@arm.com>
Patrick Williams864cc432023-02-09 14:54:44 -060011Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
Patrick Williams8dd68482022-10-04 07:57:18 -050012---
13 drivers/rpmsg/Kconfig | 10 ++
14 drivers/rpmsg/Makefile | 1 +
Patrick Williams864cc432023-02-09 14:54:44 -060015 drivers/rpmsg/rpmsg_arm_mailbox.c | 164 ++++++++++++++++++++++++++++++
Patrick Williams8dd68482022-10-04 07:57:18 -050016 3 files changed, 175 insertions(+)
17 create mode 100644 drivers/rpmsg/rpmsg_arm_mailbox.c
18
19diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
Patrick Williams864cc432023-02-09 14:54:44 -060020index d3795860f5c0..fc6916d7b523 100644
Patrick Williams8dd68482022-10-04 07:57:18 -050021--- a/drivers/rpmsg/Kconfig
22+++ b/drivers/rpmsg/Kconfig
Patrick Williams864cc432023-02-09 14:54:44 -060023@@ -81,4 +81,14 @@ config RPMSG_VIRTIO
Patrick Williams8dd68482022-10-04 07:57:18 -050024 select RPMSG_NS
25 select VIRTIO
26
27+config RPMSG_ARM
28+ tristate "ARM RPMSG driver"
29+ select RPMSG
30+ depends on HAS_IOMEM
31+ depends on MAILBOX
32+ help
33+ Say y here to enable support for rpmsg lient driver which is built
34+ around mailbox client using Arm MHUv2.1 as physical medium.This
35+ driver enables communication which remote processor using MHU.
36+
37 endmenu
38diff --git a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
Patrick Williams864cc432023-02-09 14:54:44 -060039index 58e3b382e316..6bdcc69688b2 100644
Patrick Williams8dd68482022-10-04 07:57:18 -050040--- a/drivers/rpmsg/Makefile
41+++ b/drivers/rpmsg/Makefile
42@@ -1,5 +1,6 @@
43 # SPDX-License-Identifier: GPL-2.0
44 obj-$(CONFIG_RPMSG) += rpmsg_core.o
45+obj-$(CONFIG_RPMSG_ARM) += rpmsg_arm_mailbox.o
46 obj-$(CONFIG_RPMSG_CHAR) += rpmsg_char.o
Patrick Williams864cc432023-02-09 14:54:44 -060047 obj-$(CONFIG_RPMSG_CTRL) += rpmsg_ctrl.o
Patrick Williams8dd68482022-10-04 07:57:18 -050048 obj-$(CONFIG_RPMSG_NS) += rpmsg_ns.o
Patrick Williams8dd68482022-10-04 07:57:18 -050049diff --git a/drivers/rpmsg/rpmsg_arm_mailbox.c b/drivers/rpmsg/rpmsg_arm_mailbox.c
50new file mode 100644
51index 000000000000..4a80102669f6
52--- /dev/null
53+++ b/drivers/rpmsg/rpmsg_arm_mailbox.c
54@@ -0,0 +1,164 @@
55+// SPDX-License-Identifier: GPL-2.0
56+/*
57+ * rpmsg client driver using mailbox client interface
58+ *
59+ * Copyright (C) 2019 ARM Ltd.
60+ *
61+ */
62+
63+#include <linux/bitmap.h>
64+#include <linux/export.h>
65+#include <linux/io.h>
66+#include <linux/kernel.h>
67+#include <linux/ktime.h>
68+#include <linux/mailbox_client.h>
69+#include <linux/module.h>
70+#include <linux/of_address.h>
71+#include <linux/of_device.h>
72+#include <linux/processor.h>
73+#include <linux/semaphore.h>
74+#include <linux/slab.h>
75+#include <linux/rpmsg.h>
76+#include "rpmsg_internal.h"
77+#include <linux/mailbox/arm_mhuv2_message.h>
78+
79+#define RPMSG_NAME "arm_rpmsg"
80+#define RPMSG_ADDR_ANY 0xFFFFFFFF
81+
82+struct arm_channel {
83+ struct rpmsg_endpoint ept;
84+ struct mbox_client cl;
85+ struct mbox_chan *mbox;
86+};
87+
88+#define arm_channel_from_rpmsg(_ept) container_of(_ept, struct arm_channel, ept)
89+#define arm_channel_from_mbox(_ept) container_of(_ept, struct arm_channel, cl)
90+
91+
92+static void arm_msg_rx_handler(struct mbox_client *cl, void *mssg)
93+{
94+ struct arm_mhuv2_mbox_msg *msg = mssg;
95+ struct arm_channel* channel = arm_channel_from_mbox(cl);
96+ int err = channel->ept.cb(channel->ept.rpdev, msg->data, 4, channel->ept.priv, RPMSG_ADDR_ANY);
97+ if(err) {
98+ printk("ARM Mailbox: Endpoint callback failed with error: %d", err);
99+ }
100+}
101+
102+
103+static void arm_destroy_ept(struct rpmsg_endpoint *ept)
104+{
105+ struct arm_channel *channel = arm_channel_from_rpmsg(ept);
106+ mbox_free_channel(channel->mbox);
107+ kfree(channel);
108+}
109+
110+static int arm_send(struct rpmsg_endpoint *ept, void *data, int len)
111+{
112+ struct arm_channel *channel = arm_channel_from_rpmsg(ept);
113+
114+ mbox_send_message(channel->mbox, data);
115+ return 0;
116+}
117+
118+static int arm_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dest)
119+{
120+ struct arm_mhuv2_mbox_msg msg;
121+ struct arm_channel *channel = arm_channel_from_rpmsg(ept);
122+ msg.data = data;
123+ msg.len = len;
124+ mbox_send_message(channel->mbox, &msg);
125+ return 0;
126+}
127+
128+
129+static const struct rpmsg_endpoint_ops arm_endpoint_ops = {
130+ .destroy_ept = arm_destroy_ept,
131+ .send = arm_send,
132+ .sendto = arm_sendto,
133+};
134+
135+
136+static struct rpmsg_endpoint *arm_create_ept(struct rpmsg_device *rpdev,
137+ rpmsg_rx_cb_t cb, void *priv, struct rpmsg_channel_info chinfo)
138+{
139+ struct arm_channel *channel;
140+
141+ channel = kzalloc(sizeof(*channel), GFP_KERNEL);
142+
143+ // Initialize rpmsg endpoint
144+ kref_init(&channel->ept.refcount);
145+ channel->ept.rpdev = rpdev;
146+ channel->ept.cb = cb;
147+ channel->ept.priv = priv;
148+ channel->ept.ops = &arm_endpoint_ops;
149+
150+ // Initialize mailbox client
151+ channel->cl.dev = rpdev->dev.parent;
152+ channel->cl.rx_callback = arm_msg_rx_handler;
153+ channel->cl.tx_done = NULL; /* operate in blocking mode */
154+ channel->cl.tx_block = true;
155+ channel->cl.tx_tout = 500; /* by half a second */
156+ channel->cl.knows_txdone = false; /* depending upon protocol */
157+
158+ channel->mbox = mbox_request_channel_byname(&channel->cl, chinfo.name);
159+ if (IS_ERR_OR_NULL(channel->mbox)) {
160+ printk("RPMsg ARM: Cannot get channel by name: '%s'\n", chinfo.name);
161+ return -1;
162+ }
163+
164+ return &channel->ept;
165+}
166+
167+static const struct rpmsg_device_ops arm_device_ops = {
168+ .create_ept = arm_create_ept,
169+};
170+
171+
172+static void arm_release_device(struct device *dev)
173+{
174+ struct rpmsg_device *rpdev = to_rpmsg_device(dev);
175+
176+ kfree(rpdev);
177+}
178+
179+
180+static int client_probe(struct platform_device *pdev)
181+{
182+ struct device *dev = &pdev->dev;
183+ struct rpmsg_device *rpdev;
184+
185+ rpdev = kzalloc(sizeof(*rpdev), GFP_KERNEL);
186+ if (!rpdev)
187+ return -ENOMEM;
188+
189+ /* Assign callbacks for rpmsg_device */
190+ rpdev->ops = &arm_device_ops;
191+
192+ /* Assign public information to the rpmsg_device */
193+ memcpy(rpdev->id.name, RPMSG_NAME, strlen(RPMSG_NAME));
194+
195+ rpdev->dev.parent = dev;
196+ rpdev->dev.release = arm_release_device;
197+
198+ return rpmsg_chrdev_register_device(rpdev);
199+}
200+
201+static const struct of_device_id client_of_match[] = {
202+ { .compatible = "arm,client", .data = NULL },
203+ { /* Sentinel */ },
204+};
205+
206+static struct platform_driver client_driver = {
207+ .driver = {
208+ .name = "arm-mhu-client",
209+ .of_match_table = client_of_match,
210+ },
211+ .probe = client_probe,
212+};
213+
214+module_platform_driver(client_driver);
215+
216+MODULE_LICENSE("GPL v2");
217+MODULE_DESCRIPTION("ARM RPMSG Driver");
218+MODULE_AUTHOR("Tushar Khandelwal <tushar.khandelwal@arm.com>");
219--
Patrick Williams864cc432023-02-09 14:54:44 -06002202.39.0
Patrick Williams8dd68482022-10-04 07:57:18 -0500221